From 1b00a2d5b6e4561591f54ae140912587e0b82727 Mon Sep 17 00:00:00 2001 From: Andrey Kurilin Date: Mon, 1 Aug 2016 16:58:49 +0300 Subject: [PATCH] Update github.com/spf13/pflag and github.com/spf13/cobra Update: github.com/spf13/cobra to f62e98d28ab7ad31d707ba837a966378465c7b57 github.com/spf13/cobra/doc to f62e98d28ab7ad31d707ba837a966378465c7b57 github.com/spf13/pflag to 1560c1005499d61b80f865c04d39ca7505bf7f0b Closes issue #29852 --- Godeps/Godeps.json | 6 +- cmd/hyperkube/hyperkube_test.go | 4 +- contrib/mesos/cmd/km/hyperkube_test.go | 4 +- vendor/github.com/spf13/cobra/.gitignore | 12 ++ vendor/github.com/spf13/cobra/.travis.yml | 11 +- vendor/github.com/spf13/cobra/README.md | 23 ++- .../spf13/cobra/bash_completions.go | 42 +++- .../spf13/cobra/bash_completions.md | 4 +- vendor/github.com/spf13/cobra/cobra.go | 4 + vendor/github.com/spf13/cobra/command.go | 189 ++++++++++++------ vendor/github.com/spf13/cobra/doc/man_docs.go | 83 ++++---- vendor/github.com/spf13/pflag/.travis.yml | 7 +- vendor/github.com/spf13/pflag/README.md | 21 +- vendor/github.com/spf13/pflag/flag.go | 134 +++++++++++-- vendor/github.com/spf13/pflag/golangflag.go | 7 + 15 files changed, 410 insertions(+), 141 deletions(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 642d97ebe5446..57113a1b33278 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1964,15 +1964,15 @@ }, { "ImportPath": "github.com/spf13/cobra", - "Rev": "4c05eb1145f16d0e6bb4a3e1b6d769f4713cb41f" + "Rev": "f62e98d28ab7ad31d707ba837a966378465c7b57" }, { "ImportPath": "github.com/spf13/cobra/doc", - "Rev": "4c05eb1145f16d0e6bb4a3e1b6d769f4713cb41f" + "Rev": "f62e98d28ab7ad31d707ba837a966378465c7b57" }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "08b1a584251b5b62f458943640fc8ebd4d50aaa5" + "Rev": "1560c1005499d61b80f865c04d39ca7505bf7f0b" }, { "ImportPath": "github.com/stretchr/objx", diff --git a/cmd/hyperkube/hyperkube_test.go b/cmd/hyperkube/hyperkube_test.go index 3a864331970e5..d82a1845c30a1 100644 --- a/cmd/hyperkube/hyperkube_test.go +++ b/cmd/hyperkube/hyperkube_test.go @@ -177,7 +177,7 @@ func TestServerHelp(t *testing.T) { x := runFull(t, "hyperkube test1 --help") assert.NoError(t, x.err) assert.Contains(t, x.output, "A simple server named test1") - assert.Contains(t, x.output, "--help[=false]: help for hyperkube") + assert.Contains(t, x.output, "-h, --help help for hyperkube") assert.NotContains(t, x.output, "test1 Run") } @@ -185,7 +185,7 @@ func TestServerFlagsBad(t *testing.T) { x := runFull(t, "hyperkube test1 --bad-flag") assert.EqualError(t, x.err, "unknown flag: --bad-flag") assert.Contains(t, x.output, "A simple server named test1") - assert.Contains(t, x.output, "--help[=false]: help for hyperkube") + assert.Contains(t, x.output, "-h, --help help for hyperkube") assert.NotContains(t, x.output, "test1 Run") } diff --git a/contrib/mesos/cmd/km/hyperkube_test.go b/contrib/mesos/cmd/km/hyperkube_test.go index e06f931d56fdd..439fd8bf39fc5 100644 --- a/contrib/mesos/cmd/km/hyperkube_test.go +++ b/contrib/mesos/cmd/km/hyperkube_test.go @@ -125,7 +125,7 @@ func TestServerHelp(t *testing.T) { x := runFull(t, "hyperkube test1 --help") assert.NoError(t, x.err) assert.Contains(t, x.output, "A simple server named test1") - assert.Contains(t, x.output, "--help[=false]: help for hyperkube") + assert.Contains(t, x.output, "-h, --help help for hyperkube") assert.NotContains(t, x.output, "test1 Run") } @@ -133,7 +133,7 @@ func TestServerFlagsBad(t *testing.T) { x := runFull(t, "hyperkube test1 --bad-flag") assert.EqualError(t, x.err, "unknown flag: --bad-flag") assert.Contains(t, x.output, "A simple server named test1") - assert.Contains(t, x.output, "--help[=false]: help for hyperkube") + assert.Contains(t, x.output, "-h, --help help for hyperkube") assert.NotContains(t, x.output, "test1 Run") } diff --git a/vendor/github.com/spf13/cobra/.gitignore b/vendor/github.com/spf13/cobra/.gitignore index 36d1a84d392e0..1b8c7c2611674 100644 --- a/vendor/github.com/spf13/cobra/.gitignore +++ b/vendor/github.com/spf13/cobra/.gitignore @@ -19,6 +19,18 @@ _cgo_export.* _testmain.go +# Vim files https://github.com/github/gitignore/blob/master/Global/Vim.gitignore +# swap +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +# session +Session.vim +# temporary +.netrwhist +*~ +# auto-generated tag files +tags + *.exe cobra.test diff --git a/vendor/github.com/spf13/cobra/.travis.yml b/vendor/github.com/spf13/cobra/.travis.yml index e11869ba320ed..6e84be54d16db 100644 --- a/vendor/github.com/spf13/cobra/.travis.yml +++ b/vendor/github.com/spf13/cobra/.travis.yml @@ -1,9 +1,14 @@ language: go go: - - 1.3.3 - - 1.4.2 - - 1.5.1 + - 1.4.3 + - 1.5.4 + - 1.6.3 - tip + +matrix: + allow_failures: + - go: tip + before_install: - mkdir -p bin - curl -Lso bin/shellcheck https://github.com/caarlos0/shellcheck-docker/releases/download/v0.4.3/shellcheck diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md index f326c7fa8439d..b338a0e4424a2 100644 --- a/vendor/github.com/spf13/cobra/README.md +++ b/vendor/github.com/spf13/cobra/README.md @@ -22,6 +22,7 @@ Many of the most widely used Go projects are built using Cobra including: [![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra) [![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra) +[![GoDoc](https://godoc.org/github.com/spf13/cobra?status.svg)](https://godoc.org/github.com/spf13/cobra) ![cobra](https://cloud.githubusercontent.com/assets/173412/10911369/84832a8e-8212-11e5-9f82-cc96660a4794.gif) @@ -171,6 +172,12 @@ func main() { Cobra provides its own program that will create your application and add any commands you want. It's the easiest way to incorporate Cobra into your application. +In order to use the cobra command, compile it using the following command: + + > go install github.com/spf13/cobra/cobra + +This will create the cobra executable under your go path bin directory! + ### cobra init The `cobra init [yourApp]` command will create your initial application code @@ -226,13 +233,27 @@ The cobra generator will be easier to use if you provide a simple configuration file which will help you eliminate providing a bunch of repeated information in flags over and over. -an example ~/.cobra.yaml file: +An example ~/.cobra.yaml file: ```yaml author: Steve Francia license: MIT ``` +You can specify no license by setting `license` to `none` or you can specify +a custom license: + +```yaml +license: + header: This file is part of {{ .appName }}. + text: | + {{ .copyright }} + + This is my license. There are many like it, but this one is mine. + My license is my best friend. It is my life. I must master it as I must + master my life. +``` + ## Manually implementing Cobra To manually implement cobra you need to create a bare main.go file and a RootCmd file. diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go index 3f33bb0ec8ec1..236dee67f2117 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.go +++ b/vendor/github.com/spf13/cobra/bash_completions.go @@ -116,12 +116,12 @@ __handle_reply() fi local completions - if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then - completions=("${must_have_one_flag[@]}") - elif [[ ${#must_have_one_noun[@]} -ne 0 ]]; then + completions=("${commands[@]}") + if [[ ${#must_have_one_noun[@]} -ne 0 ]]; then completions=("${must_have_one_noun[@]}") - else - completions=("${commands[@]}") + fi + if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then + completions+=("${must_have_one_flag[@]}") fi COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") ) @@ -167,6 +167,11 @@ __handle_flag() must_have_one_flag=() fi + # if you set a flag which only applies to this command, don't show subcommands + if __contains_word "${flagname}" "${local_nonpersistent_flags[@]}"; then + commands=() + fi + # keep flag value with flagname as flaghash if [ -n "${flagvalue}" ] ; then flaghash[${flagname}]=${flagvalue} @@ -263,6 +268,7 @@ func postscript(w io.Writer, name string) error { local c=0 local flags=() local two_word_flags=() + local local_nonpersistent_flags=() local flags_with_completion=() local flags_completion=() local commands=("%s") @@ -360,7 +366,7 @@ func writeFlagHandler(name string, annotations map[string][]string, w io.Writer) } func writeShortFlag(flag *pflag.Flag, w io.Writer) error { - b := (flag.Value.Type() == "bool") + b := (len(flag.NoOptDefVal) > 0) name := flag.Shorthand format := " " if !b { @@ -374,7 +380,7 @@ func writeShortFlag(flag *pflag.Flag, w io.Writer) error { } func writeFlag(flag *pflag.Flag, w io.Writer) error { - b := (flag.Value.Type() == "bool") + b := (len(flag.NoOptDefVal) > 0) name := flag.Name format := " flags+=(\"--%s" if !b { @@ -387,9 +393,24 @@ func writeFlag(flag *pflag.Flag, w io.Writer) error { return writeFlagHandler("--"+name, flag.Annotations, w) } +func writeLocalNonPersistentFlag(flag *pflag.Flag, w io.Writer) error { + b := (len(flag.NoOptDefVal) > 0) + name := flag.Name + format := " local_nonpersistent_flags+=(\"--%s" + if !b { + format += "=" + } + format += "\")\n" + if _, err := fmt.Fprintf(w, format, name); err != nil { + return err + } + return nil +} + func writeFlags(cmd *Command, w io.Writer) error { _, err := fmt.Fprintf(w, ` flags=() two_word_flags=() + local_nonpersistent_flags=() flags_with_completion=() flags_completion=() @@ -397,6 +418,7 @@ func writeFlags(cmd *Command, w io.Writer) error { if err != nil { return err } + localNonPersistentFlags := cmd.LocalNonPersistentFlags() var visitErr error cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { if err := writeFlag(flag, w); err != nil { @@ -409,6 +431,12 @@ func writeFlags(cmd *Command, w io.Writer) error { return } } + if localNonPersistentFlags.Lookup(flag.Name) != nil { + if err := writeLocalNonPersistentFlag(flag, w); err != nil { + visitErr = err + return + } + } }) if visitErr != nil { return visitErr diff --git a/vendor/github.com/spf13/cobra/bash_completions.md b/vendor/github.com/spf13/cobra/bash_completions.md index 84d5b012f412c..6e3b71f13d518 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.md +++ b/vendor/github.com/spf13/cobra/bash_completions.md @@ -117,7 +117,7 @@ cmd := &cobra.Command{ ``` The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by -the completion aglorithm if entered manually, e.g. in: +the completion algorithm if entered manually, e.g. in: ```bash # kubectl get rc [tab][tab] @@ -175,7 +175,7 @@ So while there are many other files in the CWD it only shows me subdirs and thos # Specifiy custom flag completion -Similar to the filename completion and filtering usingn cobra.BashCompFilenameExt, you can specifiy +Similar to the filename completion and filtering using cobra.BashCompFilenameExt, you can specifiy a custom flag completion function with cobra.BashCompCustom: ```go diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go index 0c4e2e5de11e2..93a2c0f3a77d7 100644 --- a/vendor/github.com/spf13/cobra/cobra.go +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -41,6 +41,10 @@ var initializers []func() // Set this to true to enable it var EnablePrefixMatching = false +//EnableCommandSorting controls sorting of the slice of commands, which is turned on by default. +//To disable sorting, set it to false. +var EnableCommandSorting = true + //AddTemplateFunc adds a template function that's available to Usage and Help //template generation. func AddTemplateFunc(name string, tmplFunc interface{}) { diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go index 0efeeb1957590..083e4ea7f47b5 100644 --- a/vendor/github.com/spf13/cobra/command.go +++ b/vendor/github.com/spf13/cobra/command.go @@ -21,6 +21,7 @@ import ( "io" "os" "path/filepath" + "sort" "strings" flag "github.com/spf13/pflag" @@ -103,11 +104,13 @@ type Command struct { commandsMaxUseLen int commandsMaxCommandPathLen int commandsMaxNameLen int + // is commands slice are sorted or not + commandsAreSorted bool flagErrorBuf *bytes.Buffer args []string // actual args parsed from flags - output *io.Writer // nil means stderr; use Out() method instead + output *io.Writer // out writer if set in SetOutput(w) usageFunc func(*Command) error // Usage can be defined by application usageTemplate string // Can be defined by Application helpTemplate string // Can be defined by Application @@ -120,6 +123,9 @@ type Command struct { DisableSuggestions bool // If displaying suggestions, allows to set the minimum levenshtein distance to display, must be > 0 SuggestionsMinimumDistance int + + // Disable the flag parsing. If this is true all flags will be passed to the command as arguments. + DisableFlagParsing bool } // os.Args[1:] by default, if desired, can be overridden @@ -128,25 +134,6 @@ func (c *Command) SetArgs(a []string) { c.args = a } -func (c *Command) getOut(def io.Writer) io.Writer { - if c.output != nil { - return *c.output - } - - if c.HasParent() { - return c.parent.Out() - } - return def -} - -func (c *Command) Out() io.Writer { - return c.getOut(os.Stderr) -} - -func (c *Command) getOutOrStdout() io.Writer { - return c.getOut(os.Stdout) -} - // SetOutput sets the destination for usage and error messages. // If output is nil, os.Stderr is used. func (c *Command) SetOutput(output io.Writer) { @@ -189,6 +176,26 @@ func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string } } +func (c *Command) OutOrStdout() io.Writer { + return c.getOut(os.Stdout) +} + +func (c *Command) OutOrStderr() io.Writer { + return c.getOut(os.Stderr) +} + +func (c *Command) getOut(def io.Writer) io.Writer { + if c.output != nil { + return *c.output + } + if c.HasParent() { + return c.parent.getOut(def) + } + return def +} + +// UsageFunc returns either the function set by SetUsageFunc for this command +// or a parent, or it returns a default usage function func (c *Command) UsageFunc() (f func(*Command) error) { if c.usageFunc != nil { return c.usageFunc @@ -198,16 +205,24 @@ func (c *Command) UsageFunc() (f func(*Command) error) { return c.parent.UsageFunc() } return func(c *Command) error { - err := tmpl(c.Out(), c.UsageTemplate(), c) + c.mergePersistentFlags() + err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c) if err != nil { - fmt.Print(err) + c.Println(err) } return err } } +// Output the usage for the command +// Used when a user provides invalid input +// Can be defined by user by overriding UsageFunc +func (c *Command) Usage() error { + return c.UsageFunc()(c) +} + // HelpFunc returns either the function set by SetHelpFunc for this command -// or a parent, or it returns a function which calls c.Help() +// or a parent, or it returns a function with default help behavior func (c *Command) HelpFunc() func(*Command, []string) { cmd := c for cmd != nil { @@ -217,13 +232,31 @@ func (c *Command) HelpFunc() func(*Command, []string) { cmd = cmd.parent } return func(*Command, []string) { - err := c.Help() + c.mergePersistentFlags() + err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c) if err != nil { c.Println(err) } } } +// Output the help for the command +// Used when a user calls help [command] +// Can be defined by user by overriding HelpFunc +func (c *Command) Help() error { + c.HelpFunc()(c, []string{}) + return nil +} + +func (c *Command) UsageString() string { + tmpOutput := c.output + bb := new(bytes.Buffer) + c.SetOutput(bb) + c.Usage() + c.output = tmpOutput + return bb.String() +} + var minUsagePadding = 25 func (c *Command) UsagePadding() int { @@ -261,7 +294,7 @@ func (c *Command) UsageTemplate() string { return c.parent.UsageTemplate() } return `Usage:{{if .Runnable}} - {{if .HasFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasSubCommands}} + {{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}} {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}} Aliases: @@ -272,16 +305,16 @@ Examples: {{ .Example }}{{end}}{{ if .HasAvailableSubCommands}} Available Commands:{{range .Commands}}{{if .IsAvailableCommand}} - {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasLocalFlags}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}} Flags: -{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasInheritedFlags}} +{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}} Global Flags: {{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}} Additional help topics:{{range .Commands}}{{if .IsHelpCommand}} - {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasSubCommands }} + {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }} Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}} ` @@ -531,12 +564,17 @@ func (c *Command) execute(a []string) (err error) { c.Println("\"help\" flag declared as non-bool. Please correct your code") return err } + if helpVal || !c.Runnable() { return flag.ErrHelp } c.preRun() + argWoFlags := c.Flags().Args() + if c.DisableFlagParsing { + argWoFlags = a + } for p := c; p != nil; p = p.Parent() { if p.PersistentPreRunE != nil { @@ -699,8 +737,7 @@ func (c *Command) initHelpCmd() { c.Printf("Unknown help topic %#q.", args) c.Root().Usage() } else { - helpFunc := cmd.HelpFunc() - helpFunc(cmd, args) + cmd.Help() } }, } @@ -714,8 +751,20 @@ func (c *Command) ResetCommands() { c.helpCommand = nil } -//Commands returns a slice of child commands. +// Sorts commands by their names +type commandSorterByName []*Command + +func (c commandSorterByName) Len() int { return len(c) } +func (c commandSorterByName) Swap(i, j int) { c[i], c[j] = c[j], c[i] } +func (c commandSorterByName) Less(i, j int) bool { return c[i].Name() < c[j].Name() } + +// Commands returns a sorted slice of child commands. func (c *Command) Commands() []*Command { + // do not sort commands if it already sorted or sorting was disabled + if EnableCommandSorting && !c.commandsAreSorted { + sort.Sort(commandSorterByName(c.commands)) + c.commandsAreSorted = true + } return c.commands } @@ -744,10 +793,11 @@ func (c *Command) AddCommand(cmds ...*Command) { x.SetGlobalNormalizationFunc(c.globNormFunc) } c.commands = append(c.commands, x) + c.commandsAreSorted = false } } -// AddCommand removes one or more commands from a parent command. +// RemoveCommand removes one or more commands from a parent command. func (c *Command) RemoveCommand(cmds ...*Command) { commands := []*Command{} main: @@ -781,50 +831,23 @@ main: } } -// Print is a convenience method to Print to the defined output +// Print is a convenience method to Print to the defined output, fallback to Stderr if not set func (c *Command) Print(i ...interface{}) { - fmt.Fprint(c.Out(), i...) + fmt.Fprint(c.OutOrStderr(), i...) } -// Println is a convenience method to Println to the defined output +// Println is a convenience method to Println to the defined output, fallback to Stderr if not set func (c *Command) Println(i ...interface{}) { str := fmt.Sprintln(i...) c.Print(str) } -// Printf is a convenience method to Printf to the defined output +// Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set func (c *Command) Printf(format string, i ...interface{}) { str := fmt.Sprintf(format, i...) c.Print(str) } -// Output the usage for the command -// Used when a user provides invalid input -// Can be defined by user by overriding UsageFunc -func (c *Command) Usage() error { - c.mergePersistentFlags() - err := c.UsageFunc()(c) - return err -} - -// Output the help for the command -// Used when a user calls help [command] -// by the default HelpFunc in the commander -func (c *Command) Help() error { - c.mergePersistentFlags() - err := tmpl(c.getOutOrStdout(), c.HelpTemplate(), c) - return err -} - -func (c *Command) UsageString() string { - tmpOutput := c.output - bb := new(bytes.Buffer) - c.SetOutput(bb) - c.Usage() - c.output = tmpOutput - return bb.String() -} - // CommandPath returns the full path to this command. func (c *Command) CommandPath() string { str := c.Name() @@ -1025,6 +1048,19 @@ func (c *Command) Flags() *flag.FlagSet { return c.flags } +// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands +func (c *Command) LocalNonPersistentFlags() *flag.FlagSet { + persistentFlags := c.PersistentFlags() + + out := flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.LocalFlags().VisitAll(func(f *flag.Flag) { + if persistentFlags.Lookup(f.Name) == nil { + out.AddFlag(f) + } + }) + return out +} + // Get the local FlagSet specifically set in the current command func (c *Command) LocalFlags() *flag.FlagSet { c.mergePersistentFlags() @@ -1114,10 +1150,34 @@ func (c *Command) HasLocalFlags() bool { return c.LocalFlags().HasFlags() } +// Does the command have flags inherited from its parent command func (c *Command) HasInheritedFlags() bool { return c.InheritedFlags().HasFlags() } +// Does the command contain any flags (local plus persistent from the entire +// structure) which are not hidden or deprecated +func (c *Command) HasAvailableFlags() bool { + return c.Flags().HasAvailableFlags() +} + +// Does the command contain persistent flags which are not hidden or deprecated +func (c *Command) HasAvailablePersistentFlags() bool { + return c.PersistentFlags().HasAvailableFlags() +} + +// Does the command has flags specifically declared locally which are not hidden +// or deprecated +func (c *Command) HasAvailableLocalFlags() bool { + return c.LocalFlags().HasAvailableFlags() +} + +// Does the command have flags inherited from its parent command which are +// not hidden or deprecated +func (c *Command) HasAvailableInheritedFlags() bool { + return c.InheritedFlags().HasAvailableFlags() +} + // Flag climbs up the command tree looking for matching flag func (c *Command) Flag(name string) (flag *flag.Flag) { flag = c.Flags().Lookup(name) @@ -1143,6 +1203,9 @@ func (c *Command) persistentFlag(name string) (flag *flag.Flag) { // ParseFlags parses persistent flag tree & local flags func (c *Command) ParseFlags(args []string) (err error) { + if c.DisableFlagParsing { + return nil + } c.mergePersistentFlags() err = c.Flags().Parse(args) return diff --git a/vendor/github.com/spf13/cobra/doc/man_docs.go b/vendor/github.com/spf13/cobra/doc/man_docs.go index a98674bf3aa3e..b202029d1e0c1 100644 --- a/vendor/github.com/spf13/cobra/doc/man_docs.go +++ b/vendor/github.com/spf13/cobra/doc/man_docs.go @@ -28,12 +28,23 @@ import ( "github.com/spf13/pflag" ) -// GenManTree will generate a man page for this command and all decendants +// GenManTree will generate a man page for this command and all descendants // in the directory given. The header may be nil. This function may not work // correctly if your command names have - in them. If you have `cmd` with two // subcmds, `sub` and `sub-third`. And `sub` has a subcommand called `third` // it is undefined which help output will be in the file `cmd-sub-third.1`. func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error { + return GenManTreeFromOpts(cmd, GenManTreeOptions{ + Header: header, + Path: dir, + CommandSeparator: "_", + }) +} + +// GenManTreeFromOpts generates a man page for the command and all descendants. +// The pages are written to the opts.Path directory. +func GenManTreeFromOpts(cmd *cobra.Command, opts GenManTreeOptions) error { + header := opts.Header if header == nil { header = &GenManHeader{} } @@ -41,28 +52,35 @@ func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error { if !c.IsAvailableCommand() || c.IsHelpCommand() { continue } - if err := GenManTree(c, header, dir); err != nil { + if err := GenManTreeFromOpts(c, opts); err != nil { return err } } - needToResetTitle := header.Title == "" + section := "1" + if header.Section != "" { + section = header.Section + } - basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".1" - filename := filepath.Join(dir, basename) + separator := "_" + if opts.CommandSeparator != "" { + separator = opts.CommandSeparator + } + basename := strings.Replace(cmd.CommandPath(), " ", separator, -1) + filename := filepath.Join(opts.Path, basename + "." + section) f, err := os.Create(filename) if err != nil { return err } defer f.Close() - if err := GenMan(cmd, header, f); err != nil { - return err - } + headerCopy := *header + return GenMan(cmd, &headerCopy, f) +} - if needToResetTitle { - header.Title = "" - } - return nil +type GenManTreeOptions struct { + Header *GenManHeader + Path string + CommandSeparator string } // GenManHeader is a lot like the .TH header at the start of man pages. These @@ -84,9 +102,10 @@ func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error { if header == nil { header = &GenManHeader{} } + fillHeader(header, cmd.CommandPath()) + b := genMan(cmd, header) - final := mangen.Render(b) - _, err := w.Write(final) + _, err := w.Write(mangen.Render(b)) return err } @@ -107,18 +126,22 @@ func fillHeader(header *GenManHeader, name string) { } } -func manPreamble(out io.Writer, header *GenManHeader, name, short, long string) { - dashName := strings.Replace(name, " ", "-", -1) +func manPreamble(out io.Writer, header *GenManHeader, cmd *cobra.Command, dashedName string) { + description := cmd.Long + if len(description) == 0 { + description = cmd.Short + } + fmt.Fprintf(out, `%% %s(%s)%s %% %s %% %s # NAME `, header.Title, header.Section, header.date, header.Source, header.Manual) - fmt.Fprintf(out, "%s \\- %s\n\n", dashName, short) + fmt.Fprintf(out, "%s \\- %s\n\n", dashedName, cmd.Short) fmt.Fprintf(out, "# SYNOPSIS\n") - fmt.Fprintf(out, "**%s** [OPTIONS]\n\n", name) + fmt.Fprintf(out, "**%s**\n\n", cmd.UseLine()) fmt.Fprintf(out, "# DESCRIPTION\n") - fmt.Fprintf(out, "%s\n\n", long) + fmt.Fprintf(out, "%s\n\n", description) } func manPrintFlags(out io.Writer, flags *pflag.FlagSet) { @@ -127,10 +150,10 @@ func manPrintFlags(out io.Writer, flags *pflag.FlagSet) { return } format := "" - if len(flag.Shorthand) > 0 { - format = "**-%s**, **--%s**" + if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 { + format = fmt.Sprintf("**-%s**, **--%s**", flag.Shorthand, flag.Name) } else { - format = "%s**--%s**" + format = fmt.Sprintf("**--%s**", flag.Name) } if len(flag.NoOptDefVal) > 0 { format = format + "[" @@ -145,7 +168,7 @@ func manPrintFlags(out io.Writer, flags *pflag.FlagSet) { format = format + "]" } format = format + "\n\t%s\n\n" - fmt.Fprintf(out, format, flag.Shorthand, flag.Name, flag.DefValue, flag.Usage) + fmt.Fprintf(out, format, flag.DefValue, flag.Usage) }) } @@ -165,22 +188,12 @@ func manPrintOptions(out io.Writer, command *cobra.Command) { } func genMan(cmd *cobra.Command, header *GenManHeader) []byte { - // something like `rootcmd subcmd1 subcmd2` - commandName := cmd.CommandPath() // something like `rootcmd-subcmd1-subcmd2` - dashCommandName := strings.Replace(commandName, " ", "-", -1) - - fillHeader(header, commandName) + dashCommandName := strings.Replace(cmd.CommandPath(), " ", "-", -1) buf := new(bytes.Buffer) - short := cmd.Short - long := cmd.Long - if len(long) == 0 { - long = short - } - - manPreamble(buf, header, commandName, short, long) + manPreamble(buf, header, cmd, dashCommandName) manPrintOptions(buf, cmd) if len(cmd.Example) > 0 { fmt.Fprintf(buf, "# EXAMPLE\n") diff --git a/vendor/github.com/spf13/pflag/.travis.yml b/vendor/github.com/spf13/pflag/.travis.yml index df435a03fd989..580ad22f59cc9 100644 --- a/vendor/github.com/spf13/pflag/.travis.yml +++ b/vendor/github.com/spf13/pflag/.travis.yml @@ -3,9 +3,8 @@ sudo: false language: go go: - - 1.3 - - 1.4 - - 1.5 + - 1.5.4 + - 1.6.3 - tip install: @@ -14,5 +13,5 @@ install: - go install ./... script: - - verify/all.sh + - verify/all.sh -v - go test ./... diff --git a/vendor/github.com/spf13/pflag/README.md b/vendor/github.com/spf13/pflag/README.md index e74dd50b41c67..08ad945658868 100644 --- a/vendor/github.com/spf13/pflag/README.md +++ b/vendor/github.com/spf13/pflag/README.md @@ -85,7 +85,7 @@ fmt.Println("flagvar has value ", flagvar) ``` There are helpers function to get values later if you have the FlagSet but -it was difficult to keep up with all of the the flag pointers in your code. +it was difficult to keep up with all of the flag pointers in your code. If you have a pflag.FlagSet with a flag called 'flagname' of type int you can use GetInt() to get the int value. But notice that 'flagname' must exist and it must be an int. GetString("flagname") will fail. @@ -244,6 +244,25 @@ It is possible to mark a flag as hidden, meaning it will still function as norma flags.MarkHidden("secretFlag") ``` +## Supporting Go flags when using pflag +In order to support flags defined using Go's `flag` package, they must be added to the `pflag` flagset. This is usually necessary +to support flags defined by third-party dependencies (e.g. `golang/glog`). + +**Example**: You want to add the Go flags to the `CommandLine` flagset +```go +import ( + goflag "flag" + flag "github.com/spf13/pflag" +) + +var ip *int = flag.Int("flagname", 1234, "help message for flagname") + +func main() { + flag.CommandLine.AddGoFlagSet(goflag.CommandLine) + flag.Parse() +} +``` + ## More info You can see the full reference documentation of the pflag package diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go index fd914403418d5..965df13797a13 100644 --- a/vendor/github.com/spf13/pflag/flag.go +++ b/vendor/github.com/spf13/pflag/flag.go @@ -242,6 +242,17 @@ func (f *FlagSet) HasFlags() bool { return len(f.formal) > 0 } +// HasAvailableFlags returns a bool to indicate if the FlagSet has any flags +// definied that are not hidden or deprecated. +func (f *FlagSet) HasAvailableFlags() bool { + for _, flag := range f.formal { + if !flag.Hidden && len(flag.Deprecated) == 0 { + return true + } + } + return false +} + // VisitAll visits the command-line flags in lexicographical order, calling // fn for each. It visits all flags, even those not set. func VisitAll(fn func(*Flag)) { @@ -408,41 +419,123 @@ func (f *FlagSet) PrintDefaults() { fmt.Fprintf(f.out(), "%s", usages) } +// isZeroValue guesses whether the string represents the zero +// value for a flag. It is not accurate but in practice works OK. +func isZeroValue(value string) bool { + switch value { + case "false": + return true + case "": + return true + case "": + return true + case "0": + return true + } + return false +} + +// UnquoteUsage extracts a back-quoted name from the usage +// string for a flag and returns it and the un-quoted usage. +// Given "a `name` to show" it returns ("name", "a name to show"). +// If there are no back quotes, the name is an educated guess of the +// type of the flag's value, or the empty string if the flag is boolean. +func UnquoteUsage(flag *Flag) (name string, usage string) { + // Look for a back-quoted name, but avoid the strings package. + usage = flag.Usage + for i := 0; i < len(usage); i++ { + if usage[i] == '`' { + for j := i + 1; j < len(usage); j++ { + if usage[j] == '`' { + name = usage[i+1 : j] + usage = usage[:i] + name + usage[j+1:] + return name, usage + } + } + break // Only one back quote; use type name. + } + } + // No explicit name, so use type if we can find one. + name = "value" + switch flag.Value.(type) { + case boolFlag: + name = "" + case *durationValue: + name = "duration" + case *float64Value: + name = "float" + case *intValue, *int64Value: + name = "int" + case *stringValue: + name = "string" + case *uintValue, *uint64Value: + name = "uint" + } + return +} + // FlagUsages Returns a string containing the usage information for all flags in // the FlagSet func (f *FlagSet) FlagUsages() string { x := new(bytes.Buffer) + lines := make([]string, 0, len(f.formal)) + + maxlen := 0 f.VisitAll(func(flag *Flag) { if len(flag.Deprecated) > 0 || flag.Hidden { return } - format := "" + + line := "" if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 { - format = " -%s, --%s" + line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name) } else { - format = " %s --%s" + line = fmt.Sprintf(" --%s", flag.Name) } - if len(flag.NoOptDefVal) > 0 { - format = format + "[" - } - if flag.Value.Type() == "string" { - // put quotes on the value - format = format + "=%q" - } else { - format = format + "=%s" + + varname, usage := UnquoteUsage(flag) + if len(varname) > 0 { + line += " " + varname } if len(flag.NoOptDefVal) > 0 { - format = format + "]" + switch flag.Value.Type() { + case "string": + line += fmt.Sprintf("[=%q]", flag.NoOptDefVal) + case "bool": + if flag.NoOptDefVal != "true" { + line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) + } + default: + line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) + } } - format = format + ": %s\n" - shorthand := flag.Shorthand - if len(flag.ShorthandDeprecated) > 0 { - shorthand = "" + + // This special character will be replaced with spacing once the + // correct alignment is calculated + line += "\x00" + if len(line) > maxlen { + maxlen = len(line) } - fmt.Fprintf(x, format, shorthand, flag.Name, flag.DefValue, flag.Usage) + + line += usage + if !isZeroValue(flag.DefValue) { + if flag.Value.Type() == "string" { + line += fmt.Sprintf(" (default %q)", flag.DefValue) + } else { + line += fmt.Sprintf(" (default %s)", flag.DefValue) + } + } + + lines = append(lines, line) }) + for _, line := range lines { + sidx := strings.Index(line, "\x00") + spacing := strings.Repeat(" ", maxlen-sidx) + fmt.Fprintln(x, line[:sidx], spacing, line[sidx+1:]) + } + return x.String() } @@ -463,6 +556,8 @@ func defaultUsage(f *FlagSet) { // Usage prints to standard error a usage message documenting all defined command-line flags. // The function is a variable that may be changed to point to a custom function. +// By default it prints a simple header and calls PrintDefaults; for details about the +// format of the output and how to control it, see the documentation for PrintDefaults. var Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) PrintDefaults() @@ -683,6 +778,9 @@ func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) } func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShorts string, outArgs []string, err error) { + if strings.HasPrefix(shorthands, "test.") { + return + } outArgs = args outShorts = shorthands[1:] c := shorthands[0] @@ -806,7 +904,7 @@ func Parsed() bool { return CommandLine.Parsed() } -// The default set of command-line flags, parsed from os.Args. +// CommandLine is the default set of command-line flags, parsed from os.Args. var CommandLine = NewFlagSet(os.Args[0], ExitOnError) // NewFlagSet returns a new, empty flag set with the specified name and diff --git a/vendor/github.com/spf13/pflag/golangflag.go b/vendor/github.com/spf13/pflag/golangflag.go index a8c24efb644f1..b056147fd8766 100644 --- a/vendor/github.com/spf13/pflag/golangflag.go +++ b/vendor/github.com/spf13/pflag/golangflag.go @@ -61,6 +61,9 @@ func (v *flagValueWrapper) Type() string { } // PFlagFromGoFlag will return a *pflag.Flag given a *flag.Flag +// If the *flag.Flag.Name was a single character (ex: `v`) it will be accessiblei +// with both `-v` and `--v` in flags. If the golang flag was more than a single +// character (ex: `verbose`) it will only be accessible via `--verbose` func PFlagFromGoFlag(goflag *goflag.Flag) *Flag { // Remember the default value as a string; it won't change. flag := &Flag{ @@ -71,6 +74,10 @@ func PFlagFromGoFlag(goflag *goflag.Flag) *Flag { //DefValue: goflag.DefValue, DefValue: goflag.Value.String(), } + // Ex: if the golang flag was -v, allow both -v and --v to work + if len(flag.Name) == 1 { + flag.Shorthand = flag.Name + } if fv, ok := goflag.Value.(goBoolFlag); ok && fv.IsBoolFlag() { flag.NoOptDefVal = "true" }