fixup! Report the source of a value when we cannot parse it

move bool to the end of the return arguments

remove "from " prefix in the source/fromWhere description

remove TODO notes from functions that don't currently perform error checking
This commit is contained in:
Mostyn Bramley-Moore 2020-11-07 14:05:37 +01:00
parent 500d6b04e6
commit cdc1f6e07c
16 changed files with 36 additions and 35 deletions

13
flag.go
View File

@ -372,17 +372,20 @@ func hasFlag(flags []Flag, fl Flag) bool {
return false return false
} }
func flagFromEnvOrFile(envVars []string, filePath string) (val string, ok bool, source string) { // Return the first value from a list of environment variables and files
// (which may or may not exist), a description of where the value was found,
// and a boolean which is true if a value was found.
func flagFromEnvOrFile(envVars []string, filePath string) (value string, fromWhere string, found bool) {
for _, envVar := range envVars { for _, envVar := range envVars {
envVar = strings.TrimSpace(envVar) envVar = strings.TrimSpace(envVar)
if val, ok := syscall.Getenv(envVar); ok { if value, found := syscall.Getenv(envVar); found {
return val, true, fmt.Sprintf("from environment variable %q", envVar) return value, fmt.Sprintf("environment variable %q", envVar), true
} }
} }
for _, fileVar := range strings.Split(filePath, ",") { for _, fileVar := range strings.Split(filePath, ",") {
if data, err := ioutil.ReadFile(fileVar); err == nil { if data, err := ioutil.ReadFile(fileVar); err == nil {
return string(data), true, fmt.Sprintf("from file %q", filePath) return string(data), fmt.Sprintf("file %q", filePath), true
} }
} }
return "", false, "" return "", "", false
} }

View File

