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