@cryptotaxi247 / kubo / commits / a22cae1bc

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 }