OLD | NEW |
---|---|
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 """Helper script for fully-annotated builds. Performs checkouts of various | 6 """Helper script for fully-annotated builds. Performs checkouts of various |
7 kinds. | 7 kinds. |
8 | 8 |
9 This script is part of the effort to move all builds to annotator-based systems. | 9 This script is part of the effort to move all builds to annotator-based systems. |
10 Any builder configured to use the AnnotatorFactory uses run.py as its entry | 10 Any builder configured to use the AnnotatorFactory uses run.py as its entry |
11 point. If that builder's factory_properties include a spec for a checkout, then | 11 point. If that builder's factory_properties include a spec for a checkout, then |
12 the work of actually performing that checkout is done here. | 12 the work of actually performing that checkout is done here. |
13 """ | 13 """ |
14 | 14 |
15 import cStringIO as StringIO | |
15 import optparse | 16 import optparse |
16 import os | 17 import os |
18 import pipes | |
17 import subprocess | 19 import subprocess |
18 import sys | 20 import sys |
19 import pipes | |
20 | 21 |
21 from common import annotator | 22 from common import annotator |
22 from common import chromium_utils | 23 from common import chromium_utils |
23 | 24 |
24 | 25 |
25 SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__)) | 26 SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__)) |
26 | 27 |
27 | 28 |
28 def get_args(): | 29 def get_args(): |
29 """Process command-line arguments.""" | 30 """Process command-line arguments.""" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
68 Attributes: | 69 Attributes: |
69 CHECKOUT_TYPE: String identifier used when selecting the type of checkout to | 70 CHECKOUT_TYPE: String identifier used when selecting the type of checkout to |
70 perform. All subclasses must specify a unique CHECKOUT_TYPE value. | 71 perform. All subclasses must specify a unique CHECKOUT_TYPE value. |
71 """ | 72 """ |
72 __metaclass__ = _CheckoutMetaclass | 73 __metaclass__ = _CheckoutMetaclass |
73 CHECKOUT_TYPE = None | 74 CHECKOUT_TYPE = None |
74 | 75 |
75 def __init__(self, spec): | 76 def __init__(self, spec): |
76 self.spec = spec | 77 self.spec = spec |
77 | 78 |
79 def setup(self): | |
80 pass | |
81 | |
78 def clean(self): | 82 def clean(self): |
79 pass | 83 pass |
80 | 84 |
81 def checkout(self): | 85 def checkout(self): |
82 pass | 86 pass |
83 | 87 |
84 def root(self): | 88 def root(self): |
85 pass | 89 pass |
86 | 90 |
87 | 91 |
88 def CheckoutFactory(type_name, spec): | 92 def CheckoutFactory(type_name, spec): |
89 """Factory to build Checkout class instances.""" | 93 """Factory to build Checkout class instances.""" |
90 class_ = _CheckoutMetaclass.checkout_registry.get(type_name) | 94 class_ = _CheckoutMetaclass.checkout_registry.get(type_name) |
91 if not class_ or not issubclass(class_, Checkout): | 95 if not class_ or not issubclass(class_, Checkout): |
92 raise KeyError('unrecognized checkout type: %s' % type_name) | 96 raise KeyError('unrecognized checkout type: %s' % type_name) |
93 return class_(spec) | 97 return class_(spec) |
94 | 98 |
95 | 99 |
96 class GclientCheckout(Checkout): | 100 class GclientCheckout(Checkout): |
97 CHECKOUT_TYPE = 'gclient' | 101 CHECKOUT_TYPE = 'gclient' |
98 | 102 |
99 gclient_path = os.path.abspath( | 103 gclient_path = os.path.abspath( |
100 os.path.join(SCRIPT_PATH, '..', '..', '..', 'depot_tools', 'gclient')) | 104 os.path.join(SCRIPT_PATH, '..', '..', '..', 'depot_tools', 'gclient')) |
101 if sys.platform.startswith('win'): | 105 if sys.platform.startswith('win'): |
102 gclient_path += '.bat' | 106 gclient_path += '.bat' |
103 | 107 |
104 def __init__(self, *args, **kwargs): | 108 def __init__(self, *args, **kwargs): |
105 super(GclientCheckout, self).__init__(*args, **kwargs) | 109 super(GclientCheckout, self).__init__(*args, **kwargs) |
106 assert 'solutions' in self.spec | 110 assert 'solutions' in self.spec |
111 | |
112 @classmethod | |
113 def run_gclient(cls, *cmd): | |
114 print 'Running: gclient %s' % ' '.join(pipes.quote(x) for x in cmd) | |
115 subprocess.check_call((cls.gclient_path,)+cmd) | |
116 | |
117 def setup(self): | |
107 spec_string = '' | 118 spec_string = '' |
108 for key in self.spec: | 119 for key in self.spec: |
109 # We should be using json.dumps here, but gclient directly execs the dict | 120 # We should be using json.dumps here, but gclient directly execs the dict |
110 # that it receives as the argument to --spec, so we have to have True, | 121 # that it receives as the argument to --spec, so we have to have True, |
111 # False, and None instead of JSON's true, false, and null. | 122 # False, and None instead of JSON's true, false, and null. |
112 spec_string += '%s = %s\n' % (key, str(self.spec[key])) | 123 spec_string += '%s = %s\n' % (key, str(self.spec[key])) |
113 self.run_gclient('config', '--spec', spec_string) | 124 self.run_gclient('config', '--spec', spec_string) |
114 | 125 |
115 @classmethod | |
116 def run_gclient(cls, *cmd): | |
117 print 'Running: gclient %s' % ' '.join(pipes.quote(x) for x in cmd) | |
118 subprocess.check_call((cls.gclient_path,)+cmd) | |
119 | |
120 def clean(self): | 126 def clean(self): |
121 self.run_gclient('revert', '--nohooks') | 127 self.run_gclient('revert', '--nohooks') |
122 | 128 |
123 def checkout(self): | 129 def checkout(self): |
124 self.run_gclient('sync', '--nohooks') | 130 self.run_gclient('sync', '--nohooks') |
125 | 131 |
126 def root(self): | 132 def root(self): |
127 return os.path.abspath(self.spec['solutions'][0]['name']) | 133 return os.path.abspath(self.spec['solutions'][0]['name']) |
128 | 134 |
129 | 135 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
165 assert os.pardir not in self.spec.get('directory', '') | 171 assert os.pardir not in self.spec.get('directory', '') |
166 | 172 |
167 dir_path = self.spec.get('directory') | 173 dir_path = self.spec.get('directory') |
168 if not dir_path: | 174 if not dir_path: |
169 dir_path = self.spec['url'].rsplit('/', 1)[-1] | 175 dir_path = self.spec['url'].rsplit('/', 1)[-1] |
170 if dir_path.endswith('.git'): # ex: https://host/foobar.git | 176 if dir_path.endswith('.git'): # ex: https://host/foobar.git |
171 dir_path = dir_path[:-len('.git')] | 177 dir_path = dir_path[:-len('.git')] |
172 if not dir_path: # ex: ssh://host:repo/foobar/.git | 178 if not dir_path: # ex: ssh://host:repo/foobar/.git |
173 dir_path = dir_path.rsplit('/', 1)[-1] | 179 dir_path = dir_path.rsplit('/', 1)[-1] |
174 self.cwd = os.path.abspath(os.path.join(os.curdir, dir_path)) | 180 self.cwd = os.path.abspath(os.path.join(os.curdir, dir_path)) |
181 | |
182 def setup(self, *args, **kwargs): | |
Vadim Shtayura
2013/05/11 00:33:32
Why 'args' and 'kwargs' are here considering they
iannucci
2013/05/11 04:12:27
Done. Not sure how that got there...
| |
175 if not os.path.exists(self.cwd): | 183 if not os.path.exists(self.cwd): |
176 os.makedirs(self.cwd) | 184 os.makedirs(self.cwd) |
177 | 185 |
178 try: | 186 try: |
179 self.run_git('branch') | 187 self.run_git('branch') |
180 exists = True | 188 exists = True |
181 except subprocess.CalledProcessError: | 189 except subprocess.CalledProcessError: |
182 exists = False | 190 exists = False |
183 if exists: | 191 if exists: |
184 self.run_git('remote', 'rm', 'origin') | 192 self.run_git('remote', 'rm', 'origin') |
(...skipping 21 matching lines...) Expand all Loading... | |
206 self.run_git('submodule', 'update', '--init', '--recursive') | 214 self.run_git('submodule', 'update', '--init', '--recursive') |
207 | 215 |
208 def root(self): | 216 def root(self): |
209 return self.cwd | 217 return self.cwd |
210 | 218 |
211 | 219 |
212 class SvnCheckout(Checkout): | 220 class SvnCheckout(Checkout): |
213 CHECKOUT_TYPE = 'svn' | 221 CHECKOUT_TYPE = 'svn' |
214 | 222 |
215 | 223 |
216 def run(checkout_type, checkout_spec): | 224 def run(checkout_type, checkout_spec, test_mode=False): |
Vadim Shtayura
2013/05/11 00:33:32
Update 'Args' section of the doc string to include
iannucci
2013/05/11 04:12:27
Done.
| |
217 """Perform a checkout with the given type and configuration. | 225 """Perform a checkout with the given type and configuration. |
218 | 226 |
219 Args: | 227 Args: |
220 checkout_type: Type of checkout to perform (matching a Checkout subclass | 228 checkout_type: Type of checkout to perform (matching a Checkout subclass |
221 CHECKOUT_TYPE attribute). | 229 CHECKOUT_TYPE attribute). |
222 checkout_spec: Configuration values needed for the type of checkout | 230 checkout_spec: Configuration values needed for the type of checkout |
223 (repository url, etc.). | 231 (repository url, etc.). |
224 | 232 |
225 Returns: | 233 Returns: |
226 Tuple of (<retcode>, <root_path>) where root_path is the absolute path | 234 Tuple of (<retcode>, <root_path>) where root_path is the absolute path |
227 to the 'root' of the checkout (as defined by |checkout_type|). | 235 to the 'root' of the checkout (as defined by |checkout_type|). |
228 """ | 236 """ |
237 stream = sys.stdout | |
238 if test_mode: | |
239 stream = StringIO.StringIO() | |
229 stream = annotator.StructuredAnnotationStream( | 240 stream = annotator.StructuredAnnotationStream( |
230 seed_steps=['checkout_setup', 'checkout_clean', 'checkout']) | 241 seed_steps=['checkout_setup', 'checkout_clean', 'checkout'], |
242 stream=stream) | |
243 | |
231 with stream.step('checkout_setup') as s: | 244 with stream.step('checkout_setup') as s: |
232 try: | 245 try: |
233 checkout = CheckoutFactory(checkout_type, checkout_spec) | 246 checkout = CheckoutFactory(checkout_type, checkout_spec) |
234 except KeyError as e: | 247 except KeyError as e: |
235 s.step_text(e) | 248 s.step_text(e) |
236 s.step_failure() | 249 s.step_failure() |
237 return (1, None) | 250 return (1, None) |
251 if test_mode: | |
252 return (0, checkout.root()) | |
253 checkout.setup() | |
238 with stream.step('checkout_clean') as s: | 254 with stream.step('checkout_clean') as s: |
239 checkout.clean() | 255 checkout.clean() |
240 with stream.step('checkout') as s: | 256 with stream.step('checkout') as s: |
241 checkout.checkout() | 257 checkout.checkout() |
242 return (0, checkout.root()) | 258 return (0, checkout.root()) |
243 | 259 |
244 | 260 |
245 def main(): | 261 def main(): |
246 opts, _ = get_args() | 262 opts, _ = get_args() |
247 return run(opts.type, opts.spec)[0] | 263 return run(opts.type, opts.spec)[0] |
248 | 264 |
249 | 265 |
250 if __name__ == '__main__': | 266 if __name__ == '__main__': |
251 sys.exit(main()) | 267 sys.exit(main()) |
OLD | NEW |