diff --git a/cmd/restic/cmd_backup.go b/cmd/restic/cmd_backup.go index 348050895..0596ee918 100644 --- a/cmd/restic/cmd_backup.go +++ b/cmd/restic/cmd_backup.go @@ -12,7 +12,6 @@ import ( "runtime" "strconv" "strings" - "sync" "time" "github.com/spf13/cobra" @@ -25,7 +24,6 @@ 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" "github.com/restic/restic/internal/ui/backup" "github.com/restic/restic/internal/ui/termstatus" ) @@ -56,31 +54,9 @@ Exit status is 3 if some source data could not be read (incomplete snapshot crea }, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { - ctx := cmd.Context() - var wg sync.WaitGroup - cancelCtx, cancel := context.WithCancel(ctx) - defer func() { - // shutdown termstatus - cancel() - wg.Wait() - }() - - term := termstatus.New(globalOptions.stdout, globalOptions.stderr, globalOptions.Quiet) - wg.Add(1) - go func() { - defer wg.Done() - term.Run(cancelCtx) - }() - - // use the terminal for stdout/stderr - prevStdout, prevStderr := globalOptions.stdout, globalOptions.stderr - defer func() { - globalOptions.stdout, globalOptions.stderr = prevStdout, prevStderr - }() - stdioWrapper := ui.NewStdioWrapper(term) - globalOptions.stdout, globalOptions.stderr = stdioWrapper.Stdout(), stdioWrapper.Stderr() - - return runBackup(ctx, backupOptions, globalOptions, term, args) + term, cancel := setupTermstatus(cmd.Context()) + defer cancel() + return runBackup(cmd.Context(), backupOptions, globalOptions, term, args) }, } diff --git a/cmd/restic/cmd_restore.go b/cmd/restic/cmd_restore.go index 6045a5d41..b5c62fdea 100644 --- a/cmd/restic/cmd_restore.go +++ b/cmd/restic/cmd_restore.go @@ -3,7 +3,6 @@ package main import ( "context" "strings" - "sync" "time" "github.com/restic/restic/internal/debug" @@ -38,31 +37,9 @@ Exit status is 0 if the command was successful, and non-zero if there was any er `, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { - ctx := cmd.Context() - var wg sync.WaitGroup - cancelCtx, cancel := context.WithCancel(ctx) - defer func() { - // shutdown termstatus - cancel() - wg.Wait() - }() - - term := termstatus.New(globalOptions.stdout, globalOptions.stderr, globalOptions.Quiet) - wg.Add(1) - go func() { - defer wg.Done() - term.Run(cancelCtx) - }() - - // allow usage of warnf / verbosef - prevStdout, prevStderr := globalOptions.stdout, globalOptions.stderr - defer func() { - globalOptions.stdout, globalOptions.stderr = prevStdout, prevStderr - }() - stdioWrapper := ui.NewStdioWrapper(term) - globalOptions.stdout, globalOptions.stderr = stdioWrapper.Stdout(), stdioWrapper.Stderr() - - return runRestore(ctx, restoreOptions, globalOptions, term, args) + term, cancel := setupTermstatus(cmd.Context()) + defer cancel() + return runRestore(cmd.Context(), restoreOptions, globalOptions, term, args) }, } diff --git a/cmd/restic/termstatus.go b/cmd/restic/termstatus.go new file mode 100644 index 000000000..e39054427 --- /dev/null +++ b/cmd/restic/termstatus.go @@ -0,0 +1,42 @@ +package main + +import ( + "context" + "sync" + + "github.com/restic/restic/internal/ui" + "github.com/restic/restic/internal/ui/termstatus" +) + +// setupTermstatus creates a new termstatus and reroutes globalOptions.{stdout,stderr} to it +// The returned function must be called to shut down the termstatus, +// +// Expected usage: +// ``` +// term, cancel := setupTermstatus(ctx) +// defer cancel() +// // do stuff +// ``` +func setupTermstatus(ctx context.Context) (*termstatus.Terminal, func()) { + var wg sync.WaitGroup + cancelCtx, cancel := context.WithCancel(ctx) + + term := termstatus.New(globalOptions.stdout, globalOptions.stderr, globalOptions.Quiet) + wg.Add(1) + go func() { + defer wg.Done() + term.Run(cancelCtx) + }() + + // use the termstatus for stdout/stderr + prevStdout, prevStderr := globalOptions.stdout, globalOptions.stderr + stdioWrapper := ui.NewStdioWrapper(term) + globalOptions.stdout, globalOptions.stderr = stdioWrapper.Stdout(), stdioWrapper.Stderr() + + return term, func() { + // shutdown termstatus + globalOptions.stdout, globalOptions.stderr = prevStdout, prevStderr + cancel() + wg.Wait() + } +}