gitproto: match CommandStatusErr by value so target-ref moves classify#72
Closed
nodo wants to merge 1 commit into
Closed
gitproto: match CommandStatusErr by value so target-ref moves classify#72nodo wants to merge 1 commit into
nodo wants to merge 1 commit into
Conversation
asRefRejectedError and annotateLeaseFailure used errors.As against a
*packp.CommandStatusErr (pointer) target, but go-git returns CommandStatusErr
BY VALUE from ReportStatus.Error() (value receiver, constructed by value in
report_status.go). A pointer target never matches a value in the error chain,
so on the real receive-pack path the errors.As fell through, no *RefRejectedError
was built, moved was never set, and errors.Is(err, ErrTargetRefMoved) was always
false. Every live concurrent target-ref rejection ("remote ref has changed")
passed through unclassified — the typed-rejection feature was inert in
production. The same bug silently disabled the lease-failure hint.
The existing unit tests masked it by feeding &packp.CommandStatusErr{} (a
pointer) as input, which the pointer target does match — but that is not how
go-git hands the error over. Switch both functions to a value target, make the
table tests construct their input via go-git's real (&CommandStatus{}).Error()
(value), and add TestAsRefRejectedError_RealReportStatusPath which drives a real
ReportStatus.Error() end to end so a pointer-vs-value relapse fails CI.
Bug was in the unreleased typed-rejection feature (#71); never shipped tagged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
Superseded by #73 — same fix, recreated with the Entire session checkpoint trailer attached. |
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.
Problem
ErrTargetRefMoved(PR #71, unreleased) never attaches on the real push path.asRefRejectedErrorandannotateLeaseFailurematch go-git'sCommandStatusErrwith a pointer target:but go-git returns
CommandStatusErrby value fromReportStatus.Error()(value receiverError(), constructed by value inreport_status.go).errors.Asagainst a**CommandStatusErrtarget never matches a value-typedCommandStatusErrin the chain, so:asRefRejectedErrorfalls through → no*RefRejectedError,movednever set →errors.Is(err, ErrTargetRefMoved)is alwaysfalseon a live receive-pack rejection.annotateLeaseFailurefalls through → the lease-failure hint never fires.Net effect: every concurrent target-ref rejection (
remote ref has changed) passes through unclassified. The downstream mirror-pipeline worker that relies onerrors.Is(err, ErrTargetRefMoved)to classify benign races sees nothing — the typed-rejection feature is inert in production.The existing tests masked this by feeding
&packp.CommandStatusErr{}(a pointer) as input, which the pointer target does match — but that is not how go-git hands the error over.Fix
errors.Astarget (var cs packp.CommandStatusErr), matching go-git's actual return type. go-git's own tests confirm a value target is correct (s.ErrorAs(rs.Error(), &CommandStatusErr{})).(&packp.CommandStatus{...}).Error()(value), and the underlying-error assertions use value targets.TestAsRefRejectedError_RealReportStatusPathdrives a realReportStatus.Error()end to end through the production wrap — it fails on the pointer target and passes on the value target, so a pointer-vs-value relapse fails CI.Verification
go test ./...,go vet,gofmtall clean. Confirmed the new test fails on the pre-fix pointer target and passes after.Bug was in the unreleased typed-rejection feature (#71); never shipped in a tagged release.
🤖 Generated with Claude Code
Note
Low Risk
Narrow error-wrapping fix in push status handling with stronger tests; behavior change is enabling the intended unreleased API rather than altering unrelated push logic.
Overview
Fixes typed push-rejection handling on the live receive-pack path so
errors.Asinto*RefRejectedErroranderrors.IsforErrTargetRefMovedactually work.annotateLeaseFailureandasRefRejectedErrornow use a valuepackp.CommandStatusErrinerrors.As, matching go-git’s value-typedReportStatus.Error()output; the previous pointer target never matched, so lease hints and concurrent-move classification were effectively no-ops in production.Tests build inputs via
CommandStatus.Error()(not hand-built pointers), assert unwrap with valueCommandStatusErr, and addTestAsRefRejectedError_RealReportStatusPathto guard against pointer-vs-value regressions. CHANGELOG documents the fix and clarifies that embedders should use a valueerrors.Astarget for the underlying go-git error.Reviewed by Cursor Bugbot for commit 84f71be. Configure here.