Chromium Code Reviews| 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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 path.pardir), # build_internal | 82 path.pardir), # build_internal |
| 83 ]) | 83 ]) |
| 84 | 84 |
| 85 | 85 |
| 86 CHROMIUM_GIT_HOST = 'https://chromium.googlesource.com' | 86 CHROMIUM_GIT_HOST = 'https://chromium.googlesource.com' |
| 87 CHROMIUM_SRC_URL = CHROMIUM_GIT_HOST + '/chromium/src.git' | 87 CHROMIUM_SRC_URL = CHROMIUM_GIT_HOST + '/chromium/src.git' |
| 88 | 88 |
| 89 # Official builds use buildspecs, so this is a special case. | 89 # Official builds use buildspecs, so this is a special case. |
| 90 BUILDSPEC_TYPE = collections.namedtuple('buildspec', | 90 BUILDSPEC_TYPE = collections.namedtuple('buildspec', |
| 91 ('container', 'version')) | 91 ('container', 'version')) |
| 92 BUILDSPEC_RE = (r'^/chrome-internal/trunk/tools/buildspec/' | 92 BUILDSPEC_RE = (r'^/chrome/tools/buildspec/\+/master/' |
|
hinoka
2016/08/26 21:59:54
If this doesn't work / isn't invoked to begin with
agable
2016/08/29 19:09:58
Deleted a bunch of buildspec code now.
| |
| 93 '(build|branches|releases)/(.+)$') | 93 '(build|branches|releases)/(.+)$') |
| 94 GIT_BUILDSPEC_PATH = ('https://chrome-internal.googlesource.com/chrome/tools/' | 94 GIT_BUILDSPEC_PATH = ('https://chrome-internal.googlesource.com/chrome/tools/' |
| 95 'buildspec') | 95 'buildspec') |
| 96 BRANCH_HEADS_REFSPEC = '+refs/branch-heads/*' | 96 BRANCH_HEADS_REFSPEC = '+refs/branch-heads/*' |
| 97 | 97 |
| 98 BUILDSPEC_COMMIT_RE = ( | 98 BUILDSPEC_COMMIT_RE = ( |
| 99 re.compile(r'Buildspec for.*version (\d+\.\d+\.\d+\.\d+)'), | 99 re.compile(r'Buildspec for.*version (\d+\.\d+\.\d+\.\d+)'), |
| 100 re.compile(r'Create (\d+\.\d+\.\d+\.\d+) buildspec'), | 100 re.compile(r'Create (\d+\.\d+\.\d+\.\d+) buildspec'), |
| 101 re.compile(r'Auto-converted (\d+\.\d+\.\d+\.\d+) buildspec to git'), | 101 re.compile(r'Auto-converted (\d+\.\d+\.\d+\.\d+) buildspec to git'), |
| 102 ) | 102 ) |
| 103 | 103 |
| 104 # Regular expression that matches a single commit footer line. | 104 # Regular expression that matches a single commit footer line. |
| 105 COMMIT_FOOTER_ENTRY_RE = re.compile(r'([^:]+):\s+(.+)') | 105 COMMIT_FOOTER_ENTRY_RE = re.compile(r'([^:]+):\s+(.+)') |
| 106 | 106 |
| 107 # Footer metadata keys for regular and gsubtreed mirrored commit positions. | 107 # Footer metadata keys for regular and gsubtreed mirrored commit positions. |
| 108 COMMIT_POSITION_FOOTER_KEY = 'Cr-Commit-Position' | 108 COMMIT_POSITION_FOOTER_KEY = 'Cr-Commit-Position' |
| 109 COMMIT_ORIGINAL_POSITION_FOOTER_KEY = 'Cr-Original-Commit-Position' | 109 COMMIT_ORIGINAL_POSITION_FOOTER_KEY = 'Cr-Original-Commit-Position' |
| 110 # Regular expression to parse a commit position | 110 # Regular expression to parse a commit position |
| 111 COMMIT_POSITION_RE = re.compile(r'(.+)@\{#(\d+)\}') | 111 COMMIT_POSITION_RE = re.compile(r'(.+)@\{#(\d+)\}') |
| 112 | 112 |
| 113 # Regular expression to parse gclient's revinfo entries. | 113 # Regular expression to parse gclient's revinfo entries. |
| 114 REVINFO_RE = re.compile(r'^([^:]+):\s+([^@]+)@(.+)$') | 114 REVINFO_RE = re.compile(r'^([^:]+):\s+([^@]+)@(.+)$') |
| 115 | 115 |
| 116 # Used by 'ResolveSvnRevisionFromGitiles' | |
| 117 GIT_SVN_PROJECT_MAP = { | |
| 118 'webkit': { | |
| 119 'svn_url': 'svn://svn.chromium.org/blink', | |
| 120 'branch_map': [ | |
| 121 (r'trunk', r'refs/heads/master'), | |
| 122 (r'branches/([^/]+)', r'refs/branch-heads/\1'), | |
| 123 ], | |
| 124 }, | |
| 125 'v8': { | |
| 126 'svn_url': 'https://v8.googlecode.com/svn', | |
| 127 'branch_map': [ | |
| 128 (r'trunk', r'refs/heads/candidates'), | |
| 129 (r'branches/bleeding_edge', r'refs/heads/master'), | |
| 130 (r'branches/([^/]+)', r'refs/branch-heads/\1'), | |
| 131 ], | |
| 132 }, | |
| 133 'nacl': { | |
| 134 'svn_url': 'svn://svn.chromium.org/native_client', | |
| 135 'branch_map': [ | |
| 136 (r'trunk/src/native_client', r'refs/heads/master'), | |
| 137 ], | |
| 138 }, | |
| 139 } | |
| 140 | |
| 141 # Key for the 'git-svn' ID metadata commit footer entry. | |
| 142 GIT_SVN_ID_FOOTER_KEY = 'git-svn-id' | |
| 143 # e.g., git-svn-id: https://v8.googlecode.com/svn/trunk@23117 | |
| 144 # ce2b1a6d-e550-0410-aec6-3dcde31c8c00 | |
| 145 GIT_SVN_ID_RE = re.compile(r'((?:\w+)://[^@]+)@(\d+)\s+(?:[a-zA-Z0-9\-]+)') | |
| 146 | |
| 147 | |
| 148 # This is the git mirror of the buildspecs repository. We could rely on the svn | |
| 149 # checkout, now that the git buildspecs are checked in alongside the svn | |
| 150 # buildspecs, but we're going to want to pull all the buildspecs from here | |
| 151 # eventually anyhow, and there's already some logic to pull from git (for the | |
| 152 # old git_buildspecs.git repo), so just stick with that. | |
| 153 GIT_BUILDSPEC_REPO = ( | |
| 154 'https://chrome-internal.googlesource.com/chrome/tools/buildspec') | |
| 155 | 116 |
| 156 # Copied from scripts/recipes/chromium.py. | 117 # Copied from scripts/recipes/chromium.py. |
| 157 GOT_REVISION_MAPPINGS = { | 118 GOT_REVISION_MAPPINGS = { |
| 158 '/chrome/trunk/src': { | 119 CHROMIUM_SRC_URL: { |
| 159 'src/': 'got_revision', | 120 'src/': 'got_revision', |
| 160 'src/native_client/': 'got_nacl_revision', | 121 'src/native_client/': 'got_nacl_revision', |
| 161 'src/tools/swarm_client/': 'got_swarm_client_revision', | 122 'src/tools/swarm_client/': 'got_swarm_client_revision', |
| 162 'src/tools/swarming_client/': 'got_swarming_client_revision', | 123 'src/tools/swarming_client/': 'got_swarming_client_revision', |
| 163 'src/third_party/WebKit/': 'got_webkit_revision', | 124 'src/third_party/WebKit/': 'got_webkit_revision', |
| 164 'src/third_party/webrtc/': 'got_webrtc_revision', | 125 'src/third_party/webrtc/': 'got_webrtc_revision', |
| 165 'src/v8/': 'got_v8_revision', | 126 'src/v8/': 'got_v8_revision', |
| 166 } | 127 } |
| 167 } | 128 } |
| 168 | 129 |
| 169 | 130 |
| 170 BOT_UPDATE_MESSAGE = """ | 131 BOT_UPDATE_MESSAGE = """ |
| 171 What is the "Bot Update" step? | 132 What is the "Bot Update" step? |
| 172 ============================== | 133 ============================== |
| 173 | 134 |
| 174 This step ensures that the source checkout on the bot (e.g. Chromium's src/ and | 135 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 | 136 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 | 137 the necessary repositories are checked out, no extra repositories are checked |
| 177 out, and no locally modified files are present. | 138 out, and no locally modified files are present. |
| 178 | 139 |
| 179 These actions used to be taken care of by the "gclient revert" and "update" | 140 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 | 141 steps. However, those steps are known to be buggy and occasionally flaky. This |
| 181 step has two main advantages over them: | 142 step has two main advantages over them: |
| 182 * it only operates in Git, so the logic can be clearer and cleaner; and | 143 * 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 | 144 * it is a slave-side script, so its behavior can be modified without |
| 184 restarting the master. | 145 restarting the master. |
| 185 | 146 |
| 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: | 147 Debugging information: |
| 199 (master/builder/slave may be unspecified on recipes) | 148 (master/builder/slave may be unspecified on recipes) |
| 200 master: %(master)s | 149 master: %(master)s |
| 201 builder: %(builder)s | 150 builder: %(builder)s |
| 202 slave: %(slave)s | 151 slave: %(slave)s |
| 203 forced by recipes: %(recipe)s | 152 forced by recipes: %(recipe)s |
| 204 CURRENT_DIR: %(CURRENT_DIR)s | 153 CURRENT_DIR: %(CURRENT_DIR)s |
| 205 BUILDER_DIR: %(BUILDER_DIR)s | 154 BUILDER_DIR: %(BUILDER_DIR)s |
| 206 SLAVE_DIR: %(SLAVE_DIR)s | 155 SLAVE_DIR: %(SLAVE_DIR)s |
| 207 THIS_DIR: %(THIS_DIR)s | 156 THIS_DIR: %(THIS_DIR)s |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 237 try: | 186 try: |
| 238 execfile(os.path.join( | 187 execfile(os.path.join( |
| 239 BUILD_INTERNAL_DIR, 'scripts', 'slave', 'bot_update_cfg.py'), | 188 BUILD_INTERNAL_DIR, 'scripts', 'slave', 'bot_update_cfg.py'), |
| 240 local_vars) | 189 local_vars) |
| 241 except Exception: | 190 except Exception: |
| 242 # Same as if BUILD_INTERNAL_DIR didn't exist in the first place. | 191 # Same as if BUILD_INTERNAL_DIR didn't exist in the first place. |
| 243 print 'Warning: unable to read internal configuration file.' | 192 print 'Warning: unable to read internal configuration file.' |
| 244 print 'If this is an internal bot, this step may be erroneously inactive.' | 193 print 'If this is an internal bot, this step may be erroneously inactive.' |
| 245 internal_data = local_vars | 194 internal_data = local_vars |
| 246 | 195 |
| 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 '/chrome-internal/trunk/src-internal': | |
| 254 'https://chrome-internal.googlesource.com/chrome/src-internal.git', | |
| 255 } | |
| 256 RECOGNIZED_PATHS.update(internal_data.get('RECOGNIZED_PATHS', {})) | |
| 257 | 196 |
| 258 ENABLED_MASTERS = [ | 197 ENABLED_MASTERS = [ |
| 259 'bot_update.always_on', | 198 'bot_update.always_on', |
| 260 'chromium.android', | 199 'chromium.android', |
| 261 'chromium.angle', | 200 'chromium.angle', |
| 262 'chromium.chrome', | 201 'chromium.chrome', |
| 263 'chromium.chromedriver', | 202 'chromium.chromedriver', |
| 264 'chromium.chromiumos', | 203 'chromium.chromiumos', |
| 265 'chromium', | 204 'chromium', |
| 266 'chromium.fyi', | 205 'chromium.fyi', |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 330 | 269 |
| 331 # Disabled filters get run AFTER enabled filters, so for example if a builder | 270 # Disabled filters get run AFTER enabled filters, so for example if a builder |
| 332 # config is enabled, but a bot on that builder is disabled, that bot will | 271 # config is enabled, but a bot on that builder is disabled, that bot will |
| 333 # be disabled. | 272 # be disabled. |
| 334 DISABLED_BUILDERS = {} | 273 DISABLED_BUILDERS = {} |
| 335 DISABLED_BUILDERS.update(internal_data.get('DISABLED_BUILDERS', {})) | 274 DISABLED_BUILDERS.update(internal_data.get('DISABLED_BUILDERS', {})) |
| 336 | 275 |
| 337 DISABLED_SLAVES = {} | 276 DISABLED_SLAVES = {} |
| 338 DISABLED_SLAVES.update(internal_data.get('DISABLED_SLAVES', {})) | 277 DISABLED_SLAVES.update(internal_data.get('DISABLED_SLAVES', {})) |
| 339 | 278 |
| 340 # These masters work only in Git, meaning for got_revision, always output | |
| 341 # a git hash rather than a SVN rev. | |
| 342 GIT_MASTERS = [ | |
| 343 'client.v8', | |
| 344 'client.v8.branches', | |
| 345 'client.v8.ports', | |
| 346 'tryserver.v8', | |
| 347 ] | |
| 348 GIT_MASTERS += internal_data.get('GIT_MASTERS', []) | |
| 349 | |
| 350 | |
| 351 # How many times to try before giving up. | 279 # How many times to try before giving up. |
| 352 ATTEMPTS = 5 | 280 ATTEMPTS = 5 |
| 353 | 281 |
| 354 GIT_CACHE_PATH = path.join(DEPOT_TOOLS_DIR, 'git_cache.py') | 282 GIT_CACHE_PATH = path.join(DEPOT_TOOLS_DIR, 'git_cache.py') |
| 355 | 283 |
| 356 # Find the patch tool. | 284 # Find the patch tool. |
| 357 if sys.platform.startswith('win'): | 285 if sys.platform.startswith('win'): |
| 358 if not BUILD_INTERNAL_DIR: | 286 if not BUILD_INTERNAL_DIR: |
| 359 print 'Warning: could not find patch tool because there is no ' | 287 print 'Warning: could not find patch tool because there is no ' |
| 360 print 'build_internal present.' | 288 print 'build_internal present.' |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 377 | 305 |
| 378 | 306 |
| 379 class PatchFailed(SubprocessFailed): | 307 class PatchFailed(SubprocessFailed): |
| 380 pass | 308 pass |
| 381 | 309 |
| 382 | 310 |
| 383 class GclientSyncFailed(SubprocessFailed): | 311 class GclientSyncFailed(SubprocessFailed): |
| 384 pass | 312 pass |
| 385 | 313 |
| 386 | 314 |
| 387 class SVNRevisionNotFound(Exception): | |
| 388 pass | |
| 389 | |
| 390 | |
| 391 class InvalidDiff(Exception): | 315 class InvalidDiff(Exception): |
| 392 pass | 316 pass |
| 393 | 317 |
| 394 | 318 |
| 395 class Inactive(Exception): | 319 class Inactive(Exception): |
| 396 """Not really an exception, just used to exit early cleanly.""" | 320 """Not really an exception, just used to exit early cleanly.""" |
| 397 pass | 321 pass |
| 398 | 322 |
| 399 | 323 |
| 400 RETRY = object() | 324 RETRY = object() |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 594 print ' %s: Ignore' % deps_name | 518 print ' %s: Ignore' % deps_name |
| 595 for k, v in solution.iteritems(): | 519 for k, v in solution.iteritems(): |
| 596 # Print out all the keys we don't know about. | 520 # Print out all the keys we don't know about. |
| 597 if k in ['name', 'url', 'deps_file', 'custom_vars', 'custom_deps', | 521 if k in ['name', 'url', 'deps_file', 'custom_vars', 'custom_deps', |
| 598 'managed']: | 522 'managed']: |
| 599 continue | 523 continue |
| 600 print ' %s is %s' % (k, v) | 524 print ' %s is %s' % (k, v) |
| 601 print | 525 print |
| 602 | 526 |
| 603 | 527 |
| 604 def solutions_to_git(input_solutions): | 528 def modify_solutions(input_solutions): |
| 605 """Modifies urls in solutions to point at Git repos. | 529 """Modifies urls in solutions to point at Git repos. |
| 606 | 530 |
| 607 returns: (git solution, svn root of first solution) tuple. | 531 returns: (git solution, buildspec) tuple. |
| 608 """ | 532 """ |
| 609 assert input_solutions | 533 assert input_solutions |
| 610 solutions = copy.deepcopy(input_solutions) | 534 solutions = copy.deepcopy(input_solutions) |
| 611 first_solution = True | 535 first_solution = True |
| 612 buildspec = None | 536 buildspec = None |
| 613 for solution in solutions: | 537 for solution in solutions: |
| 614 original_url = solution['url'] | 538 original_url = solution['url'] |
| 615 parsed_url = urlparse.urlparse(original_url) | 539 parsed_url = urlparse.urlparse(original_url) |
| 616 parsed_path = parsed_url.path | 540 parsed_path = parsed_url.path |
| 617 | 541 |
| 618 # Rewrite SVN urls into Git urls. | 542 # Rewrite SVN urls into Git urls. |
| 619 buildspec_m = re.match(BUILDSPEC_RE, parsed_path) | 543 buildspec_m = re.match(BUILDSPEC_RE, parsed_path) |
| 620 if first_solution and buildspec_m: | 544 if first_solution and buildspec_m: |
| 621 solution['url'] = GIT_BUILDSPEC_PATH | 545 solution['url'] = GIT_BUILDSPEC_PATH |
| 622 buildspec = BUILDSPEC_TYPE( | 546 buildspec = BUILDSPEC_TYPE( |
| 623 container=buildspec_m.group(1), | 547 container=buildspec_m.group(1), |
| 624 version=buildspec_m.group(2), | 548 version=buildspec_m.group(2), |
| 625 ) | 549 ) |
| 626 solution['deps_file'] = path.join(buildspec.container, buildspec.version, | 550 solution['deps_file'] = path.join( |
| 627 'DEPS') | 551 buildspec.container, buildspec.version, 'DEPS') |
| 628 elif parsed_path in RECOGNIZED_PATHS: | |
| 629 solution['url'] = RECOGNIZED_PATHS[parsed_path] | |
| 630 solution['deps_file'] = '.DEPS.git' | |
| 631 elif parsed_url.scheme == 'https' and 'googlesource' in parsed_url.netloc: | 552 elif parsed_url.scheme == 'https' and 'googlesource' in parsed_url.netloc: |
| 632 pass | 553 pass |
| 633 else: | 554 else: |
| 634 print 'Warning: %s' % ('path %r not recognized' % parsed_path,) | 555 print 'Warning: %s' % ('path %r not recognized' % parsed_path,) |
| 635 | 556 |
| 636 # Strip out deps containing $$V8_REV$$, etc. | 557 # Strip out deps containing $$V8_REV$$, etc. |
| 637 if 'custom_deps' in solution: | 558 if 'custom_deps' in solution: |
| 638 new_custom_deps = {} | 559 new_custom_deps = {} |
| 639 for deps_name, deps_value in solution['custom_deps'].iteritems(): | 560 for deps_name, deps_value in solution['custom_deps'].iteritems(): |
| 640 if deps_value and '$$' in deps_value: | 561 if deps_value and '$$' in deps_value: |
| 641 print 'Dropping %s:%s from custom deps' % (deps_name, deps_value) | 562 print 'Dropping %s:%s from custom deps' % (deps_name, deps_value) |
| 642 else: | 563 else: |
| 643 new_custom_deps[deps_name] = deps_value | 564 new_custom_deps[deps_name] = deps_value |
| 644 solution['custom_deps'] = new_custom_deps | 565 solution['custom_deps'] = new_custom_deps |
| 645 | 566 |
| 646 if first_solution: | |
| 647 root = parsed_path | |
| 648 first_solution = False | |
| 649 | |
| 650 solution['managed'] = False | 567 solution['managed'] = False |
| 651 # We don't want gclient to be using a safesync URL. Instead it should | 568 # We don't want gclient to be using a safesync URL. Instead it should |
| 652 # using the lkgr/lkcr branch/tags. | 569 # using the lkgr/lkcr branch/tags. |
| 653 if 'safesync_url' in solution: | 570 if 'safesync_url' in solution: |
| 654 print 'Removing safesync url %s from %s' % (solution['safesync_url'], | 571 print 'Removing safesync url %s from %s' % (solution['safesync_url'], |
| 655 parsed_path) | 572 parsed_path) |
| 656 del solution['safesync_url'] | 573 del solution['safesync_url'] |
| 657 return solutions, root, buildspec | 574 first_solution = False |
| 575 | |
| 576 return solutions, buildspec | |
| 658 | 577 |
| 659 | 578 |
| 660 def remove(target): | 579 def remove(target): |
| 661 """Remove a target by moving it into build.dead.""" | 580 """Remove a target by moving it into build.dead.""" |
| 662 dead_folder = path.join(BUILDER_DIR, 'build.dead') | 581 dead_folder = path.join(BUILDER_DIR, 'build.dead') |
| 663 if not path.exists(dead_folder): | 582 if not path.exists(dead_folder): |
| 664 os.makedirs(dead_folder) | 583 os.makedirs(dead_folder) |
| 665 os.rename(target, path.join(dead_folder, uuid.uuid4().hex)) | 584 os.rename(target, path.join(dead_folder, uuid.uuid4().hex)) |
| 666 | 585 |
| 667 | 586 |
| 668 def ensure_no_checkout(dir_names, scm_dirname): | 587 def ensure_no_checkout(dir_names): |
| 669 """Ensure that there is no undesired checkout under build/. | 588 """Ensure that there is no undesired checkout under build/.""" |
| 670 | 589 has_checkout = any(path.exists(path.join(os.getcwd(), dir_name, '.git')) |
| 671 If there is an incorrect checkout under build/, then | |
| 672 move build/ to build.dead/ | |
| 673 This function will check each directory in dir_names. | |
| 674 | |
| 675 scm_dirname is expected to be either ['.svn', '.git'] | |
| 676 """ | |
| 677 assert scm_dirname in ['.svn', '.git', '*'] | |
| 678 has_checkout = any(path.exists(path.join(os.getcwd(), dir_name, scm_dirname)) | |
| 679 for dir_name in dir_names) | 590 for dir_name in dir_names) |
| 680 | 591 |
| 681 if has_checkout or scm_dirname == '*': | 592 if has_checkout: |
| 682 build_dir = os.getcwd() | 593 build_dir = os.getcwd() |
| 683 prefix = '' | |
| 684 if scm_dirname != '*': | |
| 685 prefix = '%s detected in checkout, ' % scm_dirname | |
| 686 | |
| 687 for filename in os.listdir(build_dir): | 594 for filename in os.listdir(build_dir): |
| 688 deletion_target = path.join(build_dir, filename) | 595 deletion_target = path.join(build_dir, filename) |
| 689 print '%sdeleting %s...' % (prefix, deletion_target), | 596 print '.git detected in checkout, deleting %s...' % deletion_target, |
| 690 remove(deletion_target) | 597 remove(deletion_target) |
| 691 print 'done' | 598 print 'done' |
| 692 | 599 |
| 693 | 600 |
| 694 def gclient_configure(solutions, target_os, target_os_only, git_cache_dir): | 601 def gclient_configure(solutions, target_os, target_os_only, git_cache_dir): |
| 695 """Should do the same thing as gclient --spec='...'.""" | 602 """Should do the same thing as gclient --spec='...'.""" |
| 696 with codecs.open('.gclient', mode='w', encoding='utf-8') as f: | 603 with codecs.open('.gclient', mode='w', encoding='utf-8') as f: |
| 697 f.write(get_gclient_spec( | 604 f.write(get_gclient_spec( |
| 698 solutions, target_os, target_os_only, git_cache_dir)) | 605 solutions, target_os, target_os_only, git_cache_dir)) |
| 699 | 606 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 773 footers[m.group(1)] = m.group(2).strip() | 680 footers[m.group(1)] = m.group(2).strip() |
| 774 return footers | 681 return footers |
| 775 | 682 |
| 776 | 683 |
| 777 def get_commit_message_footer(message, key): | 684 def get_commit_message_footer(message, key): |
| 778 """Returns: (str/None) The footer value for 'key', or None if none was found. | 685 """Returns: (str/None) The footer value for 'key', or None if none was found. |
| 779 """ | 686 """ |
| 780 return get_commit_message_footer_map(message).get(key) | 687 return get_commit_message_footer_map(message).get(key) |
| 781 | 688 |
| 782 | 689 |
| 783 def get_svn_rev(git_hash, dir_name): | |
| 784 log = git('log', '-1', git_hash, cwd=dir_name) | |
| 785 git_svn_id = get_commit_message_footer(log, GIT_SVN_ID_FOOTER_KEY) | |
| 786 if not git_svn_id: | |
| 787 return None | |
| 788 m = GIT_SVN_ID_RE.match(git_svn_id) | |
| 789 if not m: | |
| 790 return None | |
| 791 return int(m.group(2)) | |
| 792 | |
| 793 | |
| 794 def get_git_hash(revision, branch, sln_dir): | |
| 795 """We want to search for the SVN revision on the git-svn branch. | |
| 796 | |
| 797 Note that git will search backwards from origin/master. | |
| 798 """ | |
| 799 match = "^%s: [^ ]*@%s " % (GIT_SVN_ID_FOOTER_KEY, revision) | |
| 800 ref = branch if branch.startswith('refs/') else 'origin/%s' % branch | |
| 801 cmd = ['log', '-E', '--grep', match, '--format=%H', '--max-count=1', ref] | |
| 802 result = git(*cmd, cwd=sln_dir).strip() | |
| 803 if result: | |
| 804 return result | |
| 805 raise SVNRevisionNotFound('We can\'t resolve svn r%s into a git hash in %s' % | |
| 806 (revision, sln_dir)) | |
| 807 | |
| 808 | |
| 809 def emit_log_lines(name, lines): | 690 def emit_log_lines(name, lines): |
| 810 for line in lines.splitlines(): | 691 for line in lines.splitlines(): |
| 811 print '@@@STEP_LOG_LINE@%s@%s@@@' % (name, line) | 692 print '@@@STEP_LOG_LINE@%s@%s@@@' % (name, line) |
| 812 print '@@@STEP_LOG_END@%s@@@' % name | 693 print '@@@STEP_LOG_END@%s@@@' % name |
| 813 | 694 |
| 814 | 695 |
| 815 def emit_properties(properties): | 696 def emit_properties(properties): |
| 816 for property_name, property_value in sorted(properties.items()): | 697 for property_name, property_value in sorted(properties.items()): |
| 817 print '@@@SET_BUILD_PROPERTY@%s@"%s"@@@' % (property_name, property_value) | 698 print '@@@SET_BUILD_PROPERTY@%s@"%s"@@@' % (property_name, property_value) |
| 818 | 699 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 853 | 734 |
| 854 | 735 |
| 855 def force_revision(folder_name, revision): | 736 def force_revision(folder_name, revision): |
| 856 split_revision = revision.split(':', 1) | 737 split_revision = revision.split(':', 1) |
| 857 branch = 'master' | 738 branch = 'master' |
| 858 if len(split_revision) == 2: | 739 if len(split_revision) == 2: |
| 859 # Support for "branch:revision" syntax. | 740 # Support for "branch:revision" syntax. |
| 860 branch, revision = split_revision | 741 branch, revision = split_revision |
| 861 | 742 |
| 862 if revision and revision.upper() != 'HEAD': | 743 if revision and revision.upper() != 'HEAD': |
| 863 if revision and revision.isdigit() and len(revision) < 40: | 744 git('checkout', '--force', revision, cwd=folder_name) |
| 864 # rev_num is really a svn revision number, convert it into a git hash. | |
| 865 git_ref = get_git_hash(int(revision), branch, folder_name) | |
| 866 else: | |
| 867 # rev_num is actually a git hash or ref, we can just use it. | |
| 868 git_ref = revision | |
| 869 git('checkout', '--force', git_ref, cwd=folder_name) | |
| 870 else: | 745 else: |
| 871 ref = branch if branch.startswith('refs/') else 'origin/%s' % branch | 746 ref = branch if branch.startswith('refs/') else 'origin/%s' % branch |
| 872 git('checkout', '--force', ref, cwd=folder_name) | 747 git('checkout', '--force', ref, cwd=folder_name) |
| 873 | 748 |
| 749 | |
| 874 def git_checkout(solutions, revisions, shallow, refs, git_cache_dir): | 750 def git_checkout(solutions, revisions, shallow, refs, git_cache_dir): |
| 875 build_dir = os.getcwd() | 751 build_dir = os.getcwd() |
| 876 # Before we do anything, break all git_cache locks. | 752 # Before we do anything, break all git_cache locks. |
| 877 if path.isdir(git_cache_dir): | 753 if path.isdir(git_cache_dir): |
| 878 git('cache', 'unlock', '-vv', '--force', '--all', | 754 git('cache', 'unlock', '-vv', '--force', '--all', |
| 879 '--cache-dir', git_cache_dir) | 755 '--cache-dir', git_cache_dir) |
| 880 for item in os.listdir(git_cache_dir): | 756 for item in os.listdir(git_cache_dir): |
| 881 filename = os.path.join(git_cache_dir, item) | 757 filename = os.path.join(git_cache_dir, item) |
| 882 if item.endswith('.lock'): | 758 if item.endswith('.lock'): |
| 883 raise Exception('%s exists after cache unlock' % filename) | 759 raise Exception('%s exists after cache unlock' % filename) |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 924 # Exited abnormally, theres probably something wrong. | 800 # Exited abnormally, theres probably something wrong. |
| 925 # Lets wipe the checkout and try again. | 801 # Lets wipe the checkout and try again. |
| 926 tries_left -= 1 | 802 tries_left -= 1 |
| 927 if tries_left > 0: | 803 if tries_left > 0: |
| 928 print 'Something failed: %s.' % str(e) | 804 print 'Something failed: %s.' % str(e) |
| 929 print 'waiting 5 seconds and trying again...' | 805 print 'waiting 5 seconds and trying again...' |
| 930 time.sleep(5) | 806 time.sleep(5) |
| 931 else: | 807 else: |
| 932 raise | 808 raise |
| 933 remove(sln_dir) | 809 remove(sln_dir) |
| 934 except SVNRevisionNotFound: | |
| 935 tries_left -= 1 | |
| 936 if tries_left > 0: | |
| 937 # If we don't have the correct revision, wait and try again. | |
| 938 print 'We can\'t find revision %s.' % revision | |
| 939 print 'The svn to git replicator is probably falling behind.' | |
| 940 print 'waiting 5 seconds and trying again...' | |
| 941 time.sleep(5) | |
| 942 else: | |
| 943 raise | |
| 944 | 810 |
| 945 git('clean', '-dff', cwd=sln_dir) | 811 git('clean', '-dff', cwd=sln_dir) |
| 946 | 812 |
| 947 if first_solution: | 813 if first_solution: |
| 948 git_ref = git('log', '--format=%H', '--max-count=1', | 814 git_ref = git('log', '--format=%H', '--max-count=1', |
| 949 cwd=sln_dir).strip() | 815 cwd=sln_dir).strip() |
| 950 first_solution = False | 816 first_solution = False |
| 951 return git_ref | 817 return git_ref |
| 952 | 818 |
| 953 | 819 |
| 954 def _download(url): | 820 def _download(url): |
| 955 """Fetch url and return content, with retries for flake.""" | 821 """Fetch url and return content, with retries for flake.""" |
| 956 for attempt in xrange(ATTEMPTS): | 822 for attempt in xrange(ATTEMPTS): |
| 957 try: | 823 try: |
| 958 return urllib2.urlopen(url).read() | 824 return urllib2.urlopen(url).read() |
| 959 except Exception: | 825 except Exception: |
| 960 if attempt == ATTEMPTS - 1: | 826 if attempt == ATTEMPTS - 1: |
| 961 raise | 827 raise |
| 962 | 828 |
| 963 | 829 |
| 964 def parse_diff(diff): | |
| 965 """Takes a unified diff and returns a list of diffed files and their diffs. | |
| 966 | |
| 967 The return format is a list of pairs of: | |
| 968 (<filename>, <diff contents>) | |
| 969 <diff contents> is inclusive of the diff line. | |
| 970 """ | |
| 971 result = [] | |
| 972 current_diff = '' | |
| 973 current_header = None | |
| 974 for line in diff.splitlines(): | |
| 975 # "diff" is for git style patches, and "Index: " is for SVN style patches. | |
| 976 if line.startswith('diff') or line.startswith('Index: '): | |
| 977 if current_header: | |
| 978 # If we are in a diff portion, then save the diff. | |
| 979 result.append((current_header, '%s\n' % current_diff)) | |
| 980 git_header_match = re.match(r'diff (?:--git )?(\S+) (\S+)', line) | |
| 981 svn_header_match = re.match(r'Index: (.*)', line) | |
| 982 | |
| 983 if git_header_match: | |
| 984 # First, see if its a git style header. | |
| 985 from_file = git_header_match.group(1) | |
| 986 to_file = git_header_match.group(2) | |
| 987 if from_file != to_file and from_file.startswith('a/'): | |
| 988 # Sometimes git prepends 'a/' and 'b/' in front of file paths. | |
| 989 from_file = from_file[2:] | |
| 990 current_header = from_file | |
| 991 | |
| 992 elif svn_header_match: | |
| 993 # Otherwise, check if its an SVN style header. | |
| 994 current_header = svn_header_match.group(1) | |
| 995 | |
| 996 else: | |
| 997 # Otherwise... I'm not really sure what to do with this. | |
| 998 raise InvalidDiff('Can\'t process header: %s\nFull diff:\n%s' % | |
| 999 (line, diff)) | |
| 1000 | |
| 1001 current_diff = '' | |
| 1002 current_diff += '%s\n' % line | |
| 1003 if current_header: | |
| 1004 # We hit EOF, gotta save the last diff. | |
| 1005 result.append((current_header, current_diff)) | |
| 1006 return result | |
| 1007 | |
| 1008 | |
| 1009 def get_svn_patch(patch_url): | |
| 1010 """Fetch patch from patch_url, return list of (filename, diff)""" | |
| 1011 svn_exe = 'svn.bat' if sys.platform.startswith('win') else 'svn' | |
| 1012 patch_data = call(svn_exe, 'cat', patch_url) | |
| 1013 return parse_diff(patch_data) | |
| 1014 | |
| 1015 | |
| 1016 def apply_svn_patch(patch_root, patches, whitelist=None, blacklist=None): | |
| 1017 """Expects a list of (filename, diff), applies it on top of patch_root.""" | |
| 1018 if whitelist: | |
| 1019 patches = [(name, diff) for name, diff in patches if name in whitelist] | |
| 1020 elif blacklist: | |
| 1021 patches = [(name, diff) for name, diff in patches if name not in blacklist] | |
| 1022 diffs = [diff for _, diff in patches] | |
| 1023 patch = ''.join(diffs) | |
| 1024 | |
| 1025 if patch: | |
| 1026 print '===Patching files===' | |
| 1027 for filename, _ in patches: | |
| 1028 print 'Patching %s' % filename | |
| 1029 try: | |
| 1030 call(PATCH_TOOL, '-p0', '--remove-empty-files', '--force', '--forward', | |
| 1031 stdin_data=patch, cwd=patch_root, tries=1) | |
| 1032 for filename, _ in patches: | |
| 1033 full_filename = path.abspath(path.join(patch_root, filename)) | |
| 1034 git('add', full_filename, cwd=path.dirname(full_filename)) | |
| 1035 except SubprocessFailed as e: | |
| 1036 raise PatchFailed(e.message, e.code, e.output) | |
| 1037 | |
| 1038 def apply_rietveld_issue(issue, patchset, root, server, _rev_map, _revision, | 830 def apply_rietveld_issue(issue, patchset, root, server, _rev_map, _revision, |
| 1039 email_file, key_file, whitelist=None, blacklist=None): | 831 email_file, key_file, whitelist=None, blacklist=None): |
| 1040 apply_issue_bin = ('apply_issue.bat' if sys.platform.startswith('win') | 832 apply_issue_bin = ('apply_issue.bat' if sys.platform.startswith('win') |
| 1041 else 'apply_issue') | 833 else 'apply_issue') |
| 1042 cmd = [apply_issue_bin, | 834 cmd = [apply_issue_bin, |
| 1043 # The patch will be applied on top of this directory. | 835 # The patch will be applied on top of this directory. |
| 1044 '--root_dir', root, | 836 '--root_dir', root, |
| 1045 # Tell apply_issue how to fetch the patch. | 837 # Tell apply_issue how to fetch the patch. |
| 1046 '--issue', issue, | 838 '--issue', issue, |
| 1047 '--server', server, | 839 '--server', server, |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1123 os.remove(flag_file) | 915 os.remove(flag_file) |
| 1124 | 916 |
| 1125 | 917 |
| 1126 def emit_flag(flag_file): | 918 def emit_flag(flag_file): |
| 1127 """Deposit a bot update flag on the system to tell gclient not to run.""" | 919 """Deposit a bot update flag on the system to tell gclient not to run.""" |
| 1128 print 'Emitting flag file at %s' % flag_file | 920 print 'Emitting flag file at %s' % flag_file |
| 1129 with open(flag_file, 'wb') as f: | 921 with open(flag_file, 'wb') as f: |
| 1130 f.write('Success!') | 922 f.write('Success!') |
| 1131 | 923 |
| 1132 | 924 |
| 1133 def get_commit_position_for_git_svn(url, revision): | |
| 1134 """Generates a commit position string for a 'git-svn' URL/revision. | |
| 1135 | |
| 1136 If the 'git-svn' URL maps to a known project, we will construct a commit | |
| 1137 position branch value by applying substitution on the SVN URL. | |
| 1138 """ | |
| 1139 # Identify the base URL so we can strip off trunk/branch name | |
| 1140 project_config = branch = None | |
| 1141 for _, project_config in GIT_SVN_PROJECT_MAP.iteritems(): | |
| 1142 if url.startswith(project_config['svn_url']): | |
| 1143 branch = url[len(project_config['svn_url']):] | |
| 1144 break | |
| 1145 | |
| 1146 if branch: | |
| 1147 # Strip any leading slashes | |
| 1148 branch = branch.lstrip('/') | |
| 1149 | |
| 1150 # Try and map the branch | |
| 1151 for pattern, repl in project_config.get('branch_map', ()): | |
| 1152 nbranch, subn = re.subn(pattern, repl, branch, count=1) | |
| 1153 if subn: | |
| 1154 print 'INFO: Mapped SVN branch to Git branch [%s] => [%s]' % ( | |
| 1155 branch, nbranch) | |
| 1156 branch = nbranch | |
| 1157 break | |
| 1158 else: | |
| 1159 # Use generic 'svn' branch | |
| 1160 print 'INFO: Could not resolve project for SVN URL %r' % (url,) | |
| 1161 branch = 'svn' | |
| 1162 return '%s@{#%s}' % (branch, revision) | |
| 1163 | |
| 1164 | |
| 1165 def get_commit_position(git_path, revision='HEAD'): | 925 def get_commit_position(git_path, revision='HEAD'): |
| 1166 """Dumps the 'git' log for a specific revision and parses out the commit | 926 """Dumps the 'git' log for a specific revision and parses out the commit |
| 1167 position. | 927 position. |
| 1168 | 928 |
| 1169 If a commit position metadata key is found, its value will be returned. | 929 If a commit position metadata key is found, its value will be returned. |
| 1170 | |
| 1171 Otherwise, we will search for a 'git-svn' metadata entry. If one is found, | |
| 1172 we will compose a commit position from it, using its SVN revision value as | |
| 1173 the revision. | |
| 1174 | |
| 1175 If the 'git-svn' URL maps to a known project, we will construct a commit | |
| 1176 position branch value by truncating the URL, mapping 'trunk' to | |
| 1177 "refs/heads/master". Otherwise, we will return the generic branch, 'svn'. | |
| 1178 """ | 930 """ |
| 1179 git_log = git('log', '--format=%B', '-n1', revision, cwd=git_path) | 931 git_log = git('log', '--format=%B', '-n1', revision, cwd=git_path) |
| 1180 footer_map = get_commit_message_footer_map(git_log) | 932 footer_map = get_commit_message_footer_map(git_log) |
| 1181 | 933 |
| 1182 # Search for commit position metadata | 934 # Search for commit position metadata |
| 1183 value = (footer_map.get(COMMIT_POSITION_FOOTER_KEY) or | 935 value = (footer_map.get(COMMIT_POSITION_FOOTER_KEY) or |
| 1184 footer_map.get(COMMIT_ORIGINAL_POSITION_FOOTER_KEY)) | 936 footer_map.get(COMMIT_ORIGINAL_POSITION_FOOTER_KEY)) |
| 1185 if value: | 937 if value: |
| 1186 return value | 938 return value |
| 1187 | |
| 1188 # Compose a commit position from 'git-svn' metadata | |
| 1189 value = footer_map.get(GIT_SVN_ID_FOOTER_KEY) | |
| 1190 if value: | |
| 1191 m = GIT_SVN_ID_RE.match(value) | |
| 1192 if not m: | |
| 1193 raise ValueError("Invalid 'git-svn' value: [%s]" % (value,)) | |
| 1194 return get_commit_position_for_git_svn(m.group(1), m.group(2)) | |
| 1195 return None | 939 return None |
| 1196 | 940 |
| 1197 | 941 |
| 1198 def parse_got_revision(gclient_output, got_revision_mapping, use_svn_revs): | 942 def parse_got_revision(gclient_output, got_revision_mapping): |
| 1199 """Translate git gclient revision mapping to build properties. | 943 """Translate git gclient revision mapping to build properties.""" |
| 1200 | |
| 1201 If use_svn_revs is True, then translate git hashes in the revision mapping | |
| 1202 to svn revision numbers. | |
| 1203 """ | |
| 1204 properties = {} | 944 properties = {} |
| 1205 solutions_output = { | 945 solutions_output = { |
| 1206 # Make sure path always ends with a single slash. | 946 # Make sure path always ends with a single slash. |
| 1207 '%s/' % path.rstrip('/') : solution_output for path, solution_output | 947 '%s/' % path.rstrip('/') : solution_output for path, solution_output |
| 1208 in gclient_output['solutions'].iteritems() | 948 in gclient_output['solutions'].iteritems() |
| 1209 } | 949 } |
| 1210 for dir_name, property_name in got_revision_mapping.iteritems(): | 950 for dir_name, property_name in got_revision_mapping.iteritems(): |
| 1211 # Make sure dir_name always ends with a single slash. | 951 # Make sure dir_name always ends with a single slash. |
| 1212 dir_name = '%s/' % dir_name.rstrip('/') | 952 dir_name = '%s/' % dir_name.rstrip('/') |
| 1213 if dir_name not in solutions_output: | 953 if dir_name not in solutions_output: |
| 1214 continue | 954 continue |
| 1215 solution_output = solutions_output[dir_name] | 955 solution_output = solutions_output[dir_name] |
| 1216 if solution_output.get('scm') is None: | 956 if solution_output.get('scm') is None: |
| 1217 # This is an ignored DEPS, so the output got_revision should be 'None'. | 957 # This is an ignored DEPS, so the output got_revision should be 'None'. |
| 1218 git_revision = revision = commit_position = None | 958 git_revision = revision = commit_position = None |
| 1219 else: | 959 else: |
| 1220 # Since we are using .DEPS.git, everything had better be git. | 960 # Since we are using .DEPS.git, everything had better be git. |
| 1221 assert solution_output.get('scm') == 'git' | 961 assert solution_output.get('scm') == 'git' |
| 1222 git_revision = git('rev-parse', 'HEAD', cwd=dir_name).strip() | 962 revision = git('rev-parse', 'HEAD', cwd=dir_name).strip() |
| 1223 if use_svn_revs: | |
| 1224 revision = get_svn_rev(git_revision, dir_name) | |
| 1225 if not revision: | |
| 1226 revision = git_revision | |
| 1227 else: | |
| 1228 revision = git_revision | |
| 1229 commit_position = get_commit_position(dir_name) | 963 commit_position = get_commit_position(dir_name) |
| 1230 | 964 |
| 1231 properties[property_name] = revision | 965 properties[property_name] = revision |
| 1232 if revision != git_revision: | 966 if revision != git_revision: |
| 1233 properties['%s_git' % property_name] = git_revision | 967 properties['%s_git' % property_name] = git_revision |
| 1234 if commit_position: | 968 if commit_position: |
| 1235 properties['%s_cp' % property_name] = commit_position | 969 properties['%s_cp' % property_name] = commit_position |
| 1236 | 970 |
| 1237 return properties | 971 return properties |
| 1238 | 972 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1250 def ensure_deps_revisions(deps_url_mapping, solutions, revisions): | 984 def ensure_deps_revisions(deps_url_mapping, solutions, revisions): |
| 1251 """Ensure correct DEPS revisions, ignores solutions.""" | 985 """Ensure correct DEPS revisions, ignores solutions.""" |
| 1252 for deps_name, deps_data in sorted(deps_url_mapping.items()): | 986 for deps_name, deps_data in sorted(deps_url_mapping.items()): |
| 1253 if deps_name.strip('/') in solutions: | 987 if deps_name.strip('/') in solutions: |
| 1254 # This has already been forced to the correct solution by git_checkout(). | 988 # This has already been forced to the correct solution by git_checkout(). |
| 1255 continue | 989 continue |
| 1256 revision = get_target_revision(deps_name, deps_data.get('url', None), | 990 revision = get_target_revision(deps_name, deps_data.get('url', None), |
| 1257 revisions) | 991 revisions) |
| 1258 if not revision: | 992 if not revision: |
| 1259 continue | 993 continue |
| 1260 # TODO(hinoka): Catch SVNRevisionNotFound error maybe? | |
| 1261 git('fetch', 'origin', cwd=deps_name) | 994 git('fetch', 'origin', cwd=deps_name) |
| 1262 force_revision(deps_name, revision) | 995 force_revision(deps_name, revision) |
| 1263 | 996 |
| 1264 | 997 |
| 1265 def ensure_checkout(solutions, revisions, first_sln, target_os, target_os_only, | 998 def ensure_checkout(solutions, revisions, first_sln, target_os, target_os_only, |
| 1266 patch_root, issue, patchset, patch_url, rietveld_server, | 999 patch_root, issue, patchset, rietveld_server, |
| 1267 gerrit_repo, gerrit_ref, gerrit_rebase_patch_ref, | 1000 gerrit_repo, gerrit_ref, gerrit_rebase_patch_ref, |
| 1268 revision_mapping, apply_issue_email_file, | 1001 revision_mapping, apply_issue_email_file, |
| 1269 apply_issue_key_file, buildspec, gyp_env, shallow, runhooks, | 1002 apply_issue_key_file, buildspec, gyp_env, shallow, runhooks, |
| 1270 refs, git_cache_dir, gerrit_reset): | 1003 refs, git_cache_dir, gerrit_reset): |
| 1271 # Get a checkout of each solution, without DEPS or hooks. | 1004 # Get a checkout of each solution, without DEPS or hooks. |
| 1272 # Calling git directly because there is no way to run Gclient without | 1005 # Calling git directly because there is no way to run Gclient without |
| 1273 # invoking DEPS. | 1006 # invoking DEPS. |
| 1274 print 'Fetching Git checkout' | 1007 print 'Fetching Git checkout' |
| 1275 | 1008 |
| 1276 git_ref = git_checkout(solutions, revisions, shallow, refs, git_cache_dir) | 1009 git_ref = git_checkout(solutions, revisions, shallow, refs, git_cache_dir) |
| 1277 | 1010 |
| 1278 patches = None | 1011 patches = None |
| 1279 if patch_url: | |
| 1280 patches = get_svn_patch(patch_url) | |
| 1281 | 1012 |
| 1282 print '===Processing patch solutions===' | 1013 print '===Processing patch solutions===' |
| 1283 already_patched = [] | 1014 already_patched = [] |
| 1284 patch_root = patch_root or '' | 1015 patch_root = patch_root or '' |
| 1285 print 'Patch root is %r' % patch_root | 1016 print 'Patch root is %r' % patch_root |
| 1286 for solution in solutions: | 1017 for solution in solutions: |
| 1287 print 'Processing solution %r' % solution['name'] | 1018 print 'Processing solution %r' % solution['name'] |
| 1288 if (patch_root == solution['name'] or | 1019 if (patch_root == solution['name'] or |
| 1289 solution['name'].startswith(patch_root + '/')): | 1020 solution['name'].startswith(patch_root + '/')): |
| 1290 relative_root = solution['name'][len(patch_root) + 1:] | 1021 relative_root = solution['name'][len(patch_root) + 1:] |
| 1291 target = '/'.join([relative_root, 'DEPS']).lstrip('/') | 1022 target = '/'.join([relative_root, 'DEPS']).lstrip('/') |
| 1292 print ' relative root is %r, target is %r' % (relative_root, target) | 1023 print ' relative root is %r, target is %r' % (relative_root, target) |
| 1293 if patches: | 1024 if issue: |
| 1294 apply_svn_patch(patch_root, patches, whitelist=[target]) | |
| 1295 already_patched.append(target) | |
| 1296 elif issue: | |
| 1297 apply_rietveld_issue(issue, patchset, patch_root, rietveld_server, | 1025 apply_rietveld_issue(issue, patchset, patch_root, rietveld_server, |
| 1298 revision_mapping, git_ref, apply_issue_email_file, | 1026 revision_mapping, git_ref, apply_issue_email_file, |
| 1299 apply_issue_key_file, whitelist=[target]) | 1027 apply_issue_key_file, whitelist=[target]) |
| 1300 already_patched.append(target) | 1028 already_patched.append(target) |
| 1301 elif gerrit_ref and gerrit_rebase_patch_ref: | 1029 elif gerrit_ref and gerrit_rebase_patch_ref: |
| 1302 apply_gerrit_ref(gerrit_repo, gerrit_ref, patch_root, gerrit_reset, | 1030 apply_gerrit_ref(gerrit_repo, gerrit_ref, patch_root, gerrit_reset, |
| 1303 True) | 1031 True) |
| 1304 | 1032 |
| 1305 # Ensure our build/ directory is set up with the correct .gclient file. | 1033 # Ensure our build/ directory is set up with the correct .gclient file. |
| 1306 gclient_configure(solutions, target_os, target_os_only, git_cache_dir) | 1034 gclient_configure(solutions, target_os, target_os_only, git_cache_dir) |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1321 # Run gclient runhooks if we're on an official builder. | 1049 # Run gclient runhooks if we're on an official builder. |
| 1322 # TODO(hinoka): Remove this when the official builders run their own | 1050 # TODO(hinoka): Remove this when the official builders run their own |
| 1323 # runhooks step. | 1051 # runhooks step. |
| 1324 gclient_runhooks(gyp_env) | 1052 gclient_runhooks(gyp_env) |
| 1325 | 1053 |
| 1326 # Finally, ensure that all DEPS are pinned to the correct revision. | 1054 # Finally, ensure that all DEPS are pinned to the correct revision. |
| 1327 dir_names = [sln['name'] for sln in solutions] | 1055 dir_names = [sln['name'] for sln in solutions] |
| 1328 ensure_deps_revisions(gclient_output.get('solutions', {}), | 1056 ensure_deps_revisions(gclient_output.get('solutions', {}), |
| 1329 dir_names, revisions) | 1057 dir_names, revisions) |
| 1330 # Apply the rest of the patch here (sans DEPS) | 1058 # Apply the rest of the patch here (sans DEPS) |
| 1331 if patches: | 1059 if issue: |
| 1332 apply_svn_patch(patch_root, patches, blacklist=already_patched) | |
| 1333 elif issue: | |
| 1334 apply_rietveld_issue(issue, patchset, patch_root, rietveld_server, | 1060 apply_rietveld_issue(issue, patchset, patch_root, rietveld_server, |
| 1335 revision_mapping, git_ref, apply_issue_email_file, | 1061 revision_mapping, git_ref, apply_issue_email_file, |
| 1336 apply_issue_key_file, blacklist=already_patched) | 1062 apply_issue_key_file, blacklist=already_patched) |
| 1337 elif gerrit_ref and not gerrit_rebase_patch_ref: | 1063 elif gerrit_ref and not gerrit_rebase_patch_ref: |
| 1338 apply_gerrit_ref(gerrit_repo, gerrit_ref, patch_root, gerrit_reset, False) | 1064 apply_gerrit_ref(gerrit_repo, gerrit_ref, patch_root, gerrit_reset, False) |
| 1339 | 1065 |
| 1340 # Reset the deps_file point in the solutions so that hooks get run properly. | 1066 # Reset the deps_file point in the solutions so that hooks get run properly. |
| 1341 for sln in solutions: | 1067 for sln in solutions: |
| 1342 sln['deps_file'] = sln.get('deps_file', 'DEPS').replace('.DEPS.git', 'DEPS') | 1068 sln['deps_file'] = sln.get('deps_file', 'DEPS').replace('.DEPS.git', 'DEPS') |
| 1343 gclient_configure(solutions, target_os, target_os_only, git_cache_dir) | 1069 gclient_configure(solutions, target_os, target_os_only, git_cache_dir) |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1359 expanded_revisions.extend(revision.split(',')) | 1085 expanded_revisions.extend(revision.split(',')) |
| 1360 for revision in expanded_revisions: | 1086 for revision in expanded_revisions: |
| 1361 split_revision = revision.split('@') | 1087 split_revision = revision.split('@') |
| 1362 if len(split_revision) == 1: | 1088 if len(split_revision) == 1: |
| 1363 # This is just a plain revision, set it as the revision for root. | 1089 # This is just a plain revision, set it as the revision for root. |
| 1364 results[root] = split_revision[0] | 1090 results[root] = split_revision[0] |
| 1365 elif len(split_revision) == 2: | 1091 elif len(split_revision) == 2: |
| 1366 # This is an alt_root@revision argument. | 1092 # This is an alt_root@revision argument. |
| 1367 current_root, current_rev = split_revision | 1093 current_root, current_rev = split_revision |
| 1368 | 1094 |
| 1369 # We want to normalize svn/git urls into .git urls. | |
| 1370 parsed_root = urlparse.urlparse(current_root) | 1095 parsed_root = urlparse.urlparse(current_root) |
| 1371 if parsed_root.scheme == 'svn': | 1096 if parsed_root.scheme in ['http', 'https']: |
| 1372 if parsed_root.path in RECOGNIZED_PATHS: | 1097 # We want to normalize git urls into .git urls. |
| 1373 normalized_root = RECOGNIZED_PATHS[parsed_root.path] | |
| 1374 else: | |
| 1375 print 'WARNING: SVN path %s not recognized, ignoring' % current_root | |
| 1376 continue | |
| 1377 elif parsed_root.scheme in ['http', 'https']: | |
| 1378 normalized_root = 'https://%s/%s' % (parsed_root.netloc, | 1098 normalized_root = 'https://%s/%s' % (parsed_root.netloc, |
| 1379 parsed_root.path) | 1099 parsed_root.path) |
| 1380 if not normalized_root.endswith('.git'): | 1100 if not normalized_root.endswith('.git'): |
| 1381 normalized_root = '%s.git' % normalized_root | 1101 normalized_root = '%s.git' % normalized_root |
| 1382 elif parsed_root.scheme: | 1102 elif parsed_root.scheme: |
| 1383 print 'WARNING: Unrecognized scheme %s, ignoring' % parsed_root.scheme | 1103 print 'WARNING: Unrecognized scheme %s, ignoring' % parsed_root.scheme |
| 1384 continue | 1104 continue |
| 1385 else: | 1105 else: |
| 1386 # This is probably a local path. | 1106 # This is probably a local path. |
| 1387 normalized_root = current_root.strip('/') | 1107 normalized_root = current_root.strip('/') |
| 1388 | 1108 |
| 1389 results[normalized_root] = current_rev | 1109 results[normalized_root] = current_rev |
| 1390 else: | 1110 else: |
| 1391 print ('WARNING: %r is not recognized as a valid revision specification,' | 1111 print ('WARNING: %r is not recognized as a valid revision specification,' |
| 1392 'skipping' % revision) | 1112 'skipping' % revision) |
| 1393 return results | 1113 return results |
| 1394 | 1114 |
| 1395 | 1115 |
| 1396 def parse_args(): | 1116 def parse_args(): |
| 1397 parse = optparse.OptionParser() | 1117 parse = optparse.OptionParser() |
| 1398 | 1118 |
| 1399 parse.add_option('--issue', help='Issue number to patch from.') | 1119 parse.add_option('--issue', help='Issue number to patch from.') |
| 1400 parse.add_option('--patchset', | 1120 parse.add_option('--patchset', |
| 1401 help='Patchset from issue to patch from, if applicable.') | 1121 help='Patchset from issue to patch from, if applicable.') |
| 1402 parse.add_option('--apply_issue_email_file', | 1122 parse.add_option('--apply_issue_email_file', |
| 1403 help='--email-file option passthrough for apply_patch.py.') | 1123 help='--email-file option passthrough for apply_patch.py.') |
| 1404 parse.add_option('--apply_issue_key_file', | 1124 parse.add_option('--apply_issue_key_file', |
| 1405 help='--private-key-file option passthrough for ' | 1125 help='--private-key-file option passthrough for ' |
| 1406 'apply_patch.py.') | 1126 'apply_patch.py.') |
| 1407 parse.add_option('--patch_url', help='Optional URL to SVN patch.') | 1127 parse.add_option('--patch_url', help='DEPRECATED') |
| 1408 parse.add_option('--root', dest='patch_root', | 1128 parse.add_option('--root', dest='patch_root', |
| 1409 help='DEPRECATED: Use --patch_root.') | 1129 help='DEPRECATED: Use --patch_root.') |
| 1410 parse.add_option('--patch_root', help='Directory to patch on top of.') | 1130 parse.add_option('--patch_root', help='Directory to patch on top of.') |
| 1411 parse.add_option('--rietveld_server', | 1131 parse.add_option('--rietveld_server', |
| 1412 default='codereview.chromium.org', | 1132 default='codereview.chromium.org', |
| 1413 help='Rietveld server.') | 1133 help='Rietveld server.') |
| 1414 parse.add_option('--gerrit_repo', | 1134 parse.add_option('--gerrit_repo', |
| 1415 help='Gerrit repository to pull the ref from.') | 1135 help='Gerrit repository to pull the ref from.') |
| 1416 parse.add_option('--gerrit_ref', help='Gerrit ref to apply.') | 1136 parse.add_option('--gerrit_ref', help='Gerrit ref to apply.') |
| 1417 parse.add_option('--gerrit_rebase_patch_ref', action='store_true', | 1137 parse.add_option('--gerrit_rebase_patch_ref', action='store_true', |
| 1418 help='Rebase Gerrit patch ref after of checking it out.') | 1138 help='Rebase Gerrit patch ref after of checking it out.') |
| 1419 parse.add_option('--gerrit_no_reset', action='store_true', | 1139 parse.add_option('--gerrit_no_reset', action='store_true', |
| 1420 help='Bypass calling reset after applying a gerrit ref.') | 1140 help='Bypass calling reset after applying a gerrit ref.') |
| 1421 parse.add_option('--specs', help='Gcilent spec.') | 1141 parse.add_option('--specs', help='Gcilent spec.') |
| 1422 parse.add_option('--master', | 1142 parse.add_option('--master', |
| 1423 help='Master name. If specified and it is not in ' | 1143 help='Master name. If specified and it is not in ' |
| 1424 'bot_update\'s whitelist, bot_update will be noop.') | 1144 'bot_update\'s whitelist, bot_update will be noop.') |
| 1425 parse.add_option('-f', '--force', action='store_true', | 1145 parse.add_option('-f', '--force', action='store_true', |
| 1426 help='Bypass check to see if we want to be run. ' | 1146 help='Bypass check to see if we want to be run. ' |
| 1427 'Should ONLY be used locally or by smart recipes.') | 1147 'Should ONLY be used locally or by smart recipes.') |
| 1428 parse.add_option('--revision_mapping', | 1148 parse.add_option('--revision_mapping', |
| 1429 help='{"path/to/repo/": "property_name"}') | 1149 help='{"path/to/repo/": "property_name"}') |
| 1430 parse.add_option('--revision_mapping_file', | 1150 parse.add_option('--revision_mapping_file', |
| 1431 help=('Same as revision_mapping, except its a path to a json' | 1151 help=('Same as revision_mapping, except its a path to a json' |
| 1432 ' file containing that format.')) | 1152 ' file containing that format.')) |
| 1433 parse.add_option('--revision', action='append', default=[], | 1153 parse.add_option('--revision', action='append', default=[], |
| 1434 help='Revision to check out. Can be an SVN revision number, ' | 1154 help='Revision to check out. Can be any form of git ref. ' |
| 1435 'git hash, or any form of git ref. Can prepend ' | 1155 'Can prepend root@<rev> to specify which repository, ' |
| 1436 'root@<rev> to specify which repository, where root ' | 1156 'where root is either a filesystem path or git https ' |
| 1437 'is either a filesystem path, git https url, or ' | 1157 'url. To specify Tip of Tree, set rev to HEAD. ') |
| 1438 'svn url. To specify Tip of Tree, set rev to HEAD.' | |
| 1439 'To specify a git branch and an SVN rev, <rev> can be ' | |
| 1440 'set to <branch>:<revision>.') | |
| 1441 parse.add_option('--output_manifest', action='store_true', | 1158 parse.add_option('--output_manifest', action='store_true', |
| 1442 help=('Add manifest json to the json output.')) | 1159 help=('Add manifest json to the json output.')) |
| 1443 parse.add_option('--slave_name', default=socket.getfqdn().split('.')[0], | 1160 parse.add_option('--slave_name', default=socket.getfqdn().split('.')[0], |
| 1444 help='Hostname of the current machine, ' | 1161 help='Hostname of the current machine, ' |
| 1445 'used for determining whether or not to activate.') | 1162 'used for determining whether or not to activate.') |
| 1446 parse.add_option('--builder_name', help='Name of the builder, ' | 1163 parse.add_option('--builder_name', help='Name of the builder, ' |
| 1447 'used for determining whether or not to activate.') | 1164 'used for determining whether or not to activate.') |
| 1448 parse.add_option('--build_dir', default=os.getcwd()) | 1165 parse.add_option('--build_dir', default=os.getcwd()) |
| 1449 parse.add_option('--flag_file', default=path.join(os.getcwd(), | 1166 parse.add_option('--flag_file', default=path.join(os.getcwd(), |
| 1450 'update.flag')) | 1167 'update.flag')) |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1504 options.git_cache_dir = options.git_cache_dir.replace('\\', '\\\\') | 1221 options.git_cache_dir = options.git_cache_dir.replace('\\', '\\\\') |
| 1505 | 1222 |
| 1506 return options, args | 1223 return options, args |
| 1507 | 1224 |
| 1508 | 1225 |
| 1509 def prepare(options, git_slns, active): | 1226 def prepare(options, git_slns, active): |
| 1510 """Prepares the target folder before we checkout.""" | 1227 """Prepares the target folder before we checkout.""" |
| 1511 dir_names = [sln.get('name') for sln in git_slns if 'name' in sln] | 1228 dir_names = [sln.get('name') for sln in git_slns if 'name' in sln] |
| 1512 # If we're active now, but the flag file doesn't exist (we weren't active | 1229 # If we're active now, but the flag file doesn't exist (we weren't active |
| 1513 # last run) or vice versa, blow away all checkouts. | 1230 # last run) or vice versa, blow away all checkouts. |
| 1514 if bool(active) != bool(check_flag(options.flag_file)): | 1231 if options.clobber or (bool(active) != bool(check_flag(options.flag_file))): |
| 1515 ensure_no_checkout(dir_names, '*') | 1232 ensure_no_checkout(dir_names) |
| 1516 if options.output_json: | 1233 if options.output_json: |
| 1517 # Make sure we tell recipes that we didn't run if the script exits here. | 1234 # Make sure we tell recipes that we didn't run if the script exits here. |
| 1518 emit_json(options.output_json, did_run=active) | 1235 emit_json(options.output_json, did_run=active) |
| 1519 if active: | 1236 emit_flag(options.flag_file) |
| 1520 if options.clobber: | |
| 1521 ensure_no_checkout(dir_names, '*') | |
| 1522 else: | |
| 1523 ensure_no_checkout(dir_names, '.svn') | |
| 1524 emit_flag(options.flag_file) | |
| 1525 else: | |
| 1526 delete_flag(options.flag_file) | |
| 1527 raise Inactive # This is caught in main() and we exit cleanly. | |
| 1528 | 1237 |
| 1529 # Do a shallow checkout if the disk is less than 100GB. | 1238 # Do a shallow checkout if the disk is less than 100GB. |
| 1530 total_disk_space, free_disk_space = get_total_disk_space() | 1239 total_disk_space, free_disk_space = get_total_disk_space() |
| 1531 total_disk_space_gb = int(total_disk_space / (1024 * 1024 * 1024)) | 1240 total_disk_space_gb = int(total_disk_space / (1024 * 1024 * 1024)) |
| 1532 used_disk_space_gb = int((total_disk_space - free_disk_space) | 1241 used_disk_space_gb = int((total_disk_space - free_disk_space) |
| 1533 / (1024 * 1024 * 1024)) | 1242 / (1024 * 1024 * 1024)) |
| 1534 percent_used = int(used_disk_space_gb * 100 / total_disk_space_gb) | 1243 percent_used = int(used_disk_space_gb * 100 / total_disk_space_gb) |
| 1535 step_text = '[%dGB/%dGB used (%d%%)]' % (used_disk_space_gb, | 1244 step_text = '[%dGB/%dGB used (%d%%)]' % (used_disk_space_gb, |
| 1536 total_disk_space_gb, | 1245 total_disk_space_gb, |
| 1537 percent_used) | 1246 percent_used) |
| 1538 if not options.output_json: | 1247 if not options.output_json: |
| 1539 print '@@@STEP_TEXT@%s@@@' % step_text | 1248 print '@@@STEP_TEXT@%s@@@' % step_text |
| 1540 if not options.shallow: | 1249 if not options.shallow: |
| 1541 options.shallow = (total_disk_space < SHALLOW_CLONE_THRESHOLD | 1250 options.shallow = (total_disk_space < SHALLOW_CLONE_THRESHOLD |
| 1542 and not options.no_shallow) | 1251 and not options.no_shallow) |
| 1543 | 1252 |
| 1544 # The first solution is where the primary DEPS file resides. | 1253 # The first solution is where the primary DEPS file resides. |
| 1545 first_sln = dir_names[0] | 1254 first_sln = dir_names[0] |
| 1546 | 1255 |
| 1547 # Split all the revision specifications into a nice dict. | 1256 # Split all the revision specifications into a nice dict. |
| 1548 print 'Revisions: %s' % options.revision | 1257 print 'Revisions: %s' % options.revision |
| 1549 revisions = parse_revisions(options.revision, first_sln) | 1258 revisions = parse_revisions(options.revision, first_sln) |
| 1550 print 'Fetching Git checkout at %s@%s' % (first_sln, revisions[first_sln]) | 1259 print 'Fetching Git checkout at %s@%s' % (first_sln, revisions[first_sln]) |
| 1551 return revisions, step_text | 1260 return revisions, step_text |
| 1552 | 1261 |
| 1553 | 1262 |
| 1554 def checkout(options, git_slns, specs, buildspec, master, | 1263 def checkout(options, git_slns, specs, buildspec, master, revisions, step_text): |
| 1555 svn_root, revisions, step_text): | |
| 1556 first_sln = git_slns[0]['name'] | 1264 first_sln = git_slns[0]['name'] |
| 1557 dir_names = [sln.get('name') for sln in git_slns if 'name' in sln] | 1265 dir_names = [sln.get('name') for sln in git_slns if 'name' in sln] |
| 1558 try: | 1266 try: |
| 1559 # Outer try is for catching patch failures and exiting gracefully. | 1267 # Outer try is for catching patch failures and exiting gracefully. |
| 1560 # Inner try is for catching gclient failures and retrying gracefully. | 1268 # Inner try is for catching gclient failures and retrying gracefully. |
| 1561 try: | 1269 try: |
| 1562 checkout_parameters = dict( | 1270 checkout_parameters = dict( |
| 1563 # First, pass in the base of what we want to check out. | 1271 # First, pass in the base of what we want to check out. |
| 1564 solutions=git_slns, | 1272 solutions=git_slns, |
| 1565 revisions=revisions, | 1273 revisions=revisions, |
| 1566 first_sln=first_sln, | 1274 first_sln=first_sln, |
| 1567 | 1275 |
| 1568 # Also, target os variables for gclient. | 1276 # Also, target os variables for gclient. |
| 1569 target_os=specs.get('target_os', []), | 1277 target_os=specs.get('target_os', []), |
| 1570 target_os_only=specs.get('target_os_only', False), | 1278 target_os_only=specs.get('target_os_only', False), |
| 1571 | 1279 |
| 1572 # Then, pass in information about how to patch. | 1280 # Then, pass in information about how to patch. |
| 1573 patch_root=options.patch_root, | 1281 patch_root=options.patch_root, |
| 1574 issue=options.issue, | 1282 issue=options.issue, |
| 1575 patchset=options.patchset, | 1283 patchset=options.patchset, |
| 1576 patch_url=options.patch_url, | |
| 1577 rietveld_server=options.rietveld_server, | 1284 rietveld_server=options.rietveld_server, |
| 1578 gerrit_repo=options.gerrit_repo, | 1285 gerrit_repo=options.gerrit_repo, |
| 1579 gerrit_ref=options.gerrit_ref, | 1286 gerrit_ref=options.gerrit_ref, |
| 1580 gerrit_rebase_patch_ref=options.gerrit_rebase_patch_ref, | 1287 gerrit_rebase_patch_ref=options.gerrit_rebase_patch_ref, |
| 1581 revision_mapping=options.revision_mapping, | 1288 revision_mapping=options.revision_mapping, |
| 1582 apply_issue_email_file=options.apply_issue_email_file, | 1289 apply_issue_email_file=options.apply_issue_email_file, |
| 1583 apply_issue_key_file=options.apply_issue_key_file, | 1290 apply_issue_key_file=options.apply_issue_key_file, |
| 1584 | 1291 |
| 1585 # For official builders. | 1292 # For official builders. |
| 1586 buildspec=buildspec, | 1293 buildspec=buildspec, |
| 1587 gyp_env=options.gyp_env, | 1294 gyp_env=options.gyp_env, |
| 1588 runhooks=not options.no_runhooks, | 1295 runhooks=not options.no_runhooks, |
| 1589 | 1296 |
| 1590 # Finally, extra configurations such as shallowness of the clone. | 1297 # Finally, extra configurations such as shallowness of the clone. |
| 1591 shallow=options.shallow, | 1298 shallow=options.shallow, |
| 1592 refs=options.refs, | 1299 refs=options.refs, |
| 1593 git_cache_dir=options.git_cache_dir, | 1300 git_cache_dir=options.git_cache_dir, |
| 1594 gerrit_reset=not options.gerrit_no_reset) | 1301 gerrit_reset=not options.gerrit_no_reset) |
| 1595 gclient_output = ensure_checkout(**checkout_parameters) | 1302 gclient_output = ensure_checkout(**checkout_parameters) |
| 1596 except GclientSyncFailed: | 1303 except GclientSyncFailed: |
| 1597 print 'We failed gclient sync, lets delete the checkout and retry.' | 1304 print 'We failed gclient sync, lets delete the checkout and retry.' |
| 1598 ensure_no_checkout(dir_names, '*') | 1305 ensure_no_checkout(dir_names) |
| 1599 gclient_output = ensure_checkout(**checkout_parameters) | 1306 gclient_output = ensure_checkout(**checkout_parameters) |
| 1600 except PatchFailed as e: | 1307 except PatchFailed as e: |
| 1601 if options.output_json: | 1308 if options.output_json: |
| 1602 # Tell recipes information such as root, got_revision, etc. | 1309 # Tell recipes information such as root, got_revision, etc. |
| 1603 emit_json(options.output_json, | 1310 emit_json(options.output_json, |
| 1604 did_run=True, | 1311 did_run=True, |
| 1605 root=first_sln, | 1312 root=first_sln, |
| 1606 log_lines=[('patch error', e.output),], | 1313 log_lines=[('patch error', e.output),], |
| 1607 patch_apply_return_code=e.code, | 1314 patch_apply_return_code=e.code, |
| 1608 patch_root=options.patch_root, | 1315 patch_root=options.patch_root, |
| 1609 patch_failure=True, | 1316 patch_failure=True, |
| 1610 step_text='%s PATCH FAILED' % step_text, | 1317 step_text='%s PATCH FAILED' % step_text, |
| 1611 fixed_revisions=revisions) | 1318 fixed_revisions=revisions) |
| 1612 else: | 1319 else: |
| 1613 # If we're not on recipes, tell annotator about our got_revisions. | 1320 # If we're not on recipes, tell annotator about our got_revisions. |
| 1614 emit_log_lines('patch error', e.output) | 1321 emit_log_lines('patch error', e.output) |
| 1615 print '@@@STEP_TEXT@%s PATCH FAILED@@@' % step_text | 1322 print '@@@STEP_TEXT@%s PATCH FAILED@@@' % step_text |
| 1616 raise | 1323 raise |
| 1617 | 1324 |
| 1618 # Revision is an svn revision, unless it's a git master. | |
| 1619 use_svn_rev = master not in GIT_MASTERS | |
| 1620 | |
| 1621 # Take care of got_revisions outputs. | 1325 # Take care of got_revisions outputs. |
| 1622 revision_mapping = dict(GOT_REVISION_MAPPINGS.get(svn_root, {})) | 1326 revision_mapping = GOT_REVISION_MAPPINGS.get(git_slns[0]['url'], {}) |
| 1623 if options.revision_mapping: | 1327 if options.revision_mapping: |
| 1624 revision_mapping.update(options.revision_mapping) | 1328 revision_mapping.update(options.revision_mapping) |
| 1625 | 1329 |
| 1626 # If the repo is not in the default GOT_REVISION_MAPPINGS and no | 1330 # If the repo is not in the default GOT_REVISION_MAPPINGS and no |
| 1627 # revision_mapping were specified on the command line then | 1331 # revision_mapping were specified on the command line then |
| 1628 # default to setting 'got_revision' based on the first solution. | 1332 # default to setting 'got_revision' based on the first solution. |
| 1629 if not revision_mapping: | 1333 if not revision_mapping: |
| 1630 revision_mapping[first_sln] = 'got_revision' | 1334 revision_mapping[first_sln] = 'got_revision' |
| 1631 | 1335 |
| 1632 got_revisions = parse_got_revision(gclient_output, revision_mapping, | 1336 got_revisions = parse_got_revision(gclient_output, revision_mapping) |
| 1633 use_svn_rev) | |
| 1634 | 1337 |
| 1635 if not got_revisions: | 1338 if not got_revisions: |
| 1636 # TODO(hinoka): We should probably bail out here, but in the interest | 1339 # TODO(hinoka): We should probably bail out here, but in the interest |
| 1637 # of giving mis-configured bots some time to get fixed use a dummy | 1340 # of giving mis-configured bots some time to get fixed use a dummy |
| 1638 # revision here. | 1341 # revision here. |
| 1639 got_revisions = { 'got_revision': 'BOT_UPDATE_NO_REV_FOUND' } | 1342 got_revisions = { 'got_revision': 'BOT_UPDATE_NO_REV_FOUND' } |
| 1640 #raise Exception('No got_revision(s) found in gclient output') | 1343 #raise Exception('No got_revision(s) found in gclient output') |
| 1641 | 1344 |
| 1642 if options.output_json: | 1345 if options.output_json: |
| 1643 manifest = create_manifest() if options.output_manifest else None | 1346 manifest = create_manifest() if options.output_manifest else None |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1698 # Check if this script should activate or not. | 1401 # Check if this script should activate or not. |
| 1699 active = options.force or check_valid_host(master, builder, slave) | 1402 active = options.force or check_valid_host(master, builder, slave) |
| 1700 | 1403 |
| 1701 # Print a helpful message to tell developers whats going on with this step. | 1404 # Print a helpful message to tell developers whats going on with this step. |
| 1702 print_help_text( | 1405 print_help_text( |
| 1703 options.force, options.output_json, active, master, builder, slave) | 1406 options.force, options.output_json, active, master, builder, slave) |
| 1704 | 1407 |
| 1705 # Parse, munipulate, and print the gclient solutions. | 1408 # Parse, munipulate, and print the gclient solutions. |
| 1706 specs = {} | 1409 specs = {} |
| 1707 exec(options.specs, specs) | 1410 exec(options.specs, specs) |
| 1708 svn_solutions = specs.get('solutions', []) | 1411 orig_solutions = specs.get('solutions', []) |
| 1709 git_slns, svn_root, buildspec = solutions_to_git(svn_solutions) | 1412 git_slns, buildspec = modify_solutions(orig_solutions) |
| 1710 options.revision = maybe_ignore_revision(options.revision, buildspec) | 1413 options.revision = maybe_ignore_revision(options.revision, buildspec) |
| 1711 | 1414 |
| 1712 solutions_printer(git_slns) | 1415 solutions_printer(git_slns) |
| 1713 | 1416 |
| 1714 try: | 1417 try: |
| 1715 # Dun dun dun, the main part of bot_update. | 1418 # Dun dun dun, the main part of bot_update. |
| 1716 revisions, step_text = prepare(options, git_slns, active) | 1419 revisions, step_text = prepare(options, git_slns, active) |
| 1717 checkout(options, git_slns, specs, buildspec, master, svn_root, revisions, | 1420 checkout(options, git_slns, specs, buildspec, master, revisions, step_text) |
| 1718 step_text) | |
| 1719 | 1421 |
| 1720 except Inactive: | 1422 except Inactive: |
|
hinoka
2016/08/26 21:59:54
I don't think "Inactive" is referenced anymore aft
agable
2016/08/29 19:09:58
Right, deleted.
| |
| 1721 # Not active, should count as passing. | 1423 # Not active, should count as passing. |
| 1722 pass | 1424 pass |
| 1723 except PatchFailed as e: | 1425 except PatchFailed as e: |
| 1724 emit_flag(options.flag_file) | 1426 emit_flag(options.flag_file) |
| 1725 # Return a specific non-zero exit code for patch failure (because it is | 1427 # Return a specific non-zero exit code for patch failure (because it is |
| 1726 # a failure), but make it different than other failures to distinguish | 1428 # a failure), but make it different than other failures to distinguish |
| 1727 # between infra failures (independent from patch author), and patch | 1429 # between infra failures (independent from patch author), and patch |
| 1728 # failures (that patch author can fix). However, PatchFailure due to | 1430 # failures (that patch author can fix). However, PatchFailure due to |
| 1729 # download patch failure is still an infra problem. | 1431 # download patch failure is still an infra problem. |
| 1730 if e.code == 3: | 1432 if e.code == 3: |
| 1731 # Patch download problem. | 1433 # Patch download problem. |
| 1732 return 87 | 1434 return 87 |
| 1733 # Genuine patch problem. | 1435 # Genuine patch problem. |
| 1734 return 88 | 1436 return 88 |
| 1735 except Exception: | 1437 except Exception: |
| 1736 # Unexpected failure. | 1438 # Unexpected failure. |
| 1737 emit_flag(options.flag_file) | 1439 emit_flag(options.flag_file) |
| 1738 raise | 1440 raise |
| 1739 else: | 1441 else: |
| 1740 emit_flag(options.flag_file) | 1442 emit_flag(options.flag_file) |
| 1741 | 1443 |
| 1742 | 1444 |
| 1743 if __name__ == '__main__': | 1445 if __name__ == '__main__': |
| 1744 sys.exit(main()) | 1446 sys.exit(main()) |
| OLD | NEW |