这是我尝试过的一个例子:
cd /tmp
cargo new --bin foo
cd foo
cat > src/main.rs << EOF
extern crate git2;
use git2::{Repository, ObjectType};
fn main() {
let repo = Repository::open("/tmp/foo").unwrap();
let git_ref = repo.head().unwrap();
git_ref.peel(ObjectType::Tag).unwrap();
}
EOF
cargo add git2
git add .
git commit --message "foo"
git tag foo
cargo run
我感到恐慌:
线程'main'在'
Result::unwrap()
上对'Err
值感到恐慌:错误{code:-12,klass:11,message:“id \'的git_object''33030777b0a6b61f631be64c3f1cb7d66b8f3082 \'不能被成功剥离成标签(git_otype = 4)。“ }',/ checkout / src / libcore / result.rs:906:4
我错过了什么?
答案 0 :(得分:4)
HEAD
通常不会引用标签;它引用另一个引用(例如refs/heads/master
),它引用一个提交,引用一棵树。
Peeling ,据我所知,是解除引用其他对象或引用引用的对象的过程。但是,由于HEAD
未引用标记,因此您无法剥离HEAD
并希望获得标记。
Git有两个单独的标签概念。 标记引用只是refs/tags/
下的引用。 Annotated tags 是Git数据库中的对象,就像提交,树和blob一样。标记引用可以引用任何类型的对象,但通常它们将引用提交或标记对象。
无论您是注释标签还是任何类型的标签,第一步都是相同的:您必须迭代refs/tags/
中的引用并检查它们中的任何一个是否与{ {1}}去皮。如果您对带注释的标签感兴趣,可以检查标签引用是否剥离到标签对象。
答案 1 :(得分:3)
作为Francis Gagné says,您无法从提交中获取标记 - 您必须采用其他方式。此外,提交可以有多个标记。适当的数据结构是提交引用到标记引用列表的映射:
extern crate git2;
use std::collections::BTreeMap;
use git2::Repository;
fn main() {
let repo = Repository::open("/tmp/foo").unwrap();
let tag_names = repo.tag_names(None).unwrap();
let tag_and_refs = tag_names.iter()
.flat_map(|name| name)
.flat_map(|name| {
let full_tag = format!("refs/tags/{}", name);
repo.find_reference(&full_tag).map(|reference| (name, reference))
});
let mut refs_to_tags = BTreeMap::new();
for (name, reference) in tag_and_refs {
refs_to_tags.entry(reference).or_insert_with(Vec::new).push(name);
}
let git_ref = repo.head().unwrap();
let tags = &refs_to_tags[&git_ref];
println!("tags for HEAD: {:?}", tags);
}
这只处理轻量级标记,这是您的示例所使用的。
另见: