From 11588a03fa7c6d33f2d4bbdcd3813001a4a92b0b Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Wed, 10 Jan 2018 10:35:47 -0600 Subject: [PATCH] Prevent AutomaticEnv from clobbering an explicit mapping When an explicit environment variable mapping is set for a key, do not use the automatic mapping. This allows using AutomaticEnv while specifying a special mapping for a single key. It's important to both check for the explicit mapping first, and to not fall back to the automatic mapping when the explicit environment variable is not set. Otherwise it's very difficult to use AutomaticEnv when you have a flag that uses a commonly set environment variable, such as --path. When I map --path to SPECIAL_PATH, it shouldn't fall back to PATH when SPECIAL_PATH isn't set. --- viper.go | 17 ++++++++--------- viper_test.go | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/viper.go b/viper.go index ad8a037..93442b9 100644 --- a/viper.go +++ b/viper.go @@ -931,9 +931,14 @@ func (v *Viper) find(lcaseKey string) interface{} { } // Env override next - if v.automaticEnvApplied { - // even if it hasn't been registered, if automaticEnv is used, - // check any Get request + // Check for an explicit environment key mapping first, before applying AutomaticEnv + envkey, exists := v.env[lcaseKey] + if exists { + if val = v.getEnv(envkey); val != "" { + return val + } + } else if v.automaticEnvApplied { + // If it hasn't been registered, check any Get request if val = v.getEnv(v.mergeWithEnvPrefix(lcaseKey)); val != "" { return val } @@ -941,12 +946,6 @@ func (v *Viper) find(lcaseKey string) interface{} { return nil } } - envkey, exists := v.env[lcaseKey] - if exists { - if val = v.getEnv(envkey); val != "" { - return val - } - } if nested && v.isPathShadowedInFlatMap(path, v.env) != "" { return nil } diff --git a/viper_test.go b/viper_test.go index c93480e..44f24b8 100644 --- a/viper_test.go +++ b/viper_test.go @@ -409,6 +409,20 @@ func TestAutoEnv(t *testing.T) { assert.Equal(t, "13", Get("foo_bar")) } +func TestAutoEnvOverride(t *testing.T) { + Reset() + + BindEnv("path", "SPECIAL_PATH") + AutomaticEnv() + os.Setenv("SPECIAL_PATH", "/home/me/special") + os.Setenv("PATH", "/usr/local/bin:/usr/bin") + + assert.Equal(t, "/home/me/special", Get("path")) + + os.Unsetenv("SPECIAL_PATH") + assert.Nil(t, Get("path")) +} + func TestAutoEnvWithPrefix(t *testing.T) { Reset()