a write's gc reads only the git reads of the repos it changed
Signed-off-by: dawn <90008@klbr.net>
378 unmodified linesExpand all3793803813823833833843853863873883893903913923937 unmodified lines40140240340440540640740840970 unmodified lines378 unmodified linesExpand all Ok(removed)}
/// an unreadable seal would make its files look unreferenced. nothing gets swept./// a pool already swept for the same seals is left alone, so a write's gc only reads the repos it changed.fn collect_git_reads(repo: &Path, mut seals: BTreeSet<String>) -> anyhow::Result<usize> {pub(crate) fn collect_git_reads(repo: &Path, mut seals: BTreeSet<String>) -> anyhow::Result<usize> { let store = RepoStore::served(repo); seals.extend(crate::git_xrpc::last_seal(&store)); if crate::git_xrpc::swept_for(&store, &seals) { return Ok(0); } let Some(kept) = crate::git_xrpc::kept_served(&store, &seals) else { return Ok(0); }; let (pool, seal_dir, maps_dir) = crate::git_xrpc::served_dirs(&store);7 unmodified lines .file_name() .is_some_and(|name| name.as_encoded_bytes().starts_with(b".")) })?; } crate::git_xrpc::mark_swept(&store, &seals)?; Ok(removed)}
/// an unreadable seal keeps every served file in this repo.70 unmodified lines27 unmodified lines28293031323334353637746 unmodified linesExpand all78478578678778878979079179279379479579679779879980080180215 unmodified lines27 unmodified linespub(crate) const SEAL_VERSION: u32 = 9;const POOL_KIND: &str = "git-xrpc";const SEAL_KIND: &str = "git-xrpc-seal";const LAST_SEALED: &str = "git-xrpc.last";/// the seals gc last swept the pool against, a pool kept for the same seals has nothing new to sweepconst LAST_SWEPT: &str = "git-xrpc.swept";/// per seal key: a map fragment per variable, what gc keeps, and what a carried seal needsconst MAPS_KIND: &str = "git-xrpc-maps";const CARRY_FILE: &str = "carry.json";const KEPT_FILE: &str = "kept.json";746 unmodified linesExpand allpub fn last_seal(served: &RepoStore) -> Option<String> { std::fs::read_to_string(served.kind_dir(LAST_SEALED)).ok()}
pub fn swept_for(served: &RepoStore, seals: &BTreeSet<String>) -> bool { read_json::<BTreeSet<String>>(&served.kind_dir(LAST_SWEPT)).as_ref() == Some(seals)}
pub fn mark_swept(served: &RepoStore, seals: &BTreeSet<String>) -> anyhow::Result<()> { Ok(atomic_write( &served.kind_dir(LAST_SWEPT), &serde_json::to_vec(seals)?, )?)}
pub fn kept_served(served: &RepoStore, seals: &BTreeSet<String>) -> Option<BTreeSet<PathBuf>> { let pool = served.pool(POOL_KIND); let mut kept = BTreeSet::new(); let maps = served.kind_dir(MAPS_KIND);15 unmodified lines857 unmodified linesExpand all858859860861862863864865866867868869870871872873874875876877878879880881882883884885886857 unmodified linesExpand all !super::prepare_repo(&served, &did).unwrap(), "a second run writes nothing" );}
#[test]fn gc_sweeps_a_pool_again_only_once_its_seals_change() { let fixture = fixture(); let repo_dir = fixture.served.parent().unwrap().to_path_buf(); let first = seal(&fixture.input(Vec::new())).unwrap(); let junk = first.pool.join("json/junk"); let collect = |key: &str| { crate::generate::gc::collect_git_reads(&repo_dir, BTreeSet::from([key.to_string()])) .unwrap() }; std::fs::write(&junk, "x").unwrap(); assert_eq!(collect(&first.key), 1); assert!(!junk.exists());
std::fs::write(&junk, "x").unwrap(); assert_eq!(collect(&first.key), 0, "the same seals were swept already"); assert!(junk.exists());
git(&fixture.repo, &["checkout", "-q", "feature"], 9); commit(&fixture.repo, "b.txt", "b\n", "more feature", 10); let next = seal(&fixture.input(Vec::new())).unwrap(); assert!(collect(&next.key) >= 1); assert!(!junk.exists(), "new seals sweep the pool again");}