mirror of
https://github.com/restic/restic.git
synced 2025-08-23 19:47:36 +00:00
Do not skip root tree when searching for trees (#5153)
This fixes an issue where restic cannot find the tree when trying to find the tree id of a snapshot. --------- Co-authored-by: Albin Vass <albinvass@gmail.com> Co-authored-by: Michael Eischer <michael.eischer@fau.de>
This commit is contained in:
6
changelog/unreleased/pull-5153
Normal file
6
changelog/unreleased/pull-5153
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Bugfix: Include root tree when searching using `find --tree`
|
||||||
|
|
||||||
|
`restic find --tree` didn't find trees referenced by `restic snapshot --json`.
|
||||||
|
It now correctly includes the root tree when searching.
|
||||||
|
|
||||||
|
https://github.com/restic/restic/pull/5153
|
@@ -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 {
|
func (f *Finder) findIDs(ctx context.Context, sn *restic.Snapshot) error {
|
||||||
debug.Log("searching IDs in snapshot %s", sn.ID())
|
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 node == nil {
|
||||||
|
if nodepath == "/" {
|
||||||
|
if err := f.findTree(parentTreeID, "/"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.Type == restic.NodeTypeDir && f.treeIDs != nil {
|
if node.Type == "dir" && f.treeIDs != nil {
|
||||||
treeID := node.Subtree
|
if err := f.findTree(*node.Subtree, nodepath); err != nil {
|
||||||
found := false
|
return err
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,11 +10,10 @@ import (
|
|||||||
rtest "github.com/restic/restic/internal/test"
|
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 {
|
buf, err := withCaptureStdout(func() error {
|
||||||
gopts.JSON = wantJSON
|
gopts.JSON = wantJSON
|
||||||
|
|
||||||
opts := FindOptions{}
|
|
||||||
return runFind(context.TODO(), opts, gopts, []string{pattern})
|
return runFind(context.TODO(), opts, gopts, []string{pattern})
|
||||||
})
|
})
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
@@ -31,14 +30,14 @@ func TestFind(t *testing.T) {
|
|||||||
testRunBackup(t, "", []string{env.testdata}, opts, env.gopts)
|
testRunBackup(t, "", []string{env.testdata}, opts, env.gopts)
|
||||||
testRunCheck(t, 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)
|
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")
|
lines := strings.Split(string(results), "\n")
|
||||||
rtest.Assert(t, len(lines) == 2, "expected one file found in repo (%v)", datafile)
|
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")
|
lines = strings.Split(string(results), "\n")
|
||||||
rtest.Assert(t, len(lines) == 4, "expected three files found in repo (%v)", datafile)
|
rtest.Assert(t, len(lines) == 4, "expected three files found in repo (%v)", datafile)
|
||||||
}
|
}
|
||||||
@@ -67,21 +66,28 @@ func TestFindJSON(t *testing.T) {
|
|||||||
|
|
||||||
testRunBackup(t, "", []string{env.testdata}, opts, env.gopts)
|
testRunBackup(t, "", []string{env.testdata}, opts, env.gopts)
|
||||||
testRunCheck(t, 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{}
|
matches := []testMatches{}
|
||||||
rtest.OK(t, json.Unmarshal(results, &matches))
|
rtest.OK(t, json.Unmarshal(results, &matches))
|
||||||
rtest.Assert(t, len(matches) == 0, "expected no match in repo (%v)", datafile)
|
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.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) == 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, 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)
|
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.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) == 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, 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)
|
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)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user