commands: Fixed argument value/definition mapping
Matt Bell committed
Nov 4, 2014 at 17:41 UTC
116041c5ec52335bbafe1755c05f3f30bbe2a70d
3 files changed
+85
-19
commands/cli/parse.go
+42
-9
@@ -117,25 +117,58 @@ func parseOptions(input []string) (map[string]interface{}, []string, error) {
117
}
118
119
func parseArgs(stringArgs []string, cmd *cmds.Command) ([]interface{}, error) {
120
- var argDef cmds.Argument
121
- args := make([]interface{}, len(stringArgs))
120
+ args := make([]interface{}, 0)
121
123
- for i, arg := range stringArgs {
124
- if i < len(cmd.Arguments) {
125
- argDef = cmd.Arguments[i]
122
+ // count required argument definitions
123
+ lenRequired := 0
124
+ for _, argDef := range cmd.Arguments {
125
+ if argDef.Required {
126
+ lenRequired++
127
}
128
+ }
129
128
- if argDef.Type == cmds.ArgString {
129
- args[i] = arg
130
+ j := 0
131
+ for _, argDef := range cmd.Arguments {
132
+ // skip optional argument definitions if there aren't sufficient remaining values
133
+ if len(stringArgs)-j <= lenRequired && !argDef.Required {
134
+ continue
135
+ }
136
137
+ if j >= len(stringArgs) {
138
+ break
139
+ }
140
+
141
+ if argDef.Variadic {
142
+ for _, arg := range stringArgs[j:] {
143
+ var err error
144
+ args, err = appendArg(args, argDef, arg)
145
+ if err != nil {
146
+ return nil, err
147
+ }
148
+ }
149
} else {
132
- in, err := os.Open(arg)
150
+ var err error
151
+ args, err = appendArg(args, argDef, stringArgs[j])
152
if err != nil {
153
return nil, err
154
}
136
- args[i] = in
155
}
156
+
157
+ j++
158
}
159
160
return args, nil
161
}
162
+
163
+func appendArg(args []interface{}, argDef cmds.Argument, value string) ([]interface{}, error) {
164
+ if argDef.Type == cmds.ArgString {
165
+ return append(args, value), nil
166
+
167
+ } else {
168
+ in, err := os.Open(value)
169
+ if err != nil {
170
+ return nil, err
171
+ }
172
+ return append(args, in), nil
173
+ }
174
+}
commands/command.go
+19
-5
@@ -149,13 +149,27 @@ func (c *Command) CheckArguments(req Request) error {
149
return fmt.Errorf("Expected %v arguments, got %v", len(argDefs), len(args))
150
}
151
152
+ // count required argument definitions
153
+ lenRequired := 0
154
+ for _, argDef := range c.Arguments {
155
+ if argDef.Required {
156
+ lenRequired++
157
+ }
158
+ }
159
+
160
// iterate over the arg definitions
153
- for i, argDef := range c.Arguments {
161
+ j := 0
162
+ for _, argDef := range c.Arguments {
163
+ // skip optional argument definitions if there aren't sufficient remaining values
164
+ if len(args)-j <= lenRequired && !argDef.Required {
165
+ continue
166
+ }
167
168
// the value for this argument definition. can be nil if it wasn't provided by the caller
169
var v interface{}
157
- if i < len(args) {
158
- v = args[i]
170
+ if j < len(args) {
171
+ v = args[j]
172
+ j++
173
}
174
175
err := checkArgValue(v, argDef)
@@ -164,8 +178,8 @@ func (c *Command) CheckArguments(req Request) error {
178
}
179
180
// any additional values are for the variadic arg definition
167
- if argDef.Variadic && i < len(args)-1 {
168
- for _, val := range args[i+1:] {
181
+ if argDef.Variadic && j < len(args)-1 {
182
+ for _, val := range args[j+1:] {
183
err := checkArgValue(val, argDef)
184
if err != nil {
185
return err
commands/http/parse.go
+24
-5
@@ -39,13 +39,32 @@ func Parse(r *http.Request, root *cmds.Command) (cmds.Request, error) {
39
opts, stringArgs2 := parseOptions(r)
40
stringArgs = append(stringArgs, stringArgs2...)
41
42
- // Note that the argument handling here is dumb, it does not do any error-checking.
43
- // (Arguments are further processed when the request is passed to the command to run)
42
args := make([]interface{}, 0)
43
46
- for _, arg := range cmd.Arguments {
47
- if arg.Type == cmds.ArgString {
48
- if arg.Variadic {
44
+ // count required argument definitions
45
+ lenRequired := 0
46
+ for _, argDef := range cmd.Arguments {
47
+ if argDef.Required {
48
+ lenRequired++
49
+ }
50
+ }
51
+
52
+ // count the number of provided argument values
53
+ valCount := len(stringArgs)
54
+ // TODO: add total number of parts in request body (instead of just 1 if body is present)
55
+ if r.Body != nil {
56
+ valCount += 1
57
+ }
58
+
59
+ for _, argDef := range cmd.Arguments {
60
+ // skip optional argument definitions if there aren't sufficient remaining values
61
+ if valCount <= lenRequired && !argDef.Required {
62
+ continue
63
+ }
64
+ valCount--
65
+
66
+ if argDef.Type == cmds.ArgString {
67
+ if argDef.Variadic {
68
for _, s := range stringArgs {
69
args = append(args, s)
70
}