mirror of https://github.com/restic/restic.git
refactor to use constructor functions to create cobra commands
This allows getting rid of the global options variables
This commit is contained in:
parent
dc9b6378f3
commit
aacd6a47e3
|
@ -31,10 +31,13 @@ import (
|
||||||
"github.com/restic/restic/internal/ui/termstatus"
|
"github.com/restic/restic/internal/ui/termstatus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdBackup = &cobra.Command{
|
func newBackupCommand() *cobra.Command {
|
||||||
Use: "backup [flags] [FILE/DIR] ...",
|
var opts BackupOptions
|
||||||
Short: "Create a new backup of files and/or directories",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "backup [flags] [FILE/DIR] ...",
|
||||||
|
Short: "Create a new backup of files and/or directories",
|
||||||
|
Long: `
|
||||||
The "backup" command creates a new snapshot and saves the files and directories
|
The "backup" command creates a new snapshot and saves the files and directories
|
||||||
given as the arguments.
|
given as the arguments.
|
||||||
|
|
||||||
|
@ -48,23 +51,31 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
PreRun: func(_ *cobra.Command, _ []string) {
|
PreRun: func(_ *cobra.Command, _ []string) {
|
||||||
if backupOptions.Host == "" {
|
if opts.Host == "" {
|
||||||
hostname, err := os.Hostname()
|
hostname, err := os.Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Log("os.Hostname() returned err: %v", err)
|
debug.Log("os.Hostname() returned err: %v", err)
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
opts.Host = hostname
|
||||||
}
|
}
|
||||||
backupOptions.Host = hostname
|
},
|
||||||
}
|
GroupID: cmdGroupDefault,
|
||||||
},
|
DisableAutoGenTag: true,
|
||||||
GroupID: cmdGroupDefault,
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
DisableAutoGenTag: true,
|
term, cancel := setupTermstatus()
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
defer cancel()
|
||||||
term, cancel := setupTermstatus()
|
return runBackup(cmd.Context(), opts, globalOptions, term, args)
|
||||||
defer cancel()
|
},
|
||||||
return runBackup(cmd.Context(), backupOptions, globalOptions, term, args)
|
}
|
||||||
},
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newBackupCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// BackupOptions bundles all options for the backup command.
|
// BackupOptions bundles all options for the backup command.
|
||||||
|
@ -147,17 +158,11 @@ func (opts *BackupOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var backupOptions BackupOptions
|
|
||||||
var backupFSTestHook func(fs fs.FS) fs.FS
|
var backupFSTestHook func(fs fs.FS) fs.FS
|
||||||
|
|
||||||
// ErrInvalidSourceData is used to report an incomplete backup
|
// ErrInvalidSourceData is used to report an incomplete backup
|
||||||
var ErrInvalidSourceData = errors.New("at least one source file could not be read")
|
var ErrInvalidSourceData = errors.New("at least one source file could not be read")
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdBackup)
|
|
||||||
backupOptions.AddFlags(cmdBackup.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
// filterExisting returns a slice of all existing items, or an error if no
|
// filterExisting returns a slice of all existing items, or an error if no
|
||||||
// items exist at all.
|
// items exist at all.
|
||||||
func filterExisting(items []string) (result []string, err error) {
|
func filterExisting(items []string) (result []string, err error) {
|
||||||
|
|
|
@ -16,10 +16,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdCache = &cobra.Command{
|
func newCacheCommand() *cobra.Command {
|
||||||
Use: "cache",
|
var opts CacheOptions
|
||||||
Short: "Operate on local cache directories",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "cache",
|
||||||
|
Short: "Operate on local cache directories",
|
||||||
|
Long: `
|
||||||
The "cache" command allows listing and cleaning local cache directories.
|
The "cache" command allows listing and cleaning local cache directories.
|
||||||
|
|
||||||
EXIT STATUS
|
EXIT STATUS
|
||||||
|
@ -28,11 +31,19 @@ EXIT STATUS
|
||||||
Exit status is 0 if the command was successful.
|
Exit status is 0 if the command was successful.
|
||||||
Exit status is 1 if there was any error.
|
Exit status is 1 if there was any error.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(_ *cobra.Command, args []string) error {
|
RunE: func(_ *cobra.Command, args []string) error {
|
||||||
return runCache(cacheOptions, globalOptions, args)
|
return runCache(opts, globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newCacheCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheOptions bundles all options for the snapshots command.
|
// CacheOptions bundles all options for the snapshots command.
|
||||||
|
@ -48,13 +59,6 @@ func (opts *CacheOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.BoolVar(&opts.NoSize, "no-size", false, "do not output the size of the cache directories")
|
f.BoolVar(&opts.NoSize, "no-size", false, "do not output the size of the cache directories")
|
||||||
}
|
}
|
||||||
|
|
||||||
var cacheOptions CacheOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdCache)
|
|
||||||
cacheOptions.AddFlags(cmdCache.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func runCache(opts CacheOptions, gopts GlobalOptions, args []string) error {
|
func runCache(opts CacheOptions, gopts GlobalOptions, args []string) error {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
return errors.Fatal("the cache command expects no arguments, only options - please see `restic help cache` for usage and flags")
|
return errors.Fatal("the cache command expects no arguments, only options - please see `restic help cache` for usage and flags")
|
||||||
|
|
|
@ -14,10 +14,11 @@ import (
|
||||||
|
|
||||||
var catAllowedCmds = []string{"config", "index", "snapshot", "key", "masterkey", "lock", "pack", "blob", "tree"}
|
var catAllowedCmds = []string{"config", "index", "snapshot", "key", "masterkey", "lock", "pack", "blob", "tree"}
|
||||||
|
|
||||||
var cmdCat = &cobra.Command{
|
func newCatCommand() *cobra.Command {
|
||||||
Use: "cat [flags] [masterkey|config|pack ID|blob ID|snapshot ID|index ID|key ID|lock ID|tree snapshot:subfolder]",
|
cmd := &cobra.Command{
|
||||||
Short: "Print internal objects to stdout",
|
Use: "cat [flags] [masterkey|config|pack ID|blob ID|snapshot ID|index ID|key ID|lock ID|tree snapshot:subfolder]",
|
||||||
Long: `
|
Short: "Print internal objects to stdout",
|
||||||
|
Long: `
|
||||||
The "cat" command is used to print internal objects to stdout.
|
The "cat" command is used to print internal objects to stdout.
|
||||||
|
|
||||||
EXIT STATUS
|
EXIT STATUS
|
||||||
|
@ -29,16 +30,18 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runCat(cmd.Context(), globalOptions, args)
|
return runCat(cmd.Context(), globalOptions, args)
|
||||||
},
|
},
|
||||||
ValidArgs: catAllowedCmds,
|
ValidArgs: catAllowedCmds,
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdRoot.AddCommand(cmdCat)
|
cmdRoot.AddCommand(newCatCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateCatArgs(args []string) error {
|
func validateCatArgs(args []string) error {
|
||||||
|
|
|
@ -23,10 +23,12 @@ import (
|
||||||
"github.com/restic/restic/internal/ui/termstatus"
|
"github.com/restic/restic/internal/ui/termstatus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdCheck = &cobra.Command{
|
func newCheckCommand() *cobra.Command {
|
||||||
Use: "check [flags]",
|
var opts CheckOptions
|
||||||
Short: "Check the repository for errors",
|
cmd := &cobra.Command{
|
||||||
Long: `
|
Use: "check [flags]",
|
||||||
|
Short: "Check the repository for errors",
|
||||||
|
Long: `
|
||||||
The "check" command tests the repository for errors and reports any errors it
|
The "check" command tests the repository for errors and reports any errors it
|
||||||
finds. It can also be used to read all data and therefore simulate a restore.
|
finds. It can also be used to read all data and therefore simulate a restore.
|
||||||
|
|
||||||
|
@ -42,23 +44,31 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
term, cancel := setupTermstatus()
|
term, cancel := setupTermstatus()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
summary, err := runCheck(cmd.Context(), checkOptions, globalOptions, args, term)
|
summary, err := runCheck(cmd.Context(), opts, globalOptions, args, term)
|
||||||
if globalOptions.JSON {
|
if globalOptions.JSON {
|
||||||
if err != nil && summary.NumErrors == 0 {
|
if err != nil && summary.NumErrors == 0 {
|
||||||
summary.NumErrors = 1
|
summary.NumErrors = 1
|
||||||
|
}
|
||||||
|
term.Print(ui.ToJSONString(summary))
|
||||||
}
|
}
|
||||||
term.Print(ui.ToJSONString(summary))
|
return err
|
||||||
}
|
},
|
||||||
return err
|
PreRunE: func(_ *cobra.Command, _ []string) error {
|
||||||
},
|
return checkFlags(opts)
|
||||||
PreRunE: func(_ *cobra.Command, _ []string) error {
|
},
|
||||||
return checkFlags(checkOptions)
|
}
|
||||||
},
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newCheckCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckOptions bundles all options for the 'check' command.
|
// CheckOptions bundles all options for the 'check' command.
|
||||||
|
@ -82,13 +92,6 @@ func (opts *CheckOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.BoolVar(&opts.WithCache, "with-cache", false, "use existing cache, only read uncached data from repository")
|
f.BoolVar(&opts.WithCache, "with-cache", false, "use existing cache, only read uncached data from repository")
|
||||||
}
|
}
|
||||||
|
|
||||||
var checkOptions CheckOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdCheck)
|
|
||||||
checkOptions.AddFlags(cmdCheck.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkFlags(opts CheckOptions) error {
|
func checkFlags(opts CheckOptions) error {
|
||||||
if opts.ReadData && opts.ReadDataSubset != "" {
|
if opts.ReadData && opts.ReadDataSubset != "" {
|
||||||
return errors.Fatal("check flags --read-data and --read-data-subset cannot be used together")
|
return errors.Fatal("check flags --read-data and --read-data-subset cannot be used together")
|
||||||
|
|
|
@ -14,10 +14,12 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdCopy = &cobra.Command{
|
func newCopyCommand() *cobra.Command {
|
||||||
Use: "copy [flags] [snapshotID ...]",
|
var opts CopyOptions
|
||||||
Short: "Copy snapshots from one repository to another",
|
cmd := &cobra.Command{
|
||||||
Long: `
|
Use: "copy [flags] [snapshotID ...]",
|
||||||
|
Short: "Copy snapshots from one repository to another",
|
||||||
|
Long: `
|
||||||
The "copy" command copies one or more snapshots from one repository to another.
|
The "copy" command copies one or more snapshots from one repository to another.
|
||||||
|
|
||||||
NOTE: This process will have to both download (read) and upload (write) the
|
NOTE: This process will have to both download (read) and upload (write) the
|
||||||
|
@ -41,11 +43,19 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runCopy(cmd.Context(), copyOptions, globalOptions, args)
|
return runCopy(cmd.Context(), opts, globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newCopyCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyOptions bundles all options for the copy command.
|
// CopyOptions bundles all options for the copy command.
|
||||||
|
@ -59,13 +69,6 @@ func (opts *CopyOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
var copyOptions CopyOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdCopy)
|
|
||||||
copyOptions.AddFlags(cmdCopy.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func runCopy(ctx context.Context, opts CopyOptions, gopts GlobalOptions, args []string) error {
|
func runCopy(ctx context.Context, opts CopyOptions, gopts GlobalOptions, args []string) error {
|
||||||
secondaryGopts, isFromRepo, err := fillSecondaryGlobalOpts(ctx, opts.secondaryRepoOptions, gopts, "destination")
|
secondaryGopts, isFromRepo, err := fillSecondaryGlobalOpts(ctx, opts.secondaryRepoOptions, gopts, "destination")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -29,17 +29,27 @@ import (
|
||||||
"github.com/restic/restic/internal/restic"
|
"github.com/restic/restic/internal/restic"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdDebug = &cobra.Command{
|
func newDebugCommand() *cobra.Command {
|
||||||
Use: "debug",
|
cmd := &cobra.Command{
|
||||||
Short: "Debug commands",
|
Use: "debug",
|
||||||
GroupID: cmdGroupDefault,
|
Short: "Debug commands",
|
||||||
DisableAutoGenTag: true,
|
GroupID: cmdGroupDefault,
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
cmd.AddCommand(newDebugDumpCommand())
|
||||||
|
cmd.AddCommand(newDebugExamineCommand())
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmdDebugDump = &cobra.Command{
|
func init() {
|
||||||
Use: "dump [indexes|snapshots|all|packs]",
|
cmdRoot.AddCommand(newDebugCommand())
|
||||||
Short: "Dump data structures",
|
}
|
||||||
Long: `
|
|
||||||
|
func newDebugDumpCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "dump [indexes|snapshots|all|packs]",
|
||||||
|
Short: "Dump data structures",
|
||||||
|
Long: `
|
||||||
The "dump" command dumps data structures from the repository as JSON objects. It
|
The "dump" command dumps data structures from the repository as JSON objects. It
|
||||||
is used for debugging purposes only.
|
is used for debugging purposes only.
|
||||||
|
|
||||||
|
@ -52,10 +62,28 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runDebugDump(cmd.Context(), globalOptions, args)
|
return runDebugDump(cmd.Context(), globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDebugExamineCommand() *cobra.Command {
|
||||||
|
var opts DebugExamineOptions
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "examine pack-ID...",
|
||||||
|
Short: "Examine a pack file",
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return runDebugExamine(cmd.Context(), globalOptions, opts, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
type DebugExamineOptions struct {
|
type DebugExamineOptions struct {
|
||||||
|
@ -72,15 +100,6 @@ func (opts *DebugExamineOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.BoolVar(&opts.RepairByte, "repair-byte", false, "try to repair broken blobs by trying bytes")
|
f.BoolVar(&opts.RepairByte, "repair-byte", false, "try to repair broken blobs by trying bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
var debugExamineOpts DebugExamineOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdDebug)
|
|
||||||
cmdDebug.AddCommand(cmdDebugDump)
|
|
||||||
cmdDebug.AddCommand(cmdDebugExamine)
|
|
||||||
debugExamineOpts.AddFlags(cmdDebugExamine.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func prettyPrintJSON(wr io.Writer, item interface{}) error {
|
func prettyPrintJSON(wr io.Writer, item interface{}) error {
|
||||||
buf, err := json.MarshalIndent(item, "", " ")
|
buf, err := json.MarshalIndent(item, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -197,15 +216,6 @@ func runDebugDump(ctx context.Context, gopts GlobalOptions, args []string) error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmdDebugExamine = &cobra.Command{
|
|
||||||
Use: "examine pack-ID...",
|
|
||||||
Short: "Examine a pack file",
|
|
||||||
DisableAutoGenTag: true,
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
return runDebugExamine(cmd.Context(), globalOptions, debugExamineOpts, args)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func tryRepairWithBitflip(ctx context.Context, key *crypto.Key, input []byte, bytewise bool) []byte {
|
func tryRepairWithBitflip(ctx context.Context, key *crypto.Key, input []byte, bytewise bool) []byte {
|
||||||
if bytewise {
|
if bytewise {
|
||||||
Printf(" trying to repair blob by finding a broken byte\n")
|
Printf(" trying to repair blob by finding a broken byte\n")
|
||||||
|
|
|
@ -15,10 +15,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdDiff = &cobra.Command{
|
func newDiffCommand() *cobra.Command {
|
||||||
Use: "diff [flags] snapshotID snapshotID",
|
var opts DiffOptions
|
||||||
Short: "Show differences between two snapshots",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "diff [flags] snapshotID snapshotID",
|
||||||
|
Short: "Show differences between two snapshots",
|
||||||
|
Long: `
|
||||||
The "diff" command shows differences from the first to the second snapshot. The
|
The "diff" command shows differences from the first to the second snapshot. The
|
||||||
first characters in each line display what has happened to a particular file or
|
first characters in each line display what has happened to a particular file or
|
||||||
directory:
|
directory:
|
||||||
|
@ -46,11 +49,19 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runDiff(cmd.Context(), diffOptions, globalOptions, args)
|
return runDiff(cmd.Context(), opts, globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newDiffCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiffOptions collects all options for the diff command.
|
// DiffOptions collects all options for the diff command.
|
||||||
|
@ -62,13 +73,6 @@ func (opts *DiffOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.BoolVar(&opts.ShowMetadata, "metadata", false, "print changes in metadata")
|
f.BoolVar(&opts.ShowMetadata, "metadata", false, "print changes in metadata")
|
||||||
}
|
}
|
||||||
|
|
||||||
var diffOptions DiffOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdDiff)
|
|
||||||
diffOptions.AddFlags(cmdDiff.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadSnapshot(ctx context.Context, be restic.Lister, repo restic.LoaderUnpacked, desc string) (*restic.Snapshot, string, error) {
|
func loadSnapshot(ctx context.Context, be restic.Lister, repo restic.LoaderUnpacked, desc string) (*restic.Snapshot, string, error) {
|
||||||
sn, subfolder, err := restic.FindSnapshot(ctx, be, repo, desc)
|
sn, subfolder, err := restic.FindSnapshot(ctx, be, repo, desc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -16,10 +16,12 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdDump = &cobra.Command{
|
func newDumpCommand() *cobra.Command {
|
||||||
Use: "dump [flags] snapshotID file",
|
var opts DumpOptions
|
||||||
Short: "Print a backed-up file to stdout",
|
cmd := &cobra.Command{
|
||||||
Long: `
|
Use: "dump [flags] snapshotID file",
|
||||||
|
Short: "Print a backed-up file to stdout",
|
||||||
|
Long: `
|
||||||
The "dump" command extracts files from a snapshot from the repository. If a
|
The "dump" command extracts files from a snapshot from the repository. If a
|
||||||
single file is selected, it prints its contents to stdout. Folders are output
|
single file is selected, it prints its contents to stdout. Folders are output
|
||||||
as a tar (default) or zip file containing the contents of the specified folder.
|
as a tar (default) or zip file containing the contents of the specified folder.
|
||||||
|
@ -41,11 +43,19 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runDump(cmd.Context(), dumpOptions, globalOptions, args)
|
return runDump(cmd.Context(), opts, globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newDumpCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// DumpOptions collects all options for the dump command.
|
// DumpOptions collects all options for the dump command.
|
||||||
|
@ -61,13 +71,6 @@ func (opts *DumpOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.StringVarP(&opts.Target, "target", "t", "", "write the output to target `path`")
|
f.StringVarP(&opts.Target, "target", "t", "", "write the output to target `path`")
|
||||||
}
|
}
|
||||||
|
|
||||||
var dumpOptions DumpOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdDump)
|
|
||||||
dumpOptions.AddFlags(cmdDump.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func splitPath(p string) []string {
|
func splitPath(p string) []string {
|
||||||
d, f := path.Split(p)
|
d, f := path.Split(p)
|
||||||
if d == "" || d == "/" {
|
if d == "" || d == "/" {
|
||||||
|
|
|
@ -10,10 +10,11 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var featuresCmd = &cobra.Command{
|
func newFeaturesCommand() *cobra.Command {
|
||||||
Use: "features",
|
cmd := &cobra.Command{
|
||||||
Short: "Print list of feature flags",
|
Use: "features",
|
||||||
Long: `
|
Short: "Print list of feature flags",
|
||||||
|
Long: `
|
||||||
The "features" command prints a list of supported feature flags.
|
The "features" command prints a list of supported feature flags.
|
||||||
|
|
||||||
To pass feature flags to restic, set the RESTIC_FEATURES environment variable
|
To pass feature flags to restic, set the RESTIC_FEATURES environment variable
|
||||||
|
@ -31,29 +32,32 @@ EXIT STATUS
|
||||||
Exit status is 0 if the command was successful.
|
Exit status is 0 if the command was successful.
|
||||||
Exit status is 1 if there was any error.
|
Exit status is 1 if there was any error.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupAdvanced,
|
GroupID: cmdGroupAdvanced,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(_ *cobra.Command, args []string) error {
|
RunE: func(_ *cobra.Command, args []string) error {
|
||||||
if len(args) != 0 {
|
if len(args) != 0 {
|
||||||
return errors.Fatal("the feature command expects no arguments")
|
return errors.Fatal("the feature command expects no arguments")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("All Feature Flags:\n")
|
fmt.Printf("All Feature Flags:\n")
|
||||||
flags := feature.Flag.List()
|
flags := feature.Flag.List()
|
||||||
|
|
||||||
tab := table.New()
|
tab := table.New()
|
||||||
tab.AddColumn("Name", "{{ .Name }}")
|
tab.AddColumn("Name", "{{ .Name }}")
|
||||||
tab.AddColumn("Type", "{{ .Type }}")
|
tab.AddColumn("Type", "{{ .Type }}")
|
||||||
tab.AddColumn("Default", "{{ .Default }}")
|
tab.AddColumn("Default", "{{ .Default }}")
|
||||||
tab.AddColumn("Description", "{{ .Description }}")
|
tab.AddColumn("Description", "{{ .Description }}")
|
||||||
|
|
||||||
for _, flag := range flags {
|
for _, flag := range flags {
|
||||||
tab.AddRow(flag)
|
tab.AddRow(flag)
|
||||||
}
|
}
|
||||||
return tab.Write(globalOptions.stdout)
|
return tab.Write(globalOptions.stdout)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdRoot.AddCommand(featuresCmd)
|
cmdRoot.AddCommand(newFeaturesCommand())
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,19 @@ import (
|
||||||
"github.com/restic/restic/internal/walker"
|
"github.com/restic/restic/internal/walker"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdFind = &cobra.Command{
|
func newFindCommand() *cobra.Command {
|
||||||
Use: "find [flags] PATTERN...",
|
var opts FindOptions
|
||||||
Short: "Find a file, a directory or restic IDs",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "find [flags] PATTERN...",
|
||||||
|
Short: "Find a file, a directory or restic IDs",
|
||||||
|
Long: `
|
||||||
The "find" command searches for files or directories in snapshots stored in the
|
The "find" command searches for files or directories in snapshots stored in the
|
||||||
repo.
|
repo.
|
||||||
It can also be used to search for restic blobs or trees for troubleshooting.
|
It can also be used to search for restic blobs or trees for troubleshooting.
|
||||||
The default sort option for the snapshots is youngest to oldest. To sort the
|
The default sort option for the snapshots is youngest to oldest. To sort the
|
||||||
output from oldest to youngest specify --reverse.`,
|
output from oldest to youngest specify --reverse.`,
|
||||||
Example: `restic find config.json
|
Example: `restic find config.json
|
||||||
restic find --json "*.yml" "*.json"
|
restic find --json "*.yml" "*.json"
|
||||||
restic find --json --blob 420f620f b46ebe8a ddd38656
|
restic find --json --blob 420f620f b46ebe8a ddd38656
|
||||||
restic find --show-pack-id --blob 420f620f
|
restic find --show-pack-id --blob 420f620f
|
||||||
|
@ -42,11 +45,19 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runFind(cmd.Context(), findOptions, globalOptions, args)
|
return runFind(cmd.Context(), opts, globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newFindCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindOptions bundles all options for the find command.
|
// FindOptions bundles all options for the find command.
|
||||||
|
@ -79,13 +90,6 @@ func (opts *FindOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
var findOptions FindOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdFind)
|
|
||||||
findOptions.AddFlags(cmdFind.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
type findPattern struct {
|
type findPattern struct {
|
||||||
oldest, newest time.Time
|
oldest, newest time.Time
|
||||||
pattern []string
|
pattern []string
|
||||||
|
|
|
@ -14,10 +14,14 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdForget = &cobra.Command{
|
func newForgetCommand() *cobra.Command {
|
||||||
Use: "forget [flags] [snapshot ID] [...]",
|
var opts ForgetOptions
|
||||||
Short: "Remove snapshots from the repository",
|
var pruneOpts PruneOptions
|
||||||
Long: `
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "forget [flags] [snapshot ID] [...]",
|
||||||
|
Short: "Remove snapshots from the repository",
|
||||||
|
Long: `
|
||||||
The "forget" command removes snapshots according to a policy. All snapshots are
|
The "forget" command removes snapshots according to a policy. All snapshots are
|
||||||
first divided into groups according to "--group-by", and after that the policy
|
first divided into groups according to "--group-by", and after that the policy
|
||||||
specified by the "--keep-*" options is applied to each group individually.
|
specified by the "--keep-*" options is applied to each group individually.
|
||||||
|
@ -41,13 +45,22 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
term, cancel := setupTermstatus()
|
term, cancel := setupTermstatus()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return runForget(cmd.Context(), forgetOptions, forgetPruneOptions, globalOptions, term, args)
|
return runForget(cmd.Context(), opts, pruneOpts, globalOptions, term, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
pruneOpts.AddLimitedFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newForgetCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
type ForgetPolicyCount int
|
type ForgetPolicyCount int
|
||||||
|
@ -145,15 +158,6 @@ func (opts *ForgetOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.SortFlags = false
|
f.SortFlags = false
|
||||||
}
|
}
|
||||||
|
|
||||||
var forgetOptions ForgetOptions
|
|
||||||
var forgetPruneOptions PruneOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdForget)
|
|
||||||
forgetOptions.AddFlags(cmdForget.Flags())
|
|
||||||
forgetPruneOptions.AddLimitedFlags(cmdForget.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyForgetOptions(opts *ForgetOptions) error {
|
func verifyForgetOptions(opts *ForgetOptions) error {
|
||||||
if opts.Last < -1 || opts.Hourly < -1 || opts.Daily < -1 || opts.Weekly < -1 ||
|
if opts.Last < -1 || opts.Hourly < -1 || opts.Daily < -1 || opts.Weekly < -1 ||
|
||||||
opts.Monthly < -1 || opts.Yearly < -1 {
|
opts.Monthly < -1 || opts.Yearly < -1 {
|
||||||
|
|
|
@ -11,10 +11,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdGenerate = &cobra.Command{
|
func newGenerateCommand() *cobra.Command {
|
||||||
Use: "generate [flags]",
|
var opts generateOptions
|
||||||
Short: "Generate manual pages and auto-completion files (bash, fish, zsh, powershell)",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "generate [flags]",
|
||||||
|
Short: "Generate manual pages and auto-completion files (bash, fish, zsh, powershell)",
|
||||||
|
Long: `
|
||||||
The "generate" command writes automatically generated files (like the man pages
|
The "generate" command writes automatically generated files (like the man pages
|
||||||
and the auto-completion files for bash, fish and zsh).
|
and the auto-completion files for bash, fish and zsh).
|
||||||
|
|
||||||
|
@ -24,10 +27,17 @@ EXIT STATUS
|
||||||
Exit status is 0 if the command was successful.
|
Exit status is 0 if the command was successful.
|
||||||
Exit status is 1 if there was any error.
|
Exit status is 1 if there was any error.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(_ *cobra.Command, args []string) error {
|
RunE: func(_ *cobra.Command, args []string) error {
|
||||||
return runGenerate(genOpts, args)
|
return runGenerate(opts, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newGenerateCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
type generateOptions struct {
|
type generateOptions struct {
|
||||||
|
@ -46,13 +56,6 @@ func (opts *generateOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.StringVar(&opts.PowerShellCompletionFile, "powershell-completion", "", "write powershell completion `file` (`-` for stdout)")
|
f.StringVar(&opts.PowerShellCompletionFile, "powershell-completion", "", "write powershell completion `file` (`-` for stdout)")
|
||||||
}
|
}
|
||||||
|
|
||||||
var genOpts generateOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdGenerate)
|
|
||||||
genOpts.AddFlags(cmdGenerate.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeManpages(dir string) error {
|
func writeManpages(dir string) error {
|
||||||
// use a fixed date for the man pages so that generating them is deterministic
|
// use a fixed date for the man pages so that generating them is deterministic
|
||||||
date, err := time.Parse("Jan 2006", "Jan 2017")
|
date, err := time.Parse("Jan 2006", "Jan 2017")
|
||||||
|
|
|
@ -15,10 +15,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdInit = &cobra.Command{
|
func newInitCommand() *cobra.Command {
|
||||||
Use: "init",
|
var opts InitOptions
|
||||||
Short: "Initialize a new repository",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "init",
|
||||||
|
Short: "Initialize a new repository",
|
||||||
|
Long: `
|
||||||
The "init" command initializes a new repository.
|
The "init" command initializes a new repository.
|
||||||
|
|
||||||
EXIT STATUS
|
EXIT STATUS
|
||||||
|
@ -27,11 +30,18 @@ EXIT STATUS
|
||||||
Exit status is 0 if the command was successful.
|
Exit status is 0 if the command was successful.
|
||||||
Exit status is 1 if there was any error.
|
Exit status is 1 if there was any error.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runInit(cmd.Context(), initOptions, globalOptions, args)
|
return runInit(cmd.Context(), opts, globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newInitCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitOptions bundles all options for the init command.
|
// InitOptions bundles all options for the init command.
|
||||||
|
@ -47,13 +57,6 @@ func (opts *InitOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.StringVar(&opts.RepositoryVersion, "repository-version", "stable", "repository format version to use, allowed values are a format version, 'latest' and 'stable'")
|
f.StringVar(&opts.RepositoryVersion, "repository-version", "stable", "repository format version to use, allowed values are a format version, 'latest' and 'stable'")
|
||||||
}
|
}
|
||||||
|
|
||||||
var initOptions InitOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdInit)
|
|
||||||
initOptions.AddFlags(cmdInit.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func runInit(ctx context.Context, opts InitOptions, gopts GlobalOptions, args []string) error {
|
func runInit(ctx context.Context, opts InitOptions, gopts GlobalOptions, args []string) error {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
return errors.Fatal("the init command expects no arguments, only options - please see `restic help init` for usage and flags")
|
return errors.Fatal("the init command expects no arguments, only options - please see `restic help init` for usage and flags")
|
||||||
|
|
|
@ -10,10 +10,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdKeyAdd = &cobra.Command{
|
func newKeyAddCommand() *cobra.Command {
|
||||||
Use: "add",
|
var opts KeyAddOptions
|
||||||
Short: "Add a new key (password) to the repository; returns the new key ID",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "add",
|
||||||
|
Short: "Add a new key (password) to the repository; returns the new key ID",
|
||||||
|
Long: `
|
||||||
The "add" sub-command creates a new key and validates the key. Returns the new key ID.
|
The "add" sub-command creates a new key and validates the key. Returns the new key ID.
|
||||||
|
|
||||||
EXIT STATUS
|
EXIT STATUS
|
||||||
|
@ -25,7 +28,14 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return runKeyAdd(cmd.Context(), globalOptions, opts, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.Add(cmd.Flags())
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
type KeyAddOptions struct {
|
type KeyAddOptions struct {
|
||||||
|
@ -43,13 +53,7 @@ func (opts *KeyAddOptions) Add(flags *pflag.FlagSet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdKey.AddCommand(cmdKeyAdd)
|
cmdKey.AddCommand(newKeyAddCommand())
|
||||||
|
|
||||||
var keyAddOpts KeyAddOptions
|
|
||||||
keyAddOpts.Add(cmdKeyAdd.Flags())
|
|
||||||
cmdKeyAdd.RunE = func(cmd *cobra.Command, args []string) error {
|
|
||||||
return runKeyAdd(cmd.Context(), globalOptions, keyAddOpts, args)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runKeyAdd(ctx context.Context, gopts GlobalOptions, opts KeyAddOptions, args []string) error {
|
func runKeyAdd(ctx context.Context, gopts GlobalOptions, opts KeyAddOptions, args []string) error {
|
||||||
|
|
|
@ -12,10 +12,11 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdKeyList = &cobra.Command{
|
func newKeyListCommand() *cobra.Command {
|
||||||
Use: "list",
|
cmd := &cobra.Command{
|
||||||
Short: "List keys (passwords)",
|
Use: "list",
|
||||||
Long: `
|
Short: "List keys (passwords)",
|
||||||
|
Long: `
|
||||||
The "list" sub-command lists all the keys (passwords) associated with the repository.
|
The "list" sub-command lists all the keys (passwords) associated with the repository.
|
||||||
Returns the key ID, username, hostname, created time and if it's the current key being
|
Returns the key ID, username, hostname, created time and if it's the current key being
|
||||||
used to access the repository.
|
used to access the repository.
|
||||||
|
@ -29,14 +30,16 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runKeyList(cmd.Context(), globalOptions, args)
|
return runKeyList(cmd.Context(), globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdKey.AddCommand(cmdKeyList)
|
cmdKey.AddCommand(newKeyListCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
func runKeyList(ctx context.Context, gopts GlobalOptions, args []string) error {
|
func runKeyList(ctx context.Context, gopts GlobalOptions, args []string) error {
|
||||||
|
|
|
@ -7,12 +7,16 @@ import (
|
||||||
"github.com/restic/restic/internal/errors"
|
"github.com/restic/restic/internal/errors"
|
||||||
"github.com/restic/restic/internal/repository"
|
"github.com/restic/restic/internal/repository"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdKeyPasswd = &cobra.Command{
|
func newKeyPasswdCommand() *cobra.Command {
|
||||||
Use: "passwd",
|
var opts KeyPasswdOptions
|
||||||
Short: "Change key (password); creates a new key ID and removes the old key ID, returns new key ID",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "passwd",
|
||||||
|
Short: "Change key (password); creates a new key ID and removes the old key ID, returns new key ID",
|
||||||
|
Long: `
|
||||||
The "passwd" sub-command creates a new key, validates the key and remove the old key ID.
|
The "passwd" sub-command creates a new key, validates the key and remove the old key ID.
|
||||||
Returns the new key ID.
|
Returns the new key ID.
|
||||||
|
|
||||||
|
@ -25,21 +29,26 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return runKeyPasswd(cmd.Context(), globalOptions, opts, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdKey.AddCommand(newKeyPasswdCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
type KeyPasswdOptions struct {
|
type KeyPasswdOptions struct {
|
||||||
KeyAddOptions
|
KeyAddOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func (opts *KeyPasswdOptions) AddFlags(flags *pflag.FlagSet) {
|
||||||
cmdKey.AddCommand(cmdKeyPasswd)
|
opts.KeyAddOptions.Add(flags)
|
||||||
|
|
||||||
var keyPasswdOpts KeyPasswdOptions
|
|
||||||
keyPasswdOpts.KeyAddOptions.Add(cmdKeyPasswd.Flags())
|
|
||||||
cmdKeyPasswd.RunE = func(cmd *cobra.Command, args []string) error {
|
|
||||||
return runKeyPasswd(cmd.Context(), globalOptions, keyPasswdOpts, args)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runKeyPasswd(ctx context.Context, gopts GlobalOptions, opts KeyPasswdOptions, args []string) error {
|
func runKeyPasswd(ctx context.Context, gopts GlobalOptions, opts KeyPasswdOptions, args []string) error {
|
||||||
|
|
|
@ -10,10 +10,11 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdKeyRemove = &cobra.Command{
|
func newKeyRemoveCommand() *cobra.Command {
|
||||||
Use: "remove [ID]",
|
cmd := &cobra.Command{
|
||||||
Short: "Remove key ID (password) from the repository.",
|
Use: "remove [ID]",
|
||||||
Long: `
|
Short: "Remove key ID (password) from the repository.",
|
||||||
|
Long: `
|
||||||
The "remove" sub-command removes the selected key ID. The "remove" command does not allow
|
The "remove" sub-command removes the selected key ID. The "remove" command does not allow
|
||||||
removing the current key being used to access the repository.
|
removing the current key being used to access the repository.
|
||||||
|
|
||||||
|
@ -26,14 +27,16 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runKeyRemove(cmd.Context(), globalOptions, args)
|
return runKeyRemove(cmd.Context(), globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdKey.AddCommand(cmdKeyRemove)
|
cmdKey.AddCommand(newKeyRemoveCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
func runKeyRemove(ctx context.Context, gopts GlobalOptions, args []string) error {
|
func runKeyRemove(ctx context.Context, gopts GlobalOptions, args []string) error {
|
||||||
|
|
|
@ -11,13 +11,14 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var listAllowedArgs = []string{"blobs", "packs", "index", "snapshots", "keys", "locks"}
|
func newListCommand() *cobra.Command {
|
||||||
var listAllowedArgsUseString = strings.Join(listAllowedArgs, "|")
|
var listAllowedArgs = []string{"blobs", "packs", "index", "snapshots", "keys", "locks"}
|
||||||
|
var listAllowedArgsUseString = strings.Join(listAllowedArgs, "|")
|
||||||
|
|
||||||
var cmdList = &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "list [flags] [" + listAllowedArgsUseString + "]",
|
Use: "list [flags] [" + listAllowedArgsUseString + "]",
|
||||||
Short: "List objects in the repository",
|
Short: "List objects in the repository",
|
||||||
Long: `
|
Long: `
|
||||||
The "list" command allows listing objects in the repository based on type.
|
The "list" command allows listing objects in the repository based on type.
|
||||||
|
|
||||||
EXIT STATUS
|
EXIT STATUS
|
||||||
|
@ -29,17 +30,19 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runList(cmd.Context(), globalOptions, args)
|
return runList(cmd.Context(), globalOptions, args)
|
||||||
},
|
},
|
||||||
ValidArgs: listAllowedArgs,
|
ValidArgs: listAllowedArgs,
|
||||||
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
|
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdRoot.AddCommand(cmdList)
|
cmdRoot.AddCommand(newListCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
func runList(ctx context.Context, gopts GlobalOptions, args []string) error {
|
func runList(ctx context.Context, gopts GlobalOptions, args []string) error {
|
||||||
|
|
|
@ -21,10 +21,13 @@ import (
|
||||||
"github.com/restic/restic/internal/walker"
|
"github.com/restic/restic/internal/walker"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdLs = &cobra.Command{
|
func newLsCommand() *cobra.Command {
|
||||||
Use: "ls [flags] snapshotID [dir...]",
|
var opts LsOptions
|
||||||
Short: "List files in a snapshot",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "ls [flags] snapshotID [dir...]",
|
||||||
|
Short: "List files in a snapshot",
|
||||||
|
Long: `
|
||||||
The "ls" command lists files and directories in a snapshot.
|
The "ls" command lists files and directories in a snapshot.
|
||||||
|
|
||||||
The special snapshot ID "latest" can be used to list files and
|
The special snapshot ID "latest" can be used to list files and
|
||||||
|
@ -53,11 +56,18 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runLs(cmd.Context(), lsOptions, globalOptions, args)
|
return runLs(cmd.Context(), opts, globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newLsCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// LsOptions collects all options for the ls command.
|
// LsOptions collects all options for the ls command.
|
||||||
|
@ -81,13 +91,6 @@ func (opts *LsOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.BoolVar(&opts.Reverse, "reverse", false, "reverse sorted output")
|
f.BoolVar(&opts.Reverse, "reverse", false, "reverse sorted output")
|
||||||
}
|
}
|
||||||
|
|
||||||
var lsOptions LsOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdLs)
|
|
||||||
lsOptions.AddFlags(cmdLs.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
type lsPrinter interface {
|
type lsPrinter interface {
|
||||||
Snapshot(sn *restic.Snapshot) error
|
Snapshot(sn *restic.Snapshot) error
|
||||||
Node(path string, node *restic.Node, isPrefixDirectory bool) error
|
Node(path string, node *restic.Node, isPrefixDirectory bool) error
|
||||||
|
|
|
@ -12,10 +12,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdMigrate = &cobra.Command{
|
func newMigrateCommand() *cobra.Command {
|
||||||
Use: "migrate [flags] [migration name] [...]",
|
var opts MigrateOptions
|
||||||
Short: "Apply migrations",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "migrate [flags] [migration name] [...]",
|
||||||
|
Short: "Apply migrations",
|
||||||
|
Long: `
|
||||||
The "migrate" command checks which migrations can be applied for a repository
|
The "migrate" command checks which migrations can be applied for a repository
|
||||||
and prints a list with available migration names. If one or more migration
|
and prints a list with available migration names. If one or more migration
|
||||||
names are specified, these migrations are applied.
|
names are specified, these migrations are applied.
|
||||||
|
@ -29,13 +32,21 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
term, cancel := setupTermstatus()
|
term, cancel := setupTermstatus()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return runMigrate(cmd.Context(), migrateOptions, globalOptions, args, term)
|
return runMigrate(cmd.Context(), opts, globalOptions, args, term)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newMigrateCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// MigrateOptions bundles all options for the 'check' command.
|
// MigrateOptions bundles all options for the 'check' command.
|
||||||
|
@ -47,13 +58,6 @@ func (opts *MigrateOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.BoolVarP(&opts.Force, "force", "f", false, `apply a migration a second time`)
|
f.BoolVarP(&opts.Force, "force", "f", false, `apply a migration a second time`)
|
||||||
}
|
}
|
||||||
|
|
||||||
var migrateOptions MigrateOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdMigrate)
|
|
||||||
migrateOptions.AddFlags(cmdMigrate.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkMigrations(ctx context.Context, repo restic.Repository, printer progress.Printer) error {
|
func checkMigrations(ctx context.Context, repo restic.Repository, printer progress.Printer) error {
|
||||||
printer.P("available migrations:\n")
|
printer.P("available migrations:\n")
|
||||||
found := false
|
found := false
|
||||||
|
|
|
@ -22,10 +22,13 @@ import (
|
||||||
"github.com/anacrolix/fuse/fs"
|
"github.com/anacrolix/fuse/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdMount = &cobra.Command{
|
func newMountCommand() *cobra.Command {
|
||||||
Use: "mount [flags] mountpoint",
|
var opts MountOptions
|
||||||
Short: "Mount the repository",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "mount [flags] mountpoint",
|
||||||
|
Short: "Mount the repository",
|
||||||
|
Long: `
|
||||||
The "mount" command mounts the repository via fuse to a directory. This is a
|
The "mount" command mounts the repository via fuse to a directory. This is a
|
||||||
read-only mount.
|
read-only mount.
|
||||||
|
|
||||||
|
@ -70,11 +73,19 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runMount(cmd.Context(), mountOptions, globalOptions, args)
|
return runMount(cmd.Context(), opts, globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newMountCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// MountOptions collects all options for the mount command.
|
// MountOptions collects all options for the mount command.
|
||||||
|
@ -100,13 +111,6 @@ func (opts *MountOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
_ = f.MarkDeprecated("snapshot-template", "use --time-template")
|
_ = f.MarkDeprecated("snapshot-template", "use --time-template")
|
||||||
}
|
}
|
||||||
|
|
||||||
var mountOptions MountOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdMount)
|
|
||||||
mountOptions.AddFlags(cmdMount.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func runMount(ctx context.Context, opts MountOptions, gopts GlobalOptions, args []string) error {
|
func runMount(ctx context.Context, opts MountOptions, gopts GlobalOptions, args []string) error {
|
||||||
if opts.TimeTemplate == "" {
|
if opts.TimeTemplate == "" {
|
||||||
return errors.Fatal("time template string cannot be empty")
|
return errors.Fatal("time template string cannot be empty")
|
||||||
|
|
|
@ -8,10 +8,11 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var optionsCmd = &cobra.Command{
|
func newOptionsCommand() *cobra.Command {
|
||||||
Use: "options",
|
cmd := &cobra.Command{
|
||||||
Short: "Print list of extended options",
|
Use: "options",
|
||||||
Long: `
|
Short: "Print list of extended options",
|
||||||
|
Long: `
|
||||||
The "options" command prints a list of extended options.
|
The "options" command prints a list of extended options.
|
||||||
|
|
||||||
EXIT STATUS
|
EXIT STATUS
|
||||||
|
@ -20,22 +21,24 @@ EXIT STATUS
|
||||||
Exit status is 0 if the command was successful.
|
Exit status is 0 if the command was successful.
|
||||||
Exit status is 1 if there was any error.
|
Exit status is 1 if there was any error.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupAdvanced,
|
GroupID: cmdGroupAdvanced,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
Run: func(_ *cobra.Command, _ []string) {
|
Run: func(_ *cobra.Command, _ []string) {
|
||||||
fmt.Printf("All Extended Options:\n")
|
fmt.Printf("All Extended Options:\n")
|
||||||
var maxLen int
|
var maxLen int
|
||||||
for _, opt := range options.List() {
|
for _, opt := range options.List() {
|
||||||
if l := len(opt.Namespace + "." + opt.Name); l > maxLen {
|
if l := len(opt.Namespace + "." + opt.Name); l > maxLen {
|
||||||
maxLen = l
|
maxLen = l
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
for _, opt := range options.List() {
|
||||||
for _, opt := range options.List() {
|
fmt.Printf(" %*s %s\n", -maxLen, opt.Namespace+"."+opt.Name, opt.Text)
|
||||||
fmt.Printf(" %*s %s\n", -maxLen, opt.Namespace+"."+opt.Name, opt.Text)
|
}
|
||||||
}
|
},
|
||||||
},
|
}
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdRoot.AddCommand(optionsCmd)
|
cmdRoot.AddCommand(newOptionsCommand())
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdPrune = &cobra.Command{
|
func newPruneCommand() *cobra.Command {
|
||||||
Use: "prune [flags]",
|
var opts PruneOptions
|
||||||
Short: "Remove unneeded data from the repository",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "prune [flags]",
|
||||||
|
Short: "Remove unneeded data from the repository",
|
||||||
|
Long: `
|
||||||
The "prune" command checks the repository and removes data that is not
|
The "prune" command checks the repository and removes data that is not
|
||||||
referenced and therefore not needed any more.
|
referenced and therefore not needed any more.
|
||||||
|
|
||||||
|
@ -35,13 +38,21 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
term, cancel := setupTermstatus()
|
term, cancel := setupTermstatus()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return runPrune(cmd.Context(), pruneOptions, globalOptions, term)
|
return runPrune(cmd.Context(), opts, globalOptions, term)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newPruneCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// PruneOptions collects all options for the cleanup command.
|
// PruneOptions collects all options for the cleanup command.
|
||||||
|
@ -76,13 +87,6 @@ func (opts *PruneOptions) AddLimitedFlags(f *pflag.FlagSet) {
|
||||||
f.BoolVar(&opts.RepackUncompressed, "repack-uncompressed", false, "repack all uncompressed data")
|
f.BoolVar(&opts.RepackUncompressed, "repack-uncompressed", false, "repack all uncompressed data")
|
||||||
}
|
}
|
||||||
|
|
||||||
var pruneOptions PruneOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdPrune)
|
|
||||||
pruneOptions.AddFlags(cmdPrune.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyPruneOptions(opts *PruneOptions) error {
|
func verifyPruneOptions(opts *PruneOptions) error {
|
||||||
opts.MaxRepackBytes = math.MaxUint64
|
opts.MaxRepackBytes = math.MaxUint64
|
||||||
if len(opts.MaxRepackSize) > 0 {
|
if len(opts.MaxRepackSize) > 0 {
|
||||||
|
|
|
@ -11,10 +11,11 @@ import (
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdRecover = &cobra.Command{
|
func newRecoverCommand() *cobra.Command {
|
||||||
Use: "recover [flags]",
|
cmd := &cobra.Command{
|
||||||
Short: "Recover data from the repository not referenced by snapshots",
|
Use: "recover [flags]",
|
||||||
Long: `
|
Short: "Recover data from the repository not referenced by snapshots",
|
||||||
|
Long: `
|
||||||
The "recover" command builds a new snapshot from all directories it can find in
|
The "recover" command builds a new snapshot from all directories it can find in
|
||||||
the raw data of the repository which are not referenced in an existing snapshot.
|
the raw data of the repository which are not referenced in an existing snapshot.
|
||||||
It can be used if, for example, a snapshot has been removed by accident with "forget".
|
It can be used if, for example, a snapshot has been removed by accident with "forget".
|
||||||
|
@ -28,15 +29,17 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
return runRecover(cmd.Context(), globalOptions)
|
return runRecover(cmd.Context(), globalOptions)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdRoot.AddCommand(cmdRecover)
|
cmdRoot.AddCommand(newRecoverCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRecover(ctx context.Context, gopts GlobalOptions) error {
|
func runRecover(ctx context.Context, gopts GlobalOptions) error {
|
||||||
|
|
|
@ -9,10 +9,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdRepairIndex = &cobra.Command{
|
func newRepairIndexCommand() *cobra.Command {
|
||||||
Use: "index [flags]",
|
var opts RepairIndexOptions
|
||||||
Short: "Build a new index",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "index [flags]",
|
||||||
|
Short: "Build a new index",
|
||||||
|
Long: `
|
||||||
The "repair index" command creates a new index based on the pack files in the
|
The "repair index" command creates a new index based on the pack files in the
|
||||||
repository.
|
repository.
|
||||||
|
|
||||||
|
@ -25,21 +28,20 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
term, cancel := setupTermstatus()
|
term, cancel := setupTermstatus()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return runRebuildIndex(cmd.Context(), repairIndexOptions, globalOptions, term)
|
return runRebuildIndex(cmd.Context(), opts, globalOptions, term)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmdRebuildIndex = &cobra.Command{
|
func init() {
|
||||||
Use: "rebuild-index [flags]",
|
cmdRepair.AddCommand(newRepairIndexCommand())
|
||||||
Short: cmdRepairIndex.Short,
|
|
||||||
Long: cmdRepairIndex.Long,
|
|
||||||
Deprecated: `Use "repair index" instead`,
|
|
||||||
DisableAutoGenTag: true,
|
|
||||||
RunE: cmdRepairIndex.RunE,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RepairIndexOptions collects all options for the repair index command.
|
// RepairIndexOptions collects all options for the repair index command.
|
||||||
|
@ -51,14 +53,32 @@ func (opts *RepairIndexOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.BoolVar(&opts.ReadAllPacks, "read-all-packs", false, "read all pack files to generate new index from scratch")
|
f.BoolVar(&opts.ReadAllPacks, "read-all-packs", false, "read all pack files to generate new index from scratch")
|
||||||
}
|
}
|
||||||
|
|
||||||
var repairIndexOptions RepairIndexOptions
|
func newRebuildIndexCommand() *cobra.Command {
|
||||||
|
var opts RepairIndexOptions
|
||||||
|
|
||||||
|
replacement := newRepairIndexCommand()
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "rebuild-index [flags]",
|
||||||
|
Short: replacement.Short,
|
||||||
|
Long: replacement.Long,
|
||||||
|
Deprecated: `Use "repair index" instead`,
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
// must create a new instance of the run function as it captures opts
|
||||||
|
// by reference
|
||||||
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
|
term, cancel := setupTermstatus()
|
||||||
|
defer cancel()
|
||||||
|
return runRebuildIndex(cmd.Context(), opts, globalOptions, term)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdRepair.AddCommand(cmdRepairIndex)
|
|
||||||
repairIndexOptions.AddFlags(cmdRepairIndex.Flags())
|
|
||||||
// add alias for old name
|
// add alias for old name
|
||||||
cmdRoot.AddCommand(cmdRebuildIndex)
|
cmdRoot.AddCommand(newRebuildIndexCommand())
|
||||||
repairIndexOptions.AddFlags(cmdRebuildIndex.Flags())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRebuildIndex(ctx context.Context, opts RepairIndexOptions, gopts GlobalOptions, term *termstatus.Terminal) error {
|
func runRebuildIndex(ctx context.Context, opts RepairIndexOptions, gopts GlobalOptions, term *termstatus.Terminal) error {
|
||||||
|
|
|
@ -13,10 +13,11 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdRepairPacks = &cobra.Command{
|
func newRepairPacksCommand() *cobra.Command {
|
||||||
Use: "packs [packIDs...]",
|
cmd := &cobra.Command{
|
||||||
Short: "Salvage damaged pack files",
|
Use: "packs [packIDs...]",
|
||||||
Long: `
|
Short: "Salvage damaged pack files",
|
||||||
|
Long: `
|
||||||
The "repair packs" command extracts intact blobs from the specified pack files, rebuilds
|
The "repair packs" command extracts intact blobs from the specified pack files, rebuilds
|
||||||
the index to remove the damaged pack files and removes the pack files from the repository.
|
the index to remove the damaged pack files and removes the pack files from the repository.
|
||||||
|
|
||||||
|
@ -29,16 +30,18 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
term, cancel := setupTermstatus()
|
term, cancel := setupTermstatus()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return runRepairPacks(cmd.Context(), globalOptions, term, args)
|
return runRepairPacks(cmd.Context(), globalOptions, term, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdRepair.AddCommand(cmdRepairPacks)
|
cmdRepair.AddCommand(newRepairPacksCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRepairPacks(ctx context.Context, gopts GlobalOptions, term *termstatus.Terminal, args []string) error {
|
func runRepairPacks(ctx context.Context, gopts GlobalOptions, term *termstatus.Terminal, args []string) error {
|
||||||
|
|
|
@ -11,10 +11,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdRepairSnapshots = &cobra.Command{
|
func newRepairSnapshotsCommand() *cobra.Command {
|
||||||
Use: "snapshots [flags] [snapshot ID] [...]",
|
var opts RepairOptions
|
||||||
Short: "Repair snapshots",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "snapshots [flags] [snapshot ID] [...]",
|
||||||
|
Short: "Repair snapshots",
|
||||||
|
Long: `
|
||||||
The "repair snapshots" command repairs broken snapshots. It scans the given
|
The "repair snapshots" command repairs broken snapshots. It scans the given
|
||||||
snapshots and generates new ones with damaged directories and file contents
|
snapshots and generates new ones with damaged directories and file contents
|
||||||
removed. If the broken snapshots are deleted, a prune run will be able to
|
removed. If the broken snapshots are deleted, a prune run will be able to
|
||||||
|
@ -44,10 +47,18 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runRepairSnapshots(cmd.Context(), globalOptions, repairSnapshotOptions, args)
|
return runRepairSnapshots(cmd.Context(), globalOptions, opts, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRepair.AddCommand(newRepairSnapshotsCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// RepairOptions collects all options for the repair command.
|
// RepairOptions collects all options for the repair command.
|
||||||
|
@ -65,13 +76,6 @@ func (opts *RepairOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
var repairSnapshotOptions RepairOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRepair.AddCommand(cmdRepairSnapshots)
|
|
||||||
repairSnapshotOptions.AddFlags(cmdRepairSnapshots.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func runRepairSnapshots(ctx context.Context, gopts GlobalOptions, opts RepairOptions, args []string) error {
|
func runRepairSnapshots(ctx context.Context, gopts GlobalOptions, opts RepairOptions, args []string) error {
|
||||||
ctx, repo, unlock, err := openWithExclusiveLock(ctx, gopts, opts.DryRun)
|
ctx, repo, unlock, err := openWithExclusiveLock(ctx, gopts, opts.DryRun)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -18,10 +18,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdRestore = &cobra.Command{
|
func newRestoreCommand() *cobra.Command {
|
||||||
Use: "restore [flags] snapshotID",
|
var opts RestoreOptions
|
||||||
Short: "Extract the data from a snapshot",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "restore [flags] snapshotID",
|
||||||
|
Short: "Extract the data from a snapshot",
|
||||||
|
Long: `
|
||||||
The "restore" command extracts the data from a snapshot from the repository to
|
The "restore" command extracts the data from a snapshot from the repository to
|
||||||
a directory.
|
a directory.
|
||||||
|
|
||||||
|
@ -40,13 +43,21 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
term, cancel := setupTermstatus()
|
term, cancel := setupTermstatus()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return runRestore(cmd.Context(), restoreOptions, globalOptions, term, args)
|
return runRestore(cmd.Context(), opts, globalOptions, term, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newRestoreCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// RestoreOptions collects all options for the restore command.
|
// RestoreOptions collects all options for the restore command.
|
||||||
|
@ -81,13 +92,6 @@ func (opts *RestoreOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.BoolVar(&opts.Delete, "delete", false, "delete files from target directory if they do not exist in snapshot. Use '--dry-run -vv' to check what would be deleted")
|
f.BoolVar(&opts.Delete, "delete", false, "delete files from target directory if they do not exist in snapshot. Use '--dry-run -vv' to check what would be deleted")
|
||||||
}
|
}
|
||||||
|
|
||||||
var restoreOptions RestoreOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdRestore)
|
|
||||||
restoreOptions.AddFlags(cmdRestore.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
|
func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
|
||||||
term *termstatus.Terminal, args []string) error {
|
term *termstatus.Terminal, args []string) error {
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,13 @@ import (
|
||||||
"github.com/restic/restic/internal/walker"
|
"github.com/restic/restic/internal/walker"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdRewrite = &cobra.Command{
|
func newRewriteCommand() *cobra.Command {
|
||||||
Use: "rewrite [flags] [snapshotID ...]",
|
var opts RewriteOptions
|
||||||
Short: "Rewrite snapshots to exclude unwanted files",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "rewrite [flags] [snapshotID ...]",
|
||||||
|
Short: "Rewrite snapshots to exclude unwanted files",
|
||||||
|
Long: `
|
||||||
The "rewrite" command excludes files from existing snapshots. It creates new
|
The "rewrite" command excludes files from existing snapshots. It creates new
|
||||||
snapshots containing the same data as the original ones, but without the files
|
snapshots containing the same data as the original ones, but without the files
|
||||||
you specify to exclude. All metadata (time, host, tags) will be preserved.
|
you specify to exclude. All metadata (time, host, tags) will be preserved.
|
||||||
|
@ -52,11 +55,19 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runRewrite(cmd.Context(), rewriteOptions, globalOptions, args)
|
return runRewrite(cmd.Context(), opts, globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newRewriteCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
type snapshotMetadata struct {
|
type snapshotMetadata struct {
|
||||||
|
@ -111,13 +122,6 @@ func (opts *RewriteOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
opts.ExcludePatternOptions.Add(f)
|
opts.ExcludePatternOptions.Add(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
var rewriteOptions RewriteOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdRewrite)
|
|
||||||
rewriteOptions.AddFlags(cmdRewrite.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
// rewriteFilterFunc returns the filtered tree ID or an error. If a snapshot summary is returned, the snapshot will
|
// rewriteFilterFunc returns the filtered tree ID or an error. If a snapshot summary is returned, the snapshot will
|
||||||
// be updated accordingly.
|
// be updated accordingly.
|
||||||
type rewriteFilterFunc func(ctx context.Context, sn *restic.Snapshot) (restic.ID, *restic.SnapshotSummary, error)
|
type rewriteFilterFunc func(ctx context.Context, sn *restic.Snapshot) (restic.ID, *restic.SnapshotSummary, error)
|
||||||
|
|
|
@ -13,10 +13,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdSelfUpdate = &cobra.Command{
|
func newSelfUpdateCommand() *cobra.Command {
|
||||||
Use: "self-update [flags]",
|
var opts SelfUpdateOptions
|
||||||
Short: "Update the restic binary",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "self-update [flags]",
|
||||||
|
Short: "Update the restic binary",
|
||||||
|
Long: `
|
||||||
The command "self-update" downloads the latest stable release of restic from
|
The command "self-update" downloads the latest stable release of restic from
|
||||||
GitHub and replaces the currently running binary. After download, the
|
GitHub and replaces the currently running binary. After download, the
|
||||||
authenticity of the binary is verified using the GPG signature on the release
|
authenticity of the binary is verified using the GPG signature on the release
|
||||||
|
@ -31,10 +34,18 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runSelfUpdate(cmd.Context(), selfUpdateOptions, globalOptions, args)
|
return runSelfUpdate(cmd.Context(), opts, globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newSelfUpdateCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelfUpdateOptions collects all options for the update-restic command.
|
// SelfUpdateOptions collects all options for the update-restic command.
|
||||||
|
@ -46,13 +57,6 @@ func (opts *SelfUpdateOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.StringVar(&opts.Output, "output", "", "Save the downloaded file as `filename` (default: running binary itself)")
|
f.StringVar(&opts.Output, "output", "", "Save the downloaded file as `filename` (default: running binary itself)")
|
||||||
}
|
}
|
||||||
|
|
||||||
var selfUpdateOptions SelfUpdateOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdSelfUpdate)
|
|
||||||
selfUpdateOptions.AddFlags(cmdSelfUpdate.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func runSelfUpdate(ctx context.Context, opts SelfUpdateOptions, gopts GlobalOptions, args []string) error {
|
func runSelfUpdate(ctx context.Context, opts SelfUpdateOptions, gopts GlobalOptions, args []string) error {
|
||||||
if opts.Output == "" {
|
if opts.Output == "" {
|
||||||
file, err := os.Executable()
|
file, err := os.Executable()
|
||||||
|
|
|
@ -15,10 +15,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdSnapshots = &cobra.Command{
|
func newSnapshotsCommand() *cobra.Command {
|
||||||
Use: "snapshots [flags] [snapshotID ...]",
|
var opts SnapshotOptions
|
||||||
Short: "List all snapshots",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "snapshots [flags] [snapshotID ...]",
|
||||||
|
Short: "List all snapshots",
|
||||||
|
Long: `
|
||||||
The "snapshots" command lists all snapshots stored in the repository.
|
The "snapshots" command lists all snapshots stored in the repository.
|
||||||
|
|
||||||
EXIT STATUS
|
EXIT STATUS
|
||||||
|
@ -30,11 +33,19 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runSnapshots(cmd.Context(), snapshotOptions, globalOptions, args)
|
return runSnapshots(cmd.Context(), opts, globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newSnapshotsCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// SnapshotOptions bundles all options for the snapshots command.
|
// SnapshotOptions bundles all options for the snapshots command.
|
||||||
|
@ -59,13 +70,6 @@ func (opts *SnapshotOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.VarP(&opts.GroupBy, "group-by", "g", "`group` snapshots by host, paths and/or tags, separated by comma")
|
f.VarP(&opts.GroupBy, "group-by", "g", "`group` snapshots by host, paths and/or tags, separated by comma")
|
||||||
}
|
}
|
||||||
|
|
||||||
var snapshotOptions SnapshotOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdSnapshots)
|
|
||||||
snapshotOptions.AddFlags(cmdSnapshots.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func runSnapshots(ctx context.Context, opts SnapshotOptions, gopts GlobalOptions, args []string) error {
|
func runSnapshots(ctx context.Context, opts SnapshotOptions, gopts GlobalOptions, args []string) error {
|
||||||
ctx, repo, unlock, err := openWithReadLock(ctx, gopts, gopts.NoLock)
|
ctx, repo, unlock, err := openWithReadLock(ctx, gopts, gopts.NoLock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -21,10 +21,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdStats = &cobra.Command{
|
func newStatsCommand() *cobra.Command {
|
||||||
Use: "stats [flags] [snapshot ID] [...]",
|
var opts StatsOptions
|
||||||
Short: "Scan the repository and show basic statistics",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "stats [flags] [snapshot ID] [...]",
|
||||||
|
Short: "Scan the repository and show basic statistics",
|
||||||
|
Long: `
|
||||||
The "stats" command walks one or multiple snapshots in a repository
|
The "stats" command walks one or multiple snapshots in a repository
|
||||||
and accumulates statistics about the data stored therein. It reports
|
and accumulates statistics about the data stored therein. It reports
|
||||||
on the number of unique files and their sizes, according to one of
|
on the number of unique files and their sizes, according to one of
|
||||||
|
@ -56,11 +59,22 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runStats(cmd.Context(), statsOptions, globalOptions, args)
|
return runStats(cmd.Context(), opts, globalOptions, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
must(cmd.RegisterFlagCompletionFunc("mode", func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return []string{countModeRestoreSize, countModeUniqueFilesByContents, countModeBlobsPerFile, countModeRawData}, cobra.ShellCompDirectiveDefault
|
||||||
|
}))
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newStatsCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatsOptions collects all options for the stats command.
|
// StatsOptions collects all options for the stats command.
|
||||||
|
@ -76,22 +90,12 @@ func (opts *StatsOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
var statsOptions StatsOptions
|
|
||||||
|
|
||||||
func must(err error) {
|
func must(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("error during setup: %v", err))
|
panic(fmt.Sprintf("error during setup: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdStats)
|
|
||||||
statsOptions.AddFlags(cmdStats.Flags())
|
|
||||||
must(cmdStats.RegisterFlagCompletionFunc("mode", func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
|
|
||||||
return []string{countModeRestoreSize, countModeUniqueFilesByContents, countModeBlobsPerFile, countModeRawData}, cobra.ShellCompDirectiveDefault
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func runStats(ctx context.Context, opts StatsOptions, gopts GlobalOptions, args []string) error {
|
func runStats(ctx context.Context, opts StatsOptions, gopts GlobalOptions, args []string) error {
|
||||||
err := verifyStatsInput(opts)
|
err := verifyStatsInput(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -14,10 +14,13 @@ import (
|
||||||
"github.com/restic/restic/internal/ui/termstatus"
|
"github.com/restic/restic/internal/ui/termstatus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdTag = &cobra.Command{
|
func newTagCommand() *cobra.Command {
|
||||||
Use: "tag [flags] [snapshotID ...]",
|
var opts TagOptions
|
||||||
Short: "Modify tags on snapshots",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "tag [flags] [snapshotID ...]",
|
||||||
|
Short: "Modify tags on snapshots",
|
||||||
|
Long: `
|
||||||
The "tag" command allows you to modify tags on exiting snapshots.
|
The "tag" command allows you to modify tags on exiting snapshots.
|
||||||
|
|
||||||
You can either set/replace the entire set of tags on a snapshot, or
|
You can either set/replace the entire set of tags on a snapshot, or
|
||||||
|
@ -34,13 +37,21 @@ Exit status is 10 if the repository does not exist.
|
||||||
Exit status is 11 if the repository is already locked.
|
Exit status is 11 if the repository is already locked.
|
||||||
Exit status is 12 if the password is incorrect.
|
Exit status is 12 if the password is incorrect.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
term, cancel := setupTermstatus()
|
term, cancel := setupTermstatus()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return runTag(cmd.Context(), tagOptions, globalOptions, term, args)
|
return runTag(cmd.Context(), opts, globalOptions, term, args)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newTagCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TagOptions bundles all options for the 'tag' command.
|
// TagOptions bundles all options for the 'tag' command.
|
||||||
|
@ -58,13 +69,6 @@ func (opts *TagOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagOptions TagOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(cmdTag)
|
|
||||||
tagOptions.AddFlags(cmdTag.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
type changedSnapshot struct {
|
type changedSnapshot struct {
|
||||||
MessageType string `json:"message_type"` // changed
|
MessageType string `json:"message_type"` // changed
|
||||||
OldSnapshotID restic.ID `json:"old_snapshot_id"`
|
OldSnapshotID restic.ID `json:"old_snapshot_id"`
|
||||||
|
|
|
@ -8,10 +8,13 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var unlockCmd = &cobra.Command{
|
func newUnlockCommand() *cobra.Command {
|
||||||
Use: "unlock",
|
var opts UnlockOptions
|
||||||
Short: "Remove locks other processes created",
|
|
||||||
Long: `
|
cmd := &cobra.Command{
|
||||||
|
Use: "unlock",
|
||||||
|
Short: "Remove locks other processes created",
|
||||||
|
Long: `
|
||||||
The "unlock" command removes stale locks that have been created by other restic processes.
|
The "unlock" command removes stale locks that have been created by other restic processes.
|
||||||
|
|
||||||
EXIT STATUS
|
EXIT STATUS
|
||||||
|
@ -20,11 +23,18 @@ EXIT STATUS
|
||||||
Exit status is 0 if the command was successful.
|
Exit status is 0 if the command was successful.
|
||||||
Exit status is 1 if there was any error.
|
Exit status is 1 if there was any error.
|
||||||
`,
|
`,
|
||||||
GroupID: cmdGroupDefault,
|
GroupID: cmdGroupDefault,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
return runUnlock(cmd.Context(), unlockOptions, globalOptions)
|
return runUnlock(cmd.Context(), opts, globalOptions)
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
opts.AddFlags(cmd.Flags())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdRoot.AddCommand(newUnlockCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnlockOptions collects all options for the unlock command.
|
// UnlockOptions collects all options for the unlock command.
|
||||||
|
@ -36,13 +46,6 @@ func (opts *UnlockOptions) AddFlags(f *pflag.FlagSet) {
|
||||||
f.BoolVar(&opts.RemoveAll, "remove-all", false, "remove all locks, even non-stale ones")
|
f.BoolVar(&opts.RemoveAll, "remove-all", false, "remove all locks, even non-stale ones")
|
||||||
}
|
}
|
||||||
|
|
||||||
var unlockOptions UnlockOptions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmdRoot.AddCommand(unlockCmd)
|
|
||||||
unlockOptions.AddFlags(unlockCmd.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
func runUnlock(ctx context.Context, opts UnlockOptions, gopts GlobalOptions) error {
|
func runUnlock(ctx context.Context, opts UnlockOptions, gopts GlobalOptions) error {
|
||||||
repo, err := OpenRepository(ctx, gopts)
|
repo, err := OpenRepository(ctx, gopts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -8,10 +8,11 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var versionCmd = &cobra.Command{
|
func newVersionCommand() *cobra.Command {
|
||||||
Use: "version",
|
cmd := &cobra.Command{
|
||||||
Short: "Print version information",
|
Use: "version",
|
||||||
Long: `
|
Short: "Print version information",
|
||||||
|
Long: `
|
||||||
The "version" command prints detailed information about the build environment
|
The "version" command prints detailed information about the build environment
|
||||||
and the version of this software.
|
and the version of this software.
|
||||||
|
|
||||||
|
@ -21,38 +22,40 @@ EXIT STATUS
|
||||||
Exit status is 0 if the command was successful.
|
Exit status is 0 if the command was successful.
|
||||||
Exit status is 1 if there was any error.
|
Exit status is 1 if there was any error.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
Run: func(_ *cobra.Command, _ []string) {
|
Run: func(_ *cobra.Command, _ []string) {
|
||||||
if globalOptions.JSON {
|
if globalOptions.JSON {
|
||||||
type jsonVersion struct {
|
type jsonVersion struct {
|
||||||
MessageType string `json:"message_type"` // version
|
MessageType string `json:"message_type"` // version
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
GoVersion string `json:"go_version"`
|
GoVersion string `json:"go_version"`
|
||||||
GoOS string `json:"go_os"`
|
GoOS string `json:"go_os"`
|
||||||
GoArch string `json:"go_arch"`
|
GoArch string `json:"go_arch"`
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonS := jsonVersion{
|
||||||
|
MessageType: "version",
|
||||||
|
Version: version,
|
||||||
|
GoVersion: runtime.Version(),
|
||||||
|
GoOS: runtime.GOOS,
|
||||||
|
GoArch: runtime.GOARCH,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.NewEncoder(globalOptions.stdout).Encode(jsonS)
|
||||||
|
if err != nil {
|
||||||
|
Warnf("JSON encode failed: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Printf("restic %s compiled with %v on %v/%v\n",
|
||||||
|
version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonS := jsonVersion{
|
},
|
||||||
MessageType: "version",
|
}
|
||||||
Version: version,
|
return cmd
|
||||||
GoVersion: runtime.Version(),
|
|
||||||
GoOS: runtime.GOOS,
|
|
||||||
GoArch: runtime.GOARCH,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := json.NewEncoder(globalOptions.stdout).Encode(jsonS)
|
|
||||||
if err != nil {
|
|
||||||
Warnf("JSON encode failed: %v\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Printf("restic %s compiled with %v on %v/%v\n",
|
|
||||||
version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdRoot.AddCommand(versionCmd)
|
cmdRoot.AddCommand(newVersionCommand())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue