Skip to content

refactor(errors): route git-plumbing failure bails through CommandError#3474

Merged
max-sixty merged 2 commits into
mainfrom
normalize-stdout-cr
Jul 15, 2026
Merged

refactor(errors): route git-plumbing failure bails through CommandError#3474
max-sixty merged 2 commits into
mainfrom
normalize-stdout-cr

Conversation

@max-sixty

Copy link
Copy Markdown
Owner

Follow-up to #3459. Eight git-plumbing sites turned a captured non-zero exit into bail!("…{stderr}"), bypassing CommandError::from_failed_output — the one constructor that normalizes \r and gives renderers the typed command/output split. This converts them (resolve_git_common_dir, the bulk config --list read, config --unset, config --get-regexp, merge-tree, merge-base, the untracked-diff numstat, and llm.rs::run_git_capture), so failed-command display routes through one constructor and the main.rs multiline-error tripwire has nothing left to catch on these paths. from_failed_output now takes &[impl AsRef<str>] so Vec<String> arg lists work.

One structural fix rode along: generate_commit_message now wraps only the execute_llm_command failure in GitError::LlmCommandFailed, mirroring generate_squash_message — a git failure while building the prompt is not an LLM-command failure, and flattening it into LlmCommandFailed.error dropped the typed stderr.

Rendering: context-wrapped failures render byte-identically (the outside-repo snapshots pass untouched); bare ones gain the standard git … failed (exit N) header + gutter. The only snapshot changes are two wt list task-failure lines where merge-base errors drop the hand-rolled git merge-base failed for <sha> <sha>: prefix and now match their sibling lines.

Every converted error path has a direct test — five new ones using empirically-probed failure modes (invalid regexp pattern → exit 6, invalid key → exit 1, corrupt config → 128 for the lazily-populated bulk read and merge-tree, unborn HEAD for the numstat), plus the updated run_git_capture unit test; resolve_git_common_dir and merge_base were already covered by existing snapshots.

Two same-pattern sites remain in the commands layer (step/shared.rs ls-files, step/commit.rs stage-to-temp-index) — deliberately left for a follow-up along with the non-git CLIs (gh/glab, claude/codex).

This was written by Claude Code on behalf of max

Eight sites turned a captured non-zero exit into bail!("…{stderr}"),
bypassing CommandError::from_failed_output — the one constructor that
normalizes \r and gives renderers the typed command/output split. Convert
them: resolve_git_common_dir, the bulk config --list read, config --unset,
config --get-regexp, merge-tree, merge-base, the untracked-diff numstat,
and llm.rs run_git_capture (which now builds the Cmd itself so it can name
the args). from_failed_output takes &[impl AsRef<str>] so Vec<String>
arg lists work.

generate_commit_message now wraps only the execute_llm_command failure in
LlmCommandFailed, mirroring generate_squash_message — a git failure while
building the prompt is not an LLM-command failure, and flattening it into
LlmCommandFailed.error dropped the typed stderr.

Rendering: wrapped failures (context + CommandError) render identically;
bare ones gain the standard 'git … failed (exit N)' header + gutter. The
wt list task-failure lines for merge-base errors drop the hand-rolled
'git merge-base failed for <sha> <sha>:' prefix and now match their
sibling lines (bare stderr), per the updated snapshots.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@worktrunk-bot worktrunk-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, behavior-preserving refactor — every converted path now routes failed-command display through the single from_failed_output constructor, and the direct-test coverage on each is thorough. One optional micro-nit inline; nothing blocking.

Comment thread src/git/repository/working_tree.rs Outdated
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@max-sixty max-sixty merged commit 489fd0f into main Jul 15, 2026
34 of 35 checks passed
@max-sixty max-sixty deleted the normalize-stdout-cr branch July 15, 2026 05:42
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.

2 participants