@@ -3,6 +3,8 @@ package configutil
33import (
44 "reflect"
55 "unsafe"
6+
7+ "gopkg.in/yaml.v2"
68)
79
810type pointerInterface struct {
@@ -12,7 +14,7 @@ type pointerInterface struct {
1214// Merge deeply merges two objects
1315// object MUST be a pointer of a pointer
1416// overwriteObject MUST be a pointer
15- func Merge (object interface {}, overwriteObject interface {}) {
17+ func Merge (object interface {}, overwriteObject interface {}, unifyPointers bool ) {
1618 overwriteObjectRef := reflect .ValueOf (overwriteObject )
1719
1820 if ! overwriteObjectRef .IsNil () {
@@ -21,6 +23,13 @@ func Merge(object interface{}, overwriteObject interface{}) {
2123 }
2224 objectPointerReal := reflect .ValueOf (object ).Elem ().Interface ()
2325 overwriteObject := overwriteObjectRef .Interface ()
26+
27+ if ! unifyPointers {
28+ overwriteObject = deepCopy (overwriteObject )
29+
30+ // ensure deepCopy only runs once
31+ unifyPointers = true
32+ }
2433 overwriteObjectType := reflect .TypeOf (overwriteObject )
2534 overwriteObjectKind := overwriteObjectType .Kind ()
2635 objectPointerRef := reflect .ValueOf (objectPointerReal )
@@ -53,10 +62,10 @@ func Merge(object interface{}, overwriteObject interface{}) {
5362 overwriteValue := getMapValue (overwriteObject , key , genericPointerType )
5463 valuePointerRef := objectRef .MapIndex (keyRef )
5564
56- if isZero (valuePointerRef ) == false {
65+ if isZero (valuePointerRef ) == false && ! isTrivialDataType ( valuePointerRef ) {
5766 valuePointer := valuePointerRef .Interface ()
5867
59- Merge (& valuePointer , overwriteValue )
68+ Merge (& valuePointer , overwriteValue , unifyPointers )
6069 } else {
6170 keyRef := reflect .ValueOf (key )
6271 overwriteValueRef := reflect .ValueOf (overwriteValue )
@@ -68,18 +77,17 @@ func Merge(object interface{}, overwriteObject interface{}) {
6877 case reflect .Struct :
6978 for i := 0 ; i < overwriteObjectRef .NumField (); i ++ {
7079 overwriteValueRef := overwriteObjectRef .Field (i )
71- overwriteValuePointerRef := reflect .ValueOf (overwriteValueRef .Interface ())
7280
73- if ! overwriteValuePointerRef .IsNil () {
81+ if ! overwriteValueRef .IsNil () {
7482 overwriteValue := overwriteValueRef .Interface ()
7583 valuePointerRef := objectRef .Field (i )
7684
77- if valuePointerRef .IsNil () {
78- valuePointerRef .Set (reflect . ValueOf ( overwriteValue ) )
85+ if valuePointerRef .IsNil () || isTrivialDataType ( valuePointerRef ) {
86+ valuePointerRef .Set (overwriteValueRef )
7987 } else {
8088 valuePointer := valuePointerRef .Interface ()
8189
82- Merge (& valuePointer , overwriteValue )
90+ Merge (& valuePointer , overwriteValue , unifyPointers )
8391 }
8492 }
8593 }
@@ -91,3 +99,32 @@ func Merge(object interface{}, overwriteObject interface{}) {
9199 }
92100 }
93101}
102+
103+ func isTrivialDataType (value reflect.Value ) bool {
104+ valueType := value .Type ()
105+
106+ if valueType .Kind () == reflect .Ptr {
107+ valueType = valueType .Elem ()
108+ }
109+
110+ switch valueType .Kind () {
111+ case reflect .Slice :
112+ return false
113+ case reflect .Map :
114+ return false
115+ case reflect .Struct :
116+ return false
117+ }
118+ return true
119+ }
120+
121+ func deepCopy (from interface {}) interface {} {
122+ yamlData , _ := yaml .Marshal (from )
123+ objectType := reflect .TypeOf (from )
124+
125+ copy := reflect .New (objectType ).Interface ()
126+
127+ yaml .Unmarshal (yamlData , copy )
128+
129+ return copy
130+ }
0 commit comments