build_rs_git_info/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![forbid(unsafe_code)]
5
6//! Build-script helper that emits `BUILD_GIT_SHA` and `BUILD_GIT_BRANCH`
7//! cargo environment variables by invoking the `git` CLI.
8
9use std::process::Command;
10
11fn git_output(args: &[&str]) -> anyhow::Result<String> {
12    let output = Command::new("git").args(args).output()?;
13
14    if !output.status.success() {
15        anyhow::bail!(
16            "git {:?} failed with code {:?}: {}",
17            args,
18            output.status.code(),
19            String::from_utf8_lossy(&output.stderr)
20        );
21    }
22
23    let output = String::from_utf8(output.stdout).unwrap().trim().to_owned();
24    Ok(output)
25}
26
27fn git_path(args: &[&str]) -> anyhow::Result<std::path::PathBuf> {
28    let output = git_output(args)?;
29    Ok(std::path::absolute(&output)?)
30}
31
32/// Emit git information as `cargo:rustc-env` variables so they are available via
33/// `env!()` / `option_env!()` in the consuming crate.
34pub fn emit_git_info() -> anyhow::Result<()> {
35    // Always rerun when HEAD changes (e.g. branch switch).
36    let head_path = git_path(&["rev-parse", "--git-path", "HEAD"])?;
37    println!("cargo:rerun-if-changed={}", head_path.display());
38
39    // If HEAD is a symbolic ref (i.e. points at a branch), also watch the
40    // branch ref file so we rebuild when new commits land on that branch.
41    if let Ok(head_ref) = git_output(&["symbolic-ref", "HEAD"]) {
42        // e.g. refs/heads/main → .git/refs/heads/main (or the worktree equivalent)
43        let ref_path = git_path(&["rev-parse", "--git-path", &head_ref])?;
44        println!("cargo:rerun-if-changed={}", ref_path.display());
45    }
46
47    let sha = git_output(&["rev-parse", "HEAD"])?;
48    let branch = git_output(&["rev-parse", "--abbrev-ref", "HEAD"])?;
49
50    println!("cargo:rustc-env=BUILD_GIT_SHA={sha}");
51    println!("cargo:rustc-env=BUILD_GIT_BRANCH={branch}");
52
53    Ok(())
54}