From 7e5da050b17ad0e21c4f58215c40cea7816c4dd1 Mon Sep 17 00:00:00 2001 From: Pablo Baeyens Date: Tue, 31 May 2022 10:49:08 +0200 Subject: [PATCH] Revert "Make AllKeys and AllSettings return set-but-empty keys" (#22) --- viper.go | 44 +++++++++++--------------------------------- viper_test.go | 36 ------------------------------------ 2 files changed, 11 insertions(+), 69 deletions(-) diff --git a/viper.go b/viper.go index e7c8edb..82d415a 100644 --- a/viper.go +++ b/viper.go @@ -339,16 +339,6 @@ func (v *Viper) getEnv(key string) (string, bool) { return val, ok && (v.allowEmptyEnv || val != "") } -func (v *Viper) getAllEnvBoundAndSet() map[string]interface{} { - tgt := map[string]interface{}{} - for key, value := range v.env { - if _, ok := v.getEnv(v.mergeWithEnvPrefix(key)); ok { - tgt[key] = value - } - } - return tgt -} - // ConfigFileUsed returns the file used to populate the config registry. func ConfigFileUsed() string { return v.ConfigFileUsed() } func (v *Viper) ConfigFileUsed() string { return v.configFile } @@ -1269,22 +1259,6 @@ func (v *Viper) Set(key string, value interface{}) { deepestMap[lastKey] = value } -// Unset removes a value set with Set -// Unset is case-insensitive for a key. -// Values which come from flags, config file, ENV or default can't be unset. -func Unset(key string) { v.Unset(key) } -func (v *Viper) Unset(key string) { - // If alias passed in, then set the proper override - key = v.realKey(strings.ToLower(key)) - - path := strings.Split(key, v.keyDelim) - lastKey := strings.ToLower(path[len(path)-1]) - deepestMap := deepSearch(v.override, path[0:len(path)-1]) - - // unset innermost value - delete(deepestMap, lastKey) -} - // ReadInConfig will discover and load the configuration file from disk // and key/value stores, searching in one of the defined paths. func ReadInConfig() error { return v.ReadInConfig() } @@ -1597,6 +1571,14 @@ func castToMapStringInterface( return tgt } +func castMapStringSliceToMapInterface(src map[string][]string) map[string]interface{} { + tgt := map[string]interface{}{} + for k, v := range src { + tgt[k] = v + } + return tgt +} + func castMapStringToMapInterface(src map[string]string) map[string]interface{} { tgt := map[string]interface{}{} for k, v := range src { @@ -1763,7 +1745,7 @@ func (v *Viper) AllKeys() []string { m = v.flattenAndMergeMap(m, castMapStringToMapInterface(v.aliases), "") m = v.flattenAndMergeMap(m, v.override, "") m = v.mergeFlatMap(m, castMapFlagToMapInterface(v.pflags)) - m = v.mergeFlatMap(m, v.getAllEnvBoundAndSet()) + m = v.mergeFlatMap(m, castMapStringSliceToMapInterface(v.env)) m = v.flattenAndMergeMap(m, v.config, "") m = v.flattenAndMergeMap(m, v.kvstore, "") m = v.flattenAndMergeMap(m, v.defaults, "") @@ -1807,10 +1789,6 @@ func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interfac shadow[strings.ToLower(fullKey)] = true continue } - if len(m2) == 0 { - // empty dict explicitly present in the map - shadow[strings.ToLower(fullKey)] = true - } // recursively merge to shadow map shadow = v.flattenAndMergeMap(shadow, m2, fullKey) } @@ -1847,8 +1825,8 @@ func (v *Viper) AllSettings() map[string]interface{} { for _, k := range v.AllKeys() { value := v.Get(k) if value == nil { - // Key set but empty, include it in the output as a null value - m[k] = nil + // should not happen, since AllKeys() returns only keys holding a value, + // check just in case anything changes continue } diff --git a/viper_test.go b/viper_test.go index d85adee..21efc4b 100644 --- a/viper_test.go +++ b/viper_test.go @@ -1818,39 +1818,3 @@ func TestKnownKeys(t *testing.T) { t.Error("SetKnown didn't mark key as known") } } - -func TestEmptySection(t *testing.T) { - - var yamlWithEnvVars = ` -key: - subkey: -another_key: -empty_dict: {} -` - - v := New() - initConfig(v, "yaml", yamlWithEnvVars) - v.SetKnown("is_known") - v.SetDefault("has_default", true) - v.BindEnv("is_bound") - - // AllKeys includes empty keys - keys := v.AllKeys() - assert.NotContains(t, keys, "key") // Only empty leaf nodes are returned - assert.Contains(t, keys, "key.subkey") - assert.Contains(t, keys, "another_key") - assert.Contains(t, keys, "empty_dict") - assert.NotContains(t, keys, "is_known") - assert.Contains(t, keys, "has_default") - assert.NotContains(t, keys, "is_bound") - - // AllSettings includes empty keys - vars := v.AllSettings() - assert.NotContains(t, vars, "key") // Only empty leaf nodes are returned - assert.Contains(t, vars, "key.subkey") - assert.Contains(t, vars, "another_key") - assert.Contains(t, vars, "empty_dict") - assert.NotContains(t, vars, "is_known") - assert.Contains(t, vars, "has_default") - assert.NotContains(t, vars, "is_bound") -}