Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: fetch.py

Issue 14087013: Support "--nohooks" on fetch (Closed) Base URL: git@github.com:jankeromnes/depot_tools@master
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """ 6 """
7 Tool to perform checkouts in one easy command line! 7 Tool to perform checkouts in one easy command line!
8 8
9 Usage: 9 Usage:
10 fetch <recipe> [--property=value [--property2=value2 ...]] 10 fetch <recipe> [--property=value [--property2=value2 ...]]
(...skipping 25 matching lines...) Expand all
36 class Checkout(object): 36 class Checkout(object):
37 """Base class for implementing different types of checkouts. 37 """Base class for implementing different types of checkouts.
38 38
39 Attributes: 39 Attributes:
40 |base|: the absolute path of the directory in which this script is run. 40 |base|: the absolute path of the directory in which this script is run.
41 |spec|: the spec for this checkout as returned by the recipe. Different 41 |spec|: the spec for this checkout as returned by the recipe. Different
42 subclasses will expect different keys in this dictionary. 42 subclasses will expect different keys in this dictionary.
43 |root|: the directory into which the checkout will be performed, as returned 43 |root|: the directory into which the checkout will be performed, as returned
44 by the recipe. This is a relative path from |base|. 44 by the recipe. This is a relative path from |base|.
45 """ 45 """
46 def __init__(self, dryrun, spec, root): 46 def __init__(self, dryrun, nohooks, spec, root):
47 self.base = os.getcwd() 47 self.base = os.getcwd()
48 self.dryrun = dryrun 48 self.dryrun = dryrun
49 self.nohooks = nohooks
49 self.spec = spec 50 self.spec = spec
50 self.root = root 51 self.root = root
51 52
52 def exists(self): 53 def exists(self):
53 pass 54 pass
54 55
55 def init(self): 56 def init(self):
56 pass 57 pass
57 58
58 def sync(self): 59 def sync(self):
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 def run_svn(self, *cmd, **kwargs): 91 def run_svn(self, *cmd, **kwargs):
91 if sys.platform == 'win32' and not spawn.find_executable('svn'): 92 if sys.platform == 'win32' and not spawn.find_executable('svn'):
92 svn_path = os.path.join(SCRIPT_PATH, 'svn_bin', 'svn.exe') 93 svn_path = os.path.join(SCRIPT_PATH, 'svn_bin', 'svn.exe')
93 else: 94 else:
94 svn_path = 'svn' 95 svn_path = 'svn'
95 return self.run((svn_path,) + cmd, **kwargs) 96 return self.run((svn_path,) + cmd, **kwargs)
96 97
97 98
98 class GclientGitCheckout(GclientCheckout, GitCheckout): 99 class GclientGitCheckout(GclientCheckout, GitCheckout):
99 100
100 def __init__(self, dryrun, spec, root): 101 def __init__(self, dryrun, nohooks, spec, root):
101 super(GclientGitCheckout, self).__init__(dryrun, spec, root) 102 super(GclientGitCheckout, self).__init__(dryrun, nohooks, spec, root)
102 assert 'solutions' in self.spec 103 assert 'solutions' in self.spec
103 keys = ['solutions', 'target_os', 'target_os_only'] 104 keys = ['solutions', 'target_os', 'target_os_only']
104 gclient_spec = '\n'.join('%s = %s' % (key, self.spec[key]) 105 gclient_spec = '\n'.join('%s = %s' % (key, self.spec[key])
105 for key in self.spec if key in keys) 106 for key in self.spec if key in keys)
106 self.spec['gclient_spec'] = gclient_spec 107 self.spec['gclient_spec'] = gclient_spec
107 108
108 def exists(self): 109 def exists(self):
109 return os.path.exists(os.path.join(os.getcwd(), self.root)) 110 return os.path.exists(os.path.join(os.getcwd(), self.root))
110 111
111 def init(self): 112 def init(self):
112 # TODO(dpranke): Work around issues w/ delta compression on big repos. 113 # TODO(dpranke): Work around issues w/ delta compression on big repos.
113 self.run_git('config', '--global', 'core.deltaBaseCacheLimit', '1G') 114 self.run_git('config', '--global', 'core.deltaBaseCacheLimit', '1G')
114 115
115 # Configure and do the gclient checkout. 116 # Configure and do the gclient checkout.
116 self.run_gclient('config', '--spec', self.spec['gclient_spec']) 117 self.run_gclient('config', '--spec', self.spec['gclient_spec'])
117 self.run_gclient('sync') 118
119 if self.nohooks:
120 self.run_gclient('sync', '--nohooks')
121 else:
122 self.run_gclient('sync')
118 123
119 # Configure git. 124 # Configure git.
120 wd = os.path.join(self.base, self.root) 125 wd = os.path.join(self.base, self.root)
121 if self.dryrun: 126 if self.dryrun:
122 print 'cd %s' % wd 127 print 'cd %s' % wd
123 self.run_git( 128 self.run_git(
124 'submodule', 'foreach', 129 'submodule', 'foreach',
125 'git config -f $toplevel/.git/config submodule.$name.ignore all', 130 'git config -f $toplevel/.git/config submodule.$name.ignore all',
126 cwd=wd) 131 cwd=wd)
127 self.run_git('config', 'diff.ignoreSubmodules', 'all', cwd=wd) 132 self.run_git('config', 'diff.ignoreSubmodules', 'all', cwd=wd)
128 133
129 134
130 class GclientGitSvnCheckout(GclientGitCheckout, SvnCheckout): 135 class GclientGitSvnCheckout(GclientGitCheckout, SvnCheckout):
131 136
132 def __init__(self, dryrun, spec, root): 137 def __init__(self, dryrun, nohooks, spec, root):
133 super(GclientGitSvnCheckout, self).__init__(dryrun, spec, root) 138 super(GclientGitSvnCheckout, self).__init__(dryrun, nohooks, spec, root)
134 assert 'svn_url' in self.spec 139 assert 'svn_url' in self.spec
135 assert 'svn_branch' in self.spec 140 assert 'svn_branch' in self.spec
136 assert 'svn_ref' in self.spec 141 assert 'svn_ref' in self.spec
137 142
138 def init(self): 143 def init(self):
139 # Ensure we are authenticated with subversion for all submodules. 144 # Ensure we are authenticated with subversion for all submodules.
140 git_svn_dirs = json.loads(self.spec.get('submodule_git_svn_spec', '{}')) 145 git_svn_dirs = json.loads(self.spec.get('submodule_git_svn_spec', '{}'))
141 git_svn_dirs.update({self.root: self.spec}) 146 git_svn_dirs.update({self.root: self.spec})
142 for _, svn_spec in git_svn_dirs.iteritems(): 147 for _, svn_spec in git_svn_dirs.iteritems():
143 try: 148 try:
(...skipping 22 matching lines...) Expand all
166 171
167 172
168 CHECKOUT_TYPE_MAP = { 173 CHECKOUT_TYPE_MAP = {
169 'gclient': GclientCheckout, 174 'gclient': GclientCheckout,
170 'gclient_git': GclientGitCheckout, 175 'gclient_git': GclientGitCheckout,
171 'gclient_git_svn': GclientGitSvnCheckout, 176 'gclient_git_svn': GclientGitSvnCheckout,
172 'git': GitCheckout, 177 'git': GitCheckout,
173 } 178 }
174 179
175 180
176 def CheckoutFactory(type_name, dryrun, spec, root): 181 def CheckoutFactory(type_name, dryrun, nohooks, spec, root):
177 """Factory to build Checkout class instances.""" 182 """Factory to build Checkout class instances."""
178 class_ = CHECKOUT_TYPE_MAP.get(type_name) 183 class_ = CHECKOUT_TYPE_MAP.get(type_name)
179 if not class_: 184 if not class_:
180 raise KeyError('unrecognized checkout type: %s' % type_name) 185 raise KeyError('unrecognized checkout type: %s' % type_name)
181 return class_(dryrun, spec, root) 186 return class_(dryrun, nohooks, spec, root)
182 187
183 188
184 ################################################# 189 #################################################
185 # Utility function and file entry point. 190 # Utility function and file entry point.
186 ################################################# 191 #################################################
187 def usage(msg=None): 192 def usage(msg=None):
188 """Print help and exit.""" 193 """Print help and exit."""
189 if msg: 194 if msg:
190 print 'Error:', msg 195 print 'Error:', msg
191 196
192 print ( 197 print (
193 """ 198 """
194 usage: %s [-n|--dry-run] <recipe> [--property=value [--property2=value2 ...]] 199 usage: %s [-n|--dry-run] [--nohooks] <recipe> [--property=value [--property2=val ue2 ...]]
195 """ % os.path.basename(sys.argv[0])) 200 """ % os.path.basename(sys.argv[0]))
196 sys.exit(bool(msg)) 201 sys.exit(bool(msg))
197 202
198 203
199 def handle_args(argv): 204 def handle_args(argv):
200 """Gets the recipe name from the command line arguments.""" 205 """Gets the recipe name from the command line arguments."""
201 if len(argv) <= 1: 206 if len(argv) <= 1:
202 usage('Must specify a recipe.') 207 usage('Must specify a recipe.')
203 if argv[1] in ('-h', '--help', 'help'): 208 if argv[1] in ('-h', '--help', 'help'):
204 usage() 209 usage()
205 210
206 dryrun = False 211 dryrun = False
207 if argv[1] in ('-n', '--dry-run'): 212 if argv[1] in ('-n', '--dry-run'):
208 dryrun = True 213 dryrun = True
209 argv.pop(1) 214 argv.pop(1)
210 215
216 nohooks = False
217 if argv[1] == '--nohooks':
218 nohooks = True
219 argv.pop(1)
agable 2013/04/17 17:10:40 I'm going to do a full rewrite of the fetch and re
220
211 def looks_like_arg(arg): 221 def looks_like_arg(arg):
212 return arg.startswith('--') and arg.count('=') == 1 222 return arg.startswith('--') and arg.count('=') == 1
213 223
214 bad_parms = [x for x in argv[2:] if not looks_like_arg(x)] 224 bad_parms = [x for x in argv[2:] if not looks_like_arg(x)]
215 if bad_parms: 225 if bad_parms:
216 usage('Got bad arguments %s' % bad_parms) 226 usage('Got bad arguments %s' % bad_parms)
217 227
218 recipe = argv[1] 228 recipe = argv[1]
219 props = argv[2:] 229 props = argv[2:]
220 return dryrun, recipe, props 230 return dryrun, nohooks, recipe, props
221 231
222 232
223 def run_recipe_fetch(recipe, props, aliased=False): 233 def run_recipe_fetch(recipe, props, aliased=False):
224 """Invoke a recipe's fetch method with the passed-through args 234 """Invoke a recipe's fetch method with the passed-through args
225 and return its json output as a python object.""" 235 and return its json output as a python object."""
226 recipe_path = os.path.abspath(os.path.join(SCRIPT_PATH, 'recipes', recipe)) 236 recipe_path = os.path.abspath(os.path.join(SCRIPT_PATH, 'recipes', recipe))
227 if not os.path.exists(recipe_path + '.py'): 237 if not os.path.exists(recipe_path + '.py'):
228 print "Could not find a recipe for %s" % recipe 238 print "Could not find a recipe for %s" % recipe
229 sys.exit(1) 239 sys.exit(1)
230 240
231 cmd = [sys.executable, recipe_path + '.py', 'fetch'] + props 241 cmd = [sys.executable, recipe_path + '.py', 'fetch'] + props
232 result = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] 242 result = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
233 243
234 spec = json.loads(result) 244 spec = json.loads(result)
235 if 'alias' in spec: 245 if 'alias' in spec:
236 assert not aliased 246 assert not aliased
237 return run_recipe_fetch( 247 return run_recipe_fetch(
238 spec['alias']['recipe'], spec['alias']['props'] + props, aliased=True) 248 spec['alias']['recipe'], spec['alias']['props'] + props, aliased=True)
239 cmd = [sys.executable, recipe_path + '.py', 'root'] 249 cmd = [sys.executable, recipe_path + '.py', 'root']
240 result = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] 250 result = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
241 root = json.loads(result) 251 root = json.loads(result)
242 return spec, root 252 return spec, root
243 253
244 254
245 def run(dryrun, spec, root): 255 def run(dryrun, nohooks, spec, root):
246 """Perform a checkout with the given type and configuration. 256 """Perform a checkout with the given type and configuration.
247 257
248 Args: 258 Args:
249 dryrun: if True, don't actually execute the commands 259 dryrun: if True, don't actually execute the commands
250 spec: Checkout configuration returned by the the recipe's fetch_spec 260 spec: Checkout configuration returned by the the recipe's fetch_spec
251 method (checkout type, repository url, etc.). 261 method (checkout type, repository url, etc.).
252 root: The directory into which the repo expects to be checkout out. 262 root: The directory into which the repo expects to be checkout out.
253 """ 263 """
254 assert 'type' in spec 264 assert 'type' in spec
255 checkout_type = spec['type'] 265 checkout_type = spec['type']
256 checkout_spec = spec['%s_spec' % checkout_type] 266 checkout_spec = spec['%s_spec' % checkout_type]
257 try: 267 try:
258 checkout = CheckoutFactory(checkout_type, dryrun, checkout_spec, root) 268 checkout = CheckoutFactory(
269 checkout_type, dryrun, nohooks, checkout_spec, root)
259 except KeyError: 270 except KeyError:
260 return 1 271 return 1
261 if checkout.exists(): 272 if checkout.exists():
262 print 'You appear to already have a checkout. "fetch" is used only' 273 print 'You appear to already have a checkout. "fetch" is used only'
263 print 'to get new checkouts. Use "gclient sync" to update the checkout.' 274 print 'to get new checkouts. Use "gclient sync" to update the checkout.'
264 print 275 print
265 print 'Fetch also does not yet deal with partial checkouts, so if fetch' 276 print 'Fetch also does not yet deal with partial checkouts, so if fetch'
266 print 'failed, delete the checkout and start over (crbug.com/230691).' 277 print 'failed, delete the checkout and start over (crbug.com/230691).'
267 return 1 278 return 1
268 return checkout.init() 279 return checkout.init()
269 280
270 281
271 def main(): 282 def main():
272 dryrun, recipe, props = handle_args(sys.argv) 283 dryrun, nohooks, recipe, props = handle_args(sys.argv)
273 spec, root = run_recipe_fetch(recipe, props) 284 spec, root = run_recipe_fetch(recipe, props)
274 return run(dryrun, spec, root) 285 return run(dryrun, nohooks, spec, root)
275 286
276 287
277 if __name__ == '__main__': 288 if __name__ == '__main__':
278 sys.exit(main()) 289 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698