Merge pull request #2277 from zappy-shu/bump_mergo_v0.3.8

Bump mergo v0.3.8
This commit is contained in:
Sebastiaan van Stijn 2020-01-24 17:48:45 +01:00 committed by GitHub
commit 7a0b138571
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 157 additions and 12 deletions

View File

@ -57,6 +57,8 @@ func mergeServices(base, override []types.ServiceConfig) ([]types.ServiceConfig,
reflect.TypeOf([]types.ServicePortConfig{}): mergeSlice(toServicePortConfigsMap, toServicePortConfigsSlice), reflect.TypeOf([]types.ServicePortConfig{}): mergeSlice(toServicePortConfigsMap, toServicePortConfigsSlice),
reflect.TypeOf([]types.ServiceSecretConfig{}): mergeSlice(toServiceSecretConfigsMap, toServiceSecretConfigsSlice), reflect.TypeOf([]types.ServiceSecretConfig{}): mergeSlice(toServiceSecretConfigsMap, toServiceSecretConfigsSlice),
reflect.TypeOf([]types.ServiceConfigObjConfig{}): mergeSlice(toServiceConfigObjConfigsMap, toSServiceConfigObjConfigsSlice), reflect.TypeOf([]types.ServiceConfigObjConfig{}): mergeSlice(toServiceConfigObjConfigsMap, toSServiceConfigObjConfigsSlice),
reflect.TypeOf(&types.UlimitsConfig{}): mergeUlimitsConfig,
reflect.TypeOf(&types.ServiceNetworkConfig{}): mergeServiceNetworkConfig,
}, },
} }
for name, overrideService := range overrideServices { for name, overrideService := range overrideServices {
@ -201,6 +203,28 @@ func mergeLoggingConfig(dst, src reflect.Value) error {
return nil return nil
} }
//nolint: unparam
func mergeUlimitsConfig(dst, src reflect.Value) error {
if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() {
dst.Elem().Set(src.Elem())
}
return nil
}
//nolint: unparam
func mergeServiceNetworkConfig(dst, src reflect.Value) error {
if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() {
dst.Elem().FieldByName("Aliases").Set(src.Elem().FieldByName("Aliases"))
if ipv4 := src.Elem().FieldByName("Ipv4Address").Interface().(string); ipv4 != "" {
dst.Elem().FieldByName("Ipv4Address").SetString(ipv4)
}
if ipv6 := src.Elem().FieldByName("Ipv6Address").Interface().(string); ipv6 != "" {
dst.Elem().FieldByName("Ipv6Address").SetString(ipv6)
}
}
return nil
}
func getLoggingDriver(v reflect.Value) string { func getLoggingDriver(v reflect.Value) string {
return v.FieldByName("Driver").String() return v.FieldByName("Driver").String()
} }

View File

@ -1,9 +1,11 @@
package loader package loader
import ( import (
"reflect"
"testing" "testing"
"github.com/docker/cli/cli/compose/types" "github.com/docker/cli/cli/compose/types"
"github.com/imdario/mergo"
"gotest.tools/assert" "gotest.tools/assert"
) )
@ -1014,3 +1016,94 @@ func TestLoadMultipleNetworks(t *testing.T) {
Configs: map[string]types.ConfigObjConfig{}, Configs: map[string]types.ConfigObjConfig{},
}, config) }, config)
} }
func TestMergeUlimitsConfig(t *testing.T) {
specials := &specials{
m: map[reflect.Type]func(dst, src reflect.Value) error{
reflect.TypeOf(&types.UlimitsConfig{}): mergeUlimitsConfig,
},
}
base := map[string]*types.UlimitsConfig{
"override-single": &types.UlimitsConfig{Single: 100},
"override-single-with-soft-hard": &types.UlimitsConfig{Single: 200},
"override-soft-hard": &types.UlimitsConfig{Soft: 300, Hard: 301},
"override-soft-hard-with-single": &types.UlimitsConfig{Soft: 400, Hard: 401},
"dont-override": &types.UlimitsConfig{Single: 500},
}
override := map[string]*types.UlimitsConfig{
"override-single": &types.UlimitsConfig{Single: 110},
"override-single-with-soft-hard": &types.UlimitsConfig{Soft: 210, Hard: 211},
"override-soft-hard": &types.UlimitsConfig{Soft: 310, Hard: 311},
"override-soft-hard-with-single": &types.UlimitsConfig{Single: 410},
"add": &types.UlimitsConfig{Single: 610},
}
err := mergo.Merge(&base, &override, mergo.WithOverride, mergo.WithTransformers(specials))
assert.NilError(t, err)
assert.DeepEqual(
t,
base,
map[string]*types.UlimitsConfig{
"override-single": &types.UlimitsConfig{Single: 110},
"override-single-with-soft-hard": &types.UlimitsConfig{Soft: 210, Hard: 211},
"override-soft-hard": &types.UlimitsConfig{Soft: 310, Hard: 311},
"override-soft-hard-with-single": &types.UlimitsConfig{Single: 410},
"dont-override": &types.UlimitsConfig{Single: 500},
"add": &types.UlimitsConfig{Single: 610},
},
)
}
func TestMergeServiceNetworkConfig(t *testing.T) {
specials := &specials{
m: map[reflect.Type]func(dst, src reflect.Value) error{
reflect.TypeOf(&types.ServiceNetworkConfig{}): mergeServiceNetworkConfig,
},
}
base := map[string]*types.ServiceNetworkConfig{
"override-aliases": &types.ServiceNetworkConfig{
Aliases: []string{"100", "101"},
Ipv4Address: "127.0.0.1",
Ipv6Address: "0:0:0:0:0:0:0:1",
},
"dont-override": &types.ServiceNetworkConfig{
Aliases: []string{"200", "201"},
Ipv4Address: "127.0.0.2",
Ipv6Address: "0:0:0:0:0:0:0:2",
},
}
override := map[string]*types.ServiceNetworkConfig{
"override-aliases": &types.ServiceNetworkConfig{
Aliases: []string{"110", "111"},
Ipv4Address: "127.0.1.1",
Ipv6Address: "0:0:0:0:0:0:1:1",
},
"add": &types.ServiceNetworkConfig{
Aliases: []string{"310", "311"},
Ipv4Address: "127.0.3.1",
Ipv6Address: "0:0:0:0:0:0:3:1",
},
}
err := mergo.Merge(&base, &override, mergo.WithOverride, mergo.WithTransformers(specials))
assert.NilError(t, err)
assert.DeepEqual(
t,
base,
map[string]*types.ServiceNetworkConfig{
"override-aliases": &types.ServiceNetworkConfig{
Aliases: []string{"110", "111"},
Ipv4Address: "127.0.1.1",
Ipv6Address: "0:0:0:0:0:0:1:1",
},
"dont-override": &types.ServiceNetworkConfig{
Aliases: []string{"200", "201"},
Ipv4Address: "127.0.0.2",
Ipv6Address: "0:0:0:0:0:0:0:2",
},
"add": &types.ServiceNetworkConfig{
Aliases: []string{"310", "311"},
Ipv4Address: "127.0.3.1",
Ipv6Address: "0:0:0:0:0:0:3:1",
},
},
)
}

