Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: darccio/mergo
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.3.12
Choose a base ref
...
head repository: darccio/mergo
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.3.13
Choose a head ref
  • 16 commits
  • 9 files changed
  • 7 contributors

Commits on Apr 5, 2021

  1. Fix typo in README.md

    suppot -> support
    eltociear authored Apr 5, 2021
    Copy the full SHA
    a2870b0 View commit details

Commits on Apr 20, 2021

  1. Merge pull request #184 from eltociear/patch-1

    Fix typo in README.md
    darccio authored Apr 20, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    b968a17 View commit details

Commits on May 19, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    c26eae1 View commit details

Commits on Jul 4, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    2200c5d View commit details

Commits on Sep 23, 2021

  1. Merge pull request #193 from tjpnz/master

    Adding StructBot to Mergo in the wild section
    darccio authored Sep 23, 2021
    Copy the full SHA
    c8f4443 View commit details
  2. Copy the full SHA
    d739e7a View commit details
  3. Merge pull request #191 from marcauberer/master

    Add Goreleaser to featured projects
    darccio authored Sep 23, 2021
    Copy the full SHA
    fd3dfc9 View commit details

Commits on May 16, 2022

  1. Support slices of same type

    Fixes #209
    heaths committed May 16, 2022
    Copy the full SHA
    200f90d View commit details

Commits on May 18, 2022

  1. fix: gate transformers on valid non-nil destinations

    This builds on #203 which attempted to provide a more flexible gating to
    running transformers. However upon testing #203 in my own environment, I
    ran into the first panic listed below.
    
    There are a variety of errors that can happen when trying to run
    reflection on zero values:
    
    2 just from my testing of this PR
    ```
            panic: reflect: call of reflect.Value.Type on zero Value
    
            panic: reflect: call of reflect.Value.FieldByName on zero Value
    ```
    The panic specifically calls out zero values, but it's actual a more
    specific set of values which is covered by `reflect.IsValid`.
    
    I attempted to replace the check with `reflect.IsZero`, which ends up
    being too restrictive and breaks existing tests. I also attempted to
    solely use `reflect.IsZero` which is not restrictive enough and cause
    the later panic above in the tests. Thus I arrived on the combination in
    this PR which seems to strike the "right" balance.
    Zaq? Wiedmann committed May 18, 2022
    Copy the full SHA
    ab6b270 View commit details
  2. add test for keeping zero values with transformer

    Zaq? Wiedmann committed May 18, 2022
    Copy the full SHA
    4bed36e View commit details
  3. add test for deepMerge panic

    Zaq? Wiedmann committed May 18, 2022
    Copy the full SHA
    8109749 View commit details

Commits on May 24, 2022

  1. Merge pull request #211 from zaquestion/transformer_valid_destination

    fix: gate transformers on valid non-nil destinations
    darccio authored May 24, 2022
    Copy the full SHA
    fd7d2bc View commit details

Commits on May 25, 2022

  1. Merge pull request #210 from heaths/issue209

    Support slices of same type
    darccio authored May 25, 2022
    Copy the full SHA
    39ebbbb View commit details
  2. Upgrade yaml to v3

    As requested in "Update the yaml dependency to v3? #206".
    darccio committed May 25, 2022
    Copy the full SHA
    f86e6f6 View commit details
  3. Merge pull request #212 from imdario/dcc/issue-206

    Upgrade yaml to v3
    darccio authored May 25, 2022
    Copy the full SHA
    80c13e1 View commit details
  4. Update README.md

    darccio authored May 25, 2022
    Copy the full SHA
    1949787 View commit details
Showing with 110 additions and 35 deletions.
  1. +10 −22 README.md
  2. +1 −1 go.mod
  3. +2 −2 go.sum
  4. +26 −0 issue209_test.go
  5. +1 −1 merge.go
  6. +2 −2 mergo.go
  7. +7 −7 mergo_test.go
  8. +25 −0 pr211_2_test.go
  9. +36 −0 pr211_test.go
32 changes: 10 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -8,8 +8,7 @@
[![Coverage Status][9]][10]
[![Sourcegraph][11]][12]
[![FOSSA Status][13]][14]

[![GoCenter Kudos][15]][16]
[![Become my sponsor][15]][16]

[1]: https://travis-ci.org/imdario/mergo.png
[2]: https://travis-ci.org/imdario/mergo
@@ -25,8 +24,8 @@
[12]: https://sourcegraph.com/github.com/imdario/mergo?badge
[13]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=shield
[14]: https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_shield
[15]: https://search.gocenter.io/api/ui/badge/github.com%2Fimdario%2Fmergo
[16]: https://search.gocenter.io/github.com/imdario/mergo
[15]: https://img.shields.io/github/sponsors/imdario
[16]: https://github.com/sponsors/imdario

A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements.

@@ -36,11 +35,11 @@ Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the

## Status

