libgit2 / pygit2

Python bindings for libgit2
https://www.pygit2.org/
Other
1.59k stars 383 forks source link

Repository.resolve_refish does not return a commit if given annotated tag SHA #1082

Open tomaszpietruszka-globality opened 3 years ago

tomaszpietruszka-globality commented 3 years ago

The repository.resolve_refish function is meant to return a commit object as the first element of the tuple ( source ).

However, if given a SHA of an annotated tag, it returns a tag object instead, which causes problems downstream.

The SHA of the target commit is available under result.target (see below)

How to reproduce:

Execute the following (clone the pygit2 repo into a temporary dir, create an annotated tag):

import pygit2
from pathlib import Path
import tempfile

repo_dir = tempfile.TemporaryDirectory()
repo_path = Path(repo_dir.name)

repo = pygit2.clone_repository("https://github.com/libgit2/pygit2.git", repo_path)
head_sha = repo.head.peel().id

old = repo.create_tag(
    'test_annotated_tag',
    head_sha,
    pygit2.GIT_OBJ_COMMIT,
    pygit2.Signature('John Doe', 'jdoe@example.com', 12347, 0),
    'message'
)

commit, ref = repo.resolve_refish(str(old))

Then we can investigate the results:

In [2]: commit  # not really a commit!
Out[2]: <pygit2.Object{tag:66986bf4eb1e47c3049f5a146609f0aa7b64757d}>

In [3]: commit.target
Out[3]: e2c0fdbfbd7f84374f8c7a3df256547b7ea99192

In [4]: head_sha
Out[4]: e2c0fdbfbd7f84374f8c7a3df256547b7ea99192
tomaszpietruszka-globality commented 3 years ago

(copying from https://github.com/iterative/dvc/issues/6255 for visibility)

Another way of reproducing: (please note: the 3rd command includes the output of the second one (the tag SHA) - so it requires a manual edit when reproducing):

~ ❯ mkdir repo; cd repo; git init; touch file; git add file; git commit -m "first commit"; git tag -a "new_tag" -m "tag message"                                                                                                      test
Initialized empty Git repository in /Users/tomaszpietruszka/repo/.git/
[master (root-commit) f5c40fd] first commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 file
~/repo master ❯ git show-ref --tags                                                                                                                                                                                                   test
b3f85c779d0a9fae876284efd166cd2af48df819 refs/tags/new_tag
~/repo master ❯ python -c "from pygit2 import Repository; r = Repository('.'); print(r.resolve_refish('new_tag')); print(r.resolve_refish('b3f85c779d0a9fae876284efd166cd2af48df819'))"                                               test
(<pygit2.Object{commit:f5c40fd1f5806fc9a2646697497bf7b3e7bf9072}>, <_pygit2.Reference object at 0x10452bcb0>)
(<pygit2.Object{tag:b3f85c779d0a9fae876284efd166cd2af48df819}>, None)

(the last line should have a commit object, not a tag object)

My setup:

~ ❯ pip freeze | grep pygit
pygit2==1.6.1
~ ❯ python -c "import pygit2; print(pygit2.LIBGIT2_VER)" 
(1, 1, 0)