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 1524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1535 full_entries = [os.path.join(self.root_dir, e.replace('/', os.path.sep)) | 1535 full_entries = [os.path.join(self.root_dir, e.replace('/', os.path.sep)) |
1536 for e in entries] | 1536 for e in entries] |
1537 | 1537 |
1538 for entry, prev_url in self._ReadEntries().iteritems(): | 1538 for entry, prev_url in self._ReadEntries().iteritems(): |
1539 if not prev_url: | 1539 if not prev_url: |
1540 # entry must have been overridden via .gclient custom_deps | 1540 # entry must have been overridden via .gclient custom_deps |
1541 continue | 1541 continue |
1542 # Fix path separator on Windows. | 1542 # Fix path separator on Windows. |
1543 entry_fixed = entry.replace('/', os.path.sep) | 1543 entry_fixed = entry.replace('/', os.path.sep) |
1544 e_dir = os.path.join(self.root_dir, entry_fixed) | 1544 e_dir = os.path.join(self.root_dir, entry_fixed) |
1545 | |
1546 def _IsParentOfAny(parent, path_list): | |
1547 parent_plus_slash = parent + '/' | |
1548 return any( | |
1549 path[:len(parent_plus_slash)] == parent_plus_slash | |
1550 for path in path_list) | |
1551 | |
1552 # Use entry and not entry_fixed there. | 1545 # Use entry and not entry_fixed there. |
1553 if (entry not in entries and | 1546 if (entry not in entries and |
1554 (not any(path.startswith(entry + '/') for path in entries)) and | 1547 (not any(path.startswith(entry + '/') for path in entries)) and |
1555 os.path.exists(e_dir)): | 1548 os.path.exists(e_dir)): |
| 1549 # The entry has been removed from DEPS. |
1556 scm = gclient_scm.CreateSCM( | 1550 scm = gclient_scm.CreateSCM( |
1557 prev_url, self.root_dir, entry_fixed, self.outbuf) | 1551 prev_url, self.root_dir, entry_fixed, self.outbuf) |
1558 | 1552 |
1559 # Check to see if this directory is now part of a higher-up checkout. | 1553 # Check to see if this directory is now part of a higher-up checkout. |
1560 # The directory might be part of a git OR svn checkout. | 1554 # The directory might be part of a git OR svn checkout. |
1561 scm_root = None | 1555 scm_root = None |
| 1556 scm_class = None |
1562 for scm_class in (gclient_scm.scm.GIT, gclient_scm.scm.SVN): | 1557 for scm_class in (gclient_scm.scm.GIT, gclient_scm.scm.SVN): |
1563 try: | 1558 try: |
1564 scm_root = scm_class.GetCheckoutRoot(scm.checkout_path) | 1559 scm_root = scm_class.GetCheckoutRoot(scm.checkout_path) |
1565 except subprocess2.CalledProcessError: | 1560 except subprocess2.CalledProcessError: |
1566 pass | 1561 pass |
1567 if scm_root: | 1562 if scm_root: |
1568 break | 1563 break |
1569 else: | 1564 else: |
1570 logging.warning('Could not find checkout root for %s. Unable to ' | 1565 logging.warning('Could not find checkout root for %s. Unable to ' |
1571 'determine whether it is part of a higher-level ' | 1566 'determine whether it is part of a higher-level ' |
1572 'checkout, so not removing.' % entry) | 1567 'checkout, so not removing.' % entry) |
1573 continue | 1568 continue |
| 1569 |
| 1570 # This is to handle the case of third_party/WebKit migrating from |
| 1571 # being a DEPS entry to being part of the main project. |
| 1572 # If the subproject is a Git project, we need to remove its .git |
| 1573 # folder. Otherwise git operations on that folder will have different |
| 1574 # effects depending on the current working directory. |
| 1575 if scm_class == gclient_scm.scm.GIT and ( |
| 1576 os.path.abspath(scm_root) == os.path.abspath(e_dir)): |
| 1577 e_par_dir = os.path.join(e_dir, os.pardir) |
| 1578 if scm_class.IsInsideWorkTree(e_par_dir): |
| 1579 par_scm_root = scm_class.GetCheckoutRoot(e_par_dir) |
| 1580 # rel_e_dir : relative path of entry w.r.t. its parent repo. |
| 1581 rel_e_dir = os.path.relpath(e_dir, par_scm_root) |
| 1582 if scm_class.IsDirectoryVersioned(par_scm_root, rel_e_dir): |
| 1583 save_dir = scm.GetGitBackupDirPath() |
| 1584 # Remove any eventual stale backup dir for the same project. |
| 1585 if os.path.exists(save_dir): |
| 1586 gclient_utils.rmtree(save_dir) |
| 1587 os.rename(os.path.join(e_dir, '.git'), save_dir) |
| 1588 # When switching between the two states (entry/ is a subproject |
| 1589 # -> entry/ is part of the outer project), it is very likely |
| 1590 # that some files are changed in the checkout, unless we are |
| 1591 # jumping *exactly* across the commit which changed just DEPS. |
| 1592 # In such case we want to cleanup any eventual stale files |
| 1593 # (coming from the old subproject) in order to end up with a |
| 1594 # clean checkout. |
| 1595 scm_class.CleanupDir(par_scm_root, rel_e_dir) |
| 1596 assert not os.path.exists(os.path.join(e_dir, '.git')) |
| 1597 print(('\nWARNING: \'%s\' has been moved from DEPS to a higher ' |
| 1598 'level checkout. The git folder containing all the local' |
| 1599 ' branches has been saved to %s.\n' |
| 1600 'If you don\'t care about its state you can safely ' |
| 1601 'remove that folder to free up space.') % |
| 1602 (entry, save_dir)) |
| 1603 continue |
| 1604 |
1574 if scm_root in full_entries: | 1605 if scm_root in full_entries: |
1575 logging.info('%s is part of a higher level checkout, not ' | 1606 logging.info('%s is part of a higher level checkout, not removing', |
1576 'removing.', scm.GetCheckoutRoot()) | 1607 scm.GetCheckoutRoot()) |
1577 continue | 1608 continue |
1578 | 1609 |
1579 file_list = [] | 1610 file_list = [] |
1580 scm.status(self._options, [], file_list) | 1611 scm.status(self._options, [], file_list) |
1581 modified_files = file_list != [] | 1612 modified_files = file_list != [] |
1582 if (not self._options.delete_unversioned_trees or | 1613 if (not self._options.delete_unversioned_trees or |
1583 (modified_files and not self._options.force)): | 1614 (modified_files and not self._options.force)): |
1584 # There are modified files in this entry. Keep warning until | 1615 # There are modified files in this entry. Keep warning until |
1585 # removed. | 1616 # removed. |
1586 print(('\nWARNING: \'%s\' is no longer part of this client. ' | 1617 print(('\nWARNING: \'%s\' is no longer part of this client. ' |
(...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2257 print >> sys.stderr, 'Error: %s' % str(e) | 2288 print >> sys.stderr, 'Error: %s' % str(e) |
2258 return 1 | 2289 return 1 |
2259 finally: | 2290 finally: |
2260 gclient_utils.PrintWarnings() | 2291 gclient_utils.PrintWarnings() |
2261 | 2292 |
2262 | 2293 |
2263 if '__main__' == __name__: | 2294 if '__main__' == __name__: |
2264 sys.exit(Main(sys.argv[1:])) | 2295 sys.exit(Main(sys.argv[1:])) |
2265 | 2296 |
2266 # vim: ts=2:sw=2:tw=80:et: | 2297 # vim: ts=2:sw=2:tw=80:et: |
OLD | NEW |