gclient: Sync CIPD deps before running hooks.
Bug: 882611
Change-Id: I72646544a164f557ea7d53e0ce0f16d663618a98
Reviewed-on: https://chromium-review.googlesource.com/c/1255446
Reviewed-by: Andrii Shyshkalov <tandrii@chromium.org>
Commit-Queue: Edward Lesmes <ehmaldonado@chromium.org>
diff --git a/gclient.py b/gclient.py
index 2b8ae35..f2d90f6 100755
--- a/gclient.py
+++ b/gclient.py
@@ -1563,6 +1563,103 @@
patch_refs[patch_repo] = patch_ref
return patch_refs, target_branches
+ def _RemoveUnversionedGitDirs(self):
+ """Remove directories that are no longer part of the checkout.
+
+ Notify the user if there is an orphaned entry in their working copy.
+ Only delete the directory if there are no changes in it, and
+ delete_unversioned_trees is set to true.
+ """
+
+ entries = [i.name for i in self.root.subtree(False) if i.url]
+ full_entries = [os.path.join(self.root_dir, e.replace('/', os.path.sep))
+ for e in entries]
+
+ for entry, prev_url in self._ReadEntries().iteritems():
+ if not prev_url:
+ # entry must have been overridden via .gclient custom_deps
+ continue
+ # Fix path separator on Windows.
+ entry_fixed = entry.replace('/', os.path.sep)
+ e_dir = os.path.join(self.root_dir, entry_fixed)
+ # Use entry and not entry_fixed there.
+ if (entry not in entries and
+ (not any(path.startswith(entry + '/') for path in entries)) and
+ os.path.exists(e_dir)):
+ # The entry has been removed from DEPS.
+ scm = gclient_scm.GitWrapper(
+ prev_url, self.root_dir, entry_fixed, self.outbuf)
+
+ # Check to see if this directory is now part of a higher-up checkout.
+ scm_root = None
+ try:
+ scm_root = gclient_scm.scm.GIT.GetCheckoutRoot(scm.checkout_path)
+ except subprocess2.CalledProcessError:
+ pass
+ if not scm_root:
+ logging.warning('Could not find checkout root for %s. Unable to '
+ 'determine whether it is part of a higher-level '
+ 'checkout, so not removing.' % entry)
+ continue
+
+ # This is to handle the case of third_party/WebKit migrating from
+ # being a DEPS entry to being part of the main project.
+ # If the subproject is a Git project, we need to remove its .git
+ # folder. Otherwise git operations on that folder will have different
+ # effects depending on the current working directory.
+ if os.path.abspath(scm_root) == os.path.abspath(e_dir):
+ e_par_dir = os.path.join(e_dir, os.pardir)
+ if gclient_scm.scm.GIT.IsInsideWorkTree(e_par_dir):
+ par_scm_root = gclient_scm.scm.GIT.GetCheckoutRoot(e_par_dir)
+ # rel_e_dir : relative path of entry w.r.t. its parent repo.
+ rel_e_dir = os.path.relpath(e_dir, par_scm_root)
+ if gclient_scm.scm.GIT.IsDirectoryVersioned(
+ par_scm_root, rel_e_dir):
+ save_dir = scm.GetGitBackupDirPath()
+ # Remove any eventual stale backup dir for the same project.
+ if os.path.exists(save_dir):
+ gclient_utils.rmtree(save_dir)
+ os.rename(os.path.join(e_dir, '.git'), save_dir)
+ # When switching between the two states (entry/ is a subproject
+ # -> entry/ is part of the outer project), it is very likely
+ # that some files are changed in the checkout, unless we are
+ # jumping *exactly* across the commit which changed just DEPS.
+ # In such case we want to cleanup any eventual stale files
+ # (coming from the old subproject) in order to end up with a
+ # clean checkout.
+ gclient_scm.scm.GIT.CleanupDir(par_scm_root, rel_e_dir)
+ assert not os.path.exists(os.path.join(e_dir, '.git'))
+ print(('\nWARNING: \'%s\' has been moved from DEPS to a higher '
+ 'level checkout. The git folder containing all the local'
+ ' branches has been saved to %s.\n'
+ 'If you don\'t care about its state you can safely '
+ 'remove that folder to free up space.') %
+ (entry, save_dir))
+ continue
+
+ if scm_root in full_entries:
+ logging.info('%s is part of a higher level checkout, not removing',
+ scm.GetCheckoutRoot())
+ continue
+
+ file_list = []
+ scm.status(self._options, [], file_list)
+ modified_files = file_list != []
+ if (not self._options.delete_unversioned_trees or
+ (modified_files and not self._options.force)):
+ # There are modified files in this entry. Keep warning until
+ # removed.
+ print(('\nWARNING: \'%s\' is no longer part of this client. '
+ 'It is recommended that you manually remove it.\n') %
+ entry_fixed)
+ else:
+ # Delete the entry
+ print('\n________ deleting \'%s\' in \'%s\'' % (
+ entry_fixed, self.root_dir))
+ gclient_utils.rmtree(e_dir)
+ # record the current list of entries for next time
+ self._SaveEntries()
+
def RunOnDeps(self, command, args, ignore_requirements=False, progress=True):
"""Runs a command on each dependency in a client and its dependencies.
@@ -1624,103 +1721,7 @@
if gn_args_dep and gn_args_dep.HasGNArgsFile():
gn_args_dep.WriteGNArgsFile()
- if not self._options.nohooks:
- if should_show_progress:
- pm = Progress('Running hooks', 1)
- self.RunHooksRecursively(self._options, pm)
-
- if command == 'update':
- # Notify the user if there is an orphaned entry in their working copy.
- # Only delete the directory if there are no changes in it, and
- # delete_unversioned_trees is set to true.
- entries = [i.name for i in self.root.subtree(False) if i.url]
- full_entries = [os.path.join(self.root_dir, e.replace('/', os.path.sep))
- for e in entries]
-
- for entry, prev_url in self._ReadEntries().iteritems():
- if not prev_url:
- # entry must have been overridden via .gclient custom_deps
- continue
- # Fix path separator on Windows.
- entry_fixed = entry.replace('/', os.path.sep)
- e_dir = os.path.join(self.root_dir, entry_fixed)
- # Use entry and not entry_fixed there.
- if (entry not in entries and
- (not any(path.startswith(entry + '/') for path in entries)) and
- os.path.exists(e_dir)):
- # The entry has been removed from DEPS.
- scm = gclient_scm.GitWrapper(
- prev_url, self.root_dir, entry_fixed, self.outbuf)
-
- # Check to see if this directory is now part of a higher-up checkout.
- scm_root = None
- try:
- scm_root = gclient_scm.scm.GIT.GetCheckoutRoot(scm.checkout_path)
- except subprocess2.CalledProcessError:
- pass
- if not scm_root:
- logging.warning('Could not find checkout root for %s. Unable to '
- 'determine whether it is part of a higher-level '
- 'checkout, so not removing.' % entry)
- continue
-
- # This is to handle the case of third_party/WebKit migrating from
- # being a DEPS entry to being part of the main project.
- # If the subproject is a Git project, we need to remove its .git
- # folder. Otherwise git operations on that folder will have different
- # effects depending on the current working directory.
- if os.path.abspath(scm_root) == os.path.abspath(e_dir):
- e_par_dir = os.path.join(e_dir, os.pardir)
- if gclient_scm.scm.GIT.IsInsideWorkTree(e_par_dir):
- par_scm_root = gclient_scm.scm.GIT.GetCheckoutRoot(e_par_dir)
- # rel_e_dir : relative path of entry w.r.t. its parent repo.
- rel_e_dir = os.path.relpath(e_dir, par_scm_root)
- if gclient_scm.scm.GIT.IsDirectoryVersioned(
- par_scm_root, rel_e_dir):
- save_dir = scm.GetGitBackupDirPath()
- # Remove any eventual stale backup dir for the same project.
- if os.path.exists(save_dir):
- gclient_utils.rmtree(save_dir)
- os.rename(os.path.join(e_dir, '.git'), save_dir)
- # When switching between the two states (entry/ is a subproject
- # -> entry/ is part of the outer project), it is very likely
- # that some files are changed in the checkout, unless we are
- # jumping *exactly* across the commit which changed just DEPS.
- # In such case we want to cleanup any eventual stale files
- # (coming from the old subproject) in order to end up with a
- # clean checkout.
- gclient_scm.scm.GIT.CleanupDir(par_scm_root, rel_e_dir)
- assert not os.path.exists(os.path.join(e_dir, '.git'))
- print(('\nWARNING: \'%s\' has been moved from DEPS to a higher '
- 'level checkout. The git folder containing all the local'
- ' branches has been saved to %s.\n'
- 'If you don\'t care about its state you can safely '
- 'remove that folder to free up space.') %
- (entry, save_dir))
- continue
-
- if scm_root in full_entries:
- logging.info('%s is part of a higher level checkout, not removing',
- scm.GetCheckoutRoot())
- continue
-
- file_list = []
- scm.status(self._options, [], file_list)
- modified_files = file_list != []
- if (not self._options.delete_unversioned_trees or
- (modified_files and not self._options.force)):
- # There are modified files in this entry. Keep warning until
- # removed.
- print(('\nWARNING: \'%s\' is no longer part of this client. '
- 'It is recommended that you manually remove it.\n') %
- entry_fixed)
- else:
- # Delete the entry
- print('\n________ deleting \'%s\' in \'%s\'' % (
- entry_fixed, self.root_dir))
- gclient_utils.rmtree(e_dir)
- # record the current list of entries for next time
- self._SaveEntries()
+ self._RemoveUnversionedGitDirs()
# Sync CIPD dependencies once removed deps are deleted. In case a git
# dependency was moved to CIPD, we want to remove the old git directory
@@ -1728,6 +1729,12 @@
if self._cipd_root:
self._cipd_root.run(command)
+ if not self._options.nohooks:
+ if should_show_progress:
+ pm = Progress('Running hooks', 1)
+ self.RunHooksRecursively(self._options, pm)
+
+
return 0
def PrintRevInfo(self):