提交 d06a678e 作者: Łukasz Magiera

coreapi: asunc ls option

License: MIT
Signed-off-by: 's avatarŁukasz Magiera <magik6k@gmail.com>
上级 11ee7503
......@@ -42,7 +42,12 @@ type UnixfsAddSettings struct {
Progress bool
}
type UnixfsLsSettings struct {
Async bool
}
type UnixfsAddOption func(*UnixfsAddSettings) error
type UnixfsLsOption func(*UnixfsLsSettings) error
func UnixfsAddOptions(opts ...UnixfsAddOption) (*UnixfsAddSettings, cid.Prefix, error) {
options := &UnixfsAddSettings{
......@@ -122,6 +127,21 @@ func UnixfsAddOptions(opts ...UnixfsAddOption) (*UnixfsAddSettings, cid.Prefix,
return options, prefix, nil
}
func UnixfsLsOptions(opts ...UnixfsLsOption) (*UnixfsLsSettings, error) {
options := &UnixfsLsSettings{
Async: true,
}
for _, opt := range opts {
err := opt(options)
if err != nil {
return nil, err
}
}
return options, nil
}
type unixfsOpts struct{}
var Unixfs unixfsOpts
......@@ -290,3 +310,13 @@ func (unixfsOpts) Nocopy(enable bool) UnixfsAddOption {
return nil
}
}
// Async tells ls to return results as soon as they are available, which can be
// useful for listing HAMT directories. When this option is set to true returned
// results won't be returned in order
func (unixfsOpts) Async(async bool) UnixfsLsOption {
return func(settings *UnixfsLsSettings) error {
settings.Async = async
return nil
}
}
......@@ -749,12 +749,12 @@ func (tp *provider) TestLs(t *testing.T) {
t.Error(err)
}
links, err := api.Unixfs().Ls(ctx, p)
links, err := api.Unixfs().Ls(ctx, p, options.Unixfs.Async(false))
if err != nil {
t.Error(err)
}
link := <- links
link := (<-links).Link
if link.Size != 23 {
t.Fatalf("expected size = 23, got %d", link.Size)
}
......@@ -768,6 +768,24 @@ func (tp *provider) TestLs(t *testing.T) {
t.Errorf("didn't expect a second link")
}
links, err = api.Unixfs().Ls(ctx, p, options.Unixfs.Async(true))
if err != nil {
t.Error(err)
}
link = (<-links).Link
if link.Size != 23 {
t.Fatalf("expected size = 23, got %d", link.Size)
}
if link.Name != "name-of-file" {
t.Fatalf("expected name = name-of-file, got %s", link.Name)
}
if link.Cid.String() != "QmX3qQVKxDGz3URVC3861Z3CKtQKGBn6ffXRBBWGMFz9Lr" {
t.Fatalf("expected cid = QmX3qQVKxDGz3URVC3861Z3CKtQKGBn6ffXRBBWGMFz9Lr, got %s", link.Cid)
}
if _, ok := <-links; ok {
t.Errorf("didn't expect a second link")
}
}
func (tp *provider) TestEntriesExpired(t *testing.T) {
......
......@@ -5,8 +5,8 @@ import (
"github.com/ipfs/go-ipfs/core/coreapi/interface/options"
ipld "gx/ipfs/QmRL22E4paat7ky7vx9MLpR97JHHbFPrg3ytFQw6qp1y1s/go-ipld-format"
files "gx/ipfs/QmaXvvAVAQ5ABqM5xtjYmV85xmN5MkWAZsX9H9Fwo4FVXp/go-ipfs-files"
ft "gx/ipfs/QmQ1JnYpnzkaurjW1yxkQxC2w3K1PorNE1nv1vaP5Le7sq/go-unixfs"
"gx/ipfs/QmaXvvAVAQ5ABqM5xtjYmV85xmN5MkWAZsX9H9Fwo4FVXp/go-ipfs-files"
)
type AddEvent struct {
......@@ -31,5 +31,5 @@ type UnixfsAPI interface {
Get(context.Context, Path) (files.Node, error)
// Ls returns the list of links in a directory
Ls(context.Context, Path) (<-chan *ipld.Link, error)
Ls(context.Context, Path, ...options.UnixfsLsOption) (<-chan ft.LinkResult, error)
}
......@@ -143,30 +143,49 @@ func (api *UnixfsAPI) Get(ctx context.Context, p coreiface.Path) (files.Node, er
// Ls returns the contents of an IPFS or IPNS object(s) at path p, with the format:
// `<link base58 hash> <link size in bytes> <link name>`
func (api *UnixfsAPI) Ls(ctx context.Context, p coreiface.Path) (<-chan *ipld.Link, error) {
func (api *UnixfsAPI) Ls(ctx context.Context, p coreiface.Path, opts ...options.UnixfsLsOption) (<-chan ft.LinkResult, error) {
settings, err := options.UnixfsLsOptions(opts...)
if err != nil {
return nil, err
}
dagnode, err := api.core().ResolveNode(ctx, p)
if err != nil {
return nil, err
}
var ndlinks []*ipld.Link
dir, err := uio.NewDirectoryFromNode(api.dag, dagnode)
switch err {
case nil:
l, err := dir.Links(ctx)
if err != nil {
return nil, err
}
ndlinks = l
case uio.ErrNotADir:
ndlinks = dagnode.Links()
default:
if err == uio.ErrNotADir {
return lsFromLinks(dagnode.Links())
}
if err != nil {
return nil, err
}
if !settings.Async {
return lsFromDir(ctx, dir)
}
return lsFromLinksAsync(ctx, dir)
}
func lsFromLinksAsync(ctx context.Context, dir uio.Directory) (<-chan ft.LinkResult, error) {
return dir.EnumLinksAsync(ctx), nil
}
func lsFromDir(ctx context.Context, dir uio.Directory) (<-chan ft.LinkResult, error) {
l, err := dir.Links(ctx)
if err != nil {
return nil, err
}
return lsFromLinks(l)
}
links := make(chan *ipld.Link, len(ndlinks))
func lsFromLinks(ndlinks []*ipld.Link) (<-chan ft.LinkResult, error) {
links := make(chan ft.LinkResult, len(ndlinks))
for _, l := range ndlinks {
links <- &ipld.Link{Name: l.Name, Size: l.Size, Cid: l.Cid}
links <- ft.LinkResult{Link: &ipld.Link{Name: l.Name, Size: l.Size, Cid: l.Cid}}
}
close(links)
return links, nil
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论