//! Capture the git HEAD sha at compile time and expose it as `AURA_COMMIT`, so //! `member::sim_optimal_manifest`'s `RunManifest.commit` is self-identifying //! (C8/C18 audit trail: this run = this commit) even when aura-runner is //! consumed by a downstream World program with no `aura` binary involved. //! `cargo:rustc-env` is per-compilation-unit (aura-cli's own `build.rs` does //! not propagate its env to this crate's `option_env!("AURA_COMMIT")`), so //! aura-runner needs this identical capture rather than inheriting the //! shell's. When there is no git (e.g. a packaged source tree), `AURA_COMMIT` //! is left unset and `member.rs`'s `option_env!(...)` fallback to `"unknown"` //! holds. //! //! Zero runtime/build dependency by commitment (C14/C18): we shell out to the //! `git` already in PATH rather than pulling in a libgit crate. Verbatim twin //! of `aura-cli/build.rs` (#295) — same repo-root depth (`crates/aura-runner` //! sits beside `crates/aura-cli`), same capture logic, so the two crates' //! `AURA_COMMIT` cannot disagree within one build. use std::path::Path; use std::process::Command; fn main() { // build.rs runs with CWD = the crate dir (crates/aura-runner); the repo // root, which owns `.git`, is two levels up. let repo_root = Path::new("../.."); let git_dir = repo_root.join(".git"); if !git_dir.exists() { // No git: emit nothing; the `"unknown"` fallback in member.rs holds. return; } // Re-run when HEAD moves or its working tree changes so AURA_COMMIT never // goes stale across commits. `.git/logs/HEAD` grows on every HEAD move // (commit, checkout, reset), covering branch switches without resolving the // current branch's ref file by hand. println!("cargo:rerun-if-changed=../../.git/HEAD"); println!("cargo:rerun-if-changed=../../.git/logs/HEAD"); let head = run_git(repo_root, &["rev-parse", "HEAD"]); let Some(head) = head else { return }; // Append `-dirty` when the working tree has uncommitted changes, so a run // built off an unclean tree is not silently attributed to the clean HEAD. let dirty = run_git(repo_root, &["status", "--porcelain"]) .map(|s| !s.is_empty()) .unwrap_or(false); let commit = if dirty { format!("{head}-dirty") } else { head }; println!("cargo:rustc-env=AURA_COMMIT={commit}"); } /// Run `git ` in `dir`, returning trimmed stdout on success, `None` on any /// failure (git missing, non-zero exit, non-utf8). Never panics: a build must /// not fail because git is unavailable. fn run_git(dir: &Path, args: &[&str]) -> Option { let out = Command::new("git").current_dir(dir).args(args).output().ok()?; if !out.status.success() { return None; } let s = String::from_utf8(out.stdout).ok()?; Some(s.trim().to_string()) }