@cryptotaxi247 / kubo / commits / 6681c5037

commands/cli: Decomposed 'parseArgs'

Matt Bell committed Nov 17, 2014 at 18:49 UTC 6681c5037114b99a4c122ef498c51e4be295df7d
1 file changed +92 -56
commands/cli/parse.go
+92 -56
@@ -131,15 +131,10 @@ func parseOptions(input []string) (map[string]interface{}, []string, error) {
131 func parseArgs(inputs []string, stdin *os.File, argDefs []cmds.Argument, recursive bool) ([]string, []cmds.File, error) {
132 // check if stdin is coming from terminal or is being piped in
133 if stdin != nil {
134 - stat, err := stdin.Stat()
135 - if err != nil {
134 + if term, err := isTerminal(stdin); err != nil {
135 return nil, nil, err
137 - }
138 -
139 - // if stdin isn't a CharDevice, set it to nil
140 - // (this means it is coming from terminal and we want to ignore it)
141 - if (stat.Mode() & os.ModeCharDevice) != 0 {
142 - stdin = nil
136 + } else if term {
137 + stdin = nil // set to nil so we ignore it
138 }
139 }
140
@@ -169,14 +164,7 @@ func parseArgs(inputs []string, stdin *os.File, argDefs []cmds.Argument, recursi
164
165 argDefIndex := 0 // the index of the current argument definition
166 for i := 0; i < numInputs; i++ {
172 - // get the argument definiton (should be argDefs[argDefIndex],
173 - // but if argDefIndex > len(argDefs) we use the last argument definition)
174 - var argDef cmds.Argument
175 - if argDefIndex < len(argDefs) {
176 - argDef = argDefs[argDefIndex]
177 - } else if len(argDefs) > 0 {
178 - argDef = argDefs[len(argDefs)-1]
179 - }
167 + argDef := getArgDef(argDefIndex, argDefs)
168
169 // skip optional argument definitions if there aren't sufficient remaining inputs
170 if numInputs-i <= numRequired && !argDef.Required {
@@ -185,64 +173,31 @@ func parseArgs(inputs []string, stdin *os.File, argDefs []cmds.Argument, recursi
173 numRequired--
174 }
175
176 + var err error
177 if argDef.Type == cmds.ArgString {
178 if stdin == nil {
179 // add string values
191 - stringArgs = append(stringArgs, inputs[0])
192 - inputs = inputs[1:]
180 + stringArgs, inputs = appendString(stringArgs, inputs)
181
182 } else if argDef.SupportsStdin {
183 // if we have a stdin, read it in and use the data as a string value
196 - var buf bytes.Buffer
197 - _, err := buf.ReadFrom(stdin)
184 + stringArgs, stdin, err = appendStdinAsString(stringArgs, stdin)
185 if err != nil {
186 return nil, nil, err
187 }
201 - stringArgs = append(stringArgs, buf.String())
202 - stdin = nil
188 }
189
190 } else if argDef.Type == cmds.ArgFile {
191 if stdin == nil {
192 // treat stringArg values as file paths
208 - path := inputs[0]
209 - inputs = inputs[1:]
210 -
211 - file, err := os.Open(path)
212 - if err != nil {
213 - return nil, nil, err
214 - }
215 -
216 - stat, err := file.Stat()
217 - if err != nil {
218 - return nil, nil, err
219 - }
220 -
221 - if stat.IsDir() {
222 - if !argDef.Recursive {
223 - err = fmt.Errorf("Invalid path '%s', argument '%s' does not support directories",
224 - path, argDef.Name)
225 - return nil, nil, err
226 - }
227 - if !recursive {
228 - err = fmt.Errorf("'%s' is a directory, use the '-%s' flag to specify directories",
229 - path, cmds.RecShort)
230 - return nil, nil, err
231 - }
232 - }
233 -
234 - fileArg, err := getFile(file, path)
193 + fileArgs, inputs, err = appendFile(fileArgs, inputs, argDef, recursive)
194 if err != nil {
195 return nil, nil, err
196 }
197
239 - fileArgs = append(fileArgs, fileArg)
240 -
198 } else if argDef.SupportsStdin {
199 // if we have a stdin, create a file from it
243 - fileArg := &cmds.ReaderFile{"", stdin}
244 - fileArgs = append(fileArgs, fileArg)
245 - stdin = nil
200 + fileArgs, stdin = appendStdinAsFile(fileArgs, stdin)
201 }
202 }
203
@@ -261,8 +216,76 @@ func parseArgs(inputs []string, stdin *os.File, argDefs []cmds.Argument, recursi
216 return stringArgs, fileArgs, nil
217 }
218
219 +func getArgDef(i int, argDefs []cmds.Argument) *cmds.Argument {
220 + if i < len(argDefs) {
221 + // get the argument definition (usually just argDefs[i])
222 + return &argDefs[i]
223 +
224 + } else if len(argDefs) > 0 {
225 + // but if i > len(argDefs) we use the last argument definition)
226 + return &argDefs[len(argDefs)-1]
227 + }
228 +
229 + // only happens if there aren't any definitions
230 + return nil
231 +}
232 +
233 +func appendString(args, inputs []string) ([]string, []string) {
234 + return append(args, inputs[0]), inputs[1:]
235 +}
236 +
237 +func appendStdinAsString(args []string, stdin *os.File) ([]string, *os.File, error) {
238 + var buf bytes.Buffer
239 +
240 + _, err := buf.ReadFrom(stdin)
241 + if err != nil {
242 + return nil, nil, err
243 + }
244 +
245 + return append(args, buf.String()), nil, nil
246 +}
247 +
248 +func appendFile(args []cmds.File, inputs []string, argDef *cmds.Argument, recursive bool) ([]cmds.File, []string, error) {
249 + path := inputs[0]
250 +
251 + file, err := os.Open(path)
252 + if err != nil {
253 + return nil, nil, err
254 + }
255 +
256 + stat, err := file.Stat()
257 + if err != nil {
258 + return nil, nil, err
259 + }
260 +
261 + if stat.IsDir() {
262 + if !argDef.Recursive {
263 + err = fmt.Errorf("Invalid path '%s', argument '%s' does not support directories",
264 + path, argDef.Name)
265 + return nil, nil, err
266 + }
267 + if !recursive {
268 + err = fmt.Errorf("'%s' is a directory, use the '-%s' flag to specify directories",
269 + path, cmds.RecShort)
270 + return nil, nil, err
271 + }
272 + }
273 +
274 + arg, err := openPath(file, path)
275 + if err != nil {
276 + return nil, nil, err
277 + }
278 +
279 + return append(args, arg), inputs[1:], nil
280 +}
281 +
282 +func appendStdinAsFile(args []cmds.File, stdin *os.File) ([]cmds.File, *os.File) {
283 + arg := &cmds.ReaderFile{"", stdin}
284 + return append(args, arg), nil
285 +}
286 +
287 // recursively get file or directory contents as a cmds.File
265 -func getFile(file *os.File, path string) (cmds.File, error) {
288 +func openPath(file *os.File, path string) (cmds.File, error) {
289 stat, err := file.Stat()
290 if err != nil {
291 return nil, err
@@ -288,7 +311,7 @@ func getFile(file *os.File, path string) (cmds.File, error) {
311 return nil, err
312 }
313
291 - f, err := getFile(childFile, childPath)
314 + f, err := openPath(childFile, childPath)
315 if err != nil {
316 return nil, err
317 }
@@ -298,3 +321,16 @@ func getFile(file *os.File, path string) (cmds.File, error) {
321
322 return &cmds.SliceFile{path, files}, nil
323 }
324 +
325 +// isTerminal returns true if stdin is a Stdin pipe (e.g. `cat file | ipfs`),
326 +// and false otherwise (e.g. nothing is being piped in, so stdin is
327 +// coming from the terminal)
328 +func isTerminal(stdin *os.File) (bool, error) {
329 + stat, err := stdin.Stat()
330 + if err != nil {
331 + return false, err
332 + }
333 +
334 + // if stdin is a CharDevice, return true
335 + return ((stat.Mode() & os.ModeCharDevice) != 0), nil
336 +}