diff --git a/cmd/oras/internal/display/print.go b/cmd/oras/internal/display/print.go index a0c334a6f..49983531a 100644 --- a/cmd/oras/internal/display/print.go +++ b/cmd/oras/internal/display/print.go @@ -28,24 +28,33 @@ import ( "oras.land/oras-go/v2/registry" ) -var printLock sync.Mutex +var ( + printLock sync.Mutex + to io.Writer +) -// PrintFunc is the function type returned by StatusPrinter. -type PrintFunc func(ocispec.Descriptor) error +func init() { + to = os.Stdout +} -// PrintErr prints into stderr. -func PrintErr(a ...any) error { - printLock.Lock() - defer printLock.Unlock() - _, err := fmt.Fprintln(os.Stderr, a...) - return err +// Set sets the output writer for printing. +func Set(template string, tty io.Writer) { + if template != "" { + to = tty + } } +// PrintFunc is the function type returned by StatusPrinter. +type PrintFunc func(ocispec.Descriptor) error + // Print objects to display concurrent-safely. func Print(a ...any) error { + if to == nil { + return nil + } printLock.Lock() defer printLock.Unlock() - _, err := fmt.Println(a...) + _, err := fmt.Fprintln(to, a...) return err } diff --git a/cmd/oras/internal/option/format.go b/cmd/oras/internal/option/format.go index e44f68fae..6c021f636 100644 --- a/cmd/oras/internal/option/format.go +++ b/cmd/oras/internal/option/format.go @@ -25,16 +25,18 @@ import ( ) type Format struct { - template string + Template string } // ApplyFlag implements FlagProvider.ApplyFlag func (opts *Format) ApplyFlags(fs *pflag.FlagSet) { - fs.StringVar(&opts.template, "format", "", `Format output with go template syntax`) + fs.StringVar(&opts.Template, "format", "", `Format output with go template syntax`) } func (opts *Format) WriteTo(w io.Writer, data interface{}) error { - switch opts.template { + switch opts.Template { + case "": + return nil case "json": // output json // write marshalled data @@ -50,7 +52,7 @@ func (opts *Format) WriteTo(w io.Writer, data interface{}) error { // go templating var err error t := template.New("out").Funcs(sprig.FuncMap()) - t, err = t.Parse(opts.template) + t, err = t.Parse(opts.Template) if err != nil { return err } diff --git a/cmd/oras/root/attach.go b/cmd/oras/root/attach.go index abd1d665c..1fbe92548 100644 --- a/cmd/oras/root/attach.go +++ b/cmd/oras/root/attach.go @@ -87,6 +87,7 @@ Example - Attach file to the manifest tagged 'v1' in an OCI image layout folder return nil }, RunE: func(cmd *cobra.Command, args []string) error { + display.Set(opts.Template, opts.TTY) return runAttach(cmd.Context(), opts) }, } @@ -181,8 +182,8 @@ func runAttach(ctx context.Context, opts attachOptions) error { if !strings.HasSuffix(opts.RawReference, digest) { opts.RawReference = fmt.Sprintf("%s@%s", opts.Path, subject.Digest) } - display.PrintErr("Attached to", opts.AnnotatedReference()) - display.PrintErr("Digest:", root.Digest) + display.Print("Attached to", opts.AnnotatedReference()) + display.Print("Digest:", root.Digest) // Export manifest if err = opts.ExportManifest(ctx, store, root); err != nil { diff --git a/cmd/oras/root/file.go b/cmd/oras/root/file.go index e7fddfbd1..f964b9a10 100644 --- a/cmd/oras/root/file.go +++ b/cmd/oras/root/file.go @@ -59,7 +59,7 @@ func loadFiles(ctx context.Context, store *file.Store, annotations map[string]ma files = append(files, file) } if len(files) == 0 { - display.PrintErr("Uploading empty artifact") + display.Print("Uploading empty artifact") } return files, nil } diff --git a/cmd/oras/root/push.go b/cmd/oras/root/push.go index 6203ffc43..f0e6ecf7a 100644 --- a/cmd/oras/root/push.go +++ b/cmd/oras/root/push.go @@ -124,6 +124,7 @@ Example - Push file "hi.txt" into an OCI image layout folder 'layout-dir' with t return nil }, RunE: func(cmd *cobra.Command, args []string) error { + display.Set(opts.Template, opts.TTY) return runPush(cmd.Context(), opts) }, } @@ -213,7 +214,7 @@ func runPush(ctx context.Context, opts pushOptions) error { if err != nil { return err } - display.PrintErr("Pushed", opts.AnnotatedReference()) + display.Print("Pushed", opts.AnnotatedReference()) if len(opts.extraRefs) != 0 { contentBytes, err := content.FetchAll(ctx, memoryStore, root) @@ -227,7 +228,7 @@ func runPush(ctx context.Context, opts pushOptions) error { } } - display.PrintErr("Digest:", root.Digest) + display.Print("Digest:", root.Digest) // Export manifest if err := opts.ExportManifest(ctx, memoryStore, root); err != nil {