Unverified 提交 b622e334 作者: Steven Allen 提交者: GitHub

Merge pull request #5674 from overbool/refactor/commands/pin

commands/pin: use new cmds lib
package commands package commands
import ( import (
"bytes"
"context" "context"
"fmt" "fmt"
"io" "io"
"os"
"time" "time"
cmds "github.com/ipfs/go-ipfs/commands"
core "github.com/ipfs/go-ipfs/core" core "github.com/ipfs/go-ipfs/core"
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
e "github.com/ipfs/go-ipfs/core/commands/e" e "github.com/ipfs/go-ipfs/core/commands/e"
iface "github.com/ipfs/go-ipfs/core/coreapi/interface" iface "github.com/ipfs/go-ipfs/core/coreapi/interface"
options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" options "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
...@@ -19,8 +19,9 @@ import ( ...@@ -19,8 +19,9 @@ import (
cid "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid" cid "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid"
bserv "gx/ipfs/QmVPeMNK9DfGLXDZzs2W4RoFWC9Zq1EnLGmLXtYtWrNdcW/go-blockservice" bserv "gx/ipfs/QmVPeMNK9DfGLXDZzs2W4RoFWC9Zq1EnLGmLXtYtWrNdcW/go-blockservice"
"gx/ipfs/QmYMQuypUbgsdNHmuCBSUJV6wdQVsBHRivNAp3efHJwZJD/go-verifcid" "gx/ipfs/QmYMQuypUbgsdNHmuCBSUJV6wdQVsBHRivNAp3efHJwZJD/go-verifcid"
cmds "gx/ipfs/Qma6uuSyjkecGhMFFLfzyJDPyoDtNJSHJNweDccZhaWkgU/go-ipfs-cmds"
dag "gx/ipfs/QmaDBne4KeY3UepeqSVKYpSmQGa3q9zP6x3LfVF2UjF3Hc/go-merkledag" dag "gx/ipfs/QmaDBne4KeY3UepeqSVKYpSmQGa3q9zP6x3LfVF2UjF3Hc/go-merkledag"
"gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit" cmdkit "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit"
) )
var PinCmd = &cmds.Command{ var PinCmd = &cmds.Command{
...@@ -65,117 +66,117 @@ var addPinCmd = &cmds.Command{ ...@@ -65,117 +66,117 @@ var addPinCmd = &cmds.Command{
cmdkit.BoolOption(pinProgressOptionName, "Show progress"), cmdkit.BoolOption(pinProgressOptionName, "Show progress"),
}, },
Type: AddPinOutput{}, Type: AddPinOutput{},
Run: func(req cmds.Request, res cmds.Response) { Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
n, err := req.InvocContext().GetNode() n, err := cmdenv.GetNode(env)
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
api, err := req.InvocContext().GetApi() api, err := cmdenv.GetApi(env)
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
defer n.Blockstore.PinLock().Unlock() defer n.Blockstore.PinLock().Unlock()
// set recursive flag // set recursive flag
recursive, _, err := req.Option(pinRecursiveOptionName).Bool() recursive, _ := req.Options[pinRecursiveOptionName].(bool)
if err != nil { showProgress, _ := req.Options[pinProgressOptionName].(bool)
res.SetError(err, cmdkit.ErrNormal)
return if err := req.ParseBodyArgs(); err != nil {
return err
} }
showProgress, _, _ := req.Option(pinProgressOptionName).Bool()
if !showProgress { if !showProgress {
added, err := corerepo.Pin(n, api, req.Context(), req.Arguments(), recursive) added, err := corerepo.Pin(n, api, req.Context, req.Arguments, recursive)
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
res.SetOutput(&AddPinOutput{Pins: cidsToStrings(added)}) return cmds.EmitOnce(res, &AddPinOutput{Pins: cidsToStrings(added)})
return
} }
out := make(chan interface{})
res.SetOutput((<-chan interface{})(out))
v := new(dag.ProgressTracker) v := new(dag.ProgressTracker)
ctx := v.DeriveContext(req.Context()) ctx := v.DeriveContext(req.Context)
type pinResult struct { type pinResult struct {
pins []cid.Cid pins []cid.Cid
err error err error
} }
ch := make(chan pinResult, 1) ch := make(chan pinResult, 1)
go func() { go func() {
added, err := corerepo.Pin(n, api, ctx, req.Arguments(), recursive) added, err := corerepo.Pin(n, api, ctx, req.Arguments, recursive)
ch <- pinResult{pins: added, err: err} ch <- pinResult{pins: added, err: err}
}() }()
ticker := time.NewTicker(500 * time.Millisecond) ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop() defer ticker.Stop()
defer close(out)
for { for {
select { select {
case val := <-ch: case val := <-ch:
if val.err != nil { if val.err != nil {
res.SetError(val.err, cmdkit.ErrNormal) return val.err
return
} }
if pv := v.Value(); pv != 0 { if pv := v.Value(); pv != 0 {
out <- &AddPinOutput{Progress: v.Value()} if err := res.Emit(&AddPinOutput{Progress: v.Value()}); err != nil {
return err
}
} }
out <- &AddPinOutput{Pins: cidsToStrings(val.pins)} return res.Emit(&AddPinOutput{Pins: cidsToStrings(val.pins)})
return
case <-ticker.C: case <-ticker.C:
out <- &AddPinOutput{Progress: v.Value()} if err := res.Emit(&AddPinOutput{Progress: v.Value()}); err != nil {
return err
}
case <-ctx.Done(): case <-ctx.Done():
log.Error(ctx.Err()) log.Error(ctx.Err())
res.SetError(ctx.Err(), cmdkit.ErrNormal) return ctx.Err()
return
} }
} }
}, },
Marshalers: cmds.MarshalerMap{ Encoders: cmds.EncoderMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) { cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *AddPinOutput) error {
v, err := unwrapOutput(res.Output()) rec, found := req.Options["recursive"].(bool)
if err != nil {
return nil, err
}
var added []string
switch out := v.(type) {
case *AddPinOutput:
if out.Pins != nil {
added = out.Pins
} else {
// this can only happen if the progress option is set
fmt.Fprintf(res.Stderr(), "Fetched/Processed %d nodes\r", out.Progress)
}
if res.Error() != nil {
return nil, res.Error()
}
default:
return nil, e.TypeErr(out, v)
}
var pintype string var pintype string
rec, found, _ := res.Request().Option("recursive").Bool()
if rec || !found { if rec || !found {
pintype = "recursively" pintype = "recursively"
} else { } else {
pintype = "directly" pintype = "directly"
} }
buf := new(bytes.Buffer) for _, k := range out.Pins {
for _, k := range added { fmt.Fprintf(w, "pinned %s %s\n", k, pintype)
fmt.Fprintf(buf, "pinned %s %s\n", k, pintype) }
return nil
}),
},
PostRun: cmds.PostRunMap{
cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error {
for {
v, err := res.Next()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
out, ok := v.(*AddPinOutput)
if !ok {
return e.TypeErr(out, v)
}
if out.Pins == nil {
// this can only happen if the progress option is set
fmt.Fprintf(os.Stderr, "Fetched/Processed %d nodes\r", out.Progress)
} else {
err = re.Emit(out)
if err != nil {
return err
}
}
} }
return buf, nil
}, },
}, },
} }
...@@ -196,52 +197,38 @@ collected if needed. (By default, recursively. Use -r=false for direct pins.) ...@@ -196,52 +197,38 @@ collected if needed. (By default, recursively. Use -r=false for direct pins.)
cmdkit.BoolOption(pinRecursiveOptionName, "r", "Recursively unpin the object linked to by the specified object(s).").WithDefault(true), cmdkit.BoolOption(pinRecursiveOptionName, "r", "Recursively unpin the object linked to by the specified object(s).").WithDefault(true),
}, },
Type: PinOutput{}, Type: PinOutput{},
Run: func(req cmds.Request, res cmds.Response) { Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
n, err := req.InvocContext().GetNode() n, err := cmdenv.GetNode(env)
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
api, err := req.InvocContext().GetApi() api, err := cmdenv.GetApi(env)
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
// set recursive flag // set recursive flag
recursive, _, err := req.Option(pinRecursiveOptionName).Bool() recursive, _ := req.Options[pinRecursiveOptionName].(bool)
if err != nil {
res.SetError(err, cmdkit.ErrNormal) if err := req.ParseBodyArgs(); err != nil {
return return err
} }
removed, err := corerepo.Unpin(n, api, req.Context(), req.Arguments(), recursive) removed, err := corerepo.Unpin(n, api, req.Context, req.Arguments, recursive)
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
res.SetOutput(&PinOutput{cidsToStrings(removed)}) return cmds.EmitOnce(res, &PinOutput{cidsToStrings(removed)})
}, },
Marshalers: cmds.MarshalerMap{ Encoders: cmds.EncoderMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) { cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *PinOutput) error {
v, err := unwrapOutput(res.Output()) for _, k := range out.Pins {
if err != nil { fmt.Fprintf(w, "unpinned %s\n", k)
return nil, err
} }
return nil
added, ok := v.(*PinOutput) }),
if !ok {
return nil, e.TypeErr(added, v)
}
buf := new(bytes.Buffer)
for _, k := range added.Pins {
fmt.Fprintf(buf, "unpinned %s\n", k)
}
return buf, nil
},
}, },
} }
...@@ -301,74 +288,58 @@ Example: ...@@ -301,74 +288,58 @@ Example:
cmdkit.StringOption(pinTypeOptionName, "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\".").WithDefault("all"), cmdkit.StringOption(pinTypeOptionName, "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\".").WithDefault("all"),
cmdkit.BoolOption(pinQuietOptionName, "q", "Write just hashes of objects."), cmdkit.BoolOption(pinQuietOptionName, "q", "Write just hashes of objects."),
}, },
Run: func(req cmds.Request, res cmds.Response) { Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
n, err := req.InvocContext().GetNode() n, err := cmdenv.GetNode(env)
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
api, err := req.InvocContext().GetApi() api, err := cmdenv.GetApi(env)
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
typeStr, _, err := req.Option(pinTypeOptionName).String() typeStr, _ := req.Options[pinTypeOptionName].(string)
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
switch typeStr { switch typeStr {
case "all", "direct", "indirect", "recursive": case "all", "direct", "indirect", "recursive":
default: default:
err = fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr) err = fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr)
res.SetError(err, cmdkit.ErrClient) return err
return
} }
var keys map[string]RefKeyObject var keys map[string]RefKeyObject
if len(req.Arguments()) > 0 { if len(req.Arguments) > 0 {
keys, err = pinLsKeys(req.Context(), req.Arguments(), typeStr, n, api) keys, err = pinLsKeys(req.Context, req.Arguments, typeStr, n, api)
} else { } else {
keys, err = pinLsAll(req.Context(), typeStr, n) keys, err = pinLsAll(req.Context, typeStr, n)
} }
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
} else {
res.SetOutput(&RefKeyList{Keys: keys})
} }
return cmds.EmitOnce(res, &RefKeyList{Keys: keys})
}, },
Type: RefKeyList{}, Type: RefKeyList{},
Marshalers: cmds.MarshalerMap{ Encoders: cmds.EncoderMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) { cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *RefKeyList) error {
v, err := unwrapOutput(res.Output()) quiet, _ := req.Options[pinQuietOptionName].(bool)
if err != nil {
return nil, err
}
quiet, _, err := res.Request().Option(pinQuietOptionName).Bool()
if err != nil {
return nil, err
}
keys, ok := v.(*RefKeyList) for k, v := range out.Keys {
if !ok {
return nil, e.TypeErr(keys, v)
}
out := new(bytes.Buffer)
for k, v := range keys.Keys {
if quiet { if quiet {
fmt.Fprintf(out, "%s\n", k) fmt.Fprintf(w, "%s\n", k)
} else { } else {
fmt.Fprintf(out, "%s %s\n", k, v.Type) fmt.Fprintf(w, "%s %s\n", k, v.Type)
} }
} }
return out, nil
}, return nil
}),
}, },
} }
...@@ -394,54 +365,36 @@ new pin and removing the old one. ...@@ -394,54 +365,36 @@ new pin and removing the old one.
cmdkit.BoolOption(pinUnpinOptionName, "Remove the old pin.").WithDefault(true), cmdkit.BoolOption(pinUnpinOptionName, "Remove the old pin.").WithDefault(true),
}, },
Type: PinOutput{}, Type: PinOutput{},
Run: func(req cmds.Request, res cmds.Response) { Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
api, err := req.InvocContext().GetApi() api, err := cmdenv.GetApi(env)
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
unpin, _, err := req.Option(pinUnpinOptionName).Bool() unpin, _ := req.Options[pinUnpinOptionName].(bool)
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
}
from, err := iface.ParsePath(req.Arguments()[0]) from, err := iface.ParsePath(req.Arguments[0])
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
to, err := iface.ParsePath(req.Arguments()[1]) to, err := iface.ParsePath(req.Arguments[1])
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
err = api.Pin().Update(req.Context(), from, to, options.Pin.Unpin(unpin)) err = api.Pin().Update(req.Context, from, to, options.Pin.Unpin(unpin))
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
res.SetOutput(&PinOutput{Pins: []string{from.String(), to.String()}}) return cmds.EmitOnce(res, &PinOutput{Pins: []string{from.String(), to.String()}})
}, },
Marshalers: cmds.MarshalerMap{ Encoders: cmds.EncoderMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) { cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *PinOutput) error {
v, err := unwrapOutput(res.Output()) fmt.Fprintf(w, "updated %s to %s\n", out.Pins[0], out.Pins[1])
if err != nil { return nil
return nil, err }),
}
added, ok := v.(*PinOutput)
if !ok {
return nil, e.TypeErr(added, v)
}
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "updated %s to %s\n", added.Pins[0], added.Pins[1])
return buf, nil
},
}, },
} }
...@@ -457,51 +410,40 @@ var verifyPinCmd = &cmds.Command{ ...@@ -457,51 +410,40 @@ var verifyPinCmd = &cmds.Command{
cmdkit.BoolOption(pinVerboseOptionName, "Also write the hashes of non-broken pins."), cmdkit.BoolOption(pinVerboseOptionName, "Also write the hashes of non-broken pins."),
cmdkit.BoolOption(pinQuietOptionName, "q", "Write just hashes of broken pins."), cmdkit.BoolOption(pinQuietOptionName, "q", "Write just hashes of broken pins."),
}, },
Run: func(req cmds.Request, res cmds.Response) { Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
n, err := req.InvocContext().GetNode() n, err := cmdenv.GetNode(env)
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) return err
return
} }
verbose, _, _ := res.Request().Option(pinVerboseOptionName).Bool() verbose, _ := req.Options[pinVerboseOptionName].(bool)
quiet, _, _ := res.Request().Option(pinQuietOptionName).Bool() quiet, _ := req.Options[pinQuietOptionName].(bool)
if verbose && quiet { if verbose && quiet {
res.SetError(fmt.Errorf("the --verbose and --quiet options can not be used at the same time"), cmdkit.ErrNormal) return fmt.Errorf("the --verbose and --quiet options can not be used at the same time")
} }
opts := pinVerifyOpts{ opts := pinVerifyOpts{
explain: !quiet, explain: !quiet,
includeOk: verbose, includeOk: verbose,
} }
out := pinVerify(req.Context(), n, opts) out := pinVerify(req.Context, n, opts)
res.SetOutput(out) return res.Emit(out)
}, },
Type: PinVerifyRes{}, Type: PinVerifyRes{},
Marshalers: cmds.MarshalerMap{ Encoders: cmds.EncoderMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) { cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *PinVerifyRes) error {
quiet, _, _ := res.Request().Option(pinQuietOptionName).Bool() quiet, _ := req.Options[pinQuietOptionName].(bool)
out, err := unwrapOutput(res.Output()) if quiet && !out.Ok {
if err != nil { fmt.Fprintf(w, "%s\n", out.Cid)
return nil, err
}
r, ok := out.(*PinVerifyRes)
if !ok {
return nil, e.TypeErr(r, out)
}
buf := &bytes.Buffer{}
if quiet && !r.Ok {
fmt.Fprintf(buf, "%s\n", r.Cid)
} else if !quiet { } else if !quiet {
r.Format(buf) out.Format(w)
} }
return buf, nil return nil
}, }),
}, },
} }
......
...@@ -135,7 +135,7 @@ var rootSubcommands = map[string]*cmds.Command{ ...@@ -135,7 +135,7 @@ var rootSubcommands = map[string]*cmds.Command{
"mount": MountCmd, "mount": MountCmd,
"name": name.NameCmd, "name": name.NameCmd,
"object": ocmd.ObjectCmd, "object": ocmd.ObjectCmd,
"pin": lgc.NewCommand(PinCmd), "pin": PinCmd,
"ping": PingCmd, "ping": PingCmd,
"p2p": P2PCmd, "p2p": P2PCmd,
"refs": lgc.NewCommand(RefsCmd), "refs": lgc.NewCommand(RefsCmd),
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论