From 90030346c64b559a49ced87d5fa796e3e917dc90 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 10 Jun 2026 23:58:03 +0000 Subject: [PATCH] push: use a shared remote.Pusher across tags Replace per-tag remote.Write/WriteIndex with a single remote.NewPusher reused for every tag. The pusher caches per-repo upload state, so identical blobs are checked/uploaded only once even when pushing the same digest to multiple tags (previously each tag re-HEADed every blob). Still uploads layers/index children concurrently via WithJobs. Co-authored-by: Jason Hall --- pymage/internal/cli/cli.go | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/pymage/internal/cli/cli.go b/pymage/internal/cli/cli.go index 94a3b3f..578cf5c 100644 --- a/pymage/internal/cli/cli.go +++ b/pymage/internal/cli/cli.go @@ -337,17 +337,27 @@ func output(cmd *cobra.Command, f *buildFlags, nameOpts []name.Option, img v1.Im if len(tags) == 0 { tags = []string{"latest"} } - opts := []remote.Option{ - remote.WithContext(ctx), + + var artifact remote.Taggable = img + if idx != nil { + artifact = idx + } + + // A single Pusher is shared across all tags: it uploads layers (and, for an + // index, child manifests) concurrently, and reuses its per-repo upload state + // so identical blobs are only checked/uploaded once even across tags. + pusher, err := remote.NewPusher( remote.WithAuthFromKeychain(authn.DefaultKeychain), - // Upload layers (and, for an index, child manifests) concurrently. remote.WithJobs(pushConcurrency(f.pushJobs)), + ) + if err != nil { + return err } // The artifact is pushed by content; each tag is just another pointer to // the same digest. for _, t := range tags { ref := repo.Tag(t) - if err := writeArtifact(ref, img, idx, opts...); err != nil { + if err := pusher.Push(ctx, ref, artifact); err != nil { return fmt.Errorf("push %s: %w", ref, err) } _, _ = fmt.Fprintf(stderr, "tagged %s -> %s@%s\n", ref, repo.Name(), digest) @@ -365,13 +375,6 @@ func artifactDigest(img v1.Image, idx v1.ImageIndex) (v1.Hash, error) { return img.Digest() } -func writeArtifact(ref name.Reference, img v1.Image, idx v1.ImageIndex, opts ...remote.Option) error { - if idx != nil { - return remote.WriteIndex(ref, idx, opts...) - } - return remote.Write(ref, img, opts...) -} - func writeLayout(dir string, img v1.Image, idx v1.ImageIndex) error { p, err := layout.Write(dir, empty.Index) if err != nil {