use std::path::{Path, PathBuf};
use std::process::Command;
fn main() {
println!("cargo:rerun-if-env-changed=RETE_SOURCE_REVISION");
let manifest = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap_or_default());
let commit = from_env()
.or_else(|| from_git(&manifest))
.or_else(|| from_vcs_info(&manifest))
.unwrap_or_else(|| "unknown".to_string());
println!("cargo:rustc-env=RETE_GIT_COMMIT={commit}");
println!(
"cargo:rustc-env=RETE_TARGET={}",
std::env::var("TARGET").unwrap_or_else(|_| "unknown".into())
);
println!(
"cargo:rustc-env=RETE_PROFILE={}",
std::env::var("PROFILE").unwrap_or_else(|_| "unknown".into())
);
}
fn clean(s: &str) -> Option<String> {
let s = s.trim();
(s.len() >= 7 && s.len() <= 64 && s.bytes().all(|b| b.is_ascii_hexdigit()))
.then(|| s.to_ascii_lowercase())
}
fn from_env() -> Option<String> {
clean(&std::env::var("RETE_SOURCE_REVISION").ok()?)
}
fn from_git(manifest: &Path) -> Option<String> {
let out = Command::new("git")
.args(["-c", "safe.directory=*", "rev-parse", "HEAD"])
.current_dir(manifest)
.output()
.ok()?;
if !out.status.success() {
return None;
}
let commit = clean(&String::from_utf8_lossy(&out.stdout))?;
if let Some(git_dir) = git_path(manifest, "--git-dir") {
let head = git_dir.join("HEAD");
if head.exists() {
println!("cargo:rerun-if-changed={}", head.display());
}
if let Ok(text) = std::fs::read_to_string(&head) {
if let Some(r) = text.trim().strip_prefix("ref: ") {
let common = git_path(manifest, "--git-common-dir").unwrap_or(git_dir.clone());
for p in [common.join(r), common.join("packed-refs")] {
if p.exists() {
println!("cargo:rerun-if-changed={}", p.display());
}
}
}
}
}
Some(commit)
}
fn git_path(manifest: &Path, flag: &str) -> Option<PathBuf> {
let out = Command::new("git")
.args(["-c", "safe.directory=*", "rev-parse", flag])
.current_dir(manifest)
.output()
.ok()?;
if !out.status.success() {
return None;
}
let p = PathBuf::from(String::from_utf8_lossy(&out.stdout).trim());
Some(if p.is_absolute() { p } else { manifest.join(p) })
}
fn from_vcs_info(manifest: &Path) -> Option<String> {
let text = std::fs::read_to_string(manifest.join(".cargo_vcs_info.json")).ok()?;
let at = text.find("\"sha1\"")?;
let rest = &text[at + 6..];
let start = rest.find('"')? + 1;
let end = start + rest[start..].find('"')?;
clean(&rest[start..end])
}