View File

@ -34,7 +34,7 @@ github.com/gorilla/mux 00bdffe0f3c77e27d2cf6f5c7023
github.com/grpc-ecosystem/grpc-gateway 1a03ca3bad1e1ebadaedd3abb76bc58d4ac8143b github.com/grpc-ecosystem/grpc-gateway 1a03ca3bad1e1ebadaedd3abb76bc58d4ac8143b
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746 github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
github.com/hashicorp/golang-lru 7f827b33c0f158ec5dfbba01bb0b14a4541fd81d # v0.5.3 github.com/hashicorp/golang-lru 7f827b33c0f158ec5dfbba01bb0b14a4541fd81d # v0.5.3
github.com/imdario/mergo 7c29201646fa3de8506f701213473dd407f19646 # v0.3.7 github.com/imdario/mergo 1afb36080aec31e0d1528973ebe6721b191b0369 # v0.3.8
github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 # v1.0.0 github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 # v1.0.0
github.com/jaguilar/vt100 ad4c4a5743050fb7f88ce968dca9422f72a0e3f2 git://github.com/tonistiigi/vt100.git github.com/jaguilar/vt100 ad4c4a5743050fb7f88ce968dca9422f72a0e3f2 git://github.com/tonistiigi/vt100.git
github.com/json-iterator/go 0ff49de124c6f76f8494e194af75bde0f1a49a29 # 1.1.6 github.com/json-iterator/go 0ff49de124c6f76f8494e194af75bde0f1a49a29 # 1.1.6

View File

