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 return res.Emit(&AddPinOutput{Pins: cidsToStrings(val.pins)})
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 { var pintype string
return nil, err if rec || !found {
pintype = "recursively"
} else {
pintype = "directly"
} }
var added []string for _, k := range out.Pins {
fmt.Fprintf(w, "pinned %s %s\n", k, pintype)
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
return nil, res.Error() }),
},
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
} }
default: return err
return nil, e.TypeErr(out, v)
} }
var pintype string out, ok := v.(*AddPinOutput)
rec, found, _ := res.Request().Option("recursive").Bool() if !ok {
if rec || !found { return e.TypeErr(out, v)
pintype = "recursively" }
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 { } else {
pintype = "directly" err = re.Emit(out)
if err != nil {
return err
}
} }
buf := new(bytes.Buffer)
for _, k := range added {
fmt.Fprintf(buf, "pinned %s %s\n", k, pintype)
} }
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)
return
}
removed, err := corerepo.Unpin(n, api, req.Context(), req.Arguments(), recursive) if err := req.ParseBodyArgs(); err != nil {
if err != nil { return err
res.SetError(err, cmdkit.ErrNormal)
return
} }
res.SetOutput(&PinOutput{cidsToStrings(removed)}) removed, err := corerepo.Unpin(n, api, req.Context, req.Arguments, recursive)
},
Marshalers: cmds.MarshalerMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) {
v, err := unwrapOutput(res.Output())
if err != nil { if err != nil {
return nil, err return err
}
added, ok := v.(*PinOutput)
if !ok {
return nil, e.TypeErr(added, v)
} }
buf := new(bytes.Buffer) return cmds.EmitOnce(res, &PinOutput{cidsToStrings(removed)})
for _, k := range added.Pins {
fmt.Fprintf(buf, "unpinned %s\n", k)
}
return buf, nil
}, },
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *PinOutput) error {
for _, k := range out.Pins {
fmt.Fprintf(w, "unpinned %s\n", k)
}
return 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() for k, v := range out.Keys {
if err != nil {
return nil, err
}
keys, ok := v.(*RefKeyList)
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{
cmds.Text: func(res cmds.Response) (io.Reader, error) {
v, err := unwrapOutput(res.Output())
if err != 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
}, },
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *PinOutput) error {
fmt.Fprintf(w, "updated %s to %s\n", out.Pins[0], out.Pins[1])
return 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论