diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2018-10-27 11:10:39 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2018-10-27 15:05:40 +0200 |
commit | dac7092a9cb22d59db28fb15af15f7b14ff47588 (patch) | |
tree | e001634ebe4e108abe710a24efe22a85e4568bbf /common/collections | |
parent | b27ccf34bf4e5ee618a66fa11c68a9690e395034 (diff) |
common/collections: Allow a mix of slice types in append/Scratch.Add
The type handling in these was improved in Hugo 0.49, but this also meant that it was no longer possible to start out with a string slice and later append `Page` etc. to it.
This commit makes sure that the old behaviour is now possible again by falling back to a `[]interface{}` as a last resort.
Fixes #5361
Diffstat (limited to 'common/collections')
-rw-r--r-- | common/collections/append.go | 33 | ||||
-rw-r--r-- | common/collections/append_test.go | 8 |
2 files changed, 37 insertions, 4 deletions
diff --git a/common/collections/append.go b/common/collections/append.go index 97bf84988..617d6258a 100644 --- a/common/collections/append.go +++ b/common/collections/append.go @@ -48,6 +48,10 @@ func Append(to interface{}, from ...interface{}) (interface{}, error) { // If we get []string []string, we append the from slice to to if tot == fromt { return reflect.AppendSlice(tov, fromv).Interface(), nil + } else if !fromt.AssignableTo(tot) { + // Fall back to a []interface{} slice. + return appendToInterfaceSliceFromValues(tov, fromv) + } } } @@ -60,7 +64,8 @@ func Append(to interface{}, from ...interface{}) (interface{}, error) { for _, f := range from { fv := reflect.ValueOf(f) if !fv.Type().AssignableTo(tot) { - return nil, fmt.Errorf("append element type mismatch: expected %v, got %v", tot, fv.Type()) + // Fall back to a []interface{} slice. + return appendToInterfaceSlice(tov, from...) } tov = reflect.Append(tov, fv) } @@ -68,6 +73,32 @@ func Append(to interface{}, from ...interface{}) (interface{}, error) { return tov.Interface(), nil } +func appendToInterfaceSliceFromValues(slice1, slice2 reflect.Value) ([]interface{}, error) { + var tos []interface{} + + for _, slice := range []reflect.Value{slice1, slice2} { + for i := 0; i < slice.Len(); i++ { + tos = append(tos, slice.Index(i).Interface()) + } + } + + return tos, nil +} + +func appendToInterfaceSlice(tov reflect.Value, from ...interface{}) ([]interface{}, error) { + var tos []interface{} + + for i := 0; i < tov.Len(); i++ { + tos = append(tos, tov.Index(i).Interface()) + } + + for _, v := range from { + tos = append(tos, v) + } + + return tos, nil +} + // indirect is borrowed from the Go stdlib: 'text/template/exec.go' // TODO(bep) consolidate func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { diff --git a/common/collections/append_test.go b/common/collections/append_test.go index f89ec60f0..c08a69c0d 100644 --- a/common/collections/append_test.go +++ b/common/collections/append_test.go @@ -46,10 +46,12 @@ func TestAppend(t *testing.T) { {testSlicerInterfaces{&tstSlicerIn1{"a"}, &tstSlicerIn1{"b"}}, []interface{}{&tstSlicerIn1{"c"}}, testSlicerInterfaces{&tstSlicerIn1{"a"}, &tstSlicerIn1{"b"}, &tstSlicerIn1{"c"}}}, + //https://github.com/gohugoio/hugo/issues/5361 + {[]string{"a", "b"}, []interface{}{tstSlicers{&tstSlicer{"a"}, &tstSlicer{"b"}}}, + []interface{}{"a", "b", &tstSlicer{"a"}, &tstSlicer{"b"}}}, + {[]string{"a", "b"}, []interface{}{&tstSlicer{"a"}}, + []interface{}{"a", "b", &tstSlicer{"a"}}}, // Errors - {testSlicerInterfaces{&tstSlicerIn1{"a"}, &tstSlicerIn1{"b"}}, - []interface{}{"c"}, - false}, {"", []interface{}{[]string{"a", "b"}}, false}, // No string concatenation. {"ab", |