m/cli/metroctl: use one progress bar for all files

Previously, there was a separate progress bar for each uploaded file,
now there is just one which shows the total number of bytes transferred.

Change-Id: Id4cba63889077a076cb63d437e3fe4b17cfc3786
Reviewed-on: https://review.monogon.dev/c/monogon/+/4049
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
Tested-by: Jenkins CI
diff --git a/osbase/net/sshtakeover/sshtakeover.go b/osbase/net/sshtakeover/sshtakeover.go
index b8fd8b2..fdb63f3 100644
--- a/osbase/net/sshtakeover/sshtakeover.go
+++ b/osbase/net/sshtakeover/sshtakeover.go
@@ -18,8 +18,9 @@
 )
 
 type Client struct {
-	cl *ssh.Client
-	sc *sftp.Client
+	cl       *ssh.Client
+	sc       *sftp.Client
+	progress func(int64)
 }
 
 // Dial starts an ssh client connection.
@@ -79,21 +80,26 @@
 	}
 }
 
-type contextReader struct {
-	r   io.Reader
-	ctx context.Context
+type wrappedReader struct {
+	r        io.Reader
+	ctx      context.Context
+	progress func(int64)
 }
 
-func (r *contextReader) Read(p []byte) (n int, err error) {
+func (r *wrappedReader) Read(p []byte) (n int, err error) {
 	if r.ctx.Err() != nil {
 		return 0, r.ctx.Err()
 	}
-	return r.r.Read(p)
+	n, err = r.r.Read(p)
+	if r.progress != nil {
+		r.progress(int64(n))
+	}
+	return
 }
 
 // Upload a given blob to a targetPath on the system.
 func (p *Client) Upload(ctx context.Context, targetPath string, src io.Reader) error {
-	src = &contextReader{r: src, ctx: ctx}
+	src = &wrappedReader{r: src, ctx: ctx, progress: p.progress}
 
 	df, err := p.sc.Create(targetPath)
 	if err != nil {
@@ -119,6 +125,12 @@
 	return nil
 }
 
+// SetProgress sets a callback which will be called repeatedly during uploads
+// with a number of bytes that have been read.
+func (p *Client) SetProgress(callback func(int64)) {
+	p.progress = callback
+}
+
 func (p *Client) Close() error {
 	scErr := p.sc.Close()
 	clErr := p.cl.Close()