Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(695)

Side by Side Diff: gclient.py

Issue 9560010: Rework gclient 'recurse' command to use a WorkQueue. (Closed) Base URL: http://src.chromium.org/svn/trunk/tools/depot_tools/
Patch Set: Style nit. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/gclient_smoketest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 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 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 # pylint: disable=W0221 518 # pylint: disable=W0221
519 def run(self, revision_overrides, command, args, work_queue, options): 519 def run(self, revision_overrides, command, args, work_queue, options):
520 """Runs |command| then parse the DEPS file.""" 520 """Runs |command| then parse the DEPS file."""
521 logging.info('Dependency(%s).run()' % self.name) 521 logging.info('Dependency(%s).run()' % self.name)
522 assert self._file_list == [] 522 assert self._file_list == []
523 if not self.should_process: 523 if not self.should_process:
524 return 524 return
525 # When running runhooks, there's no need to consult the SCM. 525 # When running runhooks, there's no need to consult the SCM.
526 # All known hooks are expected to run unconditionally regardless of working 526 # All known hooks are expected to run unconditionally regardless of working
527 # copy state, so skip the SCM status check. 527 # copy state, so skip the SCM status check.
528 run_scm = command not in ('runhooks', None) 528 run_scm = command not in ('runhooks', 'recurse', None)
529 parsed_url = self.LateOverride(self.url) 529 parsed_url = self.LateOverride(self.url)
530 file_list = [] 530 file_list = []
531 if run_scm and parsed_url: 531 if run_scm and parsed_url:
532 if isinstance(parsed_url, self.FileImpl): 532 if isinstance(parsed_url, self.FileImpl):
533 # Special support for single-file checkout. 533 # Special support for single-file checkout.
534 if not command in (None, 'cleanup', 'diff', 'pack', 'status'): 534 if not command in (None, 'cleanup', 'diff', 'pack', 'status'):
535 # Sadly, pylint doesn't realize that parsed_url is of FileImpl. 535 # Sadly, pylint doesn't realize that parsed_url is of FileImpl.
536 # pylint: disable=E1103 536 # pylint: disable=E1103
537 options.revision = parsed_url.GetRevision() 537 options.revision = parsed_url.GetRevision()
538 scm = gclient_scm.SVNWrapper(parsed_url.GetPath(), 538 scm = gclient_scm.SVNWrapper(parsed_url.GetPath(),
(...skipping 19 matching lines...) Expand all
558 for i in range(len(file_list)): 558 for i in range(len(file_list)):
559 # It depends on the command being executed (like runhooks vs sync). 559 # It depends on the command being executed (like runhooks vs sync).
560 if not os.path.isabs(file_list[i]): 560 if not os.path.isabs(file_list[i]):
561 continue 561 continue
562 prefix = os.path.commonprefix( 562 prefix = os.path.commonprefix(
563 [self.root.root_dir.lower(), file_list[i].lower()]) 563 [self.root.root_dir.lower(), file_list[i].lower()])
564 file_list[i] = file_list[i][len(prefix):] 564 file_list[i] = file_list[i][len(prefix):]
565 # Strip any leading path separators. 565 # Strip any leading path separators.
566 while file_list[i].startswith(('\\', '/')): 566 while file_list[i].startswith(('\\', '/')):
567 file_list[i] = file_list[i][1:] 567 file_list[i] = file_list[i][1:]
568 elif command is 'recurse':
569 if not isinstance(parsed_url, self.FileImpl):
570 # Skip file only checkout.
571 scm = gclient_scm.GetScmName(parsed_url)
572 if not options.scm or scm in options.scm:
573 cwd = os.path.normpath(os.path.join(self.root.root_dir, self.name))
574 # Pass in the SCM type as an env variable
575 env = os.environ.copy()
576 if scm:
577 env['GCLIENT_SCM'] = scm
578 if parsed_url:
579 env['GCLIENT_URL'] = parsed_url
580 if os.path.isdir(cwd):
581 gclient_utils.CheckCallAndFilter(
582 args, cwd=cwd, env=env, print_stdout=True)
583 else:
584 print >> sys.stderr, 'Skipped missing %s' % cwd
568 585
569 # Always parse the DEPS file. 586 # Always parse the DEPS file.
570 self.ParseDepsFile() 587 self.ParseDepsFile()
571 588
572 self._run_is_done(file_list, parsed_url) 589 self._run_is_done(file_list, parsed_url)
573 590
574 if self.recursion_limit: 591 if self.recursion_limit:
575 # Parse the dependencies of this dependency. 592 # Parse the dependencies of this dependency.
576 for s in self.dependencies: 593 for s in self.dependencies:
577 work_queue.enqueue(s) 594 work_queue.enqueue(s)
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
958 975
959 def RunOnDeps(self, command, args): 976 def RunOnDeps(self, command, args):
960 """Runs a command on each dependency in a client and its dependencies. 977 """Runs a command on each dependency in a client and its dependencies.
961 978
962 Args: 979 Args:
963 command: The command to use (e.g., 'status' or 'diff') 980 command: The command to use (e.g., 'status' or 'diff')
964 args: list of str - extra arguments to add to the command line. 981 args: list of str - extra arguments to add to the command line.
965 """ 982 """
966 if not self.dependencies: 983 if not self.dependencies:
967 raise gclient_utils.Error('No solution specified') 984 raise gclient_utils.Error('No solution specified')
968 revision_overrides = self._EnforceRevisions() 985 revision_overrides = {}
986 # It's unnecessary to check for revision overrides for 'recurse'.
987 # Save a few seconds by not calling _EnforceRevisions() in that case.
988 if command is not 'recurse':
989 revision_overrides = self._EnforceRevisions()
969 pm = None 990 pm = None
970 # Disable progress for non-tty stdout. 991 # Disable progress for non-tty stdout.
971 if (command in ('update', 'revert') and sys.stdout.isatty() and not 992 if (sys.stdout.isatty() and not self._options.verbose):
972 self._options.verbose): 993 if command in ('update', 'revert'):
973 pm = Progress('Syncing projects', 1) 994 pm = Progress('Syncing projects', 1)
995 elif command is 'recurse':
996 pm = Progress(' '.join(args), 1)
974 work_queue = gclient_utils.ExecutionQueue(self._options.jobs, pm) 997 work_queue = gclient_utils.ExecutionQueue(self._options.jobs, pm)
975 for s in self.dependencies: 998 for s in self.dependencies:
976 work_queue.enqueue(s) 999 work_queue.enqueue(s)
977 work_queue.flush(revision_overrides, command, args, options=self._options) 1000 work_queue.flush(revision_overrides, command, args, options=self._options)
978 1001
979 # Once all the dependencies have been processed, it's now safe to run the 1002 # Once all the dependencies have been processed, it's now safe to run the
980 # hooks. 1003 # hooks.
981 if not self._options.nohooks: 1004 if not self._options.nohooks:
982 self.RunHooksRecursively(self._options) 1005 self.RunHooksRecursively(self._options)
983 1006
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 @attr('usage', '[command] [args ...]') 1147 @attr('usage', '[command] [args ...]')
1125 def CMDrecurse(parser, args): 1148 def CMDrecurse(parser, args):
1126 """Operates on all the entries. 1149 """Operates on all the entries.
1127 1150
1128 Runs a shell command on all entries. 1151 Runs a shell command on all entries.
1129 """ 1152 """
1130 # Stop parsing at the first non-arg so that these go through to the command 1153 # Stop parsing at the first non-arg so that these go through to the command
1131 parser.disable_interspersed_args() 1154 parser.disable_interspersed_args()
1132 parser.add_option('-s', '--scm', action='append', default=[], 1155 parser.add_option('-s', '--scm', action='append', default=[],
1133 help='choose scm types to operate upon') 1156 help='choose scm types to operate upon')
1134 parser.remove_option('--jobs')
1135 options, args = parser.parse_args(args) 1157 options, args = parser.parse_args(args)
1136 if not args: 1158 if not args:
1137 print >> sys.stderr, 'Need to supply a command!' 1159 print >> sys.stderr, 'Need to supply a command!'
1138 return 1 1160 return 1
1139 root_and_entries = gclient_utils.GetGClientRootAndEntries() 1161 root_and_entries = gclient_utils.GetGClientRootAndEntries()
1140 if not root_and_entries: 1162 if not root_and_entries:
1141 print >> sys.stderr, ( 1163 print >> sys.stderr, (
1142 'You need to run gclient sync at least once to use \'recurse\'.\n' 1164 'You need to run gclient sync at least once to use \'recurse\'.\n'
1143 'This is because .gclient_entries needs to exist and be up to date.') 1165 'This is because .gclient_entries needs to exist and be up to date.')
1144 return 1 1166 return 1
1145 root, entries = root_and_entries 1167
1168 # Normalize options.scm to a set()
1146 scm_set = set() 1169 scm_set = set()
1147 for scm in options.scm: 1170 for scm in options.scm:
1148 scm_set.update(scm.split(',')) 1171 scm_set.update(scm.split(','))
1172 options.scm = scm_set
1149 1173
1150 # Pass in the SCM type as an env variable 1174 options.nohooks = True
1151 env = os.environ.copy() 1175 client = GClient.LoadCurrentConfig(options)
1152 1176 return client.RunOnDeps('recurse', args)
1153 for path, url in entries.iteritems():
1154 scm = gclient_scm.GetScmName(url)
1155 if scm_set and scm not in scm_set:
1156 continue
1157 cwd = os.path.normpath(os.path.join(root, path))
1158 if scm:
1159 env['GCLIENT_SCM'] = scm
1160 if url:
1161 env['GCLIENT_URL'] = url
1162 if os.path.isdir(cwd):
1163 subprocess2.call(args, cwd=cwd, env=env)
1164 else:
1165 print >> sys.stderr, 'Skipped missing %s' % cwd
1166 return 0
1167 1177
1168 1178
1169 @attr('usage', '[args ...]') 1179 @attr('usage', '[args ...]')
1170 def CMDfetch(parser, args): 1180 def CMDfetch(parser, args):
1171 """Fetches upstream commits for all modules. 1181 """Fetches upstream commits for all modules.
1172 1182
1173 Completely git-specific. Simply runs 'git fetch [args ...]' for each module. 1183 Completely git-specific. Simply runs 'git fetch [args ...]' for each module.
1174 """ 1184 """
1175 (_, args) = parser.parse_args(args) 1185 (options, args) = parser.parse_args(args)
1176 args = ['-s', 'git', 'git', 'fetch'] + args 1186 args = ['-j%d' % options.jobs, '-s', 'git', 'git', 'fetch'] + args
1177 return CMDrecurse(parser, args) 1187 return CMDrecurse(parser, args)
1178 1188
1179 1189
1180 @attr('usage', '[url] [safesync url]') 1190 @attr('usage', '[url] [safesync url]')
1181 def CMDconfig(parser, args): 1191 def CMDconfig(parser, args):
1182 """Create a .gclient file in the current directory. 1192 """Create a .gclient file in the current directory.
1183 1193
1184 This specifies the configuration for further commands. After update/sync, 1194 This specifies the configuration for further commands. After update/sync,
1185 top-level DEPS files in each module are read to determine dependent 1195 top-level DEPS files in each module are read to determine dependent
1186 modules to operate on as well. If optional [url] parameter is 1196 modules to operate on as well. If optional [url] parameter is
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
1549 except (gclient_utils.Error, subprocess2.CalledProcessError), e: 1559 except (gclient_utils.Error, subprocess2.CalledProcessError), e:
1550 print >> sys.stderr, 'Error: %s' % str(e) 1560 print >> sys.stderr, 'Error: %s' % str(e)
1551 return 1 1561 return 1
1552 1562
1553 1563
1554 if '__main__' == __name__: 1564 if '__main__' == __name__:
1555 fix_encoding.fix_encoding() 1565 fix_encoding.fix_encoding()
1556 sys.exit(Main(sys.argv[1:])) 1566 sys.exit(Main(sys.argv[1:]))
1557 1567
1558 # vim: ts=2:sw=2:tw=80:et: 1568 # vim: ts=2:sw=2:tw=80:et:
OLDNEW
« no previous file with comments | « no previous file | tests/gclient_smoketest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698