Skip to content

[Git] Stop returning quoted, octal-escaped untracked paths - #40

Merged
KCaverly merged 3 commits into
mainfrom
ct/diff_view/536182cd
Jul 26, 2026
Merged

[Git] Stop returning quoted, octal-escaped untracked paths#40
KCaverly merged 3 commits into
mainfrom
ct/diff_view/536182cd

Conversation

@KCaverly

@KCaverly KCaverly commented Jul 26, 2026

Copy link
Copy Markdown
Owner

UntrackedFiles read git status --porcelain without -z, so git applied its
quoting rules to any path that wasn't plain ASCII. A file called spaced name.txt came back as "spaced name.txt", quotes included, and an accented
one as "unicod\303\251.txt" with the bytes escaped octally. The diff
viewer prints those verbatim in its file index, so the mangling was already
visible today wherever a new file had a space in its name.

-z turns quoting off and NUL-fences the records instead, which is also what
lets a path hold a space without git needing to quote it in the first place.
parseUntracked splits on NUL to match.

This is a prerequisite for rendering untracked file contents: those paths
get handed to git to open, and the quoted form resolves to nothing.

The unit test had encoded the wrong assumption — it fed ?? path with spaces.md to the parser, a line plain --porcelain would never emit — so it
passed either way. It now uses the real NUL-fenced shape, and a new
integration test round-trips through the filesystem: whatever UntrackedFiles
returns has to stat.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com


Stack (bottom → top):

  1. [Git] Stop inlining binary literals in the per-commit diff #38
  2. [UI] Re-prime the stack preview when the status behind it changes #39
  3. [Git] Stop returning quoted, octal-escaped untracked paths #40 ← this PR
  4. [Git] Add DiffUntracked to render untracked file contents #41
  5. [UI] Show uncommitted work as a row in the stack #42
  6. [UI] Name one way out of the stack preview #43
  7. [UI] Give d the preview and esc the way out #44
  8. [UI] Drop the branch-diff jump from the stack screen #45
  9. [UI] Stop the stack preview overrunning a narrow terminal #46
  10. [Git] Pin the diff flags the body parser depends on #47
  11. [UI] Teach both diff viewers the same file-jump key #48
  12. [Diff] Thread the [diff] config through the viewer and zoom with z #49
  13. [Git] Carry diff args and excludes through every diff call #50
  14. [Diff] Add the external diff pager package #51
  15. [Config] Accept a [diff] section with an optional pager #52
  16. [Docs] Document the diff viewer settings #53

KCaverly and others added 3 commits July 26, 2026 15:23
DiffCommit/NumstatCommit passed --binary, which the branch-wide
DiffAgainstBase never did. --binary is for producing appliable patches: it
makes git inline a base85 "GIT binary patch" literal for every changed
binary file. A 3KB blob expands to 123 lines; a few hundred KB is enough to
exhaust the viewer's 20k-line cap and leave the preview pane showing
nothing but base85.

It also mis-colours: git's base85 alphabet includes + and -, so the diff
body styler paints scattered literal lines as additions and deletions.

Dropping the flag yields the usual one-line "Binary files a/x and b/x
differ", matching DiffAgainstBase. The numstat path is unaffected — it
already reported binary files as Binary with zero counts, so the file index
still renders them as "binary".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ct-stack-id: 7e62f7d8
Refreshing with the preview pane open left it on "loading diff…" forever.
applyStackStatus drops the per-commit diff cache — correctly, since a
restack or amend can move SHAs out from under it — but nothing re-issued
the fetch, so the pane went on looking up a key that would never be filled.
Only nudging the cursor onto another commit brought it back. Pressing r,
the most natural thing to do while reading a diff, was enough to hit it.

The four status-bearing results now re-kick the cursored commit's fetch
through ensureSplitDiff, which no-ops unless the preview is actually on
screen. Doing it at the message handler rather than inside the apply
helpers keeps them free of command plumbing and covers submit, restack and
merge — restack lands a status whose SHAs are all new, so it misses the
cache the same way a refresh does.

A real restack also drops the cache outright now, so a resurrected SHA
cannot serve a pre-restack patch. The dry run leaves it alone; it only
renders a plan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ct-stack-id: bdeaacb1
UntrackedFiles read `git status --porcelain` without -z, so git applied its
quoting rules to any path that wasn't plain ASCII. A file called `spaced
name.txt` came back as `"spaced name.txt"`, quotes included, and an accented
one as `"unicod\303\251.txt"` with the bytes escaped octally. The diff
viewer prints those verbatim in its file index, so the mangling was already
visible today wherever a new file had a space in its name.

-z turns quoting off and NUL-fences the records instead, which is also what
lets a path hold a space without git needing to quote it in the first place.
parseUntracked splits on NUL to match.

This is a prerequisite for rendering untracked file contents: those paths
get handed to git to open, and the quoted form resolves to nothing.

The unit test had encoded the wrong assumption — it fed `?? path with
spaces.md` to the parser, a line plain --porcelain would never emit — so it
passed either way. It now uses the real NUL-fenced shape, and a new
integration test round-trips through the filesystem: whatever UntrackedFiles
returns has to stat.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ct-stack-id: 536182cd
@KCaverly
KCaverly force-pushed the ct/diff_view/bdeaacb1 branch from 9a60c33 to 2a3913f Compare July 26, 2026 19:23
@KCaverly
KCaverly force-pushed the ct/diff_view/536182cd branch from 1e6423c to 4b74429 Compare July 26, 2026 19:23
Base automatically changed from ct/diff_view/bdeaacb1 to main July 26, 2026 19:29
@KCaverly
KCaverly merged commit 5920dce into main Jul 26, 2026
2 checks passed
@KCaverly
KCaverly deleted the ct/diff_view/536182cd branch July 26, 2026 19:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant