//! Shared helpers for the tier guards — the ONE place that knows where cargo puts a
//! release artifact.
//!
//! ## Why this file exists
//!
//! `tier_ladder.rs` and `thin_client.rs` each shell out to `cargo build --release` and
//! then measure the artifact that came out: bytes, `nm` symbol families, crate closures.
//! Both computed the output directory the same way, and both computed it **wrong** —
//! two copies of one bug, which is the LAW #5 argument for sharing in miniature:
//!
//! ```text
//! Path::new(env!("CARGO_MANIFEST_DIR")).ancestors().nth(2).join("target/release")
//! ```
//!
//! That hardcodes `<repo>/target/release` and ignores `CARGO_TARGET_DIR`. The child
//! `cargo build` inherits the environment and therefore honours the override, so the
//! two disagreed about where the binary is the moment anyone set it — and this repo's
//! own working rule is to keep build scratch on md1 (`/home/rickard/scratch/cargo/…`),
//! never in the checkout. So the guards were broken under the normal way of building
//! here.
//!
//! ## The failure mode that actually matters
//!
//! Discovered 2026-08-01 during the egui 0.35 migration, running the guards with
//! `CARGO_TARGET_DIR` set, as usual:
//!
//! ```text
//! thread 'every_shipped_ui_tier_is_thin_and_only_the_named_one_embeds' panicked at
//! server/ui/tests/thin_client.rs:152:13:
//! 'gui' (holger-server-ui): built, but no artifact at the path — nothing was audited
//! ```
//!
//! A loud red, and the harmless direction. The dangerous direction is the same bug with
//! a `<repo>/target/release/holger-server-ui` left over from some earlier build: the
//! guard then builds into the scratch dir, reads the STALE artifact from the checkout,
//! and reports a confident green about a binary it did not build. Bytes from last week,
//! symbol probes from last week, verdict `Measured`. That is precisely the shape of
//! silent green these two files were written to abolish — measuring an artifact rather
//! than trusting a declaration — so it belongs fixed here, once, rather than guarded.
//!
//! Nothing in the guards' own logic changes; they simply ask this function where to look.
// Each integration test binary compiles its OWN copy of this module, so whichever helper
// that particular binary does not call is "never used" from its point of view —
// `law4_no_opengl_backend` wants `repo_root` and not `release_dir`. That is inherent to
// `tests/common/mod.rs`, not a sign of a dead helper, and the alternative (a third copy of
// the walker, per test) is the duplication this module removed.
#![allow(dead_code)]
use std::path::PathBuf;
/// The directory cargo will place `--release` artifacts in, honouring
/// `CARGO_TARGET_DIR`.
///
/// A relative `CARGO_TARGET_DIR` is resolved against the repo root (cargo resolves it
/// against the invocation's working directory; the guards always invoke with an explicit
/// `--manifest-path` from the repo, so the root is the right base and an absolute path —
/// the normal case here — is used as given).
pub fn release_dir() -> PathBuf {
let base = match std::env::var_os("CARGO_TARGET_DIR") {
Some(dir) => {
let dir = PathBuf::from(dir);
if dir.is_absolute() {
dir
} else {
repo_root().join(dir)
}
}
None => repo_root().join("target"),
};
base.join("release")
}
/// The repo root — found by walking UP to the manifest that declares `[workspace]`,
/// not by counting two directories.
///
/// This is `law4_no_opengl_backend.rs`'s definition, promoted here and now shared by all
/// three tier/LAW guards, because it is the sturdier of the two that were in the tree: a
/// crate moving one level deeper silently changes what `.nth(2)` means, and a guard that
/// then measures the wrong directory is the failure this module exists to end.
pub fn repo_root() -> PathBuf {
let mut root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
while !std::fs::read_to_string(root.join("Cargo.toml"))
.is_ok_and(|s| s.lines().any(|l| l.trim() == "[workspace]"))
{
assert!(
root.pop(),
"walked past the filesystem root without finding the [workspace] manifest"
);
}
root
}