Push git-refs checkpoints from pre-push via the discovery queue · Entire

Push git-refs checkpoints from pre-push via the discovery queue

7fa01ba→main·

Soph·2w ago·3 files·+231 added/-6 removed

When the configured primary is git-refs, PrePush drains the push-discovery queue and batch force-pushes those per-checkpoint refs (one git push, +ref:ref force refspecs — independent histories, no fetch+rebase recovery) instead of pushing the v1 branch. Default config (git-branch) is unchanged.

- partitionLocalRefs drops stale queue entries (refs deleted locally); surviving refs are removed from the queue only on a confirmed push, so a failed/transient push leaves them for the next pre-push and never blocks the user's git push. - Shared post-push shadow cleanup extracted to cleanupPushedShadowBranches.

A configured git-branch mirror's v1 ref is not pushed here yet (downgrade-safety mirror push is later), and OPF stays descoped for git-refs.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Sessions

7ca5586da108View transcript

Changes

3

42 unmodified lines

... (additional unmodified lines omitted for brevity)

// prePushCheckpointRefs drains the per-checkpoint push queue and batch force-pushes
// the recorded refs (git-refs primary). Transient push failures are logged and
// swallowed — like the v1 path, they must not block the user's git push — and the
// refs stay queued for the next pre-push. OPF is not applied (it is descoped for
// the git-refs store for now).
func (s *ManualCommitStrategy) prePushCheckpointRefs(ctx context.Context, ps pushSettings) error {
    repo, err := OpenRepository(ctx)
    if err != nil {
        logging.Warn(ctx, "git-refs pre-push: open repo failed; skipping checkpoint push",
            slog.String("error", err.Error()))
        return nil
    }
    defer repo.Close()

queue, err := checkpoint.PushQueueForRepo(ctx, repo)
    if err != nil {
        logging.Warn(ctx, "git-refs pre-push: resolve push queue failed; skipping checkpoint push",
            slog.String("error", err.Error()))
        return nil
    }
    queued, err := queue.Drain()
    if err != nil {
        logging.Warn(ctx, "git-refs pre-push: drain push queue failed; skipping checkpoint push",
            slog.String("error", err.Error()))
        return nil
    }
    if len(queued) == 0 {
        return nil
    }

// Drop stale entries (refs no longer present locally) so they don't block
    // the queue forever, then push what remains.
    existing, stale := partitionLocalRefs(repo, queued)
    if len(stale) > 0 {
        if err := queue.Remove(stale); err != nil {
            logging.Warn(ctx, "git-refs pre-push: prune stale queue entries failed",
                slog.String("error", err.Error()))
        }
    }
    if len(existing) == 0 {
        return nil
    }

pushCtx, pushSpan := perf.Start(ctx, "push_checkpoint_refs")
    pushErr := batchForcePushRefs(pushCtx, ps.pushTarget(), existing)
    pushSpan.End()
    if pushErr != nil {
        // Leave the refs queued; the next pre-push retries. Non-fatal so the
        // user's push proceeds.
        logging.Warn(ctx, "git-refs pre-push: batch push failed; refs left queued for retry",
            slog.String("error", pushErr.Error()))
        return nil
    }
    if err := queue.Remove(existing); err != nil {
        logging.Warn(ctx, "git-refs pre-push: clear pushed refs from queue failed",
            slog.String("error", err.Error()))
    }

cleanupPushedShadowBranches(ctx)
    return nil
}

// partitionLocalRefs splits refs into those that exist locally (pushable) and
// those that don't (stale queue entries).
func partitionLocalRefs(repo *git.Repository, refs []plumbing.ReferenceName) (existing, stale []plumbing.ReferenceName) {
    for _, ref := range refs {
        if _, err := repo.Reference(ref, false); err != nil {
            stale = append(stale, ref)
            continue
        }
        existing = append(existing, ref)
    }
    return existing, stale
}

// batchForcePushRefs pushes all of refs to target in a single git push. Each
// uses a force refspec (+ref:ref), matching how non-branch checkpoint refs are
// already pushed: per-checkpoint refs have independent histories with no
// remote-tracking shadow.
func batchForcePushRefs(ctx context.Context, target string, refs []plumbing.ReferenceName) error {
    if len(refs) == 0 {
        return nil
    }
    refSpecs := make([]string, 0, len(refs))
    for _, ref := range refs {
        refSpecs = append(refSpecs, "+"+ref.String()+":"+ref.String())
    }
    if _, err := remote.PushWithOptions(ctx, remote.PushOptions{Remote: target, RefSpecs: refSpecs}); err != nil {
        return fmt.Errorf("batch push %d checkpoint refs: %w", len(refs), err)
    }
    return nil
}

// pushRefIfNeeded pushes a ref to the given target if it has unpushed changes.
// The target can be a remote name or a URL for direct push.