mirror of
https://github.com/restic/restic.git
synced 2025-12-11 18:47:50 +00:00
replace globalOptions.stdout with termstatus.OutputWriter
This commit is contained in:
@@ -161,7 +161,7 @@ func runCache(opts CacheOptions, gopts GlobalOptions, args []string, term ui.Ter
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = tab.Write(gopts.stdout)
|
_ = tab.Write(gopts.term.OutputWriter())
|
||||||
printer.S("%d cache dirs in %s", len(dirs), cachedir)
|
printer.S("%d cache dirs in %s", len(dirs), cachedir)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -23,15 +23,13 @@ func testRunCheckMustFail(t testing.TB, gopts GlobalOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testRunCheckOutput(t testing.TB, gopts GlobalOptions, checkUnused bool) (string, error) {
|
func testRunCheckOutput(t testing.TB, gopts GlobalOptions, checkUnused bool) (string, error) {
|
||||||
buf, err := withCaptureStdout(gopts, func(gopts GlobalOptions) error {
|
buf, err := withCaptureStdout(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
||||||
return withTermStatus(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
opts := CheckOptions{
|
||||||
opts := CheckOptions{
|
ReadData: true,
|
||||||
ReadData: true,
|
CheckUnused: checkUnused,
|
||||||
CheckUnused: checkUnused,
|
}
|
||||||
}
|
_, err := runCheck(context.TODO(), opts, gopts, nil, gopts.term)
|
||||||
_, err := runCheck(context.TODO(), opts, gopts, nil, gopts.term)
|
return err
|
||||||
return err
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
return buf.String(), err
|
return buf.String(), err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,20 +200,20 @@ func runDebugDump(ctx context.Context, gopts GlobalOptions, args []string, term
|
|||||||
|
|
||||||
switch tpe {
|
switch tpe {
|
||||||
case "indexes":
|
case "indexes":
|
||||||
return dumpIndexes(ctx, repo, gopts.stdout, printer)
|
return dumpIndexes(ctx, repo, gopts.term.OutputWriter(), printer)
|
||||||
case "snapshots":
|
case "snapshots":
|
||||||
return debugPrintSnapshots(ctx, repo, gopts.stdout)
|
return debugPrintSnapshots(ctx, repo, gopts.term.OutputWriter())
|
||||||
case "packs":
|
case "packs":
|
||||||
return printPacks(ctx, repo, gopts.stdout, printer)
|
return printPacks(ctx, repo, gopts.term.OutputWriter(), printer)
|
||||||
case "all":
|
case "all":
|
||||||
printer.S("snapshots:")
|
printer.S("snapshots:")
|
||||||
err := debugPrintSnapshots(ctx, repo, gopts.stdout)
|
err := debugPrintSnapshots(ctx, repo, gopts.term.OutputWriter())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
printer.S("indexes:")
|
printer.S("indexes:")
|
||||||
err = dumpIndexes(ctx, repo, gopts.stdout, printer)
|
err = dumpIndexes(ctx, repo, gopts.term.OutputWriter(), printer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -424,7 +424,7 @@ func runDiff(ctx context.Context, opts DiffOptions, gopts GlobalOptions, args []
|
|||||||
}
|
}
|
||||||
|
|
||||||
if gopts.JSON {
|
if gopts.JSON {
|
||||||
enc := json.NewEncoder(gopts.stdout)
|
enc := json.NewEncoder(gopts.term.OutputWriter())
|
||||||
c.printChange = func(change *Change) {
|
c.printChange = func(change *Change) {
|
||||||
err := enc.Encode(change)
|
err := enc.Encode(change)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -458,7 +458,7 @@ func runDiff(ctx context.Context, opts DiffOptions, gopts GlobalOptions, args []
|
|||||||
updateBlobs(repo, stats.BlobsAfter.Sub(both).Sub(stats.BlobsCommon), &stats.Added, printer.E)
|
updateBlobs(repo, stats.BlobsAfter.Sub(both).Sub(stats.BlobsCommon), &stats.Added, printer.E)
|
||||||
|
|
||||||
if gopts.JSON {
|
if gopts.JSON {
|
||||||
err := json.NewEncoder(gopts.stdout).Encode(stats)
|
err := json.NewEncoder(gopts.term.OutputWriter()).Encode(stats)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printer.E("JSON encode failed: %v", err)
|
printer.E("JSON encode failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func testRunDiffOutput(t testing.TB, gopts GlobalOptions, firstSnapshotID string, secondSnapshotID string) (string, error) {
|
func testRunDiffOutput(t testing.TB, gopts GlobalOptions, firstSnapshotID string, secondSnapshotID string) (string, error) {
|
||||||
buf, err := withCaptureStdout(gopts, func(gopts GlobalOptions) error {
|
buf, err := withCaptureStdout(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
||||||
opts := DiffOptions{
|
opts := DiffOptions{
|
||||||
ShowMetadata: false,
|
ShowMetadata: false,
|
||||||
}
|
}
|
||||||
return withTermStatus(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
return runDiff(ctx, opts, gopts, []string{firstSnapshotID, secondSnapshotID}, gopts.term)
|
||||||
return runDiff(ctx, opts, gopts, []string{firstSnapshotID, secondSnapshotID}, gopts.term)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
return buf.String(), err
|
return buf.String(), err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ Exit status is 1 if there was any error.
|
|||||||
for _, flag := range flags {
|
for _, flag := range flags {
|
||||||
tab.AddRow(flag)
|
tab.AddRow(flag)
|
||||||
}
|
}
|
||||||
return tab.Write(globalOptions.stdout)
|
return tab.Write(globalOptions.term.OutputWriter())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,12 +11,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func testRunFind(t testing.TB, wantJSON bool, opts FindOptions, gopts GlobalOptions, pattern string) []byte {
|
func testRunFind(t testing.TB, wantJSON bool, opts FindOptions, gopts GlobalOptions, pattern string) []byte {
|
||||||
buf, err := withCaptureStdout(gopts, func(gopts GlobalOptions) error {
|
buf, err := withCaptureStdout(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
||||||
gopts.JSON = wantJSON
|
gopts.JSON = wantJSON
|
||||||
|
|
||||||
return withTermStatus(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
return runFind(ctx, opts, gopts, []string{pattern}, gopts.term)
|
||||||
return runFind(ctx, opts, gopts, []string{pattern}, gopts.term)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
return buf.Bytes()
|
return buf.Bytes()
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption
|
|||||||
}
|
}
|
||||||
|
|
||||||
if gopts.Verbose >= 1 && !gopts.JSON {
|
if gopts.Verbose >= 1 && !gopts.JSON {
|
||||||
err = PrintSnapshotGroupHeader(gopts.stdout, k)
|
err = PrintSnapshotGroupHeader(gopts.term.OutputWriter(), k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -274,7 +274,7 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption
|
|||||||
}
|
}
|
||||||
if len(keep) != 0 && !gopts.Quiet && !gopts.JSON {
|
if len(keep) != 0 && !gopts.Quiet && !gopts.JSON {
|
||||||
printer.P("keep %d snapshots:\n", len(keep))
|
printer.P("keep %d snapshots:\n", len(keep))
|
||||||
if err := PrintSnapshots(gopts.stdout, keep, reasons, opts.Compact); err != nil {
|
if err := PrintSnapshots(gopts.term.OutputWriter(), keep, reasons, opts.Compact); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printer.P("\n")
|
printer.P("\n")
|
||||||
@@ -283,7 +283,7 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption
|
|||||||
|
|
||||||
if len(remove) != 0 && !gopts.Quiet && !gopts.JSON {
|
if len(remove) != 0 && !gopts.Quiet && !gopts.JSON {
|
||||||
printer.P("remove %d snapshots:\n", len(remove))
|
printer.P("remove %d snapshots:\n", len(remove))
|
||||||
if err := PrintSnapshots(gopts.stdout, remove, nil, opts.Compact); err != nil {
|
if err := PrintSnapshots(gopts.term.OutputWriter(), remove, nil, opts.Compact); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printer.P("\n")
|
printer.P("\n")
|
||||||
@@ -328,7 +328,7 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption
|
|||||||
}
|
}
|
||||||
|
|
||||||
if gopts.JSON && len(jsonGroups) > 0 {
|
if gopts.JSON && len(jsonGroups) > 0 {
|
||||||
err = printJSONForget(gopts.stdout, jsonGroups)
|
err = printJSONForget(gopts.term.OutputWriter(), jsonGroups)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ func writeCompletion(filename string, shell string, generate func(w io.Writer) e
|
|||||||
defer func() { err = outFile.Close() }()
|
defer func() { err = outFile.Close() }()
|
||||||
outWriter = outFile
|
outWriter = outFile
|
||||||
} else {
|
} else {
|
||||||
outWriter = gopts.stdout
|
outWriter = gopts.term.OutputWriter()
|
||||||
}
|
}
|
||||||
|
|
||||||
err = generate(outWriter)
|
err = generate(outWriter)
|
||||||
|
|||||||
@@ -9,10 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func testRunGenerate(t testing.TB, gopts GlobalOptions, opts generateOptions) ([]byte, error) {
|
func testRunGenerate(t testing.TB, gopts GlobalOptions, opts generateOptions) ([]byte, error) {
|
||||||
buf, err := withCaptureStdout(gopts, func(gopts GlobalOptions) error {
|
buf, err := withCaptureStdout(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
||||||
return withTermStatus(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
return runGenerate(opts, gopts, []string{}, gopts.term)
|
||||||
return runGenerate(opts, gopts, []string{}, gopts.term)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
return buf.Bytes(), err
|
return buf.Bytes(), err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ func runInit(ctx context.Context, opts InitOptions, gopts GlobalOptions, args []
|
|||||||
ID: s.Config().ID,
|
ID: s.Config().ID,
|
||||||
Repository: location.StripPassword(gopts.backends, gopts.Repo),
|
Repository: location.StripPassword(gopts.backends, gopts.Repo),
|
||||||
}
|
}
|
||||||
return json.NewEncoder(gopts.stdout).Encode(status)
|
return json.NewEncoder(gopts.term.OutputWriter()).Encode(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -16,10 +16,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func testRunKeyListOtherIDs(t testing.TB, gopts GlobalOptions) []string {
|
func testRunKeyListOtherIDs(t testing.TB, gopts GlobalOptions) []string {
|
||||||
buf, err := withCaptureStdout(gopts, func(gopts GlobalOptions) error {
|
buf, err := withCaptureStdout(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
||||||
return withTermStatus(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
return runKeyList(ctx, gopts, []string{}, gopts.term)
|
||||||
return runKeyList(ctx, gopts, []string{}, gopts.term)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ func listKeys(ctx context.Context, s *repository.Repository, gopts GlobalOptions
|
|||||||
}
|
}
|
||||||
|
|
||||||
if gopts.JSON {
|
if gopts.JSON {
|
||||||
return json.NewEncoder(gopts.stdout).Encode(keys)
|
return json.NewEncoder(gopts.term.OutputWriter()).Encode(keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
tab := table.New()
|
tab := table.New()
|
||||||
@@ -108,5 +108,5 @@ func listKeys(ctx context.Context, s *repository.Repository, gopts GlobalOptions
|
|||||||
tab.AddRow(key)
|
tab.AddRow(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
return tab.Write(gopts.stdout)
|
return tab.Write(gopts.term.OutputWriter())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func testRunList(t testing.TB, gopts GlobalOptions, tpe string) restic.IDs {
|
func testRunList(t testing.TB, gopts GlobalOptions, tpe string) restic.IDs {
|
||||||
buf, err := withCaptureStdout(gopts, func(gopts GlobalOptions) error {
|
buf, err := withCaptureStdout(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
||||||
return withTermStatus(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
return runList(ctx, gopts, []string{tpe}, gopts.term)
|
||||||
return runList(ctx, gopts, []string{tpe}, gopts.term)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
return parseIDsFromReader(t, buf)
|
return parseIDsFromReader(t, buf)
|
||||||
|
|||||||
@@ -382,11 +382,11 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
|
|||||||
|
|
||||||
if gopts.JSON {
|
if gopts.JSON {
|
||||||
printer = &jsonLsPrinter{
|
printer = &jsonLsPrinter{
|
||||||
enc: json.NewEncoder(gopts.stdout),
|
enc: json.NewEncoder(gopts.term.OutputWriter()),
|
||||||
}
|
}
|
||||||
} else if opts.Ncdu {
|
} else if opts.Ncdu {
|
||||||
printer = &ncduLsPrinter{
|
printer = &ncduLsPrinter{
|
||||||
out: gopts.stdout,
|
out: gopts.term.OutputWriter(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printer = &textLsPrinter{
|
printer = &textLsPrinter{
|
||||||
|
|||||||
@@ -13,11 +13,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func testRunLsWithOpts(t testing.TB, gopts GlobalOptions, opts LsOptions, args []string) []byte {
|
func testRunLsWithOpts(t testing.TB, gopts GlobalOptions, opts LsOptions, args []string) []byte {
|
||||||
buf, err := withCaptureStdout(gopts, func(gopts GlobalOptions) error {
|
buf, err := withCaptureStdout(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
||||||
gopts.Quiet = true
|
gopts.Quiet = true
|
||||||
return withTermStatus(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
return runLs(context.TODO(), opts, gopts, args, gopts.term)
|
||||||
return runLs(context.TODO(), opts, gopts, args, gopts.term)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
return buf.Bytes()
|
return buf.Bytes()
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ func createPrunableRepo(t *testing.T, env *testEnvironment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testRunForgetJSON(t testing.TB, gopts GlobalOptions, args ...string) {
|
func testRunForgetJSON(t testing.TB, gopts GlobalOptions, args ...string) {
|
||||||
buf, err := withCaptureStdout(gopts, func(gopts GlobalOptions) error {
|
buf, err := withCaptureStdout(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
||||||
gopts.JSON = true
|
gopts.JSON = true
|
||||||
opts := ForgetOptions{
|
opts := ForgetOptions{
|
||||||
DryRun: true,
|
DryRun: true,
|
||||||
@@ -98,9 +98,7 @@ func testRunForgetJSON(t testing.TB, gopts GlobalOptions, args ...string) {
|
|||||||
pruneOpts := PruneOptions{
|
pruneOpts := PruneOptions{
|
||||||
MaxUnused: "5%",
|
MaxUnused: "5%",
|
||||||
}
|
}
|
||||||
return withTermStatus(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
return runForget(context.TODO(), opts, pruneOpts, gopts, gopts.term, args)
|
||||||
return runForget(context.TODO(), opts, pruneOpts, gopts, gopts.term, args)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
|
|
||||||
func testRunRebuildIndex(t testing.TB, gopts GlobalOptions) {
|
func testRunRebuildIndex(t testing.TB, gopts GlobalOptions) {
|
||||||
rtest.OK(t, withTermStatus(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
rtest.OK(t, withTermStatus(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
||||||
gopts.stdout = io.Discard
|
gopts.Quiet = true
|
||||||
return runRebuildIndex(context.TODO(), RepairIndexOptions{}, gopts, gopts.term)
|
return runRebuildIndex(context.TODO(), RepairIndexOptions{}, gopts, gopts.term)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,7 @@ func TestRebuildIndexFailsOnAppendOnly(t *testing.T) {
|
|||||||
return &appendOnlyBackend{r}, nil
|
return &appendOnlyBackend{r}, nil
|
||||||
}
|
}
|
||||||
err := withTermStatus(t, env.gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
err := withTermStatus(t, env.gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
||||||
gopts.stdout = io.Discard
|
gopts.Quiet = true
|
||||||
return runRebuildIndex(context.TODO(), RepairIndexOptions{}, gopts, gopts.term)
|
return runRebuildIndex(context.TODO(), RepairIndexOptions{}, gopts, gopts.term)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ func runSnapshots(ctx context.Context, opts SnapshotOptions, gopts GlobalOptions
|
|||||||
}
|
}
|
||||||
|
|
||||||
if gopts.JSON {
|
if gopts.JSON {
|
||||||
err := printSnapshotGroupJSON(gopts.stdout, snapshotGroups, grouped)
|
err := printSnapshotGroupJSON(gopts.term.OutputWriter(), snapshotGroups, grouped)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printer.E("error printing snapshots: %v", err)
|
printer.E("error printing snapshots: %v", err)
|
||||||
}
|
}
|
||||||
@@ -116,12 +116,12 @@ func runSnapshots(ctx context.Context, opts SnapshotOptions, gopts GlobalOptions
|
|||||||
}
|
}
|
||||||
|
|
||||||
if grouped {
|
if grouped {
|
||||||
err := PrintSnapshotGroupHeader(gopts.stdout, k)
|
err := PrintSnapshotGroupHeader(gopts.term.OutputWriter(), k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := PrintSnapshots(gopts.stdout, list, nil, opts.Compact)
|
err := PrintSnapshots(gopts.term.OutputWriter(), list, nil, opts.Compact)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func testRunSnapshots(t testing.TB, gopts GlobalOptions) (newest *Snapshot, snapmap map[restic.ID]Snapshot) {
|
func testRunSnapshots(t testing.TB, gopts GlobalOptions) (newest *Snapshot, snapmap map[restic.ID]Snapshot) {
|
||||||
buf, err := withCaptureStdout(gopts, func(gopts GlobalOptions) error {
|
buf, err := withCaptureStdout(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
||||||
gopts.JSON = true
|
gopts.JSON = true
|
||||||
|
|
||||||
opts := SnapshotOptions{}
|
opts := SnapshotOptions{}
|
||||||
return withTermStatus(t, gopts, func(ctx context.Context, gopts GlobalOptions) error {
|
return runSnapshots(ctx, opts, gopts, []string{}, gopts.term)
|
||||||
return runSnapshots(ctx, opts, gopts, []string{}, gopts.term)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ func runStats(ctx context.Context, opts StatsOptions, gopts GlobalOptions, args
|
|||||||
}
|
}
|
||||||
|
|
||||||
if gopts.JSON {
|
if gopts.JSON {
|
||||||
err = json.NewEncoder(gopts.stdout).Encode(stats)
|
err = json.NewEncoder(gopts.term.OutputWriter()).Encode(stats)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("encoding output: %v", err)
|
return fmt.Errorf("encoding output: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ Exit status is 1 if there was any error.
|
|||||||
GoArch: runtime.GOARCH,
|
GoArch: runtime.GOARCH,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := json.NewEncoder(globalOptions.stdout).Encode(jsonS)
|
err := json.NewEncoder(globalOptions.term.OutputWriter()).Encode(jsonS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printer.E("JSON encode failed: %v\n", err)
|
printer.E("JSON encode failed: %v\n", err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -74,7 +73,6 @@ type GlobalOptions struct {
|
|||||||
limiter.Limits
|
limiter.Limits
|
||||||
|
|
||||||
password string
|
password string
|
||||||
stdout io.Writer
|
|
||||||
term ui.Terminal
|
term ui.Terminal
|
||||||
|
|
||||||
backends *location.Registry
|
backends *location.Registry
|
||||||
|
|||||||
@@ -212,10 +212,6 @@ func withTestEnvironment(t testing.TB) (env *testEnvironment, cleanup func()) {
|
|||||||
Quiet: true,
|
Quiet: true,
|
||||||
CacheDir: env.cache,
|
CacheDir: env.cache,
|
||||||
password: rtest.TestPassword,
|
password: rtest.TestPassword,
|
||||||
// stdout and stderr are written to by Warnf etc. That is the written data
|
|
||||||
// usually consists of one or multiple lines and therefore can be handled well
|
|
||||||
// by t.Log.
|
|
||||||
stdout: &logOutputter{t},
|
|
||||||
extended: make(options.Options),
|
extended: make(options.Options),
|
||||||
|
|
||||||
// replace this hook with "nil" if listing a filetype more than once is necessary
|
// replace this hook with "nil" if listing a filetype more than once is necessary
|
||||||
@@ -416,18 +412,24 @@ func testFileSize(filename string, size int64) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func withCaptureStdout(gopts GlobalOptions, inner func(gopts GlobalOptions) error) (*bytes.Buffer, error) {
|
func withCaptureStdout(t testing.TB, gopts GlobalOptions, callback func(ctx context.Context, gopts GlobalOptions) error) (*bytes.Buffer, error) {
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
gopts.stdout = buf
|
err := withTermStatusRaw(os.Stdin, buf, &logOutputter{t: t}, gopts, callback)
|
||||||
err := inner(gopts)
|
|
||||||
return buf, err
|
return buf, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func withTermStatus(t testing.TB, gopts GlobalOptions, callback func(ctx context.Context, gopts GlobalOptions) error) error {
|
func withTermStatus(t testing.TB, gopts GlobalOptions, callback func(ctx context.Context, gopts GlobalOptions) error) error {
|
||||||
|
// stdout and stderr are written to by printer functions etc. That is the written data
|
||||||
|
// usually consists of one or multiple lines and therefore can be handled well
|
||||||
|
// by t.Log.
|
||||||
|
return withTermStatusRaw(os.Stdin, &logOutputter{t: t}, &logOutputter{t: t}, gopts, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
func withTermStatusRaw(stdin io.ReadCloser, stdout, stderr io.Writer, gopts GlobalOptions, callback func(ctx context.Context, gopts GlobalOptions) error) error {
|
||||||
ctx, cancel := context.WithCancel(context.TODO())
|
ctx, cancel := context.WithCancel(context.TODO())
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
term := termstatus.New(os.Stdin, gopts.stdout, &logOutputter{t: t}, gopts.Quiet)
|
term := termstatus.New(stdin, stdout, stderr, gopts.Quiet)
|
||||||
gopts.term = term
|
gopts.term = term
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
|||||||
@@ -173,13 +173,11 @@ func main() {
|
|||||||
version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
||||||
|
|
||||||
globalOptions := GlobalOptions{
|
globalOptions := GlobalOptions{
|
||||||
stdout: os.Stdout,
|
|
||||||
backends: collectBackends(),
|
backends: collectBackends(),
|
||||||
}
|
}
|
||||||
func() {
|
func() {
|
||||||
term, cancel := termstatus.Setup(os.Stdin, os.Stdout, os.Stderr, globalOptions.Quiet)
|
term, cancel := termstatus.Setup(os.Stdin, os.Stdout, os.Stderr, globalOptions.Quiet)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
globalOptions.stdout = termstatus.WrapStdout(term)
|
|
||||||
globalOptions.term = term
|
globalOptions.term = term
|
||||||
ctx := createGlobalContext(os.Stderr)
|
ctx := createGlobalContext(os.Stderr)
|
||||||
err = newRootCommand(&globalOptions).ExecuteContext(ctx)
|
err = newRootCommand(&globalOptions).ExecuteContext(ctx)
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ func (m *MockTerminal) ReadPassword(_ context.Context, _ string) (string, error)
|
|||||||
return "password", nil
|
return "password", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MockTerminal) OutputWriter() io.Writer {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MockTerminal) OutputRaw() io.Writer {
|
func (m *MockTerminal) OutputRaw() io.Writer {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,12 @@ type Terminal interface {
|
|||||||
SetStatus(lines []string)
|
SetStatus(lines []string)
|
||||||
// CanUpdateStatus returns true if the terminal can update the status lines.
|
// CanUpdateStatus returns true if the terminal can update the status lines.
|
||||||
CanUpdateStatus() bool
|
CanUpdateStatus() bool
|
||||||
|
|
||||||
InputRaw() io.ReadCloser
|
InputRaw() io.ReadCloser
|
||||||
InputIsTerminal() bool
|
InputIsTerminal() bool
|
||||||
ReadPassword(ctx context.Context, prompt string) (string, error)
|
ReadPassword(ctx context.Context, prompt string) (string, error)
|
||||||
|
|
||||||
|
OutputWriter() io.Writer
|
||||||
// OutputRaw returns the output writer. Should only be used if there is no
|
// OutputRaw returns the output writer. Should only be used if there is no
|
||||||
// other option. Must not be used in combination with Print, Error, SetStatus
|
// other option. Must not be used in combination with Print, Error, SetStatus
|
||||||
// or any other method that writes to the terminal.
|
// or any other method that writes to the terminal.
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ type Terminal struct {
|
|||||||
outputIsTerminal bool
|
outputIsTerminal bool
|
||||||
canUpdateStatus bool
|
canUpdateStatus bool
|
||||||
|
|
||||||
|
outputWriter io.WriteCloser
|
||||||
|
outputWriterOnce sync.Once
|
||||||
|
|
||||||
// will be closed when the goroutine which runs Run() terminates, so it'll
|
// will be closed when the goroutine which runs Run() terminates, so it'll
|
||||||
// yield a default value immediately
|
// yield a default value immediately
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
@@ -73,6 +76,9 @@ func Setup(stdin io.ReadCloser, stdout, stderr io.Writer, quiet bool) (*Terminal
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
return term, func() {
|
return term, func() {
|
||||||
|
if term.outputWriter != nil {
|
||||||
|
_ = term.outputWriter.Close()
|
||||||
|
}
|
||||||
// shutdown termstatus
|
// shutdown termstatus
|
||||||
cancel()
|
cancel()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@@ -158,6 +164,13 @@ func (t *Terminal) CanUpdateStatus() bool {
|
|||||||
return t.canUpdateStatus
|
return t.canUpdateStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Terminal) OutputWriter() io.Writer {
|
||||||
|
t.outputWriterOnce.Do(func() {
|
||||||
|
t.outputWriter = newLineWriter(t.Print)
|
||||||
|
})
|
||||||
|
return t.outputWriter
|
||||||
|
}
|
||||||
|
|
||||||
// OutputRaw returns the output writer. Should only be used if there is no
|
// OutputRaw returns the output writer. Should only be used if there is no
|
||||||
// other option. Must not be used in combination with Print, Error, SetStatus
|
// other option. Must not be used in combination with Print, Error, SetStatus
|
||||||
// or any other method that writes to the terminal.
|
// or any other method that writes to the terminal.
|
||||||
|
|||||||
@@ -6,12 +6,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WrapStdout returns line-buffering replacements for os.Stdout.
|
|
||||||
// On Close, the remaining bytes are written, followed by a line break.
|
|
||||||
func WrapStdout(term *Terminal) (stdout io.WriteCloser) {
|
|
||||||
return newLineWriter(term.Print)
|
|
||||||
}
|
|
||||||
|
|
||||||
type lineWriter struct {
|
type lineWriter struct {
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
buf bytes.Buffer
|
buf bytes.Buffer
|
||||||
|
|||||||
Reference in New Issue
Block a user