@@ -3,6 +3,7 @@ package commands
3
3
import (
4
4
"fmt"
5
5
"io"
6
+ "os"
6
7
"text/tabwriter"
7
8
8
9
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
@@ -29,20 +30,16 @@ type LsLink struct {
29
30
}
30
31
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
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
40
37
}
41
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
43
41
type LsOutput struct {
44
- MultipleFolders bool
45
- Objects []LsObject
42
+ Objects []LsObject
46
43
}
47
44
48
45
const (
@@ -114,10 +111,10 @@ The JSON output contains type information.
114
111
ng := merkledag .NewSession (req .Context , nd .DAG )
115
112
ro := merkledag .NewReadOnlyDagService (ng )
116
113
114
+ output := make ([]LsObject , len (req .Arguments ))
115
+
117
116
stream , _ := req .Options [lsStreamOptionName ].(bool )
118
- multipleFolders := len (req .Arguments ) > 1
119
117
if ! stream {
120
- output := make ([]LsObject , len (req .Arguments ))
121
118
122
119
for i , dagnode := range dagnodes {
123
120
dir , err := uio .NewDirectoryFromNode (ro , dagnode )
@@ -142,10 +139,21 @@ The JSON output contains type information.
142
139
}
143
140
outputLinks [j ] = * lsLink
144
141
}
145
- output [i ] = newFullDirectoryLsObject (paths [i ], outputLinks )
142
+ output [i ] = LsObject {
143
+ Hash : paths [i ],
144
+ Links : outputLinks ,
145
+ }
146
146
}
147
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
+ }
149
157
}
150
158
151
159
for i , dagnode := range dagnodes {
@@ -161,13 +169,8 @@ The JSON output contains type information.
161
169
linkResults = dir .EnumLinksAsync (req .Context )
162
170
}
163
171
164
- output := make ([]LsObject , 1 )
165
- outputLinks := make ([]LsLink , 1 )
172
+ output [i ].Links = outputLinks
166
173
167
- output [0 ] = newDirectoryHeaderLsObject (paths [i ])
168
- if err = res .Emit (& LsOutput {multipleFolders , output }); err != nil {
169
- return nil
170
- }
171
174
for linkResult := range linkResults {
172
175
if linkResult .Err != nil {
173
176
return linkResult .Err
@@ -178,37 +181,57 @@ The JSON output contains type information.
178
181
return err
179
182
}
180
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 {
183
185
return err
184
186
}
185
187
}
186
- output [0 ] = newDirectoryFooterLsObject ()
187
- if err = res .Emit (& LsOutput {multipleFolders , output }); err != nil {
188
- return err
189
- }
188
+ output [i ].Links = nil
190
189
}
191
190
return nil
192
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
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
+ }
200
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
206
220
}
207
- if headers {
208
- fmt .Fprintln (tw , "Hash\t Size\t Name" )
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\t Size\t Name" )
232
+ }
233
+ lastDirectoryWritten = i
209
234
}
210
- }
211
- if object .HasLinks {
212
235
for _ , link := range object .Links {
213
236
if link .Type == unixfs .TDirectory {
214
237
link .Name += "/"
@@ -217,15 +240,9 @@ The JSON output contains type information.
217
240
fmt .Fprintf (tw , "%s\t %v\t %s\n " , link .Hash , link .Size , link .Name )
218
241
}
219
242
}
220
- if object .HasFooter {
221
- if output .MultipleFolders {
222
- fmt .Fprintln (tw )
223
- }
224
- }
243
+ tw .Flush ()
225
244
}
226
- tw .Flush ()
227
- return nil
228
- }),
245
+ },
229
246
},
230
247
Type : LsOutput {},
231
248
}
@@ -248,19 +265,6 @@ func makeDagNodeLinkResults(req *cmds.Request, dagnode ipld.Node) <-chan unixfs.
248
265
return linkResults
249
266
}
250
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
-
264
268
func makeLsLink (req * cmds.Request , dserv ipld.DAGService , resolve bool , link * ipld.Link ) (* LsLink , error ) {
265
269
t := unixfspb .Data_DataType (- 1 )
266
270
0 commit comments