From 374a1e3687b327a785fb1290f41b4902223d81e6 Mon Sep 17 00:00:00 2001 From: Terry Howe Date: Mon, 1 Jul 2024 09:21:03 -0600 Subject: [PATCH] refactor: Create tag handlers (#1437) Signed-off-by: Terry Howe Co-authored-by: Billy Zha --- .../internal/display/metadata/interface.go | 13 +++-- .../internal/display/metadata/json/push.go | 2 +- .../display/metadata/template/push.go | 2 +- .../internal/display/metadata/text/tag.go | 52 +++++++++++++++++++ .../internal/display/status/deprecated.go | 22 +------- cmd/oras/root/tag.go | 7 ++- 6 files changed, 70 insertions(+), 28 deletions(-) create mode 100644 cmd/oras/internal/display/metadata/text/tag.go diff --git a/cmd/oras/internal/display/metadata/interface.go b/cmd/oras/internal/display/metadata/interface.go index a11b42694..f56f09f07 100644 --- a/cmd/oras/internal/display/metadata/interface.go +++ b/cmd/oras/internal/display/metadata/interface.go @@ -22,7 +22,7 @@ import ( // PushHandler handles metadata output for push events. type PushHandler interface { - TagHandler + TaggedHandler OnCopied(opts *option.Target) error OnCompleted(root ocispec.Descriptor) error @@ -60,8 +60,15 @@ type PullHandler interface { OnCompleted(opts *option.Target, desc ocispec.Descriptor) error } -// TagHandler handles status output for tag command. -type TagHandler interface { +// TaggedHandler handles status output for tag command. +type TaggedHandler interface { // OnTagged is called when each tagging operation is done. OnTagged(desc ocispec.Descriptor, tag string) error } + +// TagHandler handles status output for tag command. +type TagHandler interface { + // OnTagging is called when tagging starts. + OnTagging(desc ocispec.Descriptor, tag string) error + TaggedHandler +} diff --git a/cmd/oras/internal/display/metadata/json/push.go b/cmd/oras/internal/display/metadata/json/push.go index 416311a8c..6c3a03ebe 100644 --- a/cmd/oras/internal/display/metadata/json/push.go +++ b/cmd/oras/internal/display/metadata/json/push.go @@ -40,7 +40,7 @@ func NewPushHandler(out io.Writer) metadata.PushHandler { } } -// OnTagged implements metadata.TagHandler. +// OnTagged implements metadata.TaggedHandler. func (ph *PushHandler) OnTagged(desc ocispec.Descriptor, tag string) error { ph.tagged.AddTag(tag) return nil diff --git a/cmd/oras/internal/display/metadata/template/push.go b/cmd/oras/internal/display/metadata/template/push.go index baf4161c5..22de93876 100644 --- a/cmd/oras/internal/display/metadata/template/push.go +++ b/cmd/oras/internal/display/metadata/template/push.go @@ -42,7 +42,7 @@ func NewPushHandler(out io.Writer, template string) metadata.PushHandler { } } -// OnTagged implements metadata.TagHandler. +// OnTagged implements metadata.TaggedHandler. func (ph *PushHandler) OnTagged(desc ocispec.Descriptor, tag string) error { ph.tagged.AddTag(tag) return nil diff --git a/cmd/oras/internal/display/metadata/text/tag.go b/cmd/oras/internal/display/metadata/text/tag.go new file mode 100644 index 000000000..eb1332054 --- /dev/null +++ b/cmd/oras/internal/display/metadata/text/tag.go @@ -0,0 +1,52 @@ +/* +Copyright The ORAS Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package text + +import ( + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "oras.land/oras/cmd/oras/internal/display/metadata" + "oras.land/oras/cmd/oras/internal/output" + "sync" +) + +// TagHandler handles text metadata output for tag events. +type TagHandler struct { + printer *output.Printer + printOnce sync.Once + refPrefix string +} + +// NewTagHandler returns a new handler for tag events. +func NewTagHandler(printer *output.Printer, refPrefix string) metadata.TagHandler { + return &TagHandler{ + printer: printer, + refPrefix: refPrefix, + } +} + +// OnTagging is called when the tagging is complete. +func (ah *TagHandler) OnTagging(desc ocispec.Descriptor, _ string) (err error) { + ah.printOnce.Do(func() { + ref := ah.refPrefix + "@" + desc.Digest.String() + err = ah.printer.Println("Tagging", ref) + }) + return err +} + +// OnTagged is called when the tagging is complete. +func (ah *TagHandler) OnTagged(_ ocispec.Descriptor, tag string) error { + return ah.printer.Println("Tagged", tag) +} diff --git a/cmd/oras/internal/display/status/deprecated.go b/cmd/oras/internal/display/status/deprecated.go index 3ed0f1244..2d85e3198 100644 --- a/cmd/oras/internal/display/status/deprecated.go +++ b/cmd/oras/internal/display/status/deprecated.go @@ -16,35 +16,15 @@ limitations under the License. package status import ( - "oras.land/oras/cmd/oras/internal/output" - "sync" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" "oras.land/oras-go/v2" + "oras.land/oras/cmd/oras/internal/output" "oras.land/oras/internal/listener" ) // Types and functions in this file are deprecated and should be removed when // no-longer referenced. -// NewTagStatusHintPrinter creates a wrapper type for printing -// tag status and hint. -func NewTagStatusHintPrinter(printer *output.Printer, target oras.Target, refPrefix string) oras.Target { - var printHint sync.Once - var printHintErr error - onTagging := func(desc ocispec.Descriptor, tag string) error { - printHint.Do(func() { - ref := refPrefix + "@" + desc.Digest.String() - printHintErr = printer.Println("Tagging", ref) - }) - return printHintErr - } - onTagged := func(desc ocispec.Descriptor, tag string) error { - return printer.Println("Tagged", tag) - } - return listener.NewTagListener(target, onTagging, onTagged) -} - // NewTagStatusPrinter creates a wrapper type for printing tag status. func NewTagStatusPrinter(printer *output.Printer, target oras.Target) oras.Target { return listener.NewTagListener(target, nil, func(desc ocispec.Descriptor, tag string) error { diff --git a/cmd/oras/root/tag.go b/cmd/oras/root/tag.go index 128a7cc4e..031ea0546 100644 --- a/cmd/oras/root/tag.go +++ b/cmd/oras/root/tag.go @@ -18,6 +18,8 @@ package root import ( "errors" "fmt" + "oras.land/oras/cmd/oras/internal/display/metadata/text" + "oras.land/oras/internal/listener" "github.com/spf13/cobra" "oras.land/oras-go/v2" @@ -25,7 +27,6 @@ import ( "oras.land/oras-go/v2/registry/remote" "oras.land/oras/cmd/oras/internal/argument" "oras.land/oras/cmd/oras/internal/command" - "oras.land/oras/cmd/oras/internal/display/status" oerrors "oras.land/oras/cmd/oras/internal/errors" "oras.land/oras/cmd/oras/internal/option" ) @@ -114,9 +115,11 @@ func tagManifest(cmd *cobra.Command, opts *tagOptions) error { tagNOpts := oras.DefaultTagNOptions tagNOpts.Concurrency = opts.concurrency + tagHandler := text.NewTagHandler(opts.Printer, fmt.Sprintf("[%s] %s", opts.Type, opts.Path)) + tagListener := listener.NewTagListener(target, tagHandler.OnTagging, tagHandler.OnTagged) _, err = oras.TagN( ctx, - status.NewTagStatusHintPrinter(opts.Printer, target, fmt.Sprintf("[%s] %s", opts.Type, opts.Path)), + tagListener, opts.Reference, opts.targetRefs, tagNOpts,