fix: don't report a tree of only empty directories as untracked. (#2490)#2673
fix: don't report a tree of only empty directories as untracked. (#2490)#2673Amey Pawar (ameyypawar) wants to merge 5 commits into
Conversation
… dirs When a directory is collapsed during the worktree walk and every collapsed entry is itself an empty directory, the collapsed directory has no files to track. Previously the `EmptyDirectory` property was dropped on collapse, so such a tree was reported as `Untracked` -- which made `gix status` surface it (and, via a submodule, report the submodule as modified) even though Git considers a tree of only empty directories clean. Propagate `EmptyDirectory` to the collapsed directory in that case so callers that skip empty directories by default (like status) behave like Git. For GitoxideLabs#2490
Deletion mode has its own handling of empty directories; restrict the `EmptyDirectory`-on-collapse propagation to status-like walks (`for_deletion.is_none()`) so deletion behavior is unchanged.
…ideLabs#2490) Update the collapse expectation for a tree of only empty directories (now carries the EmptyDirectory property) and add a regression that such a tree is not emitted when empty directories aren't requested, matching Git treating it as clean.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 558d947c51
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "Codex (@codex) review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "Codex (@codex) address that feedback".
| let collapsed_property = (opts.for_deletion.is_none() | ||
| && state.on_hold[self.start_index..] | ||
| .iter() | ||
| .all(|entry| entry.property == Some(entry::Property::EmptyDirectory))) |
There was a problem hiding this comment.
Restrict empty-directory tagging to untracked collapses
This applies the EmptyDirectory property to ignored collapses as well as untracked ones. In a non-deletion status walk with emit_ignored: Some(CollapseDirectory) (the --ignored default maps to this in gitoxide-core/src/repository/status.rs, and the CLI option is documented to show ignored files/directories in src/plumbing/options/mod.rs), a pathspec can force an ignored empty directory to be recursed; e.g. .gitignore contains ignored/, the worktree has only ignored/sub/, and the user runs gix status --ignored=collapsed ignored. The collapsed ignored entry is then filtered out later by emit_entry because emit_empty_directories is false, so the explicitly requested ignored directory disappears. Please gate this propagation on dir_status == Untracked or otherwise avoid treating ignored collapses as skippable empty directories.
Useful? React with 👍 / 👎.
An explicitly requested ignored directory (e.g. `gix status --ignored=collapsed <pathspec>`) must remain observable even when it is empty; tagging its collapse as `EmptyDirectory` caused it to be filtered out when empty directories aren't emitted. Restrict the propagation to untracked collapses, which is the only case GitoxideLabs#2490 is about.
`some/` (a tree of only empty directories) now collapses to an empty directory and is skipped when empty directories aren't emitted, matching Git which treats a tree with no files as clean. See GitoxideLabs#2490.
|
You are on fire! And I just noticed this myself, and this PR fixes it. I will try to get this merged soon! |
What
Fixes #2490.
gix status --submodules allreported a submodule as modified when it contained only empty untracked directories — Git treats a tree with no files as clean. The same surfaced as a phantom? empty-dir/in plaingix status.Root cause
gix-dir's worktree walk dropped theEmptyDirectoryproperty when collapsing a directory: a tree of only empty subdirectories collapsed to a plainUntrackeddirectory, which status then surfaced (and a submodule containing it appeared modified).Fix
In
try_collapse(gix-dir/src/walk/readdir.rs), when every collapsed entry is itself anEmptyDirectory, the collapsed directory inheritsEmptyDirectory— so callers that skip empty directories by default (like status) behave like Git.This is scoped to non-deletion walks (
for_deletion.is_none()). Deletion has its own handling of empty directories —gix cleanalways runs withfor_deletion: Some(…), so it is unaffected and still sees these directories for removal. The boundary cleanly separates status (read-only, wants empty-only trees skipped) from clean/deletion (wants them visible).Tests
gix-dir/tests/dir/walk.rs(complex_empty):only-dirs(a tree of only empty subdirs) now carriesEmptyDirectory.emit_empty_directories: false+ collapse, an empty-only tree is not emitted, matching Git treating it as clean.Verification
gix-dirtests pass (including the deletion tests, unaffected by the scoping);cargo clippy -p gix-dir --testsandcargo fmt --checkclean.gix status --submodules allon the issue's exact repro is now clean (wasM config).Notes
EmptyDirectory(a cosmetic " empty" label ingix clean) is left untouched deliberately — happy to extend if you'd prefer.