mirror of
https://github.com/restic/restic.git
synced 2025-02-23 01:18:26 +00:00
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"
|
||||
)
|
||||
|
||||
var cmdBackup = &cobra.Command{
|
||||
Use: "backup [flags] [FILE/DIR] ...",
|
||||
Short: "Create a new backup of files and/or directories",
|
||||
Long: `
|
||||
func newBackupCommand() *cobra.Command {
|
||||
var opts BackupOptions
|
||||
|
||||
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
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
PreRun: func(_ *cobra.Command, _ []string) {
|
||||
if backupOptions.Host == "" {
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
debug.Log("os.Hostname() returned err: %v", err)
|
||||
return
|
||||
PreRun: func(_ *cobra.Command, _ []string) {
|
||||
if opts.Host == "" {
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
debug.Log("os.Hostname() returned err: %v", err)
|
||||
return
|
||||
}
|
||||
opts.Host = hostname
|
||||
}
|
||||
backupOptions.Host = hostname
|
||||
}
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
return runBackup(cmd.Context(), backupOptions, globalOptions, term, args)
|
||||
},
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
return runBackup(cmd.Context(), opts, globalOptions, term, args)
|
||||
},
|
||||
}
|
||||
|
||||
opts.AddFlags(cmd.Flags())
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(newBackupCommand())
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
// ErrInvalidSourceData is used to report an incomplete backup
|
||||
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
|
||||
// items exist at all.
|
||||
func filterExisting(items []string) (result []string, err error) {
|
||||
|
@ -16,10 +16,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdCache = &cobra.Command{
|
||||
Use: "cache",
|
||||
Short: "Operate on local cache directories",
|
||||
Long: `
|
||||
func newCacheCommand() *cobra.Command {
|
||||
var opts CacheOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "cache",
|
||||
Short: "Operate on local cache directories",
|
||||
Long: `
|
||||
The "cache" command allows listing and cleaning local cache directories.
|
||||
|
||||
EXIT STATUS
|
||||
@ -28,11 +31,19 @@ EXIT STATUS
|
||||
Exit status is 0 if the command was successful.
|
||||
Exit status is 1 if there was any error.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
return runCache(cacheOptions, globalOptions, args)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
return runCache(opts, globalOptions, args)
|
||||
},
|
||||
}
|
||||
|
||||
opts.AddFlags(cmd.Flags())
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(newCacheCommand())
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
var cacheOptions CacheOptions
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdCache)
|
||||
cacheOptions.AddFlags(cmdCache.Flags())
|
||||
}
|
||||
|
||||
func runCache(opts CacheOptions, gopts GlobalOptions, args []string) error {
|
||||
if len(args) > 0 {
|
||||
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 cmdCat = &cobra.Command{
|
||||
Use: "cat [flags] [masterkey|config|pack ID|blob ID|snapshot ID|index ID|key ID|lock ID|tree snapshot:subfolder]",
|
||||
Short: "Print internal objects to stdout",
|
||||
Long: `
|
||||
func newCatCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "cat [flags] [masterkey|config|pack ID|blob ID|snapshot ID|index ID|key ID|lock ID|tree snapshot:subfolder]",
|
||||
Short: "Print internal objects to stdout",
|
||||
Long: `
|
||||
The "cat" command is used to print internal objects to stdout.
|
||||
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runCat(cmd.Context(), globalOptions, args)
|
||||
},
|
||||
ValidArgs: catAllowedCmds,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runCat(cmd.Context(), globalOptions, args)
|
||||
},
|
||||
ValidArgs: catAllowedCmds,
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdCat)
|
||||
cmdRoot.AddCommand(newCatCommand())
|
||||
}
|
||||
|
||||
func validateCatArgs(args []string) error {
|
||||
|
@ -23,10 +23,12 @@ import (
|
||||
"github.com/restic/restic/internal/ui/termstatus"
|
||||
)
|
||||
|
||||
var cmdCheck = &cobra.Command{
|
||||
Use: "check [flags]",
|
||||
Short: "Check the repository for errors",
|
||||
Long: `
|
||||
func newCheckCommand() *cobra.Command {
|
||||
var opts CheckOptions
|
||||
cmd := &cobra.Command{
|
||||
Use: "check [flags]",
|
||||
Short: "Check the repository for errors",
|
||||
Long: `
|
||||
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.
|
||||
|
||||
@ -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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
summary, err := runCheck(cmd.Context(), checkOptions, globalOptions, args, term)
|
||||
if globalOptions.JSON {
|
||||
if err != nil && summary.NumErrors == 0 {
|
||||
summary.NumErrors = 1
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
summary, err := runCheck(cmd.Context(), opts, globalOptions, args, term)
|
||||
if globalOptions.JSON {
|
||||
if err != nil && summary.NumErrors == 0 {
|
||||
summary.NumErrors = 1
|
||||
}
|
||||
term.Print(ui.ToJSONString(summary))
|
||||
}
|
||||
term.Print(ui.ToJSONString(summary))
|
||||
}
|
||||
return err
|
||||
},
|
||||
PreRunE: func(_ *cobra.Command, _ []string) error {
|
||||
return checkFlags(checkOptions)
|
||||
},
|
||||
return err
|
||||
},
|
||||
PreRunE: func(_ *cobra.Command, _ []string) error {
|
||||
return checkFlags(opts)
|
||||
},
|
||||
}
|
||||
|
||||
opts.AddFlags(cmd.Flags())
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(newCheckCommand())
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
var checkOptions CheckOptions
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdCheck)
|
||||
checkOptions.AddFlags(cmdCheck.Flags())
|
||||
}
|
||||
|
||||
func checkFlags(opts CheckOptions) error {
|
||||
if opts.ReadData && opts.ReadDataSubset != "" {
|
||||
return errors.Fatal("check flags --read-data and --read-data-subset cannot be used together")
|
||||
|
@ -14,10 +14,12 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdCopy = &cobra.Command{
|
||||
Use: "copy [flags] [snapshotID ...]",
|
||||
Short: "Copy snapshots from one repository to another",
|
||||
Long: `
|
||||
func newCopyCommand() *cobra.Command {
|
||||
var opts CopyOptions
|
||||
cmd := &cobra.Command{
|
||||
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.
|
||||
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runCopy(cmd.Context(), copyOptions, globalOptions, args)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
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.
|
||||
@ -59,13 +69,6 @@ func (opts *CopyOptions) AddFlags(f *pflag.FlagSet) {
|
||||
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 {
|
||||
secondaryGopts, isFromRepo, err := fillSecondaryGlobalOpts(ctx, opts.secondaryRepoOptions, gopts, "destination")
|
||||
if err != nil {
|
||||
|
@ -29,17 +29,27 @@ import (
|
||||
"github.com/restic/restic/internal/restic"
|
||||
)
|
||||
|
||||
var cmdDebug = &cobra.Command{
|
||||
Use: "debug",
|
||||
Short: "Debug commands",
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
func newDebugCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "debug",
|
||||
Short: "Debug commands",
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
}
|
||||
cmd.AddCommand(newDebugDumpCommand())
|
||||
cmd.AddCommand(newDebugExamineCommand())
|
||||
return cmd
|
||||
}
|
||||
|
||||
var cmdDebugDump = &cobra.Command{
|
||||
Use: "dump [indexes|snapshots|all|packs]",
|
||||
Short: "Dump data structures",
|
||||
Long: `
|
||||
func init() {
|
||||
cmdRoot.AddCommand(newDebugCommand())
|
||||
}
|
||||
|
||||
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
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runDebugDump(cmd.Context(), globalOptions, args)
|
||||
},
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
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 {
|
||||
@ -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")
|
||||
}
|
||||
|
||||
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 {
|
||||
buf, err := json.MarshalIndent(item, "", " ")
|
||||
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 {
|
||||
if bytewise {
|
||||
Printf(" trying to repair blob by finding a broken byte\n")
|
||||
|
@ -15,10 +15,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdDiff = &cobra.Command{
|
||||
Use: "diff [flags] snapshotID snapshotID",
|
||||
Short: "Show differences between two snapshots",
|
||||
Long: `
|
||||
func newDiffCommand() *cobra.Command {
|
||||
var opts DiffOptions
|
||||
|
||||
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
|
||||
first characters in each line display what has happened to a particular file or
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runDiff(cmd.Context(), diffOptions, globalOptions, args)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
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.
|
||||
@ -62,13 +73,6 @@ func (opts *DiffOptions) AddFlags(f *pflag.FlagSet) {
|
||||
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) {
|
||||
sn, subfolder, err := restic.FindSnapshot(ctx, be, repo, desc)
|
||||
if err != nil {
|
||||
|
@ -16,10 +16,12 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdDump = &cobra.Command{
|
||||
Use: "dump [flags] snapshotID file",
|
||||
Short: "Print a backed-up file to stdout",
|
||||
Long: `
|
||||
func newDumpCommand() *cobra.Command {
|
||||
var opts DumpOptions
|
||||
cmd := &cobra.Command{
|
||||
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
|
||||
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.
|
||||
@ -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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runDump(cmd.Context(), dumpOptions, globalOptions, args)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
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.
|
||||
@ -61,13 +71,6 @@ func (opts *DumpOptions) AddFlags(f *pflag.FlagSet) {
|
||||
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 {
|
||||
d, f := path.Split(p)
|
||||
if d == "" || d == "/" {
|
||||
|
@ -10,10 +10,11 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var featuresCmd = &cobra.Command{
|
||||
Use: "features",
|
||||
Short: "Print list of feature flags",
|
||||
Long: `
|
||||
func newFeaturesCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "features",
|
||||
Short: "Print list of feature flags",
|
||||
Long: `
|
||||
The "features" command prints a list of supported feature flags.
|
||||
|
||||
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 1 if there was any error.
|
||||
`,
|
||||
GroupID: cmdGroupAdvanced,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
if len(args) != 0 {
|
||||
return errors.Fatal("the feature command expects no arguments")
|
||||
}
|
||||
GroupID: cmdGroupAdvanced,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
if len(args) != 0 {
|
||||
return errors.Fatal("the feature command expects no arguments")
|
||||
}
|
||||
|
||||
fmt.Printf("All Feature Flags:\n")
|
||||
flags := feature.Flag.List()
|
||||
fmt.Printf("All Feature Flags:\n")
|
||||
flags := feature.Flag.List()
|
||||
|
||||
tab := table.New()
|
||||
tab.AddColumn("Name", "{{ .Name }}")
|
||||
tab.AddColumn("Type", "{{ .Type }}")
|
||||
tab.AddColumn("Default", "{{ .Default }}")
|
||||
tab.AddColumn("Description", "{{ .Description }}")
|
||||
tab := table.New()
|
||||
tab.AddColumn("Name", "{{ .Name }}")
|
||||
tab.AddColumn("Type", "{{ .Type }}")
|
||||
tab.AddColumn("Default", "{{ .Default }}")
|
||||
tab.AddColumn("Description", "{{ .Description }}")
|
||||
|
||||
for _, flag := range flags {
|
||||
tab.AddRow(flag)
|
||||
}
|
||||
return tab.Write(globalOptions.stdout)
|
||||
},
|
||||
for _, flag := range flags {
|
||||
tab.AddRow(flag)
|
||||
}
|
||||
return tab.Write(globalOptions.stdout)
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(featuresCmd)
|
||||
cmdRoot.AddCommand(newFeaturesCommand())
|
||||
}
|
||||
|
@ -17,16 +17,19 @@ import (
|
||||
"github.com/restic/restic/internal/walker"
|
||||
)
|
||||
|
||||
var cmdFind = &cobra.Command{
|
||||
Use: "find [flags] PATTERN...",
|
||||
Short: "Find a file, a directory or restic IDs",
|
||||
Long: `
|
||||
func newFindCommand() *cobra.Command {
|
||||
var opts FindOptions
|
||||
|
||||
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
|
||||
repo.
|
||||
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
|
||||
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 --blob 420f620f b46ebe8a ddd38656
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runFind(cmd.Context(), findOptions, globalOptions, args)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
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.
|
||||
@ -79,13 +90,6 @@ func (opts *FindOptions) AddFlags(f *pflag.FlagSet) {
|
||||
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
||||
}
|
||||
|
||||
var findOptions FindOptions
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdFind)
|
||||
findOptions.AddFlags(cmdFind.Flags())
|
||||
}
|
||||
|
||||
type findPattern struct {
|
||||
oldest, newest time.Time
|
||||
pattern []string
|
||||
|
@ -14,10 +14,14 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdForget = &cobra.Command{
|
||||
Use: "forget [flags] [snapshot ID] [...]",
|
||||
Short: "Remove snapshots from the repository",
|
||||
Long: `
|
||||
func newForgetCommand() *cobra.Command {
|
||||
var opts ForgetOptions
|
||||
var pruneOpts PruneOptions
|
||||
|
||||
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
|
||||
first divided into groups according to "--group-by", and after that the policy
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
return runForget(cmd.Context(), forgetOptions, forgetPruneOptions, globalOptions, term, args)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
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
|
||||
@ -145,15 +158,6 @@ func (opts *ForgetOptions) AddFlags(f *pflag.FlagSet) {
|
||||
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 {
|
||||
if opts.Last < -1 || opts.Hourly < -1 || opts.Daily < -1 || opts.Weekly < -1 ||
|
||||
opts.Monthly < -1 || opts.Yearly < -1 {
|
||||
|
@ -11,10 +11,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdGenerate = &cobra.Command{
|
||||
Use: "generate [flags]",
|
||||
Short: "Generate manual pages and auto-completion files (bash, fish, zsh, powershell)",
|
||||
Long: `
|
||||
func newGenerateCommand() *cobra.Command {
|
||||
var opts generateOptions
|
||||
|
||||
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
|
||||
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 1 if there was any error.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
return runGenerate(genOpts, args)
|
||||
},
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
return runGenerate(opts, args)
|
||||
},
|
||||
}
|
||||
opts.AddFlags(cmd.Flags())
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(newGenerateCommand())
|
||||
}
|
||||
|
||||
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)")
|
||||
}
|
||||
|
||||
var genOpts generateOptions
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdGenerate)
|
||||
genOpts.AddFlags(cmdGenerate.Flags())
|
||||
}
|
||||
|
||||
func writeManpages(dir string) error {
|
||||
// use a fixed date for the man pages so that generating them is deterministic
|
||||
date, err := time.Parse("Jan 2006", "Jan 2017")
|
||||
|
@ -15,10 +15,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdInit = &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Initialize a new repository",
|
||||
Long: `
|
||||
func newInitCommand() *cobra.Command {
|
||||
var opts InitOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Initialize a new repository",
|
||||
Long: `
|
||||
The "init" command initializes a new repository.
|
||||
|
||||
EXIT STATUS
|
||||
@ -27,11 +30,18 @@ EXIT STATUS
|
||||
Exit status is 0 if the command was successful.
|
||||
Exit status is 1 if there was any error.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runInit(cmd.Context(), initOptions, globalOptions, args)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
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.
|
||||
@ -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'")
|
||||
}
|
||||
|
||||
var initOptions InitOptions
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdInit)
|
||||
initOptions.AddFlags(cmdInit.Flags())
|
||||
}
|
||||
|
||||
func runInit(ctx context.Context, opts InitOptions, gopts GlobalOptions, args []string) error {
|
||||
if len(args) > 0 {
|
||||
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"
|
||||
)
|
||||
|
||||
var cmdKeyAdd = &cobra.Command{
|
||||
Use: "add",
|
||||
Short: "Add a new key (password) to the repository; returns the new key ID",
|
||||
Long: `
|
||||
func newKeyAddCommand() *cobra.Command {
|
||||
var opts KeyAddOptions
|
||||
|
||||
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.
|
||||
|
||||
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 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 {
|
||||
@ -43,13 +53,7 @@ func (opts *KeyAddOptions) Add(flags *pflag.FlagSet) {
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdKey.AddCommand(cmdKeyAdd)
|
||||
|
||||
var keyAddOpts KeyAddOptions
|
||||
keyAddOpts.Add(cmdKeyAdd.Flags())
|
||||
cmdKeyAdd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
return runKeyAdd(cmd.Context(), globalOptions, keyAddOpts, args)
|
||||
}
|
||||
cmdKey.AddCommand(newKeyAddCommand())
|
||||
}
|
||||
|
||||
func runKeyAdd(ctx context.Context, gopts GlobalOptions, opts KeyAddOptions, args []string) error {
|
||||
|
@ -12,10 +12,11 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var cmdKeyList = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List keys (passwords)",
|
||||
Long: `
|
||||
func newKeyListCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List keys (passwords)",
|
||||
Long: `
|
||||
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
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runKeyList(cmd.Context(), globalOptions, args)
|
||||
},
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runKeyList(cmd.Context(), globalOptions, args)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdKey.AddCommand(cmdKeyList)
|
||||
cmdKey.AddCommand(newKeyListCommand())
|
||||
}
|
||||
|
||||
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/repository"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdKeyPasswd = &cobra.Command{
|
||||
Use: "passwd",
|
||||
Short: "Change key (password); creates a new key ID and removes the old key ID, returns new key ID",
|
||||
Long: `
|
||||
func newKeyPasswdCommand() *cobra.Command {
|
||||
var opts KeyPasswdOptions
|
||||
|
||||
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.
|
||||
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 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 {
|
||||
KeyAddOptions
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdKey.AddCommand(cmdKeyPasswd)
|
||||
|
||||
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 (opts *KeyPasswdOptions) AddFlags(flags *pflag.FlagSet) {
|
||||
opts.KeyAddOptions.Add(flags)
|
||||
}
|
||||
|
||||
func runKeyPasswd(ctx context.Context, gopts GlobalOptions, opts KeyPasswdOptions, args []string) error {
|
||||
|
@ -10,10 +10,11 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var cmdKeyRemove = &cobra.Command{
|
||||
Use: "remove [ID]",
|
||||
Short: "Remove key ID (password) from the repository.",
|
||||
Long: `
|
||||
func newKeyRemoveCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "remove [ID]",
|
||||
Short: "Remove key ID (password) from the repository.",
|
||||
Long: `
|
||||
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.
|
||||
|
||||
@ -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 12 if the password is incorrect.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runKeyRemove(cmd.Context(), globalOptions, args)
|
||||
},
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runKeyRemove(cmd.Context(), globalOptions, args)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdKey.AddCommand(cmdKeyRemove)
|
||||
cmdKey.AddCommand(newKeyRemoveCommand())
|
||||
}
|
||||
|
||||
func runKeyRemove(ctx context.Context, gopts GlobalOptions, args []string) error {
|
||||
|
@ -11,13 +11,14 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var listAllowedArgs = []string{"blobs", "packs", "index", "snapshots", "keys", "locks"}
|
||||
var listAllowedArgsUseString = strings.Join(listAllowedArgs, "|")
|
||||
func newListCommand() *cobra.Command {
|
||||
var listAllowedArgs = []string{"blobs", "packs", "index", "snapshots", "keys", "locks"}
|
||||
var listAllowedArgsUseString = strings.Join(listAllowedArgs, "|")
|
||||
|
||||
var cmdList = &cobra.Command{
|
||||
Use: "list [flags] [" + listAllowedArgsUseString + "]",
|
||||
Short: "List objects in the repository",
|
||||
Long: `
|
||||
cmd := &cobra.Command{
|
||||
Use: "list [flags] [" + listAllowedArgsUseString + "]",
|
||||
Short: "List objects in the repository",
|
||||
Long: `
|
||||
The "list" command allows listing objects in the repository based on type.
|
||||
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
GroupID: cmdGroupDefault,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runList(cmd.Context(), globalOptions, args)
|
||||
},
|
||||
ValidArgs: listAllowedArgs,
|
||||
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
|
||||
DisableAutoGenTag: true,
|
||||
GroupID: cmdGroupDefault,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runList(cmd.Context(), globalOptions, args)
|
||||
},
|
||||
ValidArgs: listAllowedArgs,
|
||||
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdList)
|
||||
cmdRoot.AddCommand(newListCommand())
|
||||
}
|
||||
|
||||
func runList(ctx context.Context, gopts GlobalOptions, args []string) error {
|
||||
|
@ -21,10 +21,13 @@ import (
|
||||
"github.com/restic/restic/internal/walker"
|
||||
)
|
||||
|
||||
var cmdLs = &cobra.Command{
|
||||
Use: "ls [flags] snapshotID [dir...]",
|
||||
Short: "List files in a snapshot",
|
||||
Long: `
|
||||
func newLsCommand() *cobra.Command {
|
||||
var opts LsOptions
|
||||
|
||||
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 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 12 if the password is incorrect.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
GroupID: cmdGroupDefault,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runLs(cmd.Context(), lsOptions, globalOptions, args)
|
||||
},
|
||||
DisableAutoGenTag: true,
|
||||
GroupID: cmdGroupDefault,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
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.
|
||||
@ -81,13 +91,6 @@ func (opts *LsOptions) AddFlags(f *pflag.FlagSet) {
|
||||
f.BoolVar(&opts.Reverse, "reverse", false, "reverse sorted output")
|
||||
}
|
||||
|
||||
var lsOptions LsOptions
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdLs)
|
||||
lsOptions.AddFlags(cmdLs.Flags())
|
||||
}
|
||||
|
||||
type lsPrinter interface {
|
||||
Snapshot(sn *restic.Snapshot) error
|
||||
Node(path string, node *restic.Node, isPrefixDirectory bool) error
|
||||
|
@ -12,10 +12,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdMigrate = &cobra.Command{
|
||||
Use: "migrate [flags] [migration name] [...]",
|
||||
Short: "Apply migrations",
|
||||
Long: `
|
||||
func newMigrateCommand() *cobra.Command {
|
||||
var opts MigrateOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "migrate [flags] [migration name] [...]",
|
||||
Short: "Apply migrations",
|
||||
Long: `
|
||||
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
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
GroupID: cmdGroupDefault,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
return runMigrate(cmd.Context(), migrateOptions, globalOptions, args, term)
|
||||
},
|
||||
DisableAutoGenTag: true,
|
||||
GroupID: cmdGroupDefault,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
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.
|
||||
@ -47,13 +58,6 @@ func (opts *MigrateOptions) AddFlags(f *pflag.FlagSet) {
|
||||
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 {
|
||||
printer.P("available migrations:\n")
|
||||
found := false
|
||||
|
@ -22,10 +22,13 @@ import (
|
||||
"github.com/anacrolix/fuse/fs"
|
||||
)
|
||||
|
||||
var cmdMount = &cobra.Command{
|
||||
Use: "mount [flags] mountpoint",
|
||||
Short: "Mount the repository",
|
||||
Long: `
|
||||
func newMountCommand() *cobra.Command {
|
||||
var opts MountOptions
|
||||
|
||||
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
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
GroupID: cmdGroupDefault,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runMount(cmd.Context(), mountOptions, globalOptions, args)
|
||||
},
|
||||
DisableAutoGenTag: true,
|
||||
GroupID: cmdGroupDefault,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
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.
|
||||
@ -100,13 +111,6 @@ func (opts *MountOptions) AddFlags(f *pflag.FlagSet) {
|
||||
_ = 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 {
|
||||
if opts.TimeTemplate == "" {
|
||||
return errors.Fatal("time template string cannot be empty")
|
||||
|
@ -8,10 +8,11 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var optionsCmd = &cobra.Command{
|
||||
Use: "options",
|
||||
Short: "Print list of extended options",
|
||||
Long: `
|
||||
func newOptionsCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "options",
|
||||
Short: "Print list of extended options",
|
||||
Long: `
|
||||
The "options" command prints a list of extended options.
|
||||
|
||||
EXIT STATUS
|
||||
@ -20,22 +21,24 @@ EXIT STATUS
|
||||
Exit status is 0 if the command was successful.
|
||||
Exit status is 1 if there was any error.
|
||||
`,
|
||||
GroupID: cmdGroupAdvanced,
|
||||
DisableAutoGenTag: true,
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
fmt.Printf("All Extended Options:\n")
|
||||
var maxLen int
|
||||
for _, opt := range options.List() {
|
||||
if l := len(opt.Namespace + "." + opt.Name); l > maxLen {
|
||||
maxLen = l
|
||||
GroupID: cmdGroupAdvanced,
|
||||
DisableAutoGenTag: true,
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
fmt.Printf("All Extended Options:\n")
|
||||
var maxLen int
|
||||
for _, opt := range options.List() {
|
||||
if l := len(opt.Namespace + "." + opt.Name); l > maxLen {
|
||||
maxLen = l
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, opt := range options.List() {
|
||||
fmt.Printf(" %*s %s\n", -maxLen, opt.Namespace+"."+opt.Name, opt.Text)
|
||||
}
|
||||
},
|
||||
for _, opt := range options.List() {
|
||||
fmt.Printf(" %*s %s\n", -maxLen, opt.Namespace+"."+opt.Name, opt.Text)
|
||||
}
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(optionsCmd)
|
||||
cmdRoot.AddCommand(newOptionsCommand())
|
||||
}
|
||||
|
@ -19,10 +19,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdPrune = &cobra.Command{
|
||||
Use: "prune [flags]",
|
||||
Short: "Remove unneeded data from the repository",
|
||||
Long: `
|
||||
func newPruneCommand() *cobra.Command {
|
||||
var opts PruneOptions
|
||||
|
||||
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
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
return runPrune(cmd.Context(), pruneOptions, globalOptions, term)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
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.
|
||||
@ -76,13 +87,6 @@ func (opts *PruneOptions) AddLimitedFlags(f *pflag.FlagSet) {
|
||||
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 {
|
||||
opts.MaxRepackBytes = math.MaxUint64
|
||||
if len(opts.MaxRepackSize) > 0 {
|
||||
|
@ -11,10 +11,11 @@ import (
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
var cmdRecover = &cobra.Command{
|
||||
Use: "recover [flags]",
|
||||
Short: "Recover data from the repository not referenced by snapshots",
|
||||
Long: `
|
||||
func newRecoverCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "recover [flags]",
|
||||
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 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".
|
||||
@ -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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
return runRecover(cmd.Context(), globalOptions)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
return runRecover(cmd.Context(), globalOptions)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdRecover)
|
||||
cmdRoot.AddCommand(newRecoverCommand())
|
||||
}
|
||||
|
||||
func runRecover(ctx context.Context, gopts GlobalOptions) error {
|
||||
|
@ -9,10 +9,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdRepairIndex = &cobra.Command{
|
||||
Use: "index [flags]",
|
||||
Short: "Build a new index",
|
||||
Long: `
|
||||
func newRepairIndexCommand() *cobra.Command {
|
||||
var opts RepairIndexOptions
|
||||
|
||||
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
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
return runRebuildIndex(cmd.Context(), repairIndexOptions, globalOptions, term)
|
||||
},
|
||||
DisableAutoGenTag: true,
|
||||
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
|
||||
}
|
||||
|
||||
var cmdRebuildIndex = &cobra.Command{
|
||||
Use: "rebuild-index [flags]",
|
||||
Short: cmdRepairIndex.Short,
|
||||
Long: cmdRepairIndex.Long,
|
||||
Deprecated: `Use "repair index" instead`,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: cmdRepairIndex.RunE,
|
||||
func init() {
|
||||
cmdRepair.AddCommand(newRepairIndexCommand())
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
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() {
|
||||
cmdRepair.AddCommand(cmdRepairIndex)
|
||||
repairIndexOptions.AddFlags(cmdRepairIndex.Flags())
|
||||
// add alias for old name
|
||||
cmdRoot.AddCommand(cmdRebuildIndex)
|
||||
repairIndexOptions.AddFlags(cmdRebuildIndex.Flags())
|
||||
cmdRoot.AddCommand(newRebuildIndexCommand())
|
||||
}
|
||||
|
||||
func runRebuildIndex(ctx context.Context, opts RepairIndexOptions, gopts GlobalOptions, term *termstatus.Terminal) error {
|
||||
|
@ -13,10 +13,11 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var cmdRepairPacks = &cobra.Command{
|
||||
Use: "packs [packIDs...]",
|
||||
Short: "Salvage damaged pack files",
|
||||
Long: `
|
||||
func newRepairPacksCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "packs [packIDs...]",
|
||||
Short: "Salvage damaged pack files",
|
||||
Long: `
|
||||
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.
|
||||
|
||||
@ -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 12 if the password is incorrect.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
return runRepairPacks(cmd.Context(), globalOptions, term, args)
|
||||
},
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
return runRepairPacks(cmd.Context(), globalOptions, term, args)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRepair.AddCommand(cmdRepairPacks)
|
||||
cmdRepair.AddCommand(newRepairPacksCommand())
|
||||
}
|
||||
|
||||
func runRepairPacks(ctx context.Context, gopts GlobalOptions, term *termstatus.Terminal, args []string) error {
|
||||
|
@ -11,10 +11,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdRepairSnapshots = &cobra.Command{
|
||||
Use: "snapshots [flags] [snapshot ID] [...]",
|
||||
Short: "Repair snapshots",
|
||||
Long: `
|
||||
func newRepairSnapshotsCommand() *cobra.Command {
|
||||
var opts RepairOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "snapshots [flags] [snapshot ID] [...]",
|
||||
Short: "Repair snapshots",
|
||||
Long: `
|
||||
The "repair snapshots" command repairs broken snapshots. It scans the given
|
||||
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
|
||||
@ -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 12 if the password is incorrect.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runRepairSnapshots(cmd.Context(), globalOptions, repairSnapshotOptions, args)
|
||||
},
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
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.
|
||||
@ -65,13 +76,6 @@ func (opts *RepairOptions) AddFlags(f *pflag.FlagSet) {
|
||||
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 {
|
||||
ctx, repo, unlock, err := openWithExclusiveLock(ctx, gopts, opts.DryRun)
|
||||
if err != nil {
|
||||
|
@ -18,10 +18,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdRestore = &cobra.Command{
|
||||
Use: "restore [flags] snapshotID",
|
||||
Short: "Extract the data from a snapshot",
|
||||
Long: `
|
||||
func newRestoreCommand() *cobra.Command {
|
||||
var opts RestoreOptions
|
||||
|
||||
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
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
return runRestore(cmd.Context(), restoreOptions, globalOptions, term, args)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
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.
|
||||
@ -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")
|
||||
}
|
||||
|
||||
var restoreOptions RestoreOptions
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdRestore)
|
||||
restoreOptions.AddFlags(cmdRestore.Flags())
|
||||
}
|
||||
|
||||
func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
|
||||
term *termstatus.Terminal, args []string) error {
|
||||
|
||||
|
@ -16,10 +16,13 @@ import (
|
||||
"github.com/restic/restic/internal/walker"
|
||||
)
|
||||
|
||||
var cmdRewrite = &cobra.Command{
|
||||
Use: "rewrite [flags] [snapshotID ...]",
|
||||
Short: "Rewrite snapshots to exclude unwanted files",
|
||||
Long: `
|
||||
func newRewriteCommand() *cobra.Command {
|
||||
var opts RewriteOptions
|
||||
|
||||
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
|
||||
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.
|
||||
@ -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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runRewrite(cmd.Context(), rewriteOptions, globalOptions, args)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runRewrite(cmd.Context(), opts, globalOptions, args)
|
||||
},
|
||||
}
|
||||
|
||||
opts.AddFlags(cmd.Flags())
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(newRewriteCommand())
|
||||
}
|
||||
|
||||
type snapshotMetadata struct {
|
||||
@ -111,13 +122,6 @@ func (opts *RewriteOptions) AddFlags(f *pflag.FlagSet) {
|
||||
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
|
||||
// be updated accordingly.
|
||||
type rewriteFilterFunc func(ctx context.Context, sn *restic.Snapshot) (restic.ID, *restic.SnapshotSummary, error)
|
||||
|
@ -13,10 +13,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdSelfUpdate = &cobra.Command{
|
||||
Use: "self-update [flags]",
|
||||
Short: "Update the restic binary",
|
||||
Long: `
|
||||
func newSelfUpdateCommand() *cobra.Command {
|
||||
var opts SelfUpdateOptions
|
||||
|
||||
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
|
||||
GitHub and replaces the currently running binary. After download, the
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runSelfUpdate(cmd.Context(), selfUpdateOptions, globalOptions, args)
|
||||
},
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
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.
|
||||
@ -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)")
|
||||
}
|
||||
|
||||
var selfUpdateOptions SelfUpdateOptions
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdSelfUpdate)
|
||||
selfUpdateOptions.AddFlags(cmdSelfUpdate.Flags())
|
||||
}
|
||||
|
||||
func runSelfUpdate(ctx context.Context, opts SelfUpdateOptions, gopts GlobalOptions, args []string) error {
|
||||
if opts.Output == "" {
|
||||
file, err := os.Executable()
|
||||
|
@ -15,10 +15,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdSnapshots = &cobra.Command{
|
||||
Use: "snapshots [flags] [snapshotID ...]",
|
||||
Short: "List all snapshots",
|
||||
Long: `
|
||||
func newSnapshotsCommand() *cobra.Command {
|
||||
var opts SnapshotOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "snapshots [flags] [snapshotID ...]",
|
||||
Short: "List all snapshots",
|
||||
Long: `
|
||||
The "snapshots" command lists all snapshots stored in the repository.
|
||||
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runSnapshots(cmd.Context(), snapshotOptions, globalOptions, args)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
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.
|
||||
@ -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")
|
||||
}
|
||||
|
||||
var snapshotOptions SnapshotOptions
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdSnapshots)
|
||||
snapshotOptions.AddFlags(cmdSnapshots.Flags())
|
||||
}
|
||||
|
||||
func runSnapshots(ctx context.Context, opts SnapshotOptions, gopts GlobalOptions, args []string) error {
|
||||
ctx, repo, unlock, err := openWithReadLock(ctx, gopts, gopts.NoLock)
|
||||
if err != nil {
|
||||
|
@ -21,10 +21,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cmdStats = &cobra.Command{
|
||||
Use: "stats [flags] [snapshot ID] [...]",
|
||||
Short: "Scan the repository and show basic statistics",
|
||||
Long: `
|
||||
func newStatsCommand() *cobra.Command {
|
||||
var opts StatsOptions
|
||||
|
||||
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
|
||||
and accumulates statistics about the data stored therein. It reports
|
||||
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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runStats(cmd.Context(), statsOptions, globalOptions, args)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
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.
|
||||
@ -76,22 +90,12 @@ func (opts *StatsOptions) AddFlags(f *pflag.FlagSet) {
|
||||
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
||||
}
|
||||
|
||||
var statsOptions StatsOptions
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
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 {
|
||||
err := verifyStatsInput(opts)
|
||||
if err != nil {
|
||||
|
@ -14,10 +14,13 @@ import (
|
||||
"github.com/restic/restic/internal/ui/termstatus"
|
||||
)
|
||||
|
||||
var cmdTag = &cobra.Command{
|
||||
Use: "tag [flags] [snapshotID ...]",
|
||||
Short: "Modify tags on snapshots",
|
||||
Long: `
|
||||
func newTagCommand() *cobra.Command {
|
||||
var opts TagOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "tag [flags] [snapshotID ...]",
|
||||
Short: "Modify tags on snapshots",
|
||||
Long: `
|
||||
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
|
||||
@ -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 12 if the password is incorrect.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
return runTag(cmd.Context(), tagOptions, globalOptions, term, args)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
term, cancel := setupTermstatus()
|
||||
defer cancel()
|
||||
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.
|
||||
@ -58,13 +69,6 @@ func (opts *TagOptions) AddFlags(f *pflag.FlagSet) {
|
||||
initMultiSnapshotFilter(f, &opts.SnapshotFilter, true)
|
||||
}
|
||||
|
||||
var tagOptions TagOptions
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(cmdTag)
|
||||
tagOptions.AddFlags(cmdTag.Flags())
|
||||
}
|
||||
|
||||
type changedSnapshot struct {
|
||||
MessageType string `json:"message_type"` // changed
|
||||
OldSnapshotID restic.ID `json:"old_snapshot_id"`
|
||||
|
@ -8,10 +8,13 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var unlockCmd = &cobra.Command{
|
||||
Use: "unlock",
|
||||
Short: "Remove locks other processes created",
|
||||
Long: `
|
||||
func newUnlockCommand() *cobra.Command {
|
||||
var opts UnlockOptions
|
||||
|
||||
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.
|
||||
|
||||
EXIT STATUS
|
||||
@ -20,11 +23,18 @@ EXIT STATUS
|
||||
Exit status is 0 if the command was successful.
|
||||
Exit status is 1 if there was any error.
|
||||
`,
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
return runUnlock(cmd.Context(), unlockOptions, globalOptions)
|
||||
},
|
||||
GroupID: cmdGroupDefault,
|
||||
DisableAutoGenTag: true,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
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.
|
||||
@ -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")
|
||||
}
|
||||
|
||||
var unlockOptions UnlockOptions
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(unlockCmd)
|
||||
unlockOptions.AddFlags(unlockCmd.Flags())
|
||||
}
|
||||
|
||||
func runUnlock(ctx context.Context, opts UnlockOptions, gopts GlobalOptions) error {
|
||||
repo, err := OpenRepository(ctx, gopts)
|
||||
if err != nil {
|
||||
|
@ -8,10 +8,11 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print version information",
|
||||
Long: `
|
||||
func newVersionCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print version information",
|
||||
Long: `
|
||||
The "version" command prints detailed information about the build environment
|
||||
and the version of this software.
|
||||
|
||||
@ -21,38 +22,40 @@ EXIT STATUS
|
||||
Exit status is 0 if the command was successful.
|
||||
Exit status is 1 if there was any error.
|
||||
`,
|
||||
DisableAutoGenTag: true,
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
if globalOptions.JSON {
|
||||
type jsonVersion struct {
|
||||
MessageType string `json:"message_type"` // version
|
||||
Version string `json:"version"`
|
||||
GoVersion string `json:"go_version"`
|
||||
GoOS string `json:"go_os"`
|
||||
GoArch string `json:"go_arch"`
|
||||
DisableAutoGenTag: true,
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
if globalOptions.JSON {
|
||||
type jsonVersion struct {
|
||||
MessageType string `json:"message_type"` // version
|
||||
Version string `json:"version"`
|
||||
GoVersion string `json:"go_version"`
|
||||
GoOS string `json:"go_os"`
|
||||
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,
|
||||
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)
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRoot.AddCommand(versionCmd)
|
||||
cmdRoot.AddCommand(newVersionCommand())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user