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