mirror of
https://github.com/spf13/viper
synced 2024-12-22 03:27:03 +00:00
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.
This commit is contained in:
parent
3cf05f93ef
commit
2b24bea958
2 changed files with 52 additions and 13 deletions
50
viper.go
50
viper.go
|
@ -107,20 +107,23 @@ func MarshalKey(key string, rawVal interface{}) error {
|
|||
}
|
||||
|
||||
// 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 @@ func registerAlias(alias string, key string) {
|
|||
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 @@ func MarshallReader(in io.Reader) {
|
|||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -21,7 +21,9 @@ hobbies:
|
|||
clothing:
|
||||
jacket: leather
|
||||
trousers: denim
|
||||
age: 35`)
|
||||
age: 35
|
||||
beard: true
|
||||
`)
|
||||
|
||||
var tomlExample = []byte(`
|
||||
title = "TOML Example"
|
||||
|
@ -87,6 +89,15 @@ func TestAliases(t *testing.T) {
|
|||
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 @@ func TestMarshal(t *testing.T) {
|
|||
t.Fatalf("unable to decode into struct, %v", err)
|
||||
}
|
||||
assert.Equal(t, &C, &config{Name: "Steve", Port: 1234})
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue