fix(shared-writer,sync): include stdout in git cache-failure errors (#601)#606
Merged
Conversation
…601) `git_{commit_in_cache_with_args,in_cache}` in both shared_writer/core.rs and sync/core.rs captured only `output.stderr` when bailing on a non-zero exit. But `git commit`'s "nothing to commit, working tree clean" status message goes to **stdout**, leaving stderr empty — so the user saw `git commit […] in cache failed:` with nothing after the colon and no way to diagnose the failure. Worse, the four "nothing to commit" substring guards in core.rs (write_commit_push and emit_compact_push at lines 318, 416, 506, 976) were dead code for the same reason: `err_str` was built from empty stderr, so it never contained the substring they were checking for. Capturing stdout revives them — they now do what they were written to do. New bail format: git commit ["-m", "..."] in cache failed (exit status: 1): stdout: On branch crosslink/hub nothing to commit, working tree clean stderr: Same treatment applied to all four sites (commit and non-commit, in both modules) since the same shape would surface empty errors for any future failure whose diagnostic lands on stdout (pre-commit hook output, push-side rejections, etc.). Added two regression tests in shared_writer/tests.rs: - test_git_commit_in_cache_includes_stdout_on_failure asserts the "nothing to commit" string surfaces in the error. - test_git_in_cache_includes_stdout_on_failure asserts both stream labels are present on a general git error path. Tests: 2866 pass (2 new). Clippy clean -D warnings. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes GH#601.
git_{commit_in_cache_with_args,in_cache}(both inshared_writer/core.rsandsync/core.rs) captured onlyoutput.stderrwhen bailing on a non-zero exit. Butgit commit's most common failure status —"nothing to commit, working tree clean"— is written to stdout, leaving stderr empty. The user sawError: git commit […] in cache failed:with nothing after the colon and no way to diagnose what went wrong.The fix is a single-shape change applied to all four sites: include
output.stdout,output.stderr, and the exit status in the bail message.Side effect: four dead-code guards in the push path revive
The push paths in
core.rshave four substring-matching guards intended to treat "nothing to commit" as a clean no-op:…at lines 318, 416, 506, 976. They never fired on
main, becauseerr_strwas built from empty stderr. After this fix, the substring lives inerr_strand the guards do what they were written to do — so future no-op commit paths that don't have a per-callsite short-circuit (like the one added for #600) still degrade cleanly instead of bubbling a noisy empty error.New bail format
Same treatment applied to all four sites (
{commit_,}in_cache×{shared_writer,sync}) — the same stdout-vs-stderr trap would mask any future failure whose diagnostic lands on stdout (pre-commit hook output, server-side push rejections that bubble back through stdout, etc.).Out of scope
The issue notes an optional defense-in-depth: detect the no-op explicitly via
git diff --cached --quietbefore invokinggit commit. Skipped here because:Worth a separate PR if the team wants structural robustness against git's wording changing across versions/locales.
Test plan
cargo test --lib --bin crosslink— 2866 passed (2 new regression tests)cargo clippy --lib --bin crosslink --tests -- -D warnings— cleantest_git_commit_in_cache_includes_stdout_on_failure— asserts the "nothing to commit" string surfaces in the bail messagetest_git_in_cache_includes_stdout_on_failure— asserts bothstdout:andstderr:labels appear in non-commit git errors toocrosslink issue create "a" -q; crosslink issue create "b" -q; crosslink issue block L2 L1twice. With fix(shared-writer): make blocker/label/relation mutations idempotent (#600) #605 (thecrosslink issue blockexits non-zero when the blocker is already set #600 fix) merged this hits the per-callsite short-circuit; without it, the second call now reports a meaningful error including"nothing to commit, working tree clean"rather than an emptyfailed:.Related
crosslink issue blockexits non-zero when the blocker is already set #600 (PR fix(shared-writer): make blocker/label/relation mutations idempotent (#600) #605) — user-facing manifestation. Closed by per-callsite idempotency. This PR closes the underlying diagnostic-loss bug, which would have masked any similar future failure mode.🤖 Generated with Claude Code