restic: move Printer interface from internal/ui/progress

Move Printer and NewNoopPrinter to internal/restic so repository does
not have to import the ui packages.
This commit is contained in:
Michael Eischer
2026-06-14 10:50:42 +02:00
parent 0f4236cb39
commit d9d54a505e
44 changed files with 165 additions and 173 deletions
+3 -3
View File
@@ -179,7 +179,7 @@ func parsePercentage(s string) (float64, error) {
// - if the user explicitly requested --no-cache, we don't use any cache
// - if the user provides --cache-dir, we use a cache in a temporary sub-directory of the specified directory and the sub-directory is deleted after the check
// - by default, we use a cache in a temporary directory that is deleted after the check
func prepareCheckCache(opts CheckOptions, gopts *global.Options, printer progress.Printer) (cleanup func()) {
func prepareCheckCache(opts CheckOptions, gopts *global.Options, printer restic.Printer) (cleanup func()) {
cleanup = func() {}
if opts.WithCache {
// use the default cache, no setup needed
@@ -229,7 +229,7 @@ func prepareCheckCache(opts CheckOptions, gopts *global.Options, printer progres
func runCheck(ctx context.Context, opts CheckOptions, gopts global.Options, args []string, term ui.Terminal) (checkSummary, error) {
summary := checkSummary{MessageType: "summary"}
var printer progress.Printer
var printer restic.Printer
if !gopts.JSON {
printer = progress.NewTerminalPrinter(gopts.JSON, gopts.Verbosity, term)
} else {
@@ -428,7 +428,7 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts global.Options, args
return summary, nil
}
func buildPacksFilter(opts CheckOptions, printer progress.Printer,
func buildPacksFilter(opts CheckOptions, printer restic.Printer,
filteredStatus bool) (func(packs map[restic.ID]int64) map[restic.ID]int64, error) {
typeData := ""
if filteredStatus {
+2 -3
View File
@@ -12,7 +12,6 @@ import (
"github.com/restic/restic/internal/global"
"github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui/progress"
)
func TestParsePercentage(t *testing.T) {
@@ -204,7 +203,7 @@ func TestPrepareCheckCache(t *testing.T) {
rtest.OK(t, err)
}
gopts := global.Options{CacheDir: tmpDirBase}
cleanup := prepareCheckCache(testCase.opts, &gopts, progress.NewNoopPrinter())
cleanup := prepareCheckCache(testCase.opts, &gopts, restic.NewNoopPrinter())
files, err := os.ReadDir(tmpDirBase)
rtest.OK(t, err)
@@ -234,7 +233,7 @@ func TestPrepareCheckCache(t *testing.T) {
func TestPrepareDefaultCheckCache(t *testing.T) {
gopts := global.Options{CacheDir: ""}
cleanup := prepareCheckCache(CheckOptions{}, &gopts, progress.NewNoopPrinter())
cleanup := prepareCheckCache(CheckOptions{}, &gopts, restic.NewNoopPrinter())
_, err := os.ReadDir(gopts.CacheDir)
rtest.OK(t, err)
+5 -5
View File
@@ -75,7 +75,7 @@ func (opts *CopyOptions) AddFlags(f *pflag.FlagSet) {
// collectAllSnapshots: select all snapshot trees to be copied
func collectAllSnapshots(ctx context.Context, opts CopyOptions,
srcSnapshotLister restic.Lister, srcRepo restic.Repository,
dstSnapshotByOriginal map[restic.ID][]*data.Snapshot, args []string, printer progress.Printer,
dstSnapshotByOriginal map[restic.ID][]*data.Snapshot, args []string, printer restic.Printer,
) iter.Seq[*data.Snapshot] {
return func(yield func(*data.Snapshot) bool) {
for sn := range FindFilteredSnapshots(ctx, srcSnapshotLister, srcRepo, &opts.SnapshotFilter, args, printer) {
@@ -190,7 +190,7 @@ func similarSnapshots(sna *data.Snapshot, snb *data.Snapshot) bool {
// copyTreeBatched copies multiple snapshots in one go. Snapshots are written after
// data equivalent to at least 10 packfiles was written.
func copyTreeBatched(ctx context.Context, srcRepo *repository.Repository, dstRepo restic.Repository,
selectedSnapshots iter.Seq[*data.Snapshot], printer progress.Printer) error {
selectedSnapshots iter.Seq[*data.Snapshot], printer restic.Printer) error {
// remember already processed trees across all snapshots
visitedTrees := srcRepo.NewAssociatedBlobSet()
@@ -255,7 +255,7 @@ func copyTreeBatched(ctx context.Context, srcRepo *repository.Repository, dstRep
}
func copyTree(ctx context.Context, srcRepo *repository.Repository, dstRepo restic.Repository,
visitedTrees restic.AssociatedBlobSet, rootTreeID restic.ID, printer progress.Printer, uploader restic.BlobSaverWithAsync) (uint64, error) {
visitedTrees restic.AssociatedBlobSet, rootTreeID restic.ID, printer restic.Printer, uploader restic.BlobSaverWithAsync) (uint64, error) {
copyBlobs := srcRepo.NewAssociatedBlobSet()
packList := restic.NewIDSet()
@@ -312,7 +312,7 @@ func copyTree(ctx context.Context, srcRepo *repository.Repository, dstRepo resti
}
// copyStats: print statistics for the blobs to be copied
func copyStats(srcRepo restic.Repository, copyBlobs restic.AssociatedBlobSet, packList restic.IDSet, printer progress.Printer) uint64 {
func copyStats(srcRepo restic.Repository, copyBlobs restic.AssociatedBlobSet, packList restic.IDSet, printer restic.Printer) uint64 {
// count and size
countBlobs := 0
sizeBlobs := uint64(0)
@@ -329,7 +329,7 @@ func copyStats(srcRepo restic.Repository, copyBlobs restic.AssociatedBlobSet, pa
return sizeBlobs
}
func copySaveSnapshot(ctx context.Context, sn *data.Snapshot, dstRepo restic.Repository, printer progress.Printer) error {
func copySaveSnapshot(ctx context.Context, sn *data.Snapshot, dstRepo restic.Repository, printer restic.Printer) error {
sn.Parent = nil // Parent does not have relevance in the new repo.
// Use Original as a persistent snapshot ID
if sn.Original == nil {
+3 -2
View File
@@ -7,6 +7,7 @@ import (
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/global"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui"
"github.com/restic/restic/internal/ui/progress"
"github.com/spf13/cobra"
@@ -55,7 +56,7 @@ func (opts *generateOptions) AddFlags(f *pflag.FlagSet) {
f.StringVar(&opts.PowerShellCompletionFile, "powershell-completion", "", "write powershell completion `file` (`-` for stdout)")
}
func writeManpages(root *cobra.Command, dir string, printer progress.Printer) error {
func writeManpages(root *cobra.Command, dir string, printer restic.Printer) error {
// use a fixed date for the man pages so that generating them is deterministic
date, err := time.Parse("Jan 2006", "Jan 2017")
if err != nil {
@@ -73,7 +74,7 @@ func writeManpages(root *cobra.Command, dir string, printer progress.Printer) er
return doc.GenManTree(root, header, dir)
}
func writeCompletion(filename string, shell string, generate func(w io.Writer) error, printer progress.Printer, gopts global.Options) (err error) {
func writeCompletion(filename string, shell string, generate func(w io.Writer) error, printer restic.Printer, gopts global.Options) (err error) {
printer.PT("writing %s completion file to %v", shell, filename)
var outWriter io.Writer
if filename != "-" {
+1 -1
View File
@@ -108,7 +108,7 @@ func runInit(ctx context.Context, opts InitOptions, gopts global.Options, args [
return nil
}
func maybeReadChunkerPolynomial(ctx context.Context, opts InitOptions, gopts global.Options, printer progress.Printer) (*chunker.Pol, error) {
func maybeReadChunkerPolynomial(ctx context.Context, opts InitOptions, gopts global.Options, printer restic.Printer) (*chunker.Pol, error) {
if opts.CopyChunkerParameters {
otherGopts, _, err := opts.SecondaryRepoOptions.FillGlobalOpts(ctx, gopts, "secondary")
if err != nil {
+2 -3
View File
@@ -10,7 +10,6 @@ import (
"github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui/progress"
)
func testRunInit(t testing.TB, gopts global.Options) {
@@ -57,14 +56,14 @@ func TestInitCopyChunkerParams(t *testing.T) {
var repo *repository.Repository
err = withTermStatus(t, env.gopts, func(ctx context.Context, gopts global.Options) error {
repo, err = global.OpenRepository(ctx, gopts, progress.NewNoopPrinter())
repo, err = global.OpenRepository(ctx, gopts, restic.NewNoopPrinter())
return err
})
rtest.OK(t, err)
var otherRepo *repository.Repository
err = withTermStatus(t, env2.gopts, func(ctx context.Context, gopts global.Options) error {
otherRepo, err = global.OpenRepository(ctx, gopts, progress.NewNoopPrinter())
otherRepo, err = global.OpenRepository(ctx, gopts, restic.NewNoopPrinter())
return err
})
rtest.OK(t, err)
+2 -1
View File
@@ -7,6 +7,7 @@ import (
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/global"
"github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui"
"github.com/restic/restic/internal/ui/progress"
"github.com/spf13/cobra"
@@ -70,7 +71,7 @@ func runKeyAdd(ctx context.Context, gopts global.Options, opts KeyAddOptions, ar
return addKey(ctx, repo, gopts, opts, printer)
}
func addKey(ctx context.Context, repo *repository.Repository, gopts global.Options, opts KeyAddOptions, printer progress.Printer) error {
func addKey(ctx context.Context, repo *repository.Repository, gopts global.Options, opts KeyAddOptions, printer restic.Printer) error {
pw, err := getNewPassword(ctx, gopts, opts.NewPasswordFile, opts.InsecureNoPassword)
if err != nil {
return err
+3 -3
View File
@@ -3,6 +3,7 @@ package main
import (
"bufio"
"context"
"github.com/restic/restic/internal/restic"
"os"
"path/filepath"
"regexp"
@@ -13,7 +14,6 @@ import (
"github.com/restic/restic/internal/global"
"github.com/restic/restic/internal/repository"
rtest "github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui/progress"
)
func testRunKeyListOtherIDs(t testing.TB, gopts global.Options) []string {
@@ -63,7 +63,7 @@ func testRunKeyAddNewKeyUserHost(t testing.TB, gopts global.Options) {
rtest.OK(t, err)
_ = withTermStatus(t, gopts, func(ctx context.Context, gopts global.Options) error {
repo, err := global.OpenRepository(ctx, gopts, progress.NewNoopPrinter())
repo, err := global.OpenRepository(ctx, gopts, restic.NewNoopPrinter())
rtest.OK(t, err)
err = repo.SearchKey(ctx, testKeyNewPassword, 2, "")
rtest.OK(t, err)
@@ -107,7 +107,7 @@ func testRunKeyPasswdUserHost(t testing.TB, newPassword string, gopts global.Opt
gopts.Password = testKeyNewPassword
_ = withTermStatus(t, gopts, func(ctx context.Context, gopts global.Options) error {
repo, err := global.OpenRepository(ctx, gopts, progress.NewNoopPrinter())
repo, err := global.OpenRepository(ctx, gopts, restic.NewNoopPrinter())
rtest.OK(t, err)
err = repo.SearchKey(ctx, testKeyNewPassword, 1, "")
rtest.OK(t, err)
+1 -1
View File
@@ -56,7 +56,7 @@ func runKeyList(ctx context.Context, gopts global.Options, args []string, term u
return listKeys(ctx, repo, gopts, printer)
}
func listKeys(ctx context.Context, s *repository.Repository, gopts global.Options, printer progress.Printer) error {
func listKeys(ctx context.Context, s *repository.Repository, gopts global.Options, printer restic.Printer) error {
type keyInfo struct {
Current bool `json:"current"`
ID string `json:"id"`
+2 -1
View File
@@ -7,6 +7,7 @@ import (
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/global"
"github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui"
"github.com/restic/restic/internal/ui/progress"
"github.com/spf13/cobra"
@@ -65,7 +66,7 @@ func runKeyPasswd(ctx context.Context, gopts global.Options, opts KeyPasswdOptio
return changePassword(ctx, repo, gopts, opts, printer)
}
func changePassword(ctx context.Context, repo *repository.Repository, gopts global.Options, opts KeyPasswdOptions, printer progress.Printer) error {
func changePassword(ctx context.Context, repo *repository.Repository, gopts global.Options, opts KeyPasswdOptions, printer restic.Printer) error {
pw, err := getNewPassword(ctx, gopts, opts.NewPasswordFile, opts.InsecureNoPassword)
if err != nil {
return err
+1 -1
View File
@@ -53,7 +53,7 @@ func runKeyRemove(ctx context.Context, gopts global.Options, args []string, term
return deleteKey(ctx, repo, args[0], printer)
}
func deleteKey(ctx context.Context, repo *repository.Repository, idPrefix string, printer progress.Printer) error {
func deleteKey(ctx context.Context, repo *repository.Repository, idPrefix string, printer restic.Printer) error {
id, err := restic.Find(ctx, repo, restic.KeyFile, idPrefix)
if err != nil {
return err
+1 -1
View File
@@ -96,7 +96,7 @@ func runList(ctx context.Context, gopts global.Options, args []string, term ui.T
// packfileList handles the list packs <snapshotID> variant.
// It prints a sorted list of packfiles belonging to this snapshot.
func packfileList(ctx context.Context, repo restic.Repository, snapshotID string, printer progress.Printer) error {
func packfileList(ctx context.Context, repo restic.Repository, snapshotID string, printer restic.Printer) error {
sn, _, err := (&data.SnapshotFilter{}).FindLatest(ctx, repo, repo, snapshotID)
if err != nil {
return fmt.Errorf("required snapshot ID %q not found", snapshotID)
+2 -2
View File
@@ -53,7 +53,7 @@ func (opts *MigrateOptions) AddFlags(f *pflag.FlagSet) {
f.BoolVarP(&opts.Force, "force", "f", false, `apply a migration a second time`)
}
func checkMigrations(ctx context.Context, repo restic.Repository, printer progress.Printer) error {
func checkMigrations(ctx context.Context, repo restic.Repository, printer restic.Printer) error {
printer.P("available migrations:\n")
found := false
@@ -76,7 +76,7 @@ func checkMigrations(ctx context.Context, repo restic.Repository, printer progre
return nil
}
func applyMigrations(ctx context.Context, opts MigrateOptions, gopts global.Options, repo restic.Repository, args []string, term ui.Terminal, printer progress.Printer) error {
func applyMigrations(ctx context.Context, opts MigrateOptions, gopts global.Options, repo restic.Repository, args []string, term ui.Terminal, printer restic.Printer) error {
var firsterr error
for _, name := range args {
found := false
+3 -3
View File
@@ -193,7 +193,7 @@ func runPrune(ctx context.Context, opts PruneOptions, gopts global.Options, term
return runPruneWithRepo(ctx, opts, gopts, repo, restic.NewIDSet(), printer)
}
func runPruneWithRepo(ctx context.Context, opts PruneOptions, gopts global.Options, repo *repository.Repository, ignoreSnapshots restic.IDSet, printer progress.Printer) error {
func runPruneWithRepo(ctx context.Context, opts PruneOptions, gopts global.Options, repo *repository.Repository, ignoreSnapshots restic.IDSet, printer restic.Printer) error {
if repo.Cache() == nil && !gopts.JSON {
printer.S("warning: running prune without a cache, this may be very slow!")
}
@@ -246,7 +246,7 @@ func runPruneWithRepo(ctx context.Context, opts PruneOptions, gopts global.Optio
}
// printPruneStats prints out the statistics
func printPruneStats(printer progress.Printer, stats repository.PruneStats) error {
func printPruneStats(printer restic.Printer, stats repository.PruneStats) error {
printer.V("\nused: %10d blobs / %s", stats.Blobs.Used, ui.FormatBytes(stats.Size.Used))
if stats.Blobs.Duplicate > 0 {
printer.V("duplicates: %10d blobs / %s", stats.Blobs.Duplicate, ui.FormatBytes(stats.Size.Duplicate))
@@ -282,7 +282,7 @@ func printPruneStats(printer progress.Printer, stats repository.PruneStats) erro
return nil
}
func getUsedBlobs(ctx context.Context, repo restic.Repository, usedBlobs restic.FindBlobSet, ignoreSnapshots restic.IDSet, printer progress.Printer) error {
func getUsedBlobs(ctx context.Context, repo restic.Repository, usedBlobs restic.FindBlobSet, ignoreSnapshots restic.IDSet, printer restic.Printer) error {
var snapshotTrees restic.IDs
printer.P("loading all snapshots...")
err := data.ForAllSnapshots(ctx, repo, repo, ignoreSnapshots,
+1 -1
View File
@@ -174,7 +174,7 @@ func runRecover(ctx context.Context, gopts global.Options, term ui.Terminal) err
}
func createSnapshot(ctx context.Context, printer progress.Printer, name, hostname string, tags []string, repo restic.SaverUnpacked[restic.WriteableFileType], tree *restic.ID) error {
func createSnapshot(ctx context.Context, printer restic.Printer, name, hostname string, tags []string, repo restic.SaverUnpacked[restic.WriteableFileType], tree *restic.ID) error {
sn, err := data.NewSnapshot([]string{name}, tags, hostname, time.Now())
if err != nil {
return errors.Fatalf("unable to save snapshot: %v", err)
+2 -2
View File
@@ -11,9 +11,9 @@ import (
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/filter"
"github.com/restic/restic/internal/global"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/restorer"
"github.com/restic/restic/internal/ui"
"github.com/restic/restic/internal/ui/progress"
restoreui "github.com/restic/restic/internal/ui/restore"
"github.com/spf13/cobra"
@@ -281,7 +281,7 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts global.Options,
return nil
}
func getXattrSelectFilter(opts RestoreOptions, printer progress.Printer) (func(xattrName string) bool, error) {
func getXattrSelectFilter(opts RestoreOptions, printer restic.Printer) (func(xattrName string) bool, error) {
hasXattrExcludes := len(opts.ExcludeXattrPattern) > 0
hasXattrIncludes := len(opts.IncludeXattrPattern) > 0
+4 -4
View File
@@ -129,7 +129,7 @@ func (opts *RewriteOptions) AddFlags(f *pflag.FlagSet) {
// be updated accordingly.
type rewriteFilterFunc func(ctx context.Context, sn *data.Snapshot, uploader restic.BlobSaver) (restic.ID, *data.SnapshotSummary, error)
func rewriteSnapshot(ctx context.Context, repo *repository.Repository, sn *data.Snapshot, opts RewriteOptions, printer progress.Printer) (bool, error) {
func rewriteSnapshot(ctx context.Context, repo *repository.Repository, sn *data.Snapshot, opts RewriteOptions, printer restic.Printer) (bool, error) {
if sn.Tree == nil {
return false, errors.Errorf("snapshot %v has nil tree", sn.ID().Str())
}
@@ -191,7 +191,7 @@ func rewriteSnapshot(ctx context.Context, repo *repository.Repository, sn *data.
}
func filterAndReplaceSnapshot(ctx context.Context, repo restic.Repository, sn *data.Snapshot,
filter rewriteFilterFunc, dryRun bool, forget bool, newMetadata *snapshotMetadata, addTag string, printer progress.Printer,
filter rewriteFilterFunc, dryRun bool, forget bool, newMetadata *snapshotMetadata, addTag string, printer restic.Printer,
keepEmptySnapshot bool) (bool, error) {
var filteredTree restic.ID
@@ -359,7 +359,7 @@ func runRewrite(ctx context.Context, opts RewriteOptions, gopts global.Options,
return nil
}
func gatherIncludeFilters(includeByNameFuncs []filter.IncludeByNameFunc, printer progress.Printer) (rewriteNode walker.NodeRewriteFunc, keepEmptyDirectory walker.NodeKeepEmptyDirectoryFunc) {
func gatherIncludeFilters(includeByNameFuncs []filter.IncludeByNameFunc, printer restic.Printer) (rewriteNode walker.NodeRewriteFunc, keepEmptyDirectory walker.NodeKeepEmptyDirectoryFunc) {
inSelectByName := func(nodepath string, node *data.Node) bool {
for _, include := range includeByNameFuncs {
matched, childMayMatch := include(nodepath)
@@ -406,7 +406,7 @@ func gatherIncludeFilters(includeByNameFuncs []filter.IncludeByNameFunc, printer
return rewriteNode, keepEmptyDirectory
}
func gatherExcludeFilters(excludeByNameFuncs []filter.RejectByNameFunc, printer progress.Printer) (rewriteNode walker.NodeRewriteFunc) {
func gatherExcludeFilters(excludeByNameFuncs []filter.RejectByNameFunc, printer restic.Printer) (rewriteNode walker.NodeRewriteFunc) {
exSelectByName := func(nodepath string) bool {
for _, reject := range excludeByNameFuncs {
if reject(nodepath) {
+1 -1
View File
@@ -376,7 +376,7 @@ const (
countModeDebug = "debug"
)
func statsDebug(ctx context.Context, repo restic.Repository, printer progress.Printer) error {
func statsDebug(ctx context.Context, repo restic.Repository, printer restic.Printer) error {
printer.E("Collecting size statistics\n\n")
for _, t := range []restic.FileType{restic.KeyFile, restic.LockFile, restic.IndexFile, restic.SnapshotFile, restic.PackFile} {
hist, err := statsDebugFileType(ctx, repo, t)
+1 -2
View File
@@ -6,7 +6,6 @@ import (
"github.com/restic/restic/internal/data"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui/progress"
"github.com/spf13/pflag"
)
@@ -49,7 +48,7 @@ func finalizeSnapshotFilter(filt *data.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 *data.SnapshotFilter, snapshotIDs []string, printer progress.Printer) <-chan *data.Snapshot {
func FindFilteredSnapshots(ctx context.Context, be restic.Lister, loader restic.LoaderUnpacked, f *data.SnapshotFilter, snapshotIDs []string, printer restic.Printer) <-chan *data.Snapshot {
out := make(chan *data.Snapshot)
go func() {
defer close(out)
+5 -5
View File
@@ -5,10 +5,10 @@ import (
"github.com/restic/restic/internal/global"
"github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/ui/progress"
"github.com/restic/restic/internal/restic"
)
func internalOpenWithLocked(ctx context.Context, gopts global.Options, dryRun bool, exclusive bool, printer progress.Printer) (context.Context, *repository.Repository, func(), error) {
func internalOpenWithLocked(ctx context.Context, gopts global.Options, dryRun bool, exclusive bool, printer restic.Printer) (context.Context, *repository.Repository, func(), error) {
repo, err := global.OpenRepository(ctx, gopts, printer)
if err != nil {
return nil, nil, nil, err
@@ -31,18 +31,18 @@ func internalOpenWithLocked(ctx context.Context, gopts global.Options, dryRun bo
return ctx, repo, unlock, nil
}
func openWithReadLock(ctx context.Context, gopts global.Options, noLock bool, printer progress.Printer) (context.Context, *repository.Repository, func(), error) {
func openWithReadLock(ctx context.Context, gopts global.Options, noLock bool, printer restic.Printer) (context.Context, *repository.Repository, func(), error) {
// TODO enforce read-only operations once the locking code has moved to the repository
// As in-depth hardening, put the repository into read-only mode if noLock is true
// Not possible if the repository has to be locked.
return internalOpenWithLocked(ctx, gopts, noLock, false, printer)
}
func openWithAppendLock(ctx context.Context, gopts global.Options, dryRun bool, printer progress.Printer) (context.Context, *repository.Repository, func(), error) {
func openWithAppendLock(ctx context.Context, gopts global.Options, dryRun bool, printer restic.Printer) (context.Context, *repository.Repository, func(), error) {
// TODO enforce non-exclusive operations once the locking code has moved to the repository
return internalOpenWithLocked(ctx, gopts, dryRun, false, printer)
}
func openWithExclusiveLock(ctx context.Context, gopts global.Options, dryRun bool, printer progress.Printer) (context.Context, *repository.Repository, func(), error) {
func openWithExclusiveLock(ctx context.Context, gopts global.Options, dryRun bool, printer restic.Printer) (context.Context, *repository.Repository, func(), error) {
return internalOpenWithLocked(ctx, gopts, dryRun, true, printer)
}
+2 -1
View File
@@ -184,7 +184,8 @@ default backup, to be found at ``cmd/restic/testdata/backup-data.tar.gz``.
In this compressed archive you will find files, hardlinked files,
symlinked files, an empty directory and a simple directory structure which is good for testing purposes.
Commands that require a ``progress.Printer`` should either be wrapped in ``withTermStatus`` or ``withCaptureStdout``.
Commands that require a ``restic.Printer`` should either be wrapped in ``withTermStatus`` or ``withCaptureStdout``.
The interface is defined in ``internal/restic``; ``progress.NewTerminalPrinter`` returns a ``restic.Printer``.
If you want to analyze JSON output, you use ``withCaptureStdout()``.
It returns the generated output in a ``*bytes.Buffer``.
JSON output can be unmarshalled to produce the appropriate go structures; see
+8 -9
View File
@@ -25,7 +25,6 @@ import (
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/textfile"
"github.com/restic/restic/internal/ui"
"github.com/restic/restic/internal/ui/progress"
"github.com/spf13/pflag"
"github.com/restic/restic/internal/errors"
@@ -298,7 +297,7 @@ func readRepo(gopts Options) (string, error) {
const maxKeys = 20
// OpenRepository reads the password and opens the repository.
func OpenRepository(ctx context.Context, gopts Options, printer progress.Printer) (*repository.Repository, error) {
func OpenRepository(ctx context.Context, gopts Options, printer restic.Printer) (*repository.Repository, error) {
repo, err := readRepo(gopts)
if err != nil {
return nil, err
@@ -369,7 +368,7 @@ func createRepositoryInstance(be backend.Backend, gopts Options) (*repository.Re
}
// decryptRepository handles password reading and decrypts the repository.
func decryptRepository(ctx context.Context, s *repository.Repository, gopts *Options, printer progress.Printer) error {
func decryptRepository(ctx context.Context, s *repository.Repository, gopts *Options, printer restic.Printer) error {
passwordTriesLeft := 1
if gopts.Term.InputIsTerminal() && gopts.Password == "" && !gopts.InsecureNoPassword {
passwordTriesLeft = 3
@@ -406,7 +405,7 @@ func decryptRepository(ctx context.Context, s *repository.Repository, gopts *Opt
}
// printRepositoryInfo displays the repository ID, version and compression level.
func printRepositoryInfo(s *repository.Repository, gopts Options, printer progress.Printer) {
func printRepositoryInfo(s *repository.Repository, gopts Options, printer restic.Printer) {
id := s.Config().ID
if len(id) > 8 {
id = id[:8]
@@ -419,7 +418,7 @@ func printRepositoryInfo(s *repository.Repository, gopts Options, printer progre
}
// setupCache creates a new cache and removes old cache directories if instructed to do so.
func setupCache(s *repository.Repository, gopts Options, printer progress.Printer) error {
func setupCache(s *repository.Repository, gopts Options, printer restic.Printer) error {
c, err := cache.New(s.Config().ID, gopts.CacheDir)
if err != nil {
printer.E("unable to open cache: %v", err)
@@ -461,7 +460,7 @@ func setupCache(s *repository.Repository, gopts Options, printer progress.Printe
}
// CreateRepository a repository with the given version and chunker polynomial.
func CreateRepository(ctx context.Context, gopts Options, version uint, chunkerPolynomial *chunker.Pol, printer progress.Printer) (*repository.Repository, error) {
func CreateRepository(ctx context.Context, gopts Options, version uint, chunkerPolynomial *chunker.Pol, printer restic.Printer) (*repository.Repository, error) {
if version < restic.MinRepoVersion || version > restic.MaxRepoVersion {
return nil, errors.Fatalf("only repository versions between %v and %v are allowed", restic.MinRepoVersion, restic.MaxRepoVersion)
}
@@ -496,7 +495,7 @@ func CreateRepository(ctx context.Context, gopts Options, version uint, chunkerP
return s, nil
}
func innerOpenBackend(ctx context.Context, s string, gopts Options, opts options.Options, create bool, printer progress.Printer) (backend.Backend, error) {
func innerOpenBackend(ctx context.Context, s string, gopts Options, opts options.Options, create bool, printer restic.Printer) (backend.Backend, error) {
debug.Log("parsing location %v", location.StripPassword(gopts.Backends, s))
scheme, cfg, err := parseConfig(gopts.Backends, s, opts)
@@ -559,7 +558,7 @@ func setupTransport(gopts Options) (http.RoundTripper, limiter.Limiter, error) {
}
// createOrOpenBackend creates or opens a backend using the appropriate factory method.
func createOrOpenBackend(ctx context.Context, scheme string, cfg interface{}, rt http.RoundTripper, lim limiter.Limiter, gopts Options, s string, create bool, printer progress.Printer) (backend.Backend, error) {
func createOrOpenBackend(ctx context.Context, scheme string, cfg interface{}, rt http.RoundTripper, lim limiter.Limiter, gopts Options, s string, create bool, printer restic.Printer) (backend.Backend, error) {
factory := gopts.Backends.Lookup(scheme)
if factory == nil {
return nil, errors.Fatalf("invalid backend: %q", scheme)
@@ -589,7 +588,7 @@ func createOrOpenBackend(ctx context.Context, scheme string, cfg interface{}, rt
}
// wrapBackend applies debug logging, test hooks, and retry wrapper to the backend.
func wrapBackend(be backend.Backend, gopts Options, printer progress.Printer) (backend.Backend, error) {
func wrapBackend(be backend.Backend, gopts Options, printer restic.Printer) (backend.Backend, error) {
// wrap with debug logging and connection limiting
be = logger.New(sema.NewBackend(be))
+7 -8
View File
@@ -21,7 +21,6 @@ import (
"github.com/restic/restic/internal/repository/index"
"github.com/restic/restic/internal/repository/pack"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui/progress"
)
type packDumpEntry struct {
@@ -46,7 +45,7 @@ func writePackDumpJSON(wr io.Writer, item any) error {
}
// DumpPacks lists each pack file and writes its header blob layout as JSON to wr.
func DumpPacks(ctx context.Context, repo *Repository, wr io.Writer, printer progress.Printer) error {
func DumpPacks(ctx context.Context, repo *Repository, wr io.Writer, printer restic.Printer) error {
var m sync.Mutex
return restic.ParallelList(ctx, repo, restic.PackFile, repo.Connections(), func(ctx context.Context, id restic.ID, size int64) error {
blobs, err := repo.listPack(ctx, id, size)
@@ -75,7 +74,7 @@ func DumpPacks(ctx context.Context, repo *Repository, wr io.Writer, printer prog
}
// DumpIndexes loads each on-disk index file and writes its debug dump to wr.
func DumpIndexes(ctx context.Context, repo restic.ListerLoaderUnpacked, wr io.Writer, printer progress.Printer) error {
func DumpIndexes(ctx context.Context, repo restic.ListerLoaderUnpacked, wr io.Writer, printer restic.Printer) error {
return index.ForAllIndexes(ctx, repo, repo, func(id restic.ID, idx *index.Index, err error) error {
printer.S("index_id: %v", id)
if err != nil {
@@ -95,7 +94,7 @@ type ExaminePackOptions struct {
}
// ExaminePack loads and inspects a pack file and its index entries.
func ExaminePack(ctx context.Context, repo *Repository, id restic.ID, opts ExaminePackOptions, printer progress.Printer) error {
func ExaminePack(ctx context.Context, repo *Repository, id restic.ID, opts ExaminePackOptions, printer restic.Printer) error {
printer.S("examine %v", id)
buf, err := repo.LoadRaw(ctx, restic.PackFile, id)
@@ -146,7 +145,7 @@ func ExaminePack(ctx context.Context, repo *Repository, id restic.ID, opts Exami
return nil
}
func checkPackSize(blobs pack.Blobs, fileSize int, printer progress.Printer) {
func checkPackSize(blobs pack.Blobs, fileSize int, printer restic.Printer) {
// track current size and offset
var size, offset uint64
@@ -169,7 +168,7 @@ func checkPackSize(blobs pack.Blobs, fileSize int, printer progress.Printer) {
}
}
func tryRepairWithBitflip(key *crypto.Key, input []byte, bytewise bool, printer progress.Printer) []byte {
func tryRepairWithBitflip(key *crypto.Key, input []byte, bytewise bool, printer restic.Printer) []byte {
if bytewise {
printer.S(" trying to repair blob by finding a broken byte")
} else {
@@ -284,7 +283,7 @@ func decryptUnsigned(k *crypto.Key, buf []byte) []byte {
return out
}
func loadBlobs(ctx context.Context, opts ExaminePackOptions, repo *Repository, packID restic.ID, list pack.Blobs, printer progress.Printer) error {
func loadBlobs(ctx context.Context, opts ExaminePackOptions, repo *Repository, packID restic.ID, list pack.Blobs, printer restic.Printer) error {
dec, err := zstd.NewReader(nil)
if err != nil {
panic(err)
@@ -366,7 +365,7 @@ func loadBlobs(ctx context.Context, opts ExaminePackOptions, repo *Repository, p
return err
}
func storePlainBlob(id restic.ID, prefix string, plain []byte, printer progress.Printer) error {
func storePlainBlob(id restic.ID, prefix string, plain []byte, printer restic.Printer) error {
filename := fmt.Sprintf("%s%s.bin", prefix, id)
f, err := os.Create(filename)
if err != nil {
+5 -6
View File
@@ -13,7 +13,6 @@ import (
"github.com/restic/restic/internal/repository/index"
"github.com/restic/restic/internal/repository/pack"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui/progress"
)
var ErrIndexIncomplete = errors.Fatal("index is not complete")
@@ -104,7 +103,7 @@ type packInfoWithID struct {
// PlanPrune selects which files to rewrite and which to delete and which blobs to keep.
// Also some summary statistics are returned.
func PlanPrune(ctx context.Context, opts PruneOptions, repo *Repository, getUsedBlobs func(ctx context.Context, repo restic.Repository, usedBlobs restic.FindBlobSet) error, printer progress.Printer) (*PrunePlan, error) {
func PlanPrune(ctx context.Context, opts PruneOptions, repo *Repository, getUsedBlobs func(ctx context.Context, repo restic.Repository, usedBlobs restic.FindBlobSet) error, printer restic.Printer) (*PrunePlan, error) {
stats := PruneStats{MessageType: "summary"}
if opts.UnsafeRecovery {
@@ -176,7 +175,7 @@ func PlanPrune(ctx context.Context, opts PruneOptions, repo *Repository, getUsed
return &plan, nil
}
func packInfoFromIndex(ctx context.Context, idx restic.ListBlobser, usedBlobs *index.AssociatedSet[uint8], stats *PruneStats, printer progress.Printer) (*index.AssociatedSet[uint8], map[restic.ID]packInfo, error) {
func packInfoFromIndex(ctx context.Context, idx restic.ListBlobser, usedBlobs *index.AssociatedSet[uint8], stats *PruneStats, printer restic.Printer) (*index.AssociatedSet[uint8], map[restic.ID]packInfo, error) {
// iterate over all blobs in index to find out which blobs are duplicates
// The counter in usedBlobs describes how many instances of the blob exist in the repository index
// Thus 0 == blob is missing, 1 == blob exists once, >= 2 == duplicates exist
@@ -384,7 +383,7 @@ func calculateTargetPacksize(opts PruneOptions, indexPack map[restic.ID]packInfo
return targetPackSize
}
func decidePackAction(ctx context.Context, opts PruneOptions, repo *Repository, indexPack map[restic.ID]packInfo, stats *PruneStats, printer progress.Printer) (PrunePlan, error) {
func decidePackAction(ctx context.Context, opts PruneOptions, repo *Repository, indexPack map[restic.ID]packInfo, stats *PruneStats, printer restic.Printer) (PrunePlan, error) {
removePacksFirst := restic.NewIDSet()
removePacks := restic.NewIDSet()
repackPacks := restic.NewIDSet()
@@ -592,7 +591,7 @@ func (plan *PrunePlan) Stats() PruneStats {
// - rebuild the index while ignoring all files that will be deleted
// - delete the files
// plan.removePacks and plan.ignorePacks are modified in this function.
func (plan *PrunePlan) Execute(ctx context.Context, printer progress.Printer) error {
func (plan *PrunePlan) Execute(ctx context.Context, printer restic.Printer) error {
if plan.opts.DryRun {
printer.V("Repeated prune dry-runs can report slightly different amounts of data to keep or repack. This is expected behavior.\n\n")
if len(plan.removePacksFirst) > 0 {
@@ -692,7 +691,7 @@ func (plan *PrunePlan) Execute(ctx context.Context, printer progress.Printer) er
// deleteFiles deletes the given fileList of fileType in parallel
// if ignoreError=true, it will print a warning if there was an error, else it will abort.
func deleteFiles(ctx context.Context, ignoreError bool, repo restic.RemoverUnpacked[restic.FileType], fileList restic.IDSet, fileType restic.FileType, printer progress.Printer) error {
func deleteFiles(ctx context.Context, ignoreError bool, repo restic.RemoverUnpacked[restic.FileType], fileList restic.IDSet, fileType restic.FileType, printer restic.Printer) error {
bar := printer.NewCounter("files deleted")
defer bar.Done()
+2 -3
View File
@@ -9,7 +9,6 @@ import (
"github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui/progress"
)
// TestPruneMaxUnusedDuplicate checks that MaxUnused correctly accounts for duplicates.
@@ -70,10 +69,10 @@ func TestPruneMaxUnusedDuplicate(t *testing.T) {
usedBlobs.Insert(blob)
}
return nil
}, progress.NewNoopPrinter())
}, restic.NewNoopPrinter())
rtest.OK(t, err)
rtest.OK(t, plan.Execute(context.TODO(), progress.NewNoopPrinter()))
rtest.OK(t, plan.Execute(context.TODO(), restic.NewNoopPrinter()))
rsize := plan.Stats().Size
remainingUnusedSize := rsize.Duplicate + rsize.Unused - rsize.Remove - rsize.Repackrm
+4 -5
View File
@@ -12,7 +12,6 @@ import (
"github.com/restic/restic/internal/repository/pack"
"github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui/progress"
)
func testPrune(t *testing.T, opts repository.PruneOptions, errOnUnused bool) {
@@ -41,10 +40,10 @@ func testPrune(t *testing.T, opts repository.PruneOptions, errOnUnused bool) {
usedBlobs.Insert(blob)
}
return nil
}, progress.NewNoopPrinter())
}, restic.NewNoopPrinter())
rtest.OK(t, err)
rtest.OK(t, plan.Execute(context.TODO(), progress.NewNoopPrinter()))
rtest.OK(t, plan.Execute(context.TODO(), restic.NewNoopPrinter()))
repo = repository.TestOpenBackend(t, be)
repository.TestCheckRepo(t, repo)
@@ -165,9 +164,9 @@ func TestPruneSmall(t *testing.T) {
usedBlobs.Insert(blob)
}
return nil
}, progress.NewNoopPrinter())
}, restic.NewNoopPrinter())
rtest.OK(t, err)
rtest.OK(t, plan.Execute(context.TODO(), progress.NewNoopPrinter()))
rtest.OK(t, plan.Execute(context.TODO(), restic.NewNoopPrinter()))
stats := plan.Stats()
rtest.Equals(t, stats.Size.Used/blobSize, uint64(numBlobsCreated), fmt.Sprintf("total size of blobs should be %d but is %d",
+1 -2
View File
@@ -10,7 +10,6 @@ import (
"github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui/progress"
)
func randomSize(random *rand.Rand, min, max int) int {
@@ -161,7 +160,7 @@ func repack(t *testing.T, repo *repository.Repository, be backend.Backend, packs
func rebuildAndReloadIndex(t *testing.T, repo *repository.Repository) {
rtest.OK(t, repository.RepairIndex(context.TODO(), repo, repository.RepairIndexOptions{
ReadAllPacks: true,
}, progress.NewNoopPrinter()))
}, restic.NewNoopPrinter()))
rtest.OK(t, repo.LoadIndex(context.TODO(), restic.NoopTerminalCounterFactory))
}
+2 -3
View File
@@ -6,14 +6,13 @@ import (
"github.com/restic/restic/internal/repository/index"
"github.com/restic/restic/internal/repository/pack"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui/progress"
)
type RepairIndexOptions struct {
ReadAllPacks bool
}
func RepairIndex(ctx context.Context, repo *Repository, opts RepairIndexOptions, printer progress.Printer) error {
func RepairIndex(ctx context.Context, repo *Repository, opts RepairIndexOptions, printer restic.Printer) error {
var obsoleteIndexes restic.IDs
packSizeFromList := make(map[restic.ID]int64)
packSizeFromIndex := make(map[restic.ID]int64)
@@ -103,7 +102,7 @@ func RepairIndex(ctx context.Context, repo *Repository, opts RepairIndexOptions,
return nil
}
func rewriteIndexFiles(ctx context.Context, repo *Repository, removePacks restic.IDSet, oldIndexes restic.IDSet, extraObsolete restic.IDs, printer progress.Printer) error {
func rewriteIndexFiles(ctx context.Context, repo *Repository, removePacks restic.IDSet, oldIndexes restic.IDSet, extraObsolete restic.IDs, printer restic.Printer) error {
printer.P("rebuilding index\n")
bar := printer.NewCounter("indexes processed")
+1 -2
View File
@@ -10,7 +10,6 @@ import (
"github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui/progress"
)
func listIndex(t *testing.T, repo restic.Lister) restic.IDSet {
@@ -33,7 +32,7 @@ func testRebuildIndex(t *testing.T, readAllPacks bool, damage func(t *testing.T,
repo = repository.TestOpenBackend(t, be)
rtest.OK(t, repository.RepairIndex(context.TODO(), repo, repository.RepairIndexOptions{
ReadAllPacks: readAllPacks,
}, progress.NewNoopPrinter()))
}, restic.NewNoopPrinter()))
repository.TestCheckRepo(t, repo)
}
+2 -3
View File
@@ -8,10 +8,9 @@ import (
"github.com/restic/restic/internal/repository/pack"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui/progress"
)
func RepairPacks(ctx context.Context, repo *Repository, ids restic.IDSet, printer progress.Printer) error {
func RepairPacks(ctx context.Context, repo *Repository, ids restic.IDSet, printer restic.Printer) error {
printer.P("salvaging intact data from specified pack files")
bar := printer.NewCounter("pack files")
bar.SetMax(uint64(len(ids)))
@@ -92,7 +91,7 @@ func resolveBlobsForPacks(ctx context.Context, repo *Repository, ids restic.IDSe
return packToBlobs, nil
}
func reuploadBlobsFromPack(ctx context.Context, repo *Repository, packID restic.ID, blobs pack.Blobs, printer progress.Printer, uploader restic.BlobSaverWithAsync) error {
func reuploadBlobsFromPack(ctx context.Context, repo *Repository, packID restic.ID, blobs pack.Blobs, printer restic.Printer, uploader restic.BlobSaverWithAsync) error {
err := repo.loadBlobsFromPack(ctx, packID, blobs, func(blob restic.BlobHandle, buf []byte, err error) error {
if err != nil {
printer.E("failed to load blob %v: %v", blob.ID, err)
+2 -3
View File
@@ -11,7 +11,6 @@ import (
"github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test"
"github.com/restic/restic/internal/ui/progress"
)
func listBlobs(repo restic.Repository) restic.BlobSet {
@@ -105,7 +104,7 @@ func testRepairBrokenPack(t *testing.T, version uint) {
buf, err := backendtest.LoadAll(context.TODO(), be, h)
rtest.OK(t, err)
rtest.OK(t, be.Remove(context.TODO(), h))
rtest.OK(t, repository.RepairIndex(context.TODO(), repo, repository.RepairIndexOptions{}, progress.NewNoopPrinter()))
rtest.OK(t, repository.RepairIndex(context.TODO(), repo, repository.RepairIndexOptions{}, restic.NewNoopPrinter()))
rtest.OK(t, be.Save(context.TODO(), h, backend.NewByteReader(buf, be.Hasher())))
@@ -129,7 +128,7 @@ func testRepairBrokenPack(t *testing.T, version uint) {
toRepair, damagedBlobs := test.damage(t, random, repo, be, packsBefore)
rtest.OK(t, repository.RepairPacks(context.TODO(), repo, toRepair, progress.NewNoopPrinter()))
rtest.OK(t, repository.RepairPacks(context.TODO(), repo, toRepair, restic.NewNoopPrinter()))
// reload index
rtest.OK(t, repo.LoadIndex(context.TODO(), restic.NoopTerminalCounterFactory))
+64
View File
@@ -26,3 +26,67 @@ func (noopTerminalCounterFactory) NewCounterTerminalOnly(string) Counter {
// NoopTerminalCounterFactory is a TerminalCounterFactory that returns NoopCounter.
var NoopTerminalCounterFactory TerminalCounterFactory = noopTerminalCounterFactory{}
// Printer can return a new counter or print messages at different log levels.
// It must be safe to call its methods from concurrent goroutines.
type Printer interface {
// NewCounter returns a new progress counter. It is not shown if --quiet or --json is specified.
NewCounter(description string) Counter
// NewCounterTerminalOnly returns a new progress counter that is only shown if stdout points to a
// terminal. It is not shown if --quiet or --json is specified.
NewCounterTerminalOnly(description string) Counter
// E reports an error. This message is always printed to stderr.
// Appends a newline if not present.
E(msg string, args ...interface{})
// S prints a message, this is should only be used for very important messages
// that are not errors. The message is even printed if --quiet is specified.
// Appends a newline if not present.
S(msg string, args ...interface{})
// PT prints a message if verbosity >= 1 (neither --quiet nor --verbose is specified)
// and stdout points to a terminal.
// This is used for informational messages.
PT(msg string, args ...interface{})
// P prints a message if verbosity >= 1 (neither --quiet nor --verbose is specified),
// this is used for normal messages which are not errors. Appends a newline if not present.
P(msg string, args ...interface{})
// V prints a message if verbosity >= 2 (equivalent to --verbose), this is used for
// verbose messages. Appends a newline if not present.
V(msg string, args ...interface{})
// VV prints a message if verbosity >= 3 (equivalent to --verbose=2), this is used for
// debug messages. Appends a newline if not present.
VV(msg string, args ...interface{})
}
// noopPrinter discards all messages.
type noopPrinter struct{}
var (
_ Printer = (*noopPrinter)(nil)
_ TerminalCounterFactory = (*noopPrinter)(nil)
)
// NewNoopPrinter returns a Printer that discards all messages.
func NewNoopPrinter() Printer {
return &noopPrinter{}
}
func (*noopPrinter) NewCounter(_ string) Counter {
return NoopCounter
}
func (*noopPrinter) NewCounterTerminalOnly(_ string) Counter {
return NoopCounter
}
func (*noopPrinter) E(_ string, _ ...interface{}) {}
func (*noopPrinter) S(_ string, _ ...interface{}) {}
func (*noopPrinter) PT(_ string, _ ...interface{}) {}
func (*noopPrinter) P(_ string, _ ...interface{}) {}
func (*noopPrinter) V(_ string, _ ...interface{}) {}
func (*noopPrinter) VV(_ string, _ ...interface{}) {}
+3 -3
View File
@@ -989,7 +989,7 @@ func TestRestorerSparseOverwrite(t *testing.T) {
type printerMock struct {
s restoreui.State
progress.Printer
restic.Printer
}
func (p *printerMock) Update(_ restoreui.State, _ time.Duration) {
@@ -1102,7 +1102,7 @@ func TestRestorerOverwriteBehavior(t *testing.T) {
for _, test := range tests {
t.Run("", func(t *testing.T) {
mock := &printerMock{Printer: progress.NewNoopPrinter()}
mock := &printerMock{Printer: restic.NewNoopPrinter()}
progress := restoreui.NewProgress(mock, true, false, true)
tempdir := saveSnapshotsAndOverwrite(t, baseSnapshot, overwriteSnapshot, Options{}, Options{Overwrite: test.Overwrite, Progress: progress})
@@ -1154,7 +1154,7 @@ func TestRestorerOverwritePartial(t *testing.T) {
},
}
mock := &printerMock{Printer: progress.NewNoopPrinter()}
mock := &printerMock{Printer: restic.NewNoopPrinter()}
progress := restoreui.NewProgress(mock, true, false, true)
saveSnapshotsAndOverwrite(t, baseSnapshot, overwriteSnapshot, Options{}, Options{Overwrite: OverwriteAlways, Progress: progress})
progress.Finish()
+2 -1
View File
@@ -4,6 +4,7 @@ package restorer
import (
"context"
"github.com/restic/restic/internal/restic"
"io/fs"
"os"
"path/filepath"
@@ -88,7 +89,7 @@ func testRestorerProgressBar(t *testing.T, dryRun bool) {
},
}, noopGetGenericAttributes)
mock := &printerMock{Printer: progress.NewNoopPrinter()}
mock := &printerMock{Printer: restic.NewNoopPrinter()}
progress := restoreui.NewProgress(mock, true, false, true)
res := NewRestorer(repo, sn, Options{Progress: progress, DryRun: dryRun})
+1 -1
View File
@@ -12,7 +12,7 @@ import (
// jsonProgress reports progress for the `backup` command in JSON.
type jsonProgress struct {
progress.Printer
restic.Printer
term ui.Terminal
v uint
+1 -1
View File
@@ -21,7 +21,7 @@ type ProgressPrinter interface {
Finish(snapshotID restic.ID, summary *archiver.Summary, dryRun bool)
Reset()
progress.Printer
restic.Printer
}
type Counter struct {
+2 -3
View File
@@ -8,12 +8,11 @@ import (
"github.com/restic/restic/internal/archiver"
"github.com/restic/restic/internal/data"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui/progress"
)
type mockPrinter struct {
sync.Mutex
progress.Printer
restic.Printer
dirUnchanged, fileNew bool
id restic.ID
}
@@ -48,7 +47,7 @@ func (p *mockPrinter) Reset() {}
func TestProgress(t *testing.T) {
t.Parallel()
prnt := &mockPrinter{Printer: progress.NewNoopPrinter()}
prnt := &mockPrinter{Printer: restic.NewNoopPrinter()}
prog := newProgress(prnt, time.Millisecond)
prog.StartFile("foo")
+1 -1
View File
@@ -13,7 +13,7 @@ import (
// textProgress reports progress for the `backup` command.
type textProgress struct {
progress.Printer
restic.Printer
term ui.Terminal
verbosity uint
-67
View File
@@ -1,67 +0,0 @@
package progress
import (
"github.com/restic/restic/internal/restic"
)
// A Printer can can return a new counter or print messages
// at different log levels.
// It must be safe to call its methods from concurrent goroutines.
type Printer interface {
// NewCounter returns a new progress counter. It is not shown if --quiet or --json is specified.
NewCounter(description string) restic.Counter
// NewCounterTerminalOnly returns a new progress counter that is only shown if stdout points to a
// terminal. It is not shown if --quiet or --json is specified.
NewCounterTerminalOnly(description string) restic.Counter
// E reports an error. This message is always printed to stderr.
// Appends a newline if not present.
E(msg string, args ...interface{})
// S prints a message, this is should only be used for very important messages
// that are not errors. The message is even printed if --quiet is specified.
// Appends a newline if not present.
S(msg string, args ...interface{})
// PT prints a message if verbosity >= 1 (neither --quiet nor --verbose is specified)
// and stdout points to a terminal.
// This is used for informational messages.
PT(msg string, args ...interface{})
// P prints a message if verbosity >= 1 (neither --quiet nor --verbose is specified),
// this is used for normal messages which are not errors. Appends a newline if not present.
P(msg string, args ...interface{})
// V prints a message if verbosity >= 2 (equivalent to --verbose), this is used for
// verbose messages. Appends a newline if not present.
V(msg string, args ...interface{})
// VV prints a message if verbosity >= 3 (equivalent to --verbose=2), this is used for
// debug messages. Appends a newline if not present.
VV(msg string, args ...interface{})
}
// noopPrinter discards all messages.
type noopPrinter struct{}
var _ Printer = (*noopPrinter)(nil)
// NewNoopPrinter returns a Printer that discards all messages.
func NewNoopPrinter() Printer {
return &noopPrinter{}
}
func (*noopPrinter) NewCounter(_ string) restic.Counter {
return restic.NoopCounter
}
func (*noopPrinter) NewCounterTerminalOnly(_ string) restic.Counter {
return restic.NoopCounter
}
func (*noopPrinter) E(_ string, _ ...interface{}) {}
func (*noopPrinter) S(_ string, _ ...interface{}) {}
func (*noopPrinter) PT(_ string, _ ...interface{}) {}
func (*noopPrinter) P(_ string, _ ...interface{}) {}
func (*noopPrinter) V(_ string, _ ...interface{}) {}
func (*noopPrinter) VV(_ string, _ ...interface{}) {}
+1 -1
View File
@@ -98,7 +98,7 @@ func (t *terminalPrinter) VV(msg string, args ...interface{}) {
}
}
func NewTerminalPrinter(json bool, verbosity uint, term ui.Terminal) Printer {
func NewTerminalPrinter(json bool, verbosity uint, term ui.Terminal) restic.Printer {
if json {
verbosity = 0
}
+2 -1
View File
@@ -3,12 +3,13 @@ package restore
import (
"time"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui"
"github.com/restic/restic/internal/ui/progress"
)
type jsonPrinter struct {
progress.Printer
restic.Printer
terminal ui.Terminal
verbosity uint
+2 -1
View File
@@ -4,6 +4,7 @@ import (
"sync"
"time"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui/progress"
)
@@ -38,7 +39,7 @@ type ProgressPrinter interface {
Error(item string, err error) error
CompleteItem(action ItemAction, item string, size uint64)
Finish(progress State, duration time.Duration)
progress.Printer
restic.Printer
}
type ItemAction string
+3 -2
View File
@@ -1,6 +1,7 @@
package restore
import (
"github.com/restic/restic/internal/restic"
"testing"
"time"
@@ -37,7 +38,7 @@ type mockPrinter struct {
trace printerTrace
items itemTrace
errors errorTrace
progress.Printer
restic.Printer
}
const mockFinishDuration = 42 * time.Second
@@ -57,7 +58,7 @@ func (p *mockPrinter) Finish(progress State, _ time.Duration) {
}
func testProgress(fn func(progress *Progress) bool) (printerTrace, itemTrace, errorTrace) {
printer := &mockPrinter{Printer: progress.NewNoopPrinter()}
printer := &mockPrinter{Printer: restic.NewNoopPrinter()}
progress := newProgress(printer, 0)
final := fn(progress)
progress.update(0, final)
+2 -1
View File
@@ -4,12 +4,13 @@ import (
"fmt"
"time"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui"
"github.com/restic/restic/internal/ui/progress"
)
type textPrinter struct {
progress.Printer
restic.Printer
terminal ui.Terminal
}