Merge pull request #1528 from dearchap/issue_1206

Fix:(issue_1206) Default value shouldnt depend on env variable or val…
This commit is contained in:
dearchap 2022-10-15 17:58:48 -04:00 committed by GitHub
commit 5ac0710c11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 385 additions and 88 deletions

View File

@ -2625,19 +2625,6 @@ func TestSetupInitializesOnlyNilWriters(t *testing.T) {
}
}
type stringGeneric struct {
value string
}
func (s *stringGeneric) Set(value string) error {
s.value = value
return nil
}
func (s *stringGeneric) String() string {
return s.value
}
func TestFlagAction(t *testing.T) {
stringFlag := &StringFlag{
Name: "f_string",

View File

@ -22,6 +22,8 @@ type {{.TypeName}} struct {
Aliases []string
EnvVars []string
defaultValue {{if .ValuePointer}}*{{end}}{{.GoType}}
{{range .StructFields}}
{{.Name}} {{if .Pointer}}*{{end}}{{.Type}}
{{end}}

View File

@ -84,7 +84,7 @@ func (f *BoolFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return fmt.Sprintf("%v", f.Value)
return fmt.Sprintf("%v", f.defaultValue)
}
// GetEnvVars returns the env vars for this flag
@ -103,6 +103,9 @@ func (f *BoolFlag) RunAction(c *Context) error {
// Apply populates the flag given the flag set and environment
func (f *BoolFlag) Apply(set *flag.FlagSet) error {
// set default value so that environment wont be able to overwrite it
f.defaultValue = f.Value
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valBool, err := strconv.ParseBool(val)

View File

@ -32,7 +32,7 @@ func (f *DurationFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
return f.defaultValue.String()
}
// GetEnvVars returns the env vars for this flag
@ -42,6 +42,9 @@ func (f *DurationFlag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *DurationFlag) Apply(set *flag.FlagSet) error {
// set default value so that environment wont be able to overwrite it
f.defaultValue = f.Value
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valDuration, err := time.ParseDuration(val)

View File

@ -11,6 +11,19 @@ type Generic interface {
String() string
}
type stringGeneric struct {
value string
}
func (s *stringGeneric) Set(value string) error {
s.value = value
return nil
}
func (s *stringGeneric) String() string {
return s.value
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f *GenericFlag) TakesValue() bool {
return true
@ -40,7 +53,10 @@ func (f *GenericFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
if f.defaultValue != nil {
return f.defaultValue.String()
}
return ""
}
// GetEnvVars returns the env vars for this flag
@ -51,6 +67,11 @@ func (f *GenericFlag) GetEnvVars() []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 {
// set default value so that environment wont be able to overwrite it
if f.Value != nil {
f.defaultValue = &stringGeneric{value: f.Value.String()}
}
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
if err := f.Value.Set(val); err != nil {

View File

@ -32,7 +32,7 @@ func (f *IntFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
return fmt.Sprintf("%d", f.defaultValue)
}
// GetEnvVars returns the env vars for this flag
@ -42,6 +42,9 @@ func (f *IntFlag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *IntFlag) Apply(set *flag.FlagSet) error {
// set default value so that environment wont be able to overwrite it
f.defaultValue = f.Value
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valInt, err := strconv.ParseInt(val, f.Base, 64)

View File

@ -32,7 +32,7 @@ func (f *Int64Flag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
return fmt.Sprintf("%d", f.defaultValue)
}
// GetEnvVars returns the env vars for this flag
@ -42,6 +42,9 @@ func (f *Int64Flag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *Int64Flag) Apply(set *flag.FlagSet) error {
// set default value so that environment wont be able to overwrite it
f.defaultValue = f.Value
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valInt, err := strconv.ParseInt(val, f.Base, 64)

View File

@ -33,10 +33,10 @@ func (f *PathFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
if f.Value == "" {
return f.Value
if f.defaultValue == "" {
return f.defaultValue
}
return fmt.Sprintf("%q", f.Value)
return fmt.Sprintf("%q", f.defaultValue)
}
// GetEnvVars returns the env vars for this flag
@ -46,6 +46,9 @@ func (f *PathFlag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *PathFlag) Apply(set *flag.FlagSet) error {
// set default value so that environment wont be able to overwrite it
f.defaultValue = f.Value
if val, _, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
f.Value = val
f.HasBeenSet = true

View File

@ -31,10 +31,10 @@ func (f *StringFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
if f.Value == "" {
return f.Value
if f.defaultValue == "" {
return f.defaultValue
}
return fmt.Sprintf("%q", f.Value)
return fmt.Sprintf("%q", f.defaultValue)
}
// GetEnvVars returns the env vars for this flag
@ -44,6 +44,9 @@ func (f *StringFlag) GetEnvVars() []string {
// Apply populates the flag given the flag set and environment
func (f *StringFlag) Apply(set *flag.FlagSet) error {
// set default value so that environment wont be able to overwrite it
f.defaultValue = f.Value
if val, _, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
f.Value = val
f.HasBeenSet = true

View File

@ -8,7 +8,6 @@ import (
"os"
"reflect"
"regexp"
"runtime"
"strings"
"testing"
"time"
@ -477,6 +476,9 @@ var stringFlagTests = []struct {
func TestStringFlagHelpOutput(t *testing.T) {
for _, test := range stringFlagTests {
fl := &StringFlag{Name: test.name, Aliases: test.aliases, Usage: test.usage, Value: test.value}
// create a tmp flagset
tfs := flag.NewFlagSet("test", 0)
fl.Apply(tfs)
output := fl.String()
if output != test.expected {
@ -504,10 +506,7 @@ func TestStringFlagWithEnvVarHelpOutput(t *testing.T) {
fl := &StringFlag{Name: test.name, Aliases: test.aliases, Value: test.value, EnvVars: []string{"APP_FOO"}}
output := fl.String()
expectedSuffix := " [$APP_FOO]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_FOO%]"
}
expectedSuffix := withEnvHint([]string{"APP_FOO"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%s does not end with"+expectedSuffix, output)
}
@ -575,6 +574,11 @@ var pathFlagTests = []struct {
func TestPathFlagHelpOutput(t *testing.T) {
for _, test := range pathFlagTests {
fl := &PathFlag{Name: test.name, Aliases: test.aliases, Usage: test.usage, Value: test.value}
// create a temporary flag set to apply
tfs := flag.NewFlagSet("test", 0)
fl.Apply(tfs)
output := fl.String()
if output != test.expected {
@ -591,10 +595,7 @@ func TestPathFlagWithEnvVarHelpOutput(t *testing.T) {
fl := &PathFlag{Name: test.name, Aliases: test.aliases, Value: test.value, EnvVars: []string{"APP_PATH"}}
output := fl.String()
expectedSuffix := " [$APP_PATH]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_PATH%]"
}
expectedSuffix := withEnvHint([]string{"APP_PATH"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%s does not end with"+expectedSuffix, output)
}
@ -688,10 +689,7 @@ func TestStringSliceFlagWithEnvVarHelpOutput(t *testing.T) {
fl := &StringSliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value, EnvVars: []string{"APP_QWWX"}}
output := fl.String()
expectedSuffix := " [$APP_QWWX]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_QWWX%]"
}
expectedSuffix := withEnvHint([]string{"APP_QWWX"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%q does not end with"+expectedSuffix, output)
}
@ -767,6 +765,11 @@ var intFlagTests = []struct {
func TestIntFlagHelpOutput(t *testing.T) {
for _, test := range intFlagTests {
fl := &IntFlag{Name: test.name, Value: 9}
// create a temporary flag set to apply
tfs := flag.NewFlagSet("test", 0)
fl.Apply(tfs)
output := fl.String()
if output != test.expected {
@ -784,10 +787,7 @@ func TestIntFlagWithEnvVarHelpOutput(t *testing.T) {
fl := &IntFlag{Name: test.name, EnvVars: []string{"APP_BAR"}}
output := fl.String()
expectedSuffix := " [$APP_BAR]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_BAR%]"
}
expectedSuffix := withEnvHint([]string{"APP_BAR"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%s does not end with"+expectedSuffix, output)
}
@ -824,6 +824,11 @@ var int64FlagTests = []struct {
func TestInt64FlagHelpOutput(t *testing.T) {
for _, test := range int64FlagTests {
fl := Int64Flag{Name: test.name, Value: 8589934592}
// create a temporary flag set to apply
tfs := flag.NewFlagSet("test", 0)
fl.Apply(tfs)
output := fl.String()
if output != test.expected {
@ -841,10 +846,7 @@ func TestInt64FlagWithEnvVarHelpOutput(t *testing.T) {
fl := IntFlag{Name: test.name, EnvVars: []string{"APP_BAR"}}
output := fl.String()
expectedSuffix := " [$APP_BAR]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_BAR%]"
}
expectedSuffix := withEnvHint([]string{"APP_BAR"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%s does not end with"+expectedSuffix, output)
}
@ -870,6 +872,11 @@ var uintFlagTests = []struct {
func TestUintFlagHelpOutput(t *testing.T) {
for _, test := range uintFlagTests {
fl := UintFlag{Name: test.name, Value: 41}
// create a temporary flag set to apply
tfs := flag.NewFlagSet("test", 0)
fl.Apply(tfs)
output := fl.String()
if output != test.expected {
@ -887,10 +894,7 @@ func TestUintFlagWithEnvVarHelpOutput(t *testing.T) {
fl := UintFlag{Name: test.name, EnvVars: []string{"APP_BAR"}}
output := fl.String()
expectedSuffix := " [$APP_BAR]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_BAR%]"
}
expectedSuffix := withEnvHint([]string{"APP_BAR"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%s does not end with"+expectedSuffix, output)
}
@ -916,6 +920,11 @@ var uint64FlagTests = []struct {
func TestUint64FlagHelpOutput(t *testing.T) {
for _, test := range uint64FlagTests {
fl := Uint64Flag{Name: test.name, Value: 8589934582}
// create a temporary flag set to apply
tfs := flag.NewFlagSet("test", 0)
fl.Apply(tfs)
output := fl.String()
if output != test.expected {
@ -933,10 +942,7 @@ func TestUint64FlagWithEnvVarHelpOutput(t *testing.T) {
fl := UintFlag{Name: test.name, EnvVars: []string{"APP_BAR"}}
output := fl.String()
expectedSuffix := " [$APP_BAR]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_BAR%]"
}
expectedSuffix := withEnvHint([]string{"APP_BAR"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%s does not end with"+expectedSuffix, output)
}
@ -962,6 +968,11 @@ var durationFlagTests = []struct {
func TestDurationFlagHelpOutput(t *testing.T) {
for _, test := range durationFlagTests {
fl := &DurationFlag{Name: test.name, Value: 1 * time.Second}
// create a temporary flag set to apply
tfs := flag.NewFlagSet("test", 0)
fl.Apply(tfs)
output := fl.String()
if output != test.expected {
@ -979,10 +990,7 @@ func TestDurationFlagWithEnvVarHelpOutput(t *testing.T) {
fl := &DurationFlag{Name: test.name, EnvVars: []string{"APP_BAR"}}
output := fl.String()
expectedSuffix := " [$APP_BAR]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_BAR%]"
}
expectedSuffix := withEnvHint([]string{"APP_BAR"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%s does not end with"+expectedSuffix, output)
}
@ -1039,10 +1047,7 @@ func TestIntSliceFlagWithEnvVarHelpOutput(t *testing.T) {
fl := &IntSliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value, EnvVars: []string{"APP_SMURF"}}
output := fl.String()
expectedSuffix := " [$APP_SMURF]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_SMURF%]"
}
expectedSuffix := withEnvHint([]string{"APP_SMURF"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%q does not end with"+expectedSuffix, output)
}
@ -1178,10 +1183,7 @@ func TestInt64SliceFlagWithEnvVarHelpOutput(t *testing.T) {
fl := Int64SliceFlag{Name: test.name, Value: test.value, EnvVars: []string{"APP_SMURF"}}
output := fl.String()
expectedSuffix := " [$APP_SMURF]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_SMURF%]"
}
expectedSuffix := withEnvHint([]string{"APP_SMURF"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%q does not end with"+expectedSuffix, output)
}
@ -1332,10 +1334,7 @@ func TestUintSliceFlagWithEnvVarHelpOutput(t *testing.T) {
fl := UintSliceFlag{Name: test.name, Value: test.value, EnvVars: []string{"APP_SMURF"}}
output := fl.String()
expectedSuffix := " [$APP_SMURF]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_SMURF%]"
}
expectedSuffix := withEnvHint([]string{"APP_SMURF"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%q does not end with"+expectedSuffix, output)
}
@ -1478,10 +1477,7 @@ func TestUint64SliceFlagWithEnvVarHelpOutput(t *testing.T) {
fl := Uint64SliceFlag{Name: test.name, Value: test.value, EnvVars: []string{"APP_SMURF"}}
output := fl.String()
expectedSuffix := " [$APP_SMURF]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_SMURF%]"
}
expectedSuffix := withEnvHint([]string{"APP_SMURF"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%q does not end with"+expectedSuffix, output)
}
@ -1620,10 +1616,7 @@ func TestFloat64FlagWithEnvVarHelpOutput(t *testing.T) {
fl := &Float64Flag{Name: test.name, EnvVars: []string{"APP_BAZ"}}
output := fl.String()
expectedSuffix := " [$APP_BAZ]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_BAZ%]"
}
expectedSuffix := withEnvHint([]string{"APP_BAZ"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%s does not end with"+expectedSuffix, output)
}
@ -1680,10 +1673,7 @@ func TestFloat64SliceFlagWithEnvVarHelpOutput(t *testing.T) {
fl := Float64SliceFlag{Name: test.name, Value: test.value, EnvVars: []string{"APP_SMURF"}}
output := fl.String()
expectedSuffix := " [$APP_SMURF]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_SMURF%]"
}
expectedSuffix := withEnvHint([]string{"APP_SMURF"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%q does not end with"+expectedSuffix, output)
}
@ -1783,6 +1773,9 @@ var genericFlagTests = []struct {
func TestGenericFlagHelpOutput(t *testing.T) {
for _, test := range genericFlagTests {
fl := &GenericFlag{Name: test.name, Value: test.value, Usage: "test flag"}
// create a temporary flag set to apply
tfs := flag.NewFlagSet("test", 0)
fl.Apply(tfs)
output := fl.String()
if output != test.expected {
@ -1800,10 +1793,7 @@ func TestGenericFlagWithEnvVarHelpOutput(t *testing.T) {
fl := &GenericFlag{Name: test.name, EnvVars: []string{"APP_ZAP"}}
output := fl.String()
expectedSuffix := " [$APP_ZAP]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_ZAP%]"
}
expectedSuffix := withEnvHint([]string{"APP_ZAP"}, "")
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%s does not end with"+expectedSuffix, output)
}
@ -3100,6 +3090,186 @@ func TestFlagDefaultValue(t *testing.T) {
}
}
type flagDefaultTestCaseWithEnv struct {
name string
flag Flag
toParse []string
expect string
environ map[string]string
}
func TestFlagDefaultValueWithEnv(t *testing.T) {
defer resetEnv(os.Environ())
os.Clearenv()
ts, err := time.Parse(time.RFC3339, "2005-01-02T15:04:05Z")
if err != nil {
t.Fatal(err)
}
cases := []*flagDefaultTestCaseWithEnv{
{
name: "stringSlice",
flag: &StringSliceFlag{Name: "flag", Value: NewStringSlice("default1", "default2"), EnvVars: []string{"ssflag"}},
toParse: []string{"--flag", "parsed"},
expect: `--flag value [ --flag value ] (default: "default1", "default2")` + withEnvHint([]string{"ssflag"}, ""),
environ: map[string]string{
"ssflag": "some-other-env_value",
},
},
{
name: "float64Slice",
flag: &Float64SliceFlag{Name: "flag", Value: NewFloat64Slice(1.1, 2.2), EnvVars: []string{"fsflag"}},
toParse: []string{"--flag", "13.3"},
expect: `--flag value [ --flag value ] (default: 1.1, 2.2)` + withEnvHint([]string{"fsflag"}, ""),
environ: map[string]string{
"fsflag": "20304.222",
},
},
{
name: "int64Slice",
flag: &Int64SliceFlag{Name: "flag", Value: NewInt64Slice(1, 2), EnvVars: []string{"isflag"}},
toParse: []string{"--flag", "13"},
expect: `--flag value [ --flag value ] (default: 1, 2)` + withEnvHint([]string{"isflag"}, ""),
environ: map[string]string{
"isflag": "101",
},
},
{
name: "intSlice",
flag: &IntSliceFlag{Name: "flag", Value: NewIntSlice(1, 2), EnvVars: []string{"isflag"}},
toParse: []string{"--flag", "13"},
expect: `--flag value [ --flag value ] (default: 1, 2)` + withEnvHint([]string{"isflag"}, ""),
environ: map[string]string{
"isflag": "101",
},
},
{
name: "uint64Slice",
flag: &Uint64SliceFlag{Name: "flag", Value: NewUint64Slice(1, 2), EnvVars: []string{"uisflag"}},
toParse: []string{"--flag", "13"},
expect: `--flag value [ --flag value ] (default: 1, 2)` + withEnvHint([]string{"uisflag"}, ""),
environ: map[string]string{
"uisflag": "3",
},
},
{
name: "uintSlice",
flag: &UintSliceFlag{Name: "flag", Value: NewUintSlice(1, 2), EnvVars: []string{"uisflag"}},
toParse: []string{"--flag", "13"},
expect: `--flag value [ --flag value ] (default: 1, 2)` + withEnvHint([]string{"uisflag"}, ""),
environ: map[string]string{
"uisflag": "3",
},
},
{
name: "string",
flag: &StringFlag{Name: "flag", Value: "default", EnvVars: []string{"uflag"}},
toParse: []string{"--flag", "parsed"},
expect: `--flag value (default: "default")` + withEnvHint([]string{"uflag"}, ""),
environ: map[string]string{
"uflag": "some-other-string",
},
},
{
name: "bool",
flag: &BoolFlag{Name: "flag", Value: true, EnvVars: []string{"uflag"}},
toParse: []string{"--flag", "false"},
expect: `--flag (default: true)` + withEnvHint([]string{"uflag"}, ""),
environ: map[string]string{
"uflag": "false",
},
},
{
name: "uint64",
flag: &Uint64Flag{Name: "flag", Value: 1, EnvVars: []string{"uflag"}},
toParse: []string{"--flag", "13"},
expect: `--flag value (default: 1)` + withEnvHint([]string{"uflag"}, ""),
environ: map[string]string{
"uflag": "10",
},
},
{
name: "uint",
flag: &UintFlag{Name: "flag", Value: 1, EnvVars: []string{"uflag"}},
toParse: []string{"--flag", "13"},
expect: `--flag value (default: 1)` + withEnvHint([]string{"uflag"}, ""),
environ: map[string]string{
"uflag": "10",
},
},
{
name: "int64",
flag: &Int64Flag{Name: "flag", Value: 1, EnvVars: []string{"uflag"}},
toParse: []string{"--flag", "13"},
expect: `--flag value (default: 1)` + withEnvHint([]string{"uflag"}, ""),
environ: map[string]string{
"uflag": "10",
},
},
{
name: "int",
flag: &IntFlag{Name: "flag", Value: 1, EnvVars: []string{"uflag"}},
toParse: []string{"--flag", "13"},
expect: `--flag value (default: 1)` + withEnvHint([]string{"uflag"}, ""),
environ: map[string]string{
"uflag": "10",
},
},
{
name: "duration",
flag: &DurationFlag{Name: "flag", Value: time.Second, EnvVars: []string{"uflag"}},
toParse: []string{"--flag", "2m"},
expect: `--flag value (default: 1s)` + withEnvHint([]string{"uflag"}, ""),
environ: map[string]string{
"uflag": "2h4m10s",
},
},
{
name: "path",
flag: &PathFlag{Name: "flag", Value: "/tmp/foo", EnvVars: []string{"uflag"}},
toParse: []string{"--flag", "/bar/ddfr"},
expect: `--flag value (default: "/tmp/foo")` + withEnvHint([]string{"uflag"}, ""),
environ: map[string]string{
"uflag": "/bar/t/err",
},
},
{
name: "timestamp",
flag: &TimestampFlag{Name: "flag", Value: NewTimestamp(ts), Layout: time.RFC3339, EnvVars: []string{"tflag"}},
toParse: []string{"--flag", "2006-11-02T15:04:05Z"},
expect: `--flag value (default: 2005-01-02 15:04:05 +0000 UTC)` + withEnvHint([]string{"tflag"}, ""),
environ: map[string]string{
"tflag": "2010-01-02T15:04:05Z",
},
},
{
name: "generic",
flag: &GenericFlag{Name: "flag", Value: &Parser{"11", "12"}, EnvVars: []string{"gflag"}},
toParse: []string{"--flag", "15,16"},
expect: `--flag value (default: 11,12)` + withEnvHint([]string{"gflag"}, ""),
environ: map[string]string{
"gflag": "13,14",
},
},
}
for i, v := range cases {
for key, val := range v.environ {
os.Setenv(key, val)
}
set := flag.NewFlagSet("test", 0)
set.SetOutput(ioutil.Discard)
if err := v.flag.Apply(set); err != nil {
t.Fatal(err)
}
if err := set.Parse(v.toParse); err != nil {
t.Error(err)
}
if got := v.flag.String(); got != v.expect {
t.Errorf("TestFlagDefaultValue %d %s\nexpect:%s\ngot:%s", i, v.name, v.expect, got)
}
}
}
type flagValueTestCase struct {
name string
flag Flag

View File

@ -72,6 +72,25 @@ func (t *Timestamp) Get() interface{} {
return *t
}
// clone timestamp
func (t *Timestamp) clone() *Timestamp {
tc := &Timestamp{
timestamp: nil,
hasBeenSet: t.hasBeenSet,
layout: t.layout,
location: nil,
}
if t.timestamp != nil {
tts := *t.timestamp
tc.timestamp = &tts
}
if t.location != nil {
loc := *t.location
tc.location = &loc
}
return tc
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f *TimestampFlag) TakesValue() bool {
return true
@ -101,7 +120,11 @@ func (f *TimestampFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
if f.defaultValue != nil && f.defaultValue.timestamp != nil {
return f.defaultValue.timestamp.String()
}
return ""
}
// GetEnvVars returns the env vars for this flag
@ -120,6 +143,8 @@ func (f *TimestampFlag) Apply(set *flag.FlagSet) error {
f.Value.SetLayout(f.Layout)
f.Value.SetLocation(f.Timezone)
f.defaultValue = f.Value.clone()
if f.Destination != nil {
f.Destination.SetLayout(f.Layout)
f.Destination.SetLocation(f.Timezone)

View File

@ -23,6 +23,9 @@ func (f *UintFlag) GetCategory() string {
// Apply populates the flag given the flag set and environment
func (f *UintFlag) Apply(set *flag.FlagSet) error {
// set default value so that environment wont be able to overwrite it
f.defaultValue = f.Value
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valInt, err := strconv.ParseUint(val, f.Base, 64)
@ -66,7 +69,7 @@ func (f *UintFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
return fmt.Sprintf("%d", f.defaultValue)
}
// GetEnvVars returns the env vars for this flag

View File

@ -23,6 +23,9 @@ func (f *Uint64Flag) GetCategory() string {
// Apply populates the flag given the flag set and environment
func (f *Uint64Flag) Apply(set *flag.FlagSet) error {
// set default value so that environment wont be able to overwrite it
f.defaultValue = f.Value
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" {
valInt, err := strconv.ParseUint(val, f.Base, 64)
@ -66,7 +69,7 @@ func (f *Uint64Flag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
return fmt.Sprintf("%d", f.defaultValue)
}
// GetEnvVars returns the env vars for this flag

View File

@ -447,6 +447,7 @@ type BoolFlag struct {
Count *int
Action func(*Context, bool) error
// Has unexported fields.
}
BoolFlag is a flag with type bool
@ -775,6 +776,7 @@ type DurationFlag struct {
EnvVars []string
Action func(*Context, time.Duration) error
// Has unexported fields.
}
DurationFlag is a flag with type time.Duration
@ -953,6 +955,7 @@ type Float64Flag struct {
EnvVars []string
Action func(*Context, float64) error
// Has unexported fields.
}
Float64Flag is a flag with type float64
@ -1041,6 +1044,7 @@ type Float64SliceFlag struct {
EnvVars []string
Action func(*Context, []float64) error
// Has unexported fields.
}
Float64SliceFlag is a flag with type *Float64Slice
@ -1123,6 +1127,7 @@ type GenericFlag struct {
TakesFile bool
Action func(*Context, interface{}) error
// Has unexported fields.
}
GenericFlag is a flag with type Generic
@ -1191,6 +1196,7 @@ type Int64Flag struct {
Base int
Action func(*Context, int64) error
// Has unexported fields.
}
Int64Flag is a flag with type int64
@ -1279,6 +1285,7 @@ type Int64SliceFlag struct {
EnvVars []string
Action func(*Context, []int64) error
// Has unexported fields.
}
Int64SliceFlag is a flag with type *Int64Slice
@ -1355,6 +1362,7 @@ type IntFlag struct {
Base int
Action func(*Context, int) error
// Has unexported fields.
}
IntFlag is a flag with type int
@ -1447,6 +1455,7 @@ type IntSliceFlag struct {
EnvVars []string
Action func(*Context, []int) error
// Has unexported fields.
}
IntSliceFlag is a flag with type *IntSlice
@ -1557,6 +1566,7 @@ type PathFlag struct {
TakesFile bool
Action func(*Context, Path) error
// Has unexported fields.
}
PathFlag is a flag with type Path
@ -1699,6 +1709,7 @@ type StringFlag struct {
TakesFile bool
Action func(*Context, string) error
// Has unexported fields.
}
StringFlag is a flag with type string
@ -1789,6 +1800,7 @@ type StringSliceFlag struct {
TakesFile bool
Action func(*Context, []string) error
// Has unexported fields.
}
StringSliceFlag is a flag with type *StringSlice
@ -1900,6 +1912,7 @@ type TimestampFlag struct {
Timezone *time.Location
Action func(*Context, *time.Time) error
// Has unexported fields.
}
TimestampFlag is a flag with type *Timestamp
@ -1967,6 +1980,7 @@ type Uint64Flag struct {
Base int
Action func(*Context, uint64) error
// Has unexported fields.
}
Uint64Flag is a flag with type uint64
@ -2055,6 +2069,7 @@ type Uint64SliceFlag struct {
EnvVars []string
Action func(*Context, []uint64) error
// Has unexported fields.
}
Uint64SliceFlag is a flag with type *Uint64Slice
@ -2122,6 +2137,7 @@ type UintFlag struct {
Base int
Action func(*Context, uint) error
// Has unexported fields.
}
UintFlag is a flag with type uint
@ -2214,6 +2230,7 @@ type UintSliceFlag struct {
EnvVars []string
Action func(*Context, []uint) error
// Has unexported fields.
}
UintSliceFlag is a flag with type *UintSlice

View File

@ -447,6 +447,7 @@ type BoolFlag struct {
Count *int
Action func(*Context, bool) error
// Has unexported fields.
}
BoolFlag is a flag with type bool
@ -775,6 +776,7 @@ type DurationFlag struct {
EnvVars []string
Action func(*Context, time.Duration) error
// Has unexported fields.
}
DurationFlag is a flag with type time.Duration
@ -953,6 +955,7 @@ type Float64Flag struct {
EnvVars []string
Action func(*Context, float64) error
// Has unexported fields.
}
Float64Flag is a flag with type float64
@ -1041,6 +1044,7 @@ type Float64SliceFlag struct {
EnvVars []string
Action func(*Context, []float64) error
// Has unexported fields.
}
Float64SliceFlag is a flag with type *Float64Slice
@ -1123,6 +1127,7 @@ type GenericFlag struct {
TakesFile bool
Action func(*Context, interface{}) error
// Has unexported fields.
}
GenericFlag is a flag with type Generic
@ -1191,6 +1196,7 @@ type Int64Flag struct {
Base int
Action func(*Context, int64) error
// Has unexported fields.
}
Int64Flag is a flag with type int64
@ -1279,6 +1285,7 @@ type Int64SliceFlag struct {
EnvVars []string
Action func(*Context, []int64) error
// Has unexported fields.
}
Int64SliceFlag is a flag with type *Int64Slice
@ -1355,6 +1362,7 @@ type IntFlag struct {
Base int
Action func(*Context, int) error
// Has unexported fields.
}
IntFlag is a flag with type int
@ -1447,6 +1455,7 @@ type IntSliceFlag struct {
EnvVars []string
Action func(*Context, []int) error
// Has unexported fields.
}
IntSliceFlag is a flag with type *IntSlice
@ -1557,6 +1566,7 @@ type PathFlag struct {
TakesFile bool
Action func(*Context, Path) error
// Has unexported fields.
}
PathFlag is a flag with type Path
@ -1699,6 +1709,7 @@ type StringFlag struct {
TakesFile bool
Action func(*Context, string) error
// Has unexported fields.
}
StringFlag is a flag with type string
@ -1789,6 +1800,7 @@ type StringSliceFlag struct {
TakesFile bool
Action func(*Context, []string) error
// Has unexported fields.
}
StringSliceFlag is a flag with type *StringSlice
@ -1900,6 +1912,7 @@ type TimestampFlag struct {
Timezone *time.Location
Action func(*Context, *time.Time) error
// Has unexported fields.
}
TimestampFlag is a flag with type *Timestamp
@ -1967,6 +1980,7 @@ type Uint64Flag struct {
Base int
Action func(*Context, uint64) error
// Has unexported fields.
}
Uint64Flag is a flag with type uint64
@ -2055,6 +2069,7 @@ type Uint64SliceFlag struct {
EnvVars []string
Action func(*Context, []uint64) error
// Has unexported fields.
}
Uint64SliceFlag is a flag with type *Uint64Slice
@ -2122,6 +2137,7 @@ type UintFlag struct {
Base int
Action func(*Context, uint) error
// Has unexported fields.
}
UintFlag is a flag with type uint
@ -2214,6 +2230,7 @@ type UintSliceFlag struct {
EnvVars []string
Action func(*Context, []uint) error
// Has unexported fields.
}
UintSliceFlag is a flag with type *UintSlice

View File

@ -23,6 +23,8 @@ type Float64SliceFlag struct {
Aliases []string
EnvVars []string
defaultValue *Float64Slice
Action func(*Context, []float64) error
}
@ -65,6 +67,8 @@ type GenericFlag struct {
Aliases []string
EnvVars []string
defaultValue Generic
TakesFile bool
Action func(*Context, interface{}) error
@ -114,6 +118,8 @@ type Int64SliceFlag struct {
Aliases []string
EnvVars []string
defaultValue *Int64Slice
Action func(*Context, []int64) error
}
@ -156,6 +162,8 @@ type IntSliceFlag struct {
Aliases []string
EnvVars []string
defaultValue *IntSlice
Action func(*Context, []int) error
}
@ -198,6 +206,8 @@ type PathFlag struct {
Aliases []string
EnvVars []string
defaultValue Path
TakesFile bool
Action func(*Context, Path) error
@ -247,6 +257,8 @@ type StringSliceFlag struct {
Aliases []string
EnvVars []string
defaultValue *StringSlice
TakesFile bool
Action func(*Context, []string) error
@ -291,6 +303,8 @@ type TimestampFlag struct {
Aliases []string
EnvVars []string
defaultValue *Timestamp
Layout string
Timezone *time.Location
@ -342,6 +356,8 @@ type Uint64SliceFlag struct {
Aliases []string
EnvVars []string
defaultValue *Uint64Slice
Action func(*Context, []uint64) error
}
@ -384,6 +400,8 @@ type UintSliceFlag struct {
Aliases []string
EnvVars []string
defaultValue *UintSlice
Action func(*Context, []uint) error
}
@ -426,6 +444,8 @@ type BoolFlag struct {
Aliases []string
EnvVars []string
defaultValue bool
Count *int
Action func(*Context, bool) error
@ -475,6 +495,8 @@ type Float64Flag struct {
Aliases []string
EnvVars []string
defaultValue float64
Action func(*Context, float64) error
}
@ -522,6 +544,8 @@ type IntFlag struct {
Aliases []string
EnvVars []string
defaultValue int
Base int
Action func(*Context, int) error
@ -571,6 +595,8 @@ type Int64Flag struct {
Aliases []string
EnvVars []string
defaultValue int64
Base int
Action func(*Context, int64) error
@ -620,6 +646,8 @@ type StringFlag struct {
Aliases []string
EnvVars []string
defaultValue string
TakesFile bool
Action func(*Context, string) error
@ -669,6 +697,8 @@ type DurationFlag struct {
Aliases []string
EnvVars []string
defaultValue time.Duration
Action func(*Context, time.Duration) error
}
@ -716,6 +746,8 @@ type UintFlag struct {
Aliases []string
EnvVars []string
defaultValue uint
Base int
Action func(*Context, uint) error
@ -765,6 +797,8 @@ type Uint64Flag struct {
Aliases []string
EnvVars []string
defaultValue uint64
Base int
Action func(*Context, uint64) error