crates/gunnar-server/tests/repo_purge.rs
//! **`repo delete` reclaims the disk** (2026-08-30).
//!
//! MEASURED on the appliance 2026-08-29: after the linux push a `repo delete`
//! removed the catalog row and left **25 GB** of `gunnar-git.znippy/` behind —
//! pack, journal, tail, exploded tier — with the indexer still running on it.
//! `ServerStores::purge_repo` is the one verb both the CLI and the gRPC delete
//! route through; this walks the bytes before and after, as `du` would.
//!
//! Seen RED with `purge_repo`'s `remove_dir_all` commented out: "the
//! directory is still there" and `after == before`.
use gunnar_core::{NewRepo, RepoRef};
use gunnar_server::stores::{dir_bytes, ServerStores};
#[test]
fn delete_removes_the_store_directory_and_the_bytes_are_measured() {
let dir = tempfile::tempdir().expect("tempdir");
let stores = ServerStores::open(dir.path()).expect("stores");
stores
.catalog()
.create_namespace("alice")
.expect("namespace");
let path = RepoRef::new("alice", "linux").expect("legal");
let repo = stores
.catalog()
.create(NewRepo::new(path.clone()))
.expect("create");
// Open it — the engine lays down its files (pack, journal, tail, …).
let handle = stores.repo_store(&repo).expect("open");
let git_dir = handle.git_dir().to_path_buf();
drop(handle);
assert!(git_dir.is_dir(), "{} was not created", git_dir.display());
// Stand in for an exploded tier: 4 MiB the engine did not write, so the
// measurement is of the whole directory and not of one file the engine
// happens to hold open.
std::fs::write(
git_dir
.join("gunnar-git.znippy")
.join("objects.exploded.fixture"),
vec![7u8; 4 << 20],
)
.expect("fixture");
let before = dir_bytes(&git_dir);
assert!(
before >= 4 << 20,
"measured {before} bytes before; the fixture alone is 4 MiB"
);
stores.catalog().delete(&path).expect("catalog delete");
let (b, a) = stores.purge_repo(&path).expect("purge");
assert_eq!(
b, before,
"purge measured a different 'before' than the walk"
);
assert_eq!(a, 0, "bytes left after the purge");
assert!(
!git_dir.exists(),
"the directory is still there: {}",
git_dir.display()
);
assert_eq!(dir_bytes(&git_dir), 0);
assert!(
stores.catalog().get(&path).expect("catalog").is_none(),
"still catalogued"
);
// Idempotent: a second purge of a gone directory is not an error.
let (b2, a2) = stores.purge_repo(&path).expect("purge twice");
assert_eq!((b2, a2), (0, 0));
}