concinnity_dev/command/
version.rs1use std::sync::OnceLock;
7
8pub const VERSION: &str = env!("CARGO_PKG_VERSION");
13
14const COMMIT: &str = env!("CONCINNITY_COMMIT");
18const STAMP_DATE: &str = env!("CONCINNITY_STAMP_DATE");
19
20const NAME: &str = "concinnity";
23
24pub fn version() -> std::io::Result<()> {
26 println!("{}", version_line());
27 Ok(())
28}
29
30pub fn version_details() -> &'static str {
35 static DETAILS: OnceLock<String> = OnceLock::new();
36 DETAILS.get_or_init(|| details(VERSION, COMMIT, STAMP_DATE))
37}
38
39pub fn version_line() -> String {
41 format!("{NAME} {}", version_details())
42}
43
44fn details(version: &str, commit: &str, date: &str) -> String {
48 match (commit.is_empty(), date.is_empty()) {
49 (false, false) => format!("{version} ({commit} {date})"),
50 (false, true) => format!("{version} ({commit})"),
51 (true, false) => format!("{version} ({date})"),
52 (true, true) => version.to_string(),
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn a_commit_build_names_the_commit_and_its_date() {
62 assert_eq!(
63 details("0.19.0", "c980f4866", "2026-06-30"),
64 "0.19.0 (c980f4866 2026-06-30)"
65 );
66 }
67
68 #[test]
69 fn a_build_off_no_checkout_labels_the_date_as_the_build_date() {
70 assert_eq!(details("0.19.0", "", "2026-08-30"), "0.19.0 (2026-08-30)");
71 }
72
73 #[test]
74 fn a_stamp_missing_a_part_drops_only_that_part() {
75 assert_eq!(details("0.19.0", "c980f4866", ""), "0.19.0 (c980f4866)");
76 assert_eq!(details("0.19.0", "", ""), "0.19.0");
77 }
78
79 #[test]
82 fn the_line_is_the_name_then_the_details() {
83 assert_eq!(version_line(), format!("concinnity {}", version_details()));
84 assert!(version_details().starts_with(VERSION));
85 }
86
87 #[test]
88 fn the_version_is_a_dotted_release() {
89 let parts: Vec<&str> = VERSION.split('.').collect();
90 assert_eq!(parts.len(), 3, "{VERSION} is not major.minor.patch");
91 assert!(
92 parts[0].chars().all(|c| c.is_ascii_digit()),
93 "{VERSION} has a non-numeric major"
94 );
95 }
96
97 #[test]
100 fn the_build_stamp_carries_a_date() {
101 assert!(!STAMP_DATE.is_empty(), "the build script stamped no date");
102 }
103}