@cryptotaxi247 / kubo / commits / 7673ce6f6

fmt, lint, + vet commands/

Juan Batiz-Benet committed Oct 20, 2014 at 07:31 UTC 7673ce6f65ce84179f4a65f40c6516b335f6eefd
6 files changed +130 -117
commands/cli/parse.go
+52 -50
@@ -1,81 +1,83 @@
1 package cli
2
3 import (
4 - "fmt"
5 - "strings"
4 + "fmt"
5 + "strings"
6
7 - "github.com/jbenet/go-ipfs/commands"
7 + "github.com/jbenet/go-ipfs/commands"
8 )
9
10 +// Parse parses the input commandline string (cmd, flags, and args).
11 +// returns the corresponding command Request object.
12 func Parse(input []string, root *commands.Command) (*commands.Request, error) {
11 - path, input, err := parsePath(input, root)
12 - if err != nil {
13 - return nil, err
14 - }
13 + path, input, err := parsePath(input, root)
14 + if err != nil {
15 + return nil, err
16 + }
17
16 - opts, args, err := parseOptions(input)
17 - if err != nil {
18 - return nil, err
19 - }
18 + opts, args, err := parseOptions(input)
19 + if err != nil {
20 + return nil, err
21 + }
22
21 - return commands.NewRequest(path, opts, args), nil
23 + return commands.NewRequest(path, opts, args), nil
24 }
25
26 // parsePath gets the command path from the command line input
27 func parsePath(input []string, root *commands.Command) ([]string, []string, error) {
26 - cmd := root
27 - i := 0
28 + cmd := root
29 + i := 0
30
29 - for _, blob := range input {
30 - if strings.HasPrefix(blob, "-") {
31 - break
32 - }
31 + for _, blob := range input {
32 + if strings.HasPrefix(blob, "-") {
33 + break
34 + }
35
34 - cmd := cmd.Sub(blob)
35 - if cmd == nil {
36 - break
37 - }
36 + cmd := cmd.Sub(blob)
37 + if cmd == nil {
38 + break
39 + }
40
39 - i++
40 - }
41 + i++
42 + }
43
42 - return input[:i], input[i:], nil
44 + return input[:i], input[i:], nil
45 }
46
47 // parseOptions parses the raw string values of the given options
48 // returns the parsed options as strings, along with the CLI args
49 func parseOptions(input []string) (map[string]interface{}, []string, error) {
48 - opts := make(map[string]interface{})
49 - args := make([]string, 0)
50 + opts := make(map[string]interface{})
51 + args := []string{}
52
51 - for i := 0; i < len(input); i++ {
52 - blob := input[i]
53 + for i := 0; i < len(input); i++ {
54 + blob := input[i]
55
54 - if strings.HasPrefix(blob, "-") {
55 - name := blob[1:]
56 - value := ""
56 + if strings.HasPrefix(blob, "-") {
57 + name := blob[1:]
58 + value := ""
59
58 - // support single and double dash
59 - if strings.HasPrefix(name, "-") {
60 - name = name[1:]
61 - }
60 + // support single and double dash
61 + if strings.HasPrefix(name, "-") {
62 + name = name[1:]
63 + }
64
63 - if strings.Contains(name, "=") {
64 - split := strings.SplitN(name, "=", 2)
65 - name = split[0]
66 - value = split[1]
67 - }
65 + if strings.Contains(name, "=") {
66 + split := strings.SplitN(name, "=", 2)
67 + name = split[0]
68 + value = split[1]
69 + }
70
69 - if _, ok := opts[name]; ok {
70 - return nil, nil, fmt.Errorf("Duplicate values for option '%s'", name)
71 - }
71 + if _, ok := opts[name]; ok {
72 + return nil, nil, fmt.Errorf("Duplicate values for option '%s'", name)
73 + }
74
73 - opts[name] = value
75 + opts[name] = value
76
75 - } else {
76 - args = append(args, blob)
77 - }
78 - }
77 + } else {
78 + args = append(args, blob)
79 + }
80 + }
81
80 - return opts, args, nil
82 + return opts, args, nil
83 }
commands/cli/parse_test.go
+37 -37
@@ -1,48 +1,48 @@
1 package cli
2
3 import (
4 - //"fmt"
5 - "testing"
4 + //"fmt"
5 + "testing"
6
7 - "github.com/jbenet/go-ipfs/commands"
7 + "github.com/jbenet/go-ipfs/commands"
8 )
9
10 func TestOptionParsing(t *testing.T) {
11 - cmd := &commands.Command{
12 - Options: []commands.Option{
13 - commands.Option{ []string{"b"}, commands.String },
14 - },
15 - }
16 - cmd.Register("test", &commands.Command{})
11 + cmd := &commands.Command{
12 + Options: []commands.Option{
13 + commands.Option{Names: []string{"b"}, Type: commands.String},
14 + },
15 + }
16 + cmd.Register("test", &commands.Command{})
17
18 - opts, input, err := parseOptions([]string{ "--beep", "-boop=lol", "test2", "-c", "beep", "--foo=5" })
19 - /*for k, v := range opts {
20 - fmt.Printf("%s: %s\n", k, v)
21 - }
22 - fmt.Printf("%s\n", input)*/
23 - if err != nil {
24 - t.Error("Should have passed")
25 - }
26 - if len(opts) != 4 || opts["beep"] != "" || opts["boop"] != "lol" || opts["c"] != "" || opts["foo"] != "5" {
27 - t.Error("Returned options were defferent than expected: %v", opts)
28 - }
29 - if len(input) != 2 || input[0] != "test2" || input[1] != "beep" {
30 - t.Error("Returned input was different than expected: %v", input)
31 - }
18 + opts, input, err := parseOptions([]string{"--beep", "-boop=lol", "test2", "-c", "beep", "--foo=5"})
19 + /*for k, v := range opts {
20 + fmt.Printf("%s: %s\n", k, v)
21 + }
22 + fmt.Printf("%s\n", input)*/
23 + if err != nil {
24 + t.Error("Should have passed")
25 + }
26 + if len(opts) != 4 || opts["beep"] != "" || opts["boop"] != "lol" || opts["c"] != "" || opts["foo"] != "5" {
27 + t.Error("Returned options were defferent than expected: %v", opts)
28 + }
29 + if len(input) != 2 || input[0] != "test2" || input[1] != "beep" {
30 + t.Error("Returned input was different than expected: %v", input)
31 + }
32
33 - _, _, err = parseOptions([]string{ "-beep=1", "-boop=2", "-beep=3" })
34 - if err == nil {
35 - t.Error("Should have failed (duplicate option name)")
36 - }
33 + _, _, err = parseOptions([]string{"-beep=1", "-boop=2", "-beep=3"})
34 + if err == nil {
35 + t.Error("Should have failed (duplicate option name)")
36 + }
37
38 - path, args, err := parsePath([]string{ "test", "beep", "boop" }, cmd)
39 - if err != nil {
40 - t.Error("Should have passed")
41 - }
42 - if len(path) != 1 || path[0] != "test" {
43 - t.Error("Returned path was defferent than expected: %v", path)
44 - }
45 - if len(args) != 2 || args[0] != "beep" || args[1] != "boop" {
46 - t.Error("Returned args were different than expected: %v", args)
47 - }
38 + path, args, err := parsePath([]string{"test", "beep", "boop"}, cmd)
39 + if err != nil {
40 + t.Error("Should have passed")
41 + }
42 + if len(path) != 1 || path[0] != "test" {
43 + t.Error("Returned path was defferent than expected: %v", path)
44 + }
45 + if len(args) != 2 || args[0] != "beep" || args[1] != "boop" {
46 + t.Error("Returned args were different than expected: %v", args)
47 + }
48 }
commands/command.go
+8 -5
@@ -6,6 +6,7 @@ import (
6 "strings"
7 )
8
9 +// Command is an object that defines a command.
10 type Command struct {
11 Help string
12 Options []Option
@@ -13,7 +14,8 @@ type Command struct {
14 subcommands map[string]*Command
15 }
16
16 -var NotCallableError = errors.New("This command can't be called directly. Try one of its subcommands.")
17 +// ErrNotCallable signals a command that cannot be called.
18 +var ErrNotCallable = errors.New("This command can't be called directly. Try one of its subcommands.")
19
20 // Register adds a subcommand
21 func (c *Command) Register(id string, sub *Command) error {
@@ -44,25 +46,25 @@ func (c *Command) Call(req *Request) *Response {
46
47 cmds, err := c.Resolve(req.path)
48 if err != nil {
47 - res.SetError(err, Client)
49 + res.SetError(err, ErrClient)
50 return res
51 }
52 cmd := cmds[len(cmds)-1]
53
54 if cmd.f == nil {
53 - res.SetError(NotCallableError, Client)
55 + res.SetError(ErrNotCallable, ErrClient)
56 return res
57 }
58
59 options, err := c.GetOptions(req.path)
60 if err != nil {
59 - res.SetError(err, Client)
61 + res.SetError(err, ErrClient)
62 return res
63 }
64
65 err = req.convertOptions(options)
66 if err != nil {
65 - res.SetError(err, Client)
67 + res.SetError(err, ErrClient)
68 return res
69 }
70
@@ -91,6 +93,7 @@ func (c *Command) Resolve(path []string) ([]*Command, error) {
93 return cmds, nil
94 }
95
96 +// Get resolves and returns the Command addressed by path
97 func (c *Command) Get(path []string) (*Command, error) {
98 cmds, err := c.Resolve(path)
99 if err != nil {
commands/option.go
+3 -2
@@ -2,6 +2,7 @@ package commands
2
3 import "reflect"
4
5 +// Types of Command options
6 const (
7 Invalid = reflect.Invalid
8 Bool = reflect.Bool
@@ -22,11 +23,11 @@ type Option struct {
23 }
24
25 // options that are used by this package
25 -var globalOptions []Option = []Option{
26 +var globalOptions = []Option{
27 Option{[]string{"enc", "encoding"}, String},
28 }
29
30 // the above array of Options, wrapped in a Command
30 -var globalCommand *Command = &Command{
31 +var globalCommand = &Command{
32 Options: globalOptions,
33 }
commands/response.go
+28 -21
@@ -7,11 +7,13 @@ import (
7 "strings"
8 )
9
10 +// ErrorType signfies a category of errors
11 type ErrorType uint
12
13 +// ErrorTypes convey what category of error ocurred
14 const (
13 - Normal ErrorType = iota // general errors
14 - Client // error was caused by the client, (e.g. invalid CLI usage)
15 + ErrNormal ErrorType = iota // general errors
16 + ErrClient // error was caused by the client, (e.g. invalid CLI usage)
17 // TODO: add more types of errors for better error-specific handling
18 )
19
@@ -21,37 +23,44 @@ type Error struct {
23 Code ErrorType
24 }
25
26 +func (e *Error) Error() string {
27 + return fmt.Sprintf("%d error: %s", e.Code, e.Message)
28 +}
29 +
30 +// EncodingType defines a supported encoding
31 type EncodingType string
32
33 +// Supported EncodingType constants.
34 const (
27 - Json = "json"
28 - Xml = "xml"
35 + JSON = "json"
36 + XML = "xml"
37 // TODO: support more encoding types
38 )
39
40 +// Marshaller is a function used by coding types.
41 +// TODO this should just be a `coding.Codec`
42 type Marshaller func(v interface{}) ([]byte, error)
43
44 var marshallers = map[EncodingType]Marshaller{
35 - Json: json.Marshal,
36 - Xml: xml.Marshal,
45 + JSON: json.Marshal,
46 + XML: xml.Marshal,
47 }
48
49 +// Response is the result of a command request. Handlers write to the response,
50 +// setting Error or Value. Response is returned to the client.
51 type Response struct {
40 - req *Request
41 - Error error
42 - ErrorType ErrorType
43 - Value interface{}
44 -}
45 -
46 -func (r *Response) SetError(err error, errType ErrorType) {
47 - r.Error = err
48 - r.ErrorType = errType
52 + req *Request
53 + Error *Error
54 + Value interface{}
55 }
56
51 -func (r *Response) FormatError() Error {
52 - return Error{r.Error.Error(), r.ErrorType}
57 +// SetError updates the response Error.
58 +func (r *Response) SetError(err error, code ErrorType) {
59 + r.Error = &Error{Message: err.Error(), Code: code}
60 }
61
62 +// Marshal marshals out the response into a buffer. It uses the EncodingType
63 +// on the Request to chose a Marshaller (Codec).
64 func (r *Response) Marshal() ([]byte, error) {
65 if r.Error == nil && r.Value == nil {
66 return nil, fmt.Errorf("No error or value set, there is nothing to marshal")
@@ -69,9 +78,7 @@ func (r *Response) Marshal() ([]byte, error) {
78 }
79
80 if r.Error != nil {
72 - err := r.FormatError()
73 - return marshaller(err)
74 - } else {
75 - return marshaller(r.Value)
81 + return marshaller(r.Error)
82 }
83 + return marshaller(r.Value)
84 }
commands/response_test.go
+2 -2
@@ -30,7 +30,7 @@ func TestMarshalling(t *testing.T) {
30 t.Error("Should have failed (no encoding type specified in request)")
31 }
32
33 - req.SetOption("enc", Json)
33 + req.SetOption("enc", JSON)
34 req.convertOptions(options)
35
36 bytes, err := res.Marshal()
@@ -42,7 +42,7 @@ func TestMarshalling(t *testing.T) {
42 t.Error("Incorrect JSON output")
43 }
44
45 - res.SetError(fmt.Errorf("You broke something!"), Client)
45 + res.SetError(fmt.Errorf("You broke something!"), ErrClient)
46 bytes, err = res.Marshal()
47 if err != nil {
48 t.Error("Should have passed")