diff --git a/project.py b/project.py index 3870ad379..caeaa5211 100644 --- a/project.py +++ b/project.py @@ -3945,6 +3945,24 @@ class Project: return self.rev_parse(HEAD) return symbolic_head except GitError as e: + # `git rev-parse --symbolic-full-name HEAD` will fail for unborn + # branches, so try symbolic-ref before falling back to raw file + # parsing. + try: + p = GitCommand( + self._project, + ["symbolic-ref", "-q", HEAD], + bare=True, + gitdir=self._gitdir, + capture_stdout=True, + capture_stderr=True, + log_as_error=False, + ) + if p.Wait() == 0: + return p.stdout.rstrip("\n") + except GitError: + pass + logger.warning( "project %s: unparseable HEAD; trying to recover.\n" "Check that HEAD ref in .git/HEAD is valid. The error " diff --git a/tests/test_project.py b/tests/test_project.py index 7c50ad52a..501707eaf 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -19,6 +19,7 @@ import os from pathlib import Path import subprocess import tempfile +from typing import Optional import unittest import utils_for_test @@ -45,6 +46,9 @@ class FakeProject: ) self.config = git_config.GitConfig.ForRepository(gitdir=self.gitdir) + def RelPath(self, local: Optional[bool] = None) -> str: + return self.name + class ReviewableBranchTests(unittest.TestCase): """Check ReviewableBranch behavior.""" @@ -98,6 +102,29 @@ class ProjectTests(unittest.TestCase): "abcd00%21%21_%2b", ) + @unittest.skipUnless( + utils_for_test.supports_reftable(), + "git reftable support is required for this test", + ) + def test_get_head_unborn_reftable(self): + with tempfile.TemporaryDirectory(prefix="repo-tests") as tempdir: + subprocess.check_call( + [ + "git", + "-c", + "init.defaultRefFormat=reftable", + "init", + "-q", + tempdir, + ] + ) + fakeproj = FakeProject(tempdir) + expected = subprocess.check_output( + ["git", "-C", tempdir, "symbolic-ref", "-q", "HEAD"], + encoding="utf-8", + ).strip() + self.assertEqual(expected, fakeproj.work_git.GetHead()) + class CopyLinkTestCase(unittest.TestCase): """TestCase for stub repo client checkouts.