restic/tree.go

98 lines
2 KiB
Go
Raw Normal View History

2014-12-05 20:45:49 +00:00
package restic
2014-04-21 21:25:31 +00:00
import (
2014-11-30 21:34:21 +00:00
"errors"
2014-08-11 20:47:24 +00:00
"fmt"
2014-11-30 21:34:21 +00:00
"sort"
2014-09-18 20:41:24 +00:00
2014-12-05 20:45:49 +00:00
"github.com/restic/restic/backend"
2015-01-14 21:08:48 +00:00
"github.com/restic/restic/debug"
2014-04-21 21:25:31 +00:00
)
type Tree struct {
Nodes []*Node `json:"nodes"`
Map *Map `json:"map"`
}
2014-04-21 21:25:31 +00:00
2014-11-30 21:34:21 +00:00
var (
ErrNodeNotFound = errors.New("named node not found")
ErrNodeAlreadyInTree = errors.New("node already present")
)
func NewTree() *Tree {
return &Tree{
Nodes: []*Node{},
Map: NewMap(),
}
}
func (t Tree) String() string {
return fmt.Sprintf("Tree<%d nodes, %d blobs>", len(t.Nodes), len(t.Map.list))
}
2014-11-30 21:34:21 +00:00
func LoadTree(s Server, blob Blob) (*Tree, error) {
tree := &Tree{}
err := s.LoadJSON(backend.Tree, blob, tree)
2014-11-30 21:34:21 +00:00
if err != nil {
return nil, err
}
return tree, nil
}
// Equals returns true if t and other have exactly the same nodes and map.
func (t Tree) Equals(other Tree) bool {
if len(t.Nodes) != len(other.Nodes) {
2015-01-14 21:08:48 +00:00
debug.Log("Tree.Equals", "tree.Equals(): trees have different number of nodes")
return false
}
if !t.Map.Equals(other.Map) {
2015-01-14 21:08:48 +00:00
debug.Log("Tree.Equals", "tree.Equals(): maps aren't equal")
return false
}
for i := 0; i < len(t.Nodes); i++ {
if !t.Nodes[i].Equals(*other.Nodes[i]) {
2015-01-14 21:08:48 +00:00
debug.Log("Tree.Equals", "tree.Equals(): node %d is different:", i)
debug.Log("Tree.Equals", " %#v", t.Nodes[i])
debug.Log("Tree.Equals", " %#v", other.Nodes[i])
return false
}
}
return true
2014-11-30 21:34:21 +00:00
}
func (t *Tree) Insert(node *Node) error {
pos, _, err := t.find(node.Name)
if err == nil {
// already present
return ErrNodeAlreadyInTree
}
2015-02-15 13:44:54 +00:00
// https://code.google.com/p/go-wiki/wiki/SliceTricks
t.Nodes = append(t.Nodes, &Node{})
copy(t.Nodes[pos+1:], t.Nodes[pos:])
t.Nodes[pos] = node
2014-11-30 21:34:21 +00:00
return nil
}
func (t Tree) find(name string) (int, *Node, error) {
pos := sort.Search(len(t.Nodes), func(i int) bool {
return t.Nodes[i].Name >= name
2014-11-30 21:34:21 +00:00
})
if pos < len(t.Nodes) && t.Nodes[pos].Name == name {
return pos, t.Nodes[pos], nil
2014-11-30 21:34:21 +00:00
}
return pos, nil, ErrNodeNotFound
}
func (t Tree) Find(name string) (*Node, error) {
_, node, err := t.find(name)
return node, err
}