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

Side by Side Diff: fetch.py

Issue 13586004: add a -n/--dry-run to the new fetch command in depot_tools (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
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 | Annotate | Revision Log
« 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 23 matching lines...) Expand all
34 class Checkout(object): 34 class Checkout(object):
35 """Base class for implementing different types of checkouts. 35 """Base class for implementing different types of checkouts.
36 36
37 Attributes: 37 Attributes:
38 |base|: the absolute path of the directory in which this script is run. 38 |base|: the absolute path of the directory in which this script is run.
39 |spec|: the spec for this checkout as returned by the recipe. Different 39 |spec|: the spec for this checkout as returned by the recipe. Different
40 subclasses will expect different keys in this dictionary. 40 subclasses will expect different keys in this dictionary.
41 |root|: the directory into which the checkout will be performed, as returned 41 |root|: the directory into which the checkout will be performed, as returned
42 by the recipe. This is a relative path from |base|. 42 by the recipe. This is a relative path from |base|.
43 """ 43 """
44 def __init__(self, spec, root): 44 def __init__(self, dryrun, spec, root):
45 self.base = os.getcwd() 45 self.base = os.getcwd()
46 self.dryrun = dryrun
46 self.spec = spec 47 self.spec = spec
47 self.root = root 48 self.root = root
48 49
49 def exists(self): 50 def exists(self):
50 pass 51 pass
51 52
52 def init(self): 53 def init(self):
53 pass 54 pass
54 55
55 def sync(self): 56 def sync(self):
56 pass 57 pass
57 58
58 59
59 class GclientCheckout(Checkout): 60 class GclientCheckout(Checkout):
60 61
61 @staticmethod 62 def run_gclient(self, *cmd, **kwargs):
62 def run_gclient(*cmd, **kwargs):
63 print 'Running: gclient %s' % ' '.join(pipes.quote(x) for x in cmd) 63 print 'Running: gclient %s' % ' '.join(pipes.quote(x) for x in cmd)
64 return subprocess.check_call(('gclient',) + cmd, **kwargs) 64 if not self.dryrun:
65 return subprocess.check_call(('gclient',) + cmd, **kwargs)
65 66
66 67
67 class GitCheckout(Checkout): 68 class GitCheckout(Checkout):
68 69
69 @staticmethod 70 def run_git(self, *cmd, **kwargs):
70 def run_git(*cmd, **kwargs):
71 print 'Running: git %s' % ' '.join(pipes.quote(x) for x in cmd) 71 print 'Running: git %s' % ' '.join(pipes.quote(x) for x in cmd)
72 return subprocess.check_call(('git',) + cmd, **kwargs) 72 if not self.dryrun:
73 return subprocess.check_call(('git',) + cmd, **kwargs)
73 74
74 75
75 class GclientGitSvnCheckout(GclientCheckout, GitCheckout): 76 class GclientGitSvnCheckout(GclientCheckout, GitCheckout):
76 77
77 def __init__(self, spec, root): 78 def __init__(self, dryrun, spec, root):
78 super(GclientGitSvnCheckout, self).__init__(spec, root) 79 super(GclientGitSvnCheckout, self).__init__(dryrun, spec, root)
79 assert 'solutions' in self.spec 80 assert 'solutions' in self.spec
80 keys = ['solutions', 'target_os', 'target_os_only'] 81 keys = ['solutions', 'target_os', 'target_os_only']
81 gclient_spec = '\n'.join('%s = %s' % (key, self.spec[key]) 82 gclient_spec = '\n'.join('%s = %s' % (key, self.spec[key])
82 for key in self.spec if key in keys) 83 for key in self.spec if key in keys)
83 self.spec['gclient_spec'] = gclient_spec 84 self.spec['gclient_spec'] = gclient_spec
84 assert 'svn_url' in self.spec 85 assert 'svn_url' in self.spec
85 assert 'svn_branch' in self.spec 86 assert 'svn_branch' in self.spec
86 assert 'svn_ref' in self.spec 87 assert 'svn_ref' in self.spec
87 88
88 def exists(self): 89 def exists(self):
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 self.run_git('svn', 'fetch', cwd=wd) 123 self.run_git('svn', 'fetch', cwd=wd)
123 124
124 125
125 CHECKOUT_TYPE_MAP = { 126 CHECKOUT_TYPE_MAP = {
126 'gclient': GclientCheckout, 127 'gclient': GclientCheckout,
127 'gclient_git_svn': GclientGitSvnCheckout, 128 'gclient_git_svn': GclientGitSvnCheckout,
128 'git': GitCheckout, 129 'git': GitCheckout,
129 } 130 }
130 131
131 132
132 def CheckoutFactory(type_name, spec, root): 133 def CheckoutFactory(type_name, dryrun, spec, root):
133 """Factory to build Checkout class instances.""" 134 """Factory to build Checkout class instances."""
134 class_ = CHECKOUT_TYPE_MAP.get(type_name) 135 class_ = CHECKOUT_TYPE_MAP.get(type_name)
135 if not class_: 136 if not class_:
136 raise KeyError('unrecognized checkout type: %s' % type_name) 137 raise KeyError('unrecognized checkout type: %s' % type_name)
137 return class_(spec, root) 138 return class_(dryrun, spec, root)
138 139
139 140
140 ################################################# 141 #################################################
141 # Utility function and file entry point. 142 # Utility function and file entry point.
142 ################################################# 143 #################################################
143 def usage(msg=None): 144 def usage(msg=None):
144 """Print help and exit.""" 145 """Print help and exit."""
145 if msg: 146 if msg:
146 print 'Error:', msg 147 print 'Error:', msg
147 148
148 print ( 149 print (
149 """ 150 """
150 usage: %s <recipe> [--property=value [--property2=value2 ...]] 151 usage: %s [-n|--dry-run] <recipe> [--property=value [--property2=value2 ...]]
151 """ % os.path.basename(sys.argv[0])) 152 """ % os.path.basename(sys.argv[0]))
152 sys.exit(bool(msg)) 153 sys.exit(bool(msg))
153 154
154 155
155 def handle_args(argv): 156 def handle_args(argv):
156 """Gets the recipe name from the command line arguments.""" 157 """Gets the recipe name from the command line arguments."""
157 if len(argv) <= 1: 158 if len(argv) <= 1:
158 usage('Must specify a recipe.') 159 usage('Must specify a recipe.')
159 if argv[1] in ('-h', '--help', 'help'): 160 if argv[1] in ('-h', '--help', 'help'):
160 usage() 161 usage()
161 162
163 if argv[1] in ('-n', '--dry-run'):
164 dryrun = True
165 argv.pop(1)
agable 2013/04/03 21:07:00 This is the best way to do it for now. I'll look
166
162 def looks_like_arg(arg): 167 def looks_like_arg(arg):
163 return arg.startswith('--') and arg.count('=') == 1 168 return arg.startswith('--') and arg.count('=') == 1
164 169
165 bad_parms = [x for x in argv[2:] if not looks_like_arg(x)] 170 bad_parms = [x for x in argv[2:] if not looks_like_arg(x)]
166 if bad_parms: 171 if bad_parms:
167 usage('Got bad arguments %s' % bad_parms) 172 usage('Got bad arguments %s' % bad_parms)
168 173
169 recipe = argv[1] 174 recipe = argv[1]
170 props = argv[2:] 175 props = argv[2:]
171 return recipe, props 176 return dryrun, recipe, props
172 177
173 178
174 def run_recipe_fetch(recipe, props, aliased=False): 179 def run_recipe_fetch(recipe, props, aliased=False):
175 """Invoke a recipe's fetch method with the passed-through args 180 """Invoke a recipe's fetch method with the passed-through args
176 and return its json output as a python object.""" 181 and return its json output as a python object."""
177 recipe_path = os.path.abspath(os.path.join(SCRIPT_PATH, 'recipes', recipe)) 182 recipe_path = os.path.abspath(os.path.join(SCRIPT_PATH, 'recipes', recipe))
178 cmd = [sys.executable, recipe_path + '.py', 'fetch'] + props 183 cmd = [sys.executable, recipe_path + '.py', 'fetch'] + props
179 result = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] 184 result = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
180 spec = json.loads(result) 185 spec = json.loads(result)
181 if 'alias' in spec: 186 if 'alias' in spec:
182 assert not aliased 187 assert not aliased
183 return run_recipe_fetch( 188 return run_recipe_fetch(
184 spec['alias']['recipe'], spec['alias']['props'] + props, aliased=True) 189 spec['alias']['recipe'], spec['alias']['props'] + props, aliased=True)
185 cmd = [sys.executable, recipe_path + '.py', 'root'] 190 cmd = [sys.executable, recipe_path + '.py', 'root']
186 result = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] 191 result = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
187 root = json.loads(result) 192 root = json.loads(result)
188 return spec, root 193 return spec, root
189 194
190 195
191 def run(spec, root): 196 def run(dryrun, spec, root):
192 """Perform a checkout with the given type and configuration. 197 """Perform a checkout with the given type and configuration.
193 198
194 Args: 199 Args:
200 dryrun: if True, don't actually execute the commands
195 spec: Checkout configuration returned by the the recipe's fetch_spec 201 spec: Checkout configuration returned by the the recipe's fetch_spec
196 method (checkout type, repository url, etc.). 202 method (checkout type, repository url, etc.).
197 root: The directory into which the repo expects to be checkout out. 203 root: The directory into which the repo expects to be checkout out.
198 """ 204 """
199 assert 'type' in spec 205 assert 'type' in spec
200 checkout_type = spec['type'] 206 checkout_type = spec['type']
201 checkout_spec = spec['%s_spec' % checkout_type] 207 checkout_spec = spec['%s_spec' % checkout_type]
202 try: 208 try:
203 checkout = CheckoutFactory(checkout_type, checkout_spec, root) 209 checkout = CheckoutFactory(checkout_type, dryrun, checkout_spec, root)
204 except KeyError: 210 except KeyError:
205 return 1 211 return 1
206 if checkout.exists(): 212 if checkout.exists():
207 print 'You appear to already have this checkout.' 213 print 'You appear to already have this checkout.'
208 print 'Aborting to avoid clobbering your work.' 214 print 'Aborting to avoid clobbering your work.'
209 return 1 215 return 1
210 checkout.init() 216 checkout.init()
211 return 0 217 return 0
212 218
213 219
214 def main(): 220 def main():
215 recipe, props = handle_args(sys.argv) 221 dryrun, recipe, props = handle_args(sys.argv)
216 spec, root = run_recipe_fetch(recipe, props) 222 spec, root = run_recipe_fetch(recipe, props)
217 return run(spec, root) 223 return run(dryrun, spec, root)
218 224
219 225
220 if __name__ == '__main__': 226 if __name__ == '__main__':
221 sys.exit(main()) 227 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