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
+}