From 17995dec7a865a460d3292cd330a539ffb98540b Mon Sep 17 00:00:00 2001
From: Michael Eischer <michael.eischer@fau.de>
Date: Sun, 2 Aug 2020 12:22:06 +0200
Subject: [PATCH 1/2] Unify progress bar of check and prune commands

---
 cmd/restic/cmd_check.go | 33 +--------------------------------
 cmd/restic/cmd_prune.go | 31 -------------------------------
 cmd/restic/progress.go  | 36 ++++++++++++++++++++++++++++++++++++
 3 files changed, 37 insertions(+), 63 deletions(-)
 create mode 100644 cmd/restic/progress.go

diff --git a/cmd/restic/cmd_check.go b/cmd/restic/cmd_check.go
index fdd76dd3e..5d156ef78 100644
--- a/cmd/restic/cmd_check.go
+++ b/cmd/restic/cmd_check.go
@@ -5,7 +5,6 @@ import (
 	"io/ioutil"
 	"strconv"
 	"strings"
-	"time"
 
 	"github.com/spf13/cobra"
 
@@ -99,36 +98,6 @@ func stringToIntSlice(param string) (split []uint, err error) {
 	return result, nil
 }
 
-func newReadProgress(gopts GlobalOptions, todo restic.Stat) *restic.Progress {
-	if gopts.Quiet {
-		return nil
-	}
-
-	readProgress := restic.NewProgress()
-
-	readProgress.OnUpdate = func(s restic.Stat, d time.Duration, ticker bool) {
-		status := fmt.Sprintf("[%s] %s  %d / %d items",
-			formatDuration(d),
-			formatPercent(s.Blobs, todo.Blobs),
-			s.Blobs, todo.Blobs)
-
-		if w := stdoutTerminalWidth(); w > 0 {
-			if len(status) > w {
-				max := w - len(status) - 4
-				status = status[:max] + "... "
-			}
-		}
-
-		PrintProgress("%s", status)
-	}
-
-	readProgress.OnDone = func(s restic.Stat, d time.Duration, ticker bool) {
-		fmt.Printf("\nduration: %s\n", formatDuration(d))
-	}
-
-	return readProgress
-}
-
 // prepareCheckCache configures a special cache directory for check.
 //
 //  * if --with-cache is specified, the default cache is used
@@ -281,7 +250,7 @@ func runCheck(opts CheckOptions, gopts GlobalOptions, args []string) error {
 			Verbosef("read all data\n")
 		}
 
-		p := newReadProgress(gopts, restic.Stat{Blobs: packCount})
+		p := newProgressMax(!gopts.Quiet, packCount, "packs")
 		errChan := make(chan error)
 
 		go chkr.ReadPacks(gopts.ctx, packs, p, errChan)
diff --git a/cmd/restic/cmd_prune.go b/cmd/restic/cmd_prune.go
index fcddc76b1..2a386793c 100644
--- a/cmd/restic/cmd_prune.go
+++ b/cmd/restic/cmd_prune.go
@@ -1,9 +1,6 @@
 package main
 
 import (
-	"fmt"
-	"time"
-
 	"github.com/restic/restic/internal/debug"
 	"github.com/restic/restic/internal/errors"
 	"github.com/restic/restic/internal/index"
@@ -47,34 +44,6 @@ func shortenStatus(maxLength int, s string) string {
 	return s[:maxLength-3] + "..."
 }
 
-// newProgressMax returns a progress that counts blobs.
-func newProgressMax(show bool, max uint64, description string) *restic.Progress {
-	if !show {
-		return nil
-	}
-
-	p := restic.NewProgress()
-
-	p.OnUpdate = func(s restic.Stat, d time.Duration, ticker bool) {
-		status := fmt.Sprintf("[%s] %s  %d / %d %s",
-			formatDuration(d),
-			formatPercent(s.Blobs, max),
-			s.Blobs, max, description)
-
-		if w := stdoutTerminalWidth(); w > 0 {
-			status = shortenStatus(w, status)
-		}
-
-		PrintProgress("%s", status)
-	}
-
-	p.OnDone = func(s restic.Stat, d time.Duration, ticker bool) {
-		fmt.Printf("\n")
-	}
-
-	return p
-}
-
 func runPrune(gopts GlobalOptions) error {
 	repo, err := OpenRepository(gopts)
 	if err != nil {
diff --git a/cmd/restic/progress.go b/cmd/restic/progress.go
new file mode 100644
index 000000000..19bb616e3
--- /dev/null
+++ b/cmd/restic/progress.go
@@ -0,0 +1,36 @@
+package main
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/restic/restic/internal/restic"
+)
+
+// newProgressMax returns a progress that counts blobs.
+func newProgressMax(show bool, max uint64, description string) *restic.Progress {
+	if !show {
+		return nil
+	}
+
+	p := restic.NewProgress()
+
+	p.OnUpdate = func(s restic.Stat, d time.Duration, ticker bool) {
+		status := fmt.Sprintf("[%s] %s  %d / %d %s",
+			formatDuration(d),
+			formatPercent(s.Blobs, max),
+			s.Blobs, max, description)
+
+		if w := stdoutTerminalWidth(); w > 0 {
+			status = shortenStatus(w, status)
+		}
+
+		PrintProgress("%s", status)
+	}
+
+	p.OnDone = func(s restic.Stat, d time.Duration, ticker bool) {
+		fmt.Printf("\n")
+	}
+
+	return p
+}

From bc0501d72c76da39fba7ff9fb5f7fd361d60419d Mon Sep 17 00:00:00 2001
From: Michael Eischer <michael.eischer@fau.de>
Date: Tue, 25 Aug 2020 23:33:10 +0200
Subject: [PATCH 2/2] Add changelog

---
 changelog/unreleased/pull-2899 | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 changelog/unreleased/pull-2899

diff --git a/changelog/unreleased/pull-2899 b/changelog/unreleased/pull-2899
new file mode 100644
index 000000000..5aa42f36b
--- /dev/null
+++ b/changelog/unreleased/pull-2899
@@ -0,0 +1,9 @@
+Bugfix: Fix possible crash in the progress bar of check --read-data
+
+We've fixed a possible crash while displaying the progress bar for the
+check --read-data command. The crash occurred when the length of the
+progress bar status exceeded the terminal width, which only happened for
+very narrow terminal windows.
+
+https://github.com/restic/restic/pull/2899
+https://forum.restic.net/t/restic-rclone-pcloud-connection-issues/2963/15