@cryptotaxi247 / kubo / commits / 7c510662a

break merkledag utils into its own package

License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>

Jeromy committed Jul 24, 2015 at 12:45 UTC 7c510662ae2ea9beef3702e1149ab05cb7c0cf1d
4 files changed +243 -114
core/commands/object.go
+3 -114
@@ -18,6 +18,7 @@ import (
18 cmds "github.com/ipfs/go-ipfs/commands"
19 core "github.com/ipfs/go-ipfs/core"
20 dag "github.com/ipfs/go-ipfs/merkledag"
21 + dagutils "github.com/ipfs/go-ipfs/merkledag/utils"
22 path "github.com/ipfs/go-ipfs/path"
23 ft "github.com/ipfs/go-ipfs/unixfs"
24 u "github.com/ipfs/go-ipfs/util"
@@ -588,7 +589,7 @@ func rmLinkCaller(req cmds.Request, root *dag.Node) (key.Key, error) {
589
590 path := strings.Split(req.Arguments()[2], "/")
591
591 - nnode, err := rmLink(req.Context(), nd.DAG, root, path)
592 + nnode, err := dagutils.RmLink(req.Context(), nd.DAG, root, path)
593 if err != nil {
594 return "", err
595 }
@@ -596,51 +597,6 @@ func rmLinkCaller(req cmds.Request, root *dag.Node) (key.Key, error) {
597 return nnode.Key()
598 }
599
599 -func rmLink(ctx context.Context, ds dag.DAGService, root *dag.Node, path []string) (*dag.Node, error) {
600 - if len(path) == 1 {
601 - // base case, remove node in question
602 - err := root.RemoveNodeLink(path[0])
603 - if err != nil {
604 - return nil, err
605 - }
606 -
607 - _, err = ds.Add(root)
608 - if err != nil {
609 - return nil, err
610 - }
611 -
612 - return root, nil
613 - }
614 -
615 - nchild, err := root.GetNodeLink(path[0])
616 - if err != nil {
617 - return nil, err
618 - }
619 -
620 - nd, err := nchild.GetNode(ctx, ds)
621 - if err != nil {
622 - return nil, err
623 - }
624 -
625 - nnode, err := rmLink(ctx, ds, nd, path[1:])
626 - if err != nil {
627 - return nil, err
628 - }
629 -
630 - _ = root.RemoveNodeLink(path[0])
631 - err = root.AddNodeLinkClean(path[0], nnode)
632 - if err != nil {
633 - return nil, err
634 - }
635 -
636 - _, err = ds.Add(root)
637 - if err != nil {
638 - return nil, err
639 - }
640 -
641 - return root, nil
642 -}
643 -
600 func addLinkCaller(req cmds.Request, root *dag.Node) (key.Key, error) {
601 if len(req.Arguments()) < 4 {
602 return "", fmt.Errorf("not enough arguments for add-link")
@@ -661,80 +617,13 @@ func addLinkCaller(req cmds.Request, root *dag.Node) (key.Key, error) {
617 return "", err
618 }
619
664 - nnode, err := insertNodeAtPath(req.Context(), nd.DAG, root, parts, childk, create)
620 + nnode, err := dagutils.InsertNodeAtPath(req.Context(), nd.DAG, root, parts, childk, create)
621 if err != nil {
622 return "", err
623 }
624 return nnode.Key()
625 }
626
671 -func addLink(ctx context.Context, ds dag.DAGService, root *dag.Node, childname string, childk key.Key) (*dag.Node, error) {
672 - if childname == "" {
673 - return nil, errors.New("cannot create link with no name!")
674 - }
675 -
676 - ctx, cancel := context.WithTimeout(ctx, time.Second*30)
677 - defer cancel()
678 - childnd, err := ds.Get(ctx, childk)
679 - if err != nil {
680 - return nil, err
681 - }
682 -
683 - // ensure no link with that name already exists
684 - _ = root.RemoveNodeLink(childname) // ignore error, only option is ErrNotFound
685 -
686 - err = root.AddNodeLinkClean(childname, childnd)
687 - if err != nil {
688 - return nil, err
689 - }
690 -
691 - _, err = ds.Add(root)
692 - if err != nil {
693 - return nil, err
694 - }
695 - return root, nil
696 -}
697 -
698 -func insertNodeAtPath(ctx context.Context, ds dag.DAGService, root *dag.Node, path []string, toinsert key.Key, create bool) (*dag.Node, error) {
699 - if len(path) == 1 {
700 - return addLink(ctx, ds, root, path[0], toinsert)
701 - }
702 -
703 - var nd *dag.Node
704 - child, err := root.GetNodeLink(path[0])
705 - if err != nil {
706 - // if 'create' is true, we create directories on the way down as needed
707 - if err == dag.ErrNotFound && create {
708 - nd = &dag.Node{Data: ft.FolderPBData()}
709 - } else {
710 - return nil, err
711 - }
712 - } else {
713 - nd, err = child.GetNode(ctx, ds)
714 - if err != nil {
715 - return nil, err
716 - }
717 - }
718 -
719 - ndprime, err := insertNodeAtPath(ctx, ds, nd, path[1:], toinsert, create)
720 - if err != nil {
721 - return nil, err
722 - }
723 -
724 - _ = root.RemoveNodeLink(path[0])
725 - err = root.AddNodeLinkClean(path[0], ndprime)
726 - if err != nil {
727 - return nil, err
728 - }
729 -
730 - _, err = ds.Add(root)
731 - if err != nil {
732 - return nil, err
733 - }
734 -
735 - return root, nil
736 -}
737 -
627 func nodeFromTemplate(template string) (*dag.Node, error) {
628 switch template {
629 case "unixfs-dir":
merkledag/node.go
+9
@@ -153,6 +153,15 @@ func (n *Node) GetNodeLink(name string) (*Link, error) {
153 return nil, ErrNotFound
154 }
155
156 +func (n *Node) GetLinkedNode(ctx context.Context, ds DAGService, name string) (*Node, error) {
157 + lnk, err := n.GetNodeLink(name)
158 + if err != nil {
159 + return nil, err
160 + }
161 +
162 + return lnk.GetNode(ctx, ds)
163 +}
164 +
165 // Copy returns a copy of the node.
166 // NOTE: does not make copies of Node objects in the links.
167 func (n *Node) Copy() *Node {
merkledag/utils/utils.go new
+113
@@ -0,0 +1,113 @@
1 +package dagutils
2 +
3 +import (
4 + "errors"
5 + "time"
6 +
7 + context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
8 +
9 + key "github.com/ipfs/go-ipfs/blocks/key"
10 + dag "github.com/ipfs/go-ipfs/merkledag"
11 + ft "github.com/ipfs/go-ipfs/unixfs"
12 +)
13 +
14 +func AddLink(ctx context.Context, ds dag.DAGService, root *dag.Node, childname string, childk key.Key) (*dag.Node, error) {
15 + if childname == "" {
16 + return nil, errors.New("cannot create link with no name!")
17 + }
18 +
19 + ctx, cancel := context.WithTimeout(ctx, time.Second*30)
20 + defer cancel()
21 + childnd, err := ds.Get(ctx, childk)
22 + if err != nil {
23 + return nil, err
24 + }
25 +
26 + // ensure no link with that name already exists
27 + _ = root.RemoveNodeLink(childname) // ignore error, only option is ErrNotFound
28 +
29 + err = root.AddNodeLinkClean(childname, childnd)
30 + if err != nil {
31 + return nil, err
32 + }
33 +
34 + _, err = ds.Add(root)
35 + if err != nil {
36 + return nil, err
37 + }
38 + return root, nil
39 +}
40 +
41 +func InsertNodeAtPath(ctx context.Context, ds dag.DAGService, root *dag.Node, path []string, toinsert key.Key, create bool) (*dag.Node, error) {
42 + if len(path) == 1 {
43 + return AddLink(ctx, ds, root, path[0], toinsert)
44 + }
45 +
46 + nd, err := root.GetLinkedNode(ctx, ds, path[0])
47 + if err != nil {
48 + // if 'create' is true, we create directories on the way down as needed
49 + if err == dag.ErrNotFound && create {
50 + nd = &dag.Node{Data: ft.FolderPBData()}
51 + } else {
52 + return nil, err
53 + }
54 + }
55 +
56 + ndprime, err := InsertNodeAtPath(ctx, ds, nd, path[1:], toinsert, create)
57 + if err != nil {
58 + return nil, err
59 + }
60 +
61 + _ = root.RemoveNodeLink(path[0])
62 + err = root.AddNodeLinkClean(path[0], ndprime)
63 + if err != nil {
64 + return nil, err
65 + }
66 +
67 + _, err = ds.Add(root)
68 + if err != nil {
69 + return nil, err
70 + }
71 +
72 + return root, nil
73 +}
74 +
75 +func RmLink(ctx context.Context, ds dag.DAGService, root *dag.Node, path []string) (*dag.Node, error) {
76 + if len(path) == 1 {
77 + // base case, remove node in question
78 + err := root.RemoveNodeLink(path[0])
79 + if err != nil {
80 + return nil, err
81 + }
82 +
83 + _, err = ds.Add(root)
84 + if err != nil {
85 + return nil, err
86 + }
87 +
88 + return root, nil
89 + }
90 +
91 + nd, err := root.GetLinkedNode(ctx, ds, path[0])
92 + if err != nil {
93 + return nil, err
94 + }
95 +
96 + nnode, err := RmLink(ctx, ds, nd, path[1:])
97 + if err != nil {
98 + return nil, err
99 + }
100 +
101 + _ = root.RemoveNodeLink(path[0])
102 + err = root.AddNodeLinkClean(path[0], nnode)
103 + if err != nil {
104 + return nil, err
105 + }
106 +
107 + _, err = ds.Add(root)
108 + if err != nil {
109 + return nil, err
110 + }
111 +
112 + return root, nil
113 +}
merkledag/utils/utils_test.go new
+118
@@ -0,0 +1,118 @@
1 +package dagutils
2 +
3 +import (
4 + "testing"
5 +
6 + key "github.com/ipfs/go-ipfs/blocks/key"
7 + dag "github.com/ipfs/go-ipfs/merkledag"
8 + mdtest "github.com/ipfs/go-ipfs/merkledag/test"
9 +
10 + context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
11 +)
12 +
13 +func TestAddLink(t *testing.T) {
14 + ds := mdtest.Mock(t)
15 + fishnode := &dag.Node{
16 + Data: []byte("fishcakes!"),
17 + }
18 +
19 + fk, err := ds.Add(fishnode)
20 + if err != nil {
21 + t.Fatal(err)
22 + }
23 +
24 + nd := new(dag.Node)
25 + nnode, err := AddLink(context.Background(), ds, nd, "fish", fk)
26 + if err != nil {
27 + t.Fatal(err)
28 + }
29 +
30 + fnprime, err := nnode.GetLinkedNode(context.Background(), ds, "fish")
31 + if err != nil {
32 + t.Fatal(err)
33 + }
34 +
35 + fnpkey, err := fnprime.Key()
36 + if err != nil {
37 + t.Fatal(err)
38 + }
39 +
40 + if fnpkey != fk {
41 + t.Fatal("wrong child node found!")
42 + }
43 +}
44 +
45 +func assertNodeAtPath(t *testing.T, ds dag.DAGService, root *dag.Node, path []string, exp key.Key) {
46 + cur := root
47 + for _, e := range path {
48 + nxt, err := cur.GetLinkedNode(context.Background(), ds, e)
49 + if err != nil {
50 + t.Fatal(err)
51 + }
52 +
53 + cur = nxt
54 + }
55 +
56 + curk, err := cur.Key()
57 + if err != nil {
58 + t.Fatal(err)
59 + }
60 +
61 + if curk != exp {
62 + t.Fatal("node not as expected at end of path")
63 + }
64 +}
65 +
66 +func TestInsertNode(t *testing.T) {
67 + ds := mdtest.Mock(t)
68 + root := new(dag.Node)
69 +
70 + childa := &dag.Node{
71 + Data: []byte("This is child A"),
72 + }
73 + ak, err := ds.Add(childa)
74 + if err != nil {
75 + t.Fatal(err)
76 + }
77 +
78 + path := []string{"a", "b", "c", "d"}
79 + root_a, err := InsertNodeAtPath(context.Background(), ds, root, path, ak, true)
80 + if err != nil {
81 + t.Fatal(err)
82 + }
83 + assertNodeAtPath(t, ds, root_a, path, ak)
84 +
85 + childb := &dag.Node{Data: []byte("this is the second child")}
86 + bk, err := ds.Add(childb)
87 + if err != nil {
88 + t.Fatal(err)
89 + }
90 +
91 + // this one should fail, we are specifying a non-existant path
92 + // with create == false
93 + path2 := []string{"a", "b", "e", "f"}
94 + _, err = InsertNodeAtPath(context.Background(), ds, root_a, path2, bk, false)
95 + if err == nil {
96 + t.Fatal("that shouldnt have worked")
97 + }
98 + if err != dag.ErrNotFound {
99 + t.Fatal("expected this to fail with 'not found'")
100 + }
101 +
102 + // inserting a path of length one should work with create == false
103 + path3 := []string{"x"}
104 + root_b, err := InsertNodeAtPath(context.Background(), ds, root_a, path3, bk, false)
105 + if err != nil {
106 + t.Fatal(err)
107 + }
108 +
109 + assertNodeAtPath(t, ds, root_b, path3, bk)
110 +
111 + // now try overwriting a path
112 + root_c, err := InsertNodeAtPath(context.Background(), ds, root_b, path, bk, false)
113 + if err != nil {
114 + t.Fatal(err)
115 + }
116 +
117 + assertNodeAtPath(t, ds, root_c, path, bk)
118 +}