1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use anyhow::{Context, Result};
use git_repository as git;
pub fn describe(
mut repo: git::Repository,
rev_spec: Option<&str>,
mut out: impl std::io::Write,
mut err: impl std::io::Write,
describe::Options {
all_tags,
all_refs,
first_parent,
always,
statistics,
max_candidates,
long_format,
}: describe::Options,
) -> Result<()> {
repo.object_cache_size_if_unset(4 * 1024 * 1024);
let commit = match rev_spec {
Some(spec) => repo.rev_parse_single(spec)?.object()?.try_into_commit()?,
None => repo.head_commit()?,
};
use git::commit::describe::SelectRef::*;
let select_ref = if all_refs {
AllRefs
} else if all_tags {
AllTags
} else {
Default::default()
};
let resolution = commit
.describe()
.names(select_ref)
.traverse_first_parent(first_parent)
.id_as_fallback(always)
.max_candidates(max_candidates)
.try_resolve()?
.with_context(|| format!("Did not find a single candidate ref for naming id '{}'", commit.id))?;
if statistics {
writeln!(err, "traversed {} commits", resolution.outcome.commits_seen)?;
}
let mut describe_id = resolution.format()?;
describe_id.long(long_format);
writeln!(out, "{}", describe_id)?;
Ok(())
}
pub mod describe {
#[derive(Debug, Clone)]
pub struct Options {
pub all_tags: bool,
pub all_refs: bool,
pub first_parent: bool,
pub always: bool,
pub long_format: bool,
pub statistics: bool,
pub max_candidates: usize,
}
}