diff --git a/cmd/restic/global.go b/cmd/restic/global.go index f5255e22b..8d02b228e 100644 --- a/cmd/restic/global.go +++ b/cmd/restic/global.go @@ -31,6 +31,7 @@ import ( "github.com/restic/restic/internal/repository" "github.com/restic/restic/internal/restic" "github.com/restic/restic/internal/textfile" + "github.com/restic/restic/internal/ui/termstatus" "github.com/restic/restic/internal/errors" @@ -142,7 +143,13 @@ func stdinIsTerminal() bool { } func stdoutIsTerminal() bool { - return terminal.IsTerminal(int(os.Stdout.Fd())) + // mintty on windows can use pipes which behave like a posix terminal, + // but which are not a terminal handle + return terminal.IsTerminal(int(os.Stdout.Fd())) || stdoutCanUpdateStatus() +} + +func stdoutCanUpdateStatus() bool { + return termstatus.CanUpdateStatus(os.Stdout.Fd()) } func stdoutTerminalWidth() int { @@ -159,7 +166,7 @@ func stdoutTerminalWidth() int { // program execution must revert changes to the terminal configuration itself. // The terminal configuration is only restored while reading a password. func restoreTerminal() { - if !stdoutIsTerminal() { + if !terminal.IsTerminal(int(os.Stdout.Fd())) { return } @@ -248,7 +255,7 @@ func PrintProgress(format string, args ...interface{}) { message = fmt.Sprintf(format, args...) if !(strings.HasSuffix(message, "\r") || strings.HasSuffix(message, "\n")) { - if stdoutIsTerminal() { + if stdoutCanUpdateStatus() { carriageControl = "\r" } else { carriageControl = "\n" @@ -256,7 +263,7 @@ func PrintProgress(format string, args ...interface{}) { message = fmt.Sprintf("%s%s", message, carriageControl) } - if stdoutIsTerminal() { + if stdoutCanUpdateStatus() { message = fmt.Sprintf("%s%s", ClearLine(), message) } diff --git a/cmd/restic/progress.go b/cmd/restic/progress.go index 62f2e6396..0c2a24271 100644 --- a/cmd/restic/progress.go +++ b/cmd/restic/progress.go @@ -20,7 +20,7 @@ func calculateProgressInterval(show bool) time.Duration { fps = 60 } interval = time.Duration(float64(time.Second) / fps) - } else if !stdoutIsTerminal() || !show { + } else if !stdoutCanUpdateStatus() || !show { interval = 0 } return interval diff --git a/internal/ui/termstatus/status.go b/internal/ui/termstatus/status.go index 6b50effbb..e275f5b7d 100644 --- a/internal/ui/termstatus/status.go +++ b/internal/ui/termstatus/status.go @@ -67,7 +67,7 @@ func New(wr io.Writer, errWriter io.Writer, disableStatus bool) *Terminal { return t } - if d, ok := wr.(fder); ok && canUpdateStatus(d.Fd()) { + if d, ok := wr.(fder); ok && CanUpdateStatus(d.Fd()) { // only use the fancy status code when we're running on a real terminal. t.canUpdateStatus = true t.fd = d.Fd() diff --git a/internal/ui/termstatus/terminal_unix.go b/internal/ui/termstatus/terminal_unix.go index 3f0061c01..67ce06b0b 100644 --- a/internal/ui/termstatus/terminal_unix.go +++ b/internal/ui/termstatus/terminal_unix.go @@ -20,9 +20,9 @@ func moveCursorUp(wr io.Writer, fd uintptr) func(io.Writer, uintptr, int) { return posixMoveCursorUp } -// canUpdateStatus returns true if status lines can be printed, the process +// CanUpdateStatus returns true if status lines can be printed, the process // output is not redirected to a file or pipe. -func canUpdateStatus(fd uintptr) bool { +func CanUpdateStatus(fd uintptr) bool { if !terminal.IsTerminal(int(fd)) { return false } diff --git a/internal/ui/termstatus/terminal_windows.go b/internal/ui/termstatus/terminal_windows.go index 723aebdff..478d3a8ce 100644 --- a/internal/ui/termstatus/terminal_windows.go +++ b/internal/ui/termstatus/terminal_windows.go @@ -80,9 +80,9 @@ func isPipe(fd uintptr) bool { return err == nil && typ == windows.FILE_TYPE_PIPE } -// canUpdateStatus returns true if status lines can be printed, the process +// CanUpdateStatus returns true if status lines can be printed, the process // output is not redirected to a file or pipe. -func canUpdateStatus(fd uintptr) bool { +func CanUpdateStatus(fd uintptr) bool { // easy case, the terminal is cmd or psh, without redirection if isWindowsTerminal(fd) { return true