As of v0.3.0 (c73dc6c).
Summary
parse_porcelain_v2_z (src/segments/git.rs:420) treats every NUL-separated record independently. In --porcelain=v2 -z output, a rename/copy entry (2 <XY> ...<path>) is followed by the origin path as its own NUL-terminated record. That bare path is then fed through parse_record, and if it happens to start with 1 , 2 , u , or ? , it is counted as an additional status entry.
Reproduction
git mv '? note.txt' renamed.txt # a tracked file whose name starts with "? "
git status --porcelain=v2 -z emits 2 R. ... renamed.txt\0? note.txt\0; Nova counts untracked += 1 for the origin-path record, so the prompt shows a ? indicator in a repo with no untracked files.
Cause
The parser has no state for "the previous record was a 2 entry, so the next record is a path, not an entry". Pathological file names are rare, which is why this has not been visible, but the parse is structurally wrong for the documented format (git-status(1), "Porcelain Format Version 2": "the pathnames are separated by a NUL" for rename entries under -z).
Proposed fix
- In the record loop, after parsing a record that starts with
2 , skip the following record unconditionally.
- Add unit tests with
-z rename output where the origin path starts with ? , 1 , and u .
Low severity (cosmetic miscount, requires unusual file names), but it is a two-line fix in a parser that is otherwise carefully tested.
🤖 Generated with Claude Code — Claude Fable 5
As of v0.3.0 (c73dc6c).
Summary
parse_porcelain_v2_z(src/segments/git.rs:420) treats every NUL-separated record independently. In--porcelain=v2 -zoutput, a rename/copy entry (2 <XY> ...<path>) is followed by the origin path as its own NUL-terminated record. That bare path is then fed throughparse_record, and if it happens to start with1,2,u, or?, it is counted as an additional status entry.Reproduction
git status --porcelain=v2 -zemits2 R. ... renamed.txt\0? note.txt\0; Nova countsuntracked += 1for the origin-path record, so the prompt shows a?indicator in a repo with no untracked files.Cause
The parser has no state for "the previous record was a
2entry, so the next record is a path, not an entry". Pathological file names are rare, which is why this has not been visible, but the parse is structurally wrong for the documented format (git-status(1), "Porcelain Format Version 2": "the pathnames are separated by a NUL" for rename entries under-z).Proposed fix
2, skip the following record unconditionally.-zrename output where the origin path starts with?,1, andu.Low severity (cosmetic miscount, requires unusual file names), but it is a two-line fix in a parser that is otherwise carefully tested.
🤖 Generated with Claude Code — Claude Fable 5