fix(checkouts): preserve scoped descriptor ignore rules

T-699 rev20, MR 01a10d66-db02-70c2-b152-197aca92d6b7 seq3 native_glob_ignore_regression. Load authorized root/nested ignore sources through FsAccessPolicy descriptor opens, retain only bounded ancestor matchers, preserve source precedence/negation/anchors and prune ignored directories before enumeration. Expanded parity also exposed Grep source-class precedence and ignored-directory rescue errors; use the shared matcher without relaxing Grep's existing ignore-open/Git-marker provider contract. No ambient global/linked-worktree administration pointer traversal or unsafe WalkBuilder ignore loading.

Add 7 fs boundary tests, 4 actual Local/scoped provider parity tests and 1 native WIP search/link regression. Current corrected source passes cargo check --workspace --all-targets; cargo test -p fs-operation -p workdir -p tools -p worker (fs37 Workdir125 Tools72+10+29+1doc Worker780+109integration); cargo test -p worker-runtime -p yoi-workspace-server (Runtime279+17+17 Backend576+11); fmt/diff. Logs target/validation/T-699/rereview-{check,core,hosts}.log. Earlier intermediate parity/WIP assertion failures retained, not passing evidence. No target/ref integration, RO source changes, environment update or completion.
This commit is contained in:
2026-10-06 04:24:35 +09:00
parent b952e56bc2
commit 7a96c42130
10 changed files with 1196 additions and 206 deletions
+76
View File
@@ -50,6 +50,82 @@ async fn call(
.await
}
#[tokio::test]
async fn checkout_wip_search_preserves_root_and_nested_ignore_rules_and_links() {
let dir = TempDir::new().unwrap();
std::fs::create_dir(dir.path().join(".git")).unwrap();
std::fs::create_dir(dir.path().join("nested")).unwrap();
for (name, content) in [
(".ignore", "root-denied.txt\npriority.txt\n"),
(".gitignore", "git-denied.txt\n"),
("nested/.gitignore", "!priority.txt\nnested-denied.txt\n"),
] {
std::fs::write(dir.path().join(name), content).unwrap();
}
for name in [
"visible.txt",
"root-denied.txt",
"git-denied.txt",
"nested/visible.txt",
"nested/root-denied.txt",
"nested/git-denied.txt",
"nested/priority.txt",
"nested/nested-denied.txt",
] {
std::fs::write(dir.path().join(name), "needle fixture\n").unwrap();
}
let source = session(&dir, false);
let router = Arc::new(WorkdirSessionRouter::new());
router
.attach(WorkdirAttachmentAlias::new("main").unwrap(), source.clone())
.unwrap();
let r = runtime(router, None);
for base in ["", "nested"] {
let ordinary = source
.glob(workdir::GlobRequest {
path: workdir::WorkdirPath::new(base).unwrap(),
pattern: "**/*.txt".into(),
limit: 100,
})
.await
.unwrap();
let expected = ordinary
.paths
.iter()
.map(|path| format!("/checkouts/main/{}", path.as_str()))
.collect::<Vec<_>>();
assert_eq!(expected.len(), if base.is_empty() { 2 } else { 1 });
let route = if base.is_empty() {
"/checkouts/main"
} else {
"/checkouts/main/nested"
};
for (operation, args) in [
("glob", json!({"pattern":"**/*.txt"})),
(
"grep",
json!({"pattern":"needle","output_mode":"files_with_matches"}),
),
] {
let output = call(&r, route, operation, args).await.unwrap();
let result: Json = serde_json::from_str(output.content.as_deref().unwrap()).unwrap();
let mut paths = result["items"]
.as_array()
.unwrap()
.iter()
.map(|item| item["path"].as_str().unwrap().to_string())
.collect::<Vec<_>>();
// Grep retains traversal order; Glob sorts its result paths.
paths.sort();
assert_eq!(paths, expected, "{operation} at {route}");
for path in paths {
assert!(r.host.projection_live(&path).await.unwrap().is_some());
}
assert!(!output.content.unwrap().contains("denied.txt"));
}
}
}
#[tokio::test]
async fn checkout_wip_native_roundtrip_search_read_edit_write_create() {
let dir = TempDir::new().unwrap();