mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
update github.com/compose-spec/compose-go to v1.2.7
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
9
vendor/github.com/compose-spec/compose-go/dotenv/parser.go
generated
vendored
9
vendor/github.com/compose-spec/compose-go/dotenv/parser.go
generated
vendored
@ -18,6 +18,9 @@ const (
|
||||
|
||||
func parseBytes(src []byte, out map[string]string, lookupFn LookupFn) error {
|
||||
cutset := src
|
||||
if lookupFn == nil {
|
||||
lookupFn = noLookupFn
|
||||
}
|
||||
for {
|
||||
cutset = getStatementStart(cutset)
|
||||
if cutset == nil {
|
||||
@ -34,9 +37,6 @@ func parseBytes(src []byte, out map[string]string, lookupFn LookupFn) error {
|
||||
}
|
||||
|
||||
if inherited {
|
||||
if lookupFn == nil {
|
||||
lookupFn = noLookupFn
|
||||
}
|
||||
|
||||
value, ok := lookupFn(key)
|
||||
if ok {
|
||||
@ -50,6 +50,9 @@ func parseBytes(src []byte, out map[string]string, lookupFn LookupFn) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if lookUpValue, ok := lookupFn(key); ok {
|
||||
value = lookUpValue
|
||||
}
|
||||
|
||||
out[key] = value
|
||||
cutset = left
|
||||
|
5
vendor/github.com/compose-spec/compose-go/loader/full-example.yml
generated
vendored
5
vendor/github.com/compose-spec/compose-go/loader/full-example.yml
generated
vendored
@ -22,6 +22,9 @@ services:
|
||||
uid: '103'
|
||||
gid: '103'
|
||||
mode: 0440
|
||||
tags:
|
||||
- foo:v1.0.0
|
||||
- docker.io/username/foo:my-other-tag
|
||||
|
||||
|
||||
cap_add:
|
||||
@ -402,6 +405,7 @@ configs:
|
||||
external: true
|
||||
config4:
|
||||
name: foo
|
||||
file: ~/config_data
|
||||
x-bar: baz
|
||||
x-foo: bar
|
||||
|
||||
@ -417,6 +421,7 @@ secrets:
|
||||
external: true
|
||||
secret4:
|
||||
name: bar
|
||||
environment: BAR
|
||||
x-bar: baz
|
||||
x-foo: bar
|
||||
x-bar: baz
|
||||
|
47
vendor/github.com/compose-spec/compose-go/loader/loader.go
generated
vendored
47
vendor/github.com/compose-spec/compose-go/loader/loader.go
generated
vendored
@ -24,7 +24,6 @@ import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -70,7 +69,7 @@ type Options struct {
|
||||
}
|
||||
|
||||
func (o *Options) SetProjectName(name string, imperativelySet bool) {
|
||||
o.projectName = normalizeProjectName(name)
|
||||
o.projectName = NormalizeProjectName(name)
|
||||
o.projectNameImperativelySet = imperativelySet
|
||||
}
|
||||
|
||||
@ -209,7 +208,7 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
}
|
||||
|
||||
projectName, projectNameImperativelySet := opts.GetProjectName()
|
||||
model.Name = normalizeProjectName(model.Name)
|
||||
model.Name = NormalizeProjectName(model.Name)
|
||||
if !projectNameImperativelySet && model.Name != "" {
|
||||
projectName = model.Name
|
||||
}
|
||||
@ -246,7 +245,7 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
return project, nil
|
||||
}
|
||||
|
||||
func normalizeProjectName(s string) string {
|
||||
func NormalizeProjectName(s string) string {
|
||||
r := regexp.MustCompile("[a-z0-9_-]")
|
||||
s = strings.ToLower(s)
|
||||
s = strings.Join(r.FindAllString(s, -1), "")
|
||||
@ -385,7 +384,7 @@ func createTransformHook(additionalTransformers ...Transformer) mapstructure.Dec
|
||||
reflect.TypeOf(types.MappingWithEquals{}): transformMappingOrListFunc("=", true),
|
||||
reflect.TypeOf(types.Labels{}): transformMappingOrListFunc("=", false),
|
||||
reflect.TypeOf(types.MappingWithColon{}): transformMappingOrListFunc(":", false),
|
||||
reflect.TypeOf(types.HostsList{}): transformListOrMappingFunc(":", false),
|
||||
reflect.TypeOf(types.HostsList{}): transformMappingOrListFunc(":", false),
|
||||
reflect.TypeOf(types.ServiceVolumeConfig{}): transformServiceVolumeConfig,
|
||||
reflect.TypeOf(types.BuildConfig{}): transformBuildConfig,
|
||||
reflect.TypeOf(types.Duration(0)): transformStringToDuration,
|
||||
@ -571,18 +570,18 @@ func LoadService(name string, serviceDict map[string]interface{}, workingDir str
|
||||
if volume.Type != types.VolumeTypeBind {
|
||||
continue
|
||||
}
|
||||
|
||||
if volume.Source == "" {
|
||||
return nil, errors.New(`invalid mount config for type "bind": field Source must not be empty`)
|
||||
}
|
||||
|
||||
if resolvePaths {
|
||||
serviceConfig.Volumes[i] = resolveVolumePath(volume, workingDir, lookupEnv)
|
||||
if resolvePaths || convertPaths {
|
||||
volume = resolveVolumePath(volume, workingDir, lookupEnv)
|
||||
}
|
||||
|
||||
if convertPaths {
|
||||
serviceConfig.Volumes[i] = convertVolumePath(volume)
|
||||
volume = convertVolumePath(volume)
|
||||
}
|
||||
serviceConfig.Volumes[i] = volume
|
||||
}
|
||||
|
||||
return serviceConfig, nil
|
||||
@ -805,7 +804,7 @@ func loadFileObjectConfig(name string, objType string, obj types.FileObjectConfi
|
||||
return obj, errors.Errorf("%[1]s %[2]s: %[1]s.driver and %[1]s.file conflict; only use %[1]s.driver", objType, name)
|
||||
}
|
||||
default:
|
||||
if resolvePaths {
|
||||
if obj.File != "" && resolvePaths {
|
||||
obj.File = absPath(details.WorkingDir, obj.File)
|
||||
}
|
||||
}
|
||||
@ -1060,22 +1059,6 @@ func transformMappingOrListFunc(sep string, allowNil bool) TransformerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func transformListOrMappingFunc(sep string, allowNil bool) TransformerFunc {
|
||||
return func(data interface{}) (interface{}, error) {
|
||||
return transformListOrMapping(data, sep, allowNil)
|
||||
}
|
||||
}
|
||||
|
||||
func transformListOrMapping(listOrMapping interface{}, sep string, allowNil bool) (interface{}, error) {
|
||||
switch value := listOrMapping.(type) {
|
||||
case map[string]interface{}:
|
||||
return toStringList(value, sep, allowNil), nil
|
||||
case []interface{}:
|
||||
return listOrMapping, nil
|
||||
}
|
||||
return nil, errors.Errorf("expected a map or a list, got %T: %#v", listOrMapping, listOrMapping)
|
||||
}
|
||||
|
||||
func transformMappingOrList(mappingOrList interface{}, sep string, allowNil bool) (interface{}, error) {
|
||||
switch value := mappingOrList.(type) {
|
||||
case map[string]interface{}:
|
||||
@ -1168,15 +1151,3 @@ func toString(value interface{}, allowNil bool) interface{} {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func toStringList(value map[string]interface{}, separator string, allowNil bool) []string {
|
||||
var output []string
|
||||
for key, value := range value {
|
||||
if value == nil && !allowNil {
|
||||
continue
|
||||
}
|
||||
output = append(output, fmt.Sprintf("%s%s%s", key, separator, value))
|
||||
}
|
||||
sort.Strings(output)
|
||||
return output
|
||||
}
|
||||
|
10
vendor/github.com/compose-spec/compose-go/loader/validate.go
generated
vendored
10
vendor/github.com/compose-spec/compose-go/loader/validate.go
generated
vendored
@ -68,5 +68,15 @@ func checkConsistency(project *types.Project) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for name, secret := range project.Secrets {
|
||||
if secret.External.External {
|
||||
continue
|
||||
}
|
||||
if secret.File == "" && secret.Environment == "" {
|
||||
return errors.Wrap(errdefs.ErrInvalid, fmt.Sprintf("secret %q must declare either `file` or `environment`", name))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
4
vendor/github.com/compose-spec/compose-go/schema/compose-spec.json
generated
vendored
4
vendor/github.com/compose-spec/compose-go/schema/compose-spec.json
generated
vendored
@ -102,7 +102,8 @@
|
||||
"shm_size": {"type": ["integer", "string"]},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"isolation": {"type": "string"},
|
||||
"secrets": {"$ref": "#/definitions/service_config_or_secret"}
|
||||
"secrets": {"$ref": "#/definitions/service_config_or_secret"},
|
||||
"tags": {"type": "array", "items": {"type": "string"}}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
@ -684,6 +685,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"environment": {"type": "string"},
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
|
23
vendor/github.com/compose-spec/compose-go/types/config.go
generated
vendored
23
vendor/github.com/compose-spec/compose-go/types/config.go
generated
vendored
@ -18,10 +18,17 @@ package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
var (
|
||||
// isCaseInsensitiveEnvVars is true on platforms where environment variable names are treated case-insensitively.
|
||||
isCaseInsensitiveEnvVars = (runtime.GOOS == "windows")
|
||||
)
|
||||
|
||||
// ConfigDetails are the details about a group of ConfigFiles
|
||||
type ConfigDetails struct {
|
||||
Version string
|
||||
@ -33,7 +40,21 @@ type ConfigDetails struct {
|
||||
// LookupEnv provides a lookup function for environment variables
|
||||
func (cd ConfigDetails) LookupEnv(key string) (string, bool) {
|
||||
v, ok := cd.Environment[key]
|
||||
return v, ok
|
||||
if !isCaseInsensitiveEnvVars || ok {
|
||||
return v, ok
|
||||
}
|
||||
// variable names must be treated case-insensitively on some platforms (that is, Windows).
|
||||
// Resolves in this way:
|
||||
// * Return the value if its name matches with the passed name case-sensitively.
|
||||
// * Otherwise, return the value if its lower-cased name matches lower-cased passed name.
|
||||
// * The value is indefinite if multiple variables match.
|
||||
lowerKey := strings.ToLower(key)
|
||||
for k, v := range cd.Environment {
|
||||
if strings.ToLower(k) == lowerKey {
|
||||
return v, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// ConfigFile is a filename and the contents of the file as a Dict
|
||||
|
13
vendor/github.com/compose-spec/compose-go/types/types.go
generated
vendored
13
vendor/github.com/compose-spec/compose-go/types/types.go
generated
vendored
@ -305,6 +305,7 @@ type BuildConfig struct {
|
||||
Network string `yaml:",omitempty" json:"network,omitempty"`
|
||||
Target string `yaml:",omitempty" json:"target,omitempty"`
|
||||
Secrets []ServiceSecretConfig `yaml:",omitempty" json:"secrets,omitempty"`
|
||||
Tags StringList `mapstructure:"tags" yaml:"tags,omitempty" json:"tags,omitempty"`
|
||||
|
||||
Extensions map[string]interface{} `yaml:",inline" json:"-"`
|
||||
}
|
||||
@ -468,7 +469,16 @@ func (s SSHKey) MarshalJSON() ([]byte, error) {
|
||||
type MappingWithColon map[string]string
|
||||
|
||||
// HostsList is a list of colon-separated host-ip mappings
|
||||
type HostsList []string
|
||||
type HostsList map[string]string
|
||||
|
||||
// AsList return host-ip mappings as a list of colon-separated strings
|
||||
func (h HostsList) AsList() []string {
|
||||
l := make([]string, 0, len(h))
|
||||
for k, v := range h {
|
||||
l = append(l, fmt.Sprintf("%s:%s", k, v))
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// LoggingConfig the logging configuration for a service
|
||||
type LoggingConfig struct {
|
||||
@ -881,6 +891,7 @@ type CredentialSpecConfig struct {
|
||||
type FileObjectConfig struct {
|
||||
Name string `yaml:",omitempty" json:"name,omitempty"`
|
||||
File string `yaml:",omitempty" json:"file,omitempty"`
|
||||
Environment string `yaml:",omitempty" json:"environment,omitempty"`
|
||||
External External `yaml:",omitempty" json:"external,omitempty"`
|
||||
Labels Labels `yaml:",omitempty" json:"labels,omitempty"`
|
||||
Driver string `yaml:",omitempty" json:"driver,omitempty"`
|
||||
|
32
vendor/github.com/imdario/mergo/README.md
generated
vendored
32
vendor/github.com/imdario/mergo/README.md
generated
vendored
@ -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>
|
||||
[](https://beerpay.io/imdario/mergo)
|
||||
[](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
|
||||
|
||||
[](https://sourcerer.io/fame/imdario/imdario/mergo/links/0)
|
||||
[](https://sourcerer.io/fame/imdario/imdario/mergo/links/1)
|
||||
[](https://sourcerer.io/fame/imdario/imdario/mergo/links/2)
|
||||
[](https://sourcerer.io/fame/imdario/imdario/mergo/links/3)
|
||||
[](https://sourcerer.io/fame/imdario/imdario/mergo/links/4)
|
||||
[](https://sourcerer.io/fame/imdario/imdario/mergo/links/5)
|
||||
[](https://sourcerer.io/fame/imdario/imdario/mergo/links/6)
|
||||
[](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
vendor/github.com/imdario/mergo/merge.go
generated
vendored
2
vendor/github.com/imdario/mergo/merge.go
generated
vendored
@ -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
vendor/github.com/imdario/mergo/mergo.go
generated
vendored
4
vendor/github.com/imdario/mergo/mergo.go
generated
vendored
@ -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
|
||||
}
|
||||
|
13
vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
generated
vendored
13
vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
generated
vendored
@ -1,3 +1,16 @@
|
||||
## 1.5.0
|
||||
|
||||
* New option `IgnoreUntaggedFields` to ignore decoding to any fields
|
||||
without `mapstructure` (or the configured tag name) set [GH-277]
|
||||
* New option `ErrorUnset` which makes it an error if any fields
|
||||
in a target struct are not set by the decoding process. [GH-225]
|
||||
* New function `OrComposeDecodeHookFunc` to help compose decode hooks. [GH-240]
|
||||
* Decoding to slice from array no longer crashes [GH-265]
|
||||
* Decode nested struct pointers to map [GH-271]
|
||||
* Fix issue where `,squash` was ignored if `Squash` option was set. [GH-280]
|
||||
* Fix issue where fields with `,omitempty` would sometimes decode
|
||||
into a map with an empty string key [GH-281]
|
||||
|
||||
## 1.4.3
|
||||
|
||||
* Fix cases where `json.Number` didn't decode properly [GH-261]
|
||||
|
22
vendor/github.com/mitchellh/mapstructure/decode_hooks.go
generated
vendored
22
vendor/github.com/mitchellh/mapstructure/decode_hooks.go
generated
vendored
@ -77,6 +77,28 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
|
||||
// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
|
||||
func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
|
||||
return func(a, b reflect.Value) (interface{}, error) {
|
||||
var allErrs string
|
||||
var out interface{}
|
||||
var err error
|
||||
|
||||
for _, f := range ff {
|
||||
out, err = DecodeHookExec(f, a, b)
|
||||
if err != nil {
|
||||
allErrs += err.Error() + "\n"
|
||||
continue
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
return nil, errors.New(allErrs)
|
||||
}
|
||||
}
|
||||
|
||||
// StringToSliceHookFunc returns a DecodeHookFunc that converts
|
||||
// string to []string by splitting on the given sep.
|
||||
func StringToSliceHookFunc(sep string) DecodeHookFunc {
|
||||
|
83
vendor/github.com/mitchellh/mapstructure/mapstructure.go
generated
vendored
83
vendor/github.com/mitchellh/mapstructure/mapstructure.go
generated
vendored
@ -122,7 +122,7 @@
|
||||
// field value is zero and a numeric type, the field is empty, and it won't
|
||||
// be encoded into the destination type.
|
||||
//
|
||||
// type Source {
|
||||
// type Source struct {
|
||||
// Age int `mapstructure:",omitempty"`
|
||||
// }
|
||||
//
|
||||
@ -215,6 +215,12 @@ type DecoderConfig struct {
|
||||
// (extra keys).
|
||||
ErrorUnused bool
|
||||
|
||||
// If ErrorUnset is true, then it is an error for there to exist
|
||||
// fields in the result that were not set in the decoding process
|
||||
// (extra fields). This only applies to decoding to a struct. This
|
||||
// will affect all nested structs as well.
|
||||
ErrorUnset bool
|
||||
|
||||
// ZeroFields, if set to true, will zero fields before writing them.
|
||||
// For example, a map will be emptied before decoded values are put in
|
||||
// it. If this is false, a map will be merged.
|
||||
@ -259,6 +265,10 @@ type DecoderConfig struct {
|
||||
// defaults to "mapstructure"
|
||||
TagName string
|
||||
|
||||
// IgnoreUntaggedFields ignores all struct fields without explicit
|
||||
// TagName, comparable to `mapstructure:"-"` as default behaviour.
|
||||
IgnoreUntaggedFields bool
|
||||
|
||||
// MatchName is the function used to match the map key to the struct
|
||||
// field name or tag. Defaults to `strings.EqualFold`. This can be used
|
||||
// to implement case-sensitive tag values, support snake casing, etc.
|
||||
@ -284,6 +294,11 @@ type Metadata struct {
|
||||
// Unused is a slice of keys that were found in the raw value but
|
||||
// weren't decoded since there was no matching field in the result interface
|
||||
Unused []string
|
||||
|
||||
// Unset is a slice of field names that were found in the result interface
|
||||
// but weren't set in the decoding process since there was no matching value
|
||||
// in the input
|
||||
Unset []string
|
||||
}
|
||||
|
||||
// Decode takes an input structure and uses reflection to translate it to
|
||||
@ -375,6 +390,10 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
|
||||
if config.Metadata.Unused == nil {
|
||||
config.Metadata.Unused = make([]string, 0)
|
||||
}
|
||||
|
||||
if config.Metadata.Unset == nil {
|
||||
config.Metadata.Unset = make([]string, 0)
|
||||
}
|
||||
}
|
||||
|
||||
if config.TagName == "" {
|
||||
@ -906,9 +925,15 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
|
||||
tagValue := f.Tag.Get(d.config.TagName)
|
||||
keyName := f.Name
|
||||
|
||||
if tagValue == "" && d.config.IgnoreUntaggedFields {
|
||||
continue
|
||||
}
|
||||
|
||||
// If Squash is set in the config, we squash the field down.
|
||||
squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous
|
||||
|
||||
v = dereferencePtrToStructIfNeeded(v, d.config.TagName)
|
||||
|
||||
// Determine the name of the key in the map
|
||||
if index := strings.Index(tagValue, ","); index != -1 {
|
||||
if tagValue[:index] == "-" {
|
||||
@ -920,7 +945,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
|
||||
}
|
||||
|
||||
// If "squash" is specified in the tag, we squash the field down.
|
||||
squash = !squash && strings.Index(tagValue[index+1:], "squash") != -1
|
||||
squash = squash || strings.Index(tagValue[index+1:], "squash") != -1
|
||||
if squash {
|
||||
// When squashing, the embedded type can be a pointer to a struct.
|
||||
if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
|
||||
@ -932,7 +957,9 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
|
||||
return fmt.Errorf("cannot squash non-struct type '%s'", v.Type())
|
||||
}
|
||||
}
|
||||
keyName = tagValue[:index]
|
||||
if keyNameTagValue := tagValue[:index]; keyNameTagValue != "" {
|
||||
keyName = keyNameTagValue
|
||||
}
|
||||
} else if len(tagValue) > 0 {
|
||||
if tagValue == "-" {
|
||||
continue
|
||||
@ -1088,7 +1115,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
|
||||
}
|
||||
|
||||
// If the input value is nil, then don't allocate since empty != nil
|
||||
if dataVal.IsNil() {
|
||||
if dataValKind != reflect.Array && dataVal.IsNil() {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1250,6 +1277,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
|
||||
dataValKeysUnused[dataValKey.Interface()] = struct{}{}
|
||||
}
|
||||
|
||||
targetValKeysUnused := make(map[interface{}]struct{})
|
||||
errors := make([]string, 0)
|
||||
|
||||
// This slice will keep track of all the structs we'll be decoding.
|
||||
@ -1354,7 +1382,8 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
|
||||
|
||||
if !rawMapVal.IsValid() {
|
||||
// There was no matching key in the map for the value in
|
||||
// the struct. Just ignore.
|
||||
// the struct. Remember it for potential errors and metadata.
|
||||
targetValKeysUnused[fieldName] = struct{}{}
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -1414,6 +1443,17 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
|
||||
errors = appendErrors(errors, err)
|
||||
}
|
||||
|
||||
if d.config.ErrorUnset && len(targetValKeysUnused) > 0 {
|
||||
keys := make([]string, 0, len(targetValKeysUnused))
|
||||
for rawKey := range targetValKeysUnused {
|
||||
keys = append(keys, rawKey.(string))
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", "))
|
||||
errors = appendErrors(errors, err)
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return &Error{errors}
|
||||
}
|
||||
@ -1428,6 +1468,14 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
|
||||
|
||||
d.config.Metadata.Unused = append(d.config.Metadata.Unused, key)
|
||||
}
|
||||
for rawKey := range targetValKeysUnused {
|
||||
key := rawKey.(string)
|
||||
if name != "" {
|
||||
key = name + "." + key
|
||||
}
|
||||
|
||||
d.config.Metadata.Unset = append(d.config.Metadata.Unset, key)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -1465,3 +1513,28 @@ func getKind(val reflect.Value) reflect.Kind {
|
||||
return kind
|
||||
}
|
||||
}
|
||||
|
||||
func isStructTypeConvertibleToMap(typ reflect.Type, checkMapstructureTags bool, tagName string) bool {
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
f := typ.Field(i)
|
||||
if f.PkgPath == "" && !checkMapstructureTags { // check for unexported fields
|
||||
return true
|
||||
}
|
||||
if checkMapstructureTags && f.Tag.Get(tagName) != "" { // check for mapstructure tags inside
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func dereferencePtrToStructIfNeeded(v reflect.Value, tagName string) reflect.Value {
|
||||
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
|
||||
return v
|
||||
}
|
||||
deref := v.Elem()
|
||||
derefT := deref.Type()
|
||||
if isStructTypeConvertibleToMap(derefT, true, tagName) {
|
||||
return deref
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
Reference in New Issue
Block a user