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. |
| 7 |
6 import codecs | 8 import codecs |
7 import copy | 9 import copy |
8 import cStringIO | 10 import cStringIO |
9 import ctypes | 11 import ctypes |
10 import json | 12 import json |
11 import optparse | 13 import optparse |
12 import os | 14 import os |
13 import pprint | 15 import pprint |
14 import re | 16 import re |
15 import shutil | 17 import shutil |
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 finally: | 502 finally: |
501 os.remove(gclient_output_file) | 503 os.remove(gclient_output_file) |
502 | 504 |
503 | 505 |
504 def gclient_runhooks(gyp_envs): | 506 def gclient_runhooks(gyp_envs): |
505 gclient_bin = 'gclient.bat' if sys.platform.startswith('win') else 'gclient' | 507 gclient_bin = 'gclient.bat' if sys.platform.startswith('win') else 'gclient' |
506 env = dict([env_var.split('=', 1) for env_var in gyp_envs]) | 508 env = dict([env_var.split('=', 1) for env_var in gyp_envs]) |
507 call(gclient_bin, 'runhooks', env=env) | 509 call(gclient_bin, 'runhooks', env=env) |
508 | 510 |
509 | 511 |
510 def create_less_than_or_equal_regex(number): | |
511 """ Return a regular expression to test whether an integer less than or equal | |
512 to 'number' is present in a given string. | |
513 """ | |
514 | |
515 # In three parts, build a regular expression that match any numbers smaller | |
516 # than 'number'. | |
517 # For example, 78656 would give a regular expression that looks like: | |
518 # Part 1 | |
519 # (78356| # 78356 | |
520 # Part 2 | |
521 # 7835[0-5]| # 78350-78355 | |
522 # 783[0-4][0-9]| # 78300-78349 | |
523 # 78[0-2][0-9]{2}| # 78000-78299 | |
524 # 7[0-7][0-9]{3}| # 70000-77999 | |
525 # [0-6][0-9]{4}| # 10000-69999 | |
526 # Part 3 | |
527 # [0-9]{1,4} # 0-9999 | |
528 | |
529 # Part 1: Create an array with all the regexes, as described above. | |
530 # Prepopulate it with the number itself. | |
531 number = str(number) | |
532 expressions = [number] | |
533 | |
534 # Convert the number to a list, so we can translate digits in it to | |
535 # expressions. | |
536 num_list = list(number) | |
537 num_len = len(num_list) | |
538 | |
539 # Part 2: Go through all the digits in the number, starting from the end. | |
540 # Each iteration appends a line to 'expressions'. | |
541 for index in range (num_len - 1, -1, -1): | |
542 # Convert this digit back to an integer. | |
543 digit = int(num_list[index]) | |
544 | |
545 # Part 2.1: No processing if this digit is a zero. | |
546 if digit == 0: | |
547 continue | |
548 | |
549 # Part 2.2: We switch the current digit X by a range "[0-(X-1)]". | |
550 if digit == 1: | |
551 num_list[index] = '0' | |
552 else: | |
553 num_list[index] = '[0-%d]' % (digit - 1) | |
554 | |
555 # Part 2.3: We set all following digits to be "[0-9]". | |
556 # Since we just decrementented a digit in a most important position, all | |
557 # following digits don't matter. The possible numbers will always be smaller | |
558 # than before we decremented. | |
559 if (index + 1) < num_len: | |
560 if (num_len - (index + 1)) == 1: | |
561 num_list[index + 1] = '[0-9]' | |
562 else: | |
563 num_list[index + 1] = '[0-9]{%s}' % (num_len - (index + 1)) | |
564 | |
565 # Part 2.4: Add this new sub-expression to the list. | |
566 expressions.append(''.join(num_list[:min(index+2, num_len)])) | |
567 | |
568 # Part 3: We add all the full ranges to match all numbers that are at least | |
569 # one order of magnitude smaller than the original numbers. | |
570 if num_len == 2: | |
571 expressions.append('[0-9]') | |
572 elif num_len > 2: | |
573 expressions.append('[0-9]{1,%s}' % (num_len - 1)) | |
574 | |
575 # All done. We now have our final regular expression. | |
576 regex = '(%s)' % ('|'.join(expressions)) | |
577 return regex | |
578 | |
579 | |
580 def get_svn_rev(git_hash, dir_name): | 512 def get_svn_rev(git_hash, dir_name): |
581 pattern = r'^\s*git-svn-id: [^ ]*@(\d+) ' | 513 pattern = r'^\s*git-svn-id: [^ ]*@(\d+) ' |
582 lkcr_pattern = r'^\s*LK[CG]R w/ DEPS up to revision (\d+)' | |
583 log = git('log', '-1', git_hash, cwd=dir_name) | 514 log = git('log', '-1', git_hash, cwd=dir_name) |
584 match = re.search(pattern, log, re.M) | 515 match = re.search(pattern, log, re.M) |
585 if not match: | 516 if not match: |
586 # This might be a patched checkout, try the parent commit. | 517 return None |
587 log = git('log', '-1', '%s^' % git_hash, cwd=dir_name) | |
588 match = re.search(pattern, log, re.M) | |
589 if not match: | |
590 # Might be patched on top of LKCR, which has a special message. | |
591 match = re.search(lkcr_pattern, log, re.M) | |
592 if not match: | |
593 return None | |
594 return int(match.group(1)) | 518 return int(match.group(1)) |
595 | 519 |
596 | 520 |
597 def get_git_hash(revision, dir_name): | 521 def get_git_hash(revision, sln_dir): |
598 match = "^git-svn-id: [^ ]*@%s " % create_less_than_or_equal_regex(revision) | 522 """We want to search for the SVN revision on the git-svn branch. |
599 cmd = ['log', '-E', '--grep', match, '--format=%H', '--max-count=1'] | 523 |
600 results = git(*cmd, cwd=dir_name).strip().splitlines() | 524 Note that git will search backwards from origin/master. |
601 if results: | 525 """ |
602 return results[0] | 526 match = "^git-svn-id: [^ ]*@%s " % revision |
603 raise Exception('We can\'t resolve svn revision %s into a git hash' % | 527 cmd = ['log', '-E', '--grep', match, '--format=%H', '--max-count=1', |
604 revision) | 528 'origin/master'] |
| 529 result = git(*cmd, cwd=sln_dir).strip() |
| 530 if result: |
| 531 return result |
| 532 raise SVNRevisionNotFound('We can\'t resolve svn r%s into a git hash in %s' % |
| 533 (revision, sln_dir)) |
605 | 534 |
606 | 535 |
607 def get_revision_mapping(root, addl_rev_map): | 536 def get_revision_mapping(root, addl_rev_map): |
608 result = {} | 537 result = {} |
609 if root in GOT_REVISION_MAPPINGS: | 538 if root in GOT_REVISION_MAPPINGS: |
610 result.update(GOT_REVISION_MAPPINGS[root]) | 539 result.update(GOT_REVISION_MAPPINGS[root]) |
611 if addl_rev_map: | 540 if addl_rev_map: |
612 result.update(json.loads(addl_rev_map)) | 541 result.update(json.loads(addl_rev_map)) |
613 return result | 542 return result |
614 | 543 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
744 raise ctypes.WinError() | 673 raise ctypes.WinError() |
745 return (total.value, free.value) | 674 return (total.value, free.value) |
746 | 675 |
747 else: | 676 else: |
748 st = os.statvfs(cwd) | 677 st = os.statvfs(cwd) |
749 free = st.f_bavail * st.f_frsize | 678 free = st.f_bavail * st.f_frsize |
750 total = st.f_blocks * st.f_frsize | 679 total = st.f_blocks * st.f_frsize |
751 return (total, free) | 680 return (total, free) |
752 | 681 |
753 | 682 |
754 def git_checkout(solutions, revision, shallow): | 683 def get_revision(folder_name, git_url, revisions): |
| 684 normalized_name = folder_name.strip('/') |
| 685 if normalized_name in revisions: |
| 686 return revisions[normalized_name] |
| 687 if git_url in revisions: |
| 688 return revisions[git_url] |
| 689 return None |
| 690 |
| 691 |
| 692 def force_revision(folder_name, revision): |
| 693 if revision and revision.upper() != 'HEAD': |
| 694 if revision and revision.isdigit() and len(revision) < 40: |
| 695 # rev_num is really a svn revision number, convert it into a git hash. |
| 696 git_ref = get_git_hash(int(revision), folder_name) |
| 697 else: |
| 698 # rev_num is actually a git hash or ref, we can just use it. |
| 699 git_ref = revision |
| 700 git('checkout', git_ref, cwd=folder_name) |
| 701 else: |
| 702 # Revision is None or 'HEAD', we want ToT. |
| 703 git('checkout', 'origin/master', cwd=folder_name) |
| 704 |
| 705 |
| 706 def git_checkout(solutions, revisions, shallow): |
755 build_dir = os.getcwd() | 707 build_dir = os.getcwd() |
756 # Before we do anything, break all git_cache locks. | 708 # Before we do anything, break all git_cache locks. |
757 if path.isdir(CACHE_DIR): | 709 if path.isdir(CACHE_DIR): |
758 git('cache', 'unlock', '-vv', '--force', '--all', '--cache-dir', CACHE_DIR) | 710 git('cache', 'unlock', '-vv', '--force', '--all', '--cache-dir', CACHE_DIR) |
759 for item in os.listdir(CACHE_DIR): | 711 for item in os.listdir(CACHE_DIR): |
760 filename = os.path.join(CACHE_DIR, item) | 712 filename = os.path.join(CACHE_DIR, item) |
761 if item.endswith('.lock'): | 713 if item.endswith('.lock'): |
762 raise Exception('%s exists after cache unlock' % filename) | 714 raise Exception('%s exists after cache unlock' % filename) |
763 # Revision only applies to the first solution. | |
764 first_solution = True | 715 first_solution = True |
765 for sln in solutions: | 716 for sln in solutions: |
766 # This is so we can loop back and try again if we need to wait for the | 717 # This is so we can loop back and try again if we need to wait for the |
767 # git mirrors to update from SVN. | 718 # git mirrors to update from SVN. |
768 done = False | 719 done = False |
769 tries_left = 60 | 720 tries_left = 60 |
770 while not done: | 721 while not done: |
771 done = True | 722 done = True |
772 name = sln['name'] | 723 name = sln['name'] |
773 url = sln['url'] | 724 url = sln['url'] |
(...skipping 21 matching lines...) Expand all Loading... |
795 # Lets wipe the checkout and try again. | 746 # Lets wipe the checkout and try again. |
796 chromium_utils.RemoveDirectory(sln_dir) | 747 chromium_utils.RemoveDirectory(sln_dir) |
797 git(*clone_cmd) | 748 git(*clone_cmd) |
798 git('checkout', '--force', 'origin/master', cwd=sln_dir) | 749 git('checkout', '--force', 'origin/master', cwd=sln_dir) |
799 git('reset', '--hard', cwd=sln_dir) | 750 git('reset', '--hard', cwd=sln_dir) |
800 else: | 751 else: |
801 raise | 752 raise |
802 | 753 |
803 git('clean', '-df', cwd=sln_dir) | 754 git('clean', '-df', cwd=sln_dir) |
804 git('fetch', 'origin', cwd=sln_dir) | 755 git('fetch', 'origin', cwd=sln_dir) |
805 # TODO(hinoka): We probably have to make use of revision mapping. | |
806 if first_solution and revision and revision.lower() != 'head': | |
807 if revision and revision.isdigit() and len(revision) < 40: | |
808 # rev_num is really a svn revision number, convert it into a git hash. | |
809 git_ref = get_git_hash(int(revision), name) | |
810 # Lets make sure our checkout has the correct revision number. | |
811 got_revision = get_svn_rev(git_ref, sln_dir) | |
812 if not got_revision or int(got_revision) != int(revision): | |
813 tries_left -= 1 | |
814 if tries_left > 0: | |
815 # If we don't have the correct revision, wait and try again. | |
816 print 'We want revision %s, but got revision %s.' % ( | |
817 revision, got_revision) | |
818 print 'The svn to git replicator is probably falling behind.' | |
819 print 'waiting 5 seconds and trying again...' | |
820 time.sleep(5) | |
821 done = False | |
822 continue | |
823 raise SVNRevisionNotFound | |
824 else: | |
825 # rev_num is actually a git hash or ref, we can just use it. | |
826 git_ref = revision | |
827 git('checkout', git_ref, cwd=sln_dir) | |
828 else: | |
829 git('checkout', 'origin/master', cwd=sln_dir) | |
830 if first_solution: | |
831 git_ref = git('log', '--format=%H', '--max-count=1', | |
832 cwd=sln_dir).strip() | |
833 | 756 |
| 757 revision = get_revision(name, url, revisions) or 'HEAD' |
| 758 try: |
| 759 force_revision(sln_dir, revision) |
| 760 except SVNRevisionNotFound: |
| 761 tries_left -= 1 |
| 762 if tries_left > 0: |
| 763 # If we don't have the correct revision, wait and try again. |
| 764 print 'We can\'t find revision %s.' % revision |
| 765 print 'The svn to git replicator is probably falling behind.' |
| 766 print 'waiting 5 seconds and trying again...' |
| 767 time.sleep(5) |
| 768 done = False |
| 769 continue |
| 770 raise |
| 771 |
| 772 if first_solution: |
| 773 git_ref = git('log', '--format=%H', '--max-count=1', |
| 774 cwd=sln_dir).strip() |
834 first_solution = False | 775 first_solution = False |
835 return git_ref | 776 return git_ref |
836 | 777 |
837 | 778 |
838 def _download(url): | 779 def _download(url): |
839 """Fetch url and return content, with retries for flake.""" | 780 """Fetch url and return content, with retries for flake.""" |
840 for attempt in xrange(RETRIES): | 781 for attempt in xrange(RETRIES): |
841 try: | 782 try: |
842 return urllib2.urlopen(url).read() | 783 return urllib2.urlopen(url).read() |
843 except Exception: | 784 except Exception: |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 for dir_name, property_name in got_revision_mapping.iteritems(): | 843 for dir_name, property_name in got_revision_mapping.iteritems(): |
903 if dir_name not in solutions_output: | 844 if dir_name not in solutions_output: |
904 continue | 845 continue |
905 solution_output = solutions_output[dir_name] | 846 solution_output = solutions_output[dir_name] |
906 if solution_output.get('scm') is None: | 847 if solution_output.get('scm') is None: |
907 # This is an ignored DEPS, so the output got_revision should be 'None'. | 848 # This is an ignored DEPS, so the output got_revision should be 'None'. |
908 git_revision = revision = None | 849 git_revision = revision = None |
909 else: | 850 else: |
910 # Since we are using .DEPS.git, everything had better be git. | 851 # Since we are using .DEPS.git, everything had better be git. |
911 assert solution_output.get('scm') == 'git' | 852 assert solution_output.get('scm') == 'git' |
912 git_revision = get_real_git_hash(solution_output['revision'], dir_name) | 853 git_revision = git('rev-parse', 'HEAD', cwd=dir_name).strip() |
913 if use_svn_revs: | 854 if use_svn_revs: |
914 revision = get_svn_rev(git_revision, dir_name) | 855 revision = get_svn_rev(git_revision, dir_name) |
915 if not revision: | 856 if not revision: |
916 revision = git_revision | 857 revision = git_revision |
917 else: | 858 else: |
918 revision = git_revision | 859 revision = git_revision |
919 | 860 |
920 properties[property_name] = revision | 861 properties[property_name] = revision |
921 if revision != git_revision: | 862 if revision != git_revision: |
922 properties['%s_git' % property_name] = git_revision | 863 properties['%s_git' % property_name] = git_revision |
923 | 864 |
924 return properties | 865 return properties |
925 | 866 |
926 | 867 |
927 def emit_json(out_file, did_run, gclient_output=None, **kwargs): | 868 def emit_json(out_file, did_run, gclient_output=None, **kwargs): |
928 """Write run information into a JSON file.""" | 869 """Write run information into a JSON file.""" |
929 output = {} | 870 output = {} |
930 output.update(gclient_output if gclient_output else {}) | 871 output.update(gclient_output if gclient_output else {}) |
931 output.update({'did_run': did_run}) | 872 output.update({'did_run': did_run}) |
932 output.update(kwargs) | 873 output.update(kwargs) |
933 with open(out_file, 'wb') as f: | 874 with open(out_file, 'wb') as f: |
934 f.write(json.dumps(output)) | 875 f.write(json.dumps(output)) |
935 | 876 |
936 | 877 |
937 def ensure_checkout(solutions, revision, first_sln, target_os, target_os_only, | 878 def ensure_deps_revisions(deps_url_mapping, solutions, revisions): |
| 879 """Ensure correct DEPS revisions, ignores solutions.""" |
| 880 for deps_name, deps_data in sorted(deps_url_mapping.items()): |
| 881 if deps_name.strip('/') in solutions: |
| 882 # This has already been forced to the correct solution by git_checkout(). |
| 883 continue |
| 884 revision = get_revision(deps_name, deps_data.get('url', None), revisions) |
| 885 if not revision: |
| 886 continue |
| 887 # TODO(hinoka): Catch SVNRevisionNotFound error maybe? |
| 888 force_revision(deps_name, revision) |
| 889 |
| 890 |
| 891 def ensure_checkout(solutions, revisions, first_sln, target_os, target_os_only, |
938 root, issue, patchset, patch_url, rietveld_server, | 892 root, issue, patchset, patch_url, rietveld_server, |
939 revision_mapping, buildspec_name, gyp_env, shallow): | 893 revision_mapping, buildspec_name, gyp_env, shallow): |
940 # Get a checkout of each solution, without DEPS or hooks. | 894 # Get a checkout of each solution, without DEPS or hooks. |
941 # Calling git directly because there is no way to run Gclient without | 895 # Calling git directly because there is no way to run Gclient without |
942 # invoking DEPS. | 896 # invoking DEPS. |
943 print 'Fetching Git checkout' | 897 print 'Fetching Git checkout' |
944 git_ref = git_checkout(solutions, revision, shallow) | 898 git_ref = git_checkout(solutions, revisions, shallow) |
945 | 899 |
946 # If either patch_url or issue is passed in, then we need to apply a patch. | 900 # If either patch_url or issue is passed in, then we need to apply a patch. |
947 if patch_url: | 901 if patch_url: |
948 # patch_url takes precidence since its only passed in on gcl try/git try. | 902 # patch_url takes precidence since its only passed in on gcl try/git try. |
949 apply_issue_svn(root, patch_url) | 903 apply_issue_svn(root, patch_url) |
950 elif issue: | 904 elif issue: |
951 apply_issue_rietveld(issue, patchset, root, rietveld_server, | 905 apply_issue_rietveld(issue, patchset, root, rietveld_server, |
952 revision_mapping, git_ref) | 906 revision_mapping, git_ref) |
953 | 907 |
954 if buildspec_name: | 908 if buildspec_name: |
955 buildspecs2git(root, buildspec_name) | 909 buildspecs2git(root, buildspec_name) |
956 elif first_sln == root: | 910 elif first_sln == root: |
957 # Run deps2git if there is a DEPS commit after the last .DEPS.git commit. | 911 # Run deps2git if there is a DEPS commit after the last .DEPS.git commit. |
958 # We only need to ensure deps2git if the root is not overridden, since | 912 # We only need to ensure deps2git if the root is not overridden, since |
959 # if the root is overridden, it means we are working with a sub repository | 913 # if the root is overridden, it means we are working with a sub repository |
960 # patch, which means its impossible for it to touch DEPS. | 914 # patch, which means its impossible for it to touch DEPS. |
961 ensure_deps2git(root, shallow) | 915 ensure_deps2git(root, shallow) |
962 | 916 |
963 # Ensure our build/ directory is set up with the correct .gclient file. | 917 # Ensure our build/ directory is set up with the correct .gclient file. |
964 gclient_configure(solutions, target_os, target_os_only) | 918 gclient_configure(solutions, target_os, target_os_only) |
965 | 919 |
966 # Let gclient do the DEPS syncing. | 920 # Let gclient do the DEPS syncing. |
967 gclient_output = gclient_sync(buildspec_name) | 921 gclient_output = gclient_sync(buildspec_name) |
968 if buildspec_name: | 922 if buildspec_name: |
969 # Run gclient runhooks if we're on an official builder. | 923 # Run gclient runhooks if we're on an official builder. |
970 # TODO(hinoka): Remove this when the official builders run their own | 924 # TODO(hinoka): Remove this when the official builders run their own |
971 # runhooks step. | 925 # runhooks step. |
972 gclient_runhooks(gyp_env) | 926 gclient_runhooks(gyp_env) |
| 927 |
| 928 # Finally, ensure that all DEPS are pinned to the correct revision. |
| 929 dir_names = [sln['name'] for sln in solutions] |
| 930 ensure_deps_revisions(gclient_output.get('solutions', {}), |
| 931 dir_names, revisions) |
973 return gclient_output | 932 return gclient_output |
974 | 933 |
975 | 934 |
976 class UploadTelemetryThread(threading.Thread): | 935 class UploadTelemetryThread(threading.Thread): |
977 def __init__(self, prefix, master, builder, slave, kwargs): | 936 def __init__(self, prefix, master, builder, slave, kwargs): |
978 super(UploadTelemetryThread, self).__init__() | 937 super(UploadTelemetryThread, self).__init__() |
979 self.master = master | 938 self.master = master |
980 self.builder = builder | 939 self.builder = builder |
981 self.slave = slave | 940 self.slave = slave |
982 self.prefix = prefix | 941 self.prefix = prefix |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 stdin_data=json.dumps(data)) | 975 stdin_data=json.dumps(data)) |
1017 | 976 |
1018 | 977 |
1019 def upload_telemetry(prefix, master, builder, slave, **kwargs): | 978 def upload_telemetry(prefix, master, builder, slave, **kwargs): |
1020 thr = UploadTelemetryThread(prefix, master, builder, slave, kwargs) | 979 thr = UploadTelemetryThread(prefix, master, builder, slave, kwargs) |
1021 thr.daemon = True | 980 thr.daemon = True |
1022 thr.start() | 981 thr.start() |
1023 return thr | 982 return thr |
1024 | 983 |
1025 | 984 |
| 985 def parse_revisions(revisions, root): |
| 986 """Turn a list of revision specs into a nice dictionary. |
| 987 |
| 988 We will always return a dict with {root: something}. By default if root |
| 989 is unspecified, or if revisions is [], then revision will be assigned 'HEAD' |
| 990 """ |
| 991 results = {root.strip('/'): 'HEAD'} |
| 992 for revision in revisions: |
| 993 split_revision = revision.split('@') |
| 994 if len(split_revision) == 1: |
| 995 # This is just a plain revision, set it as the revision for root. |
| 996 results[root] = split_revision[0] |
| 997 elif len(split_revision) == 2: |
| 998 # This is an alt_root@revision argument. |
| 999 current_root, current_rev = split_revision |
| 1000 |
| 1001 # We want to normalize svn/git urls into .git urls. |
| 1002 parsed_root = urlparse.urlparse(current_root) |
| 1003 if parsed_root.scheme == 'svn': |
| 1004 if parsed_root.path in RECOGNIZED_PATHS: |
| 1005 normalized_root = RECOGNIZED_PATHS[parsed_root.path] |
| 1006 else: |
| 1007 print 'WARNING: SVN path %s not recognized, ignoring' % current_root |
| 1008 continue |
| 1009 elif parsed_root.scheme in ['http', 'https']: |
| 1010 normalized_root = 'https://%s/%s' % (parsed_root.netloc, |
| 1011 parsed_root.path) |
| 1012 if not normalized_root.endswith('.git'): |
| 1013 normalized_root = '%s.git' % normalized_root |
| 1014 elif parsed_root.scheme: |
| 1015 print 'WARNING: Unrecognized scheme %s, ignoring' % parsed_root.scheme |
| 1016 continue |
| 1017 else: |
| 1018 # This is probably a local path. |
| 1019 normalized_root = current_root.strip('/') |
| 1020 |
| 1021 results[normalized_root] = current_rev |
| 1022 else: |
| 1023 print ('WARNING: %r is not recognized as a valid revision specification,' |
| 1024 'skipping' % revision) |
| 1025 return results |
| 1026 |
| 1027 |
1026 def parse_args(): | 1028 def parse_args(): |
1027 parse = optparse.OptionParser() | 1029 parse = optparse.OptionParser() |
1028 | 1030 |
1029 parse.add_option('--issue', help='Issue number to patch from.') | 1031 parse.add_option('--issue', help='Issue number to patch from.') |
1030 parse.add_option('--patchset', | 1032 parse.add_option('--patchset', |
1031 help='Patchset from issue to patch from, if applicable.') | 1033 help='Patchset from issue to patch from, if applicable.') |
1032 parse.add_option('--patch_url', help='Optional URL to SVN patch.') | 1034 parse.add_option('--patch_url', help='Optional URL to SVN patch.') |
1033 parse.add_option('--root', help='Repository root.') | 1035 parse.add_option('--root', help='Repository root.') |
1034 parse.add_option('--rietveld_server', | 1036 parse.add_option('--rietveld_server', |
1035 default='codereview.chromium.org', | 1037 default='codereview.chromium.org', |
1036 help='Rietveld server.') | 1038 help='Rietveld server.') |
1037 parse.add_option('--specs', help='Gcilent spec.') | 1039 parse.add_option('--specs', help='Gcilent spec.') |
1038 parse.add_option('--master', help='Master name.') | 1040 parse.add_option('--master', help='Master name.') |
1039 parse.add_option('-f', '--force', action='store_true', | 1041 parse.add_option('-f', '--force', action='store_true', |
1040 help='Bypass check to see if we want to be run. ' | 1042 help='Bypass check to see if we want to be run. ' |
1041 'Should ONLY be used locally.') | 1043 'Should ONLY be used locally.') |
1042 parse.add_option('--revision_mapping') | 1044 parse.add_option('--revision_mapping') |
1043 parse.add_option('--revision-mapping') # Backwards compatability. | 1045 parse.add_option('--revision-mapping') # Backwards compatability. |
1044 # TODO(hinoka): Support root@revision format. | 1046 parse.add_option('--revision', action='append', default=[], |
1045 parse.add_option('--revision', | |
1046 help='Revision to check out. Can be an SVN revision number, ' | 1047 help='Revision to check out. Can be an SVN revision number, ' |
1047 'git hash, or any form of git ref.') | 1048 'git hash, or any form of git ref. Can prepend ' |
| 1049 'root@<rev> to specify which repository, where root ' |
| 1050 'is either a filesystem path, git https url, or ' |
| 1051 'svn url. To specify Tip of Tree, set rev to HEAD.') |
1048 parse.add_option('--slave_name', default=socket.getfqdn().split('.')[0], | 1052 parse.add_option('--slave_name', default=socket.getfqdn().split('.')[0], |
1049 help='Hostname of the current machine, ' | 1053 help='Hostname of the current machine, ' |
1050 'used for determining whether or not to activate.') | 1054 'used for determining whether or not to activate.') |
1051 parse.add_option('--builder_name', help='Name of the builder, ' | 1055 parse.add_option('--builder_name', help='Name of the builder, ' |
1052 'used for determining whether or not to activate.') | 1056 'used for determining whether or not to activate.') |
1053 parse.add_option('--build_dir', default=os.getcwd()) | 1057 parse.add_option('--build_dir', default=os.getcwd()) |
1054 parse.add_option('--flag_file', default=path.join(os.getcwd(), | 1058 parse.add_option('--flag_file', default=path.join(os.getcwd(), |
1055 'update.flag')) | 1059 'update.flag')) |
1056 parse.add_option('--shallow', action='store_true', | 1060 parse.add_option('--shallow', action='store_true', |
1057 help='Use shallow clones for cache repositories.') | 1061 help='Use shallow clones for cache repositories.') |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 print '@@@STEP_TEXT@%s@@@' % step_text | 1147 print '@@@STEP_TEXT@%s@@@' % step_text |
1144 if not options.shallow: | 1148 if not options.shallow: |
1145 options.shallow = total_disk_space < SHALLOW_CLONE_THRESHOLD | 1149 options.shallow = total_disk_space < SHALLOW_CLONE_THRESHOLD |
1146 | 1150 |
1147 # By default, the root should be the name of the first solution, but | 1151 # By default, the root should be the name of the first solution, but |
1148 # also make it overridable. The root is where patches are applied on top of. | 1152 # also make it overridable. The root is where patches are applied on top of. |
1149 options.root = options.root or dir_names[0] | 1153 options.root = options.root or dir_names[0] |
1150 # The first solution is where the primary DEPS file resides. | 1154 # The first solution is where the primary DEPS file resides. |
1151 first_sln = dir_names[0] | 1155 first_sln = dir_names[0] |
1152 | 1156 |
| 1157 # Split all the revision specifications into a nice dict. |
| 1158 print 'Revisions: %s' % options.revision |
| 1159 revisions = parse_revisions(options.revision, options.root) |
| 1160 # This is meant to be just an alias to the revision of the main solution. |
| 1161 root_revision = revisions[options.root] |
| 1162 print 'Fetching Git checkout at %s@%s' % (options.root, root_revision) |
| 1163 |
1153 try: | 1164 try: |
1154 checkout_parameters = dict( | 1165 checkout_parameters = dict( |
1155 # First, pass in the base of what we want to check out. | 1166 # First, pass in the base of what we want to check out. |
1156 solutions=git_solutions, | 1167 solutions=git_solutions, |
1157 revision=options.revision, | 1168 revisions=revisions, |
1158 first_sln=first_sln, | 1169 first_sln=first_sln, |
1159 | 1170 |
1160 # Also, target os variables for gclient. | 1171 # Also, target os variables for gclient. |
1161 target_os=specs.get('target_os', []), | 1172 target_os=specs.get('target_os', []), |
1162 target_os_only=specs.get('target_os_only', False), | 1173 target_os_only=specs.get('target_os_only', False), |
1163 | 1174 |
1164 # Then, pass in information about how to patch on top of the checkout. | 1175 # Then, pass in information about how to patch on top of the checkout. |
1165 root=options.root, | 1176 root=options.root, |
1166 issue=options.issue, | 1177 issue=options.issue, |
1167 patchset=options.patchset, | 1178 patchset=options.patchset, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1213 specs=options.specs) | 1224 specs=options.specs) |
1214 all_threads.append(thr) | 1225 all_threads.append(thr) |
1215 | 1226 |
1216 # Sort of wait for all telemetry threads to finish. | 1227 # Sort of wait for all telemetry threads to finish. |
1217 for thr in all_threads: | 1228 for thr in all_threads: |
1218 thr.join(5) | 1229 thr.join(5) |
1219 | 1230 |
1220 | 1231 |
1221 if __name__ == '__main__': | 1232 if __name__ == '__main__': |
1222 sys.exit(main()) | 1233 sys.exit(main()) |
OLD | NEW |