github.com/fawick/restic@v0.1.1-0.20171126184616-c02923fbfc79/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  }