pkg/util/mergemap/mergemap.go
/*Copyright (c) 2013, Peter Bourgon, SoundCloud Ltd.All rights reserved. Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, thislist of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, thislist of conditions and the following disclaimer in the documentation and/orother materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ANDANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIEDWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.package mergemap*/package mergemap import ( "reflect" herrors "github.com/horizoncd/horizon/core/errors" perror "github.com/horizoncd/horizon/pkg/errors") var ( DefaultMaxDepth = 32) // Merge recursively merges the src and dst maps. Key conflicts are resolved by// preferring src, or recursively descending, if both src and dst are maps.func Merge(dst, src map[string]interface{}) (map[string]interface{}, error) { return merge(dst, src, 0)} // Merge recursively merges the src and dst maps. Key conflicts are resolved by// preferring src, or recursively descending, if both src and dst are maps.func merge(dst, src map[string]interface{}, depth int) (map[string]interface{}, error) { var err error if depth > DefaultMaxDepth { return nil, perror.Wrap(herrors.ErrParamInvalid, "") } for key, srcVal := range src { if dstVal, ok := dst[key]; ok { srcMap, srcMapOk := mapify(srcVal) dstMap, dstMapOk := mapify(dstVal) if srcMapOk && dstMapOk { srcVal, err = merge(dstMap, srcMap, depth+1) if err != nil { return nil, err } } } dst[key] = srcVal } return dst, nil} func mapify(i interface{}) (map[string]interface{}, bool) { value := reflect.ValueOf(i) if value.Kind() == reflect.Map { m := map[string]interface{}{} for _, k := range value.MapKeys() { m[k.String()] = value.MapIndex(k).Interface() } return m, true } return map[string]interface{}{}, false}