@@ -26,6 +26,36 @@ type Manifest struct {
2626// DownloadConfirmCB is a function that is called when a Debian image is ready to be downloaded.
2727type DownloadConfirmCB func (target string ) (bool , error )
2828
29+ // PassThru wraps an existing io.Reader.
30+ //
31+ // It simply forwards the Read() call, while displaying
32+ // the results from individual calls to it.
33+ type PassThru struct {
34+ io.Reader
35+ total float64 // Total # of bytes transferred
36+ length int64 // Expected length
37+ progress float64
38+ progressCB func (f float64 )
39+ }
40+
41+ // Read 'overrides' the underlying io.Reader's Read method.
42+ // This is the one that will be called by io.Copy(). We simply
43+ // use it to keep track of the progress and then forward the call.
44+ func (pt * PassThru ) Read (p []byte ) (int , error ) {
45+ n , err := pt .Reader .Read (p )
46+ if err != nil {
47+ return 0 , err
48+ }
49+ pt .total += float64 (n )
50+ percentage := pt .total / float64 (pt .length ) * float64 (100 )
51+ if percentage - pt .progress > 1 {
52+ pt .progressCB (percentage )
53+ pt .progress = percentage
54+ }
55+
56+ return n , nil
57+ }
58+
2959func DownloadImage (client * Client , targetVersion string , upgradeConfirmCb DownloadConfirmCB , forceYes bool ) (string , string , error ) {
3060 var err error
3161
@@ -52,9 +82,10 @@ func DownloadImage(client *Client, targetVersion string, upgradeConfirmCb Downlo
5282
5383 // Download the Debian image
5484 var download io.ReadCloser
85+ var size int64
5586 if targetVersion == manifest .Latest .Version {
5687 slog .Info ("Downloading Debian image" , "version" , manifest .Latest .Version )
57- download , err = client .FetchZip (manifest .Latest .Url )
88+ download , size , err = client .FetchZip (manifest .Latest .Url )
5889 if err != nil {
5990 return "" , "" , fmt .Errorf ("could not fetch Debian image: %w" , err )
6091 }
@@ -82,8 +113,10 @@ func DownloadImage(client *Client, targetVersion string, upgradeConfirmCb Downlo
82113 }
83114 defer tmpZipFile .Close ()
84115
116+ // Download and keep track of the progress
117+ src := & PassThru {Reader : download , length : size , progressCB : func (f float64 ) { feedback .Printf ("Download progress: %.2f %%" , f ) }}
85118 md5 := md5 .New ()
86- if _ , err := io .Copy (io .MultiWriter (md5 , tmpZipFile ), download ); err != nil {
119+ if _ , err := io .Copy (io .MultiWriter (md5 , tmpZipFile ), src ); err != nil {
87120 return "" , "" , err
88121 }
89122 tmpZipFile .Close ()
0 commit comments