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

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

Issue 14602020: Add an AOSP builder recipe. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: 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 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """This module holds utilities which make writing recipes easier.""" 5 """This module holds utilities which make writing recipes easier."""
6 6
7 import contextlib as _contextlib 7 import contextlib as _contextlib
8 import os as _os 8 import os as _os
9 9
10 # These imports are intended to be passed through to recipes 10 # These imports are intended to be passed through to recipes
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 56
57 The actual checkout root is filled in by annotated_run after the recipe 57 The actual checkout root is filled in by annotated_run after the recipe
58 completes, and is dependent on the implementation of 'root()' in 58 completes, and is dependent on the implementation of 'root()' in
59 annotated_checkout for the checkout type that you've selected. 59 annotated_checkout for the checkout type that you've selected.
60 60
61 NOTE: In order for this function to work, your recipe MUST use the 'checkout' 61 NOTE: In order for this function to work, your recipe MUST use the 'checkout'
62 functionality provided by annotated_run. 62 functionality provided by annotated_run.
63 """ # pylint: disable=W0105 63 """ # pylint: disable=W0105
64 checkout_path = _path_method('checkout_path', '%(CheckoutRootPlaceholder)s') 64 checkout_path = _path_method('checkout_path', '%(CheckoutRootPlaceholder)s')
65 65
66 def path_exists(path):
67 return _os.path.exists(path)
66 68
67 @_contextlib.contextmanager 69 @_contextlib.contextmanager
68 def mock_paths(): 70 def mock_paths(mock_path_exists=None):
agable 2013/05/22 17:21:23 Thanks for adding this functionality. I find mock_
mkosiba (inactive) 2013/05/23 13:13:38 I struggled quite a bit with a good name for this
69 """Used by unittest/recipes_test.py to temporarily override the paths 71 """Used by unittest/recipes_test.py to temporarily override the paths
70 generated by the various path functions in this module. 72 generated by the various path functions in this module.
71 73
72 This is necessary to give equivalent output when running the tests on any 74 This is necessary to give equivalent output when running the tests on any
73 checkout configuration. Instead of real paths, recipes which use these 75 checkout configuration. Instead of real paths, recipes which use these
74 functions will get paths like '[DEPOT_TOOLS_ROOT]'. 76 functions will get paths like '[DEPOT_TOOLS_ROOT]'.
75 """ 77 """
76 path_base_names = ['depot_tools', 'build_internal', 'build', 'slave_build', 78 path_base_names = ['depot_tools', 'build_internal', 'build', 'slave_build',
77 'root'] 79 'root']
78 g = globals() 80 g = globals()
79 tokens = {} 81 tokens = {}
80 path_funcs = {} 82 path_funcs = {}
83 mock_path_exists = frozenset(mock_path_exists or [])
81 try: 84 try:
82 for name in path_base_names: 85 for name in path_base_names:
83 token_name = (name + '_root').upper() 86 token_name = (name + '_root').upper()
84 token_val = '[%s]' % token_name 87 token_val = '[%s]' % token_name
85 path_func_name = (name + '_path') 88 path_func_name = (name + '_path')
86 89
87 if token_name in g: 90 if token_name in g:
88 tokens[token_name] = g[token_name] 91 tokens[token_name] = g[token_name]
89 g[token_name] = token_val 92 g[token_name] = token_val
90 93
91 if path_func_name in g: 94 if path_func_name in g:
92 path_funcs[path_func_name] = g[path_func_name] 95 path_funcs[path_func_name] = g[path_func_name]
93 g[path_func_name] = _path_method(path_func_name, token_val) 96 g[path_func_name] = _path_method(path_func_name, token_val)
97
98 path_funcs['path_exists'] = g['path_exists']
99 g['path_exists'] = lambda path: path in mock_path_exists
100
94 yield 101 yield
95 finally: 102 finally:
96 g.update(tokens) 103 g.update(tokens)
97 g.update(path_funcs) 104 g.update(path_funcs)
98 105
99 106
100 def deep_set(obj, key_vals): 107 def deep_set(obj, key_vals):
101 """Take an object (a dict or list), and a list of key/value pairs to set, 108 """Take an object (a dict or list), and a list of key/value pairs to set,
102 and transform it by replacing items in obj at the key locations with the 109 and transform it by replacing items in obj at the key locations with the
103 respective values. 110 respective values.
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 'recursive': recursive, 366 'recursive': recursive,
360 }, 367 },
361 }), 368 }),
362 self.git('fetch', 'origin', *recursive_args), 369 self.git('fetch', 'origin', *recursive_args),
363 self.git('update-ref', 'refs/heads/'+branch, 'origin/'+branch), 370 self.git('update-ref', 'refs/heads/'+branch, 'origin/'+branch),
364 self.git('clean', '-f', '-d', '-X'), 371 self.git('clean', '-f', '-d', '-X'),
365 self.git('checkout', '-f', branch), 372 self.git('checkout', '-f', branch),
366 self.git('submodule', 'update', '--init', '--recursive'), 373 self.git('submodule', 'update', '--init', '--recursive'),
367 ] 374 ]
368 375
369 def gclient_checkout(self, common_repo_name, git_mode=False): 376 def gclient_checkout(self, common_repo_name_or_spec, git_mode=False,
377 spec_name=None):
370 """Returns a step generator function for gclient checkouts.""" 378 """Returns a step generator function for gclient checkouts."""
371 spec = GCLIENT_COMMON_SPECS[common_repo_name](self) 379 if isinstance(common_repo_name_or_spec, basestring):
380 spec = GCLIENT_COMMON_SPECS[common_repo_name_or_spec](self)
381 else:
382 spec = common_repo_name_or_spec
372 spec_string = '' 383 spec_string = ''
384 if not spec_name:
385 step_name = lambda n: 'gclient ' + n
386 else:
387 step_name = lambda n: '[spec: %s] gclient %s' % (spec_name, n)
agable 2013/05/22 17:21:23 I'd rather have the spec_name emitted as a @@@STEP
mkosiba (inactive) 2013/05/23 13:13:38 The reason for this is not to differentiate in the
agable 2013/05/23 17:20:12 D'oh. SGTM, then.
373 for key in spec: 388 for key in spec:
374 # We should be using json.dumps here, but gclient directly execs the dict 389 # We should be using json.dumps here, but gclient directly execs the dict
375 # that it receives as the argument to --spec, so we have to have True, 390 # that it receives as the argument to --spec, so we have to have True,
376 # False, and None instead of JSON's true, false, and null. 391 # False, and None instead of JSON's true, false, and null.
377 spec_string += '%s = %s\n' % (key, str(spec[key])) 392 spec_string += '%s = %s\n' % (key, str(spec[key]))
378 gclient = depot_tools_path('gclient') + ('.bat' if IsWindows() else '') 393 gclient = depot_tools_path('gclient') + ('.bat' if IsWindows() else '')
379 394
380 if not git_mode: 395 if not git_mode:
381 clean_step = self.step('gclient clean', [gclient, 'revert', '--nohooks']) 396 clean_step = self.step(step_name('clean'),
382 sync_step = self.step('gclient sync', [gclient, 'sync', '--nohooks']) 397 [gclient, 'revert', '--nohooks'])
398 sync_step = self.step(step_name('sync'), [gclient, 'sync', '--nohooks'])
383 else: 399 else:
384 # clean() isn't used because the gclient sync flags passed in checkout() 400 # clean() isn't used because the gclient sync flags passed in checkout()
385 # do much the same thing, and they're more correct than doing a separate 401 # do much the same thing, and they're more correct than doing a separate
386 # 'gclient revert' because it makes sure the other args are correct when 402 # 'gclient revert' because it makes sure the other args are correct when
387 # a repo was deleted and needs to be re-cloned (notably 403 # a repo was deleted and needs to be re-cloned (notably
388 # --with_branch_heads), whereas 'revert' uses default args for clone 404 # --with_branch_heads), whereas 'revert' uses default args for clone
389 # operations. 405 # operations.
390 # 406 #
391 # TODO(mmoss): To be like current official builders, this step could just 407 # TODO(mmoss): To be like current official builders, this step could just
392 # delete the whole <slave_name>/build/ directory and start each build 408 # delete the whole <slave_name>/build/ directory and start each build
393 # from scratch. That might be the least bad solution, at least until we 409 # from scratch. That might be the least bad solution, at least until we
394 # have a reliable gclient method to produce a pristine working dir for 410 # have a reliable gclient method to produce a pristine working dir for
395 # git-based builds (e.g. maybe some combination of 'git reset/clean -fx' 411 # git-based builds (e.g. maybe some combination of 'git reset/clean -fx'
396 # and removing the 'out' directory). 412 # and removing the 'out' directory).
397 clean_step = None 413 clean_step = None
398 sync_step = self.step('gclient sync', [ 414 sync_step = self.step(step_name('sync'), [
399 gclient, 'sync', '--verbose', '--with_branch_heads', '--nohooks', 415 gclient, 'sync', '--verbose', '--with_branch_heads', '--nohooks',
400 '--reset', '--delete_unversioned_trees', '--force']) 416 '--reset', '--delete_unversioned_trees', '--force'])
401 steps = [ 417 steps = [
402 self.step( 418 self.step(
403 'gclient setup', 419 step_name('setup'),
404 [gclient, 'config', '--spec', spec_string], 420 [gclient, 'config', '--spec', spec_string],
405 static_json_data={ 421 static_json_data={
406 'CheckoutRoot': slave_build_path(spec['solutions'][0]['name']), 422 'CheckoutRoot': slave_build_path(spec['solutions'][0]['name']),
407 'CheckoutSCM': 'gclient', 423 'CheckoutSCM': 'gclient',
408 'CheckoutSpec': spec 424 'CheckoutSpec': spec
409 } 425 }
410 ), 426 ),
411 ] 427 ]
412 if clean_step: 428 if clean_step:
413 steps.append(clean_step) 429 steps.append(clean_step)
414 if sync_step: 430 if sync_step:
415 steps.append(sync_step) 431 steps.append(sync_step)
416 432
417 return steps 433 return steps
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698