Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/gohugoio/hugo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2018-10-27 12:10:39 +0300
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2018-10-27 16:05:40 +0300
commitdac7092a9cb22d59db28fb15af15f7b14ff47588 (patch)
treee001634ebe4e108abe710a24efe22a85e4568bbf /common
parentb27ccf34bf4e5ee618a66fa11c68a9690e395034 (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')
-rw-r--r--common/collections/append.go33
-rw-r--r--common/collections/append_test.go8
-rw-r--r--common/maps/scratch_test.go14
3 files changed, 51 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",
diff --git a/common/maps/scratch_test.go b/common/maps/scratch_test.go
index bf37d79df..4550a22c5 100644
--- a/common/maps/scratch_test.go
+++ b/common/maps/scratch_test.go
@@ -96,6 +96,20 @@ func TestScratchAddTypedSliceToInterfaceSlice(t *testing.T) {
}
+// https://github.com/gohugoio/hugo/issues/5361
+func TestScratchAddDifferentTypedSliceToInterfaceSlice(t *testing.T) {
+ t.Parallel()
+ assert := require.New(t)
+
+ scratch := NewScratch()
+ scratch.Set("slice", []string{"foo"})
+
+ _, err := scratch.Add("slice", []int{1, 2})
+ assert.NoError(err)
+ assert.Equal([]interface{}{"foo", 1, 2}, scratch.Get("slice"))
+
+}
+
func TestScratchSet(t *testing.T) {
t.Parallel()
assert := require.New(t)