Use inherited stdio for git diff/show to support external diff tools and native paging

This commit is contained in:
Chris Wanstrath 2026-02-22 07:31:30 -08:00
parent 10ebfcf754
commit 4cde0c2086
2 changed files with 29 additions and 30 deletions

View File

@ -1,6 +1,5 @@
import { $ } from "bun" import { $ } from "bun"
import * as git from "../git.ts" import * as git from "../git.ts"
import { pager } from "../fmt.ts"
import { requireSession } from "./helpers.ts" import { requireSession } from "./helpers.ts"
export async function action(branch: string) { export async function action(branch: string) {
@ -13,27 +12,26 @@ export async function action(branch: string) {
process.exit(1) process.exit(1)
} }
let diff: string let args: string[]
if (status.text().trim().length > 0) { if (status.text().trim().length > 0) {
// Show uncommitted changes (both staged and unstaged) // Show uncommitted changes (both staged and unstaged)
const result = await $`git -C ${session.worktree} diff --color=always HEAD`.nothrow().quiet() const hasHead = await $`git -C ${session.worktree} rev-parse --verify HEAD`.nothrow().quiet()
if (result.exitCode !== 0) { args = hasHead.exitCode === 0 ? ["diff", "HEAD"] : ["diff"]
// HEAD may not exist yet (no commits); fall back to showing all tracked + untracked
const fallback = await $`git -C ${session.worktree} diff --color=always`.nothrow().quiet()
diff = fallback.text()
} else {
diff = result.text()
}
} else { } else {
// No uncommitted changes — show full branch diff vs main // No uncommitted changes — show full branch diff vs main
const main = await git.mainBranch(session.worktree) const main = await git.mainBranch(session.worktree)
const result = await $`git -C ${session.worktree} diff --color=always ${main}...${branch}`.nothrow().quiet() args = ["diff", `${main}...${branch}`]
if (result.exitCode !== 0) {
console.error("✖ git diff failed")
process.exit(1)
}
diff = result.text()
} }
await pager(diff) // Run git diff with inherited stdio so external diff tools (e.g. difftastic)
// see a real TTY and git can use its own pager
const proc = Bun.spawn(["git", "-C", session.worktree, ...args], {
stdin: "inherit",
stdout: "inherit",
stderr: "inherit",
})
const exitCode = await proc.exited
if (exitCode !== 0) {
process.exit(exitCode)
}
} }

View File

@ -1,23 +1,24 @@
import { $ } from "bun"
import * as git from "../git.ts" import * as git from "../git.ts"
import { pager } from "../fmt.ts"
import { requireSession } from "./helpers.ts" import { requireSession } from "./helpers.ts"
export async function action(branch: string) { export async function action(branch: string) {
const { session } = await requireSession(branch) const { session } = await requireSession(branch)
const main = await git.mainBranch(session.worktree)
const result = await $`git -C ${session.worktree} diff --color=always ${main}...${branch}`.nothrow().quiet()
if (result.exitCode !== 0) {
console.error("git diff failed")
process.exit(1)
}
let output = ""
if (session.prompt) { if (session.prompt) {
output += `PROMPT: ${session.prompt}\n\n` process.stderr.write(`PROMPT: ${session.prompt}\n\n`)
} }
output += result.text()
await pager(output) const main = await git.mainBranch(session.worktree)
// Run git diff with inherited stdio so external diff tools (e.g. difftastic)
// see a real TTY and git can use its own pager
const proc = Bun.spawn(["git", "-C", session.worktree, "diff", `${main}...${branch}`], {
stdin: "inherit",
stdout: "inherit",
stderr: "inherit",
})
const exitCode = await proc.exited
if (exitCode !== 0) {
process.exit(exitCode)
}
} }