server/cli/tests/the_packaged_server_names_its_commit.rs
//! **A `cargo install holger` binary names the commit it was published from**
//! (lane GUN-VERSION-STAMP, 2026-10-31).
//!
//! `cargo install holger` 3.0.0 from crates.io printed `holger v3.0.0 (unknown)`: a
//! published crate has no `.git`, so `server/lib/build.rs` found no HEAD to read. cargo
//! writes `.cargo_vcs_info.json` (with `git.sha1`) into every package it makes from a git
//! checkout, and that is the commit the crate was published from.
//!
//! This test does what crates.io does: `cargo package -p holger-server-lib`, the package
//! unpacked into a directory outside every git checkout, and a small binary built on the
//! unpacked copy that prints `holger_server_lib::VERSION_LINE`, the line `holger --version`
//! prints (`server/cli/src/lib.rs`). The other holger crates come from this checkout
//! (`[patch.crates-io]`), as crates.io's copies of the same commit would. Then:
//!
//! 1. the line names the short sha of the package's `.cargo_vcs_info.json`, never `unknown`;
//! 2. the same binary built on the git checkout keeps its old line: HEAD's short sha.
use std::path::{Path, PathBuf};
use std::process::Command;
fn root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.ancestors()
.nth(2)
.expect("server/cli is two below the root")
.to_path_buf()
}
fn cargo() -> String {
std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string())
}
/// The target directory this test binary was built in (`<target>/debug/deps/<test>`), so the
/// nested builds below reuse their dependencies from one run to the next.
fn target_root() -> PathBuf {
if let Some(t) = std::env::var_os("CARGO_TARGET_DIR") {
return PathBuf::from(t);
}
let exe = std::env::current_exe().expect("the test binary has a path");
exe.ancestors()
.nth(3)
.expect("<target>/<profile>/deps/<test>")
.to_path_buf()
}
fn run(cmd: &mut Command, what: &str) -> String {
let out = cmd
.output()
.unwrap_or_else(|e| panic!("{what}: could not run: {e}"));
assert!(
out.status.success(),
"{what} failed ({}):\n{}\n{}",
out.status,
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
);
String::from_utf8_lossy(&out.stdout).into_owned()
}
/// The workspace crates `of` reaches by path (normal and build edges, transitively).
fn path_edges(of: &str) -> Vec<String> {
let meta = run(
Command::new(cargo())
.args(["metadata", "--no-deps", "--format-version", "1"])
.current_dir(root()),
"cargo metadata",
);
let meta: serde_json::Value = serde_json::from_str(&meta).expect("cargo metadata is JSON");
let packages = meta["packages"].as_array().expect("packages");
let edges = |name: &str| -> Vec<String> {
packages
.iter()
.filter(|p| p["name"] == name)
.flat_map(|p| p["dependencies"].as_array().cloned().unwrap_or_default())
.filter(|d| d["path"].is_string() && d["kind"] != "dev")
.map(|d| d["name"].as_str().expect("a dependency name").to_string())
// Only this workspace's members (an estate crate such as holger-fleet is
// packaged from its own workspace, at the version crates.io has).
.filter(|n| packages.iter().any(|p| p["name"] == n.as_str()))
.collect()
};
let mut seen: Vec<String> = Vec::new();
let mut todo = edges(of);
while let Some(c) = todo.pop() {
if c != of && !seen.contains(&c) {
todo.extend(edges(&c));
seen.push(c);
}
}
seen.sort();
seen
}
/// Every workspace member but holger-server-lib, as `name = { path = ... }` patch lines.
fn sibling_patches() -> String {
let meta = run(
Command::new(cargo())
.args(["metadata", "--no-deps", "--format-version", "1"])
.current_dir(root()),
"cargo metadata",
);
let meta: serde_json::Value = serde_json::from_str(&meta).expect("cargo metadata is JSON");
let mut out = String::new();
for p in meta["packages"].as_array().expect("packages") {
let name = p["name"].as_str().expect("a name");
if name == "holger-server-lib" {
continue;
}
let dir = Path::new(p["manifest_path"].as_str().expect("a manifest"))
.parent()
.expect("a manifest dir")
.display()
.to_string();
out.push_str(&format!("{name} = {{ path = {dir:?} }}\n"));
}
out
}
/// A small binary on `holger_server_lib` at `dep`, printing `VERSION_LINE`.
fn version_probe(dir: &Path, dep: &Path, patches: &str) {
std::fs::create_dir_all(dir.join("src")).unwrap();
std::fs::write(
dir.join("Cargo.toml"),
format!(
"[package]\nname = \"version-probe\"\nversion = \"0.0.0\"\nedition = \"2021\"\npublish = false\n\n\
[dependencies]\nholger-server-lib = {{ path = {:?}, default-features = false }}\n\n\
[patch.crates-io]\n{patches}\n[workspace]\n",
dep.display().to_string()
),
)
.unwrap();
std::fs::write(
dir.join("src/main.rs"),
"fn main() {\n println!(\"{}\", holger_server_lib::VERSION_LINE);\n}\n",
)
.unwrap();
// The workspace's lock: the probe builds the versions the workspace builds.
std::fs::copy(root().join("Cargo.lock"), dir.join("Cargo.lock")).unwrap();
}
fn probe_version(dir: &Path, target: &Path) -> String {
run(
Command::new(cargo())
.args(["run", "--quiet", "--manifest-path"])
.arg(dir.join("Cargo.toml"))
.arg("--target-dir")
.arg(target)
.current_dir(dir),
"the version probe",
)
.trim()
.to_owned()
}
/// The `git.sha1` of a `.cargo_vcs_info.json`.
fn vcs_sha1(json: &str) -> String {
let v: serde_json::Value = serde_json::from_str(json).expect(".cargo_vcs_info.json is JSON");
let sha = v["git"]["sha1"].as_str().expect("git.sha1").to_owned();
assert!(
sha.len() == 40 && sha.bytes().all(|b| b.is_ascii_hexdigit()),
"git.sha1 is a 40-hex commit id: {sha:?}"
);
sha
}
#[test]
fn a_packaged_holger_names_the_commit_it_was_published_from() {
let work = target_root().join("packaged-version");
let pkg_target = work.join("package-target");
let probe_target = work.join("probe-target");
let version = env!("CARGO_PKG_VERSION"); // the workspace version, holger-server-lib's too
// 1. What crates.io gets: the package of holger-server-lib, with its .cargo_vcs_info.json.
run(
Command::new(cargo())
.arg("package")
// holger-server-lib's own edges at this commit (holger-job-runner's `heimdall`,
// lane HOL-HEIMDALL-02; holger-sandbox 4.0.0 and the 3.1.0 crates of a release,
// HOL-310-RELEASE) resolve against the packages made beside it, as a publish in
// order would against crates.io: every workspace crate it reaches by path.
.args(
path_edges("holger-server-lib")
.iter()
.flat_map(|c| ["-p", c.as_str()]),
)
.args(["-p", "holger-server-lib", "--no-verify", "--allow-dirty"])
.arg("--target-dir")
.arg(&pkg_target)
.current_dir(root()),
"cargo package -p holger-server-lib",
);
let crate_file = pkg_target.join(format!("package/holger-server-lib-{version}.crate"));
// 2. Unpacked OUTSIDE every git checkout: crates.io's copy has no `.git` above it either.
let outside = std::env::temp_dir().join(format!(
"holger-packaged-version-{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
));
std::fs::create_dir_all(&outside).unwrap();
run(
Command::new("tar")
.arg("-xzf")
.arg(&crate_file)
.arg("-C")
.arg(&outside),
"unpacking the package",
);
let unpacked = outside.join(format!("holger-server-lib-{version}"));
let in_git = Command::new("git")
.args(["rev-parse", "--git-dir"])
.current_dir(&unpacked)
.output()
.map(|o| o.status.success())
.unwrap_or(false);
assert!(
!in_git,
"{} is inside a git checkout; the test needs a temp dir outside one",
unpacked.display()
);
let vcs = std::fs::read_to_string(unpacked.join(".cargo_vcs_info.json"))
.expect("cargo package wrote .cargo_vcs_info.json");
let sha = vcs_sha1(&vcs);
let short = &sha[..7];
// 3. The packaged copy names the commit it was packaged from.
let patches = sibling_patches();
let probe = outside.join("probe");
version_probe(&probe, &unpacked, &patches);
let line = probe_version(&probe, &probe_target);
assert_eq!(
line,
format!("holger v{version} ({short})"),
"a packaged holger must name its commit {short} (from .cargo_vcs_info.json)"
);
// 4. The git checkout keeps its line: HEAD's short sha.
let head = run(
Command::new("git")
.args(["-c", "safe.directory=*", "rev-parse", "HEAD"])
.current_dir(root()),
"git rev-parse HEAD",
);
let checkout_probe = outside.join("checkout-probe");
version_probe(&checkout_probe, &root().join("server/lib"), &patches);
let line = probe_version(&checkout_probe, &probe_target);
assert_eq!(
line,
format!("holger v{version} ({})", &head.trim()[..7]),
"a git checkout keeps HEAD's short sha"
);
let _ = std::fs::remove_dir_all(&outside);
}