diff --git a/tagbot/action/git.py b/tagbot/action/git.py index 04c9a5b3..b0fae6c2 100644 --- a/tagbot/action/git.py +++ b/tagbot/action/git.py @@ -70,6 +70,16 @@ def check(self, *argv: str, repo: Optional[str] = "") -> bool: except Abort: return False + def commit_sha_of_tree(self, tree: str) -> Optional[str]: + """Get the commit SHA of a corresponding tree SHA.""" + # We need --all in case the registered commit isn't on the default branch. + for line in self.command("log", "--all", "--format=%H %T").splitlines(): + # The format of each line is " ". + c, t = line.split() + if t == tree: + return c + return None + def commit_sha_of_default(self) -> str: """Get the commit SHA of the default branch.""" return self.command("rev-parse", self._default_branch) diff --git a/tagbot/action/repo.py b/tagbot/action/repo.py index aee0f5df..29f4e130 100644 --- a/tagbot/action/repo.py +++ b/tagbot/action/repo.py @@ -122,7 +122,10 @@ def _commit_sha_of_tree(self, tree: str) -> Optional[str]: sha = self._commit_sha_of_tree_from_branch(branch.name, tree, since) if sha: return sha - return None + # For a valid tree SHA, the only time that we reach here is when a release + # has been made long after the commit was made, which is reasonably rare. + # Fall back to cloning the repo in that case. + return self._git.commit_sha_of_tree(tree) def _commit_sha_of_tag(self, version: str) -> Optional[str]: """Look up the commit SHA of a given tag.""" diff --git a/test/action/test_git.py b/test/action/test_git.py index ff1c74ab..05ad5251 100644 --- a/test/action/test_git.py +++ b/test/action/test_git.py @@ -77,6 +77,14 @@ def test_default_branch(): assert g._default_branch == "master" +def test_commit_sha_of_tree(): + g = _git(command="a b\n c d\n d e\n") + assert g.commit_sha_of_tree("b") == "a" + g.command.assert_called_with("log", "--all", "--format=%H %T") + assert g.commit_sha_of_tree("e") == "d" + assert g.commit_sha_of_tree("c") is None + + def test_commit_sha_of_default(): g = _git(command="abcdef") g._Git__default_branch = "branch" diff --git a/test/action/test_repo.py b/test/action/test_repo.py index 7397b3dc..5db0f9b3 100644 --- a/test/action/test_repo.py +++ b/test/action/test_repo.py @@ -106,6 +106,11 @@ def test_commit_sha_of_tree(): r._commit_sha_of_tree_from_branch.assert_called_once_with("master", "tree", now) assert r._commit_sha_of_tree("tree") == "sha2" r._commit_sha_of_tree_from_branch.assert_called_with("foo", "tree", now) + r._commit_sha_of_tree_from_branch.side_effect = None + r._commit_sha_of_tree_from_branch.return_value = None + r._git.commit_sha_of_tree = Mock(side_effect=["sha", None]) + assert r._commit_sha_of_tree("tree") == "sha" + assert r._commit_sha_of_tree("tree") is None def test_commit_sha_of_tag():