c - 从 revwalk 提交中获取带注释的标签

标签 c libgit2

我想浏览包含标签的存储库日志。到目前为止,我可以打印出所有提交的所有 SHA,包括带有 revwalk 的标签。但是,每次我想使用提交 oid 提取标签信息时,我都会收到错误

"The requested type does not match the type in ODB"

我可以看到 revwalk 报告的标签 SHA 包含 git show-ref --tags 报告的 SHA 所以我不知道为什么标签查找不起作用。

这是我使用的简化代码:

int error = 0;
git_oid oid;

git_revwalk *walk;
error = git_revwalk_new(&walk, m_repo);  

git_revwalk_sorting(walk,
                    GIT_SORT_TOPOLOGICAL |
                    GIT_SORT_TIME);

git_revwalk_push_head(walk);
//git_revwalk_hide_glob(walk, "tags/*"); -- I want to see tags so I commented this one 

while(git_revwalk_next(&oid, walk) == 0)
{
    git_commit *commit;
    char oidstr[10] = {0};

    if(git_commit_lookup(&commit, m_repo, &oid)==0)
    {

        git_tag *tag = NULL;
        int error = git_tag_lookup(&tag, m_repo, &oid);
        if(error==0)
        {
            wxString tname(git_tag_name(tag));
            data.push_back("["+tname+"] "+cltStr);
        }
        else
        {
            //It always land here with error no -3 and message: The requested type does not match the type in ODB
        }

        git_tag_free(tag);

        const git_signature *author = git_commit_author(commit); 
    }
    git_commit_free(commit);
}
git_revwalk_free(walk); 

长话短说

当我有 git_tag 对象时,我可以获得目标提交。现在我有了目标提交,那么如何获取该提交下的标签呢?类似于 git tag --points-at commit_SHA

更新

在 Carlos 的回答之后是我的新代码。现在的挑战是如何获得 git_tag*。如您所见,我有 git_reference*(名为 ref),但我不知道如何将其转换为 git_tag*

git_reference_iterator *iter = NULL;
git_reference *ref = NULL;

git_reference_iterator_glob_new(&iter, m_repo, "refs/tags/*");

while(git_reference_next(&ref, iter) == 0)
{
    git_object *target = NULL;
    git_object *obj;

    const git_oid *targetId = git_reference_target(ref);
    git_object_lookup(&obj, m_repo, targetId, GIT_OBJ_ANY);

    git_object_peel(&target, obj, GIT_OBJ_COMMIT);

    if(git_oid_equal(git_commit_id(commit), git_commit_id((git_commit*)target))==1)
    {
        //tag found
        //how do I get a git_tag* here? 
    } 
    git_object_free(obj);
    git_reference_free(ref);
    git_object_free(target); 
}

最佳答案

带注释的标签是它自己的对象,它作为对象图的根存在。 IE。它们指向对象,但没有任何东西指向它们[0],所以如果你想弄清楚反向映射,你需要自己保留列表。这就是 git tag --points-at 的反向映射所做的:获取标签列表及其指向的内容,然后在该列表中查找您感兴趣的 id。

使用 libgit2,您可以通过使用引用迭代器查看 refs/tags/ 下的任何内容来做到这一点 (git_reference_iterator_glob_new(&iter, repo, "refs/tags/*")) 并获取引用的目标 (git_reference_target()),使用 git_object_peel() 进行提交(或您感兴趣的任何其他对象类型)然后将该对象的 ID 与您要查找的 ID 进行比较。

就问题中的代码而言,git_tag_lookup 与所有其他对象查找函数一样,查找您要求的带注释的标签(git_tag 对象) .如果您传入提交的 ID,那么它将加载该提交并发现类型不匹配并给出此错误。

[0]虽然标签可以指向其他标签,但这与本例无关

更新

更新后的代码需要做的是您之前正在做的事情。使用 git_tag_lookup() 查找一个 git_tag 对象,并传入引用目标作为要查找的 id。但是我们知道并不是所有的标签引用都会指向一个标签对象。在许多项目中,标签直接指向提交。

您可以再次使用 git_object_peel() 尝试获取标签 (GIT_OBJ_TAG),如果没有带注释的标签,将返回错误。

但您还应该注意,如果您尝试复制 git tag --points-at,它并不关心链中是否有带注释的标签。只要可以将特定标记引用解析为您提供的提交,它就会返回该结果。

关于c - 从 revwalk 提交中获取带注释的标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36528576/

相关文章:

c - 将指针的值分配给其他指针时,只读位置分配错误?

在 c 中的 main() 中调用 main()

c - scanf 需要比请求更多的输入

C - 内存被释放后访问数据?

libgit2 - 如何在 gitattributes 中应用语言的差异规则

c - git diff 仅一个文件

tfs - 如何在 TFS Build 中使用私有(private)存储库配置 libgit2?

c - C语言中如何将字符串转换为浮点型

ios - 如何编译 libgit2 并创建 xcode 使用的静态库

c - checkout 新分支时无法更改文件模式