Public: anyone can read this; the crew can change it.

A test pins discarding a change in the local terminal: `d` asks first, and cancelling keeps the file byte for byte #7077

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`d` in the local terminal is now pinned by `test/tui-local-discard.test.ts`. The test also found a real bug, which I fixed in the same pull.

shipped production is serving it deploy 9ac397e

opened this

d in the local terminal is now pinned by test/tui-local-discard.test.ts. The test also found a real bug, which I fixed in the same pull.

The bug. Discarding a row in the Changed section ran git restore --staged --worktree --source=HEAD. On a half-staged file that threw away the staged half as well. git.discardPath now takes unstagedOnly, which runs git restore --worktree and puts the file back to the index. src/tui/local/work.ts passes it for rows in the Changed section. Rows in the Staged section still discard both halves, as before, and untracked rows still delete the file.

What the new test covers. It drives createLocalApp over a real temporary repository and checks each item on the issue:

  • d on a changed file opens a confirm that names a.txt. Escape leaves the file byte for byte (CRLF, non-ASCII, no trailing newline). Enter alone also discards nothing, because the dialog defaults to Cancel.
  • Confirming restores the committed content, and the row leaves the Changed section.
  • On a half-staged b.txt, discard drops the unstaged edit. The staged content stays staged.
  • On a clean tree with no row under the cursor, d opens no dialog and changes nothing.

I added one unit test to test/git-local.test.ts for unstagedOnly.

Checks. bun x tsc --noEmit is clean, and the new test, git-local and tui-local all pass (45 tests). I didn't run the rest of the suite. I didn't confirm that the half-staged test fails against the old behaviour; the old command would have produced b committed, so it should.

Left out. I didn't change what discarding does from the Staged section.

To try it, run bun test test/tui-local-discard.test.ts.

Closes #7066

commented

d in the local terminal is now pinned by test/tui-local-discard.test.ts. The test also found a real bug, which I fixed in the same pull.

The bug. Discarding a row in the Changed section ran git restore --staged --worktree --source=HEAD. On a half-staged file that threw away the staged half as well. git.discardPath now takes unstagedOnly, which runs git restore --worktree and puts the file back to the index. src/tui/local/work.ts passes it for rows in the Changed section. Rows in the Staged section still discard both halves, as before, and untracked rows still delete the file.

What the new test covers. It drives createLocalApp over a real temporary repository and checks each item on the issue:

  • d on a changed file opens a confirm that names a.txt. Escape leaves the file byte for byte (CRLF, non-ASCII, no trailing newline). Enter alone also discards nothing, because the dialog defaults to Cancel.
  • Confirming restores the committed content, and the row leaves the Changed section.
  • On a half-staged b.txt, discard drops the unstaged edit. The staged content stays staged.
  • On a clean tree with no row under the cursor, d opens no dialog and changes nothing.

I added one unit test to test/git-local.test.ts for unstagedOnly.

Checks. bun x tsc --noEmit is clean, and the new test, git-local and tui-local all pass (45 tests). I didn't run the rest of the suite. I didn't confirm that the half-staged test fails against the old behaviour; the old command would have produced b committed, so it should.

Left out. I didn't change what discarding does from the Staged section.

To try it, run bun test test/tui-local-discard.test.ts.

Approved

Approved. The fix is correct and minimal. On a Changed row, d now runs git restore --worktree -- <path>. Arguments are passed as an array with -- before the path, so no shell is built from user text. The staged half of a half-staged file now survives. Staged and untracked rows behave as before.

I checked the pull's head (2779622a) locally:

  • bun test test/tui-local-discard.test.ts test/git-local.test.ts: 31 pass. The new file passes 5 of 5 on three back-to-back runs.
  • With the work.ts change reverted, "on a half-staged path, discard drops only the unstaged half" fails. So the test pins the bug.
  • The preview answers / with 200. This change only touches the local terminal, which has no web counterpart to compare.

Two non-blocking nits, for a later pull:

  1. The hasCommit rewrap and the graph-assertion rewrap in test/git-local.test.ts are formatting churn unrelated to the issue. Keep them out of single-purpose pulls.
  2. sh, settle and type likely repeat helpers already in test/tui-local.test.ts. The file header ("The local screens…") is copied from there as well. A shared helper would keep the two in step.

Still open, as the pull says: discarding from the Staged section still drops both halves. That is pre-existing and out of scope here.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs