summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGavin Mak <gavinmak@google.com>2026-06-22 22:36:20 +0000
committergerrit-scoped@luci-project-accounts.iam.gserviceaccount.com <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com>2026-06-29 10:50:02 -0700
commit88a7e88e54d27f8d6068ba3d86fe61c291ab76a5 (patch)
treeabe7a9ca75e6c42747618301ec4bb371a69393b3
parentc21a41c7ccc0350841cb57733f845dd2054bd285 (diff)
downloadgit-repo-88a7e88e54d27f8d6068ba3d86fe61c291ab76a5.tar.gz
git-repo-88a7e88e54d27f8d6068ba3d86fe61c291ab76a5.zip
info: Report actual checked-out HEAD revision
When `repo info` runs, the reported "Current revision" is resolved using the manifest's target branch tracking ref (e.g. refs/remotes/goog/main). Introduce Project.GetHeadRevisionId(), which gets the checked-out HEAD commit in the worktree, and use it in `repo info` with a fallback to the old behavior if the project is not checked out. Bug: 526685287 Change-Id: I72280ce27daa210cada27d722a94e365644f06e0 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/599481 Reviewed-by: Brian Gan <brgan@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Tested-by: Gavin Mak <gavinmak@google.com>
-rw-r--r--project.py12
-rw-r--r--subcmds/info.py5
-rw-r--r--tests/test_project.py22
-rw-r--r--tests/test_subcmds_info.py24
4 files changed, 61 insertions, 2 deletions
diff --git a/project.py b/project.py
index 0b336b272..06719401b 100644
--- a/project.py
+++ b/project.py
@@ -1647,6 +1647,18 @@ class Project:
f"revision {self.revisionExpr} in {self.name} not found"
)
+ def GetHeadRevisionId(self) -> Optional[str]:
+ """Get the commit revision of the checked out HEAD.
+
+ Returns None if worktree is not checked out or HEAD cannot be resolved.
+ """
+ if self.work_git:
+ try:
+ return self.work_git.rev_parse("HEAD")
+ except GitError:
+ pass
+ return None
+
def GetRevisionId(self, all_refs=None):
if self.revisionId:
return self.revisionId
diff --git a/subcmds/info.py b/subcmds/info.py
index 19bb36d2a..a089838a4 100644
--- a/subcmds/info.py
+++ b/subcmds/info.py
@@ -196,7 +196,8 @@ class Info(PagedCommand):
data = {
"name": project.name,
"mount_path": project.worktree,
- "current_revision": project.GetRevisionId(),
+ "current_revision": project.GetHeadRevisionId()
+ or project.GetRevisionId(),
"manifest_revision": project.revisionExpr,
"local_branches": list(project.GetBranches()),
}
@@ -273,7 +274,7 @@ class Info(PagedCommand):
out.nl()
heading("Current revision: ")
- headtext(project.GetRevisionId())
+ headtext(project.GetHeadRevisionId() or project.GetRevisionId())
out.nl()
currentBranch = project.CurrentBranch
diff --git a/tests/test_project.py b/tests/test_project.py
index a824407cf..3973bcfec 100644
--- a/tests/test_project.py
+++ b/tests/test_project.py
@@ -104,6 +104,28 @@ class ProjectTests(unittest.TestCase):
"abcd00%21%21_%2b",
)
+ def test_get_head_revision_id(self):
+ """Check GetHeadRevisionId behavior."""
+ with utils_for_test.TempGitTree() as tempdir:
+ proj = _create_mock_project(tempdir)
+
+ # Initially unborn HEAD should return None.
+ self.assertIsNone(proj.GetHeadRevisionId())
+
+ # Create a commit.
+ with open(os.path.join(tempdir, "readme"), "w") as fp:
+ fp.write("hello")
+ proj.work_git.add("readme")
+ proj.work_git.commit("-m", "initial commit")
+
+ # HEAD should resolve to the commit SHA.
+ commit_sha = proj.work_git.rev_parse("HEAD")
+ self.assertEqual(commit_sha, proj.GetHeadRevisionId())
+
+ # Even if worktree is detached.
+ proj.work_git.checkout("HEAD~0")
+ self.assertEqual(commit_sha, proj.GetHeadRevisionId())
+
@unittest.skipUnless(
utils_for_test.supports_reftable(),
"git reftable support is required for this test",
diff --git a/tests/test_subcmds_info.py b/tests/test_subcmds_info.py
index 788ea9e26..dd6065339 100644
--- a/tests/test_subcmds_info.py
+++ b/tests/test_subcmds_info.py
@@ -199,3 +199,27 @@ def test_text_enables_pager() -> None:
cmd = _get_cmd()
opts, _ = cmd.OptionParser.parse_args([])
assert cmd.WantPager(opts)
+
+
+def test_get_project_data_uses_head_revision() -> None:
+ """_getProjectData should use GetHeadRevisionId if available."""
+ cmd = _get_cmd()
+ project = mock.MagicMock()
+ project.name = "foo"
+ project.worktree = "/path/to/foo"
+ project.revisionExpr = "refs/heads/main"
+ project.GetBranches.return_value = []
+
+ # GetHeadRevisionId() returns a SHA, it should be used.
+ project.GetHeadRevisionId.return_value = "head_sha_12345"
+ project.GetRevisionId.return_value = "manifest_sha_54321"
+
+ data = cmd._getProjectData(project)
+ assert data["current_revision"] == "head_sha_12345"
+ project.GetHeadRevisionId.assert_called_once()
+
+ # GetHeadRevisionId() is None, fall back to GetRevisionId().
+ project.GetHeadRevisionId.reset_mock()
+ project.GetHeadRevisionId.return_value = None
+ data = cmd._getProjectData(project)
+ assert data["current_revision"] == "manifest_sha_54321"