Vendor the exact same version of mergo used by k8s

Merging is buggy in master: https://github.com/imdario/mergo/issues/33
This commit is contained in:
Alfonso Acosta
2016-08-18 15:32:49 +00:00
parent 7435b4542c
commit 47056bde16
3 changed files with 27 additions and 61 deletions
+6 -16
View File
@@ -31,7 +31,7 @@ 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) (err error) {
if dst.CanAddr() {
addr := dst.UnsafeAddr()
h := 17 * addr
@@ -57,7 +57,7 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
}
fieldName := field.Name
fieldName = changeInitialCase(fieldName, unicode.ToLower)
if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v)) || overwrite) {
if v, ok := dstMap[fieldName]; !ok || isEmptyValue(reflect.ValueOf(v)) {
dstMap[fieldName] = src.Field(i).Interface()
}
}
@@ -89,12 +89,12 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
continue
}
if srcKind == dstKind {
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
if err = deepMerge(dstElement, srcElement, visited, depth+1); err != nil {
return
}
} else {
if srcKind == reflect.Map {
if err = deepMap(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
if err = deepMap(dstElement, srcElement, visited, depth+1); err != nil {
return
}
} else {
@@ -118,16 +118,6 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
// 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)
}
// MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overriden by
// non-empty src attribute values.
func MapWithOverwrite(dst, src interface{}) error {
return _map(dst, src, true)
}
func _map(dst, src interface{}, overwrite bool) error {
var (
vDst, vSrc reflect.Value
err error
@@ -138,7 +128,7 @@ func _map(dst, src interface{}, overwrite bool) error {
// 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)
}
switch vSrc.Kind() {
case reflect.Struct:
@@ -152,5 +142,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)
}
+19 -43
View File
@@ -15,7 +15,7 @@ import (
// 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) (err error) {
if !src.IsValid() {
return
}
@@ -35,7 +35,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
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 {
if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1); err != nil {
return
}
}
@@ -46,31 +46,15 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
continue
}
dstElement := dst.MapIndex(key)
switch srcElement.Kind() {
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
if srcElement.IsNil() {
continue
}
switch reflect.TypeOf(srcElement.Interface()).Kind() {
case reflect.Struct:
fallthrough
default:
if !srcElement.CanInterface() {
continue
}
switch reflect.TypeOf(srcElement.Interface()).Kind() {
case reflect.Struct:
fallthrough
case reflect.Ptr:
fallthrough
case reflect.Map:
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
return
}
case reflect.Map:
if err = deepMerge(dstElement, srcElement, visited, depth+1); err != nil {
return
}
}
if !isEmptyValue(srcElement) && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) {
if dst.IsNil() {
dst.Set(reflect.MakeMap(dst.Type()))
}
if !dstElement.IsValid() {
dst.SetMapIndex(key, srcElement)
}
}
@@ -79,36 +63,28 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
case reflect.Interface:
if src.IsNil() {
break
} else if dst.IsNil() || overwrite {
if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
} else if dst.IsNil() {
if dst.CanSet() && 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); err != nil {
return
}
default:
if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) {
if dst.CanSet() && !isEmptyValue(src) {
dst.Set(src)
}
}
return
}
// Merge will fill any empty for value type attributes on the dst struct using corresponding
// 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.
// Merge sets fields' values in dst from src if they have a zero
// value of their type.
// 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)
}
// 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)
}
func merge(dst, src interface{}, overwrite bool) error {
var (
vDst, vSrc reflect.Value
err error
@@ -119,5 +95,5 @@ func merge(dst, src interface{}, overwrite bool) error {
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)
}
+2 -2
View File
@@ -893,8 +893,8 @@
"importpath": "github.com/imdario/mergo",
"repository": "https://github.com/imdario/mergo",
"vcs": "git",
"revision": "50d4dbd4eb0e84778abe37cefef140271d96fade",
"branch": "master",
"revision": "6633656539c1639d9d78127b7d47c622b5d7b6dc",
"branch": "HEAD",
"notests": true
},
{