use std::fmt::{self, Display, Formatter};
pub use git_testament_derive::git_testament;
#[derive(Debug)]
pub enum GitModification<'a> {
Added(&'a [u8]),
Removed(&'a [u8]),
Modified(&'a [u8]),
Untracked(&'a [u8]),
}
#[derive(Debug)]
pub enum CommitKind<'a> {
NoRepository(&'a str, &'a str),
NoCommit(&'a str, &'a str),
NoTags(&'a str, &'a str),
FromTag(&'a str, &'a str, &'a str, usize),
}
#[derive(Debug)]
pub struct GitTestament<'a> {
pub commit: CommitKind<'a>,
pub modifications: &'a [GitModification<'a>],
pub branch_name: Option<&'a str>,
}
pub const EMPTY_TESTAMENT: GitTestament = GitTestament {
commit: CommitKind::NoRepository("unknown", "unknown"),
modifications: &[],
branch_name: None,
};
impl<'a> GitTestament<'a> {
#[doc(hidden)]
pub fn _render_with_version(
&self,
pkg_version: &str,
trusted_branch: Option<&'static str>,
) -> String {
match self.commit {
CommitKind::FromTag(tag, hash, date, _) => {
let trusted = match trusted_branch {
Some(_) => {
if self.branch_name == trusted_branch {
self.modifications.is_empty()
} else {
false
}
}
None => false,
};
if trusted {
format!(
"{}",
GitTestament {
commit: CommitKind::FromTag(pkg_version, hash, date, 0),
..*self
}
)
} else if tag.find(&pkg_version).is_some() {
format!("{}", self)
} else {
format!("{} :: {}", pkg_version, self)
}
}
_ => format!("{}", self),
}
}
}
#[macro_export]
macro_rules! render_testament {
( $testament:expr ) => {
$testament._render_with_version(env!("CARGO_PKG_VERSION"), None)
};
( $testament:expr, $trusted_branch:expr ) => {
$testament._render_with_version(env!("CARGO_PKG_VERSION"), Some($trusted_branch))
};
}
impl<'a> Display for CommitKind<'a> {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
match self {
CommitKind::NoRepository(crate_ver, build_date) => {
fmt.write_fmt(format_args!("{} ({})", crate_ver, build_date))
}
CommitKind::NoCommit(crate_ver, build_date) => {
fmt.write_fmt(format_args!("{} (uncommitted {})", crate_ver, build_date))
}
CommitKind::NoTags(commit, when) => {
fmt.write_fmt(format_args!("unknown ({} {})", &commit[..9], when))
}
CommitKind::FromTag(tag, commit, when, depth) => {
if *depth > 0 {
fmt.write_fmt(format_args!(
"{}+{} ({} {})",
tag,
depth,
&commit[..9],
when
))
} else {
fmt.write_fmt(format_args!("{} ({} {})", tag, &commit[..9], when))
}
}
}
}
}
impl<'a> Display for GitTestament<'a> {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
self.commit.fmt(fmt)?;
if !self.modifications.is_empty() {
fmt.write_fmt(format_args!(
" dirty {} modification{}",
self.modifications.len(),
if self.modifications.len() > 1 {
"s"
} else {
""
}
))?;
}
Ok(())
}
}