| 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(self._options) | 1058 actual_url = scm.GetActualRemoteURL(self._options) |
| 1055 if actual_url and not scm.DoesRemoteURLMatch(self._options): | 1059 if actual_url and not scm.DoesRemoteURLMatch(self._options): |
| 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 The .gclient file contains: | 1064 The .gclient file contains: |
| 1061 %(expected_url)s (%(expected_scm)s) | 1065 %(expected_url)s (%(expected_scm)s) |
| 1062 | 1066 |
| 1063 The local checkout in %(checkout_path)s reports: | 1067 The local checkout in %(checkout_path)s reports: |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1227 be invalid for the given |dep|.""" | 1231 be invalid for the given |dep|.""" |
| 1228 assert len(dep.safesync_url) > 0 | 1232 assert len(dep.safesync_url) > 0 |
| 1229 handle = urllib.urlopen(dep.safesync_url) | 1233 handle = urllib.urlopen(dep.safesync_url) |
| 1230 rev = handle.read().strip() | 1234 rev = handle.read().strip() |
| 1231 handle.close() | 1235 handle.close() |
| 1232 if not rev: | 1236 if not rev: |
| 1233 raise gclient_utils.Error( | 1237 raise gclient_utils.Error( |
| 1234 'It appears your safesync_url (%s) is not working properly\n' | 1238 'It appears your safesync_url (%s) is not working properly\n' |
| 1235 '(as it returned an empty response). Check your config.' % | 1239 '(as it returned an empty response). Check your config.' % |
| 1236 dep.safesync_url) | 1240 dep.safesync_url) |
| 1237 scm = gclient_scm.CreateSCM(dep.url, dep.root.root_dir, dep.name) | 1241 scm = gclient_scm.CreateSCM( |
| 1242 dep.url, dep.root.root_dir, dep.name, self.outbuf) |
| 1238 safe_rev = scm.GetUsableRev(rev, self._options) | 1243 safe_rev = scm.GetUsableRev(rev, self._options) |
| 1239 if self._options.verbose: | 1244 if self._options.verbose: |
| 1240 print('Using safesync_url revision: %s.\n' % safe_rev) | 1245 print('Using safesync_url revision: %s.\n' % safe_rev) |
| 1241 self._options.revisions.append('%s@%s' % (dep.name, safe_rev)) | 1246 self._options.revisions.append('%s@%s' % (dep.name, safe_rev)) |
| 1242 | 1247 |
| 1243 def RunOnDeps(self, command, args, ignore_requirements=False, progress=True): | 1248 def RunOnDeps(self, command, args, ignore_requirements=False, progress=True): |
| 1244 """Runs a command on each dependency in a client and its dependencies. | 1249 """Runs a command on each dependency in a client and its dependencies. |
| 1245 | 1250 |
| 1246 Args: | 1251 Args: |
| 1247 command: The command to use (e.g., 'status' or 'diff') | 1252 command: The command to use (e.g., 'status' or 'diff') |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1258 if command not in ('diff', 'recurse', 'runhooks', 'status'): | 1263 if command not in ('diff', 'recurse', 'runhooks', 'status'): |
| 1259 revision_overrides = self._EnforceRevisions() | 1264 revision_overrides = self._EnforceRevisions() |
| 1260 pm = None | 1265 pm = None |
| 1261 # Disable progress for non-tty stdout. | 1266 # Disable progress for non-tty stdout. |
| 1262 if (sys.stdout.isatty() and not self._options.verbose and progress): | 1267 if (sys.stdout.isatty() and not self._options.verbose and progress): |
| 1263 if command in ('update', 'revert'): | 1268 if command in ('update', 'revert'): |
| 1264 pm = Progress('Syncing projects', 1) | 1269 pm = Progress('Syncing projects', 1) |
| 1265 elif command == 'recurse': | 1270 elif command == 'recurse': |
| 1266 pm = Progress(' '.join(args), 1) | 1271 pm = Progress(' '.join(args), 1) |
| 1267 work_queue = gclient_utils.ExecutionQueue( | 1272 work_queue = gclient_utils.ExecutionQueue( |
| 1268 self._options.jobs, pm, ignore_requirements=ignore_requirements) | 1273 self._options.jobs, pm, ignore_requirements=ignore_requirements, |
| 1274 verbose=self._options.verbose) |
| 1269 for s in self.dependencies: | 1275 for s in self.dependencies: |
| 1270 work_queue.enqueue(s) | 1276 work_queue.enqueue(s) |
| 1271 work_queue.flush(revision_overrides, command, args, options=self._options) | 1277 work_queue.flush(revision_overrides, command, args, options=self._options) |
| 1272 | 1278 |
| 1273 # Once all the dependencies have been processed, it's now safe to run the | 1279 # Once all the dependencies have been processed, it's now safe to run the |
| 1274 # hooks. | 1280 # hooks. |
| 1275 if not self._options.nohooks: | 1281 if not self._options.nohooks: |
| 1276 self.RunHooksRecursively(self._options) | 1282 self.RunHooksRecursively(self._options) |
| 1277 | 1283 |
| 1278 if command == 'update': | 1284 if command == 'update': |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1294 def _IsParentOfAny(parent, path_list): | 1300 def _IsParentOfAny(parent, path_list): |
| 1295 parent_plus_slash = parent + '/' | 1301 parent_plus_slash = parent + '/' |
| 1296 return any( | 1302 return any( |
| 1297 path[:len(parent_plus_slash)] == parent_plus_slash | 1303 path[:len(parent_plus_slash)] == parent_plus_slash |
| 1298 for path in path_list) | 1304 for path in path_list) |
| 1299 | 1305 |
| 1300 # Use entry and not entry_fixed there. | 1306 # Use entry and not entry_fixed there. |
| 1301 if (entry not in entries and | 1307 if (entry not in entries and |
| 1302 (not any(path.startswith(entry + '/') for path in entries)) and | 1308 (not any(path.startswith(entry + '/') for path in entries)) and |
| 1303 os.path.exists(e_dir)): | 1309 os.path.exists(e_dir)): |
| 1304 scm = gclient_scm.CreateSCM(prev_url, self.root_dir, entry_fixed) | 1310 scm = gclient_scm.CreateSCM( |
| 1311 prev_url, self.root_dir, entry_fixed, self.outbuf) |
| 1305 | 1312 |
| 1306 # Check to see if this directory is now part of a higher-up checkout. | 1313 # Check to see if this directory is now part of a higher-up checkout. |
| 1307 if scm.GetCheckoutRoot() in full_entries: | 1314 if scm.GetCheckoutRoot() in full_entries: |
| 1308 logging.info('%s is part of a higher level checkout, not ' | 1315 logging.info('%s is part of a higher level checkout, not ' |
| 1309 'removing.', scm.GetCheckoutRoot()) | 1316 'removing.', scm.GetCheckoutRoot()) |
| 1310 continue | 1317 continue |
| 1311 | 1318 |
| 1312 file_list = [] | 1319 file_list = [] |
| 1313 scm.status(self._options, [], file_list) | 1320 scm.status(self._options, [], file_list) |
| 1314 modified_files = file_list != [] | 1321 modified_files = file_list != [] |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1325 entry_fixed, self.root_dir)) | 1332 entry_fixed, self.root_dir)) |
| 1326 gclient_utils.rmtree(e_dir) | 1333 gclient_utils.rmtree(e_dir) |
| 1327 # record the current list of entries for next time | 1334 # record the current list of entries for next time |
| 1328 self._SaveEntries() | 1335 self._SaveEntries() |
| 1329 return 0 | 1336 return 0 |
| 1330 | 1337 |
| 1331 def PrintRevInfo(self): | 1338 def PrintRevInfo(self): |
| 1332 if not self.dependencies: | 1339 if not self.dependencies: |
| 1333 raise gclient_utils.Error('No solution specified') | 1340 raise gclient_utils.Error('No solution specified') |
| 1334 # Load all the settings. | 1341 # Load all the settings. |
| 1335 work_queue = gclient_utils.ExecutionQueue(self._options.jobs, None, False) | 1342 work_queue = gclient_utils.ExecutionQueue( |
| 1343 self._options.jobs, None, False, verbose=self._options.verbose) |
| 1336 for s in self.dependencies: | 1344 for s in self.dependencies: |
| 1337 work_queue.enqueue(s) | 1345 work_queue.enqueue(s) |
| 1338 work_queue.flush({}, None, [], options=self._options) | 1346 work_queue.flush({}, None, [], options=self._options) |
| 1339 | 1347 |
| 1340 def GetURLAndRev(dep): | 1348 def GetURLAndRev(dep): |
| 1341 """Returns the revision-qualified SCM url for a Dependency.""" | 1349 """Returns the revision-qualified SCM url for a Dependency.""" |
| 1342 if dep.parsed_url is None: | 1350 if dep.parsed_url is None: |
| 1343 return None | 1351 return None |
| 1344 if isinstance(dep.parsed_url, self.FileImpl): | 1352 if isinstance(dep.parsed_url, self.FileImpl): |
| 1345 original_url = dep.parsed_url.file_location | 1353 original_url = dep.parsed_url.file_location |
| 1346 else: | 1354 else: |
| 1347 original_url = dep.parsed_url | 1355 original_url = dep.parsed_url |
| 1348 url, _ = gclient_utils.SplitUrlRevision(original_url) | 1356 url, _ = gclient_utils.SplitUrlRevision(original_url) |
| 1349 scm = gclient_scm.CreateSCM(original_url, self.root_dir, dep.name) | 1357 scm = gclient_scm.CreateSCM( |
| 1358 original_url, self.root_dir, dep.name, self.outbuf) |
| 1350 if not os.path.isdir(scm.checkout_path): | 1359 if not os.path.isdir(scm.checkout_path): |
| 1351 return None | 1360 return None |
| 1352 return '%s@%s' % (url, scm.revinfo(self._options, [], None)) | 1361 return '%s@%s' % (url, scm.revinfo(self._options, [], None)) |
| 1353 | 1362 |
| 1354 if self._options.snapshot: | 1363 if self._options.snapshot: |
| 1355 new_gclient = '' | 1364 new_gclient = '' |
| 1356 # First level at .gclient | 1365 # First level at .gclient |
| 1357 for d in self.dependencies: | 1366 for d in self.dependencies: |
| 1358 entries = {} | 1367 entries = {} |
| 1359 def GrabDeps(dep): | 1368 def GrabDeps(dep): |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1955 print >> sys.stderr, 'Error: %s' % str(e) | 1964 print >> sys.stderr, 'Error: %s' % str(e) |
| 1956 return 1 | 1965 return 1 |
| 1957 finally: | 1966 finally: |
| 1958 gclient_utils.PrintWarnings() | 1967 gclient_utils.PrintWarnings() |
| 1959 | 1968 |
| 1960 | 1969 |
| 1961 if '__main__' == __name__: | 1970 if '__main__' == __name__: |
| 1962 sys.exit(Main(sys.argv[1:])) | 1971 sys.exit(Main(sys.argv[1:])) |
| 1963 | 1972 |
| 1964 # vim: ts=2:sw=2:tw=80:et: | 1973 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |