crates/storage-git-gix/parked-gix-2/coldtier-archive/tests/refs_from_archive.rs
//! `ls-remote` answered from `__gunnar_refs__` instead of from `gix-ref`, and
//! the proof that the two are the same bytes.
//!
//! # Why this is not just an output comparison
//!
//! A fidelity check that compares two outputs is **blind to a switch that does
//! not change the output** — which is the whole point of the switch. On
//! 2026-08-04 a lane's instrument measured the wrong path for an entire round
//! because its wrapper did not forward one method and the outputs matched by
//! design. So this file asserts three separate things, and no two of them can
//! fail together silently:
//!
//! 1. **The bytes match.** Same `UploadPack`, same `ObjectStore`, two different
//! `RefStore`s — so the only variable is the ref backend.
//! 2. **The archive path actually answered.** `ArchiveRefStore::served()` is
//! read either side of the advertisement and must have moved. A byte
//! comparison cannot tell you which code produced the bytes; a counter can.
//! 3. **The filesystem is gone.** Every loose ref and `packed-refs` is deleted,
//! and the archive still produces the identical advertisement while `gix-ref`
//! now produces the *empty-repository* one. This is the same discipline
//! `cold_tier_wired.rs` applies to packs — the honest way to ask "where did
//! the bytes come from" is to take the other source away — and without it a
//! green here would also be produced by a store that quietly fell back to
//! the filesystem.
// Moved from `crates/gunnar-cli/tests/` on 2026-08-05, unchanged below this
// header. It was `#![cfg(all(feature = "server", feature = "znippy"))]` there;
// `gunnar-cli` has no `znippy` feature any more (see its manifest), and this
// crate IS the cold tier's binary, so the gate is gone rather than restated.
//
// The arm is installed by `arm()` below rather than by `main`, because a test
// binary has no `main` of ours: without it `Mode::Znippy.available()` is false
// and every assertion in this file would be measuring the `fs` arm under its
// name.
use gunnar_znippy::arm;
// The harness is `gunnar-cli`'s own, reached by path rather than copied: it is
// 787 lines and there must be exactly one of it (LAW 5). `#[path]` is what
// cargo offers for a test module that lives outside this crate's `tests/`.
#[path = "../../gunnar-cli/tests/common/mod.rs"]
mod common;
use std::path::Path;
use common::{tools_present, Harness};
use gunnar_core::{HashKind, RepoRef};
/// The 19 members of `workspace_nordisk`, the corpus every other gunnar lane
/// measures against. Overridable so the test can be pointed at one repo while
/// being written; the default is the real thing.
const REAL_MEMBERS: &[&str] = &[
"nornir",
"modgunn",
"funnel-core",
"holger",
"facett",
"edda",
"skade",
"znippy",
"znippy-zoomies",
"knut",
"korp",
"korp-collectors",
"ordning",
"Skidbladnir",
"tunnr",
"draupnir",
"dwarves",
"bifrost",
"workspace_nordisk",
];
fn real_src_root() -> std::path::PathBuf {
std::path::PathBuf::from(
std::env::var("GUNNAR_REFS_REAL_SRC").unwrap_or_else(|_| "/home/rickard/git".to_string()),
)
}
fn members() -> Vec<String> {
match std::env::var("GUNNAR_REFS_MEMBERS") {
Ok(v) if !v.trim().is_empty() => v.split(':').map(|s| s.trim().to_string()).collect(),
_ => REAL_MEMBERS.iter().map(|s| s.to_string()).collect(),
}
}
/// The v0 upload-pack advertisement, which is what `git ls-remote` reads.
///
/// Deliberately the **real** `gunnar-wire` entry point rather than a
/// reimplementation: the whole claim is that the wire layer cannot tell the two
/// ref backends apart, and a local copy of the emit loop would be a claim about
/// a copy.
fn advertisement(
objects: &dyn gunnar_store::ObjectStore,
refs: &dyn gunnar_store::RefStore,
) -> Vec<u8> {
let upload = gunnar_wire::UploadPack::new(objects, refs);
let mut out = Vec::new();
upload
.write_ref_advertisement(&mut out)
.expect("writing the v0 ref advertisement");
out
}
struct Arm;
impl Arm {
fn znippy() -> Self {
std::env::set_var(gunnar_cli::server::storage::MODE_ENV, "znippy");
Arm
}
}
impl Drop for Arm {
fn drop(&mut self) {
std::env::remove_var(gunnar_cli::server::storage::MODE_ENV);
}
}
/// Delete every reference `gix-ref` can read: the whole loose `refs/` tree and
/// `packed-refs`. `HEAD` is left alone, because `HEAD` is not a reference
/// `gix-ref` stores under `refs/` and leaving it is what makes the fs arm
/// degrade to *unborn* rather than to *broken*.
fn take_the_filesystem_away(git_dir: &Path) {
let refs_dir = git_dir.join("refs");
if refs_dir.exists() {
std::fs::remove_dir_all(&refs_dir).expect("removing the loose ref tree");
}
let packed = git_dir.join("packed-refs");
if packed.exists() {
std::fs::remove_file(&packed).expect("removing packed-refs");
}
}
/// One repository, all three assertions.
///
/// Returns `(refs_advertised, bytes)` so the caller can report the corpus totals
/// and, more importantly, so an empty corpus cannot masquerade as a pass.
fn check_one(src: &Path, name: &str) -> Option<(usize, usize)> {
let hash = HashKind::Sha1;
let _arm = Arm::znippy();
let harness = Harness::start("team", "project", hash);
// Build the corpus by pushing into a bare repo rather than cloning one:
// a clone would put refs on the server that the server never negotiated,
// and `refs/remotes/*` would come along for the ride.
let work = harness.dir.path().join("mirror");
let clone = harness.git(
harness.dir.path(),
&[
"clone",
"--bare",
"--quiet",
&src.display().to_string(),
&work.display().to_string(),
],
);
if !clone.ok {
eprintln!("skipping {name}: could not mirror-clone it");
return None;
}
let push = harness.git(
&work,
&["push", "--mirror", &harness.url("team", "project")],
);
if !push.ok {
eprintln!("skipping {name}: mirror push failed: {}", push.stderr);
return None;
}
// `gunnar gc` is what seals the consolidated pack AND `__gunnar_refs__`;
// a push alone does not write the section at all.
gunnar_cli::server::admin::gc(
&harness.stores,
gunnar_cli::cli::GcArgs {
path: Some("team/project".into()),
..Default::default()
},
)
.expect("gunnar gc with the znippy cold tier");
let repo = RepoRef::new("team", "project").expect("a legal repo path");
let opened = harness
.stores
.catalog()
.open(&repo)
.expect("the repository");
let store = harness
.stores
.repo_store(&opened)
.expect("the repository is open");
let git_dir = harness.git_dir("team", "project");
let archive = gunnar_cli::server::storage::sealed_archive_path(&git_dir);
assert!(archive.exists(), "{name}: gc did not seal an archive");
let objects = store.objects();
// ── 1. the bytes ─────────────────────────────────────────────────────────
//
// **The reference side is the STORE's ref log, not `gix-ref`.** It used to
// be `store.refs()`, and that comparison is now vacuous: a znippy-git
// repository's references live in the store, so the filesystem ref store is
// empty and `advertisement` over it returns the empty-repository answer —
// an all-zeros oid and `capabilities^{}`. Comparing the archive against
// that would pass only if the archive were empty too, which is exactly the
// hollow shape this file's own header warns about.
let live_refs = gunnar_cli::server::storage::write_refs(&git_dir, store.hash_kind())
.expect("the znippy-git ref log");
let from_gix = advertisement(&objects, live_refs.store.as_ref());
let archived = gunnar_coldtier::refstore::ArchiveRefStore::open(&archive)
.expect("reading __gunnar_refs__")
.unwrap_or_else(|| panic!("{name}: the sealed archive carries no __gunnar_refs__ section"));
let before = archived.served();
let from_archive = advertisement(&objects, &archived);
let after = archived.served();
assert_eq!(
from_gix,
from_archive,
"{name}: the advertisement from the archive differs from the live ref log.\n live: \
{:?}\n archive: {:?}",
String::from_utf8_lossy(&from_gix),
String::from_utf8_lossy(&from_archive)
);
// ── 2. the archive path actually answered ────────────────────────────────
assert!(
after > before,
"{name}: the advertisement matched but the archive store was never called, so this \
comparison is measuring gix-ref against itself"
);
// A namespace with no refs would make every comparison above trivially
// true. Refuse it rather than report a pass.
let n = archived.len();
assert!(
n > 0,
"{name}: the sealed namespace is empty; the comparison would pass on anything"
);
// ── 3. no filesystem ─────────────────────────────────────────────────────
take_the_filesystem_away(&git_dir);
let archived2 = gunnar_coldtier::refstore::ArchiveRefStore::open(&archive)
.expect("re-reading __gunnar_refs__ with no refs on disk")
.expect("the section is still there");
let from_archive_bare = advertisement(&objects, &archived2);
assert_eq!(
from_gix, from_archive_bare,
"{name}: with every ref file deleted the archive stopped producing the same \
advertisement, so it had been reading the filesystem"
);
// The red that makes the line above mean something: with the ref files gone
// `gix-ref` must NOT still produce the advertisement. If it does, this test
// is measuring a cache and says so instead of reporting a win.
let from_gix_bare = advertisement(&objects, &store.refs());
assert_ne!(
from_gix, from_gix_bare,
"{name}: gix-ref produced the full advertisement with no ref files on disk, so deleting \
them did not take the filesystem away and assertion 3 proves nothing"
);
Some((n, from_gix.len()))
}
/// The whole claim, over the 19 real repositories.
#[test]
fn the_advertisement_from_the_archive_is_byte_identical_on_the_real_corpus() {
arm();
if !tools_present() {
eprintln!("skipping: git and ssh are required");
return;
}
let root = real_src_root();
let mut checked = 0usize;
let mut refs_total = 0usize;
for name in members() {
let src = root.join(&name);
if !src.join(".git").exists() && !src.join("HEAD").exists() {
eprintln!("skipping {name}: not a git checkout at {}", src.display());
continue;
}
if let Some((n, _bytes)) = check_one(&src, &name) {
checked += 1;
refs_total += n;
eprintln!(" {name}: {n} refs, advertisement byte-identical");
}
}
// The fixture trap, eight lanes deep: a corpus that silently did not get
// built passes every assertion above by never running one.
assert!(
checked >= 12,
"only {checked} of the 19 members were checked; the corpus did not get built, and a \
corpus that did not get built cannot have proved anything"
);
assert!(
refs_total > 400,
"only {refs_total} refs across {checked} repositories; too few"
);
eprintln!("byte-identical advertisement on {checked} repositories, {refs_total} refs total");
}