mirror of
https://gerrit.googlesource.com/git-repo
synced 2026-09-26 00:30:32 +00:00
project: don't plan a stateless prune without a worktree
Skip stateless prune planning when a project's worktree directory does not exist, preventing fetch failures on subsequent syncs. Also run _LsRemote() bare so it does not depend on worktree existence. Bug: 565047698 Change-Id: I385cba4e06813d9113ec7ddc963e8499acffaec5 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/634426 Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com>
This commit is contained in:
committed by
gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
175198b0aa
commit
6624f5ed6f
+8
-2
@@ -1667,6 +1667,12 @@ class Project:
|
||||
if not self.Exists:
|
||||
return False
|
||||
|
||||
# Local changes can't be checked without a worktree, and pruning drops
|
||||
# every reflog. Sync_LocalHalf() recreates the worktree, so a later
|
||||
# sync can decide.
|
||||
if not self.worktree or not platform_utils.isdir(self.worktree):
|
||||
return False
|
||||
|
||||
if self._CheckForImmutableRevision(use_superproject=use_superproject):
|
||||
return False
|
||||
|
||||
@@ -3914,9 +3920,9 @@ class Project:
|
||||
f"{self.name} cherry-pick {rev} ", project=self.name
|
||||
)
|
||||
|
||||
def _LsRemote(self, refs):
|
||||
def _LsRemote(self, refs: str) -> Optional[str]:
|
||||
cmd = ["ls-remote", self.remote.name, refs]
|
||||
p = GitCommand(self, cmd, capture_stdout=True)
|
||||
p = GitCommand(self, cmd, bare=True, capture_stdout=True)
|
||||
if p.Wait() == 0:
|
||||
return p.stdout
|
||||
return None
|
||||
|
||||
@@ -2420,6 +2420,33 @@ class StatelessSyncTests(unittest.TestCase):
|
||||
self.assertTrue(res.success)
|
||||
self.assertFalse(getattr(proj, "stateless_prune_needed", False))
|
||||
|
||||
def test_sync_network_half_stateless_skips_without_worktree(self) -> None:
|
||||
"""Test stateless sync doesn't prune a project with no worktree."""
|
||||
with utils_for_test.TempGitTree() as tempdir:
|
||||
proj = self._get_project(tempdir)
|
||||
proj.worktree = os.path.join(tempdir, "missing")
|
||||
proj._HasDirtyOrStash = mock.MagicMock(return_value=False)
|
||||
|
||||
res = proj.Sync_NetworkHalf()
|
||||
|
||||
self.assertTrue(res.success)
|
||||
self.assertFalse(proj.stateless_prune_needed)
|
||||
proj._LsRemote.assert_not_called()
|
||||
proj._HasDirtyOrStash.assert_not_called()
|
||||
|
||||
def test_ls_remote_runs_without_worktree(self) -> None:
|
||||
"""Test ls-remote only needs the gitdir's remote config."""
|
||||
with utils_for_test.TempGitTree() as tempdir:
|
||||
proj = _create_mock_project(tempdir)
|
||||
proj.work_git.commit("--allow-empty", "-m", "initial")
|
||||
proj.work_git.config("remote.origin.url", tempdir)
|
||||
head = proj.work_git.rev_parse("HEAD")
|
||||
proj.worktree = os.path.join(tempdir, "missing")
|
||||
# _create_mock_project() stubs this out.
|
||||
del proj._LsRemote
|
||||
|
||||
self.assertEqual(f"{head}\tHEAD\n", proj._LsRemote("HEAD"))
|
||||
|
||||
def test_sync_network_half_stateless_skips_if_local_commits(self):
|
||||
"""Test stateless sync skips if there are local-only commits."""
|
||||
with utils_for_test.TempGitTree() as tempdir:
|
||||
|
||||
Reference in New Issue
Block a user