Skip to content

Commit 1d5589b

Browse files
committed
test(node): cover the serve decision across both has_path_scoped_rule branches
Drives the git_upload_pack serve decision over a real bare repo for the INV-2 caller (a reader allowed at whole-repo "/" but denied a path-scoped subtree), exercising both branches the predicate selects: root-only rules skip the walk and serve the full pack (asserting the walk would withhold nothing, so the skip is sound), and a /secret/** rule runs the walk and excludes the secret blob from the served set while keeping the public one.
1 parent cf81708 commit 1d5589b

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

‎crates/gitlawb-node/src/git/visibility_pack.rs‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,62 @@ mod tests {
330330
}
331331
}
332332

333+
#[test]
334+
fn serve_decision_skips_walk_for_root_only_and_withholds_for_path_scoped() {
335+
// Drive the git_upload_pack serve decision over a real bare repo, both
336+
// branches the has_path_scoped_rule gate selects, for the INV-2 caller:
337+
// a reader allowed at whole-repo "/" but denied a path-scoped subtree.
338+
// `replicable_objects` is the seam the serve path filters through, so the
339+
// returned set models exactly what the served pack would carry.
340+
let (_td, bare, secret, public) = fixture();
341+
let reader = Some("did:key:zReader");
342+
let all = vec![secret.clone(), public.clone()];
343+
344+
// Branch A — predicate false: skip the walk and serve the full pack. The
345+
// skip is only sound if the walk would have withheld nothing, so assert
346+
// the walk is empty and the served set is complete.
347+
let root_only = vec![rule("/", &["did:key:zReader"])];
348+
assert!(!has_path_scoped_rule(&root_only));
349+
let withheld_a = withheld_blob_oids(&bare, &root_only, true, OWNER, reader).unwrap();
350+
assert!(
351+
withheld_a.is_empty(),
352+
"root-only rules withhold nothing for a gate-passing reader; the skip is safe"
353+
);
354+
let served_a = replicable_objects(all.clone(), &withheld_a);
355+
assert!(
356+
served_a.contains(&secret) && served_a.contains(&public),
357+
"the full pack is served when no rule is path-scoped"
358+
);
359+
360+
// Branch B — predicate true: run the walk and serve the filtered pack.
361+
// /secret/** is scoped to a different DID, so the reader (allowed at "/")
362+
// is denied /secret and the secret blob must be excluded.
363+
let scoped = vec![
364+
rule("/", &["did:key:zReader"]),
365+
rule("/secret/**", &["did:key:zOther"]),
366+
];
367+
assert!(has_path_scoped_rule(&scoped));
368+
let withheld_b = withheld_blob_oids(&bare, &scoped, true, OWNER, reader).unwrap();
369+
let served_b = replicable_objects(all, &withheld_b);
370+
assert!(
371+
!served_b.contains(&secret),
372+
"a reader denied /secret must not be served the secret blob"
373+
);
374+
assert!(
375+
served_b.contains(&public),
376+
"the public blob the reader may see stays in the served pack"
377+
);
378+
379+
// Branch C — same path-scoped rules, but the caller is the owner. The
380+
// owner bypasses every rule, so the walk withholds nothing and the full
381+
// pack (secret included) is served even though a path-scoped rule exists.
382+
let withheld_c = withheld_blob_oids(&bare, &scoped, true, OWNER, Some(OWNER)).unwrap();
383+
assert!(
384+
withheld_c.is_empty(),
385+
"the owner bypasses path-scoped rules and is served everything"
386+
);
387+
}
388+
333389
#[test]
334390
fn replicable_objects_drops_withheld_keeps_rest() {
335391
let all = vec!["aaa".to_string(), "bbb".to_string(), "ccc".to_string()];

0 commit comments

Comments
 (0)