1
0
Fork 0
mirror of https://github.com/restic/restic.git synced 2025-01-03 05:35:43 +00:00

Do not skip root tree when searching for trees

This fixes an issue where restic cannot find the tree when trying to find the
tree id of a snapshot.
This commit is contained in:
Albin Vass 2024-11-27 12:45:23 +01:00
parent 1133498ef8
commit cdba0e4ca1
2 changed files with 43 additions and 25 deletions

View file

@ -336,6 +336,26 @@ func (f *Finder) findInSnapshot(ctx context.Context, sn *restic.Snapshot) error
}})
}
func (f *Finder) findTree(treeID restic.ID, nodepath string) error {
found := false
if _, ok := f.treeIDs[treeID.String()]; ok {
found = true
} else if _, ok := f.treeIDs[treeID.Str()]; ok {
found = true
}
if found {
f.out.PrintObject("tree", treeID.String(), nodepath, "", f.out.newsn)
f.itemsFound++
// Terminate if we have found all trees (and we are not
// looking for blobs)
if f.itemsFound >= len(f.treeIDs) && f.blobIDs == nil {
// Return an error to terminate the Walk
return errors.New("OK")
}
}
return nil
}
func (f *Finder) findIDs(ctx context.Context, sn *restic.Snapshot) error {
debug.Log("searching IDs in snapshot %s", sn.ID())
@ -354,26 +374,17 @@ func (f *Finder) findIDs(ctx context.Context, sn *restic.Snapshot) error {
}
if node == nil {
if nodepath == "/" {
if err := f.findTree(parentTreeID, "/"); err != nil {
return err
}
}
return nil
}
if node.Type == restic.NodeTypeDir && f.treeIDs != nil {
treeID := node.Subtree
found := false
if _, ok := f.treeIDs[treeID.Str()]; ok {
found = true
} else if _, ok := f.treeIDs[treeID.String()]; ok {
found = true
}
if found {
f.out.PrintObject("tree", treeID.String(), nodepath, "", sn)
f.itemsFound++
// Terminate if we have found all trees (and we are not
// looking for blobs)
if f.itemsFound >= len(f.treeIDs) && f.blobIDs == nil {
// Return an error to terminate the Walk
return errors.New("OK")
}
if node.Type == "dir" && f.treeIDs != nil {
if err := f.findTree(*node.Subtree, nodepath); err != nil {
return err
}
}

View file

@ -10,11 +10,10 @@ import (
rtest "github.com/restic/restic/internal/test"
)
func testRunFind(t testing.TB, wantJSON bool, gopts GlobalOptions, pattern string) []byte {
func testRunFind(t testing.TB, wantJSON bool, opts FindOptions, gopts GlobalOptions, pattern string) []byte {
buf, err := withCaptureStdout(func() error {
gopts.JSON = wantJSON
opts := FindOptions{}
return runFind(context.TODO(), opts, gopts, []string{pattern})
})
rtest.OK(t, err)
@ -31,14 +30,14 @@ func TestFind(t *testing.T) {
testRunBackup(t, "", []string{env.testdata}, opts, env.gopts)
testRunCheck(t, env.gopts)
results := testRunFind(t, false, env.gopts, "unexistingfile")
results := testRunFind(t, false, FindOptions{}, env.gopts, "unexistingfile")
rtest.Assert(t, len(results) == 0, "unexisting file found in repo (%v)", datafile)
results = testRunFind(t, false, env.gopts, "testfile")
results = testRunFind(t, false, FindOptions{}, env.gopts, "testfile")
lines := strings.Split(string(results), "\n")
rtest.Assert(t, len(lines) == 2, "expected one file found in repo (%v)", datafile)
results = testRunFind(t, false, env.gopts, "testfile*")
results = testRunFind(t, false, FindOptions{}, env.gopts, "testfile*")
lines = strings.Split(string(results), "\n")
rtest.Assert(t, len(lines) == 4, "expected three files found in repo (%v)", datafile)
}
@ -67,21 +66,29 @@ func TestFindJSON(t *testing.T) {
testRunBackup(t, "", []string{env.testdata}, opts, env.gopts)
testRunCheck(t, env.gopts)
snapshot, _ := testRunSnapshots(t, env.gopts)
results := testRunFind(t, true, env.gopts, "unexistingfile")
results := testRunFind(t, true, FindOptions{}, env.gopts, "unexistingfile")
matches := []testMatches{}
rtest.OK(t, json.Unmarshal(results, &matches))
rtest.Assert(t, len(matches) == 0, "expected no match in repo (%v)", datafile)
results = testRunFind(t, true, env.gopts, "testfile")
results = testRunFind(t, true, FindOptions{}, env.gopts, "testfile")
rtest.OK(t, json.Unmarshal(results, &matches))
rtest.Assert(t, len(matches) == 1, "expected a single snapshot in repo (%v)", datafile)
rtest.Assert(t, len(matches[0].Matches) == 1, "expected a single file to match (%v)", datafile)
rtest.Assert(t, matches[0].Hits == 1, "expected hits to show 1 match (%v)", datafile)
results = testRunFind(t, true, env.gopts, "testfile*")
results = testRunFind(t, true, FindOptions{}, env.gopts, "testfile*")
rtest.OK(t, json.Unmarshal(results, &matches))
rtest.Assert(t, len(matches) == 1, "expected a single snapshot in repo (%v)", datafile)
rtest.Assert(t, len(matches[0].Matches) == 3, "expected 3 files to match (%v)", datafile)
rtest.Assert(t, matches[0].Hits == 3, "expected hits to show 3 matches (%v)", datafile)
results = testRunFind(t, true, FindOptions{TreeID: true}, env.gopts, snapshot.Tree.String())
rtest.OK(t, json.Unmarshal(results, &matches))
rtest.Assert(t, len(matches) == 1, "expected a single snapshot in repo (%v)", matches)
rtest.Assert(t, len(matches[0].Matches) == 3, "expected 3 files to match (%v)", matches[0].Matches)
rtest.Assert(t, matches[0].Hits == 3, "expected hits to show 3 matches (%v)", datafile)
}