diff --git a/git_superproject.py b/git_superproject.py index 665b596ec..d1166fe7c 100644 --- a/git_superproject.py +++ b/git_superproject.py @@ -36,7 +36,6 @@ from git_command import git_require from git_command import GitCommand from git_config import IsId from git_config import RepoConfig -from git_refs import GitRefs import platform_utils @@ -189,7 +188,7 @@ class Superproject: if netloc: parts = netloc.split("-review", 1) host = parts[0] - rev = GitRefs(self._work_git).get("HEAD") + rev = self._GetRef("HEAD") return f"{host}/{self.name}@{rev}" return None @@ -314,7 +313,10 @@ class Superproject: # We use --negotiation-tip to speed up the fetch. Superproject branches # do not share commits. So this lets git know it only needs to send # commits reachable from the specified local refs. - rev_commit = GitRefs(self._work_git).get(f"refs/heads/{self.revision}") + negotiation_ref = self.revision + if negotiation_ref and not negotiation_ref.startswith("refs/"): + negotiation_ref = f"refs/heads/{negotiation_ref}" + rev_commit = self._GetRef(negotiation_ref) if negotiation_ref else "" if rev_commit: cmd.extend(["--negotiation-tip", rev_commit]) @@ -347,6 +349,21 @@ class Superproject: return False return True + def _GetRef(self, ref: str) -> str: + """Resolve one local ref without loading the entire ref namespace.""" + p = GitCommand( + None, + ["rev-parse", "--verify", "--quiet", ref], + gitdir=self._work_git, + bare=True, + capture_stdout=True, + capture_stderr=True, + log_as_error=False, + ) + if p.Wait() == 0: + return p.stdout.strip() + return "" + def _LsTree(self): """Gets the commit ids for all projects. diff --git a/tests/test_git_superproject.py b/tests/test_git_superproject.py index 1c22466bd..c28eb8ded 100644 --- a/tests/test_git_superproject.py +++ b/tests/test_git_superproject.py @@ -542,14 +542,15 @@ class SuperprojectTestCase(unittest.TestCase): with mock.patch( "git_superproject.GitCommand", autospec=True ) as mock_git_command: - with mock.patch( - "git_superproject.GitRefs.get", autospec=True - ) as mock_git_refs: + with mock.patch.object( + self._superproject, "_GetRef" + ) as get_ref: instance = mock_git_command.return_value instance.Wait.return_value = 0 - mock_git_refs.side_effect = ["", "1234"] + get_ref.side_effect = ["", "1234"] self.assertTrue(self._superproject._Fetch()) + get_ref.assert_called_with("refs/heads/main") self.assertEqual( # TODO: Once we require Python 3.8+, # use 'mock_git_command.call_args.args'. @@ -572,6 +573,7 @@ class SuperprojectTestCase(unittest.TestCase): # If branch for revision exists, set as --negotiation-tip. self.assertTrue(self._superproject._Fetch()) + get_ref.assert_called_with("refs/heads/main") self.assertEqual( # TODO: Once we require Python 3.8+, # use 'mock_git_command.call_args.args'. @@ -593,3 +595,21 @@ class SuperprojectTestCase(unittest.TestCase): ], ), ) + + def test_GetRef_resolves_only_the_requested_ref(self) -> None: + command = mock.MagicMock(stdout="1234\n") + command.Wait.return_value = 0 + with mock.patch( + "git_superproject.GitCommand", return_value=command + ) as git_command: + self.assertEqual("1234", self._superproject._GetRef("HEAD")) + + git_command.assert_called_once_with( + None, + ["rev-parse", "--verify", "--quiet", "HEAD"], + gitdir=self._superproject._work_git, + bare=True, + capture_stdout=True, + capture_stderr=True, + log_as_error=False, + )