@ -26,10 +26,12 @@ func hasExportedField(dst reflect.Value) (exported bool) {
} }
type Config struct { type Config struct {
Overwrite bool Overwrite bool
AppendSlice bool AppendSlice bool
Transformers Transformers TypeCheck bool
overwriteWithEmptyValue bool Transformers Transformers
overwriteWithEmptyValue bool
overwriteSliceWithEmptyValue bool
} }
type Transformers interface { type Transformers interface {
@ -41,7 +43,9 @@ type Transformers interface {
// short circuiting on recursive types. // short circuiting on recursive types.
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) { func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
overwrite := config.Overwrite overwrite := config.Overwrite
typeCheck := config.TypeCheck
overwriteWithEmptySrc := config.overwriteWithEmptyValue overwriteWithEmptySrc := config.overwriteWithEmptyValue
overwriteSliceWithEmptySrc := config.overwriteSliceWithEmptyValue
config.overwriteWithEmptyValue = false config.overwriteWithEmptyValue = false
if !src.IsValid() { if !src.IsValid() {
@ -128,11 +132,14 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
dstSlice = reflect.ValueOf(dstElement.Interface()) dstSlice = reflect.ValueOf(dstElement.Interface())
} }
if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
if typeCheck && srcSlice.Type() != dstSlice.Type() {
return fmt.Errorf("cannot override two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
}
dstSlice = srcSlice dstSlice = srcSlice
} else if config.AppendSlice { } else if config.AppendSlice {
if srcSlice.Type() != dstSlice.Type() { if srcSlice.Type() != dstSlice.Type() {
return fmt.Errorf("cannot append two slice with different type (%s, %s)", srcSlice.Type(), dstSlice.Type()) return fmt.Errorf("cannot append two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
} }
dstSlice = reflect.AppendSlice(dstSlice, srcSlice) dstSlice = reflect.AppendSlice(dstSlice, srcSlice)
} }
@ -143,7 +150,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
continue continue
} }
if srcElement.IsValid() && (overwrite || (!dstElement.IsValid() || isEmptyValue(dstElement))) { if srcElement.IsValid() && ((srcElement.Kind() != reflect.Ptr && overwrite) || !dstElement.IsValid() || isEmptyValue(dstElement)) {
if dst.IsNil() { if dst.IsNil() {
dst.Set(reflect.MakeMap(dst.Type())) dst.Set(reflect.MakeMap(dst.Type()))
} }
@ -154,7 +161,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
if !dst.CanSet() { if !dst.CanSet() {
break break
} }
if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
dst.Set(src) dst.Set(src)
} else if config.AppendSlice { } else if config.AppendSlice {
if src.Type() != dst.Type() { if src.Type() != dst.Type() {
@ -168,11 +175,21 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
if src.IsNil() { if src.IsNil() {
break break
} }
if src.Kind() != reflect.Interface {
if dst.Kind() != reflect.Ptr && src.Type().AssignableTo(dst.Type()) {
if dst.IsNil() || overwrite { if dst.IsNil() || overwrite {
if dst.CanSet() && (overwrite || isEmptyValue(dst)) { if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
dst.Set(src) dst.Set(src)
} }
}
break
}
if src.Kind() != reflect.Interface {
if dst.IsNil() || (src.Kind() != reflect.Ptr && overwrite) {
if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
dst.Set(src)
}
} else if src.Kind() == reflect.Ptr { } else if src.Kind() == reflect.Ptr {
if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil { if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
return return
@ -198,6 +215,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
dst.Set(src) dst.Set(src)
} }
} }
return return
} }
@ -209,7 +227,7 @@ func Merge(dst, src interface{}, opts ...func(*Config)) error {
return merge(dst, src, opts...) return merge(dst, src, opts...)
} }
// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by // MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overridden by
// non-empty src attribute values. // non-empty src attribute values.
// Deprecated: use Merge(…) with WithOverride // Deprecated: use Merge(…) with WithOverride
func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error { func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
@ -228,11 +246,21 @@ func WithOverride(config *Config) {
config.Overwrite = true config.Overwrite = true
} }
// WithAppendSlice will make merge append slices instead of overwriting it // WithOverride will make merge override empty dst slice with empty src slice.
func WithOverrideEmptySlice(config *Config) {
config.overwriteSliceWithEmptyValue = true
}
// WithAppendSlice will make merge append slices instead of overwriting it.
func WithAppendSlice(config *Config) { func WithAppendSlice(config *Config) {
config.AppendSlice = true config.AppendSlice = true
} }
// WithTypeCheck will make merge check types while overwriting it (must be used with WithOverride).
func WithTypeCheck(config *Config) {
config.TypeCheck = true
}
func merge(dst, src interface{}, opts ...func(*Config)) error { func merge(dst, src interface{}, opts ...func(*Config)) error {
var ( var (
vDst, vSrc reflect.Value vDst, vSrc reflect.Value