1
1
package dagcmd
2
2
3
3
import (
4
+ "errors"
4
5
"fmt"
5
6
"io"
6
7
"math"
8
+ "os"
7
9
"strings"
10
+ "time"
8
11
9
12
"github.com/ipfs/go-ipfs/core/commands/cmdenv"
10
13
"github.com/ipfs/go-ipfs/core/coredag"
@@ -23,6 +26,12 @@ import (
23
26
//gipfree "github.com/ipld/go-ipld-prime/impl/free"
24
27
//gipselector "github.com/ipld/go-ipld-prime/traversal/selector"
25
28
//gipselectorbuilder "github.com/ipld/go-ipld-prime/traversal/selector/builder"
29
+
30
+ "gopkg.in/cheggaaa/pb.v1"
31
+ )
32
+
33
+ const (
34
+ progressOptionName = "progress"
26
35
)
27
36
28
37
var DagCmd = & cmds.Command {
@@ -261,6 +270,9 @@ The output of blocks happens in strict DAG-traversal, first-seen, order.
261
270
Arguments : []cmds.Argument {
262
271
cmds .StringArg ("root" , true , false , "CID of a root to recursively export" ).EnableStdin (),
263
272
},
273
+ Options : []cmds.Option {
274
+ cmds .BoolOption (progressOptionName , "p" , "Display progress on CLI. Defaults to true when STDERR is a TTY." ),
275
+ },
264
276
Run : func (req * cmds.Request , res cmds.ResponseEmitter , env cmds.Environment ) error {
265
277
266
278
c , err := cid .Decode (req .Arguments [0 ])
@@ -334,4 +346,61 @@ The output of blocks happens in strict DAG-traversal, first-seen, order.
334
346
335
347
return err
336
348
},
349
+ PostRun : cmds.PostRunMap {
350
+ cmds .CLI : func (res cmds.Response , re cmds.ResponseEmitter ) error {
351
+
352
+ var showProgress bool
353
+ val , specified := res .Request ().Options [progressOptionName ]
354
+ if ! specified {
355
+ // default based on TTY availability
356
+ errStat , _ := os .Stderr .Stat ()
357
+ if 0 != (errStat .Mode () & os .ModeCharDevice ) {
358
+ showProgress = true
359
+ }
360
+ } else if val .(bool ) {
361
+ showProgress = true
362
+ }
363
+
364
+ // simple passthrough, no progress
365
+ if ! showProgress {
366
+ return cmds .Copy (re , res )
367
+ }
368
+
369
+ bar := pb .New64 (0 ).SetUnits (pb .U_BYTES )
370
+ bar .Output = os .Stderr
371
+ bar .ShowSpeed = true
372
+ bar .ShowElapsedTime = true
373
+ bar .RefreshRate = 500 * time .Millisecond
374
+ bar .Start ()
375
+
376
+ var processedOneResponse bool
377
+ for {
378
+ v , err := res .Next ()
379
+ if err == io .EOF {
380
+
381
+ // We only write the final bar update on success
382
+ // On error it looks too weird
383
+ bar .Finish ()
384
+
385
+ return re .Close ()
386
+ } else if err != nil {
387
+ return re .CloseWithError (err )
388
+ } else if processedOneResponse {
389
+ return re .CloseWithError (errors .New ("unexpected multipart response during emit, please file a bugreport" ))
390
+ }
391
+
392
+ r , ok := v .(io.Reader )
393
+ if ! ok {
394
+ // some sort of encoded response, this should not be happening
395
+ return errors .New ("unexpected non-stream passed to PostRun: please file a bugreport" )
396
+ }
397
+
398
+ processedOneResponse = true
399
+
400
+ if err := re .Emit (bar .NewProxyReader (r )); err != nil {
401
+ return err
402
+ }
403
+ }
404
+ },
405
+ },
337
406
}
0 commit comments