fix(commands): reduce complexity w/ typed encoder
uses single flag to support state needed by PostRun supports encoding=text License: MIT Signed-off-by: hannahhoward <hannah@hannahhoward.net>
Łukasz Magiera committed
Nov 9, 2018 at 15:09 UTC
7391cfd42146015859cbd13b12d96d39c9f24615
2 files changed
+36
-65
core/commands/ls.go
+36
-61
@@ -3,11 +3,9 @@ package commands
3
import (
4
"fmt"
5
"io"
6
- "os"
6
"text/tabwriter"
7
8
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
10
- e "github.com/ipfs/go-ipfs/core/commands/e"
9
iface "github.com/ipfs/go-ipfs/core/coreapi/interface"
10
11
cid "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid"
@@ -39,7 +37,8 @@ type LsObject struct {
37
// LsOutput is a set of printable data for directories,
38
// it can be complete or partial
39
type LsOutput struct {
42
- Objects []LsObject
40
+ Objects []LsObject
41
+ LastObjectHash string
42
}
43
44
const (
@@ -112,6 +111,8 @@ The JSON output contains type information.
111
ro := merkledag.NewReadOnlyDagService(ng)
112
113
stream, _ := req.Options[lsStreamOptionName].(bool)
114
+ lastObjectHash := ""
115
+
116
if !stream {
117
output := make([]LsObject, len(req.Arguments))
118
@@ -144,7 +145,7 @@ The JSON output contains type information.
145
}
146
}
147
147
- return cmds.EmitOnce(res, &LsOutput{output})
148
+ return cmds.EmitOnce(res, &LsOutput{output, lastObjectHash})
149
}
150
151
for i, dagnode := range dagnodes {
@@ -161,15 +162,6 @@ The JSON output contains type information.
162
}
163
164
for linkResult := range linkResults {
164
- output := make([]LsObject, len(req.Arguments))
165
-
166
- for i, path := range paths {
167
- output[i] = LsObject{
168
- Hash: path,
169
- Links: nil,
170
- }
171
- }
172
- outputLinks := make([]LsLink, 1)
165
166
if linkResult.Err != nil {
167
return linkResult.Err
@@ -179,21 +171,24 @@ The JSON output contains type information.
171
if err != nil {
172
return err
173
}
182
- outputLinks[0] = *lsLink
183
- output[i].Links = outputLinks
184
- if err = res.Emit(&LsOutput{output}); err != nil {
174
+ output := []LsObject{
175
+ {
176
+ Hash: paths[i],
177
+ Links: []LsLink{*lsLink},
178
+ },
179
+ }
180
+ if err = res.Emit(&LsOutput{output, lastObjectHash}); err != nil {
181
return err
182
}
183
+ lastObjectHash = paths[i]
184
}
185
}
186
return nil
187
},
191
- PostRun: cmds.PostRunMap{
192
- cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error {
193
- req := res.Request()
188
+ Encoders: cmds.EncoderMap{
189
+ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *LsOutput) error {
190
headers, _ := req.Options[lsHeadersOptionNameTime].(bool)
191
stream, _ := req.Options[lsStreamOptionName].(bool)
196
-
192
// in streaming mode we can't automatically align the tabs
193
// so we take a best guess
194
var minTabWidth int
@@ -204,56 +199,36 @@ The JSON output contains type information.
199
}
200
201
multipleFolders := len(req.Arguments) > 1
207
- lastDirectoryWritten := -1
208
-
209
- tw := tabwriter.NewWriter(os.Stdout, minTabWidth, 2, 1, ' ', 0)
210
- for {
211
- v, err := res.Next()
212
- if err != nil {
213
- if err == io.EOF {
214
- if multipleFolders {
215
- fmt.Fprintln(os.Stdout)
216
- }
217
- return nil
218
- }
202
+ lastObjectHash := out.LastObjectHash
203
220
- return err
221
- }
204
+ tw := tabwriter.NewWriter(w, minTabWidth, 2, 1, ' ', 0)
205
223
- output, ok := v.(*LsOutput)
224
- if !ok {
225
- return e.TypeErr(output, v)
226
- }
206
+ for _, object := range out.Objects {
207
228
- for i, object := range output.Objects {
229
- if len(object.Links) == 0 {
230
- continue
231
- }
232
- if i > lastDirectoryWritten {
233
- if i > 0 {
234
- if multipleFolders {
235
- fmt.Fprintln(tw)
236
- }
237
- }
238
- if multipleFolders {
239
- fmt.Fprintf(tw, "%s:\n", object.Hash)
208
+ if object.Hash != lastObjectHash {
209
+ if multipleFolders {
210
+ if lastObjectHash != "" {
211
+ fmt.Fprintln(tw)
212
}
241
- if headers {
242
- fmt.Fprintln(tw, "Hash\tSize\tName")
243
- }
244
- lastDirectoryWritten = i
213
+ fmt.Fprintf(tw, "%s:\n", object.Hash)
214
}
246
- for _, link := range object.Links {
247
- if link.Type == unixfs.TDirectory {
248
- link.Name += "/"
249
- }
215
+ if headers {
216
+ fmt.Fprintln(tw, "Hash\tSize\tName")
217
+ }
218
+ lastObjectHash = object.Hash
219
+ }
220
251
- fmt.Fprintf(tw, "%s\t%v\t%s\n", link.Hash, link.Size, link.Name)
221
+ for _, link := range object.Links {
222
+ if link.Type == unixfs.TDirectory {
223
+ link.Name += "/"
224
}
225
+
226
+ fmt.Fprintf(tw, "%s\t%v\t%s\n", link.Hash, link.Size, link.Name)
227
}
254
- tw.Flush()
228
}
256
- },
229
+ tw.Flush()
230
+ return nil
231
+ }),
232
},
233
Type: LsOutput{},
234
}
test/sharness/t0045-ls.sh
-4
@@ -57,7 +57,6 @@ QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL 14 a
57
QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss:
58
QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 139 128
59
QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 14 a
60
-
60
EOF
61
test_cmp expected_ls actual_ls
62
'
@@ -84,7 +83,6 @@ QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss:
83
Hash Size Name
84
QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 139 128
85
QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 14 a
87
-
86
EOF
87
test_cmp expected_ls_headers actual_ls_headers
88
'
@@ -138,7 +136,6 @@ QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL 14 a
136
QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss:
137
QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 139 128
138
QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 14 a
141
-
139
EOF
140
test_cmp expected_ls_stream actual_ls_stream
141
'
@@ -165,7 +162,6 @@ QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss:
162
Hash Size Name
163
QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 139 128
164
QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 14 a
168
-
165
EOF
166
test_cmp expected_ls_stream_headers actual_ls_stream_headers
167
'