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>
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,71 @@ |
| 0 |
+package command |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/docker/docker/api/client" |
|
| 4 |
+ "github.com/docker/docker/api/client/container" |
|
| 5 |
+ "github.com/docker/docker/api/client/image" |
|
| 6 |
+ "github.com/docker/docker/api/client/network" |
|
| 7 |
+ "github.com/docker/docker/api/client/node" |
|
| 8 |
+ "github.com/docker/docker/api/client/plugin" |
|
| 9 |
+ "github.com/docker/docker/api/client/registry" |
|
| 10 |
+ "github.com/docker/docker/api/client/service" |
|
| 11 |
+ "github.com/docker/docker/api/client/stack" |
|
| 12 |
+ "github.com/docker/docker/api/client/swarm" |
|
| 13 |
+ "github.com/docker/docker/api/client/system" |
|
| 14 |
+ "github.com/docker/docker/api/client/volume" |
|
| 15 |
+ "github.com/spf13/cobra" |
|
| 16 |
+) |
|
| 17 |
+ |
|
| 18 |
+// AddCommands adds all the commands from api/client to the root command |
|
| 19 |
+func AddCommands(cmd *cobra.Command, dockerCli *client.DockerCli) {
|
|
| 20 |
+ cmd.AddCommand( |
|
| 21 |
+ node.NewNodeCommand(dockerCli), |
|
| 22 |
+ service.NewServiceCommand(dockerCli), |
|
| 23 |
+ stack.NewStackCommand(dockerCli), |
|
| 24 |
+ stack.NewTopLevelDeployCommand(dockerCli), |
|
| 25 |
+ swarm.NewSwarmCommand(dockerCli), |
|
| 26 |
+ container.NewAttachCommand(dockerCli), |
|
| 27 |
+ container.NewCommitCommand(dockerCli), |
|
| 28 |
+ container.NewCopyCommand(dockerCli), |
|
| 29 |
+ container.NewCreateCommand(dockerCli), |
|
| 30 |
+ container.NewDiffCommand(dockerCli), |
|
| 31 |
+ container.NewExecCommand(dockerCli), |
|
| 32 |
+ container.NewExportCommand(dockerCli), |
|
| 33 |
+ container.NewKillCommand(dockerCli), |
|
| 34 |
+ container.NewLogsCommand(dockerCli), |
|
| 35 |
+ container.NewPauseCommand(dockerCli), |
|
| 36 |
+ container.NewPortCommand(dockerCli), |
|
| 37 |
+ container.NewPsCommand(dockerCli), |
|
| 38 |
+ container.NewRenameCommand(dockerCli), |
|
| 39 |
+ container.NewRestartCommand(dockerCli), |
|
| 40 |
+ container.NewRmCommand(dockerCli), |
|
| 41 |
+ container.NewRunCommand(dockerCli), |
|
| 42 |
+ container.NewStartCommand(dockerCli), |
|
| 43 |
+ container.NewStatsCommand(dockerCli), |
|
| 44 |
+ container.NewStopCommand(dockerCli), |
|
| 45 |
+ container.NewTopCommand(dockerCli), |
|
| 46 |
+ container.NewUnpauseCommand(dockerCli), |
|
| 47 |
+ container.NewUpdateCommand(dockerCli), |
|
| 48 |
+ container.NewWaitCommand(dockerCli), |
|
| 49 |
+ image.NewBuildCommand(dockerCli), |
|
| 50 |
+ image.NewHistoryCommand(dockerCli), |
|
| 51 |
+ image.NewImagesCommand(dockerCli), |
|
| 52 |
+ image.NewLoadCommand(dockerCli), |
|
| 53 |
+ image.NewRemoveCommand(dockerCli), |
|
| 54 |
+ image.NewSaveCommand(dockerCli), |
|
| 55 |
+ image.NewPullCommand(dockerCli), |
|
| 56 |
+ image.NewPushCommand(dockerCli), |
|
| 57 |
+ image.NewSearchCommand(dockerCli), |
|
| 58 |
+ image.NewImportCommand(dockerCli), |
|
| 59 |
+ image.NewTagCommand(dockerCli), |
|
| 60 |
+ network.NewNetworkCommand(dockerCli), |
|
| 61 |
+ system.NewEventsCommand(dockerCli), |
|
| 62 |
+ system.NewInspectCommand(dockerCli), |
|
| 63 |
+ registry.NewLoginCommand(dockerCli), |
|
| 64 |
+ registry.NewLogoutCommand(dockerCli), |
|
| 65 |
+ system.NewVersionCommand(dockerCli), |
|
| 66 |
+ volume.NewVolumeCommand(dockerCli), |
|
| 67 |
+ system.NewInfoCommand(dockerCli), |
|
| 68 |
+ ) |
|
| 69 |
+ plugin.NewPluginCommand(cmd, dockerCli) |
|
| 70 |
+} |
| ... | ... |
@@ -14,7 +14,6 @@ import ( |
| 14 | 14 |
"github.com/Sirupsen/logrus" |
| 15 | 15 |
"github.com/docker/docker/api/client" |
| 16 | 16 |
"github.com/docker/docker/cli" |
| 17 |
- "github.com/docker/docker/cli/cobraadaptor" |
|
| 18 | 17 |
opttypes "github.com/docker/docker/opts" |
| 19 | 18 |
"github.com/docker/docker/pkg/promise" |
| 20 | 19 |
"github.com/docker/docker/pkg/signal" |
| ... | ... |
@@ -70,7 +69,7 @@ func NewRunCommand(dockerCli *client.DockerCli) *cobra.Command {
|
| 70 | 70 |
|
| 71 | 71 |
func flagErrorFunc(cmd *cobra.Command, err error) error {
|
| 72 | 72 |
return cli.StatusError{
|
| 73 |
- Status: cobraadaptor.FlagErrorFunc(cmd, err).Error(), |
|
| 73 |
+ Status: cli.FlagErrorFunc(cmd, err).Error(), |
|
| 74 | 74 |
StatusCode: 125, |
| 75 | 75 |
} |
| 76 | 76 |
} |
| 77 | 77 |
deleted file mode 100644 |
| ... | ... |
@@ -1,191 +0,0 @@ |
| 1 |
-package cli |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "errors" |
|
| 5 |
- "fmt" |
|
| 6 |
- "io" |
|
| 7 |
- "os" |
|
| 8 |
- "strings" |
|
| 9 |
- |
|
| 10 |
- flag "github.com/docker/docker/pkg/mflag" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-// Cli represents a command line interface. |
|
| 14 |
-type Cli struct {
|
|
| 15 |
- Stderr io.Writer |
|
| 16 |
- handlers []Handler |
|
| 17 |
- Usage func() |
|
| 18 |
-} |
|
| 19 |
- |
|
| 20 |
-// Handler holds the different commands Cli will call |
|
| 21 |
-// It should have methods with names starting with `Cmd` like: |
|
| 22 |
-// func (h myHandler) CmdFoo(args ...string) error |
|
| 23 |
-type Handler interface {
|
|
| 24 |
- Command(name string) func(...string) error |
|
| 25 |
-} |
|
| 26 |
- |
|
| 27 |
-// Initializer can be optionally implemented by a Handler to |
|
| 28 |
-// initialize before each call to one of its commands. |
|
| 29 |
-type Initializer interface {
|
|
| 30 |
- Initialize() error |
|
| 31 |
-} |
|
| 32 |
- |
|
| 33 |
-// New instantiates a ready-to-use Cli. |
|
| 34 |
-func New(handlers ...Handler) *Cli {
|
|
| 35 |
- // make the generic Cli object the first cli handler |
|
| 36 |
- // in order to handle `docker help` appropriately |
|
| 37 |
- cli := new(Cli) |
|
| 38 |
- cli.handlers = append([]Handler{cli}, handlers...)
|
|
| 39 |
- return cli |
|
| 40 |
-} |
|
| 41 |
- |
|
| 42 |
-var errCommandNotFound = errors.New("command not found")
|
|
| 43 |
- |
|
| 44 |
-func (cli *Cli) command(args ...string) (func(...string) error, error) {
|
|
| 45 |
- for _, c := range cli.handlers {
|
|
| 46 |
- if c == nil {
|
|
| 47 |
- continue |
|
| 48 |
- } |
|
| 49 |
- if cmd := c.Command(strings.Join(args, " ")); cmd != nil {
|
|
| 50 |
- if ci, ok := c.(Initializer); ok {
|
|
| 51 |
- if err := ci.Initialize(); err != nil {
|
|
| 52 |
- return nil, err |
|
| 53 |
- } |
|
| 54 |
- } |
|
| 55 |
- return cmd, nil |
|
| 56 |
- } |
|
| 57 |
- } |
|
| 58 |
- return nil, errCommandNotFound |
|
| 59 |
-} |
|
| 60 |
- |
|
| 61 |
-// Run executes the specified command. |
|
| 62 |
-func (cli *Cli) Run(args ...string) error {
|
|
| 63 |
- if len(args) > 1 {
|
|
| 64 |
- command, err := cli.command(args[:2]...) |
|
| 65 |
- if err == nil {
|
|
| 66 |
- return command(args[2:]...) |
|
| 67 |
- } |
|
| 68 |
- if err != errCommandNotFound {
|
|
| 69 |
- return err |
|
| 70 |
- } |
|
| 71 |
- } |
|
| 72 |
- if len(args) > 0 {
|
|
| 73 |
- command, err := cli.command(args[0]) |
|
| 74 |
- if err != nil {
|
|
| 75 |
- if err == errCommandNotFound {
|
|
| 76 |
- cli.noSuchCommand(args[0]) |
|
| 77 |
- return nil |
|
| 78 |
- } |
|
| 79 |
- return err |
|
| 80 |
- } |
|
| 81 |
- return command(args[1:]...) |
|
| 82 |
- } |
|
| 83 |
- return cli.CmdHelp() |
|
| 84 |
-} |
|
| 85 |
- |
|
| 86 |
-func (cli *Cli) noSuchCommand(command string) {
|
|
| 87 |
- if cli.Stderr == nil {
|
|
| 88 |
- cli.Stderr = os.Stderr |
|
| 89 |
- } |
|
| 90 |
- fmt.Fprintf(cli.Stderr, "docker: '%s' is not a docker command.\nSee 'docker --help'.\n", command) |
|
| 91 |
- os.Exit(1) |
|
| 92 |
-} |
|
| 93 |
- |
|
| 94 |
-// Command returns a command handler, or nil if the command does not exist |
|
| 95 |
-func (cli *Cli) Command(name string) func(...string) error {
|
|
| 96 |
- return map[string]func(...string) error{
|
|
| 97 |
- "help": cli.CmdHelp, |
|
| 98 |
- }[name] |
|
| 99 |
-} |
|
| 100 |
- |
|
| 101 |
-// CmdHelp displays information on a Docker command. |
|
| 102 |
-// |
|
| 103 |
-// If more than one command is specified, information is only shown for the first command. |
|
| 104 |
-// |
|
| 105 |
-// Usage: docker help COMMAND or docker COMMAND --help |
|
| 106 |
-func (cli *Cli) CmdHelp(args ...string) error {
|
|
| 107 |
- if len(args) > 1 {
|
|
| 108 |
- command, err := cli.command(args[:2]...) |
|
| 109 |
- if err == nil {
|
|
| 110 |
- command("--help")
|
|
| 111 |
- return nil |
|
| 112 |
- } |
|
| 113 |
- if err != errCommandNotFound {
|
|
| 114 |
- return err |
|
| 115 |
- } |
|
| 116 |
- } |
|
| 117 |
- if len(args) > 0 {
|
|
| 118 |
- command, err := cli.command(args[0]) |
|
| 119 |
- if err != nil {
|
|
| 120 |
- if err == errCommandNotFound {
|
|
| 121 |
- cli.noSuchCommand(args[0]) |
|
| 122 |
- return nil |
|
| 123 |
- } |
|
| 124 |
- return err |
|
| 125 |
- } |
|
| 126 |
- command("--help")
|
|
| 127 |
- return nil |
|
| 128 |
- } |
|
| 129 |
- |
|
| 130 |
- if cli.Usage == nil {
|
|
| 131 |
- flag.Usage() |
|
| 132 |
- } else {
|
|
| 133 |
- cli.Usage() |
|
| 134 |
- } |
|
| 135 |
- |
|
| 136 |
- return nil |
|
| 137 |
-} |
|
| 138 |
- |
|
| 139 |
-// Subcmd is a subcommand of the main "docker" command. |
|
| 140 |
-// A subcommand represents an action that can be performed |
|
| 141 |
-// from the Docker command line client. |
|
| 142 |
-// |
|
| 143 |
-// To see all available subcommands, run "docker --help". |
|
| 144 |
-func Subcmd(name string, synopses []string, description string, exitOnError bool) *flag.FlagSet {
|
|
| 145 |
- var errorHandling flag.ErrorHandling |
|
| 146 |
- if exitOnError {
|
|
| 147 |
- errorHandling = flag.ExitOnError |
|
| 148 |
- } else {
|
|
| 149 |
- errorHandling = flag.ContinueOnError |
|
| 150 |
- } |
|
| 151 |
- flags := flag.NewFlagSet(name, errorHandling) |
|
| 152 |
- flags.Usage = func() {
|
|
| 153 |
- flags.ShortUsage() |
|
| 154 |
- flags.PrintDefaults() |
|
| 155 |
- } |
|
| 156 |
- |
|
| 157 |
- flags.ShortUsage = func() {
|
|
| 158 |
- if len(synopses) == 0 {
|
|
| 159 |
- synopses = []string{""}
|
|
| 160 |
- } |
|
| 161 |
- |
|
| 162 |
- // Allow for multiple command usage synopses. |
|
| 163 |
- for i, synopsis := range synopses {
|
|
| 164 |
- lead := "\t" |
|
| 165 |
- if i == 0 {
|
|
| 166 |
- // First line needs the word 'Usage'. |
|
| 167 |
- lead = "Usage:\t" |
|
| 168 |
- } |
|
| 169 |
- |
|
| 170 |
- if synopsis != "" {
|
|
| 171 |
- synopsis = " " + synopsis |
|
| 172 |
- } |
|
| 173 |
- |
|
| 174 |
- fmt.Fprintf(flags.Out(), "\n%sdocker %s%s", lead, name, synopsis) |
|
| 175 |
- } |
|
| 176 |
- |
|
| 177 |
- fmt.Fprintf(flags.Out(), "\n\n%s\n", description) |
|
| 178 |
- } |
|
| 179 |
- |
|
| 180 |
- return flags |
|
| 181 |
-} |
|
| 182 |
- |
|
| 183 |
-// StatusError reports an unsuccessful exit by a command. |
|
| 184 |
-type StatusError struct {
|
|
| 185 |
- Status string |
|
| 186 |
- StatusCode int |
|
| 187 |
-} |
|
| 188 |
- |
|
| 189 |
-func (e StatusError) Error() string {
|
|
| 190 |
- return fmt.Sprintf("Status: %s, Code: %d", e.Status, e.StatusCode)
|
|
| 191 |
-} |
| 192 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,54 @@ |
| 0 |
+package cli |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ |
|
| 5 |
+ "github.com/spf13/cobra" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+// SetupRootCommand sets default usage, help, and error handling for the |
|
| 9 |
+// root command. |
|
| 10 |
+func SetupRootCommand(rootCmd *cobra.Command) {
|
|
| 11 |
+ rootCmd.SetUsageTemplate(usageTemplate) |
|
| 12 |
+ rootCmd.SetHelpTemplate(helpTemplate) |
|
| 13 |
+ rootCmd.SetFlagErrorFunc(FlagErrorFunc) |
|
| 14 |
+ |
|
| 15 |
+ rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage")
|
|
| 16 |
+ rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help")
|
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+// FlagErrorFunc prints an error messages which matches the format of the |
|
| 20 |
+// docker/docker/cli error messages |
|
| 21 |
+func FlagErrorFunc(cmd *cobra.Command, err error) error {
|
|
| 22 |
+ if err == nil {
|
|
| 23 |
+ return err |
|
| 24 |
+ } |
|
| 25 |
+ |
|
| 26 |
+ usage := "" |
|
| 27 |
+ if cmd.HasSubCommands() {
|
|
| 28 |
+ usage = "\n\n" + cmd.UsageString() |
|
| 29 |
+ } |
|
| 30 |
+ return fmt.Errorf("%s\nSee '%s --help'.%s", err, cmd.CommandPath(), usage)
|
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+var usageTemplate = `Usage: {{if not .HasSubCommands}}{{.UseLine}}{{end}}{{if .HasSubCommands}}{{ .CommandPath}} COMMAND{{end}}
|
|
| 34 |
+ |
|
| 35 |
+{{ .Short | trim }}{{if gt .Aliases 0}}
|
|
| 36 |
+ |
|
| 37 |
+Aliases: |
|
| 38 |
+ {{.NameAndAliases}}{{end}}{{if .HasExample}}
|
|
| 39 |
+ |
|
| 40 |
+Examples: |
|
| 41 |
+{{ .Example }}{{end}}{{if .HasFlags}}
|
|
| 42 |
+ |
|
| 43 |
+Options: |
|
| 44 |
+{{.Flags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableSubCommands}}
|
|
| 45 |
+ |
|
| 46 |
+Commands:{{range .Commands}}{{if .IsAvailableCommand}}
|
|
| 47 |
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasSubCommands }}
|
|
| 48 |
+ |
|
| 49 |
+Run '{{.CommandPath}} COMMAND --help' for more information on a command.{{end}}
|
|
| 50 |
+` |
|
| 51 |
+ |
|
| 52 |
+var helpTemplate = ` |
|
| 53 |
+{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
|
| 0 | 54 |
deleted file mode 100644 |
| ... | ... |
@@ -1,60 +0,0 @@ |
| 1 |
-package cobraadaptor |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- |
|
| 6 |
- "github.com/spf13/cobra" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-// SetupRootCommand sets default usage, help, and error handling for the |
|
| 10 |
-// root command. |
|
| 11 |
-func SetupRootCommand(rootCmd *cobra.Command) {
|
|
| 12 |
- rootCmd.SetUsageTemplate(usageTemplate) |
|
| 13 |
- rootCmd.SetHelpTemplate(helpTemplate) |
|
| 14 |
- rootCmd.SetFlagErrorFunc(FlagErrorFunc) |
|
| 15 |
- |
|
| 16 |
- rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage")
|
|
| 17 |
- rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help")
|
|
| 18 |
-} |
|
| 19 |
- |
|
| 20 |
-// GetRootCommand returns the root command. Required to generate the man pages |
|
| 21 |
-// and reference docs from a script outside this package. |
|
| 22 |
-func (c CobraAdaptor) GetRootCommand() *cobra.Command {
|
|
| 23 |
- return c.rootCmd |
|
| 24 |
-} |
|
| 25 |
- |
|
| 26 |
-// FlagErrorFunc prints an error messages which matches the format of the |
|
| 27 |
-// docker/docker/cli error messages |
|
| 28 |
-func FlagErrorFunc(cmd *cobra.Command, err error) error {
|
|
| 29 |
- if err == nil {
|
|
| 30 |
- return err |
|
| 31 |
- } |
|
| 32 |
- |
|
| 33 |
- usage := "" |
|
| 34 |
- if cmd.HasSubCommands() {
|
|
| 35 |
- usage = "\n\n" + cmd.UsageString() |
|
| 36 |
- } |
|
| 37 |
- return fmt.Errorf("%s\nSee '%s --help'.%s", err, cmd.CommandPath(), usage)
|
|
| 38 |
-} |
|
| 39 |
- |
|
| 40 |
-var usageTemplate = `Usage: {{if not .HasSubCommands}}{{.UseLine}}{{end}}{{if .HasSubCommands}}{{ .CommandPath}} COMMAND{{end}}
|
|
| 41 |
- |
|
| 42 |
-{{ .Short | trim }}{{if gt .Aliases 0}}
|
|
| 43 |
- |
|
| 44 |
-Aliases: |
|
| 45 |
- {{.NameAndAliases}}{{end}}{{if .HasExample}}
|
|
| 46 |
- |
|
| 47 |
-Examples: |
|
| 48 |
-{{ .Example }}{{end}}{{if .HasFlags}}
|
|
| 49 |
- |
|
| 50 |
-Options: |
|
| 51 |
-{{.Flags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableSubCommands}}
|
|
| 52 |
- |
|
| 53 |
-Commands:{{range .Commands}}{{if .IsAvailableCommand}}
|
|
| 54 |
- {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasSubCommands }}
|
|
| 55 |
- |
|
| 56 |
-Run '{{.CommandPath}} COMMAND --help' for more information on a command.{{end}}
|
|
| 57 |
-` |
|
| 58 |
- |
|
| 59 |
-var helpTemplate = ` |
|
| 60 |
-{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
|
| ... | ... |
@@ -1,6 +1,9 @@ |
| 1 | 1 |
package cli |
| 2 | 2 |
|
| 3 |
-import "strings" |
|
| 3 |
+import ( |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "strings" |
|
| 6 |
+) |
|
| 4 | 7 |
|
| 5 | 8 |
// Errors is a list of errors. |
| 6 | 9 |
// 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 {
|
| 18 | 18 |
} |
| 19 | 19 |
return strings.Join(out, ", ") |
| 20 | 20 |
} |
| 21 |
+ |
|
| 22 |
+// StatusError reports an unsuccessful exit by a command. |
|
| 23 |
+type StatusError struct {
|
|
| 24 |
+ Status string |
|
| 25 |
+ StatusCode int |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+func (e StatusError) Error() string {
|
|
| 29 |
+ return fmt.Sprintf("Status: %s, Code: %d", e.Status, e.StatusCode)
|
|
| 30 |
+} |
| 21 | 31 |
deleted file mode 100644 |
| ... | ... |
@@ -1,19 +0,0 @@ |
| 1 |
-package cli |
|
| 2 |
- |
|
| 3 |
-// Command is the struct containing the command name and description |
|
| 4 |
-type Command struct {
|
|
| 5 |
- Name string |
|
| 6 |
- Description string |
|
| 7 |
-} |
|
| 8 |
- |
|
| 9 |
-// DockerCommandUsage lists the top level docker commands and their short usage |
|
| 10 |
-var DockerCommandUsage = []Command{}
|
|
| 11 |
- |
|
| 12 |
-// DockerCommands stores all the docker command |
|
| 13 |
-var DockerCommands = make(map[string]Command) |
|
| 14 |
- |
|
| 15 |
-func init() {
|
|
| 16 |
- for _, cmd := range DockerCommandUsage {
|
|
| 17 |
- DockerCommands[cmd.Name] = cmd |
|
| 18 |
- } |
|
| 19 |
-} |
| ... | ... |
@@ -6,19 +6,8 @@ import ( |
| 6 | 6 |
|
| 7 | 7 |
"github.com/Sirupsen/logrus" |
| 8 | 8 |
"github.com/docker/docker/api/client" |
| 9 |
- "github.com/docker/docker/api/client/container" |
|
| 10 |
- "github.com/docker/docker/api/client/image" |
|
| 11 |
- "github.com/docker/docker/api/client/network" |
|
| 12 |
- "github.com/docker/docker/api/client/node" |
|
| 13 |
- "github.com/docker/docker/api/client/plugin" |
|
| 14 |
- "github.com/docker/docker/api/client/registry" |
|
| 15 |
- "github.com/docker/docker/api/client/service" |
|
| 16 |
- "github.com/docker/docker/api/client/stack" |
|
| 17 |
- "github.com/docker/docker/api/client/swarm" |
|
| 18 |
- "github.com/docker/docker/api/client/system" |
|
| 19 |
- "github.com/docker/docker/api/client/volume" |
|
| 9 |
+ "github.com/docker/docker/api/client/command" |
|
| 20 | 10 |
"github.com/docker/docker/cli" |
| 21 |
- "github.com/docker/docker/cli/cobraadaptor" |
|
| 22 | 11 |
cliflags "github.com/docker/docker/cli/flags" |
| 23 | 12 |
"github.com/docker/docker/cliconfig" |
| 24 | 13 |
"github.com/docker/docker/dockerversion" |
| ... | ... |
@@ -50,7 +39,7 @@ func newDockerCommand(dockerCli *client.DockerCli) *cobra.Command {
|
| 50 | 50 |
return dockerCli.Initialize(opts) |
| 51 | 51 |
}, |
| 52 | 52 |
} |
| 53 |
- cobraadaptor.SetupRootCommand(cmd) |
|
| 53 |
+ cli.SetupRootCommand(cmd) |
|
| 54 | 54 |
|
| 55 | 55 |
flags := cmd.Flags() |
| 56 | 56 |
flags.BoolVarP(&opts.Version, "version", "v", false, "Print version information and quit") |
| ... | ... |
@@ -58,57 +47,8 @@ func newDockerCommand(dockerCli *client.DockerCli) *cobra.Command {
|
| 58 | 58 |
opts.Common.InstallFlags(flags) |
| 59 | 59 |
|
| 60 | 60 |
cmd.SetOutput(dockerCli.Out()) |
| 61 |
- cmd.AddCommand( |
|
| 62 |
- newDaemonCommand(), |
|
| 63 |
- node.NewNodeCommand(dockerCli), |
|
| 64 |
- service.NewServiceCommand(dockerCli), |
|
| 65 |
- stack.NewStackCommand(dockerCli), |
|
| 66 |
- stack.NewTopLevelDeployCommand(dockerCli), |
|
| 67 |
- swarm.NewSwarmCommand(dockerCli), |
|
| 68 |
- container.NewAttachCommand(dockerCli), |
|
| 69 |
- container.NewCommitCommand(dockerCli), |
|
| 70 |
- container.NewCopyCommand(dockerCli), |
|
| 71 |
- container.NewCreateCommand(dockerCli), |
|
| 72 |
- container.NewDiffCommand(dockerCli), |
|
| 73 |
- container.NewExecCommand(dockerCli), |
|
| 74 |
- container.NewExportCommand(dockerCli), |
|
| 75 |
- container.NewKillCommand(dockerCli), |
|
| 76 |
- container.NewLogsCommand(dockerCli), |
|
| 77 |
- container.NewPauseCommand(dockerCli), |
|
| 78 |
- container.NewPortCommand(dockerCli), |
|
| 79 |
- container.NewPsCommand(dockerCli), |
|
| 80 |
- container.NewRenameCommand(dockerCli), |
|
| 81 |
- container.NewRestartCommand(dockerCli), |
|
| 82 |
- container.NewRmCommand(dockerCli), |
|
| 83 |
- container.NewRunCommand(dockerCli), |
|
| 84 |
- container.NewStartCommand(dockerCli), |
|
| 85 |
- container.NewStatsCommand(dockerCli), |
|
| 86 |
- container.NewStopCommand(dockerCli), |
|
| 87 |
- container.NewTopCommand(dockerCli), |
|
| 88 |
- container.NewUnpauseCommand(dockerCli), |
|
| 89 |
- container.NewUpdateCommand(dockerCli), |
|
| 90 |
- container.NewWaitCommand(dockerCli), |
|
| 91 |
- image.NewBuildCommand(dockerCli), |
|
| 92 |
- image.NewHistoryCommand(dockerCli), |
|
| 93 |
- image.NewImagesCommand(dockerCli), |
|
| 94 |
- image.NewLoadCommand(dockerCli), |
|
| 95 |
- image.NewRemoveCommand(dockerCli), |
|
| 96 |
- image.NewSaveCommand(dockerCli), |
|
| 97 |
- image.NewPullCommand(dockerCli), |
|
| 98 |
- image.NewPushCommand(dockerCli), |
|
| 99 |
- image.NewSearchCommand(dockerCli), |
|
| 100 |
- image.NewImportCommand(dockerCli), |
|
| 101 |
- image.NewTagCommand(dockerCli), |
|
| 102 |
- network.NewNetworkCommand(dockerCli), |
|
| 103 |
- system.NewEventsCommand(dockerCli), |
|
| 104 |
- system.NewInspectCommand(dockerCli), |
|
| 105 |
- registry.NewLoginCommand(dockerCli), |
|
| 106 |
- registry.NewLogoutCommand(dockerCli), |
|
| 107 |
- system.NewVersionCommand(dockerCli), |
|
| 108 |
- volume.NewVolumeCommand(dockerCli), |
|
| 109 |
- system.NewInfoCommand(dockerCli), |
|
| 110 |
- ) |
|
| 111 |
- plugin.NewPluginCommand(cmd, dockerCli) |
|
| 61 |
+ cmd.AddCommand(newDaemonCommand()) |
|
| 62 |
+ command.AddCommands(cmd, dockerCli) |
|
| 112 | 63 |
|
| 113 | 64 |
return cmd |
| 114 | 65 |
} |
| 115 | 66 |
deleted file mode 100644 |
| ... | ... |
@@ -1,22 +0,0 @@ |
| 1 |
-package main |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "sort" |
|
| 5 |
- |
|
| 6 |
- "github.com/docker/docker/cli" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-type byName []cli.Command |
|
| 10 |
- |
|
| 11 |
-func (a byName) Len() int { return len(a) }
|
|
| 12 |
-func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
| 13 |
-func (a byName) Less(i, j int) bool { return a[i].Name < a[j].Name }
|
|
| 14 |
- |
|
| 15 |
-// TODO(tiborvass): do not show 'daemon' on client-only binaries |
|
| 16 |
- |
|
| 17 |
-func sortCommands(commands []cli.Command) []cli.Command {
|
|
| 18 |
- dockerCommands := make([]cli.Command, len(commands)) |
|
| 19 |
- copy(dockerCommands, commands) |
|
| 20 |
- sort.Sort(byName(dockerCommands)) |
|
| 21 |
- return dockerCommands |
|
| 22 |
-} |
| 23 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,15 +0,0 @@ |
| 1 |
-package main |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "sort" |
|
| 5 |
- "testing" |
|
| 6 |
- |
|
| 7 |
- "github.com/docker/docker/cli" |
|
| 8 |
-) |
|
| 9 |
- |
|
| 10 |
-// Tests if the subcommands of docker are sorted |
|
| 11 |
-func TestDockerSubcommandsAreSorted(t *testing.T) {
|
|
| 12 |
- if !sort.IsSorted(byName(cli.DockerCommandUsage)) {
|
|
| 13 |
- t.Fatal("Docker subcommands are not in sorted order")
|
|
| 14 |
- } |
|
| 15 |
-} |
| ... | ... |
@@ -130,7 +130,7 @@ func TestLoadDaemonConfigWithEmbeddedOptions(t *testing.T) {
|
| 130 | 130 |
func TestLoadDaemonConfigWithRegistryOptions(t *testing.T) {
|
| 131 | 131 |
content := `{
|
| 132 | 132 |
"registry-mirrors": ["https://mirrors.docker.com"], |
| 133 |
- "insecure-registries": ["https://insecure.docker.com"], |
|
| 133 |
+ "insecure-registries": ["https://insecure.docker.com"] |
|
| 134 | 134 |
}` |
| 135 | 135 |
tempFile := tempfile.NewTempFile(t, "config", content) |
| 136 | 136 |
defer tempFile.Remove() |
| ... | ... |
@@ -3,8 +3,6 @@ |
| 3 | 3 |
package main |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
- "io/ioutil" |
|
| 7 |
- "os" |
|
| 8 | 6 |
"testing" |
| 9 | 7 |
|
| 10 | 8 |
"github.com/docker/docker/daemon" |
| ... | ... |
@@ -102,30 +100,13 @@ func TestLoadDaemonConfigWithTrueDefaultValuesLeaveDefaults(t *testing.T) {
|
| 102 | 102 |
} |
| 103 | 103 |
|
| 104 | 104 |
func TestLoadDaemonConfigWithLegacyRegistryOptions(t *testing.T) {
|
| 105 |
- c := &daemon.Config{}
|
|
| 106 |
- common := &cliflags.CommonFlags{}
|
|
| 107 |
- flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
|
|
| 108 |
- c.ServiceOptions.InstallCliFlags(flags, absentFromHelp) |
|
| 109 |
- |
|
| 110 |
- f, err := ioutil.TempFile("", "docker-config-")
|
|
| 111 |
- if err != nil {
|
|
| 112 |
- t.Fatal(err) |
|
| 113 |
- } |
|
| 114 |
- configFile := f.Name() |
|
| 115 |
- defer os.Remove(configFile) |
|
| 116 |
- |
|
| 117 |
- f.Write([]byte(`{"disable-legacy-registry": true}`))
|
|
| 118 |
- f.Close() |
|
| 119 |
- |
|
| 120 |
- loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile) |
|
| 121 |
- if err != nil {
|
|
| 122 |
- t.Fatal(err) |
|
| 123 |
- } |
|
| 124 |
- if loadedConfig == nil {
|
|
| 125 |
- t.Fatal("expected configuration, got nil")
|
|
| 126 |
- } |
|
| 105 |
+ content := `{"disable-legacy-registry": true}`
|
|
| 106 |
+ tempFile := tempfile.NewTempFile(t, "config", content) |
|
| 107 |
+ defer tempFile.Remove() |
|
| 127 | 108 |
|
| 128 |
- if !loadedConfig.V2Only {
|
|
| 129 |
- t.Fatal("expected disable-legacy-registry to be true, got false")
|
|
| 130 |
- } |
|
| 109 |
+ opts := defaultOptions(tempFile.Name()) |
|
| 110 |
+ loadedConfig, err := loadDaemonCliConfig(opts) |
|
| 111 |
+ assert.NilError(t, err) |
|
| 112 |
+ assert.NotNil(t, loadedConfig) |
|
| 113 |
+ assert.Equal(t, loadedConfig.V2Only, true) |
|
| 131 | 114 |
} |
| ... | ... |
@@ -5,7 +5,6 @@ import ( |
| 5 | 5 |
|
| 6 | 6 |
"github.com/Sirupsen/logrus" |
| 7 | 7 |
"github.com/docker/docker/cli" |
| 8 |
- "github.com/docker/docker/cli/cobraadaptor" |
|
| 9 | 8 |
cliflags "github.com/docker/docker/cli/flags" |
| 10 | 9 |
"github.com/docker/docker/daemon" |
| 11 | 10 |
"github.com/docker/docker/dockerversion" |
| ... | ... |
@@ -41,7 +40,7 @@ func newDaemonCommand() *cobra.Command {
|
| 41 | 41 |
return runDaemon(opts) |
| 42 | 42 |
}, |
| 43 | 43 |
} |
| 44 |
- cobraadaptor.SetupRootCommand(cmd) |
|
| 44 |
+ cli.SetupRootCommand(cmd) |
|
| 45 | 45 |
|
| 46 | 46 |
flags := cmd.Flags() |
| 47 | 47 |
flags.BoolVarP(&opts.version, "version", "v", false, "Print version information and quit") |
| ... | ... |
@@ -176,7 +176,7 @@ func (config *Config) InstallCommonFlags(flags *pflag.FlagSet) {
|
| 176 | 176 |
flags.IntVar(&maxConcurrentDownloads, "max-concurrent-downloads", defaultMaxConcurrentDownloads, "Set the max concurrent downloads for each pull") |
| 177 | 177 |
flags.IntVar(&maxConcurrentUploads, "max-concurrent-uploads", defaultMaxConcurrentUploads, "Set the max concurrent uploads for each push") |
| 178 | 178 |
|
| 179 |
- cmd.StringVar(&config.SwarmDefaultAdvertiseAddr, []string{"-swarm-default-advertise-addr"}, "", usageFn("Set default address or interface for swarm advertised address"))
|
|
| 179 |
+ flags.StringVar(&config.SwarmDefaultAdvertiseAddr, "swarm-default-advertise-addr", "", "Set default address or interface for swarm advertised address") |
|
| 180 | 180 |
|
| 181 | 181 |
config.MaxConcurrentDownloads = &maxConcurrentDownloads |
| 182 | 182 |
config.MaxConcurrentUploads = &maxConcurrentUploads |
| ... | ... |
@@ -4,8 +4,10 @@ import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"os" |
| 6 | 6 |
|
| 7 |
- "github.com/docker/docker/cli/cobraadaptor" |
|
| 8 |
- cliflags "github.com/docker/docker/cli/flags" |
|
| 7 |
+ "github.com/docker/docker/api/client" |
|
| 8 |
+ "github.com/docker/docker/api/client/command" |
|
| 9 |
+ "github.com/docker/docker/pkg/term" |
|
| 10 |
+ "github.com/spf13/cobra" |
|
| 9 | 11 |
"github.com/spf13/cobra/doc" |
| 10 | 12 |
) |
| 11 | 13 |
|
| ... | ... |
@@ -15,10 +17,12 @@ func generateManPages(path string) error {
|
| 15 | 15 |
Section: "1", |
| 16 | 16 |
Source: "Docker Community", |
| 17 | 17 |
} |
| 18 |
- flags := &cliflags.ClientFlags{
|
|
| 19 |
- Common: cliflags.InitCommonFlags(), |
|
| 20 |
- } |
|
| 21 |
- cmd := cobraadaptor.NewCobraAdaptor(flags).GetRootCommand() |
|
| 18 |
+ |
|
| 19 |
+ stdin, stdout, stderr := term.StdStreams() |
|
| 20 |
+ dockerCli := client.NewDockerCli(stdin, stdout, stderr) |
|
| 21 |
+ cmd := &cobra.Command{Use: "docker"}
|
|
| 22 |
+ command.AddCommands(cmd, dockerCli) |
|
| 23 |
+ |
|
| 22 | 24 |
cmd.DisableAutoGenTag = true |
| 23 | 25 |
return doc.GenManTreeFromOpts(cmd, doc.GenManTreeOptions{
|
| 24 | 26 |
Header: header, |
| 25 | 27 |
deleted file mode 100644 |
| ... | ... |
@@ -1,27 +0,0 @@ |
| 1 |
-Copyright (c) 2014-2016 The Docker & Go Authors. All rights reserved. |
|
| 2 |
- |
|
| 3 |
-Redistribution and use in source and binary forms, with or without |
|
| 4 |
-modification, are permitted provided that the following conditions are |
|
| 5 |
-met: |
|
| 6 |
- |
|
| 7 |
- * Redistributions of source code must retain the above copyright |
|
| 8 |
-notice, this list of conditions and the following disclaimer. |
|
| 9 |
- * Redistributions in binary form must reproduce the above |
|
| 10 |
-copyright notice, this list of conditions and the following disclaimer |
|
| 11 |
-in the documentation and/or other materials provided with the |
|
| 12 |
-distribution. |
|
| 13 |
- * Neither the name of Google Inc. nor the names of its |
|
| 14 |
-contributors may be used to endorse or promote products derived from |
|
| 15 |
-this software without specific prior written permission. |
|
| 16 |
- |
|
| 17 |
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 18 |
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 19 |
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
| 20 |
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
| 21 |
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
| 22 |
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
| 23 |
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 24 |
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 25 |
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 26 |
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 27 |
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,40 +0,0 @@ |
| 1 |
-Package mflag (aka multiple-flag) implements command-line flag parsing. |
|
| 2 |
-It's a **hacky** fork of the [official golang package](http://golang.org/pkg/flag/) |
|
| 3 |
- |
|
| 4 |
-It adds: |
|
| 5 |
- |
|
| 6 |
-* both short and long flag version |
|
| 7 |
-`./example -s red` `./example --string blue` |
|
| 8 |
- |
|
| 9 |
-* multiple names for the same option |
|
| 10 |
-``` |
|
| 11 |
-$>./example -h |
|
| 12 |
-Usage of example: |
|
| 13 |
- -s, --string="": a simple string |
|
| 14 |
-``` |
|
| 15 |
- |
|
| 16 |
-___ |
|
| 17 |
-It is very flexible on purpose, so you can do things like: |
|
| 18 |
-``` |
|
| 19 |
-$>./example -h |
|
| 20 |
-Usage of example: |
|
| 21 |
- -s, -string, --string="": a simple string |
|
| 22 |
-``` |
|
| 23 |
- |
|
| 24 |
-Or: |
|
| 25 |
-``` |
|
| 26 |
-$>./example -h |
|
| 27 |
-Usage of example: |
|
| 28 |
- -oldflag, --newflag="": a simple string |
|
| 29 |
-``` |
|
| 30 |
- |
|
| 31 |
-You can also hide some flags from the usage, so if we want only `--newflag`: |
|
| 32 |
-``` |
|
| 33 |
-$>./example -h |
|
| 34 |
-Usage of example: |
|
| 35 |
- --newflag="": a simple string |
|
| 36 |
-$>./example -oldflag str |
|
| 37 |
-str |
|
| 38 |
-``` |
|
| 39 |
- |
|
| 40 |
-See [example.go](example/example.go) for more details. |
| 41 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,37 +0,0 @@ |
| 1 |
-package main |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- |
|
| 6 |
- flag "github.com/docker/docker/pkg/mflag" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-var ( |
|
| 10 |
- i int |
|
| 11 |
- str string |
|
| 12 |
- b, b2, h bool |
|
| 13 |
-) |
|
| 14 |
- |
|
| 15 |
-func init() {
|
|
| 16 |
- flag.Bool([]string{"#hp", "#-halp"}, false, "display the halp")
|
|
| 17 |
- flag.BoolVar(&b, []string{"b", "#bal", "#bol", "-bal"}, false, "a simple bool")
|
|
| 18 |
- flag.BoolVar(&b, []string{"g", "#gil"}, false, "a simple bool")
|
|
| 19 |
- flag.BoolVar(&b2, []string{"#-bool"}, false, "a simple bool")
|
|
| 20 |
- flag.IntVar(&i, []string{"-integer", "-number"}, -1, "a simple integer")
|
|
| 21 |
- flag.StringVar(&str, []string{"s", "#hidden", "-string"}, "", "a simple string") //-s -hidden and --string will work, but -hidden won't be in the usage
|
|
| 22 |
- flag.BoolVar(&h, []string{"h", "#help", "-help"}, false, "display the help")
|
|
| 23 |
- flag.StringVar(&str, []string{"mode"}, "mode1", "set the mode\nmode1: use the mode1\nmode2: use the mode2\nmode3: use the mode3")
|
|
| 24 |
- flag.Parse() |
|
| 25 |
-} |
|
| 26 |
-func main() {
|
|
| 27 |
- if h {
|
|
| 28 |
- flag.PrintDefaults() |
|
| 29 |
- } else {
|
|
| 30 |
- fmt.Printf("s/#hidden/-string: %s\n", str)
|
|
| 31 |
- fmt.Printf("b: %t\n", b)
|
|
| 32 |
- fmt.Printf("-bool: %t\n", b2)
|
|
| 33 |
- fmt.Printf("-integer/-number: %d\n", i)
|
|
| 34 |
- fmt.Printf("s/#hidden/-string(via lookup): %s\n", flag.Lookup("s").Value.String())
|
|
| 35 |
- fmt.Printf("ARGS: %v\n", flag.Args())
|
|
| 36 |
- } |
|
| 37 |
-} |
| 38 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,1280 +0,0 @@ |
| 1 |
-// Copyright 2014-2016 The Docker & Go Authors. All rights reserved. |
|
| 2 |
-// Use of this source code is governed by a BSD-style |
|
| 3 |
-// license that can be found in the LICENSE file. |
|
| 4 |
- |
|
| 5 |
-// Package mflag implements command-line flag parsing. |
|
| 6 |
-// |
|
| 7 |
-// Usage: |
|
| 8 |
-// |
|
| 9 |
-// Define flags using flag.String(), Bool(), Int(), etc. |
|
| 10 |
-// |
|
| 11 |
-// This declares an integer flag, -f or --flagname, stored in the pointer ip, with type *int. |
|
| 12 |
-// import flag "github.com/docker/docker/pkg/mflag" |
|
| 13 |
-// var ip = flag.Int([]string{"f", "-flagname"}, 1234, "help message for flagname")
|
|
| 14 |
-// If you like, you can bind the flag to a variable using the Var() functions. |
|
| 15 |
-// var flagvar int |
|
| 16 |
-// func init() {
|
|
| 17 |
-// // -flaghidden will work, but will be hidden from the usage |
|
| 18 |
-// flag.IntVar(&flagvar, []string{"f", "#flaghidden", "-flagname"}, 1234, "help message for flagname")
|
|
| 19 |
-// } |
|
| 20 |
-// Or you can create custom flags that satisfy the Value interface (with |
|
| 21 |
-// pointer receivers) and couple them to flag parsing by |
|
| 22 |
-// flag.Var(&flagVal, []string{"name"}, "help message for flagname")
|
|
| 23 |
-// For such flags, the default value is just the initial value of the variable. |
|
| 24 |
-// |
|
| 25 |
-// You can also add "deprecated" flags, they are still usable, but are not shown |
|
| 26 |
-// in the usage and will display a warning when you try to use them. `#` before |
|
| 27 |
-// an option means this option is deprecated, if there is a following option |
|
| 28 |
-// without `#` ahead, then that's the replacement, if not, it will just be removed: |
|
| 29 |
-// var ip = flag.Int([]string{"#f", "#flagname", "-flagname"}, 1234, "help message for flagname")
|
|
| 30 |
-// this will display: `Warning: '-f' is deprecated, it will be replaced by '--flagname' soon. See usage.` or |
|
| 31 |
-// this will display: `Warning: '-flagname' is deprecated, it will be replaced by '--flagname' soon. See usage.` |
|
| 32 |
-// var ip = flag.Int([]string{"f", "#flagname"}, 1234, "help message for flagname")
|
|
| 33 |
-// will display: `Warning: '-flagname' is deprecated, it will be removed soon. See usage.` |
|
| 34 |
-// so you can only use `-f`. |
|
| 35 |
-// |
|
| 36 |
-// You can also group one letter flags, if you declare |
|
| 37 |
-// var v = flag.Bool([]string{"v", "-verbose"}, false, "help message for verbose")
|
|
| 38 |
-// var s = flag.Bool([]string{"s", "-slow"}, false, "help message for slow")
|
|
| 39 |
-// you will be able to use the -vs or -sv |
|
| 40 |
-// |
|
| 41 |
-// After all flags are defined, call |
|
| 42 |
-// flag.Parse() |
|
| 43 |
-// to parse the command line into the defined flags. |
|
| 44 |
-// |
|
| 45 |
-// Flags may then be used directly. If you're using the flags themselves, |
|
| 46 |
-// they are all pointers; if you bind to variables, they're values. |
|
| 47 |
-// fmt.Println("ip has value ", *ip)
|
|
| 48 |
-// fmt.Println("flagvar has value ", flagvar)
|
|
| 49 |
-// |
|
| 50 |
-// After parsing, the arguments after the flag are available as the |
|
| 51 |
-// slice flag.Args() or individually as flag.Arg(i). |
|
| 52 |
-// The arguments are indexed from 0 through flag.NArg()-1. |
|
| 53 |
-// |
|
| 54 |
-// Command line flag syntax: |
|
| 55 |
-// -flag |
|
| 56 |
-// -flag=x |
|
| 57 |
-// -flag="x" |
|
| 58 |
-// -flag='x' |
|
| 59 |
-// -flag x // non-boolean flags only |
|
| 60 |
-// One or two minus signs may be used; they are equivalent. |
|
| 61 |
-// The last form is not permitted for boolean flags because the |
|
| 62 |
-// meaning of the command |
|
| 63 |
-// cmd -x * |
|
| 64 |
-// will change if there is a file called 0, false, etc. You must |
|
| 65 |
-// use the -flag=false form to turn off a boolean flag. |
|
| 66 |
-// |
|
| 67 |
-// Flag parsing stops just before the first non-flag argument |
|
| 68 |
-// ("-" is a non-flag argument) or after the terminator "--".
|
|
| 69 |
-// |
|
| 70 |
-// Integer flags accept 1234, 0664, 0x1234 and may be negative. |
|
| 71 |
-// Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False. |
|
| 72 |
-// Duration flags accept any input valid for time.ParseDuration. |
|
| 73 |
-// |
|
| 74 |
-// The default set of command-line flags is controlled by |
|
| 75 |
-// top-level functions. The FlagSet type allows one to define |
|
| 76 |
-// independent sets of flags, such as to implement subcommands |
|
| 77 |
-// in a command-line interface. The methods of FlagSet are |
|
| 78 |
-// analogous to the top-level functions for the command-line |
|
| 79 |
-// flag set. |
|
| 80 |
- |
|
| 81 |
-package mflag |
|
| 82 |
- |
|
| 83 |
-import ( |
|
| 84 |
- "errors" |
|
| 85 |
- "fmt" |
|
| 86 |
- "io" |
|
| 87 |
- "os" |
|
| 88 |
- "runtime" |
|
| 89 |
- "sort" |
|
| 90 |
- "strconv" |
|
| 91 |
- "strings" |
|
| 92 |
- "text/tabwriter" |
|
| 93 |
- "time" |
|
| 94 |
- |
|
| 95 |
- "github.com/docker/docker/pkg/homedir" |
|
| 96 |
-) |
|
| 97 |
- |
|
| 98 |
-// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined. |
|
| 99 |
-var ErrHelp = errors.New("flag: help requested")
|
|
| 100 |
- |
|
| 101 |
-// ErrRetry is the error returned if you need to try letter by letter |
|
| 102 |
-var ErrRetry = errors.New("flag: retry")
|
|
| 103 |
- |
|
| 104 |
-// -- bool Value |
|
| 105 |
-type boolValue bool |
|
| 106 |
- |
|
| 107 |
-func newBoolValue(val bool, p *bool) *boolValue {
|
|
| 108 |
- *p = val |
|
| 109 |
- return (*boolValue)(p) |
|
| 110 |
-} |
|
| 111 |
- |
|
| 112 |
-func (b *boolValue) Set(s string) error {
|
|
| 113 |
- v, err := strconv.ParseBool(s) |
|
| 114 |
- *b = boolValue(v) |
|
| 115 |
- return err |
|
| 116 |
-} |
|
| 117 |
- |
|
| 118 |
-func (b *boolValue) Get() interface{} { return bool(*b) }
|
|
| 119 |
- |
|
| 120 |
-func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }
|
|
| 121 |
- |
|
| 122 |
-func (b *boolValue) IsBoolFlag() bool { return true }
|
|
| 123 |
- |
|
| 124 |
-// optional interface to indicate boolean flags that can be |
|
| 125 |
-// supplied without "=value" text |
|
| 126 |
-type boolFlag interface {
|
|
| 127 |
- Value |
|
| 128 |
- IsBoolFlag() bool |
|
| 129 |
-} |
|
| 130 |
- |
|
| 131 |
-// -- int Value |
|
| 132 |
-type intValue int |
|
| 133 |
- |
|
| 134 |
-func newIntValue(val int, p *int) *intValue {
|
|
| 135 |
- *p = val |
|
| 136 |
- return (*intValue)(p) |
|
| 137 |
-} |
|
| 138 |
- |
|
| 139 |
-func (i *intValue) Set(s string) error {
|
|
| 140 |
- v, err := strconv.ParseInt(s, 0, 64) |
|
| 141 |
- *i = intValue(v) |
|
| 142 |
- return err |
|
| 143 |
-} |
|
| 144 |
- |
|
| 145 |
-func (i *intValue) Get() interface{} { return int(*i) }
|
|
| 146 |
- |
|
| 147 |
-func (i *intValue) String() string { return fmt.Sprintf("%v", *i) }
|
|
| 148 |
- |
|
| 149 |
-// -- int64 Value |
|
| 150 |
-type int64Value int64 |
|
| 151 |
- |
|
| 152 |
-func newInt64Value(val int64, p *int64) *int64Value {
|
|
| 153 |
- *p = val |
|
| 154 |
- return (*int64Value)(p) |
|
| 155 |
-} |
|
| 156 |
- |
|
| 157 |
-func (i *int64Value) Set(s string) error {
|
|
| 158 |
- v, err := strconv.ParseInt(s, 0, 64) |
|
| 159 |
- *i = int64Value(v) |
|
| 160 |
- return err |
|
| 161 |
-} |
|
| 162 |
- |
|
| 163 |
-func (i *int64Value) Get() interface{} { return int64(*i) }
|
|
| 164 |
- |
|
| 165 |
-func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) }
|
|
| 166 |
- |
|
| 167 |
-// -- uint Value |
|
| 168 |
-type uintValue uint |
|
| 169 |
- |
|
| 170 |
-func newUintValue(val uint, p *uint) *uintValue {
|
|
| 171 |
- *p = val |
|
| 172 |
- return (*uintValue)(p) |
|
| 173 |
-} |
|
| 174 |
- |
|
| 175 |
-func (i *uintValue) Set(s string) error {
|
|
| 176 |
- v, err := strconv.ParseUint(s, 0, 64) |
|
| 177 |
- *i = uintValue(v) |
|
| 178 |
- return err |
|
| 179 |
-} |
|
| 180 |
- |
|
| 181 |
-func (i *uintValue) Get() interface{} { return uint(*i) }
|
|
| 182 |
- |
|
| 183 |
-func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) }
|
|
| 184 |
- |
|
| 185 |
-// -- uint64 Value |
|
| 186 |
-type uint64Value uint64 |
|
| 187 |
- |
|
| 188 |
-func newUint64Value(val uint64, p *uint64) *uint64Value {
|
|
| 189 |
- *p = val |
|
| 190 |
- return (*uint64Value)(p) |
|
| 191 |
-} |
|
| 192 |
- |
|
| 193 |
-func (i *uint64Value) Set(s string) error {
|
|
| 194 |
- v, err := strconv.ParseUint(s, 0, 64) |
|
| 195 |
- *i = uint64Value(v) |
|
| 196 |
- return err |
|
| 197 |
-} |
|
| 198 |
- |
|
| 199 |
-func (i *uint64Value) Get() interface{} { return uint64(*i) }
|
|
| 200 |
- |
|
| 201 |
-func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) }
|
|
| 202 |
- |
|
| 203 |
-// -- uint16 Value |
|
| 204 |
-type uint16Value uint16 |
|
| 205 |
- |
|
| 206 |
-func newUint16Value(val uint16, p *uint16) *uint16Value {
|
|
| 207 |
- *p = val |
|
| 208 |
- return (*uint16Value)(p) |
|
| 209 |
-} |
|
| 210 |
- |
|
| 211 |
-func (i *uint16Value) Set(s string) error {
|
|
| 212 |
- v, err := strconv.ParseUint(s, 0, 16) |
|
| 213 |
- *i = uint16Value(v) |
|
| 214 |
- return err |
|
| 215 |
-} |
|
| 216 |
- |
|
| 217 |
-func (i *uint16Value) Get() interface{} { return uint16(*i) }
|
|
| 218 |
- |
|
| 219 |
-func (i *uint16Value) String() string { return fmt.Sprintf("%v", *i) }
|
|
| 220 |
- |
|
| 221 |
-// -- string Value |
|
| 222 |
-type stringValue string |
|
| 223 |
- |
|
| 224 |
-func newStringValue(val string, p *string) *stringValue {
|
|
| 225 |
- *p = val |
|
| 226 |
- return (*stringValue)(p) |
|
| 227 |
-} |
|
| 228 |
- |
|
| 229 |
-func (s *stringValue) Set(val string) error {
|
|
| 230 |
- *s = stringValue(val) |
|
| 231 |
- return nil |
|
| 232 |
-} |
|
| 233 |
- |
|
| 234 |
-func (s *stringValue) Get() interface{} { return string(*s) }
|
|
| 235 |
- |
|
| 236 |
-func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) }
|
|
| 237 |
- |
|
| 238 |
-// -- float64 Value |
|
| 239 |
-type float64Value float64 |
|
| 240 |
- |
|
| 241 |
-func newFloat64Value(val float64, p *float64) *float64Value {
|
|
| 242 |
- *p = val |
|
| 243 |
- return (*float64Value)(p) |
|
| 244 |
-} |
|
| 245 |
- |
|
| 246 |
-func (f *float64Value) Set(s string) error {
|
|
| 247 |
- v, err := strconv.ParseFloat(s, 64) |
|
| 248 |
- *f = float64Value(v) |
|
| 249 |
- return err |
|
| 250 |
-} |
|
| 251 |
- |
|
| 252 |
-func (f *float64Value) Get() interface{} { return float64(*f) }
|
|
| 253 |
- |
|
| 254 |
-func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) }
|
|
| 255 |
- |
|
| 256 |
-// -- time.Duration Value |
|
| 257 |
-type durationValue time.Duration |
|
| 258 |
- |
|
| 259 |
-func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
|
|
| 260 |
- *p = val |
|
| 261 |
- return (*durationValue)(p) |
|
| 262 |
-} |
|
| 263 |
- |
|
| 264 |
-func (d *durationValue) Set(s string) error {
|
|
| 265 |
- v, err := time.ParseDuration(s) |
|
| 266 |
- *d = durationValue(v) |
|
| 267 |
- return err |
|
| 268 |
-} |
|
| 269 |
- |
|
| 270 |
-func (d *durationValue) Get() interface{} { return time.Duration(*d) }
|
|
| 271 |
- |
|
| 272 |
-func (d *durationValue) String() string { return (*time.Duration)(d).String() }
|
|
| 273 |
- |
|
| 274 |
-// Value is the interface to the dynamic value stored in a flag. |
|
| 275 |
-// (The default value is represented as a string.) |
|
| 276 |
-// |
|
| 277 |
-// If a Value has an IsBoolFlag() bool method returning true, |
|
| 278 |
-// the command-line parser makes -name equivalent to -name=true |
|
| 279 |
-// rather than using the next command-line argument. |
|
| 280 |
-type Value interface {
|
|
| 281 |
- String() string |
|
| 282 |
- Set(string) error |
|
| 283 |
-} |
|
| 284 |
- |
|
| 285 |
-// Getter is an interface that allows the contents of a Value to be retrieved. |
|
| 286 |
-// It wraps the Value interface, rather than being part of it, because it |
|
| 287 |
-// appeared after Go 1 and its compatibility rules. All Value types provided |
|
| 288 |
-// by this package satisfy the Getter interface. |
|
| 289 |
-type Getter interface {
|
|
| 290 |
- Value |
|
| 291 |
- Get() interface{}
|
|
| 292 |
-} |
|
| 293 |
- |
|
| 294 |
-// ErrorHandling defines how to handle flag parsing errors. |
|
| 295 |
-type ErrorHandling int |
|
| 296 |
- |
|
| 297 |
-// ErrorHandling strategies available when a flag parsing error occurs |
|
| 298 |
-const ( |
|
| 299 |
- ContinueOnError ErrorHandling = iota |
|
| 300 |
- ExitOnError |
|
| 301 |
- PanicOnError |
|
| 302 |
-) |
|
| 303 |
- |
|
| 304 |
-// A FlagSet represents a set of defined flags. The zero value of a FlagSet |
|
| 305 |
-// has no name and has ContinueOnError error handling. |
|
| 306 |
-type FlagSet struct {
|
|
| 307 |
- // Usage is the function called when an error occurs while parsing flags. |
|
| 308 |
- // The field is a function (not a method) that may be changed to point to |
|
| 309 |
- // a custom error handler. |
|
| 310 |
- Usage func() |
|
| 311 |
- ShortUsage func() |
|
| 312 |
- |
|
| 313 |
- name string |
|
| 314 |
- parsed bool |
|
| 315 |
- actual map[string]*Flag |
|
| 316 |
- formal map[string]*Flag |
|
| 317 |
- args []string // arguments after flags |
|
| 318 |
- errorHandling ErrorHandling |
|
| 319 |
- output io.Writer // nil means stderr; use Out() accessor |
|
| 320 |
- nArgRequirements []nArgRequirement |
|
| 321 |
-} |
|
| 322 |
- |
|
| 323 |
-// A Flag represents the state of a flag. |
|
| 324 |
-type Flag struct {
|
|
| 325 |
- Names []string // name as it appears on command line |
|
| 326 |
- Usage string // help message |
|
| 327 |
- Value Value // value as set |
|
| 328 |
- DefValue string // default value (as text); for usage message |
|
| 329 |
-} |
|
| 330 |
- |
|
| 331 |
-type flagSlice []string |
|
| 332 |
- |
|
| 333 |
-func (p flagSlice) Len() int { return len(p) }
|
|
| 334 |
-func (p flagSlice) Less(i, j int) bool {
|
|
| 335 |
- pi, pj := strings.TrimPrefix(p[i], "-"), strings.TrimPrefix(p[j], "-") |
|
| 336 |
- lpi, lpj := strings.ToLower(pi), strings.ToLower(pj) |
|
| 337 |
- if lpi != lpj {
|
|
| 338 |
- return lpi < lpj |
|
| 339 |
- } |
|
| 340 |
- return pi < pj |
|
| 341 |
-} |
|
| 342 |
-func (p flagSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
|
| 343 |
- |
|
| 344 |
-// sortFlags returns the flags as a slice in lexicographical sorted order. |
|
| 345 |
-func sortFlags(flags map[string]*Flag) []*Flag {
|
|
| 346 |
- var list flagSlice |
|
| 347 |
- |
|
| 348 |
- // The sorted list is based on the first name, when flag map might use the other names. |
|
| 349 |
- nameMap := make(map[string]string) |
|
| 350 |
- |
|
| 351 |
- for n, f := range flags {
|
|
| 352 |
- fName := strings.TrimPrefix(f.Names[0], "#") |
|
| 353 |
- nameMap[fName] = n |
|
| 354 |
- if len(f.Names) == 1 {
|
|
| 355 |
- list = append(list, fName) |
|
| 356 |
- continue |
|
| 357 |
- } |
|
| 358 |
- |
|
| 359 |
- found := false |
|
| 360 |
- for _, name := range list {
|
|
| 361 |
- if name == fName {
|
|
| 362 |
- found = true |
|
| 363 |
- break |
|
| 364 |
- } |
|
| 365 |
- } |
|
| 366 |
- if !found {
|
|
| 367 |
- list = append(list, fName) |
|
| 368 |
- } |
|
| 369 |
- } |
|
| 370 |
- sort.Sort(list) |
|
| 371 |
- result := make([]*Flag, len(list)) |
|
| 372 |
- for i, name := range list {
|
|
| 373 |
- result[i] = flags[nameMap[name]] |
|
| 374 |
- } |
|
| 375 |
- return result |
|
| 376 |
-} |
|
| 377 |
- |
|
| 378 |
-// Name returns the name of the FlagSet. |
|
| 379 |
-func (fs *FlagSet) Name() string {
|
|
| 380 |
- return fs.name |
|
| 381 |
-} |
|
| 382 |
- |
|
| 383 |
-// Out returns the destination for usage and error messages. |
|
| 384 |
-func (fs *FlagSet) Out() io.Writer {
|
|
| 385 |
- if fs.output == nil {
|
|
| 386 |
- return os.Stderr |
|
| 387 |
- } |
|
| 388 |
- return fs.output |
|
| 389 |
-} |
|
| 390 |
- |
|
| 391 |
-// SetOutput sets the destination for usage and error messages. |
|
| 392 |
-// If output is nil, os.Stderr is used. |
|
| 393 |
-func (fs *FlagSet) SetOutput(output io.Writer) {
|
|
| 394 |
- fs.output = output |
|
| 395 |
-} |
|
| 396 |
- |
|
| 397 |
-// VisitAll visits the flags in lexicographical order, calling fn for each. |
|
| 398 |
-// It visits all flags, even those not set. |
|
| 399 |
-func (fs *FlagSet) VisitAll(fn func(*Flag)) {
|
|
| 400 |
- for _, flag := range sortFlags(fs.formal) {
|
|
| 401 |
- fn(flag) |
|
| 402 |
- } |
|
| 403 |
-} |
|
| 404 |
- |
|
| 405 |
-// VisitAll visits the command-line flags in lexicographical order, calling |
|
| 406 |
-// fn for each. It visits all flags, even those not set. |
|
| 407 |
-func VisitAll(fn func(*Flag)) {
|
|
| 408 |
- CommandLine.VisitAll(fn) |
|
| 409 |
-} |
|
| 410 |
- |
|
| 411 |
-// Visit visits the flags in lexicographical order, calling fn for each. |
|
| 412 |
-// It visits only those flags that have been set. |
|
| 413 |
-func (fs *FlagSet) Visit(fn func(*Flag)) {
|
|
| 414 |
- for _, flag := range sortFlags(fs.actual) {
|
|
| 415 |
- fn(flag) |
|
| 416 |
- } |
|
| 417 |
-} |
|
| 418 |
- |
|
| 419 |
-// Visit visits the command-line flags in lexicographical order, calling fn |
|
| 420 |
-// for each. It visits only those flags that have been set. |
|
| 421 |
-func Visit(fn func(*Flag)) {
|
|
| 422 |
- CommandLine.Visit(fn) |
|
| 423 |
-} |
|
| 424 |
- |
|
| 425 |
-// Lookup returns the Flag structure of the named flag, returning nil if none exists. |
|
| 426 |
-func (fs *FlagSet) Lookup(name string) *Flag {
|
|
| 427 |
- return fs.formal[name] |
|
| 428 |
-} |
|
| 429 |
- |
|
| 430 |
-// IsSet indicates whether the specified flag is set in the given FlagSet |
|
| 431 |
-func (fs *FlagSet) IsSet(name string) bool {
|
|
| 432 |
- return fs.actual[name] != nil |
|
| 433 |
-} |
|
| 434 |
- |
|
| 435 |
-// Lookup returns the Flag structure of the named command-line flag, |
|
| 436 |
-// returning nil if none exists. |
|
| 437 |
-func Lookup(name string) *Flag {
|
|
| 438 |
- return CommandLine.formal[name] |
|
| 439 |
-} |
|
| 440 |
- |
|
| 441 |
-// IsSet indicates whether the specified flag was specified at all on the cmd line. |
|
| 442 |
-func IsSet(name string) bool {
|
|
| 443 |
- return CommandLine.IsSet(name) |
|
| 444 |
-} |
|
| 445 |
- |
|
| 446 |
-type nArgRequirementType int |
|
| 447 |
- |
|
| 448 |
-// Indicator used to pass to BadArgs function |
|
| 449 |
-const ( |
|
| 450 |
- Exact nArgRequirementType = iota |
|
| 451 |
- Max |
|
| 452 |
- Min |
|
| 453 |
-) |
|
| 454 |
- |
|
| 455 |
-type nArgRequirement struct {
|
|
| 456 |
- Type nArgRequirementType |
|
| 457 |
- N int |
|
| 458 |
-} |
|
| 459 |
- |
|
| 460 |
-// Require adds a requirement about the number of arguments for the FlagSet. |
|
| 461 |
-// The first parameter can be Exact, Max, or Min to respectively specify the exact, |
|
| 462 |
-// the maximum, or the minimal number of arguments required. |
|
| 463 |
-// The actual check is done in FlagSet.CheckArgs(). |
|
| 464 |
-func (fs *FlagSet) Require(nArgRequirementType nArgRequirementType, nArg int) {
|
|
| 465 |
- fs.nArgRequirements = append(fs.nArgRequirements, nArgRequirement{nArgRequirementType, nArg})
|
|
| 466 |
-} |
|
| 467 |
- |
|
| 468 |
-// CheckArgs uses the requirements set by FlagSet.Require() to validate |
|
| 469 |
-// the number of arguments. If the requirements are not met, |
|
| 470 |
-// an error message string is returned. |
|
| 471 |
-func (fs *FlagSet) CheckArgs() (message string) {
|
|
| 472 |
- for _, req := range fs.nArgRequirements {
|
|
| 473 |
- var arguments string |
|
| 474 |
- if req.N == 1 {
|
|
| 475 |
- arguments = "1 argument" |
|
| 476 |
- } else {
|
|
| 477 |
- arguments = fmt.Sprintf("%d arguments", req.N)
|
|
| 478 |
- } |
|
| 479 |
- |
|
| 480 |
- str := func(kind string) string {
|
|
| 481 |
- return fmt.Sprintf("%q requires %s%s", fs.name, kind, arguments)
|
|
| 482 |
- } |
|
| 483 |
- |
|
| 484 |
- switch req.Type {
|
|
| 485 |
- case Exact: |
|
| 486 |
- if fs.NArg() != req.N {
|
|
| 487 |
- return str("")
|
|
| 488 |
- } |
|
| 489 |
- case Max: |
|
| 490 |
- if fs.NArg() > req.N {
|
|
| 491 |
- return str("a maximum of ")
|
|
| 492 |
- } |
|
| 493 |
- case Min: |
|
| 494 |
- if fs.NArg() < req.N {
|
|
| 495 |
- return str("a minimum of ")
|
|
| 496 |
- } |
|
| 497 |
- } |
|
| 498 |
- } |
|
| 499 |
- return "" |
|
| 500 |
-} |
|
| 501 |
- |
|
| 502 |
-// Set sets the value of the named flag. |
|
| 503 |
-func (fs *FlagSet) Set(name, value string) error {
|
|
| 504 |
- flag, ok := fs.formal[name] |
|
| 505 |
- if !ok {
|
|
| 506 |
- return fmt.Errorf("no such flag -%v", name)
|
|
| 507 |
- } |
|
| 508 |
- if err := flag.Value.Set(value); err != nil {
|
|
| 509 |
- return err |
|
| 510 |
- } |
|
| 511 |
- if fs.actual == nil {
|
|
| 512 |
- fs.actual = make(map[string]*Flag) |
|
| 513 |
- } |
|
| 514 |
- fs.actual[name] = flag |
|
| 515 |
- return nil |
|
| 516 |
-} |
|
| 517 |
- |
|
| 518 |
-// Set sets the value of the named command-line flag. |
|
| 519 |
-func Set(name, value string) error {
|
|
| 520 |
- return CommandLine.Set(name, value) |
|
| 521 |
-} |
|
| 522 |
- |
|
| 523 |
-// isZeroValue guesses whether the string represents the zero |
|
| 524 |
-// value for a flag. It is not accurate but in practice works OK. |
|
| 525 |
-func isZeroValue(value string) bool {
|
|
| 526 |
- switch value {
|
|
| 527 |
- case "false": |
|
| 528 |
- return true |
|
| 529 |
- case "": |
|
| 530 |
- return true |
|
| 531 |
- case "0": |
|
| 532 |
- return true |
|
| 533 |
- } |
|
| 534 |
- return false |
|
| 535 |
-} |
|
| 536 |
- |
|
| 537 |
-// PrintDefaults prints, to standard error unless configured |
|
| 538 |
-// otherwise, the default values of all defined flags in the set. |
|
| 539 |
-func (fs *FlagSet) PrintDefaults() {
|
|
| 540 |
- writer := tabwriter.NewWriter(fs.Out(), 20, 1, 3, ' ', 0) |
|
| 541 |
- home := homedir.Get() |
|
| 542 |
- |
|
| 543 |
- // Don't substitute when HOME is / |
|
| 544 |
- if runtime.GOOS != "windows" && home == "/" {
|
|
| 545 |
- home = "" |
|
| 546 |
- } |
|
| 547 |
- |
|
| 548 |
- // Add a blank line between cmd description and list of options |
|
| 549 |
- if fs.FlagCount() > 0 {
|
|
| 550 |
- fmt.Fprintln(writer, "") |
|
| 551 |
- } |
|
| 552 |
- |
|
| 553 |
- fs.VisitAll(func(flag *Flag) {
|
|
| 554 |
- names := []string{}
|
|
| 555 |
- for _, name := range flag.Names {
|
|
| 556 |
- if name[0] != '#' {
|
|
| 557 |
- names = append(names, name) |
|
| 558 |
- } |
|
| 559 |
- } |
|
| 560 |
- if len(names) > 0 && len(flag.Usage) > 0 {
|
|
| 561 |
- val := flag.DefValue |
|
| 562 |
- |
|
| 563 |
- if home != "" && strings.HasPrefix(val, home) {
|
|
| 564 |
- val = homedir.GetShortcutString() + val[len(home):] |
|
| 565 |
- } |
|
| 566 |
- |
|
| 567 |
- if isZeroValue(val) {
|
|
| 568 |
- format := " -%s" |
|
| 569 |
- fmt.Fprintf(writer, format, strings.Join(names, ", -")) |
|
| 570 |
- } else {
|
|
| 571 |
- format := " -%s=%s" |
|
| 572 |
- fmt.Fprintf(writer, format, strings.Join(names, ", -"), val) |
|
| 573 |
- } |
|
| 574 |
- for _, line := range strings.Split(flag.Usage, "\n") {
|
|
| 575 |
- fmt.Fprintln(writer, "\t", line) |
|
| 576 |
- } |
|
| 577 |
- } |
|
| 578 |
- }) |
|
| 579 |
- writer.Flush() |
|
| 580 |
-} |
|
| 581 |
- |
|
| 582 |
-// PrintDefaults prints to standard error the default values of all defined command-line flags. |
|
| 583 |
-func PrintDefaults() {
|
|
| 584 |
- CommandLine.PrintDefaults() |
|
| 585 |
-} |
|
| 586 |
- |
|
| 587 |
-// defaultUsage is the default function to print a usage message. |
|
| 588 |
-func defaultUsage(fs *FlagSet) {
|
|
| 589 |
- if fs.name == "" {
|
|
| 590 |
- fmt.Fprintf(fs.Out(), "Usage:\n") |
|
| 591 |
- } else {
|
|
| 592 |
- fmt.Fprintf(fs.Out(), "Usage of %s:\n", fs.name) |
|
| 593 |
- } |
|
| 594 |
- fs.PrintDefaults() |
|
| 595 |
-} |
|
| 596 |
- |
|
| 597 |
-// NOTE: Usage is not just defaultUsage(CommandLine) |
|
| 598 |
-// because it serves (via godoc flag Usage) as the example |
|
| 599 |
-// for how to write your own usage function. |
|
| 600 |
- |
|
| 601 |
-// Usage prints to standard error a usage message documenting all defined command-line flags. |
|
| 602 |
-// The function is a variable that may be changed to point to a custom function. |
|
| 603 |
-var Usage = func() {
|
|
| 604 |
- fmt.Fprintf(CommandLine.Out(), "Usage of %s:\n", os.Args[0]) |
|
| 605 |
- PrintDefaults() |
|
| 606 |
-} |
|
| 607 |
- |
|
| 608 |
-// ShortUsage prints to standard error a usage message documenting the standard command layout |
|
| 609 |
-// The function is a variable that may be changed to point to a custom function. |
|
| 610 |
-var ShortUsage = func() {
|
|
| 611 |
- fmt.Fprintf(CommandLine.output, "Usage of %s:\n", os.Args[0]) |
|
| 612 |
-} |
|
| 613 |
- |
|
| 614 |
-// FlagCount returns the number of flags that have been defined. |
|
| 615 |
-func (fs *FlagSet) FlagCount() int { return len(sortFlags(fs.formal)) }
|
|
| 616 |
- |
|
| 617 |
-// FlagCountUndeprecated returns the number of undeprecated flags that have been defined. |
|
| 618 |
-func (fs *FlagSet) FlagCountUndeprecated() int {
|
|
| 619 |
- count := 0 |
|
| 620 |
- for _, flag := range sortFlags(fs.formal) {
|
|
| 621 |
- for _, name := range flag.Names {
|
|
| 622 |
- if name[0] != '#' {
|
|
| 623 |
- count++ |
|
| 624 |
- break |
|
| 625 |
- } |
|
| 626 |
- } |
|
| 627 |
- } |
|
| 628 |
- return count |
|
| 629 |
-} |
|
| 630 |
- |
|
| 631 |
-// NFlag returns the number of flags that have been set. |
|
| 632 |
-func (fs *FlagSet) NFlag() int { return len(fs.actual) }
|
|
| 633 |
- |
|
| 634 |
-// NFlag returns the number of command-line flags that have been set. |
|
| 635 |
-func NFlag() int { return len(CommandLine.actual) }
|
|
| 636 |
- |
|
| 637 |
-// Arg returns the i'th argument. Arg(0) is the first remaining argument |
|
| 638 |
-// after flags have been processed. |
|
| 639 |
-func (fs *FlagSet) Arg(i int) string {
|
|
| 640 |
- if i < 0 || i >= len(fs.args) {
|
|
| 641 |
- return "" |
|
| 642 |
- } |
|
| 643 |
- return fs.args[i] |
|
| 644 |
-} |
|
| 645 |
- |
|
| 646 |
-// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument |
|
| 647 |
-// after flags have been processed. |
|
| 648 |
-func Arg(i int) string {
|
|
| 649 |
- return CommandLine.Arg(i) |
|
| 650 |
-} |
|
| 651 |
- |
|
| 652 |
-// NArg is the number of arguments remaining after flags have been processed. |
|
| 653 |
-func (fs *FlagSet) NArg() int { return len(fs.args) }
|
|
| 654 |
- |
|
| 655 |
-// NArg is the number of arguments remaining after flags have been processed. |
|
| 656 |
-func NArg() int { return len(CommandLine.args) }
|
|
| 657 |
- |
|
| 658 |
-// Args returns the non-flag arguments. |
|
| 659 |
-func (fs *FlagSet) Args() []string { return fs.args }
|
|
| 660 |
- |
|
| 661 |
-// Args returns the non-flag command-line arguments. |
|
| 662 |
-func Args() []string { return CommandLine.args }
|
|
| 663 |
- |
|
| 664 |
-// BoolVar defines a bool flag with specified name, default value, and usage string. |
|
| 665 |
-// The argument p points to a bool variable in which to store the value of the flag. |
|
| 666 |
-func (fs *FlagSet) BoolVar(p *bool, names []string, value bool, usage string) {
|
|
| 667 |
- fs.Var(newBoolValue(value, p), names, usage) |
|
| 668 |
-} |
|
| 669 |
- |
|
| 670 |
-// BoolVar defines a bool flag with specified name, default value, and usage string. |
|
| 671 |
-// The argument p points to a bool variable in which to store the value of the flag. |
|
| 672 |
-func BoolVar(p *bool, names []string, value bool, usage string) {
|
|
| 673 |
- CommandLine.Var(newBoolValue(value, p), names, usage) |
|
| 674 |
-} |
|
| 675 |
- |
|
| 676 |
-// Bool defines a bool flag with specified name, default value, and usage string. |
|
| 677 |
-// The return value is the address of a bool variable that stores the value of the flag. |
|
| 678 |
-func (fs *FlagSet) Bool(names []string, value bool, usage string) *bool {
|
|
| 679 |
- p := new(bool) |
|
| 680 |
- fs.BoolVar(p, names, value, usage) |
|
| 681 |
- return p |
|
| 682 |
-} |
|
| 683 |
- |
|
| 684 |
-// Bool defines a bool flag with specified name, default value, and usage string. |
|
| 685 |
-// The return value is the address of a bool variable that stores the value of the flag. |
|
| 686 |
-func Bool(names []string, value bool, usage string) *bool {
|
|
| 687 |
- return CommandLine.Bool(names, value, usage) |
|
| 688 |
-} |
|
| 689 |
- |
|
| 690 |
-// IntVar defines an int flag with specified name, default value, and usage string. |
|
| 691 |
-// The argument p points to an int variable in which to store the value of the flag. |
|
| 692 |
-func (fs *FlagSet) IntVar(p *int, names []string, value int, usage string) {
|
|
| 693 |
- fs.Var(newIntValue(value, p), names, usage) |
|
| 694 |
-} |
|
| 695 |
- |
|
| 696 |
-// IntVar defines an int flag with specified name, default value, and usage string. |
|
| 697 |
-// The argument p points to an int variable in which to store the value of the flag. |
|
| 698 |
-func IntVar(p *int, names []string, value int, usage string) {
|
|
| 699 |
- CommandLine.Var(newIntValue(value, p), names, usage) |
|
| 700 |
-} |
|
| 701 |
- |
|
| 702 |
-// Int defines an int flag with specified name, default value, and usage string. |
|
| 703 |
-// The return value is the address of an int variable that stores the value of the flag. |
|
| 704 |
-func (fs *FlagSet) Int(names []string, value int, usage string) *int {
|
|
| 705 |
- p := new(int) |
|
| 706 |
- fs.IntVar(p, names, value, usage) |
|
| 707 |
- return p |
|
| 708 |
-} |
|
| 709 |
- |
|
| 710 |
-// Int defines an int flag with specified name, default value, and usage string. |
|
| 711 |
-// The return value is the address of an int variable that stores the value of the flag. |
|
| 712 |
-func Int(names []string, value int, usage string) *int {
|
|
| 713 |
- return CommandLine.Int(names, value, usage) |
|
| 714 |
-} |
|
| 715 |
- |
|
| 716 |
-// Int64Var defines an int64 flag with specified name, default value, and usage string. |
|
| 717 |
-// The argument p points to an int64 variable in which to store the value of the flag. |
|
| 718 |
-func (fs *FlagSet) Int64Var(p *int64, names []string, value int64, usage string) {
|
|
| 719 |
- fs.Var(newInt64Value(value, p), names, usage) |
|
| 720 |
-} |
|
| 721 |
- |
|
| 722 |
-// Int64Var defines an int64 flag with specified name, default value, and usage string. |
|
| 723 |
-// The argument p points to an int64 variable in which to store the value of the flag. |
|
| 724 |
-func Int64Var(p *int64, names []string, value int64, usage string) {
|
|
| 725 |
- CommandLine.Var(newInt64Value(value, p), names, usage) |
|
| 726 |
-} |
|
| 727 |
- |
|
| 728 |
-// Int64 defines an int64 flag with specified name, default value, and usage string. |
|
| 729 |
-// The return value is the address of an int64 variable that stores the value of the flag. |
|
| 730 |
-func (fs *FlagSet) Int64(names []string, value int64, usage string) *int64 {
|
|
| 731 |
- p := new(int64) |
|
| 732 |
- fs.Int64Var(p, names, value, usage) |
|
| 733 |
- return p |
|
| 734 |
-} |
|
| 735 |
- |
|
| 736 |
-// Int64 defines an int64 flag with specified name, default value, and usage string. |
|
| 737 |
-// The return value is the address of an int64 variable that stores the value of the flag. |
|
| 738 |
-func Int64(names []string, value int64, usage string) *int64 {
|
|
| 739 |
- return CommandLine.Int64(names, value, usage) |
|
| 740 |
-} |
|
| 741 |
- |
|
| 742 |
-// UintVar defines a uint flag with specified name, default value, and usage string. |
|
| 743 |
-// The argument p points to a uint variable in which to store the value of the flag. |
|
| 744 |
-func (fs *FlagSet) UintVar(p *uint, names []string, value uint, usage string) {
|
|
| 745 |
- fs.Var(newUintValue(value, p), names, usage) |
|
| 746 |
-} |
|
| 747 |
- |
|
| 748 |
-// UintVar defines a uint flag with specified name, default value, and usage string. |
|
| 749 |
-// The argument p points to a uint variable in which to store the value of the flag. |
|
| 750 |
-func UintVar(p *uint, names []string, value uint, usage string) {
|
|
| 751 |
- CommandLine.Var(newUintValue(value, p), names, usage) |
|
| 752 |
-} |
|
| 753 |
- |
|
| 754 |
-// Uint defines a uint flag with specified name, default value, and usage string. |
|
| 755 |
-// The return value is the address of a uint variable that stores the value of the flag. |
|
| 756 |
-func (fs *FlagSet) Uint(names []string, value uint, usage string) *uint {
|
|
| 757 |
- p := new(uint) |
|
| 758 |
- fs.UintVar(p, names, value, usage) |
|
| 759 |
- return p |
|
| 760 |
-} |
|
| 761 |
- |
|
| 762 |
-// Uint defines a uint flag with specified name, default value, and usage string. |
|
| 763 |
-// The return value is the address of a uint variable that stores the value of the flag. |
|
| 764 |
-func Uint(names []string, value uint, usage string) *uint {
|
|
| 765 |
- return CommandLine.Uint(names, value, usage) |
|
| 766 |
-} |
|
| 767 |
- |
|
| 768 |
-// Uint64Var defines a uint64 flag with specified name, default value, and usage string. |
|
| 769 |
-// The argument p points to a uint64 variable in which to store the value of the flag. |
|
| 770 |
-func (fs *FlagSet) Uint64Var(p *uint64, names []string, value uint64, usage string) {
|
|
| 771 |
- fs.Var(newUint64Value(value, p), names, usage) |
|
| 772 |
-} |
|
| 773 |
- |
|
| 774 |
-// Uint64Var defines a uint64 flag with specified name, default value, and usage string. |
|
| 775 |
-// The argument p points to a uint64 variable in which to store the value of the flag. |
|
| 776 |
-func Uint64Var(p *uint64, names []string, value uint64, usage string) {
|
|
| 777 |
- CommandLine.Var(newUint64Value(value, p), names, usage) |
|
| 778 |
-} |
|
| 779 |
- |
|
| 780 |
-// Uint64 defines a uint64 flag with specified name, default value, and usage string. |
|
| 781 |
-// The return value is the address of a uint64 variable that stores the value of the flag. |
|
| 782 |
-func (fs *FlagSet) Uint64(names []string, value uint64, usage string) *uint64 {
|
|
| 783 |
- p := new(uint64) |
|
| 784 |
- fs.Uint64Var(p, names, value, usage) |
|
| 785 |
- return p |
|
| 786 |
-} |
|
| 787 |
- |
|
| 788 |
-// Uint64 defines a uint64 flag with specified name, default value, and usage string. |
|
| 789 |
-// The return value is the address of a uint64 variable that stores the value of the flag. |
|
| 790 |
-func Uint64(names []string, value uint64, usage string) *uint64 {
|
|
| 791 |
- return CommandLine.Uint64(names, value, usage) |
|
| 792 |
-} |
|
| 793 |
- |
|
| 794 |
-// Uint16Var defines a uint16 flag with specified name, default value, and usage string. |
|
| 795 |
-// The argument p points to a uint16 variable in which to store the value of the flag. |
|
| 796 |
-func (fs *FlagSet) Uint16Var(p *uint16, names []string, value uint16, usage string) {
|
|
| 797 |
- fs.Var(newUint16Value(value, p), names, usage) |
|
| 798 |
-} |
|
| 799 |
- |
|
| 800 |
-// Uint16Var defines a uint16 flag with specified name, default value, and usage string. |
|
| 801 |
-// The argument p points to a uint16 variable in which to store the value of the flag. |
|
| 802 |
-func Uint16Var(p *uint16, names []string, value uint16, usage string) {
|
|
| 803 |
- CommandLine.Var(newUint16Value(value, p), names, usage) |
|
| 804 |
-} |
|
| 805 |
- |
|
| 806 |
-// Uint16 defines a uint16 flag with specified name, default value, and usage string. |
|
| 807 |
-// The return value is the address of a uint16 variable that stores the value of the flag. |
|
| 808 |
-func (fs *FlagSet) Uint16(names []string, value uint16, usage string) *uint16 {
|
|
| 809 |
- p := new(uint16) |
|
| 810 |
- fs.Uint16Var(p, names, value, usage) |
|
| 811 |
- return p |
|
| 812 |
-} |
|
| 813 |
- |
|
| 814 |
-// Uint16 defines a uint16 flag with specified name, default value, and usage string. |
|
| 815 |
-// The return value is the address of a uint16 variable that stores the value of the flag. |
|
| 816 |
-func Uint16(names []string, value uint16, usage string) *uint16 {
|
|
| 817 |
- return CommandLine.Uint16(names, value, usage) |
|
| 818 |
-} |
|
| 819 |
- |
|
| 820 |
-// StringVar defines a string flag with specified name, default value, and usage string. |
|
| 821 |
-// The argument p points to a string variable in which to store the value of the flag. |
|
| 822 |
-func (fs *FlagSet) StringVar(p *string, names []string, value string, usage string) {
|
|
| 823 |
- fs.Var(newStringValue(value, p), names, usage) |
|
| 824 |
-} |
|
| 825 |
- |
|
| 826 |
-// StringVar defines a string flag with specified name, default value, and usage string. |
|
| 827 |
-// The argument p points to a string variable in which to store the value of the flag. |
|
| 828 |
-func StringVar(p *string, names []string, value string, usage string) {
|
|
| 829 |
- CommandLine.Var(newStringValue(value, p), names, usage) |
|
| 830 |
-} |
|
| 831 |
- |
|
| 832 |
-// String defines a string flag with specified name, default value, and usage string. |
|
| 833 |
-// The return value is the address of a string variable that stores the value of the flag. |
|
| 834 |
-func (fs *FlagSet) String(names []string, value string, usage string) *string {
|
|
| 835 |
- p := new(string) |
|
| 836 |
- fs.StringVar(p, names, value, usage) |
|
| 837 |
- return p |
|
| 838 |
-} |
|
| 839 |
- |
|
| 840 |
-// String defines a string flag with specified name, default value, and usage string. |
|
| 841 |
-// The return value is the address of a string variable that stores the value of the flag. |
|
| 842 |
-func String(names []string, value string, usage string) *string {
|
|
| 843 |
- return CommandLine.String(names, value, usage) |
|
| 844 |
-} |
|
| 845 |
- |
|
| 846 |
-// Float64Var defines a float64 flag with specified name, default value, and usage string. |
|
| 847 |
-// The argument p points to a float64 variable in which to store the value of the flag. |
|
| 848 |
-func (fs *FlagSet) Float64Var(p *float64, names []string, value float64, usage string) {
|
|
| 849 |
- fs.Var(newFloat64Value(value, p), names, usage) |
|
| 850 |
-} |
|
| 851 |
- |
|
| 852 |
-// Float64Var defines a float64 flag with specified name, default value, and usage string. |
|
| 853 |
-// The argument p points to a float64 variable in which to store the value of the flag. |
|
| 854 |
-func Float64Var(p *float64, names []string, value float64, usage string) {
|
|
| 855 |
- CommandLine.Var(newFloat64Value(value, p), names, usage) |
|
| 856 |
-} |
|
| 857 |
- |
|
| 858 |
-// Float64 defines a float64 flag with specified name, default value, and usage string. |
|
| 859 |
-// The return value is the address of a float64 variable that stores the value of the flag. |
|
| 860 |
-func (fs *FlagSet) Float64(names []string, value float64, usage string) *float64 {
|
|
| 861 |
- p := new(float64) |
|
| 862 |
- fs.Float64Var(p, names, value, usage) |
|
| 863 |
- return p |
|
| 864 |
-} |
|
| 865 |
- |
|
| 866 |
-// Float64 defines a float64 flag with specified name, default value, and usage string. |
|
| 867 |
-// The return value is the address of a float64 variable that stores the value of the flag. |
|
| 868 |
-func Float64(names []string, value float64, usage string) *float64 {
|
|
| 869 |
- return CommandLine.Float64(names, value, usage) |
|
| 870 |
-} |
|
| 871 |
- |
|
| 872 |
-// DurationVar defines a time.Duration flag with specified name, default value, and usage string. |
|
| 873 |
-// The argument p points to a time.Duration variable in which to store the value of the flag. |
|
| 874 |
-func (fs *FlagSet) DurationVar(p *time.Duration, names []string, value time.Duration, usage string) {
|
|
| 875 |
- fs.Var(newDurationValue(value, p), names, usage) |
|
| 876 |
-} |
|
| 877 |
- |
|
| 878 |
-// DurationVar defines a time.Duration flag with specified name, default value, and usage string. |
|
| 879 |
-// The argument p points to a time.Duration variable in which to store the value of the flag. |
|
| 880 |
-func DurationVar(p *time.Duration, names []string, value time.Duration, usage string) {
|
|
| 881 |
- CommandLine.Var(newDurationValue(value, p), names, usage) |
|
| 882 |
-} |
|
| 883 |
- |
|
| 884 |
-// Duration defines a time.Duration flag with specified name, default value, and usage string. |
|
| 885 |
-// The return value is the address of a time.Duration variable that stores the value of the flag. |
|
| 886 |
-func (fs *FlagSet) Duration(names []string, value time.Duration, usage string) *time.Duration {
|
|
| 887 |
- p := new(time.Duration) |
|
| 888 |
- fs.DurationVar(p, names, value, usage) |
|
| 889 |
- return p |
|
| 890 |
-} |
|
| 891 |
- |
|
| 892 |
-// Duration defines a time.Duration flag with specified name, default value, and usage string. |
|
| 893 |
-// The return value is the address of a time.Duration variable that stores the value of the flag. |
|
| 894 |
-func Duration(names []string, value time.Duration, usage string) *time.Duration {
|
|
| 895 |
- return CommandLine.Duration(names, value, usage) |
|
| 896 |
-} |
|
| 897 |
- |
|
| 898 |
-// Var defines a flag with the specified name and usage string. The type and |
|
| 899 |
-// value of the flag are represented by the first argument, of type Value, which |
|
| 900 |
-// typically holds a user-defined implementation of Value. For instance, the |
|
| 901 |
-// caller could create a flag that turns a comma-separated string into a slice |
|
| 902 |
-// of strings by giving the slice the methods of Value; in particular, Set would |
|
| 903 |
-// decompose the comma-separated string into the slice. |
|
| 904 |
-func (fs *FlagSet) Var(value Value, names []string, usage string) {
|
|
| 905 |
- // Remember the default value as a string; it won't change. |
|
| 906 |
- flag := &Flag{names, usage, value, value.String()}
|
|
| 907 |
- for _, name := range names {
|
|
| 908 |
- name = strings.TrimPrefix(name, "#") |
|
| 909 |
- _, alreadythere := fs.formal[name] |
|
| 910 |
- if alreadythere {
|
|
| 911 |
- var msg string |
|
| 912 |
- if fs.name == "" {
|
|
| 913 |
- msg = fmt.Sprintf("flag redefined: %s", name)
|
|
| 914 |
- } else {
|
|
| 915 |
- msg = fmt.Sprintf("%s flag redefined: %s", fs.name, name)
|
|
| 916 |
- } |
|
| 917 |
- fmt.Fprintln(fs.Out(), msg) |
|
| 918 |
- panic(msg) // Happens only if flags are declared with identical names |
|
| 919 |
- } |
|
| 920 |
- if fs.formal == nil {
|
|
| 921 |
- fs.formal = make(map[string]*Flag) |
|
| 922 |
- } |
|
| 923 |
- fs.formal[name] = flag |
|
| 924 |
- } |
|
| 925 |
-} |
|
| 926 |
- |
|
| 927 |
-// Var defines a flag with the specified name and usage string. The type and |
|
| 928 |
-// value of the flag are represented by the first argument, of type Value, which |
|
| 929 |
-// typically holds a user-defined implementation of Value. For instance, the |
|
| 930 |
-// caller could create a flag that turns a comma-separated string into a slice |
|
| 931 |
-// of strings by giving the slice the methods of Value; in particular, Set would |
|
| 932 |
-// decompose the comma-separated string into the slice. |
|
| 933 |
-func Var(value Value, names []string, usage string) {
|
|
| 934 |
- CommandLine.Var(value, names, usage) |
|
| 935 |
-} |
|
| 936 |
- |
|
| 937 |
-// failf prints to standard error a formatted error and usage message and |
|
| 938 |
-// returns the error. |
|
| 939 |
-func (fs *FlagSet) failf(format string, a ...interface{}) error {
|
|
| 940 |
- err := fmt.Errorf(format, a...) |
|
| 941 |
- fmt.Fprintln(fs.Out(), err) |
|
| 942 |
- if os.Args[0] == fs.name {
|
|
| 943 |
- fmt.Fprintf(fs.Out(), "See '%s --help'.\n", os.Args[0]) |
|
| 944 |
- } else {
|
|
| 945 |
- fmt.Fprintf(fs.Out(), "See '%s %s --help'.\n", os.Args[0], fs.name) |
|
| 946 |
- } |
|
| 947 |
- return err |
|
| 948 |
-} |
|
| 949 |
- |
|
| 950 |
-// usage calls the Usage method for the flag set, or the usage function if |
|
| 951 |
-// the flag set is CommandLine. |
|
| 952 |
-func (fs *FlagSet) usage() {
|
|
| 953 |
- if fs == CommandLine {
|
|
| 954 |
- Usage() |
|
| 955 |
- } else if fs.Usage == nil {
|
|
| 956 |
- defaultUsage(fs) |
|
| 957 |
- } else {
|
|
| 958 |
- fs.Usage() |
|
| 959 |
- } |
|
| 960 |
-} |
|
| 961 |
- |
|
| 962 |
-func trimQuotes(str string) string {
|
|
| 963 |
- if len(str) == 0 {
|
|
| 964 |
- return str |
|
| 965 |
- } |
|
| 966 |
- type quote struct {
|
|
| 967 |
- start, end byte |
|
| 968 |
- } |
|
| 969 |
- |
|
| 970 |
- // All valid quote types. |
|
| 971 |
- quotes := []quote{
|
|
| 972 |
- // Double quotes |
|
| 973 |
- {
|
|
| 974 |
- start: '"', |
|
| 975 |
- end: '"', |
|
| 976 |
- }, |
|
| 977 |
- |
|
| 978 |
- // Single quotes |
|
| 979 |
- {
|
|
| 980 |
- start: '\'', |
|
| 981 |
- end: '\'', |
|
| 982 |
- }, |
|
| 983 |
- } |
|
| 984 |
- |
|
| 985 |
- for _, quote := range quotes {
|
|
| 986 |
- // Only strip if outermost match. |
|
| 987 |
- if str[0] == quote.start && str[len(str)-1] == quote.end {
|
|
| 988 |
- str = str[1 : len(str)-1] |
|
| 989 |
- break |
|
| 990 |
- } |
|
| 991 |
- } |
|
| 992 |
- |
|
| 993 |
- return str |
|
| 994 |
-} |
|
| 995 |
- |
|
| 996 |
-// parseOne parses one flag. It reports whether a flag was seen. |
|
| 997 |
-func (fs *FlagSet) parseOne() (bool, string, error) {
|
|
| 998 |
- if len(fs.args) == 0 {
|
|
| 999 |
- return false, "", nil |
|
| 1000 |
- } |
|
| 1001 |
- s := fs.args[0] |
|
| 1002 |
- if len(s) == 0 || s[0] != '-' || len(s) == 1 {
|
|
| 1003 |
- return false, "", nil |
|
| 1004 |
- } |
|
| 1005 |
- if s[1] == '-' && len(s) == 2 { // "--" terminates the flags
|
|
| 1006 |
- fs.args = fs.args[1:] |
|
| 1007 |
- return false, "", nil |
|
| 1008 |
- } |
|
| 1009 |
- name := s[1:] |
|
| 1010 |
- if len(name) == 0 || name[0] == '=' {
|
|
| 1011 |
- return false, "", fs.failf("bad flag syntax: %s", s)
|
|
| 1012 |
- } |
|
| 1013 |
- |
|
| 1014 |
- // it's a flag. does it have an argument? |
|
| 1015 |
- fs.args = fs.args[1:] |
|
| 1016 |
- hasValue := false |
|
| 1017 |
- value := "" |
|
| 1018 |
- if i := strings.Index(name, "="); i != -1 {
|
|
| 1019 |
- value = trimQuotes(name[i+1:]) |
|
| 1020 |
- hasValue = true |
|
| 1021 |
- name = name[:i] |
|
| 1022 |
- } |
|
| 1023 |
- |
|
| 1024 |
- m := fs.formal |
|
| 1025 |
- flag, alreadythere := m[name] // BUG |
|
| 1026 |
- if !alreadythere {
|
|
| 1027 |
- if name == "-help" || name == "help" || name == "h" { // special case for nice help message.
|
|
| 1028 |
- fs.usage() |
|
| 1029 |
- return false, "", ErrHelp |
|
| 1030 |
- } |
|
| 1031 |
- if len(name) > 0 && name[0] == '-' {
|
|
| 1032 |
- return false, "", fs.failf("flag provided but not defined: -%s", name)
|
|
| 1033 |
- } |
|
| 1034 |
- return false, name, ErrRetry |
|
| 1035 |
- } |
|
| 1036 |
- if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
|
|
| 1037 |
- if hasValue {
|
|
| 1038 |
- if err := fv.Set(value); err != nil {
|
|
| 1039 |
- return false, "", fs.failf("invalid boolean value %q for -%s: %v", value, name, err)
|
|
| 1040 |
- } |
|
| 1041 |
- } else {
|
|
| 1042 |
- fv.Set("true")
|
|
| 1043 |
- } |
|
| 1044 |
- } else {
|
|
| 1045 |
- // It must have a value, which might be the next argument. |
|
| 1046 |
- if !hasValue && len(fs.args) > 0 {
|
|
| 1047 |
- // value is the next arg |
|
| 1048 |
- hasValue = true |
|
| 1049 |
- value, fs.args = fs.args[0], fs.args[1:] |
|
| 1050 |
- } |
|
| 1051 |
- if !hasValue {
|
|
| 1052 |
- return false, "", fs.failf("flag needs an argument: -%s", name)
|
|
| 1053 |
- } |
|
| 1054 |
- if err := flag.Value.Set(value); err != nil {
|
|
| 1055 |
- return false, "", fs.failf("invalid value %q for flag -%s: %v", value, name, err)
|
|
| 1056 |
- } |
|
| 1057 |
- } |
|
| 1058 |
- if fs.actual == nil {
|
|
| 1059 |
- fs.actual = make(map[string]*Flag) |
|
| 1060 |
- } |
|
| 1061 |
- fs.actual[name] = flag |
|
| 1062 |
- for i, n := range flag.Names {
|
|
| 1063 |
- if n == fmt.Sprintf("#%s", name) {
|
|
| 1064 |
- replacement := "" |
|
| 1065 |
- for j := i; j < len(flag.Names); j++ {
|
|
| 1066 |
- if flag.Names[j][0] != '#' {
|
|
| 1067 |
- replacement = flag.Names[j] |
|
| 1068 |
- break |
|
| 1069 |
- } |
|
| 1070 |
- } |
|
| 1071 |
- if replacement != "" {
|
|
| 1072 |
- fmt.Fprintf(fs.Out(), "Warning: '-%s' is deprecated, it will be replaced by '-%s' soon. See usage.\n", name, replacement) |
|
| 1073 |
- } else {
|
|
| 1074 |
- fmt.Fprintf(fs.Out(), "Warning: '-%s' is deprecated, it will be removed soon. See usage.\n", name) |
|
| 1075 |
- } |
|
| 1076 |
- } |
|
| 1077 |
- } |
|
| 1078 |
- return true, "", nil |
|
| 1079 |
-} |
|
| 1080 |
- |
|
| 1081 |
-// Parse parses flag definitions from the argument list, which should not |
|
| 1082 |
-// include the command name. Must be called after all flags in the FlagSet |
|
| 1083 |
-// are defined and before flags are accessed by the program. |
|
| 1084 |
-// The return value will be ErrHelp if -help was set but not defined. |
|
| 1085 |
-func (fs *FlagSet) Parse(arguments []string) error {
|
|
| 1086 |
- fs.parsed = true |
|
| 1087 |
- fs.args = arguments |
|
| 1088 |
- for {
|
|
| 1089 |
- seen, name, err := fs.parseOne() |
|
| 1090 |
- if seen {
|
|
| 1091 |
- continue |
|
| 1092 |
- } |
|
| 1093 |
- if err == nil {
|
|
| 1094 |
- break |
|
| 1095 |
- } |
|
| 1096 |
- if err == ErrRetry {
|
|
| 1097 |
- if len(name) > 1 {
|
|
| 1098 |
- err = nil |
|
| 1099 |
- for _, letter := range strings.Split(name, "") {
|
|
| 1100 |
- fs.args = append([]string{"-" + letter}, fs.args...)
|
|
| 1101 |
- seen2, _, err2 := fs.parseOne() |
|
| 1102 |
- if seen2 {
|
|
| 1103 |
- continue |
|
| 1104 |
- } |
|
| 1105 |
- if err2 != nil {
|
|
| 1106 |
- err = fs.failf("flag provided but not defined: -%s", name)
|
|
| 1107 |
- break |
|
| 1108 |
- } |
|
| 1109 |
- } |
|
| 1110 |
- if err == nil {
|
|
| 1111 |
- continue |
|
| 1112 |
- } |
|
| 1113 |
- } else {
|
|
| 1114 |
- err = fs.failf("flag provided but not defined: -%s", name)
|
|
| 1115 |
- } |
|
| 1116 |
- } |
|
| 1117 |
- switch fs.errorHandling {
|
|
| 1118 |
- case ContinueOnError: |
|
| 1119 |
- return err |
|
| 1120 |
- case ExitOnError: |
|
| 1121 |
- os.Exit(125) |
|
| 1122 |
- case PanicOnError: |
|
| 1123 |
- panic(err) |
|
| 1124 |
- } |
|
| 1125 |
- } |
|
| 1126 |
- return nil |
|
| 1127 |
-} |
|
| 1128 |
- |
|
| 1129 |
-// ParseFlags is a utility function that adds a help flag if withHelp is true, |
|
| 1130 |
-// calls fs.Parse(args) and prints a relevant error message if there are |
|
| 1131 |
-// incorrect number of arguments. It returns error only if error handling is |
|
| 1132 |
-// set to ContinueOnError and parsing fails. If error handling is set to |
|
| 1133 |
-// ExitOnError, it's safe to ignore the return value. |
|
| 1134 |
-func (fs *FlagSet) ParseFlags(args []string, withHelp bool) error {
|
|
| 1135 |
- var help *bool |
|
| 1136 |
- if withHelp {
|
|
| 1137 |
- help = fs.Bool([]string{"#help", "-help"}, false, "Print usage")
|
|
| 1138 |
- } |
|
| 1139 |
- if err := fs.Parse(args); err != nil {
|
|
| 1140 |
- return err |
|
| 1141 |
- } |
|
| 1142 |
- if help != nil && *help {
|
|
| 1143 |
- fs.SetOutput(os.Stdout) |
|
| 1144 |
- fs.Usage() |
|
| 1145 |
- os.Exit(0) |
|
| 1146 |
- } |
|
| 1147 |
- if str := fs.CheckArgs(); str != "" {
|
|
| 1148 |
- fs.SetOutput(os.Stderr) |
|
| 1149 |
- fs.ReportError(str, withHelp) |
|
| 1150 |
- fs.ShortUsage() |
|
| 1151 |
- os.Exit(1) |
|
| 1152 |
- } |
|
| 1153 |
- return nil |
|
| 1154 |
-} |
|
| 1155 |
- |
|
| 1156 |
-// ReportError is a utility method that prints a user-friendly message |
|
| 1157 |
-// containing the error that occurred during parsing and a suggestion to get help |
|
| 1158 |
-func (fs *FlagSet) ReportError(str string, withHelp bool) {
|
|
| 1159 |
- if withHelp {
|
|
| 1160 |
- if os.Args[0] == fs.Name() {
|
|
| 1161 |
- str += ".\nSee '" + os.Args[0] + " --help'" |
|
| 1162 |
- } else {
|
|
| 1163 |
- str += ".\nSee '" + os.Args[0] + " " + fs.Name() + " --help'" |
|
| 1164 |
- } |
|
| 1165 |
- } |
|
| 1166 |
- fmt.Fprintf(fs.Out(), "%s: %s.\n", os.Args[0], str) |
|
| 1167 |
-} |
|
| 1168 |
- |
|
| 1169 |
-// Parsed reports whether fs.Parse has been called. |
|
| 1170 |
-func (fs *FlagSet) Parsed() bool {
|
|
| 1171 |
- return fs.parsed |
|
| 1172 |
-} |
|
| 1173 |
- |
|
| 1174 |
-// Parse parses the command-line flags from os.Args[1:]. Must be called |
|
| 1175 |
-// after all flags are defined and before flags are accessed by the program. |
|
| 1176 |
-func Parse() {
|
|
| 1177 |
- // Ignore errors; CommandLine is set for ExitOnError. |
|
| 1178 |
- CommandLine.Parse(os.Args[1:]) |
|
| 1179 |
-} |
|
| 1180 |
- |
|
| 1181 |
-// Parsed returns true if the command-line flags have been parsed. |
|
| 1182 |
-func Parsed() bool {
|
|
| 1183 |
- return CommandLine.Parsed() |
|
| 1184 |
-} |
|
| 1185 |
- |
|
| 1186 |
-// CommandLine is the default set of command-line flags, parsed from os.Args. |
|
| 1187 |
-// The top-level functions such as BoolVar, Arg, and on are wrappers for the |
|
| 1188 |
-// methods of CommandLine. |
|
| 1189 |
-var CommandLine = NewFlagSet(os.Args[0], ExitOnError) |
|
| 1190 |
- |
|
| 1191 |
-// NewFlagSet returns a new, empty flag set with the specified name and |
|
| 1192 |
-// error handling property. |
|
| 1193 |
-func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
|
|
| 1194 |
- f := &FlagSet{
|
|
| 1195 |
- name: name, |
|
| 1196 |
- errorHandling: errorHandling, |
|
| 1197 |
- } |
|
| 1198 |
- return f |
|
| 1199 |
-} |
|
| 1200 |
- |
|
| 1201 |
-// Init sets the name and error handling property for a flag set. |
|
| 1202 |
-// By default, the zero FlagSet uses an empty name and the |
|
| 1203 |
-// ContinueOnError error handling policy. |
|
| 1204 |
-func (fs *FlagSet) Init(name string, errorHandling ErrorHandling) {
|
|
| 1205 |
- fs.name = name |
|
| 1206 |
- fs.errorHandling = errorHandling |
|
| 1207 |
-} |
|
| 1208 |
- |
|
| 1209 |
-type mergeVal struct {
|
|
| 1210 |
- Value |
|
| 1211 |
- key string |
|
| 1212 |
- fset *FlagSet |
|
| 1213 |
-} |
|
| 1214 |
- |
|
| 1215 |
-func (v mergeVal) Set(s string) error {
|
|
| 1216 |
- return v.fset.Set(v.key, s) |
|
| 1217 |
-} |
|
| 1218 |
- |
|
| 1219 |
-func (v mergeVal) IsBoolFlag() bool {
|
|
| 1220 |
- if b, ok := v.Value.(boolFlag); ok {
|
|
| 1221 |
- return b.IsBoolFlag() |
|
| 1222 |
- } |
|
| 1223 |
- return false |
|
| 1224 |
-} |
|
| 1225 |
- |
|
| 1226 |
-// Name returns the name of a mergeVal. |
|
| 1227 |
-// If the original value had a name, return the original name, |
|
| 1228 |
-// otherwise, return the key asinged to this mergeVal. |
|
| 1229 |
-func (v mergeVal) Name() string {
|
|
| 1230 |
- type namedValue interface {
|
|
| 1231 |
- Name() string |
|
| 1232 |
- } |
|
| 1233 |
- if nVal, ok := v.Value.(namedValue); ok {
|
|
| 1234 |
- return nVal.Name() |
|
| 1235 |
- } |
|
| 1236 |
- return v.key |
|
| 1237 |
-} |
|
| 1238 |
- |
|
| 1239 |
-// Merge is a helper function that merges n FlagSets into a single dest FlagSet |
|
| 1240 |
-// In case of name collision between the flagsets it will apply |
|
| 1241 |
-// the destination FlagSet's errorHandling behavior. |
|
| 1242 |
-func Merge(dest *FlagSet, flagsets ...*FlagSet) error {
|
|
| 1243 |
- for _, fset := range flagsets {
|
|
| 1244 |
- if fset.formal == nil {
|
|
| 1245 |
- continue |
|
| 1246 |
- } |
|
| 1247 |
- for k, f := range fset.formal {
|
|
| 1248 |
- if _, ok := dest.formal[k]; ok {
|
|
| 1249 |
- var err error |
|
| 1250 |
- if fset.name == "" {
|
|
| 1251 |
- err = fmt.Errorf("flag redefined: %s", k)
|
|
| 1252 |
- } else {
|
|
| 1253 |
- err = fmt.Errorf("%s flag redefined: %s", fset.name, k)
|
|
| 1254 |
- } |
|
| 1255 |
- fmt.Fprintln(fset.Out(), err.Error()) |
|
| 1256 |
- // Happens only if flags are declared with identical names |
|
| 1257 |
- switch dest.errorHandling {
|
|
| 1258 |
- case ContinueOnError: |
|
| 1259 |
- return err |
|
| 1260 |
- case ExitOnError: |
|
| 1261 |
- os.Exit(2) |
|
| 1262 |
- case PanicOnError: |
|
| 1263 |
- panic(err) |
|
| 1264 |
- } |
|
| 1265 |
- } |
|
| 1266 |
- newF := *f |
|
| 1267 |
- newF.Value = mergeVal{f.Value, k, fset}
|
|
| 1268 |
- if dest.formal == nil {
|
|
| 1269 |
- dest.formal = make(map[string]*Flag) |
|
| 1270 |
- } |
|
| 1271 |
- dest.formal[k] = &newF |
|
| 1272 |
- } |
|
| 1273 |
- } |
|
| 1274 |
- return nil |
|
| 1275 |
-} |
|
| 1276 |
- |
|
| 1277 |
-// IsEmpty reports if the FlagSet is actually empty. |
|
| 1278 |
-func (fs *FlagSet) IsEmpty() bool {
|
|
| 1279 |
- return len(fs.actual) == 0 |
|
| 1280 |
-} |
| 1281 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,527 +0,0 @@ |
| 1 |
-// Copyright 2014-2016 The Docker & Go Authors. All rights reserved. |
|
| 2 |
-// Use of this source code is governed by a BSD-style |
|
| 3 |
-// license that can be found in the LICENSE file. |
|
| 4 |
- |
|
| 5 |
-package mflag |
|
| 6 |
- |
|
| 7 |
-import ( |
|
| 8 |
- "bytes" |
|
| 9 |
- "fmt" |
|
| 10 |
- "os" |
|
| 11 |
- "sort" |
|
| 12 |
- "strings" |
|
| 13 |
- "testing" |
|
| 14 |
- "time" |
|
| 15 |
-) |
|
| 16 |
- |
|
| 17 |
-// ResetForTesting clears all flag state and sets the usage function as directed. |
|
| 18 |
-// After calling ResetForTesting, parse errors in flag handling will not |
|
| 19 |
-// exit the program. |
|
| 20 |
-func ResetForTesting(usage func()) {
|
|
| 21 |
- CommandLine = NewFlagSet(os.Args[0], ContinueOnError) |
|
| 22 |
- Usage = usage |
|
| 23 |
-} |
|
| 24 |
-func boolString(s string) string {
|
|
| 25 |
- if s == "0" {
|
|
| 26 |
- return "false" |
|
| 27 |
- } |
|
| 28 |
- return "true" |
|
| 29 |
-} |
|
| 30 |
- |
|
| 31 |
-func TestEverything(t *testing.T) {
|
|
| 32 |
- ResetForTesting(nil) |
|
| 33 |
- Bool([]string{"test_bool"}, false, "bool value")
|
|
| 34 |
- Int([]string{"test_int"}, 0, "int value")
|
|
| 35 |
- Int64([]string{"test_int64"}, 0, "int64 value")
|
|
| 36 |
- Uint([]string{"test_uint"}, 0, "uint value")
|
|
| 37 |
- Uint64([]string{"test_uint64"}, 0, "uint64 value")
|
|
| 38 |
- String([]string{"test_string"}, "0", "string value")
|
|
| 39 |
- Float64([]string{"test_float64"}, 0, "float64 value")
|
|
| 40 |
- Duration([]string{"test_duration"}, 0, "time.Duration value")
|
|
| 41 |
- |
|
| 42 |
- m := make(map[string]*Flag) |
|
| 43 |
- desired := "0" |
|
| 44 |
- visitor := func(f *Flag) {
|
|
| 45 |
- for _, name := range f.Names {
|
|
| 46 |
- if len(name) > 5 && name[0:5] == "test_" {
|
|
| 47 |
- m[name] = f |
|
| 48 |
- ok := false |
|
| 49 |
- switch {
|
|
| 50 |
- case f.Value.String() == desired: |
|
| 51 |
- ok = true |
|
| 52 |
- case name == "test_bool" && f.Value.String() == boolString(desired): |
|
| 53 |
- ok = true |
|
| 54 |
- case name == "test_duration" && f.Value.String() == desired+"s": |
|
| 55 |
- ok = true |
|
| 56 |
- } |
|
| 57 |
- if !ok {
|
|
| 58 |
- t.Error("Visit: bad value", f.Value.String(), "for", name)
|
|
| 59 |
- } |
|
| 60 |
- } |
|
| 61 |
- } |
|
| 62 |
- } |
|
| 63 |
- VisitAll(visitor) |
|
| 64 |
- if len(m) != 8 {
|
|
| 65 |
- t.Error("VisitAll misses some flags")
|
|
| 66 |
- for k, v := range m {
|
|
| 67 |
- t.Log(k, *v) |
|
| 68 |
- } |
|
| 69 |
- } |
|
| 70 |
- m = make(map[string]*Flag) |
|
| 71 |
- Visit(visitor) |
|
| 72 |
- if len(m) != 0 {
|
|
| 73 |
- t.Errorf("Visit sees unset flags")
|
|
| 74 |
- for k, v := range m {
|
|
| 75 |
- t.Log(k, *v) |
|
| 76 |
- } |
|
| 77 |
- } |
|
| 78 |
- // Now set all flags |
|
| 79 |
- Set("test_bool", "true")
|
|
| 80 |
- Set("test_int", "1")
|
|
| 81 |
- Set("test_int64", "1")
|
|
| 82 |
- Set("test_uint", "1")
|
|
| 83 |
- Set("test_uint64", "1")
|
|
| 84 |
- Set("test_string", "1")
|
|
| 85 |
- Set("test_float64", "1")
|
|
| 86 |
- Set("test_duration", "1s")
|
|
| 87 |
- desired = "1" |
|
| 88 |
- Visit(visitor) |
|
| 89 |
- if len(m) != 8 {
|
|
| 90 |
- t.Error("Visit fails after set")
|
|
| 91 |
- for k, v := range m {
|
|
| 92 |
- t.Log(k, *v) |
|
| 93 |
- } |
|
| 94 |
- } |
|
| 95 |
- // Now test they're visited in sort order. |
|
| 96 |
- var flagNames []string |
|
| 97 |
- Visit(func(f *Flag) {
|
|
| 98 |
- for _, name := range f.Names {
|
|
| 99 |
- flagNames = append(flagNames, name) |
|
| 100 |
- } |
|
| 101 |
- }) |
|
| 102 |
- if !sort.StringsAreSorted(flagNames) {
|
|
| 103 |
- t.Errorf("flag names not sorted: %v", flagNames)
|
|
| 104 |
- } |
|
| 105 |
-} |
|
| 106 |
- |
|
| 107 |
-func TestGet(t *testing.T) {
|
|
| 108 |
- ResetForTesting(nil) |
|
| 109 |
- Bool([]string{"test_bool"}, true, "bool value")
|
|
| 110 |
- Int([]string{"test_int"}, 1, "int value")
|
|
| 111 |
- Int64([]string{"test_int64"}, 2, "int64 value")
|
|
| 112 |
- Uint([]string{"test_uint"}, 3, "uint value")
|
|
| 113 |
- Uint64([]string{"test_uint64"}, 4, "uint64 value")
|
|
| 114 |
- String([]string{"test_string"}, "5", "string value")
|
|
| 115 |
- Float64([]string{"test_float64"}, 6, "float64 value")
|
|
| 116 |
- Duration([]string{"test_duration"}, 7, "time.Duration value")
|
|
| 117 |
- |
|
| 118 |
- visitor := func(f *Flag) {
|
|
| 119 |
- for _, name := range f.Names {
|
|
| 120 |
- if len(name) > 5 && name[0:5] == "test_" {
|
|
| 121 |
- g, ok := f.Value.(Getter) |
|
| 122 |
- if !ok {
|
|
| 123 |
- t.Errorf("Visit: value does not satisfy Getter: %T", f.Value)
|
|
| 124 |
- return |
|
| 125 |
- } |
|
| 126 |
- switch name {
|
|
| 127 |
- case "test_bool": |
|
| 128 |
- ok = g.Get() == true |
|
| 129 |
- case "test_int": |
|
| 130 |
- ok = g.Get() == int(1) |
|
| 131 |
- case "test_int64": |
|
| 132 |
- ok = g.Get() == int64(2) |
|
| 133 |
- case "test_uint": |
|
| 134 |
- ok = g.Get() == uint(3) |
|
| 135 |
- case "test_uint64": |
|
| 136 |
- ok = g.Get() == uint64(4) |
|
| 137 |
- case "test_string": |
|
| 138 |
- ok = g.Get() == "5" |
|
| 139 |
- case "test_float64": |
|
| 140 |
- ok = g.Get() == float64(6) |
|
| 141 |
- case "test_duration": |
|
| 142 |
- ok = g.Get() == time.Duration(7) |
|
| 143 |
- } |
|
| 144 |
- if !ok {
|
|
| 145 |
- t.Errorf("Visit: bad value %T(%v) for %s", g.Get(), g.Get(), name)
|
|
| 146 |
- } |
|
| 147 |
- } |
|
| 148 |
- } |
|
| 149 |
- } |
|
| 150 |
- VisitAll(visitor) |
|
| 151 |
-} |
|
| 152 |
- |
|
| 153 |
-func testParse(f *FlagSet, t *testing.T) {
|
|
| 154 |
- if f.Parsed() {
|
|
| 155 |
- t.Error("f.Parse() = true before Parse")
|
|
| 156 |
- } |
|
| 157 |
- boolFlag := f.Bool([]string{"bool"}, false, "bool value")
|
|
| 158 |
- bool2Flag := f.Bool([]string{"bool2"}, false, "bool2 value")
|
|
| 159 |
- f.Bool([]string{"bool3"}, false, "bool3 value")
|
|
| 160 |
- bool4Flag := f.Bool([]string{"bool4"}, false, "bool4 value")
|
|
| 161 |
- intFlag := f.Int([]string{"-int"}, 0, "int value")
|
|
| 162 |
- int64Flag := f.Int64([]string{"-int64"}, 0, "int64 value")
|
|
| 163 |
- uintFlag := f.Uint([]string{"uint"}, 0, "uint value")
|
|
| 164 |
- uint64Flag := f.Uint64([]string{"-uint64"}, 0, "uint64 value")
|
|
| 165 |
- stringFlag := f.String([]string{"string"}, "0", "string value")
|
|
| 166 |
- f.String([]string{"string2"}, "0", "string2 value")
|
|
| 167 |
- singleQuoteFlag := f.String([]string{"squote"}, "", "single quoted value")
|
|
| 168 |
- doubleQuoteFlag := f.String([]string{"dquote"}, "", "double quoted value")
|
|
| 169 |
- mixedQuoteFlag := f.String([]string{"mquote"}, "", "mixed quoted value")
|
|
| 170 |
- mixed2QuoteFlag := f.String([]string{"mquote2"}, "", "mixed2 quoted value")
|
|
| 171 |
- nestedQuoteFlag := f.String([]string{"nquote"}, "", "nested quoted value")
|
|
| 172 |
- nested2QuoteFlag := f.String([]string{"nquote2"}, "", "nested2 quoted value")
|
|
| 173 |
- float64Flag := f.Float64([]string{"float64"}, 0, "float64 value")
|
|
| 174 |
- durationFlag := f.Duration([]string{"duration"}, 5*time.Second, "time.Duration value")
|
|
| 175 |
- extra := "one-extra-argument" |
|
| 176 |
- args := []string{
|
|
| 177 |
- "-bool", |
|
| 178 |
- "-bool2=true", |
|
| 179 |
- "-bool4=false", |
|
| 180 |
- "--int", "22", |
|
| 181 |
- "--int64", "0x23", |
|
| 182 |
- "-uint", "24", |
|
| 183 |
- "--uint64", "25", |
|
| 184 |
- "-string", "hello", |
|
| 185 |
- "-squote='single'", |
|
| 186 |
- `-dquote="double"`, |
|
| 187 |
- `-mquote='mixed"`, |
|
| 188 |
- `-mquote2="mixed2'`, |
|
| 189 |
- `-nquote="'single nested'"`, |
|
| 190 |
- `-nquote2='"double nested"'`, |
|
| 191 |
- "-float64", "2718e28", |
|
| 192 |
- "-duration", "2m", |
|
| 193 |
- extra, |
|
| 194 |
- } |
|
| 195 |
- if err := f.Parse(args); err != nil {
|
|
| 196 |
- t.Fatal(err) |
|
| 197 |
- } |
|
| 198 |
- if !f.Parsed() {
|
|
| 199 |
- t.Error("f.Parse() = false after Parse")
|
|
| 200 |
- } |
|
| 201 |
- if *boolFlag != true {
|
|
| 202 |
- t.Error("bool flag should be true, is ", *boolFlag)
|
|
| 203 |
- } |
|
| 204 |
- if *bool2Flag != true {
|
|
| 205 |
- t.Error("bool2 flag should be true, is ", *bool2Flag)
|
|
| 206 |
- } |
|
| 207 |
- if !f.IsSet("bool2") {
|
|
| 208 |
- t.Error("bool2 should be marked as set")
|
|
| 209 |
- } |
|
| 210 |
- if f.IsSet("bool3") {
|
|
| 211 |
- t.Error("bool3 should not be marked as set")
|
|
| 212 |
- } |
|
| 213 |
- if !f.IsSet("bool4") {
|
|
| 214 |
- t.Error("bool4 should be marked as set")
|
|
| 215 |
- } |
|
| 216 |
- if *bool4Flag != false {
|
|
| 217 |
- t.Error("bool4 flag should be false, is ", *bool4Flag)
|
|
| 218 |
- } |
|
| 219 |
- if *intFlag != 22 {
|
|
| 220 |
- t.Error("int flag should be 22, is ", *intFlag)
|
|
| 221 |
- } |
|
| 222 |
- if *int64Flag != 0x23 {
|
|
| 223 |
- t.Error("int64 flag should be 0x23, is ", *int64Flag)
|
|
| 224 |
- } |
|
| 225 |
- if *uintFlag != 24 {
|
|
| 226 |
- t.Error("uint flag should be 24, is ", *uintFlag)
|
|
| 227 |
- } |
|
| 228 |
- if *uint64Flag != 25 {
|
|
| 229 |
- t.Error("uint64 flag should be 25, is ", *uint64Flag)
|
|
| 230 |
- } |
|
| 231 |
- if *stringFlag != "hello" {
|
|
| 232 |
- t.Error("string flag should be `hello`, is ", *stringFlag)
|
|
| 233 |
- } |
|
| 234 |
- if !f.IsSet("string") {
|
|
| 235 |
- t.Error("string flag should be marked as set")
|
|
| 236 |
- } |
|
| 237 |
- if f.IsSet("string2") {
|
|
| 238 |
- t.Error("string2 flag should not be marked as set")
|
|
| 239 |
- } |
|
| 240 |
- if *singleQuoteFlag != "single" {
|
|
| 241 |
- t.Error("single quote string flag should be `single`, is ", *singleQuoteFlag)
|
|
| 242 |
- } |
|
| 243 |
- if *doubleQuoteFlag != "double" {
|
|
| 244 |
- t.Error("double quote string flag should be `double`, is ", *doubleQuoteFlag)
|
|
| 245 |
- } |
|
| 246 |
- if *mixedQuoteFlag != `'mixed"` {
|
|
| 247 |
- t.Error("mixed quote string flag should be `'mixed\"`, is ", *mixedQuoteFlag)
|
|
| 248 |
- } |
|
| 249 |
- if *mixed2QuoteFlag != `"mixed2'` {
|
|
| 250 |
- t.Error("mixed2 quote string flag should be `\"mixed2'`, is ", *mixed2QuoteFlag)
|
|
| 251 |
- } |
|
| 252 |
- if *nestedQuoteFlag != "'single nested'" {
|
|
| 253 |
- t.Error("nested quote string flag should be `'single nested'`, is ", *nestedQuoteFlag)
|
|
| 254 |
- } |
|
| 255 |
- if *nested2QuoteFlag != `"double nested"` {
|
|
| 256 |
- t.Error("double quote string flag should be `\"double nested\"`, is ", *nested2QuoteFlag)
|
|
| 257 |
- } |
|
| 258 |
- if *float64Flag != 2718e28 {
|
|
| 259 |
- t.Error("float64 flag should be 2718e28, is ", *float64Flag)
|
|
| 260 |
- } |
|
| 261 |
- if *durationFlag != 2*time.Minute {
|
|
| 262 |
- t.Error("duration flag should be 2m, is ", *durationFlag)
|
|
| 263 |
- } |
|
| 264 |
- if len(f.Args()) != 1 {
|
|
| 265 |
- t.Error("expected one argument, got", len(f.Args()))
|
|
| 266 |
- } else if f.Args()[0] != extra {
|
|
| 267 |
- t.Errorf("expected argument %q got %q", extra, f.Args()[0])
|
|
| 268 |
- } |
|
| 269 |
-} |
|
| 270 |
- |
|
| 271 |
-func testPanic(f *FlagSet, t *testing.T) {
|
|
| 272 |
- f.Int([]string{"-int"}, 0, "int value")
|
|
| 273 |
- if f.Parsed() {
|
|
| 274 |
- t.Error("f.Parse() = true before Parse")
|
|
| 275 |
- } |
|
| 276 |
- args := []string{
|
|
| 277 |
- "-int", "21", |
|
| 278 |
- } |
|
| 279 |
- f.Parse(args) |
|
| 280 |
-} |
|
| 281 |
- |
|
| 282 |
-func TestParsePanic(t *testing.T) {
|
|
| 283 |
- ResetForTesting(func() {})
|
|
| 284 |
- testPanic(CommandLine, t) |
|
| 285 |
-} |
|
| 286 |
- |
|
| 287 |
-func TestParse(t *testing.T) {
|
|
| 288 |
- ResetForTesting(func() { t.Error("bad parse") })
|
|
| 289 |
- testParse(CommandLine, t) |
|
| 290 |
-} |
|
| 291 |
- |
|
| 292 |
-func TestFlagSetParse(t *testing.T) {
|
|
| 293 |
- testParse(NewFlagSet("test", ContinueOnError), t)
|
|
| 294 |
-} |
|
| 295 |
- |
|
| 296 |
-// Declare a user-defined flag type. |
|
| 297 |
-type flagVar []string |
|
| 298 |
- |
|
| 299 |
-func (f *flagVar) String() string {
|
|
| 300 |
- return fmt.Sprint([]string(*f)) |
|
| 301 |
-} |
|
| 302 |
- |
|
| 303 |
-func (f *flagVar) Set(value string) error {
|
|
| 304 |
- *f = append(*f, value) |
|
| 305 |
- return nil |
|
| 306 |
-} |
|
| 307 |
- |
|
| 308 |
-func TestUserDefined(t *testing.T) {
|
|
| 309 |
- var flags FlagSet |
|
| 310 |
- flags.Init("test", ContinueOnError)
|
|
| 311 |
- var v flagVar |
|
| 312 |
- flags.Var(&v, []string{"v"}, "usage")
|
|
| 313 |
- if err := flags.Parse([]string{"-v", "1", "-v", "2", "-v=3"}); err != nil {
|
|
| 314 |
- t.Error(err) |
|
| 315 |
- } |
|
| 316 |
- if len(v) != 3 {
|
|
| 317 |
- t.Fatal("expected 3 args; got ", len(v))
|
|
| 318 |
- } |
|
| 319 |
- expect := "[1 2 3]" |
|
| 320 |
- if v.String() != expect {
|
|
| 321 |
- t.Errorf("expected value %q got %q", expect, v.String())
|
|
| 322 |
- } |
|
| 323 |
-} |
|
| 324 |
- |
|
| 325 |
-// Declare a user-defined boolean flag type. |
|
| 326 |
-type boolFlagVar struct {
|
|
| 327 |
- count int |
|
| 328 |
-} |
|
| 329 |
- |
|
| 330 |
-func (b *boolFlagVar) String() string {
|
|
| 331 |
- return fmt.Sprintf("%d", b.count)
|
|
| 332 |
-} |
|
| 333 |
- |
|
| 334 |
-func (b *boolFlagVar) Set(value string) error {
|
|
| 335 |
- if value == "true" {
|
|
| 336 |
- b.count++ |
|
| 337 |
- } |
|
| 338 |
- return nil |
|
| 339 |
-} |
|
| 340 |
- |
|
| 341 |
-func (b *boolFlagVar) IsBoolFlag() bool {
|
|
| 342 |
- return b.count < 4 |
|
| 343 |
-} |
|
| 344 |
- |
|
| 345 |
-func TestUserDefinedBool(t *testing.T) {
|
|
| 346 |
- var flags FlagSet |
|
| 347 |
- flags.Init("test", ContinueOnError)
|
|
| 348 |
- var b boolFlagVar |
|
| 349 |
- var err error |
|
| 350 |
- flags.Var(&b, []string{"b"}, "usage")
|
|
| 351 |
- if err = flags.Parse([]string{"-b", "-b", "-b", "-b=true", "-b=false", "-b", "barg", "-b"}); err != nil {
|
|
| 352 |
- if b.count < 4 {
|
|
| 353 |
- t.Error(err) |
|
| 354 |
- } |
|
| 355 |
- } |
|
| 356 |
- |
|
| 357 |
- if b.count != 4 {
|
|
| 358 |
- t.Errorf("want: %d; got: %d", 4, b.count)
|
|
| 359 |
- } |
|
| 360 |
- |
|
| 361 |
- if err == nil {
|
|
| 362 |
- t.Error("expected error; got none")
|
|
| 363 |
- } |
|
| 364 |
-} |
|
| 365 |
- |
|
| 366 |
-func TestSetOutput(t *testing.T) {
|
|
| 367 |
- var flags FlagSet |
|
| 368 |
- var buf bytes.Buffer |
|
| 369 |
- flags.SetOutput(&buf) |
|
| 370 |
- flags.Init("test", ContinueOnError)
|
|
| 371 |
- flags.Parse([]string{"-unknown"})
|
|
| 372 |
- if out := buf.String(); !strings.Contains(out, "-unknown") {
|
|
| 373 |
- t.Logf("expected output mentioning unknown; got %q", out)
|
|
| 374 |
- } |
|
| 375 |
-} |
|
| 376 |
- |
|
| 377 |
-// This tests that one can reset the flags. This still works but not well, and is |
|
| 378 |
-// superseded by FlagSet. |
|
| 379 |
-func TestChangingArgs(t *testing.T) {
|
|
| 380 |
- ResetForTesting(func() { t.Fatal("bad parse") })
|
|
| 381 |
- oldArgs := os.Args |
|
| 382 |
- defer func() { os.Args = oldArgs }()
|
|
| 383 |
- os.Args = []string{"cmd", "-before", "subcmd", "-after", "args"}
|
|
| 384 |
- before := Bool([]string{"before"}, false, "")
|
|
| 385 |
- if err := CommandLine.Parse(os.Args[1:]); err != nil {
|
|
| 386 |
- t.Fatal(err) |
|
| 387 |
- } |
|
| 388 |
- cmd := Arg(0) |
|
| 389 |
- os.Args = Args() |
|
| 390 |
- after := Bool([]string{"after"}, false, "")
|
|
| 391 |
- Parse() |
|
| 392 |
- args := Args() |
|
| 393 |
- |
|
| 394 |
- if !*before || cmd != "subcmd" || !*after || len(args) != 1 || args[0] != "args" {
|
|
| 395 |
- t.Fatalf("expected true subcmd true [args] got %v %v %v %v", *before, cmd, *after, args)
|
|
| 396 |
- } |
|
| 397 |
-} |
|
| 398 |
- |
|
| 399 |
-// Test that -help invokes the usage message and returns ErrHelp. |
|
| 400 |
-func TestHelp(t *testing.T) {
|
|
| 401 |
- var helpCalled = false |
|
| 402 |
- fs := NewFlagSet("help test", ContinueOnError)
|
|
| 403 |
- fs.Usage = func() { helpCalled = true }
|
|
| 404 |
- var flag bool |
|
| 405 |
- fs.BoolVar(&flag, []string{"flag"}, false, "regular flag")
|
|
| 406 |
- // Regular flag invocation should work |
|
| 407 |
- err := fs.Parse([]string{"-flag=true"})
|
|
| 408 |
- if err != nil {
|
|
| 409 |
- t.Fatal("expected no error; got ", err)
|
|
| 410 |
- } |
|
| 411 |
- if !flag {
|
|
| 412 |
- t.Error("flag was not set by -flag")
|
|
| 413 |
- } |
|
| 414 |
- if helpCalled {
|
|
| 415 |
- t.Error("help called for regular flag")
|
|
| 416 |
- helpCalled = false // reset for next test |
|
| 417 |
- } |
|
| 418 |
- // Help flag should work as expected. |
|
| 419 |
- err = fs.Parse([]string{"-help"})
|
|
| 420 |
- if err == nil {
|
|
| 421 |
- t.Fatal("error expected")
|
|
| 422 |
- } |
|
| 423 |
- if err != ErrHelp {
|
|
| 424 |
- t.Fatal("expected ErrHelp; got ", err)
|
|
| 425 |
- } |
|
| 426 |
- if !helpCalled {
|
|
| 427 |
- t.Fatal("help was not called")
|
|
| 428 |
- } |
|
| 429 |
- // If we define a help flag, that should override. |
|
| 430 |
- var help bool |
|
| 431 |
- fs.BoolVar(&help, []string{"help"}, false, "help flag")
|
|
| 432 |
- helpCalled = false |
|
| 433 |
- err = fs.Parse([]string{"-help"})
|
|
| 434 |
- if err != nil {
|
|
| 435 |
- t.Fatal("expected no error for defined -help; got ", err)
|
|
| 436 |
- } |
|
| 437 |
- if helpCalled {
|
|
| 438 |
- t.Fatal("help was called; should not have been for defined help flag")
|
|
| 439 |
- } |
|
| 440 |
-} |
|
| 441 |
- |
|
| 442 |
-// Test the flag count functions. |
|
| 443 |
-func TestFlagCounts(t *testing.T) {
|
|
| 444 |
- fs := NewFlagSet("help test", ContinueOnError)
|
|
| 445 |
- var flag bool |
|
| 446 |
- fs.BoolVar(&flag, []string{"flag1"}, false, "regular flag")
|
|
| 447 |
- fs.BoolVar(&flag, []string{"#deprecated1"}, false, "regular flag")
|
|
| 448 |
- fs.BoolVar(&flag, []string{"f", "flag2"}, false, "regular flag")
|
|
| 449 |
- fs.BoolVar(&flag, []string{"#d", "#deprecated2"}, false, "regular flag")
|
|
| 450 |
- fs.BoolVar(&flag, []string{"flag3"}, false, "regular flag")
|
|
| 451 |
- fs.BoolVar(&flag, []string{"g", "#flag4", "-flag4"}, false, "regular flag")
|
|
| 452 |
- |
|
| 453 |
- if fs.FlagCount() != 6 {
|
|
| 454 |
- t.Fatal("FlagCount wrong. ", fs.FlagCount())
|
|
| 455 |
- } |
|
| 456 |
- if fs.FlagCountUndeprecated() != 4 {
|
|
| 457 |
- t.Fatal("FlagCountUndeprecated wrong. ", fs.FlagCountUndeprecated())
|
|
| 458 |
- } |
|
| 459 |
- if fs.NFlag() != 0 {
|
|
| 460 |
- t.Fatal("NFlag wrong. ", fs.NFlag())
|
|
| 461 |
- } |
|
| 462 |
- err := fs.Parse([]string{"-fd", "-g", "-flag4"})
|
|
| 463 |
- if err != nil {
|
|
| 464 |
- t.Fatal("expected no error for defined -help; got ", err)
|
|
| 465 |
- } |
|
| 466 |
- if fs.NFlag() != 4 {
|
|
| 467 |
- t.Fatal("NFlag wrong. ", fs.NFlag())
|
|
| 468 |
- } |
|
| 469 |
-} |
|
| 470 |
- |
|
| 471 |
-// Show up bug in sortFlags |
|
| 472 |
-func TestSortFlags(t *testing.T) {
|
|
| 473 |
- fs := NewFlagSet("help TestSortFlags", ContinueOnError)
|
|
| 474 |
- |
|
| 475 |
- var err error |
|
| 476 |
- |
|
| 477 |
- var b bool |
|
| 478 |
- fs.BoolVar(&b, []string{"b", "-banana"}, false, "usage")
|
|
| 479 |
- |
|
| 480 |
- err = fs.Parse([]string{"--banana=true"})
|
|
| 481 |
- if err != nil {
|
|
| 482 |
- t.Fatal("expected no error; got ", err)
|
|
| 483 |
- } |
|
| 484 |
- |
|
| 485 |
- count := 0 |
|
| 486 |
- |
|
| 487 |
- fs.VisitAll(func(flag *Flag) {
|
|
| 488 |
- count++ |
|
| 489 |
- if flag == nil {
|
|
| 490 |
- t.Fatal("VisitAll should not return a nil flag")
|
|
| 491 |
- } |
|
| 492 |
- }) |
|
| 493 |
- flagcount := fs.FlagCount() |
|
| 494 |
- if flagcount != count {
|
|
| 495 |
- t.Fatalf("FlagCount (%d) != number (%d) of elements visited", flagcount, count)
|
|
| 496 |
- } |
|
| 497 |
- // Make sure its idempotent |
|
| 498 |
- if flagcount != fs.FlagCount() {
|
|
| 499 |
- t.Fatalf("FlagCount (%d) != fs.FlagCount() (%d) of elements visited", flagcount, fs.FlagCount())
|
|
| 500 |
- } |
|
| 501 |
- |
|
| 502 |
- count = 0 |
|
| 503 |
- fs.Visit(func(flag *Flag) {
|
|
| 504 |
- count++ |
|
| 505 |
- if flag == nil {
|
|
| 506 |
- t.Fatal("Visit should not return a nil flag")
|
|
| 507 |
- } |
|
| 508 |
- }) |
|
| 509 |
- nflag := fs.NFlag() |
|
| 510 |
- if nflag != count {
|
|
| 511 |
- t.Fatalf("NFlag (%d) != number (%d) of elements visited", nflag, count)
|
|
| 512 |
- } |
|
| 513 |
- if nflag != fs.NFlag() {
|
|
| 514 |
- t.Fatalf("NFlag (%d) != fs.NFlag() (%d) of elements visited", nflag, fs.NFlag())
|
|
| 515 |
- } |
|
| 516 |
-} |
|
| 517 |
- |
|
| 518 |
-func TestMergeFlags(t *testing.T) {
|
|
| 519 |
- base := NewFlagSet("base", ContinueOnError)
|
|
| 520 |
- base.String([]string{"f"}, "", "")
|
|
| 521 |
- |
|
| 522 |
- fs := NewFlagSet("test", ContinueOnError)
|
|
| 523 |
- Merge(fs, base) |
|
| 524 |
- if len(fs.formal) != 1 {
|
|
| 525 |
- t.Fatalf("FlagCount (%d) != number (1) of elements merged", len(fs.formal))
|
|
| 526 |
- } |
|
| 527 |
-} |
| ... | ... |
@@ -3,7 +3,7 @@ |
| 3 | 3 |
package registry |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
- flag "github.com/docker/docker/pkg/mflag" |
|
| 6 |
+ "github.com/spf13/pflag" |
|
| 7 | 7 |
) |
| 8 | 8 |
|
| 9 | 9 |
var ( |
| ... | ... |
@@ -20,6 +20,6 @@ func cleanPath(s string) string {
|
| 20 | 20 |
} |
| 21 | 21 |
|
| 22 | 22 |
// installCliPlatformFlags handles any platform specific flags for the service. |
| 23 |
-func (options *ServiceOptions) installCliPlatformFlags(flags *flag.FlagSet) string) {
|
|
| 23 |
+func (options *ServiceOptions) installCliPlatformFlags(flags *pflag.FlagSet) {
|
|
| 24 | 24 |
flags.BoolVar(&options.V2Only, "disable-legacy-registry", false, "Disable contacting legacy registries") |
| 25 | 25 |
} |
| ... | ... |
@@ -5,7 +5,7 @@ import ( |
| 5 | 5 |
"path/filepath" |
| 6 | 6 |
"strings" |
| 7 | 7 |
|
| 8 |
- flag "github.com/docker/docker/pkg/mflag" |
|
| 8 |
+ "github.com/spf13/pflag" |
|
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
// CertsDir is the directory where certificates are stored |
| ... | ... |
@@ -20,6 +20,6 @@ func cleanPath(s string) string {
|
| 20 | 20 |
} |
| 21 | 21 |
|
| 22 | 22 |
// installCliPlatformFlags handles any platform specific flags for the service. |
| 23 |
-func (options *ServiceOptions) installCliPlatformFlags(flags *flag.FlagSet) string) {
|
|
| 23 |
+func (options *ServiceOptions) installCliPlatformFlags(flags *pflag.FlagSet) {
|
|
| 24 | 24 |
// No Windows specific flags. |
| 25 | 25 |
} |