@cryptotaxi247 / kubo / commits / 3a9a62eb0

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 }