diff --git a/cmd/oras/internal/display/metadata/interface.go b/cmd/oras/internal/display/metadata/interface.go index 145a65d0a..71c26de5f 100644 --- a/cmd/oras/internal/display/metadata/interface.go +++ b/cmd/oras/internal/display/metadata/interface.go @@ -20,17 +20,17 @@ import ( "oras.land/oras/cmd/oras/internal/option" ) +// Renderer renders metadata information when an operation is complete. +type Renderer interface { + Render() error +} + // PushHandler handles metadata output for push events. type PushHandler interface { TaggedHandler + Renderer - OnCopied(opts *option.Target) error - OnCompleted(root ocispec.Descriptor) error -} - -// Renderer renders metadata information when an operation is complete. -type Renderer interface { - Render() error + OnCopied(opts *option.Target, root ocispec.Descriptor) error } // AttachHandler handles metadata output for attach events. diff --git a/cmd/oras/internal/display/metadata/json/push.go b/cmd/oras/internal/display/metadata/json/push.go index 6c3a03ebe..9433829e6 100644 --- a/cmd/oras/internal/display/metadata/json/push.go +++ b/cmd/oras/internal/display/metadata/json/push.go @@ -31,6 +31,7 @@ type PushHandler struct { path string out io.Writer tagged model.Tagged + root ocispec.Descriptor } // NewPushHandler creates a new handler for push events. @@ -47,15 +48,16 @@ func (ph *PushHandler) OnTagged(desc ocispec.Descriptor, tag string) error { } // OnCopied is called after files are copied. -func (ph *PushHandler) OnCopied(opts *option.Target) error { +func (ph *PushHandler) OnCopied(opts *option.Target, root ocispec.Descriptor) error { if opts.RawReference != "" && !contentutil.IsDigest(opts.Reference) { ph.tagged.AddTag(opts.Reference) } ph.path = opts.Path + ph.root = root return nil } -// OnCompleted is called after the push is completed. -func (ph *PushHandler) OnCompleted(root ocispec.Descriptor) error { - return output.PrintPrettyJSON(ph.out, model.NewPush(root, ph.path, ph.tagged.Tags())) +// Render implements PushHandler. +func (ph *PushHandler) Render() error { + return output.PrintPrettyJSON(ph.out, model.NewPush(ph.root, ph.path, ph.tagged.Tags())) } diff --git a/cmd/oras/internal/display/metadata/template/push.go b/cmd/oras/internal/display/metadata/template/push.go index 22de93876..bc40f0afa 100644 --- a/cmd/oras/internal/display/metadata/template/push.go +++ b/cmd/oras/internal/display/metadata/template/push.go @@ -32,6 +32,7 @@ type PushHandler struct { path string tagged model.Tagged out io.Writer + root ocispec.Descriptor } // NewPushHandler returns a new handler for push events. @@ -49,15 +50,16 @@ func (ph *PushHandler) OnTagged(desc ocispec.Descriptor, tag string) error { } // OnCopied is called after files are copied. -func (ph *PushHandler) OnCopied(opts *option.Target) error { +func (ph *PushHandler) OnCopied(opts *option.Target, root ocispec.Descriptor) error { if opts.RawReference != "" && !contentutil.IsDigest(opts.Reference) { ph.tagged.AddTag(opts.Reference) } ph.path = opts.Path + ph.root = root return nil } -// OnCompleted is called after the push is completed. -func (ph *PushHandler) OnCompleted(root ocispec.Descriptor) error { - return output.ParseAndWrite(ph.out, model.NewPush(root, ph.path, ph.tagged.Tags()), ph.template) +// Render implements PushHandler. +func (ph *PushHandler) Render() error { + return output.ParseAndWrite(ph.out, model.NewPush(ph.root, ph.path, ph.tagged.Tags()), ph.template) } diff --git a/cmd/oras/internal/display/metadata/text/push.go b/cmd/oras/internal/display/metadata/text/push.go index b84b510a3..317345a63 100644 --- a/cmd/oras/internal/display/metadata/text/push.go +++ b/cmd/oras/internal/display/metadata/text/push.go @@ -28,6 +28,7 @@ import ( type PushHandler struct { printer *output.Printer tagLock sync.Mutex + root ocispec.Descriptor } // NewPushHandler returns a new handler for push events. @@ -45,15 +46,16 @@ func (h *PushHandler) OnTagged(_ ocispec.Descriptor, tag string) error { } // OnCopied is called after files are copied. -func (h *PushHandler) OnCopied(opts *option.Target) error { +func (h *PushHandler) OnCopied(opts *option.Target, root ocispec.Descriptor) error { + h.root = root return h.printer.Println("Pushed", opts.AnnotatedReference()) } -// OnCompleted is called after the push is completed. -func (h *PushHandler) OnCompleted(root ocispec.Descriptor) error { - err := h.printer.Println("ArtifactType:", root.ArtifactType) +// Render implements PushHandler. +func (h *PushHandler) Render() error { + err := h.printer.Println("ArtifactType:", h.root.ArtifactType) if err != nil { return err } - return h.printer.Println("Digest:", root.Digest) + return h.printer.Println("Digest:", h.root.Digest) } diff --git a/cmd/oras/internal/display/metadata/text/push_test.go b/cmd/oras/internal/display/metadata/text/push_test.go index 960de4134..8871b8e35 100644 --- a/cmd/oras/internal/display/metadata/text/push_test.go +++ b/cmd/oras/internal/display/metadata/text/push_test.go @@ -68,8 +68,9 @@ func TestPushHandler_OnCompleted(t *testing.T) { printer := output.NewPrinter(tt.out, os.Stderr) p := &PushHandler{ printer: printer, + root: tt.root, } - if err := p.OnCompleted(tt.root); (err != nil) != tt.wantErr { + if err := p.Render(); (err != nil) != tt.wantErr { t.Errorf("PushHandler.OnCompleted() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/cmd/oras/root/push.go b/cmd/oras/root/push.go index bc47c4fd4..1b7396aa2 100644 --- a/cmd/oras/root/push.go +++ b/cmd/oras/root/push.go @@ -218,11 +218,11 @@ func runPush(cmd *cobra.Command, opts *pushOptions) error { } memoryStore := memory.New() union := contentutil.MultiReadOnlyTarget(memoryStore, store) - displayStatus, displayMetadata, err := display.NewPushHandler(opts.Printer, opts.Format, opts.TTY, union) + statusHandler, metadataHandler, err := display.NewPushHandler(opts.Printer, opts.Format, opts.TTY, union) if err != nil { return err } - descs, err := loadFiles(ctx, store, opts.Annotations, opts.FileRefs, displayStatus) + descs, err := loadFiles(ctx, store, opts.Annotations, opts.FileRefs, statusHandler) if err != nil { return err } @@ -243,15 +243,15 @@ func runPush(cmd *cobra.Command, opts *pushOptions) error { if err != nil { return err } - dst, stopTrack, err := displayStatus.TrackTarget(originalDst) + dst, stopTrack, err := statusHandler.TrackTarget(originalDst) if err != nil { return err } copyOptions := oras.DefaultCopyOptions copyOptions.Concurrency = opts.concurrency - copyOptions.CopyGraphOptions.OnCopySkipped = displayStatus.OnCopySkipped - copyOptions.CopyGraphOptions.PreCopy = displayStatus.PreCopy - copyOptions.CopyGraphOptions.PostCopy = displayStatus.PostCopy + copyOptions.CopyGraphOptions.OnCopySkipped = statusHandler.OnCopySkipped + copyOptions.CopyGraphOptions.PreCopy = statusHandler.PreCopy + copyOptions.CopyGraphOptions.PostCopy = statusHandler.PostCopy copyWithScopeHint := func(root ocispec.Descriptor) error { // add both pull and push scope hints for dst repository // to save potential push-scope token requests during copy @@ -270,7 +270,7 @@ func runPush(cmd *cobra.Command, opts *pushOptions) error { if err != nil { return err } - err = displayMetadata.OnCopied(&opts.Target) + err = metadataHandler.OnCopied(&opts.Target, root) if err != nil { return err } @@ -282,13 +282,13 @@ func runPush(cmd *cobra.Command, opts *pushOptions) error { } tagBytesNOpts := oras.DefaultTagBytesNOptions tagBytesNOpts.Concurrency = opts.concurrency - dst := listener.NewTagListener(originalDst, nil, displayMetadata.OnTagged) + dst := listener.NewTagListener(originalDst, nil, metadataHandler.OnTagged) if _, err = oras.TagBytesN(ctx, dst, root.MediaType, contentBytes, opts.extraRefs, tagBytesNOpts); err != nil { return err } } - err = displayMetadata.OnCompleted(root) + err = metadataHandler.Render() if err != nil { return err }