package main import ( "fmt" "os" "path/filepath" "restic" "restic/errors" "restic/repository" ) type CmdLs struct { Long bool `short:"l" long:"long" description:"Use a long listing format showing size and mode"` global *GlobalOptions } func init() { _, err := parser.AddCommand("ls", "list files", "The ls command lists all files and directories in a snapshot", &CmdLs{global: &globalOpts}) if err != nil { panic(err) } } func (cmd CmdLs) printNode(prefix string, n *restic.Node) string { if !cmd.Long { return filepath.Join(prefix, n.Name) } switch n.Type { case "file": return fmt.Sprintf("%s %5d %5d %6d %s %s", n.Mode, n.UID, n.GID, n.Size, n.ModTime, filepath.Join(prefix, n.Name)) case "dir": return fmt.Sprintf("%s %5d %5d %6d %s %s", n.Mode|os.ModeDir, n.UID, n.GID, n.Size, n.ModTime, filepath.Join(prefix, n.Name)) case "symlink": return fmt.Sprintf("%s %5d %5d %6d %s %s -> %s", n.Mode|os.ModeSymlink, n.UID, n.GID, n.Size, n.ModTime, filepath.Join(prefix, n.Name), n.LinkTarget) default: return fmt.Sprintf("", n.Type, n.Name) } } func (cmd CmdLs) printTree(prefix string, repo *repository.Repository, id restic.ID) error { tree, err := repo.LoadTree(id) if err != nil { return err } for _, entry := range tree.Nodes { cmd.global.Printf(cmd.printNode(prefix, entry) + "\n") if entry.Type == "dir" && entry.Subtree != nil { err = cmd.printTree(filepath.Join(prefix, entry.Name), repo, *entry.Subtree) if err != nil { return err } } } return nil } func (cmd CmdLs) Usage() string { return "snapshot-ID [DIR]" } func (cmd CmdLs) Execute(args []string) error { if len(args) < 1 || len(args) > 2 { return errors.Fatalf("wrong number of arguments, Usage: %s", cmd.Usage()) } repo, err := cmd.global.OpenRepository() if err != nil { return err } err = repo.LoadIndex() if err != nil { return err } id, err := restic.FindSnapshot(repo, args[0]) if err != nil { return err } sn, err := restic.LoadSnapshot(repo, id) if err != nil { return err } cmd.global.Verbosef("snapshot of %v at %s:\n", sn.Paths, sn.Time) return cmd.printTree("", repo, *sn.Tree) }