从 revwalk 提交中获取带注释的标签
Get Annotated Tags from revwalk commit
我想浏览包含标签的存储库日志。到目前为止,我可以打印出所有提交的所有 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);
TL;DR
当我有 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
),如果没有带注释的标签,这将 return 出错。
但您还应该注意,如果您试图复制 git tag --points-at
,它并不关心链中是否有带注释的标签。只要可以将特定标记引用解析为您提供的提交,它就会 return 结果。
我想浏览包含标签的存储库日志。到目前为止,我可以打印出所有提交的所有 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);
TL;DR
当我有 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
),如果没有带注释的标签,这将 return 出错。
但您还应该注意,如果您试图复制 git tag --points-at
,它并不关心链中是否有带注释的标签。只要可以将特定标记引用解析为您提供的提交,它就会 return 结果。