@cryptotaxi247 / kubo / commits / 73f1e2dbf

ls: use CoreAPI

License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>

Łukasz Magiera committed Feb 2, 2019 at 00:18 UTC 73f1e2dbf09f6ef094b73b280415392c78e9c88b
3 files changed +70 -142
core/commands/ls.go
+57 -135
@@ -8,18 +8,12 @@ import (
8
9 cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
10 iface "github.com/ipfs/go-ipfs/core/coreapi/interface"
11 + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
12
13 unixfs "gx/ipfs/QmQ1JnYpnzkaurjW1yxkQxC2w3K1PorNE1nv1vaP5Le7sq/go-unixfs"
13 - uio "gx/ipfs/QmQ1JnYpnzkaurjW1yxkQxC2w3K1PorNE1nv1vaP5Le7sq/go-unixfs/io"
14 unixfspb "gx/ipfs/QmQ1JnYpnzkaurjW1yxkQxC2w3K1PorNE1nv1vaP5Le7sq/go-unixfs/pb"
15 cmds "gx/ipfs/QmR77mMvvh8mJBBWQmBfQBu8oD38NUN4KE9SL2gDgAQNc6/go-ipfs-cmds"
16 - cid "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid"
17 - ipld "gx/ipfs/QmRL22E4paat7ky7vx9MLpR97JHHbFPrg3ytFQw6qp1y1s/go-ipld-format"
18 - blockservice "gx/ipfs/QmVKQHuzni68SWByzJgBUCwHvvr4TWiXfutNWWwpZpp4rE/go-blockservice"
19 - offline "gx/ipfs/QmYZwey1thDTynSrvd6qQkX24UpTka6TFhQ2v569UpoqxD/go-ipfs-exchange-offline"
20 - merkledag "gx/ipfs/Qmb2UEG2TAeVrEJSjqsZF7Y2he7wRDkrdt6c3bECxwZf4k/go-merkledag"
21 - cidenc "gx/ipfs/QmdPQx9fvN5ExVwMhRmh7YpCQJzJrFhd1AjVBwJmRMFJeX/go-cidutil/cidenc"
22 - "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit"
16 + cmdkit "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit"
17 )
18
19 // LsLink contains printable data for a single ipld link in ls output
@@ -72,11 +66,6 @@ The JSON output contains type information.
66 cmdkit.BoolOption(lsStreamOptionName, "s", "Enable exprimental streaming of directory entries as they are traversed."),
67 },
68 Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
75 - nd, err := cmdenv.GetNode(env)
76 - if err != nil {
77 - return err
78 - }
79 -
69 api, err := cmdenv.GetApi(env, req)
70 if err != nil {
71 return err
@@ -84,12 +73,7 @@ The JSON output contains type information.
73
74 resolveType, _ := req.Options[lsResolveTypeOptionName].(bool)
75 resolveSize, _ := req.Options[lsSizeOptionName].(bool)
87 - dserv := nd.DAG
88 - if !resolveType && !resolveSize {
89 - offlineexch := offline.Exchange(nd.Blockstore)
90 - bserv := blockservice.New(nd.Blockstore, offlineexch)
91 - dserv = merkledag.NewDAGService(bserv)
92 - }
76 + stream, _ := req.Options[lsStreamOptionName].(bool)
77
78 err = req.ParseBodyArgs()
79 if err != nil {
@@ -102,90 +86,80 @@ The JSON output contains type information.
86 return err
87 }
88
105 - var dagnodes []ipld.Node
106 - for _, fpath := range paths {
107 - p, err := iface.ParsePath(fpath)
108 - if err != nil {
109 - return err
110 - }
111 - dagnode, err := api.ResolveNode(req.Context, p)
112 - if err != nil {
113 - return err
114 - }
115 - dagnodes = append(dagnodes, dagnode)
116 - }
117 - ng := merkledag.NewSession(req.Context, nd.DAG)
118 - ro := merkledag.NewReadOnlyDagService(ng)
89 + var processLink func(path string, link LsLink) error
90 + var dirDone func(i int)
91
120 - stream, _ := req.Options[lsStreamOptionName].(bool)
92 + processDir := func() (func(path string, link LsLink) error, func(i int)) {
93 + return func(path string, link LsLink) error {
94 + output := []LsObject{{
95 + Hash: path,
96 + Links: []LsLink{link},
97 + }}
98 + return res.Emit(&LsOutput{output})
99 + }, func(i int) {}
100 + }
101 + done := func() error { return nil }
102
103 if !stream {
104 output := make([]LsObject, len(req.Arguments))
105
125 - for i, dagnode := range dagnodes {
126 - dir, err := uio.NewDirectoryFromNode(ro, dagnode)
127 - if err != nil && err != uio.ErrNotADir {
128 - return fmt.Errorf("the data in %s (at %q) is not a UnixFS directory: %s", dagnode.Cid(), paths[i], err)
129 - }
130 -
131 - var links []*ipld.Link
132 - if dir == nil {
133 - links = dagnode.Links()
134 - } else {
135 - links, err = dir.Links(req.Context)
136 - if err != nil {
137 - return err
138 - }
139 - }
140 - outputLinks := make([]LsLink, len(links))
141 - for j, link := range links {
142 - lsLink, err := makeLsLink(req, dserv, resolveType, resolveSize, link, enc)
143 - if err != nil {
144 - return err
106 + processDir = func() (func(path string, link LsLink) error, func(i int)) {
107 + // for each dir
108 + outputLinks := make([]LsLink, 0)
109 + return func(path string, link LsLink) error {
110 + // for each link
111 + outputLinks = append(outputLinks, link)
112 + return nil
113 + }, func(i int) {
114 + // after each dir
115 + output[i] = LsObject{
116 + Hash: paths[i],
117 + Links: outputLinks,
118 + }
119 }
146 - outputLinks[j] = *lsLink
147 - }
148 - output[i] = LsObject{
149 - Hash: paths[i],
150 - Links: outputLinks,
151 - }
120 }
121
154 - return cmds.EmitOnce(res, &LsOutput{output})
122 + done = func() error {
123 + return cmds.EmitOnce(res, &LsOutput{output})
124 + }
125 }
126
157 - for i, dagnode := range dagnodes {
158 - dir, err := uio.NewDirectoryFromNode(ro, dagnode)
159 - if err != nil && err != uio.ErrNotADir {
160 - return fmt.Errorf("the data in %s (at %q) is not a UnixFS directory: %s", dagnode.Cid(), paths[i], err)
127 + for i, fpath := range paths {
128 + p, err := iface.ParsePath(fpath)
129 + if err != nil {
130 + return err
131 }
132
163 - var linkResults <-chan unixfs.LinkResult
164 - if dir == nil {
165 - linkResults = makeDagNodeLinkResults(req, dagnode)
166 - } else {
167 - linkResults = dir.EnumLinksAsync(req.Context)
133 + results, err := api.Unixfs().Ls(req.Context, p,
134 + options.Unixfs.Async(stream),
135 + options.Unixfs.ResolveType(resolveType),
136 + options.Unixfs.ResolveSize(resolveSize))
137 + if err != nil {
138 + return err
139 }
140
170 - for linkResult := range linkResults {
171 -
172 - if linkResult.Err != nil {
173 - return linkResult.Err
141 + processLink, dirDone = processDir()
142 + for link := range results {
143 + if link.Err != nil {
144 + return link.Err
145 }
175 - link := linkResult.Link
176 - lsLink, err := makeLsLink(req, dserv, resolveType, resolveSize, link, enc)
177 - if err != nil {
178 - return err
146 + lsLink := LsLink{
147 + Name: link.Link.Name,
148 + Hash: enc.Encode(link.Link.Cid),
149 +
150 + Size: link.Size,
151 + Type: link.Type,
152 }
180 - output := []LsObject{{
181 - Hash: paths[i],
182 - Links: []LsLink{*lsLink},
183 - }}
184 - if err = res.Emit(&LsOutput{output}); err != nil {
153 + if err := processLink(paths[i], lsLink); err != nil {
154 return err
155 }
156 }
157 + dirDone(i)
158 }
159 + if err := done(); err != nil {
160 + return err
161 + }
162 +
163 return nil
164 },
165 PostRun: cmds.PostRunMap{
@@ -219,58 +193,6 @@ The JSON output contains type information.
193 Type: LsOutput{},
194 }
195
222 -func makeDagNodeLinkResults(req *cmds.Request, dagnode ipld.Node) <-chan unixfs.LinkResult {
223 - links := dagnode.Links()
224 - linkResults := make(chan unixfs.LinkResult, len(links))
225 - defer close(linkResults)
226 - for _, l := range links {
227 - linkResults <- unixfs.LinkResult{
228 - Link: l,
229 - Err: nil,
230 - }
231 - }
232 - return linkResults
233 -}
234 -
235 -func makeLsLink(req *cmds.Request, dserv ipld.DAGService, resolveType bool, resolveSize bool, link *ipld.Link, enc cidenc.Encoder) (*LsLink, error) {
236 - t := unixfspb.Data_DataType(-1)
237 - var size uint64
238 -
239 - switch link.Cid.Type() {
240 - case cid.Raw:
241 - // No need to check with raw leaves
242 - t = unixfs.TFile
243 - size = link.Size
244 - case cid.DagProtobuf:
245 - linkNode, err := link.GetNode(req.Context, dserv)
246 - if err == ipld.ErrNotFound && !resolveType && !resolveSize {
247 - // not an error
248 - linkNode = nil
249 - } else if err != nil {
250 - return nil, err
251 - }
252 -
253 - if pn, ok := linkNode.(*merkledag.ProtoNode); ok {
254 - d, err := unixfs.FSNodeFromBytes(pn.Data())
255 - if err != nil {
256 - return nil, err
257 - }
258 - if resolveType {
259 - t = d.Type()
260 - }
261 - if d.Type() == unixfs.TFile && resolveSize {
262 - size = d.FileSize()
263 - }
264 - }
265 - }
266 - return &LsLink{
267 - Name: link.Name,
268 - Hash: enc.Encode(link.Cid),
269 - Size: size,
270 - Type: t,
271 - }, nil
272 -}
273 -
196 func tabularOutput(req *cmds.Request, w io.Writer, out *LsOutput, lastObjectHash string, ignoreBreaks bool) string {
197 headers, _ := req.Options[lsHeadersOptionNameTime].(bool)
198 stream, _ := req.Options[lsStreamOptionName].(bool)
core/coreapi/interface/options/unixfs.go
+5 -2
@@ -133,6 +133,9 @@ func UnixfsAddOptions(opts ...UnixfsAddOption) (*UnixfsAddSettings, cid.Prefix,
133 func UnixfsLsOptions(opts ...UnixfsLsOption) (*UnixfsLsSettings, error) {
134 options := &UnixfsLsSettings{
135 Async: true,
136 +
137 + ResolveSize: true,
138 + ResolveType: true,
139 }
140
141 for _, opt := range opts {
@@ -333,7 +336,7 @@ func (unixfsOpts) ResolveSize(resolve bool) UnixfsLsOption {
336
337 func (unixfsOpts) ResolveType(resolve bool) UnixfsLsOption {
338 return func(settings *UnixfsLsSettings) error {
336 - settings.ResolveSize = resolve
339 + settings.ResolveType = resolve
340 return nil
341 }
339 -}
\ No newline at end of file
342 +}
core/coreapi/unixfs.go
+8 -5
@@ -151,24 +151,27 @@ func (api *UnixfsAPI) Ls(ctx context.Context, p coreiface.Path, opts ...options.
151 return nil, err
152 }
153
154 - dagnode, err := api.core().ResolveNode(ctx, p)
154 + ses := api.core().getSession(ctx)
155 + uses := (*UnixfsAPI)(ses)
156 +
157 + dagnode, err := ses.ResolveNode(ctx, p)
158 if err != nil {
159 return nil, err
160 }
161
159 - dir, err := uio.NewDirectoryFromNode(api.dag, dagnode)
162 + dir, err := uio.NewDirectoryFromNode(ses.dag, dagnode)
163 if err == uio.ErrNotADir {
161 - return api.lsFromLinks(ctx, dagnode.Links(), settings)
164 + return uses.lsFromLinks(ctx, dagnode.Links(), settings)
165 }
166 if err != nil {
167 return nil, err
168 }
169
170 if !settings.Async {
168 - return api.lsFromDir(ctx, dir, settings)
171 + return uses.lsFromDir(ctx, dir, settings)
172 }
173
171 - return api.lsFromLinksAsync(ctx, dir, settings)
174 + return uses.lsFromLinksAsync(ctx, dir, settings)
175 }
176
177 func (api *UnixfsAPI) processLink(ctx context.Context, linkres ft.LinkResult, settings *options.UnixfsLsSettings) coreiface.LsLink {