diff --git a/cmd/oras/internal/display/status/deprecated.go b/cmd/oras/internal/display/status/deprecated.go index f53875295..8fec00c32 100644 --- a/cmd/oras/internal/display/status/deprecated.go +++ b/cmd/oras/internal/display/status/deprecated.go @@ -58,7 +58,8 @@ var printer = NewPrinter(os.Stdout) // Print objects to display concurrent-safely. func Print(a ...any) error { - return printer.Println(a...) + printer.Println(a...) + return printer.errored } // StatusPrinter returns a tracking function for transfer status. diff --git a/cmd/oras/internal/display/status/print.go b/cmd/oras/internal/display/status/print.go index b2094964a..46410c915 100644 --- a/cmd/oras/internal/display/status/print.go +++ b/cmd/oras/internal/display/status/print.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "oras.land/oras/internal/descriptor" + "os" "sync" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -31,8 +32,9 @@ type PrintFunc func(ocispec.Descriptor) error // Printer prints for status handlers. type Printer struct { - out io.Writer - lock sync.Mutex + out io.Writer + lock sync.Mutex + errored error } // NewPrinter creates a new Printer. @@ -41,11 +43,18 @@ func NewPrinter(out io.Writer) *Printer { } // Println prints objects concurrent-safely with newline. -func (p *Printer) Println(a ...any) error { +func (p *Printer) Println(a ...any) { p.lock.Lock() defer p.lock.Unlock() _, err := fmt.Fprintln(p.out, a...) - return err + if err != nil { + if p.errored == nil { + p.errored = fmt.Errorf("display output error: %w", err) + _, _ = fmt.Fprint(os.Stderr, p.errored) + return + } + } + return } // PrintStatus prints transfer status. @@ -58,7 +67,8 @@ func (p *Printer) PrintStatus(desc ocispec.Descriptor, status string, verbose bo } name = desc.MediaType } - return p.Println(status, descriptor.ShortDigest(desc), name) + p.Println(status, descriptor.ShortDigest(desc), name) + return p.errored } // StatusPrinter returns a tracking function for transfer status. diff --git a/cmd/oras/internal/display/status/text.go b/cmd/oras/internal/display/status/text.go index 56aa886b9..cd7924b44 100644 --- a/cmd/oras/internal/display/status/text.go +++ b/cmd/oras/internal/display/status/text.go @@ -44,12 +44,14 @@ func (ph *TextPushHandler) OnFileLoading(name string) error { if !ph.verbose { return nil } - return ph.printer.Println("Preparing", name) + ph.printer.Println("Preparing", name) + return ph.printer.errored } // OnEmptyArtifact is called when an empty artifact is being uploaded. func (ph *TextPushHandler) OnEmptyArtifact() error { - return ph.printer.Println("Uploading empty artifact") + ph.printer.Println("Uploading empty artifact") + return ph.printer.errored } // TrackTarget returns a tracked target.