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

Side by Side Diff: recipes.py

Issue 2131153002: update recipe bootstrap script (2c5509f) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: sync Created 4 years, 5 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 2
3 # Copyright 2015 The Chromium Authors. All rights reserved. 3 # Copyright 2016 The LUCI Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed under the Apache License, Version 2.0
5 # found in the LICENSE file. 5 # that can be found in the LICENSE file.
6 6
7 """Bootstrap script to clone and forward to the recipe engine tool.""" 7 """Bootstrap script to clone and forward to the recipe engine tool.
8
9 ***********************************************************************
10 ** DO NOT MODIFY EXCEPT IN THE PER-REPO CONFIGURATION SECTION BELOW. **
11 ***********************************************************************
12
13 This is a copy of https://github.com/luci/recipes-py/blob/master/doc/recipes.py.
14 To fix bugs, fix in the github repo then copy it back to here and fix the
15 PER-REPO CONFIGURATION section to look like this one.
16 """
17
18 import os
19
20 #### PER-REPO CONFIGURATION (editable) ####
21 # The root of the repository relative to the directory of this file.
22 REPO_ROOT = ''
23 # The path of the recipes.cfg file relative to the root of the repository.
24 RECIPES_CFG = os.path.join('infra', 'config', 'recipes.cfg')
25 #### END PER-REPO CONFIGURATION ####
26
27 BOOTSTRAP_VERSION = 1
8 28
9 import ast 29 import ast
10 import logging 30 import logging
11 import os
12 import random 31 import random
13 import re 32 import re
14 import subprocess 33 import subprocess
15 import sys 34 import sys
16 import time 35 import time
17 import traceback 36 import traceback
18 37
19 BOOTSTRAP_VERSION = 1
20 # The root of the repository relative to the directory of this file.
21 REPO_ROOT = ''
22 # The path of the recipes.cfg file relative to the root of the repository.
23 RECIPES_CFG = os.path.join('infra', 'config', 'recipes.cfg')
24
25 38
26 def parse_protobuf(fh): 39 def parse_protobuf(fh):
27 """Parse the protobuf text format just well enough to understand recipes.cfg. 40 """Parse the protobuf text format just well enough to understand recipes.cfg.
28 41
29 We don't use the protobuf library because we want to be as self-contained 42 We don't use the protobuf library because we want to be as self-contained
30 as possible in this bootstrap, so it can be simply vendored into a client 43 as possible in this bootstrap, so it can be simply vendored into a client
31 repo. 44 repo.
32 45
33 We assume all fields are repeated since we don't have a proto spec to work 46 We assume all fields are repeated since we don't have a proto spec to work
34 with. 47 with.
35 48
36 Args: 49 Args:
37 fh: a filehandle containing the text format protobuf. 50 fh: a filehandle containing the text format protobuf.
38 Returns: 51 Returns:
39 A recursive dictionary of lists. 52 A recursive dictionary of lists.
40 """ 53 """
41 def parse_atom(text): 54 def parse_atom(text):
42 if text == 'true': return True 55 if text == 'true':
43 if text == 'false': return False 56 return True
57 if text == 'false':
58 return False
44 return ast.literal_eval(text) 59 return ast.literal_eval(text)
45 60
46 ret = {} 61 ret = {}
47 for line in fh: 62 for line in fh:
48 line = line.strip() 63 line = line.strip()
49 m = re.match(r'(\w+)\s*:\s*(.*)', line) 64 m = re.match(r'(\w+)\s*:\s*(.*)', line)
50 if m: 65 if m:
51 ret.setdefault(m.group(1), []).append(parse_atom(m.group(2))) 66 ret.setdefault(m.group(1), []).append(parse_atom(m.group(2)))
52 continue 67 continue
53 68
54 m = re.match(r'(\w+)\s*{', line) 69 m = re.match(r'(\w+)\s*{', line)
55 if m: 70 if m:
56 subparse = parse_protobuf(fh) 71 subparse = parse_protobuf(fh)
57 ret.setdefault(m.group(1), []).append(subparse) 72 ret.setdefault(m.group(1), []).append(subparse)
58 continue 73 continue
59 74
60 if line == '}': return ret 75 if line == '}':
61 if line == '': continue 76 return ret
77 if line == '':
78 continue
62 79
63 raise Exception('Could not understand line: <%s>' % line) 80 raise ValueError('Could not understand line: <%s>' % line)
64 81
65 return ret 82 return ret
66 83
67 84
68 def get_unique(things): 85 def get_unique(things):
69 if len(things) == 1: 86 if len(things) == 1:
70 return things[0] 87 return things[0]
71 elif len(things) == 0: 88 elif len(things) == 0:
72 raise ValueError("Expected to get one thing, but dinna get none.") 89 raise ValueError("Expected to get one thing, but dinna get none.")
73 else: 90 else:
74 logging.warn('Expected to get one thing, but got a bunch: %s\n%s' % 91 logging.warn('Expected to get one thing, but got a bunch: %s\n%s' %
75 (things, traceback.format_stack())) 92 (things, traceback.format_stack()))
76 return things[0] 93 return things[0]
77 94
78 95
96 def _subprocess_call(argv, **kwargs):
97 logging.info('Running %r', argv)
98 return subprocess.call(argv, **kwargs)
99
100 def _subprocess_check_call(argv, **kwargs):
101 logging.info('Running %r', argv)
102 subprocess.check_call(argv, **kwargs)
103
104
79 def main(): 105 def main():
106 if '--verbose' in sys.argv:
107 logging.getLogger().setLevel(logging.INFO)
108
80 if sys.platform.startswith(('win', 'cygwin')): 109 if sys.platform.startswith(('win', 'cygwin')):
81 git = 'git.bat' 110 git = 'git.bat'
82 else: 111 else:
83 git = 'git' 112 git = 'git'
84 113
85 # Find the repository and config file to operate on. 114 # Find the repository and config file to operate on.
86 repo_root = os.path.abspath( 115 repo_root = os.path.abspath(
87 os.path.join(os.path.dirname(__file__), REPO_ROOT)) 116 os.path.join(os.path.dirname(__file__), REPO_ROOT))
88 recipes_cfg_path = os.path.join(repo_root, RECIPES_CFG) 117 recipes_cfg_path = os.path.join(repo_root, RECIPES_CFG)
89 118
(...skipping 10 matching lines...) Expand all
100 recipes_path = os.path.join(repo_root, 129 recipes_path = os.path.join(repo_root,
101 get_unique(protobuf['recipes_path']).replace('/', os.path.sep)) 130 get_unique(protobuf['recipes_path']).replace('/', os.path.sep))
102 deps_path = os.path.join(recipes_path, '.recipe_deps') 131 deps_path = os.path.join(recipes_path, '.recipe_deps')
103 engine_path = os.path.join(deps_path, 'recipe_engine') 132 engine_path = os.path.join(deps_path, 'recipe_engine')
104 133
105 # Ensure that we have the recipe engine cloned. 134 # Ensure that we have the recipe engine cloned.
106 def ensure_engine(): 135 def ensure_engine():
107 if not os.path.exists(deps_path): 136 if not os.path.exists(deps_path):
108 os.makedirs(deps_path) 137 os.makedirs(deps_path)
109 if not os.path.exists(engine_path): 138 if not os.path.exists(engine_path):
110 subprocess.check_call([git, 'clone', engine_url, engine_path]) 139 _subprocess_check_call([git, 'clone', engine_url, engine_path])
111 140
112 needs_fetch = subprocess.call( 141 needs_fetch = _subprocess_call(
113 [git, 'rev-parse', '--verify', '%s^{commit}' % engine_revision], 142 [git, 'rev-parse', '--verify', '%s^{commit}' % engine_revision],
114 cwd=engine_path, stdout=open(os.devnull, 'w')) 143 cwd=engine_path, stdout=open(os.devnull, 'w'))
115 if needs_fetch: 144 if needs_fetch:
116 subprocess.check_call([git, 'fetch'], cwd=engine_path) 145 _subprocess_check_call([git, 'fetch'], cwd=engine_path)
117 subprocess.check_call( 146 _subprocess_check_call(
118 [git, 'checkout', '--quiet', engine_revision], cwd=engine_path) 147 [git, 'checkout', '--quiet', engine_revision], cwd=engine_path)
119 148
120 try: 149 try:
121 ensure_engine() 150 ensure_engine()
122 except subprocess.CalledProcessError as e: 151 except subprocess.CalledProcessError:
123 if e.returncode == 128: # Thrown when git gets a lock error. 152 logging.exception('ensure_engine failed')
124 time.sleep(random.uniform(2,5)) 153
125 ensure_engine() 154 # Retry errors.
126 else: 155 time.sleep(random.uniform(2,5))
127 raise 156 ensure_engine()
128 157
129 args = ['--package', recipes_cfg_path, 158 args = ['--package', recipes_cfg_path,
130 '--bootstrap-script', __file__] + sys.argv[1:] 159 '--bootstrap-script', __file__] + sys.argv[1:]
131 return subprocess.call([ 160 return _subprocess_call([
132 sys.executable, '-u', 161 sys.executable, '-u',
133 os.path.join(engine_path, engine_subpath, 'recipes.py')] + args) 162 os.path.join(engine_path, engine_subpath, 'recipes.py')] + args)
134 163
135 if __name__ == '__main__': 164 if __name__ == '__main__':
136 sys.exit(main()) 165 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