use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::{SystemTime, UNIX_EPOCH};
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()?.trim().to_string();
(!s.is_empty()).then_some(s)
}
fn watch(path: &Path) {
if path.exists() {
println!("cargo:rerun-if-changed={}", path.display());
}
}
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH");
if let Some(git_dir) = git(&["rev-parse", "--git-dir"]).map(PathBuf::from) {
let common = git(&["rev-parse", "--git-common-dir"])
.map(PathBuf::from)
.unwrap_or_else(|| git_dir.clone());
watch(&git_dir.join("HEAD"));
if let Some(branch) = git(&["symbolic-ref", "-q", "HEAD"]) {
let loose = common.join(branch);
match loose.parent() {
Some(dir) if !loose.exists() => watch(dir),
_ => watch(&loose),
}
watch(&common.join("packed-refs"));
}
if let Some(hash) = git(&["rev-parse", "--short", "HEAD"]) {
let dirty = git(&["status", "--porcelain", "--untracked-files=no"]).is_some();
println!("cargo:rustc-env=ZC_GIT_HASH={hash}");
println!("cargo:rustc-env=ZC_GIT_DIRTY={}", u8::from(dirty));
}
}
let epoch = std::env::var("SOURCE_DATE_EPOCH")
.ok()
.and_then(|s| s.parse::<u64>().ok())
.unwrap_or_else(|| {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_or(0, |d| d.as_secs())
});
println!("cargo:rustc-env=ZC_BUILD_EPOCH={epoch}");
}