use std::sync::OnceLock;
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
const COMMIT: &str = env!("CONCINNITY_COMMIT");
const STAMP_DATE: &str = env!("CONCINNITY_STAMP_DATE");
const NAME: &str = "concinnity";
pub fn version() -> std::io::Result<()> {
println!("{}", version_line());
Ok(())
}
pub fn version_details() -> &'static str {
static DETAILS: OnceLock<String> = OnceLock::new();
DETAILS.get_or_init(|| details(VERSION, COMMIT, STAMP_DATE))
}
pub fn version_line() -> String {
format!("{NAME} {}", version_details())
}
fn details(version: &str, commit: &str, date: &str) -> String {
match (commit.is_empty(), date.is_empty()) {
(false, false) => format!("{version} ({commit} {date})"),
(false, true) => format!("{version} ({commit})"),
(true, false) => format!("{version} ({date})"),
(true, true) => version.to_string(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_commit_build_names_the_commit_and_its_date() {
assert_eq!(
details("0.19.0", "c980f4866", "2026-06-30"),
"0.19.0 (c980f4866 2026-06-30)"
);
}
#[test]
fn a_build_off_no_checkout_labels_the_date_as_the_build_date() {
assert_eq!(details("0.19.0", "", "2026-08-30"), "0.19.0 (2026-08-30)");
}
#[test]
fn a_stamp_missing_a_part_drops_only_that_part() {
assert_eq!(details("0.19.0", "c980f4866", ""), "0.19.0 (c980f4866)");
assert_eq!(details("0.19.0", "", ""), "0.19.0");
}
#[test]
fn the_line_is_the_name_then_the_details() {
assert_eq!(version_line(), format!("concinnity {}", version_details()));
assert!(version_details().starts_with(VERSION));
}
#[test]
fn the_version_is_a_dotted_release() {
let parts: Vec<&str> = VERSION.split('.').collect();
assert_eq!(parts.len(), 3, "{VERSION} is not major.minor.patch");
assert!(
parts[0].chars().all(|c| c.is_ascii_digit()),
"{VERSION} has a non-numeric major"
);
}
#[test]
fn the_build_stamp_carries_a_date() {
assert!(!STAMP_DATE.is_empty(), "the build script stamped no date");
}
}