diff options
-rw-r--r-- | cmd/podman/commit.go | 9 | ||||
-rw-r--r-- | cmd/podman/common.go | 2 | ||||
-rw-r--r-- | cmd/podman/inspect.go | 1 | ||||
-rw-r--r-- | cmd/podman/mount.go | 6 | ||||
-rw-r--r-- | cmd/podman/pod_inspect.go | 1 | ||||
-rw-r--r-- | cmd/podman/pod_stats.go | 6 | ||||
-rw-r--r-- | cmd/podman/ps.go | 3 | ||||
-rw-r--r-- | cmd/podman/run.go | 6 | ||||
-rw-r--r-- | cmd/podman/shared/create.go | 15 | ||||
-rw-r--r-- | cmd/podman/sign.go | 6 | ||||
-rw-r--r-- | cmd/podman/start.go | 6 | ||||
-rw-r--r-- | cmd/podman/trust_set_show.go | 1 | ||||
-rw-r--r-- | contrib/spec/podman.spec.in | 3 | ||||
-rw-r--r-- | libpod/container.go | 13 | ||||
-rw-r--r-- | libpod/events.go | 6 | ||||
-rw-r--r-- | libpod/pod_api.go | 5 | ||||
-rw-r--r-- | libpod/runtime.go | 15 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 5 | ||||
-rw-r--r-- | libpod/util.go | 10 | ||||
-rw-r--r-- | pkg/adapter/pods_remote.go | 5 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 15 | ||||
-rw-r--r-- | pkg/varlinkapi/containers_create.go | 5 | ||||
-rw-r--r-- | pkg/varlinkapi/images.go | 8 | ||||
-rw-r--r-- | vendor.conf | 1 | ||||
-rw-r--r-- | vendor/github.com/ulule/deepcopier/LICENSE | 22 | ||||
-rw-r--r-- | vendor/github.com/ulule/deepcopier/README.md | 129 | ||||
-rw-r--r-- | vendor/github.com/ulule/deepcopier/deepcopier.go | 362 |
27 files changed, 107 insertions, 559 deletions
diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go index 584ab6880..f7e206856 100644 --- a/cmd/podman/commit.go +++ b/cmd/podman/commit.go @@ -96,9 +96,14 @@ func commitCmd(c *cliconfig.CommitValues) error { return errors.Wrapf(err, "error looking up container %q", container) } - sc := image.GetSystemContext(runtime.GetConfig().SignaturePolicyPath, "", false) + rtc, err := runtime.GetConfig() + if err != nil { + return err + } + + sc := image.GetSystemContext(rtc.SignaturePolicyPath, "", false) coptions := buildah.CommitOptions{ - SignaturePolicyPath: runtime.GetConfig().SignaturePolicyPath, + SignaturePolicyPath: rtc.SignaturePolicyPath, ReportWriter: writer, SystemContext: sc, PreferredManifestType: mimeType, diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 167b3e845..10fed053e 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -12,12 +12,14 @@ import ( "github.com/containers/libpod/pkg/rootless" "github.com/containers/storage" "github.com/fatih/camelcase" + jsoniter "github.com/json-iterator/go" "github.com/pkg/errors" "github.com/spf13/cobra" ) var ( stores = make(map[storage.Store]struct{}) + json = jsoniter.ConfigCompatibleWithStandardLibrary ) const ( diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go index 3d6fd07e0..528320170 100644 --- a/cmd/podman/inspect.go +++ b/cmd/podman/inspect.go @@ -2,7 +2,6 @@ package main import ( "context" - "encoding/json" "strings" "github.com/containers/buildah/pkg/formats" diff --git a/cmd/podman/mount.go b/cmd/podman/mount.go index d074551ce..138548097 100644 --- a/cmd/podman/mount.go +++ b/cmd/podman/mount.go @@ -71,7 +71,11 @@ func mountCmd(c *cliconfig.MountValues) error { defer runtime.Shutdown(false) if os.Geteuid() != 0 { - if driver := runtime.GetConfig().StorageConfig.GraphDriverName; driver != "vfs" { + rtc, err := runtime.GetConfig() + if err != nil { + return err + } + if driver := rtc.StorageConfig.GraphDriverName; driver != "vfs" { // Do not allow to mount a graphdriver that is not vfs if we are creating the userns as part // of the mount command. return fmt.Errorf("cannot mount using driver %s in rootless mode", driver) diff --git a/cmd/podman/pod_inspect.go b/cmd/podman/pod_inspect.go index 851f39aa0..e12678354 100644 --- a/cmd/podman/pod_inspect.go +++ b/cmd/podman/pod_inspect.go @@ -1,7 +1,6 @@ package main import ( - "encoding/json" "fmt" "github.com/containers/libpod/cmd/podman/cliconfig" diff --git a/cmd/podman/pod_stats.go b/cmd/podman/pod_stats.go index e8ff322ce..36b0b95ed 100644 --- a/cmd/podman/pod_stats.go +++ b/cmd/podman/pod_stats.go @@ -9,7 +9,6 @@ import ( "text/tabwriter" "time" - "encoding/json" tm "github.com/buger/goterm" "github.com/containers/buildah/pkg/formats" "github.com/containers/libpod/cmd/podman/cliconfig" @@ -17,7 +16,6 @@ import ( "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/ulule/deepcopier" ) var ( @@ -187,7 +185,9 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error { } time.Sleep(time.Second) previousPodStats := new([]*libpod.PodContainerStats) - deepcopier.Copy(newStats).To(previousPodStats) + if err := libpod.JSONDeepCopy(newStats, previousPodStats); err != nil { + return err + } pods, err = runtime.GetStatPods(c) if err != nil { return err diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go index 27774f95d..a9802d27f 100644 --- a/cmd/podman/ps.go +++ b/cmd/podman/ps.go @@ -1,7 +1,6 @@ package main import ( - "encoding/json" "fmt" "html/template" "os" @@ -647,7 +646,7 @@ func printFormat(format string, containers []shared.PsContainerOutput) error { } func dumpJSON(containers []shared.PsContainerOutput) error { - b, err := json.MarshalIndent(containers, "", "\t") + b, err := json.MarshalIndent(containers, "", " ") if err != nil { return err } diff --git a/cmd/podman/run.go b/cmd/podman/run.go index 32e7b3510..3c26e98c1 100644 --- a/cmd/podman/run.go +++ b/cmd/podman/run.go @@ -154,7 +154,11 @@ func runCmd(c *cliconfig.RunValues) error { if errors.Cause(err) == libpod.ErrNoSuchCtr { // The container may have been removed // Go looking for an exit file - ctrExitCode, err := readExitFile(runtime.GetConfig().TmpDir, ctr.ID()) + rtc, err := runtime.GetConfig() + if err != nil { + return err + } + ctrExitCode, err := readExitFile(rtc.TmpDir, ctr.ID()) if err != nil { logrus.Errorf("Cannot get exit code: %v", err) exitCode = 127 diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index 5f7263cb6..d927e5bf6 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -43,20 +43,23 @@ func getContext() context.Context { func CreateContainer(ctx context.Context, c *cliconfig.PodmanCommand, runtime *libpod.Runtime) (*libpod.Container, *cc.CreateConfig, error) { var ( healthCheck *manifest.Schema2HealthConfig + err error + cidFile *os.File ) if c.Bool("trace") { span, _ := opentracing.StartSpanFromContext(ctx, "createContainer") defer span.Finish() } - rtc := runtime.GetConfig() + rtc, err := runtime.GetConfig() + if err != nil { + return nil, nil, err + } rootfs := "" if c.Bool("rootfs") { rootfs = c.InputArgs[0] } - var err error - var cidFile *os.File if c.IsSet("cidfile") && os.Geteuid() == 0 { cidFile, err = libpod.OpenExclusiveFile(c.String("cidfile")) if err != nil && os.IsExist(err) { @@ -721,7 +724,11 @@ func ParseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l if c.Bool("init") { initPath := c.String("init-path") if initPath == "" { - initPath = runtime.GetConfig().InitPath + rtc, err := runtime.GetConfig() + if err != nil { + return nil, err + } + initPath = rtc.InitPath } if err := config.AddContainerInitBinary(initPath); err != nil { return nil, err diff --git a/cmd/podman/sign.go b/cmd/podman/sign.go index 06418e4a5..75d723514 100644 --- a/cmd/podman/sign.go +++ b/cmd/podman/sign.go @@ -108,7 +108,11 @@ func signCmd(c *cliconfig.SignValues) error { } // create the signstore file - newImage, err := runtime.ImageRuntime().New(getContext(), signimage, runtime.GetConfig().SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{SignBy: signby}, false, nil) + rtc, err := runtime.GetConfig() + if err != nil { + return err + } + newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{SignBy: signby}, false, nil) if err != nil { return errors.Wrapf(err, "error pulling image %s", signimage) } diff --git a/cmd/podman/start.go b/cmd/podman/start.go index cf406cf66..d17a78268 100644 --- a/cmd/podman/start.go +++ b/cmd/podman/start.go @@ -129,7 +129,11 @@ func startCmd(c *cliconfig.StartValues) error { if errors.Cause(err) == libpod.ErrNoSuchCtr { // The container may have been removed // Go looking for an exit file - ctrExitCode, err := readExitFile(runtime.GetConfig().TmpDir, ctr.ID()) + rtc, err := runtime.GetConfig() + if err != nil { + return err + } + ctrExitCode, err := readExitFile(rtc.TmpDir, ctr.ID()) if err != nil { logrus.Errorf("Cannot get exit code: %v", err) exitCode = 127 diff --git a/cmd/podman/trust_set_show.go b/cmd/podman/trust_set_show.go index d7a4ea6d6..626d27aae 100644 --- a/cmd/podman/trust_set_show.go +++ b/cmd/podman/trust_set_show.go @@ -1,7 +1,6 @@ package main import ( - "encoding/json" "io/ioutil" "os" "sort" diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in index 3324ee8f9..319bbe979 100644 --- a/contrib/spec/podman.spec.in +++ b/contrib/spec/podman.spec.in @@ -151,7 +151,6 @@ Provides: bundled(golang(github.com/stretchr/testify)) = 4d4bfba8f1d1027c4fdbe37 Provides: bundled(golang(github.com/syndtr/gocapability)) = e7cb7fa329f456b3855136a2642b197bad7366ba Provides: bundled(golang(github.com/tchap/go-patricia)) = v2.2.6 Provides: bundled(golang(github.com/ulikunitz/xz)) = v0.5.4 -Provides: bundled(golang(github.com/ulule/deepcopier)) = master # "-" are not accepted in version strings, so comment out below line #Provides: bundled(golang(github.com/urfave/cli)) = fix-short-opts-parsing Provides: bundled(golang(github.com/varlink/go)) = master @@ -237,7 +236,6 @@ BuildRequires: golang(github.com/opencontainers/selinux/go-selinux) BuildRequires: golang(github.com/opencontainers/selinux/go-selinux/label) BuildRequires: golang(github.com/pkg/errors) BuildRequires: golang(github.com/sirupsen/logrus) -BuildRequires: golang(github.com/ulule/deepcopier) BuildRequires: golang(golang.org/x/crypto/ssh/terminal) BuildRequires: golang(golang.org/x/sys/unix) BuildRequires: golang(k8s.io/apimachinery/pkg/util/wait) @@ -290,7 +288,6 @@ Requires: golang(github.com/opencontainers/selinux/go-selinux) Requires: golang(github.com/opencontainers/selinux/go-selinux/label) Requires: golang(github.com/pkg/errors) Requires: golang(github.com/sirupsen/logrus) -Requires: golang(github.com/ulule/deepcopier) Requires: golang(golang.org/x/crypto/ssh/terminal) Requires: golang(golang.org/x/sys/unix) Requires: golang(k8s.io/apimachinery/pkg/util/wait) diff --git a/libpod/container.go b/libpod/container.go index 806e75c63..6d80a9bf4 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -17,7 +17,6 @@ import ( "github.com/cri-o/ocicni/pkg/ocicni" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" - "github.com/ulule/deepcopier" ) // ContainerStatus represents the current state of a container @@ -407,7 +406,9 @@ func (t ContainerStatus) String() string { // Config returns the configuration used to create the container func (c *Container) Config() *ContainerConfig { returnConfig := new(ContainerConfig) - deepcopier.Copy(c.config).To(returnConfig) + if err := JSONDeepCopy(c.config, returnConfig); err != nil { + return nil + } return returnConfig } @@ -417,7 +418,9 @@ func (c *Container) Config() *ContainerConfig { // spec may differ slightly as mounts are added based on the image func (c *Container) Spec() *spec.Spec { returnSpec := new(spec.Spec) - deepcopier.Copy(c.config.Spec).To(returnSpec) + if err := JSONDeepCopy(c.config.Spec, returnSpec); err != nil { + return nil + } return returnSpec } @@ -1094,7 +1097,9 @@ func (c *Container) ContainerState() (*ContainerState, error) { } } returnConfig := new(ContainerState) - deepcopier.Copy(c.state).To(returnConfig) + if err := JSONDeepCopy(c.state, returnConfig); err != nil { + return nil, errors.Wrapf(err, "error copying container %s state", c.ID()) + } return c.state, nil } diff --git a/libpod/events.go b/libpod/events.go index 139600982..b6a277789 100644 --- a/libpod/events.go +++ b/libpod/events.go @@ -58,6 +58,10 @@ func (v *Volume) newVolumeEvent(status events.Status) { // Events is a wrapper function for everyone to begin tailing the events log // with options func (r *Runtime) Events(fromStart, stream bool, options []events.EventFilter, eventChannel chan *events.Event) error { + if !r.valid { + return ErrRuntimeStopped + } + t, err := r.getTail(fromStart, stream) if err != nil { return err @@ -71,7 +75,7 @@ func (r *Runtime) Events(fromStart, stream bool, options []events.EventFilter, e case events.Image, events.Volume, events.Pod, events.Container: // no-op default: - return errors.Errorf("event type %s is not valid in %s", event.Type.String(), r.GetConfig().EventsLogFilePath) + return errors.Errorf("event type %s is not valid in %s", event.Type.String(), r.config.EventsLogFilePath) } include := true for _, filter := range options { diff --git a/libpod/pod_api.go b/libpod/pod_api.go index b9a11000e..9a6baf23e 100644 --- a/libpod/pod_api.go +++ b/libpod/pod_api.go @@ -6,7 +6,6 @@ import ( "github.com/containers/libpod/libpod/events" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "github.com/ulule/deepcopier" ) // Start starts all containers within a pod @@ -441,7 +440,9 @@ func (p *Pod) Inspect() (*PodInspect, error) { infraContainerID := p.state.InfraContainerID config := new(PodConfig) - deepcopier.Copy(p.config).To(config) + if err := JSONDeepCopy(p.config, config); err != nil { + return nil, err + } inspectData := PodInspect{ Config: config, State: &PodInspectState{ diff --git a/libpod/runtime.go b/libpod/runtime.go index b3b75d791..a4fc9e493 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -23,7 +23,6 @@ import ( "github.com/docker/docker/pkg/namesgenerator" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "github.com/ulule/deepcopier" ) // RuntimeStateStore is a constant indicating which state store implementation @@ -355,7 +354,9 @@ func newRuntimeFromConfig(userConfigPath string, options ...RuntimeOption) (runt if err != nil { return nil, err } - deepcopier.Copy(defaultRuntimeConfig).To(runtime.config) + if err := JSONDeepCopy(defaultRuntimeConfig, runtime.config); err != nil { + return nil, errors.Wrapf(err, "error copying runtime default config") + } runtime.config.TmpDir = tmpDir storageConf, err := util.GetDefaultStoreOptions() @@ -923,20 +924,22 @@ func makeRuntime(runtime *Runtime) (err error) { } // GetConfig returns a copy of the configuration used by the runtime -func (r *Runtime) GetConfig() *RuntimeConfig { +func (r *Runtime) GetConfig() (*RuntimeConfig, error) { r.lock.RLock() defer r.lock.RUnlock() if !r.valid { - return nil + return nil, ErrRuntimeStopped } config := new(RuntimeConfig) // Copy so the caller won't be able to modify the actual config - deepcopier.Copy(r.config).To(config) + if err := JSONDeepCopy(r.config, config); err != nil { + return nil, errors.Wrapf(err, "error copying config") + } - return config + return config, nil } // Shutdown shuts down the runtime and associated containers and storage diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index f23dc86dd..7c39d8ced 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -19,7 +19,6 @@ import ( opentracing "github.com/opentracing/opentracing-go" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "github.com/ulule/deepcopier" ) // CtrRemoveTimeout is the default number of seconds to wait after stopping a container @@ -63,7 +62,9 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. ctr.config.ID = stringid.GenerateNonCryptoID() ctr.config.Spec = new(spec.Spec) - deepcopier.Copy(rSpec).To(ctr.config.Spec) + if err := JSONDeepCopy(rSpec, ctr.config.Spec); err != nil { + return nil, errors.Wrapf(err, "error copying runtime spec while creating container") + } ctr.config.CreatedTime = time.Now() ctr.config.ShmSize = DefaultShmSize diff --git a/libpod/util.go b/libpod/util.go index b7578135a..7e2dff21a 100644 --- a/libpod/util.go +++ b/libpod/util.go @@ -187,3 +187,13 @@ func validPodNSOption(p *Pod, ctrPod string) error { } return nil } + +// JSONDeepCopy performs a deep copy by performing a JSON encode/decode of the +// given structures. From and To should be identically typed structs. +func JSONDeepCopy(from, to interface{}) error { + tmp, err := json.Marshal(from) + if err != nil { + return err + } + return json.Unmarshal(tmp, to) +} diff --git a/pkg/adapter/pods_remote.go b/pkg/adapter/pods_remote.go index ef8de90a6..4a32607a2 100644 --- a/pkg/adapter/pods_remote.go +++ b/pkg/adapter/pods_remote.go @@ -14,7 +14,6 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/varlinkapi" "github.com/pkg/errors" - "github.com/ulule/deepcopier" ) // Pod ... @@ -99,7 +98,9 @@ func (r *LocalRuntime) LookupPod(nameOrID string) (*Pod, error) { // the data of a remotepod data struct func (p *Pod) Inspect() (*libpod.PodInspect, error) { config := new(libpod.PodConfig) - deepcopier.Copy(p.remotepod.config).To(config) + if err := libpod.JSONDeepCopy(p.remotepod.config, config); err != nil { + return nil, err + } inspectData := libpod.PodInspect{ Config: config, State: p.remotepod.state, diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 79a318771..07ae633d1 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -346,8 +346,11 @@ func (c *CreateConfig) GetTmpfsMounts() []spec.Mount { return m } -func (c *CreateConfig) createExitCommand() []string { - config := c.Runtime.GetConfig() +func (c *CreateConfig) createExitCommand() ([]string, error) { + config, err := c.Runtime.GetConfig() + if err != nil { + return nil, err + } cmd, _ := os.Executable() command := []string{cmd, @@ -372,7 +375,7 @@ func (c *CreateConfig) createExitCommand() []string { command = append(command, "--rm") } - return command + return command, nil } // GetContainerCreateOptions takes a CreateConfig and returns a slice of CtrCreateOptions @@ -567,7 +570,11 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime, pod *l } // Always use a cleanup process to clean up Podman after termination - options = append(options, libpod.WithExitCommand(c.createExitCommand())) + exitCmd, err := c.createExitCommand() + if err != nil { + return nil, err + } + options = append(options, libpod.WithExitCommand(exitCmd)) if c.HealthCheck != nil { options = append(options, libpod.WithHealthCheck(c.HealthCheck)) diff --git a/pkg/varlinkapi/containers_create.go b/pkg/varlinkapi/containers_create.go index 6b53b22c6..8990ac001 100644 --- a/pkg/varlinkapi/containers_create.go +++ b/pkg/varlinkapi/containers_create.go @@ -22,7 +22,10 @@ import ( // CreateContainer ... func (i *LibpodAPI) CreateContainer(call iopodman.VarlinkCall, config iopodman.Create) error { - rtc := i.Runtime.GetConfig() + rtc, err := i.Runtime.GetConfig() + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } ctx := getContext() newImage, err := i.Runtime.ImageRuntime().New(ctx, config.Image, rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{}, false, nil) diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go index 210f139ce..23ea24a7a 100644 --- a/pkg/varlinkapi/images.go +++ b/pkg/varlinkapi/images.go @@ -514,7 +514,11 @@ func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, ch if err != nil { return call.ReplyContainerNotFound(name, err.Error()) } - sc := image.GetSystemContext(i.Runtime.GetConfig().SignaturePolicyPath, "", false) + rtc, err := i.Runtime.GetConfig() + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + sc := image.GetSystemContext(rtc.SignaturePolicyPath, "", false) var mimeType string switch manifestType { case "oci", "": //nolint @@ -525,7 +529,7 @@ func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, ch return call.ReplyErrorOccurred(fmt.Sprintf("unrecognized image format %q", manifestType)) } coptions := buildah.CommitOptions{ - SignaturePolicyPath: i.Runtime.GetConfig().SignaturePolicyPath, + SignaturePolicyPath: rtc.SignaturePolicyPath, ReportWriter: nil, SystemContext: sc, PreferredManifestType: mimeType, diff --git a/vendor.conf b/vendor.conf index bbfc96377..b2d34f553 100644 --- a/vendor.conf +++ b/vendor.conf @@ -73,7 +73,6 @@ github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2 github.com/tchap/go-patricia v2.2.6 github.com/uber/jaeger-client-go 64f57863bf63d3842dbe79cdc793d57baaff9ab5 github.com/uber/jaeger-lib d036253de8f5b698150d81b922486f1e8e7628ec -github.com/ulule/deepcopier ca99b135e50f526fde9cd88705f0ff2f3f95b77c github.com/vbatts/tar-split v0.11.1 github.com/vishvananda/netlink v1.0.0 github.com/vishvananda/netns 13995c7128ccc8e51e9a6bd2b551020a27180abd diff --git a/vendor/github.com/ulule/deepcopier/LICENSE b/vendor/github.com/ulule/deepcopier/LICENSE deleted file mode 100644 index d5c4ea02c..000000000 --- a/vendor/github.com/ulule/deepcopier/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Ulule - -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. - diff --git a/vendor/github.com/ulule/deepcopier/README.md b/vendor/github.com/ulule/deepcopier/README.md deleted file mode 100644 index 25aafae8a..000000000 --- a/vendor/github.com/ulule/deepcopier/README.md +++ /dev/null @@ -1,129 +0,0 @@ -# Deepcopier - -[![Build Status](https://secure.travis-ci.org/ulule/deepcopier.png?branch=master)](http://travis-ci.org/ulule/deepcopier) - -This package is meant to make copying of structs to/from others structs a bit easier. - -## Installation - -```bash -go get -u github.com/ulule/deepcopier -``` - -## Usage - -```golang -// Deep copy instance1 into instance2 -Copy(instance1).To(instance2) - -// Deep copy instance1 into instance2 and passes the following context (which -// is basically a map[string]interface{}) as first argument -// to methods of instance2 that defined the struct tag "context". -Copy(instance1).WithContext(map[string]interface{}{"foo": "bar"}).To(instance2) - -// Deep copy instance2 into instance1 -Copy(instance1).From(instance2) - -// Deep copy instance2 into instance1 and passes the following context (which -// is basically a map[string]interface{}) as first argument -// to methods of instance1 that defined the struct tag "context". -Copy(instance1).WithContext(map[string]interface{}{"foo": "bar"}).From(instance2) -``` - -Available options for `deepcopier` struct tag: - -| Option | Description | -| --------- | -------------------------------------------------------------------- | -| `field` | Field or method name in source instance | -| `skip` | Ignores the field | -| `context` | Takes a `map[string]interface{}` as first argument (for methods) | -| `force` | Set the value of a `sql.Null*` field (instead of copying the struct) | - -**Options example:** - -```golang -type Source struct { - Name string - SkipMe string - SQLNullStringToSQLNullString sql.NullString - SQLNullStringToString sql.NullString - -} - -func (Source) MethodThatTakesContext(c map[string]interface{}) string { - return "whatever" -} - -type Destination struct { - FieldWithAnotherNameInSource string `deepcopier:"field:Name"` - SkipMe string `deepcopier:"skip"` - MethodThatTakesContext string `deepcopier:"context"` - SQLNullStringToSQLNullString sql.NullString - SQLNullStringToString string `deepcopier:"force"` -} - -``` - -Example: - -```golang -package main - -import ( - "fmt" - - "github.com/ulule/deepcopier" -) - -// Model -type User struct { - // Basic string field - Name string - // Deepcopier supports https://golang.org/pkg/database/sql/driver/#Valuer - Email sql.NullString -} - -func (u *User) MethodThatTakesContext(ctx map[string]interface{}) string { - // do whatever you want - return "hello from this method" -} - -// Resource -type UserResource struct { - DisplayName string `deepcopier:"field:Name"` - SkipMe string `deepcopier:"skip"` - MethodThatTakesContext string `deepcopier:"context"` - Email string `deepcopier:"force"` - -} - -func main() { - user := &User{ - Name: "gilles", - Email: sql.NullString{ - Valid: true, - String: "gilles@example.com", - }, - } - - resource := &UserResource{} - - deepcopier.Copy(user).To(resource) - - fmt.Println(resource.DisplayName) - fmt.Println(resource.Email) -} -``` - -Looking for more information about the usage? - -We wrote [an introduction article](https://github.com/ulule/deepcopier/blob/master/examples/rest-usage/README.rst). -Have a look and feel free to give us your feedback. - -## Contributing - -* Ping us on twitter [@oibafsellig](https://twitter.com/oibafsellig), [@thoas](https://twitter.com/thoas) -* Fork the [project](https://github.com/ulule/deepcopier) -* Help us improving and fixing [issues](https://github.com/ulule/deepcopier/issues) - -Don't hesitate ;) diff --git a/vendor/github.com/ulule/deepcopier/deepcopier.go b/vendor/github.com/ulule/deepcopier/deepcopier.go deleted file mode 100644 index 8a6c70b55..000000000 --- a/vendor/github.com/ulule/deepcopier/deepcopier.go +++ /dev/null @@ -1,362 +0,0 @@ -package deepcopier - -import ( - "database/sql/driver" - "fmt" - "reflect" - "strings" -) - -const ( - // TagName is the deepcopier struct tag name. - TagName = "deepcopier" - // FieldOptionName is the from field option name for struct tag. - FieldOptionName = "field" - // ContextOptionName is the context option name for struct tag. - ContextOptionName = "context" - // SkipOptionName is the skip option name for struct tag. - SkipOptionName = "skip" - // ForceOptionName is the skip option name for struct tag. - ForceOptionName = "force" -) - -type ( - // TagOptions is a map that contains extracted struct tag options. - TagOptions map[string]string - - // Options are copier options. - Options struct { - // Context given to WithContext() method. - Context map[string]interface{} - // Reversed reverses struct tag checkings. - Reversed bool - } -) - -// DeepCopier deep copies a struct to/from a struct. -type DeepCopier struct { - dst interface{} - src interface{} - ctx map[string]interface{} -} - -// Copy sets source or destination. -func Copy(src interface{}) *DeepCopier { - return &DeepCopier{src: src} -} - -// WithContext injects the given context into the builder instance. -func (dc *DeepCopier) WithContext(ctx map[string]interface{}) *DeepCopier { - dc.ctx = ctx - return dc -} - -// To sets the destination. -func (dc *DeepCopier) To(dst interface{}) error { - dc.dst = dst - return process(dc.dst, dc.src, Options{Context: dc.ctx}) -} - -// From sets the given the source as destination and destination as source. -func (dc *DeepCopier) From(src interface{}) error { - dc.dst = dc.src - dc.src = src - return process(dc.dst, dc.src, Options{Context: dc.ctx, Reversed: true}) -} - -// process handles copy. -func process(dst interface{}, src interface{}, args ...Options) error { - var ( - options = Options{} - srcValue = reflect.Indirect(reflect.ValueOf(src)) - dstValue = reflect.Indirect(reflect.ValueOf(dst)) - srcFieldNames = getFieldNames(src) - srcMethodNames = getMethodNames(src) - ) - - if len(args) > 0 { - options = args[0] - } - - if !dstValue.CanAddr() { - return fmt.Errorf("destination %+v is unaddressable", dstValue.Interface()) - } - - for _, f := range srcFieldNames { - var ( - srcFieldValue = srcValue.FieldByName(f) - srcFieldType, srcFieldFound = srcValue.Type().FieldByName(f) - srcFieldName = srcFieldType.Name - dstFieldName = srcFieldName - tagOptions TagOptions - ) - - if !srcFieldFound { - continue - } - - if options.Reversed { - tagOptions = getTagOptions(srcFieldType.Tag.Get(TagName)) - if v, ok := tagOptions[FieldOptionName]; ok && v != "" { - dstFieldName = v - } - } else { - if name, opts := getRelatedField(dst, srcFieldName); name != "" { - dstFieldName, tagOptions = name, opts - } - } - - if _, ok := tagOptions[SkipOptionName]; ok { - continue - } - - var ( - dstFieldType, dstFieldFound = dstValue.Type().FieldByName(dstFieldName) - dstFieldValue = dstValue.FieldByName(dstFieldName) - ) - - if !dstFieldFound { - continue - } - - // Force option for empty interfaces and nullable types - _, force := tagOptions[ForceOptionName] - - // Valuer -> ptr - if isNullableType(srcFieldType.Type) && dstFieldValue.Kind() == reflect.Ptr && force { - // We have same nullable type on both sides - if srcFieldValue.Type().AssignableTo(dstFieldType.Type) { - dstFieldValue.Set(srcFieldValue) - continue - } - - v, _ := srcFieldValue.Interface().(driver.Valuer).Value() - if v == nil { - continue - } - - valueType := reflect.TypeOf(v) - - ptr := reflect.New(valueType) - ptr.Elem().Set(reflect.ValueOf(v)) - - if valueType.AssignableTo(dstFieldType.Type.Elem()) { - dstFieldValue.Set(ptr) - } - - continue - } - - // Valuer -> value - if isNullableType(srcFieldType.Type) { - // We have same nullable type on both sides - if srcFieldValue.Type().AssignableTo(dstFieldType.Type) { - dstFieldValue.Set(srcFieldValue) - continue - } - - if force { - v, _ := srcFieldValue.Interface().(driver.Valuer).Value() - if v == nil { - continue - } - - rv := reflect.ValueOf(v) - if rv.Type().AssignableTo(dstFieldType.Type) { - dstFieldValue.Set(rv) - } - } - - continue - } - - if dstFieldValue.Kind() == reflect.Interface { - if force { - dstFieldValue.Set(srcFieldValue) - } - continue - } - - // Ptr -> Value - if srcFieldType.Type.Kind() == reflect.Ptr && !srcFieldValue.IsNil() && dstFieldType.Type.Kind() != reflect.Ptr { - indirect := reflect.Indirect(srcFieldValue) - - if indirect.Type().AssignableTo(dstFieldType.Type) { - dstFieldValue.Set(indirect) - continue - } - } - - // Other types - if srcFieldType.Type.AssignableTo(dstFieldType.Type) { - dstFieldValue.Set(srcFieldValue) - } - } - - for _, m := range srcMethodNames { - name, opts := getRelatedField(dst, m) - if name == "" { - continue - } - - if _, ok := opts[SkipOptionName]; ok { - continue - } - - method := reflect.ValueOf(src).MethodByName(m) - if !method.IsValid() { - return fmt.Errorf("method %s is invalid", m) - } - - var ( - dstFieldType, _ = dstValue.Type().FieldByName(name) - dstFieldValue = dstValue.FieldByName(name) - _, withContext = opts[ContextOptionName] - _, force = opts[ForceOptionName] - ) - - args := []reflect.Value{} - if withContext { - args = []reflect.Value{reflect.ValueOf(options.Context)} - } - - var ( - result = method.Call(args)[0] - resultInterface = result.Interface() - resultValue = reflect.ValueOf(resultInterface) - resultType = resultValue.Type() - ) - - // Value -> Ptr - if dstFieldValue.Kind() == reflect.Ptr && force { - ptr := reflect.New(resultType) - ptr.Elem().Set(resultValue) - - if ptr.Type().AssignableTo(dstFieldType.Type) { - dstFieldValue.Set(ptr) - } - - continue - } - - // Ptr -> value - if resultValue.Kind() == reflect.Ptr && force { - if resultValue.Elem().Type().AssignableTo(dstFieldType.Type) { - dstFieldValue.Set(resultValue.Elem()) - } - - continue - } - - if resultType.AssignableTo(dstFieldType.Type) && result.IsValid() { - dstFieldValue.Set(result) - } - } - - return nil -} - -// getTagOptions parses deepcopier tag field and returns options. -func getTagOptions(value string) TagOptions { - options := TagOptions{} - - for _, opt := range strings.Split(value, ";") { - o := strings.Split(opt, ":") - - // deepcopier:"keyword; without; value;" - if len(o) == 1 { - options[o[0]] = "" - } - - // deepcopier:"key:value; anotherkey:anothervalue" - if len(o) == 2 { - options[strings.TrimSpace(o[0])] = strings.TrimSpace(o[1]) - } - } - - return options -} - -// getRelatedField returns first matching field. -func getRelatedField(instance interface{}, name string) (string, TagOptions) { - var ( - value = reflect.Indirect(reflect.ValueOf(instance)) - fieldName string - tagOptions TagOptions - ) - - for i := 0; i < value.NumField(); i++ { - var ( - vField = value.Field(i) - tField = value.Type().Field(i) - tagOptions = getTagOptions(tField.Tag.Get(TagName)) - ) - - if tField.Type.Kind() == reflect.Struct && tField.Anonymous { - if n, o := getRelatedField(vField.Interface(), name); n != "" { - return n, o - } - } - - if v, ok := tagOptions[FieldOptionName]; ok && v == name { - return tField.Name, tagOptions - } - - if tField.Name == name { - return tField.Name, tagOptions - } - } - - return fieldName, tagOptions -} - -// getMethodNames returns instance's method names. -func getMethodNames(instance interface{}) []string { - var methods []string - - t := reflect.TypeOf(instance) - for i := 0; i < t.NumMethod(); i++ { - methods = append(methods, t.Method(i).Name) - } - - return methods -} - -// getFieldNames returns instance's field names. -func getFieldNames(instance interface{}) []string { - var ( - fields []string - v = reflect.Indirect(reflect.ValueOf(instance)) - t = v.Type() - ) - - if t.Kind() != reflect.Struct { - return nil - } - - for i := 0; i < v.NumField(); i++ { - var ( - vField = v.Field(i) - tField = v.Type().Field(i) - ) - - // Is exportable? - if tField.PkgPath != "" { - continue - } - - if tField.Type.Kind() == reflect.Struct && tField.Anonymous { - fields = append(fields, getFieldNames(vField.Interface())...) - continue - } - - fields = append(fields, tField.Name) - } - - return fields -} - -// isNullableType returns true if the given type is a nullable one. -func isNullableType(t reflect.Type) bool { - return t.ConvertibleTo(reflect.TypeOf((*driver.Valuer)(nil)).Elem()) -} |