It is ready for production use. [It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, etc](https://github.com/imdario/mergo#mergo-in-the-wild).
It is ready for production use. [It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, Microsoft, etc](https://github.com/imdario/mergo#mergo-in-the-wild).

### Important note

Please keep in mind that a problematic PR broke [0.3.9](//github.com/imdario/mergo/releases/tag/0.3.9). I reverted it in [0.3.10](//github.com/imdario/mergo/releases/tag/0.3.10), and I consider it stable but not bug-free. Also, this version adds suppot for go modules.
Please keep in mind that a problematic PR broke [0.3.9](//github.com/imdario/mergo/releases/tag/0.3.9). I reverted it in [0.3.10](//github.com/imdario/mergo/releases/tag/0.3.10), and I consider it stable but not bug-free. Also, this version adds support for go modules.

Keep in mind that in [0.3.2](//github.com/imdario/mergo/releases/tag/0.3.2), Mergo changed `Merge()`and `Map()` signatures to support [transformers](#transformers). I added an optional/variadic argument so that it won't break the existing code.

@@ -51,12 +50,12 @@ If you were using Mergo before April 6th, 2015, please check your project works
If Mergo is useful to you, consider buying me a coffee, a beer, or making a monthly donation to allow me to keep building great free software. :heart_eyes:

<a href='https://ko-fi.com/B0B58839' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=0' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
[![Beerpay](https://beerpay.io/imdario/mergo/badge.svg)](https://beerpay.io/imdario/mergo)
[![Beerpay](https://beerpay.io/imdario/mergo/make-wish.svg)](https://beerpay.io/imdario/mergo)
<a href="https://liberapay.com/dario/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
<a href='https://github.com/sponsors/imdario' target='_blank'><img alt="Become my sponsor" src="https://img.shields.io/github/sponsors/imdario?style=for-the-badge" /></a>

### Mergo in the wild

- [cli/cli](https://github.com/cli/cli)
- [moby/moby](https://github.com/moby/moby)
- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
- [vmware/dispatch](https://github.com/vmware/dispatch)
@@ -98,6 +97,8 @@ If Mergo is useful to you, consider buying me a coffee, a beer, or making a mont
- [jnuthong/item_search](https://github.com/jnuthong/item_search)
- [bukalapak/snowboard](https://github.com/bukalapak/snowboard)
- [containerssh/containerssh](https://github.com/containerssh/containerssh)
- [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
- [tjpnz/structbot](https://github.com/tjpnz/structbot)

## Install

@@ -168,7 +169,7 @@ func main() {

Note: if test are failing due missing package, please execute:

go get gopkg.in/yaml.v2
go get gopkg.in/yaml.v3

### Transformers

@@ -218,7 +219,6 @@ func main() {
}
```


## Contact me

If I can help you, you have an idea or you are using Mergo in your projects, don't hesitate to drop me a line (or a pull request): [@im_dario](https://twitter.com/im_dario)
@@ -227,18 +227,6 @@ If I can help you, you have an idea or you are using Mergo in your projects, don

Written by [Dario Castañé](http://dario.im).

## Top Contributors

[![0](https://sourcerer.io/fame/imdario/imdario/mergo/images/0)](https://sourcerer.io/fame/imdario/imdario/mergo/links/0)
[![1](https://sourcerer.io/fame/imdario/imdario/mergo/images/1)](https://sourcerer.io/fame/imdario/imdario/mergo/links/1)
[![2](https://sourcerer.io/fame/imdario/imdario/mergo/images/2)](https://sourcerer.io/fame/imdario/imdario/mergo/links/2)
[![3](https://sourcerer.io/fame/imdario/imdario/mergo/images/3)](https://sourcerer.io/fame/imdario/imdario/mergo/links/3)
[![4](https://sourcerer.io/fame/imdario/imdario/mergo/images/4)](https://sourcerer.io/fame/imdario/imdario/mergo/links/4)
[![5](https://sourcerer.io/fame/imdario/imdario/mergo/images/5)](https://sourcerer.io/fame/imdario/imdario/mergo/links/5)
[![6](https://sourcerer.io/fame/imdario/imdario/mergo/images/6)](https://sourcerer.io/fame/imdario/imdario/mergo/links/6)
[![7](https://sourcerer.io/fame/imdario/imdario/mergo/images/7)](https://sourcerer.io/fame/imdario/imdario/mergo/links/7)


## License

[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE).
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -2,4 +2,4 @@ module github.com/imdario/mergo

go 1.13

require gopkg.in/yaml.v2 v2.3.0
require gopkg.in/yaml.v3 v3.0.0
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
26 changes: 26 additions & 0 deletions issue209_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package mergo_test

import (
"testing"

"github.com/imdario/mergo"
)

func TestIssue209(t *testing.T) {
dst := []string{"a", "b"}
src := []string{"c", "d"}

if err := mergo.Merge(&dst, src, mergo.WithAppendSlice); err != nil {
t.Error(err)
}

expected := []string{"a", "b", "c", "d"}
if len(dst) != len(expected) {
t.Errorf("arrays not equal length")
}
for i := range expected {
if dst[i] != expected[i] {
t.Errorf("array elements at %d are not equal", i)
}
}
}
2 changes: 1 addition & 1 deletion merge.go
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
visited[h] = &visit{addr, typ, seen}
}

if config.Transformers != nil && !isEmptyValue(dst) {
if config.Transformers != nil && !isReflectNil(dst) && dst.IsValid() {
if fn := config.Transformers.Transformer(dst.Type()); fn != nil {
err = fn(dst, src)
return
4 changes: 2 additions & 2 deletions mergo.go
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ import (
var (
ErrNilArguments = errors.New("src and dst must not be nil")
ErrDifferentArgumentsTypes = errors.New("src and dst must be of same type")
ErrNotSupported = errors.New("only structs and maps are supported")
ErrNotSupported = errors.New("only structs, maps, and slices are supported")
ErrExpectedMapAsDestination = errors.New("dst was expected to be a map")
ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct")
ErrNonPointerAgument = errors.New("dst must be a pointer")
@@ -65,7 +65,7 @@ func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err error) {
return
}
vDst = reflect.ValueOf(dst).Elem()
if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map {
if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map && vDst.Kind() != reflect.Slice {
err = ErrNotSupported
return
}
14 changes: 7 additions & 7 deletions mergo_test.go
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ import (
"time"

"github.com/imdario/mergo"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"
)

type simpleTest struct {
@@ -603,18 +603,18 @@ func TestMapsWithNilPointer(t *testing.T) {
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{})
ft := thing["fields"].(map[string]interface{})
fl := license["fields"].(map[string]interface{})
// 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 := mergo.Merge(&license, thing); err != nil {
t.Error(err.Error())
}
currentLength := len(license["fields"].(map[interface{}]interface{}))
currentLength := len(license["fields"].(map[string]interface{}))
if currentLength != expectedLength {
t.Errorf(`thing not merged in license properly, license must have %d elements instead of %d`, expectedLength, currentLength)
}
fields := license["fields"].(map[interface{}]interface{})
fields := license["fields"].(map[string]interface{})
if _, ok := fields["id"]; !ok {
t.Errorf(`thing not merged in license properly, license must have a new id field from thing`)
}
@@ -930,11 +930,11 @@ func TestMergeMapWithInnerSliceOfDifferentType(t *testing.T) {
}
}

func TestMergeSlicesIsNotSupported(t *testing.T) {
func TestMergeDifferentSlicesIsNotSupported(t *testing.T) {
src := []string{"a", "b"}
dst := []int{1, 2}

if err := mergo.Merge(&src, &dst, mergo.WithOverride, mergo.WithAppendSlice); err != mergo.ErrNotSupported {
if err := mergo.Merge(&src, &dst, mergo.WithOverride, mergo.WithAppendSlice); err != mergo.ErrDifferentArgumentsTypes {
t.Errorf("expected %q, got %q", mergo.ErrNotSupported, err)
}
}
25 changes: 25 additions & 0 deletions pr211_2_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package mergo

import (
"reflect"
"testing"
"time"
)

type transformer struct {
}

func (s *transformer) Transformer(t reflect.Type) func(dst, src reflect.Value) error {
return nil
}

func Test_deepMergeTransformerInvalidDestination(t *testing.T) {
foo := time.Time{}
src := reflect.ValueOf(foo)
deepMerge(reflect.Value{}, src, make(map[uintptr]*visit), 0, &Config{
Transformers: &transformer{},
})
// this test is intentionally not asserting on anything, it's sole
// purpose to verify deepMerge doesn't panic when a transformer is
// passed and the destination is invalid.
}
36 changes: 36 additions & 0 deletions pr211_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package mergo_test

import (
"reflect"
"testing"

"github.com/imdario/mergo"
)

func TestMergeWithTransformerZeroValue(t *testing.T) {
// This test specifically tests that a transformer can be used to
// prevent overwriting a zero value (in this case a bool). This would fail prior to #211
type fooWithBoolPtr struct {
b *bool
}
var Bool = func(b bool) *bool { return &b }
a := fooWithBoolPtr{b: Bool(false)}
b := fooWithBoolPtr{b: Bool(true)}

if err := mergo.Merge(&a, &b, mergo.WithTransformers(&transformer{
m: map[reflect.Type]func(dst, src reflect.Value) error{
reflect.TypeOf(Bool(false)): func(dst, src reflect.Value) error {
if dst.CanSet() && dst.IsNil() {
dst.Set(src)
}
return nil
},
},
})); err != nil {
t.Error(err)
}

if *a.b != false {
t.Errorf("b not merged in properly: a.b(%v) != expected(%v)", a.b, false)
}
}