-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.go
155 lines (127 loc) · 3.17 KB
/
utils.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package dagutils
import (
"errors"
"strings"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
key "github.com/ipfs/go-ipfs/blocks/key"
dag "github.com/ipfs/go-ipfs/merkledag"
)
type Editor struct {
root *dag.Node
ds dag.DAGService
}
func NewDagEditor(ds dag.DAGService, root *dag.Node) *Editor {
return &Editor{
root: root,
ds: ds,
}
}
func (e *Editor) GetNode() *dag.Node {
return e.root.Copy()
}
func (e *Editor) AddLink(ctx context.Context, childname string, childk key.Key) error {
nd, err := addLink(ctx, e.ds, e.root, childname, childk)
if err != nil {
return err
}
e.root = nd
return nil
}
func addLink(ctx context.Context, ds dag.DAGService, root *dag.Node, childname string, childk key.Key) (*dag.Node, error) {
if childname == "" {
return nil, errors.New("cannot create link with no name!")
}
childnd, err := ds.Get(ctx, childk)
if err != nil {
return nil, err
}
// ensure no link with that name already exists
_ = root.RemoveNodeLink(childname) // ignore error, only option is ErrNotFound
err = root.AddNodeLinkClean(childname, childnd)
if err != nil {
return nil, err
}
_, err = ds.Add(root)
if err != nil {
return nil, err
}
return root, nil
}
func (e *Editor) InsertNodeAtPath(ctx context.Context, path string, toinsert key.Key, create func() *dag.Node) error {
splpath := strings.Split(path, "/")
nd, err := insertNodeAtPath(ctx, e.ds, e.root, splpath, toinsert, create)
if err != nil {
return err
}
e.root = nd
return nil
}
func insertNodeAtPath(ctx context.Context, ds dag.DAGService, root *dag.Node, path []string, toinsert key.Key, create func() *dag.Node) (*dag.Node, error) {
if len(path) == 1 {
return addLink(ctx, ds, root, path[0], toinsert)
}
nd, err := root.GetLinkedNode(ctx, ds, path[0])
if err != nil {
// if 'create' is true, we create directories on the way down as needed
if err == dag.ErrNotFound && create != nil {
nd = create()
} else {
return nil, err
}
}
ndprime, err := insertNodeAtPath(ctx, ds, nd, path[1:], toinsert, create)
if err != nil {
return nil, err
}
_ = root.RemoveNodeLink(path[0])
err = root.AddNodeLinkClean(path[0], ndprime)
if err != nil {
return nil, err
}
_, err = ds.Add(root)
if err != nil {
return nil, err
}
return root, nil
}
func (e *Editor) RmLink(ctx context.Context, path string) error {
splpath := strings.Split(path, "/")
nd, err := rmLink(ctx, e.ds, e.root, splpath)
if err != nil {
return err
}
e.root = nd
return nil
}
func rmLink(ctx context.Context, ds dag.DAGService, root *dag.Node, path []string) (*dag.Node, error) {
if len(path) == 1 {
// base case, remove node in question
err := root.RemoveNodeLink(path[0])
if err != nil {
return nil, err
}
_, err = ds.Add(root)
if err != nil {
return nil, err
}
return root, nil
}
nd, err := root.GetLinkedNode(ctx, ds, path[0])
if err != nil {
return nil, err
}
nnode, err := rmLink(ctx, ds, nd, path[1:])
if err != nil {
return nil, err
}
_ = root.RemoveNodeLink(path[0])
err = root.AddNodeLinkClean(path[0], nnode)
if err != nil {
return nil, err
}
_, err = ds.Add(root)
if err != nil {
return nil, err
}
return root, nil
}