#[cfg(feature = "semver")]
pub fn parse_versions<'a, T>(
name_and_versions: T,
) -> impl Iterator<Item = (&'a str, semver::Version)>
where
T: IntoIterator<Item = &'a (&'a str, &'a str)>,
{
fn parse_version<'a>(t: &'a (&'a str, &'a str)) -> (&'a str, semver::Version) {
(t.0, t.1.parse().unwrap())
}
name_and_versions.into_iter().map(parse_version)
}
#[cfg(feature = "chrono")]
pub fn strptime(s: &str) -> chrono::DateTime<chrono::offset::Utc> {
chrono::DateTime::parse_from_rfc2822(s)
.unwrap()
.with_timezone(&chrono::offset::Utc)
}
#[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)>, git2::Error> {
match git2::Repository::discover(root) {
Ok(repo) => {
let head_ref = repo.head()?;
let branch = {
if !repo.head_detached()? {
head_ref.name()
} else {
None
}
};
let commit = head_ref.peel_to_commit()?.id();
Ok(Some((
branch.map(ToString::to_string),
format!("{}", commit),
)))
}
Err(ref e)
if e.class() == git2::ErrorClass::Repository
&& e.code() == git2::ErrorCode::NotFound =>
{
Ok(None)
}
Err(e) => Err(e),
}
}
#[must_use]
pub fn detect_ci() -> Option<super::CIPlatform> {
super::CIPlatform::detect_from_envmap(&super::get_environment())
}