From beda65323e8fb08199133b4779b9a5c079710f83 Mon Sep 17 00:00:00 2001 From: Gavin Mak Date: Thu, 8 Oct 2026 22:59:29 +0000 Subject: [PATCH] sync: skip clone.bundle when repo.fetchcmd is configured In Sync_NetworkHalf, clone_bundle defaults to True on initial sync when self.objdir does not exist yet, and _ApplyCloneBundle is called before custom_fetch_configured is checked. For remotes with HTTP/HTTPS URLs that serve /clone.bundle, this causes repo sync to download and unpack the full clone.bundle into .git/objects before invoking repo.fetchcmd. Skip _ApplyCloneBundle when custom_fetch_configured is enabled so repo.fetchcmd exclusively handles object fetching. Bug: 543101585 Change-Id: If41a775a75589ad5a23106163f9932e2940b72d2 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/641685 Commit-Queue: Gavin Mak Reviewed-by: Brian Gan Tested-by: Gavin Mak --- project.py | 13 +++++++------ tests/test_project.py | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/project.py b/project.py index ed1af52cf..6815e4f29 100644 --- a/project.py +++ b/project.py @@ -1855,8 +1855,15 @@ class Project: else: alt_dir = None + custom_fetch_configured = ( + self.manifest.manifestProject.use_local_gitdirs + and self.manifest.manifestProject.fetch_cmd + and not isinstance(self, MetaProject) + ) + if ( clone_bundle + and not custom_fetch_configured and alt_dir is None and self._ApplyCloneBundle( initial=is_new, quiet=quiet, verbose=verbose @@ -1890,12 +1897,6 @@ class Project: depth = None clone_filter = clone_filter_for_depth - custom_fetch_configured = ( - self.manifest.manifestProject.use_local_gitdirs - and self.manifest.manifestProject.fetch_cmd - and not isinstance(self, MetaProject) - ) - remote_fetched = False if custom_fetch_configured: # The custom fetch command is executed unconditionally on every sync diff --git a/tests/test_project.py b/tests/test_project.py index 3d6029b42..8908c79e3 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -3453,6 +3453,31 @@ class FetchCmdTests(unittest.TestCase): result = fakeproj.Sync(use_local_gitdirs=False) self.assertFalse(result) + def test_sync_network_half_skips_clone_bundle_with_fetch_cmd(self) -> None: + """Test Sync_NetworkHalf skips clone.bundle when fetchcmd is set.""" + with tempfile.TemporaryDirectory() as tempdir: + worktree = os.path.join(tempdir, "new-proj") + gitdir = os.path.join(worktree, ".git") + proj = _create_mock_project( + worktree, + use_local_gitdirs=True, + fetch_cmd="echo hi", + gitdir=gitdir, + objdir=gitdir, + ) + proj._InitGitDir = mock.MagicMock() + proj._InitRemote = mock.MagicMock() + proj._InitMRef = mock.MagicMock() + proj._CustomFetch = mock.MagicMock(return_value=True) + proj._ApplyCloneBundle = mock.MagicMock(return_value=True) + + res = proj.Sync_NetworkHalf(clone_bundle=True, is_new=True) + + self.assertIsNone(res.error) + self.assertTrue(res.remote_fetched) + proj._ApplyCloneBundle.assert_not_called() + proj._CustomFetch.assert_called_once() + class ReprojectCmdTests(unittest.TestCase): """Tests for the repo.reprojectcmd feature."""