Commit 3a9a62eb authored by Matt Bell's avatar Matt Bell

commands/cli: Open file paths when parsing and use in request.Files()

parent 132e7402
...@@ -15,11 +15,9 @@ var ErrInvalidSubcmd = errors.New("subcommand not found") ...@@ -15,11 +15,9 @@ var ErrInvalidSubcmd = errors.New("subcommand not found")
// Parse parses the input commandline string (cmd, flags, and args). // Parse parses the input commandline string (cmd, flags, and args).
// returns the corresponding command Request object. // returns the corresponding command Request object.
// Parse will search each root to find the one that best matches the requested subcommand.
func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *cmds.Command, []string, error) { func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *cmds.Command, []string, error) {
// use the root that matches the longest path (most accurately matches request)
path, input, cmd := parsePath(input, root) path, input, cmd := parsePath(input, root)
opts, stringArgs, err := parseOptions(input) opts, stringVals, err := parseOptions(input)
if err != nil { if err != nil {
return nil, cmd, path, err return nil, cmd, path, err
} }
...@@ -28,7 +26,7 @@ func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *c ...@@ -28,7 +26,7 @@ func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *c
return nil, nil, path, ErrInvalidSubcmd return nil, nil, path, ErrInvalidSubcmd
} }
args, err := parseArgs(stringArgs, stdin, cmd.Arguments) stringArgs, fileArgs, err := parseArgs(stringVals, stdin, cmd.Arguments)
if err != nil { if err != nil {
return nil, cmd, path, err return nil, cmd, path, err
} }
...@@ -46,7 +44,9 @@ func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *c ...@@ -46,7 +44,9 @@ func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *c
} }
} }
req, err := cmds.NewRequest(path, opts, args, cmd, optDefs) file := &cmds.SliceFile{"", fileArgs}
req, err := cmds.NewRequest(path, opts, stringArgs, file, cmd, optDefs)
if err != nil { if err != nil {
return nil, cmd, path, err return nil, cmd, path, err
} }
...@@ -120,12 +120,12 @@ func parseOptions(input []string) (map[string]interface{}, []string, error) { ...@@ -120,12 +120,12 @@ func parseOptions(input []string) (map[string]interface{}, []string, error) {
return opts, args, nil return opts, args, nil
} }
func parseArgs(stringArgs []string, stdin *os.File, arguments []cmds.Argument) ([]interface{}, error) { func parseArgs(inputs []string, stdin *os.File, arguments []cmds.Argument) ([]interface{}, []cmds.File, error) {
// check if stdin is coming from terminal or is being piped in // check if stdin is coming from terminal or is being piped in
if stdin != nil { if stdin != nil {
stat, err := stdin.Stat() stat, err := stdin.Stat()
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
// if stdin isn't a CharDevice, set it to nil // if stdin isn't a CharDevice, set it to nil
...@@ -136,22 +136,24 @@ func parseArgs(stringArgs []string, stdin *os.File, arguments []cmds.Argument) ( ...@@ -136,22 +136,24 @@ func parseArgs(stringArgs []string, stdin *os.File, arguments []cmds.Argument) (
} }
// count required argument definitions // count required argument definitions
lenRequired := 0 numRequired := 0
for _, argDef := range arguments { for _, argDef := range arguments {
if argDef.Required { if argDef.Required {
lenRequired++ numRequired++
} }
} }
valCount := len(stringArgs) // count number of values provided by user
numInputs := len(inputs)
if stdin != nil { if stdin != nil {
valCount += 1 numInputs += 1
} }
args := make([]interface{}, 0, valCount) stringArgs := make([]interface{}, 0, numInputs)
fileArgs := make([]cmds.File, 0, numInputs)
argDefIndex := 0 // the index of the current argument definition argDefIndex := 0 // the index of the current argument definition
for i := 0; i < valCount; i++ { for i, input := range inputs {
// get the argument definiton (should be arguments[argDefIndex], // get the argument definiton (should be arguments[argDefIndex],
// but if argDefIndex > len(arguments) we use the last argument definition) // but if argDefIndex > len(arguments) we use the last argument definition)
var argDef cmds.Argument var argDef cmds.Argument
...@@ -161,43 +163,48 @@ func parseArgs(stringArgs []string, stdin *os.File, arguments []cmds.Argument) ( ...@@ -161,43 +163,48 @@ func parseArgs(stringArgs []string, stdin *os.File, arguments []cmds.Argument) (
argDef = arguments[len(arguments)-1] argDef = arguments[len(arguments)-1]
} }
// skip optional argument definitions if there aren't sufficient remaining values // skip optional argument definitions if there aren't sufficient remaining inputs
if valCount-i <= lenRequired && !argDef.Required { if numInputs-i <= numRequired && !argDef.Required {
continue continue
} else if argDef.Required { } else if argDef.Required {
lenRequired-- numRequired--
} }
if argDef.Type == cmds.ArgString { if argDef.Type == cmds.ArgString {
if stdin == nil { if stdin == nil {
// add string values // add string values
args = append(args, stringArgs[0]) stringArgs = append(stringArgs, input)
stringArgs = stringArgs[1:] inputs = inputs[1:]
} else if argDef.SupportsStdin { } else if argDef.SupportsStdin {
// if we have a stdin, read it in and use the data as a string value // if we have a stdin, read it in and use the data as a string value
var buf bytes.Buffer var buf bytes.Buffer
_, err := buf.ReadFrom(stdin) _, err := buf.ReadFrom(stdin)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
args = append(args, buf.String()) stringArgs = append(stringArgs, buf.String())
stdin = nil stdin = nil
} }
} else if argDef.Type == cmds.ArgFile { } else if argDef.Type == cmds.ArgFile {
if stdin == nil { if stdin == nil {
// treat stringArg values as file paths // treat stringArg values as file paths
file, err := os.Open(stringArgs[0]) path := input
inputs = inputs[1:]
file, err := os.Open(path)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
args = append(args, file)
stringArgs = stringArgs[1:] fileArg := &cmds.ReaderFile{path, file}
fileArgs = append(fileArgs, fileArg)
} else if argDef.SupportsStdin { } else if argDef.SupportsStdin {
// if we have a stdin, use that as a reader // if we have a stdin, create a file from it
args = append(args, stdin) fileArg := &cmds.ReaderFile{"", stdin}
fileArgs = append(fileArgs, fileArg)
stdin = nil stdin = nil
} }
} }
...@@ -205,5 +212,5 @@ func parseArgs(stringArgs []string, stdin *os.File, arguments []cmds.Argument) ( ...@@ -205,5 +212,5 @@ func parseArgs(stringArgs []string, stdin *os.File, arguments []cmds.Argument) (
argDefIndex++ argDefIndex++
} }
return args, nil return stringArgs, fileArgs, nil
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment