forked from TrueCloudLab/restic
Apply feedback and use SkipNode
This commit is contained in:
parent
156d85a29b
commit
00e2fd8b5f
1 changed files with 36 additions and 23 deletions
|
@ -2,12 +2,13 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"path/filepath"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/restic/restic/internal/errors"
|
"github.com/restic/restic/internal/errors"
|
||||||
|
"github.com/restic/restic/internal/fs"
|
||||||
"github.com/restic/restic/internal/restic"
|
"github.com/restic/restic/internal/restic"
|
||||||
"github.com/restic/restic/internal/walker"
|
"github.com/restic/restic/internal/walker"
|
||||||
)
|
)
|
||||||
|
@ -25,9 +26,11 @@ snapshot originating from a certain host only.
|
||||||
|
|
||||||
File listings can optionally be filtered by directories. Any
|
File listings can optionally be filtered by directories. Any
|
||||||
positional arguments after the snapshot ID are interpreted as
|
positional arguments after the snapshot ID are interpreted as
|
||||||
directory paths, and only files inside those directories will
|
absolute directory paths, and only files inside those directories
|
||||||
be listed. If the --recursive flag is used, then the filter
|
will be listed. If the --recursive flag is used, then the filter
|
||||||
will allow traversing into matching directories' subfolders.
|
will allow traversing into matching directories' subfolders.
|
||||||
|
Any directory paths specified must be absolute (starting with
|
||||||
|
a path separator); paths use the forward slash '/' as separator.
|
||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
@ -75,16 +78,17 @@ func runLs(opts LsOptions, gopts GlobalOptions, args []string) error {
|
||||||
var dirs []string
|
var dirs []string
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
dirs = args[1:]
|
dirs = args[1:]
|
||||||
|
for _, dir := range dirs {
|
||||||
|
if !strings.HasPrefix(dir, "/") {
|
||||||
|
return errors.Fatal("All path filters must be absolute, starting with a forward slash '/'")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(gopts.ctx)
|
ctx, cancel := context.WithCancel(gopts.ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
for sn := range FindFilteredSnapshots(ctx, repo, opts.Host, opts.Tags, opts.Paths, args[:1]) {
|
for sn := range FindFilteredSnapshots(ctx, repo, opts.Host, opts.Tags, opts.Paths, args[:1]) {
|
||||||
dirsToPrint := opts.Paths
|
Verbosef("snapshot %s of %v filtered by %v at %s):\n", sn.ID().Str(), sn.Paths, dirs, sn.Time)
|
||||||
if len(dirs) > 0 {
|
|
||||||
dirsToPrint = dirs
|
|
||||||
}
|
|
||||||
Verbosef("snapshot %s of %v at %s):\n", sn.ID().Str(), dirsToPrint, sn.Time)
|
|
||||||
|
|
||||||
err := walker.Walk(ctx, repo, *sn.Tree, nil, func(nodepath string, node *restic.Node, err error) (bool, error) {
|
err := walker.Walk(ctx, repo, *sn.Tree, nil, func(nodepath string, node *restic.Node, err error) (bool, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -96,31 +100,40 @@ func runLs(opts LsOptions, gopts GlobalOptions, args []string) error {
|
||||||
|
|
||||||
// apply any directory filters
|
// apply any directory filters
|
||||||
if len(dirs) > 0 {
|
if len(dirs) > 0 {
|
||||||
var nodeDir string
|
// this first iteration ensures we do not traverse branches that
|
||||||
if !opts.Recursive {
|
// are not in matching trees or will not lead us to matching trees
|
||||||
// only needed for exact directory match; i.e. no subfolders
|
var walk bool
|
||||||
nodeDir = filepath.Dir(nodepath)
|
for _, dir := range dirs {
|
||||||
|
if fs.HasPathPrefix(nodepath, dir) || fs.HasPathPrefix(dir, nodepath) {
|
||||||
|
// we are either in or approaching the right tree
|
||||||
|
walk = true
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if !walk {
|
||||||
|
return false, walker.SkipNode
|
||||||
|
}
|
||||||
|
|
||||||
|
// this second iteration ensures that we get an exact match
|
||||||
|
// according to the filter and whether we should match subfolders
|
||||||
var match bool
|
var match bool
|
||||||
for _, dir := range dirs {
|
for _, dir := range dirs {
|
||||||
if opts.Recursive {
|
if opts.Recursive && fs.HasPathPrefix(dir, nodepath) {
|
||||||
if strings.HasPrefix(nodepath, dir) {
|
match = true
|
||||||
match = true
|
break
|
||||||
break
|
}
|
||||||
}
|
if !opts.Recursive && path.Dir(nodepath) == dir {
|
||||||
} else {
|
match = true
|
||||||
if nodeDir == dir {
|
break
|
||||||
match = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !match {
|
if !match {
|
||||||
return true, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Printf("%s\n", formatNode(nodepath, node, lsOptions.ListLong))
|
Printf("%s\n", formatNode(nodepath, node, lsOptions.ListLong))
|
||||||
|
|
||||||
return false, nil
|
return false, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue