Remove reflection on CLI init

before:
```
$ time docker --help
real  0m0.177s
user  0m0.000s
sys 0m0.040s
```

after:
```
$ time docker --help
real  0m0.010s
user  0m0.000s
sys 0m0.000s
```

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
Brian Goff 2016-04-29 11:16:34 -04:00
parent 24a8de2b60
commit 5c8950e84d
3 changed files with 80 additions and 15 deletions

59
api/client/commands.go Normal file
View file

@ -0,0 +1,59 @@
package client
// Command returns a cli command handler if one exists
func (cli *DockerCli) Command(name string) func(...string) error {
return map[string]func(...string) error{
"attach": cli.CmdAttach,
"build": cli.CmdBuild,
"commit": cli.CmdCommit,
"cp": cli.CmdCp,
"create": cli.CmdCreate,
"diff": cli.CmdDiff,
"events": cli.CmdEvents,
"exec": cli.CmdExec,
"export": cli.CmdExport,
"history": cli.CmdHistory,
"images": cli.CmdImages,
"import": cli.CmdImport,
"info": cli.CmdInfo,
"inspect": cli.CmdInspect,
"kill": cli.CmdKill,
"load": cli.CmdLoad,
"login": cli.CmdLogin,
"logout": cli.CmdLogout,
"logs": cli.CmdLogs,
"network": cli.CmdNetwork,
"network create": cli.CmdNetworkCreate,
"network connect": cli.CmdNetworkConnect,
"network disconnect": cli.CmdNetworkDisconnect,
"network inspect": cli.CmdNetworkInspect,
"network ls": cli.CmdNetworkLs,
"network rm": cli.CmdNetworkRm,
"pause": cli.CmdPause,
"port": cli.CmdPort,
"ps": cli.CmdPs,
"pull": cli.CmdPull,
"push": cli.CmdPush,
"rename": cli.CmdRename,
"restart": cli.CmdRestart,
"rm": cli.CmdRm,
"rmi": cli.CmdRmi,
"run": cli.CmdRun,
"save": cli.CmdSave,
"search": cli.CmdSearch,
"start": cli.CmdStart,
"stats": cli.CmdStats,
"stop": cli.CmdStop,
"tag": cli.CmdTag,
"top": cli.CmdTop,
"unpause": cli.CmdUnpause,
"update": cli.CmdUpdate,
"version": cli.CmdVersion,
"volume": cli.CmdVolume,
"volume create": cli.CmdVolumeCreate,
"volume inspect": cli.CmdVolumeInspect,
"volume ls": cli.CmdVolumeLs,
"volume rm": cli.CmdVolumeRm,
"wait": cli.CmdWait,
}[name]
}

View file

@ -5,7 +5,6 @@ import (
"fmt"
"io"
"os"
"reflect"
"strings"
flag "github.com/docker/docker/pkg/mflag"
@ -21,7 +20,9 @@ type Cli struct {
// Handler holds the different commands Cli will call
// It should have methods with names starting with `Cmd` like:
// func (h myHandler) CmdFoo(args ...string) error
type Handler interface{}
type Handler interface {
Command(name string) func(...string) error
}
// Initializer can be optionally implemented by a Handler to
// initialize before each call to one of its commands.
@ -50,22 +51,13 @@ func (cli *Cli) command(args ...string) (func(...string) error, error) {
if c == nil {
continue
}
camelArgs := make([]string, len(args))
for i, s := range args {
if len(s) == 0 {
return nil, errors.New("empty command")
}
camelArgs[i] = strings.ToUpper(s[:1]) + strings.ToLower(s[1:])
}
methodName := "Cmd" + strings.Join(camelArgs, "")
method := reflect.ValueOf(c).MethodByName(methodName)
if method.IsValid() {
if c, ok := c.(Initializer); ok {
if err := c.Initialize(); err != nil {
if cmd := c.Command(strings.Join(args, " ")); cmd != nil {
if ci, ok := c.(Initializer); ok {
if err := ci.Initialize(); err != nil {
return nil, initErr{err}
}
}
return method.Interface().(func(...string) error), nil
return cmd, nil
}
}
return nil, errors.New("command not found")
@ -103,6 +95,13 @@ func (cli *Cli) noSuchCommand(command string) {
os.Exit(1)
}
// Command returns a command handler, or nil if the command does not exist
func (cli *Cli) Command(name string) func(...string) error {
return map[string]func(...string) error{
"help": cli.CmdHelp,
}[name]
}
// CmdHelp displays information on a Docker command.
//
// If more than one command is specified, information is only shown for the first command.

View file

@ -9,3 +9,10 @@ type DaemonProxy struct{}
func NewDaemonProxy() DaemonProxy {
return DaemonProxy{}
}
// Command returns a cli command handler if one exists
func (p DaemonProxy) Command(name string) func(...string) error {
return map[string]func(...string) error{
"daemon": p.CmdDaemon,
}[name]
}