mirror of
https://gerrit.googlesource.com/git-repo
synced 2026-09-23 15:21:15 +00:00
project: fold normal stash detection into status
When Git 2.35 or newer supplies a stash header, use the same status snapshot for stateless dirty and stash checks. Retain rev-parse for earlier clients or when the status snapshot is unavailable. Bug: 543851900 Bug: 553599402 Change-Id: I6e310459d9c1a3ba7978f7907ae6b7a9bc611749 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/632146 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
aaadd5da35
commit
7bffc72b5b
+16
-1
@@ -930,6 +930,21 @@ class Project:
|
||||
)
|
||||
return p.Wait() == 0
|
||||
|
||||
def _HasDirtyOrStash(self) -> bool:
|
||||
"""Check dirty and normal stash state with one status when possible."""
|
||||
has_status_stash = git_require((2, 35, 0))
|
||||
status = self._GetStatusSnapshot(
|
||||
untracked_files="normal",
|
||||
show_stash=has_status_stash,
|
||||
)
|
||||
if status is not None:
|
||||
if status.is_dirty(consider_untracked=True):
|
||||
return True
|
||||
if has_status_stash:
|
||||
return bool(status.stash_count)
|
||||
return self.HasStash()
|
||||
return self.IsDirty(consider_untracked=True) or self.HasStash()
|
||||
|
||||
_userident_name = None
|
||||
_userident_email = None
|
||||
|
||||
@@ -1670,7 +1685,7 @@ class Project:
|
||||
except (GitError, IndexError, ValueError):
|
||||
return False
|
||||
|
||||
if self.IsDirty(consider_untracked=True) or self.HasStash():
|
||||
if self._HasDirtyOrStash():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
+44
-1
@@ -713,6 +713,49 @@ class ProjectTests(unittest.TestCase):
|
||||
):
|
||||
self.assertIsNone(proj._GetStatusSnapshot())
|
||||
|
||||
def test_dirty_or_stash_uses_status_stash_header(self) -> None:
|
||||
"""A normal stash is detected without a second Git process."""
|
||||
with utils_for_test.TempGitTree() as tempdir:
|
||||
proj = _create_mock_project(tempdir)
|
||||
status = git_status.StatusSnapshot()
|
||||
status.stash_count = 1
|
||||
proj._GetStatusSnapshot = mock.MagicMock(return_value=status)
|
||||
proj.HasStash = mock.MagicMock()
|
||||
|
||||
with mock.patch.object(project, "git_require", return_value=True):
|
||||
self.assertTrue(proj._HasDirtyOrStash())
|
||||
|
||||
proj.HasStash.assert_not_called()
|
||||
|
||||
def test_dirty_or_stash_clean_no_stash_on_git_2_35(self) -> None:
|
||||
"""A clean tree requires no second Git process on Git 2.35+."""
|
||||
with utils_for_test.TempGitTree() as tempdir:
|
||||
proj = _create_mock_project(tempdir)
|
||||
status = git_status.StatusSnapshot()
|
||||
proj._GetStatusSnapshot = mock.MagicMock(return_value=status)
|
||||
proj.HasStash = mock.MagicMock()
|
||||
|
||||
with mock.patch.object(project, "git_require", return_value=True):
|
||||
self.assertFalse(proj._HasDirtyOrStash())
|
||||
|
||||
proj.HasStash.assert_not_called()
|
||||
|
||||
def test_dirty_or_stash_before_2_35_checks_stash_ref(self) -> None:
|
||||
"""Older porcelain v2 output is not assumed to contain stash data."""
|
||||
with utils_for_test.TempGitTree() as tempdir:
|
||||
proj = _create_mock_project(tempdir)
|
||||
status = git_status.StatusSnapshot()
|
||||
proj._GetStatusSnapshot = mock.MagicMock(return_value=status)
|
||||
proj.HasStash = mock.MagicMock(return_value=True)
|
||||
|
||||
with mock.patch.object(project, "git_require", return_value=False):
|
||||
self.assertTrue(proj._HasDirtyOrStash())
|
||||
|
||||
proj._GetStatusSnapshot.assert_called_once_with(
|
||||
untracked_files="normal", show_stash=False
|
||||
)
|
||||
proj.HasStash.assert_called_once_with()
|
||||
|
||||
def test_old_git_dirty_check_uses_legacy_plumbing(self) -> None:
|
||||
"""Git clients before 2.11 retain the existing dirty-check path."""
|
||||
with utils_for_test.TempGitTree() as tempdir:
|
||||
@@ -2186,7 +2229,7 @@ class StatelessSyncTests(unittest.TestCase):
|
||||
"""Test stateless sync skips if stash exists."""
|
||||
with utils_for_test.TempGitTree() as tempdir:
|
||||
proj = self._get_project(tempdir)
|
||||
proj.HasStash = mock.MagicMock(return_value=True)
|
||||
proj._HasDirtyOrStash = mock.MagicMock(return_value=True)
|
||||
|
||||
res = proj.Sync_NetworkHalf()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user