@@ -35,18 +35,20 @@ import (
3535type ArtifactDownload struct {
3636 * ActionsOpts
3737 artifactsCASConn * grpc.ClientConn
38+ stdout io.Writer
3839}
3940
4041type ArtifactDownloadOpts struct {
4142 * ActionsOpts
4243 ArtifactsCASConn * grpc.ClientConn
44+ Stdout io.Writer
4345}
4446
4547func NewArtifactDownload (opts * ArtifactDownloadOpts ) * ArtifactDownload {
46- return & ArtifactDownload {opts .ActionsOpts , opts .ArtifactsCASConn }
48+ return & ArtifactDownload {opts .ActionsOpts , opts .ArtifactsCASConn , opts . Stdout }
4749}
4850
49- func (a * ArtifactDownload ) Run (downloadPath , digest string ) error {
51+ func (a * ArtifactDownload ) Run (downloadPath , outputFile , digest string ) error {
5052 h , err := crv1 .NewHash (digest )
5153 if err != nil {
5254 return fmt .Errorf ("invalid digest: %w" , err )
@@ -59,27 +61,41 @@ func (a *ArtifactDownload) Run(downloadPath, digest string) error {
5961 return fmt .Errorf ("artifact with digest %s not found" , h )
6062 }
6163
64+ if downloadPath != "" && outputFile != "" {
65+ return errors .New ("both downloadPath and outputFile cannot be set at the same time" )
66+ }
67+
6268 if downloadPath == "" {
63- var err error
6469 downloadPath , err = os .Getwd ()
6570 if err != nil {
6671 return fmt .Errorf ("getting current dir: %w" , err )
6772 }
6873 }
6974
70- downloadPath = path .Join (downloadPath , info .Filename )
71- f , err := os .Create (downloadPath )
72- if err != nil {
73- return fmt .Errorf ("creating destination file: %w" , err )
75+ // Determine output destination
76+ outputPath := path .Join (downloadPath , info .Filename )
77+ if outputFile != "" && outputFile != "-" {
78+ outputPath = outputFile
79+ }
80+
81+ // Open output file
82+ var f io.Writer
83+ if outputFile == "-" {
84+ f = a .stdout
85+ } else {
86+ f , err = os .Create (outputPath )
87+ if err != nil {
88+ return fmt .Errorf ("creating destination file: %w" , err )
89+ }
90+ defer f .(* os.File ).Close ()
91+
92+ a .Logger .Info ().Str ("name" , outputFile ).Str ("to" , outputPath ).Msg ("downloading file" )
7493 }
75- defer f .Close ()
7694
7795 // Calculate the checksum as we write it to a file
7896 hash := sha256 .New ()
7997 w := io .MultiWriter (f , hash )
8098
81- a .Logger .Info ().Str ("name" , info .Filename ).Str ("to" , downloadPath ).Msg ("downloading file" )
82-
8399 // render progress bar
84100 go renderOperationStatus (ctx , client .ProgressStatus , info .Size )
85101 defer close (client .ProgressStatus )
@@ -108,6 +124,8 @@ func renderOperationStatus(ctx context.Context, progressChan casclient.ProgressS
108124 pw .Style ().Visibility .ETA = true
109125 pw .Style ().Visibility .Speed = true
110126 pw .SetUpdateFrequency (progress .DefaultUpdateFrequency )
127+ // Render to stderr to avoid interfering with the output if the flag --output is set to "-"
128+ pw .SetOutputWriter (os .Stderr )
111129
112130 var tracker * progress.Tracker
113131 go pw .Render ()
0 commit comments