Skip to content

Commit

Permalink
feat: support tagging multiple tags at once for oras push (#616)
Browse files Browse the repository at this point in the history
Signed-off-by: Jun <[email protected]>
  • Loading branch information
wju-MSFT authored Sep 23, 2022
1 parent 265b21e commit 5bef476
Showing 1 changed file with 27 additions and 2 deletions.
29 changes: 27 additions & 2 deletions cmd/oras/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ import (
"context"
"errors"
"fmt"
"strings"
"sync"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
"oras.land/oras-go/v2"
"oras.land/oras-go/v2/content"
"oras.land/oras-go/v2/content/file"
"oras.land/oras/cmd/oras/internal/display"
"oras.land/oras/cmd/oras/internal/option"
Expand All @@ -39,14 +41,16 @@ type pushOptions struct {
option.Packer

targetRef string
extraRefs []string
manifestConfigRef string
artifactType string
concurrency int64
}

func pushCmd() *cobra.Command {
var opts pushOptions
cmd := &cobra.Command{
Use: "push [flags] <name>[:<tag>|@<digest>] <file>[:<type>] [...]",
Use: "push [flags] <name>[:<tag>[,<tag>][...]] <file>[:<type>] [...]",
Short: "Push files to remote registry",
Long: `Push files to remote registry
Expand Down Expand Up @@ -76,6 +80,12 @@ Example - Push repository with manifest annotations
Example - Push repository with manifest annotation file
oras push --annotation-file annotation.json localhost:5000/hello:latest
Example - Push file "hi.txt" with multiple tags:
oras push localhost:5000/hello:tag1,tag2,tag3 hi.txt
Example - Push file "hi.txt" with multiple tags and concurrency level tuned:
oras push --concurrency 6 localhost:5000/hello:tag1,tag2,tag3 hi.txt
`,
Args: cobra.MinimumNArgs(1),
PreRunE: func(cmd *cobra.Command, args []string) error {
Expand All @@ -85,14 +95,17 @@ Example - Push repository with manifest annotation file
return opts.ReadPassword()
},
RunE: func(cmd *cobra.Command, args []string) error {
opts.targetRef = args[0]
refs := strings.Split(args[0], ",")
opts.targetRef = refs[0]
opts.extraRefs = refs[1:]
opts.FileRefs = args[1:]
return runPush(opts)
},
}

cmd.Flags().StringVarP(&opts.manifestConfigRef, "config", "", "", "manifest config file")
cmd.Flags().StringVarP(&opts.artifactType, "artifact-type", "", "", "media type of the manifest config")
cmd.Flags().Int64VarP(&opts.concurrency, "concurrency", "", 5, "concurrency level")

option.ApplyFlags(&opts, cmd.Flags())
return cmd
Expand All @@ -113,6 +126,7 @@ func runPush(opts pushOptions) error {
// Ready to push
committed := &sync.Map{}
copyOptions := oras.DefaultCopyOptions
copyOptions.Concurrency = opts.concurrency
copyOptions.PreCopy = display.StatusPrinter("Uploading", opts.Verbose)
copyOptions.OnCopySkipped = func(ctx context.Context, desc ocispec.Descriptor) error {
committed.Store(desc.Digest.String(), desc.Annotations[ocispec.AnnotationTitle])
Expand Down Expand Up @@ -145,6 +159,17 @@ func runPush(opts pushOptions) error {
}

fmt.Println("Pushed", opts.targetRef)

if len(opts.extraRefs) != 0 {
contentBytes, err := content.FetchAll(ctx, store, desc)
if err != nil {
return err
}
tagBytesNOpts := oras.DefaultTagBytesNOptions
tagBytesNOpts.Concurrency = opts.concurrency
oras.TagBytesN(ctx, &display.TagManifestStatusPrinter{Repository: dst}, desc.MediaType, contentBytes, opts.extraRefs, tagBytesNOpts)
}

fmt.Println("Digest:", desc.Digest)

// Export manifest
Expand Down

0 comments on commit 5bef476

Please sign in to comment.