| 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 """Meta checkout manager supporting both Subversion and GIT. | 6 """Meta checkout manager supporting both Subversion and GIT. |
| 7 | 7 |
| 8 Files | 8 Files |
| 9 .gclient : Current client configuration, written by 'config' command. | 9 .gclient : Current client configuration, written by 'config' command. |
| 10 Format is a Python script defining 'solutions', a list whose | 10 Format is a Python script defining 'solutions', a list whose |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 it will be removed from the list and the list will be extended | 42 it will be removed from the list and the list will be extended |
| 43 by the list of matching files. | 43 by the list of matching files. |
| 44 | 44 |
| 45 Example: | 45 Example: |
| 46 hooks = [ | 46 hooks = [ |
| 47 { "pattern": "\\.(gif|jpe?g|pr0n|png)$", | 47 { "pattern": "\\.(gif|jpe?g|pr0n|png)$", |
| 48 "action": ["python", "image_indexer.py", "--all"]}, | 48 "action": ["python", "image_indexer.py", "--all"]}, |
| 49 ] | 49 ] |
| 50 """ | 50 """ |
| 51 | 51 |
| 52 __version__ = "0.5.2" | 52 __version__ = "0.6" |
| 53 | 53 |
| 54 import copy |
| 54 import logging | 55 import logging |
| 55 import optparse | 56 import optparse |
| 56 import os | 57 import os |
| 57 import posixpath | 58 import posixpath |
| 58 import pprint | 59 import pprint |
| 59 import re | 60 import re |
| 60 import subprocess | 61 import subprocess |
| 61 import sys | 62 import sys |
| 62 import urlparse | 63 import urlparse |
| 63 import urllib | 64 import urllib |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 # Special support for single-file checkout. | 349 # Special support for single-file checkout. |
| 349 if not command in (None, 'cleanup', 'diff', 'pack', 'status'): | 350 if not command in (None, 'cleanup', 'diff', 'pack', 'status'): |
| 350 options.revision = self.parsed_url.GetRevision() | 351 options.revision = self.parsed_url.GetRevision() |
| 351 scm = gclient_scm.SVNWrapper(self.parsed_url.GetPath(), | 352 scm = gclient_scm.SVNWrapper(self.parsed_url.GetPath(), |
| 352 self.root_dir(), | 353 self.root_dir(), |
| 353 self.name) | 354 self.name) |
| 354 scm.RunCommand('updatesingle', options, | 355 scm.RunCommand('updatesingle', options, |
| 355 args + [self.parsed_url.GetFilename()], | 356 args + [self.parsed_url.GetFilename()], |
| 356 self._file_list) | 357 self._file_list) |
| 357 else: | 358 else: |
| 359 # Create a shallow copy to mutate revision. |
| 360 options = copy.copy(options) |
| 358 options.revision = revision_overrides.get(self.name) | 361 options.revision = revision_overrides.get(self.name) |
| 359 scm = gclient_scm.CreateSCM(self.parsed_url, self.root_dir(), self.name) | 362 scm = gclient_scm.CreateSCM(self.parsed_url, self.root_dir(), self.name) |
| 360 scm.RunCommand(command, options, args, self._file_list) | 363 scm.RunCommand(command, options, args, self._file_list) |
| 361 self._file_list = [os.path.join(self.name, f.strip()) | 364 self._file_list = [os.path.join(self.name, f.strip()) |
| 362 for f in self._file_list] | 365 for f in self._file_list] |
| 363 options.revision = None | |
| 364 self.processed = True | 366 self.processed = True |
| 365 if self.recursion_limit() > 0: | 367 if self.recursion_limit() > 0: |
| 366 # Then we can parse the DEPS file. | 368 # Then we can parse the DEPS file. |
| 367 self.ParseDepsFile() | 369 self.ParseDepsFile() |
| 368 # Adjust the implicit dependency requirement; e.g. if a DEPS file contains | 370 # Adjust the implicit dependency requirement; e.g. if a DEPS file contains |
| 369 # both src/foo and src/foo/bar, src/foo/bar is implicitly dependent of | 371 # both src/foo and src/foo/bar, src/foo/bar is implicitly dependent of |
| 370 # src/foo. Yes, it's O(n^2)... It's important to do that before | 372 # src/foo. Yes, it's O(n^2)... It's important to do that before |
| 371 # enqueueing them. | 373 # enqueueing them. |
| 372 for s in self.dependencies: | 374 for s in self.dependencies: |
| 373 for s2 in self.dependencies: | 375 for s2 in self.dependencies: |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 Args: | 705 Args: |
| 704 command: The command to use (e.g., 'status' or 'diff') | 706 command: The command to use (e.g., 'status' or 'diff') |
| 705 args: list of str - extra arguments to add to the command line. | 707 args: list of str - extra arguments to add to the command line. |
| 706 """ | 708 """ |
| 707 if not self.dependencies: | 709 if not self.dependencies: |
| 708 raise gclient_utils.Error('No solution specified') | 710 raise gclient_utils.Error('No solution specified') |
| 709 revision_overrides = self._EnforceRevisions() | 711 revision_overrides = self._EnforceRevisions() |
| 710 pm = None | 712 pm = None |
| 711 if command == 'update' and not self._options.verbose: | 713 if command == 'update' and not self._options.verbose: |
| 712 pm = Progress('Syncing projects', 1) | 714 pm = Progress('Syncing projects', 1) |
| 713 work_queue = gclient_utils.ExecutionQueue(pm) | 715 work_queue = gclient_utils.ExecutionQueue(self._options.jobs, pm) |
| 714 for s in self.dependencies: | 716 for s in self.dependencies: |
| 715 work_queue.enqueue(s) | 717 work_queue.enqueue(s) |
| 716 work_queue.flush(self._options, revision_overrides, command, args, | 718 work_queue.flush(self._options, revision_overrides, command, args, |
| 717 work_queue) | 719 work_queue) |
| 718 | 720 |
| 719 # Once all the dependencies have been processed, it's now safe to run the | 721 # Once all the dependencies have been processed, it's now safe to run the |
| 720 # hooks. | 722 # hooks. |
| 721 if not self._options.nohooks: | 723 if not self._options.nohooks: |
| 722 self.RunHooksRecursively(self._options) | 724 self.RunHooksRecursively(self._options) |
| 723 | 725 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 748 entry_fixed, self.root_dir())) | 750 entry_fixed, self.root_dir())) |
| 749 gclient_utils.RemoveDirectory(e_dir) | 751 gclient_utils.RemoveDirectory(e_dir) |
| 750 # record the current list of entries for next time | 752 # record the current list of entries for next time |
| 751 self._SaveEntries() | 753 self._SaveEntries() |
| 752 return 0 | 754 return 0 |
| 753 | 755 |
| 754 def PrintRevInfo(self): | 756 def PrintRevInfo(self): |
| 755 if not self.dependencies: | 757 if not self.dependencies: |
| 756 raise gclient_utils.Error('No solution specified') | 758 raise gclient_utils.Error('No solution specified') |
| 757 # Load all the settings. | 759 # Load all the settings. |
| 758 work_queue = gclient_utils.ExecutionQueue(None) | 760 work_queue = gclient_utils.ExecutionQueue(self._options.jobs, None) |
| 759 for s in self.dependencies: | 761 for s in self.dependencies: |
| 760 work_queue.enqueue(s) | 762 work_queue.enqueue(s) |
| 761 work_queue.flush(self._options, {}, None, [], work_queue) | 763 work_queue.flush(self._options, {}, None, [], work_queue) |
| 762 | 764 |
| 763 def GetURLAndRev(dep): | 765 def GetURLAndRev(dep): |
| 764 """Returns the revision-qualified SCM url for a Dependency.""" | 766 """Returns the revision-qualified SCM url for a Dependency.""" |
| 765 if dep.parsed_url is None: | 767 if dep.parsed_url is None: |
| 766 return None | 768 return None |
| 767 if isinstance(dep.parsed_url, self.FileImpl): | 769 if isinstance(dep.parsed_url, self.FileImpl): |
| 768 original_url = dep.parsed_url.file_location | 770 original_url = dep.parsed_url.file_location |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1161 | 1163 |
| 1162 def Main(argv): | 1164 def Main(argv): |
| 1163 """Doesn't parse the arguments here, just find the right subcommand to | 1165 """Doesn't parse the arguments here, just find the right subcommand to |
| 1164 execute.""" | 1166 execute.""" |
| 1165 try: | 1167 try: |
| 1166 # Do it late so all commands are listed. | 1168 # Do it late so all commands are listed. |
| 1167 CMDhelp.usage = ('\n\nCommands are:\n' + '\n'.join([ | 1169 CMDhelp.usage = ('\n\nCommands are:\n' + '\n'.join([ |
| 1168 ' %-10s %s' % (fn[3:], Command(fn[3:]).__doc__.split('\n')[0].strip()) | 1170 ' %-10s %s' % (fn[3:], Command(fn[3:]).__doc__.split('\n')[0].strip()) |
| 1169 for fn in dir(sys.modules[__name__]) if fn.startswith('CMD')])) | 1171 for fn in dir(sys.modules[__name__]) if fn.startswith('CMD')])) |
| 1170 parser = optparse.OptionParser(version='%prog ' + __version__) | 1172 parser = optparse.OptionParser(version='%prog ' + __version__) |
| 1173 parser.add_option('-j', '--jobs', default=1, type='int', |
| 1174 help='Specify how many SCM commands can run in parallel') |
| 1171 parser.add_option('-v', '--verbose', action='count', default=0, | 1175 parser.add_option('-v', '--verbose', action='count', default=0, |
| 1172 help='Produces additional output for diagnostics. Can be ' | 1176 help='Produces additional output for diagnostics. Can be ' |
| 1173 'used up to three times for more logging info.') | 1177 'used up to three times for more logging info.') |
| 1174 parser.add_option('--gclientfile', dest='config_filename', | 1178 parser.add_option('--gclientfile', dest='config_filename', |
| 1175 default=os.environ.get('GCLIENT_FILE', '.gclient'), | 1179 default=os.environ.get('GCLIENT_FILE', '.gclient'), |
| 1176 help='Specify an alternate %default file') | 1180 help='Specify an alternate %default file') |
| 1177 # Integrate standard options processing. | 1181 # Integrate standard options processing. |
| 1178 old_parser = parser.parse_args | 1182 old_parser = parser.parse_args |
| 1179 def Parse(args): | 1183 def Parse(args): |
| 1180 (options, args) = old_parser(args) | 1184 (options, args) = old_parser(args) |
| 1181 level = None | 1185 level = None |
| 1182 if options.verbose == 2: | 1186 if options.verbose == 2: |
| 1183 level = logging.INFO | 1187 level = logging.INFO |
| 1184 elif options.verbose > 2: | 1188 elif options.verbose > 2: |
| 1185 level = logging.DEBUG | 1189 level = logging.DEBUG |
| 1186 logging.basicConfig(level=level, | 1190 logging.basicConfig(level=level, |
| 1187 format='%(module)s(%(lineno)d) %(funcName)s:%(message)s') | 1191 format='%(module)s(%(lineno)d) %(funcName)s:%(message)s') |
| 1188 options.entries_filename = options.config_filename + '_entries' | 1192 options.entries_filename = options.config_filename + '_entries' |
| 1193 if options.jobs < 1: |
| 1194 parser.error('--jobs must be 1 or higher') |
| 1189 | 1195 |
| 1190 # These hacks need to die. | 1196 # These hacks need to die. |
| 1191 if not hasattr(options, 'revisions'): | 1197 if not hasattr(options, 'revisions'): |
| 1192 # GClient.RunOnDeps expects it even if not applicable. | 1198 # GClient.RunOnDeps expects it even if not applicable. |
| 1193 options.revisions = [] | 1199 options.revisions = [] |
| 1194 if not hasattr(options, 'head'): | 1200 if not hasattr(options, 'head'): |
| 1195 options.head = None | 1201 options.head = None |
| 1196 if not hasattr(options, 'nohooks'): | 1202 if not hasattr(options, 'nohooks'): |
| 1197 options.nohooks = True | 1203 options.nohooks = True |
| 1198 if not hasattr(options, 'deps_os'): | 1204 if not hasattr(options, 'deps_os'): |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1216 return CMDhelp(parser, argv) | 1222 return CMDhelp(parser, argv) |
| 1217 except gclient_utils.Error, e: | 1223 except gclient_utils.Error, e: |
| 1218 print >> sys.stderr, 'Error: %s' % str(e) | 1224 print >> sys.stderr, 'Error: %s' % str(e) |
| 1219 return 1 | 1225 return 1 |
| 1220 | 1226 |
| 1221 | 1227 |
| 1222 if '__main__' == __name__: | 1228 if '__main__' == __name__: |
| 1223 sys.exit(Main(sys.argv[1:])) | 1229 sys.exit(Main(sys.argv[1:])) |
| 1224 | 1230 |
| 1225 # vim: ts=2:sw=2:tw=80:et: | 1231 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |