summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Maczukin <tomasz@maczukin.pl>2019-03-26 20:54:34 +0100
committerTomasz Maczukin <tomasz@maczukin.pl>2019-07-31 15:04:28 +0200
commitef0a383ec767ba64a50f64d53b384b8407e6ea6e (patch)
treedc3e990fca9803d2597b9885ff214d1ebee16e1b
parentAdd configuration template file support for registration command (diff)
downloadgitlab-runner-ef0a383ec767ba64a50f64d53b384b8407e6ea6e.tar.gz
Update github.com/imdario/mergo version
-rw-r--r--Gopkg.lock6
-rw-r--r--Gopkg.toml8
-rw-r--r--vendor/github.com/imdario/mergo/issue17_test.go4
-rw-r--r--vendor/github.com/imdario/mergo/issue23_test.go2
-rw-r--r--vendor/github.com/imdario/mergo/issue33_test.go33
-rw-r--r--vendor/github.com/imdario/mergo/issue38_test.go59
-rw-r--r--vendor/github.com/imdario/mergo/issue50_test.go18
-rw-r--r--vendor/github.com/imdario/mergo/issue52_test.go99
-rw-r--r--vendor/github.com/imdario/mergo/issue61_test.go20
-rw-r--r--vendor/github.com/imdario/mergo/issue64_test.go38
-rw-r--r--vendor/github.com/imdario/mergo/issue66_test.go48
-rw-r--r--vendor/github.com/imdario/mergo/issue84_test.go82
-rw-r--r--vendor/github.com/imdario/mergo/map.go53
-rw-r--r--vendor/github.com/imdario/mergo/merge.go164
-rw-r--r--vendor/github.com/imdario/mergo/merge_appendslice_test.go33
-rw-r--r--vendor/github.com/imdario/mergo/merge_test.go50
-rw-r--r--vendor/github.com/imdario/mergo/mergo.go9
-rw-r--r--vendor/github.com/imdario/mergo/mergo_test.go241
-rw-r--r--vendor/github.com/imdario/mergo/pr80_test.go18
-rw-r--r--vendor/github.com/imdario/mergo/pr81_test.go42
-rw-r--r--vendor/github.com/imdario/mergo/testdata/license.yml1
21 files changed, 969 insertions, 59 deletions
diff --git a/Gopkg.lock b/Gopkg.lock
index 2afd27df..dec803bf 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -411,11 +411,12 @@
revision = "bf9dde6d0d2c004a008c27aaee91170c786f6db8"
[[projects]]
- digest = "1:ff6e83dd3b5a66d41c58a3d5e144bd06fcd4c376fd1a84379ad8c9a7dd308643"
+ digest = "1:158a976af1c463daebfa72efdfb66ccd78edfa475ed6d66937744bca05ee6c9c"
name = "github.com/imdario/mergo"
packages = ["."]
pruneopts = "N"
- revision = "50d4dbd4eb0e84778abe37cefef140271d96fade"
+ revision = "7c29201646fa3de8506f701213473dd407f19646"
+ version = "v0.3.7"
[[projects]]
digest = "1:485d36dae750af66fac78a968360bb1eb5a635d9d1e3a3b92116556cc2d45b6a"
@@ -1066,6 +1067,7 @@
"github.com/gorilla/mux",
"github.com/gorilla/websocket",
"github.com/hashicorp/go-version",
+ "github.com/imdario/mergo",
"github.com/jpillora/backoff",
"github.com/kardianos/osext",
"github.com/kr/pty",
diff --git a/Gopkg.toml b/Gopkg.toml
index d4939268..0e8096b0 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -166,6 +166,10 @@ ignored = ["test", "appengine"]
name = "github.com/gofrs/flock"
branch = "master"
+[[constraint]]
+ name = "github.com/imdario/mergo"
+ version = "v0.3.7"
+
##
## Refrain innovations ;)
##
@@ -231,10 +235,6 @@ ignored = ["test", "appengine"]
revision = "599cba5e7b6137d46ddf58fb1765f5d928e69604"
[[override]]
- name = "github.com/imdario/mergo"
- revision = "50d4dbd4eb0e84778abe37cefef140271d96fade"
-
-[[override]]
name = "github.com/jonboulle/clockwork"
revision = "e3653ace2d63753697e0e5b07b9393971c0bba9d"
diff --git a/vendor/github.com/imdario/mergo/issue17_test.go b/vendor/github.com/imdario/mergo/issue17_test.go
index 0ee96f37..f9de805a 100644
--- a/vendor/github.com/imdario/mergo/issue17_test.go
+++ b/vendor/github.com/imdario/mergo/issue17_test.go
@@ -17,9 +17,9 @@ var (
func TestIssue17MergeWithOverwrite(t *testing.T) {
var something map[string]interface{}
if err := json.Unmarshal([]byte(request), &something); err != nil {
- t.Errorf("Error while Unmarshalling maprequest %s", err)
+ t.Errorf("Error while Unmarshalling maprequest: %s", err)
}
if err := MergeWithOverwrite(&something, maprequest); err != nil {
- t.Errorf("Error while merging %s", err)
+ t.Errorf("Error while merging: %s", err)
}
}
diff --git a/vendor/github.com/imdario/mergo/issue23_test.go b/vendor/github.com/imdario/mergo/issue23_test.go
index 9c325841..283f8c6a 100644
--- a/vendor/github.com/imdario/mergo/issue23_test.go
+++ b/vendor/github.com/imdario/mergo/issue23_test.go
@@ -21,7 +21,7 @@ func TestIssue23MergeWithOverwrite(t *testing.T) {
if err := MergeWithOverwrite(&dst, src); err != nil {
t.Errorf("Error while merging %s", err)
}
- if dst.Created != src.Created {
+ if !dst.Created.Equal(*src.Created) { //--> https://golang.org/pkg/time/#pkg-overview
t.Fatalf("Created not merged in properly: dst.Created(%v) != src.Created(%v)", dst.Created, src.Created)
}
}
diff --git a/vendor/github.com/imdario/mergo/issue33_test.go b/vendor/github.com/imdario/mergo/issue33_test.go
new file mode 100644
index 00000000..ae55ae23
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue33_test.go
@@ -0,0 +1,33 @@
+package mergo
+
+import (
+ "testing"
+)
+
+type Foo struct {
+ Str string
+ Bslice []byte
+}
+
+func TestIssue33Merge(t *testing.T) {
+ dest := Foo{Str: "a"}
+ toMerge := Foo{
+ Str: "b",
+ Bslice: []byte{1, 2},
+ }
+ if err := Merge(&dest, toMerge); err != nil {
+ t.Errorf("Error while merging: %s", err)
+ }
+ // Merge doesn't overwrite an attribute if in destination it doesn't have a zero value.
+ // In this case, Str isn't a zero value string.
+ if dest.Str != "a" {
+ t.Errorf("dest.Str should have not been override as it has a non-zero value: dest.Str(%v) != 'a'", dest.Str)
+ }
+ // If we want to override, we must use MergeWithOverwrite or Merge using WithOverride.
+ if err := Merge(&dest, toMerge, WithOverride); err != nil {
+ t.Errorf("Error while merging: %s", err)
+ }
+ if dest.Str != toMerge.Str {
+ t.Errorf("dest.Str should have been override: dest.Str(%v) != toMerge.Str(%v)", dest.Str, toMerge.Str)
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/issue38_test.go b/vendor/github.com/imdario/mergo/issue38_test.go
new file mode 100644
index 00000000..286b68cb
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue38_test.go
@@ -0,0 +1,59 @@
+package mergo
+
+import (
+ "testing"
+ "time"
+)
+
+type structWithoutTimePointer struct {
+ Created time.Time
+}
+
+func TestIssue38Merge(t *testing.T) {
+ dst := structWithoutTimePointer{
+ time.Now(),
+ }
+
+ expected := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+ src := structWithoutTimePointer{
+ expected,
+ }
+ if err := Merge(&dst, src); err != nil {
+ t.Errorf("Error while merging %s", err)
+ }
+ if dst.Created == src.Created {
+ t.Fatalf("Created merged unexpectedly: dst.Created(%v) == src.Created(%v)", dst.Created, src.Created)
+ }
+}
+
+func TestIssue38MergeEmptyStruct(t *testing.T) {
+ dst := structWithoutTimePointer{}
+
+ expected := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+ src := structWithoutTimePointer{
+ expected,
+ }
+ if err := Merge(&dst, src); err != nil {
+ t.Errorf("Error while merging %s", err)
+ }
+ if dst.Created == src.Created {
+ t.Fatalf("Created merged unexpectedly: dst.Created(%v) == src.Created(%v)", dst.Created, src.Created)
+ }
+}
+
+func TestIssue38MergeWithOverwrite(t *testing.T) {
+ dst := structWithoutTimePointer{
+ time.Now(),
+ }
+
+ expected := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+ src := structWithoutTimePointer{
+ expected,
+ }
+ if err := MergeWithOverwrite(&dst, src); err != nil {
+ t.Errorf("Error while merging %s", err)
+ }
+ if dst.Created != src.Created {
+ t.Fatalf("Created not merged in properly: dst.Created(%v) != src.Created(%v)", dst.Created, src.Created)
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/issue50_test.go b/vendor/github.com/imdario/mergo/issue50_test.go
new file mode 100644
index 00000000..89aa3634
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue50_test.go
@@ -0,0 +1,18 @@
+package mergo
+
+import (
+ "testing"
+ "time"
+)
+
+type testStruct struct {
+ time.Duration
+}
+
+func TestIssue50Merge(t *testing.T) {
+ to := testStruct{}
+ from := testStruct{}
+ if err := Merge(&to, from); err != nil {
+ t.Fail()
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/issue52_test.go b/vendor/github.com/imdario/mergo/issue52_test.go
new file mode 100644
index 00000000..62cd9fa7
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue52_test.go
@@ -0,0 +1,99 @@
+package mergo
+
+import (
+ "reflect"
+ "testing"
+ "time"
+)
+
+type structWithTime struct {
+ Birth time.Time
+}
+
+type timeTransfomer struct {
+ overwrite bool
+}
+
+func (t timeTransfomer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
+ if typ == reflect.TypeOf(time.Time{}) {
+ return func(dst, src reflect.Value) error {
+ if dst.CanSet() {
+ if t.overwrite {
+ isZero := src.MethodByName("IsZero")
+ result := isZero.Call([]reflect.Value{})
+ if !result[0].Bool() {
+ dst.Set(src)
+ }
+ } else {
+ isZero := dst.MethodByName("IsZero")
+ result := isZero.Call([]reflect.Value{})
+ if result[0].Bool() {
+ dst.Set(src)
+ }
+ }
+ }
+ return nil
+ }
+ }
+ return nil
+}
+
+func TestOverwriteZeroSrcTime(t *testing.T) {
+ now := time.Now()
+ dst := structWithTime{now}
+ src := structWithTime{}
+ if err := MergeWithOverwrite(&dst, src); err != nil {
+ t.FailNow()
+ }
+ if !dst.Birth.IsZero() {
+ t.Fatalf("dst should have been overwritten: dst.Birth(%v) != now(%v)", dst.Birth, now)
+ }
+}
+
+func TestOverwriteZeroSrcTimeWithTransformer(t *testing.T) {
+ now := time.Now()
+ dst := structWithTime{now}
+ src := structWithTime{}
+ if err := MergeWithOverwrite(&dst, src, WithTransformers(timeTransfomer{true})); err != nil {
+ t.FailNow()
+ }
+ if dst.Birth.IsZero() {
+ t.Fatalf("dst should not have been overwritten: dst.Birth(%v) != now(%v)", dst.Birth, now)
+ }
+}
+
+func TestOverwriteZeroDstTime(t *testing.T) {
+ now := time.Now()
+ dst := structWithTime{}
+ src := structWithTime{now}
+ if err := MergeWithOverwrite(&dst, src); err != nil {
+ t.FailNow()
+ }
+ if dst.Birth.IsZero() {
+ t.Fatalf("dst should have been overwritten: dst.Birth(%v) != zero(%v)", dst.Birth, time.Time{})
+ }
+}
+
+func TestZeroDstTime(t *testing.T) {
+ now := time.Now()
+ dst := structWithTime{}
+ src := structWithTime{now}
+ if err := Merge(&dst, src); err != nil {
+ t.FailNow()
+ }
+ if !dst.Birth.IsZero() {
+ t.Fatalf("dst should not have been overwritten: dst.Birth(%v) != zero(%v)", dst.Birth, time.Time{})
+ }
+}
+
+func TestZeroDstTimeWithTransformer(t *testing.T) {
+ now := time.Now()
+ dst := structWithTime{}
+ src := structWithTime{now}
+ if err := Merge(&dst, src, WithTransformers(timeTransfomer{})); err != nil {
+ t.FailNow()
+ }
+ if dst.Birth.IsZero() {
+ t.Fatalf("dst should have been overwritten: dst.Birth(%v) != now(%v)", dst.Birth, now)
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/issue61_test.go b/vendor/github.com/imdario/mergo/issue61_test.go
new file mode 100644
index 00000000..8efa5e45
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue61_test.go
@@ -0,0 +1,20 @@
+package mergo
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestIssue61MergeNilMap(t *testing.T) {
+ type T struct {
+ I map[string][]string
+ }
+ t1 := T{}
+ t2 := T{I: map[string][]string{"hi": {"there"}}}
+ if err := Merge(&t1, t2); err != nil {
+ t.Fail()
+ }
+ if !reflect.DeepEqual(t2, T{I: map[string][]string{"hi": {"there"}}}) {
+ t.FailNow()
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/issue64_test.go b/vendor/github.com/imdario/mergo/issue64_test.go
new file mode 100644
index 00000000..32382bef
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue64_test.go
@@ -0,0 +1,38 @@
+package mergo
+
+import (
+ "testing"
+)
+
+type Student struct {
+ Name string
+ Books []string
+}
+
+var testData = []struct {
+ S1 Student
+ S2 Student
+ ExpectedSlice []string
+}{
+ {Student{"Jack", []string{"a", "B"}}, Student{"Tom", []string{"1"}}, []string{"a", "B"}},
+ {Student{"Jack", []string{"a", "B"}}, Student{"Tom", []string{}}, []string{"a", "B"}},
+ {Student{"Jack", []string{}}, Student{"Tom", []string{"1"}}, []string{"1"}},
+ {Student{"Jack", []string{}}, Student{"Tom", []string{}}, []string{}},
+}
+
+func TestIssue64MergeSliceWithOverride(t *testing.T) {
+ for _, data := range testData {
+ err := Merge(&data.S2, data.S1, WithOverride)
+ if err != nil {
+ t.Errorf("Error while merging %s", err)
+ }
+ if len(data.S2.Books) != len(data.ExpectedSlice) {
+ t.Fatalf("Got %d elements in slice, but expected %d", len(data.S2.Books), len(data.ExpectedSlice))
+ }
+ for i, val := range data.S2.Books {
+ if val != data.ExpectedSlice[i] {
+ t.Fatalf("Expected %s, but got %s while merging slice with override", data.ExpectedSlice[i], val)
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/issue66_test.go b/vendor/github.com/imdario/mergo/issue66_test.go
new file mode 100644
index 00000000..9e4bcced
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue66_test.go
@@ -0,0 +1,48 @@
+package mergo
+
+import (
+ "testing"
+)
+
+type PrivateSliceTest66 struct {
+ PublicStrings []string
+ privateStrings []string
+}
+
+func TestPrivateSlice(t *testing.T) {
+ p1 := PrivateSliceTest66{
+ PublicStrings: []string{"one", "two", "three"},
+ privateStrings: []string{"four", "five"},
+ }
+ p2 := PrivateSliceTest66{
+ PublicStrings: []string{"six", "seven"},
+ }
+ if err := Merge(&p1, p2); err != nil {
+ t.Fatalf("Error during the merge: %v", err)
+ }
+ if len(p1.PublicStrings) != 3 {
+ t.Error("5 elements should be in 'PublicStrings' field")
+ }
+ if len(p1.privateStrings) != 2 {
+ t.Error("2 elements should be in 'privateStrings' field")
+ }
+}
+
+func TestPrivateSliceWithAppendSlice(t *testing.T) {
+ p1 := PrivateSliceTest66{
+ PublicStrings: []string{"one", "two", "three"},
+ privateStrings: []string{"four", "five"},
+ }
+ p2 := PrivateSliceTest66{
+ PublicStrings: []string{"six", "seven"},
+ }
+ if err := Merge(&p1, p2, WithAppendSlice); err != nil {
+ t.Fatalf("Error during the merge: %v", err)
+ }
+ if len(p1.PublicStrings) != 5 {
+ t.Error("5 elements should be in 'PublicStrings' field")
+ }
+ if len(p1.privateStrings) != 2 {
+ t.Error("2 elements should be in 'privateStrings' field")
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/issue84_test.go b/vendor/github.com/imdario/mergo/issue84_test.go
new file mode 100644
index 00000000..aa605269
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue84_test.go
@@ -0,0 +1,82 @@
+package mergo
+
+import (
+ "testing"
+)
+
+type DstStructIssue84 struct {
+ A int
+ B int
+ C int
+}
+
+type DstNestedStructIssue84 struct {
+ A struct {
+ A int
+ B int
+ C int
+ }
+ B int
+ C int
+}
+
+func TestIssue84MergeMapWithNilValueToStructWithOverride(t *testing.T) {
+ p1 := DstStructIssue84{
+ A: 0, B: 1, C: 2,
+ }
+ p2 := map[string]interface{}{
+ "A": 3, "B": 4, "C": 0,
+ }
+ if err := Map(&p1, p2, WithOverride); err != nil {
+ t.Fatalf("Error during the merge: %v", err)
+ }
+ if p1.C != 0 {
+ t.Error("C field should become '0'")
+ }
+}
+
+func TestIssue84MergeMapWithoutKeyExistsToStructWithOverride(t *testing.T) {
+ p1 := DstStructIssue84{
+ A: 0, B: 1, C: 2,
+ }
+ p2 := map[string]interface{}{
+ "A": 3, "B": 4,
+ }
+ if err := Map(&p1, p2, WithOverride); err != nil {
+ t.Fatalf("Error during the merge: %v", err)
+ }
+ if p1.C != 2 {
+ t.Error("C field should be '2'")
+ }
+}
+
+func TestIssue84MergeNestedMapWithNilValueToStructWithOverride(t *testing.T) {
+ p1 := DstNestedStructIssue84{
+ A: struct {
+ A int
+ B int
+ C int
+ }{A: 1, B: 2, C: 0},
+ B: 0,
+ C: 2,
+ }
+ p2 := map[string]interface{}{
+ "A": map[string]interface{}{
+ "A": 0, "B": 0, "C": 5,
+ }, "B": 4, "C": 0,
+ }
+ if err := Map(&p1, p2, WithOverride); err != nil {
+ t.Fatalf("Error during the merge: %v", err)
+ }
+ if p1.B != 4 {
+ t.Error("A.C field should become '4'")
+ }
+
+ if p1.A.C != 5 {
+ t.Error("A.C field should become '5'")
+ }
+
+ if p1.A.B != 0 || p1.A.A != 0 {
+ t.Error("A.A and A.B field should become '0'")
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/map.go b/vendor/github.com/imdario/mergo/map.go
index 8e8c4ba8..3f5afa83 100644
--- a/vendor/github.com/imdario/mergo/map.go
+++ b/vendor/github.com/imdario/mergo/map.go
@@ -31,7 +31,8 @@ func isExported(field reflect.StructField) bool {
// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
-func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
+func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
+ overwrite := config.Overwrite
if dst.CanAddr() {
addr := dst.UnsafeAddr()
h := 17 * addr
@@ -61,9 +62,17 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
dstMap[fieldName] = src.Field(i).Interface()
}
}
+ case reflect.Ptr:
+ if dst.IsNil() {
+ v := reflect.New(dst.Type().Elem())
+ dst.Set(v)
+ }
+ dst = dst.Elem()
+ fallthrough
case reflect.Struct:
srcMap := src.Interface().(map[string]interface{})
for key := range srcMap {
+ config.overwriteWithEmptyValue = true
srcValue := srcMap[key]
fieldName := changeInitialCase(key, unicode.ToUpper)
dstElement := dst.FieldByName(fieldName)
@@ -85,21 +94,24 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
srcKind = reflect.Ptr
}
}
+
if !srcElement.IsValid() {
continue
}
if srcKind == dstKind {
- if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
+ if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
return
}
- } else {
- if srcKind == reflect.Map {
- if err = deepMap(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
- return
- }
- } else {
- return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind)
+ } else if dstKind == reflect.Interface && dstElement.Kind() == reflect.Interface {
+ if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
+ return
+ }
+ } else if srcKind == reflect.Map {
+ if err = deepMap(dstElement, srcElement, visited, depth+1, config); err != nil {
+ return
}
+ } else {
+ return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind)
}
}
}
@@ -117,28 +129,35 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
// doesn't apply if dst is a map.
// This is separated method from Merge because it is cleaner and it keeps sane
// semantics: merging equal types, mapping different (restricted) types.
-func Map(dst, src interface{}) error {
- return _map(dst, src, false)
+func Map(dst, src interface{}, opts ...func(*Config)) error {
+ return _map(dst, src, opts...)
}
-// MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overriden by
+// MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overridden by
// non-empty src attribute values.
-func MapWithOverwrite(dst, src interface{}) error {
- return _map(dst, src, true)
+// Deprecated: Use Map(…) with WithOverride
+func MapWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
+ return _map(dst, src, append(opts, WithOverride)...)
}
-func _map(dst, src interface{}, overwrite bool) error {
+func _map(dst, src interface{}, opts ...func(*Config)) error {
var (
vDst, vSrc reflect.Value
err error
)
+ config := &Config{}
+
+ for _, opt := range opts {
+ opt(config)
+ }
+
if vDst, vSrc, err = resolveValues(dst, src); err != nil {
return err
}
// To be friction-less, we redirect equal-type arguments
// to deepMerge. Only because arguments can be anything.
if vSrc.Kind() == vDst.Kind() {
- return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
+ return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
}
switch vSrc.Kind() {
case reflect.Struct:
@@ -152,5 +171,5 @@ func _map(dst, src interface{}, overwrite bool) error {
default:
return ErrNotSupported
}
- return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
+ return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, config)
}
diff --git a/vendor/github.com/imdario/mergo/merge.go b/vendor/github.com/imdario/mergo/merge.go
index 513774f4..f8de6c54 100644
--- a/vendor/github.com/imdario/mergo/merge.go
+++ b/vendor/github.com/imdario/mergo/merge.go
@@ -9,13 +9,41 @@
package mergo
import (
+ "fmt"
"reflect"
)
+func hasExportedField(dst reflect.Value) (exported bool) {
+ for i, n := 0, dst.NumField(); i < n; i++ {
+ field := dst.Type().Field(i)
+ if field.Anonymous && dst.Field(i).Kind() == reflect.Struct {
+ exported = exported || hasExportedField(dst.Field(i))
+ } else {
+ exported = exported || len(field.PkgPath) == 0
+ }
+ }
+ return
+}
+
+type Config struct {
+ Overwrite bool
+ AppendSlice bool
+ Transformers Transformers
+ overwriteWithEmptyValue bool
+}
+
+type Transformers interface {
+ Transformer(reflect.Type) func(dst, src reflect.Value) error
+}
+
// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
-func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
+func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
+ overwrite := config.Overwrite
+ overwriteWithEmptySrc := config.overwriteWithEmptyValue
+ config.overwriteWithEmptyValue = false
+
if !src.IsValid() {
return
}
@@ -32,14 +60,31 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
// Remember, remember...
visited[h] = &visit{addr, typ, seen}
}
+
+ if config.Transformers != nil && !isEmptyValue(dst) {
+ if fn := config.Transformers.Transformer(dst.Type()); fn != nil {
+ err = fn(dst, src)
+ return
+ }
+ }
+
switch dst.Kind() {
case reflect.Struct:
- for i, n := 0, dst.NumField(); i < n; i++ {
- if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, overwrite); err != nil {
- return
+ if hasExportedField(dst) {
+ for i, n := 0, dst.NumField(); i < n; i++ {
+ if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, config); err != nil {
+ return
+ }
+ }
+ } else {
+ if dst.CanSet() && (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) {
+ dst.Set(src)
}
}
case reflect.Map:
+ if dst.IsNil() && !src.IsNil() {
+ dst.Set(reflect.MakeMap(dst.Type()))
+ }
for _, key := range src.MapKeys() {
srcElement := src.MapIndex(key)
if !srcElement.IsValid() {
@@ -47,7 +92,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
}
dstElement := dst.MapIndex(key)
switch srcElement.Kind() {
- case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
+ case reflect.Chan, reflect.Func, reflect.Map, reflect.Interface, reflect.Slice:
if srcElement.IsNil() {
continue
}
@@ -62,32 +107,94 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
case reflect.Ptr:
fallthrough
case reflect.Map:
- if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
+ srcMapElm := srcElement
+ dstMapElm := dstElement
+ if srcMapElm.CanInterface() {
+ srcMapElm = reflect.ValueOf(srcMapElm.Interface())
+ if dstMapElm.IsValid() {
+ dstMapElm = reflect.ValueOf(dstMapElm.Interface())
+ }
+ }
+ if err = deepMerge(dstMapElm, srcMapElm, visited, depth+1, config); err != nil {
return
}
+ case reflect.Slice:
+ srcSlice := reflect.ValueOf(srcElement.Interface())
+
+ var dstSlice reflect.Value
+ if !dstElement.IsValid() || dstElement.IsNil() {
+ dstSlice = reflect.MakeSlice(srcSlice.Type(), 0, srcSlice.Len())
+ } else {
+ dstSlice = reflect.ValueOf(dstElement.Interface())
+ }
+
+ if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
+ dstSlice = srcSlice
+ } else if config.AppendSlice {
+ if srcSlice.Type() != dstSlice.Type() {
+ return fmt.Errorf("cannot append two slice with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
+ }
+ dstSlice = reflect.AppendSlice(dstSlice, srcSlice)
+ }
+ dst.SetMapIndex(key, dstSlice)
}
}
- if !isEmptyValue(srcElement) && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) {
+ if dstElement.IsValid() && !isEmptyValue(dstElement) && (reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map || reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice) {
+ continue
+ }
+
+ if srcElement.IsValid() && (overwrite || (!dstElement.IsValid() || isEmptyValue(dstElement))) {
if dst.IsNil() {
dst.Set(reflect.MakeMap(dst.Type()))
}
dst.SetMapIndex(key, srcElement)
}
}
+ case reflect.Slice:
+ if !dst.CanSet() {
+ break
+ }
+ if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
+ dst.Set(src)
+ } else if config.AppendSlice {
+ if src.Type() != dst.Type() {
+ return fmt.Errorf("cannot append two slice with different type (%s, %s)", src.Type(), dst.Type())
+ }
+ dst.Set(reflect.AppendSlice(dst, src))
+ }
case reflect.Ptr:
fallthrough
case reflect.Interface:
if src.IsNil() {
break
- } else if dst.IsNil() || overwrite {
+ }
+ if src.Kind() != reflect.Interface {
+ if dst.IsNil() || overwrite {
+ if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
+ dst.Set(src)
+ }
+ } else if src.Kind() == reflect.Ptr {
+ if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
+ return
+ }
+ } else if dst.Elem().Type() == src.Type() {
+ if err = deepMerge(dst.Elem(), src, visited, depth+1, config); err != nil {
+ return
+ }
+ } else {
+ return ErrDifferentArgumentsTypes
+ }
+ break
+ }
+ if dst.IsNil() || overwrite {
if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
dst.Set(src)
}
- } else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, overwrite); err != nil {
+ } else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
return
}
default:
- if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) {
+ if dst.CanSet() && (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) {
dst.Set(src)
}
}
@@ -98,26 +205,51 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
// src attributes if they themselves are not empty. dst and src must be valid same-type structs
// and dst must be a pointer to struct.
// It won't merge unexported (private) fields and will do recursively any exported field.
-func Merge(dst, src interface{}) error {
- return merge(dst, src, false)
+func Merge(dst, src interface{}, opts ...func(*Config)) error {
+ return merge(dst, src, opts...)
}
// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by
// non-empty src attribute values.
-func MergeWithOverwrite(dst, src interface{}) error {
- return merge(dst, src, true)
+// Deprecated: use Merge(…) with WithOverride
+func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
+ return merge(dst, src, append(opts, WithOverride)...)
+}
+
+// WithTransformers adds transformers to merge, allowing to customize the merging of some types.
+func WithTransformers(transformers Transformers) func(*Config) {
+ return func(config *Config) {
+ config.Transformers = transformers
+ }
+}
+
+// WithOverride will make merge override non-empty dst attributes with non-empty src attributes values.
+func WithOverride(config *Config) {
+ config.Overwrite = true
}
-func merge(dst, src interface{}, overwrite bool) error {
+// WithAppendSlice will make merge append slices instead of overwriting it
+func WithAppendSlice(config *Config) {
+ config.AppendSlice = true
+}
+
+func merge(dst, src interface{}, opts ...func(*Config)) error {
var (
vDst, vSrc reflect.Value
err error
)
+
+ config := &Config{}
+
+ for _, opt := range opts {
+ opt(config)
+ }
+
if vDst, vSrc, err = resolveValues(dst, src); err != nil {
return err
}
if vDst.Type() != vSrc.Type() {
return ErrDifferentArgumentsTypes
}
- return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
+ return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
}
diff --git a/vendor/github.com/imdario/mergo/merge_appendslice_test.go b/vendor/github.com/imdario/mergo/merge_appendslice_test.go
new file mode 100644
index 00000000..a780f34a
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/merge_appendslice_test.go
@@ -0,0 +1,33 @@
+package mergo
+
+import (
+ "testing"
+)
+
+var testDataS = []struct {
+ S1 Student
+ S2 Student
+ ExpectedSlice []string
+}{
+ {Student{"Jack", []string{"a", "B"}}, Student{"Tom", []string{"1"}}, []string{"1", "a", "B"}},
+ {Student{"Jack", []string{"a", "B"}}, Student{"Tom", []string{}}, []string{"a", "B"}},
+ {Student{"Jack", []string{}}, Student{"Tom", []string{"1"}}, []string{"1"}},
+ {Student{"Jack", []string{}}, Student{"Tom", []string{}}, []string{}},
+}
+
+func TestMergeSliceWithOverrideWithAppendSlice(t *testing.T) {
+ for _, data := range testDataS {
+ err := Merge(&data.S2, data.S1, WithOverride, WithAppendSlice)
+ if err != nil {
+ t.Errorf("Error while merging %s", err)
+ }
+ if len(data.S2.Books) != len(data.ExpectedSlice) {
+ t.Fatalf("Got %d elements in slice, but expected %d", len(data.S2.Books), len(data.ExpectedSlice))
+ }
+ for i, val := range data.S2.Books {
+ if val != data.ExpectedSlice[i] {
+ t.Fatalf("Expected %s, but got %s while merging slice with override", data.ExpectedSlice[i], val)
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/merge_test.go b/vendor/github.com/imdario/mergo/merge_test.go
new file mode 100644
index 00000000..5bf808a7
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/merge_test.go
@@ -0,0 +1,50 @@
+package mergo
+
+import (
+ "reflect"
+ "testing"
+)
+
+type transformer struct {
+ m map[reflect.Type]func(dst, src reflect.Value) error
+}
+
+func (s *transformer) Transformer(t reflect.Type) func(dst, src reflect.Value) error {
+ if fn, ok := s.m[t]; ok {
+ return fn
+ }
+ return nil
+}
+
+type foo struct {
+ s string
+ Bar *bar
+}
+
+type bar struct {
+ i int
+ s map[string]string
+}
+
+func TestMergeWithTransformerNilStruct(t *testing.T) {
+ a := foo{s: "foo"}
+ b := foo{Bar: &bar{i: 2, s: map[string]string{"foo": "bar"}}}
+ if err := Merge(&a, &b, WithOverride, WithTransformers(&transformer{
+ m: map[reflect.Type]func(dst, src reflect.Value) error{
+ reflect.TypeOf(&bar{}): func(dst, src reflect.Value) error {
+ // Do sthg with Elem
+ t.Log(dst.Elem().FieldByName("i"))
+ t.Log(src.Elem())
+ return nil
+ },
+ },
+ })); err != nil {
+ t.Fatal(err)
+ }
+ if a.s != "foo" {
+ t.Fatalf("b not merged in properly: a.s.Value(%s) != expected(%s)", a.s, "foo")
+ }
+ if a.Bar == nil {
+ t.Fatalf("b not merged in properly: a.Bar shouldn't be nil")
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/mergo.go b/vendor/github.com/imdario/mergo/mergo.go
index f8a0991e..a82fea2f 100644
--- a/vendor/github.com/imdario/mergo/mergo.go
+++ b/vendor/github.com/imdario/mergo/mergo.go
@@ -32,7 +32,7 @@ type visit struct {
next *visit
}
-// From src/pkg/encoding/json.
+// From src/pkg/encoding/json/encode.go.
func isEmptyValue(v reflect.Value) bool {
switch v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
@@ -46,7 +46,14 @@ func isEmptyValue(v reflect.Value) bool {
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
+ if v.IsNil() {
+ return true
+ }
+ return isEmptyValue(v.Elem())
+ case reflect.Func:
return v.IsNil()
+ case reflect.Invalid:
+ return true
}
return false
}
diff --git a/vendor/github.com/imdario/mergo/mergo_test.go b/vendor/github.com/imdario/mergo/mergo_test.go
index c43c61cd..1f2ab0bc 100644
--- a/vendor/github.com/imdario/mergo/mergo_test.go
+++ b/vendor/github.com/imdario/mergo/mergo_test.go
@@ -10,7 +10,8 @@ import (
"reflect"
"testing"
"time"
- "gopkg.in/yaml.v1"
+
+ "gopkg.in/yaml.v2"
)
type simpleTest struct {
@@ -23,6 +24,14 @@ type complexTest struct {
ID string
}
+type mapTest struct {
+ M map[int]int
+}
+
+type ifcTest struct {
+ I interface{}
+}
+
type moreComplextText struct {
Ct complexTest
St simpleTest
@@ -217,29 +226,120 @@ func TestPointerStructNil(t *testing.T) {
}
}
-func TestSliceStruct(t *testing.T) {
- a := sliceTest{}
- b := sliceTest{[]int{1, 2, 3}}
- if err := Merge(&a, b); err != nil {
+func testSlice(t *testing.T, a []int, b []int, e []int, opts ...func(*Config)) {
+ t.Helper()
+ bc := b
+
+ sa := sliceTest{a}
+ sb := sliceTest{b}
+ if err := Merge(&sa, sb, opts...); err != nil {
t.FailNow()
}
- if len(b.S) != 3 {
+ if !reflect.DeepEqual(sb.S, bc) {
+ t.Fatalf("Source slice was modified %d != %d", sb.S, bc)
+ }
+ if !reflect.DeepEqual(sa.S, e) {
+ t.Fatalf("b not merged in a proper way %d != %d", sa.S, e)
+ }
+
+ ma := map[string][]int{"S": a}
+ mb := map[string][]int{"S": b}
+ if err := Merge(&ma, mb, opts...); err != nil {
t.FailNow()
}
- if len(a.S) != len(b.S) {
- t.Fatalf("b not merged in a proper way %d != %d", len(a.S), len(b.S))
+ if !reflect.DeepEqual(mb["S"], bc) {
+ t.Fatalf("map value: Source slice was modified %d != %d", mb["S"], bc)
+ }
+ if !reflect.DeepEqual(ma["S"], e) {
+ t.Fatalf("map value: b not merged in a proper way %d != %d", ma["S"], e)
}
- a = sliceTest{[]int{1}}
- b = sliceTest{[]int{1, 2, 3}}
+ if a == nil {
+ // test case with missing dst key
+ ma := map[string][]int{}
+ mb := map[string][]int{"S": b}
+ if err := Merge(&ma, mb); err != nil {
+ t.FailNow()
+ }
+ if !reflect.DeepEqual(mb["S"], bc) {
+ t.Fatalf("missing dst key: Source slice was modified %d != %d", mb["S"], bc)
+ }
+ if !reflect.DeepEqual(ma["S"], e) {
+ t.Fatalf("missing dst key: b not merged in a proper way %d != %d", ma["S"], e)
+ }
+ }
+
+ if b == nil {
+ // test case with missing src key
+ ma := map[string][]int{"S": a}
+ mb := map[string][]int{}
+ if err := Merge(&ma, mb); err != nil {
+ t.FailNow()
+ }
+ if !reflect.DeepEqual(mb["S"], bc) {
+ t.Fatalf("missing src key: Source slice was modified %d != %d", mb["S"], bc)
+ }
+ if !reflect.DeepEqual(ma["S"], e) {
+ t.Fatalf("missing src key: b not merged in a proper way %d != %d", ma["S"], e)
+ }
+ }
+}
+
+func TestSlice(t *testing.T) {
+ testSlice(t, nil, []int{1, 2, 3}, []int{1, 2, 3})
+ testSlice(t, []int{}, []int{1, 2, 3}, []int{1, 2, 3})
+ testSlice(t, []int{1}, []int{2, 3}, []int{1})
+ testSlice(t, []int{1}, []int{}, []int{1})
+ testSlice(t, []int{1}, nil, []int{1})
+ testSlice(t, nil, []int{1, 2, 3}, []int{1, 2, 3}, WithAppendSlice)
+ testSlice(t, []int{}, []int{1, 2, 3}, []int{1, 2, 3}, WithAppendSlice)
+ testSlice(t, []int{1}, []int{2, 3}, []int{1, 2, 3}, WithAppendSlice)
+ testSlice(t, []int{1}, []int{2, 3}, []int{1, 2, 3}, WithAppendSlice, WithOverride)
+ testSlice(t, []int{1}, []int{}, []int{1}, WithAppendSlice)
+ testSlice(t, []int{1}, nil, []int{1}, WithAppendSlice)
+}
+
+func TestEmptyMaps(t *testing.T) {
+ a := mapTest{}
+ b := mapTest{
+ map[int]int{},
+ }
if err := Merge(&a, b); err != nil {
+ t.Fail()
+ }
+ if !reflect.DeepEqual(a, b) {
t.FailNow()
}
- if len(a.S) != 1 {
+}
+
+func TestEmptyToEmptyMaps(t *testing.T) {
+ a := mapTest{}
+ b := mapTest{}
+ if err := Merge(&a, b); err != nil {
+ t.Fail()
+ }
+ if !reflect.DeepEqual(a, b) {
t.FailNow()
}
- if len(a.S) == len(b.S) {
- t.Fatalf("b merged unexpectedly %d != %d", len(a.S), len(b.S))
+}
+
+func TestEmptyToNotEmptyMaps(t *testing.T) {
+ a := mapTest{map[int]int{
+ 1: 2,
+ 3: 4,
+ }}
+ aa := mapTest{map[int]int{
+ 1: 2,
+ 3: 4,
+ }}
+ b := mapTest{
+ map[int]int{},
+ }
+ if err := Merge(&a, b); err != nil {
+ t.Fail()
+ }
+ if !reflect.DeepEqual(a, aa) {
+ t.FailNow()
}
}
@@ -312,12 +412,37 @@ func TestMaps(t *testing.T) {
}
}
+func TestMapsWithNilPointer(t *testing.T) {
+ m := map[string]*simpleTest{
+ "a": nil,
+ "b": nil,
+ }
+ n := map[string]*simpleTest{
+ "b": nil,
+ "c": nil,
+ }
+ expect := map[string]*simpleTest{
+ "a": nil,
+ "b": nil,
+ "c": nil,
+ }
+
+ if err := Merge(&m, n, WithOverride); err != nil {
+ t.Fatalf(err.Error())
+ }
+
+ if !reflect.DeepEqual(m, expect) {
+ t.Fatalf("Test failed:\ngot :\n%#v\n\nwant :\n%#v\n\n", m, expect)
+ }
+}
+
func TestYAMLMaps(t *testing.T) {
thing := loadYAML("testdata/thing.yml")
license := loadYAML("testdata/license.yml")
ft := thing["fields"].(map[interface{}]interface{})
fl := license["fields"].(map[interface{}]interface{})
- expectedLength := len(ft) + len(fl)
+ // license has one extra field (site) and another already existing in thing (author) that Mergo won't override.
+ expectedLength := len(ft) + len(fl) - 1
if err := Merge(&license, thing); err != nil {
t.Fatal(err.Error())
}
@@ -392,6 +517,45 @@ func TestSimpleMap(t *testing.T) {
}
}
+func TestIfcMap(t *testing.T) {
+ a := ifcTest{}
+ b := ifcTest{42}
+ if err := Map(&a, b); err != nil {
+ t.FailNow()
+ }
+ if a.I != 42 {
+ t.Fatalf("b not merged in properly: a.I(%d) != b.I(%d)", a.I, b.I)
+ }
+ if !reflect.DeepEqual(a, b) {
+ t.FailNow()
+ }
+}
+
+func TestIfcMapNoOverwrite(t *testing.T) {
+ a := ifcTest{13}
+ b := ifcTest{42}
+ if err := Map(&a, b); err != nil {
+ t.FailNow()
+ }
+ if a.I != 13 {
+ t.Fatalf("a not left alone: a.I(%d) == b.I(%d)", a.I, b.I)
+ }
+}
+
+func TestIfcMapWithOverwrite(t *testing.T) {
+ a := ifcTest{13}
+ b := ifcTest{42}
+ if err := MapWithOverwrite(&a, b); err != nil {
+ t.FailNow()
+ }
+ if a.I != 42 {
+ t.Fatalf("b not merged in properly: a.I(%d) != b.I(%d)", a.I, b.I)
+ }
+ if !reflect.DeepEqual(a, b) {
+ t.FailNow()
+ }
+}
+
type pointerMapTest struct {
A int
hidden int
@@ -433,6 +597,29 @@ func TestBackAndForth(t *testing.T) {
}
}
+func TestEmbeddedPointerUnpacking(t *testing.T) {
+ tests := []struct{ input pointerMapTest }{
+ {pointerMapTest{42, 1, nil}},
+ {pointerMapTest{42, 1, &simpleTest{66}}},
+ }
+ newValue := 77
+ m := map[string]interface{}{
+ "b": map[string]interface{}{
+ "value": newValue,
+ },
+ }
+ for _, test := range tests {
+ pt := test.input
+ if err := MapWithOverwrite(&pt, m); err != nil {
+ t.FailNow()
+ }
+ if pt.B.Value != newValue {
+ t.Fatalf("pt not mapped properly: pt.A.Value(%d) != m[`b`][`value`](%d)", pt.B.Value, newValue)
+ }
+
+ }
+}
+
type structWithTimePointer struct {
Birth *time.Time
}
@@ -510,10 +697,10 @@ type structWithUnexportedProperty struct {
func TestUnexportedProperty(t *testing.T) {
a := structWithMap{map[string]structWithUnexportedProperty{
- "key": structWithUnexportedProperty{"hello"},
+ "key": {"hello"},
}}
b := structWithMap{map[string]structWithUnexportedProperty{
- "key": structWithUnexportedProperty{"hi"},
+ "key": {"hi"},
}}
defer func() {
if r := recover(); r != nil {
@@ -545,3 +732,25 @@ func TestBooleanPointer(t *testing.T) {
t.Fatalf("dst.C should be true")
}
}
+
+func TestMergeMapWithInnerSliceOfDifferentType(t *testing.T) {
+ src := map[string]interface{}{
+ "foo": []string{"a", "b"},
+ }
+ dst := map[string]interface{}{
+ "foo": []int{1, 2},
+ }
+
+ if err := Merge(&src, &dst, WithOverride, WithAppendSlice); err == nil {
+ t.Fatal("expected an error, got nothing")
+ }
+}
+
+func TestMergeSliceDifferentType(t *testing.T) {
+ src := []string{"a", "b"}
+ dst := []int{1, 2}
+
+ if err := Merge(&src, &dst, WithOverride, WithAppendSlice); err == nil {
+ t.Fatal("expected an error, got nothing")
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/pr80_test.go b/vendor/github.com/imdario/mergo/pr80_test.go
new file mode 100644
index 00000000..0b3220f3
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/pr80_test.go
@@ -0,0 +1,18 @@
+package mergo
+
+import (
+ "testing"
+)
+
+type mapInterface map[string]interface{}
+
+func TestMergeMapsEmptyString(t *testing.T) {
+ a := mapInterface{"s": ""}
+ b := mapInterface{"s": "foo"}
+ if err := Merge(&a, b); err != nil {
+ t.Fatal(err)
+ }
+ if a["s"] != "foo" {
+ t.Fatalf("b not merged in properly: a.s.Value(%s) != expected(%s)", a["s"], "foo")
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/pr81_test.go b/vendor/github.com/imdario/mergo/pr81_test.go
new file mode 100644
index 00000000..e90e923f
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/pr81_test.go
@@ -0,0 +1,42 @@
+package mergo
+
+import (
+ "testing"
+)
+
+func TestMapInterfaceWithMultipleLayer(t *testing.T) {
+ m1 := map[string]interface{}{
+ "k1": map[string]interface{}{
+ "k1.1": "v1",
+ },
+ }
+
+ m2 := map[string]interface{}{
+ "k1": map[string]interface{}{
+ "k1.1": "v2",
+ "k1.2": "v3",
+ },
+ }
+
+ if err := Map(&m1, m2, WithOverride); err != nil {
+ t.Fatalf("Error merging: %v", err)
+ }
+
+ // Check overwrite of sub map works
+ expected := "v2"
+ actual := m1["k1"].(map[string]interface{})["k1.1"].(string)
+ if actual != expected {
+ t.Fatalf("Expected %v but got %v",
+ expected,
+ actual)
+ }
+
+ // Check new key is merged
+ expected = "v3"
+ actual = m1["k1"].(map[string]interface{})["k1.2"].(string)
+ if actual != expected {
+ t.Fatalf("Expected %v but got %v",
+ expected,
+ actual)
+ }
+}
diff --git a/vendor/github.com/imdario/mergo/testdata/license.yml b/vendor/github.com/imdario/mergo/testdata/license.yml
index 62fdb61e..2f1ad008 100644
--- a/vendor/github.com/imdario/mergo/testdata/license.yml
+++ b/vendor/github.com/imdario/mergo/testdata/license.yml
@@ -1,3 +1,4 @@
import: ../../../../fossene/db/schema/thing.yml
fields:
site: string
+ author: root