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

Side by Side Diff: scripts/slave/annotated_checkout.py

Issue 14988009: First cut of testing infrastructure for recipes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Address comments Created 7 years, 7 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
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 """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
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
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):
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
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):
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.).
232 test_mode: If we're in test_mode, just return error code and root without
233 actually doing anything.
224 234
225 Returns: 235 Returns:
226 Tuple of (<retcode>, <root_path>) where root_path is the absolute path 236 Tuple of (<retcode>, <root_path>) where root_path is the absolute path
227 to the 'root' of the checkout (as defined by |checkout_type|). 237 to the 'root' of the checkout (as defined by |checkout_type|).
228 """ 238 """
239 stream = sys.stdout
240 if test_mode:
241 stream = StringIO.StringIO()
Isaac (away) 2013/05/12 09:24:56 Would open(os.devnull, 'w') work?
iannucci 2013/05/14 04:31:35 Actually yes, that would work. For some reason I f
229 stream = annotator.StructuredAnnotationStream( 242 stream = annotator.StructuredAnnotationStream(
230 seed_steps=['checkout_setup', 'checkout_clean', 'checkout']) 243 seed_steps=['checkout_setup', 'checkout_clean', 'checkout'],
244 stream=stream)
245
231 with stream.step('checkout_setup') as s: 246 with stream.step('checkout_setup') as s:
232 try: 247 try:
233 checkout = CheckoutFactory(checkout_type, checkout_spec) 248 checkout = CheckoutFactory(checkout_type, checkout_spec)
234 except KeyError as e: 249 except KeyError as e:
235 s.step_text(e) 250 s.step_text(e)
236 s.step_failure() 251 s.step_failure()
237 return (1, None) 252 return (1, None)
253 if test_mode:
254 return (0, checkout.root())
255 checkout.setup()
238 with stream.step('checkout_clean') as s: 256 with stream.step('checkout_clean') as s:
239 checkout.clean() 257 checkout.clean()
240 with stream.step('checkout') as s: 258 with stream.step('checkout') as s:
241 checkout.checkout() 259 checkout.checkout()
242 return (0, checkout.root()) 260 return (0, checkout.root())
243 261
244 262
245 def main(): 263 def main():
246 opts, _ = get_args() 264 opts, _ = get_args()
247 return run(opts.type, opts.spec)[0] 265 return run(opts.type, opts.spec)[0]
248 266
249 267
250 if __name__ == '__main__': 268 if __name__ == '__main__':
251 sys.exit(main()) 269 sys.exit(main())
OLDNEW
« no previous file with comments | « PRESUBMIT.py ('k') | scripts/slave/annotated_run.py » ('j') | scripts/slave/annotated_run.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698