| OLD | NEW |
| 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 # Files | 7 # Files |
| 8 # .gclient : Current client configuration, written by 'config' command. | 8 # .gclient : Current client configuration, written by 'config' command. |
| 9 # Format is a Python script defining 'solutions', a list whose | 9 # Format is a Python script defining 'solutions', a list whose |
| 10 # entries each are maps binding the strings "name" and "url" | 10 # entries each are maps binding the strings "name" and "url" |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 if not parsed_url[0]: | 437 if not parsed_url[0]: |
| 438 # A relative url. Fetch the real base. | 438 # A relative url. Fetch the real base. |
| 439 path = parsed_url[2] | 439 path = parsed_url[2] |
| 440 if not path.startswith('/'): | 440 if not path.startswith('/'): |
| 441 raise gclient_utils.Error( | 441 raise gclient_utils.Error( |
| 442 'relative DEPS entry \'%s\' must begin with a slash' % url) | 442 'relative DEPS entry \'%s\' must begin with a slash' % url) |
| 443 # Create a scm just to query the full url. | 443 # Create a scm just to query the full url. |
| 444 parent_url = self.parent.parsed_url | 444 parent_url = self.parent.parsed_url |
| 445 if isinstance(parent_url, self.FileImpl): | 445 if isinstance(parent_url, self.FileImpl): |
| 446 parent_url = parent_url.file_location | 446 parent_url = parent_url.file_location |
| 447 scm = gclient_scm.CreateSCM(parent_url, self.root.root_dir, None) | 447 scm = gclient_scm.CreateSCM( |
| 448 parent_url, self.root.root_dir, None, self.outbuf) |
| 448 parsed_url = scm.FullUrlForRelativeUrl(url) | 449 parsed_url = scm.FullUrlForRelativeUrl(url) |
| 449 else: | 450 else: |
| 450 parsed_url = url | 451 parsed_url = url |
| 451 logging.info( | 452 logging.info( |
| 452 'Dependency(%s).LateOverride(%s) -> %s' % | 453 'Dependency(%s).LateOverride(%s) -> %s' % |
| 453 (self.name, url, parsed_url)) | 454 (self.name, url, parsed_url)) |
| 454 return parsed_url | 455 return parsed_url |
| 455 | 456 |
| 456 if isinstance(url, self.FileImpl): | 457 if isinstance(url, self.FileImpl): |
| 457 logging.info( | 458 logging.info( |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 parsed_url = self.LateOverride(self.url) | 651 parsed_url = self.LateOverride(self.url) |
| 651 file_list = [] if not options.nohooks else None | 652 file_list = [] if not options.nohooks else None |
| 652 if run_scm and parsed_url: | 653 if run_scm and parsed_url: |
| 653 if isinstance(parsed_url, self.FileImpl): | 654 if isinstance(parsed_url, self.FileImpl): |
| 654 # Special support for single-file checkout. | 655 # Special support for single-file checkout. |
| 655 if not command in (None, 'cleanup', 'diff', 'pack', 'status'): | 656 if not command in (None, 'cleanup', 'diff', 'pack', 'status'): |
| 656 # Sadly, pylint doesn't realize that parsed_url is of FileImpl. | 657 # Sadly, pylint doesn't realize that parsed_url is of FileImpl. |
| 657 # pylint: disable=E1103 | 658 # pylint: disable=E1103 |
| 658 options.revision = parsed_url.GetRevision() | 659 options.revision = parsed_url.GetRevision() |
| 659 self._used_scm = gclient_scm.SVNWrapper( | 660 self._used_scm = gclient_scm.SVNWrapper( |
| 660 parsed_url.GetPath(), self.root.root_dir, self.name) | 661 parsed_url.GetPath(), self.root.root_dir, self.name, |
| 662 out_cb=work_queue.out_cb) |
| 661 self._used_scm.RunCommand('updatesingle', | 663 self._used_scm.RunCommand('updatesingle', |
| 662 options, args + [parsed_url.GetFilename()], file_list) | 664 options, args + [parsed_url.GetFilename()], file_list) |
| 663 else: | 665 else: |
| 664 # Create a shallow copy to mutate revision. | 666 # Create a shallow copy to mutate revision. |
| 665 options = copy.copy(options) | 667 options = copy.copy(options) |
| 666 options.revision = revision_overrides.get(self.name) | 668 options.revision = revision_overrides.get(self.name) |
| 667 self.maybeGetParentRevision( | 669 self.maybeGetParentRevision( |
| 668 command, options, parsed_url, self.parent.name, revision_overrides) | 670 command, options, parsed_url, self.parent.name, revision_overrides) |
| 669 self._used_scm = gclient_scm.CreateSCM( | 671 self._used_scm = gclient_scm.CreateSCM( |
| 670 parsed_url, self.root.root_dir, self.name) | 672 parsed_url, self.root.root_dir, self.name, self.outbuf, |
| 673 out_cb=work_queue.out_cb) |
| 671 self._got_revision = self._used_scm.RunCommand(command, options, args, | 674 self._got_revision = self._used_scm.RunCommand(command, options, args, |
| 672 file_list) | 675 file_list) |
| 673 if file_list: | 676 if file_list: |
| 674 file_list = [os.path.join(self.name, f.strip()) for f in file_list] | 677 file_list = [os.path.join(self.name, f.strip()) for f in file_list] |
| 675 | 678 |
| 676 # TODO(phajdan.jr): We should know exactly when the paths are absolute. | 679 # TODO(phajdan.jr): We should know exactly when the paths are absolute. |
| 677 # Convert all absolute paths to relative. | 680 # Convert all absolute paths to relative. |
| 678 for i in range(len(file_list or [])): | 681 for i in range(len(file_list or [])): |
| 679 # It depends on the command being executed (like runhooks vs sync). | 682 # It depends on the command being executed (like runhooks vs sync). |
| 680 if not os.path.isabs(file_list[i]): | 683 if not os.path.isabs(file_list[i]): |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 """Git-specific path marshaling. It is optimized for git-grep.""" | 720 """Git-specific path marshaling. It is optimized for git-grep.""" |
| 718 | 721 |
| 719 def mod_path(git_pathspec): | 722 def mod_path(git_pathspec): |
| 720 match = re.match('^(\\S+?:)?([^\0]+)$', git_pathspec) | 723 match = re.match('^(\\S+?:)?([^\0]+)$', git_pathspec) |
| 721 modified_path = os.path.join(self.name, match.group(2)) | 724 modified_path = os.path.join(self.name, match.group(2)) |
| 722 branch = match.group(1) or '' | 725 branch = match.group(1) or '' |
| 723 return '%s%s' % (branch, modified_path) | 726 return '%s%s' % (branch, modified_path) |
| 724 | 727 |
| 725 match = re.match('^Binary file ([^\0]+) matches$', line) | 728 match = re.match('^Binary file ([^\0]+) matches$', line) |
| 726 if match: | 729 if match: |
| 727 print 'Binary file %s matches' % mod_path(match.group(1)) | 730 print 'Binary file %s matches\n' % mod_path(match.group(1)) |
| 728 return | 731 return |
| 729 | 732 |
| 730 items = line.split('\0') | 733 items = line.split('\0') |
| 731 if len(items) == 2 and items[1]: | 734 if len(items) == 2 and items[1]: |
| 732 print '%s : %s' % (mod_path(items[0]), items[1]) | 735 print '%s : %s' % (mod_path(items[0]), items[1]) |
| 733 elif len(items) >= 2: | 736 elif len(items) >= 2: |
| 734 # Multiple null bytes or a single trailing null byte indicate | 737 # Multiple null bytes or a single trailing null byte indicate |
| 735 # git is likely displaying filenames only (such as with -l) | 738 # git is likely displaying filenames only (such as with -l) |
| 736 print '\n'.join(mod_path(path) for path in items if path) | 739 print '\n'.join(mod_path(path) for path in items if path) |
| 737 else: | 740 else: |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1043 enforced_os = self.DEPS_OS_CHOICES.itervalues() | 1046 enforced_os = self.DEPS_OS_CHOICES.itervalues() |
| 1044 self._enforced_os = tuple(set(enforced_os)) | 1047 self._enforced_os = tuple(set(enforced_os)) |
| 1045 self._root_dir = root_dir | 1048 self._root_dir = root_dir |
| 1046 self.config_content = None | 1049 self.config_content = None |
| 1047 | 1050 |
| 1048 def _CheckConfig(self): | 1051 def _CheckConfig(self): |
| 1049 """Verify that the config matches the state of the existing checked-out | 1052 """Verify that the config matches the state of the existing checked-out |
| 1050 solutions.""" | 1053 solutions.""" |
| 1051 for dep in self.dependencies: | 1054 for dep in self.dependencies: |
| 1052 if dep.managed and dep.url: | 1055 if dep.managed and dep.url: |
| 1053 scm = gclient_scm.CreateSCM(dep.url, self.root_dir, dep.name) | 1056 scm = gclient_scm.CreateSCM( |
| 1057 dep.url, self.root_dir, dep.name, self.outbuf) |
| 1054 actual_url = scm.GetActualRemoteURL() | 1058 actual_url = scm.GetActualRemoteURL() |
| 1055 if actual_url and not scm.DoesRemoteURLMatch(): | 1059 if actual_url and not scm.DoesRemoteURLMatch(): |
| 1056 raise gclient_utils.Error(''' | 1060 raise gclient_utils.Error(''' |
| 1057 Your .gclient file seems to be broken. The requested URL is different from what | 1061 Your .gclient file seems to be broken. The requested URL is different from what |
| 1058 is actually checked out in %(checkout_path)s. | 1062 is actually checked out in %(checkout_path)s. |
| 1059 | 1063 |
| 1060 Expected: %(expected_url)s (%(expected_scm)s) | 1064 Expected: %(expected_url)s (%(expected_scm)s) |
| 1061 Actual: %(actual_url)s (%(actual_scm)s) | 1065 Actual: %(actual_url)s (%(actual_scm)s) |
| 1062 | 1066 |
| 1063 You should ensure that the URL listed in .gclient is correct and either change | 1067 You should ensure that the URL listed in .gclient is correct and either change |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1224 be invalid for the given |dep|.""" | 1228 be invalid for the given |dep|.""" |
| 1225 assert len(dep.safesync_url) > 0 | 1229 assert len(dep.safesync_url) > 0 |
| 1226 handle = urllib.urlopen(dep.safesync_url) | 1230 handle = urllib.urlopen(dep.safesync_url) |
| 1227 rev = handle.read().strip() | 1231 rev = handle.read().strip() |
| 1228 handle.close() | 1232 handle.close() |
| 1229 if not rev: | 1233 if not rev: |
| 1230 raise gclient_utils.Error( | 1234 raise gclient_utils.Error( |
| 1231 'It appears your safesync_url (%s) is not working properly\n' | 1235 'It appears your safesync_url (%s) is not working properly\n' |
| 1232 '(as it returned an empty response). Check your config.' % | 1236 '(as it returned an empty response). Check your config.' % |
| 1233 dep.safesync_url) | 1237 dep.safesync_url) |
| 1234 scm = gclient_scm.CreateSCM(dep.url, dep.root.root_dir, dep.name) | 1238 scm = gclient_scm.CreateSCM( |
| 1239 dep.url, dep.root.root_dir, dep.name, self.outbuf) |
| 1235 safe_rev = scm.GetUsableRev(rev, self._options) | 1240 safe_rev = scm.GetUsableRev(rev, self._options) |
| 1236 if self._options.verbose: | 1241 if self._options.verbose: |
| 1237 print('Using safesync_url revision: %s.\n' % safe_rev) | 1242 print('Using safesync_url revision: %s.\n' % safe_rev) |
| 1238 self._options.revisions.append('%s@%s' % (dep.name, safe_rev)) | 1243 self._options.revisions.append('%s@%s' % (dep.name, safe_rev)) |
| 1239 | 1244 |
| 1240 def RunOnDeps(self, command, args, ignore_requirements=False, progress=True): | 1245 def RunOnDeps(self, command, args, ignore_requirements=False, progress=True): |
| 1241 """Runs a command on each dependency in a client and its dependencies. | 1246 """Runs a command on each dependency in a client and its dependencies. |
| 1242 | 1247 |
| 1243 Args: | 1248 Args: |
| 1244 command: The command to use (e.g., 'status' or 'diff') | 1249 command: The command to use (e.g., 'status' or 'diff') |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1255 if command not in ('diff', 'recurse', 'runhooks', 'status'): | 1260 if command not in ('diff', 'recurse', 'runhooks', 'status'): |
| 1256 revision_overrides = self._EnforceRevisions() | 1261 revision_overrides = self._EnforceRevisions() |
| 1257 pm = None | 1262 pm = None |
| 1258 # Disable progress for non-tty stdout. | 1263 # Disable progress for non-tty stdout. |
| 1259 if (sys.stdout.isatty() and not self._options.verbose and progress): | 1264 if (sys.stdout.isatty() and not self._options.verbose and progress): |
| 1260 if command in ('update', 'revert'): | 1265 if command in ('update', 'revert'): |
| 1261 pm = Progress('Syncing projects', 1) | 1266 pm = Progress('Syncing projects', 1) |
| 1262 elif command == 'recurse': | 1267 elif command == 'recurse': |
| 1263 pm = Progress(' '.join(args), 1) | 1268 pm = Progress(' '.join(args), 1) |
| 1264 work_queue = gclient_utils.ExecutionQueue( | 1269 work_queue = gclient_utils.ExecutionQueue( |
| 1265 self._options.jobs, pm, ignore_requirements=ignore_requirements) | 1270 self._options.jobs, pm, ignore_requirements=ignore_requirements, |
| 1271 verbose=self._options.verbose) |
| 1266 for s in self.dependencies: | 1272 for s in self.dependencies: |
| 1267 work_queue.enqueue(s) | 1273 work_queue.enqueue(s) |
| 1268 work_queue.flush(revision_overrides, command, args, options=self._options) | 1274 work_queue.flush(revision_overrides, command, args, options=self._options) |
| 1269 | 1275 |
| 1270 # Once all the dependencies have been processed, it's now safe to run the | 1276 # Once all the dependencies have been processed, it's now safe to run the |
| 1271 # hooks. | 1277 # hooks. |
| 1272 if not self._options.nohooks: | 1278 if not self._options.nohooks: |
| 1273 self.RunHooksRecursively(self._options) | 1279 self.RunHooksRecursively(self._options) |
| 1274 | 1280 |
| 1275 if command == 'update': | 1281 if command == 'update': |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1291 def _IsParentOfAny(parent, path_list): | 1297 def _IsParentOfAny(parent, path_list): |
| 1292 parent_plus_slash = parent + '/' | 1298 parent_plus_slash = parent + '/' |
| 1293 return any( | 1299 return any( |
| 1294 path[:len(parent_plus_slash)] == parent_plus_slash | 1300 path[:len(parent_plus_slash)] == parent_plus_slash |
| 1295 for path in path_list) | 1301 for path in path_list) |
| 1296 | 1302 |
| 1297 # Use entry and not entry_fixed there. | 1303 # Use entry and not entry_fixed there. |
| 1298 if (entry not in entries and | 1304 if (entry not in entries and |
| 1299 (not any(path.startswith(entry + '/') for path in entries)) and | 1305 (not any(path.startswith(entry + '/') for path in entries)) and |
| 1300 os.path.exists(e_dir)): | 1306 os.path.exists(e_dir)): |
| 1301 scm = gclient_scm.CreateSCM(prev_url, self.root_dir, entry_fixed) | 1307 scm = gclient_scm.CreateSCM( |
| 1308 prev_url, self.root_dir, entry_fixed, self.outbuf) |
| 1302 | 1309 |
| 1303 # Check to see if this directory is now part of a higher-up checkout. | 1310 # Check to see if this directory is now part of a higher-up checkout. |
| 1304 if scm.GetCheckoutRoot() in full_entries: | 1311 if scm.GetCheckoutRoot() in full_entries: |
| 1305 logging.info('%s is part of a higher level checkout, not ' | 1312 logging.info('%s is part of a higher level checkout, not ' |
| 1306 'removing.', scm.GetCheckoutRoot()) | 1313 'removing.', scm.GetCheckoutRoot()) |
| 1307 continue | 1314 continue |
| 1308 | 1315 |
| 1309 file_list = [] | 1316 file_list = [] |
| 1310 scm.status(self._options, [], file_list) | 1317 scm.status(self._options, [], file_list) |
| 1311 modified_files = file_list != [] | 1318 modified_files = file_list != [] |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1322 entry_fixed, self.root_dir)) | 1329 entry_fixed, self.root_dir)) |
| 1323 gclient_utils.rmtree(e_dir) | 1330 gclient_utils.rmtree(e_dir) |
| 1324 # record the current list of entries for next time | 1331 # record the current list of entries for next time |
| 1325 self._SaveEntries() | 1332 self._SaveEntries() |
| 1326 return 0 | 1333 return 0 |
| 1327 | 1334 |
| 1328 def PrintRevInfo(self): | 1335 def PrintRevInfo(self): |
| 1329 if not self.dependencies: | 1336 if not self.dependencies: |
| 1330 raise gclient_utils.Error('No solution specified') | 1337 raise gclient_utils.Error('No solution specified') |
| 1331 # Load all the settings. | 1338 # Load all the settings. |
| 1332 work_queue = gclient_utils.ExecutionQueue(self._options.jobs, None, False) | 1339 work_queue = gclient_utils.ExecutionQueue( |
| 1340 self._options.jobs, None, False, verbose=self._options.verbose) |
| 1333 for s in self.dependencies: | 1341 for s in self.dependencies: |
| 1334 work_queue.enqueue(s) | 1342 work_queue.enqueue(s) |
| 1335 work_queue.flush({}, None, [], options=self._options) | 1343 work_queue.flush({}, None, [], options=self._options) |
| 1336 | 1344 |
| 1337 def GetURLAndRev(dep): | 1345 def GetURLAndRev(dep): |
| 1338 """Returns the revision-qualified SCM url for a Dependency.""" | 1346 """Returns the revision-qualified SCM url for a Dependency.""" |
| 1339 if dep.parsed_url is None: | 1347 if dep.parsed_url is None: |
| 1340 return None | 1348 return None |
| 1341 if isinstance(dep.parsed_url, self.FileImpl): | 1349 if isinstance(dep.parsed_url, self.FileImpl): |
| 1342 original_url = dep.parsed_url.file_location | 1350 original_url = dep.parsed_url.file_location |
| 1343 else: | 1351 else: |
| 1344 original_url = dep.parsed_url | 1352 original_url = dep.parsed_url |
| 1345 url, _ = gclient_utils.SplitUrlRevision(original_url) | 1353 url, _ = gclient_utils.SplitUrlRevision(original_url) |
| 1346 scm = gclient_scm.CreateSCM(original_url, self.root_dir, dep.name) | 1354 scm = gclient_scm.CreateSCM( |
| 1355 original_url, self.root_dir, dep.name, self.outbuf) |
| 1347 if not os.path.isdir(scm.checkout_path): | 1356 if not os.path.isdir(scm.checkout_path): |
| 1348 return None | 1357 return None |
| 1349 return '%s@%s' % (url, scm.revinfo(self._options, [], None)) | 1358 return '%s@%s' % (url, scm.revinfo(self._options, [], None)) |
| 1350 | 1359 |
| 1351 if self._options.snapshot: | 1360 if self._options.snapshot: |
| 1352 new_gclient = '' | 1361 new_gclient = '' |
| 1353 # First level at .gclient | 1362 # First level at .gclient |
| 1354 for d in self.dependencies: | 1363 for d in self.dependencies: |
| 1355 entries = {} | 1364 entries = {} |
| 1356 def GrabDeps(dep): | 1365 def GrabDeps(dep): |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1952 print >> sys.stderr, 'Error: %s' % str(e) | 1961 print >> sys.stderr, 'Error: %s' % str(e) |
| 1953 return 1 | 1962 return 1 |
| 1954 finally: | 1963 finally: |
| 1955 gclient_utils.PrintWarnings() | 1964 gclient_utils.PrintWarnings() |
| 1956 | 1965 |
| 1957 | 1966 |
| 1958 if '__main__' == __name__: | 1967 if '__main__' == __name__: |
| 1959 sys.exit(Main(sys.argv[1:])) | 1968 sys.exit(Main(sys.argv[1:])) |
| 1960 | 1969 |
| 1961 # vim: ts=2:sw=2:tw=80:et: | 1970 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |