mirror of
https://github.com/spf13/viper
synced 2024-12-22 11:37:02 +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
|
// Marshals the config into a Struct
|
||||||
func Marshal(rawVal interface{}) (err error) {
|
func Marshal(rawVal interface{}) error {
|
||||||
err = mapstructure.Decode(defaults, rawVal)
|
err := mapstructure.Decode(defaults, rawVal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
err = mapstructure.Decode(config, rawVal)
|
err = mapstructure.Decode(config, rawVal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
err = mapstructure.Decode(override, rawVal)
|
err = mapstructure.Decode(override, rawVal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
return
|
|
||||||
|
insensativiseMaps()
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a specific key to a flag (as used by cobra)
|
// 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)
|
alias = strings.ToLower(alias)
|
||||||
if alias != key && alias != realKey(key) {
|
if alias != key && alias != realKey(key) {
|
||||||
_, exists := aliases[alias]
|
_, exists := aliases[alias]
|
||||||
|
|
||||||
if !exists {
|
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
|
aliases[alias] = key
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -310,17 +329,26 @@ func MarshallReader(in io.Reader) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
insensativiseMap()
|
insensativiseMap(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
func insensativiseMap() {
|
func insensativiseMaps() {
|
||||||
for key, _ := range config {
|
insensativiseMap(config)
|
||||||
if key != strings.ToLower(key) {
|
insensativiseMap(defaults)
|
||||||
registerAlias(key, key)
|
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.
|
// Name for the config file.
|
||||||
// Does not include extension.
|
// Does not include extension.
|
||||||
func SetConfigName(in string) {
|
func SetConfigName(in string) {
|
||||||
|
|
|
@ -21,7 +21,9 @@ hobbies:
|
||||||
clothing:
|
clothing:
|
||||||
jacket: leather
|
jacket: leather
|
||||||
trousers: denim
|
trousers: denim
|
||||||
age: 35`)
|
age: 35
|
||||||
|
beard: true
|
||||||
|
`)
|
||||||
|
|
||||||
var tomlExample = []byte(`
|
var tomlExample = []byte(`
|
||||||
title = "TOML Example"
|
title = "TOML Example"
|
||||||
|
@ -87,6 +89,15 @@ func TestAliases(t *testing.T) {
|
||||||
assert.Equal(t, 45, Get("age"))
|
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) {
|
func TestYML(t *testing.T) {
|
||||||
Reset()
|
Reset()
|
||||||
SetConfigType("yml")
|
SetConfigType("yml")
|
||||||
|
@ -153,4 +164,4 @@ func TestMarshal(t *testing.T) {
|
||||||
t.Fatalf("unable to decode into struct, %v", err)
|
t.Fatalf("unable to decode into struct, %v", err)
|
||||||
}
|
}
|
||||||
assert.Equal(t, &C, &config{Name: "Steve", Port: 1234})
|
assert.Equal(t, &C, &config{Name: "Steve", Port: 1234})
|
||||||
}
|
}
|
Loading…
Reference in a new issue