#[cfg(feature = "git2")]
pub fn get_repo_description(root: &std::path::Path) -> Result<Option<(String, bool)>, git2::Error> {
match git2::Repository::discover(root) {
Ok(repo) => {
let mut desc_opt = git2::DescribeOptions::new();
desc_opt.describe_tags().show_commit_oid_as_fallback(true);
let tag = repo
.describe(&desc_opt)
.and_then(|desc| desc.format(None))?;
let mut st_opt = git2::StatusOptions::new();
st_opt.include_ignored(false);
st_opt.include_untracked(false);
let dirty = repo
.statuses(Some(&mut st_opt))?
.iter()
.any(|status| !matches!(status.status(), git2::Status::CURRENT));
Ok(Some((tag, dirty)))
}
Err(ref e)
if e.class() == git2::ErrorClass::Repository
&& e.code() == git2::ErrorCode::NotFound =>
{
Ok(None)
}
Err(e) => Err(e),
}
}
#[cfg(feature = "git2")]
pub fn get_repo_head(
root: &std::path::Path,
) -> Result<Option<(Option<String>, String, String)>, git2::Error> {
match git2::Repository::discover(root) {
Ok(repo) => {
let head_ref = repo.head()?;
let branch = {
if repo.head_detached()? {
None
} else {
head_ref.name().ok()
}
};
let head = head_ref.peel_to_commit()?;
let commit = head.id();
let commit_short = head.into_object().short_id()?;
Ok(Some((
branch.map(ToString::to_string),
format!("{commit}"),
commit_short.as_str().unwrap_or_default().to_string(),
)))
}
Err(ref e)
if e.class() == git2::ErrorClass::Repository
&& e.code() == git2::ErrorCode::NotFound =>
{
Ok(None)
}
Err(e) => Err(e),
}
}