From 7b47e3a2f42282c1f44dd167e5ac5e7e156e3aff Mon Sep 17 00:00:00 2001 From: rsteube Date: Sat, 27 Nov 2021 23:37:31 +0100 Subject: [PATCH] added restic --- completers/gh_completer/cmd/action/release.go | 4 +- completers/gh_completer/cmd/action/run.go | 4 +- .../restic_completer/cmd/action/host.go | 32 +++++++ .../restic_completer/cmd/action/snapshot.go | 90 +++++++++++++++++++ completers/restic_completer/cmd/backup.go | 59 ++++++++++++ completers/restic_completer/cmd/cache.go | 20 +++++ completers/restic_completer/cmd/cat.go | 31 +++++++ completers/restic_completer/cmd/check.go | 21 +++++ completers/restic_completer/cmd/copy.go | 44 +++++++++ completers/restic_completer/cmd/diff.go | 26 ++++++ completers/restic_completer/cmd/dump.go | 41 +++++++++ completers/restic_completer/cmd/find.go | 44 +++++++++ completers/restic_completer/cmd/forget.go | 58 ++++++++++++ completers/restic_completer/cmd/generate.go | 28 ++++++ completers/restic_completer/cmd/help.go | 17 ++++ completers/restic_completer/cmd/init.go | 31 +++++++ completers/restic_completer/cmd/key.go | 28 ++++++ completers/restic_completer/cmd/list.go | 21 +++++ completers/restic_completer/cmd/ls.go | 41 +++++++++ completers/restic_completer/cmd/migrate.go | 18 ++++ completers/restic_completer/cmd/mount.go | 33 +++++++ completers/restic_completer/cmd/prune.go | 21 +++++ .../restic_completer/cmd/rebuildIndex.go | 18 ++++ completers/restic_completer/cmd/recover.go | 17 ++++ completers/restic_completer/cmd/restore.go | 40 +++++++++ completers/restic_completer/cmd/root.go | 55 ++++++++++++ completers/restic_completer/cmd/selfUpdate.go | 22 +++++ completers/restic_completer/cmd/snapshots.go | 42 +++++++++ completers/restic_completer/cmd/stats.go | 37 ++++++++ completers/restic_completer/cmd/tag.go | 46 ++++++++++ completers/restic_completer/cmd/unlock.go | 18 ++++ completers/restic_completer/cmd/version.go | 17 ++++ completers/restic_completer/main.go | 7 ++ pkg/actions/time/time.go | 10 +-- pkg/actions/tools/pub/package.go | 4 +- .../action/utils/utils.go => pkg/util/ago.go | 3 +- 36 files changed, 1036 insertions(+), 12 deletions(-) create mode 100644 completers/restic_completer/cmd/action/host.go create mode 100644 completers/restic_completer/cmd/action/snapshot.go create mode 100644 completers/restic_completer/cmd/backup.go create mode 100644 completers/restic_completer/cmd/cache.go create mode 100644 completers/restic_completer/cmd/cat.go create mode 100644 completers/restic_completer/cmd/check.go create mode 100644 completers/restic_completer/cmd/copy.go create mode 100644 completers/restic_completer/cmd/diff.go create mode 100644 completers/restic_completer/cmd/dump.go create mode 100644 completers/restic_completer/cmd/find.go create mode 100644 completers/restic_completer/cmd/forget.go create mode 100644 completers/restic_completer/cmd/generate.go create mode 100644 completers/restic_completer/cmd/help.go create mode 100644 completers/restic_completer/cmd/init.go create mode 100644 completers/restic_completer/cmd/key.go create mode 100644 completers/restic_completer/cmd/list.go create mode 100644 completers/restic_completer/cmd/ls.go create mode 100644 completers/restic_completer/cmd/migrate.go create mode 100644 completers/restic_completer/cmd/mount.go create mode 100644 completers/restic_completer/cmd/prune.go create mode 100644 completers/restic_completer/cmd/rebuildIndex.go create mode 100644 completers/restic_completer/cmd/recover.go create mode 100644 completers/restic_completer/cmd/restore.go create mode 100644 completers/restic_completer/cmd/root.go create mode 100644 completers/restic_completer/cmd/selfUpdate.go create mode 100644 completers/restic_completer/cmd/snapshots.go create mode 100644 completers/restic_completer/cmd/stats.go create mode 100644 completers/restic_completer/cmd/tag.go create mode 100644 completers/restic_completer/cmd/unlock.go create mode 100644 completers/restic_completer/cmd/version.go create mode 100644 completers/restic_completer/main.go rename completers/gh_completer/cmd/action/utils/utils.go => pkg/util/ago.go (95%) diff --git a/completers/gh_completer/cmd/action/release.go b/completers/gh_completer/cmd/action/release.go index 9bdf6743ff..a7c86b68b0 100644 --- a/completers/gh_completer/cmd/action/release.go +++ b/completers/gh_completer/cmd/action/release.go @@ -4,7 +4,7 @@ import ( "time" "github.com/rsteube/carapace" - "github.com/rsteube/carapace-bin/completers/gh_completer/cmd/action/utils" + "github.com/rsteube/carapace-bin/pkg/util" "github.com/spf13/cobra" ) @@ -43,7 +43,7 @@ func ActionReleases(cmd *cobra.Command) carapace.Action { vals := make([]string, 0, len(releases)*2) for _, release := range releases { if release.Node.Tag.Name != "" { - vals = append(vals, release.Node.Tag.Name, utils.FuzzyAgo(time.Since(release.Node.CreatedAt))) + vals = append(vals, release.Node.Tag.Name, util.FuzzyAgo(time.Since(release.Node.CreatedAt))) } } return carapace.ActionValuesDescribed(vals...) diff --git a/completers/gh_completer/cmd/action/run.go b/completers/gh_completer/cmd/action/run.go index ebf442990e..f48e32e270 100644 --- a/completers/gh_completer/cmd/action/run.go +++ b/completers/gh_completer/cmd/action/run.go @@ -6,7 +6,7 @@ import ( "time" "github.com/rsteube/carapace" - "github.com/rsteube/carapace-bin/completers/gh_completer/cmd/action/utils" + "github.com/rsteube/carapace-bin/pkg/util" "github.com/spf13/cobra" ) @@ -46,7 +46,7 @@ func ActionWorkflowRuns(cmd *cobra.Command, opts RunOpts) carapace.Action { (opts.InProgress && run.Status == "in_progress") || (opts.Failed && run.Status == "completed" && run.Conclusion != "success") || (opts.Successful && run.Status == "completed" && run.Conclusion == "success") { - vals = append(vals, strconv.Itoa(run.Id), fmt.Sprintf("%v (%v) %v", run.Name, run.HeadBranch, utils.FuzzyAgo(ago))) + vals = append(vals, strconv.Itoa(run.Id), fmt.Sprintf("%v (%v) %v", run.Name, run.HeadBranch, util.FuzzyAgo(ago))) } } return carapace.ActionValuesDescribed(vals...) diff --git a/completers/restic_completer/cmd/action/host.go b/completers/restic_completer/cmd/action/host.go new file mode 100644 index 0000000000..8b00c2107e --- /dev/null +++ b/completers/restic_completer/cmd/action/host.go @@ -0,0 +1,32 @@ +package action + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/pkg/util" +) + +func ActionRepo() carapace.Action { + return carapace.ActionCallback(func(c carapace.Context) carapace.Action { + if util.HasPathPrefix(c.CallbackValue) { + return carapace.ActionDirectories() + } + return carapace.ActionMultiParts(":", func(c carapace.Context) carapace.Action { + switch len(c.Parts) { + case 0: + return carapace.ActionValuesDescribed( + "sftp", "SFTP", + "rest", "HTTP", + "s3", "Amazon S3", + "swift", "OpenStack Swift", + "b2", "Backblaze B2", + "azure", "Microsoft Azure Blob Storage", + "gs", "Google Cloud Storage", + "rclone", "rclone", + ).Invoke(c).Suffix(":").ToA() + default: + // TODO completion + return carapace.ActionValues() + } + }) + }) +} diff --git a/completers/restic_completer/cmd/action/snapshot.go b/completers/restic_completer/cmd/action/snapshot.go new file mode 100644 index 0000000000..a84319dc46 --- /dev/null +++ b/completers/restic_completer/cmd/action/snapshot.go @@ -0,0 +1,90 @@ +package action + +import ( + "encoding/json" + "time" + + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/pkg/util" + "github.com/spf13/cobra" +) + +type snapshot struct { + Hostname string + Short_id string + Tags []string `json:"tags,omitempty"` + Time time.Time +} + +type snapshotDetails struct { + Hostname string + Paths []string + Tags []string `json:"tags,omitempty"` + Time time.Time +} + +func actionSnapshots(cmd *cobra.Command, f func(snapshots []snapshot) carapace.Action) carapace.Action { + return carapace.ActionCallback(func(c carapace.Context) carapace.Action { + args := []string{"snapshots", "--json"} + if f := cmd.Flag("repo"); f.Changed { + args = append(args, "--repo", f.Value.String()) + } + return carapace.ActionExecCommand("restic", args...)(func(output []byte) carapace.Action { + var snapshots []snapshot + if err := json.Unmarshal(output, &snapshots); err != nil { + return carapace.ActionMessage(err.Error()) + } + return f(snapshots) + }) + }) +} + +func ActionSnapshotTags(cmd *cobra.Command) carapace.Action { + return actionSnapshots(cmd, func(snapshots []snapshot) carapace.Action { + tags := make(map[string]bool) + for _, s := range snapshots { + for _, t := range s.Tags { + tags[t] = true + } + } + + vals := make([]string, 0) + for tag := range tags { + vals = append(vals, tag) + } + return carapace.ActionValues(vals...) + }) +} + +func ActionSnapshotHosts(cmd *cobra.Command) carapace.Action { + return actionSnapshots(cmd, func(snapshots []snapshot) carapace.Action { + vals := make([]string, 0) + for _, s := range snapshots { + vals = append(vals, s.Hostname) + } + return carapace.ActionValues(vals...) + }) +} + +func ActionSnapshotIDs(cmd *cobra.Command) carapace.Action { + return actionSnapshots(cmd, func(snapshots []snapshot) carapace.Action { + vals := make([]string, 0) + for _, s := range snapshots { + vals = append(vals, s.Short_id, util.FuzzyAgo(time.Since(s.Time))) + } + return carapace.ActionValuesDescribed(vals...) + }) +} + +func ActionSnapshotPaths(cmd *cobra.Command, id string) carapace.Action { + // TODO repo/path/alias flags + return carapace.ActionCallback(func(c carapace.Context) carapace.Action { + return carapace.ActionExecCommand("restic", "cat", "snapshot", id)(func(output []byte) carapace.Action { + var details snapshotDetails + if err := json.Unmarshal(output, &details); err != nil { + return carapace.ActionMessage(err.Error()) + } + return carapace.ActionValues(details.Paths...) + }) + }) +} diff --git a/completers/restic_completer/cmd/backup.go b/completers/restic_completer/cmd/backup.go new file mode 100644 index 0000000000..a51e643d40 --- /dev/null +++ b/completers/restic_completer/cmd/backup.go @@ -0,0 +1,59 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/rsteube/carapace-bin/pkg/actions/time" + "github.com/spf13/cobra" +) + +var backupCmd = &cobra.Command{ + Use: "backup", + Short: "Create a new backup of files and/or directories", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(backupCmd).Standalone() + backupCmd.Flags().BoolP("dry-run", "n", false, "do not upload or write any data, just show what would be done") + backupCmd.Flags().StringArrayP("exclude", "e", []string{}, "exclude a `pattern` (can be specified multiple times)") + backupCmd.Flags().Bool("exclude-caches", false, "excludes cache directories that are marked with a CACHEDIR.TAG file. See https://bford.info/cachedir/ for the Cache Directory Tagging Standard") + backupCmd.Flags().StringArray("exclude-file", []string{}, "read exclude patterns from a `file` (can be specified multiple times)") + backupCmd.Flags().StringArray("exclude-if-present", []string{}, "takes `filename[:header]`, exclude contents of directories containing filename (except filename itself) if header of that file is as provided (can be specified multiple times)") + backupCmd.Flags().String("exclude-larger-than", "", "max `size` of the files to be backed up (allowed suffixes: k/K, m/M, g/G, t/T)") + backupCmd.Flags().StringArray("files-from", []string{}, "read the files to backup from `file` (can be combined with file args; can be specified multiple times)") + backupCmd.Flags().StringArray("files-from-raw", []string{}, "read the files to backup from `file` (can be combined with file args; can be specified multiple times)") + backupCmd.Flags().StringArray("files-from-verbatim", []string{}, "read the files to backup from `file` (can be combined with file args; can be specified multiple times)") + backupCmd.Flags().BoolP("force", "f", false, "force re-reading the target files/directories (overrides the \"parent\" flag)") + backupCmd.Flags().StringP("host", "H", "", "set the `hostname` for the snapshot manually. To prevent an expensive rescan use the \"parent\" flag") + backupCmd.Flags().String("hostname", "", "set the `hostname` for the snapshot manually") + backupCmd.Flags().StringArray("iexclude", []string{}, "same as --exclude `pattern` but ignores the casing of filenames") + backupCmd.Flags().StringArray("iexclude-file", []string{}, "same as --exclude-file but ignores casing of `file`names in patterns") + backupCmd.Flags().Bool("ignore-ctime", false, "ignore ctime changes when checking for modified files") + backupCmd.Flags().Bool("ignore-inode", false, "ignore inode number changes when checking for modified files") + backupCmd.Flags().BoolP("one-file-system", "x", false, "exclude other file systems, don't cross filesystem boundaries and subvolumes") + backupCmd.Flags().String("parent", "", "use this parent `snapshot` (default: last snapshot in the repo that has the same target files/directories)") + backupCmd.Flags().Bool("stdin", false, "read backup from stdin") + backupCmd.Flags().String("stdin-filename", "stdin", "`filename` to use when reading from stdin") + backupCmd.Flags().StringSlice("tag", []string{}, "add `tags` for the new snapshot in the format `tag[,tag,...]` (can be specified multiple times)") + backupCmd.Flags().String("time", "", "`time` of the backup (ex. '2012-11-01 22:08:41') (default: now)") + backupCmd.Flags().Bool("with-atime", false, "store the atime for all files and directories") + rootCmd.AddCommand(backupCmd) + + carapace.Gen(backupCmd).FlagCompletion(carapace.ActionMap{ + "exclude-file": carapace.ActionFiles(), + "files-from": carapace.ActionFiles(), + "files-from-raw": carapace.ActionFiles(), + "files-from-verbatim": carapace.ActionFiles(), + "host": action.ActionSnapshotHosts(backupCmd), + "parent": action.ActionSnapshotIDs(backupCmd), + "tag": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(backupCmd).Invoke(c).Filter(c.Parts).ToA() + }), + "time": time.ActionDateTime(), + }) + + carapace.Gen(backupCmd).PositionalAnyCompletion( + carapace.ActionFiles(), + ) +} diff --git a/completers/restic_completer/cmd/cache.go b/completers/restic_completer/cmd/cache.go new file mode 100644 index 0000000000..94ed9bb3ee --- /dev/null +++ b/completers/restic_completer/cmd/cache.go @@ -0,0 +1,20 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/spf13/cobra" +) + +var cacheCmd = &cobra.Command{ + Use: "cache", + Short: "Operate on local cache directories", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(cacheCmd).Standalone() + cacheCmd.Flags().Bool("cleanup", false, "remove old cache directories") + cacheCmd.Flags().Uint("max-age", 30, "max age in `days` for cache directories to be considered old") + cacheCmd.Flags().Bool("no-size", false, "do not output the size of the cache directories") + rootCmd.AddCommand(cacheCmd) +} diff --git a/completers/restic_completer/cmd/cat.go b/completers/restic_completer/cmd/cat.go new file mode 100644 index 0000000000..abe6436091 --- /dev/null +++ b/completers/restic_completer/cmd/cat.go @@ -0,0 +1,31 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var catCmd = &cobra.Command{ + Use: "cat", + Short: "Print internal objects to stdout", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(catCmd).Standalone() + rootCmd.AddCommand(catCmd) + + carapace.Gen(catCmd).PositionalCompletion( + carapace.ActionValues("pack", "blob", "snapshot", "index", "key", "masterkey", "config", "lock"), + carapace.ActionCallback(func(c carapace.Context) carapace.Action { + // TODO complete more objects + switch c.Args[0] { + case "snapshot": + return action.ActionSnapshotIDs(catCmd) + default: + return carapace.ActionValues() + } + }), + ) +} diff --git a/completers/restic_completer/cmd/check.go b/completers/restic_completer/cmd/check.go new file mode 100644 index 0000000000..0824f3e3d6 --- /dev/null +++ b/completers/restic_completer/cmd/check.go @@ -0,0 +1,21 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/spf13/cobra" +) + +var checkCmd = &cobra.Command{ + Use: "check", + Short: "Check the repository for errors", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(checkCmd).Standalone() + checkCmd.Flags().Bool("check-unused", false, "find unused blobs") + checkCmd.Flags().Bool("read-data", false, "read all data blobs") + checkCmd.Flags().String("read-data-subset", "", "read a `subset` of data packs, specified as 'n/t' for specific subset or either 'x%' or 'x.y%' for random subset") + checkCmd.Flags().Bool("with-cache", false, "use the cache") + rootCmd.AddCommand(checkCmd) +} diff --git a/completers/restic_completer/cmd/copy.go b/completers/restic_completer/cmd/copy.go new file mode 100644 index 0000000000..44ade642ac --- /dev/null +++ b/completers/restic_completer/cmd/copy.go @@ -0,0 +1,44 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var copyCmd = &cobra.Command{ + Use: "copy", + Short: "Copy snapshots from one repository to another", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(copyCmd).Standalone() + copyCmd.Flags().StringArrayP("host", "H", []string{}, "only consider snapshots for this `host`, when no snapshot ID is given (can be specified multiple times)") + copyCmd.Flags().String("key-hint2", "", "key ID of key to try decrypting the destination repository first (default: $RESTIC_KEY_HINT2)") + copyCmd.Flags().String("password-command2", "", "shell `command` to obtain the destination repository password from (default: $RESTIC_PASSWORD_COMMAND2)") + copyCmd.Flags().String("password-file2", "", "`file` to read the destination repository password from (default: $RESTIC_PASSWORD_FILE2)") + copyCmd.Flags().StringArray("path", []string{}, "only consider snapshots which include this (absolute) `path`, when no snapshot ID is given") + copyCmd.Flags().String("repo2", "", "destination `repository` to copy snapshots to (default: $RESTIC_REPOSITORY2)") + copyCmd.Flags().String("repository-file2", "", "`file` from which to read the destination repository location to copy snapshots to (default: $RESTIC_REPOSITORY_FILE2)") + copyCmd.Flags().StringSlice("tag", []string{}, "only consider snapshots which include this `taglist`, when no snapshot ID is given") + rootCmd.AddCommand(copyCmd) + + carapace.Gen(copyCmd).FlagCompletion(carapace.ActionMap{ + "host": action.ActionSnapshotHosts(copyCmd), + "password-command2": carapace.ActionFiles(), + "password-file2": carapace.ActionFiles(), + "path": carapace.ActionFiles(), + "repo2": action.ActionRepo(), + "repository-file2": carapace.ActionFiles(), + "tag": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(copyCmd).Invoke(c).Filter(c.Parts).ToA() + }), + }) + + carapace.Gen(copyCmd).PositionalAnyCompletion( + carapace.ActionCallback(func(c carapace.Context) carapace.Action { + return action.ActionSnapshotIDs(copyCmd).Invoke(c).Filter(c.Args).ToA() + }), + ) +} diff --git a/completers/restic_completer/cmd/diff.go b/completers/restic_completer/cmd/diff.go new file mode 100644 index 0000000000..4c0b9a9a99 --- /dev/null +++ b/completers/restic_completer/cmd/diff.go @@ -0,0 +1,26 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var diffCmd = &cobra.Command{ + Use: "diff", + Short: "Show differences between two snapshots", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(diffCmd).Standalone() + diffCmd.Flags().Bool("metadata", false, "print changes in metadata") + rootCmd.AddCommand(diffCmd) + + carapace.Gen(diffCmd).PositionalCompletion( + action.ActionSnapshotIDs(diffCmd), + carapace.ActionCallback(func(c carapace.Context) carapace.Action { + return action.ActionSnapshotIDs(diffCmd).Invoke(c).Filter(c.Args[:1]).ToA() + }), + ) +} diff --git a/completers/restic_completer/cmd/dump.go b/completers/restic_completer/cmd/dump.go new file mode 100644 index 0000000000..7868ce6bf8 --- /dev/null +++ b/completers/restic_completer/cmd/dump.go @@ -0,0 +1,41 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var dumpCmd = &cobra.Command{ + Use: "dump", + Short: "Print a backed-up file to stdout", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(dumpCmd).Standalone() + dumpCmd.Flags().StringP("archive", "a", "tar", "set archive `format` as \"tar\" or \"zip\"") + dumpCmd.Flags().StringArrayP("host", "H", []string{}, "only consider snapshots for this host when the snapshot ID is \"latest\" (can be specified multiple times)") + dumpCmd.Flags().StringArray("path", []string{}, "only consider snapshots which include this (absolute) `path` for snapshot ID \"latest\"") + dumpCmd.Flags().StringSlice("tag", []string{}, "only consider snapshots which include this `taglist` for snapshot ID \"latest\"") + rootCmd.AddCommand(dumpCmd) + + carapace.Gen(dumpCmd).FlagCompletion(carapace.ActionMap{ + "archive": carapace.ActionValues("tar", "zip"), + "host": action.ActionSnapshotHosts(dumpCmd), + "path": carapace.ActionFiles(), + "tag": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(dumpCmd).Invoke(c).Filter(c.Parts).ToA() + }), + }) + + carapace.Gen(dumpCmd).PositionalCompletion( + carapace.Batch( + action.ActionSnapshotIDs(dumpCmd), + carapace.ActionValues("latest"), + ).ToA(), + carapace.ActionCallback(func(c carapace.Context) carapace.Action { + return action.ActionSnapshotPaths(dumpCmd, c.Args[0]).Invoke(c).ToMultiPartsA("/") + }), + ) +} diff --git a/completers/restic_completer/cmd/find.go b/completers/restic_completer/cmd/find.go new file mode 100644 index 0000000000..d70497300c --- /dev/null +++ b/completers/restic_completer/cmd/find.go @@ -0,0 +1,44 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/rsteube/carapace-bin/pkg/actions/time" + "github.com/spf13/cobra" +) + +var findCmd = &cobra.Command{ + Use: "find", + Short: "Find a file, a directory or restic IDs", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(findCmd).Standalone() + findCmd.Flags().Bool("blob", false, "pattern is a blob-ID") + findCmd.Flags().StringArrayP("host", "H", []string{}, "only consider snapshots for this `host`, when no snapshot ID is given (can be specified multiple times)") + findCmd.Flags().BoolP("ignore-case", "i", false, "ignore case for pattern") + findCmd.Flags().BoolP("long", "l", false, "use a long listing format showing size and mode") + findCmd.Flags().StringP("newest", "N", "", "newest modification date/time") + findCmd.Flags().StringP("oldest", "O", "", "oldest modification date/time") + findCmd.Flags().Bool("pack", false, "pattern is a pack-ID") + findCmd.Flags().StringArray("path", []string{}, "only consider snapshots which include this (absolute) `path`, when no snapshot-ID is given") + findCmd.Flags().Bool("show-pack-id", false, "display the pack-ID the blobs belong to (with --blob or --tree)") + findCmd.Flags().StringArrayP("snapshot", "s", []string{}, "snapshot `id` to search in (can be given multiple times)") + findCmd.Flags().StringSlice("tag", []string{}, "only consider snapshots which include this `taglist`, when no snapshot-ID is given") + findCmd.Flags().Bool("tree", false, "pattern is a tree-ID") + rootCmd.AddCommand(findCmd) + + carapace.Gen(findCmd).FlagCompletion(carapace.ActionMap{ + "host": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotHosts(findCmd).Invoke(c).Filter(c.Args).ToA() + }), + "newest": time.ActionDateTime(), + "oldest": time.ActionDateTime(), + "path": carapace.ActionFiles(), + "snapshot": action.ActionSnapshotIDs(findCmd), + "tag": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(findCmd).Invoke(c).Filter(c.Parts).ToA() + }), + }) +} diff --git a/completers/restic_completer/cmd/forget.go b/completers/restic_completer/cmd/forget.go new file mode 100644 index 0000000000..549cdd638d --- /dev/null +++ b/completers/restic_completer/cmd/forget.go @@ -0,0 +1,58 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var forgetCmd = &cobra.Command{ + Use: "forget", + Short: "Remove snapshots from the repository", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(forgetCmd).Standalone() + forgetCmd.Flags().IntP("keep-last", "l", 0, "keep the last `n` snapshots") + forgetCmd.Flags().IntP("keep-hourly", "H", 0, "keep the last `n` hourly snapshots") + forgetCmd.Flags().IntP("keep-daily", "d", 0, "keep the last `n` daily snapshots") + forgetCmd.Flags().IntP("keep-weekly", "w", 0, "keep the last `n` weekly snapshots") + forgetCmd.Flags().IntP("keep-monthly", "m", 0, "keep the last `n` monthly snapshots") + forgetCmd.Flags().StringSlice("keep-tag", []string{}, "keep snapshots with this `taglist` (can be specified multiple times)") + forgetCmd.Flags().IntP("keep-yearly", "y", 0, "keep the last `n` yearly snapshots") + forgetCmd.Flags().BoolP("compact", "c", false, "use compact output format") + forgetCmd.Flags().BoolP("dry-run", "n", false, "do not delete anything, just print what would be done") + forgetCmd.Flags().StringP("group-by", "g", "host,paths", "string for grouping snapshots by host,paths,tags") + forgetCmd.Flags().StringArray("host", []string{}, "only consider snapshots with the given `host` (can be specified multiple times)") + forgetCmd.Flags().StringArray("hostname", []string{}, "only consider snapshots with the given `hostname` (can be specified multiple times)") + forgetCmd.Flags().String("keep-within", "", "keep snapshots that are newer than `duration` (eg. 1y5m7d2h) relative to the latest snapshot") + forgetCmd.Flags().String("keep-within-daily", "", "keep daily snapshots that are newer than `duration` (eg. 1y5m7d2h) relative to the latest snapshot") + forgetCmd.Flags().String("keep-within-hourly", "", "keep hourly snapshots that are newer than `duration` (eg. 1y5m7d2h) relative to the latest snapshot") + forgetCmd.Flags().String("keep-within-monthly", "", "keep monthly snapshots that are newer than `duration` (eg. 1y5m7d2h) relative to the latest snapshot") + forgetCmd.Flags().String("keep-within-weekly", "", "keep weekly snapshots that are newer than `duration` (eg. 1y5m7d2h) relative to the latest snapshot") + forgetCmd.Flags().String("keep-within-yearly", "", "keep yearly snapshots that are newer than `duration` (eg. 1y5m7d2h) relative to the latest snapshot") + forgetCmd.Flags().String("max-repack-size", "", "maximum `size` to repack (allowed suffixes: k/K, m/M, g/G, t/T)") + forgetCmd.Flags().String("max-unused", "5%", "tolerate given `limit` of unused data (absolute value in bytes with suffixes k/K, m/M, g/G, t/T, a value in % or the word 'unlimited')") + forgetCmd.Flags().StringArray("path", []string{}, "only consider snapshots which include this (absolute) `path` (can be specified multiple times)") + forgetCmd.Flags().Bool("prune", false, "automatically run the 'prune' command if snapshots have been removed") + forgetCmd.Flags().Bool("repack-cacheable-only", false, "only repack packs which are cacheable") + forgetCmd.Flags().StringSlice("tag", []string{}, "only consider snapshots which include this `taglist` in the format `tag[,tag,...]` (can be specified multiple times)") + rootCmd.AddCommand(forgetCmd) + + carapace.Gen(forgetCmd).FlagCompletion(carapace.ActionMap{ + "group-by": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return carapace.ActionValues("host", "paths", "tags").Invoke(c).Filter(c.Parts).ToA() + }), + "path": carapace.ActionFiles(), + "tag": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(forgetCmd).Invoke(c).Filter(c.Parts).ToA() + }), + }) + + carapace.Gen(forgetCmd).PositionalAnyCompletion( + carapace.ActionCallback(func(c carapace.Context) carapace.Action { + return action.ActionSnapshotIDs(forgetCmd).Invoke(c).Filter(c.Args).ToA() + }), + ) +} diff --git a/completers/restic_completer/cmd/generate.go b/completers/restic_completer/cmd/generate.go new file mode 100644 index 0000000000..05ffc21a9e --- /dev/null +++ b/completers/restic_completer/cmd/generate.go @@ -0,0 +1,28 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/spf13/cobra" +) + +var generateCmd = &cobra.Command{ + Use: "generate", + Short: "Generate manual pages and auto-completion files (bash, fish, zsh)", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(generateCmd).Standalone() + generateCmd.Flags().String("bash-completion", "", "write bash completion `file`") + generateCmd.Flags().String("fish-completion", "", "write fish completion `file`") + generateCmd.Flags().String("man", "", "write man pages to `directory`") + generateCmd.Flags().String("zsh-completion", "", "write zsh completion `file`") + rootCmd.AddCommand(generateCmd) + + carapace.Gen(generateCmd).FlagCompletion(carapace.ActionMap{ + "bash-completion": carapace.ActionFiles(), + "fish-completion": carapace.ActionFiles(), + "man": carapace.ActionDirectories(), + "zsh-completion": carapace.ActionFiles(), + }) +} diff --git a/completers/restic_completer/cmd/help.go b/completers/restic_completer/cmd/help.go new file mode 100644 index 0000000000..f55758d2d7 --- /dev/null +++ b/completers/restic_completer/cmd/help.go @@ -0,0 +1,17 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/spf13/cobra" +) + +var helpCmd = &cobra.Command{ + Use: "help", + Short: "Help about any command", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(helpCmd).Standalone() + rootCmd.AddCommand(helpCmd) +} diff --git a/completers/restic_completer/cmd/init.go b/completers/restic_completer/cmd/init.go new file mode 100644 index 0000000000..557fe5bda5 --- /dev/null +++ b/completers/restic_completer/cmd/init.go @@ -0,0 +1,31 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var initCmd = &cobra.Command{ + Use: "init", + Short: "Initialize a new repository", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(initCmd).Standalone() + initCmd.Flags().Bool("copy-chunker-params", false, "copy chunker parameters from the secondary repository (useful with the copy command)") + initCmd.Flags().String("key-hint2", "", "key ID of key to try decrypting the secondary repository first (default: $RESTIC_KEY_HINT2)") + initCmd.Flags().String("password-command2", "", "shell `command` to obtain the secondary repository password from (default: $RESTIC_PASSWORD_COMMAND2)") + initCmd.Flags().String("password-file2", "", "`file` to read the secondary repository password from (default: $RESTIC_PASSWORD_FILE2)") + initCmd.Flags().String("repo2", "", "secondary `repository` to copy chunker parameters from (default: $RESTIC_REPOSITORY2)") + initCmd.Flags().String("repository-file2", "", "`file` from which to read the secondary repository location to copy chunker parameters from (default: $RESTIC_REPOSITORY_FILE2)") + rootCmd.AddCommand(initCmd) + + carapace.Gen(initCmd).FlagCompletion(carapace.ActionMap{ + "password-command2": carapace.ActionFiles(), + "password-file2": carapace.ActionFiles(), + "repo2": action.ActionRepo(), + "repository-file2": carapace.ActionFiles(), + }) +} diff --git a/completers/restic_completer/cmd/key.go b/completers/restic_completer/cmd/key.go new file mode 100644 index 0000000000..83b68d945e --- /dev/null +++ b/completers/restic_completer/cmd/key.go @@ -0,0 +1,28 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/pkg/actions/net" + "github.com/rsteube/carapace-bin/pkg/actions/os" + "github.com/spf13/cobra" +) + +var keyCmd = &cobra.Command{ + Use: "key", + Short: "Manage keys (passwords)", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(keyCmd).Standalone() + keyCmd.Flags().String("host", "", "the hostname for new keys") + keyCmd.Flags().String("new-password-file", "", "`file` from which to read the new password") + keyCmd.Flags().String("user", "", "the username for new keys") + rootCmd.AddCommand(keyCmd) + + carapace.Gen(keyCmd).FlagCompletion(carapace.ActionMap{ + "host": net.ActionHosts(), + "new-password-file": carapace.ActionFiles(), + "user": os.ActionUsers(), + }) +} diff --git a/completers/restic_completer/cmd/list.go b/completers/restic_completer/cmd/list.go new file mode 100644 index 0000000000..e0265848e2 --- /dev/null +++ b/completers/restic_completer/cmd/list.go @@ -0,0 +1,21 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/spf13/cobra" +) + +var listCmd = &cobra.Command{ + Use: "list", + Short: "List objects in the repository", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(listCmd).Standalone() + rootCmd.AddCommand(listCmd) + + carapace.Gen(listCmd).PositionalCompletion( + carapace.ActionValues("blobs", "packs", "index", "snapshots", "keys", "locks"), + ) +} diff --git a/completers/restic_completer/cmd/ls.go b/completers/restic_completer/cmd/ls.go new file mode 100644 index 0000000000..ad72cf37c9 --- /dev/null +++ b/completers/restic_completer/cmd/ls.go @@ -0,0 +1,41 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var lsCmd = &cobra.Command{ + Use: "ls", + Short: "List files in a snapshot", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(lsCmd).Standalone() + lsCmd.Flags().StringArrayP("host", "H", []string{}, "only consider snapshots for this `host`, when no snapshot ID is given (can be specified multiple times)") + lsCmd.Flags().BoolP("long", "l", false, "use a long listing format showing size and mode") + lsCmd.Flags().StringArray("path", []string{}, "only consider snapshots which include this (absolute) `path`, when no snapshot ID is given") + lsCmd.Flags().Bool("recursive", false, "include files in subfolders of the listed directories") + lsCmd.Flags().StringSlice("tag", []string{}, "only consider snapshots which include this `taglist`, when no snapshot ID is given") + rootCmd.AddCommand(lsCmd) + + carapace.Gen(lsCmd).FlagCompletion(carapace.ActionMap{ + "host": action.ActionSnapshotHosts(lsCmd), + "path": carapace.ActionFiles(), + "tag": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(lsCmd).Invoke(c).Filter(c.Parts).ToA() + }), + }) + + carapace.Gen(lsCmd).PositionalCompletion( + action.ActionSnapshotIDs(lsCmd), + ) + + carapace.Gen(lsCmd).PositionalAnyCompletion( + carapace.ActionCallback(func(c carapace.Context) carapace.Action { + return action.ActionSnapshotPaths(lsCmd, c.Args[0]).Invoke(c).ToMultiPartsA("/") + }), + ) +} diff --git a/completers/restic_completer/cmd/migrate.go b/completers/restic_completer/cmd/migrate.go new file mode 100644 index 0000000000..7e3ee3ae25 --- /dev/null +++ b/completers/restic_completer/cmd/migrate.go @@ -0,0 +1,18 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/spf13/cobra" +) + +var migrateCmd = &cobra.Command{ + Use: "migrate", + Short: "Apply migrations", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(migrateCmd).Standalone() + migrateCmd.Flags().BoolP("force", "f", false, "apply a migration a second time") + rootCmd.AddCommand(migrateCmd) +} diff --git a/completers/restic_completer/cmd/mount.go b/completers/restic_completer/cmd/mount.go new file mode 100644 index 0000000000..a112947816 --- /dev/null +++ b/completers/restic_completer/cmd/mount.go @@ -0,0 +1,33 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var mountCmd = &cobra.Command{ + Use: "mount", + Short: "Mount the repository", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(mountCmd).Standalone() + mountCmd.Flags().Bool("allow-other", false, "allow other users to access the data in the mounted directory") + mountCmd.Flags().StringArrayP("host", "H", []string{}, "only consider snapshots for this host (can be specified multiple times)") + mountCmd.Flags().Bool("no-default-permissions", false, "for 'allow-other', ignore Unix permissions and allow users to read all snapshot files") + mountCmd.Flags().Bool("owner-root", false, "use 'root' as the owner of files and dirs") + mountCmd.Flags().StringArray("path", []string{}, "only consider snapshots which include this (absolute) `path`") + mountCmd.Flags().String("snapshot-template", "2006-01-02T15:04:05Z07:00", "set `template` to use for snapshot dirs") + mountCmd.Flags().StringSlice("tag", []string{}, "only consider snapshots which include this `taglist`") + rootCmd.AddCommand(mountCmd) + + carapace.Gen(mountCmd).FlagCompletion(carapace.ActionMap{ + "host": action.ActionSnapshotHosts(mountCmd), + "path": carapace.ActionFiles(), + "tag": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(mountCmd).Invoke(c).Filter(c.Parts).ToA() + }), + }) +} diff --git a/completers/restic_completer/cmd/prune.go b/completers/restic_completer/cmd/prune.go new file mode 100644 index 0000000000..4a2ae7f9e3 --- /dev/null +++ b/completers/restic_completer/cmd/prune.go @@ -0,0 +1,21 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/spf13/cobra" +) + +var pruneCmd = &cobra.Command{ + Use: "prune", + Short: "Remove unneeded data from the repository", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(pruneCmd).Standalone() + pruneCmd.Flags().BoolP("dry-run", "n", false, "do not modify the repository, just print what would be done") + pruneCmd.Flags().String("max-repack-size", "", "maximum `size` to repack (allowed suffixes: k/K, m/M, g/G, t/T)") + pruneCmd.Flags().String("max-unused", "5%", "tolerate given `limit` of unused data (absolute value in bytes with suffixes k/K, m/M, g/G, t/T, a value in % or the word 'unlimited')") + pruneCmd.Flags().Bool("repack-cacheable-only", false, "only repack packs which are cacheable") + rootCmd.AddCommand(pruneCmd) +} diff --git a/completers/restic_completer/cmd/rebuildIndex.go b/completers/restic_completer/cmd/rebuildIndex.go new file mode 100644 index 0000000000..e95aad0168 --- /dev/null +++ b/completers/restic_completer/cmd/rebuildIndex.go @@ -0,0 +1,18 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/spf13/cobra" +) + +var rebuildIndexCmd = &cobra.Command{ + Use: "rebuild-index", + Short: "Build a new index", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(rebuildIndexCmd).Standalone() + rebuildIndexCmd.Flags().Bool("read-all-packs", false, "read all pack files to generate new index from scratch") + rootCmd.AddCommand(rebuildIndexCmd) +} diff --git a/completers/restic_completer/cmd/recover.go b/completers/restic_completer/cmd/recover.go new file mode 100644 index 0000000000..a1a3afb36b --- /dev/null +++ b/completers/restic_completer/cmd/recover.go @@ -0,0 +1,17 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/spf13/cobra" +) + +var recoverCmd = &cobra.Command{ + Use: "recover", + Short: "Recover data from the repository not referenced by snapshots", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(recoverCmd).Standalone() + rootCmd.AddCommand(recoverCmd) +} diff --git a/completers/restic_completer/cmd/restore.go b/completers/restic_completer/cmd/restore.go new file mode 100644 index 0000000000..df361a8f95 --- /dev/null +++ b/completers/restic_completer/cmd/restore.go @@ -0,0 +1,40 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var restoreCmd = &cobra.Command{ + Use: "restore", + Short: "Extract the data from a snapshot", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(restoreCmd).Standalone() + restoreCmd.Flags().StringArrayP("exclude", "e", []string{}, "exclude a `pattern` (can be specified multiple times)") + restoreCmd.Flags().StringArrayP("host", "H", []string{}, "only consider snapshots for this host when the snapshot ID is \"latest\" (can be specified multiple times)") + restoreCmd.Flags().StringArray("iexclude", []string{}, "same as `--exclude` but ignores the casing of filenames") + restoreCmd.Flags().StringArray("iinclude", []string{}, "same as `--include` but ignores the casing of filenames") + restoreCmd.Flags().StringArrayP("include", "i", []string{}, "include a `pattern`, exclude everything else (can be specified multiple times)") + restoreCmd.Flags().StringArray("path", []string{}, "only consider snapshots which include this (absolute) `path` for snapshot ID \"latest\"") + restoreCmd.Flags().StringSlice("tag", []string{}, "only consider snapshots which include this `taglist` for snapshot ID \"latest\"") + restoreCmd.Flags().StringP("target", "t", "", "directory to extract data to") + restoreCmd.Flags().Bool("verify", false, "verify restored files content") + rootCmd.AddCommand(restoreCmd) + + carapace.Gen(restoreCmd).FlagCompletion(carapace.ActionMap{ + "host": action.ActionSnapshotHosts(restoreCmd), + "path": carapace.ActionFiles(), + "tag": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(restoreCmd).Invoke(c).Filter(c.Parts).ToA() + }), + "target": carapace.ActionDirectories(), + }) + + carapace.Gen(restoreCmd).PositionalCompletion( + action.ActionSnapshotIDs(restoreCmd), + ) +} diff --git a/completers/restic_completer/cmd/root.go b/completers/restic_completer/cmd/root.go new file mode 100644 index 0000000000..d5a34a8d84 --- /dev/null +++ b/completers/restic_completer/cmd/root.go @@ -0,0 +1,55 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var rootCmd = &cobra.Command{ + Use: "restic", + Short: "Backup and restore files", + Long: "https://restic.net/", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func Execute() error { + return rootCmd.Execute() +} + +func init() { + carapace.Gen(rootCmd).Standalone() + rootCmd.PersistentFlags().StringSlice("cacert", []string{}, "`file` to load root certificates from (default: use system certificates)") + rootCmd.PersistentFlags().String("cache-dir", "", "set the cache `directory`. (default: use system default cache directory)") + rootCmd.PersistentFlags().Bool("cleanup-cache", false, "auto remove old cache directories") + rootCmd.Flags().BoolP("help", "h", false, "help for restic") + rootCmd.PersistentFlags().Bool("insecure-tls", false, "skip TLS certificate verification when connecting to the repo (insecure)") + rootCmd.PersistentFlags().Bool("json", false, "set output mode to JSON for commands that support it") + rootCmd.PersistentFlags().String("key-hint", "", "`key` ID of key to try decrypting first (default: $RESTIC_KEY_HINT)") + rootCmd.PersistentFlags().Int("limit-download", 0, "limits downloads to a maximum rate in KiB/s. (default: unlimited)") + rootCmd.PersistentFlags().Int("limit-upload", 0, "limits uploads to a maximum rate in KiB/s. (default: unlimited)") + rootCmd.PersistentFlags().Bool("no-cache", false, "do not use a local cache") + rootCmd.PersistentFlags().Bool("no-lock", false, "do not lock the repository, this allows some operations on read-only repositories") + rootCmd.PersistentFlags().StringSliceP("option", "o", []string{}, "set extended option (`key=value`, can be specified multiple times)") + rootCmd.PersistentFlags().String("password-command", "", "shell `command` to obtain the repository password from (default: $RESTIC_PASSWORD_COMMAND)") + rootCmd.PersistentFlags().StringP("password-file", "p", "", "`file` to read the repository password from (default: $RESTIC_PASSWORD_FILE)") + rootCmd.PersistentFlags().BoolP("quiet", "q", false, "do not output comprehensive progress report") + rootCmd.PersistentFlags().StringP("repo", "r", "", "`repository` to backup to or restore from (default: $RESTIC_REPOSITORY)") + rootCmd.PersistentFlags().String("repository-file", "", "`file` to read the repository location from (default: $RESTIC_REPOSITORY_FILE)") + rootCmd.PersistentFlags().String("tls-client-cert", "", "path to a `file` containing PEM encoded TLS client certificate and private key") + rootCmd.PersistentFlags().StringArrayP("verbose", "v", []string{}, "be verbose (specify multiple times or a level using --verbose=`n`, max level/times is 3)") + rootCmd.Flag("verbose").NoOptDefVal = "+1" + + carapace.Gen(rootCmd).FlagCompletion(carapace.ActionMap{ + "cacert": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return carapace.ActionFiles() + }), + "cache-dir": carapace.ActionDirectories(), + "password-command": carapace.ActionFiles(), + "password-file": carapace.ActionFiles(), + "repo": action.ActionRepo(), + "repository-file": carapace.ActionFiles(), + "tls-client-cert": carapace.ActionFiles(), + "verbose": carapace.ActionValues("1", "2", "3"), + }) +} diff --git a/completers/restic_completer/cmd/selfUpdate.go b/completers/restic_completer/cmd/selfUpdate.go new file mode 100644 index 0000000000..009cfb45d3 --- /dev/null +++ b/completers/restic_completer/cmd/selfUpdate.go @@ -0,0 +1,22 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/spf13/cobra" +) + +var selfUpdateCmd = &cobra.Command{ + Use: "self-update", + Short: "Update the restic binary", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(selfUpdateCmd).Standalone() + selfUpdateCmd.Flags().String("output", "", "Save the downloaded file as `filename` (default: running binary itself)") + rootCmd.AddCommand(selfUpdateCmd) + + carapace.Gen(selfUpdateCmd).FlagCompletion(carapace.ActionMap{ + "output": carapace.ActionFiles(), + }) +} diff --git a/completers/restic_completer/cmd/snapshots.go b/completers/restic_completer/cmd/snapshots.go new file mode 100644 index 0000000000..e9fc9f1067 --- /dev/null +++ b/completers/restic_completer/cmd/snapshots.go @@ -0,0 +1,42 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var snapshotsCmd = &cobra.Command{ + Use: "snapshots", + Short: "List all snapshots", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(snapshotsCmd).Standalone() + snapshotsCmd.Flags().BoolP("compact", "c", false, "use compact output format") + snapshotsCmd.Flags().StringP("group-by", "g", "", "string for grouping snapshots by host,paths,tags") + snapshotsCmd.Flags().StringArrayP("host", "H", []string{}, "only consider snapshots for this `host` (can be specified multiple times)") + snapshotsCmd.Flags().Bool("last", false, "only show the last snapshot for each host and path") + snapshotsCmd.Flags().Int("latest", 0, "only show the last `n` snapshots for each host and path") + snapshotsCmd.Flags().StringArray("path", []string{}, "only consider snapshots for this `path` (can be specified multiple times)") + snapshotsCmd.Flags().StringSlice("tag", []string{}, "only consider snapshots which include this `taglist` in the format `tag[,tag,...]` (can be specified multiple times)") + rootCmd.AddCommand(snapshotsCmd) + + carapace.Gen(snapshotsCmd).FlagCompletion(carapace.ActionMap{ + "group-by": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return carapace.ActionValues("host", "paths", "tags").Invoke(c).Filter(c.Parts).ToA() + }), + "host": action.ActionSnapshotHosts(snapshotsCmd), + "path": carapace.ActionFiles(), + "tag": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(snapshotsCmd).Invoke(c).Filter(c.Parts).ToA() + }), + }) + + carapace.Gen(snapshotsCmd).PositionalAnyCompletion( + carapace.ActionCallback(func(c carapace.Context) carapace.Action { + return action.ActionSnapshotIDs(snapshotsCmd).Invoke(c).Filter(c.Parts).ToA() + }), + ) +} diff --git a/completers/restic_completer/cmd/stats.go b/completers/restic_completer/cmd/stats.go new file mode 100644 index 0000000000..f0545da2db --- /dev/null +++ b/completers/restic_completer/cmd/stats.go @@ -0,0 +1,37 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var statsCmd = &cobra.Command{ + Use: "stats", + Short: "Scan the repository and show basic statistics", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(statsCmd).Standalone() + statsCmd.Flags().StringArrayP("host", "H", []string{}, "only consider snapshots with the given `host` (can be specified multiple times)") + statsCmd.Flags().String("mode", "restore-size", "counting mode: restore-size (default), files-by-contents, blobs-per-file or raw-data") + statsCmd.Flags().StringArray("path", []string{}, "only consider snapshots which include this (absolute) `path` (can be specified multiple times)") + statsCmd.Flags().StringSlice("tag", []string{}, "only consider snapshots which include this `taglist` in the format `tag[,tag,...]` (can be specified multiple times)") + rootCmd.AddCommand(statsCmd) + + carapace.Gen(statsCmd).FlagCompletion(carapace.ActionMap{ + "host": action.ActionSnapshotHosts(statsCmd), + "mode": carapace.ActionValues("restore-size", "files-by-contents", "blobs-per-file", "raw-data"), + "path": carapace.ActionFiles(), + "tag": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(statsCmd).Invoke(c).Filter(c.Parts).ToA() + }), + }) + + carapace.Gen(statsCmd).PositionalAnyCompletion( + carapace.ActionCallback(func(c carapace.Context) carapace.Action { + return action.ActionSnapshotIDs(statsCmd).Invoke(c).Filter(c.Parts).ToA() + }), + ) +} diff --git a/completers/restic_completer/cmd/tag.go b/completers/restic_completer/cmd/tag.go new file mode 100644 index 0000000000..305244f84a --- /dev/null +++ b/completers/restic_completer/cmd/tag.go @@ -0,0 +1,46 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/restic_completer/cmd/action" + "github.com/spf13/cobra" +) + +var tagCmd = &cobra.Command{ + Use: "tag", + Short: "Modify tags on snapshots", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(tagCmd).Standalone() + tagCmd.Flags().StringSlice("add", []string{}, "`tags` which will be added to the existing tags in the format `tag[,tag,...]` (can be given multiple times)") + tagCmd.Flags().StringArrayP("host", "H", []string{}, "only consider snapshots for this `host`, when no snapshot ID is given (can be specified multiple times)") + tagCmd.Flags().StringArray("path", []string{}, "only consider snapshots which include this (absolute) `path`, when no snapshot-ID is given") + tagCmd.Flags().StringSlice("remove", []string{}, "`tags` which will be removed from the existing tags in the format `tag[,tag,...]` (can be given multiple times)") + tagCmd.Flags().StringSlice("set", []string{}, "`tags` which will replace the existing tags in the format `tag[,tag,...]` (can be given multiple times)") + tagCmd.Flags().StringSlice("tag", []string{}, "only consider snapshots which include this `taglist`, when no snapshot-ID is given") + rootCmd.AddCommand(tagCmd) + + carapace.Gen(tagCmd).FlagCompletion(carapace.ActionMap{ + "add": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(tagCmd).Invoke(c).Filter(c.Parts).ToA() + }), + "host": action.ActionSnapshotHosts(tagCmd), + "remove": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(tagCmd).Invoke(c).Filter(c.Parts).ToA() + }), + "set": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(tagCmd).Invoke(c).Filter(c.Parts).ToA() + }), + "tag": carapace.ActionMultiParts(",", func(c carapace.Context) carapace.Action { + return action.ActionSnapshotTags(tagCmd).Invoke(c).Filter(c.Parts).ToA() + }), + }) + + carapace.Gen(tagCmd).PositionalAnyCompletion( + carapace.ActionCallback(func(c carapace.Context) carapace.Action { + return action.ActionSnapshotIDs(tagCmd).Invoke(c).Filter(c.Parts).ToA() + }), + ) +} diff --git a/completers/restic_completer/cmd/unlock.go b/completers/restic_completer/cmd/unlock.go new file mode 100644 index 0000000000..ea69fe71de --- /dev/null +++ b/completers/restic_completer/cmd/unlock.go @@ -0,0 +1,18 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/spf13/cobra" +) + +var unlockCmd = &cobra.Command{ + Use: "unlock", + Short: "Remove locks other processes created", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(unlockCmd).Standalone() + unlockCmd.Flags().Bool("remove-all", false, "remove all locks, even non-stale ones") + rootCmd.AddCommand(unlockCmd) +} diff --git a/completers/restic_completer/cmd/version.go b/completers/restic_completer/cmd/version.go new file mode 100644 index 0000000000..04e3a72f56 --- /dev/null +++ b/completers/restic_completer/cmd/version.go @@ -0,0 +1,17 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/spf13/cobra" +) + +var versionCmd = &cobra.Command{ + Use: "version", + Short: "Print version information", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(versionCmd).Standalone() + rootCmd.AddCommand(versionCmd) +} diff --git a/completers/restic_completer/main.go b/completers/restic_completer/main.go new file mode 100644 index 0000000000..33bd112be9 --- /dev/null +++ b/completers/restic_completer/main.go @@ -0,0 +1,7 @@ +package main + +import "github.com/rsteube/carapace-bin/completers/restic_completer/cmd" + +func main() { + cmd.Execute() +} diff --git a/pkg/actions/time/time.go b/pkg/actions/time/time.go index 01af2918d1..2e28e27178 100644 --- a/pkg/actions/time/time.go +++ b/pkg/actions/time/time.go @@ -112,15 +112,15 @@ func ActionTimeS() carapace.Action { }) } -// ActionDateTime completes `yyyy-MM-ddThh:mm:ss` datetime -// 2021-11-11T04:02:12 -// 2021-04-02T16:11:33 +// ActionDateTime completes `yyyy-MM-dd hh:mm:ss` datetime +// 2021-11-11 04:02:12 +// 2021-04-02 16:11:33 func ActionDateTime() carapace.Action { - return carapace.ActionMultiParts("T", func(c carapace.Context) carapace.Action { + return carapace.ActionMultiParts(" ", func(c carapace.Context) carapace.Action { switch len(c.Parts) { case 0: if strings.Count(c.CallbackValue, "-") == 2 { - return ActionDate().Invoke(c).Suffix("T").ToA() + return ActionDate().Invoke(c).Suffix(" ").ToA() } return ActionDate() case 1: diff --git a/pkg/actions/tools/pub/package.go b/pkg/actions/tools/pub/package.go index a6c24e840c..6aa31cb331 100644 --- a/pkg/actions/tools/pub/package.go +++ b/pkg/actions/tools/pub/package.go @@ -8,7 +8,7 @@ import ( "time" "github.com/rsteube/carapace" - "github.com/rsteube/carapace-bin/completers/gh_completer/cmd/action/utils" + "github.com/rsteube/carapace-bin/pkg/util" ) type searchResult struct { @@ -72,7 +72,7 @@ func ActionPackageVersions(pkg string) carapace.Action { vals := make([]string, 0) for _, v := range result.Versions { - vals = append(vals, v.Version, utils.FuzzyAgo(time.Since(v.Published))) + vals = append(vals, v.Version, util.FuzzyAgo(time.Since(v.Published))) } return carapace.ActionValuesDescribed(vals...) }) diff --git a/completers/gh_completer/cmd/action/utils/utils.go b/pkg/util/ago.go similarity index 95% rename from completers/gh_completer/cmd/action/utils/utils.go rename to pkg/util/ago.go index 8b619b25e6..d93f3f1344 100644 --- a/completers/gh_completer/cmd/action/utils/utils.go +++ b/pkg/util/ago.go @@ -1,4 +1,5 @@ -package utils +// source https://github.com/cli/cli/blob/trunk/utils/utils.go +package util import ( "fmt"