gunnar-common 3.0.0

Shared command line, logging, and build identity for the gunnar binaries
Documentation
//! **Which build reference a binary is stamped with** — the one rule both
//! build scripts that stamp `GUNNAR_BUILD_REF` (gunnar-common's and
//! gunnar-cli's) follow, kept in one file so the banner and the build-thing
//! receipt can never name different commits. Pure: the build scripts read the
//! environment and run `git describe`; this only chooses.

/// The variables a builder sets, in the order they win.
pub const ENV_REFS: [&str; 2] = ["GUNNAR_BUILD_REF", "NORDISK_BUILD_REF"];

/// Choose the stamp: the builder's variables first (`env`, in [`ENV_REFS`]
/// order), then the checkout's own `git describe`, else `None`.
///
/// The builder's value is PREFERRED over git, not only a fallback for it. A
/// Build Thing container build of a tree copied without its `.git` has nothing
/// for `describe` to read — and a copied tree sitting inside some other
/// checkout would be described as THAT checkout. The one who handed the tree
/// over knows which commit it is (the Build Thing exports `NORDISK_BUILD_REF`
/// from the host's `git describe`, or the caller's own value).
pub fn choose(env: &[Option<String>], describe: Option<&str>) -> Option<String> {
    let clean = |s: &str| Some(s.trim().to_owned()).filter(|s| !s.is_empty());
    env.iter()
        .flatten()
        .find_map(|e| clean(e))
        .or_else(|| describe.and_then(clean))
}

/// The builder's variables, read in [`ENV_REFS`] order, each announced to cargo
/// so a changed value re-stamps. For a `build.rs` only.
#[allow(dead_code)] // the test target includes this file and reads no environment
pub fn env_refs() -> Vec<Option<String>> {
    ENV_REFS
        .iter()
        .map(|k| {
            println!("cargo:rerun-if-env-changed={k}");
            std::env::var(k).ok()
        })
        .collect()
}