use std::process::Command; fn run_git_command(args: &[&str]) -> Option { Command::new("git") .args(args) .output() .ok() .filter(|output| output.status.success()) .and_then(|output| String::from_utf8(output.stdout).ok()) .map(|s| s.trim().to_owned()) .filter(|s| !s.is_empty()) } fn get_env(env_var: &str) -> Option { match std::env::var(env_var) { | Ok(val) if !val.is_empty() => Some(val), | _ => None, } } fn main() { // built gets the default crate from the workspace. Not sure if this is intended // behavior, but it's what we want. built::write_built_file().expect("Failed to acquire build-time information"); // --- Git Information --- let mut commit_hash = None; let mut commit_hash_short = None; let mut remote_url_web = None; // Get full commit hash if let Some(hash) = get_env("GIT_COMMIT_HASH").or_else(|| run_git_command(&["rev-parse", "HEAD"])) { println!("cargo:rustc-env=GIT_COMMIT_HASH={hash}"); commit_hash = Some(hash); } // Get short commit hash if let Some(short_hash) = get_env("GIT_COMMIT_HASH_SHORT") .or_else(|| run_git_command(&["rev-parse", "--short", "HEAD"])) { println!("cargo:rustc-env=GIT_COMMIT_HASH_SHORT={short_hash}"); commit_hash_short = Some(short_hash); } // Get remote URL and convert to web URL if let Some(remote_url_raw) = get_env("GIT_REMOTE_URL") .or_else(|| run_git_command(&["config", "--get", "remote.origin.url"])) { println!("cargo:rustc-env=GIT_REMOTE_URL={remote_url_raw}"); let web_url = if remote_url_raw.starts_with("https://") { remote_url_raw.trim_end_matches(".git").to_owned() } else if remote_url_raw.starts_with("git@") { remote_url_raw .trim_end_matches(".git") .replacen(':', "/", 1) .replacen("git@", "https://", 1) } else if remote_url_raw.starts_with("ssh://") { remote_url_raw .trim_end_matches(".git") .replacen("git@", "", 1) .replacen("ssh:", "https:", 1) } else { // Assume it's already a web URL or unknown format remote_url_raw }; println!("cargo:rustc-env=GIT_REMOTE_WEB_URL={web_url}"); remote_url_web = Some(web_url); } // Construct remote commit URL if let Some(remote_commit_url) = get_env("GIT_REMOTE_COMMIT_URL") { println!("cargo:rustc-env=GIT_REMOTE_COMMIT_URL={remote_commit_url}"); } else if let (Some(base_url), Some(hash)) = (&remote_url_web, commit_hash.as_ref().or(commit_hash_short.as_ref())) { let commit_page = format!("{base_url}/commit/{hash}"); println!("cargo:rustc-env=GIT_REMOTE_COMMIT_URL={commit_page}"); } // --- Rerun Triggers --- // TODO: The git rerun triggers seem to always run // Rerun if the git HEAD changes println!("cargo:rerun-if-changed=.git/HEAD"); // Rerun if the ref pointed to by HEAD changes (e.g., new commit on branch) if let Some(ref_path) = run_git_command(&["symbolic-ref", "--quiet", "HEAD"]) { println!("cargo:rerun-if-changed=.git/{ref_path}"); } println!("cargo:rerun-if-env-changed=GIT_COMMIT_HASH"); println!("cargo:rerun-if-env-changed=GIT_COMMIT_HASH_SHORT"); println!("cargo:rerun-if-env-changed=GIT_REMOTE_URL"); println!("cargo:rerun-if-env-changed=GIT_REMOTE_COMMIT_URL"); }