func newDirFromSnapshot(repo *repository.Repository, snapshot SnapshotWithId, ownerIsRoot bool) (*dir, error) { tree, err := restic.LoadTree(repo, *snapshot.Tree) if err != nil { return nil, err } items := make(map[string]*restic.Node) for _, n := range tree.Nodes { nodes, err := replaceSpecialNodes(repo, n) if err != nil { return nil, err } for _, node := range nodes { items[node.Name] = node } } return &dir{ repo: repo, node: &restic.Node{ UID: uint32(os.Getuid()), GID: uint32(os.Getgid()), AccessTime: snapshot.Time, ModTime: snapshot.Time, ChangeTime: snapshot.Time, Mode: os.ModeDir | 0555, }, items: items, inode: inodeFromBackendId(snapshot.ID), ownerIsRoot: ownerIsRoot, }, nil }
func printTrees(repo *repository.Repository, wr io.Writer) error { done := make(chan struct{}) defer close(done) trees := []backend.ID{} for _, idx := range repo.Index().All() { for blob := range idx.Each(nil) { if blob.Type != pack.Tree { continue } trees = append(trees, blob.ID) } } for _, id := range trees { tree, err := restic.LoadTree(repo, id) if err != nil { fmt.Fprintf(os.Stderr, "LoadTree(%v): %v", id.Str(), err) continue } fmt.Fprintf(wr, "tree_id: %v\n", id) prettyPrintJSON(wr, tree) } return nil }
// replaceSpecialNodes replaces nodes with name "." and "/" by their contents. // Otherwise, the node is returned. func replaceSpecialNodes(repo *repository.Repository, node *restic.Node) ([]*restic.Node, error) { if node.Type != "dir" || node.Subtree == nil { return []*restic.Node{node}, nil } if node.Name != "." && node.Name != "/" { return []*restic.Node{node}, nil } tree, err := restic.LoadTree(repo, *node.Subtree) if err != nil { return nil, err } return tree.Nodes, nil }
func (c CmdFind) findInTree(repo *repository.Repository, id backend.ID, path string) ([]findResult, error) { debug.Log("restic.find", "checking tree %v\n", id) tree, err := restic.LoadTree(repo, id) if err != nil { return nil, err } results := []findResult{} for _, node := range tree.Nodes { debug.Log("restic.find", " testing entry %q\n", node.Name) m, err := filepath.Match(c.pattern, node.Name) if err != nil { return nil, err } if m { debug.Log("restic.find", " pattern matches\n") if !c.oldest.IsZero() && node.ModTime.Before(c.oldest) { debug.Log("restic.find", " ModTime is older than %s\n", c.oldest) continue } if !c.newest.IsZero() && node.ModTime.After(c.newest) { debug.Log("restic.find", " ModTime is newer than %s\n", c.newest) continue } results = append(results, findResult{node: node, path: path}) } else { debug.Log("restic.find", " pattern does not match\n") } if node.Type == "dir" { subdirResults, err := c.findInTree(repo, *node.Subtree, filepath.Join(path, node.Name)) if err != nil { return nil, err } results = append(results, subdirResults...) } } return results, nil }
func newDir(repo *repository.Repository, node *restic.Node, ownerIsRoot bool) (*dir, error) { tree, err := restic.LoadTree(repo, *node.Subtree) if err != nil { return nil, err } items := make(map[string]*restic.Node) for _, node := range tree.Nodes { items[node.Name] = node } return &dir{ repo: repo, node: node, items: items, inode: node.Inode, ownerIsRoot: ownerIsRoot, }, nil }
func (cmd CmdLs) printTree(prefix string, repo *repository.Repository, id backend.ID) error { tree, err := restic.LoadTree(repo, id) if err != nil { return err } for _, entry := range tree.Nodes { cmd.global.Printf(cmd.printNode(prefix, entry) + "\n") if entry.Type == "dir" && entry.Subtree != nil { err = cmd.printTree(filepath.Join(prefix, entry.Name), repo, *entry.Subtree) if err != nil { return err } } } return nil }
func TestLoadTree(t *testing.T) { repo := SetupRepo() defer TeardownRepo(repo) // save tree tree := restic.NewTree() id, err := repo.SaveJSON(pack.Tree, tree) OK(t, err) // save packs OK(t, repo.Flush()) // load tree again tree2, err := restic.LoadTree(repo, id) OK(t, err) Assert(t, tree.Equals(tree2), "trees are not equal: want %v, got %v", tree, tree2) }
func newDir(repo *repository.Repository, node *restic.Node, ownerIsRoot bool) (*dir, error) { debug.Log("newDir", "new dir for %v (%v)", node.Name, node.Subtree.Str()) tree, err := restic.LoadTree(repo, *node.Subtree) if err != nil { debug.Log("newDir", " error loading tree %v: %v", node.Subtree.Str(), err) return nil, err } items := make(map[string]*restic.Node) for _, node := range tree.Nodes { items[node.Name] = node } return &dir{ repo: repo, node: node, items: items, inode: node.Inode, ownerIsRoot: ownerIsRoot, }, nil }
func BenchmarkLoadTree(t *testing.B) { repo := SetupRepo() defer TeardownRepo(repo) if BenchArchiveDirectory == "" { t.Skip("benchdir not set, skipping TestArchiverDedup") } // archive a few files arch := restic.NewArchiver(repo) sn, _, err := arch.Snapshot(nil, []string{BenchArchiveDirectory}, nil) OK(t, err) t.Logf("archived snapshot %v", sn.ID()) list := make([]backend.ID, 0, 10) done := make(chan struct{}) for _, idx := range repo.Index().All() { for blob := range idx.Each(done) { if blob.Type != pack.Tree { continue } list = append(list, blob.ID) if len(list) == cap(list) { close(done) break } } } // start benchmark t.ResetTimer() for i := 0; i < t.N; i++ { for _, id := range list { _, err := restic.LoadTree(repo, id) OK(t, err) } } }
// loadTreeWorker loads trees from repo and sends them to out. func loadTreeWorker(repo *repository.Repository, in <-chan backend.ID, out chan<- treeJob, done <-chan struct{}, wg *sync.WaitGroup) { defer func() { debug.Log("checker.loadTreeWorker", "exiting") wg.Done() }() var ( inCh = in outCh = out job treeJob ) outCh = nil for { select { case <-done: return case treeID, ok := <-inCh: if !ok { return } debug.Log("checker.loadTreeWorker", "load tree %v", treeID.Str()) tree, err := restic.LoadTree(repo, treeID) debug.Log("checker.loadTreeWorker", "load tree %v (%v) returned err: %v", tree, treeID.Str(), err) job = treeJob{ID: treeID, error: err, Tree: tree} outCh = out inCh = nil case outCh <- job: debug.Log("checker.loadTreeWorker", "sent tree %v", job.ID.Str()) outCh = nil inCh = in } } }