use std::process::Command;
fn git(args: &[&str]) -> Option<String> {
let out = Command::new("git").args(args).output().ok()?;
if !out.status.success() {
return None;
}
let s = String::from_utf8(out.stdout).ok()?;
let s = s.trim().to_string();
if s.is_empty() { None } else { Some(s) }
}
fn is_release_build(version: &str) -> bool {
println!("cargo:rerun-if-env-changed=MEMSTEAD_RELEASE_VERSION");
if let Ok(declared) = std::env::var("MEMSTEAD_RELEASE_VERSION") {
let declared = declared.trim();
let declared = declared.strip_prefix('v').unwrap_or(declared);
if !declared.is_empty() {
return declared == version;
}
}
let Some(tags) = git(&["tag", "--points-at", "HEAD"]) else {
return false;
};
tags.lines()
.map(str::trim)
.any(|tag| tag == format!("v{version}") || tag == version)
}
fn main() {
if let Some(git_dir) = git(&["rev-parse", "--git-dir"]) {
println!("cargo:rerun-if-changed={git_dir}/HEAD");
println!("cargo:rerun-if-changed={git_dir}/packed-refs");
if let Some(head_ref) = git(&["rev-parse", "--symbolic-full-name", "HEAD"]) {
if head_ref != "HEAD" {
println!("cargo:rerun-if-changed={git_dir}/{head_ref}");
}
}
if let Some(top) = git(&["rev-parse", "--show-toplevel"]) {
for input in ["crates", "Cargo.toml", "Cargo.lock"] {
println!("cargo:rerun-if-changed={top}/{input}");
}
}
}
let sha = git(&["rev-parse", "--short", "HEAD"])
.map(|sha| {
let dirty = git(&[
"status",
"--porcelain",
"--untracked-files=no",
"--",
":/crates",
":/Cargo.toml",
":/Cargo.lock",
])
.is_some();
if dirty { format!("{sha}-dirty") } else { sha }
})
.unwrap_or_default();
let version = std::env::var("CARGO_PKG_VERSION").unwrap_or_default();
let sha = if sha.is_empty() || sha.ends_with("-dirty") || !is_release_build(&version) {
sha
} else {
String::new()
};
println!("cargo:rustc-env=MEMSTEAD_BUILD_SHA={sha}");
}