forked from TrueCloudLab/restic
Merge pull request #4318 from MichaelEischer/status-output-truncation
Fix status output truncation
This commit is contained in:
commit
db046c0acc
3 changed files with 86 additions and 10 deletions
8
changelog/unreleased/pull-4318
Normal file
8
changelog/unreleased/pull-4318
Normal file
|
@ -0,0 +1,8 @@
|
|||
Bugfix: Correctly clean up status bar output of the `backup` command
|
||||
|
||||
Due to a regression in restic 0.15.2, the status bar of the `backup` command
|
||||
could leave some output behind. This happened if filenames were printed that
|
||||
are wider than the current terminal width. This has been fixed.
|
||||
|
||||
https://github.com/restic/restic/issues/4319
|
||||
https://github.com/restic/restic/pull/4318
|
|
@ -334,6 +334,21 @@ func wideRune(s string) (wide bool, utfsize uint) {
|
|||
return wide, uint(size)
|
||||
}
|
||||
|
||||
func sanitizeLines(lines []string, width int) []string {
|
||||
// Sanitize lines and truncate them if they're too long.
|
||||
for i, line := range lines {
|
||||
line = Quote(line)
|
||||
if width > 0 {
|
||||
line = Truncate(line, width-2)
|
||||
}
|
||||
if i < len(lines)-1 { // Last line gets no line break.
|
||||
line += "\n"
|
||||
}
|
||||
lines[i] = line
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
// SetStatus updates the status lines.
|
||||
// The lines should not contain newlines; this method adds them.
|
||||
func (t *Terminal) SetStatus(lines []string) {
|
||||
|
@ -352,16 +367,7 @@ func (t *Terminal) SetStatus(lines []string) {
|
|||
}
|
||||
}
|
||||
|
||||
// Sanitize lines and truncate them if they're too long.
|
||||
for i, line := range lines {
|
||||
line = Quote(line)
|
||||
if width > 0 {
|
||||
line = Truncate(line, width-2)
|
||||
}
|
||||
if i < len(lines)-1 { // Last line gets no line break.
|
||||
lines[i] = line + "\n"
|
||||
}
|
||||
}
|
||||
sanitizeLines(lines, width)
|
||||
|
||||
select {
|
||||
case t.status <- status{lines: lines}:
|
||||
|
|
|
@ -1,12 +1,54 @@
|
|||
package termstatus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
rtest "github.com/restic/restic/internal/test"
|
||||
)
|
||||
|
||||
func TestSetStatus(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
term := New(&buf, io.Discard, false)
|
||||
|
||||
term.canUpdateStatus = true
|
||||
term.fd = ^uintptr(0)
|
||||
term.clearCurrentLine = posixClearCurrentLine
|
||||
term.moveCursorUp = posixMoveCursorUp
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go term.Run(ctx)
|
||||
|
||||
const (
|
||||
clear = posixControlClearLine
|
||||
home = posixControlMoveCursorHome
|
||||
up = posixControlMoveCursorUp
|
||||
)
|
||||
|
||||
term.SetStatus([]string{"first"})
|
||||
exp := home + clear + "first" + home
|
||||
|
||||
term.SetStatus([]string{"foo", "bar", "baz"})
|
||||
exp += home + clear + "foo\n" + home + clear + "bar\n" +
|
||||
home + clear + "baz" + home + up + up
|
||||
|
||||
term.SetStatus([]string{"quux", "needs\nquote"})
|
||||
exp += home + clear + "quux\n" +
|
||||
home + clear + "\"needs\\nquote\"\n" +
|
||||
home + clear + home + up + up // Third line implicit.
|
||||
|
||||
cancel()
|
||||
exp += home + clear + "\n" + home + clear + "\n" +
|
||||
home + up + up // Status cleared.
|
||||
|
||||
<-term.closed
|
||||
rtest.Equals(t, exp, buf.String())
|
||||
}
|
||||
|
||||
func TestQuote(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
in string
|
||||
|
@ -91,3 +133,23 @@ func BenchmarkTruncateUnicode(b *testing.B) {
|
|||
|
||||
benchmarkTruncate(b, s, w-1)
|
||||
}
|
||||
|
||||
func TestSanitizeLines(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input []string
|
||||
width int
|
||||
output []string
|
||||
}{
|
||||
{[]string{""}, 80, []string{""}},
|
||||
{[]string{"too long test line"}, 10, []string{"too long"}},
|
||||
{[]string{"too long test line", "text"}, 10, []string{"too long\n", "text"}},
|
||||
{[]string{"too long test line", "second long test line"}, 10, []string{"too long\n", "second l"}},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("%s %d", test.input, test.width), func(t *testing.T) {
|
||||
out := sanitizeLines(test.input, test.width)
|
||||
rtest.Equals(t, test.output, out)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue