What's wrong
The default untracked mode is GitUntrackedFilesMode.Normal. In that mode, git collapses a directory with no tracked files to a single record, ? newdir/, with a trailing slash. The collapse itself is documented on the enum.
However, Parsing/GitStatusParser.cs (ReadPathOnlyEntry, around lines 76 and 220) converts the path with GitParseValues.ToRelativeFilePath, which loses the trailing /. GitStatusEntry has no directory flag either. The entry is typed as a RelativeFilePath, and nothing indicates that it is a directory. Ignored (!) records have the same problem.
Failure scenario
Commit a.txt, then create newdir/x.txt. Status() returns a single entry: Path='newdir', Untracked. That is exactly what an untracked file named newdir would produce.
- A "discard untracked files" feature that calls
File.Delete(entry.Path) throws or does nothing.
- A UI can't show a folder or offer to expand it.
An untracked nested repository or submodule checkout shows up the same way.
This was reproduced with a scratch integration test through the public Status() API, which printed STATUS 'newdir' Untracked.
Suggested fix / acceptance criteria
- Detect the trailing
/ on ? and ! records and surface it, for example with bool IsDirectory on GitStatusEntry, or with a directory-path type.
- Tests:
- in default mode,
Status() over an untracked directory reports an entry marked as a directory;
- an untracked file with the same name is not marked as a directory.
What's wrong
The default untracked mode is
GitUntrackedFilesMode.Normal. In that mode, git collapses a directory with no tracked files to a single record,? newdir/, with a trailing slash. The collapse itself is documented on the enum.However,
Parsing/GitStatusParser.cs(ReadPathOnlyEntry, around lines 76 and 220) converts the path withGitParseValues.ToRelativeFilePath, which loses the trailing/.GitStatusEntryhas no directory flag either. The entry is typed as aRelativeFilePath, and nothing indicates that it is a directory. Ignored (!) records have the same problem.Failure scenario
Commit
a.txt, then createnewdir/x.txt.Status()returns a single entry:Path='newdir',Untracked. That is exactly what an untracked file namednewdirwould produce.File.Delete(entry.Path)throws or does nothing.An untracked nested repository or submodule checkout shows up the same way.
This was reproduced with a scratch integration test through the public
Status()API, which printedSTATUS 'newdir' Untracked.Suggested fix / acceptance criteria
/on?and!records and surface it, for example withbool IsDirectoryonGitStatusEntry, or with a directory-path type.Status()over an untracked directory reports an entry marked as a directory;