从revwalk commit获取带注释的标签

时间:2016-04-10 10:26:27

标签: c libgit2

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

  

“请求的类型与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); 

TL; DR

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

的东西

更新

卡洛斯回答之后是我的新代码。现在的挑战是如何获得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); 
}

1 个答案:

答案 0 :(得分:1)

带注释的标记是它自己的对象,它作为对象图的根存在。 I.E.他们指向对象,但没有任何东西指向他们[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它不关心链中是否有注释标签。只要特定的标记引用可以解析为您提供的提交,它就会返回该结果。