mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-19 01:47:43 +08:00
bump compose-go to version v2.1.3
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
This commit is contained in:
parent
9b100c2552
commit
689fd74104
4
go.mod
4
go.mod
@ -6,7 +6,7 @@ require (
|
|||||||
github.com/Masterminds/semver/v3 v3.2.1
|
github.com/Masterminds/semver/v3 v3.2.1
|
||||||
github.com/Microsoft/go-winio v0.6.2
|
github.com/Microsoft/go-winio v0.6.2
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.26.6
|
github.com/aws/aws-sdk-go-v2/config v1.26.6
|
||||||
github.com/compose-spec/compose-go/v2 v2.1.2
|
github.com/compose-spec/compose-go/v2 v2.1.3
|
||||||
github.com/containerd/console v1.0.4
|
github.com/containerd/console v1.0.4
|
||||||
github.com/containerd/containerd v1.7.18
|
github.com/containerd/containerd v1.7.18
|
||||||
github.com/containerd/continuity v0.4.3
|
github.com/containerd/continuity v0.4.3
|
||||||
@ -117,10 +117,8 @@ require (
|
|||||||
github.com/mattn/go-shellwords v1.0.12 // indirect
|
github.com/mattn/go-shellwords v1.0.12 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
|
||||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
|
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
|
||||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||||
github.com/moby/locker v1.0.1 // indirect
|
github.com/moby/locker v1.0.1 // indirect
|
||||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||||
|
8
go.sum
8
go.sum
@ -84,8 +84,8 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+g
|
|||||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
|
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
|
||||||
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
|
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
|
||||||
github.com/compose-spec/compose-go/v2 v2.1.2 h1:N2XmNYg5jHNBaU+4/zSAe2UrZLq7Kkp1eSsOHfAHbxQ=
|
github.com/compose-spec/compose-go/v2 v2.1.3 h1:bD67uqLuL/XgkAK6ir3xZvNLFPxPScEi1KW7R5esrLE=
|
||||||
github.com/compose-spec/compose-go/v2 v2.1.2/go.mod h1:NJGRGazJfh0tD7d13h66KDVvyOHK49Wil2CIhoffiD0=
|
github.com/compose-spec/compose-go/v2 v2.1.3/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc=
|
||||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
||||||
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
||||||
@ -292,16 +292,12 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfr
|
|||||||
github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||||
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
||||||
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
|
||||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
|
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
|
||||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
|
||||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
|
||||||
github.com/moby/buildkit v0.14.1 h1:2epLCZTkn4CikdImtsLtIa++7DzCimrrZCT1sway+oI=
|
github.com/moby/buildkit v0.14.1 h1:2epLCZTkn4CikdImtsLtIa++7DzCimrrZCT1sway+oI=
|
||||||
github.com/moby/buildkit v0.14.1/go.mod h1:1XssG7cAqv5Bz1xcGMxJL123iCv5TYN4Z/qf647gfuk=
|
github.com/moby/buildkit v0.14.1/go.mod h1:1XssG7cAqv5Bz1xcGMxJL123iCv5TYN4Z/qf647gfuk=
|
||||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||||
|
8
vendor/github.com/compose-spec/compose-go/v2/types/config.go
generated
vendored
8
vendor/github.com/compose-spec/compose-go/v2/types/config.go
generated
vendored
@ -100,7 +100,13 @@ type Secrets map[string]SecretConfig
|
|||||||
type Configs map[string]ConfigObjConfig
|
type Configs map[string]ConfigObjConfig
|
||||||
|
|
||||||
// Extensions is a map of custom extension
|
// Extensions is a map of custom extension
|
||||||
type Extensions map[string]interface{}
|
type Extensions map[string]any
|
||||||
|
|
||||||
|
func (e Extensions) DeepCopy(t Extensions) {
|
||||||
|
for k, v := range e {
|
||||||
|
t[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalJSON makes Config implement json.Marshaler
|
// MarshalJSON makes Config implement json.Marshaler
|
||||||
func (c Config) MarshalJSON() ([]byte, error) {
|
func (c Config) MarshalJSON() ([]byte, error) {
|
||||||
|
2067
vendor/github.com/compose-spec/compose-go/v2/types/derived.gen.go
generated
vendored
Normal file
2067
vendor/github.com/compose-spec/compose-go/v2/types/derived.gen.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11
vendor/github.com/compose-spec/compose-go/v2/types/project.go
generated
vendored
11
vendor/github.com/compose-spec/compose-go/v2/types/project.go
generated
vendored
@ -29,7 +29,6 @@ import (
|
|||||||
"github.com/compose-spec/compose-go/v2/errdefs"
|
"github.com/compose-spec/compose-go/v2/errdefs"
|
||||||
"github.com/compose-spec/compose-go/v2/utils"
|
"github.com/compose-spec/compose-go/v2/utils"
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
"github.com/mitchellh/copystructure"
|
|
||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/maps"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
@ -646,11 +645,13 @@ func (p Project) WithServicesEnvironmentResolved(discardEnvFiles bool) (*Project
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Project) deepCopy() *Project {
|
func (p *Project) deepCopy() *Project {
|
||||||
instance, err := copystructure.Copy(p)
|
if p == nil {
|
||||||
if err != nil {
|
return nil
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
return instance.(*Project)
|
n := &Project{}
|
||||||
|
deriveDeepCopyProject(n, p)
|
||||||
|
return n
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithServicesTransform applies a transformation to project services and return a new project with transformation results
|
// WithServicesTransform applies a transformation to project services and return a new project with transformation results
|
||||||
|
14
vendor/github.com/compose-spec/compose-go/v2/types/types.go
generated
vendored
14
vendor/github.com/compose-spec/compose-go/v2/types/types.go
generated
vendored
@ -24,7 +24,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
"github.com/mitchellh/copystructure"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServiceConfig is the configuration of one service
|
// ServiceConfig is the configuration of one service
|
||||||
@ -194,11 +193,12 @@ func (s *ServiceConfig) SetScale(scale int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServiceConfig) deepCopy() *ServiceConfig {
|
func (s *ServiceConfig) deepCopy() *ServiceConfig {
|
||||||
instance, err := copystructure.Copy(s)
|
if s == nil {
|
||||||
if err != nil {
|
return nil
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
return instance.(*ServiceConfig)
|
n := &ServiceConfig{}
|
||||||
|
deriveDeepCopyService(n, s)
|
||||||
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -698,7 +698,7 @@ type NetworkConfig struct {
|
|||||||
Internal bool `yaml:"internal,omitempty" json:"internal,omitempty"`
|
Internal bool `yaml:"internal,omitempty" json:"internal,omitempty"`
|
||||||
Attachable bool `yaml:"attachable,omitempty" json:"attachable,omitempty"`
|
Attachable bool `yaml:"attachable,omitempty" json:"attachable,omitempty"`
|
||||||
Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"`
|
Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"`
|
||||||
EnableIPv6 bool `yaml:"enable_ipv6,omitempty" json:"enable_ipv6,omitempty"`
|
EnableIPv6 *bool `yaml:"enable_ipv6,omitempty" json:"enable_ipv6,omitempty"`
|
||||||
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
|
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,7 +715,7 @@ type IPAMPool struct {
|
|||||||
Gateway string `yaml:"gateway,omitempty" json:"gateway,omitempty"`
|
Gateway string `yaml:"gateway,omitempty" json:"gateway,omitempty"`
|
||||||
IPRange string `yaml:"ip_range,omitempty" json:"ip_range,omitempty"`
|
IPRange string `yaml:"ip_range,omitempty" json:"ip_range,omitempty"`
|
||||||
AuxiliaryAddresses Mapping `yaml:"aux_addresses,omitempty" json:"aux_addresses,omitempty"`
|
AuxiliaryAddresses Mapping `yaml:"aux_addresses,omitempty" json:"aux_addresses,omitempty"`
|
||||||
Extensions map[string]interface{} `yaml:",inline" json:"-"`
|
Extensions Extensions `yaml:",inline" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// VolumeConfig for a volume
|
// VolumeConfig for a volume
|
||||||
|
21
vendor/github.com/mitchellh/copystructure/LICENSE
generated
vendored
21
vendor/github.com/mitchellh/copystructure/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014 Mitchell Hashimoto
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
21
vendor/github.com/mitchellh/copystructure/README.md
generated
vendored
21
vendor/github.com/mitchellh/copystructure/README.md
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
# copystructure
|
|
||||||
|
|
||||||
copystructure is a Go library for deep copying values in Go.
|
|
||||||
|
|
||||||
This allows you to copy Go values that may contain reference values
|
|
||||||
such as maps, slices, or pointers, and copy their data as well instead
|
|
||||||
of just their references.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
Standard `go get`:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ go get github.com/mitchellh/copystructure
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage & Example
|
|
||||||
|
|
||||||
For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/copystructure).
|
|
||||||
|
|
||||||
The `Copy` function has examples associated with it there.
|
|
15
vendor/github.com/mitchellh/copystructure/copier_time.go
generated
vendored
15
vendor/github.com/mitchellh/copystructure/copier_time.go
generated
vendored
@ -1,15 +0,0 @@
|
|||||||
package copystructure
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
Copiers[reflect.TypeOf(time.Time{})] = timeCopier
|
|
||||||
}
|
|
||||||
|
|
||||||
func timeCopier(v interface{}) (interface{}, error) {
|
|
||||||
// Just... copy it.
|
|
||||||
return v.(time.Time), nil
|
|
||||||
}
|
|
631
vendor/github.com/mitchellh/copystructure/copystructure.go
generated
vendored
631
vendor/github.com/mitchellh/copystructure/copystructure.go
generated
vendored
@ -1,631 +0,0 @@
|
|||||||
package copystructure
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"reflect"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/mitchellh/reflectwalk"
|
|
||||||
)
|
|
||||||
|
|
||||||
const tagKey = "copy"
|
|
||||||
|
|
||||||
// Copy returns a deep copy of v.
|
|
||||||
//
|
|
||||||
// Copy is unable to copy unexported fields in a struct (lowercase field names).
|
|
||||||
// Unexported fields can't be reflected by the Go runtime and therefore
|
|
||||||
// copystructure can't perform any data copies.
|
|
||||||
//
|
|
||||||
// For structs, copy behavior can be controlled with struct tags. For example:
|
|
||||||
//
|
|
||||||
// struct {
|
|
||||||
// Name string
|
|
||||||
// Data *bytes.Buffer `copy:"shallow"`
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// The available tag values are:
|
|
||||||
//
|
|
||||||
// * "ignore" - The field will be ignored, effectively resulting in it being
|
|
||||||
// assigned the zero value in the copy.
|
|
||||||
//
|
|
||||||
// * "shallow" - The field will be be shallow copied. This means that references
|
|
||||||
// values such as pointers, maps, slices, etc. will be directly assigned
|
|
||||||
// versus deep copied.
|
|
||||||
//
|
|
||||||
func Copy(v interface{}) (interface{}, error) {
|
|
||||||
return Config{}.Copy(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CopierFunc is a function that knows how to deep copy a specific type.
|
|
||||||
// Register these globally with the Copiers variable.
|
|
||||||
type CopierFunc func(interface{}) (interface{}, error)
|
|
||||||
|
|
||||||
// Copiers is a map of types that behave specially when they are copied.
|
|
||||||
// If a type is found in this map while deep copying, this function
|
|
||||||
// will be called to copy it instead of attempting to copy all fields.
|
|
||||||
//
|
|
||||||
// The key should be the type, obtained using: reflect.TypeOf(value with type).
|
|
||||||
//
|
|
||||||
// It is unsafe to write to this map after Copies have started. If you
|
|
||||||
// are writing to this map while also copying, wrap all modifications to
|
|
||||||
// this map as well as to Copy in a mutex.
|
|
||||||
var Copiers map[reflect.Type]CopierFunc = make(map[reflect.Type]CopierFunc)
|
|
||||||
|
|
||||||
// ShallowCopiers is a map of pointer types that behave specially
|
|
||||||
// when they are copied. If a type is found in this map while deep
|
|
||||||
// copying, the pointer value will be shallow copied and not walked
|
|
||||||
// into.
|
|
||||||
//
|
|
||||||
// The key should be the type, obtained using: reflect.TypeOf(value
|
|
||||||
// with type).
|
|
||||||
//
|
|
||||||
// It is unsafe to write to this map after Copies have started. If you
|
|
||||||
// are writing to this map while also copying, wrap all modifications to
|
|
||||||
// this map as well as to Copy in a mutex.
|
|
||||||
var ShallowCopiers map[reflect.Type]struct{} = make(map[reflect.Type]struct{})
|
|
||||||
|
|
||||||
// Must is a helper that wraps a call to a function returning
|
|
||||||
// (interface{}, error) and panics if the error is non-nil. It is intended
|
|
||||||
// for use in variable initializations and should only be used when a copy
|
|
||||||
// error should be a crashing case.
|
|
||||||
func Must(v interface{}, err error) interface{} {
|
|
||||||
if err != nil {
|
|
||||||
panic("copy error: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
var errPointerRequired = errors.New("Copy argument must be a pointer when Lock is true")
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
// Lock any types that are a sync.Locker and are not a mutex while copying.
|
|
||||||
// If there is an RLocker method, use that to get the sync.Locker.
|
|
||||||
Lock bool
|
|
||||||
|
|
||||||
// Copiers is a map of types associated with a CopierFunc. Use the global
|
|
||||||
// Copiers map if this is nil.
|
|
||||||
Copiers map[reflect.Type]CopierFunc
|
|
||||||
|
|
||||||
// ShallowCopiers is a map of pointer types that when they are
|
|
||||||
// shallow copied no matter where they are encountered. Use the
|
|
||||||
// global ShallowCopiers if this is nil.
|
|
||||||
ShallowCopiers map[reflect.Type]struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c Config) Copy(v interface{}) (interface{}, error) {
|
|
||||||
if c.Lock && reflect.ValueOf(v).Kind() != reflect.Ptr {
|
|
||||||
return nil, errPointerRequired
|
|
||||||
}
|
|
||||||
|
|
||||||
w := new(walker)
|
|
||||||
if c.Lock {
|
|
||||||
w.useLocks = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Copiers == nil {
|
|
||||||
c.Copiers = Copiers
|
|
||||||
}
|
|
||||||
w.copiers = c.Copiers
|
|
||||||
|
|
||||||
if c.ShallowCopiers == nil {
|
|
||||||
c.ShallowCopiers = ShallowCopiers
|
|
||||||
}
|
|
||||||
w.shallowCopiers = c.ShallowCopiers
|
|
||||||
|
|
||||||
err := reflectwalk.Walk(v, w)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the result. If the result is nil, then we want to turn it
|
|
||||||
// into a typed nil if we can.
|
|
||||||
result := w.Result
|
|
||||||
if result == nil {
|
|
||||||
val := reflect.ValueOf(v)
|
|
||||||
result = reflect.Indirect(reflect.New(val.Type())).Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the key used to index interfaces types we've seen. Store the number
|
|
||||||
// of pointers in the upper 32bits, and the depth in the lower 32bits. This is
|
|
||||||
// easy to calculate, easy to match a key with our current depth, and we don't
|
|
||||||
// need to deal with initializing and cleaning up nested maps or slices.
|
|
||||||
func ifaceKey(pointers, depth int) uint64 {
|
|
||||||
return uint64(pointers)<<32 | uint64(depth)
|
|
||||||
}
|
|
||||||
|
|
||||||
type walker struct {
|
|
||||||
Result interface{}
|
|
||||||
|
|
||||||
copiers map[reflect.Type]CopierFunc
|
|
||||||
shallowCopiers map[reflect.Type]struct{}
|
|
||||||
depth int
|
|
||||||
ignoreDepth int
|
|
||||||
vals []reflect.Value
|
|
||||||
cs []reflect.Value
|
|
||||||
|
|
||||||
// This stores the number of pointers we've walked over, indexed by depth.
|
|
||||||
ps []int
|
|
||||||
|
|
||||||
// If an interface is indirected by a pointer, we need to know the type of
|
|
||||||
// interface to create when creating the new value. Store the interface
|
|
||||||
// types here, indexed by both the walk depth and the number of pointers
|
|
||||||
// already seen at that depth. Use ifaceKey to calculate the proper uint64
|
|
||||||
// value.
|
|
||||||
ifaceTypes map[uint64]reflect.Type
|
|
||||||
|
|
||||||
// any locks we've taken, indexed by depth
|
|
||||||
locks []sync.Locker
|
|
||||||
// take locks while walking the structure
|
|
||||||
useLocks bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) Enter(l reflectwalk.Location) error {
|
|
||||||
w.depth++
|
|
||||||
|
|
||||||
// ensure we have enough elements to index via w.depth
|
|
||||||
for w.depth >= len(w.locks) {
|
|
||||||
w.locks = append(w.locks, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
for len(w.ps) < w.depth+1 {
|
|
||||||
w.ps = append(w.ps, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) Exit(l reflectwalk.Location) error {
|
|
||||||
locker := w.locks[w.depth]
|
|
||||||
w.locks[w.depth] = nil
|
|
||||||
if locker != nil {
|
|
||||||
defer locker.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear out pointers and interfaces as we exit the stack
|
|
||||||
w.ps[w.depth] = 0
|
|
||||||
|
|
||||||
for k := range w.ifaceTypes {
|
|
||||||
mask := uint64(^uint32(0))
|
|
||||||
if k&mask == uint64(w.depth) {
|
|
||||||
delete(w.ifaceTypes, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
w.depth--
|
|
||||||
if w.ignoreDepth > w.depth {
|
|
||||||
w.ignoreDepth = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if w.ignoring() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch l {
|
|
||||||
case reflectwalk.Array:
|
|
||||||
fallthrough
|
|
||||||
case reflectwalk.Map:
|
|
||||||
fallthrough
|
|
||||||
case reflectwalk.Slice:
|
|
||||||
w.replacePointerMaybe()
|
|
||||||
|
|
||||||
// Pop map off our container
|
|
||||||
w.cs = w.cs[:len(w.cs)-1]
|
|
||||||
case reflectwalk.MapValue:
|
|
||||||
// Pop off the key and value
|
|
||||||
mv := w.valPop()
|
|
||||||
mk := w.valPop()
|
|
||||||
m := w.cs[len(w.cs)-1]
|
|
||||||
|
|
||||||
// If mv is the zero value, SetMapIndex deletes the key form the map,
|
|
||||||
// or in this case never adds it. We need to create a properly typed
|
|
||||||
// zero value so that this key can be set.
|
|
||||||
if !mv.IsValid() {
|
|
||||||
mv = reflect.Zero(m.Elem().Type().Elem())
|
|
||||||
}
|
|
||||||
m.Elem().SetMapIndex(mk, mv)
|
|
||||||
case reflectwalk.ArrayElem:
|
|
||||||
// Pop off the value and the index and set it on the array
|
|
||||||
v := w.valPop()
|
|
||||||
i := w.valPop().Interface().(int)
|
|
||||||
if v.IsValid() {
|
|
||||||
a := w.cs[len(w.cs)-1]
|
|
||||||
ae := a.Elem().Index(i) // storing array as pointer on stack - so need Elem() call
|
|
||||||
if ae.CanSet() {
|
|
||||||
ae.Set(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflectwalk.SliceElem:
|
|
||||||
// Pop off the value and the index and set it on the slice
|
|
||||||
v := w.valPop()
|
|
||||||
i := w.valPop().Interface().(int)
|
|
||||||
if v.IsValid() {
|
|
||||||
s := w.cs[len(w.cs)-1]
|
|
||||||
se := s.Elem().Index(i)
|
|
||||||
if se.CanSet() {
|
|
||||||
se.Set(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflectwalk.Struct:
|
|
||||||
w.replacePointerMaybe()
|
|
||||||
|
|
||||||
// Remove the struct from the container stack
|
|
||||||
w.cs = w.cs[:len(w.cs)-1]
|
|
||||||
case reflectwalk.StructField:
|
|
||||||
// Pop off the value and the field
|
|
||||||
v := w.valPop()
|
|
||||||
f := w.valPop().Interface().(reflect.StructField)
|
|
||||||
if v.IsValid() {
|
|
||||||
s := w.cs[len(w.cs)-1]
|
|
||||||
sf := reflect.Indirect(s).FieldByName(f.Name)
|
|
||||||
|
|
||||||
if sf.CanSet() {
|
|
||||||
sf.Set(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflectwalk.WalkLoc:
|
|
||||||
// Clear out the slices for GC
|
|
||||||
w.cs = nil
|
|
||||||
w.vals = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) Map(m reflect.Value) error {
|
|
||||||
if w.ignoring() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
w.lock(m)
|
|
||||||
|
|
||||||
// Create the map. If the map itself is nil, then just make a nil map
|
|
||||||
var newMap reflect.Value
|
|
||||||
if m.IsNil() {
|
|
||||||
newMap = reflect.New(m.Type())
|
|
||||||
} else {
|
|
||||||
newMap = wrapPtr(reflect.MakeMap(m.Type()))
|
|
||||||
}
|
|
||||||
|
|
||||||
w.cs = append(w.cs, newMap)
|
|
||||||
w.valPush(newMap)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) MapElem(m, k, v reflect.Value) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) PointerEnter(v bool) error {
|
|
||||||
if v {
|
|
||||||
w.ps[w.depth]++
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) PointerExit(v bool) error {
|
|
||||||
if v {
|
|
||||||
w.ps[w.depth]--
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) Pointer(v reflect.Value) error {
|
|
||||||
if _, ok := w.shallowCopiers[v.Type()]; ok {
|
|
||||||
// Shallow copy this value. Use the same logic as primitive, then
|
|
||||||
// return skip.
|
|
||||||
if err := w.Primitive(v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return reflectwalk.SkipEntry
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) Interface(v reflect.Value) error {
|
|
||||||
if !v.IsValid() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if w.ifaceTypes == nil {
|
|
||||||
w.ifaceTypes = make(map[uint64]reflect.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.ifaceTypes[ifaceKey(w.ps[w.depth], w.depth)] = v.Type()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) Primitive(v reflect.Value) error {
|
|
||||||
if w.ignoring() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
w.lock(v)
|
|
||||||
|
|
||||||
// IsValid verifies the v is non-zero and CanInterface verifies
|
|
||||||
// that we're allowed to read this value (unexported fields).
|
|
||||||
var newV reflect.Value
|
|
||||||
if v.IsValid() && v.CanInterface() {
|
|
||||||
newV = reflect.New(v.Type())
|
|
||||||
newV.Elem().Set(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.valPush(newV)
|
|
||||||
w.replacePointerMaybe()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) Slice(s reflect.Value) error {
|
|
||||||
if w.ignoring() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
w.lock(s)
|
|
||||||
|
|
||||||
var newS reflect.Value
|
|
||||||
if s.IsNil() {
|
|
||||||
newS = reflect.New(s.Type())
|
|
||||||
} else {
|
|
||||||
newS = wrapPtr(reflect.MakeSlice(s.Type(), s.Len(), s.Cap()))
|
|
||||||
}
|
|
||||||
|
|
||||||
w.cs = append(w.cs, newS)
|
|
||||||
w.valPush(newS)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) SliceElem(i int, elem reflect.Value) error {
|
|
||||||
if w.ignoring() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't write the slice here because elem might still be
|
|
||||||
// arbitrarily complex. Just record the index and continue on.
|
|
||||||
w.valPush(reflect.ValueOf(i))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) Array(a reflect.Value) error {
|
|
||||||
if w.ignoring() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
w.lock(a)
|
|
||||||
|
|
||||||
newA := reflect.New(a.Type())
|
|
||||||
|
|
||||||
w.cs = append(w.cs, newA)
|
|
||||||
w.valPush(newA)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ArrayElem(i int, elem reflect.Value) error {
|
|
||||||
if w.ignoring() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't write the array here because elem might still be
|
|
||||||
// arbitrarily complex. Just record the index and continue on.
|
|
||||||
w.valPush(reflect.ValueOf(i))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) Struct(s reflect.Value) error {
|
|
||||||
if w.ignoring() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
w.lock(s)
|
|
||||||
|
|
||||||
var v reflect.Value
|
|
||||||
if c, ok := w.copiers[s.Type()]; ok {
|
|
||||||
// We have a Copier for this struct, so we use that copier to
|
|
||||||
// get the copy, and we ignore anything deeper than this.
|
|
||||||
w.ignoreDepth = w.depth
|
|
||||||
|
|
||||||
dup, err := c(s.Interface())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to put a pointer to the value on the value stack,
|
|
||||||
// so allocate a new pointer and set it.
|
|
||||||
v = reflect.New(s.Type())
|
|
||||||
reflect.Indirect(v).Set(reflect.ValueOf(dup))
|
|
||||||
} else {
|
|
||||||
// No copier, we copy ourselves and allow reflectwalk to guide
|
|
||||||
// us deeper into the structure for copying.
|
|
||||||
v = reflect.New(s.Type())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push the value onto the value stack for setting the struct field,
|
|
||||||
// and add the struct itself to the containers stack in case we walk
|
|
||||||
// deeper so that its own fields can be modified.
|
|
||||||
w.valPush(v)
|
|
||||||
w.cs = append(w.cs, v)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) StructField(f reflect.StructField, v reflect.Value) error {
|
|
||||||
if w.ignoring() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// If PkgPath is non-empty, this is a private (unexported) field.
|
|
||||||
// We do not set this unexported since the Go runtime doesn't allow us.
|
|
||||||
if f.PkgPath != "" {
|
|
||||||
return reflectwalk.SkipEntry
|
|
||||||
}
|
|
||||||
|
|
||||||
switch f.Tag.Get(tagKey) {
|
|
||||||
case "shallow":
|
|
||||||
// If we're shallow copying then assign the value directly to the
|
|
||||||
// struct and skip the entry.
|
|
||||||
if v.IsValid() {
|
|
||||||
s := w.cs[len(w.cs)-1]
|
|
||||||
sf := reflect.Indirect(s).FieldByName(f.Name)
|
|
||||||
if sf.CanSet() {
|
|
||||||
sf.Set(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return reflectwalk.SkipEntry
|
|
||||||
|
|
||||||
case "ignore":
|
|
||||||
// Do nothing
|
|
||||||
return reflectwalk.SkipEntry
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push the field onto the stack, we'll handle it when we exit
|
|
||||||
// the struct field in Exit...
|
|
||||||
w.valPush(reflect.ValueOf(f))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore causes the walker to ignore any more values until we exit this on
|
|
||||||
func (w *walker) ignore() {
|
|
||||||
w.ignoreDepth = w.depth
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ignoring() bool {
|
|
||||||
return w.ignoreDepth > 0 && w.depth >= w.ignoreDepth
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) pointerPeek() bool {
|
|
||||||
return w.ps[w.depth] > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) valPop() reflect.Value {
|
|
||||||
result := w.vals[len(w.vals)-1]
|
|
||||||
w.vals = w.vals[:len(w.vals)-1]
|
|
||||||
|
|
||||||
// If we're out of values, that means we popped everything off. In
|
|
||||||
// this case, we reset the result so the next pushed value becomes
|
|
||||||
// the result.
|
|
||||||
if len(w.vals) == 0 {
|
|
||||||
w.Result = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) valPush(v reflect.Value) {
|
|
||||||
w.vals = append(w.vals, v)
|
|
||||||
|
|
||||||
// If we haven't set the result yet, then this is the result since
|
|
||||||
// it is the first (outermost) value we're seeing.
|
|
||||||
if w.Result == nil && v.IsValid() {
|
|
||||||
w.Result = v.Interface()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) replacePointerMaybe() {
|
|
||||||
// Determine the last pointer value. If it is NOT a pointer, then
|
|
||||||
// we need to push that onto the stack.
|
|
||||||
if !w.pointerPeek() {
|
|
||||||
w.valPush(reflect.Indirect(w.valPop()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
v := w.valPop()
|
|
||||||
|
|
||||||
// If the expected type is a pointer to an interface of any depth,
|
|
||||||
// such as *interface{}, **interface{}, etc., then we need to convert
|
|
||||||
// the value "v" from *CONCRETE to *interface{} so types match for
|
|
||||||
// Set.
|
|
||||||
//
|
|
||||||
// Example if v is type *Foo where Foo is a struct, v would become
|
|
||||||
// *interface{} instead. This only happens if we have an interface expectation
|
|
||||||
// at this depth.
|
|
||||||
//
|
|
||||||
// For more info, see GH-16
|
|
||||||
if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth], w.depth)]; ok && iType.Kind() == reflect.Interface {
|
|
||||||
y := reflect.New(iType) // Create *interface{}
|
|
||||||
y.Elem().Set(reflect.Indirect(v)) // Assign "Foo" to interface{} (dereferenced)
|
|
||||||
v = y // v is now typed *interface{} (where *v = Foo)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 1; i < w.ps[w.depth]; i++ {
|
|
||||||
if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth]-i, w.depth)]; ok {
|
|
||||||
iface := reflect.New(iType).Elem()
|
|
||||||
iface.Set(v)
|
|
||||||
v = iface
|
|
||||||
}
|
|
||||||
|
|
||||||
p := reflect.New(v.Type())
|
|
||||||
p.Elem().Set(v)
|
|
||||||
v = p
|
|
||||||
}
|
|
||||||
|
|
||||||
w.valPush(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// if this value is a Locker, lock it and add it to the locks slice
|
|
||||||
func (w *walker) lock(v reflect.Value) {
|
|
||||||
if !w.useLocks {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !v.IsValid() || !v.CanInterface() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type rlocker interface {
|
|
||||||
RLocker() sync.Locker
|
|
||||||
}
|
|
||||||
|
|
||||||
var locker sync.Locker
|
|
||||||
|
|
||||||
// We can't call Interface() on a value directly, since that requires
|
|
||||||
// a copy. This is OK, since the pointer to a value which is a sync.Locker
|
|
||||||
// is also a sync.Locker.
|
|
||||||
if v.Kind() == reflect.Ptr {
|
|
||||||
switch l := v.Interface().(type) {
|
|
||||||
case rlocker:
|
|
||||||
// don't lock a mutex directly
|
|
||||||
if _, ok := l.(*sync.RWMutex); !ok {
|
|
||||||
locker = l.RLocker()
|
|
||||||
}
|
|
||||||
case sync.Locker:
|
|
||||||
locker = l
|
|
||||||
}
|
|
||||||
} else if v.CanAddr() {
|
|
||||||
switch l := v.Addr().Interface().(type) {
|
|
||||||
case rlocker:
|
|
||||||
// don't lock a mutex directly
|
|
||||||
if _, ok := l.(*sync.RWMutex); !ok {
|
|
||||||
locker = l.RLocker()
|
|
||||||
}
|
|
||||||
case sync.Locker:
|
|
||||||
locker = l
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// still no callable locker
|
|
||||||
if locker == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't lock a mutex directly
|
|
||||||
switch locker.(type) {
|
|
||||||
case *sync.Mutex, *sync.RWMutex:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
locker.Lock()
|
|
||||||
w.locks[w.depth] = locker
|
|
||||||
}
|
|
||||||
|
|
||||||
// wrapPtr is a helper that takes v and always make it *v. copystructure
|
|
||||||
// stores things internally as pointers until the last moment before unwrapping
|
|
||||||
func wrapPtr(v reflect.Value) reflect.Value {
|
|
||||||
if !v.IsValid() {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
vPtr := reflect.New(v.Type())
|
|
||||||
vPtr.Elem().Set(v)
|
|
||||||
return vPtr
|
|
||||||
}
|
|
1
vendor/github.com/mitchellh/reflectwalk/.travis.yml
generated
vendored
1
vendor/github.com/mitchellh/reflectwalk/.travis.yml
generated
vendored
@ -1 +0,0 @@
|
|||||||
language: go
|
|
21
vendor/github.com/mitchellh/reflectwalk/LICENSE
generated
vendored
21
vendor/github.com/mitchellh/reflectwalk/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2013 Mitchell Hashimoto
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
6
vendor/github.com/mitchellh/reflectwalk/README.md
generated
vendored
6
vendor/github.com/mitchellh/reflectwalk/README.md
generated
vendored
@ -1,6 +0,0 @@
|
|||||||
# reflectwalk
|
|
||||||
|
|
||||||
reflectwalk is a Go library for "walking" a value in Go using reflection,
|
|
||||||
in the same way a directory tree can be "walked" on the filesystem. Walking
|
|
||||||
a complex structure can allow you to do manipulations on unknown structures
|
|
||||||
such as those decoded from JSON.
|
|
19
vendor/github.com/mitchellh/reflectwalk/location.go
generated
vendored
19
vendor/github.com/mitchellh/reflectwalk/location.go
generated
vendored
@ -1,19 +0,0 @@
|
|||||||
package reflectwalk
|
|
||||||
|
|
||||||
//go:generate stringer -type=Location location.go
|
|
||||||
|
|
||||||
type Location uint
|
|
||||||
|
|
||||||
const (
|
|
||||||
None Location = iota
|
|
||||||
Map
|
|
||||||
MapKey
|
|
||||||
MapValue
|
|
||||||
Slice
|
|
||||||
SliceElem
|
|
||||||
Array
|
|
||||||
ArrayElem
|
|
||||||
Struct
|
|
||||||
StructField
|
|
||||||
WalkLoc
|
|
||||||
)
|
|
16
vendor/github.com/mitchellh/reflectwalk/location_string.go
generated
vendored
16
vendor/github.com/mitchellh/reflectwalk/location_string.go
generated
vendored
@ -1,16 +0,0 @@
|
|||||||
// Code generated by "stringer -type=Location location.go"; DO NOT EDIT.
|
|
||||||
|
|
||||||
package reflectwalk
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
const _Location_name = "NoneMapMapKeyMapValueSliceSliceElemArrayArrayElemStructStructFieldWalkLoc"
|
|
||||||
|
|
||||||
var _Location_index = [...]uint8{0, 4, 7, 13, 21, 26, 35, 40, 49, 55, 66, 73}
|
|
||||||
|
|
||||||
func (i Location) String() string {
|
|
||||||
if i >= Location(len(_Location_index)-1) {
|
|
||||||
return fmt.Sprintf("Location(%d)", i)
|
|
||||||
}
|
|
||||||
return _Location_name[_Location_index[i]:_Location_index[i+1]]
|
|
||||||
}
|
|
420
vendor/github.com/mitchellh/reflectwalk/reflectwalk.go
generated
vendored
420
vendor/github.com/mitchellh/reflectwalk/reflectwalk.go
generated
vendored
@ -1,420 +0,0 @@
|
|||||||
// reflectwalk is a package that allows you to "walk" complex structures
|
|
||||||
// similar to how you may "walk" a filesystem: visiting every element one
|
|
||||||
// by one and calling callback functions allowing you to handle and manipulate
|
|
||||||
// those elements.
|
|
||||||
package reflectwalk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PrimitiveWalker implementations are able to handle primitive values
|
|
||||||
// within complex structures. Primitive values are numbers, strings,
|
|
||||||
// booleans, funcs, chans.
|
|
||||||
//
|
|
||||||
// These primitive values are often members of more complex
|
|
||||||
// structures (slices, maps, etc.) that are walkable by other interfaces.
|
|
||||||
type PrimitiveWalker interface {
|
|
||||||
Primitive(reflect.Value) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// InterfaceWalker implementations are able to handle interface values as they
|
|
||||||
// are encountered during the walk.
|
|
||||||
type InterfaceWalker interface {
|
|
||||||
Interface(reflect.Value) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// MapWalker implementations are able to handle individual elements
|
|
||||||
// found within a map structure.
|
|
||||||
type MapWalker interface {
|
|
||||||
Map(m reflect.Value) error
|
|
||||||
MapElem(m, k, v reflect.Value) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// SliceWalker implementations are able to handle slice elements found
|
|
||||||
// within complex structures.
|
|
||||||
type SliceWalker interface {
|
|
||||||
Slice(reflect.Value) error
|
|
||||||
SliceElem(int, reflect.Value) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArrayWalker implementations are able to handle array elements found
|
|
||||||
// within complex structures.
|
|
||||||
type ArrayWalker interface {
|
|
||||||
Array(reflect.Value) error
|
|
||||||
ArrayElem(int, reflect.Value) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// StructWalker is an interface that has methods that are called for
|
|
||||||
// structs when a Walk is done.
|
|
||||||
type StructWalker interface {
|
|
||||||
Struct(reflect.Value) error
|
|
||||||
StructField(reflect.StructField, reflect.Value) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnterExitWalker implementations are notified before and after
|
|
||||||
// they walk deeper into complex structures (into struct fields,
|
|
||||||
// into slice elements, etc.)
|
|
||||||
type EnterExitWalker interface {
|
|
||||||
Enter(Location) error
|
|
||||||
Exit(Location) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// PointerWalker implementations are notified when the value they're
|
|
||||||
// walking is a pointer or not. Pointer is called for _every_ value whether
|
|
||||||
// it is a pointer or not.
|
|
||||||
type PointerWalker interface {
|
|
||||||
PointerEnter(bool) error
|
|
||||||
PointerExit(bool) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// PointerValueWalker implementations are notified with the value of
|
|
||||||
// a particular pointer when a pointer is walked. Pointer is called
|
|
||||||
// right before PointerEnter.
|
|
||||||
type PointerValueWalker interface {
|
|
||||||
Pointer(reflect.Value) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// SkipEntry can be returned from walk functions to skip walking
|
|
||||||
// the value of this field. This is only valid in the following functions:
|
|
||||||
//
|
|
||||||
// - Struct: skips all fields from being walked
|
|
||||||
// - StructField: skips walking the struct value
|
|
||||||
//
|
|
||||||
var SkipEntry = errors.New("skip this entry")
|
|
||||||
|
|
||||||
// Walk takes an arbitrary value and an interface and traverses the
|
|
||||||
// value, calling callbacks on the interface if they are supported.
|
|
||||||
// The interface should implement one or more of the walker interfaces
|
|
||||||
// in this package, such as PrimitiveWalker, StructWalker, etc.
|
|
||||||
func Walk(data, walker interface{}) (err error) {
|
|
||||||
v := reflect.ValueOf(data)
|
|
||||||
ew, ok := walker.(EnterExitWalker)
|
|
||||||
if ok {
|
|
||||||
err = ew.Enter(WalkLoc)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
err = walk(v, walker)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok && err == nil {
|
|
||||||
err = ew.Exit(WalkLoc)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func walk(v reflect.Value, w interface{}) (err error) {
|
|
||||||
// Determine if we're receiving a pointer and if so notify the walker.
|
|
||||||
// The logic here is convoluted but very important (tests will fail if
|
|
||||||
// almost any part is changed). I will try to explain here.
|
|
||||||
//
|
|
||||||
// First, we check if the value is an interface, if so, we really need
|
|
||||||
// to check the interface's VALUE to see whether it is a pointer.
|
|
||||||
//
|
|
||||||
// Check whether the value is then a pointer. If so, then set pointer
|
|
||||||
// to true to notify the user.
|
|
||||||
//
|
|
||||||
// If we still have a pointer or an interface after the indirections, then
|
|
||||||
// we unwrap another level
|
|
||||||
//
|
|
||||||
// At this time, we also set "v" to be the dereferenced value. This is
|
|
||||||
// because once we've unwrapped the pointer we want to use that value.
|
|
||||||
pointer := false
|
|
||||||
pointerV := v
|
|
||||||
|
|
||||||
for {
|
|
||||||
if pointerV.Kind() == reflect.Interface {
|
|
||||||
if iw, ok := w.(InterfaceWalker); ok {
|
|
||||||
if err = iw.Interface(pointerV); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pointerV = pointerV.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
if pointerV.Kind() == reflect.Ptr {
|
|
||||||
if pw, ok := w.(PointerValueWalker); ok {
|
|
||||||
if err = pw.Pointer(pointerV); err != nil {
|
|
||||||
if err == SkipEntry {
|
|
||||||
// Skip the rest of this entry but clear the error
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pointer = true
|
|
||||||
v = reflect.Indirect(pointerV)
|
|
||||||
}
|
|
||||||
if pw, ok := w.(PointerWalker); ok {
|
|
||||||
if err = pw.PointerEnter(pointer); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func(pointer bool) {
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = pw.PointerExit(pointer)
|
|
||||||
}(pointer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if pointer {
|
|
||||||
pointerV = v
|
|
||||||
}
|
|
||||||
pointer = false
|
|
||||||
|
|
||||||
// If we still have a pointer or interface we have to indirect another level.
|
|
||||||
switch pointerV.Kind() {
|
|
||||||
case reflect.Ptr, reflect.Interface:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// We preserve the original value here because if it is an interface
|
|
||||||
// type, we want to pass that directly into the walkPrimitive, so that
|
|
||||||
// we can set it.
|
|
||||||
originalV := v
|
|
||||||
if v.Kind() == reflect.Interface {
|
|
||||||
v = v.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
k := v.Kind()
|
|
||||||
if k >= reflect.Int && k <= reflect.Complex128 {
|
|
||||||
k = reflect.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
switch k {
|
|
||||||
// Primitives
|
|
||||||
case reflect.Bool, reflect.Chan, reflect.Func, reflect.Int, reflect.String, reflect.Invalid:
|
|
||||||
err = walkPrimitive(originalV, w)
|
|
||||||
return
|
|
||||||
case reflect.Map:
|
|
||||||
err = walkMap(v, w)
|
|
||||||
return
|
|
||||||
case reflect.Slice:
|
|
||||||
err = walkSlice(v, w)
|
|
||||||
return
|
|
||||||
case reflect.Struct:
|
|
||||||
err = walkStruct(v, w)
|
|
||||||
return
|
|
||||||
case reflect.Array:
|
|
||||||
err = walkArray(v, w)
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
panic("unsupported type: " + k.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func walkMap(v reflect.Value, w interface{}) error {
|
|
||||||
ew, ewok := w.(EnterExitWalker)
|
|
||||||
if ewok {
|
|
||||||
ew.Enter(Map)
|
|
||||||
}
|
|
||||||
|
|
||||||
if mw, ok := w.(MapWalker); ok {
|
|
||||||
if err := mw.Map(v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, k := range v.MapKeys() {
|
|
||||||
kv := v.MapIndex(k)
|
|
||||||
|
|
||||||
if mw, ok := w.(MapWalker); ok {
|
|
||||||
if err := mw.MapElem(v, k, kv); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ew, ok := w.(EnterExitWalker)
|
|
||||||
if ok {
|
|
||||||
ew.Enter(MapKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := walk(k, w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
ew.Exit(MapKey)
|
|
||||||
ew.Enter(MapValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the map value again as it may have changed in the MapElem call
|
|
||||||
if err := walk(v.MapIndex(k), w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
ew.Exit(MapValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ewok {
|
|
||||||
ew.Exit(Map)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func walkPrimitive(v reflect.Value, w interface{}) error {
|
|
||||||
if pw, ok := w.(PrimitiveWalker); ok {
|
|
||||||
return pw.Primitive(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func walkSlice(v reflect.Value, w interface{}) (err error) {
|
|
||||||
ew, ok := w.(EnterExitWalker)
|
|
||||||
if ok {
|
|
||||||
ew.Enter(Slice)
|
|
||||||
}
|
|
||||||
|
|
||||||
if sw, ok := w.(SliceWalker); ok {
|
|
||||||
if err := sw.Slice(v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < v.Len(); i++ {
|
|
||||||
elem := v.Index(i)
|
|
||||||
|
|
||||||
if sw, ok := w.(SliceWalker); ok {
|
|
||||||
if err := sw.SliceElem(i, elem); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ew, ok := w.(EnterExitWalker)
|
|
||||||
if ok {
|
|
||||||
ew.Enter(SliceElem)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := walk(elem, w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
ew.Exit(SliceElem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ew, ok = w.(EnterExitWalker)
|
|
||||||
if ok {
|
|
||||||
ew.Exit(Slice)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func walkArray(v reflect.Value, w interface{}) (err error) {
|
|
||||||
ew, ok := w.(EnterExitWalker)
|
|
||||||
if ok {
|
|
||||||
ew.Enter(Array)
|
|
||||||
}
|
|
||||||
|
|
||||||
if aw, ok := w.(ArrayWalker); ok {
|
|
||||||
if err := aw.Array(v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < v.Len(); i++ {
|
|
||||||
elem := v.Index(i)
|
|
||||||
|
|
||||||
if aw, ok := w.(ArrayWalker); ok {
|
|
||||||
if err := aw.ArrayElem(i, elem); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ew, ok := w.(EnterExitWalker)
|
|
||||||
if ok {
|
|
||||||
ew.Enter(ArrayElem)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := walk(elem, w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
ew.Exit(ArrayElem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ew, ok = w.(EnterExitWalker)
|
|
||||||
if ok {
|
|
||||||
ew.Exit(Array)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func walkStruct(v reflect.Value, w interface{}) (err error) {
|
|
||||||
ew, ewok := w.(EnterExitWalker)
|
|
||||||
if ewok {
|
|
||||||
ew.Enter(Struct)
|
|
||||||
}
|
|
||||||
|
|
||||||
skip := false
|
|
||||||
if sw, ok := w.(StructWalker); ok {
|
|
||||||
err = sw.Struct(v)
|
|
||||||
if err == SkipEntry {
|
|
||||||
skip = true
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !skip {
|
|
||||||
vt := v.Type()
|
|
||||||
for i := 0; i < vt.NumField(); i++ {
|
|
||||||
sf := vt.Field(i)
|
|
||||||
f := v.FieldByIndex([]int{i})
|
|
||||||
|
|
||||||
if sw, ok := w.(StructWalker); ok {
|
|
||||||
err = sw.StructField(sf, f)
|
|
||||||
|
|
||||||
// SkipEntry just pretends this field doesn't even exist
|
|
||||||
if err == SkipEntry {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ew, ok := w.(EnterExitWalker)
|
|
||||||
if ok {
|
|
||||||
ew.Enter(StructField)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = walk(f, w)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
ew.Exit(StructField)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ewok {
|
|
||||||
ew.Exit(Struct)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
8
vendor/modules.txt
vendored
8
vendor/modules.txt
vendored
@ -131,7 +131,7 @@ github.com/cenkalti/backoff/v4
|
|||||||
# github.com/cespare/xxhash/v2 v2.2.0
|
# github.com/cespare/xxhash/v2 v2.2.0
|
||||||
## explicit; go 1.11
|
## explicit; go 1.11
|
||||||
github.com/cespare/xxhash/v2
|
github.com/cespare/xxhash/v2
|
||||||
# github.com/compose-spec/compose-go/v2 v2.1.2
|
# github.com/compose-spec/compose-go/v2 v2.1.3
|
||||||
## explicit; go 1.21
|
## explicit; go 1.21
|
||||||
github.com/compose-spec/compose-go/v2/cli
|
github.com/compose-spec/compose-go/v2/cli
|
||||||
github.com/compose-spec/compose-go/v2/consts
|
github.com/compose-spec/compose-go/v2/consts
|
||||||
@ -508,17 +508,11 @@ github.com/matttproud/golang_protobuf_extensions/pbutil
|
|||||||
# github.com/miekg/pkcs11 v1.1.1
|
# github.com/miekg/pkcs11 v1.1.1
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/miekg/pkcs11
|
github.com/miekg/pkcs11
|
||||||
# github.com/mitchellh/copystructure v1.2.0
|
|
||||||
## explicit; go 1.15
|
|
||||||
github.com/mitchellh/copystructure
|
|
||||||
# github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7
|
# github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7
|
||||||
## explicit
|
## explicit
|
||||||
github.com/mitchellh/go-wordwrap
|
github.com/mitchellh/go-wordwrap
|
||||||
# github.com/mitchellh/mapstructure v1.5.0
|
# github.com/mitchellh/mapstructure v1.5.0
|
||||||
## explicit; go 1.14
|
## explicit; go 1.14
|
||||||
# github.com/mitchellh/reflectwalk v1.0.2
|
|
||||||
## explicit
|
|
||||||
github.com/mitchellh/reflectwalk
|
|
||||||
# github.com/moby/buildkit v0.14.1
|
# github.com/moby/buildkit v0.14.1
|
||||||
## explicit; go 1.21
|
## explicit; go 1.21
|
||||||
github.com/moby/buildkit/api/services/control
|
github.com/moby/buildkit/api/services/control
|
||||||
|
Loading…
x
Reference in New Issue
Block a user