| 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 | |
| 11 import copy | 10 import copy |
| 12 import ctypes | 11 import ctypes |
| 13 import json | 12 import json |
| 14 import optparse | 13 import optparse |
| 15 import os | 14 import os |
| 16 import pprint | 15 import pprint |
| 17 import random | 16 import random |
| 18 import re | 17 import re |
| 19 import socket | |
| 20 import subprocess | 18 import subprocess |
| 21 import sys | 19 import sys |
| 22 import tempfile | 20 import tempfile |
| 23 import threading | 21 import threading |
| 24 import time | 22 import time |
| 25 import urllib2 | 23 import urllib2 |
| 26 import urlparse | 24 import urlparse |
| 27 import uuid | 25 import uuid |
| 28 | 26 |
| 29 import os.path as path | 27 import os.path as path |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 del solution['safesync_url'] | 290 del solution['safesync_url'] |
| 293 | 291 |
| 294 return solutions | 292 return solutions |
| 295 | 293 |
| 296 | 294 |
| 297 def remove(target): | 295 def remove(target): |
| 298 """Remove a target by moving it into build.dead.""" | 296 """Remove a target by moving it into build.dead.""" |
| 299 dead_folder = path.join(BUILDER_DIR, 'build.dead') | 297 dead_folder = path.join(BUILDER_DIR, 'build.dead') |
| 300 if not path.exists(dead_folder): | 298 if not path.exists(dead_folder): |
| 301 os.makedirs(dead_folder) | 299 os.makedirs(dead_folder) |
| 302 os.rename(target, path.join(dead_folder, uuid.uuid4().hex)) | 300 dest = path.join(dead_folder, uuid.uuid4().hex) |
| 301 print 'Marking for removal %s => %s' % (target, dest) |
| 302 os.rename(target, dest) |
| 303 | 303 |
| 304 | 304 |
| 305 def ensure_no_checkout(dir_names): | 305 def ensure_no_checkout(dir_names): |
| 306 """Ensure that there is no undesired checkout under build/.""" | 306 """Ensure that there is no undesired checkout under build/.""" |
| 307 build_dir = os.getcwd() | 307 build_dir = os.getcwd() |
| 308 has_checkout = any(path.exists(path.join(build_dir, dir_name, '.git')) | 308 has_checkout = any(path.exists(path.join(build_dir, dir_name, '.git')) |
| 309 for dir_name in dir_names) | 309 for dir_name in dir_names) |
| 310 if has_checkout: | 310 if has_checkout: |
| 311 for filename in os.listdir(build_dir): | 311 for filename in os.listdir(build_dir): |
| 312 deletion_target = path.join(build_dir, filename) | 312 deletion_target = path.join(build_dir, filename) |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 # Support for "branch:revision" syntax. | 451 # Support for "branch:revision" syntax. |
| 452 branch, revision = split_revision | 452 branch, revision = split_revision |
| 453 | 453 |
| 454 if revision and revision.upper() != 'HEAD': | 454 if revision and revision.upper() != 'HEAD': |
| 455 git('checkout', '--force', revision, cwd=folder_name) | 455 git('checkout', '--force', revision, cwd=folder_name) |
| 456 else: | 456 else: |
| 457 ref = branch if branch.startswith('refs/') else 'origin/%s' % branch | 457 ref = branch if branch.startswith('refs/') else 'origin/%s' % branch |
| 458 git('checkout', '--force', ref, cwd=folder_name) | 458 git('checkout', '--force', ref, cwd=folder_name) |
| 459 | 459 |
| 460 | 460 |
| 461 def is_broken_repo_dir(repo_dir): |
| 462 # Treat absence of 'config' as a signal of a partially deleted repo. |
| 463 return not path.exists(os.path.join(repo_dir, '.git', 'config')) |
| 464 |
| 465 |
| 461 def git_checkout(solutions, revisions, shallow, refs, git_cache_dir): | 466 def git_checkout(solutions, revisions, shallow, refs, git_cache_dir): |
| 462 build_dir = os.getcwd() | 467 build_dir = os.getcwd() |
| 463 # Before we do anything, break all git_cache locks. | 468 # Before we do anything, break all git_cache locks. |
| 464 if path.isdir(git_cache_dir): | 469 if path.isdir(git_cache_dir): |
| 465 git('cache', 'unlock', '-vv', '--force', '--all', | 470 git('cache', 'unlock', '-vv', '--force', '--all', |
| 466 '--cache-dir', git_cache_dir) | 471 '--cache-dir', git_cache_dir) |
| 467 for item in os.listdir(git_cache_dir): | 472 for item in os.listdir(git_cache_dir): |
| 468 filename = os.path.join(git_cache_dir, item) | 473 filename = os.path.join(git_cache_dir, item) |
| 469 if item.endswith('.lock'): | 474 if item.endswith('.lock'): |
| 470 raise Exception('%s exists after cache unlock' % filename) | 475 raise Exception('%s exists after cache unlock' % filename) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 489 for ref in refs: | 494 for ref in refs: |
| 490 populate_cmd.extend(['--ref', ref]) | 495 populate_cmd.extend(['--ref', ref]) |
| 491 git(*populate_cmd) | 496 git(*populate_cmd) |
| 492 mirror_dir = git( | 497 mirror_dir = git( |
| 493 'cache', 'exists', '--quiet', | 498 'cache', 'exists', '--quiet', |
| 494 '--cache-dir', git_cache_dir, url).strip() | 499 '--cache-dir', git_cache_dir, url).strip() |
| 495 clone_cmd = ( | 500 clone_cmd = ( |
| 496 'clone', '--no-checkout', '--local', '--shared', mirror_dir, sln_dir) | 501 'clone', '--no-checkout', '--local', '--shared', mirror_dir, sln_dir) |
| 497 | 502 |
| 498 try: | 503 try: |
| 504 # If repo deletion was aborted midway, it may have left .git in broken |
| 505 # state. |
| 506 if path.exists(sln_dir) and is_broken_repo_dir(sln_dir): |
| 507 print 'Git repo %s appears to be broken, removing it' % sln_dir |
| 508 remove(sln_dir) |
| 509 |
| 499 if not path.isdir(sln_dir): | 510 if not path.isdir(sln_dir): |
| 500 git(*clone_cmd) | 511 git(*clone_cmd) |
| 501 else: | 512 else: |
| 502 git('remote', 'set-url', 'origin', mirror_dir, cwd=sln_dir) | 513 git('remote', 'set-url', 'origin', mirror_dir, cwd=sln_dir) |
| 503 git('fetch', 'origin', cwd=sln_dir) | 514 git('fetch', 'origin', cwd=sln_dir) |
| 504 for ref in refs: | 515 for ref in refs: |
| 505 refspec = '%s:%s' % (ref, ref.lstrip('+')) | 516 refspec = '%s:%s' % (ref, ref.lstrip('+')) |
| 506 git('fetch', 'origin', refspec, cwd=sln_dir) | 517 git('fetch', 'origin', refspec, cwd=sln_dir) |
| 507 | 518 |
| 508 revision = get_target_revision(name, url, revisions) or 'HEAD' | 519 revision = get_target_revision(name, url, revisions) or 'HEAD' |
| (...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1037 def main(): | 1048 def main(): |
| 1038 # Get inputs. | 1049 # Get inputs. |
| 1039 options, _ = parse_args() | 1050 options, _ = parse_args() |
| 1040 | 1051 |
| 1041 # Check if this script should activate or not. | 1052 # Check if this script should activate or not. |
| 1042 active = True | 1053 active = True |
| 1043 | 1054 |
| 1044 # Print a helpful message to tell developers whats going on with this step. | 1055 # Print a helpful message to tell developers whats going on with this step. |
| 1045 print_debug_info() | 1056 print_debug_info() |
| 1046 | 1057 |
| 1047 # Parse, munipulate, and print the gclient solutions. | 1058 # Parse, manipulate, and print the gclient solutions. |
| 1048 specs = {} | 1059 specs = {} |
| 1049 exec(options.specs, specs) | 1060 exec(options.specs, specs) |
| 1050 orig_solutions = specs.get('solutions', []) | 1061 orig_solutions = specs.get('solutions', []) |
| 1051 git_slns = modify_solutions(orig_solutions) | 1062 git_slns = modify_solutions(orig_solutions) |
| 1052 | 1063 |
| 1053 solutions_printer(git_slns) | 1064 solutions_printer(git_slns) |
| 1054 | 1065 |
| 1055 try: | 1066 try: |
| 1056 # Dun dun dun, the main part of bot_update. | 1067 # Dun dun dun, the main part of bot_update. |
| 1057 revisions, step_text, shallow = prepare(options, git_slns, active) | 1068 revisions, step_text, shallow = prepare(options, git_slns, active) |
| 1058 checkout(options, git_slns, specs, revisions, step_text, shallow) | 1069 checkout(options, git_slns, specs, revisions, step_text, shallow) |
| 1059 | 1070 |
| 1060 except PatchFailed as e: | 1071 except PatchFailed as e: |
| 1061 # Return a specific non-zero exit code for patch failure (because it is | 1072 # Return a specific non-zero exit code for patch failure (because it is |
| 1062 # a failure), but make it different than other failures to distinguish | 1073 # a failure), but make it different than other failures to distinguish |
| 1063 # between infra failures (independent from patch author), and patch | 1074 # between infra failures (independent from patch author), and patch |
| 1064 # failures (that patch author can fix). However, PatchFailure due to | 1075 # failures (that patch author can fix). However, PatchFailure due to |
| 1065 # download patch failure is still an infra problem. | 1076 # download patch failure is still an infra problem. |
| 1066 if e.code == 3: | 1077 if e.code == 3: |
| 1067 # Patch download problem. | 1078 # Patch download problem. |
| 1068 return 87 | 1079 return 87 |
| 1069 # Genuine patch problem. | 1080 # Genuine patch problem. |
| 1070 return 88 | 1081 return 88 |
| 1071 | 1082 |
| 1072 | 1083 |
| 1073 if __name__ == '__main__': | 1084 if __name__ == '__main__': |
| 1074 sys.exit(main()) | 1085 sys.exit(main()) |
| OLD | NEW |