1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-06-19 18:05:32 +08:00

coreapi: separate path into two types

License: MIT
Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
This commit is contained in:
Łukasz Magiera
2018-02-08 17:39:05 +01:00
parent 4f6c0666ea
commit 15f8fc60c0
18 changed files with 158 additions and 141 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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)
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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
}
// 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}
return &path{path: pp}, nil
}
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 *path) Namespace() string {
if len(p.path.Segments()) < 1 {
return ""
}
return p.path.Segments()[0]
}
func (p *resolvedPath) Cid() *cid.Cid { return p.cid }
func (p *resolvedPath) Root() *cid.Cid { return p.root }

View File

@ -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),
}
}
}

View File

@ -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

View File

@ -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)
}

View File

@ -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
}