use std::process::Command;
fn main() {
let dir = env!("CARGO_MANIFEST_DIR");
let version = match describe(dir) {
Some(v) => {
rerun(dir);
v
}
None => env!("CARGO_PKG_VERSION").to_string(),
};
println!("cargo:rustc-env=MKTOOL_VERSION={version}");
}
fn describe(dir: &str) -> Option<String> {
let top = git(dir, &["rev-parse", "--show-toplevel"])?;
if std::fs::canonicalize(top).ok()? != std::fs::canonicalize(dir).ok()? {
return None;
}
let rev = git(dir, &["describe", "--always", "--dirty", "--exclude=*"])?;
if !rev.ends_with("-dirty")
&& let Some(tag) = git(dir, &["describe", "--tags", "--exact-match"])
{
return Some(tag.strip_prefix('v').unwrap_or(&tag).to_string());
}
Some(format!("{}-{}", env!("CARGO_PKG_VERSION"), rev))
}
fn rerun(dir: &str) {
for p in ["HEAD", "logs/HEAD", "index", "refs", "packed-refs"] {
if let Some(path) = git(dir, &["rev-parse", "--git-path", p]) {
println!("cargo:rerun-if-changed={path}");
}
}
if let Some(files) = git(dir, &["ls-files", "--full-name"]) {
for f in files.lines() {
println!("cargo:rerun-if-changed={dir}/{f}");
}
}
}
fn git(dir: &str, args: &[&str]) -> Option<String> {
let out =
Command::new("git").arg("-C").arg(dir).args(args).output().ok()?;
out.status
.success()
.then(|| String::from_utf8_lossy(&out.stdout).trim().to_string())
.filter(|s| !s.is_empty())
}