restic/cmd/restic/cmd_ls.go

94 lines
2.6 KiB
Go
Raw Normal View History

2014-10-05 12:44:59 +00:00
package main
import (
"context"
2014-10-05 12:44:59 +00:00
"path/filepath"
2016-09-17 10:36:05 +00:00
"github.com/spf13/cobra"
2017-07-23 12:21:03 +00:00
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/repository"
2017-07-24 15:42:25 +00:00
"github.com/restic/restic/internal/restic"
2014-10-05 12:44:59 +00:00
)
2016-09-17 10:36:05 +00:00
var cmdLs = &cobra.Command{
Use: "ls [flags] [snapshot-ID ...]",
Short: "List files in a snapshot",
2016-09-17 10:36:05 +00:00
Long: `
The "ls" command allows listing files and directories in a snapshot.
2017-01-12 11:24:08 +00:00
The special snapshot-ID "latest" can be used to list files and directories of the latest snapshot in the repository.
2016-09-17 10:36:05 +00:00
`,
DisableAutoGenTag: true,
2016-09-17 10:36:05 +00:00
RunE: func(cmd *cobra.Command, args []string) error {
return runLs(lsOptions, globalOptions, args)
2016-09-17 10:36:05 +00:00
},
}
2014-12-07 15:30:52 +00:00
2017-01-14 03:19:47 +00:00
// LsOptions collects all options for the ls command.
type LsOptions struct {
ListLong bool
Host string
Tags restic.TagLists
2017-01-14 03:19:47 +00:00
Paths []string
}
var lsOptions LsOptions
2016-09-17 10:36:05 +00:00
2014-11-30 21:39:58 +00:00
func init() {
2016-09-17 10:36:05 +00:00
cmdRoot.AddCommand(cmdLs)
2017-01-14 03:19:47 +00:00
flags := cmdLs.Flags()
flags.BoolVarP(&lsOptions.ListLong, "long", "l", false, "use a long listing format showing size and mode")
flags.StringVarP(&lsOptions.Host, "host", "H", "", "only consider snapshots for this `host`, when no snapshot ID is given")
flags.Var(&lsOptions.Tags, "tag", "only consider snapshots which include this `taglist`, when no snapshot ID is given")
flags.StringArrayVar(&lsOptions.Paths, "path", nil, "only consider snapshots which include this (absolute) `path`, when no snapshot ID is given")
2014-11-30 21:39:58 +00:00
}
func printTree(ctx context.Context, repo *repository.Repository, id *restic.ID, prefix string) error {
tree, err := repo.LoadTree(ctx, *id)
2014-10-05 12:44:59 +00:00
if err != nil {
return err
}
for _, entry := range tree.Nodes {
Printf("%s\n", formatNode(prefix, entry, lsOptions.ListLong))
2014-10-05 12:44:59 +00:00
2016-09-01 19:20:03 +00:00
if entry.Type == "dir" && entry.Subtree != nil {
2018-03-30 20:35:18 +00:00
entryPath := prefix + string(filepath.Separator) + entry.Name
if err = printTree(ctx, repo, entry.Subtree, entryPath); err != nil {
2014-10-05 12:44:59 +00:00
return err
}
}
}
return nil
}
func runLs(opts LsOptions, gopts GlobalOptions, args []string) error {
if len(args) == 0 && opts.Host == "" && len(opts.Tags) == 0 && len(opts.Paths) == 0 {
return errors.Fatal("Invalid arguments, either give one or more snapshot IDs or set filters.")
2014-12-07 15:30:52 +00:00
}
2016-09-17 10:36:05 +00:00
repo, err := OpenRepository(gopts)
2014-12-07 15:30:52 +00:00
if err != nil {
return err
2014-10-05 12:44:59 +00:00
}
if err = repo.LoadIndex(gopts.ctx); err != nil {
return err
}
ctx, cancel := context.WithCancel(gopts.ctx)
defer cancel()
for sn := range FindFilteredSnapshots(ctx, repo, opts.Host, opts.Tags, opts.Paths, args) {
Verbosef("snapshot %s of %v at %s):\n", sn.ID().Str(), sn.Paths, sn.Time)
2017-01-12 11:24:08 +00:00
2018-03-30 20:35:18 +00:00
if err = printTree(gopts.ctx, repo, sn.Tree, ""); err != nil {
return err
2017-01-12 11:24:08 +00:00
}
2014-10-05 12:44:59 +00:00
}
return nil
2014-10-05 12:44:59 +00:00
}