Re: GoogleContainerTools/skaffold#4129, spf13/cobra#1047
In Skaffold we use cobra and pflags to define our CLI. We have the flags toggle values directly in an options object. We have two commands that take the same flags but with different defaults. The following snippet demonstrates the issue:
var blowup bool
cmd1 := cobra.Command{}
cmd1.Flags().BoolVar(&blowup, "blowup", false, "When set to false, blowup")
cmd2 := cobra.Command{}
cmd2.Flags().BoolVar(&blowup, "blowup", true, "When set to false, blowup")
cmd1.ParseFlags(os.Args[1:])
fmt.Printf("blowup = %v\n", blowup)
So even though we have two FlagSets, because they reference the same value, the default value for the last flag defined "wins" unless the option is explicitly defined on the command-line.
The issue here is that pflags applies the default value immediately. BoolVar() just delegates BoolVarP(), and BoolVarP() uses newBoolValue():
|
// BoolVar defines a bool flag with specified name, default value, and usage string. |
|
// The argument p points to a bool variable in which to store the value of the flag. |
|
func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) { |
|
f.BoolVarP(p, name, "", value, usage) |
|
} |
|
|
|
// BoolVarP is like BoolVar, but accepts a shorthand letter that can be used after a single dash. |
|
func (f *FlagSet) BoolVarP(p *bool, name, shorthand string, value bool, usage string) { |
|
flag := f.VarPF(newBoolValue(value, p), name, shorthand, usage) |
|
flag.NoOptDefVal = "true" |
|
} |
newBoolValue() allocates a container to map the provider pointer to the default value, but it immediately assigns the value:
|
func newBoolValue(val bool, p *bool) *boolValue { |
|
*p = val |
|
return (*boolValue)(p) |
|
} |
Re: GoogleContainerTools/skaffold#4129, spf13/cobra#1047
In Skaffold we use cobra and pflags to define our CLI. We have the flags toggle values directly in an options object. We have two commands that take the same flags but with different defaults. The following snippet demonstrates the issue:
So even though we have two FlagSets, because they reference the same value, the default value for the last flag defined "wins" unless the option is explicitly defined on the command-line.
The issue here is that pflags applies the default value immediately.
BoolVar()just delegatesBoolVarP(), andBoolVarP()usesnewBoolValue():pflag/bool.go
Lines 47 to 57 in 81378bb
newBoolValue()allocates a container to map the provider pointer to the default value, but it immediately assigns the value:pflag/bool.go
Lines 15 to 18 in 81378bb