mirror of
https://github.com/octoleo/restic.git
synced 2024-12-03 10:28:27 +00:00
find: Use walker.Walk
This commit is contained in:
parent
3a86f4852b
commit
081743d0a5
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"path"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -11,7 +10,9 @@ import (
|
|||||||
|
|
||||||
"github.com/restic/restic/internal/debug"
|
"github.com/restic/restic/internal/debug"
|
||||||
"github.com/restic/restic/internal/errors"
|
"github.com/restic/restic/internal/errors"
|
||||||
|
"github.com/restic/restic/internal/filter"
|
||||||
"github.com/restic/restic/internal/restic"
|
"github.com/restic/restic/internal/restic"
|
||||||
|
"github.com/restic/restic/internal/walker"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdFind = &cobra.Command{
|
var cmdFind = &cobra.Command{
|
||||||
@ -94,7 +95,7 @@ type statefulOutput struct {
|
|||||||
hits int
|
hits int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *statefulOutput) PrintJSON(prefix string, node *restic.Node) {
|
func (s *statefulOutput) PrintJSON(path string, node *restic.Node) {
|
||||||
type findNode restic.Node
|
type findNode restic.Node
|
||||||
b, err := json.Marshal(struct {
|
b, err := json.Marshal(struct {
|
||||||
// Add these attributes
|
// Add these attributes
|
||||||
@ -111,7 +112,7 @@ func (s *statefulOutput) PrintJSON(prefix string, node *restic.Node) {
|
|||||||
Content byte `json:"content,omitempty"`
|
Content byte `json:"content,omitempty"`
|
||||||
Subtree byte `json:"subtree,omitempty"`
|
Subtree byte `json:"subtree,omitempty"`
|
||||||
}{
|
}{
|
||||||
Path: path.Join(prefix, node.Name),
|
Path: path,
|
||||||
Permissions: node.Mode.String(),
|
Permissions: node.Mode.String(),
|
||||||
findNode: (*findNode)(node),
|
findNode: (*findNode)(node),
|
||||||
})
|
})
|
||||||
@ -138,7 +139,7 @@ func (s *statefulOutput) PrintJSON(prefix string, node *restic.Node) {
|
|||||||
s.hits++
|
s.hits++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *statefulOutput) PrintNormal(prefix string, node *restic.Node) {
|
func (s *statefulOutput) PrintNormal(path string, node *restic.Node) {
|
||||||
if s.newsn != s.oldsn {
|
if s.newsn != s.oldsn {
|
||||||
if s.oldsn != nil {
|
if s.oldsn != nil {
|
||||||
Verbosef("\n")
|
Verbosef("\n")
|
||||||
@ -146,14 +147,14 @@ func (s *statefulOutput) PrintNormal(prefix string, node *restic.Node) {
|
|||||||
s.oldsn = s.newsn
|
s.oldsn = s.newsn
|
||||||
Verbosef("Found matching entries in snapshot %s\n", s.oldsn.ID().Str())
|
Verbosef("Found matching entries in snapshot %s\n", s.oldsn.ID().Str())
|
||||||
}
|
}
|
||||||
Printf(formatNode(prefix, node, s.ListLong) + "\n")
|
Printf(formatNode(path, node, s.ListLong) + "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *statefulOutput) Print(prefix string, node *restic.Node) {
|
func (s *statefulOutput) Print(path string, node *restic.Node) {
|
||||||
if s.JSON {
|
if s.JSON {
|
||||||
s.PrintJSON(prefix, node)
|
s.PrintJSON(path, node)
|
||||||
} else {
|
} else {
|
||||||
s.PrintNormal(prefix, node)
|
s.PrintNormal(path, node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,80 +178,72 @@ type Finder struct {
|
|||||||
repo restic.Repository
|
repo restic.Repository
|
||||||
pat findPattern
|
pat findPattern
|
||||||
out statefulOutput
|
out statefulOutput
|
||||||
notfound restic.IDSet
|
ignoreTrees restic.IDSet
|
||||||
}
|
}
|
||||||
|
|
||||||
// findInTree traverses a tree and outputs matches. foundInSubtree is true if
|
func (f *Finder) findInSnapshot(ctx context.Context, sn *restic.Snapshot) error {
|
||||||
// some match has been found within some subtree. If err is non-nil, the value
|
debug.Log("searching in snapshot %s\n for entries within [%s %s]", sn.ID(), f.pat.oldest, f.pat.newest)
|
||||||
// of foundInSubtree is invalid.
|
|
||||||
func (f *Finder) findInTree(ctx context.Context, treeID restic.ID, prefix string) (foundInSubtree bool, err error) {
|
if sn.Tree == nil {
|
||||||
if f.notfound.Has(treeID) {
|
return errors.Errorf("snapshot %v has no tree", sn.ID().Str())
|
||||||
debug.Log("%v skipping tree %v, has already been checked", prefix, treeID)
|
|
||||||
return false, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.Log("%v checking tree %v\n", prefix, treeID)
|
f.out.newsn = sn
|
||||||
|
return walker.Walk(ctx, f.repo, *sn.Tree, f.ignoreTrees, func(nodepath string, node *restic.Node, err error) (bool, error) {
|
||||||
tree, err := f.repo.LoadTree(ctx, treeID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var found bool
|
if node == nil {
|
||||||
for _, node := range tree.Nodes {
|
return false, nil
|
||||||
debug.Log(" testing entry %q\n", node.Name)
|
}
|
||||||
|
|
||||||
name := node.Name
|
name := node.Name
|
||||||
if f.pat.ignoreCase {
|
if f.pat.ignoreCase {
|
||||||
name = strings.ToLower(name)
|
name = strings.ToLower(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err := path.Match(f.pat.pattern, name)
|
foundMatch, err := filter.Match(f.pat.pattern, nodepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if m {
|
var (
|
||||||
|
ignoreIfNoMatch = true
|
||||||
|
errIfNoMatch error
|
||||||
|
)
|
||||||
|
if node.Type == "dir" {
|
||||||
|
childMayMatch, err := filter.ChildMatch(f.pat.pattern, nodepath)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !childMayMatch {
|
||||||
|
ignoreIfNoMatch = true
|
||||||
|
errIfNoMatch = walker.SkipNode
|
||||||
|
} else {
|
||||||
|
ignoreIfNoMatch = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !foundMatch {
|
||||||
|
return ignoreIfNoMatch, errIfNoMatch
|
||||||
|
}
|
||||||
|
|
||||||
if !f.pat.oldest.IsZero() && node.ModTime.Before(f.pat.oldest) {
|
if !f.pat.oldest.IsZero() && node.ModTime.Before(f.pat.oldest) {
|
||||||
debug.Log(" ModTime is older than %s\n", f.pat.oldest)
|
debug.Log(" ModTime is older than %s\n", f.pat.oldest)
|
||||||
continue
|
return ignoreIfNoMatch, errIfNoMatch
|
||||||
}
|
}
|
||||||
|
|
||||||
if !f.pat.newest.IsZero() && node.ModTime.After(f.pat.newest) {
|
if !f.pat.newest.IsZero() && node.ModTime.After(f.pat.newest) {
|
||||||
debug.Log(" ModTime is newer than %s\n", f.pat.newest)
|
debug.Log(" ModTime is newer than %s\n", f.pat.newest)
|
||||||
continue
|
return ignoreIfNoMatch, errIfNoMatch
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.Log(" found match\n")
|
debug.Log(" found match\n")
|
||||||
found = true
|
f.out.Print(nodepath, node)
|
||||||
f.out.Print(prefix, node)
|
return false, nil
|
||||||
}
|
})
|
||||||
|
|
||||||
if node.Type == "dir" {
|
|
||||||
foundSubtree, err := f.findInTree(ctx, *node.Subtree, path.Join(prefix, node.Name))
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if foundSubtree {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
f.notfound.Insert(treeID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return found, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Finder) findInSnapshot(ctx context.Context, sn *restic.Snapshot) error {
|
|
||||||
debug.Log("searching in snapshot %s\n for entries within [%s %s]", sn.ID(), f.pat.oldest, f.pat.newest)
|
|
||||||
|
|
||||||
f.out.newsn = sn
|
|
||||||
_, err := f.findInTree(ctx, *sn.Tree, "/")
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runFind(opts FindOptions, gopts GlobalOptions, args []string) error {
|
func runFind(opts FindOptions, gopts GlobalOptions, args []string) error {
|
||||||
@ -301,7 +294,7 @@ func runFind(opts FindOptions, gopts GlobalOptions, args []string) error {
|
|||||||
repo: repo,
|
repo: repo,
|
||||||
pat: pat,
|
pat: pat,
|
||||||
out: statefulOutput{ListLong: opts.ListLong, JSON: globalOptions.JSON},
|
out: statefulOutput{ListLong: opts.ListLong, JSON: globalOptions.JSON},
|
||||||
notfound: restic.NewIDSet(),
|
ignoreTrees: restic.NewIDSet(),
|
||||||
}
|
}
|
||||||
for sn := range FindFilteredSnapshots(ctx, repo, opts.Host, opts.Tags, opts.Paths, opts.Snapshots) {
|
for sn := range FindFilteredSnapshots(ctx, repo, opts.Host, opts.Tags, opts.Paths, opts.Snapshots) {
|
||||||
if err = f.findInSnapshot(ctx, sn); err != nil {
|
if err = f.findInSnapshot(ctx, sn); err != nil {
|
||||||
|
@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"path/filepath"
|
"path"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
@ -53,10 +53,10 @@ func printTree(ctx context.Context, repo *repository.Repository, id *restic.ID,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, entry := range tree.Nodes {
|
for _, entry := range tree.Nodes {
|
||||||
Printf("%s\n", formatNode(prefix, entry, lsOptions.ListLong))
|
entryPath := path.Join(prefix, entry.Name)
|
||||||
|
Printf("%s\n", formatNode(entryPath, entry, lsOptions.ListLong))
|
||||||
|
|
||||||
if entry.Type == "dir" && entry.Subtree != nil {
|
if entry.Type == "dir" && entry.Subtree != nil {
|
||||||
entryPath := prefix + string(filepath.Separator) + entry.Name
|
|
||||||
if err = printTree(ctx, repo, entry.Subtree, entryPath); err != nil {
|
if err = printTree(ctx, repo, entry.Subtree, entryPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/restic/restic/internal/restic"
|
"github.com/restic/restic/internal/restic"
|
||||||
@ -63,10 +62,9 @@ func formatDuration(d time.Duration) string {
|
|||||||
return formatSeconds(sec)
|
return formatSeconds(sec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatNode(prefix string, n *restic.Node, long bool) string {
|
func formatNode(path string, n *restic.Node, long bool) string {
|
||||||
nodepath := path.Join(prefix, n.Name)
|
|
||||||
if !long {
|
if !long {
|
||||||
return nodepath
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
var mode os.FileMode
|
var mode os.FileMode
|
||||||
@ -92,6 +90,6 @@ func formatNode(prefix string, n *restic.Node, long bool) string {
|
|||||||
|
|
||||||
return fmt.Sprintf("%s %5d %5d %6d %s %s%s",
|
return fmt.Sprintf("%s %5d %5d %6d %s %s%s",
|
||||||
mode|n.Mode, n.UID, n.GID, n.Size,
|
mode|n.Mode, n.UID, n.GID, n.Size,
|
||||||
n.ModTime.Format(TimeFormat), nodepath,
|
n.ModTime.Format(TimeFormat), path,
|
||||||
target)
|
target)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user