Skip to content

Commit

Permalink
pygit: handle annotated tags in resolve_refish (iterative#6274)
Browse files Browse the repository at this point in the history
  • Loading branch information
pmrowla authored Jul 2, 2021
1 parent b8d9800 commit cfcb7e1
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 6 deletions.
21 changes: 15 additions & 6 deletions dvc/scm/git/backend/pygit2.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ def _refdb(self):

return RefdbFsBackend(self.repo)

def _resolve_refish(self, refish: str):
from pygit2 import GIT_OBJ_COMMIT, Tag

commit, ref = self.repo.resolve_refish(refish)
if isinstance(commit, Tag):
ref = commit
commit = commit.peel(GIT_OBJ_COMMIT)
return commit, ref

@property
def default_signature(self):
try:
Expand Down Expand Up @@ -153,7 +162,7 @@ def checkout(
if branch == "-":
branch = "@{-1}"
try:
commit, ref = self.repo.resolve_refish(branch)
commit, ref = self._resolve_refish(branch)
except (KeyError, GitError):
raise RevError(f"unknown Git revision '{branch}'")
self.repo.checkout_tree(commit, strategy=checkout_strategy)
Expand Down Expand Up @@ -213,7 +222,7 @@ def resolve_rev(self, rev: str) -> str:
from pygit2 import GitError

try:
commit, _ref = self.repo.resolve_refish(rev)
commit, _ref = self._resolve_refish(rev)
return str(commit.id)
except (KeyError, GitError):
pass
Expand All @@ -233,7 +242,7 @@ def resolve_commit(self, rev: str) -> "GitCommit":
from pygit2 import GitError

try:
commit, _ref = self.repo.resolve_refish(rev)
commit, _ref = self._resolve_refish(rev)
except (KeyError, GitError):
raise SCMError(f"Invalid commit '{rev}'")
return GitCommit(
Expand Down Expand Up @@ -307,12 +316,12 @@ def get_refs_containing(self, rev: str, pattern: Optional[str] = None):
from pygit2 import GitError

def _contains(repo, ref, search_commit):
commit, _ref = self.repo.resolve_refish(ref)
commit, _ref = self._resolve_refish(ref)
base = repo.merge_base(search_commit.id, commit.id)
return base == search_commit.id

try:
search_commit, _ref = self.repo.resolve_refish(rev)
search_commit, _ref = self._resolve_refish(rev)
except (KeyError, GitError):
raise SCMError(f"Invalid rev '{rev}'")

Expand Down Expand Up @@ -397,7 +406,7 @@ def _apply(index):

# libgit2 stash apply only accepts refs/stash items by index. If rev is
# not in refs/stash, we will push it onto the stash, and then pop it
commit, _ref = self.repo.resolve_refish(rev)
commit, _ref = self._resolve_refish(rev)
stash = self.repo.references.get(Stash.DEFAULT_STASH)
if stash:
for i, entry in enumerate(stash.log()):
Expand Down
27 changes: 27 additions & 0 deletions tests/unit/scm/test_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,3 +553,30 @@ def test_add(tmp_dir, scm, git):
assert set(staged["modify"]) == {"dir/baz"}
assert len(unstaged) == 1
assert len(untracked) == 1


@pytest.mark.parametrize("use_sha", [True, False])
def test_pygit_resolve_refish(tmp_dir, scm, git, use_sha):
import pygit2

if git.test_backend != "pygit2":
pytest.skip()

tmp_dir.scm_gen("foo", "foo", commit="foo")
head = scm.get_rev()
tag = "my_tag"
scm.gitpython.git.tag("-a", tag, "-m", "create annotated tag")

if use_sha:
# refish will be annotated tag SHA (not commit SHA)
ref = git.pygit2.repo.references.get(f"refs/tags/{tag}")
refish = str(ref.target)
else:
refish = tag

assert refish != head
commit, ref = git.pygit2._resolve_refish(refish)
assert isinstance(commit, pygit2.Commit)
assert str(commit.id) == head
if not use_sha:
assert ref.name == f"refs/tags/{tag}"

0 comments on commit cfcb7e1

Please sign in to comment.