Skip to content

Commit

Permalink
refactor: add stdout to metadata handlers (#1312)
Browse files Browse the repository at this point in the history
Signed-off-by: Billy Zha <[email protected]>
  • Loading branch information
qweeah authored Mar 28, 2024
1 parent 776f8df commit 24c2acf
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 43 deletions.
17 changes: 9 additions & 8 deletions cmd/oras/internal/display/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ limitations under the License.
package display

import (
"io"
"os"

"oras.land/oras/cmd/oras/internal/display/metadata"
Expand All @@ -26,7 +27,7 @@ import (
)

// NewPushHandler returns status and metadata handlers for push command.
func NewPushHandler(format string, tty *os.File, verbose bool) (status.PushHandler, metadata.PushHandler) {
func NewPushHandler(format string, tty *os.File, out io.Writer, verbose bool) (status.PushHandler, metadata.PushHandler) {
var statusHandler status.PushHandler
if tty != nil {
statusHandler = status.NewTTYPushHandler(tty)
Expand All @@ -39,18 +40,18 @@ func NewPushHandler(format string, tty *os.File, verbose bool) (status.PushHandl
var metadataHandler metadata.PushHandler
switch format {
case "":
metadataHandler = text.NewPushHandler()
metadataHandler = text.NewPushHandler(out)
case "json":
metadataHandler = json.NewPushHandler()
metadataHandler = json.NewPushHandler(out)
default:
metadataHandler = template.NewPushHandler(format)
metadataHandler = template.NewPushHandler(out, format)
}

return statusHandler, metadataHandler
}

// NewAttachHandler returns status and metadata handlers for attach command.
func NewAttachHandler(format string, tty *os.File, verbose bool) (status.AttachHandler, metadata.AttachHandler) {
func NewAttachHandler(format string, tty *os.File, out io.Writer, verbose bool) (status.AttachHandler, metadata.AttachHandler) {
var statusHandler status.AttachHandler
if tty != nil {
statusHandler = status.NewTTYAttachHandler(tty)
Expand All @@ -63,11 +64,11 @@ func NewAttachHandler(format string, tty *os.File, verbose bool) (status.AttachH
var metadataHandler metadata.AttachHandler
switch format {
case "":
metadataHandler = text.NewAttachHandler()
metadataHandler = text.NewAttachHandler(out)
case "json":
metadataHandler = json.NewAttachHandler()
metadataHandler = json.NewAttachHandler(out)
default:
metadataHandler = template.NewAttachHandler(format)
metadataHandler = template.NewAttachHandler(out, format)
}

return statusHandler, metadataHandler
Expand Down
16 changes: 11 additions & 5 deletions cmd/oras/internal/display/metadata/json/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,27 @@ limitations under the License.
package json

import (
"io"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras/cmd/oras/internal/display/metadata"
"oras.land/oras/cmd/oras/internal/display/metadata/model"
"oras.land/oras/cmd/oras/internal/option"
)

// AttachHandler handles json metadata output for attach events.
type AttachHandler struct{}
type AttachHandler struct {
out io.Writer
}

// NewAttachHandler creates a new handler for attach events.
func NewAttachHandler() metadata.AttachHandler {
return AttachHandler{}
func NewAttachHandler(out io.Writer) metadata.AttachHandler {
return &AttachHandler{
out: out,
}
}

// OnCompleted is called when the attach command is completed.
func (AttachHandler) OnCompleted(opts *option.Target, root, subject ocispec.Descriptor) error {
return printJSON(model.NewPush(root, opts.Path))
func (ah *AttachHandler) OnCompleted(opts *option.Target, root, subject ocispec.Descriptor) error {
return printJSON(ah.out, model.NewPush(root, opts.Path))
}
6 changes: 3 additions & 3 deletions cmd/oras/internal/display/metadata/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ package json

import (
"encoding/json"
"os"
"io"
)

func printJSON(object any) error {
encoder := json.NewEncoder(os.Stdout)
func printJSON(out io.Writer, object any) error {
encoder := json.NewEncoder(out)
encoder.SetIndent("", " ")
return encoder.Encode(object)
}
11 changes: 8 additions & 3 deletions cmd/oras/internal/display/metadata/json/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ limitations under the License.
package json

import (
"io"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras/cmd/oras/internal/display/metadata"
"oras.land/oras/cmd/oras/internal/display/metadata/model"
Expand All @@ -25,11 +27,14 @@ import (
// PushHandler handles JSON metadata output for push events.
type PushHandler struct {
path string
out io.Writer
}

// NewPushHandler creates a new handler for push events.
func NewPushHandler() metadata.PushHandler {
return &PushHandler{}
func NewPushHandler(out io.Writer) metadata.PushHandler {
return &PushHandler{
out: out,
}
}

// OnCopied is called after files are copied.
Expand All @@ -40,5 +45,5 @@ func (ph *PushHandler) OnCopied(opts *option.Target) error {

// OnCompleted is called after the push is completed.
func (ph *PushHandler) OnCompleted(root ocispec.Descriptor) error {
return printJSON(model.NewPush(root, ph.path))
return printJSON(ph.out, model.NewPush(root, ph.path))
}
12 changes: 9 additions & 3 deletions cmd/oras/internal/display/metadata/template/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ limitations under the License.
package template

import (
"io"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras/cmd/oras/internal/display/metadata"
"oras.land/oras/cmd/oras/internal/display/metadata/model"
Expand All @@ -25,14 +27,18 @@ import (
// AttachHandler handles go-template metadata output for attach events.
type AttachHandler struct {
template string
out io.Writer
}

// NewAttachHandler returns a new handler for attach metadata events.
func NewAttachHandler(template string) metadata.AttachHandler {
return &AttachHandler{template: template}
func NewAttachHandler(out io.Writer, template string) metadata.AttachHandler {
return &AttachHandler{
out: out,
template: template,
}
}

// OnCompleted formats the metadata of attach command.
func (ah *AttachHandler) OnCompleted(opts *option.Target, root, subject ocispec.Descriptor) error {
return parseAndWrite(model.NewPush(root, opts.Path), ah.template)
return parseAndWrite(ah.out, model.NewPush(root, opts.Path), ah.template)
}
12 changes: 9 additions & 3 deletions cmd/oras/internal/display/metadata/template/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ limitations under the License.
package template

import (
"io"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras/cmd/oras/internal/display/metadata"
"oras.land/oras/cmd/oras/internal/display/metadata/model"
Expand All @@ -26,11 +28,15 @@ import (
type PushHandler struct {
template string
path string
out io.Writer
}

// NewPushHandler returns a new handler for push events.
func NewPushHandler(template string) metadata.PushHandler {
return &PushHandler{template: template}
func NewPushHandler(out io.Writer, template string) metadata.PushHandler {
return &PushHandler{
out: out,
template: template,
}
}

// OnStarted is called after files are copied.
Expand All @@ -41,5 +47,5 @@ func (ph *PushHandler) OnCopied(opts *option.Target) error {

// OnCompleted is called after the push is completed.
func (ph *PushHandler) OnCompleted(root ocispec.Descriptor) error {
return parseAndWrite(model.NewPush(root, ph.path), ph.template)
return parseAndWrite(ph.out, model.NewPush(root, ph.path), ph.template)
}
6 changes: 3 additions & 3 deletions cmd/oras/internal/display/metadata/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ limitations under the License.
package template

import (
"os"
"io"
"text/template"

"github.com/Masterminds/sprig/v3"
)

func parseAndWrite(object any, templateStr string) error {
func parseAndWrite(out io.Writer, object any, templateStr string) error {
t, err := template.New("format output").Funcs(sprig.FuncMap()).Parse(templateStr)
if err != nil {
return err
}
return t.Execute(os.Stdout, object)
return t.Execute(out, object)
}
17 changes: 11 additions & 6 deletions cmd/oras/internal/display/metadata/text/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package text

import (
"fmt"
"io"
"strings"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
Expand All @@ -25,23 +26,27 @@ import (
)

// AttachHandler handles text metadata output for attach events.
type AttachHandler struct{}
type AttachHandler struct {
out io.Writer
}

// NewAttachHandler returns a new handler for attach events.
func NewAttachHandler() metadata.AttachHandler {
return AttachHandler{}
func NewAttachHandler(out io.Writer) metadata.AttachHandler {
return &AttachHandler{
out: out,
}
}

// OnCompleted is called when the attach command is completed.
func (AttachHandler) OnCompleted(opts *option.Target, root, subject ocispec.Descriptor) error {
func (ah *AttachHandler) OnCompleted(opts *option.Target, root, subject ocispec.Descriptor) error {
digest := subject.Digest.String()
if !strings.HasSuffix(opts.RawReference, digest) {
opts.RawReference = fmt.Sprintf("%s@%s", opts.Path, subject.Digest)
}
_, err := fmt.Println("Attached to", opts.AnnotatedReference())
_, err := fmt.Fprintln(ah.out, "Attached to", opts.AnnotatedReference())
if err != nil {
return err
}
_, err = fmt.Println("Digest:", root.Digest)
_, err = fmt.Fprintln(ah.out, "Digest:", root.Digest)
return err
}
19 changes: 12 additions & 7 deletions cmd/oras/internal/display/metadata/text/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,33 @@ package text

import (
"fmt"
"io"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras/cmd/oras/internal/display/metadata"
"oras.land/oras/cmd/oras/internal/option"
)

// PushHandler handles text metadata output for push events.
type PushHandler struct{}
type PushHandler struct {
out io.Writer
}

// NewPushHandler returns a new handler for push events.
func NewPushHandler() metadata.PushHandler {
return PushHandler{}
func NewPushHandler(out io.Writer) metadata.PushHandler {
return &PushHandler{
out: out,
}
}

// OnCopied is called after files are copied.
func (PushHandler) OnCopied(opts *option.Target) error {
_, err := fmt.Println("Pushed", opts.AnnotatedReference())
func (p *PushHandler) OnCopied(opts *option.Target) error {
_, err := fmt.Fprintln(p.out, "Pushed", opts.AnnotatedReference())
return err
}

// OnCompleted is called after the push is completed.
func (PushHandler) OnCompleted(root ocispec.Descriptor) error {
_, err := fmt.Println("Digest:", root.Digest)
func (p *PushHandler) OnCompleted(root ocispec.Descriptor) error {
_, err := fmt.Fprintln(p.out, "Digest:", root.Digest)
return err
}
2 changes: 1 addition & 1 deletion cmd/oras/root/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func runAttach(cmd *cobra.Command, opts *attachOptions) error {
Recommendation: `To attach to an existing artifact, please provide files via argument or annotations via flag "--annotation". Run "oras attach -h" for more options and examples`,
}
}
displayStatus, displayMetadata := display.NewAttachHandler(opts.Template, opts.TTY, opts.Verbose)
displayStatus, displayMetadata := display.NewAttachHandler(opts.Template, opts.TTY, cmd.OutOrStdout(), opts.Verbose)

// prepare manifest
store, err := file.New("")
Expand Down
2 changes: 1 addition & 1 deletion cmd/oras/root/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func runPush(cmd *cobra.Command, opts *pushOptions) error {
if err != nil {
return err
}
displayStatus, displayMetadata := display.NewPushHandler(opts.Template, opts.TTY, opts.Verbose)
displayStatus, displayMetadata := display.NewPushHandler(opts.Template, opts.TTY, cmd.OutOrStdout(), opts.Verbose)

// prepare pack
packOpts := oras.PackManifestOptions{
Expand Down

0 comments on commit 24c2acf

Please sign in to comment.