Skip to content

Commit

Permalink
fix: Assure that worktrees in hidden directories are not deleted (Git…
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron authored and LuaKT committed Aug 20, 2024
1 parent d03350e commit 35fd700
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 4 deletions.
13 changes: 11 additions & 2 deletions gix-dir/src/walk/classify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,17 @@ pub fn path(
),
);
}
if kind.map_or(false, |d| d.is_recursable_dir()) && out.pathspec_match.is_none() {
// we have patterns that didn't match at all, *yet*. We want to look inside.
if kind.map_or(false, |d| d.is_recursable_dir())
&& (out.pathspec_match.is_none()
|| worktree_relative_worktree_dirs.map_or(false, |worktrees| {
for_deletion.is_some()
&& worktrees
.iter()
.any(|dir| dir.starts_with_str(&*rela_path) && dir.get(rela_path.len()) == Some(&b'/'))
}))
{
// We have patterns that didn't match at all, *yet*, or there are contained worktrees.
// We want to look inside.
out.pathspec_match = Some(PathspecMatch::Prefix);
}
}
Expand Down
3 changes: 2 additions & 1 deletion gix-dir/tests/fixtures/many.sh
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ git clone dir-with-tracked-file in-repo-worktree
git clone dir-with-tracked-file in-repo-hidden-worktree
(cd in-repo-hidden-worktree
echo '/hidden/' > .gitignore
mkdir -p hidden/sbudir
mkdir -p hidden/subdir
touch hidden/file
git worktree add -b worktree-branch hidden/subdir/worktree
)
44 changes: 43 additions & 1 deletion gix-dir/tests/walk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4579,6 +4579,7 @@ fn in_repo_hidden_worktree() -> crate::Result {
&root,
ctx,
walk::Options {
for_deletion: None,
worktree_relative_worktree_dirs: Some(&BTreeSet::from(["hidden/subdir/worktree".into()])),
..options_emit_all()
},
Expand All @@ -4601,7 +4602,48 @@ fn in_repo_hidden_worktree() -> crate::Result {
entry("dir/file", Tracked, File),
entry("hidden", Ignored(Expendable), Directory),
],
"Currently, worktrees can't be found in ignored directories, even though hit should"
"Without the intend to delete, the worktree remains hidden, which is what we want to see in a `status` for example"
);

for ignored_emission_mode in [Matching, CollapseDirectory] {
for deletion_mode in [
ForDeletionMode::IgnoredDirectoriesCanHideNestedRepositories,
ForDeletionMode::FindRepositoriesInIgnoredDirectories,
ForDeletionMode::FindNonBareRepositoriesInIgnoredDirectories,
] {
let ((out, _root), entries) = collect(&root, None, |keep, ctx| {
walk(
&root,
ctx,
walk::Options {
emit_ignored: Some(ignored_emission_mode),
for_deletion: Some(deletion_mode),
worktree_relative_worktree_dirs: Some(&BTreeSet::from(["hidden/subdir/worktree".into()])),
..options_emit_all()
},
keep,
)
});
assert_eq!(
out,
walk::Outcome {
read_dir_calls: 4,
returned_entries: entries.len(),
seen_entries: 5,
}
);
assert_eq!(
entries,
&[
entry_nokind(".git", Pruned).with_property(DotGit).with_match(Always),
entry(".gitignore", Untracked, File),
entry("dir/file", Tracked, File),
entry("hidden/file", Ignored(Expendable), File),
entry("hidden/subdir/worktree", Tracked, Repository).no_index_kind(),
],
"Worktrees within hidden directories are also detected and protected by counting them as tracked (like submodules)"
);
}
}
Ok(())
}

0 comments on commit 35fd700

Please sign in to comment.