如何检查是否标记了HEAD

时间:2017-11-26 20:16:09

标签: git rust

这是我尝试过的一个例子:

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

我错过了什么?

2 个答案:

答案 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);
}

这只处理轻量级标记,这是您的示例所使用的。

另见: