git-refs: don't mask real errors as not-found; honor checkpoint policy on pre-push · Entire
git-refs: don't mask real errors as not-found; honor checkpoint policy on pre-push
e99a03a·
Soph·2w ago·4 files·+80 added/-20 removed
Addresses the open review threads on the git-refs store.
Error handling (was: any ref-resolution error treated as "missing"):
- refBase: only a plumbing.ErrReferenceNotFound starts a new orphan checkpoint; a real lookup error (IO/corruption) is surfaced instead of silently overwriting the ref's history.
- resolveRefMaybeFetch: a failed on-demand fetch (offline, network, ctx cancellation) now returns the real error; only a genuinely absent ref (or a successful fetch that finds nothing) resolves to not-found.
- checkpointTree / Read: distinguish ErrCheckpointNotFound (→ nil summary) from real commit/tree/fetch errors, which now propagate instead of reading as "checkpoint doesn't exist" (which risked silent data loss).
- partitionLocalRefs: a transient/IO error looking up a ref keeps it as pushable (retried next pre-push) instead of dropping it from the queue as stale.
Pre-push policy (was: git-refs skipped the check the v1 path runs):
- prePushCheckpointRefs now calls syncCheckpointPolicyForPrePush first; a diverged or unsupported-format checkpoint policy skips the ref push (leaving refs queued), matching the v1 branch path. Policy governs checkpoint format compatibility, which is independent of the storage backend.
Updates the fetch-failure test to assert the corrected contract (error propagates; genuine absence still reads as not-found).
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
7c18df0a2b25View transcript
Changes
4
cmd/entire/cli
checkpoint
Mrefs_store.go+35/-10
Mrefs_store_test.go+26/-7
strategy
Mmanual_commit_push.go+9
Mpush_common.go+10/-3
78 unmodified lines
func (s *gitRefsStore) resolveRefMaybeFetch(ctx context.Context, cid id.CheckpointID) (*plumbing.Reference, error) {
refName, err := RefName(cid)
if err != nil {
if err != nil { return plumbing.ZeroHash, nil, fmt.Errorf("resolve checkpoint ref %s: %w", refName, err) } commit, err := s.repo.CommitObject(ref.Hash()) if err != nil {
}
if s.refFetcher == nil { return nil, err //nolint:wrapcheck // caller maps any error to ErrCheckpointNotFound
// sessionTree resolves the FetchingTree for one session within a checkpoint ref.
func (s *gitRefsStore) Read(ctx context.Context, checkpointID id.CheckpointID) (*CheckpointSummary, error) {
ct, err := s.checkpointTree(ctx, checkpointID)
if err != nil {
return nil, nil //nolint:nilnil,nilerr // No ref means no checkpoint exists
if errors.Is(err, ErrCheckpointNotFound) {
return nil, nil //nolint:nilnil // absent ref → no checkpoint; contract normalizes to ErrCheckpointNotFound
return nil, err
}
return readSummaryFromCheckpointTree(ct)
}
Mcmd/entire/cli/checkpoint/refs_store.go+35/-10
func TestGitRefsStore_OnDemandRefFetch_FailureIsNotFound(t *testing.T) { // TestGitRefsStore_OnDemandRefFetch_FailurePropagates: a fetch that fails // (offline, network error, context cancellation) must surface as a real error // rather than be masked as "checkpoint not found" — otherwise a transient // failure looks like missing data. A fetch that succeeds but still finds no such // ref on the remote is a genuine not-found and reads as (nil, nil).
// TestGitRefsStore_WriteAllVariantsAndRead(t *testing.T) {
Mcmd/entire/cli/checkpoint/refs_store_test.go+26/-7
rating