fix coreapi unixfs resolving
License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>
Jeromy committed
Apr 30, 2017 at 14:01 UTC
a22cae1bce7dfa9b67ed5c969c469e259eac0fd9
7 files changed
+73
-25
core/coreapi/coreapi.go
+7
-1
@@ -6,6 +6,7 @@ import (
6
core "github.com/ipfs/go-ipfs/core"
7
coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
8
ipfspath "github.com/ipfs/go-ipfs/path"
9
+ uio "github.com/ipfs/go-ipfs/unixfs/io"
10
11
cid "gx/ipfs/QmYhQaCYEcaPPjxJX7YcPcVKkQfRy6sJ7B3XmGFk82XYdQ/go-cid"
12
)
@@ -42,8 +43,13 @@ func (api *CoreAPI) ResolvePath(ctx context.Context, p coreiface.Path) (coreifac
43
return p, nil
44
}
45
46
+ r := &ipfspath.Resolver{
47
+ DAG: api.node.DAG,
48
+ ResolveOnce: uio.ResolveUnixfsOnce,
49
+ }
50
+
51
p2 := ipfspath.FromString(p.String())
46
- node, err := core.Resolve(ctx, api.node.Namesys, api.node.Resolver, p2)
52
+ node, err := core.Resolve(ctx, api.node.Namesys, r, p2)
53
if err == core.ErrNoNamesys {
54
return nil, coreiface.ErrOffline
55
} else if err != nil {
core/coreapi/unixfs.go
+18
-3
@@ -9,6 +9,7 @@ import (
9
uio "github.com/ipfs/go-ipfs/unixfs/io"
10
11
cid "gx/ipfs/QmYhQaCYEcaPPjxJX7YcPcVKkQfRy6sJ7B3XmGFk82XYdQ/go-cid"
12
+ node "gx/ipfs/Qmb3Hm9QDFmfYuET4pu7Kyg8JV78jFa1nvZx5vnCZsK4ck/go-ipld-format"
13
)
14
15
type UnixfsAPI CoreAPI
@@ -46,9 +47,23 @@ func (api *UnixfsAPI) Ls(ctx context.Context, p coreiface.Path) ([]*coreiface.Li
47
return nil, err
48
}
49
49
- l := dagnode.Links()
50
- links := make([]*coreiface.Link, len(l))
51
- for i, l := range l {
50
+ var ndlinks []*node.Link
51
+ dir, err := uio.NewDirectoryFromNode(api.node.DAG, dagnode)
52
+ switch err {
53
+ case nil:
54
+ l, err := dir.Links(ctx)
55
+ if err != nil {
56
+ return nil, err
57
+ }
58
+ ndlinks = l
59
+ case uio.ErrNotADir:
60
+ ndlinks = dagnode.Links()
61
+ default:
62
+ return nil, err
63
+ }
64
+
65
+ links := make([]*coreiface.Link, len(ndlinks))
66
+ for i, l := range ndlinks {
67
links[i] = &coreiface.Link{l.Name, l.Size, l.Cid}
68
}
69
return links, nil
core/coreapi/unixfs_test.go
+7
-1
@@ -16,6 +16,7 @@ import (
16
config "github.com/ipfs/go-ipfs/repo/config"
17
testutil "github.com/ipfs/go-ipfs/thirdparty/testutil"
18
unixfs "github.com/ipfs/go-ipfs/unixfs"
19
+ cbor "gx/ipfs/QmNrbCt8j9DT5W9Pmjy2SdudT9k8GpaDr4sRuFix3BXhgR/go-ipld-cbor"
20
)
21
22
// `echo -n 'hello, world!' | ipfs add`
@@ -276,7 +277,12 @@ func TestLsNonUnixfs(t *testing.T) {
277
t.Error(err)
278
}
279
279
- c, err := node.DAG.Add(new(mdag.ProtoNode))
280
+ nd, err := cbor.WrapObject(map[string]interface{}{"foo": "bar"})
281
+ if err != nil {
282
+ t.Fatal(err)
283
+ }
284
+
285
+ c, err := node.DAG.Add(nd)
286
if err != nil {
287
t.Error(err)
288
}
path/resolver.go
+7
-6
@@ -37,7 +37,7 @@ func (e ErrNoLink) Error() string {
37
type Resolver struct {
38
DAG dag.DAGService
39
40
- ResolveOnce func(ctx context.Context, ds dag.DAGService, nd node.Node, name string) (*node.Link, error)
40
+ ResolveOnce func(ctx context.Context, ds dag.DAGService, nd node.Node, names []string) (*node.Link, []string, error)
41
}
42
43
func NewBasicResolver(ds dag.DAGService) *Resolver {
@@ -121,9 +121,10 @@ func (s *Resolver) ResolvePath(ctx context.Context, fpath Path) (node.Node, erro
121
return nodes[len(nodes)-1], err
122
}
123
124
-func ResolveSingle(ctx context.Context, ds dag.DAGService, nd node.Node, name string) (*node.Link, error) {
125
- lnk, _, err := nd.ResolveLink([]string{name})
126
- return lnk, err
124
+// ResolveSingle simply resolves one hop of a path through a graph with no
125
+// extra context (does not opaquely resolve through sharded nodes)
126
+func ResolveSingle(ctx context.Context, ds dag.DAGService, nd node.Node, names []string) (*node.Link, []string, error) {
127
+ return nd.ResolveLink(names)
128
}
129
130
// ResolvePathComponents fetches the nodes for each segment of the given path.
@@ -163,7 +164,7 @@ func (s *Resolver) ResolveLinks(ctx context.Context, ndd node.Node, names []stri
164
ctx, cancel = context.WithTimeout(ctx, time.Minute)
165
defer cancel()
166
166
- lnk, err := s.ResolveOnce(ctx, s.DAG, nd, names[0])
167
+ lnk, rest, err := s.ResolveOnce(ctx, s.DAG, nd, names)
168
if err == dag.ErrLinkNotFound {
169
return result, ErrNoLink{Name: names[0], Node: nd.Cid()}
170
} else if err != nil {
@@ -177,7 +178,7 @@ func (s *Resolver) ResolveLinks(ctx context.Context, ndd node.Node, names []stri
178
179
nd = nextnode
180
result = append(result, nextnode)
180
- names = names[1:]
181
+ names = rest
182
}
183
return result, nil
184
}
unixfs/hamt/hamt.go
+5
-2
@@ -191,6 +191,7 @@ type shardValue struct {
191
val *node.Link
192
}
193
194
+// Link returns a link to this node
195
func (sv *shardValue) Link() (*node.Link, error) {
196
return sv.val, nil
197
}
@@ -234,7 +235,8 @@ func (ds *HamtShard) Remove(ctx context.Context, name string) error {
235
return ds.modifyValue(ctx, hv, name, nil)
236
}
237
237
-func (ds *HamtShard) Find(ctx context.Context, name string) (node.Node, error) {
238
+// Find searches for a child node by 'name' within this hamt
239
+func (ds *HamtShard) Find(ctx context.Context, name string) (*node.Link, error) {
240
hv := &hashBits{b: hash([]byte(name))}
241
242
var out *node.Link
@@ -246,7 +248,7 @@ func (ds *HamtShard) Find(ctx context.Context, name string) (node.Node, error) {
248
return nil, err
249
}
250
249
- return ds.dserv.Get(ctx, out.Cid)
251
+ return out, nil
252
}
253
254
// getChild returns the i'th child of this shard. If it is cached in the
@@ -320,6 +322,7 @@ func (ds *HamtShard) setChild(i int, c child) {
322
ds.children[i] = c
323
}
324
325
+// Link returns a merklelink to this shard node
326
func (ds *HamtShard) Link() (*node.Link, error) {
327
nd, err := ds.Node()
328
if err != nil {
unixfs/io/dirbuilder.go
+7
-1
@@ -48,6 +48,7 @@ func NewDirectory(dserv mdag.DAGService) *Directory {
48
return db
49
}
50
51
+// ErrNotADir implies that the given node was not a unixfs directory
52
var ErrNotADir = fmt.Errorf("merkledag node was not a directory or shard")
53
54
func NewDirectoryFromNode(dserv mdag.DAGService, nd node.Node) (*Directory, error) {
@@ -167,7 +168,12 @@ func (d *Directory) Find(ctx context.Context, name string) (node.Node, error) {
168
return d.dserv.Get(ctx, lnk.Cid)
169
}
170
170
- return d.shard.Find(ctx, name)
171
+ lnk, err := d.shard.Find(ctx, name)
172
+ if err != nil {
173
+ return nil, err
174
+ }
175
+
176
+ return lnk.GetNode(ctx, d.dserv)
177
}
178
179
func (d *Directory) RemoveChild(ctx context.Context, name string) error {
unixfs/io/resolve.go
+22
-11
@@ -10,37 +10,48 @@ import (
10
node "gx/ipfs/Qmb3Hm9QDFmfYuET4pu7Kyg8JV78jFa1nvZx5vnCZsK4ck/go-ipld-format"
11
)
12
13
-func ResolveUnixfsOnce(ctx context.Context, ds dag.DAGService, nd node.Node, name string) (*node.Link, error) {
13
+// ResolveUnixfsOnce resolves a single hop of a path through a graph in a
14
+// unixfs context. This includes handling traversing sharded directories.
15
+func ResolveUnixfsOnce(ctx context.Context, ds dag.DAGService, nd node.Node, names []string) (*node.Link, []string, error) {
16
switch nd := nd.(type) {
17
case *dag.ProtoNode:
18
upb, err := ft.FromBytes(nd.Data())
19
if err != nil {
20
// Not a unixfs node, use standard object traversal code
19
- return nd.GetNodeLink(name)
21
+ lnk, err := nd.GetNodeLink(names[0])
22
+ if err != nil {
23
+ return nil, nil, err
24
+ }
25
+
26
+ return lnk, names[1:], nil
27
}
28
29
switch upb.GetType() {
30
case ft.THAMTShard:
31
s, err := hamt.NewHamtFromDag(ds, nd)
32
if err != nil {
26
- return nil, err
33
+ return nil, nil, err
34
}
35
29
- // TODO: optimized routine on HAMT for returning a dag.Link to avoid extra disk hits
30
- out, err := s.Find(ctx, name)
36
+ out, err := s.Find(ctx, names[0])
37
if err != nil {
32
- return nil, err
38
+ return nil, nil, err
39
}
40
35
- return node.MakeLink(out)
41
+ return out, names[1:], nil
42
default:
37
- return nd.GetNodeLink(name)
43
+ lnk, err := nd.GetNodeLink(names[0])
44
+ if err != nil {
45
+ return nil, nil, err
46
+ }
47
+
48
+ return lnk, names[1:], nil
49
}
50
default:
40
- lnk, _, err := nd.ResolveLink([]string{name})
51
+ lnk, rest, err := nd.ResolveLink(names)
52
if err != nil {
42
- return nil, err
53
+ return nil, nil, err
54
}
44
- return lnk, nil
55
+ return lnk, rest, nil
56
}
57
}