mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
fix(grasp06): exclude /prs/ subtree from cleanup-empty-repos orphan scan
The cleanup-empty-repos subcommand scans <git_data_path> for bare repos that have no matching kind 30617 announcement and reports them as orphans. Every repo under <git_data_path>/prs/ would be flagged this way because the GRASP-06 endpoint stores contributor submissions outside the standard <npub>/<id>.git layout and never has an announcement. Skip the prs first-level entry up front using is_prs_repo_path so the scan walks only standard owner directories. The /prs/ subtree has its own lifecycle (zero-ref cleanup in the receive handler and a separate periodic sweep) and must not be touched by this scan.
This commit is contained in:
@@ -542,6 +542,13 @@ async fn find_orphan_repos(
|
||||
if !npub_path.is_dir() {
|
||||
continue;
|
||||
}
|
||||
// Skip the GRASP-06 `/prs/` subtree: it does not follow the
|
||||
// `<npub>/<identifier>.git` layout and is not described by 30617
|
||||
// announcements, so every repo under it would otherwise look like
|
||||
// an orphan to this scan.
|
||||
if crate::grasp06::paths::is_prs_repo_path(&npub_path, git_data_path) {
|
||||
continue;
|
||||
}
|
||||
let npub = npub_entry.file_name().to_string_lossy().into_owned();
|
||||
|
||||
// Iterate repo-level directories inside this npub dir
|
||||
@@ -637,3 +644,76 @@ fn check_repo_empty(repo_path: &Path) -> (bool, bool) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[tokio::test]
|
||||
async fn find_orphan_repos_skips_prs_subtree() {
|
||||
// Layout under <git_data_path>:
|
||||
// prs/<hex>/<id>.git <-- must be ignored (GRASP-06 endpoint)
|
||||
// <npub-shaped>/<id>.git <-- a real orphan to prove the scan still works
|
||||
let tmp = tempdir().expect("tempdir");
|
||||
let git_data_path = tmp.path();
|
||||
|
||||
// /prs/<hex>/<id>.git — bare repo so check_repo_empty doesn't complain
|
||||
let prs_repo = crate::grasp06::paths::prs_repo_path(
|
||||
git_data_path,
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
|
||||
"my-pr-repo",
|
||||
);
|
||||
std::fs::create_dir_all(&prs_repo).expect("mkdir prs repo");
|
||||
let init = Command::new("git")
|
||||
.args(["init", "--bare", "--quiet"])
|
||||
.arg(&prs_repo)
|
||||
.status()
|
||||
.expect("git init prs repo");
|
||||
assert!(init.success(), "git init must succeed for the test fixture");
|
||||
|
||||
// A standard-shaped orphan repo so we can assert the scan still finds
|
||||
// real orphans after the /prs/ skip.
|
||||
let orphan_owner = "npub1zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz0000000";
|
||||
let orphan_repo = git_data_path.join(orphan_owner).join("standard-orphan.git");
|
||||
std::fs::create_dir_all(&orphan_repo).expect("mkdir orphan repo");
|
||||
let init = Command::new("git")
|
||||
.args(["init", "--bare", "--quiet"])
|
||||
.arg(&orphan_repo)
|
||||
.status()
|
||||
.expect("git init orphan");
|
||||
assert!(init.success(), "git init must succeed for the test fixture");
|
||||
|
||||
// Empty LMDB DB so every disk repo is an "orphan" by definition.
|
||||
let db_dir = tempdir().expect("tempdir db");
|
||||
let database: Arc<dyn NostrDatabase> = Arc::new(
|
||||
NostrLmdb::open(db_dir.path())
|
||||
.await
|
||||
.expect("open empty NostrLmdb"),
|
||||
);
|
||||
|
||||
let orphans = find_orphan_repos(git_data_path, &database)
|
||||
.await
|
||||
.expect("scan succeeds");
|
||||
|
||||
assert!(
|
||||
orphans.iter().all(|o| !o
|
||||
.repo_path
|
||||
.starts_with(prs_repo.parent().unwrap().parent().unwrap())
|
||||
|| !crate::grasp06::paths::is_prs_repo_path(&o.repo_path, git_data_path)),
|
||||
"/prs/ repo must not be reported as orphan: got {:?}",
|
||||
orphans
|
||||
.iter()
|
||||
.map(|o| o.repo_path.clone())
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
assert!(
|
||||
orphans.iter().any(|o| o.repo_path == orphan_repo),
|
||||
"standard orphan must still be detected: got {:?}",
|
||||
orphans
|
||||
.iter()
|
||||
.map(|o| o.repo_path.clone())
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user