From 827f1dd0b01847727ff97c2ce3d772cb61e2d47e Mon Sep 17 00:00:00 2001
From: Matt Bell <mappum@gmail.com>
Date: Sun, 2 Nov 2014 16:55:13 -0800
Subject: [PATCH] commands: Changed Request arguments to a []interface{}

---
 commands/argument.go    | 14 ++++++++++++++
 commands/cli/parse.go   |  4 ++--
 commands/command.go     |  1 +
 commands/http/client.go |  7 +++++--
 commands/http/parse.go  | 20 +++++++++-----------
 commands/request.go     | 10 +++++-----
 6 files changed, 36 insertions(+), 20 deletions(-)
 create mode 100644 commands/argument.go

diff --git a/commands/argument.go b/commands/argument.go
new file mode 100644
index 000000000..a5758c824
--- /dev/null
+++ b/commands/argument.go
@@ -0,0 +1,14 @@
+package commands
+
+type ArgumentType int
+
+const (
+	ArgString ArgumentType = iota
+	ArgPath
+)
+
+type Argument struct {
+	Name               string
+	Type               ArgumentType
+	Required, Variadic bool
+}
diff --git a/commands/cli/parse.go b/commands/cli/parse.go
index 39fceef8f..8f930541f 100644
--- a/commands/cli/parse.go
+++ b/commands/cli/parse.go
@@ -65,9 +65,9 @@ func parsePath(input []string, root *cmds.Command) ([]string, []string, *cmds.Co
 
 // parseOptions parses the raw string values of the given options
 // returns the parsed options as strings, along with the CLI args
-func parseOptions(input []string) (map[string]interface{}, []string, error) {
+func parseOptions(input []string) (map[string]interface{}, []interface{}, error) {
 	opts := make(map[string]interface{})
-	args := []string{}
+	args := []interface{}{}
 
 	for i := 0; i < len(input); i++ {
 		blob := input[i]
diff --git a/commands/command.go b/commands/command.go
index 0521d0baf..cf10c63b6 100644
--- a/commands/command.go
+++ b/commands/command.go
@@ -24,6 +24,7 @@ type Formatter func(Response) (string, error)
 type Command struct {
 	Help        string
 	Options     []Option
+	Arguments   []Argument
 	Run         Function
 	Format      Formatter
 	Type        interface{}
diff --git a/commands/http/client.go b/commands/http/client.go
index 2c56bd819..801c0241a 100644
--- a/commands/http/client.go
+++ b/commands/http/client.go
@@ -44,8 +44,11 @@ func Send(req cmds.Request) (cmds.Response, error) {
 	for k, v := range req.Options() {
 		query += "&" + k + "=" + v.(string)
 	}
-	for _, v := range req.Arguments() {
-		query += "&arg=" + v
+	for _, arg := range req.Arguments() {
+		s, ok := arg.(string)
+		if ok {
+			query += "&arg=" + s
+		}
 	}
 
 	httpRes, err := http.Post(url+query, "application/octet-stream", req.Stream())
diff --git a/commands/http/parse.go b/commands/http/parse.go
index 2234c9165..86b4738d1 100644
--- a/commands/http/parse.go
+++ b/commands/http/parse.go
@@ -10,7 +10,7 @@ import (
 // Parse parses the data in a http.Request and returns a command Request object
 func Parse(r *http.Request, root *cmds.Command) (cmds.Request, error) {
 	path := strings.Split(r.URL.Path, "/")[3:]
-	args := make([]string, 0)
+	args := make([]interface{}, 0)
 
 	cmd, err := root.Get(path[:len(path)-1])
 	if err != nil {
@@ -34,28 +34,26 @@ func Parse(r *http.Request, root *cmds.Command) (cmds.Request, error) {
 	opts, args2 := parseOptions(r)
 	args = append(args, args2...)
 
-	// TODO: make a way to send opts/args in request body
-	//   (e.g. if form-data or form-urlencoded, then treat the same as querystring)
-	// for now, to be simple, we just use the whole request body as the input stream
-	// (r.Body will be nil if there is no request body, like in GET requests)
-	in := r.Body
-
-	return cmds.NewRequest(path, opts, args, in, cmd), nil
+	return cmds.NewRequest(path, opts, args, nil, cmd), nil
 }
 
-func parseOptions(r *http.Request) (map[string]interface{}, []string) {
+func parseOptions(r *http.Request) (map[string]interface{}, []interface{}) {
 	opts := make(map[string]interface{})
-	var args []string
+	args := make([]interface{}, 0)
 
 	query := r.URL.Query()
 	for k, v := range query {
 		if k == "arg" {
-			args = v
+			for _, s := range v {
+				args = append(args, interface{}(s))
+			}
 		} else {
 			opts[k] = v[0]
 		}
 	}
 
+	// TODO: create multipart streams for file args
+
 	// default to setting encoding to JSON
 	_, short := opts[cmds.EncShort]
 	_, long := opts[cmds.EncLong]
diff --git a/commands/request.go b/commands/request.go
index e49eae062..c2c89050c 100644
--- a/commands/request.go
+++ b/commands/request.go
@@ -24,7 +24,7 @@ type Request interface {
 	Option(name string) (interface{}, bool)
 	Options() map[string]interface{}
 	SetOption(name string, val interface{})
-	Arguments() []string
+	Arguments() []interface{} // TODO: make argument value type instead of using interface{}
 	Stream() io.Reader
 	SetStream(io.Reader)
 	Context() *Context
@@ -37,7 +37,7 @@ type Request interface {
 type request struct {
 	path      []string
 	options   optMap
-	arguments []string
+	arguments []interface{}
 	in        io.Reader
 	cmd       *Command
 	ctx       Context
@@ -69,7 +69,7 @@ func (r *request) SetOption(name string, val interface{}) {
 }
 
 // Arguments returns the arguments slice
-func (r *request) Arguments() []string {
+func (r *request) Arguments() []interface{} {
 	return r.arguments
 }
 
@@ -165,7 +165,7 @@ func NewEmptyRequest() Request {
 }
 
 // NewRequest returns a request initialized with given arguments
-func NewRequest(path []string, opts optMap, args []string, in io.Reader, cmd *Command) Request {
+func NewRequest(path []string, opts optMap, args []interface{}, in io.Reader, cmd *Command) Request {
 	if path == nil {
 		path = make([]string, 0)
 	}
@@ -173,7 +173,7 @@ func NewRequest(path []string, opts optMap, args []string, in io.Reader, cmd *Co
 		opts = make(map[string]interface{})
 	}
 	if args == nil {
-		args = make([]string, 0)
+		args = make([]interface{}, 0)
 	}
 	return &request{path, opts, args, in, cmd, Context{}}
 }
-- 
GitLab