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)