Skip to content

Commit 348b9bf

Browse files
committed
Merge branch 'fix-clean'
2 parents 8b09cf2 + 31e795a commit 348b9bf

File tree

3 files changed

+117
-3
lines changed

3 files changed

+117
-3
lines changed

gix-dir/src/walk/classify.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,17 @@ pub fn path(
265265
),
266266
);
267267
}
268-
if kind.map_or(false, |d| d.is_recursable_dir()) && out.pathspec_match.is_none() {
269-
// we have patterns that didn't match at all, *yet*. We want to look inside.
268+
if kind.map_or(false, |d| d.is_recursable_dir())
269+
&& (out.pathspec_match.is_none()
270+
|| worktree_relative_worktree_dirs.map_or(false, |worktrees| {
271+
for_deletion.is_some()
272+
&& worktrees
273+
.iter()
274+
.any(|dir| dir.starts_with_str(&*rela_path) && dir.get(rela_path.len()) == Some(&b'/'))
275+
}))
276+
{
277+
// We have patterns that didn't match at all, *yet*, or there are contained worktrees.
278+
// We want to look inside.
270279
out.pathspec_match = Some(PathspecMatch::Prefix);
271280
}
272281
}

gix-dir/tests/fixtures/many.sh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,4 +443,12 @@ git clone dir-with-tracked-file in-repo-worktree
443443
(cd in-repo-worktree
444444
git worktree add worktree
445445
git worktree add -b other-worktree dir/worktree
446-
)
446+
)
447+
448+
git clone dir-with-tracked-file in-repo-hidden-worktree
449+
(cd in-repo-hidden-worktree
450+
echo '/hidden/' > .gitignore
451+
mkdir -p hidden/subdir
452+
touch hidden/file
453+
git worktree add -b worktree-branch hidden/subdir/worktree
454+
)

gix-dir/tests/walk/mod.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4550,3 +4550,100 @@ fn in_repo_worktree() -> crate::Result {
45504550
);
45514551
Ok(())
45524552
}
4553+
4554+
#[test]
4555+
fn in_repo_hidden_worktree() -> crate::Result {
4556+
let root = fixture("in-repo-hidden-worktree");
4557+
let ((out, _root), entries) = collect(&root, None, |keep, ctx| walk(&root, ctx, options_emit_all(), keep));
4558+
assert_eq!(
4559+
out,
4560+
walk::Outcome {
4561+
read_dir_calls: 2,
4562+
returned_entries: entries.len(),
4563+
seen_entries: 4,
4564+
}
4565+
);
4566+
assert_eq!(
4567+
entries,
4568+
&[
4569+
entry_nokind(".git", Pruned).with_property(DotGit).with_match(Always),
4570+
entry(".gitignore", Untracked, File),
4571+
entry("dir/file", Tracked, File),
4572+
entry("hidden", Ignored(Expendable), Directory),
4573+
],
4574+
"if worktree information isn't provided, they would not be discovered in hidden directories"
4575+
);
4576+
4577+
let ((out, _root), entries) = collect(&root, None, |keep, ctx| {
4578+
walk(
4579+
&root,
4580+
ctx,
4581+
walk::Options {
4582+
for_deletion: None,
4583+
worktree_relative_worktree_dirs: Some(&BTreeSet::from(["hidden/subdir/worktree".into()])),
4584+
..options_emit_all()
4585+
},
4586+
keep,
4587+
)
4588+
});
4589+
assert_eq!(
4590+
out,
4591+
walk::Outcome {
4592+
read_dir_calls: 2,
4593+
returned_entries: entries.len(),
4594+
seen_entries: 4,
4595+
}
4596+
);
4597+
assert_eq!(
4598+
entries,
4599+
&[
4600+
entry_nokind(".git", Pruned).with_property(DotGit).with_match(Always),
4601+
entry(".gitignore", Untracked, File),
4602+
entry("dir/file", Tracked, File),
4603+
entry("hidden", Ignored(Expendable), Directory),
4604+
],
4605+
"Without the intend to delete, the worktree remains hidden, which is what we want to see in a `status` for example"
4606+
);
4607+
4608+
for ignored_emission_mode in [Matching, CollapseDirectory] {
4609+
for deletion_mode in [
4610+
ForDeletionMode::IgnoredDirectoriesCanHideNestedRepositories,
4611+
ForDeletionMode::FindRepositoriesInIgnoredDirectories,
4612+
ForDeletionMode::FindNonBareRepositoriesInIgnoredDirectories,
4613+
] {
4614+
let ((out, _root), entries) = collect(&root, None, |keep, ctx| {
4615+
walk(
4616+
&root,
4617+
ctx,
4618+
walk::Options {
4619+
emit_ignored: Some(ignored_emission_mode),
4620+
for_deletion: Some(deletion_mode),
4621+
worktree_relative_worktree_dirs: Some(&BTreeSet::from(["hidden/subdir/worktree".into()])),
4622+
..options_emit_all()
4623+
},
4624+
keep,
4625+
)
4626+
});
4627+
assert_eq!(
4628+
out,
4629+
walk::Outcome {
4630+
read_dir_calls: 4,
4631+
returned_entries: entries.len(),
4632+
seen_entries: 5,
4633+
}
4634+
);
4635+
assert_eq!(
4636+
entries,
4637+
&[
4638+
entry_nokind(".git", Pruned).with_property(DotGit).with_match(Always),
4639+
entry(".gitignore", Untracked, File),
4640+
entry("dir/file", Tracked, File),
4641+
entry("hidden/file", Ignored(Expendable), File),
4642+
entry("hidden/subdir/worktree", Tracked, Repository).no_index_kind(),
4643+
],
4644+
"Worktrees within hidden directories are also detected and protected by counting them as tracked (like submodules)"
4645+
);
4646+
}
4647+
}
4648+
Ok(())
4649+
}

0 commit comments

Comments
 (0)