tpl/collections: Some more params merge adjustments

* If the end result is maps.Params, we need to lower the keys
* Also make sure to handle nested maps of different type

Update #6633
This commit is contained in:
Bjørn Erik Pedersen 2019-12-19 20:50:30 +01:00 committed by GitHub
parent a67d95fe1a
commit ccb1bf1abb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 3 deletions

View file

@ -17,6 +17,8 @@ import (
"reflect" "reflect"
"strings" "strings"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/hreflect" "github.com/gohugoio/hugo/common/hreflect"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -68,6 +70,9 @@ func mergeMap(dst, src reflect.Value) reflect.Value {
out := reflect.MakeMap(dst.Type()) out := reflect.MakeMap(dst.Type())
// If the destination is Params, we must lower case all keys.
_, lowerCase := dst.Interface().(maps.Params)
// Copy the destination map. // Copy the destination map.
for _, key := range dst.MapKeys() { for _, key := range dst.MapKeys() {
v := dst.MapIndex(key) v := dst.MapIndex(key)
@ -81,15 +86,18 @@ func mergeMap(dst, src reflect.Value) reflect.Value {
dv, found := caseInsensitiveLookup(dst, key) dv, found := caseInsensitiveLookup(dst, key)
if found { if found {
// If both are the same map type, merge. // If both are the same map key type, merge.
dve := dv.Elem() dve := dv.Elem()
if dve.Kind() == reflect.Map { if dve.Kind() == reflect.Map {
sve := sv.Elem() sve := sv.Elem()
if dve.Type() == sve.Type() { if dve.Type().Key() == sve.Type().Key() {
out.SetMapIndex(key, mergeMap(dve, sve)) out.SetMapIndex(key, mergeMap(dve, sve))
} }
} }
} else { } else {
if lowerCase && key.Kind() == reflect.String {
key = reflect.ValueOf(strings.ToLower(key.String()))
}
out.SetMapIndex(key, sv) out.SetMapIndex(key, sv)
} }
} }

View file

@ -66,11 +66,25 @@ func TestMerge(t *testing.T) {
map[string]interface{}{"a": 42, "c": 3}, map[string]interface{}{"a": 42, "c": 3},
maps.Params{"a": int(1), "b": int(2), "c": int(3)}, false}, maps.Params{"a": int(1), "b": int(2), "c": int(3)}, false},
{ {
// https://github.com/gohugoio/hugo/issues/6633 "params dst, upper case src",
maps.Params{"a": 1, "b": 2},
map[string]interface{}{"a": 42, "C": 3},
maps.Params{"a": int(1), "b": int(2), "c": int(3)}, false},
{
"params src", "params src",
map[string]interface{}{"a": 1, "c": 2}, map[string]interface{}{"a": 1, "c": 2},
maps.Params{"a": 42, "c": 3}, maps.Params{"a": 42, "c": 3},
map[string]interface{}{"a": int(1), "c": int(2)}, false}, map[string]interface{}{"a": int(1), "c": int(2)}, false},
{
"params src, upper case dst",
map[string]interface{}{"a": 1, "C": 2},
maps.Params{"a": 42, "c": 3},
map[string]interface{}{"a": int(1), "C": int(2)}, false},
{
"nested, params dst",
maps.Params{"a": 1, "b": maps.Params{"d": 1, "e": 2}},
map[string]interface{}{"a": 42, "c": 3, "b": map[string]interface{}{"d": 55, "e": 66, "f": 3}},
maps.Params{"a": 1, "b": maps.Params{"d": 1, "e": 2, "f": 3}, "c": 3}, false},
{"src nil", simpleMap, nil, simpleMap, false}, {"src nil", simpleMap, nil, simpleMap, false},
// Error cases. // Error cases.
{"dst not a map", "not a map", nil, nil, true}, {"dst not a map", "not a map", nil, nil, true},