From 6afaa6ca97affa418c408c735574614fdff52343 Mon Sep 17 00:00:00 2001 From: Josip Sokcevic Date: Fri, 8 May 2020 18:20:17 +0000 Subject: [PATCH] Prune branches that no longer exist on remote If a local branch tracks removed remote tracking branch (e.g. foo) and remote has a branch that starts with such name (e.g. foo/bar), git fetch will fail. --prune flag removes any remote-tracking branches that no longer exist. R=apolito@google.com, ehmaldonado@chromium.org Bug: 1079483 Change-Id: I9bc31bf961d52a86b6fa2342249971b99a003666 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2190341 Commit-Queue: Josip Sokcevic Reviewed-by: Edward Lesmes --- git_cache.py | 32 ++++++++++++++++++++------------ tests/git_cache_test.py | 23 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/git_cache.py b/git_cache.py index 5184c5b59..0ca9c7ddf 100755 --- a/git_cache.py +++ b/git_cache.py @@ -529,18 +529,26 @@ class Mirror(object): 'but failed. Continuing with non-optimized repository.' % len(pack_files)) - def _fetch(self, rundir, verbose, depth, no_fetch_tags, reset_fetch_config): + def _fetch(self, + rundir, + verbose, + depth, + no_fetch_tags, + reset_fetch_config, + prune=True): self.config(rundir, reset_fetch_config) - v = [] - d = [] - t = [] + + fetch_cmd = ['fetch'] if verbose: - v = ['-v', '--progress'] + fetch_cmd.extend(['-v', '--progress']) if depth: - d = ['--depth', str(depth)] + fetch_cmd.extend(['--depth', str(depth)]) if no_fetch_tags: - t = ['--no-tags'] - fetch_cmd = ['fetch'] + v + d + t + ['origin'] + fetch_cmd.append('--no-tags') + if prune: + fetch_cmd.append('--prune') + fetch_cmd.append('origin') + fetch_specs = subprocess.check_output( [self.git_exe, 'config', '--get-all', 'remote.origin.fetch'], cwd=rundir).decode('utf-8', 'ignore').strip().splitlines() @@ -574,16 +582,16 @@ class Mirror(object): try: self._ensure_bootstrapped(depth, bootstrap, reset_fetch_config) - self._fetch( - self.mirror_path, verbose, depth, no_fetch_tags, reset_fetch_config) + self._fetch(self.mirror_path, verbose, depth, no_fetch_tags, + reset_fetch_config) except ClobberNeeded: # This is a major failure, we need to clean and force a bootstrap. gclient_utils.rmtree(self.mirror_path) self.print(GIT_CACHE_CORRUPT_MESSAGE) self._ensure_bootstrapped( depth, bootstrap, reset_fetch_config, force=True) - self._fetch( - self.mirror_path, verbose, depth, no_fetch_tags, reset_fetch_config) + self._fetch(self.mirror_path, verbose, depth, no_fetch_tags, + reset_fetch_config) finally: if not ignore_lock: lockfile.unlock() diff --git a/tests/git_cache_test.py b/tests/git_cache_test.py index f3b5a2329..42df6a6c2 100755 --- a/tests/git_cache_test.py +++ b/tests/git_cache_test.py @@ -12,6 +12,13 @@ import sys import tempfile import unittest +if sys.version_info.major == 2: + from StringIO import StringIO + import mock +else: + from io import StringIO + from unittest import mock + DEPOT_TOOLS_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, DEPOT_TOOLS_ROOT) @@ -96,6 +103,22 @@ class GitCacheTest(unittest.TestCase): mirror.populate() + @mock.patch('sys.stdout', StringIO()) + def testPruneRequired(self): + self.git(['init', '-q']) + with open(os.path.join(self.origin_dir, 'foo'), 'w') as f: + f.write('touched\n') + self.git(['checkout', '-b', 'foo']) + self.git(['add', 'foo']) + self.git(['commit', '-m', 'foo']) + mirror = git_cache.Mirror(self.origin_dir) + mirror.populate() + self.git(['checkout', '-b', 'foo_tmp', 'foo']) + self.git(['branch', '-D', 'foo']) + self.git(['checkout', '-b', 'foo/bar', 'foo_tmp']) + mirror.populate() + self.assertNotIn(git_cache.GIT_CACHE_CORRUPT_MESSAGE, sys.stdout.getvalue()) + def _makeGitRepoWithTag(self): self.git(['init', '-q']) with open(os.path.join(self.origin_dir, 'foo'), 'w') as f: