Revert "Revert "Update cobra/pflag. Also update generated kubectl documentation.""

This reverts commit 69432e8b2f.

    COMMIT_BLOCKED_ON_GENDOCS
This commit is contained in:
Brendan Burns
2015-03-16 11:23:02 -07:00
parent d0b468f4b0
commit c66caa5336
58 changed files with 426 additions and 289 deletions

View File

@@ -46,6 +46,8 @@ type Command struct {
flags *flag.FlagSet
// Set of flags childrens of this command will inherit
pflags *flag.FlagSet
// Flags that are declared specifically by this command (not inherited).
lflags *flag.FlagSet
// Run runs the command.
// The args are the arguments after the command name.
Run func(cmd *Command, args []string)
@@ -218,8 +220,8 @@ Available Commands: {{range .Commands}}{{if .Runnable}}
{{end}}
{{ if .HasLocalFlags}}Flags:
{{.LocalFlags.FlagUsages}}{{end}}
{{ if .HasAnyPersistentFlags}}Global Flags:
{{.AllPersistentFlags.FlagUsages}}{{end}}{{if .HasParent}}{{if and (gt .Commands 0) (gt .Parent.Commands 1) }}
{{ if .HasInheritedFlags}}Global Flags:
{{.InheritedFlags.FlagUsages}}{{end}}{{if .HasParent}}{{if and (gt .Commands 0) (gt .Parent.Commands 1) }}
Additional help topics: {{if gt .Commands 0 }}{{range .Commands}}{{if not .Runnable}} {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if gt .Parent.Commands 1 }}{{range .Parent.Commands}}{{if .Runnable}}{{if not (eq .Name $cmd.Name) }}{{end}}
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{end}}
{{end}}{{ if .HasSubCommands }}
@@ -249,7 +251,27 @@ func (c *Command) resetChildrensParents() {
}
}
func stripFlags(args []string) []string {
// Test if the named flag is a boolean flag.
func isBooleanFlag(name string, f *flag.FlagSet) bool {
flag := f.Lookup(name)
if flag == nil {
return false
}
return flag.Value.Type() == "bool"
}
// Test if the named flag is a boolean flag.
func isBooleanShortFlag(name string, f *flag.FlagSet) bool {
result := false
f.VisitAll(func(f *flag.Flag) {
if f.Shorthand == name && f.Value.Type() == "bool" {
result = true
}
})
return result
}
func stripFlags(args []string, c *Command) []string {
if len(args) < 1 {
return args
}
@@ -257,6 +279,7 @@ func stripFlags(args []string) []string {
commands := []string{}
inQuote := false
inFlag := false
for _, y := range args {
if !inQuote {
switch {
@@ -264,8 +287,16 @@ func stripFlags(args []string) []string {
inQuote = true
case strings.Contains(y, "=\""):
inQuote = true
case strings.HasPrefix(y, "--") && !strings.Contains(y, "="):
// TODO: this isn't quite right, we should really check ahead for 'true' or 'false'
inFlag = !isBooleanFlag(y[2:], c.Flags())
case strings.HasPrefix(y, "-") && !strings.Contains(y, "=") && len(y) == 2 && !isBooleanShortFlag(y[1:], c.Flags()):
inFlag = true
case inFlag:
inFlag = false
case !strings.HasPrefix(y, "-"):
commands = append(commands, y)
inFlag = false
}
}
@@ -303,7 +334,7 @@ func (c *Command) Find(arrs []string) (*Command, []string, error) {
innerfind = func(c *Command, args []string) (*Command, []string) {
if len(args) > 0 && c.HasSubCommands() {
argsWOflags := stripFlags(args)
argsWOflags := stripFlags(args, c)
if len(argsWOflags) > 0 {
matches := make([]*Command, 0)
for _, cmd := range c.commands {
@@ -372,7 +403,10 @@ func (c *Command) execute(a []string) (err error) {
}
err = c.ParseFlags(a)
if err == flag.ErrHelp {
c.Help()
return nil
}
if err != nil {
// We're writing subcommand usage to root command's error buffer to have it displayed to the user
r := c.Root()
@@ -460,14 +494,15 @@ func (c *Command) Execute() (err error) {
if e != nil {
// Flags parsing had an error.
// If an error happens here, we have to report it to the user
c.Println(c.errorMsgFromParse())
c.Println(e.Error())
// If an error happens search also for subcommand info about that
if c.cmdErrorBuf != nil && c.cmdErrorBuf.Len() > 0 {
c.Println(c.cmdErrorBuf.String())
} else {
c.Usage()
}
return e
err = e
return
} else {
// If help is called, regardless of other flags, we print that
if c.helpFlagVal {
@@ -491,9 +526,13 @@ func (c *Command) Execute() (err error) {
}
if err != nil {
c.Println("Error:", err.Error())
c.Printf("%v: invalid command %#q\n", c.Root().Name(), os.Args[1:])
c.Printf("Run '%v help' for usage\n", c.Root().Name())
if err == flag.ErrHelp {
c.Help()
} else {
c.Println("Error:", err.Error())
c.Printf("%v: invalid command %#q\n", c.Root().Name(), os.Args[1:])
c.Printf("Run '%v help' for usage\n", c.Root().Name())
}
}
return
@@ -553,6 +592,40 @@ func (c *Command) AddCommand(cmds ...*Command) {
}
}
// AddCommand removes one or more commands from a parent command.
func (c *Command) RemoveCommand(cmds ...*Command) {
commands := []*Command{}
main:
for _, command := range c.commands {
for _, cmd := range cmds {
if command == cmd {
command.parent = nil
continue main
}
}
commands = append(commands, command)
}
c.commands = commands
// recompute all lengths
c.commandsMaxUseLen = 0
c.commandsMaxCommandPathLen = 0
c.commandsMaxNameLen = 0
for _, command := range c.commands {
usageLen := len(command.Use)
if usageLen > c.commandsMaxUseLen {
c.commandsMaxUseLen = usageLen
}
commandPathLen := len(command.CommandPath())
if commandPathLen > c.commandsMaxCommandPathLen {
c.commandsMaxCommandPathLen = commandPathLen
}
nameLen := len(command.Name())
if nameLen > c.commandsMaxNameLen {
c.commandsMaxNameLen = nameLen
}
}
}
// Convenience method to Print to the defined output
func (c *Command) Print(i ...interface{}) {
fmt.Fprint(c.Out(), i...)
@@ -726,14 +799,9 @@ func (c *Command) LocalFlags() *flag.FlagSet {
c.mergePersistentFlags()
local := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
allPersistent := c.AllPersistentFlags()
c.Flags().VisitAll(func(f *flag.Flag) {
if allPersistent.Lookup(f.Name) == nil {
local.AddFlag(f)
}
c.lflags.VisitAll(func(f *flag.Flag) {
local.AddFlag(f)
})
return local
}
@@ -741,44 +809,34 @@ func (c *Command) LocalFlags() *flag.FlagSet {
func (c *Command) InheritedFlags() *flag.FlagSet {
c.mergePersistentFlags()
local := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
inherited := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
local := c.LocalFlags()
var rmerge func(x *Command)
var rmerge func(x *Command)
rmerge = func(x *Command) {
if x.HasPersistentFlags() {
x.PersistentFlags().VisitAll(func(f *flag.Flag) {
if local.Lookup(f.Name) == nil {
local.AddFlag(f)
}
})
}
if x.HasParent() {
rmerge(x.parent)
}
}
rmerge = func(x *Command) {
if x.HasPersistentFlags() {
x.PersistentFlags().VisitAll(func(f *flag.Flag) {
if inherited.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil {
inherited.AddFlag(f)
}
})
}
if x.HasParent() {
rmerge(x.parent)
}
}
if c.HasParent() {
rmerge(c.parent)
}
return local
return inherited
}
// All Flags which were not inherited from parent commands
func (c *Command) NonInheritedFlags() *flag.FlagSet {
c.mergePersistentFlags()
local := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
inheritedFlags := c.InheritedFlags()
c.Flags().VisitAll(func(f *flag.Flag) {
if inheritedFlags.Lookup(f.Name) == nil {
local.AddFlag(f)
}
})
return local
return c.LocalFlags()
}
// Get the Persistent FlagSet specifically set in the current command
@@ -793,29 +851,6 @@ func (c *Command) PersistentFlags() *flag.FlagSet {
return c.pflags
}
// Get the Persistent FlagSet traversing the Command hierarchy
func (c *Command) AllPersistentFlags() *flag.FlagSet {
allPersistent := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
var visit func(x *Command)
visit = func(x *Command) {
if x.HasPersistentFlags() {
x.PersistentFlags().VisitAll(func(f *flag.Flag) {
if allPersistent.Lookup(f.Name) == nil {
allPersistent.AddFlag(f)
}
})
}
if x.HasParent() {
visit(x.parent)
}
}
visit(c)
return allPersistent
}
// For use in testing
func (c *Command) ResetFlags() {
c.flagErrorBuf = new(bytes.Buffer)
@@ -836,16 +871,15 @@ func (c *Command) HasPersistentFlags() bool {
return c.PersistentFlags().HasFlags()
}
// Does the command hierarchy contain persistent flags
func (c *Command) HasAnyPersistentFlags() bool {
return c.AllPersistentFlags().HasFlags()
}
// Does the command has flags specifically declared locally
func (c *Command) HasLocalFlags() bool {
return c.LocalFlags().HasFlags()
}
func (c *Command) HasInheritedFlags() bool {
return c.InheritedFlags().HasFlags()
}
// Climbs up the command tree looking for matching flag
func (c *Command) Flag(name string) (flag *flag.Flag) {
flag = c.Flags().Lookup(name)
@@ -873,16 +907,7 @@ func (c *Command) persistentFlag(name string) (flag *flag.Flag) {
func (c *Command) ParseFlags(args []string) (err error) {
c.mergePersistentFlags()
err = c.Flags().Parse(args)
// The upstream library adds spaces to the error
// response regardless of success.
// Handling it here until fixing upstream
if len(strings.TrimSpace(c.flagErrorBuf.String())) > 1 {
return fmt.Errorf("%s", c.flagErrorBuf.String())
}
//always return nil because upstream library is inconsistent & we always check the error buffer anyway
return nil
return
}
func (c *Command) Parent() *Command {
@@ -892,6 +917,19 @@ func (c *Command) Parent() *Command {
func (c *Command) mergePersistentFlags() {
var rmerge func(x *Command)
// Save the set of local flags
if c.lflags == nil {
c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
if c.flagErrorBuf == nil {
c.flagErrorBuf = new(bytes.Buffer)
}
c.lflags.SetOutput(c.flagErrorBuf)
addtolocal := func(f *flag.Flag) {
c.lflags.AddFlag(f)
}
c.Flags().VisitAll(addtolocal)
c.PersistentFlags().VisitAll(addtolocal)
}
rmerge = func(x *Command) {
if x.HasPersistentFlags() {
x.PersistentFlags().VisitAll(func(f *flag.Flag) {