@cryptotaxi247 / kubo / commits / 01aee4467

merkledag: change 'Node' to be an interface

Also change existing 'Node' type to 'ProtoNode' and use that most everywhere for now. As we move forward with the integration we will try and use the Node interface in more places that we're currently using ProtoNode. License: MIT Signed-off-by: Jeromy <why@ipfs.io>

Jeromy committed Oct 9, 2016 at 12:59 UTC 01aee44679dd8cacd0ca198206041e3c3d7c48af
61 files changed +850 -521
blocks/blocks.go
-1
@@ -14,7 +14,6 @@ import (
14 var ErrWrongHash = errors.New("data did not match given hash!")
15
16 type Block interface {
17 - Multihash() mh.Multihash
17 RawData() []byte
18 Cid() *cid.Cid
19 String() string
blockservice/test/blocks_test.go
+6 -20
@@ -18,18 +18,8 @@ import (
18 dssync "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/sync"
19 )
20
21 -func newObject(data []byte) *testObject {
22 - return &testObject{
23 - Block: blocks.NewBlock(data),
24 - }
25 -}
26 -
27 -type testObject struct {
28 - blocks.Block
29 -}
30 -
31 -func (o *testObject) Cid() *cid.Cid {
32 - return cid.NewCidV0(o.Block.Multihash())
21 +func newObject(data []byte) blocks.Block {
22 + return blocks.NewBlock(data)
23 }
24
25 func TestBlocks(t *testing.T) {
@@ -38,12 +28,8 @@ func TestBlocks(t *testing.T) {
28 defer bs.Close()
29
30 o := newObject([]byte("beep boop"))
41 - h := u.Hash([]byte("beep boop"))
42 - if !bytes.Equal(o.Multihash(), h) {
43 - t.Error("Block Multihash and data multihash not equal")
44 - }
45 -
46 - if !o.Cid().Equals(cid.NewCidV0(h)) {
31 + h := cid.NewCidV0(u.Hash([]byte("beep boop")))
32 + if !o.Cid().Equals(h) {
33 t.Error("Block key and data multihash key not equal")
34 }
35
@@ -74,8 +60,8 @@ func TestBlocks(t *testing.T) {
60 }
61 }
62
77 -func makeObjects(n int) []*testObject {
78 - var out []*testObject
63 +func makeObjects(n int) []blocks.Block {
64 + var out []blocks.Block
65 for i := 0; i < n; i++ {
66 out = append(out, newObject([]byte(fmt.Sprintf("object %d", i))))
67 }
core/commands/files/files.go
+13 -3
@@ -182,7 +182,7 @@ func statNode(ds dag.DAGService, fsn mfs.FSNode) (*Object, error) {
182
183 return &Object{
184 Hash: c.String(),
185 - Blocks: len(nd.Links),
185 + Blocks: len(nd.Links()),
186 Size: d.GetFilesize(),
187 CumulativeSize: cumulsize,
188 Type: ndtype,
@@ -245,7 +245,7 @@ var FilesCpCmd = &cmds.Command{
245 },
246 }
247
248 -func getNodeFromPath(ctx context.Context, node *core.IpfsNode, p string) (*dag.Node, error) {
248 +func getNodeFromPath(ctx context.Context, node *core.IpfsNode, p string) (*dag.ProtoNode, error) {
249 switch {
250 case strings.HasPrefix(p, "/ipfs/"):
251 np, err := path.ParsePath(p)
@@ -253,7 +253,17 @@ func getNodeFromPath(ctx context.Context, node *core.IpfsNode, p string) (*dag.N
253 return nil, err
254 }
255
256 - return core.Resolve(ctx, node, np)
256 + nd, err := core.Resolve(ctx, node, np)
257 + if err != nil {
258 + return nil, err
259 + }
260 +
261 + pbnd, ok := nd.(*dag.ProtoNode)
262 + if !ok {
263 + return nil, dag.ErrNotProtobuf
264 + }
265 +
266 + return pbnd, nil
267 default:
268 fsn, err := mfs.Lookup(node.FilesRoot, p)
269 if err != nil {
core/commands/get.go
+8 -1
@@ -13,6 +13,7 @@ import (
13
14 cmds "github.com/ipfs/go-ipfs/commands"
15 core "github.com/ipfs/go-ipfs/core"
16 + dag "github.com/ipfs/go-ipfs/merkledag"
17 path "github.com/ipfs/go-ipfs/path"
18 tar "github.com/ipfs/go-ipfs/thirdparty/tar"
19 uarchive "github.com/ipfs/go-ipfs/unixfs/archive"
@@ -69,6 +70,12 @@ may also specify the level of compression by specifying '-l=<1-9>'.
70 return
71 }
72
73 + pbnd, ok := dn.(*dag.ProtoNode)
74 + if !ok {
75 + res.SetError(err, cmds.ErrNormal)
76 + return
77 + }
78 +
79 size, err := dn.Size()
80 if err != nil {
81 res.SetError(err, cmds.ErrNormal)
@@ -78,7 +85,7 @@ may also specify the level of compression by specifying '-l=<1-9>'.
85 res.SetLength(size)
86
87 archive, _, _ := req.Option("archive").Bool()
81 - reader, err := uarchive.DagArchive(ctx, dn, p.String(), node.DAG, archive, cmplvl)
88 + reader, err := uarchive.DagArchive(ctx, pbnd, p.String(), node.DAG, archive, cmplvl)
89 if err != nil {
90 res.SetError(err, cmds.ErrNormal)
91 return
core/commands/ls.go
+15 -9
@@ -12,8 +12,6 @@ import (
12 path "github.com/ipfs/go-ipfs/path"
13 unixfs "github.com/ipfs/go-ipfs/unixfs"
14 unixfspb "github.com/ipfs/go-ipfs/unixfs/pb"
15 -
16 - cid "gx/ipfs/QmXUuRadqDq5BuFWzVU6VuKaSjTcNm1gNCtLvvP1TJCW4z/go-cid"
15 )
16
17 type LsLink struct {
@@ -72,7 +70,7 @@ The JSON output contains type information.
70
71 paths := req.Arguments()
72
75 - var dagnodes []*merkledag.Node
73 + var dagnodes []merkledag.Node
74 for _, fpath := range paths {
75 dagnode, err := core.Resolve(req.Context(), node, path.Path(fpath))
76 if err != nil {
@@ -86,12 +84,12 @@ The JSON output contains type information.
84 for i, dagnode := range dagnodes {
85 output[i] = LsObject{
86 Hash: paths[i],
89 - Links: make([]LsLink, len(dagnode.Links)),
87 + Links: make([]LsLink, len(dagnode.Links())),
88 }
91 - for j, link := range dagnode.Links {
92 - var linkNode *merkledag.Node
89 + for j, link := range dagnode.Links() {
90 + var linkNode *merkledag.ProtoNode
91 t := unixfspb.Data_DataType(-1)
94 - linkKey := cid.NewCidV0(link.Hash)
92 + linkKey := link.Cid
93 if ok, err := node.Blockstore.Has(linkKey); ok && err == nil {
94 b, err := node.Blockstore.Get(linkKey)
95 if err != nil {
@@ -106,11 +104,19 @@ The JSON output contains type information.
104 }
105
106 if linkNode == nil && resolve {
109 - linkNode, err = link.GetNode(req.Context(), node.DAG)
107 + nd, err := link.GetNode(req.Context(), node.DAG)
108 if err != nil {
109 res.SetError(err, cmds.ErrNormal)
110 return
111 }
112 +
113 + pbnd, ok := nd.(*merkledag.ProtoNode)
114 + if !ok {
115 + res.SetError(merkledag.ErrNotProtobuf, cmds.ErrNormal)
116 + return
117 + }
118 +
119 + linkNode = pbnd
120 }
121 if linkNode != nil {
122 d, err := unixfs.FromBytes(linkNode.Data())
@@ -123,7 +129,7 @@ The JSON output contains type information.
129 }
130 output[i].Links[j] = LsLink{
131 Name: link.Name,
126 - Hash: link.Hash.B58String(),
132 + Hash: link.Cid.String(),
133 Size: link.Size,
134 Type: t,
135 }
core/commands/object/diff.go
+14 -1
@@ -7,6 +7,7 @@ import (
7
8 cmds "github.com/ipfs/go-ipfs/commands"
9 core "github.com/ipfs/go-ipfs/core"
10 + dag "github.com/ipfs/go-ipfs/merkledag"
11 dagutils "github.com/ipfs/go-ipfs/merkledag/utils"
12 path "github.com/ipfs/go-ipfs/path"
13 )
@@ -85,7 +86,19 @@ Example:
86 return
87 }
88
88 - changes, err := dagutils.Diff(ctx, node.DAG, obj_a, obj_b)
89 + pbobj_a, ok := obj_a.(*dag.ProtoNode)
90 + if !ok {
91 + res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
92 + return
93 + }
94 +
95 + pbobj_b, ok := obj_b.(*dag.ProtoNode)
96 + if !ok {
97 + res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
98 + return
99 + }
100 +
101 + changes, err := dagutils.Diff(ctx, node.DAG, pbobj_a, pbobj_b)
102 if err != nil {
103 res.SetError(err, cmds.ErrNormal)
104 return
core/commands/object/object.go
+35 -21
@@ -12,13 +12,13 @@ import (
12 "strings"
13 "text/tabwriter"
14
15 - mh "gx/ipfs/QmYDds3421prZgqKbLpEK7T9Aa2eVdQ7o3YarX1LVLdP2J/go-multihash"
16 -
15 cmds "github.com/ipfs/go-ipfs/commands"
16 core "github.com/ipfs/go-ipfs/core"
17 dag "github.com/ipfs/go-ipfs/merkledag"
18 path "github.com/ipfs/go-ipfs/path"
19 ft "github.com/ipfs/go-ipfs/unixfs"
20 +
21 + cid "gx/ipfs/QmXUuRadqDq5BuFWzVU6VuKaSjTcNm1gNCtLvvP1TJCW4z/go-cid"
22 )
23
24 // ErrObjectTooLarge is returned when too much data was read from stdin. current limit 2m
@@ -98,7 +98,14 @@ is the raw data of the object.
98 res.SetError(err, cmds.ErrNormal)
99 return
100 }
101 - res.SetOutput(bytes.NewReader(node.Data()))
101 +
102 + pbnode, ok := node.(*dag.ProtoNode)
103 + if !ok {
104 + res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
105 + return
106 + }
107 +
108 + res.SetOutput(bytes.NewReader(pbnode.Data()))
109 },
110 }
111
@@ -137,6 +144,7 @@ multihash.
144 res.SetError(err, cmds.ErrNormal)
145 return
146 }
147 +
148 output, err := getOutput(node)
149 if err != nil {
150 res.SetError(err, cmds.ErrNormal)
@@ -201,14 +209,20 @@ This command outputs data in the following encodings:
209 return
210 }
211
212 + pbo, ok := object.(*dag.ProtoNode)
213 + if !ok {
214 + res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
215 + return
216 + }
217 +
218 node := &Node{
205 - Links: make([]Link, len(object.Links)),
206 - Data: string(object.Data()),
219 + Links: make([]Link, len(object.Links())),
220 + Data: string(pbo.Data()),
221 }
222
209 - for i, link := range object.Links {
223 + for i, link := range object.Links() {
224 node.Links[i] = Link{
211 - Hash: link.Hash.B58String(),
225 + Hash: link.Cid.String(),
226 Name: link.Name,
227 Size: link.Size,
228 }
@@ -413,7 +427,7 @@ Available templates:
427 return
428 }
429
416 - node := new(dag.Node)
430 + node := new(dag.ProtoNode)
431 if len(req.Arguments()) == 1 {
432 template := req.Arguments()[0]
433 var err error
@@ -440,7 +454,7 @@ Available templates:
454 Type: Object{},
455 }
456
443 -func nodeFromTemplate(template string) (*dag.Node, error) {
457 +func nodeFromTemplate(template string) (*dag.ProtoNode, error) {
458 switch template {
459 case "unixfs-dir":
460 return ft.EmptyDirNode(), nil
@@ -464,7 +478,7 @@ func objectPut(n *core.IpfsNode, input io.Reader, encoding string, dataFieldEnco
478 return nil, ErrObjectTooLarge
479 }
480
467 - var dagnode *dag.Node
481 + var dagnode *dag.ProtoNode
482 switch getObjectEnc(encoding) {
483 case objectEncodingJSON:
484 node := new(Node)
@@ -542,17 +556,17 @@ func getObjectEnc(o interface{}) objectEncoding {
556 return objectEncoding(v)
557 }
558
545 -func getOutput(dagnode *dag.Node) (*Object, error) {
559 +func getOutput(dagnode dag.Node) (*Object, error) {
560 c := dagnode.Cid()
561 output := &Object{
562 Hash: c.String(),
549 - Links: make([]Link, len(dagnode.Links)),
563 + Links: make([]Link, len(dagnode.Links())),
564 }
565
552 - for i, link := range dagnode.Links {
566 + for i, link := range dagnode.Links() {
567 output.Links[i] = Link{
568 Name: link.Name,
555 - Hash: link.Hash.B58String(),
569 + Hash: link.Cid.String(),
570 Size: link.Size,
571 }
572 }
@@ -560,9 +574,9 @@ func getOutput(dagnode *dag.Node) (*Object, error) {
574 return output, nil
575 }
576
563 -// converts the Node object into a real dag.Node
564 -func deserializeNode(node *Node, dataFieldEncoding string) (*dag.Node, error) {
565 - dagnode := new(dag.Node)
577 +// converts the Node object into a real dag.ProtoNode
578 +func deserializeNode(node *Node, dataFieldEncoding string) (*dag.ProtoNode, error) {
579 + dagnode := new(dag.ProtoNode)
580 switch dataFieldEncoding {
581 case "text":
582 dagnode.SetData([]byte(node.Data))
@@ -573,16 +587,16 @@ func deserializeNode(node *Node, dataFieldEncoding string) (*dag.Node, error) {
587 return nil, fmt.Errorf("Unkown data field encoding")
588 }
589
576 - dagnode.Links = make([]*dag.Link, len(node.Links))
590 + dagnode.SetLinks(make([]*dag.Link, len(node.Links)))
591 for i, link := range node.Links {
578 - hash, err := mh.FromB58String(link.Hash)
592 + c, err := cid.Decode(link.Hash)
593 if err != nil {
594 return nil, err
595 }
582 - dagnode.Links[i] = &dag.Link{
596 + dagnode.Links()[i] = &dag.Link{
597 Name: link.Name,
598 Size: link.Size,
585 - Hash: hash,
599 + Cid: c,
600 }
601 }
602
core/commands/object/patch.go
+38 -8
@@ -79,6 +79,12 @@ the limit will not be respected by the network.
79 return
80 }
81
82 + rtpb, ok := rootnd.(*dag.ProtoNode)
83 + if !ok {
84 + res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
85 + return
86 + }
87 +
88 fi, err := req.Files().NextFile()
89 if err != nil {
90 res.SetError(err, cmds.ErrNormal)
@@ -91,9 +97,9 @@ the limit will not be respected by the network.
97 return
98 }
99
94 - rootnd.SetData(append(rootnd.Data(), data...))
100 + rtpb.SetData(append(rtpb.Data(), data...))
101
96 - newkey, err := nd.DAG.Add(rootnd)
102 + newkey, err := nd.DAG.Add(rtpb)
103 if err != nil {
104 res.SetError(err, cmds.ErrNormal)
105 return
@@ -141,6 +147,12 @@ Example:
147 return
148 }
149
150 + rtpb, ok := root.(*dag.ProtoNode)
151 + if !ok {
152 + res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
153 + return
154 + }
155 +
156 fi, err := req.Files().NextFile()
157 if err != nil {
158 res.SetError(err, cmds.ErrNormal)
@@ -153,9 +165,9 @@ Example:
165 return
166 }
167
156 - root.SetData(data)
168 + rtpb.SetData(data)
169
158 - newkey, err := nd.DAG.Add(root)
170 + newkey, err := nd.DAG.Add(rtpb)
171 if err != nil {
172 res.SetError(err, cmds.ErrNormal)
173 return
@@ -199,9 +211,15 @@ Removes a link by the given name from root.
211 return
212 }
213
214 + rtpb, ok := root.(*dag.ProtoNode)
215 + if !ok {
216 + res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
217 + return
218 + }
219 +
220 path := req.Arguments()[1]
221
204 - e := dagutils.NewDagEditor(root, nd.DAG)
222 + e := dagutils.NewDagEditor(rtpb, nd.DAG)
223
224 err = e.RmLink(req.Context(), path)
225 if err != nil {
@@ -268,6 +286,12 @@ to a file containing 'bar', and returns the hash of the new object.
286 return
287 }
288
289 + rtpb, ok := root.(*dag.ProtoNode)
290 + if !ok {
291 + res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
292 + return
293 + }
294 +
295 npath := req.Arguments()[1]
296 childp, err := path.ParsePath(req.Arguments()[2])
297 if err != nil {
@@ -281,12 +305,12 @@ to a file containing 'bar', and returns the hash of the new object.
305 return
306 }
307
284 - var createfunc func() *dag.Node
308 + var createfunc func() *dag.ProtoNode
309 if create {
310 createfunc = ft.EmptyDirNode
311 }
312
289 - e := dagutils.NewDagEditor(root, nd.DAG)
313 + e := dagutils.NewDagEditor(rtpb, nd.DAG)
314
315 childnd, err := core.Resolve(req.Context(), nd, childp)
316 if err != nil {
@@ -294,7 +318,13 @@ to a file containing 'bar', and returns the hash of the new object.
318 return
319 }
320
297 - err = e.InsertNodeAtPath(req.Context(), npath, childnd, createfunc)
321 + chpb, ok := childnd.(*dag.ProtoNode)
322 + if !ok {
323 + res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
324 + return
325 + }
326 +
327 + err = e.InsertNodeAtPath(req.Context(), npath, chpb, createfunc)
328 if err != nil {
329 res.SetError(err, cmds.ErrNormal)
330 return
core/commands/refs.go
+9 -10
@@ -195,8 +195,8 @@ var refsMarshallerMap = cmds.MarshalerMap{
195 },
196 }
197
198 -func objectsForPaths(ctx context.Context, n *core.IpfsNode, paths []string) ([]*dag.Node, error) {
199 - objects := make([]*dag.Node, len(paths))
198 +func objectsForPaths(ctx context.Context, n *core.IpfsNode, paths []string) ([]dag.Node, error) {
199 + objects := make([]dag.Node, len(paths))
200 for i, p := range paths {
201 o, err := core.Resolve(ctx, n, path.Path(p))
202 if err != nil {
@@ -225,24 +225,24 @@ type RefWriter struct {
225 }
226
227 // WriteRefs writes refs of the given object to the underlying writer.
228 -func (rw *RefWriter) WriteRefs(n *dag.Node) (int, error) {
228 +func (rw *RefWriter) WriteRefs(n dag.Node) (int, error) {
229 if rw.Recursive {
230 return rw.writeRefsRecursive(n)
231 }
232 return rw.writeRefsSingle(n)
233 }
234
235 -func (rw *RefWriter) writeRefsRecursive(n *dag.Node) (int, error) {
235 +func (rw *RefWriter) writeRefsRecursive(n dag.Node) (int, error) {
236 nc := n.Cid()
237
238 var count int
239 for i, ng := range dag.GetDAG(rw.Ctx, rw.DAG, n) {
240 - lc := cid.NewCidV0(n.Links[i].Hash)
240 + lc := n.Links()[i].Cid
241 if rw.skip(lc) {
242 continue
243 }
244
245 - if err := rw.WriteEdge(nc, lc, n.Links[i].Name); err != nil {
245 + if err := rw.WriteEdge(nc, lc, n.Links()[i].Name); err != nil {
246 return count, err
247 }
248
@@ -260,7 +260,7 @@ func (rw *RefWriter) writeRefsRecursive(n *dag.Node) (int, error) {
260 return count, nil
261 }
262
263 -func (rw *RefWriter) writeRefsSingle(n *dag.Node) (int, error) {
263 +func (rw *RefWriter) writeRefsSingle(n dag.Node) (int, error) {
264 c := n.Cid()
265
266 if rw.skip(c) {
@@ -268,9 +268,8 @@ func (rw *RefWriter) writeRefsSingle(n *dag.Node) (int, error) {
268 }
269
270 count := 0
271 - for _, l := range n.Links {
272 - lc := cid.NewCidV0(l.Hash)
273 -
271 + for _, l := range n.Links() {
272 + lc := l.Cid
273 if rw.skip(lc) {
274 continue
275 }
core/commands/tar.go
+8 -1
@@ -7,6 +7,7 @@ import (
7 cmds "github.com/ipfs/go-ipfs/commands"
8 core "github.com/ipfs/go-ipfs/core"
9 "github.com/ipfs/go-ipfs/core/coreunix"
10 + dag "github.com/ipfs/go-ipfs/merkledag"
11 path "github.com/ipfs/go-ipfs/path"
12 tar "github.com/ipfs/go-ipfs/tar"
13 )
@@ -100,7 +101,13 @@ var tarCatCmd = &cmds.Command{
101 return
102 }
103
103 - r, err := tar.ExportTar(req.Context(), root, nd.DAG)
104 + rootpb, ok := root.(*dag.ProtoNode)
105 + if !ok {
106 + res.SetError(dag.ErrNotProtobuf, cmds.ErrNormal)
107 + return
108 + }
109 +
110 + r, err := tar.ExportTar(req.Context(), rootpb, nd.DAG)
111 if err != nil {
112 res.SetError(err, cmds.ErrNormal)
113 return
core/commands/unixfs/ls.go
+18 -7
@@ -103,7 +103,13 @@ possible, please use 'ipfs ls' instead.
103 continue
104 }
105
106 - unixFSNode, err := unixfs.FromBytes(merkleNode.Data())
106 + ndpb, ok := merkleNode.(*merkledag.ProtoNode)
107 + if !ok {
108 + res.SetError(merkledag.ErrNotProtobuf, cmds.ErrNormal)
109 + return
110 + }
111 +
112 + unixFSNode, err := unixfs.FromBytes(ndpb.Data())
113 if err != nil {
114 res.SetError(err, cmds.ErrNormal)
115 return
@@ -121,16 +127,21 @@ possible, please use 'ipfs ls' instead.
127 case unixfspb.Data_File:
128 break
129 case unixfspb.Data_Directory:
124 - links := make([]LsLink, len(merkleNode.Links))
130 + links := make([]LsLink, len(merkleNode.Links()))
131 output.Objects[hash].Links = links
126 - for i, link := range merkleNode.Links {
127 - var linkNode *merkledag.Node
128 - linkNode, err = link.GetNode(ctx, node.DAG)
132 + for i, link := range merkleNode.Links() {
133 + linkNode, err := link.GetNode(ctx, node.DAG)
134 if err != nil {
135 res.SetError(err, cmds.ErrNormal)
136 return
137 }
133 - d, err := unixfs.FromBytes(linkNode.Data())
138 + lnpb, ok := linkNode.(*merkledag.ProtoNode)
139 + if !ok {
140 + res.SetError(merkledag.ErrNotProtobuf, cmds.ErrNormal)
141 + return
142 + }
143 +
144 + d, err := unixfs.FromBytes(lnpb.Data())
145 if err != nil {
146 res.SetError(err, cmds.ErrNormal)
147 return
@@ -138,7 +149,7 @@ possible, please use 'ipfs ls' instead.
149 t := d.GetType()
150 lsLink := LsLink{
151 Name: link.Name,
141 - Hash: link.Hash.B58String(),
152 + Hash: link.Cid.String(),
153 Type: t.String(),
154 }
155 if t == unixfspb.Data_File {
core/core.go
+9 -2
@@ -499,7 +499,7 @@ func (n *IpfsNode) loadFilesRoot() error {
499 return n.Repo.Datastore().Put(dsk, c.Bytes())
500 }
501
502 - var nd *merkledag.Node
502 + var nd *merkledag.ProtoNode
503 val, err := n.Repo.Datastore().Get(dsk)
504
505 switch {
@@ -515,10 +515,17 @@ func (n *IpfsNode) loadFilesRoot() error {
515 return err
516 }
517
518 - nd, err = n.DAG.Get(n.Context(), c)
518 + rnd, err := n.DAG.Get(n.Context(), c)
519 if err != nil {
520 return fmt.Errorf("error loading filesroot from DAG: %s", err)
521 }
522 +
523 + pbnd, ok := rnd.(*merkledag.ProtoNode)
524 + if !ok {
525 + return merkledag.ErrNotProtobuf
526 + }
527 +
528 + nd = pbnd
529 default:
530 return err
531 }
core/corehttp/gateway_handler.go
+50 -12
@@ -45,7 +45,7 @@ func newGatewayHandler(node *core.IpfsNode, conf GatewayConfig) *gatewayHandler
45 }
46
47 // TODO(cryptix): find these helpers somewhere else
48 -func (i *gatewayHandler) newDagFromReader(r io.Reader) (*dag.Node, error) {
48 +func (i *gatewayHandler) newDagFromReader(r io.Reader) (*dag.ProtoNode, error) {
49 // TODO(cryptix): change and remove this helper once PR1136 is merged
50 // return ufs.AddFromReader(i.node, r.Body)
51 return importer.BuildDagFromReader(
@@ -163,6 +163,12 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
163 return
164 }
165
166 + pbnd, ok := nd.(*dag.ProtoNode)
167 + if !ok {
168 + webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest)
169 + return
170 + }
171 +
172 etag := gopath.Base(urlPath)
173 if r.Header.Get("If-None-Match") == etag {
174 w.WriteHeader(http.StatusNotModified)
@@ -190,7 +196,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
196 w.Header().Set("Suborigin", pathRoot)
197 }
198
193 - dr, err := uio.NewDagReader(ctx, nd, i.node.DAG)
199 + dr, err := uio.NewDagReader(ctx, pbnd, i.node.DAG)
200 if err != nil && err != uio.ErrIsDir {
201 // not a directory and still an error
202 internalWebError(w, err)
@@ -221,7 +227,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
227 var dirListing []directoryItem
228 // loop through files
229 foundIndex := false
224 - for _, link := range nd.Links {
230 + for _, link := range nd.Links() {
231 if link.Name == "index.html" {
232 log.Debugf("found index.html link for %s", urlPath)
233 foundIndex = true
@@ -239,7 +245,14 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
245 internalWebError(w, err)
246 return
247 }
242 - dr, err := uio.NewDagReader(ctx, nd, i.node.DAG)
248 +
249 + pbnd, ok := nd.(*dag.ProtoNode)
250 + if !ok {
251 + internalWebError(w, dag.ErrNotProtobuf)
252 + return
253 + }
254 +
255 + dr, err := uio.NewDagReader(ctx, pbnd, i.node.DAG)
256 if err != nil {
257 internalWebError(w, err)
258 return
@@ -340,7 +353,7 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
353 return
354 }
355
343 - var newnode *dag.Node
356 + var newnode *dag.ProtoNode
357 if rsegs[len(rsegs)-1] == "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" {
358 newnode = uio.NewEmptyDirectory()
359 } else {
@@ -376,7 +389,13 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
389 return
390 }
391
379 - e := dagutils.NewDagEditor(rnode, i.node.DAG)
392 + pbnd, ok := rnode.(*dag.ProtoNode)
393 + if !ok {
394 + webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest)
395 + return
396 + }
397 +
398 + e := dagutils.NewDagEditor(pbnd, i.node.DAG)
399 err = e.InsertNodeAtPath(ctx, newPath, newnode, uio.NewEmptyDirectory)
400 if err != nil {
401 webError(w, "putHandler: InsertNodeAtPath failed", err, http.StatusInternalServerError)
@@ -392,13 +411,19 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
411 newcid = nnode.Cid()
412
413 case nil:
414 + pbnd, ok := rnode.(*dag.ProtoNode)
415 + if !ok {
416 + webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest)
417 + return
418 + }
419 +
420 // object set-data case
396 - rnode.SetData(newnode.Data())
421 + pbnd.SetData(newnode.Data())
422
398 - newcid, err = i.node.DAG.Add(rnode)
423 + newcid, err = i.node.DAG.Add(pbnd)
424 if err != nil {
425 nnk := newnode.Cid()
401 - rk := rnode.Cid()
426 + rk := pbnd.Cid()
427 webError(w, fmt.Sprintf("putHandler: Could not add newnode(%q) to root(%q)", nnk.String(), rk.String()), err, http.StatusInternalServerError)
428 return
429 }
@@ -444,20 +469,33 @@ func (i *gatewayHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
469 return
470 }
471
472 + pbnd, ok := pathNodes[len(pathNodes)-1].(*dag.ProtoNode)
473 + if !ok {
474 + webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest)
475 + return
476 + }
477 +
478 // TODO(cyrptix): assumes len(pathNodes) > 1 - not found is an error above?
448 - err = pathNodes[len(pathNodes)-1].RemoveNodeLink(components[len(components)-1])
479 + err = pbnd.RemoveNodeLink(components[len(components)-1])
480 if err != nil {
481 webError(w, "Could not delete link", err, http.StatusBadRequest)
482 return
483 }
484
454 - newnode := pathNodes[len(pathNodes)-1]
485 + var newnode *dag.ProtoNode = pbnd
486 for j := len(pathNodes) - 2; j >= 0; j-- {
487 if _, err := i.node.DAG.Add(newnode); err != nil {
488 webError(w, "Could not add node", err, http.StatusInternalServerError)
489 return
490 }
460 - newnode, err = pathNodes[j].UpdateNodeLink(components[j], newnode)
491 +
492 + pathpb, ok := pathNodes[j].(*dag.ProtoNode)
493 + if !ok {
494 + webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest)
495 + return
496 + }
497 +
498 + newnode, err = pathpb.UpdateNodeLink(components[j], newnode)
499 if err != nil {
500 webError(w, "Could not update node links", err, http.StatusInternalServerError)
501 return
core/corerepo/pinning.go
+1 -1
@@ -25,7 +25,7 @@ import (
25 )
26
27 func Pin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) ([]*cid.Cid, error) {
28 - dagnodes := make([]*merkledag.Node, 0)
28 + dagnodes := make([]merkledag.Node, 0)
29 for _, fpath := range paths {
30 dagnode, err := core.Resolve(ctx, n, path.Path(fpath))
31 if err != nil {
core/coreunix/add.go
+20 -14
@@ -100,7 +100,7 @@ type Adder struct {
100 Silent bool
101 Wrap bool
102 Chunker string
103 - root *dag.Node
103 + root *dag.ProtoNode
104 mr *mfs.Root
105 unlocker bs.Unlocker
106 tempRoot *cid.Cid
@@ -111,7 +111,7 @@ func (adder *Adder) SetMfsRoot(r *mfs.Root) {
111 }
112
113 // Perform the actual add & pin locally, outputting results to reader
114 -func (adder Adder) add(reader io.Reader) (*dag.Node, error) {
114 +func (adder Adder) add(reader io.Reader) (*dag.ProtoNode, error) {
115 chnk, err := chunk.FromString(reader, adder.Chunker)
116 if err != nil {
117 return nil, err
@@ -129,7 +129,7 @@ func (adder Adder) add(reader io.Reader) (*dag.Node, error) {
129 )
130 }
131
132 -func (adder *Adder) RootNode() (*dag.Node, error) {
132 +func (adder *Adder) RootNode() (*dag.ProtoNode, error) {
133 // for memoizing
134 if adder.root != nil {
135 return adder.root, nil
@@ -141,11 +141,18 @@ func (adder *Adder) RootNode() (*dag.Node, error) {
141 }
142
143 // if not wrapping, AND one root file, use that hash as root.
144 - if !adder.Wrap && len(root.Links) == 1 {
145 - root, err = root.Links[0].GetNode(adder.ctx, adder.dagService)
144 + if !adder.Wrap && len(root.Links()) == 1 {
145 + nd, err := root.Links()[0].GetNode(adder.ctx, adder.dagService)
146 if err != nil {
147 return nil, err
148 }
149 +
150 + pbnd, ok := nd.(*dag.ProtoNode)
151 + if !ok {
152 + return nil, dag.ErrNotProtobuf
153 + }
154 +
155 + root = pbnd
156 }
157
158 adder.root = root
@@ -178,7 +185,7 @@ func (adder *Adder) PinRoot() error {
185 return adder.pinning.Flush()
186 }
187
181 -func (adder *Adder) Finalize() (*dag.Node, error) {
188 +func (adder *Adder) Finalize() (*dag.ProtoNode, error) {
189 root := adder.mr.GetValue()
190
191 // cant just call adder.RootNode() here as we need the name for printing
@@ -189,7 +196,7 @@ func (adder *Adder) Finalize() (*dag.Node, error) {
196
197 var name string
198 if !adder.Wrap {
192 - name = rootNode.Links[0].Name
199 + name = rootNode.Links()[0].Name
200
201 dir, ok := adder.mr.GetValue().(*mfs.Directory)
202 if !ok {
@@ -300,7 +307,7 @@ func AddR(n *core.IpfsNode, root string) (key string, err error) {
307 // to preserve the filename.
308 // Returns the path of the added file ("<dir hash>/filename"), the DAG node of
309 // the directory, and and error if any.
303 -func AddWrapped(n *core.IpfsNode, r io.Reader, filename string) (string, *dag.Node, error) {
310 +func AddWrapped(n *core.IpfsNode, r io.Reader, filename string) (string, *dag.ProtoNode, error) {
311 file := files.NewReaderFile(filename, filename, ioutil.NopCloser(r), nil)
312 fileAdder, err := NewAdder(n.Context(), n.Pinning, n.Blockstore, n.DAG)
313 if err != nil {
@@ -324,7 +331,7 @@ func AddWrapped(n *core.IpfsNode, r io.Reader, filename string) (string, *dag.No
331 return gopath.Join(c.String(), filename), dagnode, nil
332 }
333
327 -func (adder *Adder) addNode(node *dag.Node, path string) error {
334 +func (adder *Adder) addNode(node *dag.ProtoNode, path string) error {
335 // patch it into the root
336 if path == "" {
337 path = node.Cid().String()
@@ -449,7 +456,7 @@ func (adder *Adder) maybePauseForGC() error {
456 }
457
458 // outputDagnode sends dagnode info over the output channel
452 -func outputDagnode(out chan interface{}, name string, dn *dag.Node) error {
459 +func outputDagnode(out chan interface{}, name string, dn *dag.ProtoNode) error {
460 if out == nil {
461 return nil
462 }
@@ -475,18 +482,17 @@ func NewMemoryDagService() dag.DAGService {
482 }
483
484 // from core/commands/object.go
478 -func getOutput(dagnode *dag.Node) (*Object, error) {
485 +func getOutput(dagnode *dag.ProtoNode) (*Object, error) {
486 c := dagnode.Cid()
487
488 output := &Object{
489 Hash: c.String(),
483 - Links: make([]Link, len(dagnode.Links)),
490 + Links: make([]Link, len(dagnode.Links())),
491 }
492
486 - for i, link := range dagnode.Links {
493 + for i, link := range dagnode.Links() {
494 output.Links[i] = Link{
495 Name: link.Name,
489 - //Hash: link.Hash.B58String(),
496 Size: link.Size,
497 }
498 }
core/coreunix/cat.go
+10 -2
@@ -1,8 +1,10 @@
1 package coreunix
2
3 import (
4 - context "context"
4 + "context"
5 +
6 core "github.com/ipfs/go-ipfs/core"
7 + dag "github.com/ipfs/go-ipfs/merkledag"
8 path "github.com/ipfs/go-ipfs/path"
9 uio "github.com/ipfs/go-ipfs/unixfs/io"
10 )
@@ -12,5 +14,11 @@ func Cat(ctx context.Context, n *core.IpfsNode, pstr string) (*uio.DagReader, er
14 if err != nil {
15 return nil, err
16 }
15 - return uio.NewDagReader(ctx, dagNode, n.DAG)
17 +
18 + dnpb, ok := dagNode.(*dag.ProtoNode)
19 + if !ok {
20 + return nil, dag.ErrNotProtobuf
21 + }
22 +
23 + return uio.NewDagReader(ctx, dnpb, n.DAG)
24 }
core/coreunix/metadata.go
+7 -2
@@ -18,7 +18,7 @@ func AddMetadataTo(n *core.IpfsNode, skey string, m *ft.Metadata) (string, error
18 return "", err
19 }
20
21 - mdnode := new(dag.Node)
21 + mdnode := new(dag.ProtoNode)
22 mdata, err := ft.BytesForMetadata(m)
23 if err != nil {
24 return "", err
@@ -48,5 +48,10 @@ func Metadata(n *core.IpfsNode, skey string) (*ft.Metadata, error) {
48 return nil, err
49 }
50
51 - return ft.MetadataFromBytes(nd.Data())
51 + pbnd, ok := nd.(*dag.ProtoNode)
52 + if !ok {
53 + return nil, dag.ErrNotProtobuf
54 + }
55 +
56 + return ft.MetadataFromBytes(pbnd.Data())
57 }
core/coreunix/metadata_test.go
+6 -1
@@ -72,7 +72,12 @@ func TestMetadata(t *testing.T) {
72 t.Fatal(err)
73 }
74
75 - ndr, err := uio.NewDagReader(ctx, retnode, ds)
75 + rtnpb, ok := retnode.(*merkledag.ProtoNode)
76 + if !ok {
77 + t.Fatal("expected protobuf node")
78 + }
79 +
80 + ndr, err := uio.NewDagReader(ctx, rtnpb, ds)
81 if err != nil {
82 t.Fatal(err)
83 }
core/pathresolver.go
+3 -3
@@ -19,7 +19,7 @@ var ErrNoNamesys = errors.New(
19 // Resolve resolves the given path by parsing out protocol-specific
20 // entries (e.g. /ipns/<node-key>) and then going through the /ipfs/
21 // entries and returning the final merkledag node.
22 -func Resolve(ctx context.Context, n *IpfsNode, p path.Path) (*merkledag.Node, error) {
22 +func Resolve(ctx context.Context, n *IpfsNode, p path.Path) (merkledag.Node, error) {
23 if strings.HasPrefix(p.String(), "/ipns/") {
24 // resolve ipns paths
25
@@ -82,10 +82,10 @@ func ResolveToCid(ctx context.Context, n *IpfsNode, p path.Path) (*cid.Cid, erro
82 }
83
84 // Extract and return the key of the link to the target dag node.
85 - link, err := dagnode.GetNodeLink(tail)
85 + link, _, err := dagnode.Resolve([]string{tail})
86 if err != nil {
87 return nil, err
88 }
89
90 - return cid.NewCidV0(link.Hash), nil
90 + return link.Cid, nil
91 }
exchange/bitswap/workers.go
+1 -1
@@ -60,7 +60,7 @@ func (bs *Bitswap) taskWorker(ctx context.Context, id int) {
60 log.Event(ctx, "Bitswap.TaskWorker.Work", logging.LoggableMap{
61 "ID": id,
62 "Target": envelope.Peer.Pretty(),
63 - "Block": envelope.Block.Multihash().B58String(),
63 + "Block": envelope.Block.Cid().String(),
64 })
65
66 bs.wm.SendBlock(ctx, envelope)
fuse/ipns/ipns_unix.go
+6 -1
@@ -100,7 +100,12 @@ func loadRoot(ctx context.Context, rt *keyRoot, ipfs *core.IpfsNode, name string
100 return nil, err
101 }
102
103 - root, err := mfs.NewRoot(ctx, ipfs.DAG, node, ipnsPubFunc(ipfs, rt.k))
103 + pbnode, ok := node.(*dag.ProtoNode)
104 + if !ok {
105 + return nil, dag.ErrNotProtobuf
106 + }
107 +
108 + root, err := mfs.NewRoot(ctx, ipfs.DAG, pbnode, ipnsPubFunc(ipfs, rt.k))
109 if err != nil {
110 return nil, err
111 }
fuse/readonly/ipfs_test.go
+11 -5
@@ -33,7 +33,7 @@ func maybeSkipFuseTests(t *testing.T) {
33 }
34 }
35
36 -func randObj(t *testing.T, nd *core.IpfsNode, size int64) (*dag.Node, []byte) {
36 +func randObj(t *testing.T, nd *core.IpfsNode, size int64) (*dag.ProtoNode, []byte) {
37 buf := make([]byte, size)
38 u.NewTimeSeededRand().Read(buf)
39 read := bytes.NewReader(buf)
@@ -86,17 +86,23 @@ func TestIpfsBasicRead(t *testing.T) {
86 }
87 }
88
89 -func getPaths(t *testing.T, ipfs *core.IpfsNode, name string, n *dag.Node) []string {
90 - if len(n.Links) == 0 {
89 +func getPaths(t *testing.T, ipfs *core.IpfsNode, name string, n *dag.ProtoNode) []string {
90 + if len(n.Links()) == 0 {
91 return []string{name}
92 }
93 var out []string
94 - for _, lnk := range n.Links {
94 + for _, lnk := range n.Links() {
95 child, err := lnk.GetNode(ipfs.Context(), ipfs.DAG)
96 if err != nil {
97 t.Fatal(err)
98 }
99 - sub := getPaths(t, ipfs, path.Join(name, lnk.Name), child)
99 +
100 + childpb, ok := child.(*dag.ProtoNode)
101 + if !ok {
102 + t.Fatal(dag.ErrNotProtobuf)
103 + }
104 +
105 + sub := getPaths(t, ipfs, path.Join(name, lnk.Name), childpb)
106 out = append(out, sub...)
107 }
108 return out
fuse/readonly/readonly_unix.go
+20 -8
@@ -66,7 +66,13 @@ func (s *Root) Lookup(ctx context.Context, name string) (fs.Node, error) {
66 return nil, fuse.ENOENT
67 }
68
69 - return &Node{Ipfs: s.Ipfs, Nd: nd}, nil
69 + pbnd, ok := nd.(*mdag.ProtoNode)
70 + if !ok {
71 + log.Error("fuse node was not a protobuf node")
72 + return nil, fuse.ENOTSUP
73 + }
74 +
75 + return &Node{Ipfs: s.Ipfs, Nd: pbnd}, nil
76 }
77
78 // ReadDirAll reads a particular directory. Disallowed for root.
@@ -78,7 +84,7 @@ func (*Root) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
84 // Node is the core object representing a filesystem tree node.
85 type Node struct {
86 Ipfs *core.IpfsNode
81 - Nd *mdag.Node
87 + Nd *mdag.ProtoNode
88 fd *uio.DagReader
89 cached *ftpb.Data
90 }
@@ -105,13 +111,13 @@ func (s *Node) Attr(ctx context.Context, a *fuse.Attr) error {
111 size := s.cached.GetFilesize()
112 a.Mode = 0444
113 a.Size = uint64(size)
108 - a.Blocks = uint64(len(s.Nd.Links))
114 + a.Blocks = uint64(len(s.Nd.Links()))
115 a.Uid = uint32(os.Getuid())
116 a.Gid = uint32(os.Getgid())
117 case ftpb.Data_Raw:
118 a.Mode = 0444
119 a.Size = uint64(len(s.cached.GetData()))
114 - a.Blocks = uint64(len(s.Nd.Links))
120 + a.Blocks = uint64(len(s.Nd.Links()))
121 a.Uid = uint32(os.Getuid())
122 a.Gid = uint32(os.Getgid())
123 case ftpb.Data_Symlink:
@@ -134,17 +140,23 @@ func (s *Node) Lookup(ctx context.Context, name string) (fs.Node, error) {
140 return nil, fuse.ENOENT
141 }
142
137 - return &Node{Ipfs: s.Ipfs, Nd: nodes[len(nodes)-1]}, nil
143 + pbnd, ok := nodes[len(nodes)-1].(*mdag.ProtoNode)
144 + if !ok {
145 + log.Error("fuse lookup got non-protobuf node")
146 + return nil, fuse.ENOTSUP
147 + }
148 +
149 + return &Node{Ipfs: s.Ipfs, Nd: pbnd}, nil
150 }
151
152 // ReadDirAll reads the link structure as directory entries
153 func (s *Node) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
154 log.Debug("Node ReadDir")
143 - entries := make([]fuse.Dirent, len(s.Nd.Links))
144 - for i, link := range s.Nd.Links {
155 + entries := make([]fuse.Dirent, len(s.Nd.Links()))
156 + for i, link := range s.Nd.Links() {
157 n := link.Name
158 if len(n) == 0 {
147 - n = link.Hash.B58String()
159 + n = link.Cid.String()
160 }
161 entries[i] = fuse.Dirent{Name: n, Type: fuse.DT_File}
162 }
importer/balanced/balanced_test.go
+2 -2
@@ -22,7 +22,7 @@ import (
22
23 // TODO: extract these tests and more as a generic layout test suite
24
25 -func buildTestDag(ds dag.DAGService, spl chunk.Splitter) (*dag.Node, error) {
25 +func buildTestDag(ds dag.DAGService, spl chunk.Splitter) (*dag.ProtoNode, error) {
26 dbp := h.DagBuilderParams{
27 Dagserv: ds,
28 Maxlinks: h.DefaultLinksPerBlock,
@@ -31,7 +31,7 @@ func buildTestDag(ds dag.DAGService, spl chunk.Splitter) (*dag.Node, error) {
31 return BalancedLayout(dbp.New(spl))
32 }
33
34 -func getTestDag(t *testing.T, ds dag.DAGService, size int64, blksize int64) (*dag.Node, []byte) {
34 +func getTestDag(t *testing.T, ds dag.DAGService, size int64, blksize int64) (*dag.ProtoNode, []byte) {
35 data := make([]byte, size)
36 u.NewTimeSeededRand().Read(data)
37 r := bytes.NewReader(data)
importer/balanced/builder.go
+1 -1
@@ -7,7 +7,7 @@ import (
7 dag "github.com/ipfs/go-ipfs/merkledag"
8 )
9
10 -func BalancedLayout(db *h.DagBuilderHelper) (*dag.Node, error) {
10 +func BalancedLayout(db *h.DagBuilderHelper) (*dag.ProtoNode, error) {
11 var root *h.UnixfsNode
12 for level := 0; !db.Done(); level++ {
13
importer/helpers/dagbuilder.go
+1 -1
@@ -106,7 +106,7 @@ func (db *DagBuilderHelper) FillNodeWithData(node *UnixfsNode) error {
106 return nil
107 }
108
109 -func (db *DagBuilderHelper) Add(node *UnixfsNode) (*dag.Node, error) {
109 +func (db *DagBuilderHelper) Add(node *UnixfsNode) (*dag.ProtoNode, error) {
110 dn, err := node.GetDagNode()
111 if err != nil {
112 return nil, err
importer/helpers/helpers.go
+13 -8
@@ -37,14 +37,14 @@ var ErrSizeLimitExceeded = fmt.Errorf("object size limit exceeded")
37 // UnixfsNode is a struct created to aid in the generation
38 // of unixfs DAG trees
39 type UnixfsNode struct {
40 - node *dag.Node
40 + node *dag.ProtoNode
41 ufmt *ft.FSNode
42 }
43
44 // NewUnixfsNode creates a new Unixfs node to represent a file
45 func NewUnixfsNode() *UnixfsNode {
46 return &UnixfsNode{
47 - node: new(dag.Node),
47 + node: new(dag.ProtoNode),
48 ufmt: &ft.FSNode{Type: ft.TFile},
49 }
50 }
@@ -52,13 +52,13 @@ func NewUnixfsNode() *UnixfsNode {
52 // NewUnixfsBlock creates a new Unixfs node to represent a raw data block
53 func NewUnixfsBlock() *UnixfsNode {
54 return &UnixfsNode{
55 - node: new(dag.Node),
55 + node: new(dag.ProtoNode),
56 ufmt: &ft.FSNode{Type: ft.TRaw},
57 }
58 }
59
60 // NewUnixfsNodeFromDag reconstructs a Unixfs node from a given dag node
61 -func NewUnixfsNodeFromDag(nd *dag.Node) (*UnixfsNode, error) {
61 +func NewUnixfsNodeFromDag(nd *dag.ProtoNode) (*UnixfsNode, error) {
62 mb, err := ft.FSNodeFromBytes(nd.Data())
63 if err != nil {
64 return nil, err
@@ -75,12 +75,17 @@ func (n *UnixfsNode) NumChildren() int {
75 }
76
77 func (n *UnixfsNode) GetChild(ctx context.Context, i int, ds dag.DAGService) (*UnixfsNode, error) {
78 - nd, err := n.node.Links[i].GetNode(ctx, ds)
78 + nd, err := n.node.Links()[i].GetNode(ctx, ds)
79 if err != nil {
80 return nil, err
81 }
82
83 - return NewUnixfsNodeFromDag(nd)
83 + pbn, ok := nd.(*dag.ProtoNode)
84 + if !ok {
85 + return nil, dag.ErrNotProtobuf
86 + }
87 +
88 + return NewUnixfsNodeFromDag(pbn)
89 }
90
91 // addChild will add the given UnixfsNode as a child of the receiver.
@@ -112,7 +117,7 @@ func (n *UnixfsNode) AddChild(child *UnixfsNode, db *DagBuilderHelper) error {
117 // Removes the child node at the given index
118 func (n *UnixfsNode) RemoveChild(index int, dbh *DagBuilderHelper) {
119 n.ufmt.RemoveBlockSize(index)
115 - n.node.Links = append(n.node.Links[:index], n.node.Links[index+1:]...)
120 + n.node.SetLinks(append(n.node.Links()[:index], n.node.Links()[index+1:]...))
121 }
122
123 func (n *UnixfsNode) SetData(data []byte) {
@@ -121,7 +126,7 @@ func (n *UnixfsNode) SetData(data []byte) {
126
127 // getDagNode fills out the proper formatting for the unixfs node
128 // inside of a DAG node and returns the dag node
124 -func (n *UnixfsNode) GetDagNode() (*dag.Node, error) {
129 +func (n *UnixfsNode) GetDagNode() (*dag.ProtoNode, error) {
130 data, err := n.ufmt.GetBytes()
131 if err != nil {
132 return nil, err
importer/importer.go
+3 -3
@@ -19,7 +19,7 @@ var log = logging.Logger("importer")
19
20 // Builds a DAG from the given file, writing created blocks to disk as they are
21 // created
22 -func BuildDagFromFile(fpath string, ds dag.DAGService) (*dag.Node, error) {
22 +func BuildDagFromFile(fpath string, ds dag.DAGService) (*dag.ProtoNode, error) {
23 stat, err := os.Lstat(fpath)
24 if err != nil {
25 return nil, err
@@ -38,7 +38,7 @@ func BuildDagFromFile(fpath string, ds dag.DAGService) (*dag.Node, error) {
38 return BuildDagFromReader(ds, chunk.NewSizeSplitter(f, chunk.DefaultBlockSize))
39 }
40
41 -func BuildDagFromReader(ds dag.DAGService, spl chunk.Splitter) (*dag.Node, error) {
41 +func BuildDagFromReader(ds dag.DAGService, spl chunk.Splitter) (*dag.ProtoNode, error) {
42 dbp := h.DagBuilderParams{
43 Dagserv: ds,
44 Maxlinks: h.DefaultLinksPerBlock,
@@ -47,7 +47,7 @@ func BuildDagFromReader(ds dag.DAGService, spl chunk.Splitter) (*dag.Node, error
47 return bal.BalancedLayout(dbp.New(spl))
48 }
49
50 -func BuildTrickleDagFromReader(ds dag.DAGService, spl chunk.Splitter) (*dag.Node, error) {
50 +func BuildTrickleDagFromReader(ds dag.DAGService, spl chunk.Splitter) (*dag.ProtoNode, error) {
51 dbp := h.DagBuilderParams{
52 Dagserv: ds,
53 Maxlinks: h.DefaultLinksPerBlock,
importer/importer_test.go
+3 -3
@@ -14,7 +14,7 @@ import (
14 u "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util"
15 )
16
17 -func getBalancedDag(t testing.TB, size int64, blksize int64) (*dag.Node, dag.DAGService) {
17 +func getBalancedDag(t testing.TB, size int64, blksize int64) (*dag.ProtoNode, dag.DAGService) {
18 ds := mdtest.Mock()
19 r := io.LimitReader(u.NewTimeSeededRand(), size)
20 nd, err := BuildDagFromReader(ds, chunk.NewSizeSplitter(r, blksize))
@@ -24,7 +24,7 @@ func getBalancedDag(t testing.TB, size int64, blksize int64) (*dag.Node, dag.DAG
24 return nd, ds
25 }
26
27 -func getTrickleDag(t testing.TB, size int64, blksize int64) (*dag.Node, dag.DAGService) {
27 +func getTrickleDag(t testing.TB, size int64, blksize int64) (*dag.ProtoNode, dag.DAGService) {
28 ds := mdtest.Mock()
29 r := io.LimitReader(u.NewTimeSeededRand(), size)
30 nd, err := BuildTrickleDagFromReader(ds, chunk.NewSizeSplitter(r, blksize))
@@ -100,7 +100,7 @@ func BenchmarkTrickleReadFull(b *testing.B) {
100 runReadBench(b, nd, ds)
101 }
102
103 -func runReadBench(b *testing.B, nd *dag.Node, ds dag.DAGService) {
103 +func runReadBench(b *testing.B, nd *dag.ProtoNode, ds dag.DAGService) {
104 for i := 0; i < b.N; i++ {
105 ctx, cancel := context.WithCancel(context.Background())
106 read, err := uio.NewDagReader(ctx, nd, ds)
importer/trickle/trickle_test.go
+7 -7
@@ -20,7 +20,7 @@ import (
20 u "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util"
21 )
22
23 -func buildTestDag(ds merkledag.DAGService, spl chunk.Splitter) (*merkledag.Node, error) {
23 +func buildTestDag(ds merkledag.DAGService, spl chunk.Splitter) (*merkledag.ProtoNode, error) {
24 dbp := h.DagBuilderParams{
25 Dagserv: ds,
26 Maxlinks: h.DefaultLinksPerBlock,
@@ -523,7 +523,7 @@ func TestAppendSingleBytesToEmpty(t *testing.T) {
523
524 data := []byte("AB")
525
526 - nd := new(merkledag.Node)
526 + nd := new(merkledag.ProtoNode)
527 nd.SetData(ft.FilePBData(nil, 0))
528
529 dbp := &h.DagBuilderParams{
@@ -561,7 +561,7 @@ func TestAppendSingleBytesToEmpty(t *testing.T) {
561 }
562 }
563
564 -func printDag(nd *merkledag.Node, ds merkledag.DAGService, indent int) {
564 +func printDag(nd *merkledag.ProtoNode, ds merkledag.DAGService, indent int) {
565 pbd, err := ft.FromBytes(nd.Data())
566 if err != nil {
567 panic(err)
@@ -571,17 +571,17 @@ func printDag(nd *merkledag.Node, ds merkledag.DAGService, indent int) {
571 fmt.Print(" ")
572 }
573 fmt.Printf("{size = %d, type = %s, nc = %d", pbd.GetFilesize(), pbd.GetType().String(), len(pbd.GetBlocksizes()))
574 - if len(nd.Links) > 0 {
574 + if len(nd.Links()) > 0 {
575 fmt.Println()
576 }
577 - for _, lnk := range nd.Links {
577 + for _, lnk := range nd.Links() {
578 child, err := lnk.GetNode(context.Background(), ds)
579 if err != nil {
580 panic(err)
581 }
582 - printDag(child, ds, indent+1)
582 + printDag(child.(*merkledag.ProtoNode), ds, indent+1)
583 }
584 - if len(nd.Links) > 0 {
584 + if len(nd.Links()) > 0 {
585 for i := 0; i < indent; i++ {
586 fmt.Print(" ")
587 }
importer/trickle/trickledag.go
+17 -12
@@ -1,9 +1,9 @@
1 package trickle
2
3 import (
4 + "context"
5 "errors"
5 -
6 - context "context"
6 + "fmt"
7
8 h "github.com/ipfs/go-ipfs/importer/helpers"
9 dag "github.com/ipfs/go-ipfs/merkledag"
@@ -15,7 +15,7 @@ import (
15 // improves seek speeds.
16 const layerRepeat = 4
17
18 -func TrickleLayout(db *h.DagBuilderHelper) (*dag.Node, error) {
18 +func TrickleLayout(db *h.DagBuilderHelper) (*dag.ProtoNode, error) {
19 root := h.NewUnixfsNode()
20 if err := db.FillNodeLayer(root); err != nil {
21 return nil, err
@@ -66,7 +66,7 @@ func fillTrickleRec(db *h.DagBuilderHelper, node *h.UnixfsNode, depth int) error
66 }
67
68 // TrickleAppend appends the data in `db` to the dag, using the Trickledag format
69 -func TrickleAppend(ctx context.Context, base *dag.Node, db *h.DagBuilderHelper) (out *dag.Node, err_out error) {
69 +func TrickleAppend(ctx context.Context, base *dag.ProtoNode, db *h.DagBuilderHelper) (out *dag.ProtoNode, err_out error) {
70 defer func() {
71 if err_out == nil {
72 if err := db.Close(); err != nil {
@@ -229,15 +229,15 @@ func trickleDepthInfo(node *h.UnixfsNode, maxlinks int) (int, int) {
229
230 // VerifyTrickleDagStructure checks that the given dag matches exactly the trickle dag datastructure
231 // layout
232 -func VerifyTrickleDagStructure(nd *dag.Node, ds dag.DAGService, direct int, layerRepeat int) error {
232 +func VerifyTrickleDagStructure(nd *dag.ProtoNode, ds dag.DAGService, direct int, layerRepeat int) error {
233 return verifyTDagRec(nd, -1, direct, layerRepeat, ds)
234 }
235
236 // Recursive call for verifying the structure of a trickledag
237 -func verifyTDagRec(nd *dag.Node, depth, direct, layerRepeat int, ds dag.DAGService) error {
237 +func verifyTDagRec(nd *dag.ProtoNode, depth, direct, layerRepeat int, ds dag.DAGService) error {
238 if depth == 0 {
239 // zero depth dag is raw data block
240 - if len(nd.Links) > 0 {
240 + if len(nd.Links()) > 0 {
241 return errors.New("expected direct block")
242 }
243
@@ -259,22 +259,27 @@ func verifyTDagRec(nd *dag.Node, depth, direct, layerRepeat int, ds dag.DAGServi
259 }
260
261 if pbn.GetType() != ft.TFile {
262 - return errors.New("expected file as branch node")
262 + return fmt.Errorf("expected file as branch node, got: %s", pbn.GetType())
263 }
264
265 if len(pbn.Data) > 0 {
266 return errors.New("branch node should not have data")
267 }
268
269 - for i := 0; i < len(nd.Links); i++ {
270 - child, err := nd.Links[i].GetNode(context.TODO(), ds)
269 + for i := 0; i < len(nd.Links()); i++ {
270 + childi, err := nd.Links()[i].GetNode(context.TODO(), ds)
271 if err != nil {
272 return err
273 }
274
275 + childpb, ok := childi.(*dag.ProtoNode)
276 + if !ok {
277 + return fmt.Errorf("cannot operate on non-protobuf nodes")
278 + }
279 +
280 if i < direct {
281 // Direct blocks
277 - err := verifyTDagRec(child, 0, direct, layerRepeat, ds)
282 + err := verifyTDagRec(childpb, 0, direct, layerRepeat, ds)
283 if err != nil {
284 return err
285 }
@@ -284,7 +289,7 @@ func verifyTDagRec(nd *dag.Node, depth, direct, layerRepeat int, ds dag.DAGServi
289 if rdepth >= depth && depth > 0 {
290 return errors.New("Child dag was too deep!")
291 }
287 - err := verifyTDagRec(child, rdepth, direct, layerRepeat, ds)
292 + err := verifyTDagRec(childpb, rdepth, direct, layerRepeat, ds)
293 if err != nil {
294 return err
295 }
merkledag/coding.go
+17 -18
@@ -7,7 +7,6 @@ import (
7 pb "github.com/ipfs/go-ipfs/merkledag/pb"
8
9 cid "gx/ipfs/QmXUuRadqDq5BuFWzVU6VuKaSjTcNm1gNCtLvvP1TJCW4z/go-cid"
10 - mh "gx/ipfs/QmYDds3421prZgqKbLpEK7T9Aa2eVdQ7o3YarX1LVLdP2J/go-multihash"
10 u "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util"
11 )
12
@@ -16,23 +15,23 @@ import (
15
16 // unmarshal decodes raw data into a *Node instance.
17 // The conversion uses an intermediate PBNode.
19 -func (n *Node) unmarshal(encoded []byte) error {
18 +func (n *ProtoNode) unmarshal(encoded []byte) error {
19 var pbn pb.PBNode
20 if err := pbn.Unmarshal(encoded); err != nil {
21 return fmt.Errorf("Unmarshal failed. %v", err)
22 }
23
24 pbnl := pbn.GetLinks()
26 - n.Links = make([]*Link, len(pbnl))
25 + n.links = make([]*Link, len(pbnl))
26 for i, l := range pbnl {
28 - n.Links[i] = &Link{Name: l.GetName(), Size: l.GetTsize()}
29 - h, err := mh.Cast(l.GetHash())
27 + n.links[i] = &Link{Name: l.GetName(), Size: l.GetTsize()}
28 + c, err := cid.Cast(l.GetHash())
29 if err != nil {
30 return fmt.Errorf("Link hash #%d is not valid multihash. %v", i, err)
31 }
33 - n.Links[i].Hash = h
32 + n.links[i].Cid = c
33 }
35 - sort.Stable(LinkSlice(n.Links)) // keep links sorted
34 + sort.Stable(LinkSlice(n.links)) // keep links sorted
35
36 n.data = pbn.GetData()
37 n.encoded = encoded
@@ -41,7 +40,7 @@ func (n *Node) unmarshal(encoded []byte) error {
40
41 // Marshal encodes a *Node instance into a new byte slice.
42 // The conversion uses an intermediate PBNode.
44 -func (n *Node) Marshal() ([]byte, error) {
43 +func (n *ProtoNode) Marshal() ([]byte, error) {
44 pbn := n.getPBNode()
45 data, err := pbn.Marshal()
46 if err != nil {
@@ -50,18 +49,18 @@ func (n *Node) Marshal() ([]byte, error) {
49 return data, nil
50 }
51
53 -func (n *Node) getPBNode() *pb.PBNode {
52 +func (n *ProtoNode) getPBNode() *pb.PBNode {
53 pbn := &pb.PBNode{}
55 - if len(n.Links) > 0 {
56 - pbn.Links = make([]*pb.PBLink, len(n.Links))
54 + if len(n.links) > 0 {
55 + pbn.Links = make([]*pb.PBLink, len(n.links))
56 }
57
59 - sort.Stable(LinkSlice(n.Links)) // keep links sorted
60 - for i, l := range n.Links {
58 + sort.Stable(LinkSlice(n.links)) // keep links sorted
59 + for i, l := range n.links {
60 pbn.Links[i] = &pb.PBLink{}
61 pbn.Links[i].Name = &l.Name
62 pbn.Links[i].Tsize = &l.Size
64 - pbn.Links[i].Hash = []byte(l.Hash)
63 + pbn.Links[i].Hash = l.Cid.Bytes()
64 }
65
66 if len(n.data) > 0 {
@@ -72,8 +71,8 @@ func (n *Node) getPBNode() *pb.PBNode {
71
72 // EncodeProtobuf returns the encoded raw data version of a Node instance.
73 // It may use a cached encoded version, unless the force flag is given.
75 -func (n *Node) EncodeProtobuf(force bool) ([]byte, error) {
76 - sort.Stable(LinkSlice(n.Links)) // keep links sorted
74 +func (n *ProtoNode) EncodeProtobuf(force bool) ([]byte, error) {
75 + sort.Stable(LinkSlice(n.links)) // keep links sorted
76 if n.encoded == nil || force {
77 n.cached = nil
78 var err error
@@ -91,8 +90,8 @@ func (n *Node) EncodeProtobuf(force bool) ([]byte, error) {
90 }
91
92 // Decoded decodes raw data and returns a new Node instance.
94 -func DecodeProtobuf(encoded []byte) (*Node, error) {
95 - n := new(Node)
93 +func DecodeProtobuf(encoded []byte) (*ProtoNode, error) {
94 + n := new(ProtoNode)
95 err := n.unmarshal(encoded)
96 if err != nil {
97 return nil, fmt.Errorf("incorrectly formatted merkledag node: %s", err)
merkledag/merkledag.go
+40 -37
@@ -20,9 +20,9 @@ var ErrNotFound = fmt.Errorf("merkledag: not found")
20
21 // DAGService is an IPFS Merkle DAG service.
22 type DAGService interface {
23 - Add(*Node) (*cid.Cid, error)
24 - Get(context.Context, *cid.Cid) (*Node, error)
25 - Remove(*Node) error
23 + Add(Node) (*cid.Cid, error)
24 + Get(context.Context, *cid.Cid) (Node, error)
25 + Remove(Node) error
26
27 // GetDAG returns, in order, all the single leve child
28 // nodes of the passed in node.
@@ -45,6 +45,19 @@ func NewDAGService(bs bserv.BlockService) *dagService {
45 return &dagService{Blocks: bs}
46 }
47
48 +type Node interface {
49 + Resolve(path []string) (*Link, []string, error)
50 + Links() []*Link
51 + Tree() []string
52 +
53 + Stat() (*NodeStat, error)
54 + Size() (uint64, error)
55 + Cid() *cid.Cid
56 + Loggable() map[string]interface{}
57 + RawData() []byte
58 + String() string
59 +}
60 +
61 // dagService is an IPFS Merkle DAG service.
62 // - the root is virtual (like a forest)
63 // - stores nodes' data in a BlockService
@@ -55,7 +68,7 @@ type dagService struct {
68 }
69
70 // Add adds a node to the dagService, storing the block in the BlockService
58 -func (n *dagService) Add(nd *Node) (*cid.Cid, error) {
71 +func (n *dagService) Add(nd Node) (*cid.Cid, error) {
72 if n == nil { // FIXME remove this assertion. protect with constructor invariant
73 return nil, fmt.Errorf("dagService is nil")
74 }
@@ -68,7 +81,7 @@ func (n *dagService) Batch() *Batch {
81 }
82
83 // Get retrieves a node from the dagService, fetching the block in the BlockService
71 -func (n *dagService) Get(ctx context.Context, c *cid.Cid) (*Node, error) {
84 +func (n *dagService) Get(ctx context.Context, c *cid.Cid) (Node, error) {
85 if n == nil {
86 return nil, fmt.Errorf("dagService is nil")
87 }
@@ -84,7 +97,7 @@ func (n *dagService) Get(ctx context.Context, c *cid.Cid) (*Node, error) {
97 return nil, fmt.Errorf("Failed to get block for %s: %v", c, err)
98 }
99
87 - var res *Node
100 + var res Node
101 switch c.Type() {
102 case cid.Protobuf:
103 out, err := DecodeProtobuf(b.RawData())
@@ -94,13 +107,12 @@ func (n *dagService) Get(ctx context.Context, c *cid.Cid) (*Node, error) {
107 }
108 return nil, fmt.Errorf("Failed to decode Protocol Buffers: %v", err)
109 }
110 + out.cached = c
111 res = out
112 default:
113 return nil, fmt.Errorf("unrecognized formatting type")
114 }
115
102 - res.cached = c
103 -
116 return res, nil
117 }
118
@@ -109,7 +121,7 @@ func (n *dagService) GetLinks(ctx context.Context, c *cid.Cid) ([]*Link, error)
121 if err != nil {
122 return nil, err
123 }
112 - return node.Links, nil
124 + return node.Links(), nil
125 }
126
127 func (n *dagService) GetOfflineLinkService() LinkService {
@@ -121,7 +133,7 @@ func (n *dagService) GetOfflineLinkService() LinkService {
133 }
134 }
135
124 -func (n *dagService) Remove(nd *Node) error {
136 +func (n *dagService) Remove(nd Node) error {
137 return n.Blocks.DeleteBlock(nd)
138 }
139
@@ -143,7 +155,7 @@ func FindLinks(links []*cid.Cid, c *cid.Cid, start int) []int {
155 }
156
157 type NodeOption struct {
146 - Node *Node
158 + Node Node
159 Err error
160 }
161
@@ -166,7 +178,7 @@ func (ds *dagService) GetMany(ctx context.Context, keys []*cid.Cid) <-chan *Node
178
179 c := b.Cid()
180
169 - var nd *Node
181 + var nd Node
182 switch c.Type() {
183 case cid.Protobuf:
184 decnd, err := DecodeProtobuf(b.RawData())
@@ -174,7 +186,7 @@ func (ds *dagService) GetMany(ctx context.Context, keys []*cid.Cid) <-chan *Node
186 out <- &NodeOption{Err: err}
187 return
188 }
177 - decnd.cached = cid.NewCidV0(b.Multihash())
189 + decnd.cached = b.Cid()
190 nd = decnd
191 default:
192 out <- &NodeOption{Err: fmt.Errorf("unrecognized object type: %s", c.Type())}
@@ -197,10 +209,10 @@ func (ds *dagService) GetMany(ctx context.Context, keys []*cid.Cid) <-chan *Node
209 // GetDAG will fill out all of the links of the given Node.
210 // It returns a channel of nodes, which the caller can receive
211 // all the child nodes of 'root' on, in proper order.
200 -func GetDAG(ctx context.Context, ds DAGService, root *Node) []NodeGetter {
212 +func GetDAG(ctx context.Context, ds DAGService, root Node) []NodeGetter {
213 var cids []*cid.Cid
202 - for _, lnk := range root.Links {
203 - cids = append(cids, cid.NewCidV0(lnk.Hash))
214 + for _, lnk := range root.Links() {
215 + cids = append(cids, lnk.Cid)
216 }
217
218 return GetNodes(ctx, ds, cids)
@@ -269,16 +281,16 @@ func dedupeKeys(cids []*cid.Cid) []*cid.Cid {
281
282 func newNodePromise(ctx context.Context) NodeGetter {
283 return &nodePromise{
272 - recv: make(chan *Node, 1),
284 + recv: make(chan Node, 1),
285 ctx: ctx,
286 err: make(chan error, 1),
287 }
288 }
289
290 type nodePromise struct {
279 - cache *Node
291 + cache Node
292 clk sync.Mutex
281 - recv chan *Node
293 + recv chan Node
294 ctx context.Context
295 err chan error
296 }
@@ -288,9 +300,9 @@ type nodePromise struct {
300 // from its internal channels, subsequent calls will return the
301 // cached node.
302 type NodeGetter interface {
291 - Get(context.Context) (*Node, error)
303 + Get(context.Context) (Node, error)
304 Fail(err error)
293 - Send(*Node)
305 + Send(Node)
306 }
307
308 func (np *nodePromise) Fail(err error) {
@@ -306,7 +318,7 @@ func (np *nodePromise) Fail(err error) {
318 np.err <- err
319 }
320
309 -func (np *nodePromise) Send(nd *Node) {
321 +func (np *nodePromise) Send(nd Node) {
322 var already bool
323 np.clk.Lock()
324 if np.cache != nil {
@@ -322,7 +334,7 @@ func (np *nodePromise) Send(nd *Node) {
334 np.recv <- nd
335 }
336
325 -func (np *nodePromise) Get(ctx context.Context) (*Node, error) {
337 +func (np *nodePromise) Get(ctx context.Context) (Node, error) {
338 np.clk.Lock()
339 c := np.cache
340 np.clk.Unlock()
@@ -350,14 +362,9 @@ type Batch struct {
362 MaxSize int
363 }
364
353 -func (t *Batch) Add(nd *Node) (*cid.Cid, error) {
354 - d, err := nd.EncodeProtobuf(false)
355 - if err != nil {
356 - return nil, err
357 - }
358 -
365 +func (t *Batch) Add(nd Node) (*cid.Cid, error) {
366 t.blocks = append(t.blocks, nd)
360 - t.size += len(d)
367 + t.size += len(nd.RawData())
368 if t.size > t.MaxSize {
369 return nd.Cid(), t.Commit()
370 }
@@ -371,10 +378,6 @@ func (t *Batch) Commit() error {
378 return err
379 }
380
374 -func legacyCidFromLink(lnk *Link) *cid.Cid {
375 - return cid.NewCidV0(lnk.Hash)
376 -}
377 -
381 // EnumerateChildren will walk the dag below the given root node and add all
382 // unseen children to the passed in set.
383 // TODO: parallelize to avoid disk latency perf hits?
@@ -386,7 +389,7 @@ func EnumerateChildren(ctx context.Context, ds LinkService, root *cid.Cid, visit
389 return err
390 }
391 for _, lnk := range links {
389 - c := legacyCidFromLink(lnk)
392 + c := lnk.Cid
393 if visit(c) {
394 err = EnumerateChildren(ctx, ds, c, visit, bestEffort)
395 if err != nil {
@@ -432,8 +435,8 @@ func EnumerateChildrenAsync(ctx context.Context, ds DAGService, c *cid.Cid, visi
435 live--
436
437 var cids []*cid.Cid
435 - for _, lnk := range nd.Links {
436 - c := legacyCidFromLink(lnk)
438 + for _, lnk := range nd.Links() {
439 + c := lnk.Cid
440 if visit(c) {
441 live++
442 cids = append(cids, c)
merkledag/merkledag_test.go
+20 -15
@@ -38,13 +38,13 @@ func TestNode(t *testing.T) {
38 t.Error(err)
39 }
40
41 - printn := func(name string, n *Node) {
41 + printn := func(name string, n *ProtoNode) {
42 fmt.Println(">", name)
43 fmt.Println("data:", string(n.Data()))
44
45 fmt.Println("links:")
46 - for _, l := range n.Links {
47 - fmt.Println("-", l.Name, l.Size, l.Hash)
46 + for _, l := range n.Links() {
47 + fmt.Println("-", l.Name, l.Size, l.Cid)
48 }
49
50 e, err := n.EncodeProtobuf(false)
@@ -70,7 +70,7 @@ func TestNode(t *testing.T) {
70 printn("beep boop", n3)
71 }
72
73 -func SubtestNodeStat(t *testing.T, n *Node) {
73 +func SubtestNodeStat(t *testing.T, n *ProtoNode) {
74 enc, err := n.EncodeProtobuf(true)
75 if err != nil {
76 t.Error("n.EncodeProtobuf(true) failed")
@@ -86,7 +86,7 @@ func SubtestNodeStat(t *testing.T, n *Node) {
86 k := n.Key()
87
88 expected := NodeStat{
89 - NumLinks: len(n.Links),
89 + NumLinks: len(n.Links()),
90 BlockSize: len(enc),
91 LinksSize: len(enc) - len(n.Data()), // includes framing.
92 DataSize: len(n.Data()),
@@ -174,7 +174,12 @@ func runBatchFetchTest(t *testing.T, read io.Reader) {
174 }
175 fmt.Println("Got first node back.")
176
177 - read, err := uio.NewDagReader(ctx, first, dagservs[i])
177 + firstpb, ok := first.(*ProtoNode)
178 + if !ok {
179 + errs <- ErrNotProtobuf
180 + }
181 +
182 + read, err := uio.NewDagReader(ctx, firstpb, dagservs[i])
183 if err != nil {
184 errs <- err
185 }
@@ -201,7 +206,7 @@ func runBatchFetchTest(t *testing.T, read io.Reader) {
206 }
207 }
208
204 -func assertCanGet(t *testing.T, ds DAGService, n *Node) {
209 +func assertCanGet(t *testing.T, ds DAGService, n Node) {
210 if _, err := ds.Get(context.Background(), n.Cid()); err != nil {
211 t.Fatal(err)
212 }
@@ -263,13 +268,13 @@ func TestEnumerateChildren(t *testing.T) {
268 t.Fatal(err)
269 }
270
266 - var traverse func(n *Node)
267 - traverse = func(n *Node) {
271 + var traverse func(n Node)
272 + traverse = func(n Node) {
273 // traverse dag and check
269 - for _, lnk := range n.Links {
270 - c := cid.NewCidV0(lnk.Hash)
274 + for _, lnk := range n.Links() {
275 + c := lnk.Cid
276 if !set.Has(c) {
272 - t.Fatal("missing key in set! ", lnk.Hash.B58String())
277 + t.Fatal("missing key in set! ", lnk.Cid.String())
278 }
279 child, err := ds.Get(context.Background(), c)
280 if err != nil {
@@ -286,7 +291,7 @@ func TestFetchFailure(t *testing.T) {
291 ds := dstest.Mock()
292 ds_bad := dstest.Mock()
293
289 - top := new(Node)
294 + top := new(ProtoNode)
295 for i := 0; i < 10; i++ {
296 nd := NodeWithData([]byte{byte('a' + i)})
297 _, err := ds.Add(nd)
@@ -345,13 +350,13 @@ func TestUnmarshalFailure(t *testing.T) {
350 t.Fatal("should have failed to parse node with bad link")
351 }
352
348 - n := &Node{}
353 + n := &ProtoNode{}
354 n.Marshal()
355 }
356
357 func TestBasicAddGet(t *testing.T) {
358 ds := dstest.Mock()
354 - nd := new(Node)
359 + nd := new(ProtoNode)
360
361 c, err := ds.Add(nd)
362 if err != nil {
merkledag/node.go
+85 -42
@@ -14,8 +14,8 @@ var ErrLinkNotFound = fmt.Errorf("no link by that name")
14
15 // Node represents a node in the IPFS Merkle DAG.
16 // nodes have opaque data and a set of navigable links.
17 -type Node struct {
18 - Links []*Link
17 +type ProtoNode struct {
18 + links []*Link
19 data []byte
20
21 // cache encoded/marshaled value
@@ -48,7 +48,7 @@ type Link struct {
48 Size uint64
49
50 // multihash of the target object
51 - Hash mh.Multihash
51 + Cid *cid.Cid
52 }
53
54 type LinkSlice []*Link
@@ -58,31 +58,29 @@ func (ls LinkSlice) Swap(a, b int) { ls[a], ls[b] = ls[b], ls[a] }
58 func (ls LinkSlice) Less(a, b int) bool { return ls[a].Name < ls[b].Name }
59
60 // MakeLink creates a link to the given node
61 -func MakeLink(n *Node) (*Link, error) {
61 +func MakeLink(n Node) (*Link, error) {
62 s, err := n.Size()
63 if err != nil {
64 return nil, err
65 }
66
67 - h := n.Multihash()
68 -
67 return &Link{
68 Size: s,
71 - Hash: h,
69 + Cid: n.Cid(),
70 }, nil
71 }
72
73 // GetNode returns the MDAG Node that this link points to
76 -func (l *Link) GetNode(ctx context.Context, serv DAGService) (*Node, error) {
77 - return serv.Get(ctx, legacyCidFromLink(l))
74 +func (l *Link) GetNode(ctx context.Context, serv DAGService) (Node, error) {
75 + return serv.Get(ctx, l.Cid)
76 }
77
80 -func NodeWithData(d []byte) *Node {
81 - return &Node{data: d}
78 +func NodeWithData(d []byte) *ProtoNode {
79 + return &ProtoNode{data: d}
80 }
81
82 // AddNodeLink adds a link to another node.
85 -func (n *Node) AddNodeLink(name string, that *Node) error {
83 +func (n *ProtoNode) AddNodeLink(name string, that *ProtoNode) error {
84 n.encoded = nil
85
86 lnk, err := MakeLink(that)
@@ -99,7 +97,7 @@ func (n *Node) AddNodeLink(name string, that *Node) error {
97
98 // AddNodeLinkClean adds a link to another node. without keeping a reference to
99 // the child node
102 -func (n *Node) AddNodeLinkClean(name string, that *Node) error {
100 +func (n *ProtoNode) AddNodeLinkClean(name string, that Node) error {
101 n.encoded = nil
102 lnk, err := MakeLink(that)
103 if err != nil {
@@ -111,31 +109,31 @@ func (n *Node) AddNodeLinkClean(name string, that *Node) error {
109 }
110
111 // AddRawLink adds a copy of a link to this node
114 -func (n *Node) AddRawLink(name string, l *Link) error {
112 +func (n *ProtoNode) AddRawLink(name string, l *Link) error {
113 n.encoded = nil
116 - n.Links = append(n.Links, &Link{
114 + n.links = append(n.links, &Link{
115 Name: name,
116 Size: l.Size,
119 - Hash: l.Hash,
117 + Cid: l.Cid,
118 })
119
120 return nil
121 }
122
123 // Remove a link on this node by the given name
126 -func (n *Node) RemoveNodeLink(name string) error {
124 +func (n *ProtoNode) RemoveNodeLink(name string) error {
125 n.encoded = nil
128 - good := make([]*Link, 0, len(n.Links))
126 + good := make([]*Link, 0, len(n.links))
127 var found bool
128
131 - for _, l := range n.Links {
129 + for _, l := range n.links {
130 if l.Name != name {
131 good = append(good, l)
132 } else {
133 found = true
134 }
135 }
138 - n.Links = good
136 + n.links = good
137
138 if !found {
139 return ErrNotFound
@@ -145,20 +143,36 @@ func (n *Node) RemoveNodeLink(name string) error {
143 }
144
145 // Return a copy of the link with given name
148 -func (n *Node) GetNodeLink(name string) (*Link, error) {
149 - for _, l := range n.Links {
146 +func (n *ProtoNode) GetNodeLink(name string) (*Link, error) {
147 + for _, l := range n.links {
148 if l.Name == name {
149 return &Link{
150 Name: l.Name,
151 Size: l.Size,
154 - Hash: l.Hash,
152 + Cid: l.Cid,
153 }, nil
154 }
155 }
156 return nil, ErrLinkNotFound
157 }
158
161 -func (n *Node) GetLinkedNode(ctx context.Context, ds DAGService, name string) (*Node, error) {
159 +var ErrNotProtobuf = fmt.Errorf("expected protobuf dag node")
160 +
161 +func (n *ProtoNode) GetLinkedProtoNode(ctx context.Context, ds DAGService, name string) (*ProtoNode, error) {
162 + nd, err := n.GetLinkedNode(ctx, ds, name)
163 + if err != nil {
164 + return nil, err
165 + }
166 +
167 + pbnd, ok := nd.(*ProtoNode)
168 + if !ok {
169 + return nil, ErrNotProtobuf
170 + }
171 +
172 + return pbnd, nil
173 +}
174 +
175 +func (n *ProtoNode) GetLinkedNode(ctx context.Context, ds DAGService, name string) (Node, error) {
176 lnk, err := n.GetNodeLink(name)
177 if err != nil {
178 return nil, err
@@ -169,30 +183,30 @@ func (n *Node) GetLinkedNode(ctx context.Context, ds DAGService, name string) (*
183
184 // Copy returns a copy of the node.
185 // NOTE: Does not make copies of Node objects in the links.
172 -func (n *Node) Copy() *Node {
173 - nnode := new(Node)
186 +func (n *ProtoNode) Copy() *ProtoNode {
187 + nnode := new(ProtoNode)
188 if len(n.data) > 0 {
189 nnode.data = make([]byte, len(n.data))
190 copy(nnode.data, n.data)
191 }
192
179 - if len(n.Links) > 0 {
180 - nnode.Links = make([]*Link, len(n.Links))
181 - copy(nnode.Links, n.Links)
193 + if len(n.links) > 0 {
194 + nnode.links = make([]*Link, len(n.links))
195 + copy(nnode.links, n.links)
196 }
197 return nnode
198 }
199
186 -func (n *Node) RawData() []byte {
200 +func (n *ProtoNode) RawData() []byte {
201 out, _ := n.EncodeProtobuf(false)
202 return out
203 }
204
191 -func (n *Node) Data() []byte {
205 +func (n *ProtoNode) Data() []byte {
206 return n.data
207 }
208
195 -func (n *Node) SetData(d []byte) {
209 +func (n *ProtoNode) SetData(d []byte) {
210 n.encoded = nil
211 n.cached = nil
212 n.data = d
@@ -200,7 +214,7 @@ func (n *Node) SetData(d []byte) {
214
215 // UpdateNodeLink return a copy of the node with the link name set to point to
216 // that. If a link of the same name existed, it is removed.
203 -func (n *Node) UpdateNodeLink(name string, that *Node) (*Node, error) {
217 +func (n *ProtoNode) UpdateNodeLink(name string, that *ProtoNode) (*ProtoNode, error) {
218 newnode := n.Copy()
219 err := newnode.RemoveNodeLink(name)
220 err = nil // ignore error
@@ -210,21 +224,21 @@ func (n *Node) UpdateNodeLink(name string, that *Node) (*Node, error) {
224
225 // Size returns the total size of the data addressed by node,
226 // including the total sizes of references.
213 -func (n *Node) Size() (uint64, error) {
227 +func (n *ProtoNode) Size() (uint64, error) {
228 b, err := n.EncodeProtobuf(false)
229 if err != nil {
230 return 0, err
231 }
232
233 s := uint64(len(b))
220 - for _, l := range n.Links {
234 + for _, l := range n.links {
235 s += l.Size
236 }
237 return s, nil
238 }
239
240 // Stat returns statistics on the node.
227 -func (n *Node) Stat() (*NodeStat, error) {
241 +func (n *ProtoNode) Stat() (*NodeStat, error) {
242 enc, err := n.EncodeProtobuf(false)
243 if err != nil {
244 return nil, err
@@ -237,7 +251,7 @@ func (n *Node) Stat() (*NodeStat, error) {
251
252 return &NodeStat{
253 Hash: n.Key().B58String(),
240 - NumLinks: len(n.Links),
254 + NumLinks: len(n.links),
255 BlockSize: len(enc),
256 LinksSize: len(enc) - len(n.data), // includes framing.
257 DataSize: len(n.data),
@@ -245,28 +259,28 @@ func (n *Node) Stat() (*NodeStat, error) {
259 }, nil
260 }
261
248 -func (n *Node) Key() key.Key {
262 +func (n *ProtoNode) Key() key.Key {
263 return key.Key(n.Multihash())
264 }
265
252 -func (n *Node) Loggable() map[string]interface{} {
266 +func (n *ProtoNode) Loggable() map[string]interface{} {
267 return map[string]interface{}{
268 "node": n.String(),
269 }
270 }
271
258 -func (n *Node) Cid() *cid.Cid {
272 +func (n *ProtoNode) Cid() *cid.Cid {
273 h := n.Multihash()
274
275 return cid.NewCidV0(h)
276 }
277
264 -func (n *Node) String() string {
278 +func (n *ProtoNode) String() string {
279 return n.Cid().String()
280 }
281
282 // Multihash hashes the encoded data of this node.
269 -func (n *Node) Multihash() mh.Multihash {
283 +func (n *ProtoNode) Multihash() mh.Multihash {
284 // NOTE: EncodeProtobuf generates the hash and puts it in n.cached.
285 _, err := n.EncodeProtobuf(false)
286 if err != nil {
@@ -276,3 +290,32 @@ func (n *Node) Multihash() mh.Multihash {
290
291 return n.cached.Hash()
292 }
293 +
294 +func (n *ProtoNode) Links() []*Link {
295 + return n.links
296 +}
297 +
298 +func (n *ProtoNode) SetLinks(links []*Link) {
299 + n.links = links
300 +}
301 +
302 +func (n *ProtoNode) Resolve(path []string) (*Link, []string, error) {
303 + if len(path) == 0 {
304 + return nil, nil, fmt.Errorf("end of path, no more links to resolve")
305 + }
306 +
307 + lnk, err := n.GetNodeLink(path[0])
308 + if err != nil {
309 + return nil, nil, err
310 + }
311 +
312 + return lnk, path[1:], nil
313 +}
314 +
315 +func (n *ProtoNode) Tree() []string {
316 + out := make([]string, 0, len(n.links))
317 + for _, lnk := range n.links {
318 + out = append(out, lnk.Name)
319 + }
320 + return out
321 +}
merkledag/node_test.go
+30 -32
@@ -10,31 +10,30 @@ import (
10 )
11
12 func TestRemoveLink(t *testing.T) {
13 - nd := &Node{
14 - Links: []*Link{
15 - &Link{Name: "a"},
16 - &Link{Name: "b"},
17 - &Link{Name: "a"},
18 - &Link{Name: "a"},
19 - &Link{Name: "c"},
20 - &Link{Name: "a"},
21 - },
22 - }
13 + nd := &ProtoNode{}
14 + nd.SetLinks([]*Link{
15 + &Link{Name: "a"},
16 + &Link{Name: "b"},
17 + &Link{Name: "a"},
18 + &Link{Name: "a"},
19 + &Link{Name: "c"},
20 + &Link{Name: "a"},
21 + })
22
23 err := nd.RemoveNodeLink("a")
24 if err != nil {
25 t.Fatal(err)
26 }
27
29 - if len(nd.Links) != 2 {
28 + if len(nd.Links()) != 2 {
29 t.Fatal("number of links incorrect")
30 }
31
33 - if nd.Links[0].Name != "b" {
32 + if nd.Links()[0].Name != "b" {
33 t.Fatal("link order wrong")
34 }
35
37 - if nd.Links[1].Name != "c" {
36 + if nd.Links()[1].Name != "c" {
37 t.Fatal("link order wrong")
38 }
39
@@ -45,33 +44,32 @@ func TestRemoveLink(t *testing.T) {
44 }
45
46 // ensure nothing else got touched
48 - if len(nd.Links) != 2 {
47 + if len(nd.Links()) != 2 {
48 t.Fatal("number of links incorrect")
49 }
50
52 - if nd.Links[0].Name != "b" {
51 + if nd.Links()[0].Name != "b" {
52 t.Fatal("link order wrong")
53 }
54
56 - if nd.Links[1].Name != "c" {
55 + if nd.Links()[1].Name != "c" {
56 t.Fatal("link order wrong")
57 }
58 }
59
60 func TestFindLink(t *testing.T) {
61 ds := mdtest.Mock()
63 - k, err := ds.Add(new(Node))
62 + k, err := ds.Add(new(ProtoNode))
63 if err != nil {
64 t.Fatal(err)
65 }
66
68 - nd := &Node{
69 - Links: []*Link{
70 - &Link{Name: "a", Hash: k.Hash()},
71 - &Link{Name: "c", Hash: k.Hash()},
72 - &Link{Name: "b", Hash: k.Hash()},
73 - },
74 - }
67 + nd := &ProtoNode{}
68 + nd.SetLinks([]*Link{
69 + &Link{Name: "a", Cid: k},
70 + &Link{Name: "c", Cid: k},
71 + &Link{Name: "b", Cid: k},
72 + })
73
74 _, err = ds.Add(nd)
75 if err != nil {
@@ -107,19 +105,19 @@ func TestFindLink(t *testing.T) {
105 t.Fatal(err)
106 }
107
110 - if olnk.Hash.B58String() == k.String() {
108 + if olnk.Cid.String() == k.String() {
109 t.Fatal("new link should have different hash")
110 }
111 }
112
113 func TestNodeCopy(t *testing.T) {
116 - nd := &Node{
117 - Links: []*Link{
118 - &Link{Name: "a"},
119 - &Link{Name: "c"},
120 - &Link{Name: "b"},
121 - },
122 - }
114 + nd := &ProtoNode{}
115 + nd.SetLinks([]*Link{
116 + &Link{Name: "a"},
117 + &Link{Name: "c"},
118 + &Link{Name: "b"},
119 + })
120 +
121 nd.SetData([]byte("testing"))
122
123 ond := nd.Copy()
merkledag/traverse/traverse.go
+10 -10
@@ -30,7 +30,7 @@ type Options struct {
30
31 // State is a current traversal state
32 type State struct {
33 - Node *mdag.Node
33 + Node mdag.Node
34 Depth int
35 }
36
@@ -39,13 +39,13 @@ type traversal struct {
39 seen map[string]struct{}
40 }
41
42 -func (t *traversal) shouldSkip(n *mdag.Node) (bool, error) {
42 +func (t *traversal) shouldSkip(n mdag.Node) (bool, error) {
43 if t.opts.SkipDuplicates {
44 - k := n.Key()
45 - if _, found := t.seen[string(k)]; found {
44 + k := n.Cid()
45 + if _, found := t.seen[k.KeyString()]; found {
46 return true, nil
47 }
48 - t.seen[string(k)] = struct{}{}
48 + t.seen[k.KeyString()] = struct{}{}
49 }
50
51 return false, nil
@@ -59,9 +59,9 @@ func (t *traversal) callFunc(next State) error {
59 // stop processing. if it returns a nil node, just skip it.
60 //
61 // the error handling is a little complicated.
62 -func (t *traversal) getNode(link *mdag.Link) (*mdag.Node, error) {
62 +func (t *traversal) getNode(link *mdag.Link) (mdag.Node, error) {
63
64 - getNode := func(l *mdag.Link) (*mdag.Node, error) {
64 + getNode := func(l *mdag.Link) (mdag.Node, error) {
65 next, err := l.GetNode(context.TODO(), t.opts.DAG)
66 if err != nil {
67 return nil, err
@@ -99,7 +99,7 @@ type Func func(current State) error
99 //
100 type ErrFunc func(err error) error
101
102 -func Traverse(root *mdag.Node, o Options) error {
102 +func Traverse(root mdag.Node, o Options) error {
103 t := traversal{
104 opts: o,
105 seen: map[string]struct{}{},
@@ -145,7 +145,7 @@ func dfsPostTraverse(state State, t *traversal) error {
145 }
146
147 func dfsDescend(df dfsFunc, curr State, t *traversal) error {
148 - for _, l := range curr.Node.Links {
148 + for _, l := range curr.Node.Links() {
149 node, err := t.getNode(l)
150 if err != nil {
151 return err
@@ -184,7 +184,7 @@ func bfsTraverse(root State, t *traversal) error {
184 return err
185 }
186
187 - for _, l := range curr.Node.Links {
187 + for _, l := range curr.Node.Links() {
188 node, err := t.getNode(l)
189 if err != nil {
190 return err
merkledag/traverse/traverse_test.go
+11 -11
@@ -321,12 +321,12 @@ func TestBFSSkip(t *testing.T) {
321 `))
322 }
323
324 -func testWalkOutputs(t *testing.T, root *mdag.Node, opts Options, expect []byte) {
324 +func testWalkOutputs(t *testing.T, root mdag.Node, opts Options, expect []byte) {
325 expect = bytes.TrimLeft(expect, "\n")
326
327 buf := new(bytes.Buffer)
328 walk := func(current State) error {
329 - s := fmt.Sprintf("%d %s\n", current.Depth, current.Node.Data())
329 + s := fmt.Sprintf("%d %s\n", current.Depth, current.Node.(*mdag.ProtoNode).Data())
330 t.Logf("walk: %s", s)
331 buf.Write([]byte(s))
332 return nil
@@ -348,7 +348,7 @@ func testWalkOutputs(t *testing.T, root *mdag.Node, opts Options, expect []byte)
348 }
349 }
350
351 -func newFan(t *testing.T, ds mdag.DAGService) *mdag.Node {
351 +func newFan(t *testing.T, ds mdag.DAGService) mdag.Node {
352 a := mdag.NodeWithData([]byte("/a"))
353 addLink(t, ds, a, child(t, ds, a, "aa"))
354 addLink(t, ds, a, child(t, ds, a, "ab"))
@@ -357,7 +357,7 @@ func newFan(t *testing.T, ds mdag.DAGService) *mdag.Node {
357 return a
358 }
359
360 -func newLinkedList(t *testing.T, ds mdag.DAGService) *mdag.Node {
360 +func newLinkedList(t *testing.T, ds mdag.DAGService) mdag.Node {
361 a := mdag.NodeWithData([]byte("/a"))
362 aa := child(t, ds, a, "aa")
363 aaa := child(t, ds, aa, "aaa")
@@ -370,7 +370,7 @@ func newLinkedList(t *testing.T, ds mdag.DAGService) *mdag.Node {
370 return a
371 }
372
373 -func newBinaryTree(t *testing.T, ds mdag.DAGService) *mdag.Node {
373 +func newBinaryTree(t *testing.T, ds mdag.DAGService) mdag.Node {
374 a := mdag.NodeWithData([]byte("/a"))
375 aa := child(t, ds, a, "aa")
376 ab := child(t, ds, a, "ab")
@@ -383,7 +383,7 @@ func newBinaryTree(t *testing.T, ds mdag.DAGService) *mdag.Node {
383 return a
384 }
385
386 -func newBinaryDAG(t *testing.T, ds mdag.DAGService) *mdag.Node {
386 +func newBinaryDAG(t *testing.T, ds mdag.DAGService) mdag.Node {
387 a := mdag.NodeWithData([]byte("/a"))
388 aa := child(t, ds, a, "aa")
389 aaa := child(t, ds, aa, "aaa")
@@ -400,16 +400,16 @@ func newBinaryDAG(t *testing.T, ds mdag.DAGService) *mdag.Node {
400 return a
401 }
402
403 -func addLink(t *testing.T, ds mdag.DAGService, a, b *mdag.Node) {
404 - to := string(a.Data()) + "2" + string(b.Data())
403 +func addLink(t *testing.T, ds mdag.DAGService, a, b mdag.Node) {
404 + to := string(a.(*mdag.ProtoNode).Data()) + "2" + string(b.(*mdag.ProtoNode).Data())
405 if _, err := ds.Add(b); err != nil {
406 t.Error(err)
407 }
408 - if err := a.AddNodeLink(to, b); err != nil {
408 + if err := a.(*mdag.ProtoNode).AddNodeLink(to, b.(*mdag.ProtoNode)); err != nil {
409 t.Error(err)
410 }
411 }
412
413 -func child(t *testing.T, ds mdag.DAGService, a *mdag.Node, name string) *mdag.Node {
414 - return mdag.NodeWithData([]byte(string(a.Data()) + "/" + name))
413 +func child(t *testing.T, ds mdag.DAGService, a mdag.Node, name string) mdag.Node {
414 + return mdag.NodeWithData([]byte(string(a.(*mdag.ProtoNode).Data()) + "/" + name))
415 }
merkledag/utils/diff.go
+34 -13
@@ -1,7 +1,6 @@
1 package dagutils
2
3 import (
4 - "bytes"
4 "fmt"
5 "path"
6
@@ -37,7 +36,7 @@ func (c *Change) String() string {
36 }
37 }
38
40 -func ApplyChange(ctx context.Context, ds dag.DAGService, nd *dag.Node, cs []*Change) (*dag.Node, error) {
39 +func ApplyChange(ctx context.Context, ds dag.DAGService, nd *dag.ProtoNode, cs []*Change) (*dag.ProtoNode, error) {
40 e := NewDagEditor(nd, ds)
41 for _, c := range cs {
42 switch c.Type {
@@ -46,7 +45,13 @@ func ApplyChange(ctx context.Context, ds dag.DAGService, nd *dag.Node, cs []*Cha
45 if err != nil {
46 return nil, err
47 }
49 - err = e.InsertNodeAtPath(ctx, c.Path, child, nil)
48 +
49 + childpb, ok := child.(*dag.ProtoNode)
50 + if !ok {
51 + return nil, dag.ErrNotProtobuf
52 + }
53 +
54 + err = e.InsertNodeAtPath(ctx, c.Path, childpb, nil)
55 if err != nil {
56 return nil, err
57 }
@@ -66,7 +71,13 @@ func ApplyChange(ctx context.Context, ds dag.DAGService, nd *dag.Node, cs []*Cha
71 if err != nil {
72 return nil, err
73 }
69 - err = e.InsertNodeAtPath(ctx, c.Path, child, nil)
74 +
75 + childpb, ok := child.(*dag.ProtoNode)
76 + if !ok {
77 + return nil, dag.ErrNotProtobuf
78 + }
79 +
80 + err = e.InsertNodeAtPath(ctx, c.Path, childpb, nil)
81 if err != nil {
82 return nil, err
83 }
@@ -76,8 +87,8 @@ func ApplyChange(ctx context.Context, ds dag.DAGService, nd *dag.Node, cs []*Cha
87 return e.Finalize(ds)
88 }
89
79 -func Diff(ctx context.Context, ds dag.DAGService, a, b *dag.Node) ([]*Change, error) {
80 - if len(a.Links) == 0 && len(b.Links) == 0 {
90 +func Diff(ctx context.Context, ds dag.DAGService, a, b *dag.ProtoNode) ([]*Change, error) {
91 + if len(a.Links()) == 0 && len(b.Links()) == 0 {
92 return []*Change{
93 &Change{
94 Type: Mod,
@@ -92,10 +103,10 @@ func Diff(ctx context.Context, ds dag.DAGService, a, b *dag.Node) ([]*Change, er
103 clean_b := b.Copy()
104
105 // strip out unchanged stuff
95 - for _, lnk := range a.Links {
106 + for _, lnk := range a.Links() {
107 l, err := b.GetNodeLink(lnk.Name)
108 if err == nil {
98 - if bytes.Equal(l.Hash, lnk.Hash) {
109 + if l.Cid.Equals(lnk.Cid) {
110 // no change... ignore it
111 } else {
112 anode, err := lnk.GetNode(ctx, ds)
@@ -108,7 +119,17 @@ func Diff(ctx context.Context, ds dag.DAGService, a, b *dag.Node) ([]*Change, er
119 return nil, err
120 }
121
111 - sub, err := Diff(ctx, ds, anode, bnode)
122 + anodepb, ok := anode.(*dag.ProtoNode)
123 + if !ok {
124 + return nil, dag.ErrNotProtobuf
125 + }
126 +
127 + bnodepb, ok := bnode.(*dag.ProtoNode)
128 + if !ok {
129 + return nil, dag.ErrNotProtobuf
130 + }
131 +
132 + sub, err := Diff(ctx, ds, anodepb, bnodepb)
133 if err != nil {
134 return nil, err
135 }
@@ -123,18 +144,18 @@ func Diff(ctx context.Context, ds dag.DAGService, a, b *dag.Node) ([]*Change, er
144 }
145 }
146
126 - for _, lnk := range clean_a.Links {
147 + for _, lnk := range clean_a.Links() {
148 out = append(out, &Change{
149 Type: Remove,
150 Path: lnk.Name,
130 - Before: cid.NewCidV0(lnk.Hash),
151 + Before: lnk.Cid,
152 })
153 }
133 - for _, lnk := range clean_b.Links {
154 + for _, lnk := range clean_b.Links() {
155 out = append(out, &Change{
156 Type: Add,
157 Path: lnk.Name,
137 - After: cid.NewCidV0(lnk.Hash),
158 + After: lnk.Cid,
159 })
160 }
161
merkledag/utils/utils.go
+20 -15
@@ -15,7 +15,7 @@ import (
15 )
16
17 type Editor struct {
18 - root *dag.Node
18 + root *dag.ProtoNode
19
20 // tmp is a temporary in memory (for now) dagstore for all of the
21 // intermediary nodes to be stored in
@@ -34,7 +34,7 @@ func NewMemoryDagService() dag.DAGService {
34 }
35
36 // root is the node to be modified, source is the dagstore to pull nodes from (optional)
37 -func NewDagEditor(root *dag.Node, source dag.DAGService) *Editor {
37 +func NewDagEditor(root *dag.ProtoNode, source dag.DAGService) *Editor {
38 return &Editor{
39 root: root,
40 tmp: NewMemoryDagService(),
@@ -42,7 +42,7 @@ func NewDagEditor(root *dag.Node, source dag.DAGService) *Editor {
42 }
43 }
44
45 -func (e *Editor) GetNode() *dag.Node {
45 +func (e *Editor) GetNode() *dag.ProtoNode {
46 return e.root.Copy()
47 }
48
@@ -50,7 +50,7 @@ func (e *Editor) GetDagService() dag.DAGService {
50 return e.tmp
51 }
52
53 -func addLink(ctx context.Context, ds dag.DAGService, root *dag.Node, childname string, childnd *dag.Node) (*dag.Node, error) {
53 +func addLink(ctx context.Context, ds dag.DAGService, root *dag.ProtoNode, childname string, childnd *dag.ProtoNode) (*dag.ProtoNode, error) {
54 if childname == "" {
55 return nil, errors.New("cannot create link with no name!")
56 }
@@ -76,7 +76,7 @@ func addLink(ctx context.Context, ds dag.DAGService, root *dag.Node, childname s
76 return root, nil
77 }
78
79 -func (e *Editor) InsertNodeAtPath(ctx context.Context, pth string, toinsert *dag.Node, create func() *dag.Node) error {
79 +func (e *Editor) InsertNodeAtPath(ctx context.Context, pth string, toinsert *dag.ProtoNode, create func() *dag.ProtoNode) error {
80 splpath := path.SplitList(pth)
81 nd, err := e.insertNodeAtPath(ctx, e.root, splpath, toinsert, create)
82 if err != nil {
@@ -86,12 +86,12 @@ func (e *Editor) InsertNodeAtPath(ctx context.Context, pth string, toinsert *dag
86 return nil
87 }
88
89 -func (e *Editor) insertNodeAtPath(ctx context.Context, root *dag.Node, path []string, toinsert *dag.Node, create func() *dag.Node) (*dag.Node, error) {
89 +func (e *Editor) insertNodeAtPath(ctx context.Context, root *dag.ProtoNode, path []string, toinsert *dag.ProtoNode, create func() *dag.ProtoNode) (*dag.ProtoNode, error) {
90 if len(path) == 1 {
91 return addLink(ctx, e.tmp, root, path[0], toinsert)
92 }
93
94 - nd, err := root.GetLinkedNode(ctx, e.tmp, path[0])
94 + nd, err := root.GetLinkedProtoNode(ctx, e.tmp, path[0])
95 if err != nil {
96 // if 'create' is true, we create directories on the way down as needed
97 if err == dag.ErrLinkNotFound && create != nil {
@@ -99,7 +99,7 @@ func (e *Editor) insertNodeAtPath(ctx context.Context, root *dag.Node, path []st
99 err = nil // no longer an error case
100 } else if err == dag.ErrNotFound {
101 // try finding it in our source dagstore
102 - nd, err = root.GetLinkedNode(ctx, e.src, path[0])
102 + nd, err = root.GetLinkedProtoNode(ctx, e.src, path[0])
103 }
104
105 // if we receive an ErrNotFound, then our second 'GetLinkedNode' call
@@ -140,7 +140,7 @@ func (e *Editor) RmLink(ctx context.Context, pth string) error {
140 return nil
141 }
142
143 -func (e *Editor) rmLink(ctx context.Context, root *dag.Node, path []string) (*dag.Node, error) {
143 +func (e *Editor) rmLink(ctx context.Context, root *dag.ProtoNode, path []string) (*dag.ProtoNode, error) {
144 if len(path) == 1 {
145 // base case, remove node in question
146 err := root.RemoveNodeLink(path[0])
@@ -157,9 +157,9 @@ func (e *Editor) rmLink(ctx context.Context, root *dag.Node, path []string) (*da
157 }
158
159 // search for node in both tmp dagstore and source dagstore
160 - nd, err := root.GetLinkedNode(ctx, e.tmp, path[0])
160 + nd, err := root.GetLinkedProtoNode(ctx, e.tmp, path[0])
161 if err == dag.ErrNotFound {
162 - nd, err = root.GetLinkedNode(ctx, e.src, path[0])
162 + nd, err = root.GetLinkedProtoNode(ctx, e.src, path[0])
163 }
164
165 if err != nil {
@@ -187,19 +187,19 @@ func (e *Editor) rmLink(ctx context.Context, root *dag.Node, path []string) (*da
187 return root, nil
188 }
189
190 -func (e *Editor) Finalize(ds dag.DAGService) (*dag.Node, error) {
190 +func (e *Editor) Finalize(ds dag.DAGService) (*dag.ProtoNode, error) {
191 nd := e.GetNode()
192 err := copyDag(nd, e.tmp, ds)
193 return nd, err
194 }
195
196 -func copyDag(nd *dag.Node, from, to dag.DAGService) error {
196 +func copyDag(nd *dag.ProtoNode, from, to dag.DAGService) error {
197 _, err := to.Add(nd)
198 if err != nil {
199 return err
200 }
201
202 - for _, lnk := range nd.Links {
202 + for _, lnk := range nd.Links() {
203 child, err := lnk.GetNode(context.Background(), from)
204 if err != nil {
205 if err == dag.ErrNotFound {
@@ -210,7 +210,12 @@ func copyDag(nd *dag.Node, from, to dag.DAGService) error {
210 return err
211 }
212
213 - err = copyDag(child, from, to)
213 + childpb, ok := child.(*dag.ProtoNode)
214 + if !ok {
215 + return dag.ErrNotProtobuf
216 + }
217 +
218 + err = copyDag(childpb, from, to)
219 if err != nil {
220 return err
221 }
merkledag/utils/utils_test.go
+7 -7
@@ -20,7 +20,7 @@ func TestAddLink(t *testing.T) {
20 t.Fatal(err)
21 }
22
23 - nd := new(dag.Node)
23 + nd := new(dag.ProtoNode)
24 nnode, err := addLink(context.Background(), ds, nd, "fish", fishnode)
25 if err != nil {
26 t.Fatal(err)
@@ -37,11 +37,11 @@ func TestAddLink(t *testing.T) {
37 }
38 }
39
40 -func assertNodeAtPath(t *testing.T, ds dag.DAGService, root *dag.Node, pth string, exp *cid.Cid) {
40 +func assertNodeAtPath(t *testing.T, ds dag.DAGService, root *dag.ProtoNode, pth string, exp *cid.Cid) {
41 parts := path.SplitList(pth)
42 cur := root
43 for _, e := range parts {
44 - nxt, err := cur.GetLinkedNode(context.Background(), ds, e)
44 + nxt, err := cur.GetLinkedProtoNode(context.Background(), ds, e)
45 if err != nil {
46 t.Fatal(err)
47 }
@@ -56,7 +56,7 @@ func assertNodeAtPath(t *testing.T, ds dag.DAGService, root *dag.Node, pth strin
56 }
57
58 func TestInsertNode(t *testing.T) {
59 - root := new(dag.Node)
59 + root := new(dag.ProtoNode)
60 e := NewDagEditor(root, nil)
61
62 testInsert(t, e, "a", "anodefortesting", false, "")
@@ -83,10 +83,10 @@ func testInsert(t *testing.T, e *Editor, path, data string, create bool, experr
83 t.Fatal(err)
84 }
85
86 - var c func() *dag.Node
86 + var c func() *dag.ProtoNode
87 if create {
88 - c = func() *dag.Node {
89 - return &dag.Node{}
88 + c = func() *dag.ProtoNode {
89 + return &dag.ProtoNode{}
90 }
91 }
92
mfs/dir.go
+21 -19
@@ -28,7 +28,7 @@ type Directory struct {
28 files map[string]*File
29
30 lock sync.Mutex
31 - node *dag.Node
31 + node *dag.ProtoNode
32 ctx context.Context
33
34 modTime time.Time
@@ -36,7 +36,7 @@ type Directory struct {
36 name string
37 }
38
39 -func NewDirectory(ctx context.Context, name string, node *dag.Node, parent childCloser, dserv dag.DAGService) *Directory {
39 +func NewDirectory(ctx context.Context, name string, node *dag.ProtoNode, parent childCloser, dserv dag.DAGService) *Directory {
40 return &Directory{
41 dserv: dserv,
42 ctx: ctx,
@@ -51,7 +51,7 @@ func NewDirectory(ctx context.Context, name string, node *dag.Node, parent child
51
52 // closeChild updates the child by the given name to the dag node 'nd'
53 // and changes its own dag node
54 -func (d *Directory) closeChild(name string, nd *dag.Node, sync bool) error {
54 +func (d *Directory) closeChild(name string, nd *dag.ProtoNode, sync bool) error {
55 mynd, err := d.closeChildUpdate(name, nd, sync)
56 if err != nil {
57 return err
@@ -64,7 +64,7 @@ func (d *Directory) closeChild(name string, nd *dag.Node, sync bool) error {
64 }
65
66 // closeChildUpdate is the portion of closeChild that needs to be locked around
67 -func (d *Directory) closeChildUpdate(name string, nd *dag.Node, sync bool) (*dag.Node, error) {
67 +func (d *Directory) closeChildUpdate(name string, nd *dag.ProtoNode, sync bool) (*dag.ProtoNode, error) {
68 d.lock.Lock()
69 defer d.lock.Unlock()
70
@@ -79,7 +79,7 @@ func (d *Directory) closeChildUpdate(name string, nd *dag.Node, sync bool) (*dag
79 return nil, nil
80 }
81
82 -func (d *Directory) flushCurrentNode() (*dag.Node, error) {
82 +func (d *Directory) flushCurrentNode() (*dag.ProtoNode, error) {
83 _, err := d.dserv.Add(d.node)
84 if err != nil {
85 return nil, err
@@ -88,7 +88,7 @@ func (d *Directory) flushCurrentNode() (*dag.Node, error) {
88 return d.node.Copy(), nil
89 }
90
91 -func (d *Directory) updateChild(name string, nd *dag.Node) error {
91 +func (d *Directory) updateChild(name string, nd *dag.ProtoNode) error {
92 err := d.node.RemoveNodeLink(name)
93 if err != nil && err != dag.ErrNotFound {
94 return err
@@ -120,7 +120,7 @@ func (d *Directory) childNode(name string) (FSNode, error) {
120 }
121
122 // cacheNode caches a node into d.childDirs or d.files and returns the FSNode.
123 -func (d *Directory) cacheNode(name string, nd *dag.Node) (FSNode, error) {
123 +func (d *Directory) cacheNode(name string, nd *dag.ProtoNode) (FSNode, error) {
124 i, err := ft.FromBytes(nd.Data())
125 if err != nil {
126 return nil, err
@@ -161,14 +161,16 @@ func (d *Directory) Uncache(name string) {
161
162 // childFromDag searches through this directories dag node for a child link
163 // with the given name
164 -func (d *Directory) childFromDag(name string) (*dag.Node, error) {
165 - for _, lnk := range d.node.Links {
166 - if lnk.Name == name {
167 - return lnk.GetNode(d.ctx, d.dserv)
168 - }
164 +func (d *Directory) childFromDag(name string) (*dag.ProtoNode, error) {
165 + pbn, err := d.node.GetLinkedProtoNode(d.ctx, d.dserv, name)
166 + switch err {
167 + case nil:
168 + return pbn, nil
169 + case dag.ErrLinkNotFound:
170 + return nil, os.ErrNotExist
171 + default:
172 + return nil, err
173 }
170 -
171 - return nil, os.ErrNotExist
174 }
175
176 // childUnsync returns the child under this directory by the given name
@@ -206,7 +208,7 @@ func (d *Directory) ListNames() []string {
208 names[n] = struct{}{}
209 }
210
209 - for _, l := range d.node.Links {
211 + for _, l := range d.node.Links() {
212 names[l.Name] = struct{}{}
213 }
214
@@ -224,7 +226,7 @@ func (d *Directory) List() ([]NodeListing, error) {
226 defer d.lock.Unlock()
227
228 var out []NodeListing
227 - for _, l := range d.node.Links {
229 + for _, l := range d.node.Links() {
230 child := NodeListing{}
231 child.Name = l.Name
232
@@ -270,7 +272,7 @@ func (d *Directory) Mkdir(name string) (*Directory, error) {
272 }
273 }
274
273 - ndir := new(dag.Node)
275 + ndir := new(dag.ProtoNode)
276 ndir.SetData(ft.FolderPBData())
277
278 _, err = d.dserv.Add(ndir)
@@ -321,7 +323,7 @@ func (d *Directory) Flush() error {
323 }
324
325 // AddChild adds the node 'nd' under this directory giving it the name 'name'
324 -func (d *Directory) AddChild(name string, nd *dag.Node) error {
326 +func (d *Directory) AddChild(name string, nd *dag.ProtoNode) error {
327 d.lock.Lock()
328 defer d.lock.Unlock()
329
@@ -382,7 +384,7 @@ func (d *Directory) Path() string {
384 return out
385 }
386
385 -func (d *Directory) GetNode() (*dag.Node, error) {
387 +func (d *Directory) GetNode() (*dag.ProtoNode, error) {
388 d.lock.Lock()
389 defer d.lock.Unlock()
390
mfs/file.go
+3 -3
@@ -19,12 +19,12 @@ type File struct {
19 desclock sync.RWMutex
20
21 dserv dag.DAGService
22 - node *dag.Node
22 + node *dag.ProtoNode
23 nodelk sync.Mutex
24 }
25
26 // NewFile returns a NewFile object with the given parameters
27 -func NewFile(name string, node *dag.Node, parent childCloser, dserv dag.DAGService) (*File, error) {
27 +func NewFile(name string, node *dag.ProtoNode, parent childCloser, dserv dag.DAGService) (*File, error) {
28 return &File{
29 dserv: dserv,
30 parent: parent,
@@ -94,7 +94,7 @@ func (fi *File) Size() (int64, error) {
94 }
95
96 // GetNode returns the dag node associated with this file
97 -func (fi *File) GetNode() (*dag.Node, error) {
97 +func (fi *File) GetNode() (*dag.ProtoNode, error) {
98 fi.nodelk.Lock()
99 defer fi.nodelk.Unlock()
100 return fi.node, nil
mfs/mfs_test.go
+11 -11
@@ -30,7 +30,7 @@ import (
30 dssync "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/sync"
31 )
32
33 -func emptyDirNode() *dag.Node {
33 +func emptyDirNode() *dag.ProtoNode {
34 return dag.NodeWithData(ft.FolderPBData())
35 }
36
@@ -41,12 +41,12 @@ func getDagserv(t *testing.T) dag.DAGService {
41 return dag.NewDAGService(blockserv)
42 }
43
44 -func getRandFile(t *testing.T, ds dag.DAGService, size int64) *dag.Node {
44 +func getRandFile(t *testing.T, ds dag.DAGService, size int64) *dag.ProtoNode {
45 r := io.LimitReader(u.NewTimeSeededRand(), size)
46 return fileNodeFromReader(t, ds, r)
47 }
48
49 -func fileNodeFromReader(t *testing.T, ds dag.DAGService, r io.Reader) *dag.Node {
49 +func fileNodeFromReader(t *testing.T, ds dag.DAGService, r io.Reader) *dag.ProtoNode {
50 nd, err := importer.BuildDagFromReader(ds, chunk.DefaultSplitter(r))
51 if err != nil {
52 t.Fatal(err)
@@ -124,7 +124,7 @@ func compStrArrs(a, b []string) bool {
124 return true
125 }
126
127 -func assertFileAtPath(ds dag.DAGService, root *Directory, exp *dag.Node, pth string) error {
127 +func assertFileAtPath(ds dag.DAGService, root *Directory, exp *dag.ProtoNode, pth string) error {
128 parts := path.SplitList(pth)
129 cur := root
130 for i, d := range parts[:len(parts)-1] {
@@ -173,7 +173,7 @@ func assertFileAtPath(ds dag.DAGService, root *Directory, exp *dag.Node, pth str
173 return nil
174 }
175
176 -func catNode(ds dag.DAGService, nd *dag.Node) ([]byte, error) {
176 +func catNode(ds dag.DAGService, nd *dag.ProtoNode) ([]byte, error) {
177 r, err := uio.NewDagReader(context.TODO(), nd, ds)
178 if err != nil {
179 return nil, err
@@ -280,7 +280,7 @@ func TestDirectoryLoadFromDag(t *testing.T) {
280 t.Fatal(err)
281 }
282
283 - fihash := nd.Multihash()
283 + fihash := nd.Cid()
284
285 dir := emptyDirNode()
286 _, err = ds.Add(dir)
@@ -288,19 +288,19 @@ func TestDirectoryLoadFromDag(t *testing.T) {
288 t.Fatal(err)
289 }
290
291 - dirhash := dir.Multihash()
291 + dirhash := dir.Cid()
292
293 top := emptyDirNode()
294 - top.Links = []*dag.Link{
294 + top.SetLinks([]*dag.Link{
295 &dag.Link{
296 Name: "a",
297 - Hash: fihash,
297 + Cid: fihash,
298 },
299 &dag.Link{
300 Name: "b",
301 - Hash: dirhash,
301 + Cid: dirhash,
302 },
303 - }
303 + })
304
305 err = rootdir.AddChild("foo", top)
306 if err != nil {
mfs/ops.go
+1 -1
@@ -87,7 +87,7 @@ func lookupDir(r *Root, path string) (*Directory, error) {
87 }
88
89 // PutNode inserts 'nd' at 'path' in the given mfs
90 -func PutNode(r *Root, path string, nd *dag.Node) error {
90 +func PutNode(r *Root, path string, nd *dag.ProtoNode) error {
91 dirp, filename := gopath.Split(path)
92 if filename == "" {
93 return fmt.Errorf("cannot create file with empty name")
mfs/system.go
+5 -5
@@ -29,7 +29,7 @@ var log = logging.Logger("mfs")
29 var ErrIsDirectory = errors.New("error: is a directory")
30
31 type childCloser interface {
32 - closeChild(string, *dag.Node, bool) error
32 + closeChild(string, *dag.ProtoNode, bool) error
33 }
34
35 type NodeType int
@@ -41,7 +41,7 @@ const (
41
42 // FSNode represents any node (directory, root, or file) in the mfs filesystem
43 type FSNode interface {
44 - GetNode() (*dag.Node, error)
44 + GetNode() (*dag.ProtoNode, error)
45 Flush() error
46 Type() NodeType
47 }
@@ -49,7 +49,7 @@ type FSNode interface {
49 // Root represents the root of a filesystem tree
50 type Root struct {
51 // node is the merkledag root
52 - node *dag.Node
52 + node *dag.ProtoNode
53
54 // val represents the node. It can either be a File or a Directory
55 val FSNode
@@ -64,7 +64,7 @@ type Root struct {
64 type PubFunc func(context.Context, *cid.Cid) error
65
66 // newRoot creates a new Root and starts up a republisher routine for it
67 -func NewRoot(parent context.Context, ds dag.DAGService, node *dag.Node, pf PubFunc) (*Root, error) {
67 +func NewRoot(parent context.Context, ds dag.DAGService, node *dag.ProtoNode, pf PubFunc) (*Root, error) {
68
69 var repub *Republisher
70 if pf != nil {
@@ -118,7 +118,7 @@ func (kr *Root) Flush() error {
118
119 // closeChild implements the childCloser interface, and signals to the publisher that
120 // there are changes ready to be published
121 -func (kr *Root) closeChild(name string, nd *dag.Node, sync bool) error {
121 +func (kr *Root) closeChild(name string, nd *dag.ProtoNode, sync bool) error {
122 c, err := kr.dserv.Add(nd)
123 if err != nil {
124 return err
path/resolver.go
+19 -15
@@ -2,14 +2,13 @@
2 package path
3
4 import (
5 + "context"
6 "errors"
7 "fmt"
8 "time"
9
9 - "context"
10 - mh "gx/ipfs/QmYDds3421prZgqKbLpEK7T9Aa2eVdQ7o3YarX1LVLdP2J/go-multihash"
11 -
10 merkledag "github.com/ipfs/go-ipfs/merkledag"
11 +
12 logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
13 cid "gx/ipfs/QmXUuRadqDq5BuFWzVU6VuKaSjTcNm1gNCtLvvP1TJCW4z/go-cid"
14 )
@@ -23,11 +22,11 @@ var ErrNoComponents = errors.New(
22 // ErrNoLink is returned when a link is not found in a path
23 type ErrNoLink struct {
24 Name string
26 - Node mh.Multihash
25 + Node *cid.Cid
26 }
27
28 func (e ErrNoLink) Error() string {
30 - return fmt.Sprintf("no link named %q under %s", e.Name, e.Node.B58String())
29 + return fmt.Sprintf("no link named %q under %s", e.Name, e.Node.String())
30 }
31
32 // Resolver provides path resolution to IPFS
@@ -62,7 +61,7 @@ func SplitAbsPath(fpath Path) (*cid.Cid, []string, error) {
61
62 // ResolvePath fetches the node for given path. It returns the last item
63 // returned by ResolvePathComponents.
65 -func (s *Resolver) ResolvePath(ctx context.Context, fpath Path) (*merkledag.Node, error) {
64 +func (s *Resolver) ResolvePath(ctx context.Context, fpath Path) (merkledag.Node, error) {
65 // validate path
66 if err := fpath.IsValid(); err != nil {
67 return nil, err
@@ -78,7 +77,7 @@ func (s *Resolver) ResolvePath(ctx context.Context, fpath Path) (*merkledag.Node
77 // ResolvePathComponents fetches the nodes for each segment of the given path.
78 // It uses the first path component as a hash (key) of the first node, then
79 // resolves all other components walking the links, with ResolveLinks.
81 -func (s *Resolver) ResolvePathComponents(ctx context.Context, fpath Path) ([]*merkledag.Node, error) {
80 +func (s *Resolver) ResolvePathComponents(ctx context.Context, fpath Path) ([]merkledag.Node, error) {
81 h, parts, err := SplitAbsPath(fpath)
82 if err != nil {
83 return nil, err
@@ -100,28 +99,33 @@ func (s *Resolver) ResolvePathComponents(ctx context.Context, fpath Path) ([]*me
99 //
100 // ResolveLinks(nd, []string{"foo", "bar", "baz"})
101 // would retrieve "baz" in ("bar" in ("foo" in nd.Links).Links).Links
103 -func (s *Resolver) ResolveLinks(ctx context.Context, ndd *merkledag.Node, names []string) ([]*merkledag.Node, error) {
102 +func (s *Resolver) ResolveLinks(ctx context.Context, ndd merkledag.Node, names []string) ([]merkledag.Node, error) {
103
105 - result := make([]*merkledag.Node, 0, len(names)+1)
104 + result := make([]merkledag.Node, 0, len(names)+1)
105 result = append(result, ndd)
106 nd := ndd // dup arg workaround
107
108 // for each of the path components
110 - for _, name := range names {
111 -
109 + for len(names) > 0 {
110 var cancel context.CancelFunc
111 ctx, cancel = context.WithTimeout(ctx, time.Minute)
112 defer cancel()
113
116 - nextnode, err := nd.GetLinkedNode(ctx, s.DAG, name)
114 + lnk, rest, err := nd.Resolve(names)
115 if err == merkledag.ErrLinkNotFound {
118 - n := nd.Multihash()
119 - return result, ErrNoLink{Name: name, Node: n}
116 + n := nd.Cid()
117 + return result, ErrNoLink{Name: names[0], Node: n}
118 } else if err != nil {
121 - return append(result, nextnode), err
119 + return result, err
120 + }
121 +
122 + nextnode, err := s.DAG.Get(ctx, lnk.Cid)
123 + if err != nil {
124 + return result, err
125 }
126
127 nd = nextnode
128 + names = rest
129 result = append(result, nextnode)
130 }
131 return result, nil
path/resolver_test.go
+4 -4
@@ -13,8 +13,8 @@ import (
13 util "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util"
14 )
15
16 -func randNode() (*merkledag.Node, key.Key) {
17 - node := new(merkledag.Node)
16 +func randNode() (*merkledag.ProtoNode, key.Key) {
17 + node := new(merkledag.ProtoNode)
18 node.SetData(make([]byte, 32))
19 util.NewTimeSeededRand().Read(node.Data())
20 k := node.Key()
@@ -39,7 +39,7 @@ func TestRecurivePathResolution(t *testing.T) {
39 t.Fatal(err)
40 }
41
42 - for _, n := range []*merkledag.Node{a, b, c} {
42 + for _, n := range []merkledag.Node{a, b, c} {
43 _, err = dagService.Add(n)
44 if err != nil {
45 t.Fatal(err)
@@ -60,7 +60,7 @@ func TestRecurivePathResolution(t *testing.T) {
60 t.Fatal(err)
61 }
62
63 - key := node.Key()
63 + key := node.Cid()
64 if key.String() != cKey.String() {
65 t.Fatal(fmt.Errorf(
66 "recursive path resolution failed for %s: %s != %s",
pin/pin.go
+13 -8
@@ -83,7 +83,7 @@ func StringToPinMode(s string) (PinMode, bool) {
83 type Pinner interface {
84 IsPinned(*cid.Cid) (string, bool, error)
85 IsPinnedWithType(*cid.Cid, PinMode) (string, bool, error)
86 - Pin(context.Context, *mdag.Node, bool) error
86 + Pin(context.Context, mdag.Node, bool) error
87 Unpin(context.Context, *cid.Cid, bool) error
88
89 // Check if a set of keys are pinned, more efficient than
@@ -162,7 +162,7 @@ func NewPinner(dstore ds.Datastore, serv, internal mdag.DAGService) Pinner {
162 }
163
164 // Pin the given node, optionally recursive
165 -func (p *pinner) Pin(ctx context.Context, node *mdag.Node, recurse bool) error {
165 +func (p *pinner) Pin(ctx context.Context, node mdag.Node, recurse bool) error {
166 p.lock.Lock()
167 defer p.lock.Unlock()
168 c := node.Cid()
@@ -317,7 +317,7 @@ func (p *pinner) CheckIfPinned(cids ...*cid.Cid) ([]Pinned, error) {
317 return err
318 }
319 for _, lnk := range links {
320 - c := cid.NewCidV0(lnk.Hash)
320 + c := lnk.Cid
321
322 if toCheck.Has(c) {
323 pinned = append(pinned,
@@ -403,12 +403,17 @@ func LoadPinner(d ds.Datastore, dserv, internal mdag.DAGService) (Pinner, error)
403 return nil, fmt.Errorf("cannot find pinning root object: %v", err)
404 }
405
406 + rootpb, ok := root.(*mdag.ProtoNode)
407 + if !ok {
408 + return nil, mdag.ErrNotProtobuf
409 + }
410 +
411 internalset := cid.NewSet()
412 internalset.Add(rootCid)
413 recordInternal := internalset.Add
414
415 { // load recursive set
411 - recurseKeys, err := loadSet(ctx, internal, root, linkRecursive, recordInternal)
416 + recurseKeys, err := loadSet(ctx, internal, rootpb, linkRecursive, recordInternal)
417 if err != nil {
418 return nil, fmt.Errorf("cannot load recursive pins: %v", err)
419 }
@@ -416,7 +421,7 @@ func LoadPinner(d ds.Datastore, dserv, internal mdag.DAGService) (Pinner, error)
421 }
422
423 { // load direct set
419 - directKeys, err := loadSet(ctx, internal, root, linkDirect, recordInternal)
424 + directKeys, err := loadSet(ctx, internal, rootpb, linkDirect, recordInternal)
425 if err != nil {
426 return nil, fmt.Errorf("cannot load direct pins: %v", err)
427 }
@@ -453,7 +458,7 @@ func (p *pinner) Flush() error {
458 internalset := cid.NewSet()
459 recordInternal := internalset.Add
460
456 - root := &mdag.Node{}
461 + root := &mdag.ProtoNode{}
462 {
463 n, err := storeSet(ctx, p.internal, p.directPin.Keys(), recordInternal)
464 if err != nil {
@@ -475,7 +480,7 @@ func (p *pinner) Flush() error {
480 }
481
482 // add the empty node, its referenced by the pin sets but never created
478 - _, err := p.internal.Add(new(mdag.Node))
483 + _, err := p.internal.Add(new(mdag.ProtoNode))
484 if err != nil {
485 return err
486 }
@@ -522,7 +527,7 @@ func hasChild(ds mdag.LinkService, root *cid.Cid, child key.Key) (bool, error) {
527 return false, err
528 }
529 for _, lnk := range links {
525 - c := cid.NewCidV0(lnk.Hash)
530 + c := lnk.Cid
531 if key.Key(c.Hash()) == child {
532 return true, nil
533 }
pin/pin_test.go
+2 -2
@@ -16,8 +16,8 @@ import (
16 dssync "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/sync"
17 )
18
19 -func randNode() (*mdag.Node, *cid.Cid) {
20 - nd := new(mdag.Node)
19 +func randNode() (*mdag.ProtoNode, *cid.Cid) {
20 + nd := new(mdag.ProtoNode)
21 nd.SetData(make([]byte, 32))
22 util.NewTimeSeededRand().Read(nd.Data())
23 k := nd.Cid()
pin/set.go
+41 -22
@@ -55,25 +55,27 @@ func (s sortByHash) Len() int {
55 }
56
57 func (s sortByHash) Less(a, b int) bool {
58 - return bytes.Compare(s.links[a].Hash, s.links[b].Hash) == -1
58 + return bytes.Compare(s.links[a].Cid.Bytes(), s.links[b].Cid.Bytes()) == -1
59 }
60
61 func (s sortByHash) Swap(a, b int) {
62 s.links[a], s.links[b] = s.links[b], s.links[a]
63 }
64
65 -func storeItems(ctx context.Context, dag merkledag.DAGService, estimatedLen uint64, iter itemIterator, internalKeys keyObserver) (*merkledag.Node, error) {
65 +func storeItems(ctx context.Context, dag merkledag.DAGService, estimatedLen uint64, iter itemIterator, internalKeys keyObserver) (*merkledag.ProtoNode, error) {
66 seed, err := randomSeed()
67 if err != nil {
68 return nil, err
69 }
70 -
71 - n := &merkledag.Node{Links: make([]*merkledag.Link, 0, defaultFanout+maxItems)}
70 + links := make([]*merkledag.Link, 0, defaultFanout+maxItems)
71 for i := 0; i < defaultFanout; i++ {
73 - n.Links = append(n.Links, &merkledag.Link{Hash: emptyKey.Hash()})
72 + links = append(links, &merkledag.Link{Cid: emptyKey})
73 }
74
75 // add emptyKey to our set of internal pinset objects
76 + n := &merkledag.ProtoNode{}
77 + n.SetLinks(links)
78 +
79 internalKeys(emptyKey)
80
81 hdr := &pb.Set{
@@ -87,17 +89,22 @@ func storeItems(ctx context.Context, dag merkledag.DAGService, estimatedLen uint
89
90 if estimatedLen < maxItems {
91 // it'll probably fit
92 + links := n.Links()
93 for i := 0; i < maxItems; i++ {
94 k, ok := iter()
95 if !ok {
96 // all done
97 break
98 }
96 - n.Links = append(n.Links, &merkledag.Link{Hash: k.Hash()})
99 +
100 + links = append(links, &merkledag.Link{Cid: k})
101 }
102 +
103 + n.SetLinks(links)
104 +
105 // sort by hash, also swap item Data
106 s := sortByHash{
100 - links: n.Links[defaultFanout:],
107 + links: n.Links()[defaultFanout:],
108 }
109 sort.Stable(s)
110 }
@@ -152,15 +159,15 @@ func storeItems(ctx context.Context, dag merkledag.DAGService, estimatedLen uint
159 internalKeys(childKey)
160
161 // overwrite the 'empty key' in the existing links array
155 - n.Links[h] = &merkledag.Link{
156 - Hash: childKey.Hash(),
162 + n.Links()[h] = &merkledag.Link{
163 + Cid: childKey,
164 Size: size,
165 }
166 }
167 return n, nil
168 }
169
163 -func readHdr(n *merkledag.Node) (*pb.Set, error) {
170 +func readHdr(n *merkledag.ProtoNode) (*pb.Set, error) {
171 hdrLenRaw, consumed := binary.Uvarint(n.Data())
172 if consumed <= 0 {
173 return nil, errors.New("invalid Set header length")
@@ -180,13 +187,13 @@ func readHdr(n *merkledag.Node) (*pb.Set, error) {
187 if v := hdr.GetVersion(); v != 1 {
188 return nil, fmt.Errorf("unsupported Set version: %d", v)
189 }
183 - if uint64(hdr.GetFanout()) > uint64(len(n.Links)) {
190 + if uint64(hdr.GetFanout()) > uint64(len(n.Links())) {
191 return nil, errors.New("impossibly large Fanout")
192 }
193 return &hdr, nil
194 }
195
189 -func writeHdr(n *merkledag.Node, hdr *pb.Set) error {
196 +func writeHdr(n *merkledag.ProtoNode, hdr *pb.Set) error {
197 hdrData, err := proto.Marshal(hdr)
198 if err != nil {
199 return err
@@ -207,20 +214,20 @@ func writeHdr(n *merkledag.Node, hdr *pb.Set) error {
214
215 type walkerFunc func(idx int, link *merkledag.Link) error
216
210 -func walkItems(ctx context.Context, dag merkledag.DAGService, n *merkledag.Node, fn walkerFunc, children keyObserver) error {
217 +func walkItems(ctx context.Context, dag merkledag.DAGService, n *merkledag.ProtoNode, fn walkerFunc, children keyObserver) error {
218 hdr, err := readHdr(n)
219 if err != nil {
220 return err
221 }
222 // readHdr guarantees fanout is a safe value
223 fanout := hdr.GetFanout()
217 - for i, l := range n.Links[fanout:] {
224 + for i, l := range n.Links()[fanout:] {
225 if err := fn(i, l); err != nil {
226 return err
227 }
228 }
222 - for _, l := range n.Links[:fanout] {
223 - c := cid.NewCidV0(l.Hash)
229 + for _, l := range n.Links()[:fanout] {
230 + c := l.Cid
231 children(c)
232 if c.Equals(emptyKey) {
233 continue
@@ -229,20 +236,26 @@ func walkItems(ctx context.Context, dag merkledag.DAGService, n *merkledag.Node,
236 if err != nil {
237 return err
238 }
232 - if err := walkItems(ctx, dag, subtree, fn, children); err != nil {
239 +
240 + stpb, ok := subtree.(*merkledag.ProtoNode)
241 + if !ok {
242 + return merkledag.ErrNotProtobuf
243 + }
244 +
245 + if err := walkItems(ctx, dag, stpb, fn, children); err != nil {
246 return err
247 }
248 }
249 return nil
250 }
251
239 -func loadSet(ctx context.Context, dag merkledag.DAGService, root *merkledag.Node, name string, internalKeys keyObserver) ([]*cid.Cid, error) {
252 +func loadSet(ctx context.Context, dag merkledag.DAGService, root *merkledag.ProtoNode, name string, internalKeys keyObserver) ([]*cid.Cid, error) {
253 l, err := root.GetNodeLink(name)
254 if err != nil {
255 return nil, err
256 }
257
245 - lnkc := cid.NewCidV0(l.Hash)
258 + lnkc := l.Cid
259 internalKeys(lnkc)
260
261 n, err := l.GetNode(ctx, dag)
@@ -250,12 +263,18 @@ func loadSet(ctx context.Context, dag merkledag.DAGService, root *merkledag.Node
263 return nil, err
264 }
265
266 + pbn, ok := n.(*merkledag.ProtoNode)
267 + if !ok {
268 + return nil, merkledag.ErrNotProtobuf
269 + }
270 +
271 var res []*cid.Cid
272 walk := func(idx int, link *merkledag.Link) error {
255 - res = append(res, cid.NewCidV0(link.Hash))
273 + res = append(res, link.Cid)
274 return nil
275 }
258 - if err := walkItems(ctx, dag, n, walk, internalKeys); err != nil {
276 +
277 + if err := walkItems(ctx, dag, pbn, walk, internalKeys); err != nil {
278 return nil, err
279 }
280 return res, nil
@@ -273,7 +292,7 @@ func getCidListIterator(cids []*cid.Cid) itemIterator {
292 }
293 }
294
276 -func storeSet(ctx context.Context, dag merkledag.DAGService, cids []*cid.Cid, internalKeys keyObserver) (*merkledag.Node, error) {
295 +func storeSet(ctx context.Context, dag merkledag.DAGService, cids []*cid.Cid, internalKeys keyObserver) (*merkledag.ProtoNode, error) {
296 iter := getCidListIterator(cids)
297
298 n, err := storeItems(ctx, dag, uint64(len(cids)), iter, internalKeys)
pin/set_test.go
+1 -1
@@ -38,7 +38,7 @@ func TestSet(t *testing.T) {
38
39 // weird wrapper node because loadSet expects us to pass an
40 // object pointing to multiple named sets
41 - setroot := &dag.Node{}
41 + setroot := &dag.ProtoNode{}
42 err = setroot.AddNodeLinkClean("foo", out)
43 if err != nil {
44 t.Fatal(err)
tar/format.go
+15 -10
@@ -34,7 +34,7 @@ func marshalHeader(h *tar.Header) ([]byte, error) {
34 return buf.Bytes(), nil
35 }
36
37 -func ImportTar(r io.Reader, ds dag.DAGService) (*dag.Node, error) {
37 +func ImportTar(r io.Reader, ds dag.DAGService) (*dag.ProtoNode, error) {
38 rall, err := ioutil.ReadAll(r)
39 if err != nil {
40 return nil, err
@@ -44,7 +44,7 @@ func ImportTar(r io.Reader, ds dag.DAGService) (*dag.Node, error) {
44
45 tr := tar.NewReader(r)
46
47 - root := new(dag.Node)
47 + root := new(dag.ProtoNode)
48 root.SetData([]byte("ipfs/tar"))
49
50 e := dagutil.NewDagEditor(root, ds)
@@ -58,7 +58,7 @@ func ImportTar(r io.Reader, ds dag.DAGService) (*dag.Node, error) {
58 return nil, err
59 }
60
61 - header := new(dag.Node)
61 + header := new(dag.ProtoNode)
62
63 headerBytes, err := marshalHeader(h)
64 if err != nil {
@@ -86,7 +86,7 @@ func ImportTar(r io.Reader, ds dag.DAGService) (*dag.Node, error) {
86 }
87
88 path := escapePath(h.Name)
89 - err = e.InsertNodeAtPath(context.Background(), path, header, func() *dag.Node { return new(dag.Node) })
89 + err = e.InsertNodeAtPath(context.Background(), path, header, func() *dag.ProtoNode { return new(dag.ProtoNode) })
90 if err != nil {
91 return nil, err
92 }
@@ -170,9 +170,14 @@ func (tr *tarReader) Read(b []byte) (int, error) {
170 return 0, err
171 }
172
173 - tr.hdrBuf = bytes.NewReader(headerNd.Data())
173 + hndpb, ok := headerNd.(*dag.ProtoNode)
174 + if !ok {
175 + return 0, dag.ErrNotProtobuf
176 + }
177 +
178 + tr.hdrBuf = bytes.NewReader(hndpb.Data())
179
175 - dataNd, err := headerNd.GetLinkedNode(tr.ctx, tr.ds, "data")
180 + dataNd, err := hndpb.GetLinkedProtoNode(tr.ctx, tr.ds, "data")
181 if err != nil && err != dag.ErrLinkNotFound {
182 return 0, err
183 }
@@ -185,9 +190,9 @@ func (tr *tarReader) Read(b []byte) (int, error) {
190 }
191
192 tr.fileRead = &countReader{r: dr}
188 - } else if len(headerNd.Links) > 0 {
193 + } else if len(headerNd.Links()) > 0 {
194 tr.childRead = &tarReader{
190 - links: headerNd.Links,
195 + links: headerNd.Links(),
196 ds: tr.ds,
197 ctx: tr.ctx,
198 }
@@ -196,12 +201,12 @@ func (tr *tarReader) Read(b []byte) (int, error) {
201 return tr.Read(b)
202 }
203
199 -func ExportTar(ctx context.Context, root *dag.Node, ds dag.DAGService) (io.Reader, error) {
204 +func ExportTar(ctx context.Context, root *dag.ProtoNode, ds dag.DAGService) (io.Reader, error) {
205 if string(root.Data()) != "ipfs/tar" {
206 return nil, errors.New("not an ipfs tarchive")
207 }
208 return &tarReader{
204 - links: root.Links,
209 + links: root.Links(),
210 ds: ds,
211 ctx: ctx,
212 }, nil
unixfs/archive/archive.go
+1 -1
@@ -30,7 +30,7 @@ func (i *identityWriteCloser) Close() error {
30 }
31
32 // DagArchive is equivalent to `ipfs getdag $hash | maybe_tar | maybe_gzip`
33 -func DagArchive(ctx cxt.Context, nd *mdag.Node, name string, dag mdag.DAGService, archive bool, compression int) (io.Reader, error) {
33 +func DagArchive(ctx cxt.Context, nd *mdag.ProtoNode, name string, dag mdag.DAGService, archive bool, compression int) (io.Reader, error) {
34
35 _, filename := path.Split(name)
36
unixfs/archive/tar/writer.go
+10 -5
@@ -34,7 +34,7 @@ func NewWriter(ctx cxt.Context, dag mdag.DAGService, archive bool, compression i
34 }, nil
35 }
36
37 -func (w *Writer) writeDir(nd *mdag.Node, fpath string) error {
37 +func (w *Writer) writeDir(nd *mdag.ProtoNode, fpath string) error {
38 if err := writeDirHeader(w.TarW, fpath); err != nil {
39 return err
40 }
@@ -45,8 +45,13 @@ func (w *Writer) writeDir(nd *mdag.Node, fpath string) error {
45 return err
46 }
47
48 - npath := path.Join(fpath, nd.Links[i].Name)
49 - if err := w.WriteNode(child, npath); err != nil {
48 + childpb, ok := child.(*mdag.ProtoNode)
49 + if !ok {
50 + return mdag.ErrNotProtobuf
51 + }
52 +
53 + npath := path.Join(fpath, nd.Links()[i].Name)
54 + if err := w.WriteNode(childpb, npath); err != nil {
55 return err
56 }
57 }
@@ -54,7 +59,7 @@ func (w *Writer) writeDir(nd *mdag.Node, fpath string) error {
59 return nil
60 }
61
57 -func (w *Writer) writeFile(nd *mdag.Node, pb *upb.Data, fpath string) error {
62 +func (w *Writer) writeFile(nd *mdag.ProtoNode, pb *upb.Data, fpath string) error {
63 if err := writeFileHeader(w.TarW, fpath, pb.GetFilesize()); err != nil {
64 return err
65 }
@@ -67,7 +72,7 @@ func (w *Writer) writeFile(nd *mdag.Node, pb *upb.Data, fpath string) error {
72 return nil
73 }
74
70 -func (w *Writer) WriteNode(nd *mdag.Node, fpath string) error {
75 +func (w *Writer) WriteNode(nd *mdag.ProtoNode, fpath string) error {
76 pb := new(upb.Data)
77 if err := proto.Unmarshal(nd.Data(), pb); err != nil {
78 return err
unixfs/format.go
+1 -1
@@ -224,6 +224,6 @@ func BytesForMetadata(m *Metadata) ([]byte, error) {
224 return proto.Marshal(pbd)
225 }
226
227 -func EmptyDirNode() *dag.Node {
227 +func EmptyDirNode() *dag.ProtoNode {
228 return dag.NodeWithData(FolderPBData())
229 }
unixfs/io/dagreader.go
+18 -8
@@ -24,7 +24,7 @@ type DagReader struct {
24 serv mdag.DAGService
25
26 // the node being read
27 - node *mdag.Node
27 + node *mdag.ProtoNode
28
29 // cached protobuf structure from node.Data
30 pbdata *ftpb.Data
@@ -58,7 +58,7 @@ type ReadSeekCloser interface {
58
59 // NewDagReader creates a new reader object that reads the data represented by
60 // the given node, using the passed in DAGService for data retreival
61 -func NewDagReader(ctx context.Context, n *mdag.Node, serv mdag.DAGService) (*DagReader, error) {
61 +func NewDagReader(ctx context.Context, n *mdag.ProtoNode, serv mdag.DAGService) (*DagReader, error) {
62 pb := new(ftpb.Data)
63 if err := proto.Unmarshal(n.Data(), pb); err != nil {
64 return nil, err
@@ -71,14 +71,19 @@ func NewDagReader(ctx context.Context, n *mdag.Node, serv mdag.DAGService) (*Dag
71 case ftpb.Data_File, ftpb.Data_Raw:
72 return NewDataFileReader(ctx, n, pb, serv), nil
73 case ftpb.Data_Metadata:
74 - if len(n.Links) == 0 {
74 + if len(n.Links()) == 0 {
75 return nil, errors.New("incorrectly formatted metadata object")
76 }
77 - child, err := n.Links[0].GetNode(ctx, serv)
77 + child, err := n.Links()[0].GetNode(ctx, serv)
78 if err != nil {
79 return nil, err
80 }
81 - return NewDagReader(ctx, child, serv)
81 +
82 + childpb, ok := child.(*mdag.ProtoNode)
83 + if !ok {
84 + return nil, mdag.ErrNotProtobuf
85 + }
86 + return NewDagReader(ctx, childpb, serv)
87 case ftpb.Data_Symlink:
88 return nil, ErrCantReadSymlinks
89 default:
@@ -86,7 +91,7 @@ func NewDagReader(ctx context.Context, n *mdag.Node, serv mdag.DAGService) (*Dag
91 }
92 }
93
89 -func NewDataFileReader(ctx context.Context, n *mdag.Node, pb *ftpb.Data, serv mdag.DAGService) *DagReader {
94 +func NewDataFileReader(ctx context.Context, n *mdag.ProtoNode, pb *ftpb.Data, serv mdag.DAGService) *DagReader {
95 fctx, cancel := context.WithCancel(ctx)
96 promises := mdag.GetDAG(fctx, serv, n)
97 return &DagReader{
@@ -114,8 +119,13 @@ func (dr *DagReader) precalcNextBuf(ctx context.Context) error {
119 }
120 dr.linkPosition++
121
122 + nxtpb, ok := nxt.(*mdag.ProtoNode)
123 + if !ok {
124 + return mdag.ErrNotProtobuf
125 + }
126 +
127 pb := new(ftpb.Data)
118 - err = proto.Unmarshal(nxt.Data(), pb)
128 + err = proto.Unmarshal(nxtpb.Data(), pb)
129 if err != nil {
130 return fmt.Errorf("incorrectly formatted protobuf: %s", err)
131 }
@@ -125,7 +135,7 @@ func (dr *DagReader) precalcNextBuf(ctx context.Context) error {
135 // A directory should not exist within a file
136 return ft.ErrInvalidDirLocation
137 case ftpb.Data_File:
128 - dr.buf = NewDataFileReader(dr.ctx, nxt, pb, dr.serv)
138 + dr.buf = NewDataFileReader(dr.ctx, nxtpb, pb, dr.serv)
139 return nil
140 case ftpb.Data_Raw:
141 dr.buf = NewRSNCFromBytes(pb.GetData())
unixfs/io/dirbuilder.go
+10 -5
@@ -10,12 +10,12 @@ import (
10
11 type directoryBuilder struct {
12 dserv mdag.DAGService
13 - dirnode *mdag.Node
13 + dirnode *mdag.ProtoNode
14 }
15
16 // NewEmptyDirectory returns an empty merkledag Node with a folder Data chunk
17 -func NewEmptyDirectory() *mdag.Node {
18 - nd := new(mdag.Node)
17 +func NewEmptyDirectory() *mdag.ProtoNode {
18 + nd := new(mdag.ProtoNode)
19 nd.SetData(format.FolderPBData())
20 return nd
21 }
@@ -35,10 +35,15 @@ func (d *directoryBuilder) AddChild(ctx context.Context, name string, c *cid.Cid
35 return err
36 }
37
38 - return d.dirnode.AddNodeLinkClean(name, cnode)
38 + cnpb, ok := cnode.(*mdag.ProtoNode)
39 + if !ok {
40 + return mdag.ErrNotProtobuf
41 + }
42 +
43 + return d.dirnode.AddNodeLinkClean(name, cnpb)
44 }
45
46 // GetNode returns the root of this directoryBuilder
42 -func (d *directoryBuilder) GetNode() *mdag.Node {
47 +func (d *directoryBuilder) GetNode() *mdag.ProtoNode {
48 return d.dirnode
49 }
unixfs/io/dirbuilder_test.go
+2 -2
@@ -10,7 +10,7 @@ import (
10
11 func TestEmptyNode(t *testing.T) {
12 n := NewEmptyDirectory()
13 - if len(n.Links) != 0 {
13 + if len(n.Links()) != 0 {
14 t.Fatal("empty node should have 0 links")
15 }
16 }
@@ -27,7 +27,7 @@ func TestDirBuilder(t *testing.T) {
27 b.AddChild(ctx, "random", key)
28
29 dir := b.GetNode()
30 - outn, err := dir.GetLinkedNode(ctx, dserv, "random")
30 + outn, err := dir.GetLinkedProtoNode(ctx, dserv, "random")
31 if err != nil {
32 t.Fatal(err)
33 }
unixfs/mod/dagmodifier.go
+35 -19
@@ -32,7 +32,7 @@ var log = logging.Logger("dagio")
32 // Dear god, please rename this to something more pleasant
33 type DagModifier struct {
34 dagserv mdag.DAGService
35 - curNode *mdag.Node
35 + curNode *mdag.ProtoNode
36
37 splitter chunk.SplitterGen
38 ctx context.Context
@@ -45,7 +45,7 @@ type DagModifier struct {
45 read *uio.DagReader
46 }
47
48 -func NewDagModifier(ctx context.Context, from *mdag.Node, serv mdag.DAGService, spl chunk.SplitterGen) (*DagModifier, error) {
48 +func NewDagModifier(ctx context.Context, from *mdag.ProtoNode, serv mdag.DAGService, spl chunk.SplitterGen) (*DagModifier, error) {
49 return &DagModifier{
50 curNode: from.Copy(),
51 dagserv: serv,
@@ -178,11 +178,16 @@ func (dm *DagModifier) Sync() error {
178 return err
179 }
180
181 - dm.curNode = nd
181 + pbnd, ok := nd.(*mdag.ProtoNode)
182 + if !ok {
183 + return mdag.ErrNotProtobuf
184 + }
185 +
186 + dm.curNode = pbnd
187
188 // need to write past end of current dag
189 if !done {
185 - nd, err = dm.appendData(dm.curNode, dm.splitter(dm.wrBuf))
190 + nd, err := dm.appendData(dm.curNode, dm.splitter(dm.wrBuf))
191 if err != nil {
192 return err
193 }
@@ -204,14 +209,14 @@ func (dm *DagModifier) Sync() error {
209 // modifyDag writes the data in 'data' over the data in 'node' starting at 'offset'
210 // returns the new key of the passed in node and whether or not all the data in the reader
211 // has been consumed.
207 -func (dm *DagModifier) modifyDag(node *mdag.Node, offset uint64, data io.Reader) (*cid.Cid, bool, error) {
212 +func (dm *DagModifier) modifyDag(node *mdag.ProtoNode, offset uint64, data io.Reader) (*cid.Cid, bool, error) {
213 f, err := ft.FromBytes(node.Data())
214 if err != nil {
215 return nil, false, err
216 }
217
218 // If we've reached a leaf node.
214 - if len(node.Links) == 0 {
219 + if len(node.Links()) == 0 {
220 n, err := data.Read(f.Data[offset:])
221 if err != nil && err != io.EOF {
222 return nil, false, err
@@ -223,7 +228,7 @@ func (dm *DagModifier) modifyDag(node *mdag.Node, offset uint64, data io.Reader)
228 return nil, false, err
229 }
230
226 - nd := new(mdag.Node)
231 + nd := new(mdag.ProtoNode)
232 nd.SetData(b)
233 k, err := dm.dagserv.Add(nd)
234 if err != nil {
@@ -244,17 +249,23 @@ func (dm *DagModifier) modifyDag(node *mdag.Node, offset uint64, data io.Reader)
249 for i, bs := range f.GetBlocksizes() {
250 // We found the correct child to write into
251 if cur+bs > offset {
247 - child, err := node.Links[i].GetNode(dm.ctx, dm.dagserv)
252 + child, err := node.Links()[i].GetNode(dm.ctx, dm.dagserv)
253 if err != nil {
254 return nil, false, err
255 }
251 - k, sdone, err := dm.modifyDag(child, offset-cur, data)
256 +
257 + childpb, ok := child.(*mdag.ProtoNode)
258 + if !ok {
259 + return nil, false, mdag.ErrNotProtobuf
260 + }
261 +
262 + k, sdone, err := dm.modifyDag(childpb, offset-cur, data)
263 if err != nil {
264 return nil, false, err
265 }
266
267 offset += bs
257 - node.Links[i].Hash = k.Hash()
268 + node.Links()[i].Cid = k
269
270 // Recache serialized node
271 _, err = node.EncodeProtobuf(true)
@@ -277,7 +288,7 @@ func (dm *DagModifier) modifyDag(node *mdag.Node, offset uint64, data io.Reader)
288 }
289
290 // appendData appends the blocks from the given chan to the end of this dag
280 -func (dm *DagModifier) appendData(node *mdag.Node, spl chunk.Splitter) (*mdag.Node, error) {
291 +func (dm *DagModifier) appendData(node *mdag.ProtoNode, spl chunk.Splitter) (*mdag.ProtoNode, error) {
292 dbp := &help.DagBuilderParams{
293 Dagserv: dm.dagserv,
294 Maxlinks: help.DefaultLinksPerBlock,
@@ -340,7 +351,7 @@ func (dm *DagModifier) CtxReadFull(ctx context.Context, b []byte) (int, error) {
351 }
352
353 // GetNode gets the modified DAG Node
343 -func (dm *DagModifier) GetNode() (*mdag.Node, error) {
354 +func (dm *DagModifier) GetNode() (*mdag.ProtoNode, error) {
355 err := dm.Sync()
356 if err != nil {
357 return nil, err
@@ -425,8 +436,8 @@ func (dm *DagModifier) Truncate(size int64) error {
436 }
437
438 // dagTruncate truncates the given node to 'size' and returns the modified Node
428 -func dagTruncate(ctx context.Context, nd *mdag.Node, size uint64, ds mdag.DAGService) (*mdag.Node, error) {
429 - if len(nd.Links) == 0 {
439 +func dagTruncate(ctx context.Context, nd *mdag.ProtoNode, size uint64, ds mdag.DAGService) (*mdag.ProtoNode, error) {
440 + if len(nd.Links()) == 0 {
441 // TODO: this can likely be done without marshaling and remarshaling
442 pbn, err := ft.FromBytes(nd.Data())
443 if err != nil {
@@ -439,22 +450,27 @@ func dagTruncate(ctx context.Context, nd *mdag.Node, size uint64, ds mdag.DAGSer
450
451 var cur uint64
452 end := 0
442 - var modified *mdag.Node
453 + var modified *mdag.ProtoNode
454 ndata := new(ft.FSNode)
444 - for i, lnk := range nd.Links {
455 + for i, lnk := range nd.Links() {
456 child, err := lnk.GetNode(ctx, ds)
457 if err != nil {
458 return nil, err
459 }
460
450 - childsize, err := ft.DataSize(child.Data())
461 + childpb, ok := child.(*mdag.ProtoNode)
462 + if !ok {
463 + return nil, err
464 + }
465 +
466 + childsize, err := ft.DataSize(childpb.Data())
467 if err != nil {
468 return nil, err
469 }
470
471 // found the child we want to cut
472 if size < cur+childsize {
457 - nchild, err := dagTruncate(ctx, child, size-cur, ds)
473 + nchild, err := dagTruncate(ctx, childpb, size-cur, ds)
474 if err != nil {
475 return nil, err
476 }
@@ -474,7 +490,7 @@ func dagTruncate(ctx context.Context, nd *mdag.Node, size uint64, ds mdag.DAGSer
490 return nil, err
491 }
492
477 - nd.Links = nd.Links[:end]
493 + nd.SetLinks(nd.Links()[:end])
494 err = nd.AddNodeLinkClean("", modified)
495 if err != nil {
496 return nil, err
unixfs/test/utils.go
+8 -8
@@ -27,7 +27,7 @@ func GetDAGServ() mdag.DAGService {
27 return mdagmock.Mock()
28 }
29
30 -func GetNode(t testing.TB, dserv mdag.DAGService, data []byte) *mdag.Node {
30 +func GetNode(t testing.TB, dserv mdag.DAGService, data []byte) *mdag.ProtoNode {
31 in := bytes.NewReader(data)
32 node, err := imp.BuildTrickleDagFromReader(dserv, SizeSplitterGen(500)(in))
33 if err != nil {
@@ -37,11 +37,11 @@ func GetNode(t testing.TB, dserv mdag.DAGService, data []byte) *mdag.Node {
37 return node
38 }
39
40 -func GetEmptyNode(t testing.TB, dserv mdag.DAGService) *mdag.Node {
40 +func GetEmptyNode(t testing.TB, dserv mdag.DAGService) *mdag.ProtoNode {
41 return GetNode(t, dserv, []byte{})
42 }
43
44 -func GetRandomNode(t testing.TB, dserv mdag.DAGService, size int64) ([]byte, *mdag.Node) {
44 +func GetRandomNode(t testing.TB, dserv mdag.DAGService, size int64) ([]byte, *mdag.ProtoNode) {
45 in := io.LimitReader(u.NewTimeSeededRand(), size)
46 buf, err := ioutil.ReadAll(in)
47 if err != nil {
@@ -64,7 +64,7 @@ func ArrComp(a, b []byte) error {
64 return nil
65 }
66
67 -func PrintDag(nd *mdag.Node, ds mdag.DAGService, indent int) {
67 +func PrintDag(nd *mdag.ProtoNode, ds mdag.DAGService, indent int) {
68 pbd, err := ft.FromBytes(nd.Data())
69 if err != nil {
70 panic(err)
@@ -74,17 +74,17 @@ func PrintDag(nd *mdag.Node, ds mdag.DAGService, indent int) {
74 fmt.Print(" ")
75 }
76 fmt.Printf("{size = %d, type = %s, children = %d", pbd.GetFilesize(), pbd.GetType().String(), len(pbd.GetBlocksizes()))
77 - if len(nd.Links) > 0 {
77 + if len(nd.Links()) > 0 {
78 fmt.Println()
79 }
80 - for _, lnk := range nd.Links {
80 + for _, lnk := range nd.Links() {
81 child, err := lnk.GetNode(context.Background(), ds)
82 if err != nil {
83 panic(err)
84 }
85 - PrintDag(child, ds, indent+1)
85 + PrintDag(child.(*mdag.ProtoNode), ds, indent+1)
86 }
87 - if len(nd.Links) > 0 {
87 + if len(nd.Links()) > 0 {
88 for i := 0; i < indent; i++ {
89 fmt.Print(" ")
90 }