fix issue #8
This fixes the aliases in config files bug. Whenever we register an alias, if there is a value in
the config (or defaults or override) for the alias, we move that value to the new "real key".
Added a test for the bug, which fails without the changes and passes with the changes.
This also fixes a bug in Hugo, where specifying "Taxonomies" in your config file doesn't get recognized,
because Hugo aliases "Taxonomies" to "Indexes" which means that when the code does a Get("Taxnomies") it
got translated to Get("Indexes"), which didn't exist in the original config map.
diff --git a/viper.go b/viper.go
index 44f3819..38bd17d 100644
--- a/viper.go
+++ b/viper.go
@@ -107,20 +107,23 @@
}
// Marshals the config into a Struct
-func Marshal(rawVal interface{}) (err error) {
- err = mapstructure.Decode(defaults, rawVal)
+func Marshal(rawVal interface{}) error {
+ err := mapstructure.Decode(defaults, rawVal)
if err != nil {
- return
+ return err
}
err = mapstructure.Decode(config, rawVal)
if err != nil {
- return
+ return err
}
err = mapstructure.Decode(override, rawVal)
if err != nil {
- return
+ return err
}
- return
+
+ insensativiseMaps()
+
+ return nil
}
// Bind a specific key to a flag (as used by cobra)
@@ -224,7 +227,23 @@
alias = strings.ToLower(alias)
if alias != key && alias != realKey(key) {
_, exists := aliases[alias]
+
if !exists {
+ // if we alias something that exists in one of the maps to another
+ // name, we'll never be able to get that value using the original
+ // name, so move the config value to the new realkey.
+ if val, ok := config[alias]; ok {
+ delete(config, alias)
+ config[key] = val
+ }
+ if val, ok := defaults[alias]; ok {
+ delete(defaults, alias)
+ defaults[key] = val
+ }
+ if val, ok := override[alias]; ok {
+ delete(override, alias)
+ override[key] = val
+ }
aliases[alias] = key
}
} else {
@@ -310,17 +329,26 @@
}
}
- insensativiseMap()
+ insensativiseMap(config)
}
-func insensativiseMap() {
- for key, _ := range config {
- if key != strings.ToLower(key) {
- registerAlias(key, key)
+func insensativiseMaps() {
+ insensativiseMap(config)
+ insensativiseMap(defaults)
+ insensativiseMap(override)
+}
+
+func insensativiseMap(m map[string]interface{}) {
+ for key, val := range m {
+ lower := strings.ToLower(key)
+ if key != lower {
+ delete(m, key)
+ m[lower] = val
}
}
}
+
// Name for the config file.
// Does not include extension.
func SetConfigName(in string) {
diff --git a/viper_test.go b/viper_test.go
index b077b5b..ad20da8 100644
--- a/viper_test.go
+++ b/viper_test.go
@@ -21,7 +21,9 @@
clothing:
jacket: leather
trousers: denim
-age: 35`)
+age: 35
+beard: true
+`)
var tomlExample = []byte(`
title = "TOML Example"
@@ -87,6 +89,15 @@
assert.Equal(t, 45, Get("age"))
}
+func TestAliasInConfigFile(t *testing.T) {
+ // the config file specifies "beard". If we make this an alias for
+ // "hasbeard", we still want the old config file to work with beard.
+ RegisterAlias("beard", "hasbeard")
+ assert.Equal(t, true, Get("hasbeard"))
+ Set("hasbeard", false)
+ assert.Equal(t, false, Get("beard"))
+}
+
func TestYML(t *testing.T) {
Reset()
SetConfigType("yml")
@@ -153,4 +164,4 @@
t.Fatalf("unable to decode into struct, %v", err)
}
assert.Equal(t, &C, &config{Name: "Steve", Port: 1234})
-}
+}
\ No newline at end of file