find() looks for flag's default values only when requested.

Default value should be looked for by Get(), but not by IsSet().

This logic should remain inside find(), to make sure that shadowing
of keys is handled properly.

Fixes Issue #276.
This commit is contained in:
Benoit Masson 2017-04-11 22:15:44 +02:00 committed by Márk Sági-Kazár
parent 4e1ebbdaba
commit 9e353e395e

View file

@ -670,7 +670,7 @@ func GetViper() *Viper {
func Get(key string) interface{} { return v.Get(key) } func Get(key string) interface{} { return v.Get(key) }
func (v *Viper) Get(key string) interface{} { func (v *Viper) Get(key string) interface{} {
lcaseKey := strings.ToLower(key) lcaseKey := strings.ToLower(key)
val := v.find(lcaseKey) val := v.find(lcaseKey, true)
if val == nil { if val == nil {
return nil return nil
} }
@ -977,11 +977,15 @@ func (v *Viper) BindEnv(input ...string) error {
} }
// Given a key, find the value. // Given a key, find the value.
// Viper will check in the following order: //
// flag, env, config file, key/value store, default.
// Viper will check to see if an alias exists first. // Viper will check to see if an alias exists first.
// Viper will then check in the following order:
// flag, env, config file, key/value store.
// Lastly, if no value was found and flagDefault is true, and if the key
// corresponds to a flag, the flag's default value is returned.
//
// Note: this assumes a lower-cased key given. // Note: this assumes a lower-cased key given.
func (v *Viper) find(lcaseKey string) interface{} { func (v *Viper) find(lcaseKey string, flagDefault bool) interface{} {
var ( var (
val interface{} val interface{}
@ -1083,29 +1087,31 @@ func (v *Viper) find(lcaseKey string) interface{} {
return nil return nil
} }
// last chance: if no other value is returned and a flag does exist for the value, if flagDefault {
// get the flag's value even if the flag's value has not changed // last chance: if no value is found and a flag does exist for the key,
if flag, exists := v.pflags[lcaseKey]; exists { // get the flag's default value even if the flag's value has not been set.
switch flag.ValueType() { if flag, exists := v.pflags[lcaseKey]; exists {
case "int", "int8", "int16", "int32", "int64": switch flag.ValueType() {
return cast.ToInt(flag.ValueString()) case "int", "int8", "int16", "int32", "int64":
case "bool": return cast.ToInt(flag.ValueString())
return cast.ToBool(flag.ValueString()) case "bool":
case "stringSlice": return cast.ToBool(flag.ValueString())
s := strings.TrimPrefix(flag.ValueString(), "[") case "stringSlice":
s = strings.TrimSuffix(s, "]") s := strings.TrimPrefix(flag.ValueString(), "[")
res, _ := readAsCSV(s) s = strings.TrimSuffix(s, "]")
return res res, _ := readAsCSV(s)
case "intSlice": return res
s := strings.TrimPrefix(flag.ValueString(), "[") case "intSlice":
s = strings.TrimSuffix(s, "]") s := strings.TrimPrefix(flag.ValueString(), "[")
res, _ := readAsCSV(s) s = strings.TrimSuffix(s, "]")
return cast.ToIntSlice(res) res, _ := readAsCSV(s)
default: return cast.ToIntSlice(res)
return flag.ValueString() default:
return flag.ValueString()
}
} }
// last item, no need to check shadowing
} }
// last item, no need to check shadowing
return nil return nil
} }
@ -1124,7 +1130,7 @@ func readAsCSV(val string) ([]string, error) {
func IsSet(key string) bool { return v.IsSet(key) } func IsSet(key string) bool { return v.IsSet(key) }
func (v *Viper) IsSet(key string) bool { func (v *Viper) IsSet(key string) bool {
lcaseKey := strings.ToLower(key) lcaseKey := strings.ToLower(key)
val := v.find(lcaseKey) val := v.find(lcaseKey, false)
return val != nil return val != nil
} }