diff --git a/gix-dir/src/walk/readdir.rs b/gix-dir/src/walk/readdir.rs index 178a03295..c520f39d7 100644 --- a/gix-dir/src/walk/readdir.rs +++ b/gix-dir/src/walk/readdir.rs @@ -359,6 +359,11 @@ impl Mark { return None; } + let collapsed_property = state.on_hold[self.start_index..] + .iter() + .all(|entry| entry.property == Some(entry::Property::EmptyDirectory)) + .then_some(entry::Property::EmptyDirectory); + // Pathspecs affect the collapse of the next level, hence find the highest-value one. let dir_pathspec_match = state.on_hold[self.start_index..] .iter() @@ -396,6 +401,7 @@ impl Mark { Cow::Borrowed(dir_rela_path), classify::Outcome { status: dir_status, + property: dir_info.property.or(collapsed_property), pathspec_match: dir_pathspec_match, ..dir_info }, diff --git a/gix-dir/tests/dir/walk.rs b/gix-dir/tests/dir/walk.rs index 09ff80b17..4cfa6a327 100644 --- a/gix-dir/tests/dir/walk.rs +++ b/gix-dir/tests/dir/walk.rs @@ -443,7 +443,7 @@ fn complex_empty() -> crate::Result { &[ entry("dirs-and-files", Untracked, Directory), entry("empty-toplevel", Untracked, Directory).with_property(EmptyDirectory), - entry("only-dirs", Untracked, Directory), + entry("only-dirs", Untracked, Directory).with_property(EmptyDirectory), ], "empty directories collapse just fine" ); diff --git a/gix/tests/fixtures/make_status_repos.sh b/gix/tests/fixtures/make_status_repos.sh index a4de9fbe0..418f6a3ca 100755 --- a/gix/tests/fixtures/make_status_repos.sh +++ b/gix/tests/fixtures/make_status_repos.sh @@ -69,3 +69,12 @@ git init -q submodule-assume-unchanged-symlink rm -Rf sub ln -s ../module sub ) + +git init -q nested-empty-tree +(cd nested-empty-tree + touch tracked + git add tracked + git commit -q -m init + + mkdir -p empty/nested +) diff --git a/gix/tests/gix/status.rs b/gix/tests/gix/status.rs index 4fd061dc3..1cf960c73 100644 --- a/gix/tests/gix/status.rs +++ b/gix/tests/gix/status.rs @@ -342,6 +342,25 @@ mod index_worktree { Ok(()) } + #[test] + fn nested_empty_directories_are_ignored() -> crate::Result { + let repo = repo("nested-empty-tree")?; + let mut status = repo + .status(gix::progress::Discard)? + .index_worktree_options_mut(|opts| { + opts.sorting = + Some(gix::status::plumbing::index_as_worktree_with_renames::Sorting::ByPathCaseSensitive); + }) + .into_index_worktree_iter(None)?; + let items: Vec<_> = status.by_ref().filter_map(Result::ok).collect(); + assert_eq!( + items, + [], + "directories that only contain empty subdirectories should not be reported as untracked" + ); + Ok(()) + } + #[test] fn untracked_files_collapse_by_default() -> crate::Result { let repo = repo("untracked-only")?;