use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::{SystemTime, UNIX_EPOCH};
fn command_stdout(program: &str, args: &[&str]) -> String {
Command::new(program)
.args(args)
.output()
.ok()
.filter(|o| o.status.success())
.and_then(|o| String::from_utf8(o.stdout).ok())
.map(|s| s.trim().to_owned())
.unwrap_or_default()
}
fn run_git(args: &[&str]) -> String {
command_stdout("git", args)
}
fn build_epoch() -> String {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_secs().to_string())
.unwrap_or_default()
}
fn rust_version() -> String {
let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".to_owned());
let version = command_stdout(&rustc, &["--version"]);
if version.starts_with("rustc ") {
return version;
}
let rustup_rustc = command_stdout("rustup", &["which", "rustc"]);
if !rustup_rustc.is_empty() {
let version = command_stdout(&rustup_rustc, &["--version"]);
if version.starts_with("rustc ") {
return version;
}
}
version
}
fn rerun_if_exists(path: &Path) {
if path.exists() {
println!("cargo:rerun-if-changed={}", path.display());
}
}
fn track_git_inputs() {
let git_dir = run_git(&["rev-parse", "--absolute-git-dir"]);
if git_dir.is_empty() {
return;
}
let git_dir = PathBuf::from(git_dir);
let common_git_dir = run_git(&["rev-parse", "--path-format=absolute", "--git-common-dir"]);
let common_git_dir = if common_git_dir.is_empty() {
git_dir.clone()
} else {
PathBuf::from(common_git_dir)
};
let head = git_dir.join("HEAD");
rerun_if_exists(&head);
if let Ok(contents) = std::fs::read_to_string(&head)
&& let Some(reference) = contents.strip_prefix("ref:")
{
let reference = reference.trim();
rerun_if_exists(&git_dir.join(reference));
rerun_if_exists(&common_git_dir.join(reference));
}
rerun_if_exists(&git_dir.join("packed-refs"));
rerun_if_exists(&common_git_dir.join("packed-refs"));
}
fn main() {
let git_commit = run_git(&["rev-parse", "HEAD"]);
let mut git_branch = run_git(&["rev-parse", "--abbrev-ref", "HEAD"]);
if git_branch == "HEAD" {
git_branch.clear();
}
let build_epoch = build_epoch();
let rust_version = rust_version();
println!("cargo:rustc-env=GIT_COMMIT={git_commit}");
println!("cargo:rustc-env=GIT_BRANCH={git_branch}");
println!("cargo:rustc-env=BUILD_EPOCH={build_epoch}");
println!("cargo:rustc-env=RUST_VERSION_STR={rust_version}");
track_git_inputs();
}