diff --git a/altsrc/fg.py b/altsrc/fg.py new file mode 100644 index 0000000000..f0d150f1be --- /dev/null +++ b/altsrc/fg.py @@ -0,0 +1,45 @@ +# Only types that provide implementation of FlagInputSourceExtension can be listed here +# please keep list sorted alphabetically +flag_types = [ + "Bool", + "Duration", + "Float64", + "Generic", + "Int", + "IntSlice", + "Path", + "String", + "StringSlice", +] + +print('''// Code generated by fg.py; DO NOT EDIT. + +package altsrc + +import ( + "flag" + + "github.com/urfave/cli/v2" +)''') + +for t in flag_types: + print(f''' +// {t}Flag is the flag type that wraps cli.{t}Flag to allow +// for other values to be specified +type {t}Flag struct {{ + *cli.{t}Flag + set *flag.FlagSet +}} +var _ FlagInputSourceExtension = (*{t}Flag)(nil) + +// New{t}Flag creates a new {t}Flag +func New{t}Flag(fl *cli.{t}Flag) *{t}Flag {{ + return &{t}Flag{{{t}Flag: fl, set: nil}} +}} + +// Apply saves the flagSet for later usage calls, then calls +// the wrapped {t}Flag.Apply +func (f *{t}Flag) Apply(set *flag.FlagSet) error {{ + f.set = set + return f.{t}Flag.Apply(set) +}}''') \ No newline at end of file diff --git a/altsrc/flag.go b/altsrc/flag.go index 31b8a04e87..36413216ea 100644 --- a/altsrc/flag.go +++ b/altsrc/flag.go @@ -64,7 +64,7 @@ func InitInputSourceWithContext(flags []cli.Flag, createInputSource func(context // ApplyInputSourceValue applies a generic value to the flagSet if required func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { + if context != nil { if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVars) { value, err := isc.Generic(f.GenericFlag.Name) if err != nil { @@ -72,7 +72,7 @@ func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourc } if value != nil { for _, name := range f.Names() { - _ = f.set.Set(name, value.String()) + _ = context.Set(name, value.String()) } } } @@ -83,7 +83,7 @@ func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourc // ApplyInputSourceValue applies a StringSlice value to the flagSet if required func (f *StringSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { + if context != nil { if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVars) { value, err := isc.StringSlice(f.StringSliceFlag.Name) if err != nil { @@ -94,6 +94,7 @@ func (f *StringSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputS for _, name := range f.Names() { underlyingFlag := f.set.Lookup(name) if underlyingFlag != nil { + context.Set(name, sliceValue.Serialize()) underlyingFlag.Value = &sliceValue } } @@ -105,7 +106,7 @@ func (f *StringSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputS // ApplyInputSourceValue applies a IntSlice value if required func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { + if context != nil { if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVars) { value, err := isc.IntSlice(f.IntSliceFlag.Name) if err != nil { @@ -116,6 +117,7 @@ func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSour for _, name := range f.Names() { underlyingFlag := f.set.Lookup(name) if underlyingFlag != nil { + context.Set(name, sliceValue.Serialize()) underlyingFlag.Value = &sliceValue } } @@ -127,7 +129,7 @@ func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSour // ApplyInputSourceValue applies a Bool value to the flagSet if required func (f *BoolFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { + if context != nil { if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVars) { value, err := isc.Bool(f.BoolFlag.Name) if err != nil { @@ -135,7 +137,7 @@ func (f *BoolFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceCo } if value { for _, name := range f.Names() { - _ = f.set.Set(name, strconv.FormatBool(value)) + _ = context.Set(name, strconv.FormatBool(value)) } } } @@ -145,7 +147,7 @@ func (f *BoolFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceCo // ApplyInputSourceValue applies a String value to the flagSet if required func (f *StringFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { + if context != nil { if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVars)) { value, err := isc.String(f.StringFlag.Name) if err != nil { @@ -153,7 +155,7 @@ func (f *StringFlag) ApplyInputSourceValue(context *cli.Context, isc InputSource } if value != "" { for _, name := range f.Names() { - _ = f.set.Set(name, value) + _ = context.Set(name, value) } } } @@ -163,7 +165,7 @@ func (f *StringFlag) ApplyInputSourceValue(context *cli.Context, isc InputSource // ApplyInputSourceValue applies a Path value to the flagSet if required func (f *PathFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { + if context != nil { if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVars)) { value, err := isc.String(f.PathFlag.Name) if err != nil { @@ -181,7 +183,7 @@ func (f *PathFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceCo value = filepath.Join(filepath.Dir(basePathAbs), value) } - _ = f.set.Set(name, value) + _ = context.Set(name, value) } } } @@ -191,7 +193,7 @@ func (f *PathFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceCo // ApplyInputSourceValue applies a int value to the flagSet if required func (f *IntFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { + if context != nil { if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVars)) { value, err := isc.Int(f.IntFlag.Name) if err != nil { @@ -199,7 +201,7 @@ func (f *IntFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceCon } if value > 0 { for _, name := range f.Names() { - _ = f.set.Set(name, strconv.FormatInt(int64(value), 10)) + _ = context.Set(name, strconv.FormatInt(int64(value), 10)) } } } @@ -209,7 +211,7 @@ func (f *IntFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceCon // ApplyInputSourceValue applies a Duration value to the flagSet if required func (f *DurationFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { + if context != nil { if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVars)) { value, err := isc.Duration(f.DurationFlag.Name) if err != nil { @@ -217,7 +219,7 @@ func (f *DurationFlag) ApplyInputSourceValue(context *cli.Context, isc InputSour } if value > 0 { for _, name := range f.Names() { - _ = f.set.Set(name, value.String()) + _ = context.Set(name, value.String()) } } } @@ -227,7 +229,7 @@ func (f *DurationFlag) ApplyInputSourceValue(context *cli.Context, isc InputSour // ApplyInputSourceValue applies a Float64 value to the flagSet if required func (f *Float64Flag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { + if context != nil { if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVars)) { value, err := isc.Float64(f.Float64Flag.Name) if err != nil { @@ -236,7 +238,7 @@ func (f *Float64Flag) ApplyInputSourceValue(context *cli.Context, isc InputSourc if value > 0 { floatStr := float64ToString(value) for _, name := range f.Names() { - _ = f.set.Set(name, floatStr) + _ = context.Set(name, floatStr) } } } diff --git a/altsrc/flag_generated.go b/altsrc/flag_generated.go index c9ecea82e9..bdaf5a5ff0 100644 --- a/altsrc/flag_generated.go +++ b/altsrc/flag_generated.go @@ -1,4 +1,4 @@ -// Code generated by fg; DO NOT EDIT. +// Code generated by fg.py; DO NOT EDIT. package altsrc @@ -14,6 +14,7 @@ type BoolFlag struct { *cli.BoolFlag set *flag.FlagSet } +var _ FlagInputSourceExtension = (*BoolFlag)(nil) // NewBoolFlag creates a new BoolFlag func NewBoolFlag(fl *cli.BoolFlag) *BoolFlag { @@ -33,6 +34,7 @@ type DurationFlag struct { *cli.DurationFlag set *flag.FlagSet } +var _ FlagInputSourceExtension = (*DurationFlag)(nil) // NewDurationFlag creates a new DurationFlag func NewDurationFlag(fl *cli.DurationFlag) *DurationFlag { @@ -52,6 +54,7 @@ type Float64Flag struct { *cli.Float64Flag set *flag.FlagSet } +var _ FlagInputSourceExtension = (*Float64Flag)(nil) // NewFloat64Flag creates a new Float64Flag func NewFloat64Flag(fl *cli.Float64Flag) *Float64Flag { @@ -71,6 +74,7 @@ type GenericFlag struct { *cli.GenericFlag set *flag.FlagSet } +var _ FlagInputSourceExtension = (*GenericFlag)(nil) // NewGenericFlag creates a new GenericFlag func NewGenericFlag(fl *cli.GenericFlag) *GenericFlag { @@ -84,31 +88,13 @@ func (f *GenericFlag) Apply(set *flag.FlagSet) error { return f.GenericFlag.Apply(set) } -// Int64Flag is the flag type that wraps cli.Int64Flag to allow -// for other values to be specified -type Int64Flag struct { - *cli.Int64Flag - set *flag.FlagSet -} - -// NewInt64Flag creates a new Int64Flag -func NewInt64Flag(fl *cli.Int64Flag) *Int64Flag { - return &Int64Flag{Int64Flag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls -// the wrapped Int64Flag.Apply -func (f *Int64Flag) Apply(set *flag.FlagSet) error { - f.set = set - return f.Int64Flag.Apply(set) -} - // IntFlag is the flag type that wraps cli.IntFlag to allow // for other values to be specified type IntFlag struct { *cli.IntFlag set *flag.FlagSet } +var _ FlagInputSourceExtension = (*IntFlag)(nil) // NewIntFlag creates a new IntFlag func NewIntFlag(fl *cli.IntFlag) *IntFlag { @@ -128,6 +114,7 @@ type IntSliceFlag struct { *cli.IntSliceFlag set *flag.FlagSet } +var _ FlagInputSourceExtension = (*IntSliceFlag)(nil) // NewIntSliceFlag creates a new IntSliceFlag func NewIntSliceFlag(fl *cli.IntSliceFlag) *IntSliceFlag { @@ -141,42 +128,24 @@ func (f *IntSliceFlag) Apply(set *flag.FlagSet) error { return f.IntSliceFlag.Apply(set) } -// Int64SliceFlag is the flag type that wraps cli.Int64SliceFlag to allow +// PathFlag is the flag type that wraps cli.PathFlag to allow // for other values to be specified -type Int64SliceFlag struct { - *cli.Int64SliceFlag +type PathFlag struct { + *cli.PathFlag set *flag.FlagSet } +var _ FlagInputSourceExtension = (*PathFlag)(nil) -// NewInt64SliceFlag creates a new Int64SliceFlag -func NewInt64SliceFlag(fl *cli.Int64SliceFlag) *Int64SliceFlag { - return &Int64SliceFlag{Int64SliceFlag: fl, set: nil} +// NewPathFlag creates a new PathFlag +func NewPathFlag(fl *cli.PathFlag) *PathFlag { + return &PathFlag{PathFlag: fl, set: nil} } // Apply saves the flagSet for later usage calls, then calls -// the wrapped Int64SliceFlag.Apply -func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error { - f.set = set - return f.Int64SliceFlag.Apply(set) -} - -// Float64SliceFlag is the flag type that wraps cli.Float64SliceFlag to allow -// for other values to be specified -type Float64SliceFlag struct { - *cli.Float64SliceFlag - set *flag.FlagSet -} - -// NewFloat64SliceFlag creates a new Float64SliceFlag -func NewFloat64SliceFlag(fl *cli.Float64SliceFlag) *Float64SliceFlag { - return &Float64SliceFlag{Float64SliceFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped Float64SliceFlag.Apply -func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error { +// the wrapped PathFlag.Apply +func (f *PathFlag) Apply(set *flag.FlagSet) error { f.set = set - return f.Float64SliceFlag.Apply(set) + return f.PathFlag.Apply(set) } // StringFlag is the flag type that wraps cli.StringFlag to allow @@ -185,6 +154,7 @@ type StringFlag struct { *cli.StringFlag set *flag.FlagSet } +var _ FlagInputSourceExtension = (*StringFlag)(nil) // NewStringFlag creates a new StringFlag func NewStringFlag(fl *cli.StringFlag) *StringFlag { @@ -198,31 +168,13 @@ func (f *StringFlag) Apply(set *flag.FlagSet) error { return f.StringFlag.Apply(set) } -// PathFlag is the flag type that wraps cli.PathFlag to allow -// for other values to be specified -type PathFlag struct { - *cli.PathFlag - set *flag.FlagSet -} - -// NewPathFlag creates a new PathFlag -func NewPathFlag(fl *cli.PathFlag) *PathFlag { - return &PathFlag{PathFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped PathFlag.Apply -func (f *PathFlag) Apply(set *flag.FlagSet) error { - f.set = set - return f.PathFlag.Apply(set) -} - // StringSliceFlag is the flag type that wraps cli.StringSliceFlag to allow // for other values to be specified type StringSliceFlag struct { *cli.StringSliceFlag set *flag.FlagSet } +var _ FlagInputSourceExtension = (*StringSliceFlag)(nil) // NewStringSliceFlag creates a new StringSliceFlag func NewStringSliceFlag(fl *cli.StringSliceFlag) *StringSliceFlag { @@ -235,41 +187,3 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) error { f.set = set return f.StringSliceFlag.Apply(set) } - -// Uint64Flag is the flag type that wraps cli.Uint64Flag to allow -// for other values to be specified -type Uint64Flag struct { - *cli.Uint64Flag - set *flag.FlagSet -} - -// NewUint64Flag creates a new Uint64Flag -func NewUint64Flag(fl *cli.Uint64Flag) *Uint64Flag { - return &Uint64Flag{Uint64Flag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls -// the wrapped Uint64Flag.Apply -func (f *Uint64Flag) Apply(set *flag.FlagSet) error { - f.set = set - return f.Uint64Flag.Apply(set) -} - -// UintFlag is the flag type that wraps cli.UintFlag to allow -// for other values to be specified -type UintFlag struct { - *cli.UintFlag - set *flag.FlagSet -} - -// NewUintFlag creates a new UintFlag -func NewUintFlag(fl *cli.UintFlag) *UintFlag { - return &UintFlag{UintFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls -// the wrapped UintFlag.Apply -func (f *UintFlag) Apply(set *flag.FlagSet) error { - f.set = set - return f.UintFlag.Apply(set) -} diff --git a/altsrc/flag_test.go b/altsrc/flag_test.go index 204833118f..275a7cde31 100644 --- a/altsrc/flag_test.go +++ b/altsrc/flag_test.go @@ -1,7 +1,6 @@ package altsrc import ( - "flag" "fmt" "os" "path/filepath" @@ -19,7 +18,6 @@ type testApplyInputSource struct { FlagSetName string Expected string ContextValueString string - ContextValue flag.Value EnvVarValue string EnvVarName string SourcePath string @@ -28,167 +26,236 @@ type testApplyInputSource struct { func TestGenericApplyInputSourceValue(t *testing.T) { v := &Parser{"abc", "def"} - c := runTest(t, testApplyInputSource{ - Flag: NewGenericFlag(&cli.GenericFlag{Name: "test", Value: &Parser{}}), - FlagName: "test", - MapValue: v, - }) - expect(t, v, c.Generic("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewGenericFlag(&cli.GenericFlag{Name: "test", Value: &Parser{}}), + FlagName: "test", + MapValue: v, + }, + func(c *cli.Context) { + expect(t, v, c.Generic("test")) + }, + ) } func TestGenericApplyInputSourceMethodContextSet(t *testing.T) { p := &Parser{"abc", "def"} - c := runTest(t, testApplyInputSource{ - Flag: NewGenericFlag(&cli.GenericFlag{Name: "test", Value: &Parser{}}), - FlagName: "test", - MapValue: &Parser{"efg", "hig"}, - ContextValueString: p.String(), - }) - expect(t, p, c.Generic("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewGenericFlag(&cli.GenericFlag{Name: "test", Value: &Parser{}}), + FlagName: "test", + MapValue: &Parser{"efg", "hig"}, + ContextValueString: p.String(), + }, + func(c *cli.Context) { + expect(t, p, c.Generic("test")) + }, + ) } func TestGenericApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewGenericFlag(&cli.GenericFlag{ - Name: "test", - Value: &Parser{}, - EnvVars: []string{"TEST"}, - }), - FlagName: "test", - MapValue: &Parser{"efg", "hij"}, - EnvVarName: "TEST", - EnvVarValue: "abc,def", - }) - expect(t, &Parser{"abc", "def"}, c.Generic("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewGenericFlag(&cli.GenericFlag{ + Name: "test", + Value: &Parser{}, + EnvVars: []string{"TEST"}, + }), + FlagName: "test", + MapValue: &Parser{"efg", "hij"}, + EnvVarName: "TEST", + EnvVarValue: "abc,def", + }, + func(c *cli.Context) { + expect(t, &Parser{"abc", "def"}, c.Generic("test")) + }, + ) } func TestStringSliceApplyInputSourceValue(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewStringSliceFlag(&cli.StringSliceFlag{Name: "test"}), - FlagName: "test", - MapValue: []interface{}{"hello", "world"}, - }) - expect(t, c.StringSlice("test"), []string{"hello", "world"}) + runTest( + t, + testApplyInputSource{ + Flag: NewStringSliceFlag(&cli.StringSliceFlag{Name: "test"}), + FlagName: "test", + MapValue: []interface{}{"hello", "world"}, + }, + func(c *cli.Context) { + expect(t, []string{"hello", "world"}, c.StringSlice("test")) + }, + ) } func TestStringSliceApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewStringSliceFlag(&cli.StringSliceFlag{Name: "test"}), - FlagName: "test", - MapValue: []interface{}{"hello", "world"}, - ContextValueString: "ohno", - }) - expect(t, c.StringSlice("test"), []string{"ohno"}) + runTest( + t, + testApplyInputSource{ + Flag: NewStringSliceFlag(&cli.StringSliceFlag{Name: "test"}), + FlagName: "test", + MapValue: []interface{}{"hello", "world"}, + ContextValueString: "ohno", + }, + func(c *cli.Context) { + expect(t, []string{"ohno"}, c.StringSlice("test")) + }, + ) } func TestStringSliceApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", EnvVars: []string{"TEST"}}), - FlagName: "test", - MapValue: []interface{}{"hello", "world"}, - EnvVarName: "TEST", - EnvVarValue: "oh,no", - }) - expect(t, c.StringSlice("test"), []string{"oh", "no"}) + runTest( + t, + testApplyInputSource{ + Flag: NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", EnvVars: []string{"TEST"}}), + FlagName: "test", + MapValue: []interface{}{"hello", "world"}, + EnvVarName: "TEST", + EnvVarValue: "oh,no", + }, + func(c *cli.Context) { + expect(t, []string{"oh", "no"}, c.StringSlice("test")) + }, + ) } func TestIntSliceApplyInputSourceValue(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test"}), - FlagName: "test", - MapValue: []interface{}{1, 2}, - }) - expect(t, c.IntSlice("test"), []int{1, 2}) + runTest( + t, + testApplyInputSource{ + Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test"}), + FlagName: "test", + MapValue: []interface{}{1, 2}, + }, + func(c *cli.Context) { + expect(t, []int{1, 2}, c.IntSlice("test")) + }, + ) } func TestIntSliceApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test"}), - FlagName: "test", - MapValue: []interface{}{1, 2}, - ContextValueString: "3", - }) - expect(t, c.IntSlice("test"), []int{3}) + runTest( + t, + testApplyInputSource{ + Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test"}), + FlagName: "test", + MapValue: []interface{}{1, 2}, + ContextValueString: "3", + }, + func(c *cli.Context) { + expect(t, []int{3}, c.IntSlice("test")) + }, + ) } func TestIntSliceApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", EnvVars: []string{"TEST"}}), - FlagName: "test", - MapValue: []interface{}{1, 2}, - EnvVarName: "TEST", - EnvVarValue: "3,4", - }) - expect(t, c.IntSlice("test"), []int{3, 4}) + runTest( + t, + testApplyInputSource{ + Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", EnvVars: []string{"TEST"}}), + FlagName: "test", + MapValue: []interface{}{1, 2}, + EnvVarName: "TEST", + EnvVarValue: "3,4", + }, + func(c *cli.Context) { + expect(t, []int{3, 4}, c.IntSlice("test")) + }, + ) } func TestBoolApplyInputSourceMethodSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewBoolFlag(&cli.BoolFlag{Name: "test"}), - FlagName: "test", - MapValue: true, - }) - expect(t, true, c.Bool("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewBoolFlag(&cli.BoolFlag{Name: "test"}), + FlagName: "test", + MapValue: true, + }, + func(c *cli.Context) { + expect(t, true, c.Bool("test")) + }, + ) } func TestBoolApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewBoolFlag(&cli.BoolFlag{Name: "test"}), - FlagName: "test", - MapValue: false, - ContextValueString: "true", - }) - expect(t, true, c.Bool("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewBoolFlag(&cli.BoolFlag{Name: "test"}), + FlagName: "test", + MapValue: false, + ContextValueString: "true", + }, + func(c *cli.Context) { + expect(t, true, c.Bool("test")) + }, + ) } func TestBoolApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewBoolFlag(&cli.BoolFlag{Name: "test", EnvVars: []string{"TEST"}}), - FlagName: "test", - MapValue: false, - EnvVarName: "TEST", - EnvVarValue: "true", - }) - expect(t, true, c.Bool("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewBoolFlag(&cli.BoolFlag{Name: "test", EnvVars: []string{"TEST"}}), + FlagName: "test", + MapValue: false, + EnvVarName: "TEST", + EnvVarValue: "true", + }, + func(c *cli.Context) { + expect(t, true, c.Bool("test")) + }, + ) } func TestStringApplyInputSourceMethodSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewStringFlag(&cli.StringFlag{Name: "test"}), - FlagName: "test", - MapValue: "hello", - }) - expect(t, "hello", c.String("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewStringFlag(&cli.StringFlag{Name: "test"}), + FlagName: "test", + MapValue: "hello", + }, + func(c *cli.Context) { + expect(t, "hello", c.String("test")) + }, + ) } func TestStringApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewStringFlag(&cli.StringFlag{Name: "test"}), - FlagName: "test", - MapValue: "hello", - ContextValueString: "goodbye", - }) - expect(t, "goodbye", c.String("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewStringFlag(&cli.StringFlag{Name: "test"}), + FlagName: "test", + MapValue: "hello", + ContextValueString: "goodbye", + }, + func(c *cli.Context) { + expect(t, "goodbye", c.String("test")) + }, + ) } func TestStringApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewStringFlag(&cli.StringFlag{Name: "test", EnvVars: []string{"TEST"}}), - FlagName: "test", - MapValue: "hello", - EnvVarName: "TEST", - EnvVarValue: "goodbye", - }) - expect(t, "goodbye", c.String("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewStringFlag(&cli.StringFlag{Name: "test", EnvVars: []string{"TEST"}}), + FlagName: "test", + MapValue: "hello", + EnvVarName: "TEST", + EnvVarValue: "goodbye", + }, + func(c *cli.Context) { + expect(t, "goodbye", c.String("test")) + }, + ) } -func TestPathApplyInputSourceMethodSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewPathFlag(&cli.PathFlag{Name: "test"}), - FlagName: "test", - MapValue: "hello", - SourcePath: "/path/to/source/file", - }) +func TestPathApplyInputSourceMethodSet(t *testing.T) { expected := "/path/to/source/hello" if runtime.GOOS == "windows" { var err error @@ -199,145 +266,217 @@ func TestPathApplyInputSourceMethodSet(t *testing.T) { t.Fatal(err) } } - expect(t, expected, c.String("test")) + + runTest( + t, + testApplyInputSource{ + Flag: NewPathFlag(&cli.PathFlag{Name: "test"}), + FlagName: "test", + MapValue: "hello", + SourcePath: "/path/to/source/file", + }, + func(c *cli.Context) { + expect(t, expected, c.String("test")) + }, + ) } func TestPathApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewPathFlag(&cli.PathFlag{Name: "test"}), - FlagName: "test", - MapValue: "hello", - ContextValueString: "goodbye", - SourcePath: "/path/to/source/file", - }) - expect(t, "goodbye", c.String("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewPathFlag(&cli.PathFlag{Name: "test"}), + FlagName: "test", + MapValue: "hello", + ContextValueString: "goodbye", + SourcePath: "/path/to/source/file", + }, + func(c *cli.Context) { + expect(t, "goodbye", c.String("test")) + }, + ) } func TestPathApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewPathFlag(&cli.PathFlag{Name: "test", EnvVars: []string{"TEST"}}), - FlagName: "test", - MapValue: "hello", - EnvVarName: "TEST", - EnvVarValue: "goodbye", - SourcePath: "/path/to/source/file", - }) - expect(t, "goodbye", c.String("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewPathFlag(&cli.PathFlag{Name: "test", EnvVars: []string{"TEST"}}), + FlagName: "test", + MapValue: "hello", + EnvVarName: "TEST", + EnvVarValue: "goodbye", + SourcePath: "/path/to/source/file", + }, + func(c *cli.Context) { + expect(t, "goodbye", c.String("test")) + }, + ) } func TestIntApplyInputSourceMethodSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewIntFlag(&cli.IntFlag{Name: "test"}), - FlagName: "test", - MapValue: 15, - }) - expect(t, 15, c.Int("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewIntFlag(&cli.IntFlag{Name: "test"}), + FlagName: "test", + MapValue: 15, + }, + func(c *cli.Context) { + expect(t, 15, c.Int("test")) + }, + ) } - func TestIntApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewIntFlag(&cli.IntFlag{Name: "test"}), - FlagName: "test", - MapValue: 15, - ContextValueString: "7", - }) - expect(t, 7, c.Int("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewIntFlag(&cli.IntFlag{Name: "test"}), + FlagName: "test", + MapValue: 15, + ContextValueString: "7", + }, + func(c *cli.Context) { + expect(t, 7, c.Int("test")) + }, + ) } func TestIntApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewIntFlag(&cli.IntFlag{Name: "test", EnvVars: []string{"TEST"}}), - FlagName: "test", - MapValue: 15, - EnvVarName: "TEST", - EnvVarValue: "12", - }) - expect(t, 12, c.Int("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewIntFlag(&cli.IntFlag{Name: "test", EnvVars: []string{"TEST"}}), + FlagName: "test", + MapValue: 15, + EnvVarName: "TEST", + EnvVarValue: "12", + }, + func(c *cli.Context) { + expect(t, 12, c.Int("test")) + }, + ) } func TestDurationApplyInputSourceMethodSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewDurationFlag(&cli.DurationFlag{Name: "test"}), - FlagName: "test", - MapValue: 30 * time.Second, - }) - expect(t, 30*time.Second, c.Duration("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewDurationFlag(&cli.DurationFlag{Name: "test"}), + FlagName: "test", + MapValue: 30 * time.Second, + }, + func(c *cli.Context) { + expect(t, 30*time.Second, c.Duration("test")) + }, + ) } func TestDurationApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewDurationFlag(&cli.DurationFlag{Name: "test"}), - FlagName: "test", - MapValue: 30 * time.Second, - ContextValueString: (15 * time.Second).String(), - }) - expect(t, 15*time.Second, c.Duration("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewDurationFlag(&cli.DurationFlag{Name: "test"}), + FlagName: "test", + MapValue: 30 * time.Second, + ContextValueString: (15 * time.Second).String(), + }, + func(c *cli.Context) { + expect(t, 15*time.Second, c.Duration("test")) + }, + ) } func TestDurationApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewDurationFlag(&cli.DurationFlag{Name: "test", EnvVars: []string{"TEST"}}), - FlagName: "test", - MapValue: 30 * time.Second, - EnvVarName: "TEST", - EnvVarValue: (15 * time.Second).String(), - }) - expect(t, 15*time.Second, c.Duration("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewDurationFlag(&cli.DurationFlag{Name: "test", EnvVars: []string{"TEST"}}), + FlagName: "test", + MapValue: 30 * time.Second, + EnvVarName: "TEST", + EnvVarValue: (15 * time.Second).String(), + }, + func(c *cli.Context) { + expect(t, 15*time.Second, c.Duration("test")) + }, + ) } func TestFloat64ApplyInputSourceMethodSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewFloat64Flag(&cli.Float64Flag{Name: "test"}), - FlagName: "test", - MapValue: 1.3, - }) - expect(t, 1.3, c.Float64("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewFloat64Flag(&cli.Float64Flag{Name: "test"}), + FlagName: "test", + MapValue: 1.3, + }, + func(c *cli.Context) { + expect(t, 1.3, c.Float64("test")) + }, + ) } func TestFloat64ApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewFloat64Flag(&cli.Float64Flag{Name: "test"}), - FlagName: "test", - MapValue: 1.3, - ContextValueString: fmt.Sprintf("%v", 1.4), - }) - expect(t, 1.4, c.Float64("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewFloat64Flag(&cli.Float64Flag{Name: "test"}), + FlagName: "test", + MapValue: 1.3, + ContextValueString: fmt.Sprintf("%v", 1.4), + }, + func(c *cli.Context) { + expect(t, 1.4, c.Float64("test")) + }, + ) } func TestFloat64ApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewFloat64Flag(&cli.Float64Flag{Name: "test", EnvVars: []string{"TEST"}}), - FlagName: "test", - MapValue: 1.3, - EnvVarName: "TEST", - EnvVarValue: fmt.Sprintf("%v", 1.4), - }) - expect(t, 1.4, c.Float64("test")) + runTest( + t, + testApplyInputSource{ + Flag: NewFloat64Flag(&cli.Float64Flag{Name: "test", EnvVars: []string{"TEST"}}), + FlagName: "test", + MapValue: 1.3, + EnvVarName: "TEST", + EnvVarValue: fmt.Sprintf("%v", 1.4), + }, + func(c *cli.Context) { + expect(t, 1.4, c.Float64("test")) + }, + ) } -func runTest(t *testing.T, test testApplyInputSource) *cli.Context { +func runTest(t *testing.T, test testApplyInputSource, checkVal func(*cli.Context)) { inputSource := &MapInputSource{ file: test.SourcePath, valueMap: map[interface{}]interface{}{test.FlagName: test.MapValue}, } - set := flag.NewFlagSet(test.FlagSetName, flag.ContinueOnError) - c := cli.NewContext(nil, set, nil) + + app := cli.App{ + Flags: []cli.Flag{ + test.Flag, + }, + Action: func(c *cli.Context) error { + if test.ContextValueString != "" { + _ = c.Set(test.FlagName, test.ContextValueString) + } + _ = test.Flag.ApplyInputSourceValue(c, inputSource) + + expect(t, c.IsSet(test.FlagName), true) + checkVal(c) + + return nil + }, + } + if test.EnvVarName != "" && test.EnvVarValue != "" { _ = os.Setenv(test.EnvVarName, test.EnvVarValue) defer os.Setenv(test.EnvVarName, "") } - _ = test.Flag.Apply(set) - if test.ContextValue != nil { - f := set.Lookup(test.FlagName) - f.Value = test.ContextValue - } - if test.ContextValueString != "" { - _ = set.Set(test.FlagName, test.ContextValueString) - } - _ = test.Flag.ApplyInputSourceValue(c, inputSource) - - return c + _ = app.Run([]string{"the-app"}) } type Parser [2]string diff --git a/flag_generic.go b/flag_generic.go index b0c8ff44d2..5d1f815c95 100644 --- a/flag_generic.go +++ b/flag_generic.go @@ -68,7 +68,7 @@ func (f *GenericFlag) GetValue() string { // Apply takes the flagset and calls Set on the generic flag with the value // provided by the user for parsing by the flag -func (f GenericFlag) Apply(set *flag.FlagSet) error { +func (f *GenericFlag) Apply(set *flag.FlagSet) error { if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val != "" { if err := f.Value.Set(val); err != nil {