github.com/mckael/restic@v0.8.3/internal/restic/tree.go (about) 1 package restic 2 3 import ( 4 "fmt" 5 "sort" 6 7 "github.com/restic/restic/internal/errors" 8 9 "github.com/restic/restic/internal/debug" 10 ) 11 12 // Tree is an ordered list of nodes. 13 type Tree struct { 14 Nodes []*Node `json:"nodes"` 15 } 16 17 // NewTree creates a new tree object. 18 func NewTree() *Tree { 19 return &Tree{ 20 Nodes: []*Node{}, 21 } 22 } 23 24 func (t Tree) String() string { 25 return fmt.Sprintf("Tree<%d nodes>", len(t.Nodes)) 26 } 27 28 // Equals returns true if t and other have exactly the same nodes. 29 func (t Tree) Equals(other *Tree) bool { 30 if len(t.Nodes) != len(other.Nodes) { 31 debug.Log("tree.Equals(): trees have different number of nodes") 32 return false 33 } 34 35 for i := 0; i < len(t.Nodes); i++ { 36 if !t.Nodes[i].Equals(*other.Nodes[i]) { 37 debug.Log("tree.Equals(): node %d is different:", i) 38 debug.Log(" %#v", t.Nodes[i]) 39 debug.Log(" %#v", other.Nodes[i]) 40 return false 41 } 42 } 43 44 return true 45 } 46 47 // Insert adds a new node at the correct place in the tree. 48 func (t *Tree) Insert(node *Node) error { 49 pos, _, err := t.binarySearch(node.Name) 50 if err == nil { 51 return errors.New("node already present") 52 } 53 54 // https://code.google.com/p/go-wiki/wiki/SliceTricks 55 t.Nodes = append(t.Nodes, &Node{}) 56 copy(t.Nodes[pos+1:], t.Nodes[pos:]) 57 t.Nodes[pos] = node 58 59 return nil 60 } 61 62 func (t Tree) binarySearch(name string) (int, *Node, error) { 63 pos := sort.Search(len(t.Nodes), func(i int) bool { 64 return t.Nodes[i].Name >= name 65 }) 66 67 if pos < len(t.Nodes) && t.Nodes[pos].Name == name { 68 return pos, t.Nodes[pos], nil 69 } 70 71 return pos, nil, errors.New("named node not found") 72 } 73 74 // Sort sorts the nodes by name. 75 func (t *Tree) Sort() { 76 list := Nodes(t.Nodes) 77 sort.Sort(list) 78 t.Nodes = list 79 } 80 81 // Subtrees returns a slice of all subtree IDs of the tree. 82 func (t Tree) Subtrees() (trees IDs) { 83 for _, node := range t.Nodes { 84 if node.Type == "dir" && node.Subtree != nil { 85 trees = append(trees, *node.Subtree) 86 } 87 } 88 89 return trees 90 }