@cryptotaxi247 / kubo / commits / 93d1a695d

Feat: Separate "path" from "path/resolver"

Currently the "path" module does two very different things: * Defines how ipfs paths look like and provides tools to parse/split etc. * Provides a resolver to resolve paths. This moves the resolver stuff to `path/resolver` and leaves the path utilities in `path`. The result is that now the IPFS `path` package just defines what a path looks like and becomes a module that can be exported/re-used without problems. Currently there are circular dependency cycles (resolve_test -> merkledag/utils, merkledag->path), which the prevent the export of merkledag itself. License: MIT Signed-off-by: Hector Sanjuan <hector@protocol.ai>

Hector Sanjuan committed Feb 16, 2018 at 00:09 UTC 93d1a695d49867fcd530cd236ed6dd43ab454c50
14 files changed +71 -56
core/builder.go
+2 -2
@@ -13,7 +13,7 @@ import (
13 offline "github.com/ipfs/go-ipfs/exchange/offline"
14 filestore "github.com/ipfs/go-ipfs/filestore"
15 dag "github.com/ipfs/go-ipfs/merkledag"
16 - path "github.com/ipfs/go-ipfs/path"
16 + resolver "github.com/ipfs/go-ipfs/path/resolver"
17 pin "github.com/ipfs/go-ipfs/pin"
18 repo "github.com/ipfs/go-ipfs/repo"
19 cfg "github.com/ipfs/go-ipfs/repo/config"
@@ -230,7 +230,7 @@ func setupNode(ctx context.Context, n *IpfsNode, cfg *BuildCfg) error {
230 // this is kinda sketchy and could cause data loss
231 n.Pinning = pin.NewPinner(n.Repo.Datastore(), n.DAG, internalDag)
232 }
233 - n.Resolver = path.NewBasicResolver(n.DAG)
233 + n.Resolver = resolver.NewBasicResolver(n.DAG)
234
235 if cfg.Online {
236 if err := n.startLateOnlineServices(ctx); err != nil {
core/commands/files.go
+2 -1
@@ -19,6 +19,7 @@ import (
19 dag "github.com/ipfs/go-ipfs/merkledag"
20 mfs "github.com/ipfs/go-ipfs/mfs"
21 path "github.com/ipfs/go-ipfs/path"
22 + resolver "github.com/ipfs/go-ipfs/path/resolver"
23 ft "github.com/ipfs/go-ipfs/unixfs"
24 uio "github.com/ipfs/go-ipfs/unixfs/io"
25
@@ -352,7 +353,7 @@ func getNodeFromPath(ctx context.Context, node *core.IpfsNode, p string) (ipld.N
353 return nil, err
354 }
355
355 - resolver := &path.Resolver{
356 + resolver := &resolver.Resolver{
357 DAG: node.DAG,
358 ResolveOnce: uio.ResolveUnixfsOnce,
359 }
core/commands/ls.go
+2 -1
@@ -13,6 +13,7 @@ import (
13 offline "github.com/ipfs/go-ipfs/exchange/offline"
14 merkledag "github.com/ipfs/go-ipfs/merkledag"
15 path "github.com/ipfs/go-ipfs/path"
16 + resolver "github.com/ipfs/go-ipfs/path/resolver"
17 unixfs "github.com/ipfs/go-ipfs/unixfs"
18 uio "github.com/ipfs/go-ipfs/unixfs/io"
19 unixfspb "github.com/ipfs/go-ipfs/unixfs/pb"
@@ -92,7 +93,7 @@ The JSON output contains type information.
93 return
94 }
95
95 - r := &path.Resolver{
96 + r := &resolver.Resolver{
97 DAG: nd.DAG,
98 ResolveOnce: uio.ResolveUnixfsOnce,
99 }
core/commands/pin.go
+3 -2
@@ -15,6 +15,7 @@ import (
15 offline "github.com/ipfs/go-ipfs/exchange/offline"
16 dag "github.com/ipfs/go-ipfs/merkledag"
17 path "github.com/ipfs/go-ipfs/path"
18 + resolver "github.com/ipfs/go-ipfs/path/resolver"
19 pin "github.com/ipfs/go-ipfs/pin"
20 uio "github.com/ipfs/go-ipfs/unixfs/io"
21
@@ -387,7 +388,7 @@ new pin and removing the old one.
388 return
389 }
390
390 - r := &path.Resolver{
391 + r := &resolver.Resolver{
392 DAG: n.DAG,
393 ResolveOnce: uio.ResolveUnixfsOnce,
394 }
@@ -501,7 +502,7 @@ func pinLsKeys(args []string, typeStr string, ctx context.Context, n *core.IpfsN
502
503 keys := make(map[string]RefKeyObject)
504
504 - r := &path.Resolver{
505 + r := &resolver.Resolver{
506 DAG: n.DAG,
507 ResolveOnce: uio.ResolveUnixfsOnce,
508 }
core/commands/unixfs/ls.go
+4 -2
@@ -7,15 +7,17 @@ import (
7 "sort"
8 "text/tabwriter"
9
10 + cmdkit "gx/ipfs/QmceUdzxkimdYsgtX733uNgzf1DLHyBKN6ehGSp85ayppM/go-ipfs-cmdkit"
11 +
12 cmds "github.com/ipfs/go-ipfs/commands"
13 core "github.com/ipfs/go-ipfs/core"
14 e "github.com/ipfs/go-ipfs/core/commands/e"
15 merkledag "github.com/ipfs/go-ipfs/merkledag"
16 path "github.com/ipfs/go-ipfs/path"
17 + resolver "github.com/ipfs/go-ipfs/path/resolver"
18 unixfs "github.com/ipfs/go-ipfs/unixfs"
19 uio "github.com/ipfs/go-ipfs/unixfs/io"
20 unixfspb "github.com/ipfs/go-ipfs/unixfs/pb"
18 - cmdkit "gx/ipfs/QmceUdzxkimdYsgtX733uNgzf1DLHyBKN6ehGSp85ayppM/go-ipfs-cmdkit"
21 )
22
23 type LsLink struct {
@@ -91,7 +93,7 @@ possible, please use 'ipfs ls' instead.
93 for _, fpath := range paths {
94 ctx := req.Context()
95
94 - resolver := &path.Resolver{
96 + resolver := &resolver.Resolver{
97 DAG: node.DAG,
98 ResolveOnce: uio.ResolveUnixfsOnce,
99 }
core/core.go
+2 -2
@@ -33,7 +33,7 @@ import (
33 namesys "github.com/ipfs/go-ipfs/namesys"
34 ipnsrp "github.com/ipfs/go-ipfs/namesys/republisher"
35 p2p "github.com/ipfs/go-ipfs/p2p"
36 - path "github.com/ipfs/go-ipfs/path"
36 + "github.com/ipfs/go-ipfs/path/resolver"
37 pin "github.com/ipfs/go-ipfs/pin"
38 repo "github.com/ipfs/go-ipfs/repo"
39 config "github.com/ipfs/go-ipfs/repo/config"
@@ -119,7 +119,7 @@ type IpfsNode struct {
119 GCLocker bstore.GCLocker // the locker used to protect the blockstore during gc
120 Blocks bserv.BlockService // the block service, get/add blocks.
121 DAG ipld.DAGService // the merkle dag service, get/add objects.
122 - Resolver *path.Resolver // the path resolution system
122 + Resolver *resolver.Resolver // the path resolution system
123 Reporter metrics.Reporter
124 Discovery discovery.Service
125 FilesRoot *mfs.Root
core/coreapi/coreapi.go
+2 -1
@@ -7,6 +7,7 @@ import (
7 coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
8 namesys "github.com/ipfs/go-ipfs/namesys"
9 ipfspath "github.com/ipfs/go-ipfs/path"
10 + resolver "github.com/ipfs/go-ipfs/path/resolver"
11 uio "github.com/ipfs/go-ipfs/unixfs/io"
12
13 cid "gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid"
@@ -87,7 +88,7 @@ func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSyste
88 return p, nil
89 }
90
90 - r := &ipfspath.Resolver{
91 + r := &resolver.Resolver{
92 DAG: ng,
93 ResolveOnce: uio.ResolveUnixfsOnce,
94 }
core/corehttp/gateway_handler.go
+3 -2
@@ -19,6 +19,7 @@ import (
19 dag "github.com/ipfs/go-ipfs/merkledag"
20 dagutils "github.com/ipfs/go-ipfs/merkledag/utils"
21 path "github.com/ipfs/go-ipfs/path"
22 + resolver "github.com/ipfs/go-ipfs/path/resolver"
23 ft "github.com/ipfs/go-ipfs/unixfs"
24 uio "github.com/ipfs/go-ipfs/unixfs/io"
25
@@ -445,7 +446,7 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
446 var newcid *cid.Cid
447 rnode, err := core.Resolve(ctx, i.node.Namesys, i.node.Resolver, rootPath)
448 switch ev := err.(type) {
448 - case path.ErrNoLink:
449 + case resolver.ErrNoLink:
450 // ev.Node < node where resolve failed
451 // ev.Name < new link
452 // but we need to patch from the root
@@ -599,7 +600,7 @@ func (i *gatewayHandler) addUserHeaders(w http.ResponseWriter) {
600 }
601
602 func webError(w http.ResponseWriter, message string, err error, defaultCode int) {
602 - if _, ok := err.(path.ErrNoLink); ok {
603 + if _, ok := err.(resolver.ErrNoLink); ok {
604 webErrorWithCode(w, message, err, http.StatusNotFound)
605 } else if err == routing.ErrNotFound {
606 webErrorWithCode(w, message, err, http.StatusNotFound)
core/corerepo/pinning.go
+3 -2
@@ -19,6 +19,7 @@ import (
19
20 "github.com/ipfs/go-ipfs/core"
21 path "github.com/ipfs/go-ipfs/path"
22 + resolver "github.com/ipfs/go-ipfs/path/resolver"
23 uio "github.com/ipfs/go-ipfs/unixfs/io"
24
25 cid "gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid"
@@ -27,7 +28,7 @@ import (
28 func Pin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) ([]*cid.Cid, error) {
29 out := make([]*cid.Cid, len(paths))
30
30 - r := &path.Resolver{
31 + r := &resolver.Resolver{
32 DAG: n.DAG,
33 ResolveOnce: uio.ResolveUnixfsOnce,
34 }
@@ -60,7 +61,7 @@ func Pin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool)
61 func Unpin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) ([]*cid.Cid, error) {
62 unpinned := make([]*cid.Cid, len(paths))
63
63 - r := &path.Resolver{
64 + r := &resolver.Resolver{
65 DAG: n.DAG,
66 ResolveOnce: uio.ResolveUnixfsOnce,
67 }
core/coreunix/cat.go
+2 -1
@@ -5,11 +5,12 @@ import (
5
6 core "github.com/ipfs/go-ipfs/core"
7 path "github.com/ipfs/go-ipfs/path"
8 + resolver "github.com/ipfs/go-ipfs/path/resolver"
9 uio "github.com/ipfs/go-ipfs/unixfs/io"
10 )
11
12 func Cat(ctx context.Context, n *core.IpfsNode, pstr string) (uio.DagReader, error) {
12 - r := &path.Resolver{
13 + r := &resolver.Resolver{
14 DAG: n.DAG,
15 ResolveOnce: uio.ResolveUnixfsOnce,
16 }
core/pathresolver.go
+3 -2
@@ -7,6 +7,7 @@ import (
7
8 namesys "github.com/ipfs/go-ipfs/namesys"
9 path "github.com/ipfs/go-ipfs/path"
10 + resolver "github.com/ipfs/go-ipfs/path/resolver"
11
12 logging "gx/ipfs/QmRb5jh8z2E8hMGN2tkvs1yHynUanqnZ3UeKwgN1i9P1F8/go-log"
13 cid "gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid"
@@ -21,7 +22,7 @@ var ErrNoNamesys = errors.New(
22 // Resolve resolves the given path by parsing out protocol-specific
23 // entries (e.g. /ipns/<node-key>) and then going through the /ipfs/
24 // entries and returning the final node.
24 -func Resolve(ctx context.Context, nsys namesys.NameSystem, r *path.Resolver, p path.Path) (ipld.Node, error) {
25 +func Resolve(ctx context.Context, nsys namesys.NameSystem, r *resolver.Resolver, p path.Path) (ipld.Node, error) {
26 if strings.HasPrefix(p.String(), "/ipns/") {
27 evt := log.EventBegin(ctx, "resolveIpnsPath")
28 defer evt.Done()
@@ -70,7 +71,7 @@ func Resolve(ctx context.Context, nsys namesys.NameSystem, r *path.Resolver, p p
71 // It first checks if the path is already in the form of just a cid (<cid> or
72 // /ipfs/<cid>) and returns immediately if so. Otherwise, it falls back onto
73 // Resolve to perform resolution of the dagnode being referenced.
73 -func ResolveToCid(ctx context.Context, nsys namesys.NameSystem, r *path.Resolver, p path.Path) (*cid.Cid, error) {
74 +func ResolveToCid(ctx context.Context, nsys namesys.NameSystem, r *resolver.Resolver, p path.Path) (*cid.Cid, error) {
75
76 // If the path is simply a cid, parse and return it. Parsed paths are already
77 // normalized (read: prepended with /ipfs/ if needed), so segment[1] should
path/path.go
+31 -2
@@ -9,8 +9,15 @@ import (
9 cid "gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid"
10 )
11
12 -// ErrBadPath is returned when a given path is incorrectly formatted
13 -var ErrBadPath = errors.New("invalid 'ipfs ref' path")
12 +var (
13 + // ErrBadPath is returned when a given path is incorrectly formatted
14 + ErrBadPath = errors.New("invalid 'ipfs ref' path")
15 +
16 + // ErrNoComponents is used when Paths after a protocol
17 + // do not contain at least one component
18 + ErrNoComponents = errors.New(
19 + "path must contain at least one component")
20 +)
21
22 // A Path represents an ipfs content path:
23 // * /<cid>/path/to/file
@@ -149,3 +156,25 @@ func Join(pths []string) string {
156 func SplitList(pth string) []string {
157 return strings.Split(pth, "/")
158 }
159 +
160 +// SplitAbsPath clean up and split fpath. It extracts the first component (which
161 +// must be a Multihash) and return it separately.
162 +func SplitAbsPath(fpath Path) (*cid.Cid, []string, error) {
163 + parts := fpath.Segments()
164 + if parts[0] == "ipfs" {
165 + parts = parts[1:]
166 + }
167 +
168 + // if nothing, bail.
169 + if len(parts) == 0 {
170 + return nil, nil, ErrNoComponents
171 + }
172 +
173 + c, err := cid.Decode(parts[0])
174 + // first element in the path is a cid
175 + if err != nil {
176 + return nil, nil, err
177 + }
178 +
179 + return c, parts[1:], nil
180 +}
path/resolver/resolver.go renamed
+9 -34
@@ -1,5 +1,5 @@
1 -// Package path implements utilities for resolving paths within ipfs.
2 -package path
1 +// Package resolver implements utilities for resolving paths within ipfs.
2 +package resolver
3
4 import (
5 "context"
@@ -8,13 +8,14 @@ import (
8 "time"
9
10 dag "github.com/ipfs/go-ipfs/merkledag"
11 + path "github.com/ipfs/go-ipfs/path"
12
13 logging "gx/ipfs/QmRb5jh8z2E8hMGN2tkvs1yHynUanqnZ3UeKwgN1i9P1F8/go-log"
14 cid "gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid"
15 ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
16 )
17
17 -var log = logging.Logger("path")
18 +var log = logging.Logger("pathresolv")
19
20 // ErrNoComponents is used when Paths after a protocol
21 // do not contain at least one component
@@ -51,36 +52,10 @@ func NewBasicResolver(ds ipld.DAGService) *Resolver {
52 }
53 }
54
54 -// SplitAbsPath clean up and split fpath. It extracts the first component (which
55 -// must be a Multihash) and return it separately.
56 -func SplitAbsPath(fpath Path) (*cid.Cid, []string, error) {
57 -
58 - log.Debugf("Resolve: '%s'", fpath)
59 -
60 - parts := fpath.Segments()
61 - if parts[0] == "ipfs" {
62 - parts = parts[1:]
63 - }
64 -
65 - // if nothing, bail.
66 - if len(parts) == 0 {
67 - return nil, nil, ErrNoComponents
68 - }
69 -
70 - c, err := cid.Decode(parts[0])
71 - // first element in the path is a cid
72 - if err != nil {
73 - log.Debug("given path element is not a cid.\n")
74 - return nil, nil, err
75 - }
76 -
77 - return c, parts[1:], nil
78 -}
79 -
55 // ResolveToLastNode walks the given path and returns the ipld.Node
56 // referenced by the last element in it.
82 -func (r *Resolver) ResolveToLastNode(ctx context.Context, fpath Path) (ipld.Node, []string, error) {
83 - c, p, err := SplitAbsPath(fpath)
57 +func (r *Resolver) ResolveToLastNode(ctx context.Context, fpath path.Path) (ipld.Node, []string, error) {
58 + c, p, err := path.SplitAbsPath(fpath)
59 if err != nil {
60 return nil, nil, err
61 }
@@ -114,7 +89,7 @@ func (r *Resolver) ResolveToLastNode(ctx context.Context, fpath Path) (ipld.Node
89
90 // ResolvePath fetches the node for given path. It returns the last item
91 // returned by ResolvePathComponents.
117 -func (r *Resolver) ResolvePath(ctx context.Context, fpath Path) (ipld.Node, error) {
92 +func (r *Resolver) ResolvePath(ctx context.Context, fpath path.Path) (ipld.Node, error) {
93 // validate path
94 if err := fpath.IsValid(); err != nil {
95 return nil, err
@@ -136,11 +111,11 @@ func ResolveSingle(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names
111 // ResolvePathComponents fetches the nodes for each segment of the given path.
112 // It uses the first path component as a hash (key) of the first node, then
113 // resolves all other components walking the links, with ResolveLinks.
139 -func (r *Resolver) ResolvePathComponents(ctx context.Context, fpath Path) ([]ipld.Node, error) {
114 +func (r *Resolver) ResolvePathComponents(ctx context.Context, fpath path.Path) ([]ipld.Node, error) {
115 evt := log.EventBegin(ctx, "resolvePathComponents", logging.LoggableMap{"fpath": fpath})
116 defer evt.Done()
117
143 - h, parts, err := SplitAbsPath(fpath)
118 + h, parts, err := path.SplitAbsPath(fpath)
119 if err != nil {
120 evt.Append(logging.LoggableMap{"error": err.Error()})
121 return nil, err
path/resolver/resolver_test.go renamed
+3 -2
@@ -1,4 +1,4 @@
1 -package path_test
1 +package resolver_test
2
3 import (
4 "context"
@@ -8,6 +8,7 @@ import (
8 merkledag "github.com/ipfs/go-ipfs/merkledag"
9 dagmock "github.com/ipfs/go-ipfs/merkledag/test"
10 path "github.com/ipfs/go-ipfs/path"
11 + "github.com/ipfs/go-ipfs/path/resolver"
12
13 util "gx/ipfs/QmNiJuT8Ja3hMVpBHXv3Q6dwmperaQ6JjLtpMQgMCD7xvx/go-ipfs-util"
14 ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
@@ -53,7 +54,7 @@ func TestRecurivePathResolution(t *testing.T) {
54 t.Fatal(err)
55 }
56
56 - resolver := path.NewBasicResolver(dagService)
57 + resolver := resolver.NewBasicResolver(dagService)
58 node, err := resolver.ResolvePath(ctx, p)
59 if err != nil {
60 t.Fatal(err)