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

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: 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 | no next file » | 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)
davidbarr 2012/03/02 03:21:55 It felt a bit too tricky to implicitly rely on thi
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.CheckCallAndFilterAndHeader(args, cwd=cwd, env=env)
582 else:
583 print >> sys.stderr, 'Skipped missing %s' % cwd
568 584
569 # Always parse the DEPS file. 585 # Always parse the DEPS file.
570 self.ParseDepsFile() 586 self.ParseDepsFile()
571 587
572 self._run_is_done(file_list, parsed_url) 588 self._run_is_done(file_list, parsed_url)
573 589
574 if self.recursion_limit: 590 if self.recursion_limit:
575 # Parse the dependencies of this dependency. 591 # Parse the dependencies of this dependency.
576 for s in self.dependencies: 592 for s in self.dependencies:
577 work_queue.enqueue(s) 593 work_queue.enqueue(s)
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
958 974
959 def RunOnDeps(self, command, args): 975 def RunOnDeps(self, command, args):
960 """Runs a command on each dependency in a client and its dependencies. 976 """Runs a command on each dependency in a client and its dependencies.
961 977
962 Args: 978 Args:
963 command: The command to use (e.g., 'status' or 'diff') 979 command: The command to use (e.g., 'status' or 'diff')
964 args: list of str - extra arguments to add to the command line. 980 args: list of str - extra arguments to add to the command line.
965 """ 981 """
966 if not self.dependencies: 982 if not self.dependencies:
967 raise gclient_utils.Error('No solution specified') 983 raise gclient_utils.Error('No solution specified')
968 revision_overrides = self._EnforceRevisions() 984 revision_overrides = {}
985 if command is not 'recurse':
986 revision_overrides = self._EnforceRevisions()
davidbarr 2012/03/02 03:21:55 Is _EnforceRevisions() necessary in the 'recurse'
M-A Ruel 2012/03/02 14:25:30 Just add a comment that it's not strictly necessar
969 pm = None 987 pm = None
970 # Disable progress for non-tty stdout. 988 # Disable progress for non-tty stdout.
971 if (command in ('update', 'revert') and sys.stdout.isatty() and not 989 if (sys.stdout.isatty() and not self._options.verbose):
972 self._options.verbose): 990 if command in ('update', 'revert'):
973 pm = Progress('Syncing projects', 1) 991 pm = Progress('Syncing projects', 1)
992 elif command is 'recurse':
993 pm = Progress(' '.join(args), 1)
974 work_queue = gclient_utils.ExecutionQueue(self._options.jobs, pm) 994 work_queue = gclient_utils.ExecutionQueue(self._options.jobs, pm)
975 for s in self.dependencies: 995 for s in self.dependencies:
976 work_queue.enqueue(s) 996 work_queue.enqueue(s)
977 work_queue.flush(revision_overrides, command, args, options=self._options) 997 work_queue.flush(revision_overrides, command, args, options=self._options)
978 998
979 # Once all the dependencies have been processed, it's now safe to run the 999 # Once all the dependencies have been processed, it's now safe to run the
980 # hooks. 1000 # hooks.
981 if not self._options.nohooks: 1001 if not self._options.nohooks:
982 self.RunHooksRecursively(self._options) 1002 self.RunHooksRecursively(self._options)
983 1003
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 @attr('usage', '[command] [args ...]') 1144 @attr('usage', '[command] [args ...]')
1125 def CMDrecurse(parser, args): 1145 def CMDrecurse(parser, args):
1126 """Operates on all the entries. 1146 """Operates on all the entries.
1127 1147
1128 Runs a shell command on all entries. 1148 Runs a shell command on all entries.
1129 """ 1149 """
1130 # Stop parsing at the first non-arg so that these go through to the command 1150 # Stop parsing at the first non-arg so that these go through to the command
1131 parser.disable_interspersed_args() 1151 parser.disable_interspersed_args()
1132 parser.add_option('-s', '--scm', action='append', default=[], 1152 parser.add_option('-s', '--scm', action='append', default=[],
1133 help='choose scm types to operate upon') 1153 help='choose scm types to operate upon')
1134 parser.remove_option('--jobs')
1135 options, args = parser.parse_args(args) 1154 options, args = parser.parse_args(args)
1136 if not args: 1155 if not args:
1137 print >> sys.stderr, 'Need to supply a command!' 1156 print >> sys.stderr, 'Need to supply a command!'
1138 return 1 1157 return 1
1139 root_and_entries = gclient_utils.GetGClientRootAndEntries() 1158 root_and_entries = gclient_utils.GetGClientRootAndEntries()
1140 if not root_and_entries: 1159 if not root_and_entries:
1141 print >> sys.stderr, ( 1160 print >> sys.stderr, (
1142 'You need to run gclient sync at least once to use \'recurse\'.\n' 1161 '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.') 1162 'This is because .gclient_entries needs to exist and be up to date.')
1144 return 1 1163 return 1
1145 root, entries = root_and_entries 1164
1165 # Normalize options.scm to a set()
1146 scm_set = set() 1166 scm_set = set()
1147 for scm in options.scm: 1167 for scm in options.scm:
1148 scm_set.update(scm.split(',')) 1168 scm_set.update(scm.split(','))
1169 options.scm = scm_set
1149 1170
1150 # Pass in the SCM type as an env variable 1171 options.nohooks = True
1151 env = os.environ.copy() 1172 client = GClient.LoadCurrentConfig(options)
1152 1173 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 1174
1168 1175
1169 @attr('usage', '[args ...]') 1176 @attr('usage', '[args ...]')
1170 def CMDfetch(parser, args): 1177 def CMDfetch(parser, args):
1171 """Fetches upstream commits for all modules. 1178 """Fetches upstream commits for all modules.
1172 1179
1173 Completely git-specific. Simply runs 'git fetch [args ...]' for each module. 1180 Completely git-specific. Simply runs 'git fetch [args ...]' for each module.
1174 """ 1181 """
1175 (_, args) = parser.parse_args(args) 1182 (options, args) = parser.parse_args(args)
1176 args = ['-s', 'git', 'git', 'fetch'] + args 1183 args = ['-j%d' % options.jobs, '-s', 'git', 'git', 'fetch'] + args
1177 return CMDrecurse(parser, args) 1184 return CMDrecurse(parser, args)
1178 1185
1179 1186
1180 @attr('usage', '[url] [safesync url]') 1187 @attr('usage', '[url] [safesync url]')
1181 def CMDconfig(parser, args): 1188 def CMDconfig(parser, args):
1182 """Create a .gclient file in the current directory. 1189 """Create a .gclient file in the current directory.
1183 1190
1184 This specifies the configuration for further commands. After update/sync, 1191 This specifies the configuration for further commands. After update/sync,
1185 top-level DEPS files in each module are read to determine dependent 1192 top-level DEPS files in each module are read to determine dependent
1186 modules to operate on as well. If optional [url] parameter is 1193 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: 1556 except (gclient_utils.Error, subprocess2.CalledProcessError), e:
1550 print >> sys.stderr, 'Error: %s' % str(e) 1557 print >> sys.stderr, 'Error: %s' % str(e)
1551 return 1 1558 return 1
1552 1559
1553 1560
1554 if '__main__' == __name__: 1561 if '__main__' == __name__:
1555 fix_encoding.fix_encoding() 1562 fix_encoding.fix_encoding()
1556 sys.exit(Main(sys.argv[1:])) 1563 sys.exit(Main(sys.argv[1:]))
1557 1564
1558 # vim: ts=2:sw=2:tw=80:et: 1565 # vim: ts=2:sw=2:tw=80:et:
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698