@ -60,12 +60,12 @@ func (f *BoolFlag) GetValue() string {
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *BoolFlag) Apply(set *flag.FlagSet) error { func (f *BoolFlag) Apply(set *flag.FlagSet) error {
if val, ok, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" { if val != "" {
valBool, err := strconv.ParseBool(val) valBool, err := strconv.ParseBool(val)
if err != nil { if err != nil {
return fmt.Errorf("could not parse %q as bool value %s for flag %s: %s", val, source, f.Name, err) return fmt.Errorf("could not parse %q as bool value from %s for flag %s: %s", val, source, f.Name, err)
} }
f.Value = valBool f.Value = valBool

View File

@ -60,12 +60,12 @@ func (f *DurationFlag) GetValue() string {
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *DurationFlag) Apply(set *flag.FlagSet) error { func (f *DurationFlag) Apply(set *flag.FlagSet) error {
if val, ok, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" { if val != "" {
valDuration, err := time.ParseDuration(val) valDuration, err := time.ParseDuration(val)
if err != nil { if err != nil {
return fmt.Errorf("could not parse %q as duration value %s for flag %s: %s", val, source, f.Name, err) return fmt.Errorf("could not parse %q as duration value from %s for flag %s: %s", val, source, f.Name, err)
} }
f.Value = valDuration f.Value = valDuration

View File

@ -60,12 +60,12 @@ func (f *Float64Flag) GetValue() string {
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *Float64Flag) Apply(set *flag.FlagSet) error { func (f *Float64Flag) Apply(set *flag.FlagSet) error {
if val, ok, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" { if val != "" {
valFloat, err := strconv.ParseFloat(val, 10) valFloat, err := strconv.ParseFloat(val, 10)
if err != nil { if err != nil {
return fmt.Errorf("could not parse %q as float64 value %s for flag %s: %s", val, source, f.Name, err) return fmt.Errorf("could not parse %q as float64 value from %s for flag %s: %s", val, source, f.Name, err)
} }
f.Value = valFloat f.Value = valFloat

View File

@ -119,13 +119,13 @@ func (f *Float64SliceFlag) GetValue() string {
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error { func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error {
if val, ok, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" { if val != "" {
f.Value = &Float64Slice{} f.Value = &Float64Slice{}
for _, s := range strings.Split(val, ",") { for _, s := range strings.Split(val, ",") {
if err := f.Value.Set(strings.TrimSpace(s)); err != nil { if err := f.Value.Set(strings.TrimSpace(s)); err != nil {
return fmt.Errorf("could not parse %q as float64 slice value %s for flag %s: %s", f.Value, source, f.Name, err) return fmt.Errorf("could not parse %q as float64 slice value from %s for flag %s: %s", f.Value, source, f.Name, err)
} }
} }

View File

@ -69,10 +69,10 @@ func (f *GenericFlag) GetValue() string {
// Apply takes the flagset and calls Set on the generic flag with the value // Apply takes the flagset and calls Set on the generic flag with the value
// provided by the user for parsing by the flag // 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, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" { if val != "" {
if err := f.Value.Set(val); err != nil { if err := f.Value.Set(val); err != nil {
return fmt.Errorf("could not parse %q %s as value for flag %s: %s", val, source, f.Name, err) return fmt.Errorf("could not parse %q from %s as value for flag %s: %s", val, source, f.Name, err)
} }
f.HasBeenSet = true f.HasBeenSet = true

View File

@ -60,12 +60,12 @@ func (f *IntFlag) GetValue() string {
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *IntFlag) Apply(set *flag.FlagSet) error { func (f *IntFlag) Apply(set *flag.FlagSet) error {
if val, ok, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" { if val != "" {
valInt, err := strconv.ParseInt(val, 0, 64) valInt, err := strconv.ParseInt(val, 0, 64)
if err != nil { if err != nil {
return fmt.Errorf("could not parse %q as int value %s for flag %s: %s", val, source, f.Name, err) return fmt.Errorf("could not parse %q as int value from %s for flag %s: %s", val, source, f.Name, err)
} }
f.Value = int(valInt) f.Value = int(valInt)

View File

@ -60,12 +60,12 @@ func (f *Int64Flag) GetValue() string {
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *Int64Flag) Apply(set *flag.FlagSet) error { func (f *Int64Flag) Apply(set *flag.FlagSet) error {
if val, ok, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" { if val != "" {
valInt, err := strconv.ParseInt(val, 0, 64) valInt, err := strconv.ParseInt(val, 0, 64)
if err != nil { if err != nil {
return fmt.Errorf("could not parse %q as int value %s for flag %s: %s", val, source, f.Name, err) return fmt.Errorf("could not parse %q as int value from %s for flag %s: %s", val, source, f.Name, err)
} }
f.Value = valInt f.Value = valInt

View File

@ -120,12 +120,12 @@ func (f *Int64SliceFlag) GetValue() string {
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error { func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error {
if val, ok, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
f.Value = &Int64Slice{} f.Value = &Int64Slice{}
for _, s := range strings.Split(val, ",") { for _, s := range strings.Split(val, ",") {
if err := f.Value.Set(strings.TrimSpace(s)); err != nil { if err := f.Value.Set(strings.TrimSpace(s)); err != nil {
return fmt.Errorf("could not parse %q as int64 slice value %s for flag %s: %s", val, source, f.Name, err) return fmt.Errorf("could not parse %q as int64 slice value from %s for flag %s: %s", val, source, f.Name, err)
} }
} }

View File

@ -131,12 +131,12 @@ func (f *IntSliceFlag) GetValue() string {
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *IntSliceFlag) Apply(set *flag.FlagSet) error { func (f *IntSliceFlag) Apply(set *flag.FlagSet) error {
if val, ok, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
f.Value = &IntSlice{} f.Value = &IntSlice{}
for _, s := range strings.Split(val, ",") { for _, s := range strings.Split(val, ",") {
if err := f.Value.Set(strings.TrimSpace(s)); err != nil { if err := f.Value.Set(strings.TrimSpace(s)); err != nil {
return fmt.Errorf("could not parse %q as int slice value %s for flag %s: %s", val, source, f.Name, err) return fmt.Errorf("could not parse %q as int slice value from %s for flag %s: %s", val, source, f.Name, err)
} }
} }

View File

@ -56,8 +56,7 @@ func (f *PathFlag) GetValue() string {
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *PathFlag) Apply(set *flag.FlagSet) error { func (f *PathFlag) Apply(set *flag.FlagSet) error {
// TODO: how to report the source of parse errors? if val, _, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val, ok, _ := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
f.Value = val f.Value = val
f.HasBeenSet = true f.HasBeenSet = true
} }

View File

@ -57,8 +57,7 @@ func (f *StringFlag) GetValue() string {
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *StringFlag) Apply(set *flag.FlagSet) error { func (f *StringFlag) Apply(set *flag.FlagSet) error {
// TODO: how to report source? if val, _, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val, ok, _ := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
f.Value = val f.Value = val
f.HasBeenSet = true f.HasBeenSet = true
} }

View File

@ -123,7 +123,7 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {
} }
if val, ok, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if f.Value == nil { if f.Value == nil {
f.Value = &StringSlice{} f.Value = &StringSlice{}
} }
@ -134,7 +134,7 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {
for _, s := range strings.Split(val, ",") { for _, s := range strings.Split(val, ",") {
if err := destination.Set(strings.TrimSpace(s)); err != nil { if err := destination.Set(strings.TrimSpace(s)); err != nil {
return fmt.Errorf("could not parse %q as string value %s for flag %s: %s", val, source, f.Name, err) return fmt.Errorf("could not parse %q as string value from %s for flag %s: %s", val, source, f.Name, err)
} }
} }

View File

@ -123,9 +123,9 @@ func (f *TimestampFlag) Apply(set *flag.FlagSet) error {
} }
f.Value.SetLayout(f.Layout) f.Value.SetLayout(f.Layout)
if val, ok, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if err := f.Value.Set(val); err != nil { if err := f.Value.Set(val); err != nil {
return fmt.Errorf("could not parse %q as timestamp value %s for flag %s: %s", val, source, f.Name, err) return fmt.Errorf("could not parse %q as timestamp value from %s for flag %s: %s", val, source, f.Name, err)
} }
f.HasBeenSet = true f.HasBeenSet = true
} }

View File

@ -54,11 +54,11 @@ func (f *UintFlag) GetUsage() string {
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *UintFlag) Apply(set *flag.FlagSet) error { func (f *UintFlag) Apply(set *flag.FlagSet) error {
if val, ok, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" { if val != "" {
valInt, err := strconv.ParseUint(val, 0, 64) valInt, err := strconv.ParseUint(val, 0, 64)
if err != nil { if err != nil {
return fmt.Errorf("could not parse %q as uint value %s for flag %s: %s", val, source, f.Name, err) return fmt.Errorf("could not parse %q as uint value from %s for flag %s: %s", val, source, f.Name, err)
} }
f.Value = uint(valInt) f.Value = uint(valInt)

View File

@ -54,11 +54,11 @@ func (f *Uint64Flag) GetUsage() string {
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *Uint64Flag) Apply(set *flag.FlagSet) error { func (f *Uint64Flag) Apply(set *flag.FlagSet) error {
if val, ok, source := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
if val != "" { if val != "" {
valInt, err := strconv.ParseUint(val, 0, 64) valInt, err := strconv.ParseUint(val, 0, 64)
if err != nil { if err != nil {
return fmt.Errorf("could not parse %q as uint64 value %s for flag %s: %s", val, source, f.Name, err) return fmt.Errorf("could not parse %q as uint64 value from %s for flag %s: %s", val, source, f.Name, err)
} }
f.Value = valInt f.Value = valInt