commands/cli: Open file paths when parsing and use in request.Files()
Matt Bell committed
Nov 16, 2014 at 00:48 UTC
3a9a62eb0e6d0a48cacc6ce25d2f751c7f41b2b9
1 file changed
+34
-27
commands/cli/parse.go
+34
-27
@@ -15,11 +15,9 @@ var ErrInvalidSubcmd = errors.New("subcommand not found")
15
16
// Parse parses the input commandline string (cmd, flags, and args).
17
// returns the corresponding command Request object.
18
-// Parse will search each root to find the one that best matches the requested subcommand.
18
func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *cmds.Command, []string, error) {
20
- // use the root that matches the longest path (most accurately matches request)
19
path, input, cmd := parsePath(input, root)
22
- opts, stringArgs, err := parseOptions(input)
20
+ opts, stringVals, err := parseOptions(input)
21
if err != nil {
22
return nil, cmd, path, err
23
}
@@ -28,7 +26,7 @@ func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *c
26
return nil, nil, path, ErrInvalidSubcmd
27
}
28
31
- args, err := parseArgs(stringArgs, stdin, cmd.Arguments)
29
+ stringArgs, fileArgs, err := parseArgs(stringVals, stdin, cmd.Arguments)
30
if err != nil {
31
return nil, cmd, path, err
32
}
@@ -46,7 +44,9 @@ func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *c
44
}
45
}
46
49
- req, err := cmds.NewRequest(path, opts, args, cmd, optDefs)
47
+ file := &cmds.SliceFile{"", fileArgs}
48
+
49
+ req, err := cmds.NewRequest(path, opts, stringArgs, file, cmd, optDefs)
50
if err != nil {
51
return nil, cmd, path, err
52
}
@@ -120,12 +120,12 @@ func parseOptions(input []string) (map[string]interface{}, []string, error) {
120
return opts, args, nil
121
}
122
123
-func parseArgs(stringArgs []string, stdin *os.File, arguments []cmds.Argument) ([]interface{}, error) {
123
+func parseArgs(inputs []string, stdin *os.File, arguments []cmds.Argument) ([]interface{}, []cmds.File, error) {
124
// check if stdin is coming from terminal or is being piped in
125
if stdin != nil {
126
stat, err := stdin.Stat()
127
if err != nil {
128
- return nil, err
128
+ return nil, nil, err
129
}
130
131
// 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
}
137
138
// count required argument definitions
139
- lenRequired := 0
139
+ numRequired := 0
140
for _, argDef := range arguments {
141
if argDef.Required {
142
- lenRequired++
142
+ numRequired++
143
}
144
}
145
146
- valCount := len(stringArgs)
146
+ // count number of values provided by user
147
+ numInputs := len(inputs)
148
if stdin != nil {
148
- valCount += 1
149
+ numInputs += 1
150
}
151
151
- args := make([]interface{}, 0, valCount)
152
+ stringArgs := make([]interface{}, 0, numInputs)
153
+ fileArgs := make([]cmds.File, 0, numInputs)
154
155
argDefIndex := 0 // the index of the current argument definition
154
- for i := 0; i < valCount; i++ {
156
+ for i, input := range inputs {
157
// get the argument definiton (should be arguments[argDefIndex],
158
// but if argDefIndex > len(arguments) we use the last argument definition)
159
var argDef cmds.Argument
@@ -161,43 +163,48 @@ func parseArgs(stringArgs []string, stdin *os.File, arguments []cmds.Argument) (
163
argDef = arguments[len(arguments)-1]
164
}
165
164
- // skip optional argument definitions if there aren't sufficient remaining values
165
- if valCount-i <= lenRequired && !argDef.Required {
166
+ // skip optional argument definitions if there aren't sufficient remaining inputs
167
+ if numInputs-i <= numRequired && !argDef.Required {
168
continue
169
} else if argDef.Required {
168
- lenRequired--
170
+ numRequired--
171
}
172
173
if argDef.Type == cmds.ArgString {
174
if stdin == nil {
175
// add string values
174
- args = append(args, stringArgs[0])
175
- stringArgs = stringArgs[1:]
176
+ stringArgs = append(stringArgs, input)
177
+ inputs = inputs[1:]
178
179
} else if argDef.SupportsStdin {
180
// if we have a stdin, read it in and use the data as a string value
181
var buf bytes.Buffer
182
_, err := buf.ReadFrom(stdin)
183
if err != nil {
182
- return nil, err
184
+ return nil, nil, err
185
}
184
- args = append(args, buf.String())
186
+ stringArgs = append(stringArgs, buf.String())
187
stdin = nil
188
}
189
190
} else if argDef.Type == cmds.ArgFile {
191
if stdin == nil {
192
// treat stringArg values as file paths
191
- file, err := os.Open(stringArgs[0])
193
+ path := input
194
+ inputs = inputs[1:]
195
+
196
+ file, err := os.Open(path)
197
if err != nil {
193
- return nil, err
198
+ return nil, nil, err
199
}
195
- args = append(args, file)
196
- stringArgs = stringArgs[1:]
200
+
201
+ fileArg := &cmds.ReaderFile{path, file}
202
+ fileArgs = append(fileArgs, fileArg)
203
204
} else if argDef.SupportsStdin {
199
- // if we have a stdin, use that as a reader
200
- args = append(args, stdin)
205
+ // if we have a stdin, create a file from it
206
+ fileArg := &cmds.ReaderFile{"", stdin}
207
+ fileArgs = append(fileArgs, fileArg)
208
stdin = nil
209
}
210
}
@@ -205,5 +212,5 @@ func parseArgs(stringArgs []string, stdin *os.File, arguments []cmds.Argument) (
212
argDefIndex++
213
}
214
208
- return args, nil
215
+ return stringArgs, fileArgs, nil
216
}