提交 73f1e2db 作者: Łukasz Magiera

ls: use CoreAPI

License: MIT
Signed-off-by: 's avatarŁukasz Magiera <magik6k@gmail.com>
上级 628cd7ed
...@@ -8,18 +8,12 @@ import ( ...@@ -8,18 +8,12 @@ import (
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
iface "github.com/ipfs/go-ipfs/core/coreapi/interface" iface "github.com/ipfs/go-ipfs/core/coreapi/interface"
options "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
unixfs "gx/ipfs/QmQ1JnYpnzkaurjW1yxkQxC2w3K1PorNE1nv1vaP5Le7sq/go-unixfs" unixfs "gx/ipfs/QmQ1JnYpnzkaurjW1yxkQxC2w3K1PorNE1nv1vaP5Le7sq/go-unixfs"
uio "gx/ipfs/QmQ1JnYpnzkaurjW1yxkQxC2w3K1PorNE1nv1vaP5Le7sq/go-unixfs/io"
unixfspb "gx/ipfs/QmQ1JnYpnzkaurjW1yxkQxC2w3K1PorNE1nv1vaP5Le7sq/go-unixfs/pb" unixfspb "gx/ipfs/QmQ1JnYpnzkaurjW1yxkQxC2w3K1PorNE1nv1vaP5Le7sq/go-unixfs/pb"
cmds "gx/ipfs/QmR77mMvvh8mJBBWQmBfQBu8oD38NUN4KE9SL2gDgAQNc6/go-ipfs-cmds" cmds "gx/ipfs/QmR77mMvvh8mJBBWQmBfQBu8oD38NUN4KE9SL2gDgAQNc6/go-ipfs-cmds"
cid "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid" cmdkit "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit"
ipld "gx/ipfs/QmRL22E4paat7ky7vx9MLpR97JHHbFPrg3ytFQw6qp1y1s/go-ipld-format"
blockservice "gx/ipfs/QmVKQHuzni68SWByzJgBUCwHvvr4TWiXfutNWWwpZpp4rE/go-blockservice"
offline "gx/ipfs/QmYZwey1thDTynSrvd6qQkX24UpTka6TFhQ2v569UpoqxD/go-ipfs-exchange-offline"
merkledag "gx/ipfs/Qmb2UEG2TAeVrEJSjqsZF7Y2he7wRDkrdt6c3bECxwZf4k/go-merkledag"
cidenc "gx/ipfs/QmdPQx9fvN5ExVwMhRmh7YpCQJzJrFhd1AjVBwJmRMFJeX/go-cidutil/cidenc"
"gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit"
) )
// LsLink contains printable data for a single ipld link in ls output // LsLink contains printable data for a single ipld link in ls output
...@@ -72,11 +66,6 @@ The JSON output contains type information. ...@@ -72,11 +66,6 @@ The JSON output contains type information.
cmdkit.BoolOption(lsStreamOptionName, "s", "Enable exprimental streaming of directory entries as they are traversed."), cmdkit.BoolOption(lsStreamOptionName, "s", "Enable exprimental streaming of directory entries as they are traversed."),
}, },
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
nd, err := cmdenv.GetNode(env)
if err != nil {
return err
}
api, err := cmdenv.GetApi(env, req) api, err := cmdenv.GetApi(env, req)
if err != nil { if err != nil {
return err return err
...@@ -84,12 +73,7 @@ The JSON output contains type information. ...@@ -84,12 +73,7 @@ The JSON output contains type information.
resolveType, _ := req.Options[lsResolveTypeOptionName].(bool) resolveType, _ := req.Options[lsResolveTypeOptionName].(bool)
resolveSize, _ := req.Options[lsSizeOptionName].(bool) resolveSize, _ := req.Options[lsSizeOptionName].(bool)
dserv := nd.DAG stream, _ := req.Options[lsStreamOptionName].(bool)
if !resolveType && !resolveSize {
offlineexch := offline.Exchange(nd.Blockstore)
bserv := blockservice.New(nd.Blockstore, offlineexch)
dserv = merkledag.NewDAGService(bserv)
}
err = req.ParseBodyArgs() err = req.ParseBodyArgs()
if err != nil { if err != nil {
...@@ -102,90 +86,80 @@ The JSON output contains type information. ...@@ -102,90 +86,80 @@ The JSON output contains type information.
return err return err
} }
var dagnodes []ipld.Node var processLink func(path string, link LsLink) error
for _, fpath := range paths { var dirDone func(i int)
p, err := iface.ParsePath(fpath)
if err != nil {
return err
}
dagnode, err := api.ResolveNode(req.Context, p)
if err != nil {
return err
}
dagnodes = append(dagnodes, dagnode)
}
ng := merkledag.NewSession(req.Context, nd.DAG)
ro := merkledag.NewReadOnlyDagService(ng)
stream, _ := req.Options[lsStreamOptionName].(bool) processDir := func() (func(path string, link LsLink) error, func(i int)) {
return func(path string, link LsLink) error {
output := []LsObject{{
Hash: path,
Links: []LsLink{link},
}}
return res.Emit(&LsOutput{output})
}, func(i int) {}
}
done := func() error { return nil }
if !stream { if !stream {
output := make([]LsObject, len(req.Arguments)) output := make([]LsObject, len(req.Arguments))
for i, dagnode := range dagnodes { processDir = func() (func(path string, link LsLink) error, func(i int)) {
dir, err := uio.NewDirectoryFromNode(ro, dagnode) // for each dir
if err != nil && err != uio.ErrNotADir { outputLinks := make([]LsLink, 0)
return fmt.Errorf("the data in %s (at %q) is not a UnixFS directory: %s", dagnode.Cid(), paths[i], err) return func(path string, link LsLink) error {
} // for each link
outputLinks = append(outputLinks, link)
var links []*ipld.Link return nil
if dir == nil { }, func(i int) {
links = dagnode.Links() // after each dir
} else { output[i] = LsObject{
links, err = dir.Links(req.Context) Hash: paths[i],
if err != nil { Links: outputLinks,
return err }
}
}
outputLinks := make([]LsLink, len(links))
for j, link := range links {
lsLink, err := makeLsLink(req, dserv, resolveType, resolveSize, link, enc)
if err != nil {
return err
} }
outputLinks[j] = *lsLink
}
output[i] = LsObject{
Hash: paths[i],
Links: outputLinks,
}
} }
return cmds.EmitOnce(res, &LsOutput{output}) done = func() error {
return cmds.EmitOnce(res, &LsOutput{output})
}
} }
for i, dagnode := range dagnodes { for i, fpath := range paths {
dir, err := uio.NewDirectoryFromNode(ro, dagnode) p, err := iface.ParsePath(fpath)
if err != nil && err != uio.ErrNotADir { if err != nil {
return fmt.Errorf("the data in %s (at %q) is not a UnixFS directory: %s", dagnode.Cid(), paths[i], err) return err
} }
var linkResults <-chan unixfs.LinkResult results, err := api.Unixfs().Ls(req.Context, p,
if dir == nil { options.Unixfs.Async(stream),
linkResults = makeDagNodeLinkResults(req, dagnode) options.Unixfs.ResolveType(resolveType),
} else { options.Unixfs.ResolveSize(resolveSize))
linkResults = dir.EnumLinksAsync(req.Context) if err != nil {
return err
} }
for linkResult := range linkResults { processLink, dirDone = processDir()
for link := range results {
if linkResult.Err != nil { if link.Err != nil {
return linkResult.Err return link.Err
} }
link := linkResult.Link lsLink := LsLink{
lsLink, err := makeLsLink(req, dserv, resolveType, resolveSize, link, enc) Name: link.Link.Name,
if err != nil { Hash: enc.Encode(link.Link.Cid),
return err
Size: link.Size,
Type: link.Type,
} }
output := []LsObject{{ if err := processLink(paths[i], lsLink); err != nil {
Hash: paths[i],
Links: []LsLink{*lsLink},
}}
if err = res.Emit(&LsOutput{output}); err != nil {
return err return err
} }
} }
dirDone(i)
} }
if err := done(); err != nil {
return err
}
return nil return nil
}, },
PostRun: cmds.PostRunMap{ PostRun: cmds.PostRunMap{
...@@ -219,58 +193,6 @@ The JSON output contains type information. ...@@ -219,58 +193,6 @@ The JSON output contains type information.
Type: LsOutput{}, Type: LsOutput{},
} }
func makeDagNodeLinkResults(req *cmds.Request, dagnode ipld.Node) <-chan unixfs.LinkResult {
links := dagnode.Links()
linkResults := make(chan unixfs.LinkResult, len(links))
defer close(linkResults)
for _, l := range links {
linkResults <- unixfs.LinkResult{
Link: l,
Err: nil,
}
}
return linkResults
}
func makeLsLink(req *cmds.Request, dserv ipld.DAGService, resolveType bool, resolveSize bool, link *ipld.Link, enc cidenc.Encoder) (*LsLink, error) {
t := unixfspb.Data_DataType(-1)
var size uint64
switch link.Cid.Type() {
case cid.Raw:
// No need to check with raw leaves
t = unixfs.TFile
size = link.Size
case cid.DagProtobuf:
linkNode, err := link.GetNode(req.Context, dserv)
if err == ipld.ErrNotFound && !resolveType && !resolveSize {
// not an error
linkNode = nil
} else if err != nil {
return nil, err
}
if pn, ok := linkNode.(*merkledag.ProtoNode); ok {
d, err := unixfs.FSNodeFromBytes(pn.Data())
if err != nil {
return nil, err
}
if resolveType {
t = d.Type()
}
if d.Type() == unixfs.TFile && resolveSize {
size = d.FileSize()
}
}
}
return &LsLink{
Name: link.Name,
Hash: enc.Encode(link.Cid),
Size: size,
Type: t,
}, nil
}
func tabularOutput(req *cmds.Request, w io.Writer, out *LsOutput, lastObjectHash string, ignoreBreaks bool) string { func tabularOutput(req *cmds.Request, w io.Writer, out *LsOutput, lastObjectHash string, ignoreBreaks bool) string {
headers, _ := req.Options[lsHeadersOptionNameTime].(bool) headers, _ := req.Options[lsHeadersOptionNameTime].(bool)
stream, _ := req.Options[lsStreamOptionName].(bool) stream, _ := req.Options[lsStreamOptionName].(bool)
......
...@@ -133,6 +133,9 @@ func UnixfsAddOptions(opts ...UnixfsAddOption) (*UnixfsAddSettings, cid.Prefix, ...@@ -133,6 +133,9 @@ func UnixfsAddOptions(opts ...UnixfsAddOption) (*UnixfsAddSettings, cid.Prefix,
func UnixfsLsOptions(opts ...UnixfsLsOption) (*UnixfsLsSettings, error) { func UnixfsLsOptions(opts ...UnixfsLsOption) (*UnixfsLsSettings, error) {
options := &UnixfsLsSettings{ options := &UnixfsLsSettings{
Async: true, Async: true,
ResolveSize: true,
ResolveType: true,
} }
for _, opt := range opts { for _, opt := range opts {
...@@ -333,7 +336,7 @@ func (unixfsOpts) ResolveSize(resolve bool) UnixfsLsOption { ...@@ -333,7 +336,7 @@ func (unixfsOpts) ResolveSize(resolve bool) UnixfsLsOption {
func (unixfsOpts) ResolveType(resolve bool) UnixfsLsOption { func (unixfsOpts) ResolveType(resolve bool) UnixfsLsOption {
return func(settings *UnixfsLsSettings) error { return func(settings *UnixfsLsSettings) error {
settings.ResolveSize = resolve settings.ResolveType = resolve
return nil return nil
} }
} }
\ No newline at end of file
...@@ -151,24 +151,27 @@ func (api *UnixfsAPI) Ls(ctx context.Context, p coreiface.Path, opts ...options. ...@@ -151,24 +151,27 @@ func (api *UnixfsAPI) Ls(ctx context.Context, p coreiface.Path, opts ...options.
return nil, err return nil, err
} }
dagnode, err := api.core().ResolveNode(ctx, p) ses := api.core().getSession(ctx)
uses := (*UnixfsAPI)(ses)
dagnode, err := ses.ResolveNode(ctx, p)
if err != nil { if err != nil {
return nil, err return nil, err
} }
dir, err := uio.NewDirectoryFromNode(api.dag, dagnode) dir, err := uio.NewDirectoryFromNode(ses.dag, dagnode)
if err == uio.ErrNotADir { if err == uio.ErrNotADir {
return api.lsFromLinks(ctx, dagnode.Links(), settings) return uses.lsFromLinks(ctx, dagnode.Links(), settings)
} }
if err != nil { if err != nil {
return nil, err return nil, err
} }
if !settings.Async { if !settings.Async {
return api.lsFromDir(ctx, dir, settings) return uses.lsFromDir(ctx, dir, settings)
} }
return api.lsFromLinksAsync(ctx, dir, settings) return uses.lsFromLinksAsync(ctx, dir, settings)
} }
func (api *UnixfsAPI) processLink(ctx context.Context, linkres ft.LinkResult, settings *options.UnixfsLsSettings) coreiface.LsLink { func (api *UnixfsAPI) processLink(ctx context.Context, linkres ft.LinkResult, settings *options.UnixfsLsSettings) coreiface.LsLink {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论