OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 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 # TODO(hinoka): Use logging. | 6 # TODO(hinoka): Use logging. |
7 | 7 |
8 import cStringIO | 8 import cStringIO |
9 import codecs | 9 import codecs |
10 import collections | 10 import collections |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 '..', # ROOT_DIR | 66 '..', # ROOT_DIR |
67 'build', | 67 'build', |
68 'scripts'), | 68 'scripts'), |
69 path.join(SLAVE_DIR, '..', 'build', 'scripts'), | 69 path.join(SLAVE_DIR, '..', 'build', 'scripts'), |
70 ], default=path.dirname(THIS_DIR)) | 70 ], default=path.dirname(THIS_DIR)) |
71 BUILD_DIR = path.dirname(SCRIPTS_DIR) | 71 BUILD_DIR = path.dirname(SCRIPTS_DIR) |
72 ROOT_DIR = path.dirname(BUILD_DIR) | 72 ROOT_DIR = path.dirname(BUILD_DIR) |
73 | 73 |
74 DEPOT_TOOLS_DIR = path.abspath(path.join(THIS_DIR, '..', '..', '..')) | 74 DEPOT_TOOLS_DIR = path.abspath(path.join(THIS_DIR, '..', '..', '..')) |
75 | 75 |
76 BUILD_INTERNAL_DIR = check_dir( | |
77 'build_internal', [ | |
78 path.join(ROOT_DIR, 'build_internal'), | |
79 path.join(ROOT_DIR, # .recipe_deps | |
80 path.pardir, # slave | |
81 path.pardir, # scripts | |
82 path.pardir), # build_internal | |
83 ]) | |
84 | |
85 | |
86 CHROMIUM_GIT_HOST = 'https://chromium.googlesource.com' | 76 CHROMIUM_GIT_HOST = 'https://chromium.googlesource.com' |
87 CHROMIUM_SRC_URL = CHROMIUM_GIT_HOST + '/chromium/src.git' | 77 CHROMIUM_SRC_URL = CHROMIUM_GIT_HOST + '/chromium/src.git' |
88 | 78 |
79 RECOGNIZED_PATHS = { | |
iannucci
2016/02/11 00:56:21
followup CL: what will it take to get rid of this?
hinoka
2016/02/11 20:10:06
Remove all references to SVN in buildbot master co
| |
80 '/chrome/trunk/src': | |
81 CHROMIUM_SRC_URL, | |
82 '/chrome/trunk/src/tools/cros.DEPS': | |
83 CHROMIUM_GIT_HOST + '/chromium/src/tools/cros.DEPS.git', | |
84 '/chrome-internal/trunk/src-internal': | |
85 'https://chrome-internal.googlesource.com/chrome/src-internal.git', | |
86 } | |
87 | |
89 # Official builds use buildspecs, so this is a special case. | 88 # Official builds use buildspecs, so this is a special case. |
90 BUILDSPEC_TYPE = collections.namedtuple('buildspec', | 89 BUILDSPEC_TYPE = collections.namedtuple('buildspec', |
91 ('container', 'version')) | 90 ('container', 'version')) |
92 BUILDSPEC_RE = (r'^/chrome-internal/trunk/tools/buildspec/' | 91 BUILDSPEC_RE = (r'^/chrome-internal/trunk/tools/buildspec/' |
93 '(build|branches|releases)/(.+)$') | 92 '(build|branches|releases)/(.+)$') |
94 GIT_BUILDSPEC_PATH = ('https://chrome-internal.googlesource.com/chrome/tools/' | 93 GIT_BUILDSPEC_PATH = ('https://chrome-internal.googlesource.com/chrome/tools/' |
95 'buildspec') | 94 'buildspec') |
96 BRANCH_HEADS_REFSPEC = '+refs/branch-heads/*' | 95 BRANCH_HEADS_REFSPEC = '+refs/branch-heads/*' |
97 | 96 |
98 BUILDSPEC_COMMIT_RE = ( | 97 BUILDSPEC_COMMIT_RE = ( |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
161 'src/tools/swarm_client/': 'got_swarm_client_revision', | 160 'src/tools/swarm_client/': 'got_swarm_client_revision', |
162 'src/tools/swarming_client/': 'got_swarming_client_revision', | 161 'src/tools/swarming_client/': 'got_swarming_client_revision', |
163 'src/third_party/WebKit/': 'got_webkit_revision', | 162 'src/third_party/WebKit/': 'got_webkit_revision', |
164 'src/third_party/webrtc/': 'got_webrtc_revision', | 163 'src/third_party/webrtc/': 'got_webrtc_revision', |
165 'src/v8/': 'got_v8_revision', | 164 'src/v8/': 'got_v8_revision', |
166 } | 165 } |
167 } | 166 } |
168 | 167 |
169 | 168 |
170 BOT_UPDATE_MESSAGE = """ | 169 BOT_UPDATE_MESSAGE = """ |
171 What is the "Bot Update" step? | 170 Bot Update Debugging information: |
172 ============================== | |
173 | |
174 This step ensures that the source checkout on the bot (e.g. Chromium's src/ and | |
175 its dependencies) is checked out in a consistent state. This means that all of | |
176 the necessary repositories are checked out, no extra repositories are checked | |
177 out, and no locally modified files are present. | |
178 | |
179 These actions used to be taken care of by the "gclient revert" and "update" | |
180 steps. However, those steps are known to be buggy and occasionally flaky. This | |
181 step has two main advantages over them: | |
182 * it only operates in Git, so the logic can be clearer and cleaner; and | |
183 * it is a slave-side script, so its behavior can be modified without | |
184 restarting the master. | |
185 | |
186 Why Git, you ask? Because that is the direction that the Chromium project is | |
187 heading. This step is an integral part of the transition from using the SVN repo | |
188 at chrome/trunk/src to using the Git repo src.git. Please pardon the dust while | |
189 we fully convert everything to Git. This message will get out of your way | |
190 eventually, and the waterfall will be a happier place because of it. | |
191 | |
192 This step can be activated or deactivated independently on every builder on | |
193 every master. When it is active, the "gclient revert" and "update" steps become | |
194 no-ops. When it is inactive, it prints this message, cleans up after itself, and | |
195 lets everything else continue as though nothing has changed. Eventually, when | |
196 everything is stable enough, this step will replace them entirely. | |
197 | |
198 Debugging information: | |
199 (master/builder/slave may be unspecified on recipes) | 171 (master/builder/slave may be unspecified on recipes) |
200 master: %(master)s | 172 master: %(master)s |
201 builder: %(builder)s | 173 builder: %(builder)s |
202 slave: %(slave)s | 174 slave: %(slave)s |
203 forced by recipes: %(recipe)s | 175 forced by recipes: %(recipe)s |
204 CURRENT_DIR: %(CURRENT_DIR)s | 176 CURRENT_DIR: %(CURRENT_DIR)s |
205 BUILDER_DIR: %(BUILDER_DIR)s | 177 BUILDER_DIR: %(BUILDER_DIR)s |
206 SLAVE_DIR: %(SLAVE_DIR)s | 178 SLAVE_DIR: %(SLAVE_DIR)s |
207 THIS_DIR: %(THIS_DIR)s | 179 THIS_DIR: %(THIS_DIR)s |
208 SCRIPTS_DIR: %(SCRIPTS_DIR)s | 180 SCRIPTS_DIR: %(SCRIPTS_DIR)s |
209 BUILD_DIR: %(BUILD_DIR)s | 181 BUILD_DIR: %(BUILD_DIR)s |
210 ROOT_DIR: %(ROOT_DIR)s | 182 ROOT_DIR: %(ROOT_DIR)s |
211 DEPOT_TOOLS_DIR: %(DEPOT_TOOLS_DIR)s | 183 DEPOT_TOOLS_DIR: %(DEPOT_TOOLS_DIR)s |
212 bot_update.py is:""" | 184 bot_update.py is:""" |
iannucci
2016/02/11 00:56:21
is: Active?
Should this line be removed?
hinoka
2016/02/11 20:10:05
Done.
| |
213 | 185 |
214 ACTIVATED_MESSAGE = """ACTIVE. | |
215 The bot will perform a Git checkout in this step. | |
216 The "gclient revert" and "update" steps are no-ops. | |
217 | |
218 """ | |
219 | |
220 NOT_ACTIVATED_MESSAGE = """INACTIVE. | |
221 This step does nothing. You actually want to look at the "update" step. | |
222 | |
223 """ | |
224 | |
225 | |
226 GCLIENT_TEMPLATE = """solutions = %(solutions)s | 186 GCLIENT_TEMPLATE = """solutions = %(solutions)s |
227 | 187 |
228 cache_dir = r%(cache_dir)s | 188 cache_dir = r%(cache_dir)s |
229 %(target_os)s | 189 %(target_os)s |
230 %(target_os_only)s | 190 %(target_os_only)s |
231 """ | 191 """ |
232 | 192 |
233 | 193 |
234 internal_data = {} | |
235 if BUILD_INTERNAL_DIR: | |
236 local_vars = {} | |
237 try: | |
238 execfile(os.path.join( | |
239 BUILD_INTERNAL_DIR, 'scripts', 'slave', 'bot_update_cfg.py'), | |
240 local_vars) | |
241 except Exception: | |
242 # Same as if BUILD_INTERNAL_DIR didn't exist in the first place. | |
243 print 'Warning: unable to read internal configuration file.' | |
244 print 'If this is an internal bot, this step may be erroneously inactive.' | |
245 internal_data = local_vars | |
246 | |
247 RECOGNIZED_PATHS = { | |
248 # If SVN path matches key, the entire URL is rewritten to the Git url. | |
249 '/chrome/trunk/src': | |
250 CHROMIUM_SRC_URL, | |
251 '/chrome/trunk/src/tools/cros.DEPS': | |
252 CHROMIUM_GIT_HOST + '/chromium/src/tools/cros.DEPS.git', | |
253 } | |
254 RECOGNIZED_PATHS.update(internal_data.get('RECOGNIZED_PATHS', {})) | |
255 | |
256 ENABLED_MASTERS = [ | |
257 'bot_update.always_on', | |
258 'chromium.android', | |
259 'chromium.angle', | |
260 'chromium.chrome', | |
261 'chromium.chromedriver', | |
262 'chromium.chromiumos', | |
263 'chromium', | |
264 'chromium.fyi', | |
265 'chromium.goma', | |
266 'chromium.gpu', | |
267 'chromium.gpu.fyi', | |
268 'chromium.infra', | |
269 'chromium.infra.cron', | |
270 'chromium.linux', | |
271 'chromium.lkgr', | |
272 'chromium.mac', | |
273 'chromium.memory', | |
274 'chromium.memory.fyi', | |
275 'chromium.perf', | |
276 'chromium.perf.fyi', | |
277 'chromium.swarm', | |
278 'chromium.webkit', | |
279 'chromium.webrtc', | |
280 'chromium.webrtc.fyi', | |
281 'chromium.win', | |
282 'client.catapult', | |
283 'client.drmemory', | |
284 'client.mojo', | |
285 'client.nacl', | |
286 'client.nacl.ports', | |
287 'client.nacl.sdk', | |
288 'client.nacl.toolchain', | |
289 'client.pdfium', | |
290 'client.skia', | |
291 'client.skia.fyi', | |
292 'client.v8', | |
293 'client.v8.branches', | |
294 'client.v8.fyi', | |
295 'client.webrtc', | |
296 'client.webrtc.fyi', | |
297 'tryserver.blink', | |
298 'tryserver.client.catapult', | |
299 'tryserver.client.mojo', | |
300 'tryserver.chromium.android', | |
301 'tryserver.chromium.angle', | |
302 'tryserver.chromium.linux', | |
303 'tryserver.chromium.mac', | |
304 'tryserver.chromium.perf', | |
305 'tryserver.chromium.win', | |
306 'tryserver.infra', | |
307 'tryserver.nacl', | |
308 'tryserver.v8', | |
309 'tryserver.webrtc', | |
310 ] | |
311 ENABLED_MASTERS += internal_data.get('ENABLED_MASTERS', []) | |
312 | |
313 ENABLED_BUILDERS = { | |
314 'client.dart.fyi': [ | |
315 'v8-linux-release', | |
316 'v8-mac-release', | |
317 'v8-win-release', | |
318 ], | |
319 'client.dynamorio': [ | |
320 'linux-v8-dr', | |
321 ], | |
322 } | |
323 ENABLED_BUILDERS.update(internal_data.get('ENABLED_BUILDERS', {})) | |
324 | |
325 ENABLED_SLAVES = {} | |
326 ENABLED_SLAVES.update(internal_data.get('ENABLED_SLAVES', {})) | |
327 | |
328 # Disabled filters get run AFTER enabled filters, so for example if a builder | |
329 # config is enabled, but a bot on that builder is disabled, that bot will | |
330 # be disabled. | |
331 DISABLED_BUILDERS = {} | |
332 DISABLED_BUILDERS.update(internal_data.get('DISABLED_BUILDERS', {})) | |
333 | |
334 DISABLED_SLAVES = {} | |
335 DISABLED_SLAVES.update(internal_data.get('DISABLED_SLAVES', {})) | |
336 | |
337 # These masters work only in Git, meaning for got_revision, always output | |
338 # a git hash rather than a SVN rev. | |
339 GIT_MASTERS = [ | |
340 'client.v8', | |
341 'client.v8.branches', | |
342 'tryserver.v8', | |
343 ] | |
344 GIT_MASTERS += internal_data.get('GIT_MASTERS', []) | |
345 | |
346 | |
347 # How many times to try before giving up. | 194 # How many times to try before giving up. |
348 ATTEMPTS = 5 | 195 ATTEMPTS = 5 |
349 | 196 |
350 # Find deps2git | |
351 DEPS2GIT_DIR_PATH = path.join(SCRIPTS_DIR, 'tools', 'deps2git') | |
352 DEPS2GIT_PATH = path.join(DEPS2GIT_DIR_PATH, 'deps2git.py') | |
353 S2G_INTERNAL_PATH = path.join(SCRIPTS_DIR, 'tools', 'deps2git_internal', | |
354 'svn_to_git_internal.py') | |
355 GIT_CACHE_PATH = path.join(DEPOT_TOOLS_DIR, 'git_cache.py') | 197 GIT_CACHE_PATH = path.join(DEPOT_TOOLS_DIR, 'git_cache.py') |
356 | 198 |
357 # Find the patch tool. | 199 # Find the patch tool. |
358 if sys.platform.startswith('win'): | 200 if sys.platform.startswith('win'): |
359 if not BUILD_INTERNAL_DIR: | 201 PATCH_TOOL = path.join(DEPOT_TOOLS_DIR, 'patch.EXE') |
iannucci
2016/02/11 00:56:20
let's definitely change this to be a module resour
hinoka
2016/02/11 20:10:05
Done.
You mean THIS_DIR, right?
| |
360 print 'Warning: could not find patch tool because there is no ' | |
361 print 'build_internal present.' | |
362 PATCH_TOOL = None | |
363 else: | |
364 PATCH_TOOL = path.join(BUILD_INTERNAL_DIR, 'tools', 'patch.EXE') | |
365 else: | 202 else: |
366 PATCH_TOOL = '/usr/bin/patch' | 203 PATCH_TOOL = '/usr/bin/patch' |
367 | 204 |
368 # If there is less than 100GB of disk space on the system, then we do | 205 # If there is less than 100GB of disk space on the system, then we do |
369 # a shallow checkout. | 206 # a shallow checkout. |
370 SHALLOW_CLONE_THRESHOLD = 100 * 1024 * 1024 * 1024 | 207 SHALLOW_CLONE_THRESHOLD = 100 * 1024 * 1024 * 1024 |
371 | 208 |
372 | 209 |
373 class SubprocessFailed(Exception): | 210 class SubprocessFailed(Exception): |
374 def __init__(self, message, code, output): | 211 def __init__(self, message, code, output): |
(...skipping 11 matching lines...) Expand all Loading... | |
386 | 223 |
387 | 224 |
388 class SVNRevisionNotFound(Exception): | 225 class SVNRevisionNotFound(Exception): |
389 pass | 226 pass |
390 | 227 |
391 | 228 |
392 class InvalidDiff(Exception): | 229 class InvalidDiff(Exception): |
393 pass | 230 pass |
394 | 231 |
395 | 232 |
396 class Inactive(Exception): | |
397 """Not really an exception, just used to exit early cleanly.""" | |
398 pass | |
399 | |
400 | |
401 RETRY = object() | 233 RETRY = object() |
402 OK = object() | 234 OK = object() |
403 FAIL = object() | 235 FAIL = object() |
404 | 236 |
405 | 237 |
406 class PsPrinter(object): | 238 class PsPrinter(object): |
407 def __init__(self, interval=300): | 239 def __init__(self, interval=300): |
408 self.interval = interval | 240 self.interval = interval |
409 self.active = sys.platform.startswith('linux2') | 241 self.active = sys.platform.startswith('linux2') |
410 self.thread = None | 242 self.thread = None |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
519 | 351 |
520 def get_gclient_spec(solutions, target_os, target_os_only, git_cache_dir): | 352 def get_gclient_spec(solutions, target_os, target_os_only, git_cache_dir): |
521 return GCLIENT_TEMPLATE % { | 353 return GCLIENT_TEMPLATE % { |
522 'solutions': pprint.pformat(solutions, indent=4), | 354 'solutions': pprint.pformat(solutions, indent=4), |
523 'cache_dir': '"%s"' % git_cache_dir, | 355 'cache_dir': '"%s"' % git_cache_dir, |
524 'target_os': ('\ntarget_os=%s' % target_os) if target_os else '', | 356 'target_os': ('\ntarget_os=%s' % target_os) if target_os else '', |
525 'target_os_only': '\ntarget_os_only=%s' % target_os_only | 357 'target_os_only': '\ntarget_os_only=%s' % target_os_only |
526 } | 358 } |
527 | 359 |
528 | 360 |
529 def check_enabled(master, builder, slave): | |
530 if master in ENABLED_MASTERS: | |
531 return True | |
532 builder_list = ENABLED_BUILDERS.get(master) | |
533 if builder_list and builder in builder_list: | |
534 return True | |
535 slave_list = ENABLED_SLAVES.get(master) | |
536 if slave_list and slave in slave_list: | |
537 return True | |
538 return False | |
539 | |
540 | |
541 def check_disabled(master, builder, slave): | |
542 """Returns True if disabled, False if not disabled.""" | |
543 builder_list = DISABLED_BUILDERS.get(master) | |
544 if builder_list and builder in builder_list: | |
545 return True | |
546 slave_list = DISABLED_SLAVES.get(master) | |
547 if slave_list and slave in slave_list: | |
548 return True | |
549 return False | |
550 | |
551 | |
552 def check_valid_host(master, builder, slave): | |
553 return (check_enabled(master, builder, slave) | |
554 and not check_disabled(master, builder, slave)) | |
555 | |
556 | |
557 def maybe_ignore_revision(revision, buildspec): | 361 def maybe_ignore_revision(revision, buildspec): |
558 """Handle builders that don't care what buildbot tells them to build. | 362 """Handle builders that don't care what buildbot tells them to build. |
559 | 363 |
560 This is especially the case with branch builders that build from buildspecs | 364 This is especially the case with branch builders that build from buildspecs |
561 and/or trigger off multiple repositories, where the --revision passed in has | 365 and/or trigger off multiple repositories, where the --revision passed in has |
562 nothing to do with the solution being built. Clearing the revision in this | 366 nothing to do with the solution being built. Clearing the revision in this |
563 case causes bot_update to use HEAD rather that trying to checkout an | 367 case causes bot_update to use HEAD rather that trying to checkout an |
564 inappropriate version of the solution. | 368 inappropriate version of the solution. |
565 """ | 369 """ |
566 if buildspec and buildspec.container == 'branches': | 370 if buildspec and buildspec.container == 'branches': |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
774 footers[m.group(1)] = m.group(2).strip() | 578 footers[m.group(1)] = m.group(2).strip() |
775 return footers | 579 return footers |
776 | 580 |
777 | 581 |
778 def get_commit_message_footer(message, key): | 582 def get_commit_message_footer(message, key): |
779 """Returns: (str/None) The footer value for 'key', or None if none was found. | 583 """Returns: (str/None) The footer value for 'key', or None if none was found. |
780 """ | 584 """ |
781 return get_commit_message_footer_map(message).get(key) | 585 return get_commit_message_footer_map(message).get(key) |
782 | 586 |
783 | 587 |
784 def get_svn_rev(git_hash, dir_name): | |
785 log = git('log', '-1', git_hash, cwd=dir_name) | |
786 git_svn_id = get_commit_message_footer(log, GIT_SVN_ID_FOOTER_KEY) | |
787 if not git_svn_id: | |
788 return None | |
789 m = GIT_SVN_ID_RE.match(git_svn_id) | |
790 if not m: | |
791 return None | |
792 return int(m.group(2)) | |
793 | |
794 | |
795 def get_git_hash(revision, branch, sln_dir): | 588 def get_git_hash(revision, branch, sln_dir): |
796 """We want to search for the SVN revision on the git-svn branch. | 589 """We want to search for the SVN revision on the git-svn branch. |
797 | 590 |
798 Note that git will search backwards from origin/master. | 591 Note that git will search backwards from origin/master. |
799 """ | 592 """ |
800 match = "^%s: [^ ]*@%s " % (GIT_SVN_ID_FOOTER_KEY, revision) | 593 match = "^%s: [^ ]*@%s " % (GIT_SVN_ID_FOOTER_KEY, revision) |
801 ref = branch if branch.startswith('refs/') else 'origin/%s' % branch | 594 ref = branch if branch.startswith('refs/') else 'origin/%s' % branch |
802 cmd = ['log', '-E', '--grep', match, '--format=%H', '--max-count=1', ref] | 595 cmd = ['log', '-E', '--grep', match, '--format=%H', '--max-count=1', ref] |
803 result = git(*cmd, cwd=sln_dir).strip() | 596 result = git(*cmd, cwd=sln_dir).strip() |
804 if result: | 597 if result: |
805 return result | 598 return result |
806 raise SVNRevisionNotFound('We can\'t resolve svn r%s into a git hash in %s' % | 599 raise SVNRevisionNotFound('We can\'t resolve svn r%s into a git hash in %s' % |
807 (revision, sln_dir)) | 600 (revision, sln_dir)) |
808 | 601 |
809 | 602 |
810 def _last_commit_for_file(filename, repo_base): | |
811 cmd = ['log', '--format=%H', '--max-count=1', '--', filename] | |
812 return git(*cmd, cwd=repo_base).strip() | |
813 | |
814 | |
815 def need_to_run_deps2git(repo_base, deps_file, deps_git_file): | |
816 """Checks to see if we need to run deps2git. | |
817 | |
818 Returns True if there was a DEPS change after the last .DEPS.git update | |
819 or if DEPS has local modifications. | |
820 """ | |
821 # See if DEPS is dirty | |
822 deps_file_status = git( | |
823 'status', '--porcelain', deps_file, cwd=repo_base).strip() | |
824 if deps_file_status and deps_file_status.startswith('M '): | |
825 return True | |
826 | |
827 last_known_deps_ref = _last_commit_for_file(deps_file, repo_base) | |
828 last_known_deps_git_ref = _last_commit_for_file(deps_git_file, repo_base) | |
829 merge_base_ref = git('merge-base', last_known_deps_ref, | |
830 last_known_deps_git_ref, cwd=repo_base).strip() | |
831 | |
832 # If the merge base of the last DEPS and last .DEPS.git file is not | |
833 # equivilent to the hash of the last DEPS file, that means the DEPS file | |
834 # was committed after the last .DEPS.git file. | |
835 return last_known_deps_ref != merge_base_ref | |
836 | |
837 | |
838 def ensure_deps2git(solution, shallow, git_cache_dir): | |
839 repo_base = path.join(os.getcwd(), solution['name']) | |
840 deps_file = path.join(repo_base, 'DEPS') | |
841 deps_git_file = path.join(repo_base, '.DEPS.git') | |
842 if (not git('ls-files', 'DEPS', cwd=repo_base).strip() or | |
843 not git('ls-files', '.DEPS.git', cwd=repo_base).strip()): | |
844 return | |
845 | |
846 print 'Checking if %s is newer than %s' % (deps_file, deps_git_file) | |
847 if not need_to_run_deps2git(repo_base, deps_file, deps_git_file): | |
848 return | |
849 | |
850 print '===DEPS file modified, need to run deps2git===' | |
851 cmd = [sys.executable, DEPS2GIT_PATH, | |
852 '--workspace', os.getcwd(), | |
853 '--cache_dir', git_cache_dir, | |
854 '--deps', deps_file, | |
855 '--out', deps_git_file] | |
856 if 'chrome-internal.googlesource' in solution['url']: | |
857 cmd.extend(['--extra-rules', S2G_INTERNAL_PATH]) | |
858 if shallow: | |
859 cmd.append('--shallow') | |
860 call(*cmd) | |
861 | |
862 | |
863 def emit_log_lines(name, lines): | 603 def emit_log_lines(name, lines): |
864 for line in lines.splitlines(): | 604 for line in lines.splitlines(): |
865 print '@@@STEP_LOG_LINE@%s@%s@@@' % (name, line) | 605 print '@@@STEP_LOG_LINE@%s@%s@@@' % (name, line) |
866 print '@@@STEP_LOG_END@%s@@@' % name | 606 print '@@@STEP_LOG_END@%s@@@' % name |
867 | 607 |
868 | 608 |
869 def emit_properties(properties): | 609 def emit_properties(properties): |
870 for property_name, property_value in sorted(properties.items()): | 610 for property_name, property_value in sorted(properties.items()): |
871 print '@@@SET_BUILD_PROPERTY@%s@"%s"@@@' % (property_name, property_value) | 611 print '@@@SET_BUILD_PROPERTY@%s@"%s"@@@' % (property_name, property_value) |
872 | 612 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
918 # rev_num is really a svn revision number, convert it into a git hash. | 658 # rev_num is really a svn revision number, convert it into a git hash. |
919 git_ref = get_git_hash(int(revision), branch, folder_name) | 659 git_ref = get_git_hash(int(revision), branch, folder_name) |
920 else: | 660 else: |
921 # rev_num is actually a git hash or ref, we can just use it. | 661 # rev_num is actually a git hash or ref, we can just use it. |
922 git_ref = revision | 662 git_ref = revision |
923 git('checkout', '--force', git_ref, cwd=folder_name) | 663 git('checkout', '--force', git_ref, cwd=folder_name) |
924 else: | 664 else: |
925 ref = branch if branch.startswith('refs/') else 'origin/%s' % branch | 665 ref = branch if branch.startswith('refs/') else 'origin/%s' % branch |
926 git('checkout', '--force', ref, cwd=folder_name) | 666 git('checkout', '--force', ref, cwd=folder_name) |
927 | 667 |
668 | |
928 def git_checkout(solutions, revisions, shallow, refs, git_cache_dir): | 669 def git_checkout(solutions, revisions, shallow, refs, git_cache_dir): |
929 build_dir = os.getcwd() | 670 build_dir = os.getcwd() |
930 # Before we do anything, break all git_cache locks. | 671 # Before we do anything, break all git_cache locks. |
931 if path.isdir(git_cache_dir): | 672 if path.isdir(git_cache_dir): |
932 git('cache', 'unlock', '-vv', '--force', '--all', | 673 git('cache', 'unlock', '-vv', '--force', '--all', |
933 '--cache-dir', git_cache_dir) | 674 '--cache-dir', git_cache_dir) |
934 for item in os.listdir(git_cache_dir): | 675 for item in os.listdir(git_cache_dir): |
935 filename = os.path.join(git_cache_dir, item) | 676 filename = os.path.join(git_cache_dir, item) |
936 if item.endswith('.lock'): | 677 if item.endswith('.lock'): |
937 raise Exception('%s exists after cache unlock' % filename) | 678 raise Exception('%s exists after cache unlock' % filename) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
978 # Exited abnormally, theres probably something wrong. | 719 # Exited abnormally, theres probably something wrong. |
979 # Lets wipe the checkout and try again. | 720 # Lets wipe the checkout and try again. |
980 tries_left -= 1 | 721 tries_left -= 1 |
981 if tries_left > 0: | 722 if tries_left > 0: |
982 print 'Something failed: %s.' % str(e) | 723 print 'Something failed: %s.' % str(e) |
983 print 'waiting 5 seconds and trying again...' | 724 print 'waiting 5 seconds and trying again...' |
984 time.sleep(5) | 725 time.sleep(5) |
985 else: | 726 else: |
986 raise | 727 raise |
987 remove(sln_dir) | 728 remove(sln_dir) |
988 except SVNRevisionNotFound: | |
989 tries_left -= 1 | |
990 if tries_left > 0: | |
991 # If we don't have the correct revision, wait and try again. | |
992 print 'We can\'t find revision %s.' % revision | |
993 print 'The svn to git replicator is probably falling behind.' | |
994 print 'waiting 5 seconds and trying again...' | |
995 time.sleep(5) | |
996 else: | |
997 raise | |
998 | 729 |
999 git('clean', '-dff', cwd=sln_dir) | 730 git('clean', '-dff', cwd=sln_dir) |
1000 | 731 |
1001 if first_solution: | 732 if first_solution: |
1002 git_ref = git('log', '--format=%H', '--max-count=1', | 733 git_ref = git('log', '--format=%H', '--max-count=1', |
1003 cwd=sln_dir).strip() | 734 cwd=sln_dir).strip() |
1004 first_solution = False | 735 first_solution = False |
1005 return git_ref | 736 return git_ref |
1006 | 737 |
1007 | 738 |
1008 def _download(url): | |
1009 """Fetch url and return content, with retries for flake.""" | |
1010 for attempt in xrange(ATTEMPTS): | |
1011 try: | |
1012 return urllib2.urlopen(url).read() | |
1013 except Exception: | |
1014 if attempt == ATTEMPTS - 1: | |
1015 raise | |
1016 | |
1017 | |
1018 def parse_diff(diff): | 739 def parse_diff(diff): |
1019 """Takes a unified diff and returns a list of diffed files and their diffs. | 740 """Takes a unified diff and returns a list of diffed files and their diffs. |
1020 | 741 |
1021 The return format is a list of pairs of: | 742 The return format is a list of pairs of: |
1022 (<filename>, <diff contents>) | 743 (<filename>, <diff contents>) |
1023 <diff contents> is inclusive of the diff line. | 744 <diff contents> is inclusive of the diff line. |
1024 """ | 745 """ |
1025 result = [] | 746 result = [] |
1026 current_diff = '' | 747 current_diff = '' |
1027 current_header = None | 748 current_header = None |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1217 # Compose a commit position from 'git-svn' metadata | 938 # Compose a commit position from 'git-svn' metadata |
1218 value = footer_map.get(GIT_SVN_ID_FOOTER_KEY) | 939 value = footer_map.get(GIT_SVN_ID_FOOTER_KEY) |
1219 if value: | 940 if value: |
1220 m = GIT_SVN_ID_RE.match(value) | 941 m = GIT_SVN_ID_RE.match(value) |
1221 if not m: | 942 if not m: |
1222 raise ValueError("Invalid 'git-svn' value: [%s]" % (value,)) | 943 raise ValueError("Invalid 'git-svn' value: [%s]" % (value,)) |
1223 return get_commit_position_for_git_svn(m.group(1), m.group(2)) | 944 return get_commit_position_for_git_svn(m.group(1), m.group(2)) |
1224 return None | 945 return None |
1225 | 946 |
1226 | 947 |
1227 def parse_got_revision(gclient_output, got_revision_mapping, use_svn_revs): | 948 def parse_got_revision(gclient_output, got_revision_mapping): |
1228 """Translate git gclient revision mapping to build properties. | 949 """Translate git gclient revision mapping to build properties.""" |
1229 | |
1230 If use_svn_revs is True, then translate git hashes in the revision mapping | |
1231 to svn revision numbers. | |
1232 """ | |
1233 properties = {} | 950 properties = {} |
1234 solutions_output = { | 951 solutions_output = { |
1235 # Make sure path always ends with a single slash. | 952 # Make sure path always ends with a single slash. |
1236 '%s/' % path.rstrip('/') : solution_output for path, solution_output | 953 '%s/' % path.rstrip('/') : solution_output for path, solution_output |
1237 in gclient_output['solutions'].iteritems() | 954 in gclient_output['solutions'].iteritems() |
1238 } | 955 } |
1239 for dir_name, property_name in got_revision_mapping.iteritems(): | 956 for dir_name, property_name in got_revision_mapping.iteritems(): |
1240 # Make sure dir_name always ends with a single slash. | 957 # Make sure dir_name always ends with a single slash. |
1241 dir_name = '%s/' % dir_name.rstrip('/') | 958 dir_name = '%s/' % dir_name.rstrip('/') |
1242 if dir_name not in solutions_output: | 959 if dir_name not in solutions_output: |
1243 continue | 960 continue |
1244 solution_output = solutions_output[dir_name] | 961 solution_output = solutions_output[dir_name] |
1245 if solution_output.get('scm') is None: | 962 if solution_output.get('scm') is None: |
1246 # This is an ignored DEPS, so the output got_revision should be 'None'. | 963 # This is an ignored DEPS, so the output got_revision should be 'None'. |
1247 git_revision = revision = commit_position = None | 964 git_revision = revision = commit_position = None |
1248 else: | 965 else: |
1249 # Since we are using .DEPS.git, everything had better be git. | 966 # Since we are using .DEPS.git, everything had better be git. |
1250 assert solution_output.get('scm') == 'git' | 967 assert solution_output.get('scm') == 'git' |
1251 git_revision = git('rev-parse', 'HEAD', cwd=dir_name).strip() | 968 git_revision = git('rev-parse', 'HEAD', cwd=dir_name).strip() |
1252 if use_svn_revs: | 969 revision = git_revision |
1253 revision = get_svn_rev(git_revision, dir_name) | |
1254 if not revision: | |
1255 revision = git_revision | |
1256 else: | |
1257 revision = git_revision | |
1258 commit_position = get_commit_position(dir_name) | 970 commit_position = get_commit_position(dir_name) |
1259 | 971 |
1260 properties[property_name] = revision | 972 properties[property_name] = revision |
1261 if revision != git_revision: | 973 if revision != git_revision: |
1262 properties['%s_git' % property_name] = git_revision | 974 properties['%s_git' % property_name] = git_revision |
1263 if commit_position: | 975 if commit_position: |
1264 properties['%s_cp' % property_name] = commit_position | 976 properties['%s_cp' % property_name] = commit_position |
1265 | 977 |
1266 return properties | 978 return properties |
1267 | 979 |
(...skipping 11 matching lines...) Expand all Loading... | |
1279 def ensure_deps_revisions(deps_url_mapping, solutions, revisions): | 991 def ensure_deps_revisions(deps_url_mapping, solutions, revisions): |
1280 """Ensure correct DEPS revisions, ignores solutions.""" | 992 """Ensure correct DEPS revisions, ignores solutions.""" |
1281 for deps_name, deps_data in sorted(deps_url_mapping.items()): | 993 for deps_name, deps_data in sorted(deps_url_mapping.items()): |
1282 if deps_name.strip('/') in solutions: | 994 if deps_name.strip('/') in solutions: |
1283 # This has already been forced to the correct solution by git_checkout(). | 995 # This has already been forced to the correct solution by git_checkout(). |
1284 continue | 996 continue |
1285 revision = get_target_revision(deps_name, deps_data.get('url', None), | 997 revision = get_target_revision(deps_name, deps_data.get('url', None), |
1286 revisions) | 998 revisions) |
1287 if not revision: | 999 if not revision: |
1288 continue | 1000 continue |
1289 # TODO(hinoka): Catch SVNRevisionNotFound error maybe? | |
1290 git('fetch', 'origin', cwd=deps_name) | 1001 git('fetch', 'origin', cwd=deps_name) |
1291 force_revision(deps_name, revision) | 1002 force_revision(deps_name, revision) |
1292 | 1003 |
1293 | 1004 |
1294 def ensure_checkout(solutions, revisions, first_sln, target_os, target_os_only, | 1005 def ensure_checkout(solutions, revisions, first_sln, target_os, target_os_only, |
1295 patch_root, issue, patchset, patch_url, rietveld_server, | 1006 patch_root, issue, patchset, patch_url, rietveld_server, |
1296 gerrit_repo, gerrit_ref, revision_mapping, | 1007 gerrit_repo, gerrit_ref, revision_mapping, |
1297 apply_issue_email_file, apply_issue_key_file, buildspec, | 1008 apply_issue_email_file, apply_issue_key_file, buildspec, |
1298 gyp_env, shallow, runhooks, refs, git_cache_dir): | 1009 gyp_env, shallow, runhooks, refs, git_cache_dir): |
1299 # Get a checkout of each solution, without DEPS or hooks. | 1010 # Get a checkout of each solution, without DEPS or hooks. |
(...skipping 16 matching lines...) Expand all Loading... | |
1316 target = '/'.join([relative_root, 'DEPS']).lstrip('/') | 1027 target = '/'.join([relative_root, 'DEPS']).lstrip('/') |
1317 if patches: | 1028 if patches: |
1318 apply_svn_patch(patch_root, patches, whitelist=[target]) | 1029 apply_svn_patch(patch_root, patches, whitelist=[target]) |
1319 already_patched.append(target) | 1030 already_patched.append(target) |
1320 elif issue: | 1031 elif issue: |
1321 apply_rietveld_issue(issue, patchset, patch_root, rietveld_server, | 1032 apply_rietveld_issue(issue, patchset, patch_root, rietveld_server, |
1322 revision_mapping, git_ref, apply_issue_email_file, | 1033 revision_mapping, git_ref, apply_issue_email_file, |
1323 apply_issue_key_file, whitelist=[target]) | 1034 apply_issue_key_file, whitelist=[target]) |
1324 already_patched.append(target) | 1035 already_patched.append(target) |
1325 | 1036 |
1326 if not buildspec: | |
1327 # Run deps2git if there is a DEPS change after the last .DEPS.git commit. | |
1328 for solution in solutions: | |
1329 ensure_deps2git(solution, shallow, git_cache_dir) | |
1330 | |
1331 # Ensure our build/ directory is set up with the correct .gclient file. | 1037 # Ensure our build/ directory is set up with the correct .gclient file. |
1332 gclient_configure(solutions, target_os, target_os_only, git_cache_dir) | 1038 gclient_configure(solutions, target_os, target_os_only, git_cache_dir) |
1333 | 1039 |
1334 # Let gclient do the DEPS syncing. | 1040 # Let gclient do the DEPS syncing. |
1335 # The branch-head refspec is a special case because its possible Chrome | 1041 # The branch-head refspec is a special case because its possible Chrome |
1336 # src, which contains the branch-head refspecs, is DEPSed in. | 1042 # src, which contains the branch-head refspecs, is DEPSed in. |
1337 gclient_output = gclient_sync(buildspec or BRANCH_HEADS_REFSPEC in refs, | 1043 gclient_output = gclient_sync(buildspec or BRANCH_HEADS_REFSPEC in refs, |
1338 shallow) | 1044 shallow) |
1339 | 1045 |
1340 # Now that gclient_sync has finished, we should revert any .DEPS.git so that | 1046 # Now that gclient_sync has finished, we should revert any .DEPS.git so that |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1434 parse.add_option('--root', dest='patch_root', | 1140 parse.add_option('--root', dest='patch_root', |
1435 help='DEPRECATED: Use --patch_root.') | 1141 help='DEPRECATED: Use --patch_root.') |
1436 parse.add_option('--patch_root', help='Directory to patch on top of.') | 1142 parse.add_option('--patch_root', help='Directory to patch on top of.') |
1437 parse.add_option('--rietveld_server', | 1143 parse.add_option('--rietveld_server', |
1438 default='codereview.chromium.org', | 1144 default='codereview.chromium.org', |
1439 help='Rietveld server.') | 1145 help='Rietveld server.') |
1440 parse.add_option('--gerrit_repo', | 1146 parse.add_option('--gerrit_repo', |
1441 help='Gerrit repository to pull the ref from.') | 1147 help='Gerrit repository to pull the ref from.') |
1442 parse.add_option('--gerrit_ref', help='Gerrit ref to apply.') | 1148 parse.add_option('--gerrit_ref', help='Gerrit ref to apply.') |
1443 parse.add_option('--specs', help='Gcilent spec.') | 1149 parse.add_option('--specs', help='Gcilent spec.') |
1444 parse.add_option('--master', help='Master name.') | 1150 parse.add_option('--master', help='DEPRECATED: Master name.') |
1445 parse.add_option('-f', '--force', action='store_true', | 1151 parse.add_option('-f', '--force', action='store_true', |
1446 help='Bypass check to see if we want to be run. ' | 1152 help='DEPRECATED: Bypass check to see if we want to be run. ' |
1447 'Should ONLY be used locally or by smart recipes.') | 1153 'Should ONLY be used locally or by smart recipes.') |
1448 parse.add_option('--revision_mapping', | 1154 parse.add_option('--revision_mapping', |
1449 help='{"path/to/repo/": "property_name"}') | 1155 help='{"path/to/repo/": "property_name"}') |
1450 parse.add_option('--revision_mapping_file', | 1156 parse.add_option('--revision_mapping_file', |
1451 help=('Same as revision_mapping, except its a path to a json' | 1157 help=('Same as revision_mapping, except its a path to a json' |
1452 ' file containing that format.')) | 1158 ' file containing that format.')) |
1453 parse.add_option('--revision', action='append', default=[], | 1159 parse.add_option('--revision', action='append', default=[], |
1454 help='Revision to check out. Can be an SVN revision number, ' | 1160 help='Revision to check out. Can be an SVN revision number, ' |
1455 'git hash, or any form of git ref. Can prepend ' | 1161 'git hash, or any form of git ref. Can prepend ' |
1456 'root@<rev> to specify which repository, where root ' | 1162 'root@<rev> to specify which repository, where root ' |
1457 'is either a filesystem path, git https url, or ' | 1163 'is either a filesystem path, git https url, or ' |
1458 'svn url. To specify Tip of Tree, set rev to HEAD.' | 1164 'svn url. To specify Tip of Tree, set rev to HEAD.' |
1459 'To specify a git branch and an SVN rev, <rev> can be ' | 1165 'To specify a git branch and an SVN rev, <rev> can be ' |
1460 'set to <branch>:<revision>.') | 1166 'set to <branch>:<revision>.') |
1461 parse.add_option('--output_manifest', action='store_true', | 1167 parse.add_option('--output_manifest', action='store_true', |
1462 help=('Add manifest json to the json output.')) | 1168 help=('Add manifest json to the json output.')) |
1463 parse.add_option('--slave_name', default=socket.getfqdn().split('.')[0], | 1169 parse.add_option('--slave_name', default=socket.getfqdn().split('.')[0], |
1464 help='Hostname of the current machine, ' | 1170 help='DEPRECATED: Hostname of the current machine, ' |
1465 'used for determining whether or not to activate.') | 1171 'used for determining whether or not to activate.') |
1466 parse.add_option('--builder_name', help='Name of the builder, ' | 1172 parse.add_option('--builder_name', help='DEPRECATED: Name of the builder, ' |
iannucci
2016/02/11 00:56:21
you can remove all deprecated options now: the onl
hinoka
2016/02/11 20:10:05
Yesssssss. Ok
| |
1467 'used for determining whether or not to activate.') | 1173 'used for determining whether or not to activate.') |
1468 parse.add_option('--build_dir', default=os.getcwd()) | 1174 parse.add_option('--build_dir', default=os.getcwd()) |
1469 parse.add_option('--flag_file', default=path.join(os.getcwd(), | 1175 parse.add_option('--flag_file', default=path.join(os.getcwd(), |
1470 'update.flag')) | 1176 'update.flag')) |
1471 parse.add_option('--shallow', action='store_true', | 1177 parse.add_option('--shallow', action='store_true', |
1472 help='Use shallow clones for cache repositories.') | 1178 help='Use shallow clones for cache repositories.') |
1473 parse.add_option('--gyp_env', action='append', default=[], | 1179 parse.add_option('--gyp_env', action='append', default=[], |
1474 help='Environment variables to pass into gclient runhooks.') | 1180 help='Environment variables to pass into gclient runhooks.') |
1475 parse.add_option('--clobber', action='store_true', | 1181 parse.add_option('--clobber', action='store_true', |
1476 help='Delete checkout first, always') | 1182 help='Delete checkout first, always') |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1519 | 1225 |
1520 # Because we print CACHE_DIR out into a .gclient file, and then later run | 1226 # Because we print CACHE_DIR out into a .gclient file, and then later run |
1521 # eval() on it, backslashes need to be escaped, otherwise "E:\b\build" gets | 1227 # eval() on it, backslashes need to be escaped, otherwise "E:\b\build" gets |
1522 # parsed as "E:[\x08][\x08]uild". | 1228 # parsed as "E:[\x08][\x08]uild". |
1523 if sys.platform.startswith('win'): | 1229 if sys.platform.startswith('win'): |
1524 options.git_cache_dir = options.git_cache_dir.replace('\\', '\\\\') | 1230 options.git_cache_dir = options.git_cache_dir.replace('\\', '\\\\') |
1525 | 1231 |
1526 return options, args | 1232 return options, args |
1527 | 1233 |
1528 | 1234 |
1529 def prepare(options, git_slns, active): | 1235 def prepare(options, git_slns): |
1530 """Prepares the target folder before we checkout.""" | 1236 """Prepares the target folder before we checkout.""" |
1531 dir_names = [sln.get('name') for sln in git_slns if 'name' in sln] | 1237 dir_names = [sln.get('name') for sln in git_slns if 'name' in sln] |
1532 # If we're active now, but the flag file doesn't exist (we weren't active | |
1533 # last run) or vice versa, blow away all checkouts. | |
1534 if bool(active) != bool(check_flag(options.flag_file)): | |
1535 ensure_no_checkout(dir_names, '*') | |
1536 if options.output_json: | 1238 if options.output_json: |
1537 # Make sure we tell recipes that we didn't run if the script exits here. | 1239 # Make sure we tell recipes that we didn't run if the script exits here. |
1538 emit_json(options.output_json, did_run=active) | 1240 emit_json(options.output_json, did_run=True) |
iannucci
2016/02/11 00:56:20
yeah let's definitely get rid of did_run if we can
martiniss
2016/02/11 10:31:47
I think a fair amount of recipes still check this,
hinoka
2016/02/11 20:10:05
Acknowledged.
| |
1539 if active: | 1241 if options.clobber: |
1540 if options.clobber: | 1242 ensure_no_checkout(dir_names, '*') |
1541 ensure_no_checkout(dir_names, '*') | |
1542 else: | |
1543 ensure_no_checkout(dir_names, '.svn') | |
1544 emit_flag(options.flag_file) | |
1545 else: | 1243 else: |
1546 delete_flag(options.flag_file) | 1244 ensure_no_checkout(dir_names, '.svn') |
1547 raise Inactive # This is caught in main() and we exit cleanly. | 1245 emit_flag(options.flag_file) |
1548 | 1246 |
1549 # Do a shallow checkout if the disk is less than 100GB. | 1247 # Do a shallow checkout if the disk is less than 100GB. |
1550 total_disk_space, free_disk_space = get_total_disk_space() | 1248 total_disk_space, free_disk_space = get_total_disk_space() |
1551 total_disk_space_gb = int(total_disk_space / (1024 * 1024 * 1024)) | 1249 total_disk_space_gb = int(total_disk_space / (1024 * 1024 * 1024)) |
1552 used_disk_space_gb = int((total_disk_space - free_disk_space) | 1250 used_disk_space_gb = int((total_disk_space - free_disk_space) |
1553 / (1024 * 1024 * 1024)) | 1251 / (1024 * 1024 * 1024)) |
1554 percent_used = int(used_disk_space_gb * 100 / total_disk_space_gb) | 1252 percent_used = int(used_disk_space_gb * 100 / total_disk_space_gb) |
1555 step_text = '[%dGB/%dGB used (%d%%)]' % (used_disk_space_gb, | 1253 step_text = '[%dGB/%dGB used (%d%%)]' % (used_disk_space_gb, |
1556 total_disk_space_gb, | 1254 total_disk_space_gb, |
1557 percent_used) | 1255 percent_used) |
1558 if not options.output_json: | 1256 if not options.output_json: |
1559 print '@@@STEP_TEXT@%s@@@' % step_text | 1257 print '@@@STEP_TEXT@%s@@@' % step_text |
1560 if not options.shallow: | 1258 if not options.shallow: |
1561 options.shallow = (total_disk_space < SHALLOW_CLONE_THRESHOLD | 1259 options.shallow = (total_disk_space < SHALLOW_CLONE_THRESHOLD |
1562 and not options.no_shallow) | 1260 and not options.no_shallow) |
1563 | 1261 |
1564 # The first solution is where the primary DEPS file resides. | 1262 # The first solution is where the primary DEPS file resides. |
1565 first_sln = dir_names[0] | 1263 first_sln = dir_names[0] |
1566 | 1264 |
1567 # Split all the revision specifications into a nice dict. | 1265 # Split all the revision specifications into a nice dict. |
1568 print 'Revisions: %s' % options.revision | 1266 print 'Revisions: %s' % options.revision |
1569 revisions = parse_revisions(options.revision, first_sln) | 1267 revisions = parse_revisions(options.revision, first_sln) |
1570 print 'Fetching Git checkout at %s@%s' % (first_sln, revisions[first_sln]) | 1268 print 'Fetching Git checkout at %s@%s' % (first_sln, revisions[first_sln]) |
1571 return revisions, step_text | 1269 return revisions, step_text |
1572 | 1270 |
1573 | 1271 |
1574 def checkout(options, git_slns, specs, buildspec, master, | 1272 def checkout(options, git_slns, specs, buildspec, |
1575 svn_root, revisions, step_text): | 1273 svn_root, revisions, step_text): |
1576 first_sln = git_slns[0]['name'] | 1274 first_sln = git_slns[0]['name'] |
1577 dir_names = [sln.get('name') for sln in git_slns if 'name' in sln] | 1275 dir_names = [sln.get('name') for sln in git_slns if 'name' in sln] |
1578 try: | 1276 try: |
1579 # Outer try is for catching patch failures and exiting gracefully. | 1277 # Outer try is for catching patch failures and exiting gracefully. |
1580 # Inner try is for catching gclient failures and retrying gracefully. | 1278 # Inner try is for catching gclient failures and retrying gracefully. |
1581 try: | 1279 try: |
1582 checkout_parameters = dict( | 1280 checkout_parameters = dict( |
1583 # First, pass in the base of what we want to check out. | 1281 # First, pass in the base of what we want to check out. |
1584 solutions=git_slns, | 1282 solutions=git_slns, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1626 patch_root=options.patch_root, | 1324 patch_root=options.patch_root, |
1627 patch_failure=True, | 1325 patch_failure=True, |
1628 step_text='%s PATCH FAILED' % step_text, | 1326 step_text='%s PATCH FAILED' % step_text, |
1629 fixed_revisions=revisions) | 1327 fixed_revisions=revisions) |
1630 else: | 1328 else: |
1631 # If we're not on recipes, tell annotator about our got_revisions. | 1329 # If we're not on recipes, tell annotator about our got_revisions. |
1632 emit_log_lines('patch error', e.output) | 1330 emit_log_lines('patch error', e.output) |
1633 print '@@@STEP_TEXT@%s PATCH FAILED@@@' % step_text | 1331 print '@@@STEP_TEXT@%s PATCH FAILED@@@' % step_text |
1634 raise | 1332 raise |
1635 | 1333 |
1636 # Revision is an svn revision, unless it's a git master. | |
1637 use_svn_rev = master not in GIT_MASTERS | |
1638 | |
1639 # Take care of got_revisions outputs. | 1334 # Take care of got_revisions outputs. |
1640 revision_mapping = dict(GOT_REVISION_MAPPINGS.get(svn_root, {})) | 1335 revision_mapping = dict(GOT_REVISION_MAPPINGS.get(svn_root, {})) |
1641 if options.revision_mapping: | 1336 if options.revision_mapping: |
1642 revision_mapping.update(options.revision_mapping) | 1337 revision_mapping.update(options.revision_mapping) |
1643 | 1338 |
1644 # If the repo is not in the default GOT_REVISION_MAPPINGS and no | 1339 # If the repo is not in the default GOT_REVISION_MAPPINGS and no |
1645 # revision_mapping were specified on the command line then | 1340 # revision_mapping were specified on the command line then |
1646 # default to setting 'got_revision' based on the first solution. | 1341 # default to setting 'got_revision' based on the first solution. |
1647 if not revision_mapping: | 1342 if not revision_mapping: |
1648 revision_mapping[first_sln] = 'got_revision' | 1343 revision_mapping[first_sln] = 'got_revision' |
1649 | 1344 |
1650 got_revisions = parse_got_revision(gclient_output, revision_mapping, | 1345 got_revisions = parse_got_revision(gclient_output, revision_mapping) |
1651 use_svn_rev) | |
1652 | 1346 |
1653 if not got_revisions: | 1347 if not got_revisions: |
1654 # TODO(hinoka): We should probably bail out here, but in the interest | 1348 # TODO(hinoka): We should probably bail out here, but in the interest |
1655 # of giving mis-configured bots some time to get fixed use a dummy | 1349 # of giving mis-configured bots some time to get fixed use a dummy |
1656 # revision here. | 1350 # revision here. |
1657 got_revisions = { 'got_revision': 'BOT_UPDATE_NO_REV_FOUND' } | 1351 got_revisions = { 'got_revision': 'BOT_UPDATE_NO_REV_FOUND' } |
1658 #raise Exception('No got_revision(s) found in gclient output') | 1352 #raise Exception('No got_revision(s) found in gclient output') |
1659 | 1353 |
1660 if options.output_json: | 1354 if options.output_json: |
1661 manifest = create_manifest() if options.output_manifest else None | 1355 manifest = create_manifest() if options.output_manifest else None |
1662 # Tell recipes information such as root, got_revision, etc. | 1356 # Tell recipes information such as root, got_revision, etc. |
1663 emit_json(options.output_json, | 1357 emit_json(options.output_json, |
1664 did_run=True, | 1358 did_run=True, |
1665 root=first_sln, | 1359 root=first_sln, |
1666 patch_root=options.patch_root, | 1360 patch_root=options.patch_root, |
1667 step_text=step_text, | 1361 step_text=step_text, |
1668 fixed_revisions=revisions, | 1362 fixed_revisions=revisions, |
1669 properties=got_revisions, | 1363 properties=got_revisions, |
1670 manifest=manifest) | 1364 manifest=manifest) |
1671 else: | 1365 else: |
1672 # If we're not on recipes, tell annotator about our got_revisions. | 1366 # If we're not on recipes, tell annotator about our got_revisions. |
1673 emit_properties(got_revisions) | 1367 emit_properties(got_revisions) |
1674 | 1368 |
1675 | 1369 |
1676 def print_help_text(force, output_json, active, master, builder, slave): | 1370 def print_help_text(master, builder, slave): |
1677 """Print helpful messages to tell devs whats going on.""" | 1371 """Print helpful messages to tell devs whats going on.""" |
1678 if force and output_json: | |
1679 recipe_force = 'Forced on by recipes' | |
1680 elif active and output_json: | |
1681 recipe_force = 'Off by recipes, but forced on by bot update' | |
1682 elif not active and output_json: | |
1683 recipe_force = 'Forced off by recipes' | |
1684 else: | |
1685 recipe_force = 'N/A. Was not called by recipes' | |
1686 | |
1687 print BOT_UPDATE_MESSAGE % { | 1372 print BOT_UPDATE_MESSAGE % { |
1688 'master': master or 'Not specified', | 1373 'master': master or 'Not specified', |
1689 'builder': builder or 'Not specified', | 1374 'builder': builder or 'Not specified', |
1690 'slave': slave or 'Not specified', | 1375 'slave': slave or 'Not specified', |
1691 'recipe': recipe_force, | 1376 'recipe': 'Forced on by default', |
iannucci
2016/02/11 00:56:21
remove from here up
hinoka
2016/02/11 20:10:06
Done.
| |
1692 'CURRENT_DIR': CURRENT_DIR, | 1377 'CURRENT_DIR': CURRENT_DIR, |
1693 'BUILDER_DIR': BUILDER_DIR, | 1378 'BUILDER_DIR': BUILDER_DIR, |
1694 'SLAVE_DIR': SLAVE_DIR, | 1379 'SLAVE_DIR': SLAVE_DIR, |
1695 'THIS_DIR': THIS_DIR, | 1380 'THIS_DIR': THIS_DIR, |
1696 'SCRIPTS_DIR': SCRIPTS_DIR, | 1381 'SCRIPTS_DIR': SCRIPTS_DIR, |
1697 'BUILD_DIR': BUILD_DIR, | 1382 'BUILD_DIR': BUILD_DIR, |
1698 'ROOT_DIR': ROOT_DIR, | 1383 'ROOT_DIR': ROOT_DIR, |
1699 'DEPOT_TOOLS_DIR': DEPOT_TOOLS_DIR, | 1384 'DEPOT_TOOLS_DIR': DEPOT_TOOLS_DIR, |
1700 }, | 1385 }, |
1701 print ACTIVATED_MESSAGE if active else NOT_ACTIVATED_MESSAGE | |
1702 | 1386 |
1703 | 1387 |
1704 def main(): | 1388 def main(): |
1705 # Get inputs. | 1389 # Get inputs. |
1706 options, _ = parse_args() | 1390 options, _ = parse_args() |
1707 builder = options.builder_name | 1391 builder = options.builder_name |
1708 slave = options.slave_name | 1392 slave = options.slave_name |
1709 master = options.master | 1393 master = options.master |
1710 | 1394 |
1711 # Check if this script should activate or not. | 1395 # Prints some debugging information. |
1712 active = check_valid_host(master, builder, slave) or options.force or False | 1396 print_help_text(master, builder, slave) |
1713 | |
1714 # Print a helpful message to tell developers whats going on with this step. | |
1715 print_help_text( | |
1716 options.force, options.output_json, active, master, builder, slave) | |
1717 | 1397 |
1718 # Parse, munipulate, and print the gclient solutions. | 1398 # Parse, munipulate, and print the gclient solutions. |
1719 specs = {} | 1399 specs = {} |
1720 exec(options.specs, specs) | 1400 exec(options.specs, specs) |
1721 svn_solutions = specs.get('solutions', []) | 1401 svn_solutions = specs.get('solutions', []) |
1722 git_slns, svn_root, buildspec = solutions_to_git(svn_solutions) | 1402 git_slns, svn_root, buildspec = solutions_to_git(svn_solutions) |
1723 options.revision = maybe_ignore_revision(options.revision, buildspec) | 1403 options.revision = maybe_ignore_revision(options.revision, buildspec) |
1724 | 1404 |
1725 solutions_printer(git_slns) | 1405 solutions_printer(git_slns) |
1726 | 1406 |
1727 try: | 1407 try: |
1728 # Dun dun dun, the main part of bot_update. | 1408 # Dun dun dun, the main part of bot_update. |
1729 revisions, step_text = prepare(options, git_slns, active) | 1409 revisions, step_text = prepare(options, git_slns) |
1730 checkout(options, git_slns, specs, buildspec, master, svn_root, revisions, | 1410 checkout(options, git_slns, specs, buildspec, svn_root, revisions, |
1731 step_text) | 1411 step_text) |
1732 | 1412 |
1733 except Inactive: | |
1734 # Not active, should count as passing. | |
1735 pass | |
1736 except PatchFailed as e: | 1413 except PatchFailed as e: |
1737 emit_flag(options.flag_file) | 1414 emit_flag(options.flag_file) |
1738 # Return a specific non-zero exit code for patch failure (because it is | 1415 # Return a specific non-zero exit code for patch failure (because it is |
1739 # a failure), but make it different than other failures to distinguish | 1416 # a failure), but make it different than other failures to distinguish |
1740 # between infra failures (independent from patch author), and patch | 1417 # between infra failures (independent from patch author), and patch |
1741 # failures (that patch author can fix). However, PatchFailure due to | 1418 # failures (that patch author can fix). However, PatchFailure due to |
1742 # download patch failure is still an infra problem. | 1419 # download patch failure is still an infra problem. |
1743 if e.code == 3: | 1420 if e.code == 3: |
1744 # Patch download problem. | 1421 # Patch download problem. |
1745 return 87 | 1422 return 87 |
1746 # Genuine patch problem. | 1423 # Genuine patch problem. |
1747 return 88 | 1424 return 88 |
1748 except Exception: | 1425 except Exception: |
1749 # Unexpected failure. | 1426 # Unexpected failure. |
1750 emit_flag(options.flag_file) | 1427 emit_flag(options.flag_file) |
1751 raise | 1428 raise |
1752 else: | 1429 else: |
1753 emit_flag(options.flag_file) | 1430 emit_flag(options.flag_file) |
1754 | 1431 |
1755 | 1432 |
1756 if __name__ == '__main__': | 1433 if __name__ == '__main__': |
1757 sys.exit(main()) | 1434 sys.exit(main()) |
OLD | NEW |