diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..afd9470 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +golang-github-imdario-mergo (0.1.2+git20150606.5.61a5285-1) UNRELEASED; urgency=medium + + * Initial release (Closes: #802743) + + -- Tim Potter Fri, 23 Oct 2015 15:49:38 +1100 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +9 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..a6dcbd3 --- /dev/null +++ b/debian/control @@ -0,0 +1,23 @@ +Source: golang-github-imdario-mergo +Section: devel +Priority: extra +Maintainer: Debian Go Packaging Team +Uploaders: Tim Potter +Build-Depends: debhelper (>= 9), + dh-golang, + golang-go +Standards-Version: 3.9.6 +Homepage: https://github.com/imdario/mergo +Vcs-Browser: https://anonscm.debian.org/cgit/pkg-go/packages/golang-github-imdario-mergo.git +Vcs-Git: git://anonscm.debian.org/pkg-go/packages/golang-github-imdario-mergo.git +XS-Go-Import-Path: github.com/imdario/mergo + +Package: golang-github-imdario-mergo-dev +Architecture: all +Depends: ${shlibs:Depends}, + ${misc:Depends}, + golang-go +Description: Functions to merge structs and maps in Go + Mergo is a set of helper functions to merge structs and maps in + the Go language. It is useful for configuration default values, + avoiding messy if-statements in initialisation code. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..5174932 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,40 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: mergo +Source: https://github.com/imdario/mergo + +Files: * +Copyright: 2013 Dario Castañé + 2012 The Go Authors +License: BSD-3-clause + +Files: debian/* +Copyright: 2015 Tim Potter +License: BSD-3-clause +Comment: Debian packaging is licensed under the same terms as upstream + +License: BSD-3-clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + . + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/debian/files b/debian/files new file mode 100644 index 0000000..eb057a0 --- /dev/null +++ b/debian/files @@ -0,0 +1 @@ +golang-github-imdario-mergo-dev_0.1.2+git20150606.5.61a5285-1_all.deb devel extra diff --git a/debian/gbp.conf b/debian/gbp.conf new file mode 100644 index 0000000..cec628c --- /dev/null +++ b/debian/gbp.conf @@ -0,0 +1,2 @@ +[DEFAULT] +pristine-tar = True diff --git a/debian/golang-github-imdario-mergo-dev/DEBIAN/control b/debian/golang-github-imdario-mergo-dev/DEBIAN/control new file mode 100644 index 0000000..9a6f7a1 --- /dev/null +++ b/debian/golang-github-imdario-mergo-dev/DEBIAN/control @@ -0,0 +1,115 @@ +Package: golang-github-imdario-mergo-dev +Source: golang-github-imdario-mergo +Version: 0.1.2+git20150606.5.61a5285-1 +Architecture: all +Maintainer: Debian Go Packaging Team +Installed-Size: 32 +Depends: golang-go +Section: devel +Priority: extra +Homepage: https://github.com/imdario/mergo +Description: Mergo: merging Go structs and maps since 2013 + Mergo A helper to merge structs and maps in Golang. Useful for + configuration default values, avoiding messy if-statements. + . + Also a lovely comune (http://en.wikipedia.org/wiki/Mergo) (municipality) + in the Province of Ancona in the Italian region Marche. + . + Mergo dall'alto Status It is ready for production use. It works fine + after extensive use in the wild. + . + Build Status (https://travis-ci.org/imdario/mergo) GoDoc + (https://godoc.org/github.com/imdario/mergo) Important note Mergo is + intended to assign only zero value fields on destination with source + value. Since April 6th it works like this. Before it didn't work + properly, causing some random overwrites. After some issues and PRs + I found it didn't merge as I designed it. Thanks to imdario/mergo#8 + (https://github.com/imdario/mergo/pull/8) overwriting functions were + added and the wrong behavior was clearly detected. + . + If you were using Mergo before April 6th 2015, please check + your project works as intended after updating your local copy + with go get -u github.com/imdario/mergo. I apologize for any + issue caused by its previous behavior and any future bug that + Mergo could cause (I hope it won't!) in existing projects after + the change (release 0.2.0). Mergo in the wild• imdario/zas + (https://github.com/imdario/zas)• GoogleCloudPlatform/kubernetes + (https://github.com/GoogleCloudPlatform/kubernetes)• soniah/dnsmadeeasy + (https://github.com/soniah/dnsmadeeasy)• EagerIO/Stout + (https://github.com/EagerIO/Stout)• lynndylanhurley/defsynth-api + (https://github.com/lynndylanhurley/defsynth-api)• + russross/canvasassignments + (https://github.com/russross/canvasassignments)• rdegges/cryptly-api + (https://github.com/rdegges/cryptly-api)• casualjim/exeggutor + (https://github.com/casualjim/exeggutor)• divshot/gitling + (https://github.com/divshot/gitling)• RWJMurphy/gorl + (https://github.com/RWJMurphy/gorl)• andrerocker/deploy42 + (https://github.com/andrerocker/deploy42)• elwinar/rambler + (https://github.com/elwinar/rambler)• tmaiaroto/gopartman + (https://github.com/tmaiaroto/gopartman)• jfbus/impressionist + (https://github.com/jfbus/impressionist)• Jmeyering/zealot + (https://github.com/Jmeyering/zealot)• godep-migrator/rigger-host + (https://github.com/godep-migrator/rigger-host)• + Dronevery/MultiwaySwitch-Go + (https://github.com/Dronevery/MultiwaySwitch-Go)• thoas/picfit + (https://github.com/thoas/picfit)• mantasmatelis/whooplist-server + (https://github.com/mantasmatelis/whooplist-server)• + jnuthong/item_search + (https://github.com/jnuthong/item_search)Installationgo get + github.com/imdario/mergo + . + // use in your .go code import ( + "github.com/imdario/mergo" + ) Usage You can only merge same-type structs with exported fields + initialized as zero value of their type and same-types maps. Mergo won't + merge unexported (private) fields but will do recursively any exported + one. Also maps will be merged recursively except for structs inside + maps (because they are not addressable using Go reflection). if err := + mergo.Merge(&dst, src); err != nil { + // ... + } + . + Additionally, you can map a map[string]interface{} to a struct (and + otherwise, from struct to map), following the same restrictions as in + Merge(). Keys are capitalized to find each corresponding exported field. + if err := mergo.Map(&dst, srcMap); err != nil { + // ... + } + . + Warning: if you map a struct to map, it won't do it recursively. Don't + expect Mergo to map struct members of your struct as + map[string]interface{}. They will be just assigned as values. + . + More information and examples in godoc documentation + (http://godoc.org/github.com/imdario/mergo). Nice example ```go + package main + . + import ( + "fmt" "github.com/imdario/mergo" + ) + . + type Foo struct { + A string B int64 + } + . + func main() { + src := Foo{ + A: "one", + } + dest := Foo{ + A: "two", B: 2, + } + . + mergo.Merge(&dest, src) + . + fmt.Println(dest) // Will print // {two 2} + . + } ``` + . + Note: if test are failing due missing package, please execute: go get + gopkg.in/yaml.v1 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) About + Written by Dario Castañé (http://dario.im). License BSD 3-Clause + (http://opensource.org/licenses/BSD-3-Clause) license, as Go language + (http://golang.org/LICENSE). diff --git a/debian/golang-github-imdario-mergo-dev/DEBIAN/md5sums b/debian/golang-github-imdario-mergo-dev/DEBIAN/md5sums new file mode 100644 index 0000000..f9b0ae3 --- /dev/null +++ b/debian/golang-github-imdario-mergo-dev/DEBIAN/md5sums @@ -0,0 +1,7 @@ +cea04a95e95a86e12eeaeabffe961407 usr/share/doc/golang-github-imdario-mergo-dev/changelog.Debian.gz +23c76504c9f8fcdbc9cf9dace180e609 usr/share/doc/golang-github-imdario-mergo-dev/copyright +72d36ad766a79c6213213fe895ea689b usr/share/gocode/src/github.com/imdario/mergo/doc.go +d93b415363bfd121b6ae4d6017d2bd20 usr/share/gocode/src/github.com/imdario/mergo/map.go +cb00ac7e30385c86b544f5f61ff25305 usr/share/gocode/src/github.com/imdario/mergo/merge.go +53083cfcfcc7928978e6241303c1e0ce usr/share/gocode/src/github.com/imdario/mergo/mergo.go +db680b3570c05f2dd24fe1d035e7c9d3 usr/share/gocode/src/github.com/imdario/mergo/mergo_test.go diff --git a/debian/golang-github-imdario-mergo-dev/usr/share/doc/golang-github-imdario-mergo-dev/changelog.Debian.gz b/debian/golang-github-imdario-mergo-dev/usr/share/doc/golang-github-imdario-mergo-dev/changelog.Debian.gz new file mode 100644 index 0000000..c177e37 Binary files /dev/null and b/debian/golang-github-imdario-mergo-dev/usr/share/doc/golang-github-imdario-mergo-dev/changelog.Debian.gz differ diff --git a/debian/golang-github-imdario-mergo-dev/usr/share/doc/golang-github-imdario-mergo-dev/copyright b/debian/golang-github-imdario-mergo-dev/usr/share/doc/golang-github-imdario-mergo-dev/copyright new file mode 100644 index 0000000..0570c12 --- /dev/null +++ b/debian/golang-github-imdario-mergo-dev/usr/share/doc/golang-github-imdario-mergo-dev/copyright @@ -0,0 +1,15 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: mergo +Source: https://github.com/imdario/mergo + +Files: * +Copyright: 2013 Dario Castañé +License: BSD-3-clause + +Files: debian/* +Copyright: 2015 Tim Potter +License: BSD-3-clause +Comment: Debian packaging is licensed under the same terms as upstream + +License: BSD-3-clause +TODO \ No newline at end of file diff --git a/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/doc.go b/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/doc.go new file mode 100644 index 0000000..6e9aa7b --- /dev/null +++ b/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/doc.go @@ -0,0 +1,44 @@ +// Copyright 2013 Dario Castañé. All rights reserved. +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package mergo merges same-type structs and maps by setting default values in zero-value fields. + +Mergo won't merge unexported (private) fields but will do recursively any exported one. It also won't merge structs inside maps (because they are not addressable using Go reflection). + +Usage + +From my own work-in-progress project: + + type networkConfig struct { + Protocol string + Address string + ServerType string `json: "server_type"` + Port uint16 + } + + type FssnConfig struct { + Network networkConfig + } + + var fssnDefault = FssnConfig { + networkConfig { + "tcp", + "127.0.0.1", + "http", + 31560, + }, + } + + // Inside a function [...] + + if err := mergo.Merge(&config, fssnDefault); err != nil { + log.Fatal(err) + } + + // More code [...] + +*/ +package mergo diff --git a/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/map.go b/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/map.go new file mode 100644 index 0000000..1ed3d71 --- /dev/null +++ b/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/map.go @@ -0,0 +1,154 @@ +// Copyright 2014 Dario Castañé. All rights reserved. +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Based on src/pkg/reflect/deepequal.go from official +// golang's stdlib. + +package mergo + +import ( + "fmt" + "reflect" + "unicode" + "unicode/utf8" +) + +func changeInitialCase(s string, mapper func(rune) rune) string { + if s == "" { + return s + } + r, n := utf8.DecodeRuneInString(s) + return string(mapper(r)) + s[n:] +} + +func isExported(field reflect.StructField) bool { + r, _ := utf8.DecodeRuneInString(field.Name) + return r >= 'A' && r <= 'Z' +} + +// 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) { + if dst.CanAddr() { + addr := dst.UnsafeAddr() + h := 17 * addr + seen := visited[h] + typ := dst.Type() + for p := seen; p != nil; p = p.next { + if p.ptr == addr && p.typ == typ { + return nil + } + } + // Remember, remember... + visited[h] = &visit{addr, typ, seen} + } + zeroValue := reflect.Value{} + switch dst.Kind() { + case reflect.Map: + dstMap := dst.Interface().(map[string]interface{}) + for i, n := 0, src.NumField(); i < n; i++ { + srcType := src.Type() + field := srcType.Field(i) + if !isExported(field) { + continue + } + fieldName := field.Name + fieldName = changeInitialCase(fieldName, unicode.ToLower) + if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v)) || overwrite) { + dstMap[fieldName] = src.Field(i).Interface() + } + } + case reflect.Struct: + srcMap := src.Interface().(map[string]interface{}) + for key := range srcMap { + srcValue := srcMap[key] + fieldName := changeInitialCase(key, unicode.ToUpper) + dstElement := dst.FieldByName(fieldName) + if dstElement == zeroValue { + // We discard it because the field doesn't exist. + continue + } + srcElement := reflect.ValueOf(srcValue) + dstKind := dstElement.Kind() + srcKind := srcElement.Kind() + if srcKind == reflect.Ptr && dstKind != reflect.Ptr { + srcElement = srcElement.Elem() + srcKind = reflect.TypeOf(srcElement.Interface()).Kind() + } else if dstKind == reflect.Ptr { + // Can this work? I guess it can't. + if srcKind != reflect.Ptr && srcElement.CanAddr() { + srcPtr := srcElement.Addr() + srcElement = reflect.ValueOf(srcPtr) + srcKind = reflect.Ptr + } + } + if !srcElement.IsValid() { + continue + } + if srcKind == dstKind { + if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); 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) + } + } + } + } + return +} + +// Map sets fields' values in dst from src. +// src can be a map with string keys or a struct. dst must be the opposite: +// if src is a map, dst must be a valid pointer to struct. If src is a struct, +// dst must be map[string]interface{}. +// It won't merge unexported (private) fields and will do recursively +// any exported field. +// If dst is a map, keys will be src fields' names in lower camel case. +// Missing key in src that doesn't match a field in dst will be skipped. This +// 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 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 + ) + 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) + } + switch vSrc.Kind() { + case reflect.Struct: + if vDst.Kind() != reflect.Map { + return ErrExpectedMapAsDestination + } + case reflect.Map: + if vDst.Kind() != reflect.Struct { + return ErrExpectedStructAsDestination + } + default: + return ErrNotSupported + } + return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite) +} diff --git a/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/merge.go b/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/merge.go new file mode 100644 index 0000000..60929b7 --- /dev/null +++ b/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/merge.go @@ -0,0 +1,110 @@ +// Copyright 2013 Dario Castañé. All rights reserved. +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Based on src/pkg/reflect/deepequal.go from official +// golang's stdlib. + +package mergo + +import ( + "reflect" +) + +// 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) { + if !src.IsValid() { + return + } + if dst.CanAddr() { + addr := dst.UnsafeAddr() + h := 17 * addr + seen := visited[h] + typ := dst.Type() + for p := seen; p != nil; p = p.next { + if p.ptr == addr && p.typ == typ { + return nil + } + } + // Remember, remember... + visited[h] = &visit{addr, typ, seen} + } + 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 + } + } + case reflect.Map: + for _, key := range src.MapKeys() { + srcElement := src.MapIndex(key) + if !srcElement.IsValid() { + continue + } + dstElement := dst.MapIndex(key) + switch reflect.TypeOf(srcElement.Interface()).Kind() { + case reflect.Struct: + fallthrough + case reflect.Map: + if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil { + return + } + } + if !isEmptyValue(srcElement) && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) { + if dst.IsNil() { + dst.Set(reflect.MakeMap(dst.Type())) + } + dst.SetMapIndex(key, srcElement) + } + } + case reflect.Ptr: + fallthrough + case reflect.Interface: + if src.IsNil() { + break + } else if dst.IsNil() { + if dst.CanSet() && (overwrite || isEmptyValue(dst)) { + dst.Set(src) + } + } else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, overwrite); err != nil { + return + } + default: + if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) { + dst.Set(src) + } + } + return +} + +// 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) +} + +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 + ) + 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) +} diff --git a/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/mergo.go b/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/mergo.go new file mode 100644 index 0000000..f8a0991 --- /dev/null +++ b/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/mergo.go @@ -0,0 +1,90 @@ +// Copyright 2013 Dario Castañé. All rights reserved. +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Based on src/pkg/reflect/deepequal.go from official +// golang's stdlib. + +package mergo + +import ( + "errors" + "reflect" +) + +// Errors reported by Mergo when it finds invalid arguments. +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") + ErrExpectedMapAsDestination = errors.New("dst was expected to be a map") + ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct") +) + +// During deepMerge, must keep track of checks that are +// in progress. The comparison algorithm assumes that all +// checks in progress are true when it reencounters them. +// Visited are stored in a map indexed by 17 * a1 + a2; +type visit struct { + ptr uintptr + typ reflect.Type + next *visit +} + +// From src/pkg/encoding/json. +func isEmptyValue(v reflect.Value) bool { + switch v.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + return false +} + +func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err error) { + if dst == nil || src == nil { + err = ErrNilArguments + return + } + vDst = reflect.ValueOf(dst).Elem() + if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map { + err = ErrNotSupported + return + } + vSrc = reflect.ValueOf(src) + // We check if vSrc is a pointer to dereference it. + if vSrc.Kind() == reflect.Ptr { + vSrc = vSrc.Elem() + } + return +} + +// 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 deeper(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) { + if dst.CanAddr() { + addr := dst.UnsafeAddr() + h := 17 * addr + seen := visited[h] + typ := dst.Type() + for p := seen; p != nil; p = p.next { + if p.ptr == addr && p.typ == typ { + return nil + } + } + // Remember, remember... + visited[h] = &visit{addr, typ, seen} + } + return // TODO refactor +} diff --git a/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/mergo_test.go b/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/mergo_test.go new file mode 100644 index 0000000..8284397 --- /dev/null +++ b/debian/golang-github-imdario-mergo-dev/usr/share/gocode/src/github.com/imdario/mergo/mergo_test.go @@ -0,0 +1,310 @@ +// Copyright 2013 Dario Castañé. All rights reserved. +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mergo + +import ( + "reflect" + "testing" +) + +type simpleTest struct { + Value int +} + +type complexTest struct { + St simpleTest + sz int + Id string +} + +type moreComplextText struct { + Ct complexTest + St simpleTest + Nt simpleTest +} + +type pointerTest struct { + C *simpleTest +} + +type sliceTest struct { + S []int +} + +func TestKb(t *testing.T) { + type testStruct struct { + Name string + KeyValue map[string]interface{} + } + + akv := make(map[string]interface{}) + akv["Key1"] = "not value 1" + akv["Key2"] = "value2" + a := testStruct{} + a.Name = "A" + a.KeyValue = akv + + bkv := make(map[string]interface{}) + bkv["Key1"] = "value1" + bkv["Key3"] = "value3" + b := testStruct{} + b.Name = "B" + b.KeyValue = bkv + + ekv := make(map[string]interface{}) + ekv["Key1"] = "value1" + ekv["Key2"] = "value2" + ekv["Key3"] = "value3" + expected := testStruct{} + expected.Name = "B" + expected.KeyValue = ekv + + Merge(&b, a) + + if !reflect.DeepEqual(b, expected) { + t.Errorf("Actual: %#v did not match \nExpected: %#v", b, expected) + } +} + +func TestNil(t *testing.T) { + if err := Merge(nil, nil); err != ErrNilArguments { + t.Fail() + } +} + +func TestDifferentTypes(t *testing.T) { + a := simpleTest{42} + b := 42 + if err := Merge(&a, b); err != ErrDifferentArgumentsTypes { + t.Fail() + } +} + +func TestSimpleStruct(t *testing.T) { + a := simpleTest{} + b := simpleTest{42} + if err := Merge(&a, b); err != nil { + t.FailNow() + } + if a.Value != 42 { + t.Fatalf("b not merged in properly: a.Value(%d) != b.Value(%d)", a.Value, b.Value) + } + if !reflect.DeepEqual(a, b) { + t.FailNow() + } +} + +func TestComplexStruct(t *testing.T) { + a := complexTest{} + a.Id = "athing" + b := complexTest{simpleTest{42}, 1, "bthing"} + if err := Merge(&a, b); err != nil { + t.FailNow() + } + if a.St.Value != 42 { + t.Fatalf("b not merged in properly: a.St.Value(%d) != b.St.Value(%d)", a.St.Value, b.St.Value) + } + if a.sz == 1 { + t.Fatalf("a's private field sz not preserved from merge: a.sz(%d) == b.sz(%d)", a.sz, b.sz) + } + if a.Id == b.Id { + t.Fatalf("a's field Id merged unexpectedly: a.Id(%s) == b.Id(%s)", a.Id, b.Id) + } +} + +func TestComplexStructWithOverwrite(t *testing.T) { + a := complexTest{simpleTest{1}, 1, "do-not-overwrite-with-empty-value"} + b := complexTest{simpleTest{42}, 2, ""} + + expect := complexTest{simpleTest{42}, 1, "do-not-overwrite-with-empty-value"} + if err := MergeWithOverwrite(&a, b); err != nil { + t.FailNow() + } + + if !reflect.DeepEqual(a, expect) { + t.Fatalf("Test failed:\ngot :\n%#v\n\nwant :\n%#v\n\n", a, expect) + } +} + +func TestPointerStruct(t *testing.T) { + s1 := simpleTest{} + s2 := simpleTest{19} + a := pointerTest{&s1} + b := pointerTest{&s2} + if err := Merge(&a, b); err != nil { + t.FailNow() + } + if a.C.Value != b.C.Value { + t.Fatalf("b not merged in properly: a.C.Value(%d) != b.C.Value(%d)", a.C.Value, b.C.Value) + } +} + +type embeddingStruct struct { + embeddedStruct +} + +type embeddedStruct struct { + A string +} + +func TestEmbeddedStruct(t *testing.T) { + tests := []struct { + src embeddingStruct + dst embeddingStruct + expected embeddingStruct + }{ + { + src: embeddingStruct{ + embeddedStruct{"foo"}, + }, + dst: embeddingStruct{ + embeddedStruct{""}, + }, + expected: embeddingStruct{ + embeddedStruct{"foo"}, + }, + }, + { + src: embeddingStruct{ + embeddedStruct{""}, + }, + dst: embeddingStruct{ + embeddedStruct{"bar"}, + }, + expected: embeddingStruct{ + embeddedStruct{"bar"}, + }, + }, + { + src: embeddingStruct{ + embeddedStruct{"foo"}, + }, + dst: embeddingStruct{ + embeddedStruct{"bar"}, + }, + expected: embeddingStruct{ + embeddedStruct{"bar"}, + }, + }, + } + + for _, test := range tests { + err := Merge(&test.dst, test.src) + if err != nil { + t.Errorf("unexpected error: %v", err) + continue + } + if !reflect.DeepEqual(test.dst, test.expected) { + t.Errorf("unexpected output\nexpected:\n%+v\nsaw:\n%+v\n", test.expected, test.dst) + } + } +} + +func TestPointerStructNil(t *testing.T) { + a := pointerTest{nil} + b := pointerTest{&simpleTest{19}} + if err := Merge(&a, b); err != nil { + t.FailNow() + } + if a.C.Value != b.C.Value { + t.Fatalf("b not merged in a properly: a.C.Value(%d) != b.C.Value(%d)", a.C.Value, b.C.Value) + } +} + +func TestSliceStruct(t *testing.T) { + a := sliceTest{} + b := sliceTest{[]int{1, 2, 3}} + if err := Merge(&a, b); err != nil { + t.FailNow() + } + if len(b.S) != 3 { + 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)) + } + + a = sliceTest{[]int{1}} + b = sliceTest{[]int{1, 2, 3}} + if err := Merge(&a, b); err != nil { + t.FailNow() + } + if len(a.S) != 1 { + t.FailNow() + } + if len(a.S) == len(b.S) { + t.Fatalf("b merged unexpectedly %d != %d", len(a.S), len(b.S)) + } +} + +func TestMapsWithOverwrite(t *testing.T) { + m := map[string]simpleTest{ + "a": simpleTest{}, // overwritten by 16 + "b": simpleTest{42}, // not overwritten by empty value + "c": simpleTest{13}, // overwritten by 12 + "d": simpleTest{61}, + } + n := map[string]simpleTest{ + "a": simpleTest{16}, + "b": simpleTest{}, + "c": simpleTest{12}, + "e": simpleTest{14}, + } + expect := map[string]simpleTest{ + "a": simpleTest{16}, + "b": simpleTest{}, + "c": simpleTest{12}, + "d": simpleTest{61}, + "e": simpleTest{14}, + } + + if err := MergeWithOverwrite(&m, n); 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 TestMaps(t *testing.T) { + m := map[string]simpleTest{ + "a": simpleTest{}, + "b": simpleTest{42}, + "c": simpleTest{13}, + "d": simpleTest{61}, + } + n := map[string]simpleTest{ + "a": simpleTest{16}, + "b": simpleTest{}, + "c": simpleTest{12}, + "e": simpleTest{14}, + } + expect := map[string]simpleTest{ + "a": simpleTest{0}, + "b": simpleTest{42}, + "c": simpleTest{13}, + "d": simpleTest{61}, + "e": simpleTest{14}, + } + + if err := Merge(&m, n); 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) + } + if m["a"].Value != 0 { + t.Fatalf(`n merged in m because I solved non-addressable map values TODO: m["a"].Value(%d) != n["a"].Value(%d)`, m["a"].Value, n["a"].Value) + } + if m["b"].Value != 42 { + t.Fatalf(`n wrongly merged in m: m["b"].Value(%d) != n["b"].Value(%d)`, m["b"].Value, n["b"].Value) + } + if m["c"].Value != 13 { + t.Fatalf(`n overwritten in m: m["c"].Value(%d) != n["c"].Value(%d)`, m["c"].Value, n["c"].Value) + } +} diff --git a/debian/golang-github-imdario-mergo-dev.debhelper.log b/debian/golang-github-imdario-mergo-dev.debhelper.log new file mode 100644 index 0000000..356eeb9 --- /dev/null +++ b/debian/golang-github-imdario-mergo-dev.debhelper.log @@ -0,0 +1,18 @@ +dh_auto_configure +dh_auto_build +dh_auto_test +dh_prep +dh_auto_install +dh_installdocs +dh_installchangelogs +dh_perl +dh_link +dh_strip_nondeterminism +dh_compress +dh_fixperms +dh_installdeb +dh_golang +dh_gencontrol +dh_md5sums +dh_builddeb +dh_builddeb diff --git a/debian/golang-github-imdario-mergo-dev.substvars b/debian/golang-github-imdario-mergo-dev.substvars new file mode 100644 index 0000000..f519885 --- /dev/null +++ b/debian/golang-github-imdario-mergo-dev.substvars @@ -0,0 +1,3 @@ +misc:Built-Using=golang (= 2:1.4.3-3), +misc:Depends= +misc:Pre-Depends= diff --git a/debian/patches/0001-disable-yaml-tests.patch b/debian/patches/0001-disable-yaml-tests.patch new file mode 100644 index 0000000..ba3867a --- /dev/null +++ b/debian/patches/0001-disable-yaml-tests.patch @@ -0,0 +1,148 @@ +Index: golang-github-imdario-mergo/mergo_test.go +=================================================================== +--- golang-github-imdario-mergo.orig/mergo_test.go ++++ golang-github-imdario-mergo/mergo_test.go +@@ -6,11 +6,8 @@ + package mergo + + import ( +- "io/ioutil" + "reflect" + "testing" +- +- "gopkg.in/yaml.v1" + ) + + type simpleTest struct { +@@ -311,131 +308,3 @@ func TestMaps(t *testing.T) { + t.Fatalf(`n overwritten in m: m["c"].Value(%d) != n["c"].Value(%d)`, m["c"].Value, n["c"].Value) + } + } +- +-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) +- if err := Merge(&license, thing); err != nil { +- t.Fatal(err.Error()) +- } +- currentLength := len(license["fields"].(map[interface{}]interface{})) +- if currentLength != expectedLength { +- t.Fatalf(`thing not merged in license properly, license must have %d elements instead of %d`, expectedLength, currentLength) +- } +- fields := license["fields"].(map[interface{}]interface{}) +- if _, ok := fields["id"]; !ok { +- t.Fatalf(`thing not merged in license properly, license must have a new id field from thing`) +- } +-} +- +-func TestTwoPointerValues(t *testing.T) { +- a := &simpleTest{} +- b := &simpleTest{42} +- if err := Merge(a, b); err != nil { +- t.Fatalf(`Boom. You crossed the streams: %s`, err) +- } +-} +- +-func TestMap(t *testing.T) { +- a := complexTest{} +- a.Id = "athing" +- c := moreComplextText{a, simpleTest{}, simpleTest{}} +- b := map[string]interface{}{ +- "ct": map[string]interface{}{ +- "st": map[string]interface{}{ +- "value": 42, +- }, +- "sz": 1, +- "id": "bthing", +- }, +- "st": &simpleTest{144}, // Mapping a reference +- "zt": simpleTest{299}, // Mapping a missing field (zt doesn't exist) +- "nt": simpleTest{3}, +- } +- if err := Map(&c, b); err != nil { +- t.FailNow() +- } +- m := b["ct"].(map[string]interface{}) +- n := m["st"].(map[string]interface{}) +- o := b["st"].(*simpleTest) +- p := b["nt"].(simpleTest) +- if c.Ct.St.Value != 42 { +- t.Fatalf("b not merged in properly: c.Ct.St.Value(%d) != b.Ct.St.Value(%d)", c.Ct.St.Value, n["value"]) +- } +- if c.St.Value != 144 { +- t.Fatalf("b not merged in properly: c.St.Value(%d) != b.St.Value(%d)", c.St.Value, o.Value) +- } +- if c.Nt.Value != 3 { +- t.Fatalf("b not merged in properly: c.Nt.Value(%d) != b.Nt.Value(%d)", c.St.Value, p.Value) +- } +- if c.Ct.sz == 1 { +- t.Fatalf("a's private field sz not preserved from merge: c.Ct.sz(%d) == b.Ct.sz(%d)", c.Ct.sz, m["sz"]) +- } +- if c.Ct.Id == m["id"] { +- t.Fatalf("a's field Id merged unexpectedly: c.Ct.Id(%s) == b.Ct.Id(%s)", c.Ct.Id, m["id"]) +- } +-} +- +-func TestSimpleMap(t *testing.T) { +- a := simpleTest{} +- b := map[string]interface{}{ +- "value": 42, +- } +- if err := Map(&a, b); err != nil { +- t.FailNow() +- } +- if a.Value != 42 { +- t.Fatalf("b not merged in properly: a.Value(%d) != b.Value(%v)", a.Value, b["value"]) +- } +-} +- +-type pointerMapTest struct { +- A int +- hidden int +- B *simpleTest +-} +- +-func TestBackAndForth(t *testing.T) { +- pt := pointerMapTest{42, 1, &simpleTest{66}} +- m := make(map[string]interface{}) +- if err := Map(&m, pt); err != nil { +- t.FailNow() +- } +- var ( +- v interface{} +- ok bool +- ) +- if v, ok = m["a"]; v.(int) != pt.A || !ok { +- t.Fatalf("pt not merged in properly: m[`a`](%d) != pt.A(%d)", v, pt.A) +- } +- if v, ok = m["b"]; !ok { +- t.Fatalf("pt not merged in properly: B is missing in m") +- } +- var st *simpleTest +- if st = v.(*simpleTest); st.Value != 66 { +- t.Fatalf("something went wrong while mapping pt on m, B wasn't copied") +- } +- bpt := pointerMapTest{} +- if err := Map(&bpt, m); err != nil { +- t.Fatal(err) +- } +- if bpt.A != pt.A { +- t.Fatalf("pt not merged in properly: bpt.A(%d) != pt.A(%d)", bpt.A, pt.A) +- } +- if bpt.hidden == pt.hidden { +- t.Fatalf("pt unexpectedly merged: bpt.hidden(%d) == pt.hidden(%d)", bpt.hidden, pt.hidden) +- } +- if bpt.B.Value != pt.B.Value { +- t.Fatalf("pt not merged in properly: bpt.B.Value(%d) != pt.B.Value(%d)", bpt.B.Value, pt.B.Value) +- } +-} +- +-func loadYAML(path string) (m map[string]interface{}) { +- m = make(map[string]interface{}) +- raw, _ := ioutil.ReadFile(path) +- _ = yaml.Unmarshal(raw, &m) +- return +-} diff --git a/debian/patches/0001-rename-yaml-v1.patch b/debian/patches/0001-rename-yaml-v1.patch new file mode 100644 index 0000000..fe4d371 --- /dev/null +++ b/debian/patches/0001-rename-yaml-v1.patch @@ -0,0 +1,21 @@ +Index: golang-github-imdario-mergo/mergo_test.go +=================================================================== +--- golang-github-imdario-mergo.orig/mergo_test.go ++++ golang-github-imdario-mergo/mergo_test.go +@@ -10,7 +10,7 @@ import ( + "reflect" + "testing" + +- "gopkg.in/yaml.v1" ++ "launchpad.net/goyaml" + ) + + type simpleTest struct { +@@ -436,6 +436,6 @@ func TestBackAndForth(t *testing.T) { + func loadYAML(path string) (m map[string]interface{}) { + m = make(map[string]interface{}) + raw, _ := ioutil.ReadFile(path) +- _ = yaml.Unmarshal(raw, &m) ++ _ = goyaml.Unmarshal(raw, &m) + return + } diff --git a/debian/patches/0001-use-newer-yaml-library.patch b/debian/patches/0001-use-newer-yaml-library.patch new file mode 100644 index 0000000..0815a05 --- /dev/null +++ b/debian/patches/0001-use-newer-yaml-library.patch @@ -0,0 +1,13 @@ +Index: golang-github-imdario-mergo/mergo_test.go +=================================================================== +--- golang-github-imdario-mergo.orig/mergo_test.go ++++ golang-github-imdario-mergo/mergo_test.go +@@ -10,7 +10,7 @@ import ( + "reflect" + "testing" + +- "gopkg.in/yaml.v1" ++ "gopkg.in/yaml.v2" + ) + + type simpleTest struct { diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..dbe51cb --- /dev/null +++ b/debian/patches/series @@ -0,0 +1 @@ +0001-disable-yaml-tests.patch diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..8cce5e0 --- /dev/null +++ b/debian/rules @@ -0,0 +1,4 @@ +#!/usr/bin/make -f + +%: + dh $@ --buildsystem=golang --with=golang diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/mergo_test.go b/mergo_test.go index 877401c..8284397 100644 --- a/mergo_test.go +++ b/mergo_test.go @@ -6,11 +6,8 @@ package mergo import ( - "io/ioutil" "reflect" "testing" - - "gopkg.in/yaml.v1" ) type simpleTest struct { @@ -311,131 +308,3 @@ t.Fatalf(`n overwritten in m: m["c"].Value(%d) != n["c"].Value(%d)`, m["c"].Value, n["c"].Value) } } - -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) - if err := Merge(&license, thing); err != nil { - t.Fatal(err.Error()) - } - currentLength := len(license["fields"].(map[interface{}]interface{})) - if currentLength != expectedLength { - t.Fatalf(`thing not merged in license properly, license must have %d elements instead of %d`, expectedLength, currentLength) - } - fields := license["fields"].(map[interface{}]interface{}) - if _, ok := fields["id"]; !ok { - t.Fatalf(`thing not merged in license properly, license must have a new id field from thing`) - } -} - -func TestTwoPointerValues(t *testing.T) { - a := &simpleTest{} - b := &simpleTest{42} - if err := Merge(a, b); err != nil { - t.Fatalf(`Boom. You crossed the streams: %s`, err) - } -} - -func TestMap(t *testing.T) { - a := complexTest{} - a.Id = "athing" - c := moreComplextText{a, simpleTest{}, simpleTest{}} - b := map[string]interface{}{ - "ct": map[string]interface{}{ - "st": map[string]interface{}{ - "value": 42, - }, - "sz": 1, - "id": "bthing", - }, - "st": &simpleTest{144}, // Mapping a reference - "zt": simpleTest{299}, // Mapping a missing field (zt doesn't exist) - "nt": simpleTest{3}, - } - if err := Map(&c, b); err != nil { - t.FailNow() - } - m := b["ct"].(map[string]interface{}) - n := m["st"].(map[string]interface{}) - o := b["st"].(*simpleTest) - p := b["nt"].(simpleTest) - if c.Ct.St.Value != 42 { - t.Fatalf("b not merged in properly: c.Ct.St.Value(%d) != b.Ct.St.Value(%d)", c.Ct.St.Value, n["value"]) - } - if c.St.Value != 144 { - t.Fatalf("b not merged in properly: c.St.Value(%d) != b.St.Value(%d)", c.St.Value, o.Value) - } - if c.Nt.Value != 3 { - t.Fatalf("b not merged in properly: c.Nt.Value(%d) != b.Nt.Value(%d)", c.St.Value, p.Value) - } - if c.Ct.sz == 1 { - t.Fatalf("a's private field sz not preserved from merge: c.Ct.sz(%d) == b.Ct.sz(%d)", c.Ct.sz, m["sz"]) - } - if c.Ct.Id == m["id"] { - t.Fatalf("a's field Id merged unexpectedly: c.Ct.Id(%s) == b.Ct.Id(%s)", c.Ct.Id, m["id"]) - } -} - -func TestSimpleMap(t *testing.T) { - a := simpleTest{} - b := map[string]interface{}{ - "value": 42, - } - if err := Map(&a, b); err != nil { - t.FailNow() - } - if a.Value != 42 { - t.Fatalf("b not merged in properly: a.Value(%d) != b.Value(%v)", a.Value, b["value"]) - } -} - -type pointerMapTest struct { - A int - hidden int - B *simpleTest -} - -func TestBackAndForth(t *testing.T) { - pt := pointerMapTest{42, 1, &simpleTest{66}} - m := make(map[string]interface{}) - if err := Map(&m, pt); err != nil { - t.FailNow() - } - var ( - v interface{} - ok bool - ) - if v, ok = m["a"]; v.(int) != pt.A || !ok { - t.Fatalf("pt not merged in properly: m[`a`](%d) != pt.A(%d)", v, pt.A) - } - if v, ok = m["b"]; !ok { - t.Fatalf("pt not merged in properly: B is missing in m") - } - var st *simpleTest - if st = v.(*simpleTest); st.Value != 66 { - t.Fatalf("something went wrong while mapping pt on m, B wasn't copied") - } - bpt := pointerMapTest{} - if err := Map(&bpt, m); err != nil { - t.Fatal(err) - } - if bpt.A != pt.A { - t.Fatalf("pt not merged in properly: bpt.A(%d) != pt.A(%d)", bpt.A, pt.A) - } - if bpt.hidden == pt.hidden { - t.Fatalf("pt unexpectedly merged: bpt.hidden(%d) == pt.hidden(%d)", bpt.hidden, pt.hidden) - } - if bpt.B.Value != pt.B.Value { - t.Fatalf("pt not merged in properly: bpt.B.Value(%d) != pt.B.Value(%d)", bpt.B.Value, pt.B.Value) - } -} - -func loadYAML(path string) (m map[string]interface{}) { - m = make(map[string]interface{}) - raw, _ := ioutil.ReadFile(path) - _ = yaml.Unmarshal(raw, &m) - return -}