version: read describe and date in one Git call Git 2.32 added the %(describe) pretty placeholder. Use one log format to retrieve both repo's describe string and commit date on newer clients, with the existing describe-plus-log path retained for older Git and untagged output. Bug: 553599402 Change-Id: I108346030677b2b90ef8bfb5acea1c45be2c85f2 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/623904 Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Brian Gan <brgan@google.com>
diff --git a/subcmds/version.py b/subcmds/version.py index 5c817f1..5c05f90 100644 --- a/subcmds/version.py +++ b/subcmds/version.py
@@ -14,10 +14,12 @@ import platform import sys +from typing import Any, Tuple from command import Command from command import MirrorSafeCommand from git_command import git +from git_command import git_require from git_command import RepoSourceVersion from git_command import user_agent from git_refs import HEAD @@ -34,6 +36,22 @@ %prog """ + @staticmethod + def _RepoVersion(project: Any) -> Tuple[str, str]: + """Return repo's describe string and commit date.""" + if git_require((2, 32, 0)): + output = project.bare_git.log( + "-1", "--format=%(describe)%n%cD", HEAD + ) + description, commit_date = output.rstrip("\n").split("\n", 1) + if description: + return description, commit_date + + return ( + project.bare_git.describe(HEAD), + project.bare_git.log("-1", "--format=%cD", HEAD), + ) + def Execute(self, opt, args): rp = self.manifest.repoProject rem = rp.GetRemote() @@ -41,11 +59,11 @@ # These might not be the same. Report them both. src_ver = RepoSourceVersion() - rp_ver = rp.bare_git.describe(HEAD) + rp_ver, commit_date = self._RepoVersion(rp) print(f"repo version {rp_ver}") print(f" (from {rem.url})") print(f" (tracking {branch.merge})") - print(f" ({rp.bare_git.log('-1', '--format=%cD', HEAD)})") + print(f" ({commit_date})") if self.wrapper_path is not None: print(f"repo launcher version {self.wrapper_version}")
diff --git a/tests/test_subcmds_version.py b/tests/test_subcmds_version.py new file mode 100644 index 0000000..72935e2 --- /dev/null +++ b/tests/test_subcmds_version.py
@@ -0,0 +1,52 @@ +# Copyright (C) 2026 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Unittests for subcmds/version.py.""" + +from unittest import mock + +import pytest + +from subcmds import version + + +def test_repo_version_uses_one_pretty_format_call( + monkeypatch: pytest.MonkeyPatch, +) -> None: + project = mock.MagicMock() + project.bare_git.log.return_value = "v2.0-1-g12345678\nTue, 25 Aug\n" + monkeypatch.setattr(version, "git_require", lambda _version: True) + + result = version.Version._RepoVersion(project) + + assert result == ("v2.0-1-g12345678", "Tue, 25 Aug") + project.bare_git.log.assert_called_once_with( + "-1", "--format=%(describe)%n%cD", "HEAD" + ) + project.bare_git.describe.assert_not_called() + + +def test_repo_version_keeps_old_git_fallback( + monkeypatch: pytest.MonkeyPatch, +) -> None: + project = mock.MagicMock() + project.bare_git.describe.return_value = "v2.0" + project.bare_git.log.return_value = "Tue, 25 Aug" + monkeypatch.setattr(version, "git_require", lambda _version: False) + + result = version.Version._RepoVersion(project) + + assert result == ("v2.0", "Tue, 25 Aug") + project.bare_git.describe.assert_called_once_with("HEAD") + project.bare_git.log.assert_called_once_with("-1", "--format=%cD", "HEAD")