mirror of
https://github.com/restic/restic.git
synced 2025-10-27 23:38:35 +00:00
walker: Remove ignoreTrees functionality
It was only used in two places: - stats: apparently as a minor performance optimization, which is unlikely to be important - find: filtered directories would be ignored. However, this optimization missed that it is possible that two directories have the exact same content. Such directories would be incorrectly ignored too. Example: ``` mkdir test test/a test/b restic backup test restic find latest test/b -> incorrectly does not return anything ``` Thus, remove the functionality as it's apparently too complex to use correctly.
This commit is contained in:
@@ -244,13 +244,12 @@ func (s *statefulOutput) Finish() {
|
||||
|
||||
// Finder bundles information needed to find a file or directory.
|
||||
type Finder struct {
|
||||
repo restic.Repository
|
||||
pat findPattern
|
||||
out statefulOutput
|
||||
ignoreTrees restic.IDSet
|
||||
blobIDs map[string]struct{}
|
||||
treeIDs map[string]struct{}
|
||||
itemsFound int
|
||||
repo restic.Repository
|
||||
pat findPattern
|
||||
out statefulOutput
|
||||
blobIDs map[string]struct{}
|
||||
treeIDs map[string]struct{}
|
||||
itemsFound int
|
||||
}
|
||||
|
||||
func (f *Finder) findInSnapshot(ctx context.Context, sn *restic.Snapshot) error {
|
||||
@@ -261,17 +260,17 @@ func (f *Finder) findInSnapshot(ctx context.Context, sn *restic.Snapshot) error
|
||||
}
|
||||
|
||||
f.out.newsn = sn
|
||||
return walker.Walk(ctx, f.repo, *sn.Tree, f.ignoreTrees, func(parentTreeID restic.ID, nodepath string, node *restic.Node, err error) (bool, error) {
|
||||
return walker.Walk(ctx, f.repo, *sn.Tree, func(parentTreeID restic.ID, nodepath string, node *restic.Node, err error) error {
|
||||
if err != nil {
|
||||
debug.Log("Error loading tree %v: %v", parentTreeID, err)
|
||||
|
||||
Printf("Unable to load tree %s\n ... which belongs to snapshot %s\n", parentTreeID, sn.ID())
|
||||
|
||||
return false, walker.ErrSkipNode
|
||||
return walker.ErrSkipNode
|
||||
}
|
||||
|
||||
if node == nil {
|
||||
return false, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
normalizedNodepath := nodepath
|
||||
@@ -284,7 +283,7 @@ func (f *Finder) findInSnapshot(ctx context.Context, sn *restic.Snapshot) error
|
||||
for _, pat := range f.pat.pattern {
|
||||
found, err := filter.Match(pat, normalizedNodepath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
if found {
|
||||
foundMatch = true
|
||||
@@ -292,16 +291,13 @@ func (f *Finder) findInSnapshot(ctx context.Context, sn *restic.Snapshot) error
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
ignoreIfNoMatch = true
|
||||
errIfNoMatch error
|
||||
)
|
||||
var errIfNoMatch error
|
||||
if node.Type == "dir" {
|
||||
var childMayMatch bool
|
||||
for _, pat := range f.pat.pattern {
|
||||
mayMatch, err := filter.ChildMatch(pat, normalizedNodepath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
if mayMatch {
|
||||
childMayMatch = true
|
||||
@@ -310,30 +306,27 @@ func (f *Finder) findInSnapshot(ctx context.Context, sn *restic.Snapshot) error
|
||||
}
|
||||
|
||||
if !childMayMatch {
|
||||
ignoreIfNoMatch = true
|
||||
errIfNoMatch = walker.ErrSkipNode
|
||||
} else {
|
||||
ignoreIfNoMatch = false
|
||||
}
|
||||
}
|
||||
|
||||
if !foundMatch {
|
||||
return ignoreIfNoMatch, errIfNoMatch
|
||||
return errIfNoMatch
|
||||
}
|
||||
|
||||
if !f.pat.oldest.IsZero() && node.ModTime.Before(f.pat.oldest) {
|
||||
debug.Log(" ModTime is older than %s\n", f.pat.oldest)
|
||||
return ignoreIfNoMatch, errIfNoMatch
|
||||
return errIfNoMatch
|
||||
}
|
||||
|
||||
if !f.pat.newest.IsZero() && node.ModTime.After(f.pat.newest) {
|
||||
debug.Log(" ModTime is newer than %s\n", f.pat.newest)
|
||||
return ignoreIfNoMatch, errIfNoMatch
|
||||
return errIfNoMatch
|
||||
}
|
||||
|
||||
debug.Log(" found match\n")
|
||||
f.out.PrintPattern(nodepath, node)
|
||||
return false, nil
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -345,17 +338,17 @@ func (f *Finder) findIDs(ctx context.Context, sn *restic.Snapshot) error {
|
||||
}
|
||||
|
||||
f.out.newsn = sn
|
||||
return walker.Walk(ctx, f.repo, *sn.Tree, f.ignoreTrees, func(parentTreeID restic.ID, nodepath string, node *restic.Node, err error) (bool, error) {
|
||||
return walker.Walk(ctx, f.repo, *sn.Tree, func(parentTreeID restic.ID, nodepath string, node *restic.Node, err error) error {
|
||||
if err != nil {
|
||||
debug.Log("Error loading tree %v: %v", parentTreeID, err)
|
||||
|
||||
Printf("Unable to load tree %s\n ... which belongs to snapshot %s\n", parentTreeID, sn.ID())
|
||||
|
||||
return false, walker.ErrSkipNode
|
||||
return walker.ErrSkipNode
|
||||
}
|
||||
|
||||
if node == nil {
|
||||
return false, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if node.Type == "dir" && f.treeIDs != nil {
|
||||
@@ -373,7 +366,7 @@ func (f *Finder) findIDs(ctx context.Context, sn *restic.Snapshot) error {
|
||||
// looking for blobs)
|
||||
if f.itemsFound >= len(f.treeIDs) && f.blobIDs == nil {
|
||||
// Return an error to terminate the Walk
|
||||
return true, errors.New("OK")
|
||||
return errors.New("OK")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -394,7 +387,7 @@ func (f *Finder) findIDs(ctx context.Context, sn *restic.Snapshot) error {
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -593,10 +586,9 @@ func runFind(ctx context.Context, opts FindOptions, gopts GlobalOptions, args []
|
||||
}
|
||||
|
||||
f := &Finder{
|
||||
repo: repo,
|
||||
pat: pat,
|
||||
out: statefulOutput{ListLong: opts.ListLong, HumanReadable: opts.HumanReadable, JSON: gopts.JSON},
|
||||
ignoreTrees: restic.NewIDSet(),
|
||||
repo: repo,
|
||||
pat: pat,
|
||||
out: statefulOutput{ListLong: opts.ListLong, HumanReadable: opts.HumanReadable, JSON: gopts.JSON},
|
||||
}
|
||||
|
||||
if opts.BlobID {
|
||||
|
||||
@@ -230,12 +230,12 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
|
||||
|
||||
printSnapshot(sn)
|
||||
|
||||
err = walker.Walk(ctx, repo, *sn.Tree, nil, func(_ restic.ID, nodepath string, node *restic.Node, err error) (bool, error) {
|
||||
err = walker.Walk(ctx, repo, *sn.Tree, func(_ restic.ID, nodepath string, node *restic.Node, err error) error {
|
||||
if err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
if node == nil {
|
||||
return false, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if withinDir(nodepath) {
|
||||
@@ -245,22 +245,22 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
|
||||
// if recursive listing is requested, signal the walker that it
|
||||
// should continue walking recursively
|
||||
if opts.Recursive {
|
||||
return false, nil
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// if there's an upcoming match deeper in the tree (but we're not
|
||||
// there yet), signal the walker to descend into any subdirs
|
||||
if approachingMatchingTree(nodepath) {
|
||||
return false, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// otherwise, signal the walker to not walk recursively into any
|
||||
// subdirs
|
||||
if node.Type == "dir" {
|
||||
return false, walker.ErrSkipNode
|
||||
return walker.ErrSkipNode
|
||||
}
|
||||
return false, nil
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -203,7 +203,7 @@ func statsWalkSnapshot(ctx context.Context, snapshot *restic.Snapshot, repo rest
|
||||
}
|
||||
|
||||
hardLinkIndex := restorer.NewHardlinkIndex[struct{}]()
|
||||
err := walker.Walk(ctx, repo, *snapshot.Tree, restic.NewIDSet(), statsWalkTree(repo, opts, stats, hardLinkIndex))
|
||||
err := walker.Walk(ctx, repo, *snapshot.Tree, statsWalkTree(repo, opts, stats, hardLinkIndex))
|
||||
if err != nil {
|
||||
return fmt.Errorf("walking tree %s: %v", *snapshot.Tree, err)
|
||||
}
|
||||
@@ -212,12 +212,12 @@ func statsWalkSnapshot(ctx context.Context, snapshot *restic.Snapshot, repo rest
|
||||
}
|
||||
|
||||
func statsWalkTree(repo restic.Repository, opts StatsOptions, stats *statsContainer, hardLinkIndex *restorer.HardlinkIndex[struct{}]) walker.WalkFunc {
|
||||
return func(parentTreeID restic.ID, npath string, node *restic.Node, nodeErr error) (bool, error) {
|
||||
return func(parentTreeID restic.ID, npath string, node *restic.Node, nodeErr error) error {
|
||||
if nodeErr != nil {
|
||||
return true, nodeErr
|
||||
return nodeErr
|
||||
}
|
||||
if node == nil {
|
||||
return true, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if opts.countMode == countModeUniqueFilesByContents || opts.countMode == countModeBlobsPerFile {
|
||||
@@ -247,7 +247,7 @@ func statsWalkTree(repo restic.Repository, opts StatsOptions, stats *statsContai
|
||||
// is always a data blob since we're accessing it via a file's Content array
|
||||
blobSize, found := repo.LookupBlobSize(blobID, restic.DataBlob)
|
||||
if !found {
|
||||
return true, fmt.Errorf("blob %s not found for tree %s", blobID, parentTreeID)
|
||||
return fmt.Errorf("blob %s not found for tree %s", blobID, parentTreeID)
|
||||
}
|
||||
|
||||
// count the blob's size, then add this blob by this
|
||||
@@ -274,11 +274,9 @@ func statsWalkTree(repo restic.Repository, opts StatsOptions, stats *statsContai
|
||||
hardLinkIndex.Add(node.Inode, node.DeviceID, struct{}{})
|
||||
stats.TotalSize += node.Size
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user