-
Notifications
You must be signed in to change notification settings - Fork 33
/
linker.go
108 lines (88 loc) · 2.94 KB
/
linker.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package nodes
import (
"fmt"
ie "github.com/sahib/brig/catfs/errors"
h "github.com/sahib/brig/util/hashlib"
)
// Linker will tell a node how it relates to other nodes
// and gives it the ability to resolve other nodes by hash.
// Apart from that it gives the underlying linker implementation
// the possibility to be notified when a hash changes.
type Linker interface {
// Root should return the current root directory.
Root() (*Directory, error)
// LookupNode should resolve `path` starting from the root directory.
// If the path does not exist an error is returned and can be checked
// with IsNoSuchFileError()
LookupNode(path string) (Node, error)
// NodeByHash resolves the hash to a specific node.
// If the node does not exist, nil is returned.
NodeByHash(hash h.Hash) (Node, error)
// MemIndexSwap should be called when
// the hash of a node changes.
MemIndexSwap(nd Node, oldHash h.Hash, updatePathIndex bool)
// MemSetRoot should be called when the current root directory changed.
MemSetRoot(root *Directory)
}
////////////////////////////
// MOCKING IMPLEMENTATION //
////////////////////////////
// MockLinker is supposed to be used for testing.
// It simply holds all nodes in memory. New nodes should be added via AddNode.
type MockLinker struct {
root *Directory
paths map[string]Node
hashes map[string]Node
}
// NewMockLinker returns a Linker that can be easily used for testing.
func NewMockLinker() *MockLinker {
return &MockLinker{
paths: make(map[string]Node),
hashes: make(map[string]Node),
}
}
// Root returns the currently set root.
// If none was created yet, an empty directory is returned.
func (ml *MockLinker) Root() (*Directory, error) {
if ml.root != nil {
return ml.root, nil
}
root, err := NewEmptyDirectory(ml, nil, "", "", 0)
if err != nil {
return nil, err
}
ml.root = root
return root, nil
}
// LookupNode tries to lookup if there is already a node with this path.
func (ml *MockLinker) LookupNode(path string) (Node, error) {
if node, ok := ml.paths[path]; ok {
return node, nil
}
return nil, ie.NoSuchFile(path)
}
// NodeByHash will return a previously added node (via AddNode) by it's hash.
func (ml *MockLinker) NodeByHash(hash h.Hash) (Node, error) {
if node, ok := ml.hashes[hash.B58String()]; ok {
return node, nil
}
return nil, fmt.Errorf("No such hash")
}
// MemSetRoot sets the current root to be `root`.
func (ml *MockLinker) MemSetRoot(root *Directory) {
ml.root = root
}
// MemIndexSwap will replace a node (referenced by `oldHash`) with `nd`.
// The path does not change.
func (ml *MockLinker) MemIndexSwap(nd Node, oldHash h.Hash, updatePathIndex bool) {
delete(ml.hashes, oldHash.B58String())
ml.AddNode(nd, updatePathIndex)
}
// AddNode will add a node to the memory index.
// This is not part of the linker interface.
func (ml *MockLinker) AddNode(nd Node, updatePathIndex bool) {
ml.hashes[nd.TreeHash().B58String()] = nd
if updatePathIndex {
ml.paths[nd.Path()] = nd
}
}