Add git-refs per-checkpoint checkpoint backend · Entire

Add git-refs per-checkpoint checkpoint backend

040eac5·

Soph·2w ago·11 files·+1,143 added/-14 removed

Second slice of #1471: a git-backed store that keeps one commit per refs/entire/checkpoints// (tree root = checkpoint contents), sharing the treeWriter subtree core with the git-branch store.

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

Sessions

a4baf5553823View transcript

Changes

11

12 unmodified lines

// CheckpointVersionBranchV1 identifies the branch-backed checkpoint metadata format. const CheckpointVersionBranchV1 = "branch-v1"

// CheckpointVersionRefsV1 identifies the per-checkpoint-ref checkpoint metadata // format (one ref per checkpoint at refs/entire/checkpoints//). The // value follows the -v convention (cf. branch-v1) so // checkpointpolicy.ParseFormat parses it. const CheckpointVersionRefsV1 = "refs-v1"

Mapi/checkpoint/errors.go+6

// CheckpointVersionBranchV1 identifies the branch-backed checkpoint metadata format. const CheckpointVersionBranchV1 = apicheckpoint.CheckpointVersionBranchV1

// CheckpointVersionRefsV1 identifies the per-checkpoint-ref checkpoint metadata format. const CheckpointVersionRefsV1 = apicheckpoint.CheckpointVersionRefsV1

// Sentinel errors (re-exported so errors.Is keeps working across packages). var ( ErrCheckpointNotFound = apicheckpoint.ErrCheckpointNotFound )

Mcmd/entire/cli/checkpoint/persistent.go+27/-11

package checkpoint

import ( "context" )

// Push-discovery queue file names, kept in the git common dir so every worktree // sharing the object store enqueues into one queue. The git-refs backend cannot // push every local checkpoint ref at pre-push time (reads fetch refs too, and // deleting them after push would hurt local workflows), so each write records // the ref it touched here and pre-push drains + batch-pushes exactly those. const ( pushQueueFileName = "entire-checkpoint-push-queue.jsonl" pushQueueLockName = "entire-checkpoint-push-queue.lock" )

// pushQueueEntry is one JSONL record: a checkpoint ref awaiting push. type pushQueueEntry struct { Ref string json:"ref" }

// PushQueue is a flock-protected JSONL list of checkpoint refs awaiting push, // stored in the git common dir. Entries are removed only after a confirmed push // (Remove), so an interrupted or failed push leaves them for the next pre-push. // Duplicates are tolerated on disk and collapsed by Drain. type PushQueue struct { dir string }

// NewPushQueue returns the push queue rooted at gitCommonDir. func NewPushQueue(gitCommonDir string) *PushQueue { return &PushQueue{dir: gitCommonDir} }

func (q *PushQueue) queuePath() string { return filepath.Join(q.dir, pushQueueFileName) } func (q *PushQueue) lockPath() string { return filepath.Join(q.dir, pushQueueLockName) }

// Enqueue appends a ref to the queue. It is safe to enqueue a ref already // present (or already pushed): Drain collapses duplicates and the batch push is // idempotent. Enqueue takes the lock so concurrent writers never interleave a // partial line. func (q *PushQueue) Enqueue(ref plumbing.ReferenceName) error { // Implementation }

// Drain returns the de-duplicated refs currently queued, in first-seen order. It // does NOT remove them; call Remove after a confirmed push so a failed push // retries next time. A missing queue file yields no refs. func (q *PushQueue) Drain() ([]plumbing.ReferenceName, error) { // Implementation }

// Remove deletes the given refs from the queue, preserving any entries appended // after a Drain (e.g. a write that landed during the push). Called after a // confirmed push. func (q *PushQueue) Remove(refs []plumbing.ReferenceName) error { // Implementation }

// readLocked parses the queue file into de-duplicated refs, preserving first-seen // order. The caller must hold the lock. func (q *PushQueue) readLocked() ([]plumbing.ReferenceName, error) { // Implementation }

// writeFileAtomicInDir writes data to a temp file in dir and renames it over // path, so a reader (under the lock) never sees a half-written queue. func writeFileAtomicInDir(dir, path string, data []byte) error { // Implementation }