mirror of https://github.com/docker/cli.git
Remove old cli framework.
Also consolidate the leftover packages under cli. Remove pkg/mflag. Make manpage generation work with new cobra layout. Remove remaining mflag and fix tests after rebase with master. Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
parent
fc1a3d79f8
commit
38aca22dcd
191
cli.go
191
cli.go
|
@ -1,191 +0,0 @@
|
||||||
package cli
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
flag "github.com/docker/docker/pkg/mflag"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Cli represents a command line interface.
|
|
||||||
type Cli struct {
|
|
||||||
Stderr io.Writer
|
|
||||||
handlers []Handler
|
|
||||||
Usage func()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 {
|
|
||||||
Command(name string) func(...string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initializer can be optionally implemented by a Handler to
|
|
||||||
// initialize before each call to one of its commands.
|
|
||||||
type Initializer interface {
|
|
||||||
Initialize() error
|
|
||||||
}
|
|
||||||
|
|
||||||
// New instantiates a ready-to-use Cli.
|
|
||||||
func New(handlers ...Handler) *Cli {
|
|
||||||
// make the generic Cli object the first cli handler
|
|
||||||
// in order to handle `docker help` appropriately
|
|
||||||
cli := new(Cli)
|
|
||||||
cli.handlers = append([]Handler{cli}, handlers...)
|
|
||||||
return cli
|
|
||||||
}
|
|
||||||
|
|
||||||
var errCommandNotFound = errors.New("command not found")
|
|
||||||
|
|
||||||
func (cli *Cli) command(args ...string) (func(...string) error, error) {
|
|
||||||
for _, c := range cli.handlers {
|
|
||||||
if c == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if cmd := c.Command(strings.Join(args, " ")); cmd != nil {
|
|
||||||
if ci, ok := c.(Initializer); ok {
|
|
||||||
if err := ci.Initialize(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cmd, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, errCommandNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run executes the specified command.
|
|
||||||
func (cli *Cli) Run(args ...string) error {
|
|
||||||
if len(args) > 1 {
|
|
||||||
command, err := cli.command(args[:2]...)
|
|
||||||
if err == nil {
|
|
||||||
return command(args[2:]...)
|
|
||||||
}
|
|
||||||
if err != errCommandNotFound {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(args) > 0 {
|
|
||||||
command, err := cli.command(args[0])
|
|
||||||
if err != nil {
|
|
||||||
if err == errCommandNotFound {
|
|
||||||
cli.noSuchCommand(args[0])
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return command(args[1:]...)
|
|
||||||
}
|
|
||||||
return cli.CmdHelp()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cli *Cli) noSuchCommand(command string) {
|
|
||||||
if cli.Stderr == nil {
|
|
||||||
cli.Stderr = os.Stderr
|
|
||||||
}
|
|
||||||
fmt.Fprintf(cli.Stderr, "docker: '%s' is not a docker command.\nSee 'docker --help'.\n", command)
|
|
||||||
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.
|
|
||||||
//
|
|
||||||
// Usage: docker help COMMAND or docker COMMAND --help
|
|
||||||
func (cli *Cli) CmdHelp(args ...string) error {
|
|
||||||
if len(args) > 1 {
|
|
||||||
command, err := cli.command(args[:2]...)
|
|
||||||
if err == nil {
|
|
||||||
command("--help")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != errCommandNotFound {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(args) > 0 {
|
|
||||||
command, err := cli.command(args[0])
|
|
||||||
if err != nil {
|
|
||||||
if err == errCommandNotFound {
|
|
||||||
cli.noSuchCommand(args[0])
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
command("--help")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if cli.Usage == nil {
|
|
||||||
flag.Usage()
|
|
||||||
} else {
|
|
||||||
cli.Usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subcmd is a subcommand of the main "docker" command.
|
|
||||||
// A subcommand represents an action that can be performed
|
|
||||||
// from the Docker command line client.
|
|
||||||
//
|
|
||||||
// To see all available subcommands, run "docker --help".
|
|
||||||
func Subcmd(name string, synopses []string, description string, exitOnError bool) *flag.FlagSet {
|
|
||||||
var errorHandling flag.ErrorHandling
|
|
||||||
if exitOnError {
|
|
||||||
errorHandling = flag.ExitOnError
|
|
||||||
} else {
|
|
||||||
errorHandling = flag.ContinueOnError
|
|
||||||
}
|
|
||||||
flags := flag.NewFlagSet(name, errorHandling)
|
|
||||||
flags.Usage = func() {
|
|
||||||
flags.ShortUsage()
|
|
||||||
flags.PrintDefaults()
|
|
||||||
}
|
|
||||||
|
|
||||||
flags.ShortUsage = func() {
|
|
||||||
if len(synopses) == 0 {
|
|
||||||
synopses = []string{""}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow for multiple command usage synopses.
|
|
||||||
for i, synopsis := range synopses {
|
|
||||||
lead := "\t"
|
|
||||||
if i == 0 {
|
|
||||||
// First line needs the word 'Usage'.
|
|
||||||
lead = "Usage:\t"
|
|
||||||
}
|
|
||||||
|
|
||||||
if synopsis != "" {
|
|
||||||
synopsis = " " + synopsis
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(flags.Out(), "\n%sdocker %s%s", lead, name, synopsis)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(flags.Out(), "\n\n%s\n", description)
|
|
||||||
}
|
|
||||||
|
|
||||||
return flags
|
|
||||||
}
|
|
||||||
|
|
||||||
// StatusError reports an unsuccessful exit by a command.
|
|
||||||
type StatusError struct {
|
|
||||||
Status string
|
|
||||||
StatusCode int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e StatusError) Error() string {
|
|
||||||
return fmt.Sprintf("Status: %s, Code: %d", e.Status, e.StatusCode)
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
package cobraadaptor
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -17,12 +17,6 @@ func SetupRootCommand(rootCmd *cobra.Command) {
|
||||||
rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help")
|
rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRootCommand returns the root command. Required to generate the man pages
|
|
||||||
// and reference docs from a script outside this package.
|
|
||||||
func (c CobraAdaptor) GetRootCommand() *cobra.Command {
|
|
||||||
return c.rootCmd
|
|
||||||
}
|
|
||||||
|
|
||||||
// FlagErrorFunc prints an error messages which matches the format of the
|
// FlagErrorFunc prints an error messages which matches the format of the
|
||||||
// docker/docker/cli error messages
|
// docker/docker/cli error messages
|
||||||
func FlagErrorFunc(cmd *cobra.Command, err error) error {
|
func FlagErrorFunc(cmd *cobra.Command, err error) error {
|
15
error.go
15
error.go
|
@ -1,6 +1,9 @@
|
||||||
package cli
|
package cli
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// Errors is a list of errors.
|
// Errors is a list of errors.
|
||||||
// Useful in a loop if you don't want to return the error right away and you want to display after the loop,
|
// Useful in a loop if you don't want to return the error right away and you want to display after the loop,
|
||||||
|
@ -18,3 +21,13 @@ func (errList Errors) Error() string {
|
||||||
}
|
}
|
||||||
return strings.Join(out, ", ")
|
return strings.Join(out, ", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StatusError reports an unsuccessful exit by a command.
|
||||||
|
type StatusError struct {
|
||||||
|
Status string
|
||||||
|
StatusCode int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e StatusError) Error() string {
|
||||||
|
return fmt.Sprintf("Status: %s, Code: %d", e.Status, e.StatusCode)
|
||||||
|
}
|
||||||
|
|
19
usage.go
19
usage.go
|
@ -1,19 +0,0 @@
|
||||||
package cli
|
|
||||||
|
|
||||||
// Command is the struct containing the command name and description
|
|
||||||
type Command struct {
|
|
||||||
Name string
|
|
||||||
Description string
|
|
||||||
}
|
|
||||||
|
|
||||||
// DockerCommandUsage lists the top level docker commands and their short usage
|
|
||||||
var DockerCommandUsage = []Command{}
|
|
||||||
|
|
||||||
// DockerCommands stores all the docker command
|
|
||||||
var DockerCommands = make(map[string]Command)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
for _, cmd := range DockerCommandUsage {
|
|
||||||
DockerCommands[cmd.Name] = cmd
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue