1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-07-15 07:58:15 +08:00

Report progress during 'pin add'.

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
This commit is contained in:
Kevin Atkinson
2017-02-17 16:17:50 -05:00
parent 584c095647
commit cdd29c24a2
4 changed files with 242 additions and 15 deletions

View File

@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"io"
"time"
cmds "github.com/ipfs/go-ipfs/commands"
core "github.com/ipfs/go-ipfs/core"
@ -33,6 +34,11 @@ type PinOutput struct {
Pins []*cid.Cid
}
type AddPinOutput struct {
Pins []*cid.Cid
Progress int `json:",omitempty"`
}
var addPinCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Pin objects to local storage.",
@ -44,8 +50,9 @@ var addPinCmd = &cmds.Command{
},
Options: []cmds.Option{
cmds.BoolOption("recursive", "r", "Recursively pin the object linked to by the specified object(s).").Default(true),
cmds.BoolOption("progress", "Show progress"),
},
Type: PinOutput{},
Type: AddPinOutput{},
Run: func(req cmds.Request, res cmds.Response) {
n, err := req.InvocContext().GetNode()
if err != nil {
@ -61,22 +68,88 @@ var addPinCmd = &cmds.Command{
res.SetError(err, cmds.ErrNormal)
return
}
showProgress, _, _ := req.Option("progress").Bool()
added, err := corerepo.Pin(n, req.Context(), req.Arguments(), recursive)
if err != nil {
res.SetError(err, cmds.ErrNormal)
if !showProgress {
added, err := corerepo.Pin(n, req.Context(), req.Arguments(), recursive)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
res.SetOutput(&AddPinOutput{Pins: added})
return
}
res.SetOutput(&PinOutput{added})
v := new(dag.ProgressTracker)
ctx := v.DeriveContext(req.Context())
ch := make(chan []*cid.Cid)
go func() {
defer close(ch)
added, err := corerepo.Pin(n, ctx, req.Arguments(), recursive)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
ch <- added
}()
out := make(chan interface{})
res.SetOutput((<-chan interface{})(out))
go func() {
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
defer close(out)
for {
select {
case val, ok := <-ch:
if !ok {
// error already set just return
return
}
if pv := v.Value(); pv != 0 {
out <- &AddPinOutput{Progress: v.Value()}
}
out <- &AddPinOutput{Pins: val}
return
case <-ticker.C:
out <- &AddPinOutput{Progress: v.Value()}
case <-ctx.Done():
res.SetError(ctx.Err(), cmds.ErrNormal)
return
}
}
}()
},
Marshalers: cmds.MarshalerMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) {
added, ok := res.Output().(*PinOutput)
if !ok {
var added []*cid.Cid
switch out := res.Output().(type) {
case *AddPinOutput:
added = out.Pins
case <-chan interface{}:
progressLine := false
for r0 := range out {
r := r0.(*AddPinOutput)
if r.Pins != nil {
added = r.Pins
} else {
if progressLine {
fmt.Fprintf(res.Stderr(), "\r")
}
fmt.Fprintf(res.Stderr(), "Fetched/Processed %d nodes", r.Progress)
progressLine = true
}
}
if progressLine {
fmt.Fprintf(res.Stderr(), "\n")
}
if res.Error() != nil {
return nil, res.Error()
}
default:
return nil, u.ErrCast()
}
var pintype string
rec, found, _ := res.Request().Option("recursive").Bool()
if rec || !found {
@ -86,7 +159,7 @@ var addPinCmd = &cmds.Command{
}
buf := new(bytes.Buffer)
for _, k := range added.Pins {
for _, k := range added {
fmt.Fprintf(buf, "pinned %s %s\n", k, pintype)
}
return buf, nil