Merge pull request #4647 from MichaelEischer/reduce-globals

Remove all usages of the global command-specific options
This commit is contained in:
Michael Eischer 2024-01-23 19:46:15 +01:00 committed by GitHub
commit 5b36c4eb5f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 93 additions and 79 deletions

View file

@ -633,7 +633,7 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter
wg.Go(func() error { return sc.Scan(cancelCtx, targets) }) wg.Go(func() error { return sc.Scan(cancelCtx, targets) })
} }
arch := archiver.New(repo, targetFS, archiver.Options{ReadConcurrency: backupOptions.ReadConcurrency}) arch := archiver.New(repo, targetFS, archiver.Options{ReadConcurrency: opts.ReadConcurrency})
arch.SelectByName = selectByNameFilter arch.SelectByName = selectByNameFilter
arch.Select = selectFilter arch.Select = selectFilter
arch.WithAtime = opts.WithAtime arch.WithAtime = opts.WithAtime

View file

@ -52,19 +52,23 @@ Exit status is 0 if the command was successful, and non-zero if there was any er
}, },
} }
var tryRepair bool type DebugExamineOptions struct {
var repairByte bool TryRepair bool
var extractPack bool RepairByte bool
var reuploadBlobs bool ExtractPack bool
ReuploadBlobs bool
}
var debugExamineOpts DebugExamineOptions
func init() { func init() {
cmdRoot.AddCommand(cmdDebug) cmdRoot.AddCommand(cmdDebug)
cmdDebug.AddCommand(cmdDebugDump) cmdDebug.AddCommand(cmdDebugDump)
cmdDebug.AddCommand(cmdDebugExamine) cmdDebug.AddCommand(cmdDebugExamine)
cmdDebugExamine.Flags().BoolVar(&extractPack, "extract-pack", false, "write blobs to the current directory") cmdDebugExamine.Flags().BoolVar(&debugExamineOpts.ExtractPack, "extract-pack", false, "write blobs to the current directory")
cmdDebugExamine.Flags().BoolVar(&reuploadBlobs, "reupload-blobs", false, "reupload blobs to the repository") cmdDebugExamine.Flags().BoolVar(&debugExamineOpts.ReuploadBlobs, "reupload-blobs", false, "reupload blobs to the repository")
cmdDebugExamine.Flags().BoolVar(&tryRepair, "try-repair", false, "try to repair broken blobs with single bit flips") cmdDebugExamine.Flags().BoolVar(&debugExamineOpts.TryRepair, "try-repair", false, "try to repair broken blobs with single bit flips")
cmdDebugExamine.Flags().BoolVar(&repairByte, "repair-byte", false, "try to repair broken blobs by trying bytes") cmdDebugExamine.Flags().BoolVar(&debugExamineOpts.RepairByte, "repair-byte", false, "try to repair broken blobs by trying bytes")
} }
func prettyPrintJSON(wr io.Writer, item interface{}) error { func prettyPrintJSON(wr io.Writer, item interface{}) error {
@ -196,7 +200,7 @@ var cmdDebugExamine = &cobra.Command{
Short: "Examine a pack file", Short: "Examine a pack file",
DisableAutoGenTag: true, DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return runDebugExamine(cmd.Context(), globalOptions, args) return runDebugExamine(cmd.Context(), globalOptions, debugExamineOpts, args)
}, },
} }
@ -315,7 +319,7 @@ func decryptUnsigned(ctx context.Context, k *crypto.Key, buf []byte) []byte {
return out return out
} }
func loadBlobs(ctx context.Context, repo restic.Repository, packID restic.ID, list []restic.Blob) error { func loadBlobs(ctx context.Context, opts DebugExamineOptions, repo restic.Repository, packID restic.ID, list []restic.Blob) error {
dec, err := zstd.NewReader(nil) dec, err := zstd.NewReader(nil)
if err != nil { if err != nil {
panic(err) panic(err)
@ -328,7 +332,7 @@ func loadBlobs(ctx context.Context, repo restic.Repository, packID restic.ID, li
wg, ctx := errgroup.WithContext(ctx) wg, ctx := errgroup.WithContext(ctx)
if reuploadBlobs { if opts.ReuploadBlobs {
repo.StartPackUploader(ctx, wg) repo.StartPackUploader(ctx, wg)
} }
@ -356,8 +360,8 @@ func loadBlobs(ctx context.Context, repo restic.Repository, packID restic.ID, li
filePrefix := "" filePrefix := ""
if err != nil { if err != nil {
Warnf("error decrypting blob: %v\n", err) Warnf("error decrypting blob: %v\n", err)
if tryRepair || repairByte { if opts.TryRepair || opts.RepairByte {
plaintext = tryRepairWithBitflip(ctx, key, buf, repairByte) plaintext = tryRepairWithBitflip(ctx, key, buf, opts.RepairByte)
} }
if plaintext != nil { if plaintext != nil {
outputPrefix = "repaired " outputPrefix = "repaired "
@ -391,13 +395,13 @@ func loadBlobs(ctx context.Context, repo restic.Repository, packID restic.ID, li
Printf(" successfully %vdecrypted blob (length %v), hash is %v, ID matches\n", outputPrefix, len(plaintext), id) Printf(" successfully %vdecrypted blob (length %v), hash is %v, ID matches\n", outputPrefix, len(plaintext), id)
prefix = "correct-" prefix = "correct-"
} }
if extractPack { if opts.ExtractPack {
err = storePlainBlob(id, filePrefix+prefix, plaintext) err = storePlainBlob(id, filePrefix+prefix, plaintext)
if err != nil { if err != nil {
return err return err
} }
} }
if reuploadBlobs { if opts.ReuploadBlobs {
_, _, _, err := repo.SaveBlob(ctx, blob.Type, plaintext, id, true) _, _, _, err := repo.SaveBlob(ctx, blob.Type, plaintext, id, true)
if err != nil { if err != nil {
return err return err
@ -406,7 +410,7 @@ func loadBlobs(ctx context.Context, repo restic.Repository, packID restic.ID, li
} }
} }
if reuploadBlobs { if opts.ReuploadBlobs {
return repo.Flush(ctx) return repo.Flush(ctx)
} }
return nil return nil
@ -437,7 +441,7 @@ func storePlainBlob(id restic.ID, prefix string, plain []byte) error {
return nil return nil
} }
func runDebugExamine(ctx context.Context, gopts GlobalOptions, args []string) error { func runDebugExamine(ctx context.Context, gopts GlobalOptions, opts DebugExamineOptions, args []string) error {
repo, err := OpenRepository(ctx, gopts) repo, err := OpenRepository(ctx, gopts)
if err != nil { if err != nil {
return err return err
@ -476,7 +480,7 @@ func runDebugExamine(ctx context.Context, gopts GlobalOptions, args []string) er
} }
for _, id := range ids { for _, id := range ids {
err := examinePack(ctx, repo, id) err := examinePack(ctx, opts, repo, id)
if err != nil { if err != nil {
Warnf("error: %v\n", err) Warnf("error: %v\n", err)
} }
@ -487,7 +491,7 @@ func runDebugExamine(ctx context.Context, gopts GlobalOptions, args []string) er
return nil return nil
} }
func examinePack(ctx context.Context, repo restic.Repository, id restic.ID) error { func examinePack(ctx context.Context, opts DebugExamineOptions, repo restic.Repository, id restic.ID) error {
Printf("examine %v\n", id) Printf("examine %v\n", id)
h := backend.Handle{ h := backend.Handle{
@ -524,7 +528,7 @@ func examinePack(ctx context.Context, repo restic.Repository, id restic.ID) erro
checkPackSize(blobs, fi.Size) checkPackSize(blobs, fi.Size)
err = loadBlobs(ctx, repo, id, blobs) err = loadBlobs(ctx, opts, repo, id, blobs)
if err != nil { if err != nil {
Warnf("error: %v\n", err) Warnf("error: %v\n", err)
} else { } else {
@ -542,7 +546,7 @@ func examinePack(ctx context.Context, repo restic.Repository, id restic.ID) erro
checkPackSize(blobs, fi.Size) checkPackSize(blobs, fi.Size)
if !blobsLoaded { if !blobsLoaded {
return loadBlobs(ctx, repo, id, blobs) return loadBlobs(ctx, opts, repo, id, blobs)
} }
return nil return nil
} }

View file

@ -401,7 +401,7 @@ func runDiff(ctx context.Context, opts DiffOptions, gopts GlobalOptions, args []
c := &Comparer{ c := &Comparer{
repo: repo, repo: repo,
opts: diffOptions, opts: opts,
printChange: func(change *Change) { printChange: func(change *Change) {
Printf("%-5s%v\n", change.Modifier, change.Path) Printf("%-5s%v\n", change.Modifier, change.Path)
}, },

View file

@ -33,7 +33,7 @@ Exit status is 0 if the command was successful, and non-zero if there was any er
`, `,
DisableAutoGenTag: true, DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return runForget(cmd.Context(), forgetOptions, globalOptions, args) return runForget(cmd.Context(), forgetOptions, forgetPruneOptions, globalOptions, args)
}, },
} }
@ -98,6 +98,7 @@ type ForgetOptions struct {
} }
var forgetOptions ForgetOptions var forgetOptions ForgetOptions
var forgetPruneOptions PruneOptions
func init() { func init() {
cmdRoot.AddCommand(cmdForget) cmdRoot.AddCommand(cmdForget)
@ -132,7 +133,7 @@ func init() {
f.BoolVar(&forgetOptions.Prune, "prune", false, "automatically run the 'prune' command if snapshots have been removed") f.BoolVar(&forgetOptions.Prune, "prune", false, "automatically run the 'prune' command if snapshots have been removed")
f.SortFlags = false f.SortFlags = false
addPruneOptions(cmdForget) addPruneOptions(cmdForget, &forgetPruneOptions)
} }
func verifyForgetOptions(opts *ForgetOptions) error { func verifyForgetOptions(opts *ForgetOptions) error {
@ -151,7 +152,7 @@ func verifyForgetOptions(opts *ForgetOptions) error {
return nil return nil
} }
func runForget(ctx context.Context, opts ForgetOptions, gopts GlobalOptions, args []string) error { func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOptions, gopts GlobalOptions, args []string) error {
err := verifyForgetOptions(&opts) err := verifyForgetOptions(&opts)
if err != nil { if err != nil {
return err return err

View file

@ -9,5 +9,8 @@ import (
func testRunForget(t testing.TB, gopts GlobalOptions, args ...string) { func testRunForget(t testing.TB, gopts GlobalOptions, args ...string) {
opts := ForgetOptions{} opts := ForgetOptions{}
rtest.OK(t, runForget(context.TODO(), opts, gopts, args)) pruneOpts := PruneOptions{
MaxUnused: "5%",
}
rtest.OK(t, runForget(context.TODO(), opts, pruneOpts, gopts, args))
} }

View file

@ -21,7 +21,9 @@ EXIT STATUS
Exit status is 0 if the command was successful, and non-zero if there was any error. Exit status is 0 if the command was successful, and non-zero if there was any error.
`, `,
DisableAutoGenTag: true, DisableAutoGenTag: true,
RunE: runGenerate, RunE: func(cmd *cobra.Command, args []string) error {
return runGenerate(genOpts, args)
},
} }
type generateOptions struct { type generateOptions struct {
@ -90,48 +92,48 @@ func writePowerShellCompletion(file string) error {
return cmdRoot.GenPowerShellCompletionFile(file) return cmdRoot.GenPowerShellCompletionFile(file)
} }
func runGenerate(_ *cobra.Command, args []string) error { func runGenerate(opts generateOptions, args []string) error {
if len(args) > 0 { if len(args) > 0 {
return errors.Fatal("the generate command expects no arguments, only options - please see `restic help generate` for usage and flags") return errors.Fatal("the generate command expects no arguments, only options - please see `restic help generate` for usage and flags")
} }
if genOpts.ManDir != "" { if opts.ManDir != "" {
err := writeManpages(genOpts.ManDir) err := writeManpages(opts.ManDir)
if err != nil { if err != nil {
return err return err
} }
} }
if genOpts.BashCompletionFile != "" { if opts.BashCompletionFile != "" {
err := writeBashCompletion(genOpts.BashCompletionFile) err := writeBashCompletion(opts.BashCompletionFile)
if err != nil { if err != nil {
return err return err
} }
} }
if genOpts.FishCompletionFile != "" { if opts.FishCompletionFile != "" {
err := writeFishCompletion(genOpts.FishCompletionFile) err := writeFishCompletion(opts.FishCompletionFile)
if err != nil { if err != nil {
return err return err
} }
} }
if genOpts.ZSHCompletionFile != "" { if opts.ZSHCompletionFile != "" {
err := writeZSHCompletion(genOpts.ZSHCompletionFile) err := writeZSHCompletion(opts.ZSHCompletionFile)
if err != nil { if err != nil {
return err return err
} }
} }
if genOpts.PowerShellCompletionFile != "" { if opts.PowerShellCompletionFile != "" {
err := writePowerShellCompletion(genOpts.PowerShellCompletionFile) err := writePowerShellCompletion(opts.PowerShellCompletionFile)
if err != nil { if err != nil {
return err return err
} }
} }
var empty generateOptions var empty generateOptions
if genOpts == empty { if opts == empty {
return errors.Fatal("nothing to do, please specify at least one output file/dir") return errors.Fatal("nothing to do, please specify at least one output file/dir")
} }

View file

@ -29,23 +29,25 @@ Exit status is 0 if the command was successful, and non-zero if there was any er
`, `,
DisableAutoGenTag: true, DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return runKey(cmd.Context(), globalOptions, args) return runKey(cmd.Context(), globalOptions, keyOpts, args)
}, },
} }
var ( type KeyOptions struct {
newPasswordFile string NewPasswordFile string
keyUsername string Username string
keyHostname string Hostname string
) }
var keyOpts KeyOptions
func init() { func init() {
cmdRoot.AddCommand(cmdKey) cmdRoot.AddCommand(cmdKey)
flags := cmdKey.Flags() flags := cmdKey.Flags()
flags.StringVarP(&newPasswordFile, "new-password-file", "", "", "`file` from which to read the new password") flags.StringVarP(&keyOpts.NewPasswordFile, "new-password-file", "", "", "`file` from which to read the new password")
flags.StringVarP(&keyUsername, "user", "", "", "the username for new keys") flags.StringVarP(&keyOpts.Username, "user", "", "", "the username for new keys")
flags.StringVarP(&keyHostname, "host", "", "", "the hostname for new keys") flags.StringVarP(&keyOpts.Hostname, "host", "", "", "the hostname for new keys")
} }
func listKeys(ctx context.Context, s *repository.Repository, gopts GlobalOptions) error { func listKeys(ctx context.Context, s *repository.Repository, gopts GlobalOptions) error {
@ -105,7 +107,7 @@ func listKeys(ctx context.Context, s *repository.Repository, gopts GlobalOptions
// testKeyNewPassword is used to set a new password during integration testing. // testKeyNewPassword is used to set a new password during integration testing.
var testKeyNewPassword string var testKeyNewPassword string
func getNewPassword(gopts GlobalOptions) (string, error) { func getNewPassword(gopts GlobalOptions, newPasswordFile string) (string, error) {
if testKeyNewPassword != "" { if testKeyNewPassword != "" {
return testKeyNewPassword, nil return testKeyNewPassword, nil
} }
@ -124,13 +126,13 @@ func getNewPassword(gopts GlobalOptions) (string, error) {
"enter password again: ") "enter password again: ")
} }
func addKey(ctx context.Context, repo *repository.Repository, gopts GlobalOptions) error { func addKey(ctx context.Context, repo *repository.Repository, gopts GlobalOptions, opts KeyOptions) error {
pw, err := getNewPassword(gopts) pw, err := getNewPassword(gopts, opts.NewPasswordFile)
if err != nil { if err != nil {
return err return err
} }
id, err := repository.AddKey(ctx, repo, pw, keyUsername, keyHostname, repo.Key()) id, err := repository.AddKey(ctx, repo, pw, opts.Username, opts.Hostname, repo.Key())
if err != nil { if err != nil {
return errors.Fatalf("creating new key failed: %v\n", err) return errors.Fatalf("creating new key failed: %v\n", err)
} }
@ -160,8 +162,8 @@ func deleteKey(ctx context.Context, repo *repository.Repository, id restic.ID) e
return nil return nil
} }
func changePassword(ctx context.Context, repo *repository.Repository, gopts GlobalOptions) error { func changePassword(ctx context.Context, repo *repository.Repository, gopts GlobalOptions, newPasswordFile string) error {
pw, err := getNewPassword(gopts) pw, err := getNewPassword(gopts, newPasswordFile)
if err != nil { if err != nil {
return err return err
} }
@ -201,7 +203,7 @@ func switchToNewKeyAndRemoveIfBroken(ctx context.Context, repo *repository.Repos
return nil return nil
} }
func runKey(ctx context.Context, gopts GlobalOptions, args []string) error { func runKey(ctx context.Context, gopts GlobalOptions, opts KeyOptions, args []string) error {
if len(args) < 1 || (args[0] == "remove" && len(args) != 2) || (args[0] != "remove" && len(args) != 1) { if len(args) < 1 || (args[0] == "remove" && len(args) != 2) || (args[0] != "remove" && len(args) != 1) {
return errors.Fatal("wrong number of arguments") return errors.Fatal("wrong number of arguments")
} }
@ -230,7 +232,7 @@ func runKey(ctx context.Context, gopts GlobalOptions, args []string) error {
return err return err
} }
return addKey(ctx, repo, gopts) return addKey(ctx, repo, gopts, opts)
case "remove": case "remove":
lock, ctx, err := lockRepoExclusive(ctx, repo, gopts.RetryLock, gopts.JSON) lock, ctx, err := lockRepoExclusive(ctx, repo, gopts.RetryLock, gopts.JSON)
defer unlockRepo(lock) defer unlockRepo(lock)
@ -251,7 +253,7 @@ func runKey(ctx context.Context, gopts GlobalOptions, args []string) error {
return err return err
} }
return changePassword(ctx, repo, gopts) return changePassword(ctx, repo, gopts, opts.NewPasswordFile)
} }
return nil return nil

View file

@ -13,7 +13,7 @@ import (
func testRunKeyListOtherIDs(t testing.TB, gopts GlobalOptions) []string { func testRunKeyListOtherIDs(t testing.TB, gopts GlobalOptions) []string {
buf, err := withCaptureStdout(func() error { buf, err := withCaptureStdout(func() error {
return runKey(context.TODO(), gopts, []string{"list"}) return runKey(context.TODO(), gopts, KeyOptions{}, []string{"list"})
}) })
rtest.OK(t, err) rtest.OK(t, err)
@ -36,21 +36,20 @@ func testRunKeyAddNewKey(t testing.TB, newPassword string, gopts GlobalOptions)
testKeyNewPassword = "" testKeyNewPassword = ""
}() }()
rtest.OK(t, runKey(context.TODO(), gopts, []string{"add"})) rtest.OK(t, runKey(context.TODO(), gopts, KeyOptions{}, []string{"add"}))
} }
func testRunKeyAddNewKeyUserHost(t testing.TB, gopts GlobalOptions) { func testRunKeyAddNewKeyUserHost(t testing.TB, gopts GlobalOptions) {
testKeyNewPassword = "john's geheimnis" testKeyNewPassword = "john's geheimnis"
defer func() { defer func() {
testKeyNewPassword = "" testKeyNewPassword = ""
keyUsername = ""
keyHostname = ""
}() }()
rtest.OK(t, cmdKey.Flags().Parse([]string{"--user=john", "--host=example.com"}))
t.Log("adding key for john@example.com") t.Log("adding key for john@example.com")
rtest.OK(t, runKey(context.TODO(), gopts, []string{"add"})) rtest.OK(t, runKey(context.TODO(), gopts, KeyOptions{
Username: "john",
Hostname: "example.com",
}, []string{"add"}))
repo, err := OpenRepository(context.TODO(), gopts) repo, err := OpenRepository(context.TODO(), gopts)
rtest.OK(t, err) rtest.OK(t, err)
@ -67,13 +66,13 @@ func testRunKeyPasswd(t testing.TB, newPassword string, gopts GlobalOptions) {
testKeyNewPassword = "" testKeyNewPassword = ""
}() }()
rtest.OK(t, runKey(context.TODO(), gopts, []string{"passwd"})) rtest.OK(t, runKey(context.TODO(), gopts, KeyOptions{}, []string{"passwd"}))
} }
func testRunKeyRemove(t testing.TB, gopts GlobalOptions, IDs []string) { func testRunKeyRemove(t testing.TB, gopts GlobalOptions, IDs []string) {
t.Logf("remove %d keys: %q\n", len(IDs), IDs) t.Logf("remove %d keys: %q\n", len(IDs), IDs)
for _, id := range IDs { for _, id := range IDs {
rtest.OK(t, runKey(context.TODO(), gopts, []string{"remove", id})) rtest.OK(t, runKey(context.TODO(), gopts, KeyOptions{}, []string{"remove", id}))
} }
} }
@ -103,7 +102,7 @@ func TestKeyAddRemove(t *testing.T) {
env.gopts.password = passwordList[len(passwordList)-1] env.gopts.password = passwordList[len(passwordList)-1]
t.Logf("testing access with last password %q\n", env.gopts.password) t.Logf("testing access with last password %q\n", env.gopts.password)
rtest.OK(t, runKey(context.TODO(), env.gopts, []string{"list"})) rtest.OK(t, runKey(context.TODO(), env.gopts, KeyOptions{}, []string{"list"}))
testRunCheck(t, env.gopts) testRunCheck(t, env.gopts)
testRunKeyAddNewKeyUserHost(t, env.gopts) testRunKeyAddNewKeyUserHost(t, env.gopts)
@ -131,15 +130,15 @@ func TestKeyProblems(t *testing.T) {
testKeyNewPassword = "" testKeyNewPassword = ""
}() }()
err := runKey(context.TODO(), env.gopts, []string{"passwd"}) err := runKey(context.TODO(), env.gopts, KeyOptions{}, []string{"passwd"})
t.Log(err) t.Log(err)
rtest.Assert(t, err != nil, "expected passwd change to fail") rtest.Assert(t, err != nil, "expected passwd change to fail")
err = runKey(context.TODO(), env.gopts, []string{"add"}) err = runKey(context.TODO(), env.gopts, KeyOptions{}, []string{"add"})
t.Log(err) t.Log(err)
rtest.Assert(t, err != nil, "expected key adding to fail") rtest.Assert(t, err != nil, "expected key adding to fail")
t.Logf("testing access with initial password %q\n", env.gopts.password) t.Logf("testing access with initial password %q\n", env.gopts.password)
rtest.OK(t, runKey(context.TODO(), env.gopts, []string{"list"})) rtest.OK(t, runKey(context.TODO(), env.gopts, KeyOptions{}, []string{"list"}))
testRunCheck(t, env.gopts) testRunCheck(t, env.gopts)
} }

View file

@ -23,7 +23,7 @@ Exit status is 0 if the command was successful, and non-zero if there was any er
`, `,
DisableAutoGenTag: true, DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return runList(cmd.Context(), cmd, globalOptions, args) return runList(cmd.Context(), globalOptions, args)
}, },
} }
@ -31,9 +31,9 @@ func init() {
cmdRoot.AddCommand(cmdList) cmdRoot.AddCommand(cmdList)
} }
func runList(ctx context.Context, cmd *cobra.Command, gopts GlobalOptions, args []string) error { func runList(ctx context.Context, gopts GlobalOptions, args []string) error {
if len(args) != 1 { if len(args) != 1 {
return errors.Fatal("type not specified, usage: " + cmd.Use) return errors.Fatal("type not specified")
} }
repo, err := OpenRepository(ctx, gopts) repo, err := OpenRepository(ctx, gopts)

View file

@ -12,7 +12,7 @@ import (
func testRunList(t testing.TB, tpe string, opts GlobalOptions) restic.IDs { func testRunList(t testing.TB, tpe string, opts GlobalOptions) restic.IDs {
buf, err := withCaptureStdout(func() error { buf, err := withCaptureStdout(func() error {
return runList(context.TODO(), cmdList, opts, []string{tpe}) return runList(context.TODO(), opts, []string{tpe})
}) })
rtest.OK(t, err) rtest.OK(t, err)
return parseIDsFromReader(t, buf) return parseIDsFromReader(t, buf)

View file

@ -210,7 +210,7 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
Verbosef("%v filtered by %v:\n", sn, dirs) Verbosef("%v filtered by %v:\n", sn, dirs)
} }
printNode = func(path string, node *restic.Node) { printNode = func(path string, node *restic.Node) {
Printf("%s\n", formatNode(path, node, lsOptions.ListLong, lsOptions.HumanReadable)) Printf("%s\n", formatNode(path, node, opts.ListLong, opts.HumanReadable))
} }
} }

View file

@ -66,10 +66,10 @@ func init() {
f := cmdPrune.Flags() f := cmdPrune.Flags()
f.BoolVarP(&pruneOptions.DryRun, "dry-run", "n", false, "do not modify the repository, just print what would be done") f.BoolVarP(&pruneOptions.DryRun, "dry-run", "n", false, "do not modify the repository, just print what would be done")
f.StringVarP(&pruneOptions.UnsafeNoSpaceRecovery, "unsafe-recover-no-free-space", "", "", "UNSAFE, READ THE DOCUMENTATION BEFORE USING! Try to recover a repository stuck with no free space. Do not use without trying out 'prune --max-repack-size 0' first.") f.StringVarP(&pruneOptions.UnsafeNoSpaceRecovery, "unsafe-recover-no-free-space", "", "", "UNSAFE, READ THE DOCUMENTATION BEFORE USING! Try to recover a repository stuck with no free space. Do not use without trying out 'prune --max-repack-size 0' first.")
addPruneOptions(cmdPrune) addPruneOptions(cmdPrune, &pruneOptions)
} }
func addPruneOptions(c *cobra.Command) { func addPruneOptions(c *cobra.Command, pruneOptions *PruneOptions) {
f := c.Flags() f := c.Flags()
f.StringVar(&pruneOptions.MaxUnused, "max-unused", "5%", "tolerate given `limit` of unused data (absolute value in bytes with suffixes k/K, m/M, g/G, t/T, a value in % or the word 'unlimited')") f.StringVar(&pruneOptions.MaxUnused, "max-unused", "5%", "tolerate given `limit` of unused data (absolute value in bytes with suffixes k/K, m/M, g/G, t/T, a value in % or the word 'unlimited')")
f.StringVar(&pruneOptions.MaxRepackSize, "max-repack-size", "", "maximum `size` to repack (allowed suffixes: k/K, m/M, g/G, t/T)") f.StringVar(&pruneOptions.MaxRepackSize, "max-repack-size", "", "maximum `size` to repack (allowed suffixes: k/K, m/M, g/G, t/T)")

View file

@ -81,7 +81,10 @@ func testRunForgetJSON(t testing.TB, gopts GlobalOptions, args ...string) {
DryRun: true, DryRun: true,
Last: 1, Last: 1,
} }
return runForget(context.TODO(), opts, gopts, args) pruneOpts := PruneOptions{
MaxUnused: "5%",
}
return runForget(context.TODO(), opts, pruneOpts, gopts, args)
}) })
rtest.OK(t, err) rtest.OK(t, err)