From caeaee5689d06f6881350504c750d26a2bcfd0d9 Mon Sep 17 00:00:00 2001 From: Sunil Arora Date: Mon, 27 Aug 2018 13:44:35 -0700 Subject: [PATCH] updated vendor deps to use versioned deps of controller-tools Highlights: - updated the vendor deps for the CLI - Pin to versioned pkg of controller-tools instead of master branch --- cmd/Gopkg.lock | 112 +++- cmd/Gopkg.toml | 46 +- .../github.com/Masterminds/semver/.travis.yml | 27 - .../Masterminds/semver/CHANGELOG.md | 86 --- .../github.com/Masterminds/semver/Makefile | 36 -- .../github.com/Masterminds/semver/README.md | 165 ------ .../Masterminds/semver/appveyor.yml | 44 -- .../Masterminds/semver/benchmark_test.go | 157 ------ .../Masterminds/semver/collection_test.go | 46 -- .../Masterminds/semver/constraints_test.go | 465 ----------------- .../Masterminds/semver/version_test.go | 490 ------------------ cmd/vendor/github.com/spf13/afero/LICENSE.txt | 174 +++++++ cmd/vendor/github.com/spf13/afero/afero.go | 108 ++++ cmd/vendor/github.com/spf13/afero/basepath.go | 180 +++++++ .../github.com/spf13/afero/cacheOnReadFs.go | 290 +++++++++++ .../github.com/spf13/afero/const_bsds.go | 22 + .../github.com/spf13/afero/const_win_unix.go | 25 + .../github.com/spf13/afero/copyOnWriteFs.go | 292 +++++++++++ cmd/vendor/github.com/spf13/afero/httpFs.go | 110 ++++ cmd/vendor/github.com/spf13/afero/ioutil.go | 230 ++++++++ cmd/vendor/github.com/spf13/afero/lstater.go | 27 + cmd/vendor/github.com/spf13/afero/match.go | 110 ++++ cmd/vendor/github.com/spf13/afero/mem/dir.go | 37 ++ .../github.com/spf13/afero/mem/dirmap.go | 43 ++ cmd/vendor/github.com/spf13/afero/mem/file.go | 317 +++++++++++ cmd/vendor/github.com/spf13/afero/memmap.go | 365 +++++++++++++ cmd/vendor/github.com/spf13/afero/os.go | 101 ++++ cmd/vendor/github.com/spf13/afero/path.go | 106 ++++ .../github.com/spf13/afero/readonlyfs.go | 80 +++ cmd/vendor/github.com/spf13/afero/regexpfs.go | 214 ++++++++ .../github.com/spf13/afero/sftpfs/file.go | 95 ++++ .../github.com/spf13/afero/sftpfs/sftp.go | 129 +++++ .../github.com/spf13/afero/unionFile.go | 305 +++++++++++ cmd/vendor/github.com/spf13/afero/util.go | 330 ++++++++++++ .../pkg/crd/generator/generator.go | 61 ++- .../generator/testData/cmd/manager/main.go | 58 +++ .../pkg/apis/addtoscheme_fun_v1alpha1.go | 25 + .../crd/generator/testData/pkg/apis/apis.go | 32 ++ .../generator/testData/pkg/apis/fun/group.go | 17 + .../testData/pkg/apis/fun/v1alpha1/doc.go | 22 + .../pkg/apis/fun/v1alpha1/register.go | 37 ++ .../pkg/apis/fun/v1alpha1/toy_types.go | 84 +++ .../fun/v1alpha1/zz_generated.deepcopy.go | 128 +++++ .../testData/pkg/controller/controller.go | 33 ++ .../controller-tools/pkg/crd/util/util.go | 22 +- .../pkg/internal/codegen/parse/apis.go | 4 +- .../pkg/internal/codegen/parse/controllers.go | 85 --- .../pkg/internal/codegen/parse/crd.go | 2 - .../pkg/internal/codegen/parse/parser.go | 101 +--- .../pkg/internal/codegen/parse/rbac.go | 134 ----- .../pkg/scaffold/project/gopkg.go | 212 +------- .../pkg/scaffold/project/makefile.go | 2 +- .../controller-tools/pkg/scaffold/scaffold.go | 2 +- .../controller-tools/pkg/util/util.go | 27 +- 54 files changed, 4324 insertions(+), 2128 deletions(-) delete mode 100644 cmd/vendor/github.com/Masterminds/semver/.travis.yml delete mode 100644 cmd/vendor/github.com/Masterminds/semver/CHANGELOG.md delete mode 100644 cmd/vendor/github.com/Masterminds/semver/Makefile delete mode 100644 cmd/vendor/github.com/Masterminds/semver/README.md delete mode 100644 cmd/vendor/github.com/Masterminds/semver/appveyor.yml delete mode 100644 cmd/vendor/github.com/Masterminds/semver/benchmark_test.go delete mode 100644 cmd/vendor/github.com/Masterminds/semver/collection_test.go delete mode 100644 cmd/vendor/github.com/Masterminds/semver/constraints_test.go delete mode 100644 cmd/vendor/github.com/Masterminds/semver/version_test.go create mode 100644 cmd/vendor/github.com/spf13/afero/LICENSE.txt create mode 100644 cmd/vendor/github.com/spf13/afero/afero.go create mode 100644 cmd/vendor/github.com/spf13/afero/basepath.go create mode 100644 cmd/vendor/github.com/spf13/afero/cacheOnReadFs.go create mode 100644 cmd/vendor/github.com/spf13/afero/const_bsds.go create mode 100644 cmd/vendor/github.com/spf13/afero/const_win_unix.go create mode 100644 cmd/vendor/github.com/spf13/afero/copyOnWriteFs.go create mode 100644 cmd/vendor/github.com/spf13/afero/httpFs.go create mode 100644 cmd/vendor/github.com/spf13/afero/ioutil.go create mode 100644 cmd/vendor/github.com/spf13/afero/lstater.go create mode 100644 cmd/vendor/github.com/spf13/afero/match.go create mode 100644 cmd/vendor/github.com/spf13/afero/mem/dir.go create mode 100644 cmd/vendor/github.com/spf13/afero/mem/dirmap.go create mode 100644 cmd/vendor/github.com/spf13/afero/mem/file.go create mode 100644 cmd/vendor/github.com/spf13/afero/memmap.go create mode 100644 cmd/vendor/github.com/spf13/afero/os.go create mode 100644 cmd/vendor/github.com/spf13/afero/path.go create mode 100644 cmd/vendor/github.com/spf13/afero/readonlyfs.go create mode 100644 cmd/vendor/github.com/spf13/afero/regexpfs.go create mode 100644 cmd/vendor/github.com/spf13/afero/sftpfs/file.go create mode 100644 cmd/vendor/github.com/spf13/afero/sftpfs/sftp.go create mode 100644 cmd/vendor/github.com/spf13/afero/unionFile.go create mode 100644 cmd/vendor/github.com/spf13/afero/util.go create mode 100644 cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/cmd/manager/main.go create mode 100644 cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/addtoscheme_fun_v1alpha1.go create mode 100644 cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/apis.go create mode 100644 cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/group.go create mode 100644 cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/doc.go create mode 100644 cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/register.go create mode 100644 cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/toy_types.go create mode 100644 cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/zz_generated.deepcopy.go create mode 100644 cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/controller/controller.go delete mode 100644 cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/controllers.go delete mode 100644 cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/rbac.go diff --git a/cmd/Gopkg.lock b/cmd/Gopkg.lock index 778ca5142e..0c6ab5cf4b 100644 --- a/cmd/Gopkg.lock +++ b/cmd/Gopkg.lock @@ -2,89 +2,127 @@ [[projects]] + digest = "1:a26f8da48b22e6176c1c6a2459904bb30bd0c49ada04b2963c2c3a203e81a620" name = "github.com/Masterminds/semver" packages = ["."] + pruneopts = "NT" revision = "c7af12943936e8c39859482e61f0574c2fd7fc75" version = "v1.4.2" [[projects]] + digest = "1:81466b4218bf6adddac2572a30ac733a9255919bc2f470b4827a317bd4ee1756" name = "github.com/ghodss/yaml" packages = ["."] + pruneopts = "NT" revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" version = "v1.0.0" [[projects]] + digest = "1:bdd9f217558ee887966977cbcb507347f47c595f63797b938c002bc9e26e8d16" name = "github.com/gobuffalo/envy" packages = ["."] + pruneopts = "NT" revision = "2d0f467653f3d961ce9ada4d32a230bdcb3bfe11" version = "v1.6.3" [[projects]] + digest = "1:fc5eb28d80d93864aeecba8e387bb994d21f75ec9f0b070f141f36dac7bada98" name = "github.com/gogo/protobuf" packages = [ "proto", - "sortkeys" + "sortkeys", ] + pruneopts = "NT" revision = "1adfc126b41513cc696b209667c8656ea7aac67c" version = "v1.0.0" [[projects]] + digest = "1:78b8040ece2ff622580def2708b9eb0b2857711b6744c475439bf337e9c677ea" name = "github.com/golang/glog" packages = ["."] + pruneopts = "NT" revision = "44145f04b68cf362d9c4df2182967c2275eaefed" [[projects]] branch = "master" + digest = "1:52c5834e2bebac9030c97cc0798ac11c3aa8a39f098aeb419f142533da6cd3cc" name = "github.com/google/gofuzz" packages = ["."] + pruneopts = "NT" revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1" [[projects]] + digest = "1:406338ad39ab2e37b7f4452906442a3dbf0eb3379dd1f06aafb5c07e769a5fbb" name = "github.com/inconshreveable/mousetrap" packages = ["."] + pruneopts = "NT" revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" version = "v1.0" [[projects]] + digest = "1:7048335faaa24ba4f2943b15903666cfa4f2fd14adf10520cd2bd3dbac01b770" name = "github.com/joho/godotenv" packages = ["."] + pruneopts = "NT" revision = "a79fa1e548e2c689c241d10173efd51e5d689d5b" version = "v1.2.0" [[projects]] branch = "master" + digest = "1:24608ad934c247c3903eeaccb58ab7d6360a9bccafe1a6393756d0820f9950f9" name = "github.com/markbates/inflect" packages = ["."] + pruneopts = "NT" revision = "84854b5b4c0dbb0c107480d480a71f7db1fc7dae" [[projects]] + digest = "1:f26ba12e3509cccba1e9afadeb142fcd3b6a7a89073cbb147431536715d87f72" name = "github.com/pkg/errors" packages = ["."] + pruneopts = "NT" revision = "a22138067af1c4942683050411a841ade67fe1eb" [[projects]] + digest = "1:2a7c79c506479dc73c0100982a40bacc89e06d96dc458eb41c9b6aa44d9e0b6d" + name = "github.com/spf13/afero" + packages = [ + ".", + "mem", + ] + pruneopts = "NT" + revision = "787d034dfe70e44075ccc060d346146ef53270ad" + version = "v1.1.1" + +[[projects]] + digest = "1:17fb0c5e7f7df714f7e3ff6419a714a6a81d580c22e9aeb38acfe3b1cdeab824" name = "github.com/spf13/cobra" packages = ["."] + pruneopts = "NT" revision = "f62e98d28ab7ad31d707ba837a966378465c7b57" [[projects]] + digest = "1:15e5c398fbd9d2c439b635a08ac161b13d04f0c2aa587fe256b65dc0c3efe8b7" name = "github.com/spf13/pflag" packages = ["."] + pruneopts = "NT" revision = "583c0c0531f06d5278b7d917446061adc344b5cd" version = "v1.0.1" [[projects]] branch = "master" + digest = "1:0ccbd3b459d7977ed04b6688b22a874874176e74e31f5663e25ca61ac8e38b70" name = "golang.org/x/net" packages = [ "http/httpguts", "http2", "http2/hpack", - "idna" + "idna", ] + pruneopts = "NT" revision = "cffdcf672aee934982473246bc7e9a8ba446aa9b" [[projects]] + digest = "1:8c74f97396ed63cc2ef04ebb5fc37bb032871b8fd890a25991ed40974b00cd2a" name = "golang.org/x/text" packages = [ "collate", @@ -100,53 +138,65 @@ "unicode/bidi", "unicode/cldr", "unicode/norm", - "unicode/rangetable" + "unicode/rangetable", ] + pruneopts = "NT" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] branch = "master" + digest = "1:01539dc7a411cab980c02b6e59cfb655184247c0c3d4710e8e70cbf2e562cb26" name = "golang.org/x/tools" packages = [ "go/ast/astutil", "imports", - "internal/fastwalk" + "internal/fastwalk", ] + pruneopts = "NT" revision = "2087f8c10712366cfc2f4fcb1bf99eeef61ab21e" [[projects]] + digest = "1:2d1fbdc6777e5408cabeb02bf336305e724b925ff4546ded0fa8715a7267922a" name = "gopkg.in/inf.v0" packages = ["."] + pruneopts = "NT" revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf" version = "v0.9.1" [[projects]] + digest = "1:7c95b35057a0ff2e19f707173cc1a947fa43a6eb5c4d300d196ece0334046082" name = "gopkg.in/yaml.v2" packages = ["."] + pruneopts = "NT" revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" version = "v2.2.1" [[projects]] + digest = "1:6b4ae148679d49dda5e1f7026701662758701b6cbd144cc8db1769710a01c4d2" name = "k8s.io/api" packages = [ "apps/v1", "core/v1", - "rbac/v1" + "rbac/v1", ] + pruneopts = "NT" revision = "73d903622b7391f3312dcbac6483fed484e185f8" version = "kubernetes-1.10.0" [[projects]] + digest = "1:0a30c7cce6e0ec50da6d5448b6e9ddae5c968143df3f89f2f507c7cc7e3bd226" name = "k8s.io/apiextensions-apiserver" packages = [ "pkg/apis/apiextensions", - "pkg/apis/apiextensions/v1beta1" + "pkg/apis/apiextensions/v1beta1", ] + pruneopts = "NT" revision = "4347b330d0ff094db860f2f75fa725b4f4b53618" version = "kubernetes-1.10.1" [[projects]] + digest = "1:f9f9f2c6c29573e8248c3fed2fd83119fb050b8e021875bee29ce302c1783c03" name = "k8s.io/apimachinery" packages = [ "pkg/api/resource", @@ -169,37 +219,44 @@ "pkg/util/validation/field", "pkg/util/wait", "pkg/watch", - "third_party/forked/golang/reflect" + "third_party/forked/golang/reflect", ] + pruneopts = "NT" revision = "302974c03f7e50f16561ba237db776ab93594ef6" version = "kubernetes-1.10.0" [[projects]] + digest = "1:b98460f5a530d62c99db22e2c50556571b93b0acd279a51cf1fd469518915c41" name = "k8s.io/apiserver" packages = ["pkg/util/logs"] + pruneopts = "NT" revision = "06e4be4fafa2c9356e02424aac4e714e2ebeff60" version = "kubernetes-1.10.1" [[projects]] + digest = "1:65486e65828b157536291fe8d3c4c06dd60ea8c053543680a8f06c3754fe92a6" name = "k8s.io/client-go" packages = ["util/homedir"] + pruneopts = "NT" revision = "989be4278f353e42f26c416c53757d16fcff77db" version = "kubernetes-1.10.1" [[projects]] branch = "master" + digest = "1:2701cf2b017bde402587b0e38ed3d2193e058a42eb49cd03a0f72480f8a67096" name = "k8s.io/gengo" packages = [ "args", "generator", "namer", "parser", - "types" + "types", ] + pruneopts = "NT" revision = "fdcf9f9480fdd5bf2b3c3df9bf4ecd22b25b87e2" [[projects]] - branch = "master" + digest = "1:30621a2b23b5cfc672d3130350a9aa5449724d47899705b16e33ec994f806c4c" name = "sigs.k8s.io/controller-tools" packages = [ "pkg/scaffold", @@ -208,13 +265,44 @@ "pkg/scaffold/manager", "pkg/scaffold/project", "pkg/scaffold/resource", - "pkg/util" + "pkg/util", ] - revision = "ade554d58413a7b2327cf38fde98484e23e66c82" + pruneopts = "NT" + revision = "a92b5ff3ebb5767eb3d8344bd097a95863e52c3f" + version = "v0.1.2" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "475f5f0a899cbffb136a7173a0fcb0a18d13580717b537c7413264544542e3d1" + input-imports = [ + "github.com/Masterminds/semver", + "github.com/ghodss/yaml", + "github.com/golang/glog", + "github.com/markbates/inflect", + "github.com/pkg/errors", + "github.com/spf13/cobra", + "github.com/spf13/pflag", + "k8s.io/api/apps/v1", + "k8s.io/api/core/v1", + "k8s.io/api/rbac/v1", + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1", + "k8s.io/apimachinery/pkg/api/resource", + "k8s.io/apimachinery/pkg/apis/meta/v1", + "k8s.io/apimachinery/pkg/runtime/schema", + "k8s.io/apimachinery/pkg/util/sets", + "k8s.io/apiserver/pkg/util/logs", + "k8s.io/client-go/util/homedir", + "k8s.io/gengo/args", + "k8s.io/gengo/generator", + "k8s.io/gengo/namer", + "k8s.io/gengo/parser", + "k8s.io/gengo/types", + "sigs.k8s.io/controller-tools/pkg/scaffold", + "sigs.k8s.io/controller-tools/pkg/scaffold/controller", + "sigs.k8s.io/controller-tools/pkg/scaffold/input", + "sigs.k8s.io/controller-tools/pkg/scaffold/manager", + "sigs.k8s.io/controller-tools/pkg/scaffold/project", + "sigs.k8s.io/controller-tools/pkg/scaffold/resource", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/cmd/Gopkg.toml b/cmd/Gopkg.toml index 0ed0e44491..bbb2ebb12a 100644 --- a/cmd/Gopkg.toml +++ b/cmd/Gopkg.toml @@ -5,49 +5,5 @@ go-tests = true [[constraint]] - name = "github.com/emicklei/go-restful" - revision = "ff4f55a206334ef123e4f79bbf348980da81ca46" - -[[constraint]] - name = "github.com/golang/glog" - revision = "44145f04b68cf362d9c4df2182967c2275eaefed" - -[[constraint]] - branch = "master" - name = "github.com/markbates/inflect" - -[[constraint]] - name = "github.com/pkg/errors" - revision = "a22138067af1c4942683050411a841ade67fe1eb" - -[[constraint]] - name = "github.com/spf13/cobra" - revision = "f62e98d28ab7ad31d707ba837a966378465c7b57" - -[[constraint]] - version = "kubernetes-1.10.1" - name = "k8s.io/api" - -[[constraint]] - version = "kubernetes-1.10.1" - name = "k8s.io/apiextensions-apiserver" - -[[constraint]] - version = "kubernetes-1.10.1" - name = "k8s.io/apimachinery" - -[[constraint]] - version = "kubernetes-1.10.1" - name = "k8s.io/apiserver" - -[[constraint]] - version = "kubernetes-1.10.1" - name = "k8s.io/client-go" - -[[constraint]] - branch = "master" name = "sigs.k8s.io/controller-tools" - -[[constraint]] - name = "github.com/Masterminds/semver" - version = "1.4.2" + version="v0.1.1" diff --git a/cmd/vendor/github.com/Masterminds/semver/.travis.yml b/cmd/vendor/github.com/Masterminds/semver/.travis.yml deleted file mode 100644 index 3d9ebadb93..0000000000 --- a/cmd/vendor/github.com/Masterminds/semver/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: go - -go: - - 1.6.x - - 1.7.x - - 1.8.x - - 1.9.x - - 1.10.x - - tip - -# Setting sudo access to false will let Travis CI use containers rather than -# VMs to run the tests. For more details see: -# - http://docs.travis-ci.com/user/workers/container-based-infrastructure/ -# - http://docs.travis-ci.com/user/workers/standard-infrastructure/ -sudo: false - -script: - - make setup - - make test - -notifications: - webhooks: - urls: - - https://webhooks.gitter.im/e/06e3328629952dabe3e0 - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: never # options: [always|never|change] default: always diff --git a/cmd/vendor/github.com/Masterminds/semver/CHANGELOG.md b/cmd/vendor/github.com/Masterminds/semver/CHANGELOG.md deleted file mode 100644 index b888e20aba..0000000000 --- a/cmd/vendor/github.com/Masterminds/semver/CHANGELOG.md +++ /dev/null @@ -1,86 +0,0 @@ -# 1.4.2 (2018-04-10) - -## Changed -- #72: Updated the docs to point to vert for a console appliaction -- #71: Update the docs on pre-release comparator handling - -## Fixed -- #70: Fix the handling of pre-releases and the 0.0.0 release edge case - -# 1.4.1 (2018-04-02) - -## Fixed -- Fixed #64: Fix pre-release precedence issue (thanks @uudashr) - -# 1.4.0 (2017-10-04) - -## Changed -- #61: Update NewVersion to parse ints with a 64bit int size (thanks @zknill) - -# 1.3.1 (2017-07-10) - -## Fixed -- Fixed #57: number comparisons in prerelease sometimes inaccurate - -# 1.3.0 (2017-05-02) - -## Added -- #45: Added json (un)marshaling support (thanks @mh-cbon) -- Stability marker. See https://masterminds.github.io/stability/ - -## Fixed -- #51: Fix handling of single digit tilde constraint (thanks @dgodd) - -## Changed -- #55: The godoc icon moved from png to svg - -# 1.2.3 (2017-04-03) - -## Fixed -- #46: Fixed 0.x.x and 0.0.x in constraints being treated as * - -# Release 1.2.2 (2016-12-13) - -## Fixed -- #34: Fixed issue where hyphen range was not working with pre-release parsing. - -# Release 1.2.1 (2016-11-28) - -## Fixed -- #24: Fixed edge case issue where constraint "> 0" does not handle "0.0.1-alpha" - properly. - -# Release 1.2.0 (2016-11-04) - -## Added -- #20: Added MustParse function for versions (thanks @adamreese) -- #15: Added increment methods on versions (thanks @mh-cbon) - -## Fixed -- Issue #21: Per the SemVer spec (section 9) a pre-release is unstable and - might not satisfy the intended compatibility. The change here ignores pre-releases - on constraint checks (e.g., ~ or ^) when a pre-release is not part of the - constraint. For example, `^1.2.3` will ignore pre-releases while - `^1.2.3-alpha` will include them. - -# Release 1.1.1 (2016-06-30) - -## Changed -- Issue #9: Speed up version comparison performance (thanks @sdboyer) -- Issue #8: Added benchmarks (thanks @sdboyer) -- Updated Go Report Card URL to new location -- Updated Readme to add code snippet formatting (thanks @mh-cbon) -- Updating tagging to v[SemVer] structure for compatibility with other tools. - -# Release 1.1.0 (2016-03-11) - -- Issue #2: Implemented validation to provide reasons a versions failed a - constraint. - -# Release 1.0.1 (2015-12-31) - -- Fixed #1: * constraint failing on valid versions. - -# Release 1.0.0 (2015-10-20) - -- Initial release diff --git a/cmd/vendor/github.com/Masterminds/semver/Makefile b/cmd/vendor/github.com/Masterminds/semver/Makefile deleted file mode 100644 index a7a1b4e36d..0000000000 --- a/cmd/vendor/github.com/Masterminds/semver/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -.PHONY: setup -setup: - go get -u gopkg.in/alecthomas/gometalinter.v1 - gometalinter.v1 --install - -.PHONY: test -test: validate lint - @echo "==> Running tests" - go test -v - -.PHONY: validate -validate: - @echo "==> Running static validations" - @gometalinter.v1 \ - --disable-all \ - --enable deadcode \ - --severity deadcode:error \ - --enable gofmt \ - --enable gosimple \ - --enable ineffassign \ - --enable misspell \ - --enable vet \ - --tests \ - --vendor \ - --deadline 60s \ - ./... || exit_code=1 - -.PHONY: lint -lint: - @echo "==> Running linters" - @gometalinter.v1 \ - --disable-all \ - --enable golint \ - --vendor \ - --deadline 60s \ - ./... || : diff --git a/cmd/vendor/github.com/Masterminds/semver/README.md b/cmd/vendor/github.com/Masterminds/semver/README.md deleted file mode 100644 index 3e934ed71e..0000000000 --- a/cmd/vendor/github.com/Masterminds/semver/README.md +++ /dev/null @@ -1,165 +0,0 @@ -# SemVer - -The `semver` package provides the ability to work with [Semantic Versions](http://semver.org) in Go. Specifically it provides the ability to: - -* Parse semantic versions -* Sort semantic versions -* Check if a semantic version fits within a set of constraints -* Optionally work with a `v` prefix - -[![Stability: -Active](https://masterminds.github.io/stability/active.svg)](https://masterminds.github.io/stability/active.html) -[![Build Status](https://travis-ci.org/Masterminds/semver.svg)](https://travis-ci.org/Masterminds/semver) [![Build status](https://ci.appveyor.com/api/projects/status/jfk66lib7hb985k8/branch/master?svg=true&passingText=windows%20build%20passing&failingText=windows%20build%20failing)](https://ci.appveyor.com/project/mattfarina/semver/branch/master) [![GoDoc](https://godoc.org/github.com/Masterminds/semver?status.svg)](https://godoc.org/github.com/Masterminds/semver) [![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/semver)](https://goreportcard.com/report/github.com/Masterminds/semver) - -## Parsing Semantic Versions - -To parse a semantic version use the `NewVersion` function. For example, - -```go - v, err := semver.NewVersion("1.2.3-beta.1+build345") -``` - -If there is an error the version wasn't parseable. The version object has methods -to get the parts of the version, compare it to other versions, convert the -version back into a string, and get the original string. For more details -please see the [documentation](https://godoc.org/github.com/Masterminds/semver). - -## Sorting Semantic Versions - -A set of versions can be sorted using the [`sort`](https://golang.org/pkg/sort/) -package from the standard library. For example, - -```go - raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",} - vs := make([]*semver.Version, len(raw)) - for i, r := range raw { - v, err := semver.NewVersion(r) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - - vs[i] = v - } - - sort.Sort(semver.Collection(vs)) -``` - -## Checking Version Constraints - -Checking a version against version constraints is one of the most featureful -parts of the package. - -```go - c, err := semver.NewConstraint(">= 1.2.3") - if err != nil { - // Handle constraint not being parseable. - } - - v, _ := semver.NewVersion("1.3") - if err != nil { - // Handle version not being parseable. - } - // Check if the version meets the constraints. The a variable will be true. - a := c.Check(v) -``` - -## Basic Comparisons - -There are two elements to the comparisons. First, a comparison string is a list -of comma separated and comparisons. These are then separated by || separated or -comparisons. For example, `">= 1.2, < 3.0.0 || >= 4.2.3"` is looking for a -comparison that's greater than or equal to 1.2 and less than 3.0.0 or is -greater than or equal to 4.2.3. - -The basic comparisons are: - -* `=`: equal (aliased to no operator) -* `!=`: not equal -* `>`: greater than -* `<`: less than -* `>=`: greater than or equal to -* `<=`: less than or equal to - -_Note, according to the Semantic Version specification pre-releases may not be -API compliant with their release counterpart. It says,_ - -> _A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version._ - -_SemVer comparisons without a pre-release value will skip pre-release versions. -For example, `>1.2.3` will skip pre-releases when looking at a list of values -while `>1.2.3-alpha.1` will evaluate pre-releases._ - -## Hyphen Range Comparisons - -There are multiple methods to handle ranges and the first is hyphens ranges. -These look like: - -* `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5` -* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4, <= 4.5` - -## Wildcards In Comparisons - -The `x`, `X`, and `*` characters can be used as a wildcard character. This works -for all comparison operators. When used on the `=` operator it falls -back to the pack level comparison (see tilde below). For example, - -* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` -* `>= 1.2.x` is equivalent to `>= 1.2.0` -* `<= 2.x` is equivalent to `<= 3` -* `*` is equivalent to `>= 0.0.0` - -## Tilde Range Comparisons (Patch) - -The tilde (`~`) comparison operator is for patch level ranges when a minor -version is specified and major level changes when the minor number is missing. -For example, - -* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0` -* `~1` is equivalent to `>= 1, < 2` -* `~2.3` is equivalent to `>= 2.3, < 2.4` -* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` -* `~1.x` is equivalent to `>= 1, < 2` - -## Caret Range Comparisons (Major) - -The caret (`^`) comparison operator is for major level changes. This is useful -when comparisons of API versions as a major change is API breaking. For example, - -* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0` -* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0` -* `^2.3` is equivalent to `>= 2.3, < 3` -* `^2.x` is equivalent to `>= 2.0.0, < 3` - -# Validation - -In addition to testing a version against a constraint, a version can be validated -against a constraint. When validation fails a slice of errors containing why a -version didn't meet the constraint is returned. For example, - -```go - c, err := semver.NewConstraint("<= 1.2.3, >= 1.4") - if err != nil { - // Handle constraint not being parseable. - } - - v, _ := semver.NewVersion("1.3") - if err != nil { - // Handle version not being parseable. - } - - // Validate a version against a constraint. - a, msgs := c.Validate(v) - // a is false - for _, m := range msgs { - fmt.Println(m) - - // Loops over the errors which would read - // "1.3 is greater than 1.2.3" - // "1.3 is less than 1.4" - } -``` - -# Contribute - -If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues) -or [create a pull request](https://github.com/Masterminds/semver/pulls). diff --git a/cmd/vendor/github.com/Masterminds/semver/appveyor.yml b/cmd/vendor/github.com/Masterminds/semver/appveyor.yml deleted file mode 100644 index b2778df15a..0000000000 --- a/cmd/vendor/github.com/Masterminds/semver/appveyor.yml +++ /dev/null @@ -1,44 +0,0 @@ -version: build-{build}.{branch} - -clone_folder: C:\gopath\src\github.com\Masterminds\semver -shallow_clone: true - -environment: - GOPATH: C:\gopath - -platform: - - x64 - -install: - - go version - - go env - - go get -u gopkg.in/alecthomas/gometalinter.v1 - - set PATH=%PATH%;%GOPATH%\bin - - gometalinter.v1.exe --install - -build_script: - - go install -v ./... - -test_script: - - "gometalinter.v1 \ - --disable-all \ - --enable deadcode \ - --severity deadcode:error \ - --enable gofmt \ - --enable gosimple \ - --enable ineffassign \ - --enable misspell \ - --enable vet \ - --tests \ - --vendor \ - --deadline 60s \ - ./... || exit_code=1" - - "gometalinter.v1 \ - --disable-all \ - --enable golint \ - --vendor \ - --deadline 60s \ - ./... || :" - - go test -v - -deploy: off diff --git a/cmd/vendor/github.com/Masterminds/semver/benchmark_test.go b/cmd/vendor/github.com/Masterminds/semver/benchmark_test.go deleted file mode 100644 index 58a5c289f4..0000000000 --- a/cmd/vendor/github.com/Masterminds/semver/benchmark_test.go +++ /dev/null @@ -1,157 +0,0 @@ -package semver_test - -import ( - "testing" - - "github.com/Masterminds/semver" -) - -/* Constraint creation benchmarks */ - -func benchNewConstraint(c string, b *testing.B) { - for i := 0; i < b.N; i++ { - semver.NewConstraint(c) - } -} - -func BenchmarkNewConstraintUnary(b *testing.B) { - benchNewConstraint("=2.0", b) -} - -func BenchmarkNewConstraintTilde(b *testing.B) { - benchNewConstraint("~2.0.0", b) -} - -func BenchmarkNewConstraintCaret(b *testing.B) { - benchNewConstraint("^2.0.0", b) -} - -func BenchmarkNewConstraintWildcard(b *testing.B) { - benchNewConstraint("1.x", b) -} - -func BenchmarkNewConstraintRange(b *testing.B) { - benchNewConstraint(">=2.1.x, <3.1.0", b) -} - -func BenchmarkNewConstraintUnion(b *testing.B) { - benchNewConstraint("~2.0.0 || =3.1.0", b) -} - -/* Check benchmarks */ - -func benchCheckVersion(c, v string, b *testing.B) { - version, _ := semver.NewVersion(v) - constraint, _ := semver.NewConstraint(c) - - for i := 0; i < b.N; i++ { - constraint.Check(version) - } -} - -func BenchmarkCheckVersionUnary(b *testing.B) { - benchCheckVersion("=2.0", "2.0.0", b) -} - -func BenchmarkCheckVersionTilde(b *testing.B) { - benchCheckVersion("~2.0.0", "2.0.5", b) -} - -func BenchmarkCheckVersionCaret(b *testing.B) { - benchCheckVersion("^2.0.0", "2.1.0", b) -} - -func BenchmarkCheckVersionWildcard(b *testing.B) { - benchCheckVersion("1.x", "1.4.0", b) -} - -func BenchmarkCheckVersionRange(b *testing.B) { - benchCheckVersion(">=2.1.x, <3.1.0", "2.4.5", b) -} - -func BenchmarkCheckVersionUnion(b *testing.B) { - benchCheckVersion("~2.0.0 || =3.1.0", "3.1.0", b) -} - -func benchValidateVersion(c, v string, b *testing.B) { - version, _ := semver.NewVersion(v) - constraint, _ := semver.NewConstraint(c) - - for i := 0; i < b.N; i++ { - constraint.Validate(version) - } -} - -/* Validate benchmarks, including fails */ - -func BenchmarkValidateVersionUnary(b *testing.B) { - benchValidateVersion("=2.0", "2.0.0", b) -} - -func BenchmarkValidateVersionUnaryFail(b *testing.B) { - benchValidateVersion("=2.0", "2.0.1", b) -} - -func BenchmarkValidateVersionTilde(b *testing.B) { - benchValidateVersion("~2.0.0", "2.0.5", b) -} - -func BenchmarkValidateVersionTildeFail(b *testing.B) { - benchValidateVersion("~2.0.0", "1.0.5", b) -} - -func BenchmarkValidateVersionCaret(b *testing.B) { - benchValidateVersion("^2.0.0", "2.1.0", b) -} - -func BenchmarkValidateVersionCaretFail(b *testing.B) { - benchValidateVersion("^2.0.0", "4.1.0", b) -} - -func BenchmarkValidateVersionWildcard(b *testing.B) { - benchValidateVersion("1.x", "1.4.0", b) -} - -func BenchmarkValidateVersionWildcardFail(b *testing.B) { - benchValidateVersion("1.x", "2.4.0", b) -} - -func BenchmarkValidateVersionRange(b *testing.B) { - benchValidateVersion(">=2.1.x, <3.1.0", "2.4.5", b) -} - -func BenchmarkValidateVersionRangeFail(b *testing.B) { - benchValidateVersion(">=2.1.x, <3.1.0", "1.4.5", b) -} - -func BenchmarkValidateVersionUnion(b *testing.B) { - benchValidateVersion("~2.0.0 || =3.1.0", "3.1.0", b) -} - -func BenchmarkValidateVersionUnionFail(b *testing.B) { - benchValidateVersion("~2.0.0 || =3.1.0", "3.1.1", b) -} - -/* Version creation benchmarks */ - -func benchNewVersion(v string, b *testing.B) { - for i := 0; i < b.N; i++ { - semver.NewVersion(v) - } -} - -func BenchmarkNewVersionSimple(b *testing.B) { - benchNewVersion("1.0.0", b) -} - -func BenchmarkNewVersionPre(b *testing.B) { - benchNewVersion("1.0.0-alpha", b) -} - -func BenchmarkNewVersionMeta(b *testing.B) { - benchNewVersion("1.0.0+metadata", b) -} - -func BenchmarkNewVersionMetaDash(b *testing.B) { - benchNewVersion("1.0.0+metadata-dash", b) -} diff --git a/cmd/vendor/github.com/Masterminds/semver/collection_test.go b/cmd/vendor/github.com/Masterminds/semver/collection_test.go deleted file mode 100644 index 71b909c4e0..0000000000 --- a/cmd/vendor/github.com/Masterminds/semver/collection_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package semver - -import ( - "reflect" - "sort" - "testing" -) - -func TestCollection(t *testing.T) { - raw := []string{ - "1.2.3", - "1.0", - "1.3", - "2", - "0.4.2", - } - - vs := make([]*Version, len(raw)) - for i, r := range raw { - v, err := NewVersion(r) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - - vs[i] = v - } - - sort.Sort(Collection(vs)) - - e := []string{ - "0.4.2", - "1.0.0", - "1.2.3", - "1.3.0", - "2.0.0", - } - - a := make([]string, len(vs)) - for i, v := range vs { - a[i] = v.String() - } - - if !reflect.DeepEqual(a, e) { - t.Error("Sorting Collection failed") - } -} diff --git a/cmd/vendor/github.com/Masterminds/semver/constraints_test.go b/cmd/vendor/github.com/Masterminds/semver/constraints_test.go deleted file mode 100644 index bf52c90bd2..0000000000 --- a/cmd/vendor/github.com/Masterminds/semver/constraints_test.go +++ /dev/null @@ -1,465 +0,0 @@ -package semver - -import ( - "reflect" - "testing" -) - -func TestParseConstraint(t *testing.T) { - tests := []struct { - in string - f cfunc - v string - err bool - }{ - {">= 1.2", constraintGreaterThanEqual, "1.2.0", false}, - {"1.0", constraintTildeOrEqual, "1.0.0", false}, - {"foo", nil, "", true}, - {"<= 1.2", constraintLessThanEqual, "1.2.0", false}, - {"=< 1.2", constraintLessThanEqual, "1.2.0", false}, - {"=> 1.2", constraintGreaterThanEqual, "1.2.0", false}, - {"v1.2", constraintTildeOrEqual, "1.2.0", false}, - {"=1.5", constraintTildeOrEqual, "1.5.0", false}, - {"> 1.3", constraintGreaterThan, "1.3.0", false}, - {"< 1.4.1", constraintLessThan, "1.4.1", false}, - } - - for _, tc := range tests { - c, err := parseConstraint(tc.in) - if tc.err && err == nil { - t.Errorf("Expected error for %s didn't occur", tc.in) - } else if !tc.err && err != nil { - t.Errorf("Unexpected error for %s", tc.in) - } - - // If an error was expected continue the loop and don't try the other - // tests as they will cause errors. - if tc.err { - continue - } - - if tc.v != c.con.String() { - t.Errorf("Incorrect version found on %s", tc.in) - } - - f1 := reflect.ValueOf(tc.f) - f2 := reflect.ValueOf(c.function) - if f1 != f2 { - t.Errorf("Wrong constraint found for %s", tc.in) - } - } -} - -func TestConstraintCheck(t *testing.T) { - tests := []struct { - constraint string - version string - check bool - }{ - {"= 2.0", "1.2.3", false}, - {"= 2.0", "2.0.0", true}, - {"4.1", "4.1.0", true}, - {"!=4.1", "4.1.0", false}, - {"!=4.1", "5.1.0", true}, - {">1.1", "4.1.0", true}, - {">1.1", "1.1.0", false}, - {"<1.1", "0.1.0", true}, - {"<1.1", "1.1.0", false}, - {"<1.1", "1.1.1", false}, - {">=1.1", "4.1.0", true}, - {">=1.1", "1.1.0", true}, - {">=1.1", "0.0.9", false}, - {"<=1.1", "0.1.0", true}, - {"<=1.1", "1.1.0", true}, - {"<=1.1", "1.1.1", false}, - {">0", "0.0.1-alpha", true}, - {">=0", "0.0.1-alpha", true}, - {">0", "0", false}, - {">=0", "0", true}, - {"=0", "1", false}, - } - - for _, tc := range tests { - c, err := parseConstraint(tc.constraint) - if err != nil { - t.Errorf("err: %s", err) - continue - } - - v, err := NewVersion(tc.version) - if err != nil { - t.Errorf("err: %s", err) - continue - } - - a := c.check(v) - if a != tc.check { - t.Errorf("Constraint %q failing with %q", tc.constraint, tc.version) - } - } -} - -func TestNewConstraint(t *testing.T) { - tests := []struct { - input string - ors int - count int - err bool - }{ - {">= 1.1", 1, 1, false}, - {"2.0", 1, 1, false}, - {"v2.3.5-20161202202307-sha.e8fc5e5", 1, 1, false}, - {">= bar", 0, 0, true}, - {">= 1.2.3, < 2.0", 1, 2, false}, - {">= 1.2.3, < 2.0 || => 3.0, < 4", 2, 2, false}, - - // The 3 - 4 should be broken into 2 by the range rewriting - {"3 - 4 || => 3.0, < 4", 2, 2, false}, - } - - for _, tc := range tests { - v, err := NewConstraint(tc.input) - if tc.err && err == nil { - t.Errorf("expected but did not get error for: %s", tc.input) - continue - } else if !tc.err && err != nil { - t.Errorf("unexpectederror for input %s: %s", tc.input, err) - continue - } - if tc.err { - continue - } - - l := len(v.constraints) - if tc.ors != l { - t.Errorf("Expected %s to have %d ORs but got %d", - tc.input, tc.ors, l) - } - - l = len(v.constraints[0]) - if tc.count != l { - t.Errorf("Expected %s to have %d constraints but got %d", - tc.input, tc.count, l) - } - } -} - -func TestConstraintsCheck(t *testing.T) { - tests := []struct { - constraint string - version string - check bool - }{ - {"*", "1.2.3", true}, - {"~0.0.0", "1.2.3", true}, - {"0.x.x", "1.2.3", false}, - {"0.0.x", "1.2.3", false}, - {"0.0.0", "1.2.3", false}, - {"*", "1.2.3", true}, - {"^0.0.0", "1.2.3", false}, - {"= 2.0", "1.2.3", false}, - {"= 2.0", "2.0.0", true}, - {"4.1", "4.1.0", true}, - {"4.1.x", "4.1.3", true}, - {"1.x", "1.4", true}, - {"!=4.1", "4.1.0", false}, - {"!=4.1-alpha", "4.1.0-alpha", false}, - {"!=4.1-alpha", "4.1.0", true}, - {"!=4.1", "5.1.0", true}, - {"!=4.x", "5.1.0", true}, - {"!=4.x", "4.1.0", false}, - {"!=4.1.x", "4.2.0", true}, - {"!=4.2.x", "4.2.3", false}, - {">1.1", "4.1.0", true}, - {">1.1", "1.1.0", false}, - {"<1.1", "0.1.0", true}, - {"<1.1", "1.1.0", false}, - {"<1.1", "1.1.1", false}, - {"<1.x", "1.1.1", true}, - {"<1.x", "2.1.1", false}, - {"<1.1.x", "1.2.1", false}, - {"<1.1.x", "1.1.500", true}, - {"<1.2.x", "1.1.1", true}, - {">=1.1", "4.1.0", true}, - {">=1.1", "4.1.0-beta", false}, - {">=1.1", "1.1.0", true}, - {">=1.1", "0.0.9", false}, - {"<=1.1", "0.1.0", true}, - {"<=1.1", "0.1.0-alpha", false}, - {"<=1.1-a", "0.1.0-alpha", true}, - {"<=1.1", "1.1.0", true}, - {"<=1.x", "1.1.0", true}, - {"<=2.x", "3.1.0", false}, - {"<=1.1", "1.1.1", false}, - {"<=1.1.x", "1.2.500", false}, - {">1.1, <2", "1.1.1", true}, - {">1.1, <3", "4.3.2", false}, - {">=1.1, <2, !=1.2.3", "1.2.3", false}, - {">=1.1, <2, !=1.2.3 || > 3", "3.1.2", true}, - {">=1.1, <2, !=1.2.3 || >= 3", "3.0.0", true}, - {">=1.1, <2, !=1.2.3 || > 3", "3.0.0", false}, - {">=1.1, <2, !=1.2.3 || > 3", "1.2.3", false}, - {"1.1 - 2", "1.1.1", true}, - {"1.1-3", "4.3.2", false}, - {"^1.1", "1.1.1", true}, - {"^1.1", "4.3.2", false}, - {"^1.x", "1.1.1", true}, - {"^2.x", "1.1.1", false}, - {"^1.x", "2.1.1", false}, - {"^1.x", "1.1.1-beta1", false}, - {"^1.1.2-alpha", "1.2.1-beta1", true}, - {"^1.2.x-alpha", "1.1.1-beta1", false}, - {"~*", "2.1.1", true}, - {"~1", "2.1.1", false}, - {"~1", "1.3.5", true}, - {"~1", "1.4", true}, - {"~1.x", "2.1.1", false}, - {"~1.x", "1.3.5", true}, - {"~1.x", "1.4", true}, - {"~1.1", "1.1.1", true}, - {"~1.1", "1.1.1-alpha", false}, - {"~1.1-alpha", "1.1.1-beta", true}, - {"~1.1.1-beta", "1.1.1-alpha", false}, - {"~1.1.1-beta", "1.1.1", true}, - {"~1.2.3", "1.2.5", true}, - {"~1.2.3", "1.2.2", false}, - {"~1.2.3", "1.3.2", false}, - {"~1.1", "1.2.3", false}, - {"~1.3", "2.4.5", false}, - } - - for _, tc := range tests { - c, err := NewConstraint(tc.constraint) - if err != nil { - t.Errorf("err: %s", err) - continue - } - - v, err := NewVersion(tc.version) - if err != nil { - t.Errorf("err: %s", err) - continue - } - - a := c.Check(v) - if a != tc.check { - t.Errorf("Constraint '%s' failing with '%s'", tc.constraint, tc.version) - } - } -} - -func TestRewriteRange(t *testing.T) { - tests := []struct { - c string - nc string - }{ - {"2 - 3", ">= 2, <= 3"}, - {"2 - 3, 2 - 3", ">= 2, <= 3,>= 2, <= 3"}, - {"2 - 3, 4.0.0 - 5.1", ">= 2, <= 3,>= 4.0.0, <= 5.1"}, - } - - for _, tc := range tests { - o := rewriteRange(tc.c) - - if o != tc.nc { - t.Errorf("Range %s rewritten incorrectly as '%s'", tc.c, o) - } - } -} - -func TestIsX(t *testing.T) { - tests := []struct { - t string - c bool - }{ - {"A", false}, - {"%", false}, - {"X", true}, - {"x", true}, - {"*", true}, - } - - for _, tc := range tests { - a := isX(tc.t) - if a != tc.c { - t.Errorf("Function isX error on %s", tc.t) - } - } -} - -func TestConstraintsValidate(t *testing.T) { - tests := []struct { - constraint string - version string - check bool - }{ - {"*", "1.2.3", true}, - {"~0.0.0", "1.2.3", true}, - {"= 2.0", "1.2.3", false}, - {"= 2.0", "2.0.0", true}, - {"4.1", "4.1.0", true}, - {"4.1.x", "4.1.3", true}, - {"1.x", "1.4", true}, - {"!=4.1", "4.1.0", false}, - {"!=4.1", "5.1.0", true}, - {"!=4.x", "5.1.0", true}, - {"!=4.x", "4.1.0", false}, - {"!=4.1.x", "4.2.0", true}, - {"!=4.2.x", "4.2.3", false}, - {">1.1", "4.1.0", true}, - {">1.1", "1.1.0", false}, - {"<1.1", "0.1.0", true}, - {"<1.1", "1.1.0", false}, - {"<1.1", "1.1.1", false}, - {"<1.x", "1.1.1", true}, - {"<1.x", "2.1.1", false}, - {"<1.1.x", "1.2.1", false}, - {"<1.1.x", "1.1.500", true}, - {"<1.2.x", "1.1.1", true}, - {">=1.1", "4.1.0", true}, - {">=1.1", "1.1.0", true}, - {">=1.1", "0.0.9", false}, - {"<=1.1", "0.1.0", true}, - {"<=1.1", "1.1.0", true}, - {"<=1.x", "1.1.0", true}, - {"<=2.x", "3.1.0", false}, - {"<=1.1", "1.1.1", false}, - {"<=1.1.x", "1.2.500", false}, - {">1.1, <2", "1.1.1", true}, - {">1.1, <3", "4.3.2", false}, - {">=1.1, <2, !=1.2.3", "1.2.3", false}, - {">=1.1, <2, !=1.2.3 || > 3", "3.1.2", true}, - {">=1.1, <2, !=1.2.3 || >= 3", "3.0.0", true}, - {">=1.1, <2, !=1.2.3 || > 3", "3.0.0", false}, - {">=1.1, <2, !=1.2.3 || > 3", "1.2.3", false}, - {"1.1 - 2", "1.1.1", true}, - {"1.1-3", "4.3.2", false}, - {"^1.1", "1.1.1", true}, - {"^1.1", "1.1.1-alpha", false}, - {"^1.1.1-alpha", "1.1.1-beta", true}, - {"^1.1.1-beta", "1.1.1-alpha", false}, - {"^1.1", "4.3.2", false}, - {"^1.x", "1.1.1", true}, - {"^2.x", "1.1.1", false}, - {"^1.x", "2.1.1", false}, - {"~*", "2.1.1", true}, - {"~1", "2.1.1", false}, - {"~1", "1.3.5", true}, - {"~1", "1.3.5-beta", false}, - {"~1.x", "2.1.1", false}, - {"~1.x", "1.3.5", true}, - {"~1.x", "1.3.5-beta", false}, - {"~1.3.6-alpha", "1.3.5-beta", false}, - {"~1.3.5-alpha", "1.3.5-beta", true}, - {"~1.3.5-beta", "1.3.5-alpha", false}, - {"~1.x", "1.4", true}, - {"~1.1", "1.1.1", true}, - {"~1.2.3", "1.2.5", true}, - {"~1.2.3", "1.2.2", false}, - {"~1.2.3", "1.3.2", false}, - {"~1.1", "1.2.3", false}, - {"~1.3", "2.4.5", false}, - } - - for _, tc := range tests { - c, err := NewConstraint(tc.constraint) - if err != nil { - t.Errorf("err: %s", err) - continue - } - - v, err := NewVersion(tc.version) - if err != nil { - t.Errorf("err: %s", err) - continue - } - - a, msgs := c.Validate(v) - if a != tc.check { - t.Errorf("Constraint '%s' failing with '%s'", tc.constraint, tc.version) - } else if !a && len(msgs) == 0 { - t.Errorf("%q failed with %q but no errors returned", tc.constraint, tc.version) - } - - // if a == false { - // for _, m := range msgs { - // t.Errorf("%s", m) - // } - // } - } - - v, err := NewVersion("1.2.3") - if err != nil { - t.Errorf("err: %s", err) - } - - c, err := NewConstraint("!= 1.2.5, ^2, <= 1.1.x") - if err != nil { - t.Errorf("err: %s", err) - } - - _, msgs := c.Validate(v) - if len(msgs) != 2 { - t.Error("Invalid number of validations found") - } - e := msgs[0].Error() - if e != "1.2.3 does not have same major version as 2" { - t.Error("Did not get expected message: 1.2.3 does not have same major version as 2") - } - e = msgs[1].Error() - if e != "1.2.3 is greater than 1.1.x" { - t.Error("Did not get expected message: 1.2.3 is greater than 1.1.x") - } - - tests2 := []struct { - constraint, version, msg string - }{ - {"= 2.0", "1.2.3", "1.2.3 is not equal to 2.0"}, - {"!=4.1", "4.1.0", "4.1.0 is equal to 4.1"}, - {"!=4.x", "4.1.0", "4.1.0 is equal to 4.x"}, - {"!=4.2.x", "4.2.3", "4.2.3 is equal to 4.2.x"}, - {">1.1", "1.1.0", "1.1.0 is less than or equal to 1.1"}, - {"<1.1", "1.1.0", "1.1.0 is greater than or equal to 1.1"}, - {"<1.1", "1.1.1", "1.1.1 is greater than or equal to 1.1"}, - {"<1.x", "2.1.1", "2.1.1 is greater than or equal to 1.x"}, - {"<1.1.x", "1.2.1", "1.2.1 is greater than or equal to 1.1.x"}, - {">=1.1", "0.0.9", "0.0.9 is less than 1.1"}, - {"<=2.x", "3.1.0", "3.1.0 is greater than 2.x"}, - {"<=1.1", "1.1.1", "1.1.1 is greater than 1.1"}, - {"<=1.1.x", "1.2.500", "1.2.500 is greater than 1.1.x"}, - {">1.1, <3", "4.3.2", "4.3.2 is greater than or equal to 3"}, - {">=1.1, <2, !=1.2.3", "1.2.3", "1.2.3 is equal to 1.2.3"}, - {">=1.1, <2, !=1.2.3 || > 3", "3.0.0", "3.0.0 is greater than or equal to 2"}, - {">=1.1, <2, !=1.2.3 || > 3", "1.2.3", "1.2.3 is equal to 1.2.3"}, - {"1.1 - 3", "4.3.2", "4.3.2 is greater than 3"}, - {"^1.1", "4.3.2", "4.3.2 does not have same major version as 1.1"}, - {"^2.x", "1.1.1", "1.1.1 does not have same major version as 2.x"}, - {"^1.x", "2.1.1", "2.1.1 does not have same major version as 1.x"}, - {"~1", "2.1.2", "2.1.2 does not have same major and minor version as 1"}, - {"~1.x", "2.1.1", "2.1.1 does not have same major and minor version as 1.x"}, - {"~1.2.3", "1.2.2", "1.2.2 does not have same major and minor version as 1.2.3"}, - {"~1.2.3", "1.3.2", "1.3.2 does not have same major and minor version as 1.2.3"}, - {"~1.1", "1.2.3", "1.2.3 does not have same major and minor version as 1.1"}, - {"~1.3", "2.4.5", "2.4.5 does not have same major and minor version as 1.3"}, - } - - for _, tc := range tests2 { - c, err := NewConstraint(tc.constraint) - if err != nil { - t.Errorf("err: %s", err) - continue - } - - v, err := NewVersion(tc.version) - if err != nil { - t.Errorf("err: %s", err) - continue - } - - _, msgs := c.Validate(v) - e := msgs[0].Error() - if e != tc.msg { - t.Errorf("Did not get expected message %q: %s", tc.msg, e) - } - } -} diff --git a/cmd/vendor/github.com/Masterminds/semver/version_test.go b/cmd/vendor/github.com/Masterminds/semver/version_test.go deleted file mode 100644 index ff5d644a74..0000000000 --- a/cmd/vendor/github.com/Masterminds/semver/version_test.go +++ /dev/null @@ -1,490 +0,0 @@ -package semver - -import ( - "encoding/json" - "fmt" - "testing" -) - -func TestNewVersion(t *testing.T) { - tests := []struct { - version string - err bool - }{ - {"1.2.3", false}, - {"v1.2.3", false}, - {"1.0", false}, - {"v1.0", false}, - {"1", false}, - {"v1", false}, - {"1.2.beta", true}, - {"v1.2.beta", true}, - {"foo", true}, - {"1.2-5", false}, - {"v1.2-5", false}, - {"1.2-beta.5", false}, - {"v1.2-beta.5", false}, - {"\n1.2", true}, - {"\nv1.2", true}, - {"1.2.0-x.Y.0+metadata", false}, - {"v1.2.0-x.Y.0+metadata", false}, - {"1.2.0-x.Y.0+metadata-width-hypen", false}, - {"v1.2.0-x.Y.0+metadata-width-hypen", false}, - {"1.2.3-rc1-with-hypen", false}, - {"v1.2.3-rc1-with-hypen", false}, - {"1.2.3.4", true}, - {"v1.2.3.4", true}, - {"1.2.2147483648", false}, - {"1.2147483648.3", false}, - {"2147483648.3.0", false}, - } - - for _, tc := range tests { - _, err := NewVersion(tc.version) - if tc.err && err == nil { - t.Fatalf("expected error for version: %s", tc.version) - } else if !tc.err && err != nil { - t.Fatalf("error for version %s: %s", tc.version, err) - } - } -} - -func TestOriginal(t *testing.T) { - tests := []string{ - "1.2.3", - "v1.2.3", - "1.0", - "v1.0", - "1", - "v1", - "1.2-5", - "v1.2-5", - "1.2-beta.5", - "v1.2-beta.5", - "1.2.0-x.Y.0+metadata", - "v1.2.0-x.Y.0+metadata", - "1.2.0-x.Y.0+metadata-width-hypen", - "v1.2.0-x.Y.0+metadata-width-hypen", - "1.2.3-rc1-with-hypen", - "v1.2.3-rc1-with-hypen", - } - - for _, tc := range tests { - v, err := NewVersion(tc) - if err != nil { - t.Errorf("Error parsing version %s", tc) - } - - o := v.Original() - if o != tc { - t.Errorf("Error retrieving originl. Expected '%s' but got '%s'", tc, v) - } - } -} - -func TestParts(t *testing.T) { - v, err := NewVersion("1.2.3-beta.1+build.123") - if err != nil { - t.Error("Error parsing version 1.2.3-beta.1+build.123") - } - - if v.Major() != 1 { - t.Error("Major() returning wrong value") - } - if v.Minor() != 2 { - t.Error("Minor() returning wrong value") - } - if v.Patch() != 3 { - t.Error("Patch() returning wrong value") - } - if v.Prerelease() != "beta.1" { - t.Error("Prerelease() returning wrong value") - } - if v.Metadata() != "build.123" { - t.Error("Metadata() returning wrong value") - } -} - -func TestString(t *testing.T) { - tests := []struct { - version string - expected string - }{ - {"1.2.3", "1.2.3"}, - {"v1.2.3", "1.2.3"}, - {"1.0", "1.0.0"}, - {"v1.0", "1.0.0"}, - {"1", "1.0.0"}, - {"v1", "1.0.0"}, - {"1.2-5", "1.2.0-5"}, - {"v1.2-5", "1.2.0-5"}, - {"1.2-beta.5", "1.2.0-beta.5"}, - {"v1.2-beta.5", "1.2.0-beta.5"}, - {"1.2.0-x.Y.0+metadata", "1.2.0-x.Y.0+metadata"}, - {"v1.2.0-x.Y.0+metadata", "1.2.0-x.Y.0+metadata"}, - {"1.2.0-x.Y.0+metadata-width-hypen", "1.2.0-x.Y.0+metadata-width-hypen"}, - {"v1.2.0-x.Y.0+metadata-width-hypen", "1.2.0-x.Y.0+metadata-width-hypen"}, - {"1.2.3-rc1-with-hypen", "1.2.3-rc1-with-hypen"}, - {"v1.2.3-rc1-with-hypen", "1.2.3-rc1-with-hypen"}, - } - - for _, tc := range tests { - v, err := NewVersion(tc.version) - if err != nil { - t.Errorf("Error parsing version %s", tc) - } - - s := v.String() - if s != tc.expected { - t.Errorf("Error generating string. Expected '%s' but got '%s'", tc.expected, s) - } - } -} - -func TestCompare(t *testing.T) { - tests := []struct { - v1 string - v2 string - expected int - }{ - {"1.2.3", "1.5.1", -1}, - {"2.2.3", "1.5.1", 1}, - {"2.2.3", "2.2.2", 1}, - {"3.2-beta", "3.2-beta", 0}, - {"1.3", "1.1.4", 1}, - {"4.2", "4.2-beta", 1}, - {"4.2-beta", "4.2", -1}, - {"4.2-alpha", "4.2-beta", -1}, - {"4.2-alpha", "4.2-alpha", 0}, - {"4.2-beta.2", "4.2-beta.1", 1}, - {"4.2-beta2", "4.2-beta1", 1}, - {"4.2-beta", "4.2-beta.2", -1}, - {"4.2-beta", "4.2-beta.foo", -1}, - {"4.2-beta.2", "4.2-beta", 1}, - {"4.2-beta.foo", "4.2-beta", 1}, - {"1.2+bar", "1.2+baz", 0}, - } - - for _, tc := range tests { - v1, err := NewVersion(tc.v1) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - - v2, err := NewVersion(tc.v2) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - - a := v1.Compare(v2) - e := tc.expected - if a != e { - t.Errorf( - "Comparison of '%s' and '%s' failed. Expected '%d', got '%d'", - tc.v1, tc.v2, e, a, - ) - } - } -} - -func TestLessThan(t *testing.T) { - tests := []struct { - v1 string - v2 string - expected bool - }{ - {"1.2.3", "1.5.1", true}, - {"2.2.3", "1.5.1", false}, - {"3.2-beta", "3.2-beta", false}, - } - - for _, tc := range tests { - v1, err := NewVersion(tc.v1) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - - v2, err := NewVersion(tc.v2) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - - a := v1.LessThan(v2) - e := tc.expected - if a != e { - t.Errorf( - "Comparison of '%s' and '%s' failed. Expected '%t', got '%t'", - tc.v1, tc.v2, e, a, - ) - } - } -} - -func TestGreaterThan(t *testing.T) { - tests := []struct { - v1 string - v2 string - expected bool - }{ - {"1.2.3", "1.5.1", false}, - {"2.2.3", "1.5.1", true}, - {"3.2-beta", "3.2-beta", false}, - {"3.2.0-beta.1", "3.2.0-beta.5", false}, - {"3.2-beta.4", "3.2-beta.2", true}, - {"7.43.0-SNAPSHOT.99", "7.43.0-SNAPSHOT.103", false}, - {"7.43.0-SNAPSHOT.FOO", "7.43.0-SNAPSHOT.103", true}, - {"7.43.0-SNAPSHOT.99", "7.43.0-SNAPSHOT.BAR", false}, - } - - for _, tc := range tests { - v1, err := NewVersion(tc.v1) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - - v2, err := NewVersion(tc.v2) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - - a := v1.GreaterThan(v2) - e := tc.expected - if a != e { - t.Errorf( - "Comparison of '%s' and '%s' failed. Expected '%t', got '%t'", - tc.v1, tc.v2, e, a, - ) - } - } -} - -func TestEqual(t *testing.T) { - tests := []struct { - v1 string - v2 string - expected bool - }{ - {"1.2.3", "1.5.1", false}, - {"2.2.3", "1.5.1", false}, - {"3.2-beta", "3.2-beta", true}, - {"3.2-beta+foo", "3.2-beta+bar", true}, - } - - for _, tc := range tests { - v1, err := NewVersion(tc.v1) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - - v2, err := NewVersion(tc.v2) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - - a := v1.Equal(v2) - e := tc.expected - if a != e { - t.Errorf( - "Comparison of '%s' and '%s' failed. Expected '%t', got '%t'", - tc.v1, tc.v2, e, a, - ) - } - } -} - -func TestInc(t *testing.T) { - tests := []struct { - v1 string - expected string - how string - expectedOriginal string - }{ - {"1.2.3", "1.2.4", "patch", "1.2.4"}, - {"v1.2.4", "1.2.5", "patch", "v1.2.5"}, - {"1.2.3", "1.3.0", "minor", "1.3.0"}, - {"v1.2.4", "1.3.0", "minor", "v1.3.0"}, - {"1.2.3", "2.0.0", "major", "2.0.0"}, - {"v1.2.4", "2.0.0", "major", "v2.0.0"}, - {"1.2.3+meta", "1.2.4", "patch", "1.2.4"}, - {"1.2.3-beta+meta", "1.2.3", "patch", "1.2.3"}, - {"v1.2.4-beta+meta", "1.2.4", "patch", "v1.2.4"}, - {"1.2.3-beta+meta", "1.3.0", "minor", "1.3.0"}, - {"v1.2.4-beta+meta", "1.3.0", "minor", "v1.3.0"}, - {"1.2.3-beta+meta", "2.0.0", "major", "2.0.0"}, - {"v1.2.4-beta+meta", "2.0.0", "major", "v2.0.0"}, - } - - for _, tc := range tests { - v1, err := NewVersion(tc.v1) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - var v2 Version - switch tc.how { - case "patch": - v2 = v1.IncPatch() - case "minor": - v2 = v1.IncMinor() - case "major": - v2 = v1.IncMajor() - } - - a := v2.String() - e := tc.expected - if a != e { - t.Errorf( - "Inc %q failed. Expected %q got %q", - tc.how, e, a, - ) - } - - a = v2.Original() - e = tc.expectedOriginal - if a != e { - t.Errorf( - "Inc %q failed. Expected original %q got %q", - tc.how, e, a, - ) - } - } -} - -func TestSetPrerelease(t *testing.T) { - tests := []struct { - v1 string - prerelease string - expectedVersion string - expectedPrerelease string - expectedOriginal string - expectedErr error - }{ - {"1.2.3", "**", "1.2.3", "", "1.2.3", ErrInvalidPrerelease}, - {"1.2.3", "beta", "1.2.3-beta", "beta", "1.2.3-beta", nil}, - {"v1.2.4", "beta", "1.2.4-beta", "beta", "v1.2.4-beta", nil}, - } - - for _, tc := range tests { - v1, err := NewVersion(tc.v1) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - - v2, err := v1.SetPrerelease(tc.prerelease) - if err != tc.expectedErr { - t.Errorf("Expected to get err=%s, but got err=%s", tc.expectedErr, err) - } - - a := v2.Prerelease() - e := tc.expectedPrerelease - if a != e { - t.Errorf("Expected prerelease value=%q, but got %q", e, a) - } - - a = v2.String() - e = tc.expectedVersion - if a != e { - t.Errorf("Expected version string=%q, but got %q", e, a) - } - - a = v2.Original() - e = tc.expectedOriginal - if a != e { - t.Errorf("Expected version original=%q, but got %q", e, a) - } - } -} - -func TestSetMetadata(t *testing.T) { - tests := []struct { - v1 string - metadata string - expectedVersion string - expectedMetadata string - expectedOriginal string - expectedErr error - }{ - {"1.2.3", "**", "1.2.3", "", "1.2.3", ErrInvalidMetadata}, - {"1.2.3", "meta", "1.2.3+meta", "meta", "1.2.3+meta", nil}, - {"v1.2.4", "meta", "1.2.4+meta", "meta", "v1.2.4+meta", nil}, - } - - for _, tc := range tests { - v1, err := NewVersion(tc.v1) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } - - v2, err := v1.SetMetadata(tc.metadata) - if err != tc.expectedErr { - t.Errorf("Expected to get err=%s, but got err=%s", tc.expectedErr, err) - } - - a := v2.Metadata() - e := tc.expectedMetadata - if a != e { - t.Errorf("Expected metadata value=%q, but got %q", e, a) - } - - a = v2.String() - e = tc.expectedVersion - if e != a { - t.Errorf("Expected version string=%q, but got %q", e, a) - } - - a = v2.Original() - e = tc.expectedOriginal - if a != e { - t.Errorf("Expected version original=%q, but got %q", e, a) - } - } -} - -func TestOriginalVPrefix(t *testing.T) { - tests := []struct { - version string - vprefix string - }{ - {"1.2.3", ""}, - {"v1.2.4", "v"}, - } - - for _, tc := range tests { - v1, _ := NewVersion(tc.version) - a := v1.originalVPrefix() - e := tc.vprefix - if a != e { - t.Errorf("Expected vprefix=%q, but got %q", e, a) - } - } -} - -func TestJsonMarshal(t *testing.T) { - sVer := "1.1.1" - x, err := NewVersion(sVer) - if err != nil { - t.Errorf("Error creating version: %s", err) - } - out, err2 := json.Marshal(x) - if err2 != nil { - t.Errorf("Error marshaling version: %s", err2) - } - got := string(out) - want := fmt.Sprintf("%q", sVer) - if got != want { - t.Errorf("Error marshaling unexpected marshaled content: got=%q want=%q", got, want) - } -} - -func TestJsonUnmarshal(t *testing.T) { - sVer := "1.1.1" - ver := &Version{} - err := json.Unmarshal([]byte(fmt.Sprintf("%q", sVer)), ver) - if err != nil { - t.Errorf("Error unmarshaling version: %s", err) - } - got := ver.String() - want := sVer - if got != want { - t.Errorf("Error unmarshaling unexpected object content: got=%q want=%q", got, want) - } -} diff --git a/cmd/vendor/github.com/spf13/afero/LICENSE.txt b/cmd/vendor/github.com/spf13/afero/LICENSE.txt new file mode 100644 index 0000000000..298f0e2665 --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/LICENSE.txt @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/cmd/vendor/github.com/spf13/afero/afero.go b/cmd/vendor/github.com/spf13/afero/afero.go new file mode 100644 index 0000000000..f5b5e127cd --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/afero.go @@ -0,0 +1,108 @@ +// Copyright © 2014 Steve Francia . +// Copyright 2013 tsuru authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package afero provides types and methods for interacting with the filesystem, +// as an abstraction layer. + +// Afero also provides a few implementations that are mostly interoperable. One that +// uses the operating system filesystem, one that uses memory to store files +// (cross platform) and an interface that should be implemented if you want to +// provide your own filesystem. + +package afero + +import ( + "errors" + "io" + "os" + "time" +) + +type Afero struct { + Fs +} + +// File represents a file in the filesystem. +type File interface { + io.Closer + io.Reader + io.ReaderAt + io.Seeker + io.Writer + io.WriterAt + + Name() string + Readdir(count int) ([]os.FileInfo, error) + Readdirnames(n int) ([]string, error) + Stat() (os.FileInfo, error) + Sync() error + Truncate(size int64) error + WriteString(s string) (ret int, err error) +} + +// Fs is the filesystem interface. +// +// Any simulated or real filesystem should implement this interface. +type Fs interface { + // Create creates a file in the filesystem, returning the file and an + // error, if any happens. + Create(name string) (File, error) + + // Mkdir creates a directory in the filesystem, return an error if any + // happens. + Mkdir(name string, perm os.FileMode) error + + // MkdirAll creates a directory path and all parents that does not exist + // yet. + MkdirAll(path string, perm os.FileMode) error + + // Open opens a file, returning it or an error, if any happens. + Open(name string) (File, error) + + // OpenFile opens a file using the given flags and the given mode. + OpenFile(name string, flag int, perm os.FileMode) (File, error) + + // Remove removes a file identified by name, returning an error, if any + // happens. + Remove(name string) error + + // RemoveAll removes a directory path and any children it contains. It + // does not fail if the path does not exist (return nil). + RemoveAll(path string) error + + // Rename renames a file. + Rename(oldname, newname string) error + + // Stat returns a FileInfo describing the named file, or an error, if any + // happens. + Stat(name string) (os.FileInfo, error) + + // The name of this FileSystem + Name() string + + //Chmod changes the mode of the named file to mode. + Chmod(name string, mode os.FileMode) error + + //Chtimes changes the access and modification times of the named file + Chtimes(name string, atime time.Time, mtime time.Time) error +} + +var ( + ErrFileClosed = errors.New("File is closed") + ErrOutOfRange = errors.New("Out of range") + ErrTooLarge = errors.New("Too large") + ErrFileNotFound = os.ErrNotExist + ErrFileExists = os.ErrExist + ErrDestinationExists = os.ErrExist +) diff --git a/cmd/vendor/github.com/spf13/afero/basepath.go b/cmd/vendor/github.com/spf13/afero/basepath.go new file mode 100644 index 0000000000..616ff8ff74 --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/basepath.go @@ -0,0 +1,180 @@ +package afero + +import ( + "os" + "path/filepath" + "runtime" + "strings" + "time" +) + +var _ Lstater = (*BasePathFs)(nil) + +// The BasePathFs restricts all operations to a given path within an Fs. +// The given file name to the operations on this Fs will be prepended with +// the base path before calling the base Fs. +// Any file name (after filepath.Clean()) outside this base path will be +// treated as non existing file. +// +// Note that it does not clean the error messages on return, so you may +// reveal the real path on errors. +type BasePathFs struct { + source Fs + path string +} + +type BasePathFile struct { + File + path string +} + +func (f *BasePathFile) Name() string { + sourcename := f.File.Name() + return strings.TrimPrefix(sourcename, filepath.Clean(f.path)) +} + +func NewBasePathFs(source Fs, path string) Fs { + return &BasePathFs{source: source, path: path} +} + +// on a file outside the base path it returns the given file name and an error, +// else the given file with the base path prepended +func (b *BasePathFs) RealPath(name string) (path string, err error) { + if err := validateBasePathName(name); err != nil { + return name, err + } + + bpath := filepath.Clean(b.path) + path = filepath.Clean(filepath.Join(bpath, name)) + if !strings.HasPrefix(path, bpath) { + return name, os.ErrNotExist + } + + return path, nil +} + +func validateBasePathName(name string) error { + if runtime.GOOS != "windows" { + // Not much to do here; + // the virtual file paths all look absolute on *nix. + return nil + } + + // On Windows a common mistake would be to provide an absolute OS path + // We could strip out the base part, but that would not be very portable. + if filepath.IsAbs(name) { + return os.ErrNotExist + } + + return nil +} + +func (b *BasePathFs) Chtimes(name string, atime, mtime time.Time) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "chtimes", Path: name, Err: err} + } + return b.source.Chtimes(name, atime, mtime) +} + +func (b *BasePathFs) Chmod(name string, mode os.FileMode) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "chmod", Path: name, Err: err} + } + return b.source.Chmod(name, mode) +} + +func (b *BasePathFs) Name() string { + return "BasePathFs" +} + +func (b *BasePathFs) Stat(name string) (fi os.FileInfo, err error) { + if name, err = b.RealPath(name); err != nil { + return nil, &os.PathError{Op: "stat", Path: name, Err: err} + } + return b.source.Stat(name) +} + +func (b *BasePathFs) Rename(oldname, newname string) (err error) { + if oldname, err = b.RealPath(oldname); err != nil { + return &os.PathError{Op: "rename", Path: oldname, Err: err} + } + if newname, err = b.RealPath(newname); err != nil { + return &os.PathError{Op: "rename", Path: newname, Err: err} + } + return b.source.Rename(oldname, newname) +} + +func (b *BasePathFs) RemoveAll(name string) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "remove_all", Path: name, Err: err} + } + return b.source.RemoveAll(name) +} + +func (b *BasePathFs) Remove(name string) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "remove", Path: name, Err: err} + } + return b.source.Remove(name) +} + +func (b *BasePathFs) OpenFile(name string, flag int, mode os.FileMode) (f File, err error) { + if name, err = b.RealPath(name); err != nil { + return nil, &os.PathError{Op: "openfile", Path: name, Err: err} + } + sourcef, err := b.source.OpenFile(name, flag, mode) + if err != nil { + return nil, err + } + return &BasePathFile{sourcef, b.path}, nil +} + +func (b *BasePathFs) Open(name string) (f File, err error) { + if name, err = b.RealPath(name); err != nil { + return nil, &os.PathError{Op: "open", Path: name, Err: err} + } + sourcef, err := b.source.Open(name) + if err != nil { + return nil, err + } + return &BasePathFile{File: sourcef, path: b.path}, nil +} + +func (b *BasePathFs) Mkdir(name string, mode os.FileMode) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "mkdir", Path: name, Err: err} + } + return b.source.Mkdir(name, mode) +} + +func (b *BasePathFs) MkdirAll(name string, mode os.FileMode) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "mkdir", Path: name, Err: err} + } + return b.source.MkdirAll(name, mode) +} + +func (b *BasePathFs) Create(name string) (f File, err error) { + if name, err = b.RealPath(name); err != nil { + return nil, &os.PathError{Op: "create", Path: name, Err: err} + } + sourcef, err := b.source.Create(name) + if err != nil { + return nil, err + } + return &BasePathFile{File: sourcef, path: b.path}, nil +} + +func (b *BasePathFs) LstatIfPossible(name string) (os.FileInfo, bool, error) { + name, err := b.RealPath(name) + if err != nil { + return nil, false, &os.PathError{Op: "lstat", Path: name, Err: err} + } + if lstater, ok := b.source.(Lstater); ok { + return lstater.LstatIfPossible(name) + } + fi, err := b.source.Stat(name) + return fi, false, err +} + +// vim: ts=4 sw=4 noexpandtab nolist syn=go diff --git a/cmd/vendor/github.com/spf13/afero/cacheOnReadFs.go b/cmd/vendor/github.com/spf13/afero/cacheOnReadFs.go new file mode 100644 index 0000000000..29a26c67dd --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/cacheOnReadFs.go @@ -0,0 +1,290 @@ +package afero + +import ( + "os" + "syscall" + "time" +) + +// If the cache duration is 0, cache time will be unlimited, i.e. once +// a file is in the layer, the base will never be read again for this file. +// +// For cache times greater than 0, the modification time of a file is +// checked. Note that a lot of file system implementations only allow a +// resolution of a second for timestamps... or as the godoc for os.Chtimes() +// states: "The underlying filesystem may truncate or round the values to a +// less precise time unit." +// +// This caching union will forward all write calls also to the base file +// system first. To prevent writing to the base Fs, wrap it in a read-only +// filter - Note: this will also make the overlay read-only, for writing files +// in the overlay, use the overlay Fs directly, not via the union Fs. +type CacheOnReadFs struct { + base Fs + layer Fs + cacheTime time.Duration +} + +func NewCacheOnReadFs(base Fs, layer Fs, cacheTime time.Duration) Fs { + return &CacheOnReadFs{base: base, layer: layer, cacheTime: cacheTime} +} + +type cacheState int + +const ( + // not present in the overlay, unknown if it exists in the base: + cacheMiss cacheState = iota + // present in the overlay and in base, base file is newer: + cacheStale + // present in the overlay - with cache time == 0 it may exist in the base, + // with cacheTime > 0 it exists in the base and is same age or newer in the + // overlay + cacheHit + // happens if someone writes directly to the overlay without + // going through this union + cacheLocal +) + +func (u *CacheOnReadFs) cacheStatus(name string) (state cacheState, fi os.FileInfo, err error) { + var lfi, bfi os.FileInfo + lfi, err = u.layer.Stat(name) + if err == nil { + if u.cacheTime == 0 { + return cacheHit, lfi, nil + } + if lfi.ModTime().Add(u.cacheTime).Before(time.Now()) { + bfi, err = u.base.Stat(name) + if err != nil { + return cacheLocal, lfi, nil + } + if bfi.ModTime().After(lfi.ModTime()) { + return cacheStale, bfi, nil + } + } + return cacheHit, lfi, nil + } + + if err == syscall.ENOENT || os.IsNotExist(err) { + return cacheMiss, nil, nil + } + + return cacheMiss, nil, err +} + +func (u *CacheOnReadFs) copyToLayer(name string) error { + return copyToLayer(u.base, u.layer, name) +} + +func (u *CacheOnReadFs) Chtimes(name string, atime, mtime time.Time) error { + st, _, err := u.cacheStatus(name) + if err != nil { + return err + } + switch st { + case cacheLocal: + case cacheHit: + err = u.base.Chtimes(name, atime, mtime) + case cacheStale, cacheMiss: + if err := u.copyToLayer(name); err != nil { + return err + } + err = u.base.Chtimes(name, atime, mtime) + } + if err != nil { + return err + } + return u.layer.Chtimes(name, atime, mtime) +} + +func (u *CacheOnReadFs) Chmod(name string, mode os.FileMode) error { + st, _, err := u.cacheStatus(name) + if err != nil { + return err + } + switch st { + case cacheLocal: + case cacheHit: + err = u.base.Chmod(name, mode) + case cacheStale, cacheMiss: + if err := u.copyToLayer(name); err != nil { + return err + } + err = u.base.Chmod(name, mode) + } + if err != nil { + return err + } + return u.layer.Chmod(name, mode) +} + +func (u *CacheOnReadFs) Stat(name string) (os.FileInfo, error) { + st, fi, err := u.cacheStatus(name) + if err != nil { + return nil, err + } + switch st { + case cacheMiss: + return u.base.Stat(name) + default: // cacheStale has base, cacheHit and cacheLocal the layer os.FileInfo + return fi, nil + } +} + +func (u *CacheOnReadFs) Rename(oldname, newname string) error { + st, _, err := u.cacheStatus(oldname) + if err != nil { + return err + } + switch st { + case cacheLocal: + case cacheHit: + err = u.base.Rename(oldname, newname) + case cacheStale, cacheMiss: + if err := u.copyToLayer(oldname); err != nil { + return err + } + err = u.base.Rename(oldname, newname) + } + if err != nil { + return err + } + return u.layer.Rename(oldname, newname) +} + +func (u *CacheOnReadFs) Remove(name string) error { + st, _, err := u.cacheStatus(name) + if err != nil { + return err + } + switch st { + case cacheLocal: + case cacheHit, cacheStale, cacheMiss: + err = u.base.Remove(name) + } + if err != nil { + return err + } + return u.layer.Remove(name) +} + +func (u *CacheOnReadFs) RemoveAll(name string) error { + st, _, err := u.cacheStatus(name) + if err != nil { + return err + } + switch st { + case cacheLocal: + case cacheHit, cacheStale, cacheMiss: + err = u.base.RemoveAll(name) + } + if err != nil { + return err + } + return u.layer.RemoveAll(name) +} + +func (u *CacheOnReadFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + st, _, err := u.cacheStatus(name) + if err != nil { + return nil, err + } + switch st { + case cacheLocal, cacheHit: + default: + if err := u.copyToLayer(name); err != nil { + return nil, err + } + } + if flag&(os.O_WRONLY|syscall.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 { + bfi, err := u.base.OpenFile(name, flag, perm) + if err != nil { + return nil, err + } + lfi, err := u.layer.OpenFile(name, flag, perm) + if err != nil { + bfi.Close() // oops, what if O_TRUNC was set and file opening in the layer failed...? + return nil, err + } + return &UnionFile{Base: bfi, Layer: lfi}, nil + } + return u.layer.OpenFile(name, flag, perm) +} + +func (u *CacheOnReadFs) Open(name string) (File, error) { + st, fi, err := u.cacheStatus(name) + if err != nil { + return nil, err + } + + switch st { + case cacheLocal: + return u.layer.Open(name) + + case cacheMiss: + bfi, err := u.base.Stat(name) + if err != nil { + return nil, err + } + if bfi.IsDir() { + return u.base.Open(name) + } + if err := u.copyToLayer(name); err != nil { + return nil, err + } + return u.layer.Open(name) + + case cacheStale: + if !fi.IsDir() { + if err := u.copyToLayer(name); err != nil { + return nil, err + } + return u.layer.Open(name) + } + case cacheHit: + if !fi.IsDir() { + return u.layer.Open(name) + } + } + // the dirs from cacheHit, cacheStale fall down here: + bfile, _ := u.base.Open(name) + lfile, err := u.layer.Open(name) + if err != nil && bfile == nil { + return nil, err + } + return &UnionFile{Base: bfile, Layer: lfile}, nil +} + +func (u *CacheOnReadFs) Mkdir(name string, perm os.FileMode) error { + err := u.base.Mkdir(name, perm) + if err != nil { + return err + } + return u.layer.MkdirAll(name, perm) // yes, MkdirAll... we cannot assume it exists in the cache +} + +func (u *CacheOnReadFs) Name() string { + return "CacheOnReadFs" +} + +func (u *CacheOnReadFs) MkdirAll(name string, perm os.FileMode) error { + err := u.base.MkdirAll(name, perm) + if err != nil { + return err + } + return u.layer.MkdirAll(name, perm) +} + +func (u *CacheOnReadFs) Create(name string) (File, error) { + bfh, err := u.base.Create(name) + if err != nil { + return nil, err + } + lfh, err := u.layer.Create(name) + if err != nil { + // oops, see comment about OS_TRUNC above, should we remove? then we have to + // remember if the file did not exist before + bfh.Close() + return nil, err + } + return &UnionFile{Base: bfh, Layer: lfh}, nil +} diff --git a/cmd/vendor/github.com/spf13/afero/const_bsds.go b/cmd/vendor/github.com/spf13/afero/const_bsds.go new file mode 100644 index 0000000000..5728243d96 --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/const_bsds.go @@ -0,0 +1,22 @@ +// Copyright © 2016 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build darwin openbsd freebsd netbsd dragonfly + +package afero + +import ( + "syscall" +) + +const BADFD = syscall.EBADF diff --git a/cmd/vendor/github.com/spf13/afero/const_win_unix.go b/cmd/vendor/github.com/spf13/afero/const_win_unix.go new file mode 100644 index 0000000000..968fc2783e --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/const_win_unix.go @@ -0,0 +1,25 @@ +// Copyright © 2016 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +build !darwin +// +build !openbsd +// +build !freebsd +// +build !dragonfly +// +build !netbsd + +package afero + +import ( + "syscall" +) + +const BADFD = syscall.EBADFD diff --git a/cmd/vendor/github.com/spf13/afero/copyOnWriteFs.go b/cmd/vendor/github.com/spf13/afero/copyOnWriteFs.go new file mode 100644 index 0000000000..9aef39794c --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/copyOnWriteFs.go @@ -0,0 +1,292 @@ +package afero + +import ( + "fmt" + "os" + "path/filepath" + "syscall" + "time" +) + +var _ Lstater = (*CopyOnWriteFs)(nil) + +// The CopyOnWriteFs is a union filesystem: a read only base file system with +// a possibly writeable layer on top. Changes to the file system will only +// be made in the overlay: Changing an existing file in the base layer which +// is not present in the overlay will copy the file to the overlay ("changing" +// includes also calls to e.g. Chtimes() and Chmod()). +// +// Reading directories is currently only supported via Open(), not OpenFile(). +type CopyOnWriteFs struct { + base Fs + layer Fs +} + +func NewCopyOnWriteFs(base Fs, layer Fs) Fs { + return &CopyOnWriteFs{base: base, layer: layer} +} + +// Returns true if the file is not in the overlay +func (u *CopyOnWriteFs) isBaseFile(name string) (bool, error) { + if _, err := u.layer.Stat(name); err == nil { + return false, nil + } + _, err := u.base.Stat(name) + if err != nil { + if oerr, ok := err.(*os.PathError); ok { + if oerr.Err == os.ErrNotExist || oerr.Err == syscall.ENOENT || oerr.Err == syscall.ENOTDIR { + return false, nil + } + } + if err == syscall.ENOENT { + return false, nil + } + } + return true, err +} + +func (u *CopyOnWriteFs) copyToLayer(name string) error { + return copyToLayer(u.base, u.layer, name) +} + +func (u *CopyOnWriteFs) Chtimes(name string, atime, mtime time.Time) error { + b, err := u.isBaseFile(name) + if err != nil { + return err + } + if b { + if err := u.copyToLayer(name); err != nil { + return err + } + } + return u.layer.Chtimes(name, atime, mtime) +} + +func (u *CopyOnWriteFs) Chmod(name string, mode os.FileMode) error { + b, err := u.isBaseFile(name) + if err != nil { + return err + } + if b { + if err := u.copyToLayer(name); err != nil { + return err + } + } + return u.layer.Chmod(name, mode) +} + +func (u *CopyOnWriteFs) Stat(name string) (os.FileInfo, error) { + fi, err := u.layer.Stat(name) + if err != nil { + isNotExist := u.isNotExist(err) + if isNotExist { + return u.base.Stat(name) + } + return nil, err + } + return fi, nil +} + +func (u *CopyOnWriteFs) LstatIfPossible(name string) (os.FileInfo, bool, error) { + llayer, ok1 := u.layer.(Lstater) + lbase, ok2 := u.base.(Lstater) + + if ok1 { + fi, b, err := llayer.LstatIfPossible(name) + if err == nil { + return fi, b, nil + } + + if !u.isNotExist(err) { + return nil, b, err + } + } + + if ok2 { + fi, b, err := lbase.LstatIfPossible(name) + if err == nil { + return fi, b, nil + } + if !u.isNotExist(err) { + return nil, b, err + } + } + + fi, err := u.Stat(name) + + return fi, false, err +} + +func (u *CopyOnWriteFs) isNotExist(err error) bool { + if e, ok := err.(*os.PathError); ok { + err = e.Err + } + if err == os.ErrNotExist || err == syscall.ENOENT || err == syscall.ENOTDIR { + return true + } + return false +} + +// Renaming files present only in the base layer is not permitted +func (u *CopyOnWriteFs) Rename(oldname, newname string) error { + b, err := u.isBaseFile(oldname) + if err != nil { + return err + } + if b { + return syscall.EPERM + } + return u.layer.Rename(oldname, newname) +} + +// Removing files present only in the base layer is not permitted. If +// a file is present in the base layer and the overlay, only the overlay +// will be removed. +func (u *CopyOnWriteFs) Remove(name string) error { + err := u.layer.Remove(name) + switch err { + case syscall.ENOENT: + _, err = u.base.Stat(name) + if err == nil { + return syscall.EPERM + } + return syscall.ENOENT + default: + return err + } +} + +func (u *CopyOnWriteFs) RemoveAll(name string) error { + err := u.layer.RemoveAll(name) + switch err { + case syscall.ENOENT: + _, err = u.base.Stat(name) + if err == nil { + return syscall.EPERM + } + return syscall.ENOENT + default: + return err + } +} + +func (u *CopyOnWriteFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + b, err := u.isBaseFile(name) + if err != nil { + return nil, err + } + + if flag&(os.O_WRONLY|os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 { + if b { + if err = u.copyToLayer(name); err != nil { + return nil, err + } + return u.layer.OpenFile(name, flag, perm) + } + + dir := filepath.Dir(name) + isaDir, err := IsDir(u.base, dir) + if err != nil && !os.IsNotExist(err) { + return nil, err + } + if isaDir { + if err = u.layer.MkdirAll(dir, 0777); err != nil { + return nil, err + } + return u.layer.OpenFile(name, flag, perm) + } + + isaDir, err = IsDir(u.layer, dir) + if err != nil { + return nil, err + } + if isaDir { + return u.layer.OpenFile(name, flag, perm) + } + + return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOTDIR} // ...or os.ErrNotExist? + } + if b { + return u.base.OpenFile(name, flag, perm) + } + return u.layer.OpenFile(name, flag, perm) +} + +// This function handles the 9 different possibilities caused +// by the union which are the intersection of the following... +// layer: doesn't exist, exists as a file, and exists as a directory +// base: doesn't exist, exists as a file, and exists as a directory +func (u *CopyOnWriteFs) Open(name string) (File, error) { + // Since the overlay overrides the base we check that first + b, err := u.isBaseFile(name) + if err != nil { + return nil, err + } + + // If overlay doesn't exist, return the base (base state irrelevant) + if b { + return u.base.Open(name) + } + + // If overlay is a file, return it (base state irrelevant) + dir, err := IsDir(u.layer, name) + if err != nil { + return nil, err + } + if !dir { + return u.layer.Open(name) + } + + // Overlay is a directory, base state now matters. + // Base state has 3 states to check but 2 outcomes: + // A. It's a file or non-readable in the base (return just the overlay) + // B. It's an accessible directory in the base (return a UnionFile) + + // If base is file or nonreadable, return overlay + dir, err = IsDir(u.base, name) + if !dir || err != nil { + return u.layer.Open(name) + } + + // Both base & layer are directories + // Return union file (if opens are without error) + bfile, bErr := u.base.Open(name) + lfile, lErr := u.layer.Open(name) + + // If either have errors at this point something is very wrong. Return nil and the errors + if bErr != nil || lErr != nil { + return nil, fmt.Errorf("BaseErr: %v\nOverlayErr: %v", bErr, lErr) + } + + return &UnionFile{Base: bfile, Layer: lfile}, nil +} + +func (u *CopyOnWriteFs) Mkdir(name string, perm os.FileMode) error { + dir, err := IsDir(u.base, name) + if err != nil { + return u.layer.MkdirAll(name, perm) + } + if dir { + return syscall.EEXIST + } + return u.layer.MkdirAll(name, perm) +} + +func (u *CopyOnWriteFs) Name() string { + return "CopyOnWriteFs" +} + +func (u *CopyOnWriteFs) MkdirAll(name string, perm os.FileMode) error { + dir, err := IsDir(u.base, name) + if err != nil { + return u.layer.MkdirAll(name, perm) + } + if dir { + return syscall.EEXIST + } + return u.layer.MkdirAll(name, perm) +} + +func (u *CopyOnWriteFs) Create(name string) (File, error) { + return u.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666) +} diff --git a/cmd/vendor/github.com/spf13/afero/httpFs.go b/cmd/vendor/github.com/spf13/afero/httpFs.go new file mode 100644 index 0000000000..c42193688c --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/httpFs.go @@ -0,0 +1,110 @@ +// Copyright © 2014 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "errors" + "net/http" + "os" + "path" + "path/filepath" + "strings" + "time" +) + +type httpDir struct { + basePath string + fs HttpFs +} + +func (d httpDir) Open(name string) (http.File, error) { + if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 || + strings.Contains(name, "\x00") { + return nil, errors.New("http: invalid character in file path") + } + dir := string(d.basePath) + if dir == "" { + dir = "." + } + + f, err := d.fs.Open(filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name)))) + if err != nil { + return nil, err + } + return f, nil +} + +type HttpFs struct { + source Fs +} + +func NewHttpFs(source Fs) *HttpFs { + return &HttpFs{source: source} +} + +func (h HttpFs) Dir(s string) *httpDir { + return &httpDir{basePath: s, fs: h} +} + +func (h HttpFs) Name() string { return "h HttpFs" } + +func (h HttpFs) Create(name string) (File, error) { + return h.source.Create(name) +} + +func (h HttpFs) Chmod(name string, mode os.FileMode) error { + return h.source.Chmod(name, mode) +} + +func (h HttpFs) Chtimes(name string, atime time.Time, mtime time.Time) error { + return h.source.Chtimes(name, atime, mtime) +} + +func (h HttpFs) Mkdir(name string, perm os.FileMode) error { + return h.source.Mkdir(name, perm) +} + +func (h HttpFs) MkdirAll(path string, perm os.FileMode) error { + return h.source.MkdirAll(path, perm) +} + +func (h HttpFs) Open(name string) (http.File, error) { + f, err := h.source.Open(name) + if err == nil { + if httpfile, ok := f.(http.File); ok { + return httpfile, nil + } + } + return nil, err +} + +func (h HttpFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + return h.source.OpenFile(name, flag, perm) +} + +func (h HttpFs) Remove(name string) error { + return h.source.Remove(name) +} + +func (h HttpFs) RemoveAll(path string) error { + return h.source.RemoveAll(path) +} + +func (h HttpFs) Rename(oldname, newname string) error { + return h.source.Rename(oldname, newname) +} + +func (h HttpFs) Stat(name string) (os.FileInfo, error) { + return h.source.Stat(name) +} diff --git a/cmd/vendor/github.com/spf13/afero/ioutil.go b/cmd/vendor/github.com/spf13/afero/ioutil.go new file mode 100644 index 0000000000..5c3a3d8fff --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/ioutil.go @@ -0,0 +1,230 @@ +// Copyright ©2015 The Go Authors +// Copyright ©2015 Steve Francia +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "bytes" + "io" + "os" + "path/filepath" + "sort" + "strconv" + "sync" + "time" +) + +// byName implements sort.Interface. +type byName []os.FileInfo + +func (f byName) Len() int { return len(f) } +func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() } +func (f byName) Swap(i, j int) { f[i], f[j] = f[j], f[i] } + +// ReadDir reads the directory named by dirname and returns +// a list of sorted directory entries. +func (a Afero) ReadDir(dirname string) ([]os.FileInfo, error) { + return ReadDir(a.Fs, dirname) +} + +func ReadDir(fs Fs, dirname string) ([]os.FileInfo, error) { + f, err := fs.Open(dirname) + if err != nil { + return nil, err + } + list, err := f.Readdir(-1) + f.Close() + if err != nil { + return nil, err + } + sort.Sort(byName(list)) + return list, nil +} + +// ReadFile reads the file named by filename and returns the contents. +// A successful call returns err == nil, not err == EOF. Because ReadFile +// reads the whole file, it does not treat an EOF from Read as an error +// to be reported. +func (a Afero) ReadFile(filename string) ([]byte, error) { + return ReadFile(a.Fs, filename) +} + +func ReadFile(fs Fs, filename string) ([]byte, error) { + f, err := fs.Open(filename) + if err != nil { + return nil, err + } + defer f.Close() + // It's a good but not certain bet that FileInfo will tell us exactly how much to + // read, so let's try it but be prepared for the answer to be wrong. + var n int64 + + if fi, err := f.Stat(); err == nil { + // Don't preallocate a huge buffer, just in case. + if size := fi.Size(); size < 1e9 { + n = size + } + } + // As initial capacity for readAll, use n + a little extra in case Size is zero, + // and to avoid another allocation after Read has filled the buffer. The readAll + // call will read into its allocated internal buffer cheaply. If the size was + // wrong, we'll either waste some space off the end or reallocate as needed, but + // in the overwhelmingly common case we'll get it just right. + return readAll(f, n+bytes.MinRead) +} + +// readAll reads from r until an error or EOF and returns the data it read +// from the internal buffer allocated with a specified capacity. +func readAll(r io.Reader, capacity int64) (b []byte, err error) { + buf := bytes.NewBuffer(make([]byte, 0, capacity)) + // If the buffer overflows, we will get bytes.ErrTooLarge. + // Return that as an error. Any other panic remains. + defer func() { + e := recover() + if e == nil { + return + } + if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge { + err = panicErr + } else { + panic(e) + } + }() + _, err = buf.ReadFrom(r) + return buf.Bytes(), err +} + +// ReadAll reads from r until an error or EOF and returns the data it read. +// A successful call returns err == nil, not err == EOF. Because ReadAll is +// defined to read from src until EOF, it does not treat an EOF from Read +// as an error to be reported. +func ReadAll(r io.Reader) ([]byte, error) { + return readAll(r, bytes.MinRead) +} + +// WriteFile writes data to a file named by filename. +// If the file does not exist, WriteFile creates it with permissions perm; +// otherwise WriteFile truncates it before writing. +func (a Afero) WriteFile(filename string, data []byte, perm os.FileMode) error { + return WriteFile(a.Fs, filename, data, perm) +} + +func WriteFile(fs Fs, filename string, data []byte, perm os.FileMode) error { + f, err := fs.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) + if err != nil { + return err + } + n, err := f.Write(data) + if err == nil && n < len(data) { + err = io.ErrShortWrite + } + if err1 := f.Close(); err == nil { + err = err1 + } + return err +} + +// Random number state. +// We generate random temporary file names so that there's a good +// chance the file doesn't exist yet - keeps the number of tries in +// TempFile to a minimum. +var rand uint32 +var randmu sync.Mutex + +func reseed() uint32 { + return uint32(time.Now().UnixNano() + int64(os.Getpid())) +} + +func nextSuffix() string { + randmu.Lock() + r := rand + if r == 0 { + r = reseed() + } + r = r*1664525 + 1013904223 // constants from Numerical Recipes + rand = r + randmu.Unlock() + return strconv.Itoa(int(1e9 + r%1e9))[1:] +} + +// TempFile creates a new temporary file in the directory dir +// with a name beginning with prefix, opens the file for reading +// and writing, and returns the resulting *File. +// If dir is the empty string, TempFile uses the default directory +// for temporary files (see os.TempDir). +// Multiple programs calling TempFile simultaneously +// will not choose the same file. The caller can use f.Name() +// to find the pathname of the file. It is the caller's responsibility +// to remove the file when no longer needed. +func (a Afero) TempFile(dir, prefix string) (f File, err error) { + return TempFile(a.Fs, dir, prefix) +} + +func TempFile(fs Fs, dir, prefix string) (f File, err error) { + if dir == "" { + dir = os.TempDir() + } + + nconflict := 0 + for i := 0; i < 10000; i++ { + name := filepath.Join(dir, prefix+nextSuffix()) + f, err = fs.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) + if os.IsExist(err) { + if nconflict++; nconflict > 10 { + randmu.Lock() + rand = reseed() + randmu.Unlock() + } + continue + } + break + } + return +} + +// TempDir creates a new temporary directory in the directory dir +// with a name beginning with prefix and returns the path of the +// new directory. If dir is the empty string, TempDir uses the +// default directory for temporary files (see os.TempDir). +// Multiple programs calling TempDir simultaneously +// will not choose the same directory. It is the caller's responsibility +// to remove the directory when no longer needed. +func (a Afero) TempDir(dir, prefix string) (name string, err error) { + return TempDir(a.Fs, dir, prefix) +} +func TempDir(fs Fs, dir, prefix string) (name string, err error) { + if dir == "" { + dir = os.TempDir() + } + + nconflict := 0 + for i := 0; i < 10000; i++ { + try := filepath.Join(dir, prefix+nextSuffix()) + err = fs.Mkdir(try, 0700) + if os.IsExist(err) { + if nconflict++; nconflict > 10 { + randmu.Lock() + rand = reseed() + randmu.Unlock() + } + continue + } + if err == nil { + name = try + } + break + } + return +} diff --git a/cmd/vendor/github.com/spf13/afero/lstater.go b/cmd/vendor/github.com/spf13/afero/lstater.go new file mode 100644 index 0000000000..89c1bfc0a7 --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/lstater.go @@ -0,0 +1,27 @@ +// Copyright © 2018 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "os" +) + +// Lstater is an optional interface in Afero. It is only implemented by the +// filesystems saying so. +// It will call Lstat if the filesystem iself is, or it delegates to, the os filesystem. +// Else it will call Stat. +// In addtion to the FileInfo, it will return a boolean telling whether Lstat was called or not. +type Lstater interface { + LstatIfPossible(name string) (os.FileInfo, bool, error) +} diff --git a/cmd/vendor/github.com/spf13/afero/match.go b/cmd/vendor/github.com/spf13/afero/match.go new file mode 100644 index 0000000000..c18a87fb71 --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/match.go @@ -0,0 +1,110 @@ +// Copyright © 2014 Steve Francia . +// Copyright 2009 The Go Authors. All rights reserved. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "path/filepath" + "sort" + "strings" +) + +// Glob returns the names of all files matching pattern or nil +// if there is no matching file. The syntax of patterns is the same +// as in Match. The pattern may describe hierarchical names such as +// /usr/*/bin/ed (assuming the Separator is '/'). +// +// Glob ignores file system errors such as I/O errors reading directories. +// The only possible returned error is ErrBadPattern, when pattern +// is malformed. +// +// This was adapted from (http://golang.org/pkg/path/filepath) and uses several +// built-ins from that package. +func Glob(fs Fs, pattern string) (matches []string, err error) { + if !hasMeta(pattern) { + // Lstat not supported by a ll filesystems. + if _, err = lstatIfPossible(fs, pattern); err != nil { + return nil, nil + } + return []string{pattern}, nil + } + + dir, file := filepath.Split(pattern) + switch dir { + case "": + dir = "." + case string(filepath.Separator): + // nothing + default: + dir = dir[0 : len(dir)-1] // chop off trailing separator + } + + if !hasMeta(dir) { + return glob(fs, dir, file, nil) + } + + var m []string + m, err = Glob(fs, dir) + if err != nil { + return + } + for _, d := range m { + matches, err = glob(fs, d, file, matches) + if err != nil { + return + } + } + return +} + +// glob searches for files matching pattern in the directory dir +// and appends them to matches. If the directory cannot be +// opened, it returns the existing matches. New matches are +// added in lexicographical order. +func glob(fs Fs, dir, pattern string, matches []string) (m []string, e error) { + m = matches + fi, err := fs.Stat(dir) + if err != nil { + return + } + if !fi.IsDir() { + return + } + d, err := fs.Open(dir) + if err != nil { + return + } + defer d.Close() + + names, _ := d.Readdirnames(-1) + sort.Strings(names) + + for _, n := range names { + matched, err := filepath.Match(pattern, n) + if err != nil { + return m, err + } + if matched { + m = append(m, filepath.Join(dir, n)) + } + } + return +} + +// hasMeta reports whether path contains any of the magic characters +// recognized by Match. +func hasMeta(path string) bool { + // TODO(niemeyer): Should other magic characters be added here? + return strings.IndexAny(path, "*?[") >= 0 +} diff --git a/cmd/vendor/github.com/spf13/afero/mem/dir.go b/cmd/vendor/github.com/spf13/afero/mem/dir.go new file mode 100644 index 0000000000..e104013f45 --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/mem/dir.go @@ -0,0 +1,37 @@ +// Copyright © 2014 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mem + +type Dir interface { + Len() int + Names() []string + Files() []*FileData + Add(*FileData) + Remove(*FileData) +} + +func RemoveFromMemDir(dir *FileData, f *FileData) { + dir.memDir.Remove(f) +} + +func AddToMemDir(dir *FileData, f *FileData) { + dir.memDir.Add(f) +} + +func InitializeDir(d *FileData) { + if d.memDir == nil { + d.dir = true + d.memDir = &DirMap{} + } +} diff --git a/cmd/vendor/github.com/spf13/afero/mem/dirmap.go b/cmd/vendor/github.com/spf13/afero/mem/dirmap.go new file mode 100644 index 0000000000..03a57ee5b5 --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/mem/dirmap.go @@ -0,0 +1,43 @@ +// Copyright © 2015 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mem + +import "sort" + +type DirMap map[string]*FileData + +func (m DirMap) Len() int { return len(m) } +func (m DirMap) Add(f *FileData) { m[f.name] = f } +func (m DirMap) Remove(f *FileData) { delete(m, f.name) } +func (m DirMap) Files() (files []*FileData) { + for _, f := range m { + files = append(files, f) + } + sort.Sort(filesSorter(files)) + return files +} + +// implement sort.Interface for []*FileData +type filesSorter []*FileData + +func (s filesSorter) Len() int { return len(s) } +func (s filesSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s filesSorter) Less(i, j int) bool { return s[i].name < s[j].name } + +func (m DirMap) Names() (names []string) { + for x := range m { + names = append(names, x) + } + return names +} diff --git a/cmd/vendor/github.com/spf13/afero/mem/file.go b/cmd/vendor/github.com/spf13/afero/mem/file.go new file mode 100644 index 0000000000..7af2fb56ff --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/mem/file.go @@ -0,0 +1,317 @@ +// Copyright © 2015 Steve Francia . +// Copyright 2013 tsuru authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mem + +import ( + "bytes" + "errors" + "io" + "os" + "path/filepath" + "sync" + "sync/atomic" +) + +import "time" + +const FilePathSeparator = string(filepath.Separator) + +type File struct { + // atomic requires 64-bit alignment for struct field access + at int64 + readDirCount int64 + closed bool + readOnly bool + fileData *FileData +} + +func NewFileHandle(data *FileData) *File { + return &File{fileData: data} +} + +func NewReadOnlyFileHandle(data *FileData) *File { + return &File{fileData: data, readOnly: true} +} + +func (f File) Data() *FileData { + return f.fileData +} + +type FileData struct { + sync.Mutex + name string + data []byte + memDir Dir + dir bool + mode os.FileMode + modtime time.Time +} + +func (d *FileData) Name() string { + d.Lock() + defer d.Unlock() + return d.name +} + +func CreateFile(name string) *FileData { + return &FileData{name: name, mode: os.ModeTemporary, modtime: time.Now()} +} + +func CreateDir(name string) *FileData { + return &FileData{name: name, memDir: &DirMap{}, dir: true} +} + +func ChangeFileName(f *FileData, newname string) { + f.Lock() + f.name = newname + f.Unlock() +} + +func SetMode(f *FileData, mode os.FileMode) { + f.Lock() + f.mode = mode + f.Unlock() +} + +func SetModTime(f *FileData, mtime time.Time) { + f.Lock() + setModTime(f, mtime) + f.Unlock() +} + +func setModTime(f *FileData, mtime time.Time) { + f.modtime = mtime +} + +func GetFileInfo(f *FileData) *FileInfo { + return &FileInfo{f} +} + +func (f *File) Open() error { + atomic.StoreInt64(&f.at, 0) + atomic.StoreInt64(&f.readDirCount, 0) + f.fileData.Lock() + f.closed = false + f.fileData.Unlock() + return nil +} + +func (f *File) Close() error { + f.fileData.Lock() + f.closed = true + if !f.readOnly { + setModTime(f.fileData, time.Now()) + } + f.fileData.Unlock() + return nil +} + +func (f *File) Name() string { + return f.fileData.Name() +} + +func (f *File) Stat() (os.FileInfo, error) { + return &FileInfo{f.fileData}, nil +} + +func (f *File) Sync() error { + return nil +} + +func (f *File) Readdir(count int) (res []os.FileInfo, err error) { + if !f.fileData.dir { + return nil, &os.PathError{Op: "readdir", Path: f.fileData.name, Err: errors.New("not a dir")} + } + var outLength int64 + + f.fileData.Lock() + files := f.fileData.memDir.Files()[f.readDirCount:] + if count > 0 { + if len(files) < count { + outLength = int64(len(files)) + } else { + outLength = int64(count) + } + if len(files) == 0 { + err = io.EOF + } + } else { + outLength = int64(len(files)) + } + f.readDirCount += outLength + f.fileData.Unlock() + + res = make([]os.FileInfo, outLength) + for i := range res { + res[i] = &FileInfo{files[i]} + } + + return res, err +} + +func (f *File) Readdirnames(n int) (names []string, err error) { + fi, err := f.Readdir(n) + names = make([]string, len(fi)) + for i, f := range fi { + _, names[i] = filepath.Split(f.Name()) + } + return names, err +} + +func (f *File) Read(b []byte) (n int, err error) { + f.fileData.Lock() + defer f.fileData.Unlock() + if f.closed == true { + return 0, ErrFileClosed + } + if len(b) > 0 && int(f.at) == len(f.fileData.data) { + return 0, io.EOF + } + if int(f.at) > len(f.fileData.data) { + return 0, io.ErrUnexpectedEOF + } + if len(f.fileData.data)-int(f.at) >= len(b) { + n = len(b) + } else { + n = len(f.fileData.data) - int(f.at) + } + copy(b, f.fileData.data[f.at:f.at+int64(n)]) + atomic.AddInt64(&f.at, int64(n)) + return +} + +func (f *File) ReadAt(b []byte, off int64) (n int, err error) { + atomic.StoreInt64(&f.at, off) + return f.Read(b) +} + +func (f *File) Truncate(size int64) error { + if f.closed == true { + return ErrFileClosed + } + if f.readOnly { + return &os.PathError{Op: "truncate", Path: f.fileData.name, Err: errors.New("file handle is read only")} + } + if size < 0 { + return ErrOutOfRange + } + if size > int64(len(f.fileData.data)) { + diff := size - int64(len(f.fileData.data)) + f.fileData.data = append(f.fileData.data, bytes.Repeat([]byte{00}, int(diff))...) + } else { + f.fileData.data = f.fileData.data[0:size] + } + setModTime(f.fileData, time.Now()) + return nil +} + +func (f *File) Seek(offset int64, whence int) (int64, error) { + if f.closed == true { + return 0, ErrFileClosed + } + switch whence { + case 0: + atomic.StoreInt64(&f.at, offset) + case 1: + atomic.AddInt64(&f.at, int64(offset)) + case 2: + atomic.StoreInt64(&f.at, int64(len(f.fileData.data))+offset) + } + return f.at, nil +} + +func (f *File) Write(b []byte) (n int, err error) { + if f.readOnly { + return 0, &os.PathError{Op: "write", Path: f.fileData.name, Err: errors.New("file handle is read only")} + } + n = len(b) + cur := atomic.LoadInt64(&f.at) + f.fileData.Lock() + defer f.fileData.Unlock() + diff := cur - int64(len(f.fileData.data)) + var tail []byte + if n+int(cur) < len(f.fileData.data) { + tail = f.fileData.data[n+int(cur):] + } + if diff > 0 { + f.fileData.data = append(bytes.Repeat([]byte{00}, int(diff)), b...) + f.fileData.data = append(f.fileData.data, tail...) + } else { + f.fileData.data = append(f.fileData.data[:cur], b...) + f.fileData.data = append(f.fileData.data, tail...) + } + setModTime(f.fileData, time.Now()) + + atomic.StoreInt64(&f.at, int64(len(f.fileData.data))) + return +} + +func (f *File) WriteAt(b []byte, off int64) (n int, err error) { + atomic.StoreInt64(&f.at, off) + return f.Write(b) +} + +func (f *File) WriteString(s string) (ret int, err error) { + return f.Write([]byte(s)) +} + +func (f *File) Info() *FileInfo { + return &FileInfo{f.fileData} +} + +type FileInfo struct { + *FileData +} + +// Implements os.FileInfo +func (s *FileInfo) Name() string { + s.Lock() + _, name := filepath.Split(s.name) + s.Unlock() + return name +} +func (s *FileInfo) Mode() os.FileMode { + s.Lock() + defer s.Unlock() + return s.mode +} +func (s *FileInfo) ModTime() time.Time { + s.Lock() + defer s.Unlock() + return s.modtime +} +func (s *FileInfo) IsDir() bool { + s.Lock() + defer s.Unlock() + return s.dir +} +func (s *FileInfo) Sys() interface{} { return nil } +func (s *FileInfo) Size() int64 { + if s.IsDir() { + return int64(42) + } + s.Lock() + defer s.Unlock() + return int64(len(s.data)) +} + +var ( + ErrFileClosed = errors.New("File is closed") + ErrOutOfRange = errors.New("Out of range") + ErrTooLarge = errors.New("Too large") + ErrFileNotFound = os.ErrNotExist + ErrFileExists = os.ErrExist + ErrDestinationExists = os.ErrExist +) diff --git a/cmd/vendor/github.com/spf13/afero/memmap.go b/cmd/vendor/github.com/spf13/afero/memmap.go new file mode 100644 index 0000000000..09498e70fb --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/memmap.go @@ -0,0 +1,365 @@ +// Copyright © 2014 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "fmt" + "log" + "os" + "path/filepath" + "strings" + "sync" + "time" + + "github.com/spf13/afero/mem" +) + +type MemMapFs struct { + mu sync.RWMutex + data map[string]*mem.FileData + init sync.Once +} + +func NewMemMapFs() Fs { + return &MemMapFs{} +} + +func (m *MemMapFs) getData() map[string]*mem.FileData { + m.init.Do(func() { + m.data = make(map[string]*mem.FileData) + // Root should always exist, right? + // TODO: what about windows? + m.data[FilePathSeparator] = mem.CreateDir(FilePathSeparator) + }) + return m.data +} + +func (*MemMapFs) Name() string { return "MemMapFS" } + +func (m *MemMapFs) Create(name string) (File, error) { + name = normalizePath(name) + m.mu.Lock() + file := mem.CreateFile(name) + m.getData()[name] = file + m.registerWithParent(file) + m.mu.Unlock() + return mem.NewFileHandle(file), nil +} + +func (m *MemMapFs) unRegisterWithParent(fileName string) error { + f, err := m.lockfreeOpen(fileName) + if err != nil { + return err + } + parent := m.findParent(f) + if parent == nil { + log.Panic("parent of ", f.Name(), " is nil") + } + + parent.Lock() + mem.RemoveFromMemDir(parent, f) + parent.Unlock() + return nil +} + +func (m *MemMapFs) findParent(f *mem.FileData) *mem.FileData { + pdir, _ := filepath.Split(f.Name()) + pdir = filepath.Clean(pdir) + pfile, err := m.lockfreeOpen(pdir) + if err != nil { + return nil + } + return pfile +} + +func (m *MemMapFs) registerWithParent(f *mem.FileData) { + if f == nil { + return + } + parent := m.findParent(f) + if parent == nil { + pdir := filepath.Dir(filepath.Clean(f.Name())) + err := m.lockfreeMkdir(pdir, 0777) + if err != nil { + //log.Println("Mkdir error:", err) + return + } + parent, err = m.lockfreeOpen(pdir) + if err != nil { + //log.Println("Open after Mkdir error:", err) + return + } + } + + parent.Lock() + mem.InitializeDir(parent) + mem.AddToMemDir(parent, f) + parent.Unlock() +} + +func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error { + name = normalizePath(name) + x, ok := m.getData()[name] + if ok { + // Only return ErrFileExists if it's a file, not a directory. + i := mem.FileInfo{FileData: x} + if !i.IsDir() { + return ErrFileExists + } + } else { + item := mem.CreateDir(name) + m.getData()[name] = item + m.registerWithParent(item) + } + return nil +} + +func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error { + name = normalizePath(name) + + m.mu.RLock() + _, ok := m.getData()[name] + m.mu.RUnlock() + if ok { + return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists} + } + + m.mu.Lock() + item := mem.CreateDir(name) + m.getData()[name] = item + m.registerWithParent(item) + m.mu.Unlock() + + m.Chmod(name, perm|os.ModeDir) + + return nil +} + +func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error { + err := m.Mkdir(path, perm) + if err != nil { + if err.(*os.PathError).Err == ErrFileExists { + return nil + } + return err + } + return nil +} + +// Handle some relative paths +func normalizePath(path string) string { + path = filepath.Clean(path) + + switch path { + case ".": + return FilePathSeparator + case "..": + return FilePathSeparator + default: + return path + } +} + +func (m *MemMapFs) Open(name string) (File, error) { + f, err := m.open(name) + if f != nil { + return mem.NewReadOnlyFileHandle(f), err + } + return nil, err +} + +func (m *MemMapFs) openWrite(name string) (File, error) { + f, err := m.open(name) + if f != nil { + return mem.NewFileHandle(f), err + } + return nil, err +} + +func (m *MemMapFs) open(name string) (*mem.FileData, error) { + name = normalizePath(name) + + m.mu.RLock() + f, ok := m.getData()[name] + m.mu.RUnlock() + if !ok { + return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileNotFound} + } + return f, nil +} + +func (m *MemMapFs) lockfreeOpen(name string) (*mem.FileData, error) { + name = normalizePath(name) + f, ok := m.getData()[name] + if ok { + return f, nil + } else { + return nil, ErrFileNotFound + } +} + +func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + chmod := false + file, err := m.openWrite(name) + if os.IsNotExist(err) && (flag&os.O_CREATE > 0) { + file, err = m.Create(name) + chmod = true + } + if err != nil { + return nil, err + } + if flag == os.O_RDONLY { + file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data()) + } + if flag&os.O_APPEND > 0 { + _, err = file.Seek(0, os.SEEK_END) + if err != nil { + file.Close() + return nil, err + } + } + if flag&os.O_TRUNC > 0 && flag&(os.O_RDWR|os.O_WRONLY) > 0 { + err = file.Truncate(0) + if err != nil { + file.Close() + return nil, err + } + } + if chmod { + m.Chmod(name, perm) + } + return file, nil +} + +func (m *MemMapFs) Remove(name string) error { + name = normalizePath(name) + + m.mu.Lock() + defer m.mu.Unlock() + + if _, ok := m.getData()[name]; ok { + err := m.unRegisterWithParent(name) + if err != nil { + return &os.PathError{Op: "remove", Path: name, Err: err} + } + delete(m.getData(), name) + } else { + return &os.PathError{Op: "remove", Path: name, Err: os.ErrNotExist} + } + return nil +} + +func (m *MemMapFs) RemoveAll(path string) error { + path = normalizePath(path) + m.mu.Lock() + m.unRegisterWithParent(path) + m.mu.Unlock() + + m.mu.RLock() + defer m.mu.RUnlock() + + for p, _ := range m.getData() { + if strings.HasPrefix(p, path) { + m.mu.RUnlock() + m.mu.Lock() + delete(m.getData(), p) + m.mu.Unlock() + m.mu.RLock() + } + } + return nil +} + +func (m *MemMapFs) Rename(oldname, newname string) error { + oldname = normalizePath(oldname) + newname = normalizePath(newname) + + if oldname == newname { + return nil + } + + m.mu.RLock() + defer m.mu.RUnlock() + if _, ok := m.getData()[oldname]; ok { + m.mu.RUnlock() + m.mu.Lock() + m.unRegisterWithParent(oldname) + fileData := m.getData()[oldname] + delete(m.getData(), oldname) + mem.ChangeFileName(fileData, newname) + m.getData()[newname] = fileData + m.registerWithParent(fileData) + m.mu.Unlock() + m.mu.RLock() + } else { + return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound} + } + return nil +} + +func (m *MemMapFs) Stat(name string) (os.FileInfo, error) { + f, err := m.Open(name) + if err != nil { + return nil, err + } + fi := mem.GetFileInfo(f.(*mem.File).Data()) + return fi, nil +} + +func (m *MemMapFs) Chmod(name string, mode os.FileMode) error { + name = normalizePath(name) + + m.mu.RLock() + f, ok := m.getData()[name] + m.mu.RUnlock() + if !ok { + return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound} + } + + m.mu.Lock() + mem.SetMode(f, mode) + m.mu.Unlock() + + return nil +} + +func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error { + name = normalizePath(name) + + m.mu.RLock() + f, ok := m.getData()[name] + m.mu.RUnlock() + if !ok { + return &os.PathError{Op: "chtimes", Path: name, Err: ErrFileNotFound} + } + + m.mu.Lock() + mem.SetModTime(f, mtime) + m.mu.Unlock() + + return nil +} + +func (m *MemMapFs) List() { + for _, x := range m.data { + y := mem.FileInfo{FileData: x} + fmt.Println(x.Name(), y.Size()) + } +} + +// func debugMemMapList(fs Fs) { +// if x, ok := fs.(*MemMapFs); ok { +// x.List() +// } +// } diff --git a/cmd/vendor/github.com/spf13/afero/os.go b/cmd/vendor/github.com/spf13/afero/os.go new file mode 100644 index 0000000000..13cc1b84c9 --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/os.go @@ -0,0 +1,101 @@ +// Copyright © 2014 Steve Francia . +// Copyright 2013 tsuru authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "os" + "time" +) + +var _ Lstater = (*OsFs)(nil) + +// OsFs is a Fs implementation that uses functions provided by the os package. +// +// For details in any method, check the documentation of the os package +// (http://golang.org/pkg/os/). +type OsFs struct{} + +func NewOsFs() Fs { + return &OsFs{} +} + +func (OsFs) Name() string { return "OsFs" } + +func (OsFs) Create(name string) (File, error) { + f, e := os.Create(name) + if f == nil { + // while this looks strange, we need to return a bare nil (of type nil) not + // a nil value of type *os.File or nil won't be nil + return nil, e + } + return f, e +} + +func (OsFs) Mkdir(name string, perm os.FileMode) error { + return os.Mkdir(name, perm) +} + +func (OsFs) MkdirAll(path string, perm os.FileMode) error { + return os.MkdirAll(path, perm) +} + +func (OsFs) Open(name string) (File, error) { + f, e := os.Open(name) + if f == nil { + // while this looks strange, we need to return a bare nil (of type nil) not + // a nil value of type *os.File or nil won't be nil + return nil, e + } + return f, e +} + +func (OsFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + f, e := os.OpenFile(name, flag, perm) + if f == nil { + // while this looks strange, we need to return a bare nil (of type nil) not + // a nil value of type *os.File or nil won't be nil + return nil, e + } + return f, e +} + +func (OsFs) Remove(name string) error { + return os.Remove(name) +} + +func (OsFs) RemoveAll(path string) error { + return os.RemoveAll(path) +} + +func (OsFs) Rename(oldname, newname string) error { + return os.Rename(oldname, newname) +} + +func (OsFs) Stat(name string) (os.FileInfo, error) { + return os.Stat(name) +} + +func (OsFs) Chmod(name string, mode os.FileMode) error { + return os.Chmod(name, mode) +} + +func (OsFs) Chtimes(name string, atime time.Time, mtime time.Time) error { + return os.Chtimes(name, atime, mtime) +} + +func (OsFs) LstatIfPossible(name string) (os.FileInfo, bool, error) { + fi, err := os.Lstat(name) + return fi, true, err +} diff --git a/cmd/vendor/github.com/spf13/afero/path.go b/cmd/vendor/github.com/spf13/afero/path.go new file mode 100644 index 0000000000..18f60a0f6b --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/path.go @@ -0,0 +1,106 @@ +// Copyright ©2015 The Go Authors +// Copyright ©2015 Steve Francia +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "os" + "path/filepath" + "sort" +) + +// readDirNames reads the directory named by dirname and returns +// a sorted list of directory entries. +// adapted from https://golang.org/src/path/filepath/path.go +func readDirNames(fs Fs, dirname string) ([]string, error) { + f, err := fs.Open(dirname) + if err != nil { + return nil, err + } + names, err := f.Readdirnames(-1) + f.Close() + if err != nil { + return nil, err + } + sort.Strings(names) + return names, nil +} + +// walk recursively descends path, calling walkFn +// adapted from https://golang.org/src/path/filepath/path.go +func walk(fs Fs, path string, info os.FileInfo, walkFn filepath.WalkFunc) error { + err := walkFn(path, info, nil) + if err != nil { + if info.IsDir() && err == filepath.SkipDir { + return nil + } + return err + } + + if !info.IsDir() { + return nil + } + + names, err := readDirNames(fs, path) + if err != nil { + return walkFn(path, info, err) + } + + for _, name := range names { + filename := filepath.Join(path, name) + fileInfo, err := lstatIfPossible(fs, filename) + if err != nil { + if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir { + return err + } + } else { + err = walk(fs, filename, fileInfo, walkFn) + if err != nil { + if !fileInfo.IsDir() || err != filepath.SkipDir { + return err + } + } + } + } + return nil +} + +// if the filesystem supports it, use Lstat, else use fs.Stat +func lstatIfPossible(fs Fs, path string) (os.FileInfo, error) { + if lfs, ok := fs.(Lstater); ok { + fi, _, err := lfs.LstatIfPossible(path) + return fi, err + } + return fs.Stat(path) +} + +// Walk walks the file tree rooted at root, calling walkFn for each file or +// directory in the tree, including root. All errors that arise visiting files +// and directories are filtered by walkFn. The files are walked in lexical +// order, which makes the output deterministic but means that for very +// large directories Walk can be inefficient. +// Walk does not follow symbolic links. + +func (a Afero) Walk(root string, walkFn filepath.WalkFunc) error { + return Walk(a.Fs, root, walkFn) +} + +func Walk(fs Fs, root string, walkFn filepath.WalkFunc) error { + info, err := lstatIfPossible(fs, root) + if err != nil { + return walkFn(root, nil, err) + } + return walk(fs, root, info, walkFn) +} diff --git a/cmd/vendor/github.com/spf13/afero/readonlyfs.go b/cmd/vendor/github.com/spf13/afero/readonlyfs.go new file mode 100644 index 0000000000..c6376ec373 --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/readonlyfs.go @@ -0,0 +1,80 @@ +package afero + +import ( + "os" + "syscall" + "time" +) + +var _ Lstater = (*ReadOnlyFs)(nil) + +type ReadOnlyFs struct { + source Fs +} + +func NewReadOnlyFs(source Fs) Fs { + return &ReadOnlyFs{source: source} +} + +func (r *ReadOnlyFs) ReadDir(name string) ([]os.FileInfo, error) { + return ReadDir(r.source, name) +} + +func (r *ReadOnlyFs) Chtimes(n string, a, m time.Time) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) Chmod(n string, m os.FileMode) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) Name() string { + return "ReadOnlyFilter" +} + +func (r *ReadOnlyFs) Stat(name string) (os.FileInfo, error) { + return r.source.Stat(name) +} + +func (r *ReadOnlyFs) LstatIfPossible(name string) (os.FileInfo, bool, error) { + if lsf, ok := r.source.(Lstater); ok { + return lsf.LstatIfPossible(name) + } + fi, err := r.Stat(name) + return fi, false, err +} + +func (r *ReadOnlyFs) Rename(o, n string) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) RemoveAll(p string) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) Remove(n string) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + if flag&(os.O_WRONLY|syscall.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 { + return nil, syscall.EPERM + } + return r.source.OpenFile(name, flag, perm) +} + +func (r *ReadOnlyFs) Open(n string) (File, error) { + return r.source.Open(n) +} + +func (r *ReadOnlyFs) Mkdir(n string, p os.FileMode) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) MkdirAll(n string, p os.FileMode) error { + return syscall.EPERM +} + +func (r *ReadOnlyFs) Create(n string) (File, error) { + return nil, syscall.EPERM +} diff --git a/cmd/vendor/github.com/spf13/afero/regexpfs.go b/cmd/vendor/github.com/spf13/afero/regexpfs.go new file mode 100644 index 0000000000..9d92dbc051 --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/regexpfs.go @@ -0,0 +1,214 @@ +package afero + +import ( + "os" + "regexp" + "syscall" + "time" +) + +// The RegexpFs filters files (not directories) by regular expression. Only +// files matching the given regexp will be allowed, all others get a ENOENT error ( +// "No such file or directory"). +// +type RegexpFs struct { + re *regexp.Regexp + source Fs +} + +func NewRegexpFs(source Fs, re *regexp.Regexp) Fs { + return &RegexpFs{source: source, re: re} +} + +type RegexpFile struct { + f File + re *regexp.Regexp +} + +func (r *RegexpFs) matchesName(name string) error { + if r.re == nil { + return nil + } + if r.re.MatchString(name) { + return nil + } + return syscall.ENOENT +} + +func (r *RegexpFs) dirOrMatches(name string) error { + dir, err := IsDir(r.source, name) + if err != nil { + return err + } + if dir { + return nil + } + return r.matchesName(name) +} + +func (r *RegexpFs) Chtimes(name string, a, m time.Time) error { + if err := r.dirOrMatches(name); err != nil { + return err + } + return r.source.Chtimes(name, a, m) +} + +func (r *RegexpFs) Chmod(name string, mode os.FileMode) error { + if err := r.dirOrMatches(name); err != nil { + return err + } + return r.source.Chmod(name, mode) +} + +func (r *RegexpFs) Name() string { + return "RegexpFs" +} + +func (r *RegexpFs) Stat(name string) (os.FileInfo, error) { + if err := r.dirOrMatches(name); err != nil { + return nil, err + } + return r.source.Stat(name) +} + +func (r *RegexpFs) Rename(oldname, newname string) error { + dir, err := IsDir(r.source, oldname) + if err != nil { + return err + } + if dir { + return nil + } + if err := r.matchesName(oldname); err != nil { + return err + } + if err := r.matchesName(newname); err != nil { + return err + } + return r.source.Rename(oldname, newname) +} + +func (r *RegexpFs) RemoveAll(p string) error { + dir, err := IsDir(r.source, p) + if err != nil { + return err + } + if !dir { + if err := r.matchesName(p); err != nil { + return err + } + } + return r.source.RemoveAll(p) +} + +func (r *RegexpFs) Remove(name string) error { + if err := r.dirOrMatches(name); err != nil { + return err + } + return r.source.Remove(name) +} + +func (r *RegexpFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + if err := r.dirOrMatches(name); err != nil { + return nil, err + } + return r.source.OpenFile(name, flag, perm) +} + +func (r *RegexpFs) Open(name string) (File, error) { + dir, err := IsDir(r.source, name) + if err != nil { + return nil, err + } + if !dir { + if err := r.matchesName(name); err != nil { + return nil, err + } + } + f, err := r.source.Open(name) + return &RegexpFile{f: f, re: r.re}, nil +} + +func (r *RegexpFs) Mkdir(n string, p os.FileMode) error { + return r.source.Mkdir(n, p) +} + +func (r *RegexpFs) MkdirAll(n string, p os.FileMode) error { + return r.source.MkdirAll(n, p) +} + +func (r *RegexpFs) Create(name string) (File, error) { + if err := r.matchesName(name); err != nil { + return nil, err + } + return r.source.Create(name) +} + +func (f *RegexpFile) Close() error { + return f.f.Close() +} + +func (f *RegexpFile) Read(s []byte) (int, error) { + return f.f.Read(s) +} + +func (f *RegexpFile) ReadAt(s []byte, o int64) (int, error) { + return f.f.ReadAt(s, o) +} + +func (f *RegexpFile) Seek(o int64, w int) (int64, error) { + return f.f.Seek(o, w) +} + +func (f *RegexpFile) Write(s []byte) (int, error) { + return f.f.Write(s) +} + +func (f *RegexpFile) WriteAt(s []byte, o int64) (int, error) { + return f.f.WriteAt(s, o) +} + +func (f *RegexpFile) Name() string { + return f.f.Name() +} + +func (f *RegexpFile) Readdir(c int) (fi []os.FileInfo, err error) { + var rfi []os.FileInfo + rfi, err = f.f.Readdir(c) + if err != nil { + return nil, err + } + for _, i := range rfi { + if i.IsDir() || f.re.MatchString(i.Name()) { + fi = append(fi, i) + } + } + return fi, nil +} + +func (f *RegexpFile) Readdirnames(c int) (n []string, err error) { + fi, err := f.Readdir(c) + if err != nil { + return nil, err + } + for _, s := range fi { + n = append(n, s.Name()) + } + return n, nil +} + +func (f *RegexpFile) Stat() (os.FileInfo, error) { + return f.f.Stat() +} + +func (f *RegexpFile) Sync() error { + return f.f.Sync() +} + +func (f *RegexpFile) Truncate(s int64) error { + return f.f.Truncate(s) +} + +func (f *RegexpFile) WriteString(s string) (int, error) { + return f.f.WriteString(s) +} diff --git a/cmd/vendor/github.com/spf13/afero/sftpfs/file.go b/cmd/vendor/github.com/spf13/afero/sftpfs/file.go new file mode 100644 index 0000000000..e4ccb55c0c --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/sftpfs/file.go @@ -0,0 +1,95 @@ +// Copyright © 2015 Jerry Jacobs . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sftpfs + +import ( + "github.com/pkg/sftp" + "os" +) + +type File struct { + fd *sftp.File +} + +func FileOpen(s *sftp.Client, name string) (*File, error) { + fd, err := s.Open(name) + if err != nil { + return &File{}, err + } + return &File{fd: fd}, nil +} + +func FileCreate(s *sftp.Client, name string) (*File, error) { + fd, err := s.Create(name) + if err != nil { + return &File{}, err + } + return &File{fd: fd}, nil +} + +func (f *File) Close() error { + return f.fd.Close() +} + +func (f *File) Name() string { + return f.fd.Name() +} + +func (f *File) Stat() (os.FileInfo, error) { + return f.fd.Stat() +} + +func (f *File) Sync() error { + return nil +} + +func (f *File) Truncate(size int64) error { + return f.fd.Truncate(size) +} + +func (f *File) Read(b []byte) (n int, err error) { + return f.fd.Read(b) +} + +// TODO +func (f *File) ReadAt(b []byte, off int64) (n int, err error) { + return 0, nil +} + +// TODO +func (f *File) Readdir(count int) (res []os.FileInfo, err error) { + return nil, nil +} + +// TODO +func (f *File) Readdirnames(n int) (names []string, err error) { + return nil, nil +} + +func (f *File) Seek(offset int64, whence int) (int64, error) { + return f.fd.Seek(offset, whence) +} + +func (f *File) Write(b []byte) (n int, err error) { + return f.fd.Write(b) +} + +// TODO +func (f *File) WriteAt(b []byte, off int64) (n int, err error) { + return 0, nil +} + +func (f *File) WriteString(s string) (ret int, err error) { + return f.fd.Write([]byte(s)) +} diff --git a/cmd/vendor/github.com/spf13/afero/sftpfs/sftp.go b/cmd/vendor/github.com/spf13/afero/sftpfs/sftp.go new file mode 100644 index 0000000000..28721da761 --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/sftpfs/sftp.go @@ -0,0 +1,129 @@ +// Copyright © 2015 Jerry Jacobs . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sftpfs + +import ( + "os" + "time" + + "github.com/pkg/sftp" + "github.com/spf13/afero" +) + +// Fs is a afero.Fs implementation that uses functions provided by the sftp package. +// +// For details in any method, check the documentation of the sftp package +// (github.com/pkg/sftp). +type Fs struct { + client *sftp.Client +} + +func New(client *sftp.Client) afero.Fs { + return &Fs{client: client} +} + +func (s Fs) Name() string { return "sftpfs" } + +func (s Fs) Create(name string) (afero.File, error) { + return FileCreate(s.client, name) +} + +func (s Fs) Mkdir(name string, perm os.FileMode) error { + err := s.client.Mkdir(name) + if err != nil { + return err + } + return s.client.Chmod(name, perm) +} + +func (s Fs) MkdirAll(path string, perm os.FileMode) error { + // Fast path: if we can tell whether path is a directory or file, stop with success or error. + dir, err := s.Stat(path) + if err == nil { + if dir.IsDir() { + return nil + } + return err + } + + // Slow path: make sure parent exists and then call Mkdir for path. + i := len(path) + for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator. + i-- + } + + j := i + for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element. + j-- + } + + if j > 1 { + // Create parent + err = s.MkdirAll(path[0:j-1], perm) + if err != nil { + return err + } + } + + // Parent now exists; invoke Mkdir and use its result. + err = s.Mkdir(path, perm) + if err != nil { + // Handle arguments like "foo/." by + // double-checking that directory doesn't exist. + dir, err1 := s.Lstat(path) + if err1 == nil && dir.IsDir() { + return nil + } + return err + } + return nil +} + +func (s Fs) Open(name string) (afero.File, error) { + return FileOpen(s.client, name) +} + +func (s Fs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) { + return nil, nil +} + +func (s Fs) Remove(name string) error { + return s.client.Remove(name) +} + +func (s Fs) RemoveAll(path string) error { + // TODO have a look at os.RemoveAll + // https://github.com/golang/go/blob/master/src/os/path.go#L66 + return nil +} + +func (s Fs) Rename(oldname, newname string) error { + return s.client.Rename(oldname, newname) +} + +func (s Fs) Stat(name string) (os.FileInfo, error) { + return s.client.Stat(name) +} + +func (s Fs) Lstat(p string) (os.FileInfo, error) { + return s.client.Lstat(p) +} + +func (s Fs) Chmod(name string, mode os.FileMode) error { + return s.client.Chmod(name, mode) +} + +func (s Fs) Chtimes(name string, atime time.Time, mtime time.Time) error { + return s.client.Chtimes(name, atime, mtime) +} diff --git a/cmd/vendor/github.com/spf13/afero/unionFile.go b/cmd/vendor/github.com/spf13/afero/unionFile.go new file mode 100644 index 0000000000..1e78f7d1ef --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/unionFile.go @@ -0,0 +1,305 @@ +package afero + +import ( + "io" + "os" + "path/filepath" + "syscall" +) + +// The UnionFile implements the afero.File interface and will be returned +// when reading a directory present at least in the overlay or opening a file +// for writing. +// +// The calls to +// Readdir() and Readdirnames() merge the file os.FileInfo / names from the +// base and the overlay - for files present in both layers, only those +// from the overlay will be used. +// +// When opening files for writing (Create() / OpenFile() with the right flags) +// the operations will be done in both layers, starting with the overlay. A +// successful read in the overlay will move the cursor position in the base layer +// by the number of bytes read. +type UnionFile struct { + Base File + Layer File + Merger DirsMerger + off int + files []os.FileInfo +} + +func (f *UnionFile) Close() error { + // first close base, so we have a newer timestamp in the overlay. If we'd close + // the overlay first, we'd get a cacheStale the next time we access this file + // -> cache would be useless ;-) + if f.Base != nil { + f.Base.Close() + } + if f.Layer != nil { + return f.Layer.Close() + } + return BADFD +} + +func (f *UnionFile) Read(s []byte) (int, error) { + if f.Layer != nil { + n, err := f.Layer.Read(s) + if (err == nil || err == io.EOF) && f.Base != nil { + // advance the file position also in the base file, the next + // call may be a write at this position (or a seek with SEEK_CUR) + if _, seekErr := f.Base.Seek(int64(n), os.SEEK_CUR); seekErr != nil { + // only overwrite err in case the seek fails: we need to + // report an eventual io.EOF to the caller + err = seekErr + } + } + return n, err + } + if f.Base != nil { + return f.Base.Read(s) + } + return 0, BADFD +} + +func (f *UnionFile) ReadAt(s []byte, o int64) (int, error) { + if f.Layer != nil { + n, err := f.Layer.ReadAt(s, o) + if (err == nil || err == io.EOF) && f.Base != nil { + _, err = f.Base.Seek(o+int64(n), os.SEEK_SET) + } + return n, err + } + if f.Base != nil { + return f.Base.ReadAt(s, o) + } + return 0, BADFD +} + +func (f *UnionFile) Seek(o int64, w int) (pos int64, err error) { + if f.Layer != nil { + pos, err = f.Layer.Seek(o, w) + if (err == nil || err == io.EOF) && f.Base != nil { + _, err = f.Base.Seek(o, w) + } + return pos, err + } + if f.Base != nil { + return f.Base.Seek(o, w) + } + return 0, BADFD +} + +func (f *UnionFile) Write(s []byte) (n int, err error) { + if f.Layer != nil { + n, err = f.Layer.Write(s) + if err == nil && f.Base != nil { // hmm, do we have fixed size files where a write may hit the EOF mark? + _, err = f.Base.Write(s) + } + return n, err + } + if f.Base != nil { + return f.Base.Write(s) + } + return 0, BADFD +} + +func (f *UnionFile) WriteAt(s []byte, o int64) (n int, err error) { + if f.Layer != nil { + n, err = f.Layer.WriteAt(s, o) + if err == nil && f.Base != nil { + _, err = f.Base.WriteAt(s, o) + } + return n, err + } + if f.Base != nil { + return f.Base.WriteAt(s, o) + } + return 0, BADFD +} + +func (f *UnionFile) Name() string { + if f.Layer != nil { + return f.Layer.Name() + } + return f.Base.Name() +} + +// DirsMerger is how UnionFile weaves two directories together. +// It takes the FileInfo slices from the layer and the base and returns a +// single view. +type DirsMerger func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error) + +var defaultUnionMergeDirsFn = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error) { + var files = make(map[string]os.FileInfo) + + for _, fi := range lofi { + files[fi.Name()] = fi + } + + for _, fi := range bofi { + if _, exists := files[fi.Name()]; !exists { + files[fi.Name()] = fi + } + } + + rfi := make([]os.FileInfo, len(files)) + + i := 0 + for _, fi := range files { + rfi[i] = fi + i++ + } + + return rfi, nil + +} + +// Readdir will weave the two directories together and +// return a single view of the overlayed directories +func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) { + var merge DirsMerger = f.Merger + if merge == nil { + merge = defaultUnionMergeDirsFn + } + + if f.off == 0 { + var lfi []os.FileInfo + if f.Layer != nil { + lfi, err = f.Layer.Readdir(-1) + if err != nil { + return nil, err + } + } + + var bfi []os.FileInfo + if f.Base != nil { + bfi, err = f.Base.Readdir(-1) + if err != nil { + return nil, err + } + + } + merged, err := merge(lfi, bfi) + if err != nil { + return nil, err + } + f.files = append(f.files, merged...) + } + if c == -1 { + return f.files[f.off:], nil + } + defer func() { f.off += c }() + return f.files[f.off:c], nil +} + +func (f *UnionFile) Readdirnames(c int) ([]string, error) { + rfi, err := f.Readdir(c) + if err != nil { + return nil, err + } + var names []string + for _, fi := range rfi { + names = append(names, fi.Name()) + } + return names, nil +} + +func (f *UnionFile) Stat() (os.FileInfo, error) { + if f.Layer != nil { + return f.Layer.Stat() + } + if f.Base != nil { + return f.Base.Stat() + } + return nil, BADFD +} + +func (f *UnionFile) Sync() (err error) { + if f.Layer != nil { + err = f.Layer.Sync() + if err == nil && f.Base != nil { + err = f.Base.Sync() + } + return err + } + if f.Base != nil { + return f.Base.Sync() + } + return BADFD +} + +func (f *UnionFile) Truncate(s int64) (err error) { + if f.Layer != nil { + err = f.Layer.Truncate(s) + if err == nil && f.Base != nil { + err = f.Base.Truncate(s) + } + return err + } + if f.Base != nil { + return f.Base.Truncate(s) + } + return BADFD +} + +func (f *UnionFile) WriteString(s string) (n int, err error) { + if f.Layer != nil { + n, err = f.Layer.WriteString(s) + if err == nil && f.Base != nil { + _, err = f.Base.WriteString(s) + } + return n, err + } + if f.Base != nil { + return f.Base.WriteString(s) + } + return 0, BADFD +} + +func copyToLayer(base Fs, layer Fs, name string) error { + bfh, err := base.Open(name) + if err != nil { + return err + } + defer bfh.Close() + + // First make sure the directory exists + exists, err := Exists(layer, filepath.Dir(name)) + if err != nil { + return err + } + if !exists { + err = layer.MkdirAll(filepath.Dir(name), 0777) // FIXME? + if err != nil { + return err + } + } + + // Create the file on the overlay + lfh, err := layer.Create(name) + if err != nil { + return err + } + n, err := io.Copy(lfh, bfh) + if err != nil { + // If anything fails, clean up the file + layer.Remove(name) + lfh.Close() + return err + } + + bfi, err := bfh.Stat() + if err != nil || bfi.Size() != n { + layer.Remove(name) + lfh.Close() + return syscall.EIO + } + + err = lfh.Close() + if err != nil { + layer.Remove(name) + lfh.Close() + return err + } + return layer.Chtimes(name, bfi.ModTime(), bfi.ModTime()) +} diff --git a/cmd/vendor/github.com/spf13/afero/util.go b/cmd/vendor/github.com/spf13/afero/util.go new file mode 100644 index 0000000000..4f253f481e --- /dev/null +++ b/cmd/vendor/github.com/spf13/afero/util.go @@ -0,0 +1,330 @@ +// Copyright ©2015 Steve Francia +// Portions Copyright ©2015 The Hugo Authors +// Portions Copyright 2016-present Bjørn Erik Pedersen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package afero + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "strings" + "unicode" + + "golang.org/x/text/transform" + "golang.org/x/text/unicode/norm" +) + +// Filepath separator defined by os.Separator. +const FilePathSeparator = string(filepath.Separator) + +// Takes a reader and a path and writes the content +func (a Afero) WriteReader(path string, r io.Reader) (err error) { + return WriteReader(a.Fs, path, r) +} + +func WriteReader(fs Fs, path string, r io.Reader) (err error) { + dir, _ := filepath.Split(path) + ospath := filepath.FromSlash(dir) + + if ospath != "" { + err = fs.MkdirAll(ospath, 0777) // rwx, rw, r + if err != nil { + if err != os.ErrExist { + return err + } + } + } + + file, err := fs.Create(path) + if err != nil { + return + } + defer file.Close() + + _, err = io.Copy(file, r) + return +} + +// Same as WriteReader but checks to see if file/directory already exists. +func (a Afero) SafeWriteReader(path string, r io.Reader) (err error) { + return SafeWriteReader(a.Fs, path, r) +} + +func SafeWriteReader(fs Fs, path string, r io.Reader) (err error) { + dir, _ := filepath.Split(path) + ospath := filepath.FromSlash(dir) + + if ospath != "" { + err = fs.MkdirAll(ospath, 0777) // rwx, rw, r + if err != nil { + return + } + } + + exists, err := Exists(fs, path) + if err != nil { + return + } + if exists { + return fmt.Errorf("%v already exists", path) + } + + file, err := fs.Create(path) + if err != nil { + return + } + defer file.Close() + + _, err = io.Copy(file, r) + return +} + +func (a Afero) GetTempDir(subPath string) string { + return GetTempDir(a.Fs, subPath) +} + +// GetTempDir returns the default temp directory with trailing slash +// if subPath is not empty then it will be created recursively with mode 777 rwx rwx rwx +func GetTempDir(fs Fs, subPath string) string { + addSlash := func(p string) string { + if FilePathSeparator != p[len(p)-1:] { + p = p + FilePathSeparator + } + return p + } + dir := addSlash(os.TempDir()) + + if subPath != "" { + // preserve windows backslash :-( + if FilePathSeparator == "\\" { + subPath = strings.Replace(subPath, "\\", "____", -1) + } + dir = dir + UnicodeSanitize((subPath)) + if FilePathSeparator == "\\" { + dir = strings.Replace(dir, "____", "\\", -1) + } + + if exists, _ := Exists(fs, dir); exists { + return addSlash(dir) + } + + err := fs.MkdirAll(dir, 0777) + if err != nil { + panic(err) + } + dir = addSlash(dir) + } + return dir +} + +// Rewrite string to remove non-standard path characters +func UnicodeSanitize(s string) string { + source := []rune(s) + target := make([]rune, 0, len(source)) + + for _, r := range source { + if unicode.IsLetter(r) || + unicode.IsDigit(r) || + unicode.IsMark(r) || + r == '.' || + r == '/' || + r == '\\' || + r == '_' || + r == '-' || + r == '%' || + r == ' ' || + r == '#' { + target = append(target, r) + } + } + + return string(target) +} + +// Transform characters with accents into plain forms. +func NeuterAccents(s string) string { + t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC) + result, _, _ := transform.String(t, string(s)) + + return result +} + +func isMn(r rune) bool { + return unicode.Is(unicode.Mn, r) // Mn: nonspacing marks +} + +func (a Afero) FileContainsBytes(filename string, subslice []byte) (bool, error) { + return FileContainsBytes(a.Fs, filename, subslice) +} + +// Check if a file contains a specified byte slice. +func FileContainsBytes(fs Fs, filename string, subslice []byte) (bool, error) { + f, err := fs.Open(filename) + if err != nil { + return false, err + } + defer f.Close() + + return readerContainsAny(f, subslice), nil +} + +func (a Afero) FileContainsAnyBytes(filename string, subslices [][]byte) (bool, error) { + return FileContainsAnyBytes(a.Fs, filename, subslices) +} + +// Check if a file contains any of the specified byte slices. +func FileContainsAnyBytes(fs Fs, filename string, subslices [][]byte) (bool, error) { + f, err := fs.Open(filename) + if err != nil { + return false, err + } + defer f.Close() + + return readerContainsAny(f, subslices...), nil +} + +// readerContains reports whether any of the subslices is within r. +func readerContainsAny(r io.Reader, subslices ...[]byte) bool { + + if r == nil || len(subslices) == 0 { + return false + } + + largestSlice := 0 + + for _, sl := range subslices { + if len(sl) > largestSlice { + largestSlice = len(sl) + } + } + + if largestSlice == 0 { + return false + } + + bufflen := largestSlice * 4 + halflen := bufflen / 2 + buff := make([]byte, bufflen) + var err error + var n, i int + + for { + i++ + if i == 1 { + n, err = io.ReadAtLeast(r, buff[:halflen], halflen) + } else { + if i != 2 { + // shift left to catch overlapping matches + copy(buff[:], buff[halflen:]) + } + n, err = io.ReadAtLeast(r, buff[halflen:], halflen) + } + + if n > 0 { + for _, sl := range subslices { + if bytes.Contains(buff, sl) { + return true + } + } + } + + if err != nil { + break + } + } + return false +} + +func (a Afero) DirExists(path string) (bool, error) { + return DirExists(a.Fs, path) +} + +// DirExists checks if a path exists and is a directory. +func DirExists(fs Fs, path string) (bool, error) { + fi, err := fs.Stat(path) + if err == nil && fi.IsDir() { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} + +func (a Afero) IsDir(path string) (bool, error) { + return IsDir(a.Fs, path) +} + +// IsDir checks if a given path is a directory. +func IsDir(fs Fs, path string) (bool, error) { + fi, err := fs.Stat(path) + if err != nil { + return false, err + } + return fi.IsDir(), nil +} + +func (a Afero) IsEmpty(path string) (bool, error) { + return IsEmpty(a.Fs, path) +} + +// IsEmpty checks if a given file or directory is empty. +func IsEmpty(fs Fs, path string) (bool, error) { + if b, _ := Exists(fs, path); !b { + return false, fmt.Errorf("%q path does not exist", path) + } + fi, err := fs.Stat(path) + if err != nil { + return false, err + } + if fi.IsDir() { + f, err := fs.Open(path) + if err != nil { + return false, err + } + defer f.Close() + list, err := f.Readdir(-1) + return len(list) == 0, nil + } + return fi.Size() == 0, nil +} + +func (a Afero) Exists(path string) (bool, error) { + return Exists(a.Fs, path) +} + +// Check if a file or directory exists. +func Exists(fs Fs, path string) (bool, error) { + _, err := fs.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} + +func FullBaseFsPath(basePathFs *BasePathFs, relativePath string) string { + combinedPath := filepath.Join(basePathFs.path, relativePath) + if parent, ok := basePathFs.source.(*BasePathFs); ok { + return FullBaseFsPath(parent, combinedPath) + } + + return combinedPath +} diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/generator.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/generator.go index 684b950dc4..5123118732 100644 --- a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/generator.go +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/generator.go @@ -24,8 +24,10 @@ import ( "strings" "github.com/ghodss/yaml" + "github.com/spf13/afero" extensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/gengo/args" + "k8s.io/gengo/types" crdutil "sigs.k8s.io/controller-tools/pkg/crd/util" "sigs.k8s.io/controller-tools/pkg/internal/codegen" "sigs.k8s.io/controller-tools/pkg/internal/codegen/parse" @@ -39,12 +41,23 @@ type Generator struct { Domain string Namespace string SkipMapValidation bool + + // OutFs is filesystem to be used for writing out the result + OutFs afero.Fs + + // apisPkg is the absolute Go pkg name for current project's 'pkg/apis' pkg. + // This is needed to determine if a Type belongs to the project or it is a referred Type. + apisPkg string } // ValidateAndInitFields validate and init generator fields. func (c *Generator) ValidateAndInitFields() error { var err error + if c.OutFs == nil { + c.OutFs = afero.NewOsFs() + } + if len(c.RootPath) == 0 { // Take current path as root path if not specified. c.RootPath, err = os.Getwd() @@ -61,18 +74,9 @@ func (c *Generator) ValidateAndInitFields() error { // If Domain is not explicitly specified, // try to search for PROJECT file as a basis. if len(c.Domain) == 0 { - for { - if crdutil.PathHasProjectFile(c.RootPath) { - break - } - - if crdutil.IsGoSrcPath(c.RootPath) { - return fmt.Errorf("failed to find working directory that contains %s", "PROJECT") - } - - c.RootPath = path.Dir(c.RootPath) + if !crdutil.PathHasProjectFile(c.RootPath) { + return fmt.Errorf("PROJECT file missing in dir %s", c.RootPath) } - c.Domain = crdutil.GetDomainFromProject(c.RootPath) } @@ -82,6 +86,11 @@ func (c *Generator) ValidateAndInitFields() error { return fmt.Errorf("error validating apis path %s: %v", apisPath, err) } + c.apisPkg, err = crdutil.DirToGoPkg(apisPath) + if err != nil { + return err + } + // Init output directory if c.OutputDir == "" { c.OutputDir = path.Join(c.RootPath, "config/crds") @@ -114,22 +123,24 @@ func (c *Generator) Do() error { arguments.CustomArgs = &parse.Options{SkipMapValidation: c.SkipMapValidation} // TODO: find an elegant way to fulfill the domain in APIs. - p := parse.NewAPIs(ctx, arguments, c.Domain) - + p := parse.NewAPIs(ctx, arguments, c.Domain, c.apisPkg) crds := c.getCrds(p) + return c.writeCRDs(crds) +} + +func (c *Generator) writeCRDs(crds map[string][]byte) error { // Ensure output dir exists. - if err := os.MkdirAll(c.OutputDir, os.FileMode(0700)); err != nil { + if err := c.OutFs.MkdirAll(c.OutputDir, os.FileMode(0700)); err != nil { return err } for file, crd := range crds { outFile := path.Join(c.OutputDir, file) - if err := util.WriteFile(outFile, crd); err != nil { + if err := (&util.FileWriter{Fs: c.OutFs}).WriteFile(outFile, crd); err != nil { return err } } - return nil } @@ -138,12 +149,16 @@ func getCRDFileName(resource *codegen.APIResource) string { return strings.Join(elems, "_") + ".yaml" } -func (c *Generator) getCrds(p *parse.APIs) map[string]string { +func (c *Generator) getCrds(p *parse.APIs) map[string][]byte { crds := map[string]extensionsv1beta1.CustomResourceDefinition{} for _, g := range p.APIs.Groups { for _, v := range g.Versions { for _, r := range v.Resources { crd := r.CRD + // ignore types which do not belong to this project + if !c.belongsToAPIsPkg(r.Type) { + continue + } if len(c.Namespace) > 0 { crd.Namespace = c.Namespace } @@ -153,14 +168,20 @@ func (c *Generator) getCrds(p *parse.APIs) map[string]string { } } - result := map[string]string{} + result := map[string][]byte{} for file, crd := range crds { - s, err := yaml.Marshal(crd) + b, err := yaml.Marshal(crd) if err != nil { log.Fatalf("Error: %v", err) } - result[file] = string(s) + result[file] = b } return result } + +// belongsToAPIsPkg returns true if type t is defined under pkg/apis pkg of +// current project. +func (c *Generator) belongsToAPIsPkg(t *types.Type) bool { + return strings.HasPrefix(t.Name.Package, c.apisPkg) +} diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/cmd/manager/main.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/cmd/manager/main.go new file mode 100644 index 0000000000..8a7e8a79b3 --- /dev/null +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/cmd/manager/main.go @@ -0,0 +1,58 @@ +/* + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "log" + + _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" + "sigs.k8s.io/controller-runtime/pkg/client/config" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/runtime/signals" + "sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis" + "sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/controller" +) + +func main() { + // Get a config to talk to the apiserver + cfg, err := config.GetConfig() + if err != nil { + log.Fatal(err) + } + + // Create a new Cmd to provide shared dependencies and start components + mgr, err := manager.New(cfg, manager.Options{}) + if err != nil { + log.Fatal(err) + } + + log.Printf("Registering Components.") + + // Setup Scheme for all resources + if err := apis.AddToScheme(mgr.GetScheme()); err != nil { + log.Fatal(err) + } + + // Setup all Controllers + if err := controller.AddToManager(mgr); err != nil { + log.Fatal(err) + } + + log.Printf("Starting the Cmd.") + + // Start the Cmd + log.Fatal(mgr.Start(signals.SetupSignalHandler())) +} diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/addtoscheme_fun_v1alpha1.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/addtoscheme_fun_v1alpha1.go new file mode 100644 index 0000000000..1bbe4b6e04 --- /dev/null +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/addtoscheme_fun_v1alpha1.go @@ -0,0 +1,25 @@ +/* + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apis + +import ( + "sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1" +) + +func init() { + // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back + AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme) +} diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/apis.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/apis.go new file mode 100644 index 0000000000..15ccbf9c8a --- /dev/null +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/apis.go @@ -0,0 +1,32 @@ +/* + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Generate deepcopy for apis +//go:generate go run ../../vendor/k8s.io/code-generator/cmd/deepcopy-gen/main.go -O zz_generated.deepcopy -i ./... -h ../../hack/boilerplate.go.txt + +// Package apis contains Kubernetes API groups. +package apis + +import ( + "k8s.io/apimachinery/pkg/runtime" +) + +// AddToSchemes may be used to add all resources defined in the project to a Scheme +var AddToSchemes runtime.SchemeBuilder + +// AddToScheme adds all Resources to the Scheme +func AddToScheme(s *runtime.Scheme) error { + return AddToSchemes.AddToScheme(s) +} diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/group.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/group.go new file mode 100644 index 0000000000..5b6760cc6e --- /dev/null +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/group.go @@ -0,0 +1,17 @@ +/* + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package fun contains fun API versions +package fun diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/doc.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/doc.go new file mode 100644 index 0000000000..6641032377 --- /dev/null +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/doc.go @@ -0,0 +1,22 @@ +/* + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1alpha1 contains API Schema definitions for the fun v1alpha1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun +// +k8s:defaulter-gen=TypeMeta +// +groupName=fun.myk8s.io +package v1alpha1 diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/register.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/register.go new file mode 100644 index 0000000000..3d1ffd0d0f --- /dev/null +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/register.go @@ -0,0 +1,37 @@ +/* + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// NOTE: Boilerplate only. Ignore this file. + +// Package v1alpha1 contains API Schema definitions for the fun v1alpha1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun +// +k8s:defaulter-gen=TypeMeta +// +groupName=fun.myk8s.io +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/runtime/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "fun.myk8s.io", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} +) diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/toy_types.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/toy_types.go new file mode 100644 index 0000000000..29e41cfa0e --- /dev/null +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/toy_types.go @@ -0,0 +1,84 @@ +/* + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// ToySpec defines the desired state of Toy +type ToySpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // +kubebuilder:validation:Maximum=100 + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:ExclusiveMinimum=true + Power float32 `json:"power,omitempty"` + Bricks int32 `json:"bricks,omitempty"` + // +kubebuilder:validation:MaxLength=15 + // +kubebuilder:validation:MinLength=1 + Name string `json:"name,omitempty"` + // +kubebuilder:validation:MaxItems=500 + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:UniqueItems=false + Knights []string `json:"knights,omitempty"` + Winner bool `json:"winner,omitempty"` + // +kubebuilder:validation:Enum=Lion,Wolf,Dragon + Alias string `json:"alias,omitempty"` + // +kubebuilder:validation:Enum=1,2,3 + Rank int `json:"rank"` + Comment []byte `json:"comment,omitempty"` + + Template v1.PodTemplateSpec `json:"template"` + Claim v1.PersistentVolumeClaim `json:"claim,omitempty"` +} + +// ToyStatus defines the observed state of Toy +type ToyStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Toy is the Schema for the toys API +// +k8s:openapi-gen=true +type Toy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ToySpec `json:"spec,omitempty"` + Status ToyStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ToyList contains a list of Toy +type ToyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Toy `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Toy{}, &ToyList{}) +} diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/zz_generated.deepcopy.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..79f2edef17 --- /dev/null +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/apis/fun/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,128 @@ +// +build !ignore_autogenerated + +/* + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by main. DO NOT EDIT. + +package v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Toy) DeepCopyInto(out *Toy) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Toy. +func (in *Toy) DeepCopy() *Toy { + if in == nil { + return nil + } + out := new(Toy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Toy) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ToyList) DeepCopyInto(out *ToyList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Toy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ToyList. +func (in *ToyList) DeepCopy() *ToyList { + if in == nil { + return nil + } + out := new(ToyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ToyList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ToySpec) DeepCopyInto(out *ToySpec) { + *out = *in + if in.Knights != nil { + in, out := &in.Knights, &out.Knights + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Comment != nil { + in, out := &in.Comment, &out.Comment + *out = make([]byte, len(*in)) + copy(*out, *in) + } + in.Template.DeepCopyInto(&out.Template) + in.Claim.DeepCopyInto(&out.Claim) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ToySpec. +func (in *ToySpec) DeepCopy() *ToySpec { + if in == nil { + return nil + } + out := new(ToySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ToyStatus) DeepCopyInto(out *ToyStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ToyStatus. +func (in *ToyStatus) DeepCopy() *ToyStatus { + if in == nil { + return nil + } + out := new(ToyStatus) + in.DeepCopyInto(out) + return out +} diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/controller/controller.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/controller/controller.go new file mode 100644 index 0000000000..b2acc50372 --- /dev/null +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/generator/testData/pkg/controller/controller.go @@ -0,0 +1,33 @@ +/* + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controller + +import ( + "sigs.k8s.io/controller-runtime/pkg/manager" +) + +// AddToManagerFuncs is a list of functions to add all Controllers to the Manager +var AddToManagerFuncs []func(manager.Manager) error + +// AddToManager adds all Controllers to the Manager +func AddToManager(m manager.Manager) error { + for _, f := range AddToManagerFuncs { + if err := f(m); err != nil { + return err + } + } + return nil +} diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/util/util.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/util/util.go index ea9a96c3f5..821aab5d25 100644 --- a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/util/util.go +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/crd/util/util.go @@ -18,6 +18,7 @@ package util import ( "bufio" + "fmt" gobuild "go/build" "log" "os" @@ -50,12 +51,31 @@ func IsUnderGoSrcPath(filePath string) bool { return false } +// DirToGoPkg returns the Gopkg for the given directory if it exists +// under a GOPATH otherwise returns error. For example, +// /Users/x/go/src/github.com/y/z ==> github.com/y/z +func DirToGoPkg(dir string) (pkg string, err error) { + goPaths := getGoPaths() + for _, gopath := range goPaths { + goSrc := path.Join(gopath, "src") + if !strings.HasPrefix(dir, goSrc) { + continue + } + pkg, err := filepath.Rel(goSrc, dir) + if err == nil { + return pkg, err + } + } + + return "", fmt.Errorf("dir '%s' does not exist under any GOPATH %v", dir, goPaths) +} + func getGoPaths() []string { gopaths := os.Getenv("GOPATH") if len(gopaths) == 0 { gopaths = gobuild.Default.GOPATH } - return strings.Split(gopaths, ":") + return filepath.SplitList(gopaths) } // PathHasProjectFile validate if PROJECT file exists under the path. diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/apis.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/apis.go index 6fbc9eb7e1..c953b4b3b6 100644 --- a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/apis.go +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/apis.go @@ -78,7 +78,9 @@ func (b *APIs) parseAPIs() { apiVersion.Pkg = b.context.Universe[resource.Type.Name.Package] // Set the package for the api group apiGroup.Pkg = b.context.Universe[filepath.Dir(resource.Type.Name.Package)] - apiGroup.PkgPath = apiGroup.Pkg.Path + if apiGroup.Pkg != nil { + apiGroup.PkgPath = apiGroup.Pkg.Path + } apiGroup.UnversionedResources[kind] = apiResource } diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/controllers.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/controllers.go deleted file mode 100644 index f97a59d5aa..0000000000 --- a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/controllers.go +++ /dev/null @@ -1,85 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package parse - -import ( - "log" - "strings" - - "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/gengo/types" - "sigs.k8s.io/controller-tools/pkg/internal/codegen" -) - -// resourceTags contains the tags present in a "+resource=" comment -type controllerTags struct { - gvk schema.GroupVersionKind - resource string -} - -// parseControllers populates the list of controllers to generate code from the -// list of annotated types. -func (b *APIs) parseControllers() { - for _, c := range b.context.Order { - if IsController(c) { - tags := parseControllerTag(b.getControllerTag(c)) - repo := strings.Split(c.Name.Package, "/pkg/controller")[0] - pkg := b.context.Universe[c.Name.Package] - b.Controllers = append(b.Controllers, codegen.Controller{ - Target: tags.gvk, - Resource: tags.resource, - Pkg: pkg, - Repo: repo, - }) - } - } -} - -func (b *APIs) getControllerTag(c *types.Type) string { - comments := Comments(c.CommentLines) - resource := comments.getTag("controller", ":") + comments.getTag("kubebuilder:controller", ":") - if len(resource) == 0 { - panic(errors.Errorf("Must specify +kubebuilder:controller comment for type %v", c.Name)) - } - return resource -} - -// parseResourceTag parses the tags in a "+resource=" comment into a resourceTags struct -func parseControllerTag(tag string) controllerTags { - result := controllerTags{} - for _, elem := range strings.Split(tag, ",") { - kv := strings.Split(elem, "=") - if len(kv) != 2 { - log.Fatalf("// +kubebuilder:controller: tags must be key value pairs. Expected "+ - "keys [group=,version=,kind=,resource=] "+ - "Got string: [%s]", tag) - } - value := kv[1] - switch kv[0] { - case "group": - result.gvk.Group = value - case "version": - result.gvk.Version = value - case "kind": - result.gvk.Kind = value - case "resource": - result.resource = value - } - } - return result -} diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/crd.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/crd.go index 93399392c2..7da964d85a 100644 --- a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/crd.go +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/crd.go @@ -384,14 +384,12 @@ func getValidation(comment string, props *v1beta1.JSONSchemaProps) { if !strings.HasPrefix(comment, "+kubebuilder:validation:") { return } - log.Printf("Doing %s\n", comment) c := strings.Replace(comment, "+kubebuilder:validation:", "", -1) parts := strings.Split(c, "=") if len(parts) != 2 { log.Fatalf("Expected +kubebuilder:validation:= actual: %s", comment) return } - log.Printf("Switch %v\n", parts) switch parts[0] { case "Maximum": f, err := strconv.ParseFloat(parts[1], 64) diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/parser.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/parser.go index 4375ffe45d..c7a55dd3de 100644 --- a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/parser.go +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/parser.go @@ -18,15 +18,12 @@ package parse import ( "bufio" - "fmt" "go/build" "log" "os" "path/filepath" "strings" - "github.com/golang/glog" - "github.com/markbates/inflect" "github.com/pkg/errors" rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -60,19 +57,16 @@ type APIs struct { } // NewAPIs returns a new APIs instance with given context. -func NewAPIs(context *generator.Context, arguments *args.GeneratorArgs, domain string) *APIs { +func NewAPIs(context *generator.Context, arguments *args.GeneratorArgs, domain, apisPkg string) *APIs { b := &APIs{ context: context, arguments: arguments, Domain: domain, + APIsPkg: apisPkg, } b.parsePackages() b.parseGroupNames() b.parseIndex() - b.parseControllers() - b.parseRBAC() - b.parseInformers() - b.verifyRBACAnnotations() b.parseAPIs() b.parseCRDs() if len(b.Domain) == 0 { @@ -81,84 +75,6 @@ func NewAPIs(context *generator.Context, arguments *args.GeneratorArgs, domain s return b } -// verifyRBACAnnotations verifies that there are corresponding RBAC annotations for -// each informer annotation. -// e.g. if there is an // +kubebuilder:informer annotation for Pods, then there -// should also be a // +kubebuilder:rbac annotation for Pods -func (b *APIs) verifyRBACAnnotations() { - parseOption := b.arguments.CustomArgs.(*Options) - if parseOption.SkipRBACValidation { - log.Println("skipping RBAC validations") - return - } - err := rbacMatchesInformers(b.Informers, b.Rules) - if err != nil { - log.Fatal(err) - } -} - -func rbacMatchesInformers(informers map[v1.GroupVersionKind]bool, rbacRules []rbacv1.PolicyRule) error { - rs := inflect.NewDefaultRuleset() - - // For each informer, look for the RBAC annotation - for gvk := range informers { - found := false - - // Search all RBAC rules for one that matches the informer group and resource - for _, rule := range rbacRules { - - // Check if the group matches the informer group - groupFound := false - for _, g := range rule.APIGroups { - // RBAC has the full group with domain, whereas informers do not. Strip the domain - // from the group before comparing. - parts := strings.Split(g, ".") - group := parts[len(parts)-1] - - // If the RBAC group is wildcard or matches, it is a match - if g == "*" || group == gvk.Group { - groupFound = true - break - } - // Edge case where "core" and "" are equivalent - if (group == "core" || group == "") && (gvk.Group == "core" || gvk.Group == "") { - groupFound = true - break - } - } - if !groupFound { - continue - } - - // The resource name is the lower-plural of the Kind - resource := rs.Pluralize(strings.ToLower(gvk.Kind)) - // Check if the resource matches the informer resource - resourceFound := false - for _, k := range rule.Resources { - // If the RBAC resource is a wildcard or matches the informer resource, it is a match - if k == "*" || k == resource { - resourceFound = true - break - } - } - if !resourceFound { - continue - } - - // Found a matching RBAC rule - found = true - break - } - if !found { - return fmt.Errorf("Missing rbac rule for %s.%s. Add with // +kubebuilder:rbac:groups=%s,"+ - "resources=%s,verbs=get;list;watch comment on controller struct "+ - "or run the command with '--skip-rbac-validation' arg", gvk.Group, gvk.Kind, gvk.Group, - inflect.NewDefaultRuleset().Pluralize(strings.ToLower(gvk.Kind))) - } - } - return nil -} - // parseGroupNames initializes b.GroupNames with the set of all groups func (b *APIs) parseGroupNames() { b.GroupNames = sets.String{} @@ -183,15 +99,6 @@ func (b *APIs) parsePackages() { unversioned := filepath.Dir(versioned) b.UnversionedPkgs.Insert(unversioned) - - if apis := filepath.Dir(unversioned); apis != b.APIsPkg && len(b.APIsPkg) > 0 { - panic(errors.Errorf( - "Found multiple apis directory paths: %v and %v. "+ - "Do you have a +resource tag on a resource that is not in a version "+ - "directory?", b.APIsPkg, apis)) - } else { - b.APIsPkg = apis - } } } } @@ -222,7 +129,7 @@ func parseDomainFromFiles(paths []string) string { file, err := os.Open(filePath) if err != nil { - glog.Fatal(err) + log.Fatal(err) } defer file.Close() scanner := bufio.NewScanner(file) @@ -232,7 +139,7 @@ func parseDomainFromFiles(paths []string) string { } } if err := scanner.Err(); err != nil { - glog.Fatal(err) + log.Fatal(err) } comments := Comments(lines) diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/rbac.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/rbac.go deleted file mode 100644 index 7ce2664269..0000000000 --- a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/rbac.go +++ /dev/null @@ -1,134 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package parse - -import ( - "fmt" - "log" - "strings" - - rbacv1 "k8s.io/api/rbac/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/gengo/types" -) - -// parseRBAC populates the RBAC rules for each annotated type. -func (b *APIs) parseRBAC() { - for _, c := range b.context.Order { - if IsRBAC(c) { - for _, tag := range b.getRBACTag(c) { - b.Rules = append(b.Rules, parseRBACTag(tag)) - } - } - } -} - -func (b *APIs) getRBACTag(c *types.Type) []string { - comments := Comments(c.CommentLines) - resource := comments.getTags("rbac", ":") - resource = append(resource, comments.getTags("kubebuilder:rbac", ":")...) - if len(resource) == 0 { - panic(fmt.Errorf("Must specify +kubebuilder:rbac comment for type %v", c.Name)) - } - return resource -} - -func parseRBACTag(tag string) rbacv1.PolicyRule { - result := rbacv1.PolicyRule{} - for _, elem := range strings.Split(tag, ",") { - kv := strings.Split(elem, "=") - if len(kv) != 2 { - log.Fatalf("// +kubebuilder:rbac: tags must be key value pairs. Expected "+ - "keys [groups=,resources=,verbs=] "+ - "Got string: [%s]", tag) - } - value := kv[1] - values := []string{} - if strings.HasPrefix(value, "\"") && strings.HasSuffix(value, "\"") { - value = value[1 : len(value)-1] - } - values = strings.Split(value, ";") - switch kv[0] { - case "groups": - normalized := []string{} - for _, v := range values { - if v == "core" { - normalized = append(normalized, "") - } else { - normalized = append(normalized, v) - } - } - result.APIGroups = normalized - case "resources": - result.Resources = values - case "verbs": - result.Verbs = values - case "urls": - result.NonResourceURLs = values - } - } - return result -} - -// parseInfomers populates the informers to generate on each annotated type. -func (b *APIs) parseInformers() { - for _, c := range b.context.Order { - if IsInformer(c) { - for _, tag := range b.getInformerTag(c) { - if b.Informers == nil { - b.Informers = map[v1.GroupVersionKind]bool{} - } - b.Informers[parseInformerTag(tag)] = true - } - } - } -} - -func (b *APIs) getInformerTag(c *types.Type) []string { - comments := Comments(c.CommentLines) - resource := comments.getTags("informers", ":") - resource = append(resource, comments.getTags("kubebuilder:informers", ":")...) - if len(resource) == 0 { - panic(fmt.Errorf("Must specify +kubebuilder:informers comment for type %v", c.Name)) - } - return resource -} - -func parseInformerTag(tag string) v1.GroupVersionKind { - result := v1.GroupVersionKind{} - for _, elem := range strings.Split(tag, ",") { - kv := strings.Split(elem, "=") - if len(kv) != 2 { - log.Fatalf("// +kubebuilder:informers: tags must be key value pairs. Expected "+ - "keys [group=core,version=v1,kind=Pod] "+ - "Got string: [%s]", tag) - } - value := kv[1] - switch kv[0] { - case "group": - if value == "" { - value = "core" - } - result.Group = value - case "version": - result.Version = value - case "kind": - result.Kind = value - } - } - return result -} diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/scaffold/project/gopkg.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/scaffold/project/gopkg.go index 192e3459e3..62a6d5dec2 100644 --- a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/scaffold/project/gopkg.go +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/scaffold/project/gopkg.go @@ -143,213 +143,13 @@ name="{{ .Name }}" {{ if .Revision }}revision="{{.Revision}}"{{ end }} {{ end -}} -[[override]] -name="cloud.google.com/go" -version="v0.21.0" - -[[override]] -name="github.com/davecgh/go-spew" -version="v1.1.0" - -[[override]] -name="github.com/emicklei/go-restful" -version="v2.8.0" - -[[override]] -name="github.com/ghodss/yaml" -version="v1.0.0" - -[[override]] -name="github.com/go-logr/logr" -revision="9fb12b3b21c5415d16ac18dc5cd42c1cfdd40c4e" - -[[override]] -name="github.com/go-logr/zapr" -revision="7536572e8d55209135cd5e7ccf7fce43dca217ab" - -[[override]] -name="github.com/gobuffalo/envy" -version="v1.6.3" - -[[override]] -name="github.com/gogo/protobuf" -version="v1.1.1" - -[[override]] -name="github.com/golang/glog" -revision="23def4e6c14b4da8ac2ed8007337bc5eb5007998" - -[[override]] -name="github.com/golang/groupcache" -revision="66deaeb636dff1ac7d938ce666d090556056a4b0" - -[[override]] -name="github.com/golang/protobuf" -version="v1.1.0" - -[[override]] -name="github.com/google/gofuzz" -revision="24818f796faf91cd76ec7bddd72458fbced7a6c1" - -[[override]] -name="github.com/googleapis/gnostic" -version="v0.1.0" - -[[override]] -name="github.com/hashicorp/golang-lru" -revision="0fb14efe8c47ae851c0034ed7a448854d3d34cf3" - -[[override]] -name="github.com/howeyc/gopass" -revision="bf9dde6d0d2c004a008c27aaee91170c786f6db8" - -[[override]] -name="github.com/hpcloud/tail" -version="v1.0.0" - -[[override]] -name="github.com/imdario/mergo" -version="v0.3.5" - -[[override]] -name="github.com/inconshreveable/mousetrap" -version="v1.0" - -[[override]] -name="github.com/joho/godotenv" -version="v1.2.0" - -[[override]] -name="github.com/json-iterator/go" -version="1.1.4" - -[[override]] -name="github.com/markbates/inflect" -version="v1.0.0" - -[[override]] -name="github.com/modern-go/concurrent" -version="1.0.3" - -[[override]] -name="github.com/modern-go/reflect2" -version="1.0.1" - -[[override]] -name="github.com/onsi/ginkgo" -version="v1.6.0" - -[[override]] -name="github.com/onsi/gomega" -version="v1.4.1" - -[[override]] -name="github.com/pkg/errors" -version="v0.8.0" +[[constraint]] + name="sigs.k8s.io/controller-runtime" + version="v0.1.1" -[[override]] -name="github.com/spf13/cobra" -version="v0.0.3" - -[[override]] -name="github.com/spf13/pflag" -version="v1.0.1" - -[[override]] -name="go.uber.org/atomic" -version="v1.3.2" - -[[override]] -name="go.uber.org/multierr" -version="v1.1.0" - -[[override]] -name="go.uber.org/zap" -version="v1.8.0" - -[[override]] -name="golang.org/x/crypto" -revision="4ec37c66abab2c7e02ae775328b2ff001c3f025a" - -[[override]] -name="golang.org/x/net" -revision="640f4622ab692b87c2f3a94265e6f579fe38263d" - -[[override]] -name="golang.org/x/oauth2" -revision="cdc340f7c179dbbfa4afd43b7614e8fcadde4269" - -[[override]] -name="golang.org/x/sys" -revision="7db1c3b1a98089d0071c84f646ff5c96aad43682" - -[[override]] -name="golang.org/x/text" -version="v0.3.0" - -[[override]] -name="golang.org/x/time" -revision="fbb02b2291d28baffd63558aa44b4b56f178d650" - -[[override]] -name="golang.org/x/tools" -revision="32950ab3be12acf6d472893021373669979907ab" - -[[override]] -name="google.golang.org/appengine" -version="v1.1.0" - -[[override]] -name="gopkg.in/inf.v0" -version="v0.9.1" - -[[override]] -name="gopkg.in/tomb.v1" -revision = "dd632973f1e7218eb1089048e0798ec9ae7dceb8" - -[[override]] -name="gopkg.in/yaml.v2" -version="v2.2.1" - -[[override]] -name="k8s.io/api" -version="kubernetes-1.10.0" - -[[override]] -name="k8s.io/apiextensions-apiserver" -version="kubernetes-1.10.1" - -[[override]] -name="k8s.io/apimachinery" -version="kubernetes-1.10.0" - -[[override]] -name="k8s.io/client-go" -version="kubernetes-1.10.1" - -[[override]] -name="k8s.io/code-generator" -revision="7b3961072db196a1068e97f76c74ca6bc6b65350" - -[[override]] -name="k8s.io/gengo" -revision="906d99f89cd644eecf75ab547b29bf9f876f0b59" - -[[override]] -name="k8s.io/kube-openapi" -revision="f08db293d3ef80052d6513ece19792642a289fea" - -[[override]] -name="sigs.k8s.io/controller-runtime" -branch="master" - -[[override]] -name="sigs.k8s.io/controller-tools" -branch="master" - -[[override]] -name="sigs.k8s.io/testing_frameworks" -revision="f53464b8b84b4507805a0b033a8377b225163fea" +[[constraint]] + name="sigs.k8s.io/controller-tools" + version="v0.1.1" # For dependency below: Refer to issue https://github.com/golang/dep/issues/1799 [[override]] diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/scaffold/project/makefile.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/scaffold/project/makefile.go index 83bf0ff7ae..abb5a35518 100644 --- a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/scaffold/project/makefile.go +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/scaffold/project/makefile.go @@ -95,7 +95,7 @@ generate: docker-build: test docker build . -t ${IMG} @echo "updating kustomize image patch file for manager resource" - sed -i 's@image: .*@image: '"${IMG}"'@' ./config/default/manager_image_patch.yaml + sed -i'' -e 's@image: .*@image: '"${IMG}"'@' ./config/default/manager_image_patch.yaml # Push the docker image docker-push: diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/scaffold/scaffold.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/scaffold/scaffold.go index 9a5e4992b1..08850a5b69 100644 --- a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/scaffold/scaffold.go +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/scaffold/scaffold.go @@ -133,7 +133,7 @@ func (s *Scaffold) defaultOptions(options *input.Options) error { // Execute executes scaffolding the Files func (s *Scaffold) Execute(options input.Options, files ...input.File) error { if s.GetWriter == nil { - s.GetWriter = util.NewWriteCloser + s.GetWriter = (&util.FileWriter{}).WriteCloser } if err := s.defaultOptions(&options); err != nil { diff --git a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/util/util.go b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/util/util.go index 76865f9972..9649913b38 100644 --- a/cmd/vendor/sigs.k8s.io/controller-tools/pkg/util/util.go +++ b/cmd/vendor/sigs.k8s.io/controller-tools/pkg/util/util.go @@ -22,17 +22,27 @@ import ( "log" "os" "path/filepath" + + "github.com/spf13/afero" ) -// NewWriteCloser returns a WriteCloser to write to given path -func NewWriteCloser(path string) (io.Writer, error) { +// FileWriter is a io wrapper to write files +type FileWriter struct { + Fs afero.Fs +} + +// WriteCloser returns a WriteCloser to write to given path +func (fw *FileWriter) WriteCloser(path string) (io.Writer, error) { + if fw.Fs == nil { + fw.Fs = afero.NewOsFs() + } dir := filepath.Dir(path) - err := os.MkdirAll(dir, 0700) + err := fw.Fs.MkdirAll(dir, 0700) if err != nil { return nil, err } - fi, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + fi, err := fw.Fs.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return nil, err } @@ -41,8 +51,11 @@ func NewWriteCloser(path string) (io.Writer, error) { } // WriteFile write given content to the file path -func WriteFile(filePath, content string) error { - f, err := NewWriteCloser(filePath) +func (fw *FileWriter) WriteFile(filePath string, content []byte) error { + if fw.Fs == nil { + fw.Fs = afero.NewOsFs() + } + f, err := fw.WriteCloser(filePath) if err != nil { return fmt.Errorf("failed to create %s: %v", filePath, err) } @@ -55,7 +68,7 @@ func WriteFile(filePath, content string) error { }() } - _, err = f.Write([]byte(content)) + _, err = f.Write(content) if err != nil { return fmt.Errorf("failed to write %s: %v", filePath, err) }