@cryptotaxi247 / kubo / commits / 5672ae6bb

fix(commands): Refactor to use a PostRun

Removes flags on LSOutput License: MIT Signed-off-by: hannahhoward <hannah@hannahhoward.net>

hannahhoward committed Nov 8, 2018 at 14:07 UTC 5672ae6bbb32382b65b6e4a1ee9c49a7659c3646
1 file changed +66 -62
core/commands/ls.go
+66 -62
@@ -3,6 +3,7 @@ package commands
3 import (
4 "fmt"
5 "io"
6 + "os"
7 "text/tabwriter"
8
9 cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
@@ -29,20 +30,16 @@ type LsLink struct {
30 }
31
32 // LsObject is an element of LsOutput
32 -// It can represent a whole directory, a directory header, one or more links,
33 -// Or a the end of a directory
33 +// It can represent all or part of a directory
34 type LsObject struct {
35 - Hash string
36 - Links []LsLink
37 - HasHeader bool
38 - HasLinks bool
39 - HasFooter bool
35 + Hash string
36 + Links []LsLink
37 }
38
42 -// LsOutput is a set of printable data for directories
39 +// LsOutput is a set of printable data for directories,
40 +// it can be complete or partial
41 type LsOutput struct {
44 - MultipleFolders bool
45 - Objects []LsObject
42 + Objects []LsObject
43 }
44
45 const (
@@ -114,10 +111,10 @@ The JSON output contains type information.
111 ng := merkledag.NewSession(req.Context, nd.DAG)
112 ro := merkledag.NewReadOnlyDagService(ng)
113
114 + output := make([]LsObject, len(req.Arguments))
115 +
116 stream, _ := req.Options[lsStreamOptionName].(bool)
118 - multipleFolders := len(req.Arguments) > 1
117 if !stream {
120 - output := make([]LsObject, len(req.Arguments))
118
119 for i, dagnode := range dagnodes {
120 dir, err := uio.NewDirectoryFromNode(ro, dagnode)
@@ -142,10 +139,21 @@ The JSON output contains type information.
139 }
140 outputLinks[j] = *lsLink
141 }
145 - output[i] = newFullDirectoryLsObject(paths[i], outputLinks)
142 + output[i] = LsObject{
143 + Hash: paths[i],
144 + Links: outputLinks,
145 + }
146 }
147
148 - return cmds.EmitOnce(res, &LsOutput{multipleFolders, output})
148 + return cmds.EmitOnce(res, &LsOutput{output})
149 + }
150 +
151 + outputLinks := make([]LsLink, 1)
152 + for i, path := range paths {
153 + output[i] = LsObject{
154 + Hash: path,
155 + Links: nil,
156 + }
157 }
158
159 for i, dagnode := range dagnodes {
@@ -161,13 +169,8 @@ The JSON output contains type information.
169 linkResults = dir.EnumLinksAsync(req.Context)
170 }
171
164 - output := make([]LsObject, 1)
165 - outputLinks := make([]LsLink, 1)
172 + output[i].Links = outputLinks
173
167 - output[0] = newDirectoryHeaderLsObject(paths[i])
168 - if err = res.Emit(&LsOutput{multipleFolders, output}); err != nil {
169 - return nil
170 - }
174 for linkResult := range linkResults {
175 if linkResult.Err != nil {
176 return linkResult.Err
@@ -178,37 +181,57 @@ The JSON output contains type information.
181 return err
182 }
183 outputLinks[0] = *lsLink
181 - output[0] = newDirectoryLinksLsObject(outputLinks)
182 - if err = res.Emit(&LsOutput{multipleFolders, output}); err != nil {
184 + if err = res.Emit(&LsOutput{output}); err != nil {
185 return err
186 }
187 }
186 - output[0] = newDirectoryFooterLsObject()
187 - if err = res.Emit(&LsOutput{multipleFolders, output}); err != nil {
188 - return err
189 - }
188 + output[i].Links = nil
189 }
190 return nil
191 },
193 - Encoders: cmds.EncoderMap{
194 - cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error {
192 + PostRun: cmds.PostRunMap{
193 + cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error {
194 + req := res.Request()
195 headers, _ := req.Options[lsHeadersOptionNameTime].(bool)
196 - output, ok := v.(*LsOutput)
197 - if !ok {
198 - return e.TypeErr(output, v)
199 - }
196 + multipleFolders := len(req.Arguments) > 1
197 + lastDirectoryWritten := -1
198 + tw := tabwriter.NewWriter(os.Stdout, 1, 2, 1, ' ', 0)
199 + for {
200 + v, err := res.Next()
201 + if err != nil {
202 + if err == io.EOF {
203 + if multipleFolders {
204 + fmt.Fprintln(os.Stdout)
205 + }
206 + return nil
207 + }
208 +
209 + return err
210 + }
211 +
212 + output, ok := v.(*LsOutput)
213 + if !ok {
214 + return e.TypeErr(output, v)
215 + }
216
201 - tw := tabwriter.NewWriter(w, 1, 2, 1, ' ', 0)
202 - for _, object := range output.Objects {
203 - if object.HasHeader {
204 - if output.MultipleFolders {
205 - fmt.Fprintf(tw, "%s:\n", object.Hash)
217 + for i, object := range output.Objects {
218 + if len(object.Links) == 0 {
219 + continue
220 }
207 - if headers {
208 - fmt.Fprintln(tw, "Hash\tSize\tName")
221 + if i > lastDirectoryWritten {
222 + if i > 0 {
223 + if multipleFolders {
224 + fmt.Fprintln(tw)
225 + }
226 + }
227 + if multipleFolders {
228 + fmt.Fprintf(tw, "%s:\n", object.Hash)
229 + }
230 + if headers {
231 + fmt.Fprintln(tw, "Hash\tSize\tName")
232 + }
233 + lastDirectoryWritten = i
234 }
210 - }
211 - if object.HasLinks {
235 for _, link := range object.Links {
236 if link.Type == unixfs.TDirectory {
237 link.Name += "/"
@@ -217,15 +240,9 @@ The JSON output contains type information.
240 fmt.Fprintf(tw, "%s\t%v\t%s\n", link.Hash, link.Size, link.Name)
241 }
242 }
220 - if object.HasFooter {
221 - if output.MultipleFolders {
222 - fmt.Fprintln(tw)
223 - }
224 - }
243 + tw.Flush()
244 }
226 - tw.Flush()
227 - return nil
228 - }),
245 + },
246 },
247 Type: LsOutput{},
248 }
@@ -248,19 +265,6 @@ func makeDagNodeLinkResults(req *cmds.Request, dagnode ipld.Node) <-chan unixfs.
265 return linkResults
266 }
267
251 -func newFullDirectoryLsObject(hash string, links []LsLink) LsObject {
252 - return LsObject{hash, links, true, true, true}
253 -}
254 -func newDirectoryHeaderLsObject(hash string) LsObject {
255 - return LsObject{hash, nil, true, false, false}
256 -}
257 -func newDirectoryLinksLsObject(links []LsLink) LsObject {
258 - return LsObject{"", links, false, true, false}
259 -}
260 -func newDirectoryFooterLsObject() LsObject {
261 - return LsObject{"", nil, false, false, true}
262 -}
263 -
268 func makeLsLink(req *cmds.Request, dserv ipld.DAGService, resolve bool, link *ipld.Link) (*LsLink, error) {
269 t := unixfspb.Data_DataType(-1)
270