diff --git a/cmd/restic/integration_helpers_test.go b/cmd/restic/integration_helpers_test.go index b9a2db4c5..f574dbb13 100644 --- a/cmd/restic/integration_helpers_test.go +++ b/cmd/restic/integration_helpers_test.go @@ -10,7 +10,6 @@ import ( "path/filepath" "runtime" "strings" - "sync" "testing" "github.com/restic/restic/internal/backend" @@ -429,18 +428,10 @@ func withTermStatus(t testing.TB, gopts global.Options, callback func(ctx contex } func withTermStatusRaw(stdin io.ReadCloser, stdout, stderr io.Writer, gopts global.Options, callback func(ctx context.Context, gopts global.Options) error) error { - ctx, cancel := context.WithCancel(context.TODO()) - var wg sync.WaitGroup - - term := termstatus.New(stdin, stdout, stderr, gopts.Quiet) + term, cancel := termstatus.Setup(stdin, stdout, stderr, gopts.Quiet) gopts.Term = term - wg.Add(1) - go func() { - defer wg.Done() - term.Run(ctx) - }() - - defer wg.Wait() + defer cancel() + ctx, cancel := context.WithCancel(context.TODO()) defer cancel() return callback(ctx, gopts) diff --git a/internal/ui/termstatus/status.go b/internal/ui/termstatus/status.go index 6f5f744e0..63f168472 100644 --- a/internal/ui/termstatus/status.go +++ b/internal/ui/termstatus/status.go @@ -58,7 +58,15 @@ type fder interface { } // Setup creates a new termstatus. -// The returned function must be called to shut down the termstatus, +// The returned function must be called to shut down the termstatus. +// +// A goroutine is started to update the +// terminal. It is terminated when ctx is cancelled. When stdout is redirected to +// a file (e.g. via shell output redirection) or is just an io.Writer (not the +// open *os.File for stdout), no status lines are printed. The status lines and +// normal output (via Print/Printf) are written to stdout, error messages are +// written to stderr. If quiet is set to true, no status messages +// are printed even if the terminal supports it. // // Expected usage: // ``` @@ -66,12 +74,12 @@ type fder interface { // defer cancel() // // do stuff // ``` -func Setup(stdin io.ReadCloser, stdout, stderr io.Writer, quiet bool) (*Terminal, func()) { +func Setup(stdin io.ReadCloser, stdout, stderr io.Writer, quiet bool) (ui.Terminal, func()) { var wg sync.WaitGroup // only shutdown once cancel is called to ensure that no output is lost cancelCtx, cancel := context.WithCancel(context.Background()) - term := New(stdin, stdout, stderr, quiet) + term := new(stdin, stdout, stderr, quiet) wg.Add(1) go func() { defer wg.Done() @@ -89,14 +97,7 @@ func Setup(stdin io.ReadCloser, stdout, stderr io.Writer, quiet bool) (*Terminal } } -// New returns a new Terminal for wr. A goroutine is started to update the -// terminal. It is terminated when ctx is cancelled. When wr is redirected to -// a file (e.g. via shell output redirection) or is just an io.Writer (not the -// open *os.File for stdout), no status lines are printed. The status lines and -// normal output (via Print/Printf) are written to wr, error messages are -// written to errWriter. If disableStatus is set to true, no status messages -// are printed even if the terminal supports it. -func New(rd io.ReadCloser, wr io.Writer, errWriter io.Writer, disableStatus bool) *Terminal { +func new(rd io.ReadCloser, wr io.Writer, errWriter io.Writer, disableStatus bool) *Terminal { t := &Terminal{ rd: rd, wr: wr, diff --git a/internal/ui/termstatus/status_test.go b/internal/ui/termstatus/status_test.go index 989d2e782..78bc5ec6a 100644 --- a/internal/ui/termstatus/status_test.go +++ b/internal/ui/termstatus/status_test.go @@ -84,7 +84,7 @@ func TestSetStatusUnchangedLines(t *testing.T) { func setupStatusTest() (*bytes.Buffer, *Terminal, context.CancelFunc) { buf := &bytes.Buffer{} - term := New(nil, buf, buf, false) + term := new(nil, buf, buf, false) term.canUpdateStatus = true term.fd = ^uintptr(0) @@ -148,7 +148,7 @@ func TestReadPassword(t *testing.T) { func TestReadPasswordTerminal(t *testing.T) { expected := "password" - term := New(io.NopCloser(strings.NewReader(expected)), io.Discard, io.Discard, false) + term := new(io.NopCloser(strings.NewReader(expected)), io.Discard, io.Discard, false) pw, err := term.ReadPassword(context.Background(), "test") rtest.OK(t, err) rtest.Equals(t, expected, pw)