Skip to content

Commit 2e636be

Browse files
committed
fix: Assure that worktrees in hidden directories are not deleted (#1470)
1 parent 2bacc45 commit 2e636be

File tree

3 files changed

+45
-32
lines changed

3 files changed

+45
-32
lines changed

gix-dir/src/walk/classify.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,16 @@ 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+
worktrees
272+
.iter()
273+
.any(|dir| dir.starts_with_str(&*rela_path) && dir.get(rela_path.len()) == Some(&b'/'))
274+
}))
275+
{
276+
// We have patterns that didn't match at all, *yet*, or there are contained worktrees.
277+
// We want to look inside.
270278
out.pathspec_match = Some(PathspecMatch::Prefix);
271279
}
272280
}

gix-dir/tests/fixtures/many.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,7 @@ git clone dir-with-tracked-file in-repo-worktree
448448
git clone dir-with-tracked-file in-repo-hidden-worktree
449449
(cd in-repo-hidden-worktree
450450
echo '/hidden/' > .gitignore
451-
mkdir -p hidden/sbudir
451+
mkdir -p hidden/subdir
452+
touch hidden/file
452453
git worktree add -b worktree-branch hidden/subdir/worktree
453454
)

gix-dir/tests/walk/mod.rs

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4574,34 +4574,38 @@ fn in_repo_hidden_worktree() -> crate::Result {
45744574
"if worktree information isn't provided, they would not be discovered in hidden directories"
45754575
);
45764576

4577-
let ((out, _root), entries) = collect(&root, None, |keep, ctx| {
4578-
walk(
4579-
&root,
4580-
ctx,
4581-
walk::Options {
4582-
worktree_relative_worktree_dirs: Some(&BTreeSet::from(["hidden/subdir/worktree".into()])),
4583-
..options_emit_all()
4584-
},
4585-
keep,
4586-
)
4587-
});
4588-
assert_eq!(
4589-
out,
4590-
walk::Outcome {
4591-
read_dir_calls: 2,
4592-
returned_entries: entries.len(),
4593-
seen_entries: 4,
4594-
}
4595-
);
4596-
assert_eq!(
4597-
entries,
4598-
&[
4599-
entry_nokind(".git", Pruned).with_property(DotGit).with_match(Always),
4600-
entry(".gitignore", Untracked, File),
4601-
entry("dir/file", Tracked, File),
4602-
entry("hidden", Ignored(Expendable), Directory),
4603-
],
4604-
"Currently, worktrees can't be found in ignored directories, even though hit should"
4605-
);
4577+
for ignored_emission_mode in [Matching, CollapseDirectory] {
4578+
let ((out, _root), entries) = collect(&root, None, |keep, ctx| {
4579+
walk(
4580+
&root,
4581+
ctx,
4582+
walk::Options {
4583+
emit_ignored: Some(ignored_emission_mode),
4584+
worktree_relative_worktree_dirs: Some(&BTreeSet::from(["hidden/subdir/worktree".into()])),
4585+
..options_emit_all()
4586+
},
4587+
keep,
4588+
)
4589+
});
4590+
assert_eq!(
4591+
out,
4592+
walk::Outcome {
4593+
read_dir_calls: 4,
4594+
returned_entries: entries.len(),
4595+
seen_entries: 5,
4596+
}
4597+
);
4598+
assert_eq!(
4599+
entries,
4600+
&[
4601+
entry_nokind(".git", Pruned).with_property(DotGit).with_match(Always),
4602+
entry(".gitignore", Untracked, File),
4603+
entry("dir/file", Tracked, File),
4604+
entry("hidden/file", Ignored(Expendable), File),
4605+
entry("hidden/subdir/worktree", Tracked, Repository).no_index_kind(),
4606+
],
4607+
"Worktrees within hidden directories are also detected and protected by counting them as tracked (like submodules)"
4608+
);
4609+
}
46064610
Ok(())
46074611
}

0 commit comments

Comments
 (0)