@cryptotaxi247 / kubo / commits / 96433cc6e

starting to rework stdin handling

License: MIT Signed-off-by: Jeromy <why@ipfs.io>

Jeromy committed Jul 7, 2016 at 16:58 UTC 96433cc6e1dc22c3fc11b4ee4b87a960548240ac
5 files changed +71 -24
commands/argument.go
-3
@@ -42,9 +42,6 @@ func FileArg(name string, required, variadic bool, description string) Argument
42 // (`FileArg("file", ArgRequired, ArgStdin, ArgRecursive)`)
43
44 func (a Argument) EnableStdin() Argument {
45 - if a.Type == ArgString {
46 - panic("Only FileArgs can be read from Stdin")
47 - }
45 a.SupportsStdin = true
46 return a
47 }
commands/cli/parse.go
+10 -4
@@ -276,6 +276,7 @@ func parseArgs(inputs []string, stdin *os.File, argDefs []cmds.Argument, recursi
276
277 fileArgs := make(map[string]files.File)
278 argDefIndex := 0 // the index of the current argument definition
279 +
280 for i := 0; i < numInputs; i++ {
281 argDef := getArgDef(argDefIndex, argDefs)
282
@@ -289,14 +290,19 @@ func parseArgs(inputs []string, stdin *os.File, argDefs []cmds.Argument, recursi
290 }
291
292 fillingVariadic := argDefIndex+1 > len(argDefs)
292 -
293 - if argDef.Type == cmds.ArgString {
293 + switch argDef.Type {
294 + case cmds.ArgString:
295 if len(inputs) > 0 {
296 stringArgs, inputs = append(stringArgs, inputs[0]), inputs[1:]
297 } else {
297 - break
298 + if stdin != nil && argDef.SupportsStdin && !fillingVariadic {
299 + if err := printReadInfo(stdin, msgStdinInfo); err == nil {
300 + fileArgs[stdin.Name()] = files.NewReaderFile("", stdin.Name(), stdin, nil)
301 + stdin = nil
302 + }
303 + }
304 }
299 - } else if argDef.Type == cmds.ArgFile {
305 + case cmds.ArgFile:
306 if len(inputs) > 0 {
307 // treat stringArg values as file paths
308 fpath := inputs[0]
commands/command.go
+4
@@ -281,6 +281,10 @@ func (c *Command) ProcessHelp() {
281 // checkArgValue returns an error if a given arg value is not valid for the
282 // given Argument
283 func checkArgValue(v string, found bool, def Argument) error {
284 + if def.Variadic && def.SupportsStdin {
285 + return nil
286 + }
287 +
288 if !found && def.Required {
289 return fmt.Errorf("Argument '%s' is required", def.Name)
290 }
core/commands/pin.go
+56 -16
@@ -1,6 +1,7 @@
1 package commands
2
3 import (
4 + "bufio"
5 "bytes"
6 "fmt"
7 "io"
@@ -39,7 +40,7 @@ var addPinCmd = &cmds.Command{
40 },
41
42 Arguments: []cmds.Argument{
42 - cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be pinned."),
43 + cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be pinned.").EnableStdin(),
44 },
45 Options: []cmds.Option{
46 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{
62 return
63 }
64
64 - added, err := corerepo.Pin(n, req.Context(), req.Arguments(), recursive)
65 - if err != nil {
66 - res.SetError(err, cmds.ErrNormal)
67 - return
68 - }
65 + if len(req.Arguments()) > 0 {
66 + added, err := corerepo.Pin(n, req.Context(), req.Arguments(), recursive)
67 + if err != nil {
68 + res.SetError(err, cmds.ErrNormal)
69 + return
70 + }
71
70 - res.SetOutput(&PinOutput{added})
72 + res.SetOutput(&PinOutput{added})
73 + } else {
74 + fi, err := req.Files().NextFile()
75 + if err != nil {
76 + res.SetError(err, cmds.ErrNormal)
77 + return
78 + }
79 +
80 + out := make(chan interface{})
81 + go func(ctx context.Context) {
82 + defer close(out)
83 + scan := bufio.NewScanner(fi)
84 + for scan.Scan() {
85 + added, err := corerepo.Pin(n, ctx, []string{scan.Text()}, recursive)
86 + if err != nil {
87 + res.SetError(err, cmds.ErrNormal)
88 + return
89 + }
90 +
91 + out <- &PinOutput{added}
92 + }
93 + }(req.Context())
94 + res.SetOutput((<-chan interface{})(out))
95 + }
96 },
97 Marshalers: cmds.MarshalerMap{
98 cmds.Text: func(res cmds.Response) (io.Reader, error) {
74 - added, ok := res.Output().(*PinOutput)
75 - if !ok {
76 - return nil, u.ErrCast()
77 - }
78 -
99 var pintype string
100 rec, found, _ := res.Request().Option("recursive").Bool()
101 if rec || !found {
@@ -84,11 +104,31 @@ var addPinCmd = &cmds.Command{
104 pintype = "directly"
105 }
106
87 - buf := new(bytes.Buffer)
88 - for _, k := range added.Pins {
89 - fmt.Fprintf(buf, "pinned %s %s\n", k, pintype)
107 + marshalPinOutput := func(po *PinOutput) io.Reader {
108 + buf := new(bytes.Buffer)
109 + for _, k := range po.Pins {
110 + fmt.Fprintf(buf, "pinned %s %s\n", k, pintype)
111 + }
112 + return buf
113 + }
114 +
115 + switch out := res.Output().(type) {
116 + case *PinOutput:
117 + return marshalPinOutput(out), nil
118 + case <-chan interface{}:
119 +
120 + marshal := func(i interface{}) (io.Reader, error) {
121 + return marshalPinOutput(i.(*PinOutput)), nil
122 + }
123 +
124 + return &cmds.ChannelMarshaler{
125 + Res: res,
126 + Marshaler: marshal,
127 + Channel: out,
128 + }, nil
129 + default:
130 + return nil, u.ErrCast()
131 }
91 - return buf, nil
132 },
133 },
134 }
test/sharness/t0022-init-default.sh
+1 -1
@@ -48,7 +48,7 @@ test_expect_success "ipfs config output looks good" '
48 test_cmp expected actual
49 '
50
51 -test_launch_ipfs_daemon
51 +test_launch_ipfs_daemon --offline
52
53 test_kill_ipfs_daemon
54