diff --git a/cmd/restic/cmd_backup.go b/cmd/restic/cmd_backup.go index 6b694a2bc..cbd2a6861 100644 --- a/cmd/restic/cmd_backup.go +++ b/cmd/restic/cmd_backup.go @@ -28,6 +28,7 @@ import ( "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/progress" "github.com/restic/restic/internal/ui/termstatus" ) @@ -161,11 +162,11 @@ var ErrInvalidSourceData = errors.New("at least one source file could not be rea // filterExisting returns a slice of all existing items, or an error if no // items exist at all. -func filterExisting(items []string) (result []string, err error) { +func filterExisting(items []string, printer progress.Printer) (result []string, err error) { for _, item := range items { _, err := fs.Lstat(item) if errors.Is(err, os.ErrNotExist) { - Warnf("%v does not exist, skipping\n", item) + printer.E("%v does not exist, skipping\n", item) continue } @@ -306,7 +307,7 @@ func (opts BackupOptions) Check(gopts GlobalOptions, args []string) error { // collectRejectByNameFuncs returns a list of all functions which may reject data // from being saved in a snapshot based on path only -func collectRejectByNameFuncs(opts BackupOptions, repo *repository.Repository) (fs []archiver.RejectByNameFunc, err error) { +func collectRejectByNameFuncs(opts BackupOptions, repo *repository.Repository, printer progress.Printer) (fs []archiver.RejectByNameFunc, err error) { // exclude restic cache if repo.Cache() != nil { f, err := rejectResticCache(repo) @@ -317,7 +318,7 @@ func collectRejectByNameFuncs(opts BackupOptions, repo *repository.Repository) ( fs = append(fs, f) } - fsPatterns, err := opts.ExcludePatternOptions.CollectPatterns(Warnf) + fsPatterns, err := opts.ExcludePatternOptions.CollectPatterns(printer.E) if err != nil { return nil, err } @@ -330,7 +331,7 @@ func collectRejectByNameFuncs(opts BackupOptions, repo *repository.Repository) ( // collectRejectFuncs returns a list of all functions which may reject data // from being saved in a snapshot based on path and file info -func collectRejectFuncs(opts BackupOptions, targets []string, fs fs.FS) (funcs []archiver.RejectFunc, err error) { +func collectRejectFuncs(opts BackupOptions, targets []string, fs fs.FS, printer progress.Printer) (funcs []archiver.RejectFunc, err error) { // allowed devices if opts.ExcludeOtherFS && !opts.Stdin && !opts.StdinCommand { f, err := archiver.RejectByDevice(targets, fs) @@ -357,7 +358,7 @@ func collectRejectFuncs(opts BackupOptions, targets []string, fs fs.FS) (funcs [ if runtime.GOOS != "windows" { return nil, errors.Fatalf("exclude-cloud-files is only supported on Windows") } - f, err := archiver.RejectCloudFiles(Warnf) + f, err := archiver.RejectCloudFiles(printer.E) if err != nil { return nil, err } @@ -369,7 +370,7 @@ func collectRejectFuncs(opts BackupOptions, targets []string, fs fs.FS) (funcs [ } for _, spec := range opts.ExcludeIfPresent { - f, err := archiver.RejectIfPresent(spec, Warnf) + f, err := archiver.RejectIfPresent(spec, printer.E) if err != nil { return nil, err } @@ -381,7 +382,7 @@ func collectRejectFuncs(opts BackupOptions, targets []string, fs fs.FS) (funcs [ } // collectTargets returns a list of target files/dirs from several sources. -func collectTargets(opts BackupOptions, args []string) (targets []string, err error) { +func collectTargets(opts BackupOptions, args []string, printer progress.Printer) (targets []string, err error) { if opts.Stdin || opts.StdinCommand { return nil, nil } @@ -405,7 +406,7 @@ func collectTargets(opts BackupOptions, args []string) (targets []string, err er return nil, fmt.Errorf("pattern: %s: %w", line, err) } if len(expanded) == 0 { - Warnf("pattern %q does not match any files, skipping\n", line) + printer.E("pattern %q does not match any files, skipping\n", line) } targets = append(targets, expanded...) } @@ -439,7 +440,7 @@ func collectTargets(opts BackupOptions, args []string) (targets []string, err er return nil, errors.Fatal("nothing to backup, please specify source files/dirs") } - targets, err = filterExisting(targets) + targets, err = filterExisting(targets, printer) if err != nil { return nil, err } @@ -493,7 +494,7 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter return err } - targets, err := collectTargets(opts, args) + targets, err := collectTargets(opts, args, msg) if err != nil { return err } @@ -528,7 +529,7 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter defer progressReporter.Done() // rejectByNameFuncs collect functions that can reject items from the backup based on path only - rejectByNameFuncs, err := collectRejectByNameFuncs(opts, repo) + rejectByNameFuncs, err := collectRejectByNameFuncs(opts, repo, msg) if err != nil { return err } @@ -607,7 +608,7 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter } // rejectFuncs collect functions that can reject items from the backup based on path and file info - rejectFuncs, err := collectRejectFuncs(opts, targets, targetFS) + rejectFuncs, err := collectRejectFuncs(opts, targets, targetFS, msg) if err != nil { return err } diff --git a/cmd/restic/cmd_backup_test.go b/cmd/restic/cmd_backup_test.go index 44e08ff96..41fddee6f 100644 --- a/cmd/restic/cmd_backup_test.go +++ b/cmd/restic/cmd_backup_test.go @@ -11,6 +11,7 @@ import ( "testing" rtest "github.com/restic/restic/internal/test" + "github.com/restic/restic/internal/ui/progress" ) func TestCollectTargets(t *testing.T) { @@ -67,7 +68,7 @@ func TestCollectTargets(t *testing.T) { FilesFromRaw: []string{f3.Name()}, } - targets, err := collectTargets(opts, []string{filepath.Join(dir, "cmdline arg")}) + targets, err := collectTargets(opts, []string{filepath.Join(dir, "cmdline arg")}, &progress.NoopPrinter{}) rtest.OK(t, err) sort.Strings(targets) rtest.Equals(t, expect, targets) diff --git a/cmd/restic/cmd_check.go b/cmd/restic/cmd_check.go index d659af67a..a251d96bf 100644 --- a/cmd/restic/cmd_check.go +++ b/cmd/restic/cmd_check.go @@ -194,7 +194,7 @@ func prepareCheckCache(opts CheckOptions, gopts *GlobalOptions, printer progress // use a cache in a temporary directory err := os.MkdirAll(cachedir, 0755) if err != nil { - Warnf("unable to create cache directory %s, disabling cache: %v\n", cachedir, err) + printer.E("unable to create cache directory %s, disabling cache: %v", cachedir, err) gopts.NoCache = true return cleanup } diff --git a/cmd/restic/cmd_copy.go b/cmd/restic/cmd_copy.go index a90170056..11b093657 100644 --- a/cmd/restic/cmd_copy.go +++ b/cmd/restic/cmd_copy.go @@ -115,7 +115,7 @@ func runCopy(ctx context.Context, opts CopyOptions, gopts GlobalOptions, args [] } dstSnapshotByOriginal := make(map[restic.ID][]*restic.Snapshot) - for sn := range FindFilteredSnapshots(ctx, dstSnapshotLister, dstRepo, &opts.SnapshotFilter, nil) { + for sn := range FindFilteredSnapshots(ctx, dstSnapshotLister, dstRepo, &opts.SnapshotFilter, nil, printer) { if sn.Original != nil && !sn.Original.IsNull() { dstSnapshotByOriginal[*sn.Original] = append(dstSnapshotByOriginal[*sn.Original], sn) } @@ -129,7 +129,7 @@ func runCopy(ctx context.Context, opts CopyOptions, gopts GlobalOptions, args [] // remember already processed trees across all snapshots visitedTrees := restic.NewIDSet() - for sn := range FindFilteredSnapshots(ctx, srcSnapshotLister, srcRepo, &opts.SnapshotFilter, args) { + for sn := range FindFilteredSnapshots(ctx, srcSnapshotLister, srcRepo, &opts.SnapshotFilter, args, printer) { // check whether the destination has a snapshot with the same persistent ID which has similar snapshot fields srcOriginal := *sn.ID() if sn.Original != nil { diff --git a/cmd/restic/cmd_find.go b/cmd/restic/cmd_find.go index 392696769..b97465e7d 100644 --- a/cmd/restic/cmd_find.go +++ b/cmd/restic/cmd_find.go @@ -658,7 +658,7 @@ func runFind(ctx context.Context, opts FindOptions, gopts GlobalOptions, args [] } var filteredSnapshots []*restic.Snapshot - for sn := range FindFilteredSnapshots(ctx, snapshotLister, repo, &opts.SnapshotFilter, opts.Snapshots) { + for sn := range FindFilteredSnapshots(ctx, snapshotLister, repo, &opts.SnapshotFilter, opts.Snapshots, printer) { filteredSnapshots = append(filteredSnapshots, sn) } if ctx.Err() != nil { diff --git a/cmd/restic/cmd_forget.go b/cmd/restic/cmd_forget.go index 7531bed70..b7f66278e 100644 --- a/cmd/restic/cmd_forget.go +++ b/cmd/restic/cmd_forget.go @@ -198,7 +198,7 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption var snapshots restic.Snapshots removeSnIDs := restic.NewIDSet() - for sn := range FindFilteredSnapshots(ctx, repo, repo, &opts.SnapshotFilter, args) { + for sn := range FindFilteredSnapshots(ctx, repo, repo, &opts.SnapshotFilter, args, printer) { snapshots = append(snapshots, sn) } if ctx.Err() != nil { diff --git a/cmd/restic/cmd_repair_packs.go b/cmd/restic/cmd_repair_packs.go index 01c652120..4c2177647 100644 --- a/cmd/restic/cmd_repair_packs.go +++ b/cmd/restic/cmd_repair_packs.go @@ -93,6 +93,6 @@ func runRepairPacks(ctx context.Context, gopts GlobalOptions, term *termstatus.T return errors.Fatalf("%s", err) } - Warnf("\nUse `restic repair snapshots --forget` to remove the corrupted data blobs from all snapshots\n") + printer.E("\nUse `restic repair snapshots --forget` to remove the corrupted data blobs from all snapshots") return nil } diff --git a/cmd/restic/cmd_repair_snapshots.go b/cmd/restic/cmd_repair_snapshots.go index b0b09673d..09c0bfa79 100644 --- a/cmd/restic/cmd_repair_snapshots.go +++ b/cmd/restic/cmd_repair_snapshots.go @@ -148,7 +148,7 @@ func runRepairSnapshots(ctx context.Context, gopts GlobalOptions, opts RepairOpt }) changedCount := 0 - for sn := range FindFilteredSnapshots(ctx, snapshotLister, repo, &opts.SnapshotFilter, args) { + for sn := range FindFilteredSnapshots(ctx, snapshotLister, repo, &opts.SnapshotFilter, args, printer) { printer.P("\n%v", sn) changed, err := filterAndReplaceSnapshot(ctx, repo, sn, func(ctx context.Context, sn *restic.Snapshot) (restic.ID, *restic.SnapshotSummary, error) { diff --git a/cmd/restic/cmd_restore.go b/cmd/restic/cmd_restore.go index d04b8a6b1..f28406be4 100644 --- a/cmd/restic/cmd_restore.go +++ b/cmd/restic/cmd_restore.go @@ -10,6 +10,7 @@ import ( "github.com/restic/restic/internal/filter" "github.com/restic/restic/internal/restic" "github.com/restic/restic/internal/restorer" + "github.com/restic/restic/internal/ui/progress" restoreui "github.com/restic/restic/internal/ui/restore" "github.com/restic/restic/internal/ui/termstatus" @@ -91,12 +92,12 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions, term *termstatus.Terminal, args []string) error { msg := newTerminalProgressPrinter(gopts.JSON, gopts.verbosity, term) - excludePatternFns, err := opts.ExcludePatternOptions.CollectPatterns(Warnf) + excludePatternFns, err := opts.ExcludePatternOptions.CollectPatterns(msg.E) if err != nil { return err } - includePatternFns, err := opts.IncludePatternOptions.CollectPatterns(Warnf) + includePatternFns, err := opts.IncludePatternOptions.CollectPatterns(msg.E) if err != nil { return err } @@ -233,7 +234,7 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions, res.SelectFilter = selectIncludeFilter } - res.XattrSelectFilter, err = getXattrSelectFilter(opts) + res.XattrSelectFilter, err = getXattrSelectFilter(opts, msg) if err != nil { return err } @@ -277,7 +278,7 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions, return nil } -func getXattrSelectFilter(opts RestoreOptions) (func(xattrName string) bool, error) { +func getXattrSelectFilter(opts RestoreOptions, printer progress.Printer) (func(xattrName string) bool, error) { hasXattrExcludes := len(opts.ExcludeXattrPattern) > 0 hasXattrIncludes := len(opts.IncludeXattrPattern) > 0 @@ -291,7 +292,7 @@ func getXattrSelectFilter(opts RestoreOptions) (func(xattrName string) bool, err } return func(xattrName string) bool { - shouldReject := filter.RejectByPattern(opts.ExcludeXattrPattern, Warnf)(xattrName) + shouldReject := filter.RejectByPattern(opts.ExcludeXattrPattern, printer.E)(xattrName) return !shouldReject }, nil } @@ -303,7 +304,7 @@ func getXattrSelectFilter(opts RestoreOptions) (func(xattrName string) bool, err } return func(xattrName string) bool { - shouldInclude, _ := filter.IncludeByPattern(opts.IncludeXattrPattern, Warnf)(xattrName) + shouldInclude, _ := filter.IncludeByPattern(opts.IncludeXattrPattern, printer.E)(xattrName) return shouldInclude }, nil } diff --git a/cmd/restic/cmd_rewrite.go b/cmd/restic/cmd_rewrite.go index 82f3e0ea9..0e06e4009 100644 --- a/cmd/restic/cmd_rewrite.go +++ b/cmd/restic/cmd_rewrite.go @@ -326,7 +326,7 @@ func runRewrite(ctx context.Context, opts RewriteOptions, gopts GlobalOptions, a } changedCount := 0 - for sn := range FindFilteredSnapshots(ctx, snapshotLister, repo, &opts.SnapshotFilter, args) { + for sn := range FindFilteredSnapshots(ctx, snapshotLister, repo, &opts.SnapshotFilter, args, printer) { printer.P("\n%v", sn) changed, err := rewriteSnapshot(ctx, repo, sn, opts, printer) if err != nil { diff --git a/cmd/restic/cmd_snapshots.go b/cmd/restic/cmd_snapshots.go index 29ab08e07..8cd663e06 100644 --- a/cmd/restic/cmd_snapshots.go +++ b/cmd/restic/cmd_snapshots.go @@ -78,7 +78,7 @@ func runSnapshots(ctx context.Context, opts SnapshotOptions, gopts GlobalOptions defer unlock() var snapshots restic.Snapshots - for sn := range FindFilteredSnapshots(ctx, repo, repo, &opts.SnapshotFilter, args) { + for sn := range FindFilteredSnapshots(ctx, repo, repo, &opts.SnapshotFilter, args, printer) { snapshots = append(snapshots, sn) } if ctx.Err() != nil { diff --git a/cmd/restic/cmd_stats.go b/cmd/restic/cmd_stats.go index 2b87384f0..411ac9e31 100644 --- a/cmd/restic/cmd_stats.go +++ b/cmd/restic/cmd_stats.go @@ -135,7 +135,7 @@ func runStats(ctx context.Context, opts StatsOptions, gopts GlobalOptions, args SnapshotsCount: 0, } - for sn := range FindFilteredSnapshots(ctx, snapshotLister, repo, &opts.SnapshotFilter, args) { + for sn := range FindFilteredSnapshots(ctx, snapshotLister, repo, &opts.SnapshotFilter, args, printer) { err = statsWalkSnapshot(ctx, sn, repo, opts, stats) if err != nil { return fmt.Errorf("error walking snapshot: %v", err) diff --git a/cmd/restic/cmd_tag.go b/cmd/restic/cmd_tag.go index dc5e33fa8..5d1f19a63 100644 --- a/cmd/restic/cmd_tag.go +++ b/cmd/restic/cmd_tag.go @@ -158,7 +158,7 @@ func runTag(ctx context.Context, opts TagOptions, gopts GlobalOptions, term *ter } } - for sn := range FindFilteredSnapshots(ctx, repo, repo, &opts.SnapshotFilter, args) { + for sn := range FindFilteredSnapshots(ctx, repo, repo, &opts.SnapshotFilter, args, printer) { changed, err := changeTags(ctx, repo, sn, opts.SetTags.Flatten(), opts.AddTags.Flatten(), opts.RemoveTags.Flatten(), printFunc) if err != nil { printer.E("unable to modify the tags for snapshot ID %q, ignoring: %v", sn.ID(), err) diff --git a/cmd/restic/find.go b/cmd/restic/find.go index faf7024e1..eab8b5d90 100644 --- a/cmd/restic/find.go +++ b/cmd/restic/find.go @@ -5,6 +5,7 @@ import ( "os" "github.com/restic/restic/internal/restic" + "github.com/restic/restic/internal/ui/progress" "github.com/spf13/pflag" ) @@ -39,19 +40,19 @@ func initSingleSnapshotFilter(flags *pflag.FlagSet, filt *restic.SnapshotFilter) } // FindFilteredSnapshots yields Snapshots, either given explicitly by `snapshotIDs` or filtered from the list of all snapshots. -func FindFilteredSnapshots(ctx context.Context, be restic.Lister, loader restic.LoaderUnpacked, f *restic.SnapshotFilter, snapshotIDs []string) <-chan *restic.Snapshot { +func FindFilteredSnapshots(ctx context.Context, be restic.Lister, loader restic.LoaderUnpacked, f *restic.SnapshotFilter, snapshotIDs []string, printer progress.Printer) <-chan *restic.Snapshot { out := make(chan *restic.Snapshot) go func() { defer close(out) be, err := restic.MemorizeList(ctx, be, restic.SnapshotFile) if err != nil { - Warnf("could not load snapshots: %v\n", err) + printer.E("could not load snapshots: %v", err) return } err = f.FindAll(ctx, be, loader, snapshotIDs, func(id string, sn *restic.Snapshot, err error) error { if err != nil { - Warnf("Ignoring %q: %v\n", id, err) + printer.E("Ignoring %q: %v", id, err) } else { select { case <-ctx.Done(): @@ -62,7 +63,7 @@ func FindFilteredSnapshots(ctx context.Context, be restic.Lister, loader restic. return nil }) if err != nil { - Warnf("could not load snapshots: %v\n", err) + printer.E("could not load snapshots: %v", err) } }() return out diff --git a/cmd/restic/integration_test.go b/cmd/restic/integration_test.go index 0525c7e29..3b2f53d38 100644 --- a/cmd/restic/integration_test.go +++ b/cmd/restic/integration_test.go @@ -174,7 +174,7 @@ func TestFindListOnce(t *testing.T) { secondSnapshot[0].String(), secondSnapshot[1].String()[:8], "latest", - }) { + }, printer) { snapshotIDs.Insert(*sn.ID()) }