diff --git a/build.rs b/build.rs index 2e13954..21dca88 100644 --- a/build.rs +++ b/build.rs @@ -1,3 +1,4 @@ +use std::env; use std::process::Command; fn git(args: &[&str]) -> Option { @@ -12,14 +13,29 @@ fn git(args: &[&str]) -> Option { fn main() { println!("cargo:rerun-if-changed=.git/HEAD"); println!("cargo:rerun-if-changed=.git/index"); + println!("cargo:rerun-if-env-changed=DOSH_BUILD_GIT_HASH"); + println!("cargo:rerun-if-env-changed=DOSH_BUILD_COMMIT_DATE"); + println!("cargo:rerun-if-env-changed=DOSH_BUILD_GIT_DIRTY"); - let hash = git(&["rev-parse", "--short=12", "HEAD"]).unwrap_or_else(|| "unknown".into()); - let date = git(&["show", "-s", "--format=%cs", "HEAD"]).unwrap_or_else(|| "unknown".into()); - let dirty = Command::new("git") - .args(["diff", "--quiet", "--ignore-submodules", "--"]) - .status() - .map(|status| if status.success() { "" } else { "+dirty" }) - .unwrap_or(""); + let hash = env::var("DOSH_BUILD_GIT_HASH") + .ok() + .filter(|value| !value.is_empty()) + .or_else(|| git(&["rev-parse", "--short=12", "HEAD"])) + .unwrap_or_else(|| "unknown".into()); + let date = env::var("DOSH_BUILD_COMMIT_DATE") + .ok() + .filter(|value| !value.is_empty()) + .or_else(|| git(&["show", "-s", "--format=%cs", "HEAD"])) + .unwrap_or_else(|| "unknown".into()); + let dirty = match env::var("DOSH_BUILD_GIT_DIRTY").ok().as_deref() { + Some("1" | "true" | "yes" | "+dirty") => "+dirty", + Some(_) => "", + None => Command::new("git") + .args(["diff", "--quiet", "--ignore-submodules", "--"]) + .status() + .map(|status| if status.success() { "" } else { "+dirty" }) + .unwrap_or(""), + }; println!("cargo:rustc-env=DOSH_GIT_HASH={hash}{dirty}"); println!("cargo:rustc-env=DOSH_COMMIT_DATE={date}"); diff --git a/scripts/package-release.sh b/scripts/package-release.sh index d666cb9..1f77e3b 100755 --- a/scripts/package-release.sh +++ b/scripts/package-release.sh @@ -52,6 +52,22 @@ else release_dir="target/release" fi +if command -v git >/dev/null 2>&1 && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then + if [ -z "${DOSH_BUILD_GIT_HASH:-}" ]; then + export DOSH_BUILD_GIT_HASH="$(git rev-parse --short=12 HEAD)" + fi + if [ -z "${DOSH_BUILD_COMMIT_DATE:-}" ]; then + export DOSH_BUILD_COMMIT_DATE="$(git show -s --format=%cs HEAD)" + fi + if [ -z "${DOSH_BUILD_GIT_DIRTY+x}" ]; then + if git diff --quiet --ignore-submodules --; then + export DOSH_BUILD_GIT_DIRTY=0 + else + export DOSH_BUILD_GIT_DIRTY=1 + fi + fi +fi + if [ "$os" = "windows" ]; then if [ -n "$target" ]; then cargo build --release --target "$target" --bin dosh-client --bin dosh-bench diff --git a/tests/release_scripts.rs b/tests/release_scripts.rs index 9a312a2..81f5719 100644 --- a/tests/release_scripts.rs +++ b/tests/release_scripts.rs @@ -42,6 +42,23 @@ fn package_check_verifies_only_artifacts_it_builds() { ); } +#[test] +fn package_release_stamps_git_build_info() { + let package = include_str!("../scripts/package-release.sh"); + let build = include_str!("../build.rs"); + for name in [ + "DOSH_BUILD_GIT_HASH", + "DOSH_BUILD_COMMIT_DATE", + "DOSH_BUILD_GIT_DIRTY", + ] { + assert!(package.contains(name), "package script must export {name}"); + assert!(build.contains(name), "build.rs must consume {name}"); + } + assert!(package.contains("git rev-parse --short=12 HEAD")); + assert!(package.contains("git show -s --format=%cs HEAD")); + assert!(build.contains("cargo:rerun-if-env-changed=DOSH_BUILD_GIT_HASH")); +} + #[test] fn systemd_service_does_not_sandbox_remote_shells() { let service = include_str!("../packaging/systemd/dosh-server.service");