use anyhow::{Context, Result}; pub fn describe( mut repo: gix::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 gix::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, } }