make path resolver no longer require whole node for construction
License: MIT Signed-off-by: Jeromy <why@ipfs.io>
Jeromy committed
Oct 19, 2016 at 10:05 UTC
67c2a4ec14a230818e0cd0052725ac001b048968
23 files changed
+161
-50
core/builder.go
+1
-1
@@ -214,7 +214,7 @@ func setupNode(ctx context.Context, n *IpfsNode, cfg *BuildCfg) error {
214
// this is kinda sketchy and could cause data loss
215
n.Pinning = pin.NewPinner(n.Repo.Datastore(), n.DAG, internalDag)
216
}
217
- n.Resolver = &path.Resolver{DAG: n.DAG}
217
+ n.Resolver = path.NewBasicResolver(n.DAG)
218
219
err = n.loadFilesRoot()
220
if err != nil {
core/commands/files/files.go
+7
-2
@@ -16,6 +16,7 @@ import (
16
mfs "github.com/ipfs/go-ipfs/mfs"
17
path "github.com/ipfs/go-ipfs/path"
18
ft "github.com/ipfs/go-ipfs/unixfs"
19
+ uio "github.com/ipfs/go-ipfs/unixfs/io"
20
21
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
22
node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node"
@@ -259,11 +260,15 @@ func getNodeFromPath(ctx context.Context, node *core.IpfsNode, p string) (node.N
260
return nil, err
261
}
262
262
- nd, err := core.Resolve(ctx, node, np)
263
+ resolver := &path.Resolver{
264
+ DAG: node.DAG,
265
+ ResolveOnce: uio.ResolveUnixfsOnce,
266
+ }
267
+
268
+ nd, err := core.Resolve(ctx, node.Namesys, resolver, np)
269
if err != nil {
270
return nil, err
271
}
266
-
272
pbnd, ok := nd.(*dag.ProtoNode)
273
if !ok {
274
return nil, dag.ErrNotProtobuf
core/commands/get.go
+1
-1
@@ -64,7 +64,7 @@ may also specify the level of compression by specifying '-l=<1-9>'.
64
}
65
p := path.Path(req.Arguments()[0])
66
ctx := req.Context()
67
- dn, err := core.Resolve(ctx, node, p)
67
+ dn, err := core.Resolve(ctx, node.Namesys, node.Resolver, p)
68
if err != nil {
69
res.SetError(err, cmds.ErrNormal)
70
return
core/commands/ls.go
+13
-1
@@ -11,6 +11,7 @@ import (
11
merkledag "github.com/ipfs/go-ipfs/merkledag"
12
path "github.com/ipfs/go-ipfs/path"
13
unixfs "github.com/ipfs/go-ipfs/unixfs"
14
+ uio "github.com/ipfs/go-ipfs/unixfs/io"
15
unixfspb "github.com/ipfs/go-ipfs/unixfs/pb"
16
17
node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node"
@@ -74,7 +75,18 @@ The JSON output contains type information.
75
76
var dagnodes []node.Node
77
for _, fpath := range paths {
77
- dagnode, err := core.Resolve(req.Context(), nd, path.Path(fpath))
78
+ p, err := path.ParsePath(fpath)
79
+ if err != nil {
80
+ res.SetError(err, cmds.ErrNormal)
81
+ return
82
+ }
83
+
84
+ r := &path.Resolver{
85
+ DAG: nd.DAG,
86
+ ResolveOnce: uio.ResolveUnixfsOnce,
87
+ }
88
+
89
+ dagnode, err := core.Resolve(req.Context(), nd.Namesys, r, p)
90
if err != nil {
91
res.SetError(err, cmds.ErrNormal)
92
return
core/commands/object/diff.go
+2
-2
@@ -74,13 +74,13 @@ Example:
74
75
ctx := req.Context()
76
77
- obj_a, err := core.Resolve(ctx, node, pa)
77
+ obj_a, err := core.Resolve(ctx, node.Namesys, node.Resolver, pa)
78
if err != nil {
79
res.SetError(err, cmds.ErrNormal)
80
return
81
}
82
83
- obj_b, err := core.Resolve(ctx, node, pb)
83
+ obj_b, err := core.Resolve(ctx, node.Namesys, node.Resolver, pb)
84
if err != nil {
85
res.SetError(err, cmds.ErrNormal)
86
return
core/commands/object/object.go
+4
-4
@@ -94,7 +94,7 @@ is the raw data of the object.
94
return
95
}
96
97
- node, err := core.Resolve(req.Context(), n, fpath)
97
+ node, err := core.Resolve(req.Context(), n.Namesys, n.Resolver, fpath)
98
if err != nil {
99
res.SetError(err, cmds.ErrNormal)
100
return
@@ -140,7 +140,7 @@ multihash.
140
}
141
142
fpath := path.Path(req.Arguments()[0])
143
- node, err := core.Resolve(req.Context(), n, fpath)
143
+ node, err := core.Resolve(req.Context(), n.Namesys, n.Resolver, fpath)
144
if err != nil {
145
res.SetError(err, cmds.ErrNormal)
146
return
@@ -204,7 +204,7 @@ This command outputs data in the following encodings:
204
205
fpath := path.Path(req.Arguments()[0])
206
207
- object, err := core.Resolve(req.Context(), n, fpath)
207
+ object, err := core.Resolve(req.Context(), n.Namesys, n.Resolver, fpath)
208
if err != nil {
209
res.SetError(err, cmds.ErrNormal)
210
return
@@ -277,7 +277,7 @@ var ObjectStatCmd = &cmds.Command{
277
278
fpath := path.Path(req.Arguments()[0])
279
280
- object, err := core.Resolve(req.Context(), n, fpath)
280
+ object, err := core.Resolve(req.Context(), n.Namesys, n.Resolver, fpath)
281
if err != nil {
282
res.SetError(err, cmds.ErrNormal)
283
return
core/commands/object/patch.go
+5
-5
@@ -73,7 +73,7 @@ the limit will not be respected by the network.
73
return
74
}
75
76
- rootnd, err := core.Resolve(req.Context(), nd, root)
76
+ rootnd, err := core.Resolve(req.Context(), nd.Namesys, nd.Resolver, root)
77
if err != nil {
78
res.SetError(err, cmds.ErrNormal)
79
return
@@ -141,7 +141,7 @@ Example:
141
return
142
}
143
144
- root, err := core.Resolve(req.Context(), nd, rp)
144
+ root, err := core.Resolve(req.Context(), nd.Namesys, nd.Resolver, rp)
145
if err != nil {
146
res.SetError(err, cmds.ErrNormal)
147
return
@@ -205,7 +205,7 @@ Removes a link by the given name from root.
205
return
206
}
207
208
- root, err := core.Resolve(req.Context(), nd, rootp)
208
+ root, err := core.Resolve(req.Context(), nd.Namesys, nd.Resolver, rootp)
209
if err != nil {
210
res.SetError(err, cmds.ErrNormal)
211
return
@@ -280,7 +280,7 @@ to a file containing 'bar', and returns the hash of the new object.
280
return
281
}
282
283
- root, err := core.Resolve(req.Context(), nd, rootp)
283
+ root, err := core.Resolve(req.Context(), nd.Namesys, nd.Resolver, rootp)
284
if err != nil {
285
res.SetError(err, cmds.ErrNormal)
286
return
@@ -312,7 +312,7 @@ to a file containing 'bar', and returns the hash of the new object.
312
313
e := dagutils.NewDagEditor(rtpb, nd.DAG)
314
315
- childnd, err := core.Resolve(req.Context(), nd, childp)
315
+ childnd, err := core.Resolve(req.Context(), nd.Namesys, nd.Resolver, childp)
316
if err != nil {
317
res.SetError(err, cmds.ErrNormal)
318
return
core/commands/pin.go
+1
-1
@@ -277,7 +277,7 @@ func pinLsKeys(args []string, typeStr string, ctx context.Context, n *core.IpfsN
277
return nil, err
278
}
279
280
- dagNode, err := core.Resolve(ctx, n, pth)
280
+ dagNode, err := core.Resolve(ctx, n.Namesys, n.Resolver, pth)
281
if err != nil {
282
return nil, err
283
}
core/commands/publish.go
+1
-1
@@ -135,7 +135,7 @@ func publish(ctx context.Context, n *core.IpfsNode, k crypto.PrivKey, ref path.P
135
136
if opts.verifyExists {
137
// verify the path exists
138
- _, err := core.Resolve(ctx, n, ref)
138
+ _, err := core.Resolve(ctx, n.Namesys, n.Resolver, ref)
139
if err != nil {
140
return nil, err
141
}
core/commands/refs.go
+7
-2
@@ -198,8 +198,13 @@ var refsMarshallerMap = cmds.MarshalerMap{
198
199
func objectsForPaths(ctx context.Context, n *core.IpfsNode, paths []string) ([]node.Node, error) {
200
objects := make([]node.Node, len(paths))
201
- for i, p := range paths {
202
- o, err := core.Resolve(ctx, n, path.Path(p))
201
+ for i, sp := range paths {
202
+ p, err := path.ParsePath(sp)
203
+ if err != nil {
204
+ return nil, err
205
+ }
206
+
207
+ o, err := core.Resolve(ctx, n.Namesys, n.Resolver, p)
208
if err != nil {
209
return nil, err
210
}
core/commands/resolve.go
+1
-1
@@ -99,7 +99,7 @@ Resolve the value of an IPFS DAG path:
99
return
100
}
101
102
- node, err := core.Resolve(req.Context(), n, p)
102
+ node, err := core.Resolve(req.Context(), n.Namesys, n.Resolver, p)
103
if err != nil {
104
res.SetError(err, cmds.ErrNormal)
105
return
core/commands/tar.go
+1
-1
@@ -95,7 +95,7 @@ var tarCatCmd = &cmds.Command{
95
return
96
}
97
98
- root, err := core.Resolve(req.Context(), nd, p)
98
+ root, err := core.Resolve(req.Context(), nd.Namesys, nd.Resolver, p)
99
if err != nil {
100
res.SetError(err, cmds.ErrNormal)
101
return
core/commands/unixfs/ls.go
+8
-1
@@ -12,6 +12,7 @@ import (
12
merkledag "github.com/ipfs/go-ipfs/merkledag"
13
path "github.com/ipfs/go-ipfs/path"
14
unixfs "github.com/ipfs/go-ipfs/unixfs"
15
+ uio "github.com/ipfs/go-ipfs/unixfs/io"
16
unixfspb "github.com/ipfs/go-ipfs/unixfs/pb"
17
)
18
@@ -87,7 +88,13 @@ possible, please use 'ipfs ls' instead.
88
89
for _, fpath := range paths {
90
ctx := req.Context()
90
- merkleNode, err := core.Resolve(ctx, node, path.Path(fpath))
91
+
92
+ resolver := &path.Resolver{
93
+ DAG: node.DAG,
94
+ ResolveOnce: uio.ResolveUnixfsOnce,
95
+ }
96
+
97
+ merkleNode, err := core.Resolve(ctx, node.Namesys, resolver, path.Path(fpath))
98
if err != nil {
99
res.SetError(err, cmds.ErrNormal)
100
return
core/core.go
+2
-2
@@ -60,7 +60,7 @@ import (
60
pin "github.com/ipfs/go-ipfs/pin"
61
repo "github.com/ipfs/go-ipfs/repo"
62
config "github.com/ipfs/go-ipfs/repo/config"
63
- uio "github.com/ipfs/go-ipfs/unixfs/io"
63
+ ft "github.com/ipfs/go-ipfs/unixfs"
64
u "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util"
65
)
66
@@ -504,7 +504,7 @@ func (n *IpfsNode) loadFilesRoot() error {
504
505
switch {
506
case err == ds.ErrNotFound || val == nil:
507
- nd = uio.NewEmptyDirectory()
507
+ nd = ft.EmptyDirNode()
508
_, err := n.DAG.Add(nd)
509
if err != nil {
510
return fmt.Errorf("failure writing to dagstore: %s", err)
core/corehttp/gateway_handler.go
+18
-5
@@ -17,6 +17,7 @@ import (
17
dag "github.com/ipfs/go-ipfs/merkledag"
18
dagutils "github.com/ipfs/go-ipfs/merkledag/utils"
19
path "github.com/ipfs/go-ipfs/path"
20
+ ft "github.com/ipfs/go-ipfs/unixfs"
21
uio "github.com/ipfs/go-ipfs/unixfs/io"
22
23
humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize"
@@ -153,7 +154,13 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
154
ipnsHostname = true
155
}
156
156
- nd, err := core.Resolve(ctx, i.node, path.Path(urlPath))
157
+ p, err := path.ParsePath(urlPath)
158
+ if err != nil {
159
+ webError(w, "Invalid Path Error", err, http.StatusBadRequest)
160
+ return
161
+ }
162
+
163
+ nd, err := core.Resolve(ctx, i.node.Namesys, i.node.Resolver, p)
164
// If node is in offline mode the error code and message should be different
165
if err == core.ErrNoNamesys && !i.node.OnlineMode() {
166
w.WriteHeader(http.StatusServiceUnavailable)
@@ -240,8 +247,14 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
247
return
248
}
249
250
+ p, err := path.ParsePath(urlPath + "/index.html")
251
+ if err != nil {
252
+ internalWebError(w, err)
253
+ return
254
+ }
255
+
256
// return index page instead.
244
- nd, err := core.Resolve(ctx, i.node, path.Path(urlPath+"/index.html"))
257
+ nd, err := core.Resolve(ctx, i.node.Namesys, i.node.Resolver, p)
258
if err != nil {
259
internalWebError(w, err)
260
return
@@ -356,7 +369,7 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
369
370
var newnode node.Node
371
if rsegs[len(rsegs)-1] == "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" {
359
- newnode = uio.NewEmptyDirectory()
372
+ newnode = ft.EmptyDirNode()
373
} else {
374
putNode, err := i.newDagFromReader(r.Body)
375
if err != nil {
@@ -372,7 +385,7 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
385
}
386
387
var newcid *cid.Cid
375
- rnode, err := core.Resolve(ctx, i.node, rootPath)
388
+ rnode, err := core.Resolve(ctx, i.node.Namesys, i.node.Resolver, rootPath)
389
switch ev := err.(type) {
390
case path.ErrNoLink:
391
// ev.Node < node where resolve failed
@@ -397,7 +410,7 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
410
}
411
412
e := dagutils.NewDagEditor(pbnd, i.node.DAG)
400
- err = e.InsertNodeAtPath(ctx, newPath, newnode, uio.NewEmptyDirectory)
413
+ err = e.InsertNodeAtPath(ctx, newPath, newnode, ft.EmptyDirNode)
414
if err != nil {
415
webError(w, "putHandler: InsertNodeAtPath failed", err, http.StatusInternalServerError)
416
return
core/corerepo/pinning.go
+6
-1
@@ -27,7 +27,12 @@ import (
27
func Pin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) ([]*cid.Cid, error) {
28
dagnodes := make([]node.Node, 0)
29
for _, fpath := range paths {
30
- dagnode, err := core.Resolve(ctx, n, path.Path(fpath))
30
+ p, err := path.ParsePath(fpath)
31
+ if err != nil {
32
+ return nil, err
33
+ }
34
+
35
+ dagnode, err := core.Resolve(ctx, n.Namesys, n.Resolver, p)
36
if err != nil {
37
return nil, fmt.Errorf("pin: %s", err)
38
}
core/coreunix/cat.go
+1
-1
@@ -9,7 +9,7 @@ import (
9
)
10
11
func Cat(ctx context.Context, n *core.IpfsNode, pstr string) (*uio.DagReader, error) {
12
- dagNode, err := core.Resolve(ctx, n, path.Path(pstr))
12
+ dagNode, err := core.Resolve(ctx, n.Namesys, n.Resolver, path.Path(pstr))
13
if err != nil {
14
return nil, err
15
}
core/pathresolver.go
+7
-6
@@ -5,6 +5,7 @@ import (
5
"errors"
6
"strings"
7
8
+ namesys "github.com/ipfs/go-ipfs/namesys"
9
path "github.com/ipfs/go-ipfs/path"
10
11
node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node"
@@ -18,13 +19,13 @@ var ErrNoNamesys = errors.New(
19
20
// Resolve resolves the given path by parsing out protocol-specific
21
// 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) (node.Node, error) {
22
+// entries and returning the final node.
23
+func Resolve(ctx context.Context, nsys namesys.NameSystem, r *path.Resolver, p path.Path) (node.Node, error) {
24
if strings.HasPrefix(p.String(), "/ipns/") {
25
// resolve ipns paths
26
27
// TODO(cryptix): we sould be able to query the local cache for the path
27
- if n.Namesys == nil {
28
+ if nsys == nil {
29
return nil, ErrNoNamesys
30
}
31
@@ -40,7 +41,7 @@ func Resolve(ctx context.Context, n *IpfsNode, p path.Path) (node.Node, error) {
41
return nil, err
42
}
43
43
- respath, err := n.Namesys.Resolve(ctx, resolvable.String())
44
+ respath, err := nsys.Resolve(ctx, resolvable.String())
45
if err != nil {
46
return nil, err
47
}
@@ -53,7 +54,7 @@ func Resolve(ctx context.Context, n *IpfsNode, p path.Path) (node.Node, error) {
54
}
55
56
// ok, we have an ipfs path now (or what we'll treat as one)
56
- return n.Resolver.ResolvePath(ctx, p)
57
+ return r.ResolvePath(ctx, p)
58
}
59
60
// ResolveToKey resolves a path to a key.
@@ -76,7 +77,7 @@ func ResolveToCid(ctx context.Context, n *IpfsNode, p path.Path) (*cid.Cid, erro
77
if err != nil {
78
return nil, err
79
}
79
- dagnode, err := Resolve(ctx, n, head)
80
+ dagnode, err := Resolve(ctx, n.Namesys, n.Resolver, head)
81
if err != nil {
82
return nil, err
83
}
core/pathresolver_test.go
+3
-3
@@ -14,17 +14,17 @@ func TestResolveNoComponents(t *testing.T) {
14
t.Fatal("Should have constructed a mock node", err)
15
}
16
17
- _, err = core.Resolve(n.Context(), n, path.Path("/ipns/"))
17
+ _, err = core.Resolve(n.Context(), n.Namesys, n.Resolver, path.Path("/ipns/"))
18
if err != path.ErrNoComponents {
19
t.Fatal("Should error with no components (/ipns/).", err)
20
}
21
22
- _, err = core.Resolve(n.Context(), n, path.Path("/ipfs/"))
22
+ _, err = core.Resolve(n.Context(), n.Namesys, n.Resolver, path.Path("/ipfs/"))
23
if err != path.ErrNoComponents {
24
t.Fatal("Should error with no components (/ipfs/).", err)
25
}
26
27
- _, err = core.Resolve(n.Context(), n, path.Path("/../.."))
27
+ _, err = core.Resolve(n.Context(), n.Namesys, n.Resolver, path.Path("/../.."))
28
if err != path.ErrBadPath {
29
t.Fatal("Should error with invalid path.", err)
30
}
fuse/ipns/ipns_unix.go
+1
-1
@@ -94,7 +94,7 @@ func loadRoot(ctx context.Context, rt *keyRoot, ipfs *core.IpfsNode, name string
94
return nil, err
95
}
96
97
- node, err := core.Resolve(ctx, ipfs, p)
97
+ node, err := core.Resolve(ctx, ipfs.Namesys, ipfs.Resolver, p)
98
if err != nil {
99
log.Errorf("looking up %s: %s", p, err)
100
return nil, err
path/resolver.go
+24
-7
@@ -7,7 +7,7 @@ import (
7
"fmt"
8
"time"
9
10
- merkledag "github.com/ipfs/go-ipfs/merkledag"
10
+ dag "github.com/ipfs/go-ipfs/merkledag"
11
12
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
13
node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node"
@@ -32,8 +32,19 @@ func (e ErrNoLink) Error() string {
32
33
// Resolver provides path resolution to IPFS
34
// It has a pointer to a DAGService, which is uses to resolve nodes.
35
+// TODO: now that this is more modular, try to unify this code with the
36
+// the resolvers in namesys
37
type Resolver struct {
36
- DAG merkledag.DAGService
38
+ DAG dag.DAGService
39
+
40
+ ResolveOnce func(ctx context.Context, ds dag.DAGService, nd node.Node, name string) (*node.Link, error)
41
+}
42
+
43
+func NewBasicResolver(ds dag.DAGService) *Resolver {
44
+ return &Resolver{
45
+ DAG: ds,
46
+ ResolveOnce: ResolveSingle,
47
+ }
48
}
49
50
// SplitAbsPath clean up and split fpath. It extracts the first component (which
@@ -53,7 +64,9 @@ func SplitAbsPath(fpath Path) (*cid.Cid, []string, error) {
64
}
65
66
c, err := cid.Decode(parts[0])
67
+ // first element in the path is a cid
68
if err != nil {
69
+ log.Debug("given path element is not a cid.\n")
70
return nil, nil, err
71
}
72
@@ -75,6 +88,11 @@ func (s *Resolver) ResolvePath(ctx context.Context, fpath Path) (node.Node, erro
88
return nodes[len(nodes)-1], err
89
}
90
91
+func ResolveSingle(ctx context.Context, ds dag.DAGService, nd node.Node, name string) (*node.Link, error) {
92
+ lnk, _, err := nd.ResolveLink([]string{name})
93
+ return lnk, err
94
+}
95
+
96
// ResolvePathComponents fetches the nodes for each segment of the given path.
97
// It uses the first path component as a hash (key) of the first node, then
98
// resolves all other components walking the links, with ResolveLinks.
@@ -113,21 +131,20 @@ func (s *Resolver) ResolveLinks(ctx context.Context, ndd node.Node, names []stri
131
defer cancel()
132
133
lnk, rest, err := nd.ResolveLink(names)
116
- if err == merkledag.ErrLinkNotFound {
117
- n := nd.Cid()
118
- return result, ErrNoLink{Name: names[0], Node: n}
134
+ if err == dag.ErrLinkNotFound {
135
+ return result, ErrNoLink{Name: names[0], Node: nd.Cid()}
136
} else if err != nil {
137
return result, err
138
}
139
123
- nextnode, err := s.DAG.Get(ctx, lnk.Cid)
140
+ nextnode, err := lnk.GetNode(ctx, s.DAG)
141
if err != nil {
142
return result, err
143
}
144
145
nd = nextnode
129
- names = rest
146
result = append(result, nextnode)
147
+ names = rest
148
}
149
return result, nil
150
}
path/resolver_test.go
+1
-1
@@ -55,7 +55,7 @@ func TestRecurivePathResolution(t *testing.T) {
55
t.Fatal(err)
56
}
57
58
- resolver := &path.Resolver{DAG: dagService}
58
+ resolver := path.NewBasicResolver(dagService)
59
node, err := resolver.ResolvePath(ctx, p)
60
if err != nil {
61
t.Fatal(err)
unixfs/io/resolve.go
new
+46
@@ -0,0 +1,46 @@
1
+package io
2
+
3
+import (
4
+ "context"
5
+
6
+ dag "github.com/ipfs/go-ipfs/merkledag"
7
+ ft "github.com/ipfs/go-ipfs/unixfs"
8
+
9
+ node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node"
10
+)
11
+
12
+func ResolveUnixfsOnce(ctx context.Context, ds dag.DAGService, nd node.Node, name string) (*node.Link, error) {
13
+ pbnd, ok := nd.(*dag.ProtoNode)
14
+ if !ok {
15
+ lnk, _, err := nd.ResolveLink([]string{name})
16
+ return lnk, err
17
+ }
18
+
19
+ upb, err := ft.FromBytes(pbnd.Data())
20
+ if err != nil {
21
+ // Not a unixfs node, use standard object traversal code
22
+ lnk, _, err := nd.ResolveLink([]string{name})
23
+ return lnk, err
24
+ }
25
+
26
+ switch upb.GetType() {
27
+ /*
28
+ case ft.THAMTShard:
29
+ s, err := hamt.NewHamtFromDag(ds, nd)
30
+ if err != nil {
31
+ return nil, err
32
+ }
33
+
34
+ // TODO: optimized routine on HAMT for returning a dag.Link to avoid extra disk hits
35
+ out, err := s.Find(ctx, name)
36
+ if err != nil {
37
+ return nil, err
38
+ }
39
+
40
+ return dag.MakeLink(out)
41
+ */
42
+ default:
43
+ lnk, _, err := nd.ResolveLink([]string{name})
44
+ return lnk, err
45
+ }
46
+}