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 import codecs | 6 import codecs |
| 7 import copy | 7 import copy |
| 8 import cStringIO | 8 import cStringIO |
| 9 import ctypes | 9 import ctypes |
| 10 import json | 10 import json |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 457 finally: | 457 finally: |
| 458 os.remove(gclient_output_file) | 458 os.remove(gclient_output_file) |
| 459 | 459 |
| 460 | 460 |
| 461 def gclient_runhooks(gyp_envs): | 461 def gclient_runhooks(gyp_envs): |
| 462 gclient_bin = 'gclient.bat' if sys.platform.startswith('win') else 'gclient' | 462 gclient_bin = 'gclient.bat' if sys.platform.startswith('win') else 'gclient' |
| 463 env = dict([env_var.split('=', 1) for env_var in gyp_envs]) | 463 env = dict([env_var.split('=', 1) for env_var in gyp_envs]) |
| 464 call(gclient_bin, 'runhooks', env=env) | 464 call(gclient_bin, 'runhooks', env=env) |
| 465 | 465 |
| 466 | 466 |
| 467 def create_less_than_or_equal_regex(number): | |
| 468 """ Return a regular expression to test whether an integer less than or equal | |
| 469 to 'number' is present in a given string. | |
| 470 """ | |
| 471 | |
| 472 # In three parts, build a regular expression that match any numbers smaller | |
| 473 # than 'number'. | |
| 474 # For example, 78656 would give a regular expression that looks like: | |
| 475 # Part 1 | |
| 476 # (78356| # 78356 | |
| 477 # Part 2 | |
| 478 # 7835[0-5]| # 78350-78355 | |
| 479 # 783[0-4][0-9]| # 78300-78349 | |
| 480 # 78[0-2][0-9]{2}| # 78000-78299 | |
| 481 # 7[0-7][0-9]{3}| # 70000-77999 | |
| 482 # [0-6][0-9]{4}| # 10000-69999 | |
| 483 # Part 3 | |
| 484 # [0-9]{1,4} # 0-9999 | |
| 485 | |
| 486 # Part 1: Create an array with all the regexes, as described above. | |
| 487 # Prepopulate it with the number itself. | |
| 488 number = str(number) | |
| 489 expressions = [number] | |
| 490 | |
| 491 # Convert the number to a list, so we can translate digits in it to | |
| 492 # expressions. | |
| 493 num_list = list(number) | |
| 494 num_len = len(num_list) | |
| 495 | |
| 496 # Part 2: Go through all the digits in the number, starting from the end. | |
| 497 # Each iteration appends a line to 'expressions'. | |
| 498 for index in range (num_len - 1, -1, -1): | |
| 499 # Convert this digit back to an integer. | |
| 500 digit = int(num_list[index]) | |
| 501 | |
| 502 # Part 2.1: No processing if this digit is a zero. | |
| 503 if digit == 0: | |
| 504 continue | |
| 505 | |
| 506 # Part 2.2: We switch the current digit X by a range "[0-(X-1)]". | |
| 507 if digit == 1: | |
| 508 num_list[index] = '0' | |
| 509 else: | |
| 510 num_list[index] = '[0-%d]' % (digit - 1) | |
| 511 | |
| 512 # Part 2.3: We set all following digits to be "[0-9]". | |
| 513 # Since we just decrementented a digit in a most important position, all | |
| 514 # following digits don't matter. The possible numbers will always be smaller | |
| 515 # than before we decremented. | |
| 516 if (index + 1) < num_len: | |
| 517 if (num_len - (index + 1)) == 1: | |
| 518 num_list[index + 1] = '[0-9]' | |
| 519 else: | |
| 520 num_list[index + 1] = '[0-9]{%s}' % (num_len - (index + 1)) | |
| 521 | |
| 522 # Part 2.4: Add this new sub-expression to the list. | |
| 523 expressions.append(''.join(num_list[:min(index+2, num_len)])) | |
| 524 | |
| 525 # Part 3: We add all the full ranges to match all numbers that are at least | |
| 526 # one order of magnitude smaller than the original numbers. | |
| 527 if num_len == 2: | |
| 528 expressions.append('[0-9]') | |
| 529 elif num_len > 2: | |
| 530 expressions.append('[0-9]{1,%s}' % (num_len - 1)) | |
| 531 | |
| 532 # All done. We now have our final regular expression. | |
| 533 regex = '(%s)' % ('|'.join(expressions)) | |
| 534 return regex | |
| 535 | |
| 536 | |
| 537 def get_svn_rev(git_hash, dir_name): | 467 def get_svn_rev(git_hash, dir_name): |
| 538 pattern = r'^\s*git-svn-id: [^ ]*@(\d+) ' | 468 pattern = r'^\s*git-svn-id: [^ ]*@(\d+) ' |
| 539 lkcr_pattern = r'^\s*LK[CG]R w/ DEPS up to revision (\d+)' | |
| 540 log = git('log', '-1', git_hash, cwd=dir_name) | 469 log = git('log', '-1', git_hash, cwd=dir_name) |
| 541 match = re.search(pattern, log, re.M) | 470 match = re.search(pattern, log, re.M) |
| 542 if not match: | 471 if not match: |
| 543 # This might be a patched checkout, try the parent commit. | 472 return None |
| 544 log = git('log', '-1', '%s^' % git_hash, cwd=dir_name) | |
| 545 match = re.search(pattern, log, re.M) | |
| 546 if not match: | |
| 547 # Might be patched on top of LKCR, which has a special message. | |
| 548 match = re.search(lkcr_pattern, log, re.M) | |
| 549 if not match: | |
| 550 return None | |
| 551 return int(match.group(1)) | 473 return int(match.group(1)) |
| 552 | 474 |
| 553 | 475 |
| 554 def get_git_hash(revision, dir_name): | 476 def get_git_hash(revision, sln_dir): |
| 555 match = "^git-svn-id: [^ ]*@%s " % create_less_than_or_equal_regex(revision) | 477 """We want to search for the SVN revision on the git-svn branch. |
| 478 | |
| 479 Note that for this to work, the git checkout in sln_dir must be newer and in | |
| 480 the same lineage as the commit we are searching for. This is because Git | |
| 481 searches backwards from the current commit. | |
|
iannucci
2014/05/08 23:50:06
s/current commit/HEAD
though you could specify th
hinoka
2014/05/10 00:54:08
Redid this to always start from origin/master
| |
| 482 """ | |
| 483 match = "^git-svn-id: [^ ]*@%s " % revision | |
| 556 cmd = ['log', '-E', '--grep', match, '--format=%H', '--max-count=1'] | 484 cmd = ['log', '-E', '--grep', match, '--format=%H', '--max-count=1'] |
| 557 results = git(*cmd, cwd=dir_name).strip().splitlines() | 485 result = git(*cmd, cwd=sln_dir).strip() |
| 558 if results: | 486 if result: |
| 559 return results[0] | 487 return result |
| 560 raise Exception('We can\'t resolve svn revision %s into a git hash' % | 488 raise SVNRevisionNotFound('We can\'t resolve svn r%s into a git hash in %s' % |
| 561 revision) | 489 (revision, sln_dir)) |
| 562 | 490 |
| 563 | 491 |
| 564 def get_revision_mapping(root, addl_rev_map): | 492 def get_revision_mapping(root, addl_rev_map): |
| 565 result = {} | 493 result = {} |
| 566 if root in GOT_REVISION_MAPPINGS: | 494 if root in GOT_REVISION_MAPPINGS: |
| 567 result.update(GOT_REVISION_MAPPINGS[root]) | 495 result.update(GOT_REVISION_MAPPINGS[root]) |
| 568 if addl_rev_map: | 496 if addl_rev_map: |
| 569 result.update(json.loads(addl_rev_map)) | 497 result.update(json.loads(addl_rev_map)) |
| 570 return result | 498 return result |
| 571 | 499 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 701 raise ctypes.WinError() | 629 raise ctypes.WinError() |
| 702 return (total.value, free.value) | 630 return (total.value, free.value) |
| 703 | 631 |
| 704 else: | 632 else: |
| 705 st = os.statvfs(cwd) | 633 st = os.statvfs(cwd) |
| 706 free = st.f_bavail * st.f_frsize | 634 free = st.f_bavail * st.f_frsize |
| 707 total = st.f_blocks * st.f_frsize | 635 total = st.f_blocks * st.f_frsize |
| 708 return (total, free) | 636 return (total, free) |
| 709 | 637 |
| 710 | 638 |
| 711 def git_checkout(solutions, revision, shallow): | 639 def get_revision(folder_name, git_url, revisions): |
| 640 normalized_name = folder_name.strip('/') | |
| 641 if normalized_name in revisions: | |
| 642 return revisions[normalized_name] | |
| 643 if git_url in revisions: | |
| 644 return revisions[git_url] | |
| 645 return None | |
| 646 | |
| 647 | |
| 648 def force_revision(folder_name, revision): | |
| 649 # We do this first because git log --grep only traverses backwards. | |
| 650 # TODO(hinoka): Prefer origin/git-svn if it exists. | |
|
iannucci
2014/05/08 23:50:06
You should just pass origin/master to `git log` in
hinoka
2014/05/10 00:54:08
Done.
| |
| 651 git('checkout', 'origin/master', cwd=folder_name) | |
| 652 if revision and revision.lower() != 'head': | |
| 653 if revision and revision.isdigit() and len(revision) < 40: | |
| 654 # rev_num is really a svn revision number, convert it into a git hash. | |
| 655 git_ref = get_git_hash(int(revision), folder_name) | |
| 656 else: | |
| 657 # rev_num is actually a git hash or ref, we can just use it. | |
| 658 git_ref = revision | |
| 659 git('checkout', git_ref, cwd=folder_name) | |
| 660 | |
| 661 | |
| 662 def git_checkout(solutions, revisions, shallow): | |
| 712 build_dir = os.getcwd() | 663 build_dir = os.getcwd() |
| 713 # Before we do anything, break all git_cache locks. | 664 # Before we do anything, break all git_cache locks. |
| 714 if path.isdir(CACHE_DIR): | 665 if path.isdir(CACHE_DIR): |
| 715 git('cache', 'unlock', '-vv', '--force', '--all', '--cache-dir', CACHE_DIR) | 666 git('cache', 'unlock', '-vv', '--force', '--all', '--cache-dir', CACHE_DIR) |
| 716 for item in os.listdir(CACHE_DIR): | 667 for item in os.listdir(CACHE_DIR): |
| 717 filename = os.path.join(CACHE_DIR, item) | 668 filename = os.path.join(CACHE_DIR, item) |
| 718 if item.endswith('.lock'): | 669 if item.endswith('.lock'): |
| 719 raise Exception('%s exists after cache unlock' % filename) | 670 raise Exception('%s exists after cache unlock' % filename) |
| 720 # Revision only applies to the first solution. | |
| 721 first_solution = True | 671 first_solution = True |
| 722 for sln in solutions: | 672 for sln in solutions: |
| 723 # This is so we can loop back and try again if we need to wait for the | 673 # This is so we can loop back and try again if we need to wait for the |
| 724 # git mirrors to update from SVN. | 674 # git mirrors to update from SVN. |
| 725 done = False | 675 done = False |
| 726 tries_left = 60 | 676 tries_left = 60 |
| 727 while not done: | 677 while not done: |
| 728 done = True | 678 done = True |
| 729 name = sln['name'] | 679 name = sln['name'] |
| 730 url = sln['url'] | 680 url = sln['url'] |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 752 # Lets wipe the checkout and try again. | 702 # Lets wipe the checkout and try again. |
| 753 chromium_utils.RemoveDirectory(sln_dir) | 703 chromium_utils.RemoveDirectory(sln_dir) |
| 754 git(*clone_cmd) | 704 git(*clone_cmd) |
| 755 git('checkout', '--force', 'origin/master', cwd=sln_dir) | 705 git('checkout', '--force', 'origin/master', cwd=sln_dir) |
| 756 git('reset', '--hard', cwd=sln_dir) | 706 git('reset', '--hard', cwd=sln_dir) |
| 757 else: | 707 else: |
| 758 raise | 708 raise |
| 759 | 709 |
| 760 git('clean', '-df', cwd=sln_dir) | 710 git('clean', '-df', cwd=sln_dir) |
| 761 git('fetch', 'origin', cwd=sln_dir) | 711 git('fetch', 'origin', cwd=sln_dir) |
| 762 # TODO(hinoka): We probably have to make use of revision mapping. | |
| 763 if first_solution and revision and revision.lower() != 'head': | |
| 764 if revision and revision.isdigit() and len(revision) < 40: | |
| 765 # rev_num is really a svn revision number, convert it into a git hash. | |
| 766 git_ref = get_git_hash(int(revision), name) | |
| 767 # Lets make sure our checkout has the correct revision number. | |
| 768 got_revision = get_svn_rev(git_ref, sln_dir) | |
| 769 if not got_revision or int(got_revision) != int(revision): | |
| 770 tries_left -= 1 | |
| 771 if tries_left > 0: | |
| 772 # If we don't have the correct revision, wait and try again. | |
| 773 print 'We want revision %s, but got revision %s.' % ( | |
| 774 revision, got_revision) | |
| 775 print 'The svn to git replicator is probably falling behind.' | |
| 776 print 'waiting 5 seconds and trying again...' | |
| 777 time.sleep(5) | |
| 778 done = False | |
| 779 continue | |
| 780 raise SVNRevisionNotFound | |
| 781 else: | |
| 782 # rev_num is actually a git hash or ref, we can just use it. | |
| 783 git_ref = revision | |
| 784 git('checkout', git_ref, cwd=sln_dir) | |
| 785 else: | |
| 786 git('checkout', 'origin/master', cwd=sln_dir) | |
| 787 if first_solution: | |
| 788 git_ref = git('log', '--format=%H', '--max-count=1', | |
| 789 cwd=sln_dir).strip() | |
| 790 | 712 |
| 713 revision = get_revision(name, url, revisions) or 'HEAD' | |
| 714 try: | |
| 715 force_revision(sln_dir, revision) | |
| 716 except SVNRevisionNotFound: | |
| 717 tries_left -= 1 | |
| 718 if tries_left > 0: | |
| 719 # If we don't have the correct revision, wait and try again. | |
| 720 print 'We can\'t find revision %s.' % revision | |
| 721 print 'The svn to git replicator is probably falling behind.' | |
| 722 print 'waiting 5 seconds and trying again...' | |
| 723 time.sleep(5) | |
|
iannucci
2014/05/08 23:50:06
ick :/
hinoka
2014/05/10 00:54:08
As long as we are mirroring, we need a sleep somew
| |
| 724 done = False | |
| 725 continue | |
| 726 raise | |
| 727 | |
| 728 if first_solution: | |
| 729 git_ref = git('log', '--format=%H', '--max-count=1', | |
| 730 cwd=sln_dir).strip() | |
| 791 first_solution = False | 731 first_solution = False |
| 792 return git_ref | 732 return git_ref |
| 793 | 733 |
| 794 | 734 |
| 795 def _download(url): | 735 def _download(url): |
| 796 """Fetch url and return content, with retries for flake.""" | 736 """Fetch url and return content, with retries for flake.""" |
| 797 for attempt in xrange(RETRIES): | 737 for attempt in xrange(RETRIES): |
| 798 try: | 738 try: |
| 799 return urllib2.urlopen(url).read() | 739 return urllib2.urlopen(url).read() |
| 800 except Exception: | 740 except Exception: |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 859 for dir_name, property_name in got_revision_mapping.iteritems(): | 799 for dir_name, property_name in got_revision_mapping.iteritems(): |
| 860 if dir_name not in solutions_output: | 800 if dir_name not in solutions_output: |
| 861 continue | 801 continue |
| 862 solution_output = solutions_output[dir_name] | 802 solution_output = solutions_output[dir_name] |
| 863 if solution_output.get('scm') is None: | 803 if solution_output.get('scm') is None: |
| 864 # This is an ignored DEPS, so the output got_revision should be 'None'. | 804 # This is an ignored DEPS, so the output got_revision should be 'None'. |
| 865 git_revision = revision = None | 805 git_revision = revision = None |
| 866 else: | 806 else: |
| 867 # Since we are using .DEPS.git, everything had better be git. | 807 # Since we are using .DEPS.git, everything had better be git. |
| 868 assert solution_output.get('scm') == 'git' | 808 assert solution_output.get('scm') == 'git' |
| 869 git_revision = get_real_git_hash(solution_output['revision'], dir_name) | 809 git_revision = git('log', '-1', '--format=%H', cwd=dir_name).strip() |
|
iannucci
2014/05/08 23:50:06
er... `git rev-parse HEAD` ?
hinoka
2014/05/10 00:54:08
Done.
| |
| 870 if use_svn_revs: | 810 if use_svn_revs: |
| 871 revision = get_svn_rev(git_revision, dir_name) | 811 revision = get_svn_rev(git_revision, dir_name) |
| 872 if not revision: | 812 if not revision: |
| 873 revision = git_revision | 813 revision = git_revision |
| 874 else: | 814 else: |
| 875 revision = git_revision | 815 revision = git_revision |
| 876 | 816 |
| 877 properties[property_name] = revision | 817 properties[property_name] = revision |
| 878 if revision != git_revision: | 818 if revision != git_revision: |
| 879 properties['%s_git' % property_name] = git_revision | 819 properties['%s_git' % property_name] = git_revision |
| 880 | 820 |
| 881 return properties | 821 return properties |
| 882 | 822 |
| 883 | 823 |
| 884 def emit_json(out_file, did_run, gclient_output=None, **kwargs): | 824 def emit_json(out_file, did_run, gclient_output=None, **kwargs): |
| 885 """Write run information into a JSON file.""" | 825 """Write run information into a JSON file.""" |
| 886 output = {} | 826 output = {} |
| 887 output.update(gclient_output if gclient_output else {}) | 827 output.update(gclient_output if gclient_output else {}) |
| 888 output.update({'did_run': did_run}) | 828 output.update({'did_run': did_run}) |
| 889 output.update(kwargs) | 829 output.update(kwargs) |
| 890 with open(out_file, 'wb') as f: | 830 with open(out_file, 'wb') as f: |
| 891 f.write(json.dumps(output)) | 831 f.write(json.dumps(output)) |
| 892 | 832 |
| 893 | 833 |
| 894 def ensure_checkout(solutions, revision, first_sln, target_os, target_os_only, | 834 def ensure_deps_revisions(deps_url_mapping, solutions, revisions): |
| 835 """Ensure correct DEPS revisions, ignores solutions.""" | |
| 836 for deps_name, deps_data in sorted(deps_url_mapping.items()): | |
| 837 if deps_name.strip('/') in solutions: | |
| 838 # This has already been forced to the correct solution by git_checkout(). | |
| 839 continue | |
| 840 revision = get_revision(deps_name, deps_data.get('url', None), revisions) | |
| 841 if not revision: | |
| 842 continue | |
| 843 # TODO(hinoka): Catch SVNRevisionNotFound error maybe? | |
| 844 force_revision(deps_name, revision) | |
| 845 | |
| 846 | |
| 847 def ensure_checkout(solutions, revisions, first_sln, target_os, target_os_only, | |
| 895 root, issue, patchset, patch_url, rietveld_server, | 848 root, issue, patchset, patch_url, rietveld_server, |
| 896 revision_mapping, buildspec_name, gyp_env, shallow): | 849 revision_mapping, buildspec_name, gyp_env, shallow): |
| 897 # Get a checkout of each solution, without DEPS or hooks. | 850 # Get a checkout of each solution, without DEPS or hooks. |
| 898 # Calling git directly because there is no way to run Gclient without | 851 # Calling git directly because there is no way to run Gclient without |
| 899 # invoking DEPS. | 852 # invoking DEPS. |
| 900 print 'Fetching Git checkout' | 853 print 'Fetching Git checkout' |
| 901 git_ref = git_checkout(solutions, revision, shallow) | 854 git_ref = git_checkout(solutions, revisions, shallow) |
| 902 | 855 |
| 903 # If either patch_url or issue is passed in, then we need to apply a patch. | 856 # If either patch_url or issue is passed in, then we need to apply a patch. |
| 904 if patch_url: | 857 if patch_url: |
| 905 # patch_url takes precidence since its only passed in on gcl try/git try. | 858 # patch_url takes precidence since its only passed in on gcl try/git try. |
| 906 apply_issue_svn(root, patch_url) | 859 apply_issue_svn(root, patch_url) |
| 907 elif issue: | 860 elif issue: |
| 908 apply_issue_rietveld(issue, patchset, root, rietveld_server, | 861 apply_issue_rietveld(issue, patchset, root, rietveld_server, |
| 909 revision_mapping, git_ref) | 862 revision_mapping, git_ref) |
| 910 | 863 |
| 911 if buildspec_name: | 864 if buildspec_name: |
| 912 buildspecs2git(root, buildspec_name) | 865 buildspecs2git(root, buildspec_name) |
| 913 elif first_sln == root: | 866 elif first_sln == root: |
| 914 # Run deps2git if there is a DEPS commit after the last .DEPS.git commit. | 867 # Run deps2git if there is a DEPS commit after the last .DEPS.git commit. |
| 915 # We only need to ensure deps2git if the root is not overridden, since | 868 # We only need to ensure deps2git if the root is not overridden, since |
| 916 # if the root is overridden, it means we are working with a sub repository | 869 # if the root is overridden, it means we are working with a sub repository |
| 917 # patch, which means its impossible for it to touch DEPS. | 870 # patch, which means its impossible for it to touch DEPS. |
| 918 ensure_deps2git(root, shallow) | 871 ensure_deps2git(root, shallow) |
| 919 | 872 |
| 920 # Ensure our build/ directory is set up with the correct .gclient file. | 873 # Ensure our build/ directory is set up with the correct .gclient file. |
| 921 gclient_configure(solutions, target_os, target_os_only) | 874 gclient_configure(solutions, target_os, target_os_only) |
| 922 | 875 |
| 923 # Let gclient do the DEPS syncing. | 876 # Let gclient do the DEPS syncing. |
| 924 gclient_output = gclient_sync(buildspec_name) | 877 gclient_output = gclient_sync(buildspec_name) |
| 925 if buildspec_name: | 878 if buildspec_name: |
| 926 # Run gclient runhooks if we're on an official builder. | 879 # Run gclient runhooks if we're on an official builder. |
| 927 # TODO(hinoka): Remove this when the official builders run their own | 880 # TODO(hinoka): Remove this when the official builders run their own |
| 928 # runhooks step. | 881 # runhooks step. |
| 929 gclient_runhooks(gyp_env) | 882 gclient_runhooks(gyp_env) |
| 883 | |
| 884 # Finally, ensure that all DEPS are pinned to the correct revision. | |
| 885 dir_names = [sln['name'] for sln in solutions] | |
| 886 ensure_deps_revisions(gclient_output.get('solutions', {}), | |
| 887 dir_names, revisions) | |
| 930 return gclient_output | 888 return gclient_output |
| 931 | 889 |
| 932 | 890 |
| 891 def parse_revisions(revisions, root): | |
| 892 """Turn a list of revision specs into a nice dictionary. | |
| 893 | |
| 894 We will always return a dict with {root: something}. By default if root | |
|
iannucci
2014/05/08 23:50:06
is 'root' like 'src' or 'src/tools/gyp' ?
hinoka
2014/05/10 00:54:08
both!
I'm expecting things like src and src/third_
| |
| 895 is unspecified, or if revisions is [], then revision will be assigned 'HEAD' | |
| 896 """ | |
| 897 results = {root.strip('/'): 'HEAD'} | |
| 898 for revision in revisions: | |
| 899 split_revision = revision.split('@') | |
| 900 if len(split_revision) == 1: | |
| 901 # This is just a plain revision, set it as the revision for root. | |
| 902 results[root] = split_revision[0] | |
| 903 elif len(split_revision) == 2: | |
| 904 # This is an alt_root@revision argument. | |
| 905 current_root, current_rev = split_revision | |
| 906 | |
| 907 # We want to normalize svn/git urls into .git urls. | |
| 908 parsed_root = urlparse.urlparse(current_root) | |
| 909 if parsed_root.scheme == 'svn': | |
| 910 if parsed_root.path in RECOGNIZED_PATHS: | |
| 911 normalized_root = RECOGNIZED_PATHS[parsed_root.path] | |
| 912 else: | |
| 913 print 'WARNING: SVN path %s not recognized, ignoring' % current_root | |
|
iannucci
2014/05/08 23:50:06
in general I would recommend using the logging mod
hinoka
2014/05/10 00:54:08
I'll agree, but that sounds like a rabbit hole. I
| |
| 914 continue | |
| 915 elif parsed_root.scheme in ['http', 'https']: | |
| 916 normalized_root = 'https://%s/%s' % (parsed_root.netloc, | |
| 917 parsed_root.path) | |
| 918 if not normalized_root.endswith('.git'): | |
| 919 normalized_root = '%s.git' % normalized_root | |
| 920 elif parsed_root.scheme: | |
| 921 print 'WARNING: Unrecognized scheme %s, ignoring' % parsed_root.scheme | |
| 922 continue | |
| 923 else: | |
| 924 # This is probably a local path. | |
| 925 normalized_root = current_root.strip('/') | |
| 926 | |
| 927 results[normalized_root] = current_rev | |
| 928 else: | |
| 929 print ('WARNING: %s is not recognized as a valid revision specification,' | |
|
iannucci
2014/05/08 23:50:06
I would use %r (everywhere) to get automatic quoti
hinoka
2014/05/10 00:54:08
Done.
| |
| 930 'skipping' % revision) | |
| 931 return results | |
| 932 | |
| 933 | |
| 933 def parse_args(): | 934 def parse_args(): |
| 934 parse = optparse.OptionParser() | 935 parse = optparse.OptionParser() |
| 935 | 936 |
| 936 parse.add_option('--issue', help='Issue number to patch from.') | 937 parse.add_option('--issue', help='Issue number to patch from.') |
| 937 parse.add_option('--patchset', | 938 parse.add_option('--patchset', |
| 938 help='Patchset from issue to patch from, if applicable.') | 939 help='Patchset from issue to patch from, if applicable.') |
| 939 parse.add_option('--patch_url', help='Optional URL to SVN patch.') | 940 parse.add_option('--patch_url', help='Optional URL to SVN patch.') |
| 940 parse.add_option('--root', help='Repository root.') | 941 parse.add_option('--root', help='Repository root.') |
| 941 parse.add_option('--rietveld_server', | 942 parse.add_option('--rietveld_server', |
| 942 default='codereview.chromium.org', | 943 default='codereview.chromium.org', |
| 943 help='Rietveld server.') | 944 help='Rietveld server.') |
| 944 parse.add_option('--specs', help='Gcilent spec.') | 945 parse.add_option('--specs', help='Gcilent spec.') |
| 945 parse.add_option('--master', help='Master name.') | 946 parse.add_option('--master', help='Master name.') |
| 946 parse.add_option('-f', '--force', action='store_true', | 947 parse.add_option('-f', '--force', action='store_true', |
| 947 help='Bypass check to see if we want to be run. ' | 948 help='Bypass check to see if we want to be run. ' |
| 948 'Should ONLY be used locally.') | 949 'Should ONLY be used locally.') |
| 949 parse.add_option('--revision_mapping') | 950 parse.add_option('--revision_mapping') |
| 950 parse.add_option('--revision-mapping') # Backwards compatability. | 951 parse.add_option('--revision-mapping') # Backwards compatability. |
| 951 # TODO(hinoka): Support root@revision format. | 952 parse.add_option('--revision', action='append', default=[], |
| 952 parse.add_option('--revision', | |
| 953 help='Revision to check out. Can be an SVN revision number, ' | 953 help='Revision to check out. Can be an SVN revision number, ' |
| 954 'git hash, or any form of git ref.') | 954 'git hash, or any form of git ref. Can prepend ' |
| 955 'root@<rev> to specify which repository, where root ' | |
| 956 'is either a filesystem path, git https url, or ' | |
| 957 'svn url. To specify Tip of Tree, set rev to HEAD.') | |
|
iannucci
2014/05/08 23:50:06
Note that gclient would accept `--revision src@<re
hinoka
2014/05/10 00:54:08
Discussed offline - All revision handling is done
| |
| 955 parse.add_option('--slave_name', default=socket.getfqdn().split('.')[0], | 958 parse.add_option('--slave_name', default=socket.getfqdn().split('.')[0], |
| 956 help='Hostname of the current machine, ' | 959 help='Hostname of the current machine, ' |
| 957 'used for determining whether or not to activate.') | 960 'used for determining whether or not to activate.') |
| 958 parse.add_option('--builder_name', help='Name of the builder, ' | 961 parse.add_option('--builder_name', help='Name of the builder, ' |
| 959 'used for determining whether or not to activate.') | 962 'used for determining whether or not to activate.') |
| 960 parse.add_option('--build_dir', default=os.getcwd()) | 963 parse.add_option('--build_dir', default=os.getcwd()) |
| 961 parse.add_option('--flag_file', default=path.join(os.getcwd(), | 964 parse.add_option('--flag_file', default=path.join(os.getcwd(), |
| 962 'update.flag')) | 965 'update.flag')) |
| 963 parse.add_option('--shallow', action='store_true', | 966 parse.add_option('--shallow', action='store_true', |
| 964 help='Use shallow clones for cache repositories.') | 967 help='Use shallow clones for cache repositories.') |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1035 print '@@@STEP_TEXT@%s@@@' % step_text | 1038 print '@@@STEP_TEXT@%s@@@' % step_text |
| 1036 if not options.shallow: | 1039 if not options.shallow: |
| 1037 options.shallow = total_disk_space < SHALLOW_CLONE_THRESHOLD | 1040 options.shallow = total_disk_space < SHALLOW_CLONE_THRESHOLD |
| 1038 | 1041 |
| 1039 # By default, the root should be the name of the first solution, but | 1042 # By default, the root should be the name of the first solution, but |
| 1040 # also make it overridable. The root is where patches are applied on top of. | 1043 # also make it overridable. The root is where patches are applied on top of. |
| 1041 options.root = options.root or dir_names[0] | 1044 options.root = options.root or dir_names[0] |
| 1042 # The first solution is where the primary DEPS file resides. | 1045 # The first solution is where the primary DEPS file resides. |
| 1043 first_sln = dir_names[0] | 1046 first_sln = dir_names[0] |
| 1044 | 1047 |
| 1048 # Split all the revision specifications into a nice dict. | |
| 1049 print 'Revisions: %s' % options.revision | |
| 1050 revisions = parse_revisions(options.revision, options.root) | |
| 1051 # This is meant to be just an alias to the revision of the main solution. | |
| 1052 root_revision = revisions[options.root] | |
| 1053 print 'Fetching Git checkout at %s@%s' % (options.root, root_revision) | |
| 1054 | |
| 1045 try: | 1055 try: |
| 1046 checkout_parameters = dict( | 1056 checkout_parameters = dict( |
| 1047 # First, pass in the base of what we want to check out. | 1057 # First, pass in the base of what we want to check out. |
| 1048 solutions=git_solutions, | 1058 solutions=git_solutions, |
| 1049 revision=options.revision, | 1059 revisions=revisions, |
| 1050 first_sln=first_sln, | 1060 first_sln=first_sln, |
| 1051 | 1061 |
| 1052 # Also, target os variables for gclient. | 1062 # Also, target os variables for gclient. |
| 1053 target_os=specs.get('target_os', []), | 1063 target_os=specs.get('target_os', []), |
| 1054 target_os_only=specs.get('target_os_only', False), | 1064 target_os_only=specs.get('target_os_only', False), |
| 1055 | 1065 |
| 1056 # Then, pass in information about how to patch on top of the checkout. | 1066 # Then, pass in information about how to patch on top of the checkout. |
| 1057 root=options.root, | 1067 root=options.root, |
| 1058 issue=options.issue, | 1068 issue=options.issue, |
| 1059 patchset=options.patchset, | 1069 patchset=options.patchset, |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 1088 patch_root=options.root, | 1098 patch_root=options.root, |
| 1089 step_text=step_text, | 1099 step_text=step_text, |
| 1090 properties=got_revisions) | 1100 properties=got_revisions) |
| 1091 else: | 1101 else: |
| 1092 # If we're not on recipes, tell annotator about our got_revisions. | 1102 # If we're not on recipes, tell annotator about our got_revisions. |
| 1093 emit_properties(got_revisions) | 1103 emit_properties(got_revisions) |
| 1094 | 1104 |
| 1095 | 1105 |
| 1096 if __name__ == '__main__': | 1106 if __name__ == '__main__': |
| 1097 sys.exit(main()) | 1107 sys.exit(main()) |
| OLD | NEW |