OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2010 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 """A wrapper script to manage a set of client modules in different SCM. | 6 """A wrapper script to manage a set of client modules in different SCM. |
7 | 7 |
8 This script is intended to be used to help basic management of client | 8 This script is intended to be used to help basic management of client |
9 program sources residing in one or more Subversion modules and Git | 9 program sources residing in one or more Subversion modules and Git |
10 repositories, along with other modules it depends on, also in Subversion or Git, | 10 repositories, along with other modules it depends on, also in Subversion or Git, |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 # match each hook's pattern. | 499 # match each hook's pattern. |
500 for hook_dict in hooks: | 500 for hook_dict in hooks: |
501 pattern = re.compile(hook_dict['pattern']) | 501 pattern = re.compile(hook_dict['pattern']) |
502 matching_file_list = [f for f in file_list if pattern.search(f)] | 502 matching_file_list = [f for f in file_list if pattern.search(f)] |
503 if matching_file_list: | 503 if matching_file_list: |
504 self._RunHookAction(hook_dict, matching_file_list) | 504 self._RunHookAction(hook_dict, matching_file_list) |
505 | 505 |
506 def _EnforceRevisions(self, solutions): | 506 def _EnforceRevisions(self, solutions): |
507 """Checks for revision overrides.""" | 507 """Checks for revision overrides.""" |
508 revision_overrides = {} | 508 revision_overrides = {} |
509 solutions = [s['name'] for s in solutions] | 509 if self._options.head: |
510 if self._options.revisions: | 510 return revision_overrides |
511 revision = self._options.revisions[0] | 511 for s in solutions: |
512 # Ignore solution@ | 512 if not s.get('safesync_url', None): |
513 rev = revision | 513 continue |
514 if '@' in revision: | 514 handle = urllib.urlopen(s['safesync_url']) |
515 rev = revision.split('@', 1)[1] | 515 rev = handle.read().strip() |
516 revision_overrides[solutions[0]] = rev | 516 handle.close() |
517 | 517 if len(rev): |
518 if len(self._options.revisions) > 1: | 518 self._options.revisions.append('%s@%s' % (s['name'], rev)) |
519 # Enforce solution@rev format for following params. | 519 if not self._options.revisions: |
520 for revision in self._options.revisions[1:]: | 520 return revision_overrides |
521 if not '@' in revision: | 521 # --revision will take over safesync_url. |
522 raise gclient_utils.Error( | 522 solutions_names = [s['name'] for s in solutions] |
523 'Specify the full dependency when specifying a revision number ' | 523 index = 0 |
524 'for non-primary solution.') | 524 for revision in self._options.revisions: |
525 sol, rev = revision.split("@", 1) | 525 if not '@' in revision: |
526 # Disallow conflicting revs | 526 # Support for --revision 123 |
527 if revision_overrides.get(sol, rev) != rev: | 527 revision = '%s@%s' % (solutions_names[index], revision) |
528 raise gclient_utils.Error( | 528 sol, rev = revision.split("@", 1) |
529 'Conflicting revision numbers specified for %s: %s and %s.' % | 529 if not sol in solutions_names: |
530 (sol, revision_overrides[sol], rev)) | 530 #raise gclient_utils.Error('%s is not a valid solution.' % sol) |
531 if not sol in solutions: | 531 print >> sys.stderr, ('Please fix your script, having invalid ' |
532 raise gclient_utils.Error('%s is not a valid solution.' % sol) | 532 '--revision flags will soon considered an error.') |
| 533 else: |
533 revision_overrides[sol] = rev | 534 revision_overrides[sol] = rev |
| 535 index += 1 |
534 return revision_overrides | 536 return revision_overrides |
535 | 537 |
536 def RunOnDeps(self, command, args): | 538 def RunOnDeps(self, command, args): |
537 """Runs a command on each dependency in a client and its dependencies. | 539 """Runs a command on each dependency in a client and its dependencies. |
538 | 540 |
539 The module's dependencies are specified in its top-level DEPS files. | 541 The module's dependencies are specified in its top-level DEPS files. |
540 | 542 |
541 Args: | 543 Args: |
542 command: The command to use (e.g., 'status' or 'diff') | 544 command: The command to use (e.g., 'status' or 'diff') |
543 args: list of str - extra arguments to add to the command line. | 545 args: list of str - extra arguments to add to the command line. |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 update src directory to r31000 | 937 update src directory to r31000 |
936 """) | 938 """) |
937 def CMDsync(parser, args): | 939 def CMDsync(parser, args): |
938 """Checkout/update all modules.""" | 940 """Checkout/update all modules.""" |
939 parser.add_option("--force", action="store_true", | 941 parser.add_option("--force", action="store_true", |
940 help="force update even for unchanged modules") | 942 help="force update even for unchanged modules") |
941 parser.add_option("--nohooks", action="store_true", | 943 parser.add_option("--nohooks", action="store_true", |
942 help="don't run hooks after the update is complete") | 944 help="don't run hooks after the update is complete") |
943 parser.add_option("-r", "--revision", action="append", | 945 parser.add_option("-r", "--revision", action="append", |
944 dest="revisions", metavar="REV", default=[], | 946 dest="revisions", metavar="REV", default=[], |
945 help="Enforces revision/hash for the primary solution. " | 947 help="Enforces revision/hash for the solutions with the " |
946 "To modify a secondary solution, use it at least once " | 948 "format src@rev. The src@ part is optional and can be " |
947 "for the primary solution and then use the format " | 949 "skipped. -r can be used multiple times when .gclient " |
948 "solution@rev/hash, e.g. -r src@123") | 950 "has multiple solutions configured and will work even " |
| 951 "if the src@ part is skipped.") |
949 parser.add_option("--head", action="store_true", | 952 parser.add_option("--head", action="store_true", |
950 help="skips any safesync_urls specified in " | 953 help="skips any safesync_urls specified in " |
951 "configured solutions and sync to head instead") | 954 "configured solutions and sync to head instead") |
952 parser.add_option("--delete_unversioned_trees", action="store_true", | 955 parser.add_option("--delete_unversioned_trees", action="store_true", |
953 help="delete any unexpected unversioned trees " | 956 help="delete any unexpected unversioned trees " |
954 "that are in the checkout") | 957 "that are in the checkout") |
955 parser.add_option("--reset", action="store_true", | 958 parser.add_option("--reset", action="store_true", |
956 help="resets any local changes before updating (git only)") | 959 help="resets any local changes before updating (git only)") |
957 parser.add_option("--deps", dest="deps_os", metavar="OS_LIST", | 960 parser.add_option("--deps", dest="deps_os", metavar="OS_LIST", |
958 help="override deps for the specified (comma-separated) " | 961 help="override deps for the specified (comma-separated) " |
959 "platform(s); 'all' will process all deps_os " | 962 "platform(s); 'all' will process all deps_os " |
960 "references") | 963 "references") |
961 parser.add_option("--manually_grab_svn_rev", action="store_true", | 964 parser.add_option("--manually_grab_svn_rev", action="store_true", |
962 help="Skip svn up whenever possible by requesting " | 965 help="Skip svn up whenever possible by requesting " |
963 "actual HEAD revision from the repository") | 966 "actual HEAD revision from the repository") |
964 (options, args) = parser.parse_args(args) | 967 (options, args) = parser.parse_args(args) |
965 client = GClient.LoadCurrentConfig(options) | 968 client = GClient.LoadCurrentConfig(options) |
966 | 969 |
967 if not client: | 970 if not client: |
968 raise gclient_utils.Error("client not configured; see 'gclient config'") | 971 raise gclient_utils.Error("client not configured; see 'gclient config'") |
969 | 972 |
970 if not options.head: | 973 if options.revisions and options.head: |
971 solutions = client.GetVar('solutions') | 974 # TODO(maruel): Make it a parser.error if it doesn't break any builder. |
972 if solutions: | 975 print("Warning: you cannot use both --head and --revision") |
973 first = True | |
974 for s in solutions: | |
975 if s.get('safesync_url', None): | |
976 # rip through revisions and make sure we're not over-riding | |
977 # something that was explicitly passed | |
978 has_key = False | |
979 r_first = True | |
980 for r in options.revisions: | |
981 if (first and r_first) or r.split('@', 1)[0] == s['name']: | |
982 has_key = True | |
983 break | |
984 r_first = False | |
985 | |
986 if not has_key: | |
987 handle = urllib.urlopen(s['safesync_url']) | |
988 rev = handle.read().strip() | |
989 handle.close() | |
990 if len(rev): | |
991 options.revisions.append(s['name']+'@'+rev) | |
992 first = False | |
993 | 976 |
994 if options.verbose: | 977 if options.verbose: |
995 # Print out the .gclient file. This is longer than if we just printed the | 978 # Print out the .gclient file. This is longer than if we just printed the |
996 # client dict, but more legible, and it might contain helpful comments. | 979 # client dict, but more legible, and it might contain helpful comments. |
997 print(client.ConfigContent()) | 980 print(client.ConfigContent()) |
998 return client.RunOnDeps('update', args) | 981 return client.RunOnDeps('update', args) |
999 | 982 |
1000 | 983 |
1001 def CMDupdate(parser, args): | 984 def CMDupdate(parser, args): |
1002 """Alias for the sync command. Deprecated.""" | 985 """Alias for the sync command. Deprecated.""" |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 def Parse(args): | 1101 def Parse(args): |
1119 (options, args) = old_parser(args) | 1102 (options, args) = old_parser(args) |
1120 if options.verbose == 2: | 1103 if options.verbose == 2: |
1121 logging.basicConfig(level=logging.INFO) | 1104 logging.basicConfig(level=logging.INFO) |
1122 elif options.verbose > 2: | 1105 elif options.verbose > 2: |
1123 logging.basicConfig(level=logging.DEBUG) | 1106 logging.basicConfig(level=logging.DEBUG) |
1124 options.entries_filename = options.config_filename + "_entries" | 1107 options.entries_filename = options.config_filename + "_entries" |
1125 if not hasattr(options, 'revisions'): | 1108 if not hasattr(options, 'revisions'): |
1126 # GClient.RunOnDeps expects it even if not applicable. | 1109 # GClient.RunOnDeps expects it even if not applicable. |
1127 options.revisions = [] | 1110 options.revisions = [] |
| 1111 if not hasattr(options, 'head'): |
| 1112 options.head = None |
1128 return (options, args) | 1113 return (options, args) |
1129 parser.parse_args = Parse | 1114 parser.parse_args = Parse |
1130 # We don't want wordwrapping in epilog (usually examples) | 1115 # We don't want wordwrapping in epilog (usually examples) |
1131 parser.format_epilog = lambda _: parser.epilog or '' | 1116 parser.format_epilog = lambda _: parser.epilog or '' |
1132 if argv: | 1117 if argv: |
1133 command = Command(argv[0]) | 1118 command = Command(argv[0]) |
1134 if command: | 1119 if command: |
1135 # "fix" the usage and the description now that we know the subcommand. | 1120 # "fix" the usage and the description now that we know the subcommand. |
1136 GenUsage(parser, argv[0]) | 1121 GenUsage(parser, argv[0]) |
1137 return command(parser, argv[1:]) | 1122 return command(parser, argv[1:]) |
1138 # Not a known command. Default to help. | 1123 # Not a known command. Default to help. |
1139 GenUsage(parser, 'help') | 1124 GenUsage(parser, 'help') |
1140 return CMDhelp(parser, argv) | 1125 return CMDhelp(parser, argv) |
1141 | 1126 |
1142 | 1127 |
1143 if "__main__" == __name__: | 1128 if "__main__" == __name__: |
1144 try: | 1129 try: |
1145 sys.exit(Main(sys.argv[1:])) | 1130 sys.exit(Main(sys.argv[1:])) |
1146 except gclient_utils.Error, e: | 1131 except gclient_utils.Error, e: |
1147 print >> sys.stderr, "Error: %s" % str(e) | 1132 print >> sys.stderr, "Error: %s" % str(e) |
1148 sys.exit(1) | 1133 sys.exit(1) |
1149 | 1134 |
1150 # vim: ts=2:sw=2:tw=80:et: | 1135 # vim: ts=2:sw=2:tw=80:et: |
OLD | NEW |