提交 96433cc6 作者: Jeromy

starting to rework stdin handling

License: MIT
Signed-off-by: 's avatarJeromy <why@ipfs.io>
上级 5d1b28e2
......@@ -42,9 +42,6 @@ func FileArg(name string, required, variadic bool, description string) Argument
// (`FileArg("file", ArgRequired, ArgStdin, ArgRecursive)`)
func (a Argument) EnableStdin() Argument {
if a.Type == ArgString {
panic("Only FileArgs can be read from Stdin")
}
a.SupportsStdin = true
return a
}
......
......@@ -276,6 +276,7 @@ func parseArgs(inputs []string, stdin *os.File, argDefs []cmds.Argument, recursi
fileArgs := make(map[string]files.File)
argDefIndex := 0 // the index of the current argument definition
for i := 0; i < numInputs; i++ {
argDef := getArgDef(argDefIndex, argDefs)
......@@ -289,14 +290,19 @@ func parseArgs(inputs []string, stdin *os.File, argDefs []cmds.Argument, recursi
}
fillingVariadic := argDefIndex+1 > len(argDefs)
if argDef.Type == cmds.ArgString {
switch argDef.Type {
case cmds.ArgString:
if len(inputs) > 0 {
stringArgs, inputs = append(stringArgs, inputs[0]), inputs[1:]
} else {
break
if stdin != nil && argDef.SupportsStdin && !fillingVariadic {
if err := printReadInfo(stdin, msgStdinInfo); err == nil {
fileArgs[stdin.Name()] = files.NewReaderFile("", stdin.Name(), stdin, nil)
stdin = nil
}
}
}
} else if argDef.Type == cmds.ArgFile {
case cmds.ArgFile:
if len(inputs) > 0 {
// treat stringArg values as file paths
fpath := inputs[0]
......
......@@ -281,6 +281,10 @@ func (c *Command) ProcessHelp() {
// checkArgValue returns an error if a given arg value is not valid for the
// given Argument
func checkArgValue(v string, found bool, def Argument) error {
if def.Variadic && def.SupportsStdin {
return nil
}
if !found && def.Required {
return fmt.Errorf("Argument '%s' is required", def.Name)
}
......
package commands
import (
"bufio"
"bytes"
"fmt"
"io"
......@@ -39,7 +40,7 @@ var addPinCmd = &cmds.Command{
},
Arguments: []cmds.Argument{
cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be pinned."),
cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be pinned.").EnableStdin(),
},
Options: []cmds.Option{
cmds.BoolOption("recursive", "r", "Recursively pin the object linked to by the specified object(s).").Default(true),
......@@ -61,21 +62,40 @@ var addPinCmd = &cmds.Command{
return
}
added, err := corerepo.Pin(n, req.Context(), req.Arguments(), recursive)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
if len(req.Arguments()) > 0 {
added, err := corerepo.Pin(n, req.Context(), req.Arguments(), recursive)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
res.SetOutput(&PinOutput{added})
res.SetOutput(&PinOutput{added})
} else {
fi, err := req.Files().NextFile()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
out := make(chan interface{})
go func(ctx context.Context) {
defer close(out)
scan := bufio.NewScanner(fi)
for scan.Scan() {
added, err := corerepo.Pin(n, ctx, []string{scan.Text()}, recursive)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
out <- &PinOutput{added}
}
}(req.Context())
res.SetOutput((<-chan interface{})(out))
}
},
Marshalers: cmds.MarshalerMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) {
added, ok := res.Output().(*PinOutput)
if !ok {
return nil, u.ErrCast()
}
var pintype string
rec, found, _ := res.Request().Option("recursive").Bool()
if rec || !found {
......@@ -84,11 +104,31 @@ var addPinCmd = &cmds.Command{
pintype = "directly"
}
buf := new(bytes.Buffer)
for _, k := range added.Pins {
fmt.Fprintf(buf, "pinned %s %s\n", k, pintype)
marshalPinOutput := func(po *PinOutput) io.Reader {
buf := new(bytes.Buffer)
for _, k := range po.Pins {
fmt.Fprintf(buf, "pinned %s %s\n", k, pintype)
}
return buf
}
switch out := res.Output().(type) {
case *PinOutput:
return marshalPinOutput(out), nil
case <-chan interface{}:
marshal := func(i interface{}) (io.Reader, error) {
return marshalPinOutput(i.(*PinOutput)), nil
}
return &cmds.ChannelMarshaler{
Res: res,
Marshaler: marshal,
Channel: out,
}, nil
default:
return nil, u.ErrCast()
}
return buf, nil
},
},
}
......
......@@ -48,7 +48,7 @@ test_expect_success "ipfs config output looks good" '
test_cmp expected actual
'
test_launch_ipfs_daemon
test_launch_ipfs_daemon --offline
test_kill_ipfs_daemon
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论