@cryptotaxi247 / kubo / commits / ddc8d0c60

commands: remove EnableStdin support for StringArg

With verbose flag: * remove EnableStdin() flags on all StringArg, * remove all unneeded parsing code for StringArg, and print an * informative message if `ipfs` begins reading from a CharDevice, * remove broken go tests for EnableStdin cli parsing, and add some * trivial test cases for reading FileArg from stdin, * add a panic to prevent EnableStdin from being set on * StringArg in the future. Resolves: #2877, #2870 License: MIT Signed-off-by: Thomas Gardner <tmg@fastmail.com>

Thomas Gardner committed Jun 23, 2016 at 22:35 UTC ddc8d0c60c7e4e46f63afc3d754f4c973ae084a8
23 files changed +82 -143
commands/argument.go
+4 -1
@@ -42,13 +42,16 @@ 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 + }
48 a.SupportsStdin = true
49 return a
50 }
51
52 func (a Argument) EnableRecursive() Argument {
53 if a.Type != ArgFile {
51 - panic("Only ArgFile arguments can enable recursive")
54 + panic("Only FileArgs can enable recursive")
55 }
56
57 a.Recursive = true
commands/cli/parse.go
+28 -45
@@ -1,7 +1,6 @@
1 package cli
2
3 import (
4 - "bytes"
4 "fmt"
5 "os"
6 "path"
@@ -13,8 +12,11 @@ import (
12 cmds "github.com/ipfs/go-ipfs/commands"
13 files "github.com/ipfs/go-ipfs/commands/files"
14 u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
15 + logging "gx/ipfs/QmYtB7Qge8cJpXc4irsEp8zRqfnZMBeB7aTrMEkPk67DRv/go-log"
16 )
17
18 +var log = logging.Logger("commands/cli")
19 +
20 // Parse parses the input commandline string (cmd, flags, and args).
21 // returns the corresponding command Request object.
22 func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *cmds.Command, []string, error) {
@@ -238,6 +240,8 @@ func parseOpts(args []string, root *cmds.Command) (
240 return
241 }
242
243 +const msgStdinInfo = "ipfs: Reading from %s; send Ctrl-d to stop.\n"
244 +
245 func parseArgs(inputs []string, stdin *os.File, argDefs []cmds.Argument, recursive, hidden bool, root *cmds.Command) ([]string, []files.File, error) {
246 // ignore stdin on Windows
247 if runtime.GOOS == "windows" {
@@ -286,36 +290,11 @@ func parseArgs(inputs []string, stdin *os.File, argDefs []cmds.Argument, recursi
290
291 fillingVariadic := argDefIndex+1 > len(argDefs)
292
289 - var err error
293 if argDef.Type == cmds.ArgString {
294 if len(inputs) > 0 {
292 - // If argument is "-" use stdin
293 - if inputs[0] == "-" && argDef.SupportsStdin {
294 - stringArgs, stdin, err = appendStdinAsString(stringArgs, stdin)
295 - if err != nil {
296 - return nil, nil, err
297 - }
298 - }
299 - // add string values
300 - stringArgs, inputs = appendString(stringArgs, inputs)
301 - } else if !argDef.SupportsStdin {
302 - if len(inputs) == 0 {
303 - // failure case, we have stdin, but our current
304 - // argument doesnt want stdin
305 - break
306 - }
307 -
308 - stringArgs, inputs = appendString(stringArgs, inputs)
295 + stringArgs, inputs = append(stringArgs, inputs[0]), inputs[1:]
296 } else {
310 - if stdin != nil && argDef.Required && !fillingVariadic {
311 - // if we have a stdin, read it in and use the data as a string value
312 - stringArgs, stdin, err = appendStdinAsString(stringArgs, stdin)
313 - if err != nil {
314 - return nil, nil, err
315 - }
316 - } else {
317 - break
318 - }
297 + break
298 }
299 } else if argDef.Type == cmds.ArgFile {
300 if len(inputs) > 0 {
@@ -325,7 +304,9 @@ func parseArgs(inputs []string, stdin *os.File, argDefs []cmds.Argument, recursi
304 var file files.File
305 var err error
306 if fpath == "-" {
328 - file = files.NewReaderFile("", "", stdin, nil)
307 + if err = printReadInfo(stdin, msgStdinInfo); err == nil {
308 + file = files.NewReaderFile("", "", stdin, nil)
309 + }
310 } else {
311 file, err = appendFile(fpath, argDef, recursive, hidden)
312 }
@@ -337,6 +318,9 @@ func parseArgs(inputs []string, stdin *os.File, argDefs []cmds.Argument, recursi
318 } else {
319 if stdin != nil && argDef.SupportsStdin &&
320 argDef.Required && !fillingVariadic {
321 + if err := printReadInfo(stdin, msgStdinInfo); err != nil {
322 + return nil, nil, err
323 + }
324 fileArgs[""] = files.NewReaderFile("", "", stdin, nil)
325 } else {
326 break
@@ -389,22 +373,6 @@ func getArgDef(i int, argDefs []cmds.Argument) *cmds.Argument {
373 return nil
374 }
375
392 -func appendString(args, inputs []string) ([]string, []string) {
393 - return append(args, inputs[0]), inputs[1:]
394 -}
395 -
396 -func appendStdinAsString(args []string, stdin *os.File) ([]string, *os.File, error) {
397 - buf := new(bytes.Buffer)
398 -
399 - _, err := buf.ReadFrom(stdin)
400 - if err != nil {
401 - return nil, nil, err
402 - }
403 -
404 - input := strings.TrimSpace(buf.String())
405 - return append(args, strings.Split(input, "\n")...), nil, nil
406 -}
407 -
376 const notRecursiveFmtStr = "'%s' is a directory, use the '-%s' flag to specify directories"
377 const dirNotSupportedFmtStr = "Invalid path '%s', argument '%s' does not support directories"
378
@@ -435,3 +403,18 @@ func appendFile(fpath string, argDef *cmds.Argument, recursive, hidden bool) (fi
403
404 return files.NewSerialFile(path.Base(fpath), fpath, hidden, stat)
405 }
406 +
407 +// Inform the user if a file is waiting on input
408 +func printReadInfo(f *os.File, msg string) error {
409 + fInfo, err := f.Stat()
410 + if err != nil {
411 + log.Error(err)
412 + return err
413 + }
414 +
415 + if (fInfo.Mode() & os.ModeCharDevice) != 0 {
416 + fmt.Fprintf(os.Stderr, msg, f.Name())
417 + }
418 +
419 + return nil
420 +}
commands/cli/parse_test.go
+8 -56
@@ -177,26 +177,14 @@ func TestArgumentParsing(t *testing.T) {
177 commands.StringArg("b", true, false, "another arg"),
178 },
179 },
180 - "stdinenabled": {
180 + "FileArg": {
181 Arguments: []commands.Argument{
182 - commands.StringArg("a", true, true, "some arg").EnableStdin(),
182 + commands.FileArg("a", false, false, "some arg"),
183 },
184 },
185 - "stdinenabled2args": &commands.Command{
185 + "FileArg+Stdin": {
186 Arguments: []commands.Argument{
187 - commands.StringArg("a", true, false, "some arg"),
188 - commands.StringArg("b", true, true, "another arg").EnableStdin(),
189 - },
190 - },
191 - "stdinenablednotvariadic": &commands.Command{
192 - Arguments: []commands.Argument{
193 - commands.StringArg("a", true, false, "some arg").EnableStdin(),
194 - },
195 - },
196 - "stdinenablednotvariadic2args": &commands.Command{
197 - Arguments: []commands.Argument{
198 - commands.StringArg("a", true, false, "some arg"),
199 - commands.StringArg("b", true, false, "another arg").EnableStdin(),
187 + commands.FileArg("a", true, true, "some arg").EnableStdin(),
188 },
189 },
190 },
@@ -259,53 +247,17 @@ func TestArgumentParsing(t *testing.T) {
247 if err != nil {
248 t.Fatal(err)
249 }
262 - defer os.Remove(fstdin.Name())
250
251 if _, err := io.WriteString(fstdin, content); err != nil {
252 t.Fatal(err)
253 }
254 return fstdin
255 }
269 -
270 - test([]string{"stdinenabled", "value1", "value2"}, nil, []string{"value1", "value2"})
271 -
256 fstdin := fileToSimulateStdin(t, "stdin1")
273 - test([]string{"stdinenabled"}, fstdin, []string{"stdin1"})
274 - test([]string{"stdinenabled", "value1"}, fstdin, []string{"value1"})
275 - test([]string{"stdinenabled", "value1", "value2"}, fstdin, []string{"value1", "value2"})
257 + defer os.Remove(fstdin.Name())
258
277 - fstdin = fileToSimulateStdin(t, "stdin1\nstdin2")
278 - test([]string{"stdinenabled"}, fstdin, []string{"stdin1", "stdin2"})
279 -
280 - fstdin = fileToSimulateStdin(t, "stdin1\nstdin2\nstdin3")
281 - test([]string{"stdinenabled"}, fstdin, []string{"stdin1", "stdin2", "stdin3"})
282 -
283 - test([]string{"stdinenabled2args", "value1", "value2"}, nil, []string{"value1", "value2"})
284 -
285 - fstdin = fileToSimulateStdin(t, "stdin1")
286 - test([]string{"stdinenabled2args", "value1"}, fstdin, []string{"value1", "stdin1"})
287 - test([]string{"stdinenabled2args", "value1", "value2"}, fstdin, []string{"value1", "value2"})
288 - test([]string{"stdinenabled2args", "value1", "value2", "value3"}, fstdin, []string{"value1", "value2", "value3"})
289 -
290 - fstdin = fileToSimulateStdin(t, "stdin1\nstdin2")
291 - test([]string{"stdinenabled2args", "value1"}, fstdin, []string{"value1", "stdin1", "stdin2"})
292 -
293 - test([]string{"stdinenablednotvariadic", "value1"}, nil, []string{"value1"})
294 -
295 - fstdin = fileToSimulateStdin(t, "stdin1")
296 - test([]string{"stdinenablednotvariadic"}, fstdin, []string{"stdin1"})
297 - test([]string{"stdinenablednotvariadic", "value1"}, fstdin, []string{"value1"})
298 -
299 - test([]string{"stdinenablednotvariadic2args", "value1", "value2"}, nil, []string{"value1", "value2"})
300 -
301 - fstdin = fileToSimulateStdin(t, "stdin1")
302 - test([]string{"stdinenablednotvariadic2args", "value1"}, fstdin, []string{"value1", "stdin1"})
303 - test([]string{"stdinenablednotvariadic2args", "value1", "value2"}, fstdin, []string{"value1", "value2"})
304 - testFail([]string{"stdinenablednotvariadic2args"}, fstdin, "cant use stdin for non stdin arg")
305 -
306 - fstdin = fileToSimulateStdin(t, "stdin1")
259 test([]string{"noarg"}, fstdin, []string{})
308 -
309 - fstdin = fileToSimulateStdin(t, "stdin1")
310 - test([]string{"optionalsecond", "value1", "value2"}, fstdin, []string{"value1", "value2"})
260 + test([]string{"FileArg", fstdin.Name()}, nil, []string{})
261 + test([]string{"FileArg+Stdin"}, fstdin, []string{})
262 + test([]string{"FileArg+Stdin", "-"}, fstdin, []string{})
263 }
core/commands/bitswap.go
+1 -1
@@ -31,7 +31,7 @@ var unwantCmd = &cmds.Command{
31 Tagline: "Remove a given block from your wantlist.",
32 },
33 Arguments: []cmds.Argument{
34 - cmds.StringArg("key", true, true, "Key(s) to remove from your wantlist.").EnableStdin(),
34 + cmds.StringArg("key", true, true, "Key(s) to remove from your wantlist."),
35 },
36 Run: func(req cmds.Request, res cmds.Response) {
37 nd, err := req.InvocContext().GetNode()
core/commands/block.go
+2 -2
@@ -55,7 +55,7 @@ on raw ipfs blocks. It outputs the following to stdout:
55 },
56
57 Arguments: []cmds.Argument{
58 - cmds.StringArg("key", true, false, "The base58 multihash of an existing block to get.").EnableStdin(),
58 + cmds.StringArg("key", true, false, "The base58 multihash of an existing block to get."),
59 },
60 Run: func(req cmds.Request, res cmds.Response) {
61 b, err := getBlockForKey(req, req.Arguments()[0])
@@ -88,7 +88,7 @@ It outputs to stdout, and <key> is a base58 encoded multihash.
88 },
89
90 Arguments: []cmds.Argument{
91 - cmds.StringArg("key", true, false, "The base58 multihash of an existing block to get.").EnableStdin(),
91 + cmds.StringArg("key", true, false, "The base58 multihash of an existing block to get."),
92 },
93 Run: func(req cmds.Request, res cmds.Response) {
94 b, err := getBlockForKey(req, req.Arguments()[0])
core/commands/bootstrap.go
+2 -2
@@ -47,7 +47,7 @@ in the bootstrap list).
47 },
48
49 Arguments: []cmds.Argument{
50 - cmds.StringArg("peer", false, true, peerOptionDesc).EnableStdin(),
50 + cmds.StringArg("peer", false, true, peerOptionDesc),
51 },
52
53 Options: []cmds.Option{
@@ -129,7 +129,7 @@ var bootstrapRemoveCmd = &cmds.Command{
129 },
130
131 Arguments: []cmds.Argument{
132 - cmds.StringArg("peer", false, true, peerOptionDesc).EnableStdin(),
132 + cmds.StringArg("peer", false, true, peerOptionDesc),
133 },
134 Options: []cmds.Option{
135 cmds.BoolOption("all", "Remove all bootstrap peers.").Default(false),
core/commands/cat.go
+1 -1
@@ -20,7 +20,7 @@ var CatCmd = &cmds.Command{
20 },
21
22 Arguments: []cmds.Argument{
23 - cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to be outputted.").EnableStdin(),
23 + cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to be outputted."),
24 },
25 Run: func(req cmds.Request, res cmds.Response) {
26 node, err := req.InvocContext().GetNode()
core/commands/dht.go
+1 -1
@@ -459,7 +459,7 @@ NOTE: A value may not exceed 2048 bytes.
459
460 Arguments: []cmds.Argument{
461 cmds.StringArg("key", true, false, "The key to store the value at."),
462 - cmds.StringArg("value", true, false, "The value to store.").EnableStdin(),
462 + cmds.StringArg("value", true, false, "The value to store."),
463 },
464 Options: []cmds.Option{
465 cmds.BoolOption("verbose", "v", "Print extra information.").Default(false),
core/commands/dns.go
+1 -1
@@ -44,7 +44,7 @@ The resolver can recursively resolve:
44 },
45
46 Arguments: []cmds.Argument{
47 - cmds.StringArg("domain-name", true, false, "The domain-name name to resolve.").EnableStdin(),
47 + cmds.StringArg("domain-name", true, false, "The domain-name name to resolve."),
48 },
49 Options: []cmds.Option{
50 cmds.BoolOption("recursive", "r", "Resolve until the result is not a DNS link.").Default(false),
core/commands/get.go
+1 -1
@@ -37,7 +37,7 @@ may also specify the level of compression by specifying '-l=<1-9>'.
37 },
38
39 Arguments: []cmds.Argument{
40 - cmds.StringArg("ipfs-path", true, false, "The path to the IPFS object(s) to be outputted.").EnableStdin(),
40 + cmds.StringArg("ipfs-path", true, false, "The path to the IPFS object(s) to be outputted."),
41 },
42 Options: []cmds.Option{
43 cmds.StringOption("output", "o", "The path where the output should be stored."),
core/commands/id.go
+1 -1
@@ -58,7 +58,7 @@ EXAMPLE:
58 `,
59 },
60 Arguments: []cmds.Argument{
61 - cmds.StringArg("peerid", false, false, "Peer.ID of node to look up.").EnableStdin(),
61 + cmds.StringArg("peerid", false, false, "Peer.ID of node to look up."),
62 },
63 Options: []cmds.Option{
64 cmds.StringOption("format", "f", "Optional output format."),
core/commands/ipns.go
+1 -1
@@ -46,7 +46,7 @@ Resolve the value of a reference:
46 },
47
48 Arguments: []cmds.Argument{
49 - cmds.StringArg("name", false, false, "The IPNS name to resolve. Defaults to your node's peerID.").EnableStdin(),
49 + cmds.StringArg("name", false, false, "The IPNS name to resolve. Defaults to your node's peerID."),
50 },
51 Options: []cmds.Option{
52 cmds.BoolOption("recursive", "r", "Resolve until the result is not an IPNS name.").Default(false),
core/commands/ls.go
+1 -1
@@ -41,7 +41,7 @@ format:
41 },
42
43 Arguments: []cmds.Argument{
44 - cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to list links from.").EnableStdin(),
44 + cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to list links from."),
45 },
46 Options: []cmds.Option{
47 cmds.BoolOption("headers", "v", "Print table headers (Hash, Size, Name).").Default(false),
core/commands/object/object.go
+4 -4
@@ -78,7 +78,7 @@ is the raw data of the object.
78 },
79
80 Arguments: []cmds.Argument{
81 - cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format.").EnableStdin(),
81 + cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format."),
82 },
83 Run: func(req cmds.Request, res cmds.Response) {
84 n, err := req.InvocContext().GetNode()
@@ -108,7 +108,7 @@ multihash.
108 },
109
110 Arguments: []cmds.Argument{
111 - cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format.").EnableStdin(),
111 + cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format."),
112 },
113 Options: []cmds.Option{
114 cmds.BoolOption("headers", "v", "Print table headers (Hash, Size, Name).").Default(false),
@@ -179,7 +179,7 @@ This command outputs data in the following encodings:
179 },
180
181 Arguments: []cmds.Argument{
182 - cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format.").EnableStdin(),
182 + cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format."),
183 },
184 Run: func(req cmds.Request, res cmds.Response) {
185 n, err := req.InvocContext().GetNode()
@@ -246,7 +246,7 @@ var ObjectStatCmd = &cmds.Command{
246 },
247
248 Arguments: []cmds.Argument{
249 - cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format.").EnableStdin(),
249 + cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format."),
250 },
251 Run: func(req cmds.Request, res cmds.Response) {
252 n, err := req.InvocContext().GetNode()
core/commands/pin.go
+2 -2
@@ -39,7 +39,7 @@ var addPinCmd = &cmds.Command{
39 },
40
41 Arguments: []cmds.Argument{
42 - cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be pinned.").EnableStdin(),
42 + cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be pinned."),
43 },
44 Options: []cmds.Option{
45 cmds.BoolOption("recursive", "r", "Recursively pin the object linked to by the specified object(s).").Default(true),
@@ -103,7 +103,7 @@ collected if needed. (By default, recursively. Use -r=false for direct pins)
103 },
104
105 Arguments: []cmds.Argument{
106 - cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be unpinned.").EnableStdin(),
106 + cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be unpinned."),
107 },
108 Options: []cmds.Option{
109 cmds.BoolOption("recursive", "r", "Recursively unpin the object linked to by the specified object(s).").Default(true),
core/commands/ping.go
+1 -1
@@ -37,7 +37,7 @@ trip latency information.
37 `,
38 },
39 Arguments: []cmds.Argument{
40 - cmds.StringArg("peer ID", true, true, "ID of peer to be pinged.").EnableStdin(),
40 + cmds.StringArg("peer ID", true, true, "ID of peer to be pinged."),
41 },
42 Options: []cmds.Option{
43 cmds.IntOption("count", "n", "Number of ping messages to send.").Default(10),
core/commands/publish.go
+1 -1
@@ -47,7 +47,7 @@ Publish an <ipfs-path> to another public key (not implemented):
47 },
48
49 Arguments: []cmds.Argument{
50 - cmds.StringArg("ipfs-path", true, false, "IPFS path of the object to be published.").EnableStdin(),
50 + cmds.StringArg("ipfs-path", true, false, "IPFS path of the object to be published."),
51 },
52 Options: []cmds.Option{
53 cmds.BoolOption("resolve", "Resolve given path before publishing.").Default(true),
core/commands/refs.go
+1 -1
@@ -46,7 +46,7 @@ NOTE: List all references recursively by using the flag '-r'.
46 "local": RefsLocalCmd,
47 },
48 Arguments: []cmds.Argument{
49 - cmds.StringArg("ipfs-path", true, true, "Path to the object(s) to list refs from.").EnableStdin(),
49 + cmds.StringArg("ipfs-path", true, true, "Path to the object(s) to list refs from."),
50 },
51 Options: []cmds.Option{
52 cmds.StringOption("format", "Emit edges with given format. Available tokens: <src> <dst> <linkname>.").Default("<dst>"),
core/commands/resolve.go
+1 -1
@@ -56,7 +56,7 @@ Resolve the value of an IPFS DAG path:
56 },
57
58 Arguments: []cmds.Argument{
59 - cmds.StringArg("name", true, false, "The name to resolve.").EnableStdin(),
59 + cmds.StringArg("name", true, false, "The name to resolve."),
60 },
61 Options: []cmds.Option{
62 cmds.BoolOption("recursive", "r", "Resolve until the result is an IPFS name.").Default(false),
core/commands/swarm.go
+4 -4
@@ -215,7 +215,7 @@ ipfs swarm connect /ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3
215 `,
216 },
217 Arguments: []cmds.Argument{
218 - cmds.StringArg("address", true, true, "Address of peer to connect to.").EnableStdin(),
218 + cmds.StringArg("address", true, true, "Address of peer to connect to."),
219 },
220 Run: func(req cmds.Request, res cmds.Response) {
221 ctx := req.Context()
@@ -273,7 +273,7 @@ it will reconnect.
273 `,
274 },
275 Arguments: []cmds.Argument{
276 - cmds.StringArg("address", true, true, "Address of peer to disconnect from.").EnableStdin(),
276 + cmds.StringArg("address", true, true, "Address of peer to disconnect from."),
277 },
278 Run: func(req cmds.Request, res cmds.Response) {
279 n, err := req.InvocContext().GetNode()
@@ -441,7 +441,7 @@ add your filters to the ipfs config file.
441 `,
442 },
443 Arguments: []cmds.Argument{
444 - cmds.StringArg("address", true, true, "Multiaddr to filter.").EnableStdin(),
444 + cmds.StringArg("address", true, true, "Multiaddr to filter."),
445 },
446 Run: func(req cmds.Request, res cmds.Response) {
447 n, err := req.InvocContext().GetNode()
@@ -513,7 +513,7 @@ remove your filters from the ipfs config file.
513 `,
514 },
515 Arguments: []cmds.Argument{
516 - cmds.StringArg("address", true, true, "Multiaddr filter to remove.").EnableStdin(),
516 + cmds.StringArg("address", true, true, "Multiaddr filter to remove."),
517 },
518 Run: func(req cmds.Request, res cmds.Response) {
519 n, err := req.InvocContext().GetNode()
core/commands/tar.go
+1 -1
@@ -83,7 +83,7 @@ var tarCatCmd = &cmds.Command{
83 },
84
85 Arguments: []cmds.Argument{
86 - cmds.StringArg("path", true, false, "IPFS path of archive to export.").EnableStdin(),
86 + cmds.StringArg("path", true, false, "IPFS path of archive to export."),
87 },
88 Run: func(req cmds.Request, res cmds.Response) {
89 nd, err := req.InvocContext().GetNode()
core/commands/unixfs/ls.go
+1 -1
@@ -64,7 +64,7 @@ Example:
64 },
65
66 Arguments: []cmds.Argument{
67 - cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to list links from.").EnableStdin(),
67 + cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to list links from."),
68 },
69 Run: func(req cmds.Request, res cmds.Response) {
70 node, err := req.InvocContext().GetNode()
test/sharness/t0040-add-and-cat.sh
+14 -13
@@ -223,8 +223,8 @@ test_expect_success "ipfs cat output looks good" '
223 test_cmp expected actual
224 '
225
226 -test_expect_success "ipfs cat accept hash from stdin" '
227 - echo "$HASH" | ipfs cat >actual
226 +test_expect_success "ipfs cat accept hash from built input" '
227 + echo "$HASH" | xargs ipfs cat >actual
228 '
229
230 test_expect_success "ipfs cat output looks good" '
@@ -279,11 +279,11 @@ test_expect_success "'ipfs add' output looks good" '
279 test_cmp expected actual
280 '
281
282 -test_expect_success "'ipfs cat' with stdin input succeeds" '
283 - echo "$HASH" | ipfs cat >actual
282 +test_expect_success "'ipfs cat' with built input succeeds" '
283 + echo "$HASH" | xargs ipfs cat >actual
284 '
285
286 -test_expect_success "ipfs cat with stdin input output looks good" '
286 +test_expect_success "ipfs cat with built input output looks good" '
287 printf "Hello Neptune!\nHello Pluton!" >expected &&
288 test_cmp expected actual
289 '
@@ -330,8 +330,8 @@ test_expect_success "'ipfs add -rn' output looks good" '
330 test_cmp expected actual
331 '
332
333 -test_expect_success "ipfs cat accept many hashes from stdin" '
334 - { echo "$MARS"; echo "$VENUS"; } | ipfs cat >actual
333 +test_expect_success "ipfs cat accept many hashes from built input" '
334 + { echo "$MARS"; echo "$VENUS"; } | xargs ipfs cat >actual
335 '
336
337 test_expect_success "ipfs cat output looks good" '
@@ -347,21 +347,22 @@ test_expect_success "ipfs cat output looks good" '
347 test_cmp expected actual
348 '
349
350 -test_expect_success "ipfs cat with both arg and stdin" '
351 - echo "$MARS" | ipfs cat "$VENUS" >actual
350 +test_expect_success "ipfs cat with both arg and built input" '
351 + echo "$MARS" | xargs ipfs cat "$VENUS" >actual
352 '
353
354 test_expect_success "ipfs cat output looks good" '
355 - cat mountdir/planets/venus.txt >expected &&
355 + cat mountdir/planets/venus.txt mountdir/planets/mars.txt >expected &&
356 test_cmp expected actual
357 '
358
359 -test_expect_success "ipfs cat with two args and stdin" '
360 - echo "$MARS" | ipfs cat "$VENUS" "$VENUS" >actual
359 +test_expect_success "ipfs cat with two args and built input" '
360 + echo "$MARS" | xargs ipfs cat "$VENUS" "$VENUS" >actual
361 '
362
363 test_expect_success "ipfs cat output looks good" '
364 - cat mountdir/planets/venus.txt mountdir/planets/venus.txt >expected &&
364 + cat mountdir/planets/venus.txt mountdir/planets/venus.txt \
365 + mountdir/planets/mars.txt >expected &&
366 test_cmp expected actual
367 '
368