From 338e90e9c8391828b362b84624811c764d14313b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 2 Feb 2018 16:00:37 +0100 Subject: [PATCH 01/15] coreapi: expand public path api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/block.go | 4 ++-- core/coreapi/coreapi.go | 20 +++++++++++++---- core/coreapi/dag.go | 4 ++-- core/coreapi/dag_test.go | 4 +--- core/coreapi/interface/coreapi.go | 13 +++++++++++ core/coreapi/interface/options/path.go | 30 ++++++++++++++++++++++++++ core/coreapi/object.go | 8 +++---- core/coreapi/pin.go | 28 +++++++++++------------- core/coreapi/unixfs.go | 2 +- core/coreapi/unixfs_test.go | 6 +++--- core/corehttp/gateway_handler.go | 5 ++--- 11 files changed, 87 insertions(+), 37 deletions(-) create mode 100644 core/coreapi/interface/options/path.go diff --git a/core/coreapi/block.go b/core/coreapi/block.go index 497b0099c84..88df76d9b91 100644 --- a/core/coreapi/block.go +++ b/core/coreapi/block.go @@ -65,7 +65,7 @@ func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Bloc return nil, err } - return ParseCid(b.Cid()), nil + return api.ParseCid(b.Cid()), nil } func (api *BlockAPI) Get(ctx context.Context, p coreiface.Path) (io.Reader, error) { @@ -117,7 +117,7 @@ func (api *BlockAPI) Stat(ctx context.Context, p coreiface.Path) (coreiface.Bloc } return &BlockStat{ - path: ParseCid(b.Cid()), + path: api.ParseCid(b.Cid()), size: len(b.RawData()), }, nil } diff --git a/core/coreapi/coreapi.go b/core/coreapi/coreapi.go index 22c13b84ecc..71aa8e75f41 100644 --- a/core/coreapi/coreapi.go +++ b/core/coreapi/coreapi.go @@ -18,6 +18,7 @@ import ( core "github.com/ipfs/go-ipfs/core" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" + caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options" namesys "github.com/ipfs/go-ipfs/namesys" ipfspath "github.com/ipfs/go-ipfs/path" resolver "github.com/ipfs/go-ipfs/path/resolver" @@ -29,11 +30,12 @@ import ( type CoreAPI struct { node *core.IpfsNode + *caopts.ApiOptions } // NewCoreAPI creates new instance of IPFS CoreAPI backed by go-ipfs Node. func NewCoreAPI(n *core.IpfsNode) coreiface.CoreAPI { - api := &CoreAPI{n} + api := &CoreAPI{n, nil} return api } @@ -132,16 +134,26 @@ type path struct { } // ParsePath parses path `p` using ipfspath parser, returns the parsed path. -func ParsePath(p string) (coreiface.Path, error) { +func (api *CoreAPI) ParsePath(ctx context.Context, p string, opts ...caopts.ParsePathOption) (coreiface.Path, error) { + options, err := caopts.ParsePathOptions(opts...) + if err != nil { + return nil, err + } + pp, err := ipfspath.ParsePath(p) if err != nil { return nil, err } - return &path{path: pp}, nil + + res := &path{path: pp} + if options.Resolve { + return api.ResolvePath(ctx, res) + } + return res, nil } // ParseCid parses the path from `c`, returns the parsed path. -func ParseCid(c *cid.Cid) coreiface.Path { +func (api *CoreAPI) ParseCid(c *cid.Cid) coreiface.Path { return &path{path: ipfspath.FromCid(c), cid: c, root: c} } diff --git a/core/coreapi/dag.go b/core/coreapi/dag.go index 9e9be2d9f4e..3f0b404f584 100644 --- a/core/coreapi/dag.go +++ b/core/coreapi/dag.go @@ -44,7 +44,7 @@ func (api *DagAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.DagPut return nil, err } - return ParseCid(nds[0].Cid()), nil + return api.ParseCid(nds[0].Cid()), nil } // Get resolves `path` using Unixfs resolver, returns the resolved Node. @@ -66,7 +66,7 @@ func (api *DagAPI) Tree(ctx context.Context, p coreiface.Path, opts ...caopts.Da paths := n.Tree("", settings.Depth) out := make([]coreiface.Path, len(paths)) for n, p2 := range paths { - out[n], err = ParsePath(gopath.Join(p.String(), p2)) + out[n], err = api.ParsePath(ctx, gopath.Join(p.String(), p2)) if err != nil { return nil, err } diff --git a/core/coreapi/dag_test.go b/core/coreapi/dag_test.go index ef7190104b0..ad6511c994f 100644 --- a/core/coreapi/dag_test.go +++ b/core/coreapi/dag_test.go @@ -6,8 +6,6 @@ import ( "strings" "testing" - coreapi "github.com/ipfs/go-ipfs/core/coreapi" - mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" opt "github.com/ipfs/go-ipfs/core/coreapi/interface/options" @@ -74,7 +72,7 @@ func TestPath(t *testing.T) { t.Error(err) } - p, err := coreapi.ParsePath(path.Join(res.Cid().String(), "lnk")) + p, err := api.ParsePath(ctx, path.Join(res.Cid().String(), "lnk")) if err != nil { t.Error(err) } diff --git a/core/coreapi/interface/coreapi.go b/core/coreapi/interface/coreapi.go index a77ad636720..179531352d4 100644 --- a/core/coreapi/interface/coreapi.go +++ b/core/coreapi/interface/coreapi.go @@ -5,6 +5,9 @@ package iface import ( "context" + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" + + cid "gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid" ipld "gx/ipfs/QmZtNq8dArGfnpCZfx2pUNY7UcjGhVp5qqwQ4hH6mpTMRQ/go-ipld-format" ) @@ -37,4 +40,14 @@ type CoreAPI interface { // ResolveNode resolves the path (if not resolved already) using Unixfs // resolver, gets and returns the resolved Node ResolveNode(context.Context, Path) (ipld.Node, error) + + // ParsePath parses string path to a Path + ParsePath(context.Context, string, ...options.ParsePathOption) (Path, error) + + // WithResolve is an option for ParsePath which when set to true tells + // ParsePath to also resolve the path + WithResolve(bool) options.ParsePathOption + + // ParseCid creates new path from the provided CID + ParseCid(*cid.Cid) Path } diff --git a/core/coreapi/interface/options/path.go b/core/coreapi/interface/options/path.go new file mode 100644 index 00000000000..bf6eed65b8c --- /dev/null +++ b/core/coreapi/interface/options/path.go @@ -0,0 +1,30 @@ +package options + +type ParsePathSettings struct { + Resolve bool +} + +type ParsePathOption func(*ParsePathSettings) error + +func ParsePathOptions(opts ...ParsePathOption) (*ParsePathSettings, error) { + options := &ParsePathSettings{ + Resolve: false, + } + + for _, opt := range opts { + err := opt(options) + if err != nil { + return nil, err + } + } + return options, nil +} + +type ApiOptions struct{} + +func (api *ApiOptions) WithResolve(r bool) ParsePathOption { + return func(settings *ParsePathSettings) error { + settings.Resolve = r + return nil + } +} diff --git a/core/coreapi/object.go b/core/coreapi/object.go index 5919a24330a..dc192e446f3 100644 --- a/core/coreapi/object.go +++ b/core/coreapi/object.go @@ -121,7 +121,7 @@ func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Obj return nil, err } - return ParseCid(dagnode.Cid()), nil + return api.ParseCid(dagnode.Cid()), nil } func (api *ObjectAPI) Get(ctx context.Context, path coreiface.Path) (ipld.Node, error) { @@ -218,7 +218,7 @@ func (api *ObjectAPI) AddLink(ctx context.Context, base coreiface.Path, name str return nil, err } - return ParseCid(nnode.Cid()), nil + return api.ParseCid(nnode.Cid()), nil } func (api *ObjectAPI) RmLink(ctx context.Context, base coreiface.Path, link string) (coreiface.Path, error) { @@ -244,7 +244,7 @@ func (api *ObjectAPI) RmLink(ctx context.Context, base coreiface.Path, link stri return nil, err } - return ParseCid(nnode.Cid()), nil + return api.ParseCid(nnode.Cid()), nil } func (api *ObjectAPI) AppendData(ctx context.Context, path coreiface.Path, r io.Reader) (coreiface.Path, error) { @@ -281,7 +281,7 @@ func (api *ObjectAPI) patchData(ctx context.Context, path coreiface.Path, r io.R return nil, err } - return ParseCid(pbnd.Cid()), nil + return api.ParseCid(pbnd.Cid()), nil } func (api *ObjectAPI) core() coreiface.CoreAPI { diff --git a/core/coreapi/pin.go b/core/coreapi/pin.go index 13013f583c6..8d0eaa77d48 100644 --- a/core/coreapi/pin.go +++ b/core/coreapi/pin.go @@ -9,11 +9,9 @@ import ( caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options" corerepo "github.com/ipfs/go-ipfs/core/corerepo" merkledag "github.com/ipfs/go-ipfs/merkledag" - pin "github.com/ipfs/go-ipfs/pin" offline "gx/ipfs/QmShbyKV9P7QuFecDHXsgrQ4rxxm71MUkGVpwedT4VQ8Bf/go-ipfs-exchange-offline" cid "gx/ipfs/QmYVNvtQkeZ6AKSwDrjQTs432QtL6umrrK41EBq3cu7iSP/go-cid" - ipld "gx/ipfs/QmZtNq8dArGfnpCZfx2pUNY7UcjGhVp5qqwQ4hH6mpTMRQ/go-ipld-format" ) type PinAPI CoreAPI @@ -46,7 +44,7 @@ func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) ([]coreif return nil, fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", settings.Type) } - return pinLsAll(settings.Type, ctx, api.node.Pinning, api.node.DAG) + return api.pinLsAll(settings.Type, ctx) } func (api *PinAPI) Rm(ctx context.Context, p coreiface.Path) error { @@ -75,8 +73,8 @@ type pinStatus struct { // BadNode is used in PinVerifyRes type badNode struct { - cid *cid.Cid - err error + path coreiface.Path + err error } func (s *pinStatus) Ok() bool { @@ -88,7 +86,7 @@ func (s *pinStatus) BadNodes() []coreiface.BadPinNode { } func (n *badNode) Path() coreiface.Path { - return ParseCid(n.cid) + return n.path } func (n *badNode) Err() error { @@ -112,7 +110,7 @@ func (api *PinAPI) Verify(ctx context.Context) (<-chan coreiface.PinStatus, erro links, err := getLinks(ctx, root) if err != nil { status := &pinStatus{ok: false, cid: root} - status.badNodes = []coreiface.BadPinNode{&badNode{cid: root, err: err}} + status.badNodes = []coreiface.BadPinNode{&badNode{path: api.ParseCid(root), err: err}} visited[key] = status return status } @@ -143,18 +141,18 @@ func (api *PinAPI) Verify(ctx context.Context) (<-chan coreiface.PinStatus, erro type pinInfo struct { pinType string - object *cid.Cid + object coreiface.Path } func (p *pinInfo) Path() coreiface.Path { - return ParseCid(p.object) + return p.object } func (p *pinInfo) Type() string { return p.pinType } -func pinLsAll(typeStr string, ctx context.Context, pinning pin.Pinner, dag ipld.DAGService) ([]coreiface.Pin, error) { +func (api *PinAPI) pinLsAll(typeStr string, ctx context.Context) ([]coreiface.Pin, error) { keys := make(map[string]*pinInfo) @@ -162,18 +160,18 @@ func pinLsAll(typeStr string, ctx context.Context, pinning pin.Pinner, dag ipld. for _, c := range keyList { keys[c.String()] = &pinInfo{ pinType: typeStr, - object: c, + object: api.ParseCid(c), } } } if typeStr == "direct" || typeStr == "all" { - AddToResultKeys(pinning.DirectKeys(), "direct") + AddToResultKeys(api.node.Pinning.DirectKeys(), "direct") } if typeStr == "indirect" || typeStr == "all" { set := cid.NewSet() - for _, k := range pinning.RecursiveKeys() { - err := merkledag.EnumerateChildren(ctx, merkledag.GetLinksWithDAG(dag), k, set.Visit) + for _, k := range api.node.Pinning.RecursiveKeys() { + err := merkledag.EnumerateChildren(ctx, merkledag.GetLinksWithDAG(api.node.DAG), k, set.Visit) if err != nil { return nil, err } @@ -181,7 +179,7 @@ func pinLsAll(typeStr string, ctx context.Context, pinning pin.Pinner, dag ipld. AddToResultKeys(set.Keys(), "indirect") } if typeStr == "recursive" || typeStr == "all" { - AddToResultKeys(pinning.RecursiveKeys(), "recursive") + AddToResultKeys(api.node.Pinning.RecursiveKeys(), "recursive") } out := make([]coreiface.Pin, 0, len(keys)) diff --git a/core/coreapi/unixfs.go b/core/coreapi/unixfs.go index 51b58404cd8..d104f88e6b5 100644 --- a/core/coreapi/unixfs.go +++ b/core/coreapi/unixfs.go @@ -25,7 +25,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, r io.Reader) (coreiface.Path, err if err != nil { return nil, err } - return ParseCid(c), nil + return api.core().ParseCid(c), nil } // Cat returns the data contained by an IPFS or IPNS object(s) at path `p`. diff --git a/core/coreapi/unixfs_test.go b/core/coreapi/unixfs_test.go index c8ea4bc59b8..b7cba704cc5 100644 --- a/core/coreapi/unixfs_test.go +++ b/core/coreapi/unixfs_test.go @@ -206,7 +206,7 @@ func TestCatDir(t *testing.T) { if err != nil { t.Error(err) } - p := coreapi.ParseCid(edir.Cid()) + p := api.ParseCid(edir.Cid()) if p.String() != emptyDir.String() { t.Fatalf("expected path %s, got: %s", emptyDir, p) @@ -231,7 +231,7 @@ func TestCatNonUnixfs(t *testing.T) { t.Error(err) } - _, err = api.Unixfs().Cat(ctx, coreapi.ParseCid(nd.Cid())) + _, err = api.Unixfs().Cat(ctx, api.ParseCid(nd.Cid())) if !strings.Contains(err.Error(), "proto: required field") { t.Fatalf("expected protobuf error, got: %s", err) } @@ -327,7 +327,7 @@ func TestLsNonUnixfs(t *testing.T) { t.Error(err) } - links, err := api.Unixfs().Ls(ctx, coreapi.ParseCid(nd.Cid())) + links, err := api.Unixfs().Ls(ctx, api.ParseCid(nd.Cid())) if err != nil { t.Error(err) } diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index a53c71f2a19..2f0303d26ef 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -13,7 +13,6 @@ import ( "time" core "github.com/ipfs/go-ipfs/core" - coreapi "github.com/ipfs/go-ipfs/core/coreapi" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" "github.com/ipfs/go-ipfs/importer" dag "github.com/ipfs/go-ipfs/merkledag" @@ -160,7 +159,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr ipnsHostname = true } - parsedPath, err := coreapi.ParsePath(urlPath) + parsedPath, err := i.api.ParsePath(ctx, urlPath) if err != nil { webError(w, "invalid ipfs path", err, http.StatusBadRequest) return @@ -288,7 +287,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr return } - dr, err := i.api.Unixfs().Cat(ctx, coreapi.ParseCid(ixnd.Cid())) + dr, err := i.api.Unixfs().Cat(ctx, i.api.ParseCid(ixnd.Cid())) if err != nil { internalWebError(w, err) return From 4f6c0666ea40128025fa1feb355f0036941bd549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 8 Feb 2018 02:25:30 +0100 Subject: [PATCH 02/15] coreapi: move path impl to path.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/coreapi.go | 102 ------------------------------------- core/coreapi/path.go | 109 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 102 deletions(-) create mode 100644 core/coreapi/path.go diff --git a/core/coreapi/coreapi.go b/core/coreapi/coreapi.go index 71aa8e75f41..151f1fe343b 100644 --- a/core/coreapi/coreapi.go +++ b/core/coreapi/coreapi.go @@ -14,18 +14,9 @@ Interfaces here aren't yet completely stable. package coreapi import ( - "context" - core "github.com/ipfs/go-ipfs/core" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options" - namesys "github.com/ipfs/go-ipfs/namesys" - ipfspath "github.com/ipfs/go-ipfs/path" - resolver "github.com/ipfs/go-ipfs/path/resolver" - uio "github.com/ipfs/go-ipfs/unixfs/io" - - cid "gx/ipfs/QmYVNvtQkeZ6AKSwDrjQTs432QtL6umrrK41EBq3cu7iSP/go-cid" - ipld "gx/ipfs/QmZtNq8dArGfnpCZfx2pUNY7UcjGhVp5qqwQ4hH6mpTMRQ/go-ipld-format" ) type CoreAPI struct { @@ -73,96 +64,3 @@ func (api *CoreAPI) Object() coreiface.ObjectAPI { func (api *CoreAPI) Pin() coreiface.PinAPI { return (*PinAPI)(api) } - -// ResolveNode resolves the path `p` using Unixfx resolver, gets and returns the -// resolved Node. -func (api *CoreAPI) ResolveNode(ctx context.Context, p coreiface.Path) (ipld.Node, error) { - return resolveNode(ctx, api.node.DAG, api.node.Namesys, p) -} - -func resolveNode(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSystem, p coreiface.Path) (ipld.Node, error) { - p, err := resolvePath(ctx, ng, nsys, p) - if err != nil { - return nil, err - } - - node, err := ng.Get(ctx, p.Cid()) - if err != nil { - return nil, err - } - return node, nil -} - -// ResolvePath resolves the path `p` using Unixfs resolver, returns the -// resolved path. -// TODO: store all of ipfspath.Resolver.ResolvePathComponents() in Path -func (api *CoreAPI) ResolvePath(ctx context.Context, p coreiface.Path) (coreiface.Path, error) { - return resolvePath(ctx, api.node.DAG, api.node.Namesys, p) -} - -func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSystem, p coreiface.Path) (coreiface.Path, error) { - if p.Resolved() { - return p, nil - } - - r := &resolver.Resolver{ - DAG: ng, - ResolveOnce: uio.ResolveUnixfsOnce, - } - - p2 := ipfspath.FromString(p.String()) - node, err := core.Resolve(ctx, nsys, r, p2) - if err == core.ErrNoNamesys { - return nil, coreiface.ErrOffline - } else if err != nil { - return nil, err - } - - var root *cid.Cid - if p2.IsJustAKey() { - root = node.Cid() - } - - return ResolvedPath(p.String(), node.Cid(), root), nil -} - -// Implements coreiface.Path -type path struct { - path ipfspath.Path - cid *cid.Cid - root *cid.Cid -} - -// ParsePath parses path `p` using ipfspath parser, returns the parsed path. -func (api *CoreAPI) ParsePath(ctx context.Context, p string, opts ...caopts.ParsePathOption) (coreiface.Path, error) { - options, err := caopts.ParsePathOptions(opts...) - if err != nil { - return nil, err - } - - pp, err := ipfspath.ParsePath(p) - if err != nil { - return nil, err - } - - res := &path{path: pp} - if options.Resolve { - return api.ResolvePath(ctx, res) - } - return res, nil -} - -// ParseCid parses the path from `c`, returns the parsed path. -func (api *CoreAPI) ParseCid(c *cid.Cid) coreiface.Path { - return &path{path: ipfspath.FromCid(c), cid: c, root: c} -} - -// ResolvePath parses path from string `p`, returns parsed path. -func ResolvedPath(p string, c *cid.Cid, r *cid.Cid) coreiface.Path { - return &path{path: ipfspath.FromString(p), cid: c, root: r} -} - -func (p *path) String() string { return p.path.String() } -func (p *path) Cid() *cid.Cid { return p.cid } -func (p *path) Root() *cid.Cid { return p.root } -func (p *path) Resolved() bool { return p.cid != nil } diff --git a/core/coreapi/path.go b/core/coreapi/path.go new file mode 100644 index 00000000000..ebfb33733c8 --- /dev/null +++ b/core/coreapi/path.go @@ -0,0 +1,109 @@ +package coreapi + +import ( + "context" + + core "github.com/ipfs/go-ipfs/core" + coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" + caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options" + namesys "github.com/ipfs/go-ipfs/namesys" + ipfspath "github.com/ipfs/go-ipfs/path" + resolver "github.com/ipfs/go-ipfs/path/resolver" + uio "github.com/ipfs/go-ipfs/unixfs/io" + + ipld "gx/ipfs/QmWi2BYBL5gJ3CiAiQchg6rn1A8iBsrWy51EYxvHVjFvLb/go-ipld-format" + cid "gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid" +) + +// ResolveNode resolves the path `p` using Unixfx resolver, gets and returns the +// resolved Node. +func (api *CoreAPI) ResolveNode(ctx context.Context, p coreiface.Path) (ipld.Node, error) { + return resolveNode(ctx, api.node.DAG, api.node.Namesys, p) +} + +func resolveNode(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSystem, p coreiface.Path) (ipld.Node, error) { + p, err := resolvePath(ctx, ng, nsys, p) + if err != nil { + return nil, err + } + + node, err := ng.Get(ctx, p.Cid()) + if err != nil { + return nil, err + } + return node, nil +} + +// ResolvePath resolves the path `p` using Unixfs resolver, returns the +// resolved path. +// TODO: store all of ipfspath.Resolver.ResolvePathComponents() in Path +func (api *CoreAPI) ResolvePath(ctx context.Context, p coreiface.Path) (coreiface.Path, error) { + return resolvePath(ctx, api.node.DAG, api.node.Namesys, p) +} + +func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSystem, p coreiface.Path) (coreiface.Path, error) { + if p.Resolved() { + return p, nil + } + + r := &resolver.Resolver{ + DAG: ng, + ResolveOnce: uio.ResolveUnixfsOnce, + } + + p2 := ipfspath.FromString(p.String()) + node, err := core.Resolve(ctx, nsys, r, p2) + if err == core.ErrNoNamesys { + return nil, coreiface.ErrOffline + } else if err != nil { + return nil, err + } + + var root *cid.Cid + if p2.IsJustAKey() { + root = node.Cid() + } + + return ResolvedPath(p.String(), node.Cid(), root), nil +} + +// Implements coreiface.Path +type path struct { + path ipfspath.Path + cid *cid.Cid + root *cid.Cid +} + +// ParsePath parses path `p` using ipfspath parser, returns the parsed path. +func (api *CoreAPI) ParsePath(ctx context.Context, p string, opts ...caopts.ParsePathOption) (coreiface.Path, error) { + options, err := caopts.ParsePathOptions(opts...) + if err != nil { + return nil, err + } + + pp, err := ipfspath.ParsePath(p) + if err != nil { + return nil, err + } + + res := &path{path: pp} + if options.Resolve { + return api.ResolvePath(ctx, res) + } + return res, nil +} + +// ParseCid parses the path from `c`, retruns the parsed path. +func (api *CoreAPI) ParseCid(c *cid.Cid) coreiface.Path { + return &path{path: ipfspath.FromCid(c), cid: c, root: c} +} + +// ResolvePath parses path from string `p`, returns parsed path. +func ResolvedPath(p string, c *cid.Cid, r *cid.Cid) coreiface.Path { + return &path{path: ipfspath.FromString(p), cid: c, root: r} +} + +func (p *path) String() string { return p.path.String() } +func (p *path) Cid() *cid.Cid { return p.cid } +func (p *path) Root() *cid.Cid { return p.root } +func (p *path) Resolved() bool { return p.cid != nil } From 15f8fc60c0fc49044385aa5319004785002aaa73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 8 Feb 2018 17:39:05 +0100 Subject: [PATCH 03/15] coreapi: separate path into two types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/block.go | 27 +++++++-- core/coreapi/coreapi.go | 4 +- core/coreapi/dag.go | 2 +- core/coreapi/dag_test.go | 2 +- core/coreapi/interface/block.go | 4 +- core/coreapi/interface/coreapi.go | 14 ++--- core/coreapi/interface/dag.go | 2 +- core/coreapi/interface/object.go | 10 ++-- core/coreapi/interface/options/path.go | 30 ---------- core/coreapi/interface/path.go | 15 ++++- core/coreapi/interface/pin.go | 4 +- core/coreapi/interface/unixfs.go | 2 +- core/coreapi/object.go | 12 ++-- core/coreapi/path.go | 83 ++++++++++++-------------- core/coreapi/pin.go | 24 +++++--- core/coreapi/unixfs.go | 2 +- core/coreapi/unixfs_test.go | 58 ++++++++++++------ path/path.go | 2 +- 18 files changed, 157 insertions(+), 140 deletions(-) delete mode 100644 core/coreapi/interface/options/path.go diff --git a/core/coreapi/block.go b/core/coreapi/block.go index 88df76d9b91..1ff38b9f80f 100644 --- a/core/coreapi/block.go +++ b/core/coreapi/block.go @@ -20,11 +20,11 @@ import ( type BlockAPI CoreAPI type BlockStat struct { - path coreiface.Path + path coreiface.ResolvedPath size int } -func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.BlockPutOption) (coreiface.Path, error) { +func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.BlockPutOption) (coreiface.ResolvedPath, error) { settings, err := caopts.BlockPutOptions(opts...) if err != nil { return nil, err @@ -69,7 +69,12 @@ func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Bloc } func (api *BlockAPI) Get(ctx context.Context, p coreiface.Path) (io.Reader, error) { - b, err := api.node.Blocks.GetBlock(ctx, p.Cid()) + rp, err := api.ResolvePath(ctx, p) + if err != nil { + return nil, err + } + + b, err := api.node.Blocks.GetBlock(ctx, rp.Cid()) if err != nil { return nil, err } @@ -78,11 +83,16 @@ func (api *BlockAPI) Get(ctx context.Context, p coreiface.Path) (io.Reader, erro } func (api *BlockAPI) Rm(ctx context.Context, p coreiface.Path, opts ...caopts.BlockRmOption) error { + rp, err := api.ResolvePath(ctx, p) + if err != nil { + return err + } + settings, err := caopts.BlockRmOptions(opts...) if err != nil { return err } - cids := []*cid.Cid{p.Cid()} + cids := []*cid.Cid{rp.Cid()} o := util.RmBlocksOpts{Force: settings.Force} out, err := util.RmBlocks(api.node.Blockstore, api.node.Pinning, cids, o) @@ -111,7 +121,12 @@ func (api *BlockAPI) Rm(ctx context.Context, p coreiface.Path, opts ...caopts.Bl } func (api *BlockAPI) Stat(ctx context.Context, p coreiface.Path) (coreiface.BlockStat, error) { - b, err := api.node.Blocks.GetBlock(ctx, p.Cid()) + rp, err := api.ResolvePath(ctx, p) + if err != nil { + return nil, err + } + + b, err := api.node.Blocks.GetBlock(ctx, rp.Cid()) if err != nil { return nil, err } @@ -126,6 +141,6 @@ func (bs *BlockStat) Size() int { return bs.size } -func (bs *BlockStat) Path() coreiface.Path { +func (bs *BlockStat) Path() coreiface.ResolvedPath { return bs.path } diff --git a/core/coreapi/coreapi.go b/core/coreapi/coreapi.go index 151f1fe343b..e9ec439518a 100644 --- a/core/coreapi/coreapi.go +++ b/core/coreapi/coreapi.go @@ -16,17 +16,15 @@ package coreapi import ( core "github.com/ipfs/go-ipfs/core" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" - caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options" ) type CoreAPI struct { node *core.IpfsNode - *caopts.ApiOptions } // NewCoreAPI creates new instance of IPFS CoreAPI backed by go-ipfs Node. func NewCoreAPI(n *core.IpfsNode) coreiface.CoreAPI { - api := &CoreAPI{n, nil} + api := &CoreAPI{n} return api } diff --git a/core/coreapi/dag.go b/core/coreapi/dag.go index 3f0b404f584..b6194bd81c3 100644 --- a/core/coreapi/dag.go +++ b/core/coreapi/dag.go @@ -20,7 +20,7 @@ type DagAPI CoreAPI // Put inserts data using specified format and input encoding. Unless used with // `WithCodes` or `WithHash`, the defaults "dag-cbor" and "sha256" are used. // Returns the path of the inserted data. -func (api *DagAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.DagPutOption) (coreiface.Path, error) { +func (api *DagAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.DagPutOption) (coreiface.ResolvedPath, error) { settings, err := caopts.DagPutOptions(opts...) if err != nil { return nil, err diff --git a/core/coreapi/dag_test.go b/core/coreapi/dag_test.go index ad6511c994f..416d7d97bf0 100644 --- a/core/coreapi/dag_test.go +++ b/core/coreapi/dag_test.go @@ -72,7 +72,7 @@ func TestPath(t *testing.T) { t.Error(err) } - p, err := api.ParsePath(ctx, path.Join(res.Cid().String(), "lnk")) + p, err := api.ParsePath(path.Join(res.Cid().String(), "lnk")) if err != nil { t.Error(err) } diff --git a/core/coreapi/interface/block.go b/core/coreapi/interface/block.go index a9e577d7655..468c0094788 100644 --- a/core/coreapi/interface/block.go +++ b/core/coreapi/interface/block.go @@ -13,13 +13,13 @@ type BlockStat interface { Size() int // Path returns path to the block - Path() Path + Path() ResolvedPath } // BlockAPI specifies the interface to the block layer type BlockAPI interface { // Put imports raw block data, hashing it using specified settings. - Put(context.Context, io.Reader, ...options.BlockPutOption) (Path, error) + Put(context.Context, io.Reader, ...options.BlockPutOption) (ResolvedPath, error) // Get attempts to resolve the path and return a reader for data in the block Get(context.Context, Path) (io.Reader, error) diff --git a/core/coreapi/interface/coreapi.go b/core/coreapi/interface/coreapi.go index 179531352d4..615b039b313 100644 --- a/core/coreapi/interface/coreapi.go +++ b/core/coreapi/interface/coreapi.go @@ -5,10 +5,8 @@ package iface import ( "context" - options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" - - cid "gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid" ipld "gx/ipfs/QmZtNq8dArGfnpCZfx2pUNY7UcjGhVp5qqwQ4hH6mpTMRQ/go-ipld-format" + cid "gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid" ) // CoreAPI defines an unified interface to IPFS for Go programs @@ -35,19 +33,15 @@ type CoreAPI interface { Object() ObjectAPI // ResolvePath resolves the path using Unixfs resolver - ResolvePath(context.Context, Path) (Path, error) + ResolvePath(context.Context, Path) (ResolvedPath, error) // ResolveNode resolves the path (if not resolved already) using Unixfs // resolver, gets and returns the resolved Node ResolveNode(context.Context, Path) (ipld.Node, error) // ParsePath parses string path to a Path - ParsePath(context.Context, string, ...options.ParsePathOption) (Path, error) - - // WithResolve is an option for ParsePath which when set to true tells - // ParsePath to also resolve the path - WithResolve(bool) options.ParsePathOption + ParsePath(context.Context, string) (Path, error) // ParseCid creates new path from the provided CID - ParseCid(*cid.Cid) Path + ParseCid(*cid.Cid) ResolvedPath } diff --git a/core/coreapi/interface/dag.go b/core/coreapi/interface/dag.go index 158db7419d5..3f92ebab34c 100644 --- a/core/coreapi/interface/dag.go +++ b/core/coreapi/interface/dag.go @@ -14,7 +14,7 @@ type DagAPI interface { // Put inserts data using specified format and input encoding. // Unless used with WithCodec or WithHash, the defaults "dag-cbor" and // "sha256" are used. - Put(ctx context.Context, src io.Reader, opts ...options.DagPutOption) (Path, error) + Put(ctx context.Context, src io.Reader, opts ...options.DagPutOption) (ResolvedPath, error) // Get attempts to resolve and get the node specified by the path Get(ctx context.Context, path Path) (ipld.Node, error) diff --git a/core/coreapi/interface/object.go b/core/coreapi/interface/object.go index a18a38ebe5d..ea9aa59480b 100644 --- a/core/coreapi/interface/object.go +++ b/core/coreapi/interface/object.go @@ -38,7 +38,7 @@ type ObjectAPI interface { New(context.Context, ...options.ObjectNewOption) (ipld.Node, error) // Put imports the data into merkledag - Put(context.Context, io.Reader, ...options.ObjectPutOption) (Path, error) + Put(context.Context, io.Reader, ...options.ObjectPutOption) (ResolvedPath, error) // Get returns the node for the path Get(context.Context, Path) (ipld.Node, error) @@ -55,14 +55,14 @@ type ObjectAPI interface { // AddLink adds a link under the specified path. child path can point to a // subdirectory within the patent which must be present (can be overridden // with WithCreate option). - AddLink(ctx context.Context, base Path, name string, child Path, opts ...options.ObjectAddLinkOption) (Path, error) + AddLink(ctx context.Context, base Path, name string, child Path, opts ...options.ObjectAddLinkOption) (ResolvedPath, error) // RmLink removes a link from the node - RmLink(ctx context.Context, base Path, link string) (Path, error) + RmLink(ctx context.Context, base Path, link string) (ResolvedPath, error) // AppendData appends data to the node - AppendData(context.Context, Path, io.Reader) (Path, error) + AppendData(context.Context, Path, io.Reader) (ResolvedPath, error) // SetData sets the data contained in the node - SetData(context.Context, Path, io.Reader) (Path, error) + SetData(context.Context, Path, io.Reader) (ResolvedPath, error) } diff --git a/core/coreapi/interface/options/path.go b/core/coreapi/interface/options/path.go deleted file mode 100644 index bf6eed65b8c..00000000000 --- a/core/coreapi/interface/options/path.go +++ /dev/null @@ -1,30 +0,0 @@ -package options - -type ParsePathSettings struct { - Resolve bool -} - -type ParsePathOption func(*ParsePathSettings) error - -func ParsePathOptions(opts ...ParsePathOption) (*ParsePathSettings, error) { - options := &ParsePathSettings{ - Resolve: false, - } - - for _, opt := range opts { - err := opt(options) - if err != nil { - return nil, err - } - } - return options, nil -} - -type ApiOptions struct{} - -func (api *ApiOptions) WithResolve(r bool) ParsePathOption { - return func(settings *ParsePathSettings) error { - settings.Resolve = r - return nil - } -} diff --git a/core/coreapi/interface/path.go b/core/coreapi/interface/path.go index 51513772fd4..4cfd916deb9 100644 --- a/core/coreapi/interface/path.go +++ b/core/coreapi/interface/path.go @@ -6,13 +6,24 @@ import ( // Path is a generic wrapper for paths used in the API. A path can be resolved // to a CID using one of Resolve functions in the API. +// TODO: figure out/explain namespaces type Path interface { // String returns the path as a string. String() string + + // Namespace returns the first component of the path + Namespace() string +} + +// ResolvedPath is a resolved Path +type ResolvedPath interface { // Cid returns cid referred to by path Cid() *cid.Cid + // Root returns cid of root path Root() *cid.Cid - // Resolved returns whether path has been fully resolved - Resolved() bool + + //TODO: Path remainder + + Path } diff --git a/core/coreapi/interface/pin.go b/core/coreapi/interface/pin.go index 5994c758686..2e119cbeae8 100644 --- a/core/coreapi/interface/pin.go +++ b/core/coreapi/interface/pin.go @@ -9,7 +9,7 @@ import ( // Pin holds information about pinned resource type Pin interface { // Path to the pinned object - Path() Path + Path() ResolvedPath // Type of the pin Type() string @@ -27,7 +27,7 @@ type PinStatus interface { // BadPinNode is a node that has been marked as bad by Pin.Verify type BadPinNode interface { // Path is the path of the node - Path() Path + Path() ResolvedPath // Err is the reason why the node has been marked as bad Err() error diff --git a/core/coreapi/interface/unixfs.go b/core/coreapi/interface/unixfs.go index c59451d002f..1ddc2067444 100644 --- a/core/coreapi/interface/unixfs.go +++ b/core/coreapi/interface/unixfs.go @@ -10,7 +10,7 @@ import ( // UnixfsAPI is the basic interface to immutable files in IPFS type UnixfsAPI interface { // Add imports the data from the reader into merkledag file - Add(context.Context, io.Reader) (Path, error) + Add(context.Context, io.Reader) (ResolvedPath, error) // Cat returns a reader for the file Cat(context.Context, Path) (Reader, error) diff --git a/core/coreapi/object.go b/core/coreapi/object.go index dc192e446f3..06e1434bd64 100644 --- a/core/coreapi/object.go +++ b/core/coreapi/object.go @@ -56,7 +56,7 @@ func (api *ObjectAPI) New(ctx context.Context, opts ...caopts.ObjectNewOption) ( return n, nil } -func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.ObjectPutOption) (coreiface.Path, error) { +func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.ObjectPutOption) (coreiface.ResolvedPath, error) { options, err := caopts.ObjectPutOptions(opts...) if err != nil { return nil, err @@ -180,7 +180,7 @@ func (api *ObjectAPI) Stat(ctx context.Context, path coreiface.Path) (*coreiface return out, nil } -func (api *ObjectAPI) AddLink(ctx context.Context, base coreiface.Path, name string, child coreiface.Path, opts ...caopts.ObjectAddLinkOption) (coreiface.Path, error) { +func (api *ObjectAPI) AddLink(ctx context.Context, base coreiface.Path, name string, child coreiface.Path, opts ...caopts.ObjectAddLinkOption) (coreiface.ResolvedPath, error) { options, err := caopts.ObjectAddLinkOptions(opts...) if err != nil { return nil, err @@ -221,7 +221,7 @@ func (api *ObjectAPI) AddLink(ctx context.Context, base coreiface.Path, name str return api.ParseCid(nnode.Cid()), nil } -func (api *ObjectAPI) RmLink(ctx context.Context, base coreiface.Path, link string) (coreiface.Path, error) { +func (api *ObjectAPI) RmLink(ctx context.Context, base coreiface.Path, link string) (coreiface.ResolvedPath, error) { baseNd, err := api.core().ResolveNode(ctx, base) if err != nil { return nil, err @@ -247,15 +247,15 @@ func (api *ObjectAPI) RmLink(ctx context.Context, base coreiface.Path, link stri return api.ParseCid(nnode.Cid()), nil } -func (api *ObjectAPI) AppendData(ctx context.Context, path coreiface.Path, r io.Reader) (coreiface.Path, error) { +func (api *ObjectAPI) AppendData(ctx context.Context, path coreiface.Path, r io.Reader) (coreiface.ResolvedPath, error) { return api.patchData(ctx, path, r, true) } -func (api *ObjectAPI) SetData(ctx context.Context, path coreiface.Path, r io.Reader) (coreiface.Path, error) { +func (api *ObjectAPI) SetData(ctx context.Context, path coreiface.Path, r io.Reader) (coreiface.ResolvedPath, error) { return api.patchData(ctx, path, r, false) } -func (api *ObjectAPI) patchData(ctx context.Context, path coreiface.Path, r io.Reader, appendData bool) (coreiface.Path, error) { +func (api *ObjectAPI) patchData(ctx context.Context, path coreiface.Path, r io.Reader, appendData bool) (coreiface.ResolvedPath, error) { nd, err := api.core().ResolveNode(ctx, path) if err != nil { return nil, err diff --git a/core/coreapi/path.go b/core/coreapi/path.go index ebfb33733c8..2c12543dd97 100644 --- a/core/coreapi/path.go +++ b/core/coreapi/path.go @@ -5,7 +5,6 @@ import ( core "github.com/ipfs/go-ipfs/core" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" - caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options" namesys "github.com/ipfs/go-ipfs/namesys" ipfspath "github.com/ipfs/go-ipfs/path" resolver "github.com/ipfs/go-ipfs/path/resolver" @@ -15,35 +14,51 @@ import ( cid "gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid" ) +// path implements coreiface.Path +type path struct { + path ipfspath.Path +} + +// resolvedPath implements coreiface.resolvedPath +type resolvedPath struct { + path + cid *cid.Cid + root *cid.Cid +} + +// ParseCid parses the path from `c`, retruns the parsed path. +func (api *CoreAPI) ParseCid(c *cid.Cid) coreiface.ResolvedPath { + return &resolvedPath{path: path{ipfspath.FromCid(c)}, cid: c, root: c} +} + // ResolveNode resolves the path `p` using Unixfx resolver, gets and returns the // resolved Node. func (api *CoreAPI) ResolveNode(ctx context.Context, p coreiface.Path) (ipld.Node, error) { return resolveNode(ctx, api.node.DAG, api.node.Namesys, p) } +// ResolvePath resolves the path `p` using Unixfs resolver, returns the +// resolved path. +func (api *CoreAPI) ResolvePath(ctx context.Context, p coreiface.Path) (coreiface.ResolvedPath, error) { + return resolvePath(ctx, api.node.DAG, api.node.Namesys, p) +} + func resolveNode(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSystem, p coreiface.Path) (ipld.Node, error) { - p, err := resolvePath(ctx, ng, nsys, p) + rp, err := resolvePath(ctx, ng, nsys, p) if err != nil { return nil, err } - node, err := ng.Get(ctx, p.Cid()) + node, err := ng.Get(ctx, rp.Cid()) if err != nil { return nil, err } return node, nil } -// ResolvePath resolves the path `p` using Unixfs resolver, returns the -// resolved path. -// TODO: store all of ipfspath.Resolver.ResolvePathComponents() in Path -func (api *CoreAPI) ResolvePath(ctx context.Context, p coreiface.Path) (coreiface.Path, error) { - return resolvePath(ctx, api.node.DAG, api.node.Namesys, p) -} - -func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSystem, p coreiface.Path) (coreiface.Path, error) { - if p.Resolved() { - return p, nil +func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSystem, p coreiface.Path) (coreiface.ResolvedPath, error) { + if _, ok := p.(coreiface.ResolvedPath); ok { + return p.(coreiface.ResolvedPath), nil } r := &resolver.Resolver{ @@ -64,46 +79,26 @@ func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSyste root = node.Cid() } - return ResolvedPath(p.String(), node.Cid(), root), nil -} - -// Implements coreiface.Path -type path struct { - path ipfspath.Path - cid *cid.Cid - root *cid.Cid + return &resolvedPath{path: path{p2}, cid: node.Cid(), root: root}, nil } // ParsePath parses path `p` using ipfspath parser, returns the parsed path. -func (api *CoreAPI) ParsePath(ctx context.Context, p string, opts ...caopts.ParsePathOption) (coreiface.Path, error) { - options, err := caopts.ParsePathOptions(opts...) - if err != nil { - return nil, err - } - +func (api *CoreAPI) ParsePath(ctx context.Context, p string) (coreiface.Path, error) { pp, err := ipfspath.ParsePath(p) if err != nil { return nil, err } - res := &path{path: pp} - if options.Resolve { - return api.ResolvePath(ctx, res) - } - return res, nil + return &path{path: pp}, nil } -// ParseCid parses the path from `c`, retruns the parsed path. -func (api *CoreAPI) ParseCid(c *cid.Cid) coreiface.Path { - return &path{path: ipfspath.FromCid(c), cid: c, root: c} -} - -// ResolvePath parses path from string `p`, returns parsed path. -func ResolvedPath(p string, c *cid.Cid, r *cid.Cid) coreiface.Path { - return &path{path: ipfspath.FromString(p), cid: c, root: r} +func (p *path) String() string { return p.path.String() } +func (p *path) Namespace() string { + if len(p.path.Segments()) < 1 { + return "" + } + return p.path.Segments()[0] } -func (p *path) String() string { return p.path.String() } -func (p *path) Cid() *cid.Cid { return p.cid } -func (p *path) Root() *cid.Cid { return p.root } -func (p *path) Resolved() bool { return p.cid != nil } +func (p *resolvedPath) Cid() *cid.Cid { return p.cid } +func (p *resolvedPath) Root() *cid.Cid { return p.root } diff --git a/core/coreapi/pin.go b/core/coreapi/pin.go index 8d0eaa77d48..f5b2a343afe 100644 --- a/core/coreapi/pin.go +++ b/core/coreapi/pin.go @@ -62,7 +62,17 @@ func (api *PinAPI) Update(ctx context.Context, from coreiface.Path, to coreiface return err } - return api.node.Pinning.Update(ctx, from.Cid(), to.Cid(), settings.Unpin) + fp, err := api.ResolvePath(ctx, from) + if err != nil { + return err + } + + tp, err := api.ResolvePath(ctx, to) + if err != nil { + return err + } + + return api.node.Pinning.Update(ctx, fp.Cid(), tp.Cid(), settings.Unpin) } type pinStatus struct { @@ -73,7 +83,7 @@ type pinStatus struct { // BadNode is used in PinVerifyRes type badNode struct { - path coreiface.Path + path coreiface.ResolvedPath err error } @@ -85,7 +95,7 @@ func (s *pinStatus) BadNodes() []coreiface.BadPinNode { return s.badNodes } -func (n *badNode) Path() coreiface.Path { +func (n *badNode) Path() coreiface.ResolvedPath { return n.path } @@ -141,11 +151,11 @@ func (api *PinAPI) Verify(ctx context.Context) (<-chan coreiface.PinStatus, erro type pinInfo struct { pinType string - object coreiface.Path + path coreiface.ResolvedPath } -func (p *pinInfo) Path() coreiface.Path { - return p.object +func (p *pinInfo) Path() coreiface.ResolvedPath { + return p.path } func (p *pinInfo) Type() string { @@ -160,7 +170,7 @@ func (api *PinAPI) pinLsAll(typeStr string, ctx context.Context) ([]coreiface.Pi for _, c := range keyList { keys[c.String()] = &pinInfo{ pinType: typeStr, - object: api.ParseCid(c), + path: api.ParseCid(c), } } } diff --git a/core/coreapi/unixfs.go b/core/coreapi/unixfs.go index d104f88e6b5..61b6db57dcf 100644 --- a/core/coreapi/unixfs.go +++ b/core/coreapi/unixfs.go @@ -16,7 +16,7 @@ type UnixfsAPI CoreAPI // Add builds a merkledag node from a reader, adds it to the blockstore, // and returns the key representing that node. -func (api *UnixfsAPI) Add(ctx context.Context, r io.Reader) (coreiface.Path, error) { +func (api *UnixfsAPI) Add(ctx context.Context, r io.Reader) (coreiface.ResolvedPath, error) { k, err := coreunix.AddWithContext(ctx, api.node, r) if err != nil { return nil, err diff --git a/core/coreapi/unixfs_test.go b/core/coreapi/unixfs_test.go index b7cba704cc5..7ea44cc9c57 100644 --- a/core/coreapi/unixfs_test.go +++ b/core/coreapi/unixfs_test.go @@ -29,14 +29,11 @@ import ( const testPeerID = "QmTFauExutTsy4XP6JbMFcw2Wa9645HJt2bTqL6qYDCKfe" // `echo -n 'hello, world!' | ipfs add` -var hello = coreapi.ResolvedPath("/ipfs/QmQy2Dw4Wk7rdJKjThjYXzfFJNaRKRHhHP5gHHXroJMYxk", nil, nil) +var hello = "/ipfs/QmQy2Dw4Wk7rdJKjThjYXzfFJNaRKRHhHP5gHHXroJMYxk" var helloStr = "hello, world!" -// `ipfs object new unixfs-dir` -var emptyDir = coreapi.ResolvedPath("/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn", nil, nil) - // `echo -n | ipfs add` -var emptyFile = coreapi.ResolvedPath("/ipfs/QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH", nil, nil) +var emptyFile = "/ipfs/QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH" func makeAPIIdent(ctx context.Context, fullIdentity bool) (*core.IpfsNode, coreiface.CoreAPI, error) { var ident config.Identity @@ -98,11 +95,11 @@ func TestAdd(t *testing.T) { t.Error(err) } - if p.String() != hello.String() { + if p.String() != hello { t.Fatalf("expected path %s, got: %s", hello, p) } - r, err := api.Unixfs().Cat(ctx, hello) + r, err := api.Unixfs().Cat(ctx, p) if err != nil { t.Fatal(err) } @@ -130,7 +127,7 @@ func TestAddEmptyFile(t *testing.T) { t.Error(err) } - if p.String() != emptyFile.String() { + if p.String() != emptyFile { t.Fatalf("expected path %s, got: %s", hello, p) } } @@ -149,11 +146,16 @@ func TestCatBasic(t *testing.T) { } p = "/ipfs/" + p - if p != hello.String() { + if p != hello { t.Fatalf("expected CID %s, got: %s", hello, p) } - r, err := api.Unixfs().Cat(ctx, hello) + helloPath, err := api.ParsePath(hello) + if err != nil { + t.Fatal(err) + } + + r, err := api.Unixfs().Cat(ctx, helloPath) if err != nil { t.Fatal(err) } @@ -180,7 +182,12 @@ func TestCatEmptyFile(t *testing.T) { t.Fatal(err) } - r, err := api.Unixfs().Cat(ctx, emptyFile) + emptyFilePath, err := api.ParsePath(emptyFile) + if err != nil { + t.Fatal(err) + } + + r, err := api.Unixfs().Cat(ctx, emptyFilePath) if err != nil { t.Fatal(err) } @@ -208,11 +215,16 @@ func TestCatDir(t *testing.T) { } p := api.ParseCid(edir.Cid()) - if p.String() != emptyDir.String() { - t.Fatalf("expected path %s, got: %s", emptyDir, p) + emptyDir, err := api.Object().New(ctx, api.Object().WithType("unixfs-dir")) + if err != nil { + t.Error(err) } - _, err = api.Unixfs().Cat(ctx, emptyDir) + if p.String() != api.ParseCid(emptyDir.Cid()).String() { + t.Fatalf("expected path %s, got: %s", emptyDir.Cid(), p.String()) + } + + _, err = api.Unixfs().Cat(ctx, api.ParseCid(emptyDir.Cid())) if err != coreiface.ErrIsDir { t.Fatalf("expected ErrIsDir, got: %s", err) } @@ -244,7 +256,11 @@ func TestCatOffline(t *testing.T) { t.Error(err) } - _, err = api.Unixfs().Cat(ctx, coreapi.ResolvedPath("/ipns/Qmfoobar", nil, nil)) + p, err := api.ParsePath("/ipns/Qmfoobar") + if err != nil { + t.Error(err) + } + _, err = api.Unixfs().Cat(ctx, p) if err != coreiface.ErrOffline { t.Fatalf("expected ErrOffline, got: %s", err) } @@ -266,7 +282,10 @@ func TestLs(t *testing.T) { if len(parts) != 2 { t.Errorf("unexpected path: %s", k) } - p := coreapi.ResolvedPath("/ipfs/"+parts[0], nil, nil) + p, err := api.ParsePath("/ipfs/" + parts[0]) + if err != nil { + t.Error(err) + } links, err := api.Unixfs().Ls(ctx, p) if err != nil { @@ -299,7 +318,12 @@ func TestLsEmptyDir(t *testing.T) { t.Error(err) } - links, err := api.Unixfs().Ls(ctx, emptyDir) + emptyDir, err := api.Object().New(ctx, api.Object().WithType("unixfs-dir")) + if err != nil { + t.Error(err) + } + + links, err := api.Unixfs().Ls(ctx, api.ParseCid(emptyDir.Cid())) if err != nil { t.Error(err) } diff --git a/path/path.go b/path/path.go index 5622a6d0517..cc0ec31b2f2 100644 --- a/path/path.go +++ b/path/path.go @@ -120,7 +120,7 @@ func ParsePath(txt string) (Path, error) { if _, err := ParseCidToPath(parts[2]); err != nil { return "", err } - } else if parts[1] != "ipns" { + } else if parts[1] != "ipns" && parts[1] != "ipld" { //TODO: make this smarter return "", ErrBadPath } From f5f44ab246bb58d39372df88760722dd9e9f14e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 30 Mar 2018 22:21:57 +0200 Subject: [PATCH 04/15] coreapi: remove ctx from ParsePath, split ParseCid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/block.go | 14 +++++++++----- core/coreapi/dag.go | 4 ++-- core/coreapi/interface/coreapi.go | 9 ++++++--- core/coreapi/object.go | 8 ++++---- core/coreapi/path.go | 15 ++++++++++----- core/coreapi/pin.go | 19 ++++++++++++++----- core/coreapi/pin_test.go | 6 +++--- core/coreapi/unixfs.go | 2 +- core/coreapi/unixfs_test.go | 17 +++++++++-------- core/corehttp/gateway_handler.go | 4 ++-- 10 files changed, 60 insertions(+), 38 deletions(-) diff --git a/core/coreapi/block.go b/core/coreapi/block.go index 1ff38b9f80f..6342dc692eb 100644 --- a/core/coreapi/block.go +++ b/core/coreapi/block.go @@ -65,11 +65,11 @@ func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Bloc return nil, err } - return api.ParseCid(b.Cid()), nil + return api.core().IpldPath(b.Cid()), nil } func (api *BlockAPI) Get(ctx context.Context, p coreiface.Path) (io.Reader, error) { - rp, err := api.ResolvePath(ctx, p) + rp, err := api.core().ResolvePath(ctx, p) if err != nil { return nil, err } @@ -83,7 +83,7 @@ func (api *BlockAPI) Get(ctx context.Context, p coreiface.Path) (io.Reader, erro } func (api *BlockAPI) Rm(ctx context.Context, p coreiface.Path, opts ...caopts.BlockRmOption) error { - rp, err := api.ResolvePath(ctx, p) + rp, err := api.core().ResolvePath(ctx, p) if err != nil { return err } @@ -121,7 +121,7 @@ func (api *BlockAPI) Rm(ctx context.Context, p coreiface.Path, opts ...caopts.Bl } func (api *BlockAPI) Stat(ctx context.Context, p coreiface.Path) (coreiface.BlockStat, error) { - rp, err := api.ResolvePath(ctx, p) + rp, err := api.core().ResolvePath(ctx, p) if err != nil { return nil, err } @@ -132,7 +132,7 @@ func (api *BlockAPI) Stat(ctx context.Context, p coreiface.Path) (coreiface.Bloc } return &BlockStat{ - path: api.ParseCid(b.Cid()), + path: api.core().IpldPath(b.Cid()), size: len(b.RawData()), }, nil } @@ -144,3 +144,7 @@ func (bs *BlockStat) Size() int { func (bs *BlockStat) Path() coreiface.ResolvedPath { return bs.path } + +func (api *BlockAPI) core() coreiface.CoreAPI { + return (*CoreAPI)(api) +} diff --git a/core/coreapi/dag.go b/core/coreapi/dag.go index b6194bd81c3..60692157ce2 100644 --- a/core/coreapi/dag.go +++ b/core/coreapi/dag.go @@ -44,7 +44,7 @@ func (api *DagAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.DagPut return nil, err } - return api.ParseCid(nds[0].Cid()), nil + return api.core().IpldPath(nds[0].Cid()), nil } // Get resolves `path` using Unixfs resolver, returns the resolved Node. @@ -66,7 +66,7 @@ func (api *DagAPI) Tree(ctx context.Context, p coreiface.Path, opts ...caopts.Da paths := n.Tree("", settings.Depth) out := make([]coreiface.Path, len(paths)) for n, p2 := range paths { - out[n], err = api.ParsePath(ctx, gopath.Join(p.String(), p2)) + out[n], err = api.core().ParsePath(gopath.Join(p.String(), p2)) if err != nil { return nil, err } diff --git a/core/coreapi/interface/coreapi.go b/core/coreapi/interface/coreapi.go index 615b039b313..f5e81adce6d 100644 --- a/core/coreapi/interface/coreapi.go +++ b/core/coreapi/interface/coreapi.go @@ -40,8 +40,11 @@ type CoreAPI interface { ResolveNode(context.Context, Path) (ipld.Node, error) // ParsePath parses string path to a Path - ParsePath(context.Context, string) (Path, error) + ParsePath(string) (Path, error) - // ParseCid creates new path from the provided CID - ParseCid(*cid.Cid) ResolvedPath + // IpfsPath creates new /ipfs path from the provided CID + IpfsPath(*cid.Cid) ResolvedPath + + // IpldPath creates new /ipld path from the provided CID + IpldPath(*cid.Cid) ResolvedPath } diff --git a/core/coreapi/object.go b/core/coreapi/object.go index 06e1434bd64..b8a007bd5ac 100644 --- a/core/coreapi/object.go +++ b/core/coreapi/object.go @@ -121,7 +121,7 @@ func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Obj return nil, err } - return api.ParseCid(dagnode.Cid()), nil + return api.core().IpfsPath(dagnode.Cid()), nil } func (api *ObjectAPI) Get(ctx context.Context, path coreiface.Path) (ipld.Node, error) { @@ -218,7 +218,7 @@ func (api *ObjectAPI) AddLink(ctx context.Context, base coreiface.Path, name str return nil, err } - return api.ParseCid(nnode.Cid()), nil + return api.core().IpfsPath(nnode.Cid()), nil } func (api *ObjectAPI) RmLink(ctx context.Context, base coreiface.Path, link string) (coreiface.ResolvedPath, error) { @@ -244,7 +244,7 @@ func (api *ObjectAPI) RmLink(ctx context.Context, base coreiface.Path, link stri return nil, err } - return api.ParseCid(nnode.Cid()), nil + return api.core().IpfsPath(nnode.Cid()), nil } func (api *ObjectAPI) AppendData(ctx context.Context, path coreiface.Path, r io.Reader) (coreiface.ResolvedPath, error) { @@ -281,7 +281,7 @@ func (api *ObjectAPI) patchData(ctx context.Context, path coreiface.Path, r io.R return nil, err } - return api.ParseCid(pbnd.Cid()), nil + return api.core().IpfsPath(pbnd.Cid()), nil } func (api *ObjectAPI) core() coreiface.CoreAPI { diff --git a/core/coreapi/path.go b/core/coreapi/path.go index 2c12543dd97..88dcb6f86ee 100644 --- a/core/coreapi/path.go +++ b/core/coreapi/path.go @@ -26,12 +26,17 @@ type resolvedPath struct { root *cid.Cid } -// ParseCid parses the path from `c`, retruns the parsed path. -func (api *CoreAPI) ParseCid(c *cid.Cid) coreiface.ResolvedPath { - return &resolvedPath{path: path{ipfspath.FromCid(c)}, cid: c, root: c} +// IpfsPath parses the path from `c`, reruns the parsed path. +func (api *CoreAPI) IpfsPath(c *cid.Cid) coreiface.ResolvedPath { + return &resolvedPath{path: path{ipfspath.Path("/ipfs/" + c.String())}, cid: c, root: c} } -// ResolveNode resolves the path `p` using Unixfx resolver, gets and returns the +// IpldPath parses the path from `c`, reruns the parsed path. +func (api *CoreAPI) IpldPath(c *cid.Cid) coreiface.ResolvedPath { + return &resolvedPath{path: path{ipfspath.Path("/ipld/" + c.String())}, cid: c, root: c} +} + +// ResolveNode resolves the path `p` using Unixfs resolver, gets and returns the // resolved Node. func (api *CoreAPI) ResolveNode(ctx context.Context, p coreiface.Path) (ipld.Node, error) { return resolveNode(ctx, api.node.DAG, api.node.Namesys, p) @@ -83,7 +88,7 @@ func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSyste } // ParsePath parses path `p` using ipfspath parser, returns the parsed path. -func (api *CoreAPI) ParsePath(ctx context.Context, p string) (coreiface.Path, error) { +func (api *CoreAPI) ParsePath(p string) (coreiface.Path, error) { pp, err := ipfspath.ParsePath(p) if err != nil { return nil, err diff --git a/core/coreapi/pin.go b/core/coreapi/pin.go index f5b2a343afe..e705a20c26d 100644 --- a/core/coreapi/pin.go +++ b/core/coreapi/pin.go @@ -24,7 +24,12 @@ func (api *PinAPI) Add(ctx context.Context, p coreiface.Path, opts ...caopts.Pin defer api.node.Blockstore.PinLock().Unlock() - _, err = corerepo.Pin(api.node, ctx, []string{p.String()}, settings.Recursive) + rp, err := api.core().ResolvePath(ctx, p) + if err != nil { + return err + } + + _, err = corerepo.Pin(api.node, ctx, []string{rp.Cid().String()}, settings.Recursive) if err != nil { return err } @@ -62,12 +67,12 @@ func (api *PinAPI) Update(ctx context.Context, from coreiface.Path, to coreiface return err } - fp, err := api.ResolvePath(ctx, from) + fp, err := api.core().ResolvePath(ctx, from) if err != nil { return err } - tp, err := api.ResolvePath(ctx, to) + tp, err := api.core().ResolvePath(ctx, to) if err != nil { return err } @@ -120,7 +125,7 @@ func (api *PinAPI) Verify(ctx context.Context) (<-chan coreiface.PinStatus, erro links, err := getLinks(ctx, root) if err != nil { status := &pinStatus{ok: false, cid: root} - status.badNodes = []coreiface.BadPinNode{&badNode{path: api.ParseCid(root), err: err}} + status.badNodes = []coreiface.BadPinNode{&badNode{path: api.core().IpldPath(root), err: err}} visited[key] = status return status } @@ -170,7 +175,7 @@ func (api *PinAPI) pinLsAll(typeStr string, ctx context.Context) ([]coreiface.Pi for _, c := range keyList { keys[c.String()] = &pinInfo{ pinType: typeStr, - path: api.ParseCid(c), + path: api.core().IpldPath(c), } } } @@ -199,3 +204,7 @@ func (api *PinAPI) pinLsAll(typeStr string, ctx context.Context) ([]coreiface.Pi return out, nil } + +func (api *PinAPI) core() coreiface.CoreAPI { + return (*CoreAPI)(api) +} diff --git a/core/coreapi/pin_test.go b/core/coreapi/pin_test.go index 936bae3bd40..9bbf16c9cfa 100644 --- a/core/coreapi/pin_test.go +++ b/core/coreapi/pin_test.go @@ -52,7 +52,7 @@ func TestPinSimple(t *testing.T) { t.Errorf("unexpected pin list len: %d", len(list)) } - if list[0].Path().String() != p.String() { + if list[0].Path().Cid().String() != p.Cid().String() { t.Error("paths don't match") } @@ -156,7 +156,7 @@ func TestPinRecursive(t *testing.T) { t.Errorf("unexpected pin list len: %d", len(list)) } - if list[0].Path().String() != p0.String() { + if list[0].Path().Cid().String() != p0.Cid().String() { t.Error("unexpected path") } @@ -195,7 +195,7 @@ func TestPinRecursive(t *testing.T) { t.Fatalf("unexpected badNodes len") } - if r.BadNodes()[0].Path().String() != p0.String() { + if r.BadNodes()[0].Path().Cid().String() != p0.Cid().String() { t.Error("unexpected badNode path") } diff --git a/core/coreapi/unixfs.go b/core/coreapi/unixfs.go index 61b6db57dcf..ef454798908 100644 --- a/core/coreapi/unixfs.go +++ b/core/coreapi/unixfs.go @@ -25,7 +25,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, r io.Reader) (coreiface.ResolvedP if err != nil { return nil, err } - return api.core().ParseCid(c), nil + return api.core().IpfsPath(c), nil } // Cat returns the data contained by an IPFS or IPNS object(s) at path `p`. diff --git a/core/coreapi/unixfs_test.go b/core/coreapi/unixfs_test.go index 7ea44cc9c57..c7325f3ac48 100644 --- a/core/coreapi/unixfs_test.go +++ b/core/coreapi/unixfs_test.go @@ -12,6 +12,7 @@ import ( core "github.com/ipfs/go-ipfs/core" coreapi "github.com/ipfs/go-ipfs/core/coreapi" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" coreunix "github.com/ipfs/go-ipfs/core/coreunix" keystore "github.com/ipfs/go-ipfs/keystore" mdag "github.com/ipfs/go-ipfs/merkledag" @@ -213,18 +214,18 @@ func TestCatDir(t *testing.T) { if err != nil { t.Error(err) } - p := api.ParseCid(edir.Cid()) + p := api.IpfsPath(edir.Cid()) - emptyDir, err := api.Object().New(ctx, api.Object().WithType("unixfs-dir")) + emptyDir, err := api.Object().New(ctx, options.Object.Type("unixfs-dir")) if err != nil { t.Error(err) } - if p.String() != api.ParseCid(emptyDir.Cid()).String() { + if p.String() != api.IpfsPath(emptyDir.Cid()).String() { t.Fatalf("expected path %s, got: %s", emptyDir.Cid(), p.String()) } - _, err = api.Unixfs().Cat(ctx, api.ParseCid(emptyDir.Cid())) + _, err = api.Unixfs().Cat(ctx, api.IpfsPath(emptyDir.Cid())) if err != coreiface.ErrIsDir { t.Fatalf("expected ErrIsDir, got: %s", err) } @@ -243,7 +244,7 @@ func TestCatNonUnixfs(t *testing.T) { t.Error(err) } - _, err = api.Unixfs().Cat(ctx, api.ParseCid(nd.Cid())) + _, err = api.Unixfs().Cat(ctx, api.IpfsPath(nd.Cid())) if !strings.Contains(err.Error(), "proto: required field") { t.Fatalf("expected protobuf error, got: %s", err) } @@ -318,12 +319,12 @@ func TestLsEmptyDir(t *testing.T) { t.Error(err) } - emptyDir, err := api.Object().New(ctx, api.Object().WithType("unixfs-dir")) + emptyDir, err := api.Object().New(ctx, options.Object.Type("unixfs-dir")) if err != nil { t.Error(err) } - links, err := api.Unixfs().Ls(ctx, api.ParseCid(emptyDir.Cid())) + links, err := api.Unixfs().Ls(ctx, api.IpfsPath(emptyDir.Cid())) if err != nil { t.Error(err) } @@ -351,7 +352,7 @@ func TestLsNonUnixfs(t *testing.T) { t.Error(err) } - links, err := api.Unixfs().Ls(ctx, api.ParseCid(nd.Cid())) + links, err := api.Unixfs().Ls(ctx, api.IpfsPath(nd.Cid())) if err != nil { t.Error(err) } diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index 2f0303d26ef..0f148a4956d 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -159,7 +159,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr ipnsHostname = true } - parsedPath, err := i.api.ParsePath(ctx, urlPath) + parsedPath, err := i.api.ParsePath(urlPath) if err != nil { webError(w, "invalid ipfs path", err, http.StatusBadRequest) return @@ -287,7 +287,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr return } - dr, err := i.api.Unixfs().Cat(ctx, i.api.ParseCid(ixnd.Cid())) + dr, err := i.api.Unixfs().Cat(ctx, i.api.IpfsPath(ixnd.Cid())) if err != nil { internalWebError(w, err) return From 7ee6194352ddea86679e66e64a8d71c13dff8b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 30 Mar 2018 22:44:23 +0200 Subject: [PATCH 05/15] coreapi: path.Mutable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/interface/path.go | 14 +++++++++++++- core/coreapi/path.go | 19 ++++++++++++++++--- core/coreapi/path_test.go | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 core/coreapi/path_test.go diff --git a/core/coreapi/interface/path.go b/core/coreapi/interface/path.go index 4cfd916deb9..bb87a6b3bce 100644 --- a/core/coreapi/interface/path.go +++ b/core/coreapi/interface/path.go @@ -6,13 +6,25 @@ import ( // Path is a generic wrapper for paths used in the API. A path can be resolved // to a CID using one of Resolve functions in the API. -// TODO: figure out/explain namespaces +// +// Paths must be prefixed with a valid prefix: +// +// * /ipfs - Immutable unixfs path (files) +// * /ipld - Immutable ipld path (data) +// * /ipns - Mutable names. Usually resolves to one of the immutable paths +//TODO: /local (MFS) type Path interface { // String returns the path as a string. String() string // Namespace returns the first component of the path Namespace() string + + // Mutable returns false if the data pointed to by this path in guaranteed + // to not change. + // + // Note that resolved mutable path can be immutable. + Mutable() bool } // ResolvedPath is a resolved Path diff --git a/core/coreapi/path.go b/core/coreapi/path.go index 88dcb6f86ee..85407211d4a 100644 --- a/core/coreapi/path.go +++ b/core/coreapi/path.go @@ -97,7 +97,10 @@ func (api *CoreAPI) ParsePath(p string) (coreiface.Path, error) { return &path{path: pp}, nil } -func (p *path) String() string { return p.path.String() } +func (p *path) String() string { + return p.path.String() +} + func (p *path) Namespace() string { if len(p.path.Segments()) < 1 { return "" @@ -105,5 +108,15 @@ func (p *path) Namespace() string { return p.path.Segments()[0] } -func (p *resolvedPath) Cid() *cid.Cid { return p.cid } -func (p *resolvedPath) Root() *cid.Cid { return p.root } +func (p *path) Mutable() bool { + //TODO: MFS: check for /local + return p.Namespace() == "ipns" +} + +func (p *resolvedPath) Cid() *cid.Cid { + return p.cid +} + +func (p *resolvedPath) Root() *cid.Cid { + return p.root +} diff --git a/core/coreapi/path_test.go b/core/coreapi/path_test.go new file mode 100644 index 00000000000..7fc5ad5afaa --- /dev/null +++ b/core/coreapi/path_test.go @@ -0,0 +1,34 @@ +package coreapi_test + +import ( + "context" + "strings" + "testing" +) + +func TestMutablePath(t *testing.T) { + ctx := context.Background() + _, api, err := makeAPI(ctx) + if err != nil { + t.Fatal(err) + } + + // get self /ipns path + keys, err := api.Key().List(ctx) + if err != nil { + t.Fatal(err) + } + + if !keys[0].Path().Mutable() { + t.Error("expected self /ipns path to be mutable") + } + + blk, err := api.Block().Put(ctx, strings.NewReader(`foo`)) + if err != nil { + t.Error(err) + } + + if blk.Mutable() { + t.Error("expected /ipld path to be immutable") + } +} From 9b288560a44ad98ae9c8fdbcd13a7c8de60ed27c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 3 Apr 2018 14:49:33 +0200 Subject: [PATCH 06/15] coreapi: path remainders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/interface/path.go | 7 +-- core/coreapi/path.go | 58 ++++++++++++++++++------ core/coreapi/path_test.go | 81 ++++++++++++++++++++++++++++++++++ core/pathresolver.go | 27 ++++++++---- path/path.go | 2 +- 5 files changed, 149 insertions(+), 26 deletions(-) diff --git a/core/coreapi/interface/path.go b/core/coreapi/interface/path.go index bb87a6b3bce..b4a9f0dbd9a 100644 --- a/core/coreapi/interface/path.go +++ b/core/coreapi/interface/path.go @@ -29,13 +29,14 @@ type Path interface { // ResolvedPath is a resolved Path type ResolvedPath interface { - // Cid returns cid referred to by path + // Cid returns the CID referred to by path Cid() *cid.Cid - // Root returns cid of root path + // Root returns the CID of root path Root() *cid.Cid - //TODO: Path remainder + // Remainder returns unresolved part of the path + Remainder() string Path } diff --git a/core/coreapi/path.go b/core/coreapi/path.go index 85407211d4a..bb9d59b9cf9 100644 --- a/core/coreapi/path.go +++ b/core/coreapi/path.go @@ -1,7 +1,9 @@ package coreapi import ( - "context" + context "context" + gopath "path" + strings "strings" core "github.com/ipfs/go-ipfs/core" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" @@ -22,18 +24,29 @@ type path struct { // resolvedPath implements coreiface.resolvedPath type resolvedPath struct { path - cid *cid.Cid - root *cid.Cid + cid *cid.Cid + root *cid.Cid + remainder string } // IpfsPath parses the path from `c`, reruns the parsed path. func (api *CoreAPI) IpfsPath(c *cid.Cid) coreiface.ResolvedPath { - return &resolvedPath{path: path{ipfspath.Path("/ipfs/" + c.String())}, cid: c, root: c} + return &resolvedPath{ + path: path{ipfspath.Path("/ipfs/" + c.String())}, + cid: c, + root: c, + remainder: "", + } } // IpldPath parses the path from `c`, reruns the parsed path. func (api *CoreAPI) IpldPath(c *cid.Cid) coreiface.ResolvedPath { - return &resolvedPath{path: path{ipfspath.Path("/ipld/" + c.String())}, cid: c, root: c} + return &resolvedPath{ + path: path{ipfspath.Path("/ipld/" + c.String())}, + cid: c, + root: c, + remainder: "", + } } // ResolveNode resolves the path `p` using Unixfs resolver, gets and returns the @@ -66,25 +79,40 @@ func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSyste return p.(coreiface.ResolvedPath), nil } + ipath := p.(*path).path + ipath, err := core.ResolveIPNS(ctx, nsys, ipath) + if err == core.ErrNoNamesys { + return nil, coreiface.ErrOffline + } else if err != nil { + return nil, err + } + + resolveOnce := uio.ResolveUnixfsOnce + if strings.HasPrefix(ipath.String(), "/ipld") { + resolveOnce = resolver.ResolveSingle + } + r := &resolver.Resolver{ DAG: ng, - ResolveOnce: uio.ResolveUnixfsOnce, + ResolveOnce: resolveOnce, } - p2 := ipfspath.FromString(p.String()) - node, err := core.Resolve(ctx, nsys, r, p2) - if err == core.ErrNoNamesys { - return nil, coreiface.ErrOffline - } else if err != nil { + node, rest, err := r.ResolveToLastNode(ctx, ipath) + if err != nil { return nil, err } var root *cid.Cid - if p2.IsJustAKey() { + if ipath.IsJustAKey() { root = node.Cid() } - return &resolvedPath{path: path{p2}, cid: node.Cid(), root: root}, nil + return &resolvedPath{ + path: path{ipath}, + cid: node.Cid(), + root: root, + remainder: gopath.Join(rest...), + }, nil } // ParsePath parses path `p` using ipfspath parser, returns the parsed path. @@ -120,3 +148,7 @@ func (p *resolvedPath) Cid() *cid.Cid { func (p *resolvedPath) Root() *cid.Cid { return p.root } + +func (p *resolvedPath) Remainder() string { + return p.remainder +} diff --git a/core/coreapi/path_test.go b/core/coreapi/path_test.go index 7fc5ad5afaa..d35e57ba9a1 100644 --- a/core/coreapi/path_test.go +++ b/core/coreapi/path_test.go @@ -32,3 +32,84 @@ func TestMutablePath(t *testing.T) { t.Error("expected /ipld path to be immutable") } } + +func TestPathRemainder(t *testing.T) { + ctx := context.Background() + _, api, err := makeAPI(ctx) + if err != nil { + t.Fatal(err) + } + + obj, err := api.Dag().Put(ctx, strings.NewReader(`{"foo": {"bar": "baz"}}`)) + if err != nil { + t.Fatal(err) + } + + p1, err := api.ParsePath(obj.String() + "/foo/bar") + if err != nil { + t.Error(err) + } + + rp1, err := api.ResolvePath(ctx, p1) + if err != nil { + t.Fatal(err) + } + + if rp1.Remainder() != "foo/bar" { + t.Error("expected to get path remainder") + } +} + +func TestEmptyPathRemainder(t *testing.T) { + ctx := context.Background() + _, api, err := makeAPI(ctx) + if err != nil { + t.Fatal(err) + } + + obj, err := api.Dag().Put(ctx, strings.NewReader(`{"foo": {"bar": "baz"}}`)) + if err != nil { + t.Fatal(err) + } + + if obj.Remainder() != "" { + t.Error("expected the resolved path to not have a remainder") + } + + p1, err := api.ParsePath(obj.String()) + if err != nil { + t.Error(err) + } + + rp1, err := api.ResolvePath(ctx, p1) + if err != nil { + t.Fatal(err) + } + + if rp1.Remainder() != "" { + t.Error("expected the resolved path to not have a remainder") + } +} + +func TestInvalidPathRemainder(t *testing.T) { + ctx := context.Background() + _, api, err := makeAPI(ctx) + if err != nil { + t.Fatal(err) + } + + obj, err := api.Dag().Put(ctx, strings.NewReader(`{"foo": {"bar": "baz"}}`)) + if err != nil { + t.Fatal(err) + } + + p1, err := api.ParsePath(obj.String() + "/bar/baz") + if err != nil { + t.Error(err) + } + + _, err = api.ResolvePath(ctx, p1) + if err == nil || err.Error() != "no such link found" { + t.Fatalf("unexpected error: %s", err) + } +} diff --git a/core/pathresolver.go b/core/pathresolver.go index ea5ea7d9c1b..7fbb47d6a7f 100644 --- a/core/pathresolver.go +++ b/core/pathresolver.go @@ -19,10 +19,8 @@ import ( var ErrNoNamesys = errors.New( "core/resolve: no Namesys on IpfsNode - can't resolve ipns entry") -// Resolve resolves the given path by parsing out protocol-specific -// entries (e.g. /ipns/) and then going through the /ipfs/ -// entries and returning the final node. -func Resolve(ctx context.Context, nsys namesys.NameSystem, r *resolver.Resolver, p path.Path) (ipld.Node, error) { +// ResolveIPNS resolves /ipns paths +func ResolveIPNS(ctx context.Context, nsys namesys.NameSystem, p path.Path) (path.Path, error) { if strings.HasPrefix(p.String(), "/ipns/") { evt := log.EventBegin(ctx, "resolveIpnsPath") defer evt.Done() @@ -31,36 +29,47 @@ func Resolve(ctx context.Context, nsys namesys.NameSystem, r *resolver.Resolver, // TODO(cryptix): we should be able to query the local cache for the path if nsys == nil { evt.Append(logging.LoggableMap{"error": ErrNoNamesys.Error()}) - return nil, ErrNoNamesys + return "", ErrNoNamesys } seg := p.Segments() if len(seg) < 2 || seg[1] == "" { // just "/" without further segments evt.Append(logging.LoggableMap{"error": path.ErrNoComponents.Error()}) - return nil, path.ErrNoComponents + return "", path.ErrNoComponents } extensions := seg[2:] resolvable, err := path.FromSegments("/", seg[0], seg[1]) if err != nil { evt.Append(logging.LoggableMap{"error": err.Error()}) - return nil, err + return "", err } respath, err := nsys.Resolve(ctx, resolvable.String()) if err != nil { evt.Append(logging.LoggableMap{"error": err.Error()}) - return nil, err + return "", err } segments := append(respath.Segments(), extensions...) p, err = path.FromSegments("/", segments...) if err != nil { evt.Append(logging.LoggableMap{"error": err.Error()}) - return nil, err + return "", err } } + return p, nil +} + +// Resolve resolves the given path by parsing out protocol-specific +// entries (e.g. /ipns/) and then going through the /ipfs/ +// entries and returning the final node. +func Resolve(ctx context.Context, nsys namesys.NameSystem, r *resolver.Resolver, p path.Path) (ipld.Node, error) { + p, err := ResolveIPNS(ctx, nsys, p) + if err != nil { + return nil, err + } // ok, we have an IPFS path now (or what we'll treat as one) return r.ResolvePath(ctx, p) diff --git a/path/path.go b/path/path.go index cc0ec31b2f2..1c2bd2fe60b 100644 --- a/path/path.go +++ b/path/path.go @@ -161,7 +161,7 @@ func SplitList(pth string) []string { // must be a Multihash) and return it separately. func SplitAbsPath(fpath Path) (*cid.Cid, []string, error) { parts := fpath.Segments() - if parts[0] == "ipfs" { + if parts[0] == "ipfs" || parts[0] == "ipld" { parts = parts[1:] } From 1d23bbeb0fc971b799dc82b44ed9fc224944848f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 20 Apr 2018 13:31:05 +0200 Subject: [PATCH 07/15] coreapi: path review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/path.go | 14 ++++++++++---- path/resolver/resolver.go | 5 ++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/core/coreapi/path.go b/core/coreapi/path.go index bb9d59b9cf9..e7ce0f0e4bc 100644 --- a/core/coreapi/path.go +++ b/core/coreapi/path.go @@ -2,8 +2,8 @@ package coreapi import ( context "context" + fmt "fmt" gopath "path" - strings "strings" core "github.com/ipfs/go-ipfs/core" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" @@ -87,9 +87,15 @@ func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSyste return nil, err } - resolveOnce := uio.ResolveUnixfsOnce - if strings.HasPrefix(ipath.String(), "/ipld") { + var resolveOnce resolver.ResolveOnce + + switch p.Namespace() { + case "ipfs": + resolveOnce = uio.ResolveUnixfsOnce + case "ipld": resolveOnce = resolver.ResolveSingle + default: + return nil, fmt.Errorf("unsupported path namespace: %s", p.Namespace()) } r := &resolver.Resolver{ @@ -131,7 +137,7 @@ func (p *path) String() string { func (p *path) Namespace() string { if len(p.path.Segments()) < 1 { - return "" + panic("path without namespace") //this shouldn't happen under any scenario } return p.path.Segments()[0] } diff --git a/path/resolver/resolver.go b/path/resolver/resolver.go index 8c7b28b1c0c..05341655a33 100644 --- a/path/resolver/resolver.go +++ b/path/resolver/resolver.go @@ -34,6 +34,9 @@ func (e ErrNoLink) Error() string { return fmt.Sprintf("no link named %q under %s", e.Name, e.Node.String()) } +// ResolveOnce resolves path through a single node +type ResolveOnce func(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names []string) (*ipld.Link, []string, error) + // Resolver provides path resolution to IPFS // It has a pointer to a DAGService, which is uses to resolve nodes. // TODO: now that this is more modular, try to unify this code with the @@ -41,7 +44,7 @@ func (e ErrNoLink) Error() string { type Resolver struct { DAG ipld.NodeGetter - ResolveOnce func(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names []string) (*ipld.Link, []string, error) + ResolveOnce ResolveOnce } // NewBasicResolver constructs a new basic resolver. From d5b5e0d7ac73fbeeed78b81af25dfb5e8555a308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 20 Apr 2018 13:56:33 +0200 Subject: [PATCH 08/15] coreapi: add more docs for path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/interface/path.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/core/coreapi/interface/path.go b/core/coreapi/interface/path.go index b4a9f0dbd9a..d233afae53e 100644 --- a/core/coreapi/interface/path.go +++ b/core/coreapi/interface/path.go @@ -17,7 +17,9 @@ type Path interface { // String returns the path as a string. String() string - // Namespace returns the first component of the path + // Namespace returns the first component of the path. + // + // For example path "/ipfs/QmHash", calling Namespace() will return "ipfs" Namespace() string // Mutable returns false if the data pointed to by this path in guaranteed @@ -29,13 +31,29 @@ type Path interface { // ResolvedPath is a resolved Path type ResolvedPath interface { - // Cid returns the CID referred to by path + // Cid returns the CID of the object referenced by the path. + // + // Example: + // If you have 3 linked objects: QmRoot -> A -> B, and resolve path + // "/ipfs/QmRoot/A/B", the Cid method will return the CID of object B Cid() *cid.Cid - // Root returns the CID of root path + // Root returns the CID of the root object of the path + // + // Example: + // If you have 3 linked objects: QmRoot -> A -> B, and resolve path + // "/ipfs/QmRoot/A/B", the Root method will return the CID of object QmRoot Root() *cid.Cid // Remainder returns unresolved part of the path + // + // Example: + // If you have 2 linked objects: QmRoot -> A, where A is a CBOR node + // containing the following data: + // + // {"foo": {"bar": 42}} + // + // When resolving "/ipld/QmRoot/A/foo/bar", Remainder will return "foo/bar" Remainder() string Path From 604b187cca81c63ecd4c22e4c3a46eb3462b5e0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 24 Apr 2018 02:11:46 +0200 Subject: [PATCH 09/15] path: add tests for ipld paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- path/path.go | 5 +++-- path/path_test.go | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/path/path.go b/path/path.go index 1c2bd2fe60b..1608b6ca3c0 100644 --- a/path/path.go +++ b/path/path.go @@ -59,10 +59,11 @@ func (p Path) String() string { return string(p) } -// IsJustAKey returns true if the path is of the form or /ipfs/. +// IsJustAKey returns true if the path is of the form or /ipfs/, or +// /ipld/ func (p Path) IsJustAKey() bool { parts := p.Segments() - return len(parts) == 2 && parts[0] == "ipfs" + return len(parts) == 2 && (parts[0] == "ipfs" || parts[0] == "ipld") } // PopLastSegment returns a new Path without its final segment, and the final diff --git a/path/path_test.go b/path/path_test.go index b095ffd98e7..db28193c8da 100644 --- a/path/path_test.go +++ b/path/path_test.go @@ -9,6 +9,9 @@ func TestPathParsing(t *testing.T) { "/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n": true, "/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a": true, "/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a/b/c/d/e/f": true, + "/ipld/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n": true, + "/ipld/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a": true, + "/ipld/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a/b/c/d/e/f": true, "/ipns/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a/b/c/d/e/f": true, "/ipns/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n": true, "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a/b/c/d/e/f": true, @@ -36,6 +39,8 @@ func TestIsJustAKey(t *testing.T) { "/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a": false, "/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a/b": false, "/ipns/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n": false, + "/ipld/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a/b": false, + "/ipld/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n": true, } for p, expected := range cases { @@ -57,6 +62,7 @@ func TestPopLastSegment(t *testing.T) { "/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a": []string{"/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n", "a"}, "/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a/b": []string{"/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a", "b"}, "/ipns/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/x/y/z": []string{"/ipns/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/x/y", "z"}, + "/ipld/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/x/y/z": []string{"/ipld/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/x/y", "z"}, } for p, expected := range cases { From e227fc38659a62a09455ac752bb89c2327df1873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 24 Apr 2018 15:20:51 +0200 Subject: [PATCH 10/15] coreapi: fix ipns path resolving MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/path.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/coreapi/path.go b/core/coreapi/path.go index e7ce0f0e4bc..afabe4db2e0 100644 --- a/core/coreapi/path.go +++ b/core/coreapi/path.go @@ -89,7 +89,7 @@ func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSyste var resolveOnce resolver.ResolveOnce - switch p.Namespace() { + switch ipath.Segments()[0] { case "ipfs": resolveOnce = uio.ResolveUnixfsOnce case "ipld": From 0f6bd2d17354489c3287b3d1101994743cfbd906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 24 Apr 2018 16:08:00 +0200 Subject: [PATCH 11/15] coreapi: fix resolved path root for some paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/path.go | 6 +++--- core/coreapi/path_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/core/coreapi/path.go b/core/coreapi/path.go index afabe4db2e0..85dc0f7ccdb 100644 --- a/core/coreapi/path.go +++ b/core/coreapi/path.go @@ -108,9 +108,9 @@ func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSyste return nil, err } - var root *cid.Cid - if ipath.IsJustAKey() { - root = node.Cid() + root, err := cid.Parse(ipath.Segments()[1]) + if err != nil { + return nil, err } return &resolvedPath{ diff --git a/core/coreapi/path_test.go b/core/coreapi/path_test.go index d35e57ba9a1..7f1f686faab 100644 --- a/core/coreapi/path_test.go +++ b/core/coreapi/path_test.go @@ -4,6 +4,8 @@ import ( "context" "strings" "testing" + + "github.com/ipfs/go-ipfs/core/coreapi/interface/options" ) func TestMutablePath(t *testing.T) { @@ -113,3 +115,39 @@ func TestInvalidPathRemainder(t *testing.T) { t.Fatalf("unexpected error: %s", err) } } + +func TestPathRoot(t *testing.T) { + ctx := context.Background() + _, api, err := makeAPI(ctx) + if err != nil { + t.Fatal(err) + } + + blk, err := api.Block().Put(ctx, strings.NewReader(`foo`), options.Block.Format("raw")) + if err != nil { + t.Error(err) + } + + obj, err := api.Dag().Put(ctx, strings.NewReader(`{"foo": {"/": "`+blk.Cid().String()+`"}}`)) + if err != nil { + t.Fatal(err) + } + + p1, err := api.ParsePath(obj.String() + "/foo") + if err != nil { + t.Error(err) + } + + rp, err := api.ResolvePath(ctx, p1) + if err != nil { + t.Fatal(err) + } + + if rp.Root().String() != obj.Cid().String() { + t.Error("unexpected path root") + } + + if rp.Cid().String() != blk.Cid().String() { + t.Error("unexpected path cid") + } +} From 0adb69a7734bb6b9e15c5f895341dd33206c5bc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 6 Jun 2018 21:00:50 +0200 Subject: [PATCH 12/15] coreapi: fix TestGatewayGet after rebase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/corehttp/gateway_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/corehttp/gateway_test.go b/core/corehttp/gateway_test.go index 900020cbab6..e8ac707837b 100644 --- a/core/corehttp/gateway_test.go +++ b/core/corehttp/gateway_test.go @@ -171,7 +171,7 @@ func TestGatewayGet(t *testing.T) { {"working.example.com", "/", http.StatusOK, "fnord"}, {"double.example.com", "/", http.StatusOK, "fnord"}, {"triple.example.com", "/", http.StatusOK, "fnord"}, - {"working.example.com", "/ipfs/" + k, http.StatusNotFound, "ipfs resolve -r /ipns/working.example.com/ipfs/" + k + ": no link named \"ipfs\" under " + k + "\n"}, + {"working.example.com", "/ipfs/" + k, http.StatusNotFound, "ipfs resolve -r /ipns/working.example.com/ipfs/" + k + ": no link by that name\n"}, {"broken.example.com", "/", http.StatusNotFound, "ipfs resolve -r /ipns/broken.example.com/: " + namesys.ErrResolveFailed.Error() + "\n"}, {"broken.example.com", "/ipfs/" + k, http.StatusNotFound, "ipfs resolve -r /ipns/broken.example.com/ipfs/" + k + ": " + namesys.ErrResolveFailed.Error() + "\n"}, } { From 082498de6d779fdbddb70109cea8373ef1d4cfb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 12 Jun 2018 02:57:57 +0200 Subject: [PATCH 13/15] coreapi: more docs for ResolvedPath MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/interface/path.go | 41 +++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/core/coreapi/interface/path.go b/core/coreapi/interface/path.go index d233afae53e..acdcd85da70 100644 --- a/core/coreapi/interface/path.go +++ b/core/coreapi/interface/path.go @@ -29,13 +29,38 @@ type Path interface { Mutable() bool } -// ResolvedPath is a resolved Path +// ResolvedPath is a path which was resolved to the last resolvable node type ResolvedPath interface { - // Cid returns the CID of the object referenced by the path. + // Cid returns the CID of the node referenced by the path. Remainder of the + // path is guaranteed to be within the node. // - // Example: - // If you have 3 linked objects: QmRoot -> A -> B, and resolve path - // "/ipfs/QmRoot/A/B", the Cid method will return the CID of object B + // Examples: + // If you have 3 linked objects: QmRoot -> A -> B: + // + // cidB := {"foo": {"bar": 42 }} + // cidA := {"B": {"/": cidB }} + // cidRoot := {"A": {"/": cidA }} + // + // And resolve paths: + // * "/ipfs/${cidRoot}" + // * Calling Cid() will return `cidRoot` + // * Calling Root() will return `cidRoot` + // * Calling Remainder() will return `` + // + // * "/ipfs/${cidRoot}/A" + // * Calling Cid() will return `cidA` + // * Calling Root() will return `cidRoot` + // * Calling Remainder() will return `` + // + // * "/ipfs/${cidRoot}/A/B/foo" + // * Calling Cid() will return `cidB` + // * Calling Root() will return `cidRoot` + // * Calling Remainder() will return `foo` + // + // * "/ipfs/${cidRoot}/A/B/foo/bar" + // * Calling Cid() will return `cidB` + // * Calling Root() will return `cidRoot` + // * Calling Remainder() will return `foo/bar` Cid() *cid.Cid // Root returns the CID of the root object of the path @@ -43,6 +68,8 @@ type ResolvedPath interface { // Example: // If you have 3 linked objects: QmRoot -> A -> B, and resolve path // "/ipfs/QmRoot/A/B", the Root method will return the CID of object QmRoot + // + // For more examples see the documentation of Cid() method Root() *cid.Cid // Remainder returns unresolved part of the path @@ -51,9 +78,11 @@ type ResolvedPath interface { // If you have 2 linked objects: QmRoot -> A, where A is a CBOR node // containing the following data: // - // {"foo": {"bar": 42}} + // {"foo": {"bar": 42 }} // // When resolving "/ipld/QmRoot/A/foo/bar", Remainder will return "foo/bar" + // + // For more examples see the documentation of Cid() method Remainder() string Path From 7adf1cb40d013ea9e6b1af09276542df8ace4bbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 12 Jun 2018 03:52:26 +0200 Subject: [PATCH 14/15] coreapi: move path utils to interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/block.go | 4 +- core/coreapi/dag.go | 4 +- core/coreapi/dag_test.go | 7 +-- core/coreapi/interface/coreapi.go | 10 ---- core/coreapi/interface/path.go | 87 +++++++++++++++++++++++++++++++ core/coreapi/key.go | 7 ++- core/coreapi/name.go | 2 +- core/coreapi/object.go | 8 +-- core/coreapi/path.go | 80 +--------------------------- core/coreapi/path_test.go | 9 ++-- core/coreapi/pin.go | 4 +- core/coreapi/unixfs.go | 2 +- core/coreapi/unixfs_test.go | 20 +++---- core/corehttp/gateway_handler.go | 4 +- 14 files changed, 128 insertions(+), 120 deletions(-) diff --git a/core/coreapi/block.go b/core/coreapi/block.go index 6342dc692eb..69f5060c877 100644 --- a/core/coreapi/block.go +++ b/core/coreapi/block.go @@ -65,7 +65,7 @@ func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Bloc return nil, err } - return api.core().IpldPath(b.Cid()), nil + return coreiface.IpldPath(b.Cid()), nil } func (api *BlockAPI) Get(ctx context.Context, p coreiface.Path) (io.Reader, error) { @@ -132,7 +132,7 @@ func (api *BlockAPI) Stat(ctx context.Context, p coreiface.Path) (coreiface.Bloc } return &BlockStat{ - path: api.core().IpldPath(b.Cid()), + path: coreiface.IpldPath(b.Cid()), size: len(b.RawData()), }, nil } diff --git a/core/coreapi/dag.go b/core/coreapi/dag.go index 60692157ce2..75416a249d0 100644 --- a/core/coreapi/dag.go +++ b/core/coreapi/dag.go @@ -44,7 +44,7 @@ func (api *DagAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.DagPut return nil, err } - return api.core().IpldPath(nds[0].Cid()), nil + return coreiface.IpldPath(nds[0].Cid()), nil } // Get resolves `path` using Unixfs resolver, returns the resolved Node. @@ -66,7 +66,7 @@ func (api *DagAPI) Tree(ctx context.Context, p coreiface.Path, opts ...caopts.Da paths := n.Tree("", settings.Depth) out := make([]coreiface.Path, len(paths)) for n, p2 := range paths { - out[n], err = api.core().ParsePath(gopath.Join(p.String(), p2)) + out[n], err = coreiface.ParsePath(gopath.Join(p.String(), p2)) if err != nil { return nil, err } diff --git a/core/coreapi/dag_test.go b/core/coreapi/dag_test.go index 416d7d97bf0..773ff0f1a4c 100644 --- a/core/coreapi/dag_test.go +++ b/core/coreapi/dag_test.go @@ -6,9 +6,10 @@ import ( "strings" "testing" - mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" - + coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" opt "github.com/ipfs/go-ipfs/core/coreapi/interface/options" + + mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" ) var ( @@ -72,7 +73,7 @@ func TestPath(t *testing.T) { t.Error(err) } - p, err := api.ParsePath(path.Join(res.Cid().String(), "lnk")) + p, err := coreiface.ParsePath(path.Join(res.Cid().String(), "lnk")) if err != nil { t.Error(err) } diff --git a/core/coreapi/interface/coreapi.go b/core/coreapi/interface/coreapi.go index f5e81adce6d..82a2ebf4e32 100644 --- a/core/coreapi/interface/coreapi.go +++ b/core/coreapi/interface/coreapi.go @@ -6,7 +6,6 @@ import ( "context" ipld "gx/ipfs/QmZtNq8dArGfnpCZfx2pUNY7UcjGhVp5qqwQ4hH6mpTMRQ/go-ipld-format" - cid "gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid" ) // CoreAPI defines an unified interface to IPFS for Go programs @@ -38,13 +37,4 @@ type CoreAPI interface { // ResolveNode resolves the path (if not resolved already) using Unixfs // resolver, gets and returns the resolved Node ResolveNode(context.Context, Path) (ipld.Node, error) - - // ParsePath parses string path to a Path - ParsePath(string) (Path, error) - - // IpfsPath creates new /ipfs path from the provided CID - IpfsPath(*cid.Cid) ResolvedPath - - // IpldPath creates new /ipld path from the provided CID - IpldPath(*cid.Cid) ResolvedPath } diff --git a/core/coreapi/interface/path.go b/core/coreapi/interface/path.go index acdcd85da70..e097ea3b692 100644 --- a/core/coreapi/interface/path.go +++ b/core/coreapi/interface/path.go @@ -1,9 +1,13 @@ package iface import ( + ipfspath "github.com/ipfs/go-ipfs/path" + cid "gx/ipfs/QmYVNvtQkeZ6AKSwDrjQTs432QtL6umrrK41EBq3cu7iSP/go-cid" ) +//TODO: merge with ipfspath so we don't depend on it + // Path is a generic wrapper for paths used in the API. A path can be resolved // to a CID using one of Resolve functions in the API. // @@ -87,3 +91,86 @@ type ResolvedPath interface { Path } + +// path implements coreiface.Path +type path struct { + path ipfspath.Path +} + +// resolvedPath implements coreiface.resolvedPath +type resolvedPath struct { + path + cid *cid.Cid + root *cid.Cid + remainder string +} + +// IpfsPath creates new /ipfs path from the provided CID +func IpfsPath(c *cid.Cid) ResolvedPath { + return &resolvedPath{ + path: path{ipfspath.Path("/ipfs/" + c.String())}, + cid: c, + root: c, + remainder: "", + } +} + +// IpldPath creates new /ipld path from the provided CID +func IpldPath(c *cid.Cid) ResolvedPath { + return &resolvedPath{ + path: path{ipfspath.Path("/ipld/" + c.String())}, + cid: c, + root: c, + remainder: "", + } +} + +// ParsePath parses string path to a Path +func ParsePath(p string) (Path, error) { + pp, err := ipfspath.ParsePath(p) + if err != nil { + return nil, err + } + + return &path{path: pp}, nil +} + +// NewResolvedPath creates new ResolvedPath. This function performs no checks +// and is intended to be used by resolver implementations. Incorrect inputs may +// cause panics. Handle with care. +func NewResolvedPath(ipath ipfspath.Path, c *cid.Cid, root *cid.Cid, remainder string) ResolvedPath { + return &resolvedPath{ + path: path{ipath}, + cid: c, + root: root, + remainder: remainder, + } +} + +func (p *path) String() string { + return p.path.String() +} + +func (p *path) Namespace() string { + if len(p.path.Segments()) < 1 { + panic("path without namespace") //this shouldn't happen under any scenario + } + return p.path.Segments()[0] +} + +func (p *path) Mutable() bool { + //TODO: MFS: check for /local + return p.Namespace() == "ipns" +} + +func (p *resolvedPath) Cid() *cid.Cid { + return p.cid +} + +func (p *resolvedPath) Root() *cid.Cid { + return p.root +} + +func (p *resolvedPath) Remainder() string { + return p.remainder +} diff --git a/core/coreapi/key.go b/core/coreapi/key.go index 0198f6762b8..e22d70cb424 100644 --- a/core/coreapi/key.go +++ b/core/coreapi/key.go @@ -28,7 +28,12 @@ func (k *key) Name() string { // Path returns the path of the key. func (k *key) Path() coreiface.Path { - return &path{path: ipfspath.FromString(ipfspath.Join([]string{"/ipns", k.peerId}))} + path, err := coreiface.ParsePath(ipfspath.Join([]string{"/ipns", k.peerId})) + if err != nil { + panic("error parsing path: " + err.Error()) + } + + return path } // Generate generates new key, stores it in the keystore under the specified diff --git a/core/coreapi/name.go b/core/coreapi/name.go index 651d8552318..4e1018b5471 100644 --- a/core/coreapi/name.go +++ b/core/coreapi/name.go @@ -129,7 +129,7 @@ func (api *NameAPI) Resolve(ctx context.Context, name string, opts ...caopts.Nam return nil, err } - return &path{path: output}, nil + return coreiface.ParsePath(output.String()) } func keylookup(n *core.IpfsNode, k string) (crypto.PrivKey, error) { diff --git a/core/coreapi/object.go b/core/coreapi/object.go index b8a007bd5ac..f0ccecef6fa 100644 --- a/core/coreapi/object.go +++ b/core/coreapi/object.go @@ -121,7 +121,7 @@ func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Obj return nil, err } - return api.core().IpfsPath(dagnode.Cid()), nil + return coreiface.IpfsPath(dagnode.Cid()), nil } func (api *ObjectAPI) Get(ctx context.Context, path coreiface.Path) (ipld.Node, error) { @@ -218,7 +218,7 @@ func (api *ObjectAPI) AddLink(ctx context.Context, base coreiface.Path, name str return nil, err } - return api.core().IpfsPath(nnode.Cid()), nil + return coreiface.IpfsPath(nnode.Cid()), nil } func (api *ObjectAPI) RmLink(ctx context.Context, base coreiface.Path, link string) (coreiface.ResolvedPath, error) { @@ -244,7 +244,7 @@ func (api *ObjectAPI) RmLink(ctx context.Context, base coreiface.Path, link stri return nil, err } - return api.core().IpfsPath(nnode.Cid()), nil + return coreiface.IpfsPath(nnode.Cid()), nil } func (api *ObjectAPI) AppendData(ctx context.Context, path coreiface.Path, r io.Reader) (coreiface.ResolvedPath, error) { @@ -281,7 +281,7 @@ func (api *ObjectAPI) patchData(ctx context.Context, path coreiface.Path, r io.R return nil, err } - return api.core().IpfsPath(pbnd.Cid()), nil + return coreiface.IpfsPath(pbnd.Cid()), nil } func (api *ObjectAPI) core() coreiface.CoreAPI { diff --git a/core/coreapi/path.go b/core/coreapi/path.go index 85dc0f7ccdb..c8987006ed1 100644 --- a/core/coreapi/path.go +++ b/core/coreapi/path.go @@ -16,39 +16,6 @@ import ( cid "gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid" ) -// path implements coreiface.Path -type path struct { - path ipfspath.Path -} - -// resolvedPath implements coreiface.resolvedPath -type resolvedPath struct { - path - cid *cid.Cid - root *cid.Cid - remainder string -} - -// IpfsPath parses the path from `c`, reruns the parsed path. -func (api *CoreAPI) IpfsPath(c *cid.Cid) coreiface.ResolvedPath { - return &resolvedPath{ - path: path{ipfspath.Path("/ipfs/" + c.String())}, - cid: c, - root: c, - remainder: "", - } -} - -// IpldPath parses the path from `c`, reruns the parsed path. -func (api *CoreAPI) IpldPath(c *cid.Cid) coreiface.ResolvedPath { - return &resolvedPath{ - path: path{ipfspath.Path("/ipld/" + c.String())}, - cid: c, - root: c, - remainder: "", - } -} - // ResolveNode resolves the path `p` using Unixfs resolver, gets and returns the // resolved Node. func (api *CoreAPI) ResolveNode(ctx context.Context, p coreiface.Path) (ipld.Node, error) { @@ -79,7 +46,7 @@ func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSyste return p.(coreiface.ResolvedPath), nil } - ipath := p.(*path).path + ipath := ipfspath.Path(p.String()) ipath, err := core.ResolveIPNS(ctx, nsys, ipath) if err == core.ErrNoNamesys { return nil, coreiface.ErrOffline @@ -113,48 +80,5 @@ func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSyste return nil, err } - return &resolvedPath{ - path: path{ipath}, - cid: node.Cid(), - root: root, - remainder: gopath.Join(rest...), - }, nil -} - -// ParsePath parses path `p` using ipfspath parser, returns the parsed path. -func (api *CoreAPI) ParsePath(p string) (coreiface.Path, error) { - pp, err := ipfspath.ParsePath(p) - if err != nil { - return nil, err - } - - return &path{path: pp}, nil -} - -func (p *path) String() string { - return p.path.String() -} - -func (p *path) Namespace() string { - if len(p.path.Segments()) < 1 { - panic("path without namespace") //this shouldn't happen under any scenario - } - return p.path.Segments()[0] -} - -func (p *path) Mutable() bool { - //TODO: MFS: check for /local - return p.Namespace() == "ipns" -} - -func (p *resolvedPath) Cid() *cid.Cid { - return p.cid -} - -func (p *resolvedPath) Root() *cid.Cid { - return p.root -} - -func (p *resolvedPath) Remainder() string { - return p.remainder + return coreiface.NewResolvedPath(ipath, node.Cid(), root, gopath.Join(rest...)), nil } diff --git a/core/coreapi/path_test.go b/core/coreapi/path_test.go index 7f1f686faab..76e78b5453a 100644 --- a/core/coreapi/path_test.go +++ b/core/coreapi/path_test.go @@ -5,6 +5,7 @@ import ( "strings" "testing" + coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" "github.com/ipfs/go-ipfs/core/coreapi/interface/options" ) @@ -47,7 +48,7 @@ func TestPathRemainder(t *testing.T) { t.Fatal(err) } - p1, err := api.ParsePath(obj.String() + "/foo/bar") + p1, err := coreiface.ParsePath(obj.String() + "/foo/bar") if err != nil { t.Error(err) } @@ -78,7 +79,7 @@ func TestEmptyPathRemainder(t *testing.T) { t.Error("expected the resolved path to not have a remainder") } - p1, err := api.ParsePath(obj.String()) + p1, err := coreiface.ParsePath(obj.String()) if err != nil { t.Error(err) } @@ -105,7 +106,7 @@ func TestInvalidPathRemainder(t *testing.T) { t.Fatal(err) } - p1, err := api.ParsePath(obj.String() + "/bar/baz") + p1, err := coreiface.ParsePath(obj.String() + "/bar/baz") if err != nil { t.Error(err) } @@ -133,7 +134,7 @@ func TestPathRoot(t *testing.T) { t.Fatal(err) } - p1, err := api.ParsePath(obj.String() + "/foo") + p1, err := coreiface.ParsePath(obj.String() + "/foo") if err != nil { t.Error(err) } diff --git a/core/coreapi/pin.go b/core/coreapi/pin.go index e705a20c26d..6c5a0fbdb71 100644 --- a/core/coreapi/pin.go +++ b/core/coreapi/pin.go @@ -125,7 +125,7 @@ func (api *PinAPI) Verify(ctx context.Context) (<-chan coreiface.PinStatus, erro links, err := getLinks(ctx, root) if err != nil { status := &pinStatus{ok: false, cid: root} - status.badNodes = []coreiface.BadPinNode{&badNode{path: api.core().IpldPath(root), err: err}} + status.badNodes = []coreiface.BadPinNode{&badNode{path: coreiface.IpldPath(root), err: err}} visited[key] = status return status } @@ -175,7 +175,7 @@ func (api *PinAPI) pinLsAll(typeStr string, ctx context.Context) ([]coreiface.Pi for _, c := range keyList { keys[c.String()] = &pinInfo{ pinType: typeStr, - path: api.core().IpldPath(c), + path: coreiface.IpldPath(c), } } } diff --git a/core/coreapi/unixfs.go b/core/coreapi/unixfs.go index ef454798908..9cc16ddc596 100644 --- a/core/coreapi/unixfs.go +++ b/core/coreapi/unixfs.go @@ -25,7 +25,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, r io.Reader) (coreiface.ResolvedP if err != nil { return nil, err } - return api.core().IpfsPath(c), nil + return coreiface.IpfsPath(c), nil } // Cat returns the data contained by an IPFS or IPNS object(s) at path `p`. diff --git a/core/coreapi/unixfs_test.go b/core/coreapi/unixfs_test.go index c7325f3ac48..2e7f15f62eb 100644 --- a/core/coreapi/unixfs_test.go +++ b/core/coreapi/unixfs_test.go @@ -151,7 +151,7 @@ func TestCatBasic(t *testing.T) { t.Fatalf("expected CID %s, got: %s", hello, p) } - helloPath, err := api.ParsePath(hello) + helloPath, err := coreiface.ParsePath(hello) if err != nil { t.Fatal(err) } @@ -183,7 +183,7 @@ func TestCatEmptyFile(t *testing.T) { t.Fatal(err) } - emptyFilePath, err := api.ParsePath(emptyFile) + emptyFilePath, err := coreiface.ParsePath(emptyFile) if err != nil { t.Fatal(err) } @@ -214,18 +214,18 @@ func TestCatDir(t *testing.T) { if err != nil { t.Error(err) } - p := api.IpfsPath(edir.Cid()) + p := coreiface.IpfsPath(edir.Cid()) emptyDir, err := api.Object().New(ctx, options.Object.Type("unixfs-dir")) if err != nil { t.Error(err) } - if p.String() != api.IpfsPath(emptyDir.Cid()).String() { + if p.String() != coreiface.IpfsPath(emptyDir.Cid()).String() { t.Fatalf("expected path %s, got: %s", emptyDir.Cid(), p.String()) } - _, err = api.Unixfs().Cat(ctx, api.IpfsPath(emptyDir.Cid())) + _, err = api.Unixfs().Cat(ctx, coreiface.IpfsPath(emptyDir.Cid())) if err != coreiface.ErrIsDir { t.Fatalf("expected ErrIsDir, got: %s", err) } @@ -244,7 +244,7 @@ func TestCatNonUnixfs(t *testing.T) { t.Error(err) } - _, err = api.Unixfs().Cat(ctx, api.IpfsPath(nd.Cid())) + _, err = api.Unixfs().Cat(ctx, coreiface.IpfsPath(nd.Cid())) if !strings.Contains(err.Error(), "proto: required field") { t.Fatalf("expected protobuf error, got: %s", err) } @@ -257,7 +257,7 @@ func TestCatOffline(t *testing.T) { t.Error(err) } - p, err := api.ParsePath("/ipns/Qmfoobar") + p, err := coreiface.ParsePath("/ipns/Qmfoobar") if err != nil { t.Error(err) } @@ -283,7 +283,7 @@ func TestLs(t *testing.T) { if len(parts) != 2 { t.Errorf("unexpected path: %s", k) } - p, err := api.ParsePath("/ipfs/" + parts[0]) + p, err := coreiface.ParsePath("/ipfs/" + parts[0]) if err != nil { t.Error(err) } @@ -324,7 +324,7 @@ func TestLsEmptyDir(t *testing.T) { t.Error(err) } - links, err := api.Unixfs().Ls(ctx, api.IpfsPath(emptyDir.Cid())) + links, err := api.Unixfs().Ls(ctx, coreiface.IpfsPath(emptyDir.Cid())) if err != nil { t.Error(err) } @@ -352,7 +352,7 @@ func TestLsNonUnixfs(t *testing.T) { t.Error(err) } - links, err := api.Unixfs().Ls(ctx, api.IpfsPath(nd.Cid())) + links, err := api.Unixfs().Ls(ctx, coreiface.IpfsPath(nd.Cid())) if err != nil { t.Error(err) } diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index 0f148a4956d..1236b30f576 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -159,7 +159,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr ipnsHostname = true } - parsedPath, err := i.api.ParsePath(urlPath) + parsedPath, err := coreiface.ParsePath(urlPath) if err != nil { webError(w, "invalid ipfs path", err, http.StatusBadRequest) return @@ -287,7 +287,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr return } - dr, err := i.api.Unixfs().Cat(ctx, i.api.IpfsPath(ixnd.Cid())) + dr, err := i.api.Unixfs().Cat(ctx, coreiface.IpfsPath(ixnd.Cid())) if err != nil { internalWebError(w, err) return From 4d5a96b0d6b357d12174e634ec5ce71ec452ac52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 17 Jul 2018 08:47:17 +0200 Subject: [PATCH 15/15] coreapi: path rebase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/coreapi/path.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/coreapi/path.go b/core/coreapi/path.go index c8987006ed1..f2f578ed19d 100644 --- a/core/coreapi/path.go +++ b/core/coreapi/path.go @@ -12,8 +12,8 @@ import ( resolver "github.com/ipfs/go-ipfs/path/resolver" uio "github.com/ipfs/go-ipfs/unixfs/io" - ipld "gx/ipfs/QmWi2BYBL5gJ3CiAiQchg6rn1A8iBsrWy51EYxvHVjFvLb/go-ipld-format" - cid "gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid" + cid "gx/ipfs/QmYVNvtQkeZ6AKSwDrjQTs432QtL6umrrK41EBq3cu7iSP/go-cid" + ipld "gx/ipfs/QmZtNq8dArGfnpCZfx2pUNY7UcjGhVp5qqwQ4hH6mpTMRQ/go-ipld-format" ) // ResolveNode resolves the path `p` using Unixfs resolver, gets and returns the