Files
orca/src/shared/git-command-failure-text.ts
T
Neil 53adf5e2e6 fix(git): share one failed-command error-text reader between local and the SSH relay (#18398)
* fix(git): share one error-text reader between the local and relay branch-delete fallbacks

The relay and the desktop each carried their own `getErrorText`, and they had
drifted: the relay read `message` + `stderr` + `stdout`, the desktop only
`message` + `stderr`. A `git branch -d` refusal arriving on `stdout` therefore
routed the SSH removal through prune-and-retry while the local removal gave up
and preserved the branch.

Against a real binary the two agree, because Git prints the refusal through
`error()` on every supported version — verified on 2.25.1, 2.38.1, 2.49.1 and
2.55.0, none of which put a byte of it on stdout. What the desktop copy actually
missed is that Orca classifies errors it built itself, with the Git output on
`.stdout`: `worktree remove`'s submodule retry attaches `git status --porcelain`
that way on both paths. The stdout-reading form is also already the shared
spelling — `isSubmoduleWorktreeRemovalRefusal` uses it for both hosts — so this
converges on it rather than on the shorter one.

Move the reader to src/shared/git-command-failure-text.ts and the predicate it
feeds to src/shared/git-branch-delete-refusal.ts, and delete all three copies.
The predicate carries both refusal wordings live in the supported range: Git
through 2.40 says "checked out at", 2.43+ says "used by worktree at".

The real-binary contract now pins that boundary: the refusal is recognized, it
lands on stderr, and stdout stays empty on every Git in the matrix.

* fix(test): consolidate the duplicate worktree import in the parity test
2026-09-03 14:42:54 -07:00

28 lines
1.2 KiB
TypeScript

/**
* The text a failed Git invocation left behind, for the predicates that classify a
* failure by what Git said.
*
* Why all three streams and not just `message` + `stderr`: the errors Orca classifies
* do not all come straight out of `execFile`. Node puts Git's stderr in both `message`
* and `stderr`, but Orca also throws its own failures with the Git output on `stdout`
* (`worktree remove`'s submodule retry attaches `git status --porcelain` output that
* way on both the local runner and the relay). Reading all three is what keeps the
* local and relay classifiers from disagreeing about the same error object.
*
* Against a real binary this reads no differently: Git emits every refusal this module
* classifies through `error()`/`die()`, i.e. stderr only, on 2.25 through 2.55.
*/
export function readGitCommandFailureText(error: unknown): string {
if (typeof error !== 'object' || error === null) {
return String(error)
}
const parts: string[] = []
for (const field of ['message', 'stderr', 'stdout'] as const) {
const value = (error as Record<string, unknown>)[field]
if (typeof value === 'string' && value) {
parts.push(value)
}
}
return parts.join('\n')
}