Bump github.com/hashicorp/terraform-plugin-docs from 0.7.0 to 0.13.0
Bumps [github.com/hashicorp/terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs) from 0.7.0 to 0.13.0. - [Release notes](https://github.com/hashicorp/terraform-plugin-docs/releases) - [Changelog](https://github.com/hashicorp/terraform-plugin-docs/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/terraform-plugin-docs/compare/v0.7.0...v0.13.0) --- updated-dependencies: - dependency-name: github.com/hashicorp/terraform-plugin-docs dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
parent
ad07770b6b
commit
b4859cda6b
26
go.mod
26
go.mod
@ -4,24 +4,24 @@ go 1.18
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
code.gitea.io/sdk/gitea v0.15.1
|
code.gitea.io/sdk/gitea v0.15.1
|
||||||
github.com/hashicorp/terraform-plugin-docs v0.7.0
|
github.com/hashicorp/terraform-plugin-docs v0.13.0
|
||||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0
|
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Masterminds/goutils v1.1.0 // indirect
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
github.com/Masterminds/semver v1.5.0 // indirect
|
github.com/Masterminds/semver/v3 v3.1.1 // indirect
|
||||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
|
||||||
github.com/agext/levenshtein v1.2.2 // indirect
|
github.com/agext/levenshtein v1.2.2 // indirect
|
||||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect
|
github.com/armon/go-radix v1.0.0 // indirect
|
||||||
github.com/bgentry/speakeasy v0.1.0 // indirect
|
github.com/bgentry/speakeasy v0.1.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/fatih/color v1.13.0 // indirect
|
github.com/fatih/color v1.13.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/google/go-cmp v0.5.8 // indirect
|
github.com/google/go-cmp v0.5.8 // indirect
|
||||||
github.com/google/uuid v1.1.2 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
|
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
|
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
|
||||||
@ -41,25 +41,27 @@ require (
|
|||||||
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect
|
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect
|
||||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect
|
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect
|
||||||
github.com/huandu/xstrings v1.3.2 // indirect
|
github.com/huandu/xstrings v1.3.2 // indirect
|
||||||
github.com/imdario/mergo v0.3.12 // indirect
|
github.com/imdario/mergo v0.3.13 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
github.com/mitchellh/cli v1.1.2 // indirect
|
github.com/mitchellh/cli v1.1.4 // indirect
|
||||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||||
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
|
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||||
github.com/oklog/run v1.0.0 // indirect
|
github.com/oklog/run v1.0.0 // indirect
|
||||||
github.com/posener/complete v1.1.1 // indirect
|
github.com/posener/complete v1.2.3 // indirect
|
||||||
github.com/russross/blackfriday v1.6.0 // indirect
|
github.com/russross/blackfriday v1.6.0 // indirect
|
||||||
|
github.com/shopspring/decimal v1.3.1 // indirect
|
||||||
|
github.com/spf13/cast v1.5.0 // indirect
|
||||||
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
|
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
|
||||||
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
|
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
|
||||||
github.com/vmihailenco/tagparser v0.1.1 // indirect
|
github.com/vmihailenco/tagparser v0.1.1 // indirect
|
||||||
github.com/zclconf/go-cty v1.10.0 // indirect
|
github.com/zclconf/go-cty v1.10.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 // indirect
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect
|
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
google.golang.org/appengine v1.6.6 // indirect
|
google.golang.org/appengine v1.6.6 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20200711021454-869866162049 // indirect
|
google.golang.org/genproto v0.0.0-20200711021454-869866162049 // indirect
|
||||||
|
57
go.sum
57
go.sum
@ -4,12 +4,14 @@ code.gitea.io/gitea-vet v0.2.1/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFj
|
|||||||
code.gitea.io/sdk/gitea v0.15.1 h1:WJreC7YYuxbn0UDaPuWIe/mtiNKTvLN8MLkaw71yx/M=
|
code.gitea.io/sdk/gitea v0.15.1 h1:WJreC7YYuxbn0UDaPuWIe/mtiNKTvLN8MLkaw71yx/M=
|
||||||
code.gitea.io/sdk/gitea v0.15.1/go.mod h1:klY2LVI3s3NChzIk/MzMn7G1FHrfU7qd63iSMVoHRBA=
|
code.gitea.io/sdk/gitea v0.15.1/go.mod h1:klY2LVI3s3NChzIk/MzMn7G1FHrfU7qd63iSMVoHRBA=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
|
|
||||||
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||||
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
|
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
||||||
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
|
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||||
|
github.com/Masterminds/sprig/v3 v3.2.0/go.mod h1:tWhwTbUTndesPNeF0C900vKoq283u6zp4APT9vaF3SI=
|
||||||
|
github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
|
||||||
|
github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
|
||||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||||
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
|
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
|
||||||
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||||
@ -26,8 +28,9 @@ github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/
|
|||||||
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
|
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
|
||||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
|
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
|
||||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=
|
|
||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
|
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
|
||||||
|
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
@ -56,6 +59,7 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
|
|||||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||||
|
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||||
@ -95,11 +99,14 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
|
||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||||
|
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=
|
github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=
|
||||||
github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
|
github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||||
@ -133,8 +140,8 @@ github.com/hashicorp/terraform-exec v0.17.2 h1:EU7i3Fh7vDUI9nNRdMATCEfnm9axzTnad
|
|||||||
github.com/hashicorp/terraform-exec v0.17.2/go.mod h1:tuIbsL2l4MlwwIZx9HPM+LOV9vVyEfBYu2GsO1uH3/8=
|
github.com/hashicorp/terraform-exec v0.17.2/go.mod h1:tuIbsL2l4MlwwIZx9HPM+LOV9vVyEfBYu2GsO1uH3/8=
|
||||||
github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s=
|
github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s=
|
||||||
github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM=
|
github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM=
|
||||||
github.com/hashicorp/terraform-plugin-docs v0.7.0 h1:7XKAOYHAxghe7q4/vx468X43X9GikdQ2dxtmcu2gQv0=
|
github.com/hashicorp/terraform-plugin-docs v0.13.0 h1:6e+VIWsVGb6jYJewfzq2ok2smPzZrt1Wlm9koLeKazY=
|
||||||
github.com/hashicorp/terraform-plugin-docs v0.7.0/go.mod h1:57CICKfW7/KbW4lPhKOledyT6vu1LeAOzuvWXsVaxUE=
|
github.com/hashicorp/terraform-plugin-docs v0.13.0/go.mod h1:W0oCmHAjIlTHBbvtppWHe8fLfZ2BznQbuv8+UD8OucQ=
|
||||||
github.com/hashicorp/terraform-plugin-go v0.12.0 h1:6wW9mT1dSs0Xq4LR6HXj1heQ5ovr5GxXNJwkErZzpJw=
|
github.com/hashicorp/terraform-plugin-go v0.12.0 h1:6wW9mT1dSs0Xq4LR6HXj1heQ5ovr5GxXNJwkErZzpJw=
|
||||||
github.com/hashicorp/terraform-plugin-go v0.12.0/go.mod h1:kwhmaWHNDvT1B3QiSJdAtrB/D4RaKSY/v3r2BuoWK4M=
|
github.com/hashicorp/terraform-plugin-go v0.12.0/go.mod h1:kwhmaWHNDvT1B3QiSJdAtrB/D4RaKSY/v3r2BuoWK4M=
|
||||||
github.com/hashicorp/terraform-plugin-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs=
|
github.com/hashicorp/terraform-plugin-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs=
|
||||||
@ -147,11 +154,13 @@ github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKL
|
|||||||
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg=
|
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg=
|
||||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
|
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
|
||||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||||
|
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||||
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
|
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
|
||||||
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
|
||||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
|
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
|
||||||
|
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||||
@ -160,8 +169,8 @@ github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgy
|
|||||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@ -177,8 +186,8 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
|
|||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw=
|
github.com/mitchellh/cli v1.1.4 h1:qj8czE26AU4PbiaPXK5uVmMSM+V5BYsFBiM9HhGRLUA=
|
||||||
github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
|
github.com/mitchellh/cli v1.1.4/go.mod h1:vTLESy5mRhKOs9KDp0/RATawxP1UqBmdrpVRMnpcvKQ=
|
||||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||||
@ -201,16 +210,24 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
|||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
|
|
||||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||||
|
github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
|
||||||
|
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
|
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||||
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
|
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
|
||||||
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
|
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
|
||||||
github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
|
github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
|
||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||||
|
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||||
|
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||||
|
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
|
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
|
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||||
|
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
@ -240,13 +257,14 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe
|
|||||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 h1:O8uGbHCqlTp2P6QJSLmCojM4mN6UemYv8K+dCnmHmu0=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
||||||
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
@ -298,8 +316,9 @@ golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
|
|
||||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8=
|
||||||
|
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
@ -363,9 +382,9 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN
|
|||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
25
vendor/github.com/Masterminds/goutils/cryptorandomstringutils.go
generated
vendored
25
vendor/github.com/Masterminds/goutils/cryptorandomstringutils.go
generated
vendored
@ -21,7 +21,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"regexp"
|
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -99,27 +98,7 @@ Returns:
|
|||||||
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
*/
|
*/
|
||||||
func CryptoRandomAlphaNumeric(count int) (string, error) {
|
func CryptoRandomAlphaNumeric(count int) (string, error) {
|
||||||
if count == 0 {
|
return CryptoRandom(count, 0, 0, true, true)
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
RandomString, err := CryptoRandom(count, 0, 0, true, true)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("Error: %s", err)
|
|
||||||
}
|
|
||||||
match, err := regexp.MatchString("([0-9]+)", RandomString)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !match {
|
|
||||||
//Get the position between 0 and the length of the string-1 to insert a random number
|
|
||||||
position := getCryptoRandomInt(count)
|
|
||||||
//Insert a random number between [0-9] in the position
|
|
||||||
RandomString = RandomString[:position] + string('0' + getCryptoRandomInt(10)) + RandomString[position + 1:]
|
|
||||||
return RandomString, err
|
|
||||||
}
|
|
||||||
return RandomString, err
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -204,7 +183,7 @@ func CryptoRandom(count int, start int, end int, letters bool, numbers bool, cha
|
|||||||
if chars == nil {
|
if chars == nil {
|
||||||
ch = rune(getCryptoRandomInt(gap) + int64(start))
|
ch = rune(getCryptoRandomInt(gap) + int64(start))
|
||||||
} else {
|
} else {
|
||||||
ch = chars[getCryptoRandomInt(gap) + int64(start)]
|
ch = chars[getCryptoRandomInt(gap)+int64(start)]
|
||||||
}
|
}
|
||||||
|
|
||||||
if letters && unicode.IsLetter(ch) || numbers && unicode.IsDigit(ch) || !letters && !numbers {
|
if letters && unicode.IsLetter(ch) || numbers && unicode.IsDigit(ch) || !letters && !numbers {
|
||||||
|
24
vendor/github.com/Masterminds/goutils/randomstringutils.go
generated
vendored
24
vendor/github.com/Masterminds/goutils/randomstringutils.go
generated
vendored
@ -20,7 +20,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"regexp"
|
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
@ -75,12 +74,10 @@ func RandomNumeric(count int) (string, error) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
RandomAlphabetic creates a random string whose length is the number of characters specified.
|
RandomAlphabetic creates a random string whose length is the number of characters specified.
|
||||||
Characters will be chosen from the set of alpha-numeric characters as indicated by the arguments.
|
Characters will be chosen from the set of alphabetic characters.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
count - the length of random string to create
|
count - the length of random string to create
|
||||||
letters - if true, generated string may include alphabetic characters
|
|
||||||
numbers - if true, generated string may include numeric characters
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
string - the random string
|
string - the random string
|
||||||
@ -102,24 +99,7 @@ Returns:
|
|||||||
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
|
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
|
||||||
*/
|
*/
|
||||||
func RandomAlphaNumeric(count int) (string, error) {
|
func RandomAlphaNumeric(count int) (string, error) {
|
||||||
RandomString, err := Random(count, 0, 0, true, true)
|
return Random(count, 0, 0, true, true)
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("Error: %s", err)
|
|
||||||
}
|
|
||||||
match, err := regexp.MatchString("([0-9]+)", RandomString)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !match {
|
|
||||||
//Get the position between 0 and the length of the string-1 to insert a random number
|
|
||||||
position := rand.Intn(count)
|
|
||||||
//Insert a random number between [0-9] in the position
|
|
||||||
RandomString = RandomString[:position] + string('0'+rand.Intn(10)) + RandomString[position+1:]
|
|
||||||
return RandomString, err
|
|
||||||
}
|
|
||||||
return RandomString, err
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
16
vendor/github.com/Masterminds/goutils/stringutils.go
generated
vendored
16
vendor/github.com/Masterminds/goutils/stringutils.go
generated
vendored
@ -222,3 +222,19 @@ func IndexOf(str string, sub string, start int) int {
|
|||||||
func IsEmpty(str string) bool {
|
func IsEmpty(str string) bool {
|
||||||
return len(str) == 0
|
return len(str) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns either the passed in string, or if the string is empty, the value of defaultStr.
|
||||||
|
func DefaultString(str string, defaultStr string) string {
|
||||||
|
if IsEmpty(str) {
|
||||||
|
return defaultStr
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns either the passed in string, or if the string is whitespace, empty (""), the value of defaultStr.
|
||||||
|
func DefaultIfBlank(str string, defaultStr string) string {
|
||||||
|
if IsBlank(str) {
|
||||||
|
return defaultStr
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
29
vendor/github.com/Masterminds/semver/.travis.yml
generated
vendored
29
vendor/github.com/Masterminds/semver/.travis.yml
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.6.x
|
|
||||||
- 1.7.x
|
|
||||||
- 1.8.x
|
|
||||||
- 1.9.x
|
|
||||||
- 1.10.x
|
|
||||||
- 1.11.x
|
|
||||||
- 1.12.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
|
|
109
vendor/github.com/Masterminds/semver/CHANGELOG.md
generated
vendored
109
vendor/github.com/Masterminds/semver/CHANGELOG.md
generated
vendored
@ -1,109 +0,0 @@
|
|||||||
# 1.5.0 (2019-09-11)
|
|
||||||
|
|
||||||
## Added
|
|
||||||
|
|
||||||
- #103: Add basic fuzzing for `NewVersion()` (thanks @jesse-c)
|
|
||||||
|
|
||||||
## Changed
|
|
||||||
|
|
||||||
- #82: Clarify wildcard meaning in range constraints and update tests for it (thanks @greysteil)
|
|
||||||
- #83: Clarify caret operator range for pre-1.0.0 dependencies (thanks @greysteil)
|
|
||||||
- #72: Adding docs comment pointing to vert for a cli
|
|
||||||
- #71: Update the docs on pre-release comparator handling
|
|
||||||
- #89: Test with new go versions (thanks @thedevsaddam)
|
|
||||||
- #87: Added $ to ValidPrerelease for better validation (thanks @jeremycarroll)
|
|
||||||
|
|
||||||
## Fixed
|
|
||||||
|
|
||||||
- #78: Fix unchecked error in example code (thanks @ravron)
|
|
||||||
- #70: Fix the handling of pre-releases and the 0.0.0 release edge case
|
|
||||||
- #97: Fixed copyright file for proper display on GitHub
|
|
||||||
- #107: Fix handling prerelease when sorting alphanum and num
|
|
||||||
- #109: Fixed where Validate sometimes returns wrong message on error
|
|
||||||
|
|
||||||
# 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
|
|
36
vendor/github.com/Masterminds/semver/Makefile
generated
vendored
36
vendor/github.com/Masterminds/semver/Makefile
generated
vendored
@ -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 \
|
|
||||||
./... || :
|
|
194
vendor/github.com/Masterminds/semver/README.md
generated
vendored
194
vendor/github.com/Masterminds/semver/README.md
generated
vendored
@ -1,194 +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)
|
|
||||||
|
|
||||||
If you are looking for a command line tool for version comparisons please see
|
|
||||||
[vert](https://github.com/Masterminds/vert) which uses this library.
|
|
||||||
|
|
||||||
## 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
|
|
||||||
|
|
||||||
## Working With Pre-release Versions
|
|
||||||
|
|
||||||
Pre-releases, for those not familiar with them, are used for software releases
|
|
||||||
prior to stable or generally available releases. Examples of pre-releases include
|
|
||||||
development, alpha, beta, and release candidate releases. A pre-release may be
|
|
||||||
a version such as `1.2.3-beta.1` while the stable release would be `1.2.3`. In the
|
|
||||||
order of precidence, pre-releases come before their associated releases. In this
|
|
||||||
example `1.2.3-beta.1 < 1.2.3`.
|
|
||||||
|
|
||||||
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 comparator will skip pre-release versions.
|
|
||||||
For example, `>=1.2.3` will skip pre-releases when looking at a list of releases
|
|
||||||
while `>=1.2.3-0` will evaluate and find pre-releases.
|
|
||||||
|
|
||||||
The reason for the `0` as a pre-release version in the example comparison is
|
|
||||||
because pre-releases can only contain ASCII alphanumerics and hyphens (along with
|
|
||||||
`.` separators), per the spec. Sorting happens in ASCII sort order, again per the spec. The lowest character is a `0` in ASCII sort order (see an [ASCII Table](http://www.asciitable.com/))
|
|
||||||
|
|
||||||
Understanding ASCII sort ordering is important because A-Z comes before a-z. That
|
|
||||||
means `>=1.2.3-BETA` will return `1.2.3-alpha`. What you might expect from case
|
|
||||||
sensitivity doesn't apply here. This is due to ASCII sort ordering which is what
|
|
||||||
the spec specifies.
|
|
||||||
|
|
||||||
## 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`
|
|
||||||
* `^0.0.1` is equivalent to `>= 0.0.1, < 1.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"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
# Fuzzing
|
|
||||||
|
|
||||||
[dvyukov/go-fuzz](https://github.com/dvyukov/go-fuzz) is used for fuzzing.
|
|
||||||
|
|
||||||
1. `go-fuzz-build`
|
|
||||||
2. `go-fuzz -workdir=fuzz`
|
|
||||||
|
|
||||||
# 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).
|
|
44
vendor/github.com/Masterminds/semver/appveyor.yml
generated
vendored
44
vendor/github.com/Masterminds/semver/appveyor.yml
generated
vendored
@ -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
|
|
423
vendor/github.com/Masterminds/semver/constraints.go
generated
vendored
423
vendor/github.com/Masterminds/semver/constraints.go
generated
vendored
@ -1,423 +0,0 @@
|
|||||||
package semver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Constraints is one or more constraint that a semantic version can be
|
|
||||||
// checked against.
|
|
||||||
type Constraints struct {
|
|
||||||
constraints [][]*constraint
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewConstraint returns a Constraints instance that a Version instance can
|
|
||||||
// be checked against. If there is a parse error it will be returned.
|
|
||||||
func NewConstraint(c string) (*Constraints, error) {
|
|
||||||
|
|
||||||
// Rewrite - ranges into a comparison operation.
|
|
||||||
c = rewriteRange(c)
|
|
||||||
|
|
||||||
ors := strings.Split(c, "||")
|
|
||||||
or := make([][]*constraint, len(ors))
|
|
||||||
for k, v := range ors {
|
|
||||||
cs := strings.Split(v, ",")
|
|
||||||
result := make([]*constraint, len(cs))
|
|
||||||
for i, s := range cs {
|
|
||||||
pc, err := parseConstraint(s)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result[i] = pc
|
|
||||||
}
|
|
||||||
or[k] = result
|
|
||||||
}
|
|
||||||
|
|
||||||
o := &Constraints{constraints: or}
|
|
||||||
return o, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check tests if a version satisfies the constraints.
|
|
||||||
func (cs Constraints) Check(v *Version) bool {
|
|
||||||
// loop over the ORs and check the inner ANDs
|
|
||||||
for _, o := range cs.constraints {
|
|
||||||
joy := true
|
|
||||||
for _, c := range o {
|
|
||||||
if !c.check(v) {
|
|
||||||
joy = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if joy {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate checks if a version satisfies a constraint. If not a slice of
|
|
||||||
// reasons for the failure are returned in addition to a bool.
|
|
||||||
func (cs Constraints) Validate(v *Version) (bool, []error) {
|
|
||||||
// loop over the ORs and check the inner ANDs
|
|
||||||
var e []error
|
|
||||||
|
|
||||||
// Capture the prerelease message only once. When it happens the first time
|
|
||||||
// this var is marked
|
|
||||||
var prerelesase bool
|
|
||||||
for _, o := range cs.constraints {
|
|
||||||
joy := true
|
|
||||||
for _, c := range o {
|
|
||||||
// Before running the check handle the case there the version is
|
|
||||||
// a prerelease and the check is not searching for prereleases.
|
|
||||||
if c.con.pre == "" && v.pre != "" {
|
|
||||||
if !prerelesase {
|
|
||||||
em := fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
|
|
||||||
e = append(e, em)
|
|
||||||
prerelesase = true
|
|
||||||
}
|
|
||||||
joy = false
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if !c.check(v) {
|
|
||||||
em := fmt.Errorf(c.msg, v, c.orig)
|
|
||||||
e = append(e, em)
|
|
||||||
joy = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if joy {
|
|
||||||
return true, []error{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, e
|
|
||||||
}
|
|
||||||
|
|
||||||
var constraintOps map[string]cfunc
|
|
||||||
var constraintMsg map[string]string
|
|
||||||
var constraintRegex *regexp.Regexp
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
constraintOps = map[string]cfunc{
|
|
||||||
"": constraintTildeOrEqual,
|
|
||||||
"=": constraintTildeOrEqual,
|
|
||||||
"!=": constraintNotEqual,
|
|
||||||
">": constraintGreaterThan,
|
|
||||||
"<": constraintLessThan,
|
|
||||||
">=": constraintGreaterThanEqual,
|
|
||||||
"=>": constraintGreaterThanEqual,
|
|
||||||
"<=": constraintLessThanEqual,
|
|
||||||
"=<": constraintLessThanEqual,
|
|
||||||
"~": constraintTilde,
|
|
||||||
"~>": constraintTilde,
|
|
||||||
"^": constraintCaret,
|
|
||||||
}
|
|
||||||
|
|
||||||
constraintMsg = map[string]string{
|
|
||||||
"": "%s is not equal to %s",
|
|
||||||
"=": "%s is not equal to %s",
|
|
||||||
"!=": "%s is equal to %s",
|
|
||||||
">": "%s is less than or equal to %s",
|
|
||||||
"<": "%s is greater than or equal to %s",
|
|
||||||
">=": "%s is less than %s",
|
|
||||||
"=>": "%s is less than %s",
|
|
||||||
"<=": "%s is greater than %s",
|
|
||||||
"=<": "%s is greater than %s",
|
|
||||||
"~": "%s does not have same major and minor version as %s",
|
|
||||||
"~>": "%s does not have same major and minor version as %s",
|
|
||||||
"^": "%s does not have same major version as %s",
|
|
||||||
}
|
|
||||||
|
|
||||||
ops := make([]string, 0, len(constraintOps))
|
|
||||||
for k := range constraintOps {
|
|
||||||
ops = append(ops, regexp.QuoteMeta(k))
|
|
||||||
}
|
|
||||||
|
|
||||||
constraintRegex = regexp.MustCompile(fmt.Sprintf(
|
|
||||||
`^\s*(%s)\s*(%s)\s*$`,
|
|
||||||
strings.Join(ops, "|"),
|
|
||||||
cvRegex))
|
|
||||||
|
|
||||||
constraintRangeRegex = regexp.MustCompile(fmt.Sprintf(
|
|
||||||
`\s*(%s)\s+-\s+(%s)\s*`,
|
|
||||||
cvRegex, cvRegex))
|
|
||||||
}
|
|
||||||
|
|
||||||
// An individual constraint
|
|
||||||
type constraint struct {
|
|
||||||
// The callback function for the restraint. It performs the logic for
|
|
||||||
// the constraint.
|
|
||||||
function cfunc
|
|
||||||
|
|
||||||
msg string
|
|
||||||
|
|
||||||
// The version used in the constraint check. For example, if a constraint
|
|
||||||
// is '<= 2.0.0' the con a version instance representing 2.0.0.
|
|
||||||
con *Version
|
|
||||||
|
|
||||||
// The original parsed version (e.g., 4.x from != 4.x)
|
|
||||||
orig string
|
|
||||||
|
|
||||||
// When an x is used as part of the version (e.g., 1.x)
|
|
||||||
minorDirty bool
|
|
||||||
dirty bool
|
|
||||||
patchDirty bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if a version meets the constraint
|
|
||||||
func (c *constraint) check(v *Version) bool {
|
|
||||||
return c.function(v, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
type cfunc func(v *Version, c *constraint) bool
|
|
||||||
|
|
||||||
func parseConstraint(c string) (*constraint, error) {
|
|
||||||
m := constraintRegex.FindStringSubmatch(c)
|
|
||||||
if m == nil {
|
|
||||||
return nil, fmt.Errorf("improper constraint: %s", c)
|
|
||||||
}
|
|
||||||
|
|
||||||
ver := m[2]
|
|
||||||
orig := ver
|
|
||||||
minorDirty := false
|
|
||||||
patchDirty := false
|
|
||||||
dirty := false
|
|
||||||
if isX(m[3]) {
|
|
||||||
ver = "0.0.0"
|
|
||||||
dirty = true
|
|
||||||
} else if isX(strings.TrimPrefix(m[4], ".")) || m[4] == "" {
|
|
||||||
minorDirty = true
|
|
||||||
dirty = true
|
|
||||||
ver = fmt.Sprintf("%s.0.0%s", m[3], m[6])
|
|
||||||
} else if isX(strings.TrimPrefix(m[5], ".")) {
|
|
||||||
dirty = true
|
|
||||||
patchDirty = true
|
|
||||||
ver = fmt.Sprintf("%s%s.0%s", m[3], m[4], m[6])
|
|
||||||
}
|
|
||||||
|
|
||||||
con, err := NewVersion(ver)
|
|
||||||
if err != nil {
|
|
||||||
|
|
||||||
// The constraintRegex should catch any regex parsing errors. So,
|
|
||||||
// we should never get here.
|
|
||||||
return nil, errors.New("constraint Parser Error")
|
|
||||||
}
|
|
||||||
|
|
||||||
cs := &constraint{
|
|
||||||
function: constraintOps[m[1]],
|
|
||||||
msg: constraintMsg[m[1]],
|
|
||||||
con: con,
|
|
||||||
orig: orig,
|
|
||||||
minorDirty: minorDirty,
|
|
||||||
patchDirty: patchDirty,
|
|
||||||
dirty: dirty,
|
|
||||||
}
|
|
||||||
return cs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constraint functions
|
|
||||||
func constraintNotEqual(v *Version, c *constraint) bool {
|
|
||||||
if c.dirty {
|
|
||||||
|
|
||||||
// If there is a pre-release on the version but the constraint isn't looking
|
|
||||||
// for them assume that pre-releases are not compatible. See issue 21 for
|
|
||||||
// more details.
|
|
||||||
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.con.Major() != v.Major() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if c.con.Minor() != v.Minor() && !c.minorDirty {
|
|
||||||
return true
|
|
||||||
} else if c.minorDirty {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return !v.Equal(c.con)
|
|
||||||
}
|
|
||||||
|
|
||||||
func constraintGreaterThan(v *Version, c *constraint) bool {
|
|
||||||
|
|
||||||
// If there is a pre-release on the version but the constraint isn't looking
|
|
||||||
// for them assume that pre-releases are not compatible. See issue 21 for
|
|
||||||
// more details.
|
|
||||||
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return v.Compare(c.con) == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func constraintLessThan(v *Version, c *constraint) bool {
|
|
||||||
// If there is a pre-release on the version but the constraint isn't looking
|
|
||||||
// for them assume that pre-releases are not compatible. See issue 21 for
|
|
||||||
// more details.
|
|
||||||
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.dirty {
|
|
||||||
return v.Compare(c.con) < 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Major() > c.con.Major() {
|
|
||||||
return false
|
|
||||||
} else if v.Minor() > c.con.Minor() && !c.minorDirty {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func constraintGreaterThanEqual(v *Version, c *constraint) bool {
|
|
||||||
|
|
||||||
// If there is a pre-release on the version but the constraint isn't looking
|
|
||||||
// for them assume that pre-releases are not compatible. See issue 21 for
|
|
||||||
// more details.
|
|
||||||
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return v.Compare(c.con) >= 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func constraintLessThanEqual(v *Version, c *constraint) bool {
|
|
||||||
// If there is a pre-release on the version but the constraint isn't looking
|
|
||||||
// for them assume that pre-releases are not compatible. See issue 21 for
|
|
||||||
// more details.
|
|
||||||
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.dirty {
|
|
||||||
return v.Compare(c.con) <= 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Major() > c.con.Major() {
|
|
||||||
return false
|
|
||||||
} else if v.Minor() > c.con.Minor() && !c.minorDirty {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// ~*, ~>* --> >= 0.0.0 (any)
|
|
||||||
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0, <3.0.0
|
|
||||||
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0, <2.1.0
|
|
||||||
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0, <1.3.0
|
|
||||||
// ~1.2.3, ~>1.2.3 --> >=1.2.3, <1.3.0
|
|
||||||
// ~1.2.0, ~>1.2.0 --> >=1.2.0, <1.3.0
|
|
||||||
func constraintTilde(v *Version, c *constraint) bool {
|
|
||||||
// If there is a pre-release on the version but the constraint isn't looking
|
|
||||||
// for them assume that pre-releases are not compatible. See issue 21 for
|
|
||||||
// more details.
|
|
||||||
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.LessThan(c.con) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// ~0.0.0 is a special case where all constraints are accepted. It's
|
|
||||||
// equivalent to >= 0.0.0.
|
|
||||||
if c.con.Major() == 0 && c.con.Minor() == 0 && c.con.Patch() == 0 &&
|
|
||||||
!c.minorDirty && !c.patchDirty {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Major() != c.con.Major() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Minor() != c.con.Minor() && !c.minorDirty {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// When there is a .x (dirty) status it automatically opts in to ~. Otherwise
|
|
||||||
// it's a straight =
|
|
||||||
func constraintTildeOrEqual(v *Version, c *constraint) bool {
|
|
||||||
// If there is a pre-release on the version but the constraint isn't looking
|
|
||||||
// for them assume that pre-releases are not compatible. See issue 21 for
|
|
||||||
// more details.
|
|
||||||
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.dirty {
|
|
||||||
c.msg = constraintMsg["~"]
|
|
||||||
return constraintTilde(v, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
return v.Equal(c.con)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ^* --> (any)
|
|
||||||
// ^2, ^2.x, ^2.x.x --> >=2.0.0, <3.0.0
|
|
||||||
// ^2.0, ^2.0.x --> >=2.0.0, <3.0.0
|
|
||||||
// ^1.2, ^1.2.x --> >=1.2.0, <2.0.0
|
|
||||||
// ^1.2.3 --> >=1.2.3, <2.0.0
|
|
||||||
// ^1.2.0 --> >=1.2.0, <2.0.0
|
|
||||||
func constraintCaret(v *Version, c *constraint) bool {
|
|
||||||
// If there is a pre-release on the version but the constraint isn't looking
|
|
||||||
// for them assume that pre-releases are not compatible. See issue 21 for
|
|
||||||
// more details.
|
|
||||||
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.LessThan(c.con) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Major() != c.con.Major() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var constraintRangeRegex *regexp.Regexp
|
|
||||||
|
|
||||||
const cvRegex string = `v?([0-9|x|X|\*]+)(\.[0-9|x|X|\*]+)?(\.[0-9|x|X|\*]+)?` +
|
|
||||||
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
|
|
||||||
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
|
|
||||||
|
|
||||||
func isX(x string) bool {
|
|
||||||
switch x {
|
|
||||||
case "x", "*", "X":
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func rewriteRange(i string) string {
|
|
||||||
m := constraintRangeRegex.FindAllStringSubmatch(i, -1)
|
|
||||||
if m == nil {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
o := i
|
|
||||||
for _, v := range m {
|
|
||||||
t := fmt.Sprintf(">= %s, <= %s", v[1], v[11])
|
|
||||||
o = strings.Replace(o, v[0], t, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return o
|
|
||||||
}
|
|
115
vendor/github.com/Masterminds/semver/doc.go
generated
vendored
115
vendor/github.com/Masterminds/semver/doc.go
generated
vendored
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
Package semver 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
|
|
||||||
|
|
||||||
Parsing Semantic Versions
|
|
||||||
|
|
||||||
To parse a semantic version use the `NewVersion` function. For example,
|
|
||||||
|
|
||||||
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 at https://godoc.org/github.com/Masterminds/semver.
|
|
||||||
|
|
||||||
Sorting Semantic Versions
|
|
||||||
|
|
||||||
A set of versions can be sorted using the `sort` package from the standard library.
|
|
||||||
For example,
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
c, err := semver.NewConstraint(">= 1.2.3")
|
|
||||||
if err != nil {
|
|
||||||
// Handle constraint not being parseable.
|
|
||||||
}
|
|
||||||
|
|
||||||
v, err := 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
|
|
||||||
|
|
||||||
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`
|
|
||||||
*/
|
|
||||||
package semver
|
|
1
vendor/github.com/Masterminds/semver/v3/.gitignore
generated
vendored
Normal file
1
vendor/github.com/Masterminds/semver/v3/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
_fuzz/
|
26
vendor/github.com/Masterminds/semver/v3/.golangci.yml
generated
vendored
Normal file
26
vendor/github.com/Masterminds/semver/v3/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
run:
|
||||||
|
deadline: 2m
|
||||||
|
|
||||||
|
linters:
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- deadcode
|
||||||
|
- dupl
|
||||||
|
- errcheck
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
- golint
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- misspell
|
||||||
|
- nakedret
|
||||||
|
- structcheck
|
||||||
|
- unused
|
||||||
|
- varcheck
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
gofmt:
|
||||||
|
simplify: true
|
||||||
|
dupl:
|
||||||
|
threshold: 400
|
194
vendor/github.com/Masterminds/semver/v3/CHANGELOG.md
generated
vendored
Normal file
194
vendor/github.com/Masterminds/semver/v3/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 3.1.1 (2020-11-23)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- #158: Fixed issue with generated regex operation order that could cause problem
|
||||||
|
|
||||||
|
## 3.1.0 (2020-04-15)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- #131: Add support for serializing/deserializing SQL (thanks @ryancurrah)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- #148: More accurate validation messages on constraints
|
||||||
|
|
||||||
|
## 3.0.3 (2019-12-13)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- #141: Fixed issue with <= comparison
|
||||||
|
|
||||||
|
## 3.0.2 (2019-11-14)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- #134: Fixed broken constraint checking with ^0.0 (thanks @krmichelos)
|
||||||
|
|
||||||
|
## 3.0.1 (2019-09-13)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- #125: Fixes issue with module path for v3
|
||||||
|
|
||||||
|
## 3.0.0 (2019-09-12)
|
||||||
|
|
||||||
|
This is a major release of the semver package which includes API changes. The Go
|
||||||
|
API is compatible with ^1. The Go API was not changed because many people are using
|
||||||
|
`go get` without Go modules for their applications and API breaking changes cause
|
||||||
|
errors which we have or would need to support.
|
||||||
|
|
||||||
|
The changes in this release are the handling based on the data passed into the
|
||||||
|
functions. These are described in the added and changed sections below.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- StrictNewVersion function. This is similar to NewVersion but will return an
|
||||||
|
error if the version passed in is not a strict semantic version. For example,
|
||||||
|
1.2.3 would pass but v1.2.3 or 1.2 would fail because they are not strictly
|
||||||
|
speaking semantic versions. This function is faster, performs fewer operations,
|
||||||
|
and uses fewer allocations than NewVersion.
|
||||||
|
- Fuzzing has been performed on NewVersion, StrictNewVersion, and NewConstraint.
|
||||||
|
The Makefile contains the operations used. For more information on you can start
|
||||||
|
on Wikipedia at https://en.wikipedia.org/wiki/Fuzzing
|
||||||
|
- Now using Go modules
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- NewVersion has proper prerelease and metadata validation with error messages
|
||||||
|
to signal an issue with either of them
|
||||||
|
- ^ now operates using a similar set of rules to npm/js and Rust/Cargo. If the
|
||||||
|
version is >=1 the ^ ranges works the same as v1. For major versions of 0 the
|
||||||
|
rules have changed. The minor version is treated as the stable version unless
|
||||||
|
a patch is specified and then it is equivalent to =. One difference from npm/js
|
||||||
|
is that prereleases there are only to a specific version (e.g. 1.2.3).
|
||||||
|
Prereleases here look over multiple versions and follow semantic version
|
||||||
|
ordering rules. This pattern now follows along with the expected and requested
|
||||||
|
handling of this packaged by numerous users.
|
||||||
|
|
||||||
|
## 1.5.0 (2019-09-11)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- #103: Add basic fuzzing for `NewVersion()` (thanks @jesse-c)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- #82: Clarify wildcard meaning in range constraints and update tests for it (thanks @greysteil)
|
||||||
|
- #83: Clarify caret operator range for pre-1.0.0 dependencies (thanks @greysteil)
|
||||||
|
- #72: Adding docs comment pointing to vert for a cli
|
||||||
|
- #71: Update the docs on pre-release comparator handling
|
||||||
|
- #89: Test with new go versions (thanks @thedevsaddam)
|
||||||
|
- #87: Added $ to ValidPrerelease for better validation (thanks @jeremycarroll)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- #78: Fix unchecked error in example code (thanks @ravron)
|
||||||
|
- #70: Fix the handling of pre-releases and the 0.0.0 release edge case
|
||||||
|
- #97: Fixed copyright file for proper display on GitHub
|
||||||
|
- #107: Fix handling prerelease when sorting alphanum and num
|
||||||
|
- #109: Fixed where Validate sometimes returns wrong message on error
|
||||||
|
|
||||||
|
## 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
|
37
vendor/github.com/Masterminds/semver/v3/Makefile
generated
vendored
Normal file
37
vendor/github.com/Masterminds/semver/v3/Makefile
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
GOPATH=$(shell go env GOPATH)
|
||||||
|
GOLANGCI_LINT=$(GOPATH)/bin/golangci-lint
|
||||||
|
GOFUZZBUILD = $(GOPATH)/bin/go-fuzz-build
|
||||||
|
GOFUZZ = $(GOPATH)/bin/go-fuzz
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint: $(GOLANGCI_LINT)
|
||||||
|
@echo "==> Linting codebase"
|
||||||
|
@$(GOLANGCI_LINT) run
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
@echo "==> Running tests"
|
||||||
|
GO111MODULE=on go test -v
|
||||||
|
|
||||||
|
.PHONY: test-cover
|
||||||
|
test-cover:
|
||||||
|
@echo "==> Running Tests with coverage"
|
||||||
|
GO111MODULE=on go test -cover .
|
||||||
|
|
||||||
|
.PHONY: fuzz
|
||||||
|
fuzz: $(GOFUZZBUILD) $(GOFUZZ)
|
||||||
|
@echo "==> Fuzz testing"
|
||||||
|
$(GOFUZZBUILD)
|
||||||
|
$(GOFUZZ) -workdir=_fuzz
|
||||||
|
|
||||||
|
$(GOLANGCI_LINT):
|
||||||
|
# Install golangci-lint. The configuration for it is in the .golangci.yml
|
||||||
|
# file in the root of the repository
|
||||||
|
echo ${GOPATH}
|
||||||
|
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.17.1
|
||||||
|
|
||||||
|
$(GOFUZZBUILD):
|
||||||
|
cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz-build
|
||||||
|
|
||||||
|
$(GOFUZZ):
|
||||||
|
cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-dep
|
244
vendor/github.com/Masterminds/semver/v3/README.md
generated
vendored
Normal file
244
vendor/github.com/Masterminds/semver/v3/README.md
generated
vendored
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
# 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)
|
||||||
|
[![](https://github.com/Masterminds/semver/workflows/Tests/badge.svg)](https://github.com/Masterminds/semver/actions)
|
||||||
|
[![GoDoc](https://img.shields.io/static/v1?label=godoc&message=reference&color=blue)](https://pkg.go.dev/github.com/Masterminds/semver/v3)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/semver)](https://goreportcard.com/report/github.com/Masterminds/semver)
|
||||||
|
|
||||||
|
If you are looking for a command line tool for version comparisons please see
|
||||||
|
[vert](https://github.com/Masterminds/vert) which uses this library.
|
||||||
|
|
||||||
|
## Package Versions
|
||||||
|
|
||||||
|
There are three major versions fo the `semver` package.
|
||||||
|
|
||||||
|
* 3.x.x is the new stable and active version. This version is focused on constraint
|
||||||
|
compatibility for range handling in other tools from other languages. It has
|
||||||
|
a similar API to the v1 releases. The development of this version is on the master
|
||||||
|
branch. The documentation for this version is below.
|
||||||
|
* 2.x was developed primarily for [dep](https://github.com/golang/dep). There are
|
||||||
|
no tagged releases and the development was performed by [@sdboyer](https://github.com/sdboyer).
|
||||||
|
There are API breaking changes from v1. This version lives on the [2.x branch](https://github.com/Masterminds/semver/tree/2.x).
|
||||||
|
* 1.x.x is the most widely used version with numerous tagged releases. This is the
|
||||||
|
previous stable and is still maintained for bug fixes. The development, to fix
|
||||||
|
bugs, occurs on the release-1 branch. You can read the documentation [here](https://github.com/Masterminds/semver/blob/release-1/README.md).
|
||||||
|
|
||||||
|
## Parsing Semantic Versions
|
||||||
|
|
||||||
|
There are two functions that can parse semantic versions. The `StrictNewVersion`
|
||||||
|
function only parses valid version 2 semantic versions as outlined in the
|
||||||
|
specification. The `NewVersion` function attempts to coerce a version into a
|
||||||
|
semantic version and parse it. For example, if there is a leading v or a version
|
||||||
|
listed without all 3 parts (e.g. `v1.2`) it will attempt to coerce it into a valid
|
||||||
|
semantic version (e.g., 1.2.0). In both cases a `Version` object is returned
|
||||||
|
that can be sorted, compared, and used in constraints.
|
||||||
|
|
||||||
|
When parsing a version an error is returned if there is an issue parsing the
|
||||||
|
version. For example,
|
||||||
|
|
||||||
|
v, err := semver.NewVersion("1.2.3-beta.1+build345")
|
||||||
|
|
||||||
|
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. Getting the original string is useful if the semantic version was coerced
|
||||||
|
into a valid form.
|
||||||
|
|
||||||
|
## Sorting Semantic Versions
|
||||||
|
|
||||||
|
A set of versions can be sorted using the `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
|
||||||
|
|
||||||
|
There are two methods for comparing versions. One uses comparison methods on
|
||||||
|
`Version` instances and the other uses `Constraints`. There are some important
|
||||||
|
differences to notes between these two methods of comparison.
|
||||||
|
|
||||||
|
1. When two versions are compared using functions such as `Compare`, `LessThan`,
|
||||||
|
and others it will follow the specification and always include prereleases
|
||||||
|
within the comparison. It will provide an answer that is valid with the
|
||||||
|
comparison section of the spec at https://semver.org/#spec-item-11
|
||||||
|
2. When constraint checking is used for checks or validation it will follow a
|
||||||
|
different set of rules that are common for ranges with tools like npm/js
|
||||||
|
and Rust/Cargo. This includes considering prereleases to be invalid if the
|
||||||
|
ranges does not include one. If you want to have it include pre-releases a
|
||||||
|
simple solution is to include `-0` in your range.
|
||||||
|
3. Constraint ranges can have some complex rules including the shorthand use of
|
||||||
|
~ and ^. For more details on those see the options below.
|
||||||
|
|
||||||
|
There are differences between the two methods or checking versions because the
|
||||||
|
comparison methods on `Version` follow the specification while comparison ranges
|
||||||
|
are not part of the specification. Different packages and tools have taken it
|
||||||
|
upon themselves to come up with range rules. This has resulted in differences.
|
||||||
|
For example, npm/js and Cargo/Rust follow similar patterns while PHP has a
|
||||||
|
different pattern for ^. The comparison features in this package follow the
|
||||||
|
npm/js and Cargo/Rust lead because applications using it have followed similar
|
||||||
|
patters with their versions.
|
||||||
|
|
||||||
|
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 parsable.
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := semver.NewVersion("1.3")
|
||||||
|
if err != nil {
|
||||||
|
// Handle version not being parsable.
|
||||||
|
}
|
||||||
|
// 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 space or comma separated AND comparisons. These are then separated by || (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
|
||||||
|
|
||||||
|
### Working With Prerelease Versions
|
||||||
|
|
||||||
|
Pre-releases, for those not familiar with them, are used for software releases
|
||||||
|
prior to stable or generally available releases. Examples of prereleases include
|
||||||
|
development, alpha, beta, and release candidate releases. A prerelease may be
|
||||||
|
a version such as `1.2.3-beta.1` while the stable release would be `1.2.3`. In the
|
||||||
|
order of precedence, prereleases come before their associated releases. In this
|
||||||
|
example `1.2.3-beta.1 < 1.2.3`.
|
||||||
|
|
||||||
|
According to the Semantic Version specification prereleases 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 using constraints without a prerelease comparator will skip
|
||||||
|
prerelease versions. For example, `>=1.2.3` will skip prereleases when looking
|
||||||
|
at a list of releases while `>=1.2.3-0` will evaluate and find prereleases.
|
||||||
|
|
||||||
|
The reason for the `0` as a pre-release version in the example comparison is
|
||||||
|
because pre-releases can only contain ASCII alphanumerics and hyphens (along with
|
||||||
|
`.` separators), per the spec. Sorting happens in ASCII sort order, again per the
|
||||||
|
spec. The lowest character is a `0` in ASCII sort order
|
||||||
|
(see an [ASCII Table](http://www.asciitable.com/))
|
||||||
|
|
||||||
|
Understanding ASCII sort ordering is important because A-Z comes before a-z. That
|
||||||
|
means `>=1.2.3-BETA` will return `1.2.3-alpha`. What you might expect from case
|
||||||
|
sensitivity doesn't apply here. This is due to ASCII sort ordering which is what
|
||||||
|
the spec specifies.
|
||||||
|
|
||||||
|
### 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 patch 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 once a stable
|
||||||
|
(1.0.0) release has occurred. Prior to a 1.0.0 release the minor versions acts
|
||||||
|
as the API stability level. 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`
|
||||||
|
* `^0.2.3` is equivalent to `>=0.2.3 <0.3.0`
|
||||||
|
* `^0.2` is equivalent to `>=0.2.0 <0.3.0`
|
||||||
|
* `^0.0.3` is equivalent to `>=0.0.3 <0.0.4`
|
||||||
|
* `^0.0` is equivalent to `>=0.0.0 <0.1.0`
|
||||||
|
* `^0` is equivalent to `>=0.0.0 <1.0.0`
|
||||||
|
|
||||||
|
## 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, err := 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).
|
568
vendor/github.com/Masterminds/semver/v3/constraints.go
generated
vendored
Normal file
568
vendor/github.com/Masterminds/semver/v3/constraints.go
generated
vendored
Normal file
@ -0,0 +1,568 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Constraints is one or more constraint that a semantic version can be
|
||||||
|
// checked against.
|
||||||
|
type Constraints struct {
|
||||||
|
constraints [][]*constraint
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConstraint returns a Constraints instance that a Version instance can
|
||||||
|
// be checked against. If there is a parse error it will be returned.
|
||||||
|
func NewConstraint(c string) (*Constraints, error) {
|
||||||
|
|
||||||
|
// Rewrite - ranges into a comparison operation.
|
||||||
|
c = rewriteRange(c)
|
||||||
|
|
||||||
|
ors := strings.Split(c, "||")
|
||||||
|
or := make([][]*constraint, len(ors))
|
||||||
|
for k, v := range ors {
|
||||||
|
|
||||||
|
// TODO: Find a way to validate and fetch all the constraints in a simpler form
|
||||||
|
|
||||||
|
// Validate the segment
|
||||||
|
if !validConstraintRegex.MatchString(v) {
|
||||||
|
return nil, fmt.Errorf("improper constraint: %s", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
cs := findConstraintRegex.FindAllString(v, -1)
|
||||||
|
if cs == nil {
|
||||||
|
cs = append(cs, v)
|
||||||
|
}
|
||||||
|
result := make([]*constraint, len(cs))
|
||||||
|
for i, s := range cs {
|
||||||
|
pc, err := parseConstraint(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result[i] = pc
|
||||||
|
}
|
||||||
|
or[k] = result
|
||||||
|
}
|
||||||
|
|
||||||
|
o := &Constraints{constraints: or}
|
||||||
|
return o, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check tests if a version satisfies the constraints.
|
||||||
|
func (cs Constraints) Check(v *Version) bool {
|
||||||
|
// TODO(mattfarina): For v4 of this library consolidate the Check and Validate
|
||||||
|
// functions as the underlying functions make that possible now.
|
||||||
|
// loop over the ORs and check the inner ANDs
|
||||||
|
for _, o := range cs.constraints {
|
||||||
|
joy := true
|
||||||
|
for _, c := range o {
|
||||||
|
if check, _ := c.check(v); !check {
|
||||||
|
joy = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if joy {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks if a version satisfies a constraint. If not a slice of
|
||||||
|
// reasons for the failure are returned in addition to a bool.
|
||||||
|
func (cs Constraints) Validate(v *Version) (bool, []error) {
|
||||||
|
// loop over the ORs and check the inner ANDs
|
||||||
|
var e []error
|
||||||
|
|
||||||
|
// Capture the prerelease message only once. When it happens the first time
|
||||||
|
// this var is marked
|
||||||
|
var prerelesase bool
|
||||||
|
for _, o := range cs.constraints {
|
||||||
|
joy := true
|
||||||
|
for _, c := range o {
|
||||||
|
// Before running the check handle the case there the version is
|
||||||
|
// a prerelease and the check is not searching for prereleases.
|
||||||
|
if c.con.pre == "" && v.pre != "" {
|
||||||
|
if !prerelesase {
|
||||||
|
em := fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
|
||||||
|
e = append(e, em)
|
||||||
|
prerelesase = true
|
||||||
|
}
|
||||||
|
joy = false
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if _, err := c.check(v); err != nil {
|
||||||
|
e = append(e, err)
|
||||||
|
joy = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if joy {
|
||||||
|
return true, []error{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs Constraints) String() string {
|
||||||
|
buf := make([]string, len(cs.constraints))
|
||||||
|
var tmp bytes.Buffer
|
||||||
|
|
||||||
|
for k, v := range cs.constraints {
|
||||||
|
tmp.Reset()
|
||||||
|
vlen := len(v)
|
||||||
|
for kk, c := range v {
|
||||||
|
tmp.WriteString(c.string())
|
||||||
|
|
||||||
|
// Space separate the AND conditions
|
||||||
|
if vlen > 1 && kk < vlen-1 {
|
||||||
|
tmp.WriteString(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf[k] = tmp.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(buf, " || ")
|
||||||
|
}
|
||||||
|
|
||||||
|
var constraintOps map[string]cfunc
|
||||||
|
var constraintRegex *regexp.Regexp
|
||||||
|
var constraintRangeRegex *regexp.Regexp
|
||||||
|
|
||||||
|
// Used to find individual constraints within a multi-constraint string
|
||||||
|
var findConstraintRegex *regexp.Regexp
|
||||||
|
|
||||||
|
// Used to validate an segment of ANDs is valid
|
||||||
|
var validConstraintRegex *regexp.Regexp
|
||||||
|
|
||||||
|
const cvRegex string = `v?([0-9|x|X|\*]+)(\.[0-9|x|X|\*]+)?(\.[0-9|x|X|\*]+)?` +
|
||||||
|
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
|
||||||
|
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
constraintOps = map[string]cfunc{
|
||||||
|
"": constraintTildeOrEqual,
|
||||||
|
"=": constraintTildeOrEqual,
|
||||||
|
"!=": constraintNotEqual,
|
||||||
|
">": constraintGreaterThan,
|
||||||
|
"<": constraintLessThan,
|
||||||
|
">=": constraintGreaterThanEqual,
|
||||||
|
"=>": constraintGreaterThanEqual,
|
||||||
|
"<=": constraintLessThanEqual,
|
||||||
|
"=<": constraintLessThanEqual,
|
||||||
|
"~": constraintTilde,
|
||||||
|
"~>": constraintTilde,
|
||||||
|
"^": constraintCaret,
|
||||||
|
}
|
||||||
|
|
||||||
|
ops := `=||!=|>|<|>=|=>|<=|=<|~|~>|\^`
|
||||||
|
|
||||||
|
constraintRegex = regexp.MustCompile(fmt.Sprintf(
|
||||||
|
`^\s*(%s)\s*(%s)\s*$`,
|
||||||
|
ops,
|
||||||
|
cvRegex))
|
||||||
|
|
||||||
|
constraintRangeRegex = regexp.MustCompile(fmt.Sprintf(
|
||||||
|
`\s*(%s)\s+-\s+(%s)\s*`,
|
||||||
|
cvRegex, cvRegex))
|
||||||
|
|
||||||
|
findConstraintRegex = regexp.MustCompile(fmt.Sprintf(
|
||||||
|
`(%s)\s*(%s)`,
|
||||||
|
ops,
|
||||||
|
cvRegex))
|
||||||
|
|
||||||
|
validConstraintRegex = regexp.MustCompile(fmt.Sprintf(
|
||||||
|
`^(\s*(%s)\s*(%s)\s*\,?)+$`,
|
||||||
|
ops,
|
||||||
|
cvRegex))
|
||||||
|
}
|
||||||
|
|
||||||
|
// An individual constraint
|
||||||
|
type constraint struct {
|
||||||
|
// The version used in the constraint check. For example, if a constraint
|
||||||
|
// is '<= 2.0.0' the con a version instance representing 2.0.0.
|
||||||
|
con *Version
|
||||||
|
|
||||||
|
// The original parsed version (e.g., 4.x from != 4.x)
|
||||||
|
orig string
|
||||||
|
|
||||||
|
// The original operator for the constraint
|
||||||
|
origfunc string
|
||||||
|
|
||||||
|
// When an x is used as part of the version (e.g., 1.x)
|
||||||
|
minorDirty bool
|
||||||
|
dirty bool
|
||||||
|
patchDirty bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a version meets the constraint
|
||||||
|
func (c *constraint) check(v *Version) (bool, error) {
|
||||||
|
return constraintOps[c.origfunc](v, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String prints an individual constraint into a string
|
||||||
|
func (c *constraint) string() string {
|
||||||
|
return c.origfunc + c.orig
|
||||||
|
}
|
||||||
|
|
||||||
|
type cfunc func(v *Version, c *constraint) (bool, error)
|
||||||
|
|
||||||
|
func parseConstraint(c string) (*constraint, error) {
|
||||||
|
if len(c) > 0 {
|
||||||
|
m := constraintRegex.FindStringSubmatch(c)
|
||||||
|
if m == nil {
|
||||||
|
return nil, fmt.Errorf("improper constraint: %s", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
cs := &constraint{
|
||||||
|
orig: m[2],
|
||||||
|
origfunc: m[1],
|
||||||
|
}
|
||||||
|
|
||||||
|
ver := m[2]
|
||||||
|
minorDirty := false
|
||||||
|
patchDirty := false
|
||||||
|
dirty := false
|
||||||
|
if isX(m[3]) || m[3] == "" {
|
||||||
|
ver = "0.0.0"
|
||||||
|
dirty = true
|
||||||
|
} else if isX(strings.TrimPrefix(m[4], ".")) || m[4] == "" {
|
||||||
|
minorDirty = true
|
||||||
|
dirty = true
|
||||||
|
ver = fmt.Sprintf("%s.0.0%s", m[3], m[6])
|
||||||
|
} else if isX(strings.TrimPrefix(m[5], ".")) || m[5] == "" {
|
||||||
|
dirty = true
|
||||||
|
patchDirty = true
|
||||||
|
ver = fmt.Sprintf("%s%s.0%s", m[3], m[4], m[6])
|
||||||
|
}
|
||||||
|
|
||||||
|
con, err := NewVersion(ver)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
// The constraintRegex should catch any regex parsing errors. So,
|
||||||
|
// we should never get here.
|
||||||
|
return nil, errors.New("constraint Parser Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
cs.con = con
|
||||||
|
cs.minorDirty = minorDirty
|
||||||
|
cs.patchDirty = patchDirty
|
||||||
|
cs.dirty = dirty
|
||||||
|
|
||||||
|
return cs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The rest is the special case where an empty string was passed in which
|
||||||
|
// is equivalent to * or >=0.0.0
|
||||||
|
con, err := StrictNewVersion("0.0.0")
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
// The constraintRegex should catch any regex parsing errors. So,
|
||||||
|
// we should never get here.
|
||||||
|
return nil, errors.New("constraint Parser Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
cs := &constraint{
|
||||||
|
con: con,
|
||||||
|
orig: c,
|
||||||
|
origfunc: "",
|
||||||
|
minorDirty: false,
|
||||||
|
patchDirty: false,
|
||||||
|
dirty: true,
|
||||||
|
}
|
||||||
|
return cs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constraint functions
|
||||||
|
func constraintNotEqual(v *Version, c *constraint) (bool, error) {
|
||||||
|
if c.dirty {
|
||||||
|
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.con.Major() != v.Major() {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
if c.con.Minor() != v.Minor() && !c.minorDirty {
|
||||||
|
return true, nil
|
||||||
|
} else if c.minorDirty {
|
||||||
|
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
|
||||||
|
} else if c.con.Patch() != v.Patch() && !c.patchDirty {
|
||||||
|
return true, nil
|
||||||
|
} else if c.patchDirty {
|
||||||
|
// Need to handle prereleases if present
|
||||||
|
if v.Prerelease() != "" || c.con.Prerelease() != "" {
|
||||||
|
eq := comparePrerelease(v.Prerelease(), c.con.Prerelease()) != 0
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eq := v.Equal(c.con)
|
||||||
|
if eq {
|
||||||
|
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintGreaterThan(v *Version, c *constraint) (bool, error) {
|
||||||
|
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var eq bool
|
||||||
|
|
||||||
|
if !c.dirty {
|
||||||
|
eq = v.Compare(c.con) == 1
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Major() > c.con.Major() {
|
||||||
|
return true, nil
|
||||||
|
} else if v.Major() < c.con.Major() {
|
||||||
|
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
|
||||||
|
} else if c.minorDirty {
|
||||||
|
// This is a range case such as >11. When the version is something like
|
||||||
|
// 11.1.0 is it not > 11. For that we would need 12 or higher
|
||||||
|
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
|
||||||
|
} else if c.patchDirty {
|
||||||
|
// This is for ranges such as >11.1. A version of 11.1.1 is not greater
|
||||||
|
// which one of 11.2.1 is greater
|
||||||
|
eq = v.Minor() > c.con.Minor()
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have gotten here we are not comparing pre-preleases and can use the
|
||||||
|
// Compare function to accomplish that.
|
||||||
|
eq = v.Compare(c.con) == 1
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintLessThan(v *Version, c *constraint) (bool, error) {
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
eq := v.Compare(c.con) < 0
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("%s is greater than or equal to %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintGreaterThanEqual(v *Version, c *constraint) (bool, error) {
|
||||||
|
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
eq := v.Compare(c.con) >= 0
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("%s is less than %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintLessThanEqual(v *Version, c *constraint) (bool, error) {
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var eq bool
|
||||||
|
|
||||||
|
if !c.dirty {
|
||||||
|
eq = v.Compare(c.con) <= 0
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("%s is greater than %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Major() > c.con.Major() {
|
||||||
|
return false, fmt.Errorf("%s is greater than %s", v, c.orig)
|
||||||
|
} else if v.Major() == c.con.Major() && v.Minor() > c.con.Minor() && !c.minorDirty {
|
||||||
|
return false, fmt.Errorf("%s is greater than %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~*, ~>* --> >= 0.0.0 (any)
|
||||||
|
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0, <3.0.0
|
||||||
|
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0, <2.1.0
|
||||||
|
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0, <1.3.0
|
||||||
|
// ~1.2.3, ~>1.2.3 --> >=1.2.3, <1.3.0
|
||||||
|
// ~1.2.0, ~>1.2.0 --> >=1.2.0, <1.3.0
|
||||||
|
func constraintTilde(v *Version, c *constraint) (bool, error) {
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.LessThan(c.con) {
|
||||||
|
return false, fmt.Errorf("%s is less than %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~0.0.0 is a special case where all constraints are accepted. It's
|
||||||
|
// equivalent to >= 0.0.0.
|
||||||
|
if c.con.Major() == 0 && c.con.Minor() == 0 && c.con.Patch() == 0 &&
|
||||||
|
!c.minorDirty && !c.patchDirty {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Major() != c.con.Major() {
|
||||||
|
return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Minor() != c.con.Minor() && !c.minorDirty {
|
||||||
|
return false, fmt.Errorf("%s does not have same major and minor version as %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// When there is a .x (dirty) status it automatically opts in to ~. Otherwise
|
||||||
|
// it's a straight =
|
||||||
|
func constraintTildeOrEqual(v *Version, c *constraint) (bool, error) {
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.dirty {
|
||||||
|
return constraintTilde(v, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
eq := v.Equal(c.con)
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, fmt.Errorf("%s is not equal to %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ^* --> (any)
|
||||||
|
// ^1.2.3 --> >=1.2.3 <2.0.0
|
||||||
|
// ^1.2 --> >=1.2.0 <2.0.0
|
||||||
|
// ^1 --> >=1.0.0 <2.0.0
|
||||||
|
// ^0.2.3 --> >=0.2.3 <0.3.0
|
||||||
|
// ^0.2 --> >=0.2.0 <0.3.0
|
||||||
|
// ^0.0.3 --> >=0.0.3 <0.0.4
|
||||||
|
// ^0.0 --> >=0.0.0 <0.1.0
|
||||||
|
// ^0 --> >=0.0.0 <1.0.0
|
||||||
|
func constraintCaret(v *Version, c *constraint) (bool, error) {
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This less than handles prereleases
|
||||||
|
if v.LessThan(c.con) {
|
||||||
|
return false, fmt.Errorf("%s is less than %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
var eq bool
|
||||||
|
|
||||||
|
// ^ when the major > 0 is >=x.y.z < x+1
|
||||||
|
if c.con.Major() > 0 || c.minorDirty {
|
||||||
|
|
||||||
|
// ^ has to be within a major range for > 0. Everything less than was
|
||||||
|
// filtered out with the LessThan call above. This filters out those
|
||||||
|
// that greater but not within the same major range.
|
||||||
|
eq = v.Major() == c.con.Major()
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ^ when the major is 0 and minor > 0 is >=0.y.z < 0.y+1
|
||||||
|
if c.con.Major() == 0 && v.Major() > 0 {
|
||||||
|
return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
|
||||||
|
}
|
||||||
|
// If the con Minor is > 0 it is not dirty
|
||||||
|
if c.con.Minor() > 0 || c.patchDirty {
|
||||||
|
eq = v.Minor() == c.con.Minor()
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("%s does not have same minor version as %s. Expected minor versions to match when constraint major version is 0", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point the major is 0 and the minor is 0 and not dirty. The patch
|
||||||
|
// is not dirty so we need to check if they are equal. If they are not equal
|
||||||
|
eq = c.con.Patch() == v.Patch()
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("%s does not equal %s. Expect version and constraint to equal when major and minor versions are 0", v, c.orig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isX(x string) bool {
|
||||||
|
switch x {
|
||||||
|
case "x", "*", "X":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rewriteRange(i string) string {
|
||||||
|
m := constraintRangeRegex.FindAllStringSubmatch(i, -1)
|
||||||
|
if m == nil {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
o := i
|
||||||
|
for _, v := range m {
|
||||||
|
t := fmt.Sprintf(">= %s, <= %s", v[1], v[11])
|
||||||
|
o = strings.Replace(o, v[0], t, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
184
vendor/github.com/Masterminds/semver/v3/doc.go
generated
vendored
Normal file
184
vendor/github.com/Masterminds/semver/v3/doc.go
generated
vendored
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
Package semver 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
|
||||||
|
|
||||||
|
Parsing Semantic Versions
|
||||||
|
|
||||||
|
There are two functions that can parse semantic versions. The `StrictNewVersion`
|
||||||
|
function only parses valid version 2 semantic versions as outlined in the
|
||||||
|
specification. The `NewVersion` function attempts to coerce a version into a
|
||||||
|
semantic version and parse it. For example, if there is a leading v or a version
|
||||||
|
listed without all 3 parts (e.g. 1.2) it will attempt to coerce it into a valid
|
||||||
|
semantic version (e.g., 1.2.0). In both cases a `Version` object is returned
|
||||||
|
that can be sorted, compared, and used in constraints.
|
||||||
|
|
||||||
|
When parsing a version an optional error can be returned if there is an issue
|
||||||
|
parsing the version. For example,
|
||||||
|
|
||||||
|
v, err := semver.NewVersion("1.2.3-beta.1+b345")
|
||||||
|
|
||||||
|
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
|
||||||
|
at https://godoc.org/github.com/Masterminds/semver.
|
||||||
|
|
||||||
|
Sorting Semantic Versions
|
||||||
|
|
||||||
|
A set of versions can be sorted using the `sort` package from the standard library.
|
||||||
|
For example,
|
||||||
|
|
||||||
|
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 and Comparing Versions
|
||||||
|
|
||||||
|
There are two methods for comparing versions. One uses comparison methods on
|
||||||
|
`Version` instances and the other is using Constraints. There are some important
|
||||||
|
differences to notes between these two methods of comparison.
|
||||||
|
|
||||||
|
1. When two versions are compared using functions such as `Compare`, `LessThan`,
|
||||||
|
and others it will follow the specification and always include prereleases
|
||||||
|
within the comparison. It will provide an answer valid with the comparison
|
||||||
|
spec section at https://semver.org/#spec-item-11
|
||||||
|
2. When constraint checking is used for checks or validation it will follow a
|
||||||
|
different set of rules that are common for ranges with tools like npm/js
|
||||||
|
and Rust/Cargo. This includes considering prereleases to be invalid if the
|
||||||
|
ranges does not include on. If you want to have it include pre-releases a
|
||||||
|
simple solution is to include `-0` in your range.
|
||||||
|
3. Constraint ranges can have some complex rules including the shorthard use of
|
||||||
|
~ and ^. For more details on those see the options below.
|
||||||
|
|
||||||
|
There are differences between the two methods or checking versions because the
|
||||||
|
comparison methods on `Version` follow the specification while comparison ranges
|
||||||
|
are not part of the specification. Different packages and tools have taken it
|
||||||
|
upon themselves to come up with range rules. This has resulted in differences.
|
||||||
|
For example, npm/js and Cargo/Rust follow similar patterns which PHP has a
|
||||||
|
different pattern for ^. The comparison features in this package follow the
|
||||||
|
npm/js and Cargo/Rust lead because applications using it have followed similar
|
||||||
|
patters with their versions.
|
||||||
|
|
||||||
|
Checking a version against version constraints is one of the most featureful
|
||||||
|
parts of the package.
|
||||||
|
|
||||||
|
c, err := semver.NewConstraint(">= 1.2.3")
|
||||||
|
if err != nil {
|
||||||
|
// Handle constraint not being parsable.
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := semver.NewVersion("1.3")
|
||||||
|
if err != nil {
|
||||||
|
// Handle version not being parsable.
|
||||||
|
}
|
||||||
|
// 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 or space separated AND comparisons. These are then separated by || (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. This can also be written as
|
||||||
|
`">= 1.2, < 3.0.0 || >= 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
|
||||||
|
|
||||||
|
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 tilde operation. 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 once a stable
|
||||||
|
(1.0.0) release has occurred. Prior to a 1.0.0 release the minor versions acts
|
||||||
|
as the API stability level. 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`
|
||||||
|
* `^0.2.3` is equivalent to `>=0.2.3 <0.3.0`
|
||||||
|
* `^0.2` is equivalent to `>=0.2.0 <0.3.0`
|
||||||
|
* `^0.0.3` is equivalent to `>=0.0.3 <0.0.4`
|
||||||
|
* `^0.0` is equivalent to `>=0.0.0 <0.1.0`
|
||||||
|
* `^0` is equivalent to `>=0.0.0 <1.0.0`
|
||||||
|
|
||||||
|
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,
|
||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
package semver
|
22
vendor/github.com/Masterminds/semver/v3/fuzz.go
generated
vendored
Normal file
22
vendor/github.com/Masterminds/semver/v3/fuzz.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package semver
|
||||||
|
|
||||||
|
func Fuzz(data []byte) int {
|
||||||
|
d := string(data)
|
||||||
|
|
||||||
|
// Test NewVersion
|
||||||
|
_, _ = NewVersion(d)
|
||||||
|
|
||||||
|
// Test StrictNewVersion
|
||||||
|
_, _ = StrictNewVersion(d)
|
||||||
|
|
||||||
|
// Test NewConstraint
|
||||||
|
_, _ = NewConstraint(d)
|
||||||
|
|
||||||
|
// The return value should be 0 normally, 1 if the priority in future tests
|
||||||
|
// should be increased, and -1 if future tests should skip passing in that
|
||||||
|
// data. We do not have a reason to change priority so 0 is always returned.
|
||||||
|
// There are example tests that do this.
|
||||||
|
return 0
|
||||||
|
}
|
@ -2,6 +2,7 @@ package semver
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"database/sql/driver"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -13,13 +14,23 @@ import (
|
|||||||
// The compiled version of the regex created at init() is cached here so it
|
// The compiled version of the regex created at init() is cached here so it
|
||||||
// only needs to be created once.
|
// only needs to be created once.
|
||||||
var versionRegex *regexp.Regexp
|
var versionRegex *regexp.Regexp
|
||||||
var validPrereleaseRegex *regexp.Regexp
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrInvalidSemVer is returned a version is found to be invalid when
|
// ErrInvalidSemVer is returned a version is found to be invalid when
|
||||||
// being parsed.
|
// being parsed.
|
||||||
ErrInvalidSemVer = errors.New("Invalid Semantic Version")
|
ErrInvalidSemVer = errors.New("Invalid Semantic Version")
|
||||||
|
|
||||||
|
// ErrEmptyString is returned when an empty string is passed in for parsing.
|
||||||
|
ErrEmptyString = errors.New("Version string empty")
|
||||||
|
|
||||||
|
// ErrInvalidCharacters is returned when invalid characters are found as
|
||||||
|
// part of a version
|
||||||
|
ErrInvalidCharacters = errors.New("Invalid characters in version")
|
||||||
|
|
||||||
|
// ErrSegmentStartsZero is returned when a version segment starts with 0.
|
||||||
|
// This is invalid in SemVer.
|
||||||
|
ErrSegmentStartsZero = errors.New("Version segment starts with 0")
|
||||||
|
|
||||||
// ErrInvalidMetadata is returned when the metadata is an invalid format
|
// ErrInvalidMetadata is returned when the metadata is an invalid format
|
||||||
ErrInvalidMetadata = errors.New("Invalid Metadata string")
|
ErrInvalidMetadata = errors.New("Invalid Metadata string")
|
||||||
|
|
||||||
@ -27,30 +38,121 @@ var (
|
|||||||
ErrInvalidPrerelease = errors.New("Invalid Prerelease string")
|
ErrInvalidPrerelease = errors.New("Invalid Prerelease string")
|
||||||
)
|
)
|
||||||
|
|
||||||
// SemVerRegex is the regular expression used to parse a semantic version.
|
// semVerRegex is the regular expression used to parse a semantic version.
|
||||||
const SemVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` +
|
const semVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` +
|
||||||
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
|
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
|
||||||
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
|
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
|
||||||
|
|
||||||
// ValidPrerelease is the regular expression which validates
|
|
||||||
// both prerelease and metadata values.
|
|
||||||
const ValidPrerelease string = `^([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*)$`
|
|
||||||
|
|
||||||
// Version represents a single semantic version.
|
// Version represents a single semantic version.
|
||||||
type Version struct {
|
type Version struct {
|
||||||
major, minor, patch int64
|
major, minor, patch uint64
|
||||||
pre string
|
pre string
|
||||||
metadata string
|
metadata string
|
||||||
original string
|
original string
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
versionRegex = regexp.MustCompile("^" + SemVerRegex + "$")
|
versionRegex = regexp.MustCompile("^" + semVerRegex + "$")
|
||||||
validPrereleaseRegex = regexp.MustCompile(ValidPrerelease)
|
}
|
||||||
|
|
||||||
|
const num string = "0123456789"
|
||||||
|
const allowed string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" + num
|
||||||
|
|
||||||
|
// StrictNewVersion parses a given version and returns an instance of Version or
|
||||||
|
// an error if unable to parse the version. Only parses valid semantic versions.
|
||||||
|
// Performs checking that can find errors within the version.
|
||||||
|
// If you want to coerce a version, such as 1 or 1.2, and perse that as the 1.x
|
||||||
|
// releases of semver provided use the NewSemver() function.
|
||||||
|
func StrictNewVersion(v string) (*Version, error) {
|
||||||
|
// Parsing here does not use RegEx in order to increase performance and reduce
|
||||||
|
// allocations.
|
||||||
|
|
||||||
|
if len(v) == 0 {
|
||||||
|
return nil, ErrEmptyString
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split the parts into [0]major, [1]minor, and [2]patch,prerelease,build
|
||||||
|
parts := strings.SplitN(v, ".", 3)
|
||||||
|
if len(parts) != 3 {
|
||||||
|
return nil, ErrInvalidSemVer
|
||||||
|
}
|
||||||
|
|
||||||
|
sv := &Version{
|
||||||
|
original: v,
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for prerelease or build metadata
|
||||||
|
var extra []string
|
||||||
|
if strings.ContainsAny(parts[2], "-+") {
|
||||||
|
// Start with the build metadata first as it needs to be on the right
|
||||||
|
extra = strings.SplitN(parts[2], "+", 2)
|
||||||
|
if len(extra) > 1 {
|
||||||
|
// build metadata found
|
||||||
|
sv.metadata = extra[1]
|
||||||
|
parts[2] = extra[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
extra = strings.SplitN(parts[2], "-", 2)
|
||||||
|
if len(extra) > 1 {
|
||||||
|
// prerelease found
|
||||||
|
sv.pre = extra[1]
|
||||||
|
parts[2] = extra[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the number segments are valid. This includes only having positive
|
||||||
|
// numbers and no leading 0's.
|
||||||
|
for _, p := range parts {
|
||||||
|
if !containsOnly(p, num) {
|
||||||
|
return nil, ErrInvalidCharacters
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p) > 1 && p[0] == '0' {
|
||||||
|
return nil, ErrSegmentStartsZero
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the major, minor, and patch elements onto the returned Version
|
||||||
|
var err error
|
||||||
|
sv.major, err = strconv.ParseUint(parts[0], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sv.minor, err = strconv.ParseUint(parts[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sv.patch, err = strconv.ParseUint(parts[2], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// No prerelease or build metadata found so returning now as a fastpath.
|
||||||
|
if sv.pre == "" && sv.metadata == "" {
|
||||||
|
return sv, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if sv.pre != "" {
|
||||||
|
if err = validatePrerelease(sv.pre); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sv.metadata != "" {
|
||||||
|
if err = validateMetadata(sv.metadata); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVersion parses a given version and returns an instance of Version or
|
// NewVersion parses a given version and returns an instance of Version or
|
||||||
// an error if unable to parse the version.
|
// an error if unable to parse the version. If the version is SemVer-ish it
|
||||||
|
// attempts to convert it to SemVer. If you want to validate it was a strict
|
||||||
|
// semantic version at parse time see StrictNewVersion().
|
||||||
func NewVersion(v string) (*Version, error) {
|
func NewVersion(v string) (*Version, error) {
|
||||||
m := versionRegex.FindStringSubmatch(v)
|
m := versionRegex.FindStringSubmatch(v)
|
||||||
if m == nil {
|
if m == nil {
|
||||||
@ -63,33 +165,45 @@ func NewVersion(v string) (*Version, error) {
|
|||||||
original: v,
|
original: v,
|
||||||
}
|
}
|
||||||
|
|
||||||
var temp int64
|
var err error
|
||||||
temp, err := strconv.ParseInt(m[1], 10, 64)
|
sv.major, err = strconv.ParseUint(m[1], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
||||||
}
|
}
|
||||||
sv.major = temp
|
|
||||||
|
|
||||||
if m[2] != "" {
|
if m[2] != "" {
|
||||||
temp, err = strconv.ParseInt(strings.TrimPrefix(m[2], "."), 10, 64)
|
sv.minor, err = strconv.ParseUint(strings.TrimPrefix(m[2], "."), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
||||||
}
|
}
|
||||||
sv.minor = temp
|
|
||||||
} else {
|
} else {
|
||||||
sv.minor = 0
|
sv.minor = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if m[3] != "" {
|
if m[3] != "" {
|
||||||
temp, err = strconv.ParseInt(strings.TrimPrefix(m[3], "."), 10, 64)
|
sv.patch, err = strconv.ParseUint(strings.TrimPrefix(m[3], "."), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
||||||
}
|
}
|
||||||
sv.patch = temp
|
|
||||||
} else {
|
} else {
|
||||||
sv.patch = 0
|
sv.patch = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform some basic due diligence on the extra parts to ensure they are
|
||||||
|
// valid.
|
||||||
|
|
||||||
|
if sv.pre != "" {
|
||||||
|
if err = validatePrerelease(sv.pre); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sv.metadata != "" {
|
||||||
|
if err = validateMetadata(sv.metadata); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return sv, nil
|
return sv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +221,7 @@ func MustParse(v string) *Version {
|
|||||||
// See the Original() method to retrieve the original value. Semantic Versions
|
// See the Original() method to retrieve the original value. Semantic Versions
|
||||||
// don't contain a leading v per the spec. Instead it's optional on
|
// don't contain a leading v per the spec. Instead it's optional on
|
||||||
// implementation.
|
// implementation.
|
||||||
func (v *Version) String() string {
|
func (v Version) String() string {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
fmt.Fprintf(&buf, "%d.%d.%d", v.major, v.minor, v.patch)
|
fmt.Fprintf(&buf, "%d.%d.%d", v.major, v.minor, v.patch)
|
||||||
@ -127,32 +241,32 @@ func (v *Version) Original() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Major returns the major version.
|
// Major returns the major version.
|
||||||
func (v *Version) Major() int64 {
|
func (v Version) Major() uint64 {
|
||||||
return v.major
|
return v.major
|
||||||
}
|
}
|
||||||
|
|
||||||
// Minor returns the minor version.
|
// Minor returns the minor version.
|
||||||
func (v *Version) Minor() int64 {
|
func (v Version) Minor() uint64 {
|
||||||
return v.minor
|
return v.minor
|
||||||
}
|
}
|
||||||
|
|
||||||
// Patch returns the patch version.
|
// Patch returns the patch version.
|
||||||
func (v *Version) Patch() int64 {
|
func (v Version) Patch() uint64 {
|
||||||
return v.patch
|
return v.patch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prerelease returns the pre-release version.
|
// Prerelease returns the pre-release version.
|
||||||
func (v *Version) Prerelease() string {
|
func (v Version) Prerelease() string {
|
||||||
return v.pre
|
return v.pre
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metadata returns the metadata on the version.
|
// Metadata returns the metadata on the version.
|
||||||
func (v *Version) Metadata() string {
|
func (v Version) Metadata() string {
|
||||||
return v.metadata
|
return v.metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
// originalVPrefix returns the original 'v' prefix if any.
|
// originalVPrefix returns the original 'v' prefix if any.
|
||||||
func (v *Version) originalVPrefix() string {
|
func (v Version) originalVPrefix() string {
|
||||||
|
|
||||||
// Note, only lowercase v is supported as a prefix by the parser.
|
// Note, only lowercase v is supported as a prefix by the parser.
|
||||||
if v.original != "" && v.original[:1] == "v" {
|
if v.original != "" && v.original[:1] == "v" {
|
||||||
@ -165,7 +279,7 @@ func (v *Version) originalVPrefix() string {
|
|||||||
// If the current version does not have prerelease/metadata information,
|
// If the current version does not have prerelease/metadata information,
|
||||||
// it unsets metadata and prerelease values, increments patch number.
|
// it unsets metadata and prerelease values, increments patch number.
|
||||||
// If the current version has any of prerelease or metadata information,
|
// If the current version has any of prerelease or metadata information,
|
||||||
// it unsets both values and keeps curent patch value
|
// it unsets both values and keeps current patch value
|
||||||
func (v Version) IncPatch() Version {
|
func (v Version) IncPatch() Version {
|
||||||
vNext := v
|
vNext := v
|
||||||
// according to http://semver.org/#spec-item-9
|
// according to http://semver.org/#spec-item-9
|
||||||
@ -217,11 +331,13 @@ func (v Version) IncMajor() Version {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetPrerelease defines the prerelease value.
|
// SetPrerelease defines the prerelease value.
|
||||||
// Value must not include the required 'hypen' prefix.
|
// Value must not include the required 'hyphen' prefix.
|
||||||
func (v Version) SetPrerelease(prerelease string) (Version, error) {
|
func (v Version) SetPrerelease(prerelease string) (Version, error) {
|
||||||
vNext := v
|
vNext := v
|
||||||
if len(prerelease) > 0 && !validPrereleaseRegex.MatchString(prerelease) {
|
if len(prerelease) > 0 {
|
||||||
return vNext, ErrInvalidPrerelease
|
if err := validatePrerelease(prerelease); err != nil {
|
||||||
|
return vNext, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vNext.pre = prerelease
|
vNext.pre = prerelease
|
||||||
vNext.original = v.originalVPrefix() + "" + vNext.String()
|
vNext.original = v.originalVPrefix() + "" + vNext.String()
|
||||||
@ -232,8 +348,10 @@ func (v Version) SetPrerelease(prerelease string) (Version, error) {
|
|||||||
// Value must not include the required 'plus' prefix.
|
// Value must not include the required 'plus' prefix.
|
||||||
func (v Version) SetMetadata(metadata string) (Version, error) {
|
func (v Version) SetMetadata(metadata string) (Version, error) {
|
||||||
vNext := v
|
vNext := v
|
||||||
if len(metadata) > 0 && !validPrereleaseRegex.MatchString(metadata) {
|
if len(metadata) > 0 {
|
||||||
return vNext, ErrInvalidMetadata
|
if err := validateMetadata(metadata); err != nil {
|
||||||
|
return vNext, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vNext.metadata = metadata
|
vNext.metadata = metadata
|
||||||
vNext.original = v.originalVPrefix() + "" + vNext.String()
|
vNext.original = v.originalVPrefix() + "" + vNext.String()
|
||||||
@ -261,7 +379,9 @@ func (v *Version) Equal(o *Version) bool {
|
|||||||
// the version smaller, equal, or larger than the other version.
|
// the version smaller, equal, or larger than the other version.
|
||||||
//
|
//
|
||||||
// Versions are compared by X.Y.Z. Build metadata is ignored. Prerelease is
|
// Versions are compared by X.Y.Z. Build metadata is ignored. Prerelease is
|
||||||
// lower than the version without a prerelease.
|
// lower than the version without a prerelease. Compare always takes into account
|
||||||
|
// prereleases. If you want to work with ranges using typical range syntaxes that
|
||||||
|
// skip prereleases if the range is not looking for them use constraints.
|
||||||
func (v *Version) Compare(o *Version) int {
|
func (v *Version) Compare(o *Version) int {
|
||||||
// Compare the major, minor, and patch version for differences. If a
|
// Compare the major, minor, and patch version for differences. If a
|
||||||
// difference is found return the comparison.
|
// difference is found return the comparison.
|
||||||
@ -308,16 +428,37 @@ func (v *Version) UnmarshalJSON(b []byte) error {
|
|||||||
v.pre = temp.pre
|
v.pre = temp.pre
|
||||||
v.metadata = temp.metadata
|
v.metadata = temp.metadata
|
||||||
v.original = temp.original
|
v.original = temp.original
|
||||||
temp = nil
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements JSON.Marshaler interface.
|
// MarshalJSON implements JSON.Marshaler interface.
|
||||||
func (v *Version) MarshalJSON() ([]byte, error) {
|
func (v Version) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(v.String())
|
return json.Marshal(v.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func compareSegment(v, o int64) int {
|
// Scan implements the SQL.Scanner interface.
|
||||||
|
func (v *Version) Scan(value interface{}) error {
|
||||||
|
var s string
|
||||||
|
s, _ = value.(string)
|
||||||
|
temp, err := NewVersion(s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.major = temp.major
|
||||||
|
v.minor = temp.minor
|
||||||
|
v.patch = temp.patch
|
||||||
|
v.pre = temp.pre
|
||||||
|
v.metadata = temp.metadata
|
||||||
|
v.original = temp.original
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value implements the Driver.Valuer interface.
|
||||||
|
func (v Version) Value() (driver.Value, error) {
|
||||||
|
return v.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func compareSegment(v, o uint64) int {
|
||||||
if v < o {
|
if v < o {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
@ -423,3 +564,43 @@ func comparePrePart(s, o string) int {
|
|||||||
return -1
|
return -1
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Like strings.ContainsAny but does an only instead of any.
|
||||||
|
func containsOnly(s string, comp string) bool {
|
||||||
|
return strings.IndexFunc(s, func(r rune) bool {
|
||||||
|
return !strings.ContainsRune(comp, r)
|
||||||
|
}) == -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// From the spec, "Identifiers MUST comprise only
|
||||||
|
// ASCII alphanumerics and hyphen [0-9A-Za-z-]. Identifiers MUST NOT be empty.
|
||||||
|
// Numeric identifiers MUST NOT include leading zeroes.". These segments can
|
||||||
|
// be dot separated.
|
||||||
|
func validatePrerelease(p string) error {
|
||||||
|
eparts := strings.Split(p, ".")
|
||||||
|
for _, p := range eparts {
|
||||||
|
if containsOnly(p, num) {
|
||||||
|
if len(p) > 1 && p[0] == '0' {
|
||||||
|
return ErrSegmentStartsZero
|
||||||
|
}
|
||||||
|
} else if !containsOnly(p, allowed) {
|
||||||
|
return ErrInvalidPrerelease
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// From the spec, "Build metadata MAY be denoted by
|
||||||
|
// appending a plus sign and a series of dot separated identifiers immediately
|
||||||
|
// following the patch or pre-release version. Identifiers MUST comprise only
|
||||||
|
// ASCII alphanumerics and hyphen [0-9A-Za-z-]. Identifiers MUST NOT be empty."
|
||||||
|
func validateMetadata(m string) error {
|
||||||
|
eparts := strings.Split(m, ".")
|
||||||
|
for _, p := range eparts {
|
||||||
|
if !containsOnly(p, allowed) {
|
||||||
|
return ErrInvalidMetadata
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
10
vendor/github.com/Masterminds/semver/version_fuzz.go
generated
vendored
10
vendor/github.com/Masterminds/semver/version_fuzz.go
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
// +build gofuzz
|
|
||||||
|
|
||||||
package semver
|
|
||||||
|
|
||||||
func Fuzz(data []byte) int {
|
|
||||||
if _, err := NewVersion(string(data)); err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return 1
|
|
||||||
}
|
|
26
vendor/github.com/Masterminds/sprig/.travis.yml
generated
vendored
26
vendor/github.com/Masterminds/sprig/.travis.yml
generated
vendored
@ -1,26 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.9.x
|
|
||||||
- 1.10.x
|
|
||||||
- 1.11.x
|
|
||||||
- 1.12.x
|
|
||||||
- 1.13.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 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
|
|
13
vendor/github.com/Masterminds/sprig/Makefile
generated
vendored
13
vendor/github.com/Masterminds/sprig/Makefile
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
|
|
||||||
HAS_GLIDE := $(shell command -v glide;)
|
|
||||||
|
|
||||||
.PHONY: test
|
|
||||||
test:
|
|
||||||
go test -v .
|
|
||||||
|
|
||||||
.PHONY: setup
|
|
||||||
setup:
|
|
||||||
ifndef HAS_GLIDE
|
|
||||||
go get -u github.com/Masterminds/glide
|
|
||||||
endif
|
|
||||||
glide install
|
|
26
vendor/github.com/Masterminds/sprig/appveyor.yml
generated
vendored
26
vendor/github.com/Masterminds/sprig/appveyor.yml
generated
vendored
@ -1,26 +0,0 @@
|
|||||||
|
|
||||||
version: build-{build}.{branch}
|
|
||||||
|
|
||||||
clone_folder: C:\gopath\src\github.com\Masterminds\sprig
|
|
||||||
shallow_clone: true
|
|
||||||
|
|
||||||
environment:
|
|
||||||
GOPATH: C:\gopath
|
|
||||||
|
|
||||||
platform:
|
|
||||||
- x64
|
|
||||||
|
|
||||||
install:
|
|
||||||
- go get -u github.com/Masterminds/glide
|
|
||||||
- set PATH=%GOPATH%\bin;%PATH%
|
|
||||||
- go version
|
|
||||||
- go env
|
|
||||||
|
|
||||||
build_script:
|
|
||||||
- glide install
|
|
||||||
- go install ./...
|
|
||||||
|
|
||||||
test_script:
|
|
||||||
- go test -v
|
|
||||||
|
|
||||||
deploy: off
|
|
19
vendor/github.com/Masterminds/sprig/glide.yaml
generated
vendored
19
vendor/github.com/Masterminds/sprig/glide.yaml
generated
vendored
@ -1,19 +0,0 @@
|
|||||||
package: github.com/Masterminds/sprig
|
|
||||||
import:
|
|
||||||
- package: github.com/Masterminds/goutils
|
|
||||||
version: ^1.0.0
|
|
||||||
- package: github.com/google/uuid
|
|
||||||
version: ^1.0.0
|
|
||||||
- package: golang.org/x/crypto
|
|
||||||
subpackages:
|
|
||||||
- scrypt
|
|
||||||
- package: github.com/Masterminds/semver
|
|
||||||
version: ^v1.2.2
|
|
||||||
- package: github.com/stretchr/testify
|
|
||||||
version: ^v1.2.2
|
|
||||||
- package: github.com/imdario/mergo
|
|
||||||
version: ~0.3.7
|
|
||||||
- package: github.com/huandu/xstrings
|
|
||||||
version: ^1.2
|
|
||||||
- package: github.com/mitchellh/copystructure
|
|
||||||
version: ^1.0.0
|
|
169
vendor/github.com/Masterminds/sprig/numeric.go
generated
vendored
169
vendor/github.com/Masterminds/sprig/numeric.go
generated
vendored
@ -1,169 +0,0 @@
|
|||||||
package sprig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// toFloat64 converts 64-bit floats
|
|
||||||
func toFloat64(v interface{}) float64 {
|
|
||||||
if str, ok := v.(string); ok {
|
|
||||||
iv, err := strconv.ParseFloat(str, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return iv
|
|
||||||
}
|
|
||||||
|
|
||||||
val := reflect.Indirect(reflect.ValueOf(v))
|
|
||||||
switch val.Kind() {
|
|
||||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
|
||||||
return float64(val.Int())
|
|
||||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32:
|
|
||||||
return float64(val.Uint())
|
|
||||||
case reflect.Uint, reflect.Uint64:
|
|
||||||
return float64(val.Uint())
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return val.Float()
|
|
||||||
case reflect.Bool:
|
|
||||||
if val.Bool() == true {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
default:
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func toInt(v interface{}) int {
|
|
||||||
//It's not optimal. Bud I don't want duplicate toInt64 code.
|
|
||||||
return int(toInt64(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// toInt64 converts integer types to 64-bit integers
|
|
||||||
func toInt64(v interface{}) int64 {
|
|
||||||
if str, ok := v.(string); ok {
|
|
||||||
iv, err := strconv.ParseInt(str, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return iv
|
|
||||||
}
|
|
||||||
|
|
||||||
val := reflect.Indirect(reflect.ValueOf(v))
|
|
||||||
switch val.Kind() {
|
|
||||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
|
||||||
return val.Int()
|
|
||||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32:
|
|
||||||
return int64(val.Uint())
|
|
||||||
case reflect.Uint, reflect.Uint64:
|
|
||||||
tv := val.Uint()
|
|
||||||
if tv <= math.MaxInt64 {
|
|
||||||
return int64(tv)
|
|
||||||
}
|
|
||||||
// TODO: What is the sensible thing to do here?
|
|
||||||
return math.MaxInt64
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return int64(val.Float())
|
|
||||||
case reflect.Bool:
|
|
||||||
if val.Bool() == true {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
default:
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func max(a interface{}, i ...interface{}) int64 {
|
|
||||||
aa := toInt64(a)
|
|
||||||
for _, b := range i {
|
|
||||||
bb := toInt64(b)
|
|
||||||
if bb > aa {
|
|
||||||
aa = bb
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return aa
|
|
||||||
}
|
|
||||||
|
|
||||||
func min(a interface{}, i ...interface{}) int64 {
|
|
||||||
aa := toInt64(a)
|
|
||||||
for _, b := range i {
|
|
||||||
bb := toInt64(b)
|
|
||||||
if bb < aa {
|
|
||||||
aa = bb
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return aa
|
|
||||||
}
|
|
||||||
|
|
||||||
func until(count int) []int {
|
|
||||||
step := 1
|
|
||||||
if count < 0 {
|
|
||||||
step = -1
|
|
||||||
}
|
|
||||||
return untilStep(0, count, step)
|
|
||||||
}
|
|
||||||
|
|
||||||
func untilStep(start, stop, step int) []int {
|
|
||||||
v := []int{}
|
|
||||||
|
|
||||||
if stop < start {
|
|
||||||
if step >= 0 {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
for i := start; i > stop; i += step {
|
|
||||||
v = append(v, i)
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
if step <= 0 {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
for i := start; i < stop; i += step {
|
|
||||||
v = append(v, i)
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func floor(a interface{}) float64 {
|
|
||||||
aa := toFloat64(a)
|
|
||||||
return math.Floor(aa)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ceil(a interface{}) float64 {
|
|
||||||
aa := toFloat64(a)
|
|
||||||
return math.Ceil(aa)
|
|
||||||
}
|
|
||||||
|
|
||||||
func round(a interface{}, p int, r_opt ...float64) float64 {
|
|
||||||
roundOn := .5
|
|
||||||
if len(r_opt) > 0 {
|
|
||||||
roundOn = r_opt[0]
|
|
||||||
}
|
|
||||||
val := toFloat64(a)
|
|
||||||
places := toFloat64(p)
|
|
||||||
|
|
||||||
var round float64
|
|
||||||
pow := math.Pow(10, places)
|
|
||||||
digit := pow * val
|
|
||||||
_, div := math.Modf(digit)
|
|
||||||
if div >= roundOn {
|
|
||||||
round = math.Ceil(digit)
|
|
||||||
} else {
|
|
||||||
round = math.Floor(digit)
|
|
||||||
}
|
|
||||||
return round / pow
|
|
||||||
}
|
|
||||||
|
|
||||||
// converts unix octal to decimal
|
|
||||||
func toDecimal(v interface{}) int64 {
|
|
||||||
result, err := strconv.ParseInt(fmt.Sprint(v), 8, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
35
vendor/github.com/Masterminds/sprig/regex.go
generated
vendored
35
vendor/github.com/Masterminds/sprig/regex.go
generated
vendored
@ -1,35 +0,0 @@
|
|||||||
package sprig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
)
|
|
||||||
|
|
||||||
func regexMatch(regex string, s string) bool {
|
|
||||||
match, _ := regexp.MatchString(regex, s)
|
|
||||||
return match
|
|
||||||
}
|
|
||||||
|
|
||||||
func regexFindAll(regex string, s string, n int) []string {
|
|
||||||
r := regexp.MustCompile(regex)
|
|
||||||
return r.FindAllString(s, n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func regexFind(regex string, s string) string {
|
|
||||||
r := regexp.MustCompile(regex)
|
|
||||||
return r.FindString(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func regexReplaceAll(regex string, s string, repl string) string {
|
|
||||||
r := regexp.MustCompile(regex)
|
|
||||||
return r.ReplaceAllString(s, repl)
|
|
||||||
}
|
|
||||||
|
|
||||||
func regexReplaceAllLiteral(regex string, s string, repl string) string {
|
|
||||||
r := regexp.MustCompile(regex)
|
|
||||||
return r.ReplaceAllLiteralString(s, repl)
|
|
||||||
}
|
|
||||||
|
|
||||||
func regexSplit(regex string, s string, n int) []string {
|
|
||||||
r := regexp.MustCompile(regex)
|
|
||||||
return r.Split(s, n)
|
|
||||||
}
|
|
@ -1,5 +1,93 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Release 3.2.1 (2021-02-04)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Upgraded `Masterminds/goutils` to `v1.1.1`. see the [Security Advisory](https://github.com/Masterminds/goutils/security/advisories/GHSA-xg2h-wx96-xgxr)
|
||||||
|
|
||||||
|
## Release 3.2.0 (2020-12-14)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- #211: Added randInt function (thanks @kochurovro)
|
||||||
|
- #223: Added fromJson and mustFromJson functions (thanks @mholt)
|
||||||
|
- #242: Added a bcrypt function (thanks @robbiet480)
|
||||||
|
- #253: Added randBytes function (thanks @MikaelSmith)
|
||||||
|
- #254: Added dig function for dicts (thanks @nyarly)
|
||||||
|
- #257: Added regexQuoteMeta for quoting regex metadata (thanks @rheaton)
|
||||||
|
- #261: Added filepath functions osBase, osDir, osExt, osClean, osIsAbs (thanks @zugl)
|
||||||
|
- #268: Added and and all functions for testing conditions (thanks @phuslu)
|
||||||
|
- #181: Added float64 arithmetic addf, add1f, subf, divf, mulf, maxf, and minf
|
||||||
|
(thanks @andrewmostello)
|
||||||
|
- #265: Added chunk function to split array into smaller arrays (thanks @karelbilek)
|
||||||
|
- #270: Extend certificate functions to handle non-RSA keys + add support for
|
||||||
|
ed25519 keys (thanks @misberner)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Removed testing and support for Go 1.12. ed25519 support requires Go 1.13 or newer
|
||||||
|
- Using semver 3.1.1 and mergo 0.3.11
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- #249: Fix htmlDateInZone example (thanks @spawnia)
|
||||||
|
|
||||||
|
NOTE: The dependency github.com/imdario/mergo reverted the breaking change in
|
||||||
|
0.3.9 via 0.3.10 release.
|
||||||
|
|
||||||
|
## Release 3.1.0 (2020-04-16)
|
||||||
|
|
||||||
|
NOTE: The dependency github.com/imdario/mergo made a behavior change in 0.3.9
|
||||||
|
that impacts sprig functionality. Do not use sprig with a version newer than 0.3.8.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- #225: Added support for generating htpasswd hash (thanks @rustycl0ck)
|
||||||
|
- #224: Added duration filter (thanks @frebib)
|
||||||
|
- #205: Added `seq` function (thanks @thadc23)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- #203: Unlambda functions with correct signature (thanks @muesli)
|
||||||
|
- #236: Updated the license formatting for GitHub display purposes
|
||||||
|
- #238: Updated package dependency versions. Note, mergo not updated to 0.3.9
|
||||||
|
as it causes a breaking change for sprig. That issue is tracked at
|
||||||
|
https://github.com/imdario/mergo/issues/139
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- #229: Fix `seq` example in docs (thanks @kalmant)
|
||||||
|
|
||||||
|
## Release 3.0.2 (2019-12-13)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- #220: Updating to semver v3.0.3 to fix issue with <= ranges
|
||||||
|
- #218: fix typo elyptical->elliptic in ecdsa key description (thanks @laverya)
|
||||||
|
|
||||||
|
## Release 3.0.1 (2019-12-08)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- #212: Updated semver fixing broken constraint checking with ^0.0
|
||||||
|
|
||||||
|
## Release 3.0.0 (2019-10-02)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- #187: Added durationRound function (thanks @yjp20)
|
||||||
|
- #189: Added numerous template functions that return errors rather than panic (thanks @nrvnrvn)
|
||||||
|
- #193: Added toRawJson support (thanks @Dean-Coakley)
|
||||||
|
- #197: Added get support to dicts (thanks @Dean-Coakley)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- #186: Moving dependency management to Go modules
|
||||||
|
- #186: Updated semver to v3. This has changes in the way ^ is handled
|
||||||
|
- #194: Updated documentation on merging and how it copies. Added example using deepCopy
|
||||||
|
- #196: trunc now supports negative values (thanks @Dean-Coakley)
|
||||||
|
|
||||||
## Release 2.22.0 (2019-10-02)
|
## Release 2.22.0 (2019-10-02)
|
||||||
|
|
||||||
### Added
|
### Added
|
@ -1,5 +1,4 @@
|
|||||||
Sprig
|
Copyright (C) 2013-2020 Masterminds
|
||||||
Copyright (C) 2013 Masterminds
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
9
vendor/github.com/Masterminds/sprig/v3/Makefile
generated
vendored
Normal file
9
vendor/github.com/Masterminds/sprig/v3/Makefile
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
@echo "==> Running tests"
|
||||||
|
GO111MODULE=on go test -v
|
||||||
|
|
||||||
|
.PHONY: test-cover
|
||||||
|
test-cover:
|
||||||
|
@echo "==> Running Tests with coverage"
|
||||||
|
GO111MODULE=on go test -cover .
|
@ -1,6 +1,9 @@
|
|||||||
# Sprig: Template functions for Go templates
|
# Sprig: Template functions for Go templates
|
||||||
|
|
||||||
|
[![GoDoc](https://img.shields.io/static/v1?label=godoc&message=reference&color=blue)](https://pkg.go.dev/github.com/Masterminds/sprig/v3)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/sprig)](https://goreportcard.com/report/github.com/Masterminds/sprig)
|
||||||
[![Stability: Sustained](https://masterminds.github.io/stability/sustained.svg)](https://masterminds.github.io/stability/sustained.html)
|
[![Stability: Sustained](https://masterminds.github.io/stability/sustained.svg)](https://masterminds.github.io/stability/sustained.html)
|
||||||
[![Build Status](https://travis-ci.org/Masterminds/sprig.svg?branch=master)](https://travis-ci.org/Masterminds/sprig)
|
[![](https://github.com/Masterminds/sprig/workflows/Tests/badge.svg)](https://github.com/Masterminds/sprig/actions)
|
||||||
|
|
||||||
The Go language comes with a [built-in template
|
The Go language comes with a [built-in template
|
||||||
language](http://golang.org/pkg/text/template/), but not
|
language](http://golang.org/pkg/text/template/), but not
|
||||||
@ -11,6 +14,26 @@ It is inspired by the template functions found in
|
|||||||
[Twig](http://twig.sensiolabs.org/documentation) and in various
|
[Twig](http://twig.sensiolabs.org/documentation) and in various
|
||||||
JavaScript libraries, such as [underscore.js](http://underscorejs.org/).
|
JavaScript libraries, such as [underscore.js](http://underscorejs.org/).
|
||||||
|
|
||||||
|
## IMPORTANT NOTES
|
||||||
|
|
||||||
|
Sprig leverages [mergo](https://github.com/imdario/mergo) to handle merges. In
|
||||||
|
its v0.3.9 release there was a behavior change that impacts merging template
|
||||||
|
functions in sprig. It is currently recommended to use v0.3.8 of that package.
|
||||||
|
Using v0.3.9 will cause sprig tests to fail. The issue in mergo is tracked at
|
||||||
|
https://github.com/imdario/mergo/issues/139.
|
||||||
|
|
||||||
|
## Package Versions
|
||||||
|
|
||||||
|
There are two active major versions of the `sprig` package.
|
||||||
|
|
||||||
|
* v3 is currently stable release series on the `master` branch. The Go API should
|
||||||
|
remain compatible with v2, the current stable version. Behavior change behind
|
||||||
|
some functions is the reason for the new major version.
|
||||||
|
* v2 is the previous stable release series. It has been more than three years since
|
||||||
|
the initial release of v2. You can read the documentation and see the code
|
||||||
|
on the [release-2](https://github.com/Masterminds/sprig/tree/release-2) branch.
|
||||||
|
Bug fixes to this major version will continue for some time.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
**Template developers**: Please use Sprig's [function documentation](http://masterminds.github.io/sprig/) for
|
**Template developers**: Please use Sprig's [function documentation](http://masterminds.github.io/sprig/) for
|
@ -2,10 +2,12 @@ package sprig
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto"
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/dsa"
|
"crypto/dsa"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
"crypto/ed25519"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
@ -21,13 +23,16 @@ import (
|
|||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"hash/adler32"
|
"hash/adler32"
|
||||||
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
bcrypt_lib "golang.org/x/crypto/bcrypt"
|
||||||
"golang.org/x/crypto/scrypt"
|
"golang.org/x/crypto/scrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -46,14 +51,38 @@ func adler32sum(input string) string {
|
|||||||
return fmt.Sprintf("%d", hash)
|
return fmt.Sprintf("%d", hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// uuidv4 provides a safe and secure UUID v4 implementation
|
func bcrypt(input string) string {
|
||||||
func uuidv4() string {
|
hash, err := bcrypt_lib.GenerateFromPassword([]byte(input), bcrypt_lib.DefaultCost)
|
||||||
return fmt.Sprintf("%s", uuid.New())
|
if err != nil {
|
||||||
|
return fmt.Sprintf("failed to encrypt string with bcrypt: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
var master_password_seed = "com.lyndir.masterpassword"
|
func htpasswd(username string, password string) string {
|
||||||
|
if strings.Contains(username, ":") {
|
||||||
|
return fmt.Sprintf("invalid username: %s", username)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s:%s", username, bcrypt(password))
|
||||||
|
}
|
||||||
|
|
||||||
var password_type_templates = map[string][][]byte{
|
func randBytes(count int) (string, error) {
|
||||||
|
buf := make([]byte, count)
|
||||||
|
if _, err := rand.Read(buf); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return base64.StdEncoding.EncodeToString(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// uuidv4 provides a safe and secure UUID v4 implementation
|
||||||
|
func uuidv4() string {
|
||||||
|
return uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
var masterPasswordSeed = "com.lyndir.masterpassword"
|
||||||
|
|
||||||
|
var passwordTypeTemplates = map[string][][]byte{
|
||||||
"maximum": {[]byte("anoxxxxxxxxxxxxxxxxx"), []byte("axxxxxxxxxxxxxxxxxno")},
|
"maximum": {[]byte("anoxxxxxxxxxxxxxxxxx"), []byte("axxxxxxxxxxxxxxxxxno")},
|
||||||
"long": {[]byte("CvcvnoCvcvCvcv"), []byte("CvcvCvcvnoCvcv"), []byte("CvcvCvcvCvcvno"), []byte("CvccnoCvcvCvcv"), []byte("CvccCvcvnoCvcv"),
|
"long": {[]byte("CvcvnoCvcvCvcv"), []byte("CvcvCvcvnoCvcv"), []byte("CvcvCvcvCvcvno"), []byte("CvccnoCvcvCvcv"), []byte("CvccCvcvnoCvcv"),
|
||||||
[]byte("CvccCvcvCvcvno"), []byte("CvcvnoCvccCvcv"), []byte("CvcvCvccnoCvcv"), []byte("CvcvCvccCvcvno"), []byte("CvcvnoCvcvCvcc"),
|
[]byte("CvccCvcvCvcvno"), []byte("CvcvnoCvccCvcv"), []byte("CvcvCvccnoCvcv"), []byte("CvcvCvccCvcvno"), []byte("CvcvnoCvcvCvcc"),
|
||||||
@ -66,7 +95,7 @@ var password_type_templates = map[string][][]byte{
|
|||||||
"pin": {[]byte("nnnn")},
|
"pin": {[]byte("nnnn")},
|
||||||
}
|
}
|
||||||
|
|
||||||
var template_characters = map[byte]string{
|
var templateCharacters = map[byte]string{
|
||||||
'V': "AEIOU",
|
'V': "AEIOU",
|
||||||
'C': "BCDFGHJKLMNPQRSTVWXYZ",
|
'C': "BCDFGHJKLMNPQRSTVWXYZ",
|
||||||
'v': "aeiou",
|
'v': "aeiou",
|
||||||
@ -78,14 +107,14 @@ var template_characters = map[byte]string{
|
|||||||
'x': "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()",
|
'x': "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()",
|
||||||
}
|
}
|
||||||
|
|
||||||
func derivePassword(counter uint32, password_type, password, user, site string) string {
|
func derivePassword(counter uint32, passwordType, password, user, site string) string {
|
||||||
var templates = password_type_templates[password_type]
|
var templates = passwordTypeTemplates[passwordType]
|
||||||
if templates == nil {
|
if templates == nil {
|
||||||
return fmt.Sprintf("cannot find password template %s", password_type)
|
return fmt.Sprintf("cannot find password template %s", passwordType)
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
buffer.WriteString(master_password_seed)
|
buffer.WriteString(masterPasswordSeed)
|
||||||
binary.Write(&buffer, binary.BigEndian, uint32(len(user)))
|
binary.Write(&buffer, binary.BigEndian, uint32(len(user)))
|
||||||
buffer.WriteString(user)
|
buffer.WriteString(user)
|
||||||
|
|
||||||
@ -95,7 +124,7 @@ func derivePassword(counter uint32, password_type, password, user, site string)
|
|||||||
return fmt.Sprintf("failed to derive password: %s", err)
|
return fmt.Sprintf("failed to derive password: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.Truncate(len(master_password_seed))
|
buffer.Truncate(len(masterPasswordSeed))
|
||||||
binary.Write(&buffer, binary.BigEndian, uint32(len(site)))
|
binary.Write(&buffer, binary.BigEndian, uint32(len(site)))
|
||||||
buffer.WriteString(site)
|
buffer.WriteString(site)
|
||||||
binary.Write(&buffer, binary.BigEndian, counter)
|
binary.Write(&buffer, binary.BigEndian, counter)
|
||||||
@ -107,9 +136,9 @@ func derivePassword(counter uint32, password_type, password, user, site string)
|
|||||||
|
|
||||||
buffer.Truncate(0)
|
buffer.Truncate(0)
|
||||||
for i, element := range temp {
|
for i, element := range temp {
|
||||||
pass_chars := template_characters[element]
|
passChars := templateCharacters[element]
|
||||||
pass_char := pass_chars[int(seed[i+1])%len(pass_chars)]
|
passChar := passChars[int(seed[i+1])%len(passChars)]
|
||||||
buffer.WriteByte(pass_char)
|
buffer.WriteByte(passChar)
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
@ -133,6 +162,8 @@ func generatePrivateKey(typ string) string {
|
|||||||
case "ecdsa":
|
case "ecdsa":
|
||||||
// again, good enough for government work
|
// again, good enough for government work
|
||||||
priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
case "ed25519":
|
||||||
|
_, priv, err = ed25519.GenerateKey(rand.Reader)
|
||||||
default:
|
default:
|
||||||
return "Unknown type " + typ
|
return "Unknown type " + typ
|
||||||
}
|
}
|
||||||
@ -143,6 +174,8 @@ func generatePrivateKey(typ string) string {
|
|||||||
return string(pem.EncodeToMemory(pemBlockForKey(priv)))
|
return string(pem.EncodeToMemory(pemBlockForKey(priv)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DSAKeyFormat stores the format for DSA keys.
|
||||||
|
// Used by pemBlockForKey
|
||||||
type DSAKeyFormat struct {
|
type DSAKeyFormat struct {
|
||||||
Version int
|
Version int
|
||||||
P, Q, G, Y, X *big.Int
|
P, Q, G, Y, X *big.Int
|
||||||
@ -163,7 +196,73 @@ func pemBlockForKey(priv interface{}) *pem.Block {
|
|||||||
b, _ := x509.MarshalECPrivateKey(k)
|
b, _ := x509.MarshalECPrivateKey(k)
|
||||||
return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
|
return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
|
||||||
default:
|
default:
|
||||||
return nil
|
// attempt PKCS#8 format for all other keys
|
||||||
|
b, err := x509.MarshalPKCS8PrivateKey(k)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &pem.Block{Type: "PRIVATE KEY", Bytes: b}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parsePrivateKeyPEM(pemBlock string) (crypto.PrivateKey, error) {
|
||||||
|
block, _ := pem.Decode([]byte(pemBlock))
|
||||||
|
if block == nil {
|
||||||
|
return nil, errors.New("no PEM data in input")
|
||||||
|
}
|
||||||
|
|
||||||
|
if block.Type == "PRIVATE KEY" {
|
||||||
|
priv, err := x509.ParsePKCS8PrivateKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("decoding PEM as PKCS#8: %s", err)
|
||||||
|
}
|
||||||
|
return priv, nil
|
||||||
|
} else if !strings.HasSuffix(block.Type, " PRIVATE KEY") {
|
||||||
|
return nil, fmt.Errorf("no private key data in PEM block of type %s", block.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch block.Type[:len(block.Type)-12] { // strip " PRIVATE KEY"
|
||||||
|
case "RSA":
|
||||||
|
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parsing RSA private key from PEM: %s", err)
|
||||||
|
}
|
||||||
|
return priv, nil
|
||||||
|
case "EC":
|
||||||
|
priv, err := x509.ParseECPrivateKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parsing EC private key from PEM: %s", err)
|
||||||
|
}
|
||||||
|
return priv, nil
|
||||||
|
case "DSA":
|
||||||
|
var k DSAKeyFormat
|
||||||
|
_, err := asn1.Unmarshal(block.Bytes, &k)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parsing DSA private key from PEM: %s", err)
|
||||||
|
}
|
||||||
|
priv := &dsa.PrivateKey{
|
||||||
|
PublicKey: dsa.PublicKey{
|
||||||
|
Parameters: dsa.Parameters{
|
||||||
|
P: k.P, Q: k.Q, G: k.G,
|
||||||
|
},
|
||||||
|
Y: k.Y,
|
||||||
|
},
|
||||||
|
X: k.X,
|
||||||
|
}
|
||||||
|
return priv, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid private key type %s", block.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPublicKey(priv crypto.PrivateKey) (crypto.PublicKey, error) {
|
||||||
|
switch k := priv.(type) {
|
||||||
|
case interface{ Public() crypto.PublicKey }:
|
||||||
|
return k.Public(), nil
|
||||||
|
case *dsa.PrivateKey:
|
||||||
|
return &k.PublicKey, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unable to get public key for type %T", priv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,14 +296,10 @@ func buildCustomCertificate(b64cert string, b64key string) (certificate, error)
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
decodedKey, _ := pem.Decode(key)
|
_, err = parsePrivateKeyPEM(string(key))
|
||||||
if decodedKey == nil {
|
|
||||||
return crt, errors.New("unable to decode key")
|
|
||||||
}
|
|
||||||
_, err = x509.ParsePKCS1PrivateKey(decodedKey.Bytes)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return crt, fmt.Errorf(
|
return crt, fmt.Errorf(
|
||||||
"error parsing prive key: decodedKey.Bytes: %s",
|
"error parsing private key: %s",
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -218,6 +313,31 @@ func buildCustomCertificate(b64cert string, b64key string) (certificate, error)
|
|||||||
func generateCertificateAuthority(
|
func generateCertificateAuthority(
|
||||||
cn string,
|
cn string,
|
||||||
daysValid int,
|
daysValid int,
|
||||||
|
) (certificate, error) {
|
||||||
|
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
|
if err != nil {
|
||||||
|
return certificate{}, fmt.Errorf("error generating rsa key: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return generateCertificateAuthorityWithKeyInternal(cn, daysValid, priv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateCertificateAuthorityWithPEMKey(
|
||||||
|
cn string,
|
||||||
|
daysValid int,
|
||||||
|
privPEM string,
|
||||||
|
) (certificate, error) {
|
||||||
|
priv, err := parsePrivateKeyPEM(privPEM)
|
||||||
|
if err != nil {
|
||||||
|
return certificate{}, fmt.Errorf("parsing private key: %s", err)
|
||||||
|
}
|
||||||
|
return generateCertificateAuthorityWithKeyInternal(cn, daysValid, priv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateCertificateAuthorityWithKeyInternal(
|
||||||
|
cn string,
|
||||||
|
daysValid int,
|
||||||
|
priv crypto.PrivateKey,
|
||||||
) (certificate, error) {
|
) (certificate, error) {
|
||||||
ca := certificate{}
|
ca := certificate{}
|
||||||
|
|
||||||
@ -231,17 +351,9 @@ func generateCertificateAuthority(
|
|||||||
x509.KeyUsageCertSign
|
x509.KeyUsageCertSign
|
||||||
template.IsCA = true
|
template.IsCA = true
|
||||||
|
|
||||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
||||||
if err != nil {
|
|
||||||
return ca, fmt.Errorf("error generating rsa key: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ca.Cert, ca.Key, err = getCertAndKey(template, priv, template, priv)
|
ca.Cert, ca.Key, err = getCertAndKey(template, priv, template, priv)
|
||||||
if err != nil {
|
|
||||||
return ca, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ca, nil
|
return ca, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateSelfSignedCertificate(
|
func generateSelfSignedCertificate(
|
||||||
@ -249,6 +361,34 @@ func generateSelfSignedCertificate(
|
|||||||
ips []interface{},
|
ips []interface{},
|
||||||
alternateDNS []interface{},
|
alternateDNS []interface{},
|
||||||
daysValid int,
|
daysValid int,
|
||||||
|
) (certificate, error) {
|
||||||
|
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
|
if err != nil {
|
||||||
|
return certificate{}, fmt.Errorf("error generating rsa key: %s", err)
|
||||||
|
}
|
||||||
|
return generateSelfSignedCertificateWithKeyInternal(cn, ips, alternateDNS, daysValid, priv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateSelfSignedCertificateWithPEMKey(
|
||||||
|
cn string,
|
||||||
|
ips []interface{},
|
||||||
|
alternateDNS []interface{},
|
||||||
|
daysValid int,
|
||||||
|
privPEM string,
|
||||||
|
) (certificate, error) {
|
||||||
|
priv, err := parsePrivateKeyPEM(privPEM)
|
||||||
|
if err != nil {
|
||||||
|
return certificate{}, fmt.Errorf("parsing private key: %s", err)
|
||||||
|
}
|
||||||
|
return generateSelfSignedCertificateWithKeyInternal(cn, ips, alternateDNS, daysValid, priv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateSelfSignedCertificateWithKeyInternal(
|
||||||
|
cn string,
|
||||||
|
ips []interface{},
|
||||||
|
alternateDNS []interface{},
|
||||||
|
daysValid int,
|
||||||
|
priv crypto.PrivateKey,
|
||||||
) (certificate, error) {
|
) (certificate, error) {
|
||||||
cert := certificate{}
|
cert := certificate{}
|
||||||
|
|
||||||
@ -257,17 +397,9 @@ func generateSelfSignedCertificate(
|
|||||||
return cert, err
|
return cert, err
|
||||||
}
|
}
|
||||||
|
|
||||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
||||||
if err != nil {
|
|
||||||
return cert, fmt.Errorf("error generating rsa key: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cert.Cert, cert.Key, err = getCertAndKey(template, priv, template, priv)
|
cert.Cert, cert.Key, err = getCertAndKey(template, priv, template, priv)
|
||||||
if err != nil {
|
|
||||||
return cert, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return cert, nil
|
return cert, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateSignedCertificate(
|
func generateSignedCertificate(
|
||||||
@ -276,6 +408,36 @@ func generateSignedCertificate(
|
|||||||
alternateDNS []interface{},
|
alternateDNS []interface{},
|
||||||
daysValid int,
|
daysValid int,
|
||||||
ca certificate,
|
ca certificate,
|
||||||
|
) (certificate, error) {
|
||||||
|
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
|
if err != nil {
|
||||||
|
return certificate{}, fmt.Errorf("error generating rsa key: %s", err)
|
||||||
|
}
|
||||||
|
return generateSignedCertificateWithKeyInternal(cn, ips, alternateDNS, daysValid, ca, priv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateSignedCertificateWithPEMKey(
|
||||||
|
cn string,
|
||||||
|
ips []interface{},
|
||||||
|
alternateDNS []interface{},
|
||||||
|
daysValid int,
|
||||||
|
ca certificate,
|
||||||
|
privPEM string,
|
||||||
|
) (certificate, error) {
|
||||||
|
priv, err := parsePrivateKeyPEM(privPEM)
|
||||||
|
if err != nil {
|
||||||
|
return certificate{}, fmt.Errorf("parsing private key: %s", err)
|
||||||
|
}
|
||||||
|
return generateSignedCertificateWithKeyInternal(cn, ips, alternateDNS, daysValid, ca, priv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateSignedCertificateWithKeyInternal(
|
||||||
|
cn string,
|
||||||
|
ips []interface{},
|
||||||
|
alternateDNS []interface{},
|
||||||
|
daysValid int,
|
||||||
|
ca certificate,
|
||||||
|
priv crypto.PrivateKey,
|
||||||
) (certificate, error) {
|
) (certificate, error) {
|
||||||
cert := certificate{}
|
cert := certificate{}
|
||||||
|
|
||||||
@ -290,14 +452,10 @@ func generateSignedCertificate(
|
|||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
decodedSignerKey, _ := pem.Decode([]byte(ca.Key))
|
signerKey, err := parsePrivateKeyPEM(ca.Key)
|
||||||
if decodedSignerKey == nil {
|
|
||||||
return cert, errors.New("unable to decode key")
|
|
||||||
}
|
|
||||||
signerKey, err := x509.ParsePKCS1PrivateKey(decodedSignerKey.Bytes)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cert, fmt.Errorf(
|
return cert, fmt.Errorf(
|
||||||
"error parsing prive key: decodedSignerKey.Bytes: %s",
|
"error parsing private key: %s",
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -307,35 +465,31 @@ func generateSignedCertificate(
|
|||||||
return cert, err
|
return cert, err
|
||||||
}
|
}
|
||||||
|
|
||||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
||||||
if err != nil {
|
|
||||||
return cert, fmt.Errorf("error generating rsa key: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cert.Cert, cert.Key, err = getCertAndKey(
|
cert.Cert, cert.Key, err = getCertAndKey(
|
||||||
template,
|
template,
|
||||||
priv,
|
priv,
|
||||||
signerCert,
|
signerCert,
|
||||||
signerKey,
|
signerKey,
|
||||||
)
|
)
|
||||||
if err != nil {
|
|
||||||
return cert, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return cert, nil
|
return cert, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCertAndKey(
|
func getCertAndKey(
|
||||||
template *x509.Certificate,
|
template *x509.Certificate,
|
||||||
signeeKey *rsa.PrivateKey,
|
signeeKey crypto.PrivateKey,
|
||||||
parent *x509.Certificate,
|
parent *x509.Certificate,
|
||||||
signingKey *rsa.PrivateKey,
|
signingKey crypto.PrivateKey,
|
||||||
) (string, string, error) {
|
) (string, string, error) {
|
||||||
|
signeePubKey, err := getPublicKey(signeeKey)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", fmt.Errorf("error retrieving public key from signee key: %s", err)
|
||||||
|
}
|
||||||
derBytes, err := x509.CreateCertificate(
|
derBytes, err := x509.CreateCertificate(
|
||||||
rand.Reader,
|
rand.Reader,
|
||||||
template,
|
template,
|
||||||
parent,
|
parent,
|
||||||
&signeeKey.PublicKey,
|
signeePubKey,
|
||||||
signingKey,
|
signingKey,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -353,15 +507,12 @@ func getCertAndKey(
|
|||||||
keyBuffer := bytes.Buffer{}
|
keyBuffer := bytes.Buffer{}
|
||||||
if err := pem.Encode(
|
if err := pem.Encode(
|
||||||
&keyBuffer,
|
&keyBuffer,
|
||||||
&pem.Block{
|
pemBlockForKey(signeeKey),
|
||||||
Type: "RSA PRIVATE KEY",
|
|
||||||
Bytes: x509.MarshalPKCS1PrivateKey(signeeKey),
|
|
||||||
},
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return "", "", fmt.Errorf("error pem-encoding key: %s", err)
|
return "", "", fmt.Errorf("error pem-encoding key: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(certBuffer.Bytes()), string(keyBuffer.Bytes()), nil
|
return certBuffer.String(), keyBuffer.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBaseCertTemplate(
|
func getBaseCertTemplate(
|
@ -55,6 +55,14 @@ func dateModify(fmt string, date time.Time) time.Time {
|
|||||||
return date.Add(d)
|
return date.Add(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustDateModify(fmt string, date time.Time) (time.Time, error) {
|
||||||
|
d, err := time.ParseDuration(fmt)
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, err
|
||||||
|
}
|
||||||
|
return date.Add(d), nil
|
||||||
|
}
|
||||||
|
|
||||||
func dateAgo(date interface{}) string {
|
func dateAgo(date interface{}) string {
|
||||||
var t time.Time
|
var t time.Time
|
||||||
|
|
||||||
@ -73,11 +81,72 @@ func dateAgo(date interface{}) string {
|
|||||||
return duration.String()
|
return duration.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func duration(sec interface{}) string {
|
||||||
|
var n int64
|
||||||
|
switch value := sec.(type) {
|
||||||
|
default:
|
||||||
|
n = 0
|
||||||
|
case string:
|
||||||
|
n, _ = strconv.ParseInt(value, 10, 64)
|
||||||
|
case int64:
|
||||||
|
n = value
|
||||||
|
}
|
||||||
|
return (time.Duration(n) * time.Second).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func durationRound(duration interface{}) string {
|
||||||
|
var d time.Duration
|
||||||
|
switch duration := duration.(type) {
|
||||||
|
default:
|
||||||
|
d = 0
|
||||||
|
case string:
|
||||||
|
d, _ = time.ParseDuration(duration)
|
||||||
|
case int64:
|
||||||
|
d = time.Duration(duration)
|
||||||
|
case time.Time:
|
||||||
|
d = time.Since(duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
u := uint64(d)
|
||||||
|
neg := d < 0
|
||||||
|
if neg {
|
||||||
|
u = -u
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
year = uint64(time.Hour) * 24 * 365
|
||||||
|
month = uint64(time.Hour) * 24 * 30
|
||||||
|
day = uint64(time.Hour) * 24
|
||||||
|
hour = uint64(time.Hour)
|
||||||
|
minute = uint64(time.Minute)
|
||||||
|
second = uint64(time.Second)
|
||||||
|
)
|
||||||
|
switch {
|
||||||
|
case u > year:
|
||||||
|
return strconv.FormatUint(u/year, 10) + "y"
|
||||||
|
case u > month:
|
||||||
|
return strconv.FormatUint(u/month, 10) + "mo"
|
||||||
|
case u > day:
|
||||||
|
return strconv.FormatUint(u/day, 10) + "d"
|
||||||
|
case u > hour:
|
||||||
|
return strconv.FormatUint(u/hour, 10) + "h"
|
||||||
|
case u > minute:
|
||||||
|
return strconv.FormatUint(u/minute, 10) + "m"
|
||||||
|
case u > second:
|
||||||
|
return strconv.FormatUint(u/second, 10) + "s"
|
||||||
|
}
|
||||||
|
return "0s"
|
||||||
|
}
|
||||||
|
|
||||||
func toDate(fmt, str string) time.Time {
|
func toDate(fmt, str string) time.Time {
|
||||||
t, _ := time.ParseInLocation(fmt, str, time.Local)
|
t, _ := time.ParseInLocation(fmt, str, time.Local)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustToDate(fmt, str string) (time.Time, error) {
|
||||||
|
return time.ParseInLocation(fmt, str, time.Local)
|
||||||
|
}
|
||||||
|
|
||||||
func unixEpoch(date time.Time) string {
|
func unixEpoch(date time.Time) string {
|
||||||
return strconv.FormatInt(date.Unix(), 10)
|
return strconv.FormatInt(date.Unix(), 10)
|
||||||
}
|
}
|
@ -1,10 +1,18 @@
|
|||||||
package sprig
|
package sprig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
// dfault checks whether `given` is set, and returns default if not set.
|
// dfault checks whether `given` is set, and returns default if not set.
|
||||||
//
|
//
|
||||||
// This returns `d` if `given` appears not to be set, and `given` otherwise.
|
// This returns `d` if `given` appears not to be set, and `given` otherwise.
|
||||||
@ -37,7 +45,7 @@ func empty(given interface{}) bool {
|
|||||||
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
|
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
|
||||||
return g.Len() == 0
|
return g.Len() == 0
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
return g.Bool() == false
|
return !g.Bool()
|
||||||
case reflect.Complex64, reflect.Complex128:
|
case reflect.Complex64, reflect.Complex128:
|
||||||
return g.Complex() == 0
|
return g.Complex() == 0
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
@ -61,18 +69,90 @@ func coalesce(v ...interface{}) interface{} {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// all returns true if empty(x) is false for all values x in the list.
|
||||||
|
// If the list is empty, return true.
|
||||||
|
func all(v ...interface{}) bool {
|
||||||
|
for _, val := range v {
|
||||||
|
if empty(val) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// any returns true if empty(x) is false for any x in the list.
|
||||||
|
// If the list is empty, return false.
|
||||||
|
func any(v ...interface{}) bool {
|
||||||
|
for _, val := range v {
|
||||||
|
if !empty(val) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// fromJson decodes JSON into a structured value, ignoring errors.
|
||||||
|
func fromJson(v string) interface{} {
|
||||||
|
output, _ := mustFromJson(v)
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustFromJson decodes JSON into a structured value, returning errors.
|
||||||
|
func mustFromJson(v string) (interface{}, error) {
|
||||||
|
var output interface{}
|
||||||
|
err := json.Unmarshal([]byte(v), &output)
|
||||||
|
return output, err
|
||||||
|
}
|
||||||
|
|
||||||
// toJson encodes an item into a JSON string
|
// toJson encodes an item into a JSON string
|
||||||
func toJson(v interface{}) string {
|
func toJson(v interface{}) string {
|
||||||
output, _ := json.Marshal(v)
|
output, _ := json.Marshal(v)
|
||||||
return string(output)
|
return string(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustToJson(v interface{}) (string, error) {
|
||||||
|
output, err := json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(output), nil
|
||||||
|
}
|
||||||
|
|
||||||
// toPrettyJson encodes an item into a pretty (indented) JSON string
|
// toPrettyJson encodes an item into a pretty (indented) JSON string
|
||||||
func toPrettyJson(v interface{}) string {
|
func toPrettyJson(v interface{}) string {
|
||||||
output, _ := json.MarshalIndent(v, "", " ")
|
output, _ := json.MarshalIndent(v, "", " ")
|
||||||
return string(output)
|
return string(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustToPrettyJson(v interface{}) (string, error) {
|
||||||
|
output, err := json.MarshalIndent(v, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(output), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toRawJson encodes an item into a JSON string with no escaping of HTML characters.
|
||||||
|
func toRawJson(v interface{}) string {
|
||||||
|
output, err := mustToRawJson(v)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return string(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustToRawJson encodes an item into a JSON string with no escaping of HTML characters.
|
||||||
|
func mustToRawJson(v interface{}) (string, error) {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
enc := json.NewEncoder(buf)
|
||||||
|
enc.SetEscapeHTML(false)
|
||||||
|
err := enc.Encode(&v)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.TrimSuffix(buf.String(), "\n"), nil
|
||||||
|
}
|
||||||
|
|
||||||
// ternary returns the first value if the last value is true, otherwise returns the second value.
|
// ternary returns the first value if the last value is true, otherwise returns the second value.
|
||||||
func ternary(vt interface{}, vf interface{}, v bool) interface{} {
|
func ternary(vt interface{}, vf interface{}, v bool) interface{} {
|
||||||
if v {
|
if v {
|
@ -5,6 +5,13 @@ import (
|
|||||||
"github.com/mitchellh/copystructure"
|
"github.com/mitchellh/copystructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func get(d map[string]interface{}, key string) interface{} {
|
||||||
|
if val, ok := d[key]; ok {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func set(d map[string]interface{}, key string, value interface{}) map[string]interface{} {
|
func set(d map[string]interface{}, key string, value interface{}) map[string]interface{} {
|
||||||
d[key] = value
|
d[key] = value
|
||||||
return d
|
return d
|
||||||
@ -90,6 +97,15 @@ func merge(dst map[string]interface{}, srcs ...map[string]interface{}) interface
|
|||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustMerge(dst map[string]interface{}, srcs ...map[string]interface{}) (interface{}, error) {
|
||||||
|
for _, src := range srcs {
|
||||||
|
if err := mergo.Merge(&dst, src); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst, nil
|
||||||
|
}
|
||||||
|
|
||||||
func mergeOverwrite(dst map[string]interface{}, srcs ...map[string]interface{}) interface{} {
|
func mergeOverwrite(dst map[string]interface{}, srcs ...map[string]interface{}) interface{} {
|
||||||
for _, src := range srcs {
|
for _, src := range srcs {
|
||||||
if err := mergo.MergeWithOverwrite(&dst, src); err != nil {
|
if err := mergo.MergeWithOverwrite(&dst, src); err != nil {
|
||||||
@ -100,6 +116,15 @@ func mergeOverwrite(dst map[string]interface{}, srcs ...map[string]interface{})
|
|||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustMergeOverwrite(dst map[string]interface{}, srcs ...map[string]interface{}) (interface{}, error) {
|
||||||
|
for _, src := range srcs {
|
||||||
|
if err := mergo.MergeWithOverwrite(&dst, src); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst, nil
|
||||||
|
}
|
||||||
|
|
||||||
func values(dict map[string]interface{}) []interface{} {
|
func values(dict map[string]interface{}) []interface{} {
|
||||||
values := []interface{}{}
|
values := []interface{}{}
|
||||||
for _, value := range dict {
|
for _, value := range dict {
|
||||||
@ -110,10 +135,40 @@ func values(dict map[string]interface{}) []interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func deepCopy(i interface{}) interface{} {
|
func deepCopy(i interface{}) interface{} {
|
||||||
c, err := copystructure.Copy(i)
|
c, err := mustDeepCopy(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("deepCopy error: " + err.Error())
|
panic("deepCopy error: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustDeepCopy(i interface{}) (interface{}, error) {
|
||||||
|
return copystructure.Copy(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func dig(ps ...interface{}) (interface{}, error) {
|
||||||
|
if len(ps) < 3 {
|
||||||
|
panic("dig needs at least three arguments")
|
||||||
|
}
|
||||||
|
dict := ps[len(ps)-1].(map[string]interface{})
|
||||||
|
def := ps[len(ps)-2]
|
||||||
|
ks := make([]string, len(ps)-2)
|
||||||
|
for i := 0; i < len(ks); i++ {
|
||||||
|
ks[i] = ps[i].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
return digFromDict(dict, def, ks)
|
||||||
|
}
|
||||||
|
|
||||||
|
func digFromDict(dict map[string]interface{}, d interface{}, ks []string) (interface{}, error) {
|
||||||
|
k, ns := ks[0], ks[1:len(ks)]
|
||||||
|
step, has := dict[k]
|
||||||
|
if !has {
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
if len(ns) == 0 {
|
||||||
|
return step, nil
|
||||||
|
}
|
||||||
|
return digFromDict(step.(map[string]interface{}), d, ns)
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Sprig: Template functions for Go.
|
Package sprig provides template functions for Go.
|
||||||
|
|
||||||
This package contains a number of utility functions for working with data
|
This package contains a number of utility functions for working with data
|
||||||
inside of Go `html/template` and `text/template` files.
|
inside of Go `html/template` and `text/template` files.
|
@ -3,8 +3,10 @@ package sprig
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -13,9 +15,10 @@ import (
|
|||||||
|
|
||||||
util "github.com/Masterminds/goutils"
|
util "github.com/Masterminds/goutils"
|
||||||
"github.com/huandu/xstrings"
|
"github.com/huandu/xstrings"
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Produce the function map.
|
// FuncMap produces the function map.
|
||||||
//
|
//
|
||||||
// Use this to pass the functions into the template engine:
|
// Use this to pass the functions into the template engine:
|
||||||
//
|
//
|
||||||
@ -63,7 +66,7 @@ func GenericFuncMap() map[string]interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// These functions are not guaranteed to evaluate to the same result for given input, because they
|
// These functions are not guaranteed to evaluate to the same result for given input, because they
|
||||||
// refer to the environemnt or global state.
|
// refer to the environment or global state.
|
||||||
var nonhermeticFunctions = []string{
|
var nonhermeticFunctions = []string{
|
||||||
// Date functions
|
// Date functions
|
||||||
"date",
|
"date",
|
||||||
@ -80,6 +83,7 @@ var nonhermeticFunctions = []string{
|
|||||||
"randAlpha",
|
"randAlpha",
|
||||||
"randAscii",
|
"randAscii",
|
||||||
"randNumeric",
|
"randNumeric",
|
||||||
|
"randBytes",
|
||||||
"uuidv4",
|
"uuidv4",
|
||||||
|
|
||||||
// OS
|
// OS
|
||||||
@ -94,17 +98,22 @@ var genericMap = map[string]interface{}{
|
|||||||
"hello": func() string { return "Hello!" },
|
"hello": func() string { return "Hello!" },
|
||||||
|
|
||||||
// Date functions
|
// Date functions
|
||||||
"date": date,
|
"ago": dateAgo,
|
||||||
"date_in_zone": dateInZone,
|
"date": date,
|
||||||
"date_modify": dateModify,
|
"date_in_zone": dateInZone,
|
||||||
"now": func() time.Time { return time.Now() },
|
"date_modify": dateModify,
|
||||||
"htmlDate": htmlDate,
|
"dateInZone": dateInZone,
|
||||||
"htmlDateInZone": htmlDateInZone,
|
"dateModify": dateModify,
|
||||||
"dateInZone": dateInZone,
|
"duration": duration,
|
||||||
"dateModify": dateModify,
|
"durationRound": durationRound,
|
||||||
"ago": dateAgo,
|
"htmlDate": htmlDate,
|
||||||
"toDate": toDate,
|
"htmlDateInZone": htmlDateInZone,
|
||||||
"unixEpoch": unixEpoch,
|
"must_date_modify": mustDateModify,
|
||||||
|
"mustDateModify": mustDateModify,
|
||||||
|
"mustToDate": mustToDate,
|
||||||
|
"now": time.Now,
|
||||||
|
"toDate": toDate,
|
||||||
|
"unixEpoch": unixEpoch,
|
||||||
|
|
||||||
// Strings
|
// Strings
|
||||||
"abbrev": abbrev,
|
"abbrev": abbrev,
|
||||||
@ -158,6 +167,7 @@ var genericMap = map[string]interface{}{
|
|||||||
"int64": toInt64,
|
"int64": toInt64,
|
||||||
"int": toInt,
|
"int": toInt,
|
||||||
"float64": toFloat64,
|
"float64": toFloat64,
|
||||||
|
"seq": seq,
|
||||||
"toDecimal": toDecimal,
|
"toDecimal": toDecimal,
|
||||||
|
|
||||||
//"gt": func(a, b int) bool {return a > b},
|
//"gt": func(a, b int) bool {return a > b},
|
||||||
@ -194,9 +204,28 @@ var genericMap = map[string]interface{}{
|
|||||||
}
|
}
|
||||||
return val
|
return val
|
||||||
},
|
},
|
||||||
|
"randInt": func(min, max int) int { return rand.Intn(max-min) + min },
|
||||||
|
"add1f": func(i interface{}) float64 {
|
||||||
|
return execDecimalOp(i, []interface{}{1}, func(d1, d2 decimal.Decimal) decimal.Decimal { return d1.Add(d2) })
|
||||||
|
},
|
||||||
|
"addf": func(i ...interface{}) float64 {
|
||||||
|
a := interface{}(float64(0))
|
||||||
|
return execDecimalOp(a, i, func(d1, d2 decimal.Decimal) decimal.Decimal { return d1.Add(d2) })
|
||||||
|
},
|
||||||
|
"subf": func(a interface{}, v ...interface{}) float64 {
|
||||||
|
return execDecimalOp(a, v, func(d1, d2 decimal.Decimal) decimal.Decimal { return d1.Sub(d2) })
|
||||||
|
},
|
||||||
|
"divf": func(a interface{}, v ...interface{}) float64 {
|
||||||
|
return execDecimalOp(a, v, func(d1, d2 decimal.Decimal) decimal.Decimal { return d1.Div(d2) })
|
||||||
|
},
|
||||||
|
"mulf": func(a interface{}, v ...interface{}) float64 {
|
||||||
|
return execDecimalOp(a, v, func(d1, d2 decimal.Decimal) decimal.Decimal { return d1.Mul(d2) })
|
||||||
|
},
|
||||||
"biggest": max,
|
"biggest": max,
|
||||||
"max": max,
|
"max": max,
|
||||||
"min": min,
|
"min": min,
|
||||||
|
"maxf": maxf,
|
||||||
|
"minf": minf,
|
||||||
"ceil": ceil,
|
"ceil": ceil,
|
||||||
"floor": floor,
|
"floor": floor,
|
||||||
"round": round,
|
"round": round,
|
||||||
@ -207,14 +236,24 @@ var genericMap = map[string]interface{}{
|
|||||||
"sortAlpha": sortAlpha,
|
"sortAlpha": sortAlpha,
|
||||||
|
|
||||||
// Defaults
|
// Defaults
|
||||||
"default": dfault,
|
"default": dfault,
|
||||||
"empty": empty,
|
"empty": empty,
|
||||||
"coalesce": coalesce,
|
"coalesce": coalesce,
|
||||||
"compact": compact,
|
"all": all,
|
||||||
"deepCopy": deepCopy,
|
"any": any,
|
||||||
"toJson": toJson,
|
"compact": compact,
|
||||||
"toPrettyJson": toPrettyJson,
|
"mustCompact": mustCompact,
|
||||||
"ternary": ternary,
|
"fromJson": fromJson,
|
||||||
|
"toJson": toJson,
|
||||||
|
"toPrettyJson": toPrettyJson,
|
||||||
|
"toRawJson": toRawJson,
|
||||||
|
"mustFromJson": mustFromJson,
|
||||||
|
"mustToJson": mustToJson,
|
||||||
|
"mustToPrettyJson": mustToPrettyJson,
|
||||||
|
"mustToRawJson": mustToRawJson,
|
||||||
|
"ternary": ternary,
|
||||||
|
"deepCopy": deepCopy,
|
||||||
|
"mustDeepCopy": mustDeepCopy,
|
||||||
|
|
||||||
// Reflection
|
// Reflection
|
||||||
"typeOf": typeOf,
|
"typeOf": typeOf,
|
||||||
@ -225,19 +264,26 @@ var genericMap = map[string]interface{}{
|
|||||||
"deepEqual": reflect.DeepEqual,
|
"deepEqual": reflect.DeepEqual,
|
||||||
|
|
||||||
// OS:
|
// OS:
|
||||||
"env": func(s string) string { return os.Getenv(s) },
|
"env": os.Getenv,
|
||||||
"expandenv": func(s string) string { return os.ExpandEnv(s) },
|
"expandenv": os.ExpandEnv,
|
||||||
|
|
||||||
// Network:
|
// Network:
|
||||||
"getHostByName": getHostByName,
|
"getHostByName": getHostByName,
|
||||||
|
|
||||||
// File Paths:
|
// Paths:
|
||||||
"base": path.Base,
|
"base": path.Base,
|
||||||
"dir": path.Dir,
|
"dir": path.Dir,
|
||||||
"clean": path.Clean,
|
"clean": path.Clean,
|
||||||
"ext": path.Ext,
|
"ext": path.Ext,
|
||||||
"isAbs": path.IsAbs,
|
"isAbs": path.IsAbs,
|
||||||
|
|
||||||
|
// Filepaths:
|
||||||
|
"osBase": filepath.Base,
|
||||||
|
"osClean": filepath.Clean,
|
||||||
|
"osDir": filepath.Dir,
|
||||||
|
"osExt": filepath.Ext,
|
||||||
|
"osIsAbs": filepath.IsAbs,
|
||||||
|
|
||||||
// Encoding:
|
// Encoding:
|
||||||
"b64enc": base64encode,
|
"b64enc": base64encode,
|
||||||
"b64dec": base64decode,
|
"b64dec": base64decode,
|
||||||
@ -245,42 +291,65 @@ var genericMap = map[string]interface{}{
|
|||||||
"b32dec": base32decode,
|
"b32dec": base32decode,
|
||||||
|
|
||||||
// Data Structures:
|
// Data Structures:
|
||||||
"tuple": list, // FIXME: with the addition of append/prepend these are no longer immutable.
|
"tuple": list, // FIXME: with the addition of append/prepend these are no longer immutable.
|
||||||
"list": list,
|
"list": list,
|
||||||
"dict": dict,
|
"dict": dict,
|
||||||
"set": set,
|
"get": get,
|
||||||
"unset": unset,
|
"set": set,
|
||||||
"hasKey": hasKey,
|
"unset": unset,
|
||||||
"pluck": pluck,
|
"hasKey": hasKey,
|
||||||
"keys": keys,
|
"pluck": pluck,
|
||||||
"pick": pick,
|
"keys": keys,
|
||||||
"omit": omit,
|
"pick": pick,
|
||||||
"merge": merge,
|
"omit": omit,
|
||||||
"mergeOverwrite": mergeOverwrite,
|
"merge": merge,
|
||||||
"values": values,
|
"mergeOverwrite": mergeOverwrite,
|
||||||
|
"mustMerge": mustMerge,
|
||||||
|
"mustMergeOverwrite": mustMergeOverwrite,
|
||||||
|
"values": values,
|
||||||
|
|
||||||
"append": push, "push": push,
|
"append": push, "push": push,
|
||||||
"prepend": prepend,
|
"mustAppend": mustPush, "mustPush": mustPush,
|
||||||
"first": first,
|
"prepend": prepend,
|
||||||
"rest": rest,
|
"mustPrepend": mustPrepend,
|
||||||
"last": last,
|
"first": first,
|
||||||
"initial": initial,
|
"mustFirst": mustFirst,
|
||||||
"reverse": reverse,
|
"rest": rest,
|
||||||
"uniq": uniq,
|
"mustRest": mustRest,
|
||||||
"without": without,
|
"last": last,
|
||||||
"has": has,
|
"mustLast": mustLast,
|
||||||
"slice": slice,
|
"initial": initial,
|
||||||
"concat": concat,
|
"mustInitial": mustInitial,
|
||||||
|
"reverse": reverse,
|
||||||
|
"mustReverse": mustReverse,
|
||||||
|
"uniq": uniq,
|
||||||
|
"mustUniq": mustUniq,
|
||||||
|
"without": without,
|
||||||
|
"mustWithout": mustWithout,
|
||||||
|
"has": has,
|
||||||
|
"mustHas": mustHas,
|
||||||
|
"slice": slice,
|
||||||
|
"mustSlice": mustSlice,
|
||||||
|
"concat": concat,
|
||||||
|
"dig": dig,
|
||||||
|
"chunk": chunk,
|
||||||
|
"mustChunk": mustChunk,
|
||||||
|
|
||||||
// Crypto:
|
// Crypto:
|
||||||
|
"bcrypt": bcrypt,
|
||||||
|
"htpasswd": htpasswd,
|
||||||
"genPrivateKey": generatePrivateKey,
|
"genPrivateKey": generatePrivateKey,
|
||||||
"derivePassword": derivePassword,
|
"derivePassword": derivePassword,
|
||||||
"buildCustomCert": buildCustomCertificate,
|
"buildCustomCert": buildCustomCertificate,
|
||||||
"genCA": generateCertificateAuthority,
|
"genCA": generateCertificateAuthority,
|
||||||
|
"genCAWithKey": generateCertificateAuthorityWithPEMKey,
|
||||||
"genSelfSignedCert": generateSelfSignedCertificate,
|
"genSelfSignedCert": generateSelfSignedCertificate,
|
||||||
|
"genSelfSignedCertWithKey": generateSelfSignedCertificateWithPEMKey,
|
||||||
"genSignedCert": generateSignedCertificate,
|
"genSignedCert": generateSignedCertificate,
|
||||||
|
"genSignedCertWithKey": generateSignedCertificateWithPEMKey,
|
||||||
"encryptAES": encryptAES,
|
"encryptAES": encryptAES,
|
||||||
"decryptAES": decryptAES,
|
"decryptAES": decryptAES,
|
||||||
|
"randBytes": randBytes,
|
||||||
|
|
||||||
// UUIDs:
|
// UUIDs:
|
||||||
"uuidv4": uuidv4,
|
"uuidv4": uuidv4,
|
||||||
@ -293,12 +362,19 @@ var genericMap = map[string]interface{}{
|
|||||||
"fail": func(msg string) (string, error) { return "", errors.New(msg) },
|
"fail": func(msg string) (string, error) { return "", errors.New(msg) },
|
||||||
|
|
||||||
// Regex
|
// Regex
|
||||||
"regexMatch": regexMatch,
|
"regexMatch": regexMatch,
|
||||||
"regexFindAll": regexFindAll,
|
"mustRegexMatch": mustRegexMatch,
|
||||||
"regexFind": regexFind,
|
"regexFindAll": regexFindAll,
|
||||||
"regexReplaceAll": regexReplaceAll,
|
"mustRegexFindAll": mustRegexFindAll,
|
||||||
"regexReplaceAllLiteral": regexReplaceAllLiteral,
|
"regexFind": regexFind,
|
||||||
"regexSplit": regexSplit,
|
"mustRegexFind": mustRegexFind,
|
||||||
|
"regexReplaceAll": regexReplaceAll,
|
||||||
|
"mustRegexReplaceAll": mustRegexReplaceAll,
|
||||||
|
"regexReplaceAllLiteral": regexReplaceAllLiteral,
|
||||||
|
"mustRegexReplaceAllLiteral": mustRegexReplaceAllLiteral,
|
||||||
|
"regexSplit": regexSplit,
|
||||||
|
"mustRegexSplit": mustRegexSplit,
|
||||||
|
"regexQuoteMeta": regexQuoteMeta,
|
||||||
|
|
||||||
// URLs:
|
// URLs:
|
||||||
"urlParse": urlParse,
|
"urlParse": urlParse,
|
215
vendor/github.com/Masterminds/sprig/list.go → vendor/github.com/Masterminds/sprig/v3/list.go
generated
vendored
215
vendor/github.com/Masterminds/sprig/list.go → vendor/github.com/Masterminds/sprig/v3/list.go
generated
vendored
@ -2,6 +2,7 @@ package sprig
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
@ -15,6 +16,15 @@ func list(v ...interface{}) []interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func push(list interface{}, v interface{}) []interface{} {
|
func push(list interface{}, v interface{}) []interface{} {
|
||||||
|
l, err := mustPush(list, v)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustPush(list interface{}, v interface{}) ([]interface{}, error) {
|
||||||
tp := reflect.TypeOf(list).Kind()
|
tp := reflect.TypeOf(list).Kind()
|
||||||
switch tp {
|
switch tp {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
@ -26,14 +36,23 @@ func push(list interface{}, v interface{}) []interface{} {
|
|||||||
nl[i] = l2.Index(i).Interface()
|
nl[i] = l2.Index(i).Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(nl, v)
|
return append(nl, v), nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Cannot push on type %s", tp))
|
return nil, fmt.Errorf("Cannot push on type %s", tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepend(list interface{}, v interface{}) []interface{} {
|
func prepend(list interface{}, v interface{}) []interface{} {
|
||||||
|
l, err := mustPrepend(list, v)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustPrepend(list interface{}, v interface{}) ([]interface{}, error) {
|
||||||
//return append([]interface{}{v}, list...)
|
//return append([]interface{}{v}, list...)
|
||||||
|
|
||||||
tp := reflect.TypeOf(list).Kind()
|
tp := reflect.TypeOf(list).Kind()
|
||||||
@ -47,14 +66,67 @@ func prepend(list interface{}, v interface{}) []interface{} {
|
|||||||
nl[i] = l2.Index(i).Interface()
|
nl[i] = l2.Index(i).Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
return append([]interface{}{v}, nl...)
|
return append([]interface{}{v}, nl...), nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Cannot prepend on type %s", tp))
|
return nil, fmt.Errorf("Cannot prepend on type %s", tp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func chunk(size int, list interface{}) [][]interface{} {
|
||||||
|
l, err := mustChunk(size, list)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustChunk(size int, list interface{}) ([][]interface{}, error) {
|
||||||
|
tp := reflect.TypeOf(list).Kind()
|
||||||
|
switch tp {
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
l2 := reflect.ValueOf(list)
|
||||||
|
|
||||||
|
l := l2.Len()
|
||||||
|
|
||||||
|
cs := int(math.Floor(float64(l-1)/float64(size)) + 1)
|
||||||
|
nl := make([][]interface{}, cs)
|
||||||
|
|
||||||
|
for i := 0; i < cs; i++ {
|
||||||
|
clen := size
|
||||||
|
if i == cs-1 {
|
||||||
|
clen = int(math.Floor(math.Mod(float64(l), float64(size))))
|
||||||
|
if clen == 0 {
|
||||||
|
clen = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nl[i] = make([]interface{}, clen)
|
||||||
|
|
||||||
|
for j := 0; j < clen; j++ {
|
||||||
|
ix := i*size + j
|
||||||
|
nl[i][j] = l2.Index(ix).Interface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nl, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("Cannot chunk type %s", tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func last(list interface{}) interface{} {
|
func last(list interface{}) interface{} {
|
||||||
|
l, err := mustLast(list)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustLast(list interface{}) (interface{}, error) {
|
||||||
tp := reflect.TypeOf(list).Kind()
|
tp := reflect.TypeOf(list).Kind()
|
||||||
switch tp {
|
switch tp {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
@ -62,16 +134,25 @@ func last(list interface{}) interface{} {
|
|||||||
|
|
||||||
l := l2.Len()
|
l := l2.Len()
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return l2.Index(l - 1).Interface()
|
return l2.Index(l - 1).Interface(), nil
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Cannot find last on type %s", tp))
|
return nil, fmt.Errorf("Cannot find last on type %s", tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func first(list interface{}) interface{} {
|
func first(list interface{}) interface{} {
|
||||||
|
l, err := mustFirst(list)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustFirst(list interface{}) (interface{}, error) {
|
||||||
tp := reflect.TypeOf(list).Kind()
|
tp := reflect.TypeOf(list).Kind()
|
||||||
switch tp {
|
switch tp {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
@ -79,16 +160,25 @@ func first(list interface{}) interface{} {
|
|||||||
|
|
||||||
l := l2.Len()
|
l := l2.Len()
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return l2.Index(0).Interface()
|
return l2.Index(0).Interface(), nil
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Cannot find first on type %s", tp))
|
return nil, fmt.Errorf("Cannot find first on type %s", tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func rest(list interface{}) []interface{} {
|
func rest(list interface{}) []interface{} {
|
||||||
|
l, err := mustRest(list)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustRest(list interface{}) ([]interface{}, error) {
|
||||||
tp := reflect.TypeOf(list).Kind()
|
tp := reflect.TypeOf(list).Kind()
|
||||||
switch tp {
|
switch tp {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
@ -96,7 +186,7 @@ func rest(list interface{}) []interface{} {
|
|||||||
|
|
||||||
l := l2.Len()
|
l := l2.Len()
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
nl := make([]interface{}, l-1)
|
nl := make([]interface{}, l-1)
|
||||||
@ -104,13 +194,22 @@ func rest(list interface{}) []interface{} {
|
|||||||
nl[i-1] = l2.Index(i).Interface()
|
nl[i-1] = l2.Index(i).Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nl
|
return nl, nil
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Cannot find rest on type %s", tp))
|
return nil, fmt.Errorf("Cannot find rest on type %s", tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initial(list interface{}) []interface{} {
|
func initial(list interface{}) []interface{} {
|
||||||
|
l, err := mustInitial(list)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustInitial(list interface{}) ([]interface{}, error) {
|
||||||
tp := reflect.TypeOf(list).Kind()
|
tp := reflect.TypeOf(list).Kind()
|
||||||
switch tp {
|
switch tp {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
@ -118,7 +217,7 @@ func initial(list interface{}) []interface{} {
|
|||||||
|
|
||||||
l := l2.Len()
|
l := l2.Len()
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
nl := make([]interface{}, l-1)
|
nl := make([]interface{}, l-1)
|
||||||
@ -126,9 +225,9 @@ func initial(list interface{}) []interface{} {
|
|||||||
nl[i] = l2.Index(i).Interface()
|
nl[i] = l2.Index(i).Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nl
|
return nl, nil
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Cannot find initial on type %s", tp))
|
return nil, fmt.Errorf("Cannot find initial on type %s", tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +244,15 @@ func sortAlpha(list interface{}) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func reverse(v interface{}) []interface{} {
|
func reverse(v interface{}) []interface{} {
|
||||||
|
l, err := mustReverse(v)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustReverse(v interface{}) ([]interface{}, error) {
|
||||||
tp := reflect.TypeOf(v).Kind()
|
tp := reflect.TypeOf(v).Kind()
|
||||||
switch tp {
|
switch tp {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
@ -157,13 +265,22 @@ func reverse(v interface{}) []interface{} {
|
|||||||
nl[l-i-1] = l2.Index(i).Interface()
|
nl[l-i-1] = l2.Index(i).Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nl
|
return nl, nil
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Cannot find reverse on type %s", tp))
|
return nil, fmt.Errorf("Cannot find reverse on type %s", tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func compact(list interface{}) []interface{} {
|
func compact(list interface{}) []interface{} {
|
||||||
|
l, err := mustCompact(list)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustCompact(list interface{}) ([]interface{}, error) {
|
||||||
tp := reflect.TypeOf(list).Kind()
|
tp := reflect.TypeOf(list).Kind()
|
||||||
switch tp {
|
switch tp {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
@ -179,13 +296,22 @@ func compact(list interface{}) []interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nl
|
return nl, nil
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Cannot compact on type %s", tp))
|
return nil, fmt.Errorf("Cannot compact on type %s", tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func uniq(list interface{}) []interface{} {
|
func uniq(list interface{}) []interface{} {
|
||||||
|
l, err := mustUniq(list)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustUniq(list interface{}) ([]interface{}, error) {
|
||||||
tp := reflect.TypeOf(list).Kind()
|
tp := reflect.TypeOf(list).Kind()
|
||||||
switch tp {
|
switch tp {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
@ -201,9 +327,9 @@ func uniq(list interface{}) []interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dest
|
return dest, nil
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Cannot find uniq on type %s", tp))
|
return nil, fmt.Errorf("Cannot find uniq on type %s", tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,6 +343,15 @@ func inList(haystack []interface{}, needle interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func without(list interface{}, omit ...interface{}) []interface{} {
|
func without(list interface{}, omit ...interface{}) []interface{} {
|
||||||
|
l, err := mustWithout(list, omit...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustWithout(list interface{}, omit ...interface{}) ([]interface{}, error) {
|
||||||
tp := reflect.TypeOf(list).Kind()
|
tp := reflect.TypeOf(list).Kind()
|
||||||
switch tp {
|
switch tp {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
@ -232,15 +367,24 @@ func without(list interface{}, omit ...interface{}) []interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return res, nil
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Cannot find without on type %s", tp))
|
return nil, fmt.Errorf("Cannot find without on type %s", tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func has(needle interface{}, haystack interface{}) bool {
|
func has(needle interface{}, haystack interface{}) bool {
|
||||||
|
l, err := mustHas(needle, haystack)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustHas(needle interface{}, haystack interface{}) (bool, error) {
|
||||||
if haystack == nil {
|
if haystack == nil {
|
||||||
return false
|
return false, nil
|
||||||
}
|
}
|
||||||
tp := reflect.TypeOf(haystack).Kind()
|
tp := reflect.TypeOf(haystack).Kind()
|
||||||
switch tp {
|
switch tp {
|
||||||
@ -251,13 +395,13 @@ func has(needle interface{}, haystack interface{}) bool {
|
|||||||
for i := 0; i < l; i++ {
|
for i := 0; i < l; i++ {
|
||||||
item = l2.Index(i).Interface()
|
item = l2.Index(i).Interface()
|
||||||
if reflect.DeepEqual(needle, item) {
|
if reflect.DeepEqual(needle, item) {
|
||||||
return true
|
return true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false, nil
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Cannot find has on type %s", tp))
|
return false, fmt.Errorf("Cannot find has on type %s", tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,6 +411,15 @@ func has(needle interface{}, haystack interface{}) bool {
|
|||||||
// slice $list 3 5 -> list[3:5]
|
// slice $list 3 5 -> list[3:5]
|
||||||
// slice $list 3 -> list[3:5] = list[3:]
|
// slice $list 3 -> list[3:5] = list[3:]
|
||||||
func slice(list interface{}, indices ...interface{}) interface{} {
|
func slice(list interface{}, indices ...interface{}) interface{} {
|
||||||
|
l, err := mustSlice(list, indices...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustSlice(list interface{}, indices ...interface{}) (interface{}, error) {
|
||||||
tp := reflect.TypeOf(list).Kind()
|
tp := reflect.TypeOf(list).Kind()
|
||||||
switch tp {
|
switch tp {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
@ -274,7 +427,7 @@ func slice(list interface{}, indices ...interface{}) interface{} {
|
|||||||
|
|
||||||
l := l2.Len()
|
l := l2.Len()
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var start, end int
|
var start, end int
|
||||||
@ -287,9 +440,9 @@ func slice(list interface{}, indices ...interface{}) interface{} {
|
|||||||
end = toInt(indices[1])
|
end = toInt(indices[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
return l2.Slice(start, end).Interface()
|
return l2.Slice(start, end).Interface(), nil
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("list should be type of slice or array but %s", tp))
|
return nil, fmt.Errorf("list should be type of slice or array but %s", tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,6 +7,6 @@ import (
|
|||||||
|
|
||||||
func getHostByName(name string) string {
|
func getHostByName(name string) string {
|
||||||
addrs, _ := net.LookupHost(name)
|
addrs, _ := net.LookupHost(name)
|
||||||
//TODO: add error handing when release v3 cames out
|
//TODO: add error handing when release v3 comes out
|
||||||
return addrs[rand.Intn(len(addrs))]
|
return addrs[rand.Intn(len(addrs))]
|
||||||
}
|
}
|
186
vendor/github.com/Masterminds/sprig/v3/numeric.go
generated
vendored
Normal file
186
vendor/github.com/Masterminds/sprig/v3/numeric.go
generated
vendored
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
package sprig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cast"
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// toFloat64 converts 64-bit floats
|
||||||
|
func toFloat64(v interface{}) float64 {
|
||||||
|
return cast.ToFloat64(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toInt(v interface{}) int {
|
||||||
|
return cast.ToInt(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// toInt64 converts integer types to 64-bit integers
|
||||||
|
func toInt64(v interface{}) int64 {
|
||||||
|
return cast.ToInt64(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func max(a interface{}, i ...interface{}) int64 {
|
||||||
|
aa := toInt64(a)
|
||||||
|
for _, b := range i {
|
||||||
|
bb := toInt64(b)
|
||||||
|
if bb > aa {
|
||||||
|
aa = bb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aa
|
||||||
|
}
|
||||||
|
|
||||||
|
func maxf(a interface{}, i ...interface{}) float64 {
|
||||||
|
aa := toFloat64(a)
|
||||||
|
for _, b := range i {
|
||||||
|
bb := toFloat64(b)
|
||||||
|
aa = math.Max(aa, bb)
|
||||||
|
}
|
||||||
|
return aa
|
||||||
|
}
|
||||||
|
|
||||||
|
func min(a interface{}, i ...interface{}) int64 {
|
||||||
|
aa := toInt64(a)
|
||||||
|
for _, b := range i {
|
||||||
|
bb := toInt64(b)
|
||||||
|
if bb < aa {
|
||||||
|
aa = bb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aa
|
||||||
|
}
|
||||||
|
|
||||||
|
func minf(a interface{}, i ...interface{}) float64 {
|
||||||
|
aa := toFloat64(a)
|
||||||
|
for _, b := range i {
|
||||||
|
bb := toFloat64(b)
|
||||||
|
aa = math.Min(aa, bb)
|
||||||
|
}
|
||||||
|
return aa
|
||||||
|
}
|
||||||
|
|
||||||
|
func until(count int) []int {
|
||||||
|
step := 1
|
||||||
|
if count < 0 {
|
||||||
|
step = -1
|
||||||
|
}
|
||||||
|
return untilStep(0, count, step)
|
||||||
|
}
|
||||||
|
|
||||||
|
func untilStep(start, stop, step int) []int {
|
||||||
|
v := []int{}
|
||||||
|
|
||||||
|
if stop < start {
|
||||||
|
if step >= 0 {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
for i := start; i > stop; i += step {
|
||||||
|
v = append(v, i)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
if step <= 0 {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
for i := start; i < stop; i += step {
|
||||||
|
v = append(v, i)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func floor(a interface{}) float64 {
|
||||||
|
aa := toFloat64(a)
|
||||||
|
return math.Floor(aa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ceil(a interface{}) float64 {
|
||||||
|
aa := toFloat64(a)
|
||||||
|
return math.Ceil(aa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func round(a interface{}, p int, rOpt ...float64) float64 {
|
||||||
|
roundOn := .5
|
||||||
|
if len(rOpt) > 0 {
|
||||||
|
roundOn = rOpt[0]
|
||||||
|
}
|
||||||
|
val := toFloat64(a)
|
||||||
|
places := toFloat64(p)
|
||||||
|
|
||||||
|
var round float64
|
||||||
|
pow := math.Pow(10, places)
|
||||||
|
digit := pow * val
|
||||||
|
_, div := math.Modf(digit)
|
||||||
|
if div >= roundOn {
|
||||||
|
round = math.Ceil(digit)
|
||||||
|
} else {
|
||||||
|
round = math.Floor(digit)
|
||||||
|
}
|
||||||
|
return round / pow
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts unix octal to decimal
|
||||||
|
func toDecimal(v interface{}) int64 {
|
||||||
|
result, err := strconv.ParseInt(fmt.Sprint(v), 8, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func seq(params ...int) string {
|
||||||
|
increment := 1
|
||||||
|
switch len(params) {
|
||||||
|
case 0:
|
||||||
|
return ""
|
||||||
|
case 1:
|
||||||
|
start := 1
|
||||||
|
end := params[0]
|
||||||
|
if end < start {
|
||||||
|
increment = -1
|
||||||
|
}
|
||||||
|
return intArrayToString(untilStep(start, end+increment, increment), " ")
|
||||||
|
case 3:
|
||||||
|
start := params[0]
|
||||||
|
end := params[2]
|
||||||
|
step := params[1]
|
||||||
|
if end < start {
|
||||||
|
increment = -1
|
||||||
|
if step > 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return intArrayToString(untilStep(start, end+increment, step), " ")
|
||||||
|
case 2:
|
||||||
|
start := params[0]
|
||||||
|
end := params[1]
|
||||||
|
step := 1
|
||||||
|
if end < start {
|
||||||
|
step = -1
|
||||||
|
}
|
||||||
|
return intArrayToString(untilStep(start, end+step, step), " ")
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func intArrayToString(slice []int, delimeter string) string {
|
||||||
|
return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(slice)), delimeter), "[]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// performs a float and subsequent decimal.Decimal conversion on inputs,
|
||||||
|
// and iterates through a and b executing the mathmetical operation f
|
||||||
|
func execDecimalOp(a interface{}, b []interface{}, f func(d1, d2 decimal.Decimal) decimal.Decimal) float64 {
|
||||||
|
prt := decimal.NewFromFloat(toFloat64(a))
|
||||||
|
for _, x := range b {
|
||||||
|
dx := decimal.NewFromFloat(toFloat64(x))
|
||||||
|
prt = f(prt, dx)
|
||||||
|
}
|
||||||
|
rslt, _ := prt.Float64()
|
||||||
|
return rslt
|
||||||
|
}
|
83
vendor/github.com/Masterminds/sprig/v3/regex.go
generated
vendored
Normal file
83
vendor/github.com/Masterminds/sprig/v3/regex.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package sprig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func regexMatch(regex string, s string) bool {
|
||||||
|
match, _ := regexp.MatchString(regex, s)
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustRegexMatch(regex string, s string) (bool, error) {
|
||||||
|
return regexp.MatchString(regex, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func regexFindAll(regex string, s string, n int) []string {
|
||||||
|
r := regexp.MustCompile(regex)
|
||||||
|
return r.FindAllString(s, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustRegexFindAll(regex string, s string, n int) ([]string, error) {
|
||||||
|
r, err := regexp.Compile(regex)
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
return r.FindAllString(s, n), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func regexFind(regex string, s string) string {
|
||||||
|
r := regexp.MustCompile(regex)
|
||||||
|
return r.FindString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustRegexFind(regex string, s string) (string, error) {
|
||||||
|
r, err := regexp.Compile(regex)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return r.FindString(s), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func regexReplaceAll(regex string, s string, repl string) string {
|
||||||
|
r := regexp.MustCompile(regex)
|
||||||
|
return r.ReplaceAllString(s, repl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustRegexReplaceAll(regex string, s string, repl string) (string, error) {
|
||||||
|
r, err := regexp.Compile(regex)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return r.ReplaceAllString(s, repl), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func regexReplaceAllLiteral(regex string, s string, repl string) string {
|
||||||
|
r := regexp.MustCompile(regex)
|
||||||
|
return r.ReplaceAllLiteralString(s, repl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustRegexReplaceAllLiteral(regex string, s string, repl string) (string, error) {
|
||||||
|
r, err := regexp.Compile(regex)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return r.ReplaceAllLiteralString(s, repl), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func regexSplit(regex string, s string, n int) []string {
|
||||||
|
r := regexp.MustCompile(regex)
|
||||||
|
return r.Split(s, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustRegexSplit(regex string, s string, n int) ([]string, error) {
|
||||||
|
r, err := regexp.Compile(regex)
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
return r.Split(s, n), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func regexQuoteMeta(s string) string {
|
||||||
|
return regexp.QuoteMeta(s)
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package sprig
|
package sprig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
sv2 "github.com/Masterminds/semver"
|
sv2 "github.com/Masterminds/semver/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func semverCompare(constraint, version string) (bool, error) {
|
func semverCompare(constraint, version string) (bool, error) {
|
@ -154,9 +154,9 @@ func strslice(v interface{}) []string {
|
|||||||
default:
|
default:
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return []string{}
|
return []string{}
|
||||||
} else {
|
|
||||||
return []string{strval(v)}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return []string{strval(v)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,10 +187,13 @@ func strval(v interface{}) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func trunc(c int, s string) string {
|
func trunc(c int, s string) string {
|
||||||
if len(s) <= c {
|
if c < 0 && len(s)+c > 0 {
|
||||||
return s
|
return s[len(s)+c:]
|
||||||
}
|
}
|
||||||
return s[0:c]
|
if c >= 0 && len(s) > c {
|
||||||
|
return s[:c]
|
||||||
|
}
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func join(sep string, v interface{}) string {
|
func join(sep string, v interface{}) string {
|
@ -7,7 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func dictGetOrEmpty(dict map[string]interface{}, key string) string {
|
func dictGetOrEmpty(dict map[string]interface{}, key string) string {
|
||||||
value, ok := dict[key]; if !ok {
|
value, ok := dict[key]
|
||||||
|
if !ok {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
tp := reflect.TypeOf(value).Kind()
|
tp := reflect.TypeOf(value).Kind()
|
||||||
@ -20,19 +21,19 @@ func dictGetOrEmpty(dict map[string]interface{}, key string) string {
|
|||||||
// parses given URL to return dict object
|
// parses given URL to return dict object
|
||||||
func urlParse(v string) map[string]interface{} {
|
func urlParse(v string) map[string]interface{} {
|
||||||
dict := map[string]interface{}{}
|
dict := map[string]interface{}{}
|
||||||
parsedUrl, err := url.Parse(v)
|
parsedURL, err := url.Parse(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("unable to parse url: %s", err))
|
panic(fmt.Sprintf("unable to parse url: %s", err))
|
||||||
}
|
}
|
||||||
dict["scheme"] = parsedUrl.Scheme
|
dict["scheme"] = parsedURL.Scheme
|
||||||
dict["host"] = parsedUrl.Host
|
dict["host"] = parsedURL.Host
|
||||||
dict["hostname"] = parsedUrl.Hostname()
|
dict["hostname"] = parsedURL.Hostname()
|
||||||
dict["path"] = parsedUrl.Path
|
dict["path"] = parsedURL.Path
|
||||||
dict["query"] = parsedUrl.RawQuery
|
dict["query"] = parsedURL.RawQuery
|
||||||
dict["opaque"] = parsedUrl.Opaque
|
dict["opaque"] = parsedURL.Opaque
|
||||||
dict["fragment"] = parsedUrl.Fragment
|
dict["fragment"] = parsedURL.Fragment
|
||||||
if parsedUrl.User != nil {
|
if parsedURL.User != nil {
|
||||||
dict["userinfo"] = parsedUrl.User.String()
|
dict["userinfo"] = parsedURL.User.String()
|
||||||
} else {
|
} else {
|
||||||
dict["userinfo"] = ""
|
dict["userinfo"] = ""
|
||||||
}
|
}
|
||||||
@ -42,25 +43,24 @@ func urlParse(v string) map[string]interface{} {
|
|||||||
|
|
||||||
// join given dict to URL string
|
// join given dict to URL string
|
||||||
func urlJoin(d map[string]interface{}) string {
|
func urlJoin(d map[string]interface{}) string {
|
||||||
resUrl := url.URL{
|
resURL := url.URL{
|
||||||
Scheme: dictGetOrEmpty(d, "scheme"),
|
Scheme: dictGetOrEmpty(d, "scheme"),
|
||||||
Host: dictGetOrEmpty(d, "host"),
|
Host: dictGetOrEmpty(d, "host"),
|
||||||
Path: dictGetOrEmpty(d, "path"),
|
Path: dictGetOrEmpty(d, "path"),
|
||||||
RawQuery: dictGetOrEmpty(d, "query"),
|
RawQuery: dictGetOrEmpty(d, "query"),
|
||||||
Opaque: dictGetOrEmpty(d, "opaque"),
|
Opaque: dictGetOrEmpty(d, "opaque"),
|
||||||
Fragment: dictGetOrEmpty(d, "fragment"),
|
Fragment: dictGetOrEmpty(d, "fragment"),
|
||||||
|
|
||||||
}
|
}
|
||||||
userinfo := dictGetOrEmpty(d, "userinfo")
|
userinfo := dictGetOrEmpty(d, "userinfo")
|
||||||
var user *url.Userinfo = nil
|
var user *url.Userinfo
|
||||||
if userinfo != "" {
|
if userinfo != "" {
|
||||||
tempUrl, err := url.Parse(fmt.Sprintf("proto://%s@host", userinfo))
|
tempURL, err := url.Parse(fmt.Sprintf("proto://%s@host", userinfo))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("unable to parse userinfo in dict: %s", err))
|
panic(fmt.Sprintf("unable to parse userinfo in dict: %s", err))
|
||||||
}
|
}
|
||||||
user = tempUrl.User
|
user = tempURL.User
|
||||||
}
|
}
|
||||||
|
|
||||||
resUrl.User = user
|
resURL.User = user
|
||||||
return resUrl.String()
|
return resURL.String()
|
||||||
}
|
}
|
4
vendor/github.com/google/uuid/hash.go
generated
vendored
4
vendor/github.com/google/uuid/hash.go
generated
vendored
@ -26,8 +26,8 @@ var (
|
|||||||
// NewMD5 and NewSHA1.
|
// NewMD5 and NewSHA1.
|
||||||
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
|
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
|
||||||
h.Reset()
|
h.Reset()
|
||||||
h.Write(space[:])
|
h.Write(space[:]) //nolint:errcheck
|
||||||
h.Write(data)
|
h.Write(data) //nolint:errcheck
|
||||||
s := h.Sum(nil)
|
s := h.Sum(nil)
|
||||||
var uuid UUID
|
var uuid UUID
|
||||||
copy(uuid[:], s)
|
copy(uuid[:], s)
|
||||||
|
118
vendor/github.com/google/uuid/null.go
generated
vendored
Normal file
118
vendor/github.com/google/uuid/null.go
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
// Copyright 2021 Google Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package uuid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"database/sql/driver"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var jsonNull = []byte("null")
|
||||||
|
|
||||||
|
// NullUUID represents a UUID that may be null.
|
||||||
|
// NullUUID implements the SQL driver.Scanner interface so
|
||||||
|
// it can be used as a scan destination:
|
||||||
|
//
|
||||||
|
// var u uuid.NullUUID
|
||||||
|
// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u)
|
||||||
|
// ...
|
||||||
|
// if u.Valid {
|
||||||
|
// // use u.UUID
|
||||||
|
// } else {
|
||||||
|
// // NULL value
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
type NullUUID struct {
|
||||||
|
UUID UUID
|
||||||
|
Valid bool // Valid is true if UUID is not NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan implements the SQL driver.Scanner interface.
|
||||||
|
func (nu *NullUUID) Scan(value interface{}) error {
|
||||||
|
if value == nil {
|
||||||
|
nu.UUID, nu.Valid = Nil, false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := nu.UUID.Scan(value)
|
||||||
|
if err != nil {
|
||||||
|
nu.Valid = false
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
nu.Valid = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value implements the driver Valuer interface.
|
||||||
|
func (nu NullUUID) Value() (driver.Value, error) {
|
||||||
|
if !nu.Valid {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
// Delegate to UUID Value function
|
||||||
|
return nu.UUID.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary implements encoding.BinaryMarshaler.
|
||||||
|
func (nu NullUUID) MarshalBinary() ([]byte, error) {
|
||||||
|
if nu.Valid {
|
||||||
|
return nu.UUID[:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(nil), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
|
||||||
|
func (nu *NullUUID) UnmarshalBinary(data []byte) error {
|
||||||
|
if len(data) != 16 {
|
||||||
|
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
|
||||||
|
}
|
||||||
|
copy(nu.UUID[:], data)
|
||||||
|
nu.Valid = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
|
func (nu NullUUID) MarshalText() ([]byte, error) {
|
||||||
|
if nu.Valid {
|
||||||
|
return nu.UUID.MarshalText()
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonNull, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
func (nu *NullUUID) UnmarshalText(data []byte) error {
|
||||||
|
id, err := ParseBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
nu.Valid = false
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nu.UUID = id
|
||||||
|
nu.Valid = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements json.Marshaler.
|
||||||
|
func (nu NullUUID) MarshalJSON() ([]byte, error) {
|
||||||
|
if nu.Valid {
|
||||||
|
return json.Marshal(nu.UUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonNull, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements json.Unmarshaler.
|
||||||
|
func (nu *NullUUID) UnmarshalJSON(data []byte) error {
|
||||||
|
if bytes.Equal(data, jsonNull) {
|
||||||
|
*nu = NullUUID{}
|
||||||
|
return nil // valid null UUID
|
||||||
|
}
|
||||||
|
err := json.Unmarshal(data, &nu.UUID)
|
||||||
|
nu.Valid = err == nil
|
||||||
|
return err
|
||||||
|
}
|
2
vendor/github.com/google/uuid/sql.go
generated
vendored
2
vendor/github.com/google/uuid/sql.go
generated
vendored
@ -9,7 +9,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Scan implements sql.Scanner so UUIDs can be read from databases transparently
|
// Scan implements sql.Scanner so UUIDs can be read from databases transparently.
|
||||||
// Currently, database types that map to string and []byte are supported. Please
|
// Currently, database types that map to string and []byte are supported. Please
|
||||||
// consult database-specific driver documentation for matching types.
|
// consult database-specific driver documentation for matching types.
|
||||||
func (uuid *UUID) Scan(src interface{}) error {
|
func (uuid *UUID) Scan(src interface{}) error {
|
||||||
|
55
vendor/github.com/google/uuid/uuid.go
generated
vendored
55
vendor/github.com/google/uuid/uuid.go
generated
vendored
@ -12,6 +12,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
|
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
|
||||||
@ -33,7 +34,27 @@ const (
|
|||||||
Future // Reserved for future definition.
|
Future // Reserved for future definition.
|
||||||
)
|
)
|
||||||
|
|
||||||
var rander = rand.Reader // random function
|
const randPoolSize = 16 * 16
|
||||||
|
|
||||||
|
var (
|
||||||
|
rander = rand.Reader // random function
|
||||||
|
poolEnabled = false
|
||||||
|
poolMu sync.Mutex
|
||||||
|
poolPos = randPoolSize // protected with poolMu
|
||||||
|
pool [randPoolSize]byte // protected with poolMu
|
||||||
|
)
|
||||||
|
|
||||||
|
type invalidLengthError struct{ len int }
|
||||||
|
|
||||||
|
func (err invalidLengthError) Error() string {
|
||||||
|
return fmt.Sprintf("invalid UUID length: %d", err.len)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsInvalidLengthError is matcher function for custom error invalidLengthError
|
||||||
|
func IsInvalidLengthError(err error) bool {
|
||||||
|
_, ok := err.(invalidLengthError)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
// Parse decodes s into a UUID or returns an error. Both the standard UUID
|
// Parse decodes s into a UUID or returns an error. Both the standard UUID
|
||||||
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
||||||
@ -68,7 +89,7 @@ func Parse(s string) (UUID, error) {
|
|||||||
}
|
}
|
||||||
return uuid, nil
|
return uuid, nil
|
||||||
default:
|
default:
|
||||||
return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
|
return uuid, invalidLengthError{len(s)}
|
||||||
}
|
}
|
||||||
// s is now at least 36 bytes long
|
// s is now at least 36 bytes long
|
||||||
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
@ -112,7 +133,7 @@ func ParseBytes(b []byte) (UUID, error) {
|
|||||||
}
|
}
|
||||||
return uuid, nil
|
return uuid, nil
|
||||||
default:
|
default:
|
||||||
return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
|
return uuid, invalidLengthError{len(b)}
|
||||||
}
|
}
|
||||||
// s is now at least 36 bytes long
|
// s is now at least 36 bytes long
|
||||||
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
@ -243,3 +264,31 @@ func SetRand(r io.Reader) {
|
|||||||
}
|
}
|
||||||
rander = r
|
rander = r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnableRandPool enables internal randomness pool used for Random
|
||||||
|
// (Version 4) UUID generation. The pool contains random bytes read from
|
||||||
|
// the random number generator on demand in batches. Enabling the pool
|
||||||
|
// may improve the UUID generation throughput significantly.
|
||||||
|
//
|
||||||
|
// Since the pool is stored on the Go heap, this feature may be a bad fit
|
||||||
|
// for security sensitive applications.
|
||||||
|
//
|
||||||
|
// Both EnableRandPool and DisableRandPool are not thread-safe and should
|
||||||
|
// only be called when there is no possibility that New or any other
|
||||||
|
// UUID Version 4 generation function will be called concurrently.
|
||||||
|
func EnableRandPool() {
|
||||||
|
poolEnabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableRandPool disables the randomness pool if it was previously
|
||||||
|
// enabled with EnableRandPool.
|
||||||
|
//
|
||||||
|
// Both EnableRandPool and DisableRandPool are not thread-safe and should
|
||||||
|
// only be called when there is no possibility that New or any other
|
||||||
|
// UUID Version 4 generation function will be called concurrently.
|
||||||
|
func DisableRandPool() {
|
||||||
|
poolEnabled = false
|
||||||
|
defer poolMu.Unlock()
|
||||||
|
poolMu.Lock()
|
||||||
|
poolPos = randPoolSize
|
||||||
|
}
|
||||||
|
35
vendor/github.com/google/uuid/version4.go
generated
vendored
35
vendor/github.com/google/uuid/version4.go
generated
vendored
@ -14,11 +14,21 @@ func New() UUID {
|
|||||||
return Must(NewRandom())
|
return Must(NewRandom())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewString creates a new random UUID and returns it as a string or panics.
|
||||||
|
// NewString is equivalent to the expression
|
||||||
|
//
|
||||||
|
// uuid.New().String()
|
||||||
|
func NewString() string {
|
||||||
|
return Must(NewRandom()).String()
|
||||||
|
}
|
||||||
|
|
||||||
// NewRandom returns a Random (Version 4) UUID.
|
// NewRandom returns a Random (Version 4) UUID.
|
||||||
//
|
//
|
||||||
// The strength of the UUIDs is based on the strength of the crypto/rand
|
// The strength of the UUIDs is based on the strength of the crypto/rand
|
||||||
// package.
|
// package.
|
||||||
//
|
//
|
||||||
|
// Uses the randomness pool if it was enabled with EnableRandPool.
|
||||||
|
//
|
||||||
// A note about uniqueness derived from the UUID Wikipedia entry:
|
// A note about uniqueness derived from the UUID Wikipedia entry:
|
||||||
//
|
//
|
||||||
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
|
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
|
||||||
@ -27,7 +37,10 @@ func New() UUID {
|
|||||||
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
|
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
|
||||||
// year and having one duplicate.
|
// year and having one duplicate.
|
||||||
func NewRandom() (UUID, error) {
|
func NewRandom() (UUID, error) {
|
||||||
return NewRandomFromReader(rander)
|
if !poolEnabled {
|
||||||
|
return NewRandomFromReader(rander)
|
||||||
|
}
|
||||||
|
return newRandomFromPool()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRandomFromReader returns a UUID based on bytes read from a given io.Reader.
|
// NewRandomFromReader returns a UUID based on bytes read from a given io.Reader.
|
||||||
@ -41,3 +54,23 @@ func NewRandomFromReader(r io.Reader) (UUID, error) {
|
|||||||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
|
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
|
||||||
return uuid, nil
|
return uuid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newRandomFromPool() (UUID, error) {
|
||||||
|
var uuid UUID
|
||||||
|
poolMu.Lock()
|
||||||
|
if poolPos == randPoolSize {
|
||||||
|
_, err := io.ReadFull(rander, pool[:])
|
||||||
|
if err != nil {
|
||||||
|
poolMu.Unlock()
|
||||||
|
return Nil, err
|
||||||
|
}
|
||||||
|
poolPos = 0
|
||||||
|
}
|
||||||
|
copy(uuid[:], pool[poolPos:(poolPos+16)])
|
||||||
|
poolPos += 16
|
||||||
|
poolMu.Unlock()
|
||||||
|
|
||||||
|
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
|
||||||
|
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
|
||||||
|
return uuid, nil
|
||||||
|
}
|
||||||
|
9
vendor/github.com/hashicorp/errwrap/errwrap.go
generated
vendored
9
vendor/github.com/hashicorp/errwrap/errwrap.go
generated
vendored
@ -44,6 +44,8 @@ func Wrap(outer, inner error) error {
|
|||||||
//
|
//
|
||||||
// format is the format of the error message. The string '{{err}}' will
|
// format is the format of the error message. The string '{{err}}' will
|
||||||
// be replaced with the original error message.
|
// be replaced with the original error message.
|
||||||
|
//
|
||||||
|
// Deprecated: Use fmt.Errorf()
|
||||||
func Wrapf(format string, err error) error {
|
func Wrapf(format string, err error) error {
|
||||||
outerMsg := "<nil>"
|
outerMsg := "<nil>"
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -148,6 +150,9 @@ func Walk(err error, cb WalkFunc) {
|
|||||||
for _, err := range e.WrappedErrors() {
|
for _, err := range e.WrappedErrors() {
|
||||||
Walk(err, cb)
|
Walk(err, cb)
|
||||||
}
|
}
|
||||||
|
case interface{ Unwrap() error }:
|
||||||
|
cb(err)
|
||||||
|
Walk(e.Unwrap(), cb)
|
||||||
default:
|
default:
|
||||||
cb(err)
|
cb(err)
|
||||||
}
|
}
|
||||||
@ -167,3 +172,7 @@ func (w *wrappedError) Error() string {
|
|||||||
func (w *wrappedError) WrappedErrors() []error {
|
func (w *wrappedError) WrappedErrors() []error {
|
||||||
return []error{w.Outer, w.Inner}
|
return []error{w.Outer, w.Inner}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *wrappedError) Unwrap() error {
|
||||||
|
return w.Inner
|
||||||
|
}
|
||||||
|
70
vendor/github.com/hashicorp/terraform-plugin-docs/internal/cmd/generate.go
generated
vendored
70
vendor/github.com/hashicorp/terraform-plugin-docs/internal/cmd/generate.go
generated
vendored
@ -3,6 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-docs/internal/provider"
|
"github.com/hashicorp/terraform-plugin-docs/internal/provider"
|
||||||
)
|
)
|
||||||
@ -10,8 +11,17 @@ import (
|
|||||||
type generateCmd struct {
|
type generateCmd struct {
|
||||||
commonCmd
|
commonCmd
|
||||||
|
|
||||||
flagLegacySidebar bool
|
flagLegacySidebar bool
|
||||||
tfVersion string
|
flagIgnoreDeprecated bool
|
||||||
|
|
||||||
|
flagProviderName string
|
||||||
|
flagRenderedProviderName string
|
||||||
|
|
||||||
|
flagRenderedWebsiteDir string
|
||||||
|
flagExamplesDir string
|
||||||
|
flagWebsiteTmpDir string
|
||||||
|
flagWebsiteSourceDir string
|
||||||
|
tfVersion string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *generateCmd) Synopsis() string {
|
func (cmd *generateCmd) Synopsis() string {
|
||||||
@ -19,13 +29,54 @@ func (cmd *generateCmd) Synopsis() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *generateCmd) Help() string {
|
func (cmd *generateCmd) Help() string {
|
||||||
return `Usage: tfplugindocs generate`
|
strBuilder := &strings.Builder{}
|
||||||
|
|
||||||
|
longestName := 0
|
||||||
|
longestUsage := 0
|
||||||
|
cmd.Flags().VisitAll(func(f *flag.Flag) {
|
||||||
|
if len(f.Name) > longestName {
|
||||||
|
longestName = len(f.Name)
|
||||||
|
}
|
||||||
|
if len(f.Usage) > longestUsage {
|
||||||
|
longestUsage = len(f.Usage)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
strBuilder.WriteString(fmt.Sprintf("\nUsage: tfplugindocs generate [<args>]\n\n"))
|
||||||
|
cmd.Flags().VisitAll(func(f *flag.Flag) {
|
||||||
|
if f.DefValue != "" {
|
||||||
|
strBuilder.WriteString(fmt.Sprintf(" --%s <ARG> %s%s%s (default: %q)\n",
|
||||||
|
f.Name,
|
||||||
|
strings.Repeat(" ", longestName-len(f.Name)+2),
|
||||||
|
f.Usage,
|
||||||
|
strings.Repeat(" ", longestUsage-len(f.Usage)+2),
|
||||||
|
f.DefValue,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
strBuilder.WriteString(fmt.Sprintf(" --%s <ARG> %s%s%s\n",
|
||||||
|
f.Name,
|
||||||
|
strings.Repeat(" ", longestName-len(f.Name)+2),
|
||||||
|
f.Usage,
|
||||||
|
strings.Repeat(" ", longestUsage-len(f.Usage)+2),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
strBuilder.WriteString("\n")
|
||||||
|
|
||||||
|
return strBuilder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *generateCmd) Flags() *flag.FlagSet {
|
func (cmd *generateCmd) Flags() *flag.FlagSet {
|
||||||
fs := flag.NewFlagSet("generate", flag.ExitOnError)
|
fs := flag.NewFlagSet("generate", flag.ExitOnError)
|
||||||
fs.BoolVar(&cmd.flagLegacySidebar, "legacy-sidebar", false, "generate the legacy .erb sidebar file")
|
fs.BoolVar(&cmd.flagLegacySidebar, "legacy-sidebar", false, "generate the legacy .erb sidebar file")
|
||||||
|
fs.StringVar(&cmd.flagProviderName, "provider-name", "", "provider name, as used in Terraform configurations")
|
||||||
|
fs.StringVar(&cmd.flagRenderedProviderName, "rendered-provider-name", "", "provider name, as generated in documentation (ex. page titles, ...)")
|
||||||
|
fs.StringVar(&cmd.flagRenderedWebsiteDir, "rendered-website-dir", "docs", "output directory")
|
||||||
|
fs.StringVar(&cmd.flagExamplesDir, "examples-dir", "examples", "examples directory")
|
||||||
|
fs.StringVar(&cmd.flagWebsiteTmpDir, "website-temp-dir", "", "temporary directory (used during generation)")
|
||||||
|
fs.StringVar(&cmd.flagWebsiteSourceDir, "website-source-dir", "templates", "templates directory")
|
||||||
fs.StringVar(&cmd.tfVersion, "tf-version", "", "terraform binary version to download")
|
fs.StringVar(&cmd.tfVersion, "tf-version", "", "terraform binary version to download")
|
||||||
|
fs.BoolVar(&cmd.flagIgnoreDeprecated, "ignore-deprecated", false, "don't generate documentation for deprecated resources and data-sources")
|
||||||
return fs
|
return fs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +92,18 @@ func (cmd *generateCmd) Run(args []string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *generateCmd) runInternal() error {
|
func (cmd *generateCmd) runInternal() error {
|
||||||
err := provider.Generate(cmd.ui, cmd.flagLegacySidebar, cmd.tfVersion)
|
err := provider.Generate(
|
||||||
|
cmd.ui,
|
||||||
|
cmd.flagLegacySidebar,
|
||||||
|
cmd.flagProviderName,
|
||||||
|
cmd.flagRenderedProviderName,
|
||||||
|
cmd.flagRenderedWebsiteDir,
|
||||||
|
cmd.flagExamplesDir,
|
||||||
|
cmd.flagWebsiteTmpDir,
|
||||||
|
cmd.flagWebsiteSourceDir,
|
||||||
|
cmd.tfVersion,
|
||||||
|
cmd.flagIgnoreDeprecated,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to generate website: %w", err)
|
return fmt.Errorf("unable to generate website: %w", err)
|
||||||
}
|
}
|
||||||
|
37
vendor/github.com/hashicorp/terraform-plugin-docs/internal/cmd/validate.go
generated
vendored
37
vendor/github.com/hashicorp/terraform-plugin-docs/internal/cmd/validate.go
generated
vendored
@ -3,6 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-docs/internal/provider"
|
"github.com/hashicorp/terraform-plugin-docs/internal/provider"
|
||||||
)
|
)
|
||||||
@ -16,7 +17,41 @@ func (cmd *validateCmd) Synopsis() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *validateCmd) Help() string {
|
func (cmd *validateCmd) Help() string {
|
||||||
return `Usage: tfplugindocs validate`
|
strBuilder := &strings.Builder{}
|
||||||
|
|
||||||
|
longestName := 0
|
||||||
|
longestUsage := 0
|
||||||
|
cmd.Flags().VisitAll(func(f *flag.Flag) {
|
||||||
|
if len(f.Name) > longestName {
|
||||||
|
longestName = len(f.Name)
|
||||||
|
}
|
||||||
|
if len(f.Usage) > longestUsage {
|
||||||
|
longestUsage = len(f.Usage)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
strBuilder.WriteString(fmt.Sprintf("\nUsage: tfplugindocs validate [<args>]\n\n"))
|
||||||
|
cmd.Flags().VisitAll(func(f *flag.Flag) {
|
||||||
|
if f.DefValue != "" {
|
||||||
|
strBuilder.WriteString(fmt.Sprintf(" --%s <ARG> %s%s%s (default: %q)\n",
|
||||||
|
f.Name,
|
||||||
|
strings.Repeat(" ", longestName-len(f.Name)+2),
|
||||||
|
f.Usage,
|
||||||
|
strings.Repeat(" ", longestUsage-len(f.Usage)+2),
|
||||||
|
f.DefValue,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
strBuilder.WriteString(fmt.Sprintf(" --%s <ARG> %s%s%s\n",
|
||||||
|
f.Name,
|
||||||
|
strings.Repeat(" ", longestName-len(f.Name)+2),
|
||||||
|
f.Usage,
|
||||||
|
strings.Repeat(" ", longestUsage-len(f.Usage)+2),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
strBuilder.WriteString("\n")
|
||||||
|
|
||||||
|
return strBuilder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *validateCmd) Flags() *flag.FlagSet {
|
func (cmd *validateCmd) Flags() *flag.FlagSet {
|
||||||
|
129
vendor/github.com/hashicorp/terraform-plugin-docs/internal/provider/generate.go
generated
vendored
129
vendor/github.com/hashicorp/terraform-plugin-docs/internal/provider/generate.go
generated
vendored
@ -22,25 +22,12 @@ import (
|
|||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: convert these to flags?
|
|
||||||
var (
|
var (
|
||||||
providerName string
|
|
||||||
|
|
||||||
// rendered website dir
|
|
||||||
renderedWebsiteDir = "docs"
|
|
||||||
|
|
||||||
// examples directory defaults
|
|
||||||
examplesDir = "examples"
|
|
||||||
// relative to examples dir
|
|
||||||
examplesResourceFileTemplate = resourceFileTemplate("resources/{{.Name}}/resource.tf")
|
examplesResourceFileTemplate = resourceFileTemplate("resources/{{.Name}}/resource.tf")
|
||||||
examplesResourceImportTemplate = resourceFileTemplate("resources/{{.Name}}/import.sh")
|
examplesResourceImportTemplate = resourceFileTemplate("resources/{{.Name}}/import.sh")
|
||||||
examplesDataSourceFileTemplate = resourceFileTemplate("data-sources/{{ .Name }}/data-source.tf")
|
examplesDataSourceFileTemplate = resourceFileTemplate("data-sources/{{ .Name }}/data-source.tf")
|
||||||
examplesProviderFileTemplate = providerFileTemplate("provider/provider.tf")
|
examplesProviderFileTemplate = providerFileTemplate("provider/provider.tf")
|
||||||
|
|
||||||
// templated website directory defaults
|
|
||||||
websiteTmp = ""
|
|
||||||
|
|
||||||
websiteSourceDir = "templates" // used for override content
|
|
||||||
websiteResourceFileTemplate = resourceFileTemplate("resources/{{ .ShortName }}.md.tmpl")
|
websiteResourceFileTemplate = resourceFileTemplate("resources/{{ .ShortName }}.md.tmpl")
|
||||||
websiteResourceFallbackFileTemplate = resourceFileTemplate("resources.md.tmpl")
|
websiteResourceFallbackFileTemplate = resourceFileTemplate("resources.md.tmpl")
|
||||||
websiteResourceFileStatic = []resourceFileTemplate{
|
websiteResourceFileStatic = []resourceFileTemplate{
|
||||||
@ -77,8 +64,16 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type generator struct {
|
type generator struct {
|
||||||
legacySidebar bool
|
ignoreDeprecated bool
|
||||||
tfVersion string
|
legacySidebar bool
|
||||||
|
tfVersion string
|
||||||
|
|
||||||
|
providerName string
|
||||||
|
renderedProviderName string
|
||||||
|
renderedWebsiteDir string
|
||||||
|
examplesDir string
|
||||||
|
websiteTmpDir string
|
||||||
|
websiteSourceDir string
|
||||||
|
|
||||||
ui cli.Ui
|
ui cli.Ui
|
||||||
}
|
}
|
||||||
@ -91,10 +86,18 @@ func (g *generator) warnf(format string, a ...interface{}) {
|
|||||||
g.ui.Warn(fmt.Sprintf(format, a...))
|
g.ui.Warn(fmt.Sprintf(format, a...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Generate(ui cli.Ui, legacySidebar bool, tfVersion string) error {
|
func Generate(ui cli.Ui, legacySidebar bool, providerName, renderedProviderName, renderedWebsiteDir, examplesDir, websiteTmpDir, websiteSourceDir, tfVersion string, ignoreDeprecated bool) error {
|
||||||
g := &generator{
|
g := &generator{
|
||||||
legacySidebar: legacySidebar,
|
ignoreDeprecated: ignoreDeprecated,
|
||||||
tfVersion: tfVersion,
|
legacySidebar: legacySidebar,
|
||||||
|
tfVersion: tfVersion,
|
||||||
|
|
||||||
|
providerName: providerName,
|
||||||
|
renderedProviderName: renderedProviderName,
|
||||||
|
renderedWebsiteDir: renderedWebsiteDir,
|
||||||
|
examplesDir: examplesDir,
|
||||||
|
websiteTmpDir: websiteTmpDir,
|
||||||
|
websiteSourceDir: websiteSourceDir,
|
||||||
|
|
||||||
ui: ui,
|
ui: ui,
|
||||||
}
|
}
|
||||||
@ -112,34 +115,39 @@ func (g *generator) Generate(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if providerName == "" {
|
providerName := g.providerName
|
||||||
|
if g.providerName == "" {
|
||||||
providerName = filepath.Base(wd)
|
providerName = filepath.Base(wd)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.infof("rendering website for provider %q", providerName)
|
if g.renderedProviderName == "" {
|
||||||
|
g.renderedProviderName = providerName
|
||||||
|
}
|
||||||
|
|
||||||
|
g.infof("rendering website for provider %q (as %q)", providerName, g.renderedProviderName)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case websiteTmp == "":
|
case g.websiteTmpDir == "":
|
||||||
websiteTmp, err = ioutil.TempDir("", "tfws")
|
g.websiteTmpDir, err = ioutil.TempDir("", "tfws")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(websiteTmp)
|
defer os.RemoveAll(g.websiteTmpDir)
|
||||||
default:
|
default:
|
||||||
g.infof("cleaning tmp dir %q", websiteTmp)
|
g.infof("cleaning tmp dir %q", g.websiteTmpDir)
|
||||||
err = os.RemoveAll(websiteTmp)
|
err = os.RemoveAll(g.websiteTmpDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
g.infof("creating tmp dir %q", websiteTmp)
|
g.infof("creating tmp dir %q", g.websiteTmpDir)
|
||||||
err = os.MkdirAll(websiteTmp, 0755)
|
err = os.MkdirAll(g.websiteTmpDir, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
websiteSourceDirInfo, err := os.Stat(websiteSourceDir)
|
websiteSourceDirInfo, err := os.Stat(g.websiteSourceDir)
|
||||||
switch {
|
switch {
|
||||||
case os.IsNotExist(err):
|
case os.IsNotExist(err):
|
||||||
// do nothing, no template dir
|
// do nothing, no template dir
|
||||||
@ -147,11 +155,11 @@ func (g *generator) Generate(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
default:
|
default:
|
||||||
if !websiteSourceDirInfo.IsDir() {
|
if !websiteSourceDirInfo.IsDir() {
|
||||||
return fmt.Errorf("template path is not a directory: %s", websiteSourceDir)
|
return fmt.Errorf("template path is not a directory: %s", g.websiteSourceDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.infof("copying any existing content to tmp dir")
|
g.infof("copying any existing content to tmp dir")
|
||||||
err = cp(websiteSourceDir, filepath.Join(websiteTmp, "templates"))
|
err = cp(g.websiteSourceDir, filepath.Join(g.websiteTmpDir, "templates"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -189,7 +197,7 @@ func (g *generator) renderMissingResourceDoc(providerName, name, typeName string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to render path for resource %q: %w", name, err)
|
return fmt.Errorf("unable to render path for resource %q: %w", name, err)
|
||||||
}
|
}
|
||||||
tmplPath = filepath.Join(websiteTmp, websiteSourceDir, tmplPath)
|
tmplPath = filepath.Join(g.websiteTmpDir, g.websiteSourceDir, tmplPath)
|
||||||
if fileExists(tmplPath) {
|
if fileExists(tmplPath) {
|
||||||
g.infof("resource %q template exists, skipping", name)
|
g.infof("resource %q template exists, skipping", name)
|
||||||
return nil
|
return nil
|
||||||
@ -200,7 +208,7 @@ func (g *generator) renderMissingResourceDoc(providerName, name, typeName string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to render path for resource %q: %w", name, err)
|
return fmt.Errorf("unable to render path for resource %q: %w", name, err)
|
||||||
}
|
}
|
||||||
candidatePath = filepath.Join(websiteTmp, websiteSourceDir, candidatePath)
|
candidatePath = filepath.Join(g.websiteTmpDir, g.websiteSourceDir, candidatePath)
|
||||||
if fileExists(candidatePath) {
|
if fileExists(candidatePath) {
|
||||||
g.infof("resource %q static file exists, skipping", name)
|
g.infof("resource %q static file exists, skipping", name)
|
||||||
return nil
|
return nil
|
||||||
@ -212,7 +220,7 @@ func (g *generator) renderMissingResourceDoc(providerName, name, typeName string
|
|||||||
return fmt.Errorf("unable to render example file path for %q: %w", name, err)
|
return fmt.Errorf("unable to render example file path for %q: %w", name, err)
|
||||||
}
|
}
|
||||||
if examplePath != "" {
|
if examplePath != "" {
|
||||||
examplePath = filepath.Join(examplesDir, examplePath)
|
examplePath = filepath.Join(g.examplesDir, examplePath)
|
||||||
}
|
}
|
||||||
if !fileExists(examplePath) {
|
if !fileExists(examplePath) {
|
||||||
examplePath = ""
|
examplePath = ""
|
||||||
@ -225,7 +233,7 @@ func (g *generator) renderMissingResourceDoc(providerName, name, typeName string
|
|||||||
return fmt.Errorf("unable to render example import file path for %q: %w", name, err)
|
return fmt.Errorf("unable to render example import file path for %q: %w", name, err)
|
||||||
}
|
}
|
||||||
if importPath != "" {
|
if importPath != "" {
|
||||||
importPath = filepath.Join(examplesDir, importPath)
|
importPath = filepath.Join(g.examplesDir, importPath)
|
||||||
}
|
}
|
||||||
if !fileExists(importPath) {
|
if !fileExists(importPath) {
|
||||||
importPath = ""
|
importPath = ""
|
||||||
@ -238,7 +246,7 @@ func (g *generator) renderMissingResourceDoc(providerName, name, typeName string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to render path for resource %q: %w", name, err)
|
return fmt.Errorf("unable to render path for resource %q: %w", name, err)
|
||||||
}
|
}
|
||||||
fallbackTmplPath = filepath.Join(websiteTmp, websiteSourceDir, fallbackTmplPath)
|
fallbackTmplPath = filepath.Join(g.websiteTmpDir, g.websiteSourceDir, fallbackTmplPath)
|
||||||
if fileExists(fallbackTmplPath) {
|
if fileExists(fallbackTmplPath) {
|
||||||
g.infof("resource %q fallback template exists", name)
|
g.infof("resource %q fallback template exists", name)
|
||||||
tmplData, err := ioutil.ReadFile(fallbackTmplPath)
|
tmplData, err := ioutil.ReadFile(fallbackTmplPath)
|
||||||
@ -249,7 +257,7 @@ func (g *generator) renderMissingResourceDoc(providerName, name, typeName string
|
|||||||
}
|
}
|
||||||
|
|
||||||
g.infof("generating template for %q", name)
|
g.infof("generating template for %q", name)
|
||||||
md, err := targetResourceTemplate.Render(name, providerName, typeName, examplePath, importPath, schema)
|
md, err := targetResourceTemplate.Render(name, providerName, g.renderedProviderName, typeName, examplePath, importPath, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to render template for %q: %w", name, err)
|
return fmt.Errorf("unable to render template for %q: %w", name, err)
|
||||||
}
|
}
|
||||||
@ -267,7 +275,7 @@ func (g *generator) renderMissingProviderDoc(providerName string, schema *tfjson
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to render path for provider %q: %w", providerName, err)
|
return fmt.Errorf("unable to render path for provider %q: %w", providerName, err)
|
||||||
}
|
}
|
||||||
tmplPath = filepath.Join(websiteTmp, websiteSourceDir, tmplPath)
|
tmplPath = filepath.Join(g.websiteTmpDir, g.websiteSourceDir, tmplPath)
|
||||||
if fileExists(tmplPath) {
|
if fileExists(tmplPath) {
|
||||||
g.infof("provider %q template exists, skipping", providerName)
|
g.infof("provider %q template exists, skipping", providerName)
|
||||||
return nil
|
return nil
|
||||||
@ -278,7 +286,7 @@ func (g *generator) renderMissingProviderDoc(providerName string, schema *tfjson
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to render path for provider %q: %w", providerName, err)
|
return fmt.Errorf("unable to render path for provider %q: %w", providerName, err)
|
||||||
}
|
}
|
||||||
candidatePath = filepath.Join(websiteTmp, websiteSourceDir, candidatePath)
|
candidatePath = filepath.Join(g.websiteTmpDir, g.websiteSourceDir, candidatePath)
|
||||||
if fileExists(candidatePath) {
|
if fileExists(candidatePath) {
|
||||||
g.infof("provider %q static file exists, skipping", providerName)
|
g.infof("provider %q static file exists, skipping", providerName)
|
||||||
return nil
|
return nil
|
||||||
@ -290,14 +298,14 @@ func (g *generator) renderMissingProviderDoc(providerName string, schema *tfjson
|
|||||||
return fmt.Errorf("unable to render example file path for %q: %w", providerName, err)
|
return fmt.Errorf("unable to render example file path for %q: %w", providerName, err)
|
||||||
}
|
}
|
||||||
if examplePath != "" {
|
if examplePath != "" {
|
||||||
examplePath = filepath.Join(examplesDir, examplePath)
|
examplePath = filepath.Join(g.examplesDir, examplePath)
|
||||||
}
|
}
|
||||||
if !fileExists(examplePath) {
|
if !fileExists(examplePath) {
|
||||||
examplePath = ""
|
examplePath = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
g.infof("generating template for %q", providerName)
|
g.infof("generating template for %q", providerName)
|
||||||
md, err := defaultProviderTemplate.Render(providerName, examplePath, schema)
|
md, err := defaultProviderTemplate.Render(providerName, g.renderedProviderName, examplePath, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to render template for %q: %w", providerName, err)
|
return fmt.Errorf("unable to render template for %q: %w", providerName, err)
|
||||||
}
|
}
|
||||||
@ -313,6 +321,10 @@ func (g *generator) renderMissingProviderDoc(providerName string, schema *tfjson
|
|||||||
func (g *generator) renderMissingDocs(providerName string, providerSchema *tfjson.ProviderSchema) error {
|
func (g *generator) renderMissingDocs(providerName string, providerSchema *tfjson.ProviderSchema) error {
|
||||||
g.infof("generating missing resource content")
|
g.infof("generating missing resource content")
|
||||||
for name, schema := range providerSchema.ResourceSchemas {
|
for name, schema := range providerSchema.ResourceSchemas {
|
||||||
|
if g.ignoreDeprecated && schema.Block.Deprecated {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
err := g.renderMissingResourceDoc(providerName, name, "Resource", schema,
|
err := g.renderMissingResourceDoc(providerName, name, "Resource", schema,
|
||||||
websiteResourceFileTemplate,
|
websiteResourceFileTemplate,
|
||||||
websiteResourceFallbackFileTemplate,
|
websiteResourceFallbackFileTemplate,
|
||||||
@ -326,6 +338,10 @@ func (g *generator) renderMissingDocs(providerName string, providerSchema *tfjso
|
|||||||
|
|
||||||
g.infof("generating missing data source content")
|
g.infof("generating missing data source content")
|
||||||
for name, schema := range providerSchema.DataSourceSchemas {
|
for name, schema := range providerSchema.DataSourceSchemas {
|
||||||
|
if g.ignoreDeprecated && schema.Block.Deprecated {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
err := g.renderMissingResourceDoc(providerName, name, "Data Source", schema,
|
err := g.renderMissingResourceDoc(providerName, name, "Data Source", schema,
|
||||||
websiteDataSourceFileTemplate,
|
websiteDataSourceFileTemplate,
|
||||||
websiteDataSourceFallbackFileTemplate,
|
websiteDataSourceFallbackFileTemplate,
|
||||||
@ -352,7 +368,7 @@ func (g *generator) renderMissingDocs(providerName string, providerSchema *tfjso
|
|||||||
|
|
||||||
func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfjson.ProviderSchema) error {
|
func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfjson.ProviderSchema) error {
|
||||||
g.infof("cleaning rendered website dir")
|
g.infof("cleaning rendered website dir")
|
||||||
err := os.RemoveAll(renderedWebsiteDir)
|
err := os.RemoveAll(g.renderedWebsiteDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -361,13 +377,13 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj
|
|||||||
|
|
||||||
g.infof("rendering templated website to static markdown")
|
g.infof("rendering templated website to static markdown")
|
||||||
|
|
||||||
err = filepath.Walk(websiteTmp, func(path string, info os.FileInfo, err error) error {
|
err = filepath.Walk(g.websiteTmpDir, func(path string, info os.FileInfo, err error) error {
|
||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
// skip directories
|
// skip directories
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rel, err := filepath.Rel(filepath.Join(websiteTmp, websiteSourceDir), path)
|
rel, err := filepath.Rel(filepath.Join(g.websiteTmpDir, g.websiteSourceDir), path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -380,7 +396,7 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
renderedPath := filepath.Join(renderedWebsiteDir, rel)
|
renderedPath := filepath.Join(g.renderedWebsiteDir, rel)
|
||||||
err = os.MkdirAll(filepath.Dir(renderedPath), 0755)
|
err = os.MkdirAll(filepath.Dir(renderedPath), 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -408,11 +424,11 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj
|
|||||||
g.infof("rendering %q", rel)
|
g.infof("rendering %q", rel)
|
||||||
switch relDir {
|
switch relDir {
|
||||||
case "data-sources/":
|
case "data-sources/":
|
||||||
resName := shortName + "_" + removeAllExt(relFile)
|
resSchema, resName := resourceSchema(providerSchema.DataSourceSchemas, shortName, relFile)
|
||||||
resSchema, ok := providerSchema.DataSourceSchemas[resName]
|
exampleFilePath := filepath.Join(g.examplesDir, "data-sources", resName, "data-source.tf")
|
||||||
if ok {
|
if resSchema != nil {
|
||||||
tmpl := resourceTemplate(tmplData)
|
tmpl := resourceTemplate(tmplData)
|
||||||
render, err := tmpl.Render(resName, providerName, "Data Source", "", "", resSchema)
|
render, err := tmpl.Render(resName, providerName, g.renderedProviderName, "Data Source", exampleFilePath, "", resSchema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to render data source template %q: %w", rel, err)
|
return fmt.Errorf("unable to render data source template %q: %w", rel, err)
|
||||||
}
|
}
|
||||||
@ -422,12 +438,15 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
g.warnf("data source entitled %q, or %q does not exist", shortName, resName)
|
||||||
case "resources/":
|
case "resources/":
|
||||||
resName := shortName + "_" + removeAllExt(relFile)
|
resSchema, resName := resourceSchema(providerSchema.ResourceSchemas, shortName, relFile)
|
||||||
resSchema, ok := providerSchema.ResourceSchemas[resName]
|
exampleFilePath := filepath.Join(g.examplesDir, "resources", resName, "resource.tf")
|
||||||
if ok {
|
importFilePath := filepath.Join(g.examplesDir, "resources", resName, "import.sh")
|
||||||
|
|
||||||
|
if resSchema != nil {
|
||||||
tmpl := resourceTemplate(tmplData)
|
tmpl := resourceTemplate(tmplData)
|
||||||
render, err := tmpl.Render(resName, providerName, "Resource", "", "", resSchema)
|
render, err := tmpl.Render(resName, providerName, g.renderedProviderName, "Resource", exampleFilePath, importFilePath, resSchema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to render resource template %q: %w", rel, err)
|
return fmt.Errorf("unable to render resource template %q: %w", rel, err)
|
||||||
}
|
}
|
||||||
@ -437,10 +456,12 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
g.warnf("resource entitled %q, or %q does not exist", shortName, resName)
|
||||||
case "": // provider
|
case "": // provider
|
||||||
if relFile == "index.md.tmpl" {
|
if relFile == "index.md.tmpl" {
|
||||||
tmpl := providerTemplate(tmplData)
|
tmpl := providerTemplate(tmplData)
|
||||||
render, err := tmpl.Render(providerName, "", providerSchema.ConfigSchema)
|
exampleFilePath := filepath.Join(g.examplesDir, "provider", "provider.tf")
|
||||||
|
render, err := tmpl.Render(providerName, g.renderedProviderName, exampleFilePath, providerSchema.ConfigSchema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to render provider template %q: %w", rel, err)
|
return fmt.Errorf("unable to render provider template %q: %w", rel, err)
|
||||||
}
|
}
|
||||||
@ -505,7 +526,7 @@ provider %[1]q {
|
|||||||
}
|
}
|
||||||
|
|
||||||
i := install.NewInstaller()
|
i := install.NewInstaller()
|
||||||
sources := []src.Source{}
|
var sources []src.Source
|
||||||
if g.tfVersion != "" {
|
if g.tfVersion != "" {
|
||||||
g.infof("downloading Terraform CLI binary version from releases.hashicorp.com: %s", g.tfVersion)
|
g.infof("downloading Terraform CLI binary version from releases.hashicorp.com: %s", g.tfVersion)
|
||||||
sources = []src.Source{
|
sources = []src.Source{
|
||||||
|
48
vendor/github.com/hashicorp/terraform-plugin-docs/internal/provider/template.go
generated
vendored
48
vendor/github.com/hashicorp/terraform-plugin-docs/internal/provider/template.go
generated
vendored
@ -7,7 +7,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"golang.org/x/text/cases"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
tfjson "github.com/hashicorp/terraform-json"
|
tfjson "github.com/hashicorp/terraform-json"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-docs/internal/mdplain"
|
"github.com/hashicorp/terraform-plugin-docs/internal/mdplain"
|
||||||
"github.com/hashicorp/terraform-plugin-docs/internal/tmplfuncs"
|
"github.com/hashicorp/terraform-plugin-docs/internal/tmplfuncs"
|
||||||
"github.com/hashicorp/terraform-plugin-docs/schemamd"
|
"github.com/hashicorp/terraform-plugin-docs/schemamd"
|
||||||
@ -30,17 +34,19 @@ type (
|
|||||||
|
|
||||||
func newTemplate(name, text string) (*template.Template, error) {
|
func newTemplate(name, text string) (*template.Template, error) {
|
||||||
tmpl := template.New(name)
|
tmpl := template.New(name)
|
||||||
|
titleCaser := cases.Title(language.Und)
|
||||||
|
|
||||||
tmpl.Funcs(template.FuncMap(map[string]interface{}{
|
tmpl.Funcs(map[string]interface{}{
|
||||||
"codefile": tmplfuncs.CodeFile,
|
"codefile": tmplfuncs.CodeFile,
|
||||||
|
"lower": strings.ToLower,
|
||||||
"plainmarkdown": mdplain.PlainMarkdown,
|
"plainmarkdown": mdplain.PlainMarkdown,
|
||||||
"prefixlines": tmplfuncs.PrefixLines,
|
"prefixlines": tmplfuncs.PrefixLines,
|
||||||
"tffile": func(file string) (string, error) {
|
"split": strings.Split,
|
||||||
// TODO: omit comment handling
|
"tffile": terraformCodeFile,
|
||||||
return tmplfuncs.CodeFile("terraform", file)
|
"title": titleCaser.String,
|
||||||
},
|
"trimspace": strings.TrimSpace,
|
||||||
"trimspace": strings.TrimSpace,
|
"upper": strings.ToUpper,
|
||||||
}))
|
})
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
tmpl, err = tmpl.Parse(text)
|
tmpl, err = tmpl.Parse(text)
|
||||||
@ -51,6 +57,11 @@ func newTemplate(name, text string) (*template.Template, error) {
|
|||||||
return tmpl, nil
|
return tmpl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func terraformCodeFile(file string) (string, error) {
|
||||||
|
// TODO: omit comment handling
|
||||||
|
return tmplfuncs.CodeFile("terraform", file)
|
||||||
|
}
|
||||||
|
|
||||||
func renderTemplate(name string, text string, out io.Writer, data interface{}) error {
|
func renderTemplate(name string, text string, out io.Writer, data interface{}) error {
|
||||||
tmpl, err := newTemplate(name, text)
|
tmpl, err := newTemplate(name, text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -116,7 +127,7 @@ func (t providerFileTemplate) Render(name string) (string, error) {
|
|||||||
}{name, providerShortName(name)})
|
}{name, providerShortName(name)})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t providerTemplate) Render(providerName, exampleFile string, schema *tfjson.Schema) (string, error) {
|
func (t providerTemplate) Render(providerName, renderedProviderName, exampleFile string, schema *tfjson.Schema) (string, error) {
|
||||||
schemaBuffer := bytes.NewBuffer(nil)
|
schemaBuffer := bytes.NewBuffer(nil)
|
||||||
err := schemamd.Render(schema, schemaBuffer)
|
err := schemamd.Render(schema, schemaBuffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -128,34 +139,33 @@ func (t providerTemplate) Render(providerName, exampleFile string, schema *tfjso
|
|||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return renderStringTemplate("providerTemplate", s, struct {
|
return renderStringTemplate("providerTemplate", s, struct {
|
||||||
Type string
|
|
||||||
Name string
|
|
||||||
Description string
|
Description string
|
||||||
|
|
||||||
HasExample bool
|
HasExample bool
|
||||||
ExampleFile string
|
ExampleFile string
|
||||||
|
|
||||||
HasImport bool
|
|
||||||
ImportFile string
|
|
||||||
|
|
||||||
ProviderName string
|
ProviderName string
|
||||||
ProviderShortName string
|
ProviderShortName string
|
||||||
|
|
||||||
SchemaMarkdown string
|
SchemaMarkdown string
|
||||||
|
|
||||||
|
RenderedProviderName string
|
||||||
}{
|
}{
|
||||||
Description: schema.Block.Description,
|
Description: schema.Block.Description,
|
||||||
|
|
||||||
HasExample: exampleFile != "",
|
HasExample: exampleFile != "" && fileExists(exampleFile),
|
||||||
ExampleFile: exampleFile,
|
ExampleFile: exampleFile,
|
||||||
|
|
||||||
ProviderName: providerName,
|
ProviderName: providerName,
|
||||||
ProviderShortName: providerShortName(providerName),
|
ProviderShortName: providerShortName(providerName),
|
||||||
|
|
||||||
SchemaMarkdown: schemaComment + "\n" + schemaBuffer.String(),
|
SchemaMarkdown: schemaComment + "\n" + schemaBuffer.String(),
|
||||||
|
|
||||||
|
RenderedProviderName: renderedProviderName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t resourceTemplate) Render(name, providerName, typeName, exampleFile, importFile string, schema *tfjson.Schema) (string, error) {
|
func (t resourceTemplate) Render(name, providerName, renderedProviderName, typeName, exampleFile, importFile string, schema *tfjson.Schema) (string, error) {
|
||||||
schemaBuffer := bytes.NewBuffer(nil)
|
schemaBuffer := bytes.NewBuffer(nil)
|
||||||
err := schemamd.Render(schema, schemaBuffer)
|
err := schemamd.Render(schema, schemaBuffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -182,21 +192,25 @@ func (t resourceTemplate) Render(name, providerName, typeName, exampleFile, impo
|
|||||||
ProviderShortName string
|
ProviderShortName string
|
||||||
|
|
||||||
SchemaMarkdown string
|
SchemaMarkdown string
|
||||||
|
|
||||||
|
RenderedProviderName string
|
||||||
}{
|
}{
|
||||||
Type: typeName,
|
Type: typeName,
|
||||||
Name: name,
|
Name: name,
|
||||||
Description: schema.Block.Description,
|
Description: schema.Block.Description,
|
||||||
|
|
||||||
HasExample: exampleFile != "",
|
HasExample: exampleFile != "" && fileExists(exampleFile),
|
||||||
ExampleFile: exampleFile,
|
ExampleFile: exampleFile,
|
||||||
|
|
||||||
HasImport: importFile != "",
|
HasImport: importFile != "" && fileExists(importFile),
|
||||||
ImportFile: importFile,
|
ImportFile: importFile,
|
||||||
|
|
||||||
ProviderName: providerName,
|
ProviderName: providerName,
|
||||||
ProviderShortName: providerShortName(providerName),
|
ProviderShortName: providerShortName(providerName),
|
||||||
|
|
||||||
SchemaMarkdown: schemaComment + "\n" + schemaBuffer.String(),
|
SchemaMarkdown: schemaComment + "\n" + schemaBuffer.String(),
|
||||||
|
|
||||||
|
RenderedProviderName: renderedProviderName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
vendor/github.com/hashicorp/terraform-plugin-docs/internal/provider/util.go
generated
vendored
19
vendor/github.com/hashicorp/terraform-plugin-docs/internal/provider/util.go
generated
vendored
@ -9,6 +9,8 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
tfjson "github.com/hashicorp/terraform-json"
|
||||||
)
|
)
|
||||||
|
|
||||||
func providerShortName(n string) string {
|
func providerShortName(n string) string {
|
||||||
@ -52,6 +54,23 @@ func removeAllExt(file string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resourceSchema determines whether there is a schema in the supplied schemas map which
|
||||||
|
// has either the providerShortName or the providerShortName concatenated with the
|
||||||
|
// templateFileName (stripped of file extension.
|
||||||
|
func resourceSchema(schemas map[string]*tfjson.Schema, providerShortName, templateFileName string) (*tfjson.Schema, string) {
|
||||||
|
if schema, ok := schemas[providerShortName]; ok {
|
||||||
|
return schema, providerShortName
|
||||||
|
}
|
||||||
|
|
||||||
|
resName := providerShortName + "_" + removeAllExt(templateFileName)
|
||||||
|
|
||||||
|
if schema, ok := schemas[resName]; ok {
|
||||||
|
return schema, resName
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, resName
|
||||||
|
}
|
||||||
|
|
||||||
func writeFile(path string, data string) error {
|
func writeFile(path string, data string) error {
|
||||||
dir, _ := filepath.Split(path)
|
dir, _ := filepath.Split(path)
|
||||||
err := os.MkdirAll(dir, 0755)
|
err := os.MkdirAll(dir, 0755)
|
||||||
|
7
vendor/github.com/hashicorp/terraform-plugin-docs/schemamd/behaviors.go
generated
vendored
7
vendor/github.com/hashicorp/terraform-plugin-docs/schemamd/behaviors.go
generated
vendored
@ -16,12 +16,17 @@ func childAttributeIsOptional(att *tfjson.SchemaAttribute) bool {
|
|||||||
return att.Optional
|
return att.Optional
|
||||||
}
|
}
|
||||||
|
|
||||||
// childBlockIsOptional returns true for blocks with with min items 0 and any required or optional children.
|
// childBlockIsOptional returns true for blocks with with min items 0
|
||||||
|
// which are either empty or have any required or optional children.
|
||||||
func childBlockIsOptional(block *tfjson.SchemaBlockType) bool {
|
func childBlockIsOptional(block *tfjson.SchemaBlockType) bool {
|
||||||
if block.MinItems > 0 {
|
if block.MinItems > 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(block.Block.NestedBlocks) == 0 && len(block.Block.Attributes) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
for _, childBlock := range block.Block.NestedBlocks {
|
for _, childBlock := range block.Block.NestedBlocks {
|
||||||
if childBlockIsRequired(childBlock) {
|
if childBlockIsRequired(childBlock) {
|
||||||
return true
|
return true
|
||||||
|
74
vendor/github.com/hashicorp/terraform-plugin-docs/schemamd/render.go
generated
vendored
74
vendor/github.com/hashicorp/terraform-plugin-docs/schemamd/render.go
generated
vendored
@ -70,10 +70,6 @@ func writeAttribute(w io.Writer, path []string, att *tfjson.SchemaAttribute, gro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if name == "id" && att.Description == "" {
|
|
||||||
att.Description = "The ID of this resource."
|
|
||||||
}
|
|
||||||
|
|
||||||
if att.AttributeNestedType == nil {
|
if att.AttributeNestedType == nil {
|
||||||
err = WriteAttributeDescription(w, att, false)
|
err = WriteAttributeDescription(w, att, false)
|
||||||
} else {
|
} else {
|
||||||
@ -225,7 +221,18 @@ nameLoop:
|
|||||||
}
|
}
|
||||||
} else if childAtt, ok := block.Attributes[n]; ok {
|
} else if childAtt, ok := block.Attributes[n]; ok {
|
||||||
for i, gf := range groupFilters {
|
for i, gf := range groupFilters {
|
||||||
if gf.filterAttribute(childAtt) {
|
// By default, the attribute `id` is place in the "Read-Only" group
|
||||||
|
// if the provider schema contained no `.Description` for it.
|
||||||
|
//
|
||||||
|
// If a `.Description` is provided instead, the behaviour will be the
|
||||||
|
// same as for every other attribute.
|
||||||
|
if strings.ToLower(n) == "id" && childAtt.Description == "" {
|
||||||
|
if strings.Contains(gf.topLevelTitle, "Read-Only") {
|
||||||
|
childAtt.Description = "The ID of this resource."
|
||||||
|
groups[i] = append(groups[i], n)
|
||||||
|
continue nameLoop
|
||||||
|
}
|
||||||
|
} else if gf.filterAttribute(childAtt) {
|
||||||
groups[i] = append(groups[i], n)
|
groups[i] = append(groups[i], n)
|
||||||
continue nameLoop
|
continue nameLoop
|
||||||
}
|
}
|
||||||
@ -286,7 +293,9 @@ nameLoop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range sortedNames {
|
for _, name := range sortedNames {
|
||||||
path := append(parents, name)
|
path := make([]string, len(parents), len(parents)+1)
|
||||||
|
copy(path, parents)
|
||||||
|
path = append(path, name)
|
||||||
|
|
||||||
if childBlock, ok := block.NestedBlocks[name]; ok {
|
if childBlock, ok := block.NestedBlocks[name]; ok {
|
||||||
nt, err := writeBlockType(w, path, childBlock)
|
nt, err := writeBlockType(w, path, childBlock)
|
||||||
@ -466,36 +475,55 @@ func writeObjectChildren(w io.Writer, parents []string, ty cty.Type, group group
|
|||||||
}
|
}
|
||||||
|
|
||||||
func writeNestedAttributeChildren(w io.Writer, parents []string, nestedAttributes *tfjson.SchemaNestedAttributeType, group groupFilter) error {
|
func writeNestedAttributeChildren(w io.Writer, parents []string, nestedAttributes *tfjson.SchemaNestedAttributeType, group groupFilter) error {
|
||||||
_, err := io.WriteString(w, group.nestedTitle+"\n\n")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
sortedNames := []string{}
|
sortedNames := []string{}
|
||||||
for n := range nestedAttributes.Attributes {
|
for n := range nestedAttributes.Attributes {
|
||||||
sortedNames = append(sortedNames, n)
|
sortedNames = append(sortedNames, n)
|
||||||
}
|
}
|
||||||
sort.Strings(sortedNames)
|
sort.Strings(sortedNames)
|
||||||
nestedTypes := []nestedType{}
|
|
||||||
|
|
||||||
|
groups := map[int][]string{}
|
||||||
for _, name := range sortedNames {
|
for _, name := range sortedNames {
|
||||||
att := nestedAttributes.Attributes[name]
|
att := nestedAttributes.Attributes[name]
|
||||||
path := append(parents, name)
|
|
||||||
|
|
||||||
nt, err := writeAttribute(w, path, att, group)
|
for i, gf := range groupFilters {
|
||||||
if err != nil {
|
if gf.filterAttribute(att) {
|
||||||
return fmt.Errorf("unable to render attribute %q: %w", name, err)
|
groups[i] = append(groups[i], name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nestedTypes := []nestedType{}
|
||||||
|
|
||||||
|
for i, gf := range groupFilters {
|
||||||
|
names, ok := groups[i]
|
||||||
|
if !ok || len(names) == 0 {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
nestedTypes = append(nestedTypes, nt...)
|
_, err := io.WriteString(w, gf.nestedTitle+"\n\n")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
att := nestedAttributes.Attributes[name]
|
||||||
|
path := append(parents, name)
|
||||||
|
|
||||||
|
nt, err := writeAttribute(w, path, att, group)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to render attribute %q: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
nestedTypes = append(nestedTypes, nt...)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.WriteString(w, "\n")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = io.WriteString(w, "\n")
|
err := writeNestedTypes(w, nestedTypes)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = writeNestedTypes(w, nestedTypes)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
32
vendor/github.com/imdario/mergo/README.md
generated
vendored
32
vendor/github.com/imdario/mergo/README.md
generated
vendored
@ -8,8 +8,7 @@
|
|||||||
[![Coverage Status][9]][10]
|
[![Coverage Status][9]][10]
|
||||||
[![Sourcegraph][11]][12]
|
[![Sourcegraph][11]][12]
|
||||||
[![FOSSA Status][13]][14]
|
[![FOSSA Status][13]][14]
|
||||||
|
[![Become my sponsor][15]][16]
|
||||||
[![GoCenter Kudos][15]][16]
|
|
||||||
|
|
||||||
[1]: https://travis-ci.org/imdario/mergo.png
|
[1]: https://travis-ci.org/imdario/mergo.png
|
||||||
[2]: https://travis-ci.org/imdario/mergo
|
[2]: https://travis-ci.org/imdario/mergo
|
||||||
@ -25,8 +24,8 @@
|
|||||||
[12]: https://sourcegraph.com/github.com/imdario/mergo?badge
|
[12]: https://sourcegraph.com/github.com/imdario/mergo?badge
|
||||||
[13]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=shield
|
[13]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=shield
|
||||||
[14]: https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_shield
|
[14]: https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_shield
|
||||||
[15]: https://search.gocenter.io/api/ui/badge/github.com%2Fimdario%2Fmergo
|
[15]: https://img.shields.io/github/sponsors/imdario
|
||||||
[16]: https://search.gocenter.io/github.com/imdario/mergo
|
[16]: https://github.com/sponsors/imdario
|
||||||
|
|
||||||
A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements.
|
A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements.
|
||||||
|
|
||||||
@ -36,11 +35,11 @@ Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the
|
|||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
It is ready for production use. [It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, etc](https://github.com/imdario/mergo#mergo-in-the-wild).
|
It is ready for production use. [It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, Microsoft, etc](https://github.com/imdario/mergo#mergo-in-the-wild).
|
||||||
|
|
||||||
### Important note
|
### Important note
|
||||||
|
|
||||||
Please keep in mind that a problematic PR broke [0.3.9](//github.com/imdario/mergo/releases/tag/0.3.9). I reverted it in [0.3.10](//github.com/imdario/mergo/releases/tag/0.3.10), and I consider it stable but not bug-free. Also, this version adds suppot for go modules.
|
Please keep in mind that a problematic PR broke [0.3.9](//github.com/imdario/mergo/releases/tag/0.3.9). I reverted it in [0.3.10](//github.com/imdario/mergo/releases/tag/0.3.10), and I consider it stable but not bug-free. Also, this version adds support for go modules.
|
||||||
|
|
||||||
Keep in mind that in [0.3.2](//github.com/imdario/mergo/releases/tag/0.3.2), Mergo changed `Merge()`and `Map()` signatures to support [transformers](#transformers). I added an optional/variadic argument so that it won't break the existing code.
|
Keep in mind that in [0.3.2](//github.com/imdario/mergo/releases/tag/0.3.2), Mergo changed `Merge()`and `Map()` signatures to support [transformers](#transformers). I added an optional/variadic argument so that it won't break the existing code.
|
||||||
|
|
||||||
@ -51,12 +50,12 @@ If you were using Mergo before April 6th, 2015, please check your project works
|
|||||||
If Mergo is useful to you, consider buying me a coffee, a beer, or making a monthly donation to allow me to keep building great free software. :heart_eyes:
|
If Mergo is useful to you, consider buying me a coffee, a beer, or making a monthly donation to allow me to keep building great free software. :heart_eyes:
|
||||||
|
|
||||||
<a href='https://ko-fi.com/B0B58839' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=0' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
<a href='https://ko-fi.com/B0B58839' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=0' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
||||||
[![Beerpay](https://beerpay.io/imdario/mergo/badge.svg)](https://beerpay.io/imdario/mergo)
|
|
||||||
[![Beerpay](https://beerpay.io/imdario/mergo/make-wish.svg)](https://beerpay.io/imdario/mergo)
|
|
||||||
<a href="https://liberapay.com/dario/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
|
<a href="https://liberapay.com/dario/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
|
||||||
|
<a href='https://github.com/sponsors/imdario' target='_blank'><img alt="Become my sponsor" src="https://img.shields.io/github/sponsors/imdario?style=for-the-badge" /></a>
|
||||||
|
|
||||||
### Mergo in the wild
|
### Mergo in the wild
|
||||||
|
|
||||||
|
- [cli/cli](https://github.com/cli/cli)
|
||||||
- [moby/moby](https://github.com/moby/moby)
|
- [moby/moby](https://github.com/moby/moby)
|
||||||
- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
|
- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
|
||||||
- [vmware/dispatch](https://github.com/vmware/dispatch)
|
- [vmware/dispatch](https://github.com/vmware/dispatch)
|
||||||
@ -98,6 +97,8 @@ If Mergo is useful to you, consider buying me a coffee, a beer, or making a mont
|
|||||||
- [jnuthong/item_search](https://github.com/jnuthong/item_search)
|
- [jnuthong/item_search](https://github.com/jnuthong/item_search)
|
||||||
- [bukalapak/snowboard](https://github.com/bukalapak/snowboard)
|
- [bukalapak/snowboard](https://github.com/bukalapak/snowboard)
|
||||||
- [containerssh/containerssh](https://github.com/containerssh/containerssh)
|
- [containerssh/containerssh](https://github.com/containerssh/containerssh)
|
||||||
|
- [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
|
||||||
|
- [tjpnz/structbot](https://github.com/tjpnz/structbot)
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
@ -168,7 +169,7 @@ func main() {
|
|||||||
|
|
||||||
Note: if test are failing due missing package, please execute:
|
Note: if test are failing due missing package, please execute:
|
||||||
|
|
||||||
go get gopkg.in/yaml.v2
|
go get gopkg.in/yaml.v3
|
||||||
|
|
||||||
### Transformers
|
### Transformers
|
||||||
|
|
||||||
@ -218,7 +219,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Contact me
|
## Contact me
|
||||||
|
|
||||||
If I can help you, you have an idea or you are using Mergo in your projects, don't hesitate to drop me a line (or a pull request): [@im_dario](https://twitter.com/im_dario)
|
If I can help you, you have an idea or you are using Mergo in your projects, don't hesitate to drop me a line (or a pull request): [@im_dario](https://twitter.com/im_dario)
|
||||||
@ -227,18 +227,6 @@ If I can help you, you have an idea or you are using Mergo in your projects, don
|
|||||||
|
|
||||||
Written by [Dario Castañé](http://dario.im).
|
Written by [Dario Castañé](http://dario.im).
|
||||||
|
|
||||||
## Top Contributors
|
|
||||||
|
|
||||||
[![0](https://sourcerer.io/fame/imdario/imdario/mergo/images/0)](https://sourcerer.io/fame/imdario/imdario/mergo/links/0)
|
|
||||||
[![1](https://sourcerer.io/fame/imdario/imdario/mergo/images/1)](https://sourcerer.io/fame/imdario/imdario/mergo/links/1)
|
|
||||||
[![2](https://sourcerer.io/fame/imdario/imdario/mergo/images/2)](https://sourcerer.io/fame/imdario/imdario/mergo/links/2)
|
|
||||||
[![3](https://sourcerer.io/fame/imdario/imdario/mergo/images/3)](https://sourcerer.io/fame/imdario/imdario/mergo/links/3)
|
|
||||||
[![4](https://sourcerer.io/fame/imdario/imdario/mergo/images/4)](https://sourcerer.io/fame/imdario/imdario/mergo/links/4)
|
|
||||||
[![5](https://sourcerer.io/fame/imdario/imdario/mergo/images/5)](https://sourcerer.io/fame/imdario/imdario/mergo/links/5)
|
|
||||||
[![6](https://sourcerer.io/fame/imdario/imdario/mergo/images/6)](https://sourcerer.io/fame/imdario/imdario/mergo/links/6)
|
|
||||||
[![7](https://sourcerer.io/fame/imdario/imdario/mergo/images/7)](https://sourcerer.io/fame/imdario/imdario/mergo/links/7)
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE).
|
[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE).
|
||||||
|
2
vendor/github.com/imdario/mergo/merge.go
generated
vendored
2
vendor/github.com/imdario/mergo/merge.go
generated
vendored
@ -79,7 +79,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
|||||||
visited[h] = &visit{addr, typ, seen}
|
visited[h] = &visit{addr, typ, seen}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Transformers != nil && !isEmptyValue(dst) {
|
if config.Transformers != nil && !isReflectNil(dst) && dst.IsValid() {
|
||||||
if fn := config.Transformers.Transformer(dst.Type()); fn != nil {
|
if fn := config.Transformers.Transformer(dst.Type()); fn != nil {
|
||||||
err = fn(dst, src)
|
err = fn(dst, src)
|
||||||
return
|
return
|
||||||
|
4
vendor/github.com/imdario/mergo/mergo.go
generated
vendored
4
vendor/github.com/imdario/mergo/mergo.go
generated
vendored
@ -17,7 +17,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
ErrNilArguments = errors.New("src and dst must not be nil")
|
ErrNilArguments = errors.New("src and dst must not be nil")
|
||||||
ErrDifferentArgumentsTypes = errors.New("src and dst must be of same type")
|
ErrDifferentArgumentsTypes = errors.New("src and dst must be of same type")
|
||||||
ErrNotSupported = errors.New("only structs and maps are supported")
|
ErrNotSupported = errors.New("only structs, maps, and slices are supported")
|
||||||
ErrExpectedMapAsDestination = errors.New("dst was expected to be a map")
|
ErrExpectedMapAsDestination = errors.New("dst was expected to be a map")
|
||||||
ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct")
|
ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct")
|
||||||
ErrNonPointerAgument = errors.New("dst must be a pointer")
|
ErrNonPointerAgument = errors.New("dst must be a pointer")
|
||||||
@ -65,7 +65,7 @@ func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
vDst = reflect.ValueOf(dst).Elem()
|
vDst = reflect.ValueOf(dst).Elem()
|
||||||
if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map {
|
if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map && vDst.Kind() != reflect.Slice {
|
||||||
err = ErrNotSupported
|
err = ErrNotSupported
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
16
vendor/github.com/mitchellh/cli/.travis.yml
generated
vendored
16
vendor/github.com/mitchellh/cli/.travis.yml
generated
vendored
@ -1,16 +0,0 @@
|
|||||||
sudo: false
|
|
||||||
|
|
||||||
language: go
|
|
||||||
|
|
||||||
env:
|
|
||||||
- GO111MODULE=on
|
|
||||||
|
|
||||||
go:
|
|
||||||
- "1.14"
|
|
||||||
- "1.15"
|
|
||||||
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
|
|
||||||
script: make updatedeps test testrace
|
|
11
vendor/github.com/mitchellh/cli/README.md
generated
vendored
11
vendor/github.com/mitchellh/cli/README.md
generated
vendored
@ -1,13 +1,12 @@
|
|||||||
# Go CLI Library [![GoDoc](https://godoc.org/github.com/mitchellh/cli?status.png)](https://godoc.org/github.com/mitchellh/cli)
|
# Go CLI Library [![GoDoc](https://godoc.org/github.com/mitchellh/cli?status.png)](https://pkg.go.dev/github.com/mitchellh/cli)
|
||||||
|
|
||||||
cli is a library for implementing powerful command-line interfaces in Go.
|
cli is a library for implementing command-line interfaces in Go.
|
||||||
cli is the library that powers the CLI for
|
cli is the library that powers the CLI for
|
||||||
[Packer](https://github.com/mitchellh/packer),
|
[Packer](https://github.com/mitchellh/packer),
|
||||||
[Serf](https://github.com/hashicorp/serf),
|
|
||||||
[Consul](https://github.com/hashicorp/consul),
|
[Consul](https://github.com/hashicorp/consul),
|
||||||
[Vault](https://github.com/hashicorp/vault),
|
[Vault](https://github.com/hashicorp/vault),
|
||||||
[Terraform](https://github.com/hashicorp/terraform), and
|
[Terraform](https://github.com/hashicorp/terraform),
|
||||||
[Nomad](https://github.com/hashicorp/nomad).
|
[Nomad](https://github.com/hashicorp/nomad), and more.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@ -21,7 +20,7 @@ cli is the library that powers the CLI for
|
|||||||
* Support for shell autocompletion of subcommands, flags, and arguments
|
* Support for shell autocompletion of subcommands, flags, and arguments
|
||||||
with callbacks in Go. You don't need to write any shell code.
|
with callbacks in Go. You don't need to write any shell code.
|
||||||
|
|
||||||
* Automatic help generation for listing subcommands
|
* Automatic help generation for listing subcommands.
|
||||||
|
|
||||||
* Automatic help flag recognition of `-h`, `--help`, etc.
|
* Automatic help flag recognition of `-h`, `--help`, etc.
|
||||||
|
|
||||||
|
11
vendor/github.com/mitchellh/cli/cli.go
generated
vendored
11
vendor/github.com/mitchellh/cli/cli.go
generated
vendored
@ -11,7 +11,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/Masterminds/sprig"
|
"github.com/Masterminds/sprig/v3"
|
||||||
"github.com/armon/go-radix"
|
"github.com/armon/go-radix"
|
||||||
"github.com/posener/complete"
|
"github.com/posener/complete"
|
||||||
)
|
)
|
||||||
@ -680,12 +680,13 @@ func (c *CLI) processArgs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Determine the argument we look to to end subcommands.
|
// Determine the argument we look to to end subcommands.
|
||||||
// We look at all arguments until one has a space. This
|
// We look at all arguments until one is a flag or has a space.
|
||||||
// disallows commands like: ./cli foo "bar baz". An argument
|
// This disallows commands like: ./cli foo "bar baz". An
|
||||||
// with a space is always an argument.
|
// argument with a space is always an argument. A blank
|
||||||
|
// argument is always an argument.
|
||||||
j := 0
|
j := 0
|
||||||
for k, v := range c.Args[i:] {
|
for k, v := range c.Args[i:] {
|
||||||
if strings.ContainsRune(v, ' ') {
|
if strings.ContainsRune(v, ' ') || v == "" || v[0] == '-' {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
vendor/github.com/posener/complete/.gitignore
generated
vendored
2
vendor/github.com/posener/complete/.gitignore
generated
vendored
@ -1,2 +1,4 @@
|
|||||||
.idea
|
.idea
|
||||||
coverage.txt
|
coverage.txt
|
||||||
|
gocomplete/gocomplete
|
||||||
|
example/self/self
|
||||||
|
19
vendor/github.com/posener/complete/.travis.yml
generated
vendored
19
vendor/github.com/posener/complete/.travis.yml
generated
vendored
@ -1,17 +1,16 @@
|
|||||||
language: go
|
language: go
|
||||||
sudo: false
|
|
||||||
go:
|
go:
|
||||||
- 1.9
|
- tip
|
||||||
- 1.8
|
- 1.12.x
|
||||||
|
- 1.11.x
|
||||||
before_install:
|
- 1.10.x
|
||||||
- go get -u -t ./...
|
|
||||||
- go get -u gopkg.in/alecthomas/gometalinter.v1
|
|
||||||
- gometalinter.v1 --install
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- gometalinter.v1 --config metalinter.json ./...
|
- go test -race -coverprofile=coverage.txt -covermode=atomic ./...
|
||||||
- ./test.sh
|
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- go: tip
|
@ -1,27 +1,29 @@
|
|||||||
# complete
|
# complete
|
||||||
|
|
||||||
A tool for bash writing bash completion in go, and bash completion for the go command line.
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/posener/complete.svg?branch=master)](https://travis-ci.org/posener/complete)
|
[![Build Status](https://travis-ci.org/posener/complete.svg?branch=master)](https://travis-ci.org/posener/complete)
|
||||||
[![codecov](https://codecov.io/gh/posener/complete/branch/master/graph/badge.svg)](https://codecov.io/gh/posener/complete)
|
[![codecov](https://codecov.io/gh/posener/complete/branch/master/graph/badge.svg)](https://codecov.io/gh/posener/complete)
|
||||||
|
[![golangci](https://golangci.com/badges/github.com/posener/complete.svg)](https://golangci.com/r/github.com/posener/complete)
|
||||||
[![GoDoc](https://godoc.org/github.com/posener/complete?status.svg)](http://godoc.org/github.com/posener/complete)
|
[![GoDoc](https://godoc.org/github.com/posener/complete?status.svg)](http://godoc.org/github.com/posener/complete)
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/posener/complete)](https://goreportcard.com/report/github.com/posener/complete)
|
[![goreadme](https://goreadme.herokuapp.com/badge/posener/complete.svg)](https://goreadme.herokuapp.com)
|
||||||
|
|
||||||
|
Package complete provides a tool for bash writing bash completion in go, and bash completion for the go command line.
|
||||||
|
|
||||||
Writing bash completion scripts is a hard work. This package provides an easy way
|
Writing bash completion scripts is a hard work. This package provides an easy way
|
||||||
to create bash completion scripts for any command, and also an easy way to install/uninstall
|
to create bash completion scripts for any command, and also an easy way to install/uninstall
|
||||||
the completion of the command.
|
the completion of the command.
|
||||||
|
|
||||||
## go command bash completion
|
#### Go Command Bash Completion
|
||||||
|
|
||||||
In [gocomplete](./gocomplete) there is an example for bash completion for the `go` command line.
|
In [./cmd/gocomplete](./cmd/gocomplete) there is an example for bash completion for the `go` command line.
|
||||||
|
|
||||||
This is an example that uses the `complete` package on the `go` command - the `complete` package
|
This is an example that uses the `complete` package on the `go` command - the `complete` package
|
||||||
can also be used to implement any completions, see [Usage](#usage).
|
can also be used to implement any completions, see #usage.
|
||||||
|
|
||||||
### Install
|
#### Install
|
||||||
|
|
||||||
1. Type in your shell:
|
1. Type in your shell:
|
||||||
```
|
|
||||||
|
```go
|
||||||
go get -u github.com/posener/complete/gocomplete
|
go get -u github.com/posener/complete/gocomplete
|
||||||
gocomplete -install
|
gocomplete -install
|
||||||
```
|
```
|
||||||
@ -30,13 +32,13 @@ gocomplete -install
|
|||||||
|
|
||||||
Uninstall by `gocomplete -uninstall`
|
Uninstall by `gocomplete -uninstall`
|
||||||
|
|
||||||
### Features
|
#### Features
|
||||||
|
|
||||||
- Complete `go` command, including sub commands and all flags.
|
- Complete `go` command, including sub commands and all flags.
|
||||||
- Complete packages names or `.go` files when necessary.
|
- Complete packages names or `.go` files when necessary.
|
||||||
- Complete test names after `-run` flag.
|
- Complete test names after `-run` flag.
|
||||||
|
|
||||||
## complete package
|
#### Complete package
|
||||||
|
|
||||||
Supported shells:
|
Supported shells:
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ Supported shells:
|
|||||||
- [x] zsh
|
- [x] zsh
|
||||||
- [x] fish
|
- [x] fish
|
||||||
|
|
||||||
### Usage
|
#### Usage
|
||||||
|
|
||||||
Assuming you have program called `run` and you want to have bash completion
|
Assuming you have program called `run` and you want to have bash completion
|
||||||
for it, meaning, if you type `run` then space, then press the `Tab` key,
|
for it, meaning, if you type `run` then space, then press the `Tab` key,
|
||||||
@ -109,9 +111,21 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Self completing program
|
#### Self completing program
|
||||||
|
|
||||||
In case that the program that we want to complete is written in go we
|
In case that the program that we want to complete is written in go we
|
||||||
can make it self completing.
|
can make it self completing.
|
||||||
|
Here is an example: [./example/self/main.go](./example/self/main.go) .
|
||||||
|
|
||||||
Here is an [example](./example/self/main.go)
|
## Sub Packages
|
||||||
|
|
||||||
|
* [cmd](./cmd): Package cmd used for command line options for the complete tool
|
||||||
|
|
||||||
|
* [gocomplete](./gocomplete): Package main is complete tool for the go command line
|
||||||
|
|
||||||
|
* [match](./match): Package match contains matchers that decide if to apply completion.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Created by [goreadme](https://github.com/apps/goreadme)
|
24
vendor/github.com/posener/complete/args.go
generated
vendored
24
vendor/github.com/posener/complete/args.go
generated
vendored
@ -28,6 +28,8 @@ type Args struct {
|
|||||||
// Directory gives the directory of the current written
|
// Directory gives the directory of the current written
|
||||||
// last argument if it represents a file name being written.
|
// last argument if it represents a file name being written.
|
||||||
// in case that it is not, we fall back to the current directory.
|
// in case that it is not, we fall back to the current directory.
|
||||||
|
//
|
||||||
|
// Deprecated.
|
||||||
func (a Args) Directory() string {
|
func (a Args) Directory() string {
|
||||||
if info, err := os.Stat(a.Last); err == nil && info.IsDir() {
|
if info, err := os.Stat(a.Last); err == nil && info.IsDir() {
|
||||||
return fixPathForm(a.Last, a.Last)
|
return fixPathForm(a.Last, a.Last)
|
||||||
@ -57,11 +59,20 @@ func newArgs(line string) Args {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// splitFields returns a list of fields from the given command line.
|
||||||
|
// If the last character is space, it appends an empty field in the end
|
||||||
|
// indicating that the field before it was completed.
|
||||||
|
// If the last field is of the form "a=b", it splits it to two fields: "a", "b",
|
||||||
|
// So it can be completed.
|
||||||
func splitFields(line string) []string {
|
func splitFields(line string) []string {
|
||||||
parts := strings.Fields(line)
|
parts := strings.Fields(line)
|
||||||
|
|
||||||
|
// Add empty field if the last field was completed.
|
||||||
if len(line) > 0 && unicode.IsSpace(rune(line[len(line)-1])) {
|
if len(line) > 0 && unicode.IsSpace(rune(line[len(line)-1])) {
|
||||||
parts = append(parts, "")
|
parts = append(parts, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Treat the last field if it is of the form "a=b"
|
||||||
parts = splitLastEqual(parts)
|
parts = splitLastEqual(parts)
|
||||||
return parts
|
return parts
|
||||||
}
|
}
|
||||||
@ -74,16 +85,17 @@ func splitLastEqual(line []string) []string {
|
|||||||
return append(line[:len(line)-1], parts...)
|
return append(line[:len(line)-1], parts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// from returns a copy of Args of all arguments after the i'th argument.
|
||||||
func (a Args) from(i int) Args {
|
func (a Args) from(i int) Args {
|
||||||
if i > len(a.All) {
|
if i >= len(a.All) {
|
||||||
i = len(a.All)
|
i = len(a.All) - 1
|
||||||
}
|
}
|
||||||
a.All = a.All[i:]
|
a.All = a.All[i+1:]
|
||||||
|
|
||||||
if i > len(a.Completed) {
|
if i >= len(a.Completed) {
|
||||||
i = len(a.Completed)
|
i = len(a.Completed) - 1
|
||||||
}
|
}
|
||||||
a.Completed = a.Completed[i:]
|
a.Completed = a.Completed[i+1:]
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
vendor/github.com/posener/complete/cmd/cmd.go
generated
vendored
2
vendor/github.com/posener/complete/cmd/cmd.go
generated
vendored
@ -103,7 +103,7 @@ func (f *CLI) AddFlags(flags *flag.FlagSet) {
|
|||||||
fmt.Sprintf("Uninstall completion for %s command", f.Name))
|
fmt.Sprintf("Uninstall completion for %s command", f.Name))
|
||||||
}
|
}
|
||||||
if flags.Lookup("y") == nil {
|
if flags.Lookup("y") == nil {
|
||||||
flags.BoolVar(&f.yes, "y", false, "Don't prompt user for typing 'yes'")
|
flags.BoolVar(&f.yes, "y", false, "Don't prompt user for typing 'yes' when installing completion")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
vendor/github.com/posener/complete/cmd/install/bash.go
generated
vendored
13
vendor/github.com/posener/complete/cmd/install/bash.go
generated
vendored
@ -10,20 +10,25 @@ type bash struct {
|
|||||||
rc string
|
rc string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b bash) Install(cmd, bin string) error {
|
func (b bash) IsInstalled(cmd, bin string) bool {
|
||||||
completeCmd := b.cmd(cmd, bin)
|
completeCmd := b.cmd(cmd, bin)
|
||||||
if lineInFile(b.rc, completeCmd) {
|
return lineInFile(b.rc, completeCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b bash) Install(cmd, bin string) error {
|
||||||
|
if b.IsInstalled(cmd, bin) {
|
||||||
return fmt.Errorf("already installed in %s", b.rc)
|
return fmt.Errorf("already installed in %s", b.rc)
|
||||||
}
|
}
|
||||||
|
completeCmd := b.cmd(cmd, bin)
|
||||||
return appendToFile(b.rc, completeCmd)
|
return appendToFile(b.rc, completeCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b bash) Uninstall(cmd, bin string) error {
|
func (b bash) Uninstall(cmd, bin string) error {
|
||||||
completeCmd := b.cmd(cmd, bin)
|
if !b.IsInstalled(cmd, bin) {
|
||||||
if !lineInFile(b.rc, completeCmd) {
|
|
||||||
return fmt.Errorf("does not installed in %s", b.rc)
|
return fmt.Errorf("does not installed in %s", b.rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
completeCmd := b.cmd(cmd, bin)
|
||||||
return removeFromFile(b.rc, completeCmd)
|
return removeFromFile(b.rc, completeCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
47
vendor/github.com/posener/complete/cmd/install/fish.go
generated
vendored
47
vendor/github.com/posener/complete/cmd/install/fish.go
generated
vendored
@ -14,37 +14,56 @@ type fish struct {
|
|||||||
configDir string
|
configDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f fish) Install(cmd, bin string) error {
|
func (f fish) IsInstalled(cmd, bin string) bool {
|
||||||
completionFile := filepath.Join(f.configDir, "completions", fmt.Sprintf("%s.fish", cmd))
|
completionFile := f.getCompletionFilePath(cmd)
|
||||||
completeCmd := f.cmd(cmd, bin)
|
|
||||||
if _, err := os.Stat(completionFile); err == nil {
|
if _, err := os.Stat(completionFile); err == nil {
|
||||||
return fmt.Errorf("already installed at %s", completionFile)
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fish) Install(cmd, bin string) error {
|
||||||
|
if f.IsInstalled(cmd, bin) {
|
||||||
|
return fmt.Errorf("already installed at %s", f.getCompletionFilePath(cmd))
|
||||||
|
}
|
||||||
|
|
||||||
|
completionFile := f.getCompletionFilePath(cmd)
|
||||||
|
completeCmd, err := f.cmd(cmd, bin)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return createFile(completionFile, completeCmd)
|
return createFile(completionFile, completeCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f fish) Uninstall(cmd, bin string) error {
|
func (f fish) Uninstall(cmd, bin string) error {
|
||||||
completionFile := filepath.Join(f.configDir, "completions", fmt.Sprintf("%s.fish", cmd))
|
if !f.IsInstalled(cmd, bin) {
|
||||||
if _, err := os.Stat(completionFile); err != nil {
|
|
||||||
return fmt.Errorf("does not installed in %s", f.configDir)
|
return fmt.Errorf("does not installed in %s", f.configDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
completionFile := f.getCompletionFilePath(cmd)
|
||||||
return os.Remove(completionFile)
|
return os.Remove(completionFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f fish) cmd(cmd, bin string) string {
|
func (f fish) getCompletionFilePath(cmd string) string {
|
||||||
|
return filepath.Join(f.configDir, "completions", fmt.Sprintf("%s.fish", cmd))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fish) cmd(cmd, bin string) (string, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
params := struct{ Cmd, Bin string }{cmd, bin}
|
params := struct{ Cmd, Bin string }{cmd, bin}
|
||||||
template.Must(template.New("cmd").Parse(`
|
tmpl := template.Must(template.New("cmd").Parse(`
|
||||||
function __complete_{{.Cmd}}
|
function __complete_{{.Cmd}}
|
||||||
set -lx COMP_LINE (string join ' ' (commandline -o))
|
set -lx COMP_LINE (commandline -cp)
|
||||||
test (commandline -ct) = ""
|
test -z (commandline -ct)
|
||||||
and set COMP_LINE "$COMP_LINE "
|
and set COMP_LINE "$COMP_LINE "
|
||||||
{{.Bin}}
|
{{.Bin}}
|
||||||
end
|
end
|
||||||
complete -c {{.Cmd}} -a "(__complete_{{.Cmd}})"
|
complete -f -c {{.Cmd}} -a "(__complete_{{.Cmd}})"
|
||||||
`)).Execute(&buf, params)
|
`))
|
||||||
|
err := tmpl.Execute(&buf, params)
|
||||||
return string(buf.Bytes())
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return buf.String(), nil
|
||||||
}
|
}
|
||||||
|
33
vendor/github.com/posener/complete/cmd/install/install.go
generated
vendored
33
vendor/github.com/posener/complete/cmd/install/install.go
generated
vendored
@ -5,11 +5,13 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
)
|
)
|
||||||
|
|
||||||
type installer interface {
|
type installer interface {
|
||||||
|
IsInstalled(cmd, bin string) bool
|
||||||
Install(cmd, bin string) error
|
Install(cmd, bin string) error
|
||||||
Uninstall(cmd, bin string) error
|
Uninstall(cmd, bin string) error
|
||||||
}
|
}
|
||||||
@ -36,6 +38,24 @@ func Install(cmd string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsInstalled returns true if the completion
|
||||||
|
// for the given cmd is installed.
|
||||||
|
func IsInstalled(cmd string) bool {
|
||||||
|
bin, err := getBinaryPath()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, i := range installers() {
|
||||||
|
installed := i.IsInstalled(cmd, bin)
|
||||||
|
if installed {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Uninstall complete command given:
|
// Uninstall complete command given:
|
||||||
// cmd: is the command name
|
// cmd: is the command name
|
||||||
func Uninstall(cmd string) error {
|
func Uninstall(cmd string) error {
|
||||||
@ -51,7 +71,7 @@ func Uninstall(cmd string) error {
|
|||||||
for _, i := range is {
|
for _, i := range is {
|
||||||
errI := i.Uninstall(cmd, bin)
|
errI := i.Uninstall(cmd, bin)
|
||||||
if errI != nil {
|
if errI != nil {
|
||||||
multierror.Append(err, errI)
|
err = multierror.Append(err, errI)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +79,16 @@ func Uninstall(cmd string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func installers() (i []installer) {
|
func installers() (i []installer) {
|
||||||
for _, rc := range [...]string{".bashrc", ".bash_profile", ".bash_login", ".profile"} {
|
// The list of bash config files candidates where it is
|
||||||
|
// possible to install the completion command.
|
||||||
|
var bashConfFiles []string
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin":
|
||||||
|
bashConfFiles = []string{".bash_profile"}
|
||||||
|
default:
|
||||||
|
bashConfFiles = []string{".bashrc", ".bash_profile", ".bash_login", ".profile"}
|
||||||
|
}
|
||||||
|
for _, rc := range bashConfFiles {
|
||||||
if f := rcFile(rc); f != "" {
|
if f := rcFile(rc); f != "" {
|
||||||
i = append(i, bash{f})
|
i = append(i, bash{f})
|
||||||
break
|
break
|
||||||
|
5
vendor/github.com/posener/complete/cmd/install/utils.go
generated
vendored
5
vendor/github.com/posener/complete/cmd/install/utils.go
generated
vendored
@ -115,7 +115,10 @@ func removeContentToTempFile(name, content string) (string, error) {
|
|||||||
if str == content {
|
if str == content {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
wf.WriteString(str + "\n")
|
_, err = wf.WriteString(str + "\n")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
prefix = prefix[:0]
|
prefix = prefix[:0]
|
||||||
}
|
}
|
||||||
return wf.Name(), nil
|
return wf.Name(), nil
|
||||||
|
13
vendor/github.com/posener/complete/cmd/install/zsh.go
generated
vendored
13
vendor/github.com/posener/complete/cmd/install/zsh.go
generated
vendored
@ -11,12 +11,17 @@ type zsh struct {
|
|||||||
rc string
|
rc string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z zsh) Install(cmd, bin string) error {
|
func (z zsh) IsInstalled(cmd, bin string) bool {
|
||||||
completeCmd := z.cmd(cmd, bin)
|
completeCmd := z.cmd(cmd, bin)
|
||||||
if lineInFile(z.rc, completeCmd) {
|
return lineInFile(z.rc, completeCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z zsh) Install(cmd, bin string) error {
|
||||||
|
if z.IsInstalled(cmd, bin) {
|
||||||
return fmt.Errorf("already installed in %s", z.rc)
|
return fmt.Errorf("already installed in %s", z.rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
completeCmd := z.cmd(cmd, bin)
|
||||||
bashCompInit := "autoload -U +X bashcompinit && bashcompinit"
|
bashCompInit := "autoload -U +X bashcompinit && bashcompinit"
|
||||||
if !lineInFile(z.rc, bashCompInit) {
|
if !lineInFile(z.rc, bashCompInit) {
|
||||||
completeCmd = bashCompInit + "\n" + completeCmd
|
completeCmd = bashCompInit + "\n" + completeCmd
|
||||||
@ -26,11 +31,11 @@ func (z zsh) Install(cmd, bin string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (z zsh) Uninstall(cmd, bin string) error {
|
func (z zsh) Uninstall(cmd, bin string) error {
|
||||||
completeCmd := z.cmd(cmd, bin)
|
if !z.IsInstalled(cmd, bin) {
|
||||||
if !lineInFile(z.rc, completeCmd) {
|
|
||||||
return fmt.Errorf("does not installed in %s", z.rc)
|
return fmt.Errorf("does not installed in %s", z.rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
completeCmd := z.cmd(cmd, bin)
|
||||||
return removeFromFile(z.rc, completeCmd)
|
return removeFromFile(z.rc, completeCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
39
vendor/github.com/posener/complete/complete.go
generated
vendored
39
vendor/github.com/posener/complete/complete.go
generated
vendored
@ -1,8 +1,3 @@
|
|||||||
// Package complete provides a tool for bash writing bash completion in go.
|
|
||||||
//
|
|
||||||
// Writing bash completion scripts is a hard work. This package provides an easy way
|
|
||||||
// to create bash completion scripts for any command, and also an easy way to install/uninstall
|
|
||||||
// the completion of the command.
|
|
||||||
package complete
|
package complete
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -10,14 +5,16 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/posener/complete/cmd"
|
"github.com/posener/complete/cmd"
|
||||||
"github.com/posener/complete/match"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
envComplete = "COMP_LINE"
|
envLine = "COMP_LINE"
|
||||||
envDebug = "COMP_DEBUG"
|
envPoint = "COMP_POINT"
|
||||||
|
envDebug = "COMP_DEBUG"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Complete structs define completion for a command with CLI options
|
// Complete structs define completion for a command with CLI options
|
||||||
@ -55,13 +52,18 @@ func (c *Complete) Run() bool {
|
|||||||
// For installation: it assumes that flags were added and parsed before
|
// For installation: it assumes that flags were added and parsed before
|
||||||
// it was called.
|
// it was called.
|
||||||
func (c *Complete) Complete() bool {
|
func (c *Complete) Complete() bool {
|
||||||
line, ok := getLine()
|
line, point, ok := getEnv()
|
||||||
if !ok {
|
if !ok {
|
||||||
// make sure flags parsed,
|
// make sure flags parsed,
|
||||||
// in case they were not added in the main program
|
// in case they were not added in the main program
|
||||||
return c.CLI.Run()
|
return c.CLI.Run()
|
||||||
}
|
}
|
||||||
Log("Completing line: %s", line)
|
|
||||||
|
if point >= 0 && point < len(line) {
|
||||||
|
line = line[:point]
|
||||||
|
}
|
||||||
|
|
||||||
|
Log("Completing phrase: %s", line)
|
||||||
a := newArgs(line)
|
a := newArgs(line)
|
||||||
Log("Completing last field: %s", a.Last)
|
Log("Completing last field: %s", a.Last)
|
||||||
options := c.Command.Predict(a)
|
options := c.Command.Predict(a)
|
||||||
@ -70,7 +72,7 @@ func (c *Complete) Complete() bool {
|
|||||||
// filter only options that match the last argument
|
// filter only options that match the last argument
|
||||||
matches := []string{}
|
matches := []string{}
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
if match.Prefix(option, a.Last) {
|
if strings.HasPrefix(option, a.Last) {
|
||||||
matches = append(matches, option)
|
matches = append(matches, option)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,12 +81,19 @@ func (c *Complete) Complete() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLine() (string, bool) {
|
func getEnv() (line string, point int, ok bool) {
|
||||||
line := os.Getenv(envComplete)
|
line = os.Getenv(envLine)
|
||||||
if line == "" {
|
if line == "" {
|
||||||
return "", false
|
return
|
||||||
}
|
}
|
||||||
return line, true
|
point, err := strconv.Atoi(os.Getenv(envPoint))
|
||||||
|
if err != nil {
|
||||||
|
// If failed parsing point for some reason, set it to point
|
||||||
|
// on the end of the line.
|
||||||
|
Log("Failed parsing point %s: %v", os.Getenv(envPoint), err)
|
||||||
|
point = len(line)
|
||||||
|
}
|
||||||
|
return line, point, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Complete) output(options []string) {
|
func (c *Complete) output(options []string) {
|
||||||
|
110
vendor/github.com/posener/complete/doc.go
generated
vendored
Normal file
110
vendor/github.com/posener/complete/doc.go
generated
vendored
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
Package complete provides a tool for bash writing bash completion in go, and bash completion for the go command line.
|
||||||
|
|
||||||
|
Writing bash completion scripts is a hard work. This package provides an easy way
|
||||||
|
to create bash completion scripts for any command, and also an easy way to install/uninstall
|
||||||
|
the completion of the command.
|
||||||
|
|
||||||
|
Go Command Bash Completion
|
||||||
|
|
||||||
|
In ./cmd/gocomplete there is an example for bash completion for the `go` command line.
|
||||||
|
|
||||||
|
This is an example that uses the `complete` package on the `go` command - the `complete` package
|
||||||
|
can also be used to implement any completions, see #usage.
|
||||||
|
|
||||||
|
Install
|
||||||
|
|
||||||
|
1. Type in your shell:
|
||||||
|
|
||||||
|
go get -u github.com/posener/complete/gocomplete
|
||||||
|
gocomplete -install
|
||||||
|
|
||||||
|
2. Restart your shell
|
||||||
|
|
||||||
|
Uninstall by `gocomplete -uninstall`
|
||||||
|
|
||||||
|
Features
|
||||||
|
|
||||||
|
- Complete `go` command, including sub commands and all flags.
|
||||||
|
- Complete packages names or `.go` files when necessary.
|
||||||
|
- Complete test names after `-run` flag.
|
||||||
|
|
||||||
|
Complete package
|
||||||
|
|
||||||
|
Supported shells:
|
||||||
|
|
||||||
|
- [x] bash
|
||||||
|
- [x] zsh
|
||||||
|
- [x] fish
|
||||||
|
|
||||||
|
Usage
|
||||||
|
|
||||||
|
Assuming you have program called `run` and you want to have bash completion
|
||||||
|
for it, meaning, if you type `run` then space, then press the `Tab` key,
|
||||||
|
the shell will suggest relevant complete options.
|
||||||
|
|
||||||
|
In that case, we will create a program called `runcomplete`, a go program,
|
||||||
|
with a `func main()` and so, that will make the completion of the `run`
|
||||||
|
program. Once the `runcomplete` will be in a binary form, we could
|
||||||
|
`runcomplete -install` and that will add to our shell all the bash completion
|
||||||
|
options for `run`.
|
||||||
|
|
||||||
|
So here it is:
|
||||||
|
|
||||||
|
import "github.com/posener/complete"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
// create a Command object, that represents the command we want
|
||||||
|
// to complete.
|
||||||
|
run := complete.Command{
|
||||||
|
|
||||||
|
// Sub defines a list of sub commands of the program,
|
||||||
|
// this is recursive, since every command is of type command also.
|
||||||
|
Sub: complete.Commands{
|
||||||
|
|
||||||
|
// add a build sub command
|
||||||
|
"build": complete.Command {
|
||||||
|
|
||||||
|
// define flags of the build sub command
|
||||||
|
Flags: complete.Flags{
|
||||||
|
// build sub command has a flag '-cpus', which
|
||||||
|
// expects number of cpus after it. in that case
|
||||||
|
// anything could complete this flag.
|
||||||
|
"-cpus": complete.PredictAnything,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// define flags of the 'run' main command
|
||||||
|
Flags: complete.Flags{
|
||||||
|
// a flag -o, which expects a file ending with .out after
|
||||||
|
// it, the tab completion will auto complete for files matching
|
||||||
|
// the given pattern.
|
||||||
|
"-o": complete.PredictFiles("*.out"),
|
||||||
|
},
|
||||||
|
|
||||||
|
// define global flags of the 'run' main command
|
||||||
|
// those will show up also when a sub command was entered in the
|
||||||
|
// command line
|
||||||
|
GlobalFlags: complete.Flags{
|
||||||
|
|
||||||
|
// a flag '-h' which does not expects anything after it
|
||||||
|
"-h": complete.PredictNothing,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// run the command completion, as part of the main() function.
|
||||||
|
// this triggers the autocompletion when needed.
|
||||||
|
// name must be exactly as the binary that we want to complete.
|
||||||
|
complete.New("run", run).Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
Self completing program
|
||||||
|
|
||||||
|
In case that the program that we want to complete is written in go we
|
||||||
|
can make it self completing.
|
||||||
|
Here is an example: ./example/self/main.go .
|
||||||
|
|
||||||
|
*/
|
||||||
|
package complete
|
9
vendor/github.com/posener/complete/goreadme.json
generated
vendored
Normal file
9
vendor/github.com/posener/complete/goreadme.json
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"badges": {
|
||||||
|
"travis_ci": true,
|
||||||
|
"code_cov": true,
|
||||||
|
"golang_ci": true,
|
||||||
|
"go_doc": true,
|
||||||
|
"goreadme": true
|
||||||
|
}
|
||||||
|
}
|
3
vendor/github.com/posener/complete/log.go
generated
vendored
3
vendor/github.com/posener/complete/log.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
package complete
|
package complete
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -15,7 +14,7 @@ import (
|
|||||||
var Log = getLogger()
|
var Log = getLogger()
|
||||||
|
|
||||||
func getLogger() func(format string, args ...interface{}) {
|
func getLogger() func(format string, args ...interface{}) {
|
||||||
var logfile io.Writer = ioutil.Discard
|
var logfile = ioutil.Discard
|
||||||
if os.Getenv(envDebug) != "" {
|
if os.Getenv(envDebug) != "" {
|
||||||
logfile = os.Stderr
|
logfile = os.Stderr
|
||||||
}
|
}
|
||||||
|
19
vendor/github.com/posener/complete/match/file.go
generated
vendored
19
vendor/github.com/posener/complete/match/file.go
generated
vendored
@ -1,19 +0,0 @@
|
|||||||
package match
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
// File returns true if prefix can match the file
|
|
||||||
func File(file, prefix string) bool {
|
|
||||||
// special case for current directory completion
|
|
||||||
if file == "./" && (prefix == "." || prefix == "") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if prefix == "." && strings.HasPrefix(file, ".") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
file = strings.TrimPrefix(file, "./")
|
|
||||||
prefix = strings.TrimPrefix(prefix, "./")
|
|
||||||
|
|
||||||
return strings.HasPrefix(file, prefix)
|
|
||||||
}
|
|
6
vendor/github.com/posener/complete/match/match.go
generated
vendored
6
vendor/github.com/posener/complete/match/match.go
generated
vendored
@ -1,6 +0,0 @@
|
|||||||
package match
|
|
||||||
|
|
||||||
// Match matches two strings
|
|
||||||
// it is used for comparing a term to the last typed
|
|
||||||
// word, the prefix, and see if it is a possible auto complete option.
|
|
||||||
type Match func(term, prefix string) bool
|
|
9
vendor/github.com/posener/complete/match/prefix.go
generated
vendored
9
vendor/github.com/posener/complete/match/prefix.go
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
package match
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
// Prefix is a simple Matcher, if the word is it's prefix, there is a match
|
|
||||||
// Match returns true if a has the prefix as prefix
|
|
||||||
func Prefix(long, prefix string) bool {
|
|
||||||
return strings.HasPrefix(long, prefix)
|
|
||||||
}
|
|
21
vendor/github.com/posener/complete/metalinter.json
generated
vendored
21
vendor/github.com/posener/complete/metalinter.json
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"Vendor": true,
|
|
||||||
"DisableAll": true,
|
|
||||||
"Enable": [
|
|
||||||
"gofmt",
|
|
||||||
"goimports",
|
|
||||||
"interfacer",
|
|
||||||
"goconst",
|
|
||||||
"misspell",
|
|
||||||
"unconvert",
|
|
||||||
"gosimple",
|
|
||||||
"golint",
|
|
||||||
"structcheck",
|
|
||||||
"deadcode",
|
|
||||||
"vet"
|
|
||||||
],
|
|
||||||
"Exclude": [
|
|
||||||
"initTests is unused"
|
|
||||||
],
|
|
||||||
"Deadline": "2m"
|
|
||||||
}
|
|
74
vendor/github.com/posener/complete/predict_files.go
generated
vendored
74
vendor/github.com/posener/complete/predict_files.go
generated
vendored
@ -5,8 +5,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/posener/complete/match"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PredictDirs will search for directories in the given started to be typed
|
// PredictDirs will search for directories in the given started to be typed
|
||||||
@ -53,7 +51,7 @@ func predictFiles(a Args, pattern string, allowFiles bool) []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
dir := a.Directory()
|
dir := directory(a.Last)
|
||||||
files := listFiles(dir, pattern, allowFiles)
|
files := listFiles(dir, pattern, allowFiles)
|
||||||
|
|
||||||
// add dir if match
|
// add dir if match
|
||||||
@ -62,6 +60,19 @@ func predictFiles(a Args, pattern string, allowFiles bool) []string {
|
|||||||
return PredictFilesSet(files).Predict(a)
|
return PredictFilesSet(files).Predict(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// directory gives the directory of the given partial path
|
||||||
|
// in case that it is not, we fall back to the current directory.
|
||||||
|
func directory(path string) string {
|
||||||
|
if info, err := os.Stat(path); err == nil && info.IsDir() {
|
||||||
|
return fixPathForm(path, path)
|
||||||
|
}
|
||||||
|
dir := filepath.Dir(path)
|
||||||
|
if info, err := os.Stat(dir); err == nil && info.IsDir() {
|
||||||
|
return fixPathForm(path, dir)
|
||||||
|
}
|
||||||
|
return "./"
|
||||||
|
}
|
||||||
|
|
||||||
// PredictFilesSet predict according to file rules to a given set of file names
|
// PredictFilesSet predict according to file rules to a given set of file names
|
||||||
func PredictFilesSet(files []string) PredictFunc {
|
func PredictFilesSet(files []string) PredictFunc {
|
||||||
return func(a Args) (prediction []string) {
|
return func(a Args) (prediction []string) {
|
||||||
@ -70,7 +81,7 @@ func PredictFilesSet(files []string) PredictFunc {
|
|||||||
f = fixPathForm(a.Last, f)
|
f = fixPathForm(a.Last, f)
|
||||||
|
|
||||||
// test matching of file to the argument
|
// test matching of file to the argument
|
||||||
if match.File(f, a.Last) {
|
if matchFile(f, a.Last) {
|
||||||
prediction = append(prediction, f)
|
prediction = append(prediction, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,3 +117,58 @@ func listFiles(dir, pattern string, allowFiles bool) []string {
|
|||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchFile returns true if prefix can match the file
|
||||||
|
func matchFile(file, prefix string) bool {
|
||||||
|
// special case for current directory completion
|
||||||
|
if file == "./" && (prefix == "." || prefix == "") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if prefix == "." && strings.HasPrefix(file, ".") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
file = strings.TrimPrefix(file, "./")
|
||||||
|
prefix = strings.TrimPrefix(prefix, "./")
|
||||||
|
|
||||||
|
return strings.HasPrefix(file, prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixPathForm changes a file name to a relative name
|
||||||
|
func fixPathForm(last string, file string) string {
|
||||||
|
// get wording directory for relative name
|
||||||
|
workDir, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
abs, err := filepath.Abs(file)
|
||||||
|
if err != nil {
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
// if last is absolute, return path as absolute
|
||||||
|
if filepath.IsAbs(last) {
|
||||||
|
return fixDirPath(abs)
|
||||||
|
}
|
||||||
|
|
||||||
|
rel, err := filepath.Rel(workDir, abs)
|
||||||
|
if err != nil {
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
// fix ./ prefix of path
|
||||||
|
if rel != "." && strings.HasPrefix(last, ".") {
|
||||||
|
rel = "./" + rel
|
||||||
|
}
|
||||||
|
|
||||||
|
return fixDirPath(rel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fixDirPath(path string) string {
|
||||||
|
info, err := os.Stat(path)
|
||||||
|
if err == nil && info.IsDir() && !strings.HasSuffix(path, "/") {
|
||||||
|
path += "/"
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
12
vendor/github.com/posener/complete/test.sh
generated
vendored
12
vendor/github.com/posener/complete/test.sh
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
echo "" > coverage.txt
|
|
||||||
|
|
||||||
for d in $(go list ./... | grep -v vendor); do
|
|
||||||
go test -v -race -coverprofile=profile.out -covermode=atomic $d
|
|
||||||
if [ -f profile.out ]; then
|
|
||||||
cat profile.out >> coverage.txt
|
|
||||||
rm profile.out
|
|
||||||
fi
|
|
||||||
done
|
|
46
vendor/github.com/posener/complete/utils.go
generated
vendored
46
vendor/github.com/posener/complete/utils.go
generated
vendored
@ -1,46 +0,0 @@
|
|||||||
package complete
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// fixPathForm changes a file name to a relative name
|
|
||||||
func fixPathForm(last string, file string) string {
|
|
||||||
// get wording directory for relative name
|
|
||||||
workDir, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
|
||||||
abs, err := filepath.Abs(file)
|
|
||||||
if err != nil {
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
|
||||||
// if last is absolute, return path as absolute
|
|
||||||
if filepath.IsAbs(last) {
|
|
||||||
return fixDirPath(abs)
|
|
||||||
}
|
|
||||||
|
|
||||||
rel, err := filepath.Rel(workDir, abs)
|
|
||||||
if err != nil {
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
|
||||||
// fix ./ prefix of path
|
|
||||||
if rel != "." && strings.HasPrefix(last, ".") {
|
|
||||||
rel = "./" + rel
|
|
||||||
}
|
|
||||||
|
|
||||||
return fixDirPath(rel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func fixDirPath(path string) string {
|
|
||||||
info, err := os.Stat(path)
|
|
||||||
if err == nil && info.IsDir() && !strings.HasSuffix(path, "/") {
|
|
||||||
path += "/"
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
}
|
|
9
vendor/github.com/shopspring/decimal/.gitignore
generated
vendored
Normal file
9
vendor/github.com/shopspring/decimal/.gitignore
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.git
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
# VS code
|
||||||
|
*.code-workspace
|
19
vendor/github.com/shopspring/decimal/.travis.yml
generated
vendored
Normal file
19
vendor/github.com/shopspring/decimal/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
arch:
|
||||||
|
- amd64
|
||||||
|
- ppc64le
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.7.x
|
||||||
|
- 1.14.x
|
||||||
|
- 1.15.x
|
||||||
|
- 1.16.x
|
||||||
|
- 1.17.x
|
||||||
|
- tip
|
||||||
|
|
||||||
|
install:
|
||||||
|
- go build .
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go test -v
|
49
vendor/github.com/shopspring/decimal/CHANGELOG.md
generated
vendored
Normal file
49
vendor/github.com/shopspring/decimal/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
## Decimal v1.3.1
|
||||||
|
|
||||||
|
#### ENHANCEMENTS
|
||||||
|
- Reduce memory allocation in case of initialization from big.Int [#252](https://github.com/shopspring/decimal/pull/252)
|
||||||
|
|
||||||
|
#### BUGFIXES
|
||||||
|
- Fix binary marshalling of decimal zero value [#253](https://github.com/shopspring/decimal/pull/253)
|
||||||
|
|
||||||
|
## Decimal v1.3.0
|
||||||
|
|
||||||
|
#### FEATURES
|
||||||
|
- Add NewFromFormattedString initializer [#184](https://github.com/shopspring/decimal/pull/184)
|
||||||
|
- Add NewNullDecimal initializer [#234](https://github.com/shopspring/decimal/pull/234)
|
||||||
|
- Add implementation of natural exponent function (Taylor, Hull-Abraham) [#229](https://github.com/shopspring/decimal/pull/229)
|
||||||
|
- Add RoundUp, RoundDown, RoundCeil, RoundFloor methods [#196](https://github.com/shopspring/decimal/pull/196) [#202](https://github.com/shopspring/decimal/pull/202) [#220](https://github.com/shopspring/decimal/pull/220)
|
||||||
|
- Add XML support for NullDecimal [#192](https://github.com/shopspring/decimal/pull/192)
|
||||||
|
- Add IsInteger method [#179](https://github.com/shopspring/decimal/pull/179)
|
||||||
|
- Add Copy helper method [#123](https://github.com/shopspring/decimal/pull/123)
|
||||||
|
- Add InexactFloat64 helper method [#205](https://github.com/shopspring/decimal/pull/205)
|
||||||
|
- Add CoefficientInt64 helper method [#244](https://github.com/shopspring/decimal/pull/244)
|
||||||
|
|
||||||
|
#### ENHANCEMENTS
|
||||||
|
- Performance optimization of NewFromString init method [#198](https://github.com/shopspring/decimal/pull/198)
|
||||||
|
- Performance optimization of Abs and Round methods [#240](https://github.com/shopspring/decimal/pull/240)
|
||||||
|
- Additional tests (CI) for ppc64le architecture [#188](https://github.com/shopspring/decimal/pull/188)
|
||||||
|
|
||||||
|
#### BUGFIXES
|
||||||
|
- Fix rounding in FormatFloat fallback path (roundShortest method, fix taken from Go main repository) [#161](https://github.com/shopspring/decimal/pull/161)
|
||||||
|
- Add slice range checks to UnmarshalBinary method [#232](https://github.com/shopspring/decimal/pull/232)
|
||||||
|
|
||||||
|
## Decimal v1.2.0
|
||||||
|
|
||||||
|
#### BREAKING
|
||||||
|
- Drop support for Go version older than 1.7 [#172](https://github.com/shopspring/decimal/pull/172)
|
||||||
|
|
||||||
|
#### FEATURES
|
||||||
|
- Add NewFromInt and NewFromInt32 initializers [#72](https://github.com/shopspring/decimal/pull/72)
|
||||||
|
- Add support for Go modules [#157](https://github.com/shopspring/decimal/pull/157)
|
||||||
|
- Add BigInt, BigFloat helper methods [#171](https://github.com/shopspring/decimal/pull/171)
|
||||||
|
|
||||||
|
#### ENHANCEMENTS
|
||||||
|
- Memory usage optimization [#160](https://github.com/shopspring/decimal/pull/160)
|
||||||
|
- Updated travis CI golang versions [#156](https://github.com/shopspring/decimal/pull/156)
|
||||||
|
- Update documentation [#173](https://github.com/shopspring/decimal/pull/173)
|
||||||
|
- Improve code quality [#174](https://github.com/shopspring/decimal/pull/174)
|
||||||
|
|
||||||
|
#### BUGFIXES
|
||||||
|
- Revert remove insignificant digits [#159](https://github.com/shopspring/decimal/pull/159)
|
||||||
|
- Remove 15 interval for RoundCash [#166](https://github.com/shopspring/decimal/pull/166)
|
45
vendor/github.com/shopspring/decimal/LICENSE
generated
vendored
Normal file
45
vendor/github.com/shopspring/decimal/LICENSE
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Spring, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
- Based on https://github.com/oguzbilgic/fpd, which has the following license:
|
||||||
|
"""
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2013 Oguz Bilgic
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
"""
|
130
vendor/github.com/shopspring/decimal/README.md
generated
vendored
Normal file
130
vendor/github.com/shopspring/decimal/README.md
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# decimal
|
||||||
|
|
||||||
|
[![Build Status](https://app.travis-ci.com/shopspring/decimal.svg?branch=master)](https://app.travis-ci.com/shopspring/decimal) [![GoDoc](https://godoc.org/github.com/shopspring/decimal?status.svg)](https://godoc.org/github.com/shopspring/decimal) [![Go Report Card](https://goreportcard.com/badge/github.com/shopspring/decimal)](https://goreportcard.com/report/github.com/shopspring/decimal)
|
||||||
|
|
||||||
|
Arbitrary-precision fixed-point decimal numbers in go.
|
||||||
|
|
||||||
|
_Note:_ Decimal library can "only" represent numbers with a maximum of 2^31 digits after the decimal point.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* The zero-value is 0, and is safe to use without initialization
|
||||||
|
* Addition, subtraction, multiplication with no loss of precision
|
||||||
|
* Division with specified precision
|
||||||
|
* Database/sql serialization/deserialization
|
||||||
|
* JSON and XML serialization/deserialization
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
Run `go get github.com/shopspring/decimal`
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
Decimal library requires Go version `>=1.7`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
price, err := decimal.NewFromString("136.02")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
quantity := decimal.NewFromInt(3)
|
||||||
|
|
||||||
|
fee, _ := decimal.NewFromString(".035")
|
||||||
|
taxRate, _ := decimal.NewFromString(".08875")
|
||||||
|
|
||||||
|
subtotal := price.Mul(quantity)
|
||||||
|
|
||||||
|
preTax := subtotal.Mul(fee.Add(decimal.NewFromFloat(1)))
|
||||||
|
|
||||||
|
total := preTax.Mul(taxRate.Add(decimal.NewFromFloat(1)))
|
||||||
|
|
||||||
|
fmt.Println("Subtotal:", subtotal) // Subtotal: 408.06
|
||||||
|
fmt.Println("Pre-tax:", preTax) // Pre-tax: 422.3421
|
||||||
|
fmt.Println("Taxes:", total.Sub(preTax)) // Taxes: 37.482861375
|
||||||
|
fmt.Println("Total:", total) // Total: 459.824961375
|
||||||
|
fmt.Println("Tax rate:", total.Sub(preTax).Div(preTax)) // Tax rate: 0.08875
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
http://godoc.org/github.com/shopspring/decimal
|
||||||
|
|
||||||
|
## Production Usage
|
||||||
|
|
||||||
|
* [Spring](https://shopspring.com/), since August 14, 2014.
|
||||||
|
* If you are using this in production, please let us know!
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
#### Why don't you just use float64?
|
||||||
|
|
||||||
|
Because float64 (or any binary floating point type, actually) can't represent
|
||||||
|
numbers such as `0.1` exactly.
|
||||||
|
|
||||||
|
Consider this code: http://play.golang.org/p/TQBd4yJe6B You might expect that
|
||||||
|
it prints out `10`, but it actually prints `9.999999999999831`. Over time,
|
||||||
|
these small errors can really add up!
|
||||||
|
|
||||||
|
#### Why don't you just use big.Rat?
|
||||||
|
|
||||||
|
big.Rat is fine for representing rational numbers, but Decimal is better for
|
||||||
|
representing money. Why? Here's a (contrived) example:
|
||||||
|
|
||||||
|
Let's say you use big.Rat, and you have two numbers, x and y, both
|
||||||
|
representing 1/3, and you have `z = 1 - x - y = 1/3`. If you print each one
|
||||||
|
out, the string output has to stop somewhere (let's say it stops at 3 decimal
|
||||||
|
digits, for simplicity), so you'll get 0.333, 0.333, and 0.333. But where did
|
||||||
|
the other 0.001 go?
|
||||||
|
|
||||||
|
Here's the above example as code: http://play.golang.org/p/lCZZs0w9KE
|
||||||
|
|
||||||
|
With Decimal, the strings being printed out represent the number exactly. So,
|
||||||
|
if you have `x = y = 1/3` (with precision 3), they will actually be equal to
|
||||||
|
0.333, and when you do `z = 1 - x - y`, `z` will be equal to .334. No money is
|
||||||
|
unaccounted for!
|
||||||
|
|
||||||
|
You still have to be careful. If you want to split a number `N` 3 ways, you
|
||||||
|
can't just send `N/3` to three different people. You have to pick one to send
|
||||||
|
`N - (2/3*N)` to. That person will receive the fraction of a penny remainder.
|
||||||
|
|
||||||
|
But, it is much easier to be careful with Decimal than with big.Rat.
|
||||||
|
|
||||||
|
#### Why isn't the API similar to big.Int's?
|
||||||
|
|
||||||
|
big.Int's API is built to reduce the number of memory allocations for maximal
|
||||||
|
performance. This makes sense for its use-case, but the trade-off is that the
|
||||||
|
API is awkward and easy to misuse.
|
||||||
|
|
||||||
|
For example, to add two big.Ints, you do: `z := new(big.Int).Add(x, y)`. A
|
||||||
|
developer unfamiliar with this API might try to do `z := a.Add(a, b)`. This
|
||||||
|
modifies `a` and sets `z` as an alias for `a`, which they might not expect. It
|
||||||
|
also modifies any other aliases to `a`.
|
||||||
|
|
||||||
|
Here's an example of the subtle bugs you can introduce with big.Int's API:
|
||||||
|
https://play.golang.org/p/x2R_78pa8r
|
||||||
|
|
||||||
|
In contrast, it's difficult to make such mistakes with decimal. Decimals
|
||||||
|
behave like other go numbers types: even though `a = b` will not deep copy
|
||||||
|
`b` into `a`, it is impossible to modify a Decimal, since all Decimal methods
|
||||||
|
return new Decimals and do not modify the originals. The downside is that
|
||||||
|
this causes extra allocations, so Decimal is less performant. My assumption
|
||||||
|
is that if you're using Decimals, you probably care more about correctness
|
||||||
|
than performance.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
This is a heavily modified fork of [fpd.Decimal](https://github.com/oguzbilgic/fpd), which was also released under the MIT License.
|
415
vendor/github.com/shopspring/decimal/decimal-go.go
generated
vendored
Normal file
415
vendor/github.com/shopspring/decimal/decimal-go.go
generated
vendored
Normal file
@ -0,0 +1,415 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Multiprecision decimal numbers.
|
||||||
|
// For floating-point formatting only; not general purpose.
|
||||||
|
// Only operations are assign and (binary) left/right shift.
|
||||||
|
// Can do binary floating point in multiprecision decimal precisely
|
||||||
|
// because 2 divides 10; cannot do decimal floating point
|
||||||
|
// in multiprecision binary precisely.
|
||||||
|
|
||||||
|
package decimal
|
||||||
|
|
||||||
|
type decimal struct {
|
||||||
|
d [800]byte // digits, big-endian representation
|
||||||
|
nd int // number of digits used
|
||||||
|
dp int // decimal point
|
||||||
|
neg bool // negative flag
|
||||||
|
trunc bool // discarded nonzero digits beyond d[:nd]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *decimal) String() string {
|
||||||
|
n := 10 + a.nd
|
||||||
|
if a.dp > 0 {
|
||||||
|
n += a.dp
|
||||||
|
}
|
||||||
|
if a.dp < 0 {
|
||||||
|
n += -a.dp
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, n)
|
||||||
|
w := 0
|
||||||
|
switch {
|
||||||
|
case a.nd == 0:
|
||||||
|
return "0"
|
||||||
|
|
||||||
|
case a.dp <= 0:
|
||||||
|
// zeros fill space between decimal point and digits
|
||||||
|
buf[w] = '0'
|
||||||
|
w++
|
||||||
|
buf[w] = '.'
|
||||||
|
w++
|
||||||
|
w += digitZero(buf[w : w+-a.dp])
|
||||||
|
w += copy(buf[w:], a.d[0:a.nd])
|
||||||
|
|
||||||
|
case a.dp < a.nd:
|
||||||
|
// decimal point in middle of digits
|
||||||
|
w += copy(buf[w:], a.d[0:a.dp])
|
||||||
|
buf[w] = '.'
|
||||||
|
w++
|
||||||
|
w += copy(buf[w:], a.d[a.dp:a.nd])
|
||||||
|
|
||||||
|
default:
|
||||||
|
// zeros fill space between digits and decimal point
|
||||||
|
w += copy(buf[w:], a.d[0:a.nd])
|
||||||
|
w += digitZero(buf[w : w+a.dp-a.nd])
|
||||||
|
}
|
||||||
|
return string(buf[0:w])
|
||||||
|
}
|
||||||
|
|
||||||
|
func digitZero(dst []byte) int {
|
||||||
|
for i := range dst {
|
||||||
|
dst[i] = '0'
|
||||||
|
}
|
||||||
|
return len(dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim trailing zeros from number.
|
||||||
|
// (They are meaningless; the decimal point is tracked
|
||||||
|
// independent of the number of digits.)
|
||||||
|
func trim(a *decimal) {
|
||||||
|
for a.nd > 0 && a.d[a.nd-1] == '0' {
|
||||||
|
a.nd--
|
||||||
|
}
|
||||||
|
if a.nd == 0 {
|
||||||
|
a.dp = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign v to a.
|
||||||
|
func (a *decimal) Assign(v uint64) {
|
||||||
|
var buf [24]byte
|
||||||
|
|
||||||
|
// Write reversed decimal in buf.
|
||||||
|
n := 0
|
||||||
|
for v > 0 {
|
||||||
|
v1 := v / 10
|
||||||
|
v -= 10 * v1
|
||||||
|
buf[n] = byte(v + '0')
|
||||||
|
n++
|
||||||
|
v = v1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reverse again to produce forward decimal in a.d.
|
||||||
|
a.nd = 0
|
||||||
|
for n--; n >= 0; n-- {
|
||||||
|
a.d[a.nd] = buf[n]
|
||||||
|
a.nd++
|
||||||
|
}
|
||||||
|
a.dp = a.nd
|
||||||
|
trim(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maximum shift that we can do in one pass without overflow.
|
||||||
|
// A uint has 32 or 64 bits, and we have to be able to accommodate 9<<k.
|
||||||
|
const uintSize = 32 << (^uint(0) >> 63)
|
||||||
|
const maxShift = uintSize - 4
|
||||||
|
|
||||||
|
// Binary shift right (/ 2) by k bits. k <= maxShift to avoid overflow.
|
||||||
|
func rightShift(a *decimal, k uint) {
|
||||||
|
r := 0 // read pointer
|
||||||
|
w := 0 // write pointer
|
||||||
|
|
||||||
|
// Pick up enough leading digits to cover first shift.
|
||||||
|
var n uint
|
||||||
|
for ; n>>k == 0; r++ {
|
||||||
|
if r >= a.nd {
|
||||||
|
if n == 0 {
|
||||||
|
// a == 0; shouldn't get here, but handle anyway.
|
||||||
|
a.nd = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for n>>k == 0 {
|
||||||
|
n = n * 10
|
||||||
|
r++
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := uint(a.d[r])
|
||||||
|
n = n*10 + c - '0'
|
||||||
|
}
|
||||||
|
a.dp -= r - 1
|
||||||
|
|
||||||
|
var mask uint = (1 << k) - 1
|
||||||
|
|
||||||
|
// Pick up a digit, put down a digit.
|
||||||
|
for ; r < a.nd; r++ {
|
||||||
|
c := uint(a.d[r])
|
||||||
|
dig := n >> k
|
||||||
|
n &= mask
|
||||||
|
a.d[w] = byte(dig + '0')
|
||||||
|
w++
|
||||||
|
n = n*10 + c - '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put down extra digits.
|
||||||
|
for n > 0 {
|
||||||
|
dig := n >> k
|
||||||
|
n &= mask
|
||||||
|
if w < len(a.d) {
|
||||||
|
a.d[w] = byte(dig + '0')
|
||||||
|
w++
|
||||||
|
} else if dig > 0 {
|
||||||
|
a.trunc = true
|
||||||
|
}
|
||||||
|
n = n * 10
|
||||||
|
}
|
||||||
|
|
||||||
|
a.nd = w
|
||||||
|
trim(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cheat sheet for left shift: table indexed by shift count giving
|
||||||
|
// number of new digits that will be introduced by that shift.
|
||||||
|
//
|
||||||
|
// For example, leftcheats[4] = {2, "625"}. That means that
|
||||||
|
// if we are shifting by 4 (multiplying by 16), it will add 2 digits
|
||||||
|
// when the string prefix is "625" through "999", and one fewer digit
|
||||||
|
// if the string prefix is "000" through "624".
|
||||||
|
//
|
||||||
|
// Credit for this trick goes to Ken.
|
||||||
|
|
||||||
|
type leftCheat struct {
|
||||||
|
delta int // number of new digits
|
||||||
|
cutoff string // minus one digit if original < a.
|
||||||
|
}
|
||||||
|
|
||||||
|
var leftcheats = []leftCheat{
|
||||||
|
// Leading digits of 1/2^i = 5^i.
|
||||||
|
// 5^23 is not an exact 64-bit floating point number,
|
||||||
|
// so have to use bc for the math.
|
||||||
|
// Go up to 60 to be large enough for 32bit and 64bit platforms.
|
||||||
|
/*
|
||||||
|
seq 60 | sed 's/^/5^/' | bc |
|
||||||
|
awk 'BEGIN{ print "\t{ 0, \"\" }," }
|
||||||
|
{
|
||||||
|
log2 = log(2)/log(10)
|
||||||
|
printf("\t{ %d, \"%s\" },\t// * %d\n",
|
||||||
|
int(log2*NR+1), $0, 2**NR)
|
||||||
|
}'
|
||||||
|
*/
|
||||||
|
{0, ""},
|
||||||
|
{1, "5"}, // * 2
|
||||||
|
{1, "25"}, // * 4
|
||||||
|
{1, "125"}, // * 8
|
||||||
|
{2, "625"}, // * 16
|
||||||
|
{2, "3125"}, // * 32
|
||||||
|
{2, "15625"}, // * 64
|
||||||
|
{3, "78125"}, // * 128
|
||||||
|
{3, "390625"}, // * 256
|
||||||
|
{3, "1953125"}, // * 512
|
||||||
|
{4, "9765625"}, // * 1024
|
||||||
|
{4, "48828125"}, // * 2048
|
||||||
|
{4, "244140625"}, // * 4096
|
||||||
|
{4, "1220703125"}, // * 8192
|
||||||
|
{5, "6103515625"}, // * 16384
|
||||||
|
{5, "30517578125"}, // * 32768
|
||||||
|
{5, "152587890625"}, // * 65536
|
||||||
|
{6, "762939453125"}, // * 131072
|
||||||
|
{6, "3814697265625"}, // * 262144
|
||||||
|
{6, "19073486328125"}, // * 524288
|
||||||
|
{7, "95367431640625"}, // * 1048576
|
||||||
|
{7, "476837158203125"}, // * 2097152
|
||||||
|
{7, "2384185791015625"}, // * 4194304
|
||||||
|
{7, "11920928955078125"}, // * 8388608
|
||||||
|
{8, "59604644775390625"}, // * 16777216
|
||||||
|
{8, "298023223876953125"}, // * 33554432
|
||||||
|
{8, "1490116119384765625"}, // * 67108864
|
||||||
|
{9, "7450580596923828125"}, // * 134217728
|
||||||
|
{9, "37252902984619140625"}, // * 268435456
|
||||||
|
{9, "186264514923095703125"}, // * 536870912
|
||||||
|
{10, "931322574615478515625"}, // * 1073741824
|
||||||
|
{10, "4656612873077392578125"}, // * 2147483648
|
||||||
|
{10, "23283064365386962890625"}, // * 4294967296
|
||||||
|
{10, "116415321826934814453125"}, // * 8589934592
|
||||||
|
{11, "582076609134674072265625"}, // * 17179869184
|
||||||
|
{11, "2910383045673370361328125"}, // * 34359738368
|
||||||
|
{11, "14551915228366851806640625"}, // * 68719476736
|
||||||
|
{12, "72759576141834259033203125"}, // * 137438953472
|
||||||
|
{12, "363797880709171295166015625"}, // * 274877906944
|
||||||
|
{12, "1818989403545856475830078125"}, // * 549755813888
|
||||||
|
{13, "9094947017729282379150390625"}, // * 1099511627776
|
||||||
|
{13, "45474735088646411895751953125"}, // * 2199023255552
|
||||||
|
{13, "227373675443232059478759765625"}, // * 4398046511104
|
||||||
|
{13, "1136868377216160297393798828125"}, // * 8796093022208
|
||||||
|
{14, "5684341886080801486968994140625"}, // * 17592186044416
|
||||||
|
{14, "28421709430404007434844970703125"}, // * 35184372088832
|
||||||
|
{14, "142108547152020037174224853515625"}, // * 70368744177664
|
||||||
|
{15, "710542735760100185871124267578125"}, // * 140737488355328
|
||||||
|
{15, "3552713678800500929355621337890625"}, // * 281474976710656
|
||||||
|
{15, "17763568394002504646778106689453125"}, // * 562949953421312
|
||||||
|
{16, "88817841970012523233890533447265625"}, // * 1125899906842624
|
||||||
|
{16, "444089209850062616169452667236328125"}, // * 2251799813685248
|
||||||
|
{16, "2220446049250313080847263336181640625"}, // * 4503599627370496
|
||||||
|
{16, "11102230246251565404236316680908203125"}, // * 9007199254740992
|
||||||
|
{17, "55511151231257827021181583404541015625"}, // * 18014398509481984
|
||||||
|
{17, "277555756156289135105907917022705078125"}, // * 36028797018963968
|
||||||
|
{17, "1387778780781445675529539585113525390625"}, // * 72057594037927936
|
||||||
|
{18, "6938893903907228377647697925567626953125"}, // * 144115188075855872
|
||||||
|
{18, "34694469519536141888238489627838134765625"}, // * 288230376151711744
|
||||||
|
{18, "173472347597680709441192448139190673828125"}, // * 576460752303423488
|
||||||
|
{19, "867361737988403547205962240695953369140625"}, // * 1152921504606846976
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the leading prefix of b lexicographically less than s?
|
||||||
|
func prefixIsLessThan(b []byte, s string) bool {
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if i >= len(b) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if b[i] != s[i] {
|
||||||
|
return b[i] < s[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary shift left (* 2) by k bits. k <= maxShift to avoid overflow.
|
||||||
|
func leftShift(a *decimal, k uint) {
|
||||||
|
delta := leftcheats[k].delta
|
||||||
|
if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
|
||||||
|
delta--
|
||||||
|
}
|
||||||
|
|
||||||
|
r := a.nd // read index
|
||||||
|
w := a.nd + delta // write index
|
||||||
|
|
||||||
|
// Pick up a digit, put down a digit.
|
||||||
|
var n uint
|
||||||
|
for r--; r >= 0; r-- {
|
||||||
|
n += (uint(a.d[r]) - '0') << k
|
||||||
|
quo := n / 10
|
||||||
|
rem := n - 10*quo
|
||||||
|
w--
|
||||||
|
if w < len(a.d) {
|
||||||
|
a.d[w] = byte(rem + '0')
|
||||||
|
} else if rem != 0 {
|
||||||
|
a.trunc = true
|
||||||
|
}
|
||||||
|
n = quo
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put down extra digits.
|
||||||
|
for n > 0 {
|
||||||
|
quo := n / 10
|
||||||
|
rem := n - 10*quo
|
||||||
|
w--
|
||||||
|
if w < len(a.d) {
|
||||||
|
a.d[w] = byte(rem + '0')
|
||||||
|
} else if rem != 0 {
|
||||||
|
a.trunc = true
|
||||||
|
}
|
||||||
|
n = quo
|
||||||
|
}
|
||||||
|
|
||||||
|
a.nd += delta
|
||||||
|
if a.nd >= len(a.d) {
|
||||||
|
a.nd = len(a.d)
|
||||||
|
}
|
||||||
|
a.dp += delta
|
||||||
|
trim(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary shift left (k > 0) or right (k < 0).
|
||||||
|
func (a *decimal) Shift(k int) {
|
||||||
|
switch {
|
||||||
|
case a.nd == 0:
|
||||||
|
// nothing to do: a == 0
|
||||||
|
case k > 0:
|
||||||
|
for k > maxShift {
|
||||||
|
leftShift(a, maxShift)
|
||||||
|
k -= maxShift
|
||||||
|
}
|
||||||
|
leftShift(a, uint(k))
|
||||||
|
case k < 0:
|
||||||
|
for k < -maxShift {
|
||||||
|
rightShift(a, maxShift)
|
||||||
|
k += maxShift
|
||||||
|
}
|
||||||
|
rightShift(a, uint(-k))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we chop a at nd digits, should we round up?
|
||||||
|
func shouldRoundUp(a *decimal, nd int) bool {
|
||||||
|
if nd < 0 || nd >= a.nd {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even
|
||||||
|
// if we truncated, a little higher than what's recorded - always round up
|
||||||
|
if a.trunc {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return nd > 0 && (a.d[nd-1]-'0')%2 != 0
|
||||||
|
}
|
||||||
|
// not halfway - digit tells all
|
||||||
|
return a.d[nd] >= '5'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round a to nd digits (or fewer).
|
||||||
|
// If nd is zero, it means we're rounding
|
||||||
|
// just to the left of the digits, as in
|
||||||
|
// 0.09 -> 0.1.
|
||||||
|
func (a *decimal) Round(nd int) {
|
||||||
|
if nd < 0 || nd >= a.nd {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if shouldRoundUp(a, nd) {
|
||||||
|
a.RoundUp(nd)
|
||||||
|
} else {
|
||||||
|
a.RoundDown(nd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round a down to nd digits (or fewer).
|
||||||
|
func (a *decimal) RoundDown(nd int) {
|
||||||
|
if nd < 0 || nd >= a.nd {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
a.nd = nd
|
||||||
|
trim(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round a up to nd digits (or fewer).
|
||||||
|
func (a *decimal) RoundUp(nd int) {
|
||||||
|
if nd < 0 || nd >= a.nd {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// round up
|
||||||
|
for i := nd - 1; i >= 0; i-- {
|
||||||
|
c := a.d[i]
|
||||||
|
if c < '9' { // can stop after this digit
|
||||||
|
a.d[i]++
|
||||||
|
a.nd = i + 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number is all 9s.
|
||||||
|
// Change to single 1 with adjusted decimal point.
|
||||||
|
a.d[0] = '1'
|
||||||
|
a.nd = 1
|
||||||
|
a.dp++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract integer part, rounded appropriately.
|
||||||
|
// No guarantees about overflow.
|
||||||
|
func (a *decimal) RoundedInteger() uint64 {
|
||||||
|
if a.dp > 20 {
|
||||||
|
return 0xFFFFFFFFFFFFFFFF
|
||||||
|
}
|
||||||
|
var i int
|
||||||
|
n := uint64(0)
|
||||||
|
for i = 0; i < a.dp && i < a.nd; i++ {
|
||||||
|
n = n*10 + uint64(a.d[i]-'0')
|
||||||
|
}
|
||||||
|
for ; i < a.dp; i++ {
|
||||||
|
n *= 10
|
||||||
|
}
|
||||||
|
if shouldRoundUp(a, a.dp) {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
1904
vendor/github.com/shopspring/decimal/decimal.go
generated
vendored
Normal file
1904
vendor/github.com/shopspring/decimal/decimal.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
160
vendor/github.com/shopspring/decimal/rounding.go
generated
vendored
Normal file
160
vendor/github.com/shopspring/decimal/rounding.go
generated
vendored
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Multiprecision decimal numbers.
|
||||||
|
// For floating-point formatting only; not general purpose.
|
||||||
|
// Only operations are assign and (binary) left/right shift.
|
||||||
|
// Can do binary floating point in multiprecision decimal precisely
|
||||||
|
// because 2 divides 10; cannot do decimal floating point
|
||||||
|
// in multiprecision binary precisely.
|
||||||
|
|
||||||
|
package decimal
|
||||||
|
|
||||||
|
type floatInfo struct {
|
||||||
|
mantbits uint
|
||||||
|
expbits uint
|
||||||
|
bias int
|
||||||
|
}
|
||||||
|
|
||||||
|
var float32info = floatInfo{23, 8, -127}
|
||||||
|
var float64info = floatInfo{52, 11, -1023}
|
||||||
|
|
||||||
|
// roundShortest rounds d (= mant * 2^exp) to the shortest number of digits
|
||||||
|
// that will let the original floating point value be precisely reconstructed.
|
||||||
|
func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
|
||||||
|
// If mantissa is zero, the number is zero; stop now.
|
||||||
|
if mant == 0 {
|
||||||
|
d.nd = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute upper and lower such that any decimal number
|
||||||
|
// between upper and lower (possibly inclusive)
|
||||||
|
// will round to the original floating point number.
|
||||||
|
|
||||||
|
// We may see at once that the number is already shortest.
|
||||||
|
//
|
||||||
|
// Suppose d is not denormal, so that 2^exp <= d < 10^dp.
|
||||||
|
// The closest shorter number is at least 10^(dp-nd) away.
|
||||||
|
// The lower/upper bounds computed below are at distance
|
||||||
|
// at most 2^(exp-mantbits).
|
||||||
|
//
|
||||||
|
// So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits),
|
||||||
|
// or equivalently log2(10)*(dp-nd) > exp-mantbits.
|
||||||
|
// It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32).
|
||||||
|
minexp := flt.bias + 1 // minimum possible exponent
|
||||||
|
if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) {
|
||||||
|
// The number is already shortest.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// d = mant << (exp - mantbits)
|
||||||
|
// Next highest floating point number is mant+1 << exp-mantbits.
|
||||||
|
// Our upper bound is halfway between, mant*2+1 << exp-mantbits-1.
|
||||||
|
upper := new(decimal)
|
||||||
|
upper.Assign(mant*2 + 1)
|
||||||
|
upper.Shift(exp - int(flt.mantbits) - 1)
|
||||||
|
|
||||||
|
// d = mant << (exp - mantbits)
|
||||||
|
// Next lowest floating point number is mant-1 << exp-mantbits,
|
||||||
|
// unless mant-1 drops the significant bit and exp is not the minimum exp,
|
||||||
|
// in which case the next lowest is mant*2-1 << exp-mantbits-1.
|
||||||
|
// Either way, call it mantlo << explo-mantbits.
|
||||||
|
// Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1.
|
||||||
|
var mantlo uint64
|
||||||
|
var explo int
|
||||||
|
if mant > 1<<flt.mantbits || exp == minexp {
|
||||||
|
mantlo = mant - 1
|
||||||
|
explo = exp
|
||||||
|
} else {
|
||||||
|
mantlo = mant*2 - 1
|
||||||
|
explo = exp - 1
|
||||||
|
}
|
||||||
|
lower := new(decimal)
|
||||||
|
lower.Assign(mantlo*2 + 1)
|
||||||
|
lower.Shift(explo - int(flt.mantbits) - 1)
|
||||||
|
|
||||||
|
// The upper and lower bounds are possible outputs only if
|
||||||
|
// the original mantissa is even, so that IEEE round-to-even
|
||||||
|
// would round to the original mantissa and not the neighbors.
|
||||||
|
inclusive := mant%2 == 0
|
||||||
|
|
||||||
|
// As we walk the digits we want to know whether rounding up would fall
|
||||||
|
// within the upper bound. This is tracked by upperdelta:
|
||||||
|
//
|
||||||
|
// If upperdelta == 0, the digits of d and upper are the same so far.
|
||||||
|
//
|
||||||
|
// If upperdelta == 1, we saw a difference of 1 between d and upper on a
|
||||||
|
// previous digit and subsequently only 9s for d and 0s for upper.
|
||||||
|
// (Thus rounding up may fall outside the bound, if it is exclusive.)
|
||||||
|
//
|
||||||
|
// If upperdelta == 2, then the difference is greater than 1
|
||||||
|
// and we know that rounding up falls within the bound.
|
||||||
|
var upperdelta uint8
|
||||||
|
|
||||||
|
// Now we can figure out the minimum number of digits required.
|
||||||
|
// Walk along until d has distinguished itself from upper and lower.
|
||||||
|
for ui := 0; ; ui++ {
|
||||||
|
// lower, d, and upper may have the decimal points at different
|
||||||
|
// places. In this case upper is the longest, so we iterate from
|
||||||
|
// ui==0 and start li and mi at (possibly) -1.
|
||||||
|
mi := ui - upper.dp + d.dp
|
||||||
|
if mi >= d.nd {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
li := ui - upper.dp + lower.dp
|
||||||
|
l := byte('0') // lower digit
|
||||||
|
if li >= 0 && li < lower.nd {
|
||||||
|
l = lower.d[li]
|
||||||
|
}
|
||||||
|
m := byte('0') // middle digit
|
||||||
|
if mi >= 0 {
|
||||||
|
m = d.d[mi]
|
||||||
|
}
|
||||||
|
u := byte('0') // upper digit
|
||||||
|
if ui < upper.nd {
|
||||||
|
u = upper.d[ui]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Okay to round down (truncate) if lower has a different digit
|
||||||
|
// or if lower is inclusive and is exactly the result of rounding
|
||||||
|
// down (i.e., and we have reached the final digit of lower).
|
||||||
|
okdown := l != m || inclusive && li+1 == lower.nd
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case upperdelta == 0 && m+1 < u:
|
||||||
|
// Example:
|
||||||
|
// m = 12345xxx
|
||||||
|
// u = 12347xxx
|
||||||
|
upperdelta = 2
|
||||||
|
case upperdelta == 0 && m != u:
|
||||||
|
// Example:
|
||||||
|
// m = 12345xxx
|
||||||
|
// u = 12346xxx
|
||||||
|
upperdelta = 1
|
||||||
|
case upperdelta == 1 && (m != '9' || u != '0'):
|
||||||
|
// Example:
|
||||||
|
// m = 1234598x
|
||||||
|
// u = 1234600x
|
||||||
|
upperdelta = 2
|
||||||
|
}
|
||||||
|
// Okay to round up if upper has a different digit and either upper
|
||||||
|
// is inclusive or upper is bigger than the result of rounding up.
|
||||||
|
okup := upperdelta > 0 && (inclusive || upperdelta > 1 || ui+1 < upper.nd)
|
||||||
|
|
||||||
|
// If it's okay to do either, then round to the nearest one.
|
||||||
|
// If it's okay to do only one, do it.
|
||||||
|
switch {
|
||||||
|
case okdown && okup:
|
||||||
|
d.Round(mi + 1)
|
||||||
|
return
|
||||||
|
case okdown:
|
||||||
|
d.RoundDown(mi + 1)
|
||||||
|
return
|
||||||
|
case okup:
|
||||||
|
d.RoundUp(mi + 1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
vendor/github.com/spf13/cast/.gitignore
generated
vendored
Normal file
25
vendor/github.com/spf13/cast/.gitignore
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
|
||||||
|
*.bench
|
21
vendor/github.com/spf13/cast/LICENSE
generated
vendored
Normal file
21
vendor/github.com/spf13/cast/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Steve Francia
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
40
vendor/github.com/spf13/cast/Makefile
generated
vendored
Normal file
40
vendor/github.com/spf13/cast/Makefile
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
GOVERSION := $(shell go version | cut -d ' ' -f 3 | cut -d '.' -f 2)
|
||||||
|
|
||||||
|
.PHONY: check fmt lint test test-race vet test-cover-html help
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
|
|
||||||
|
check: test-race fmt vet lint ## Run tests and linters
|
||||||
|
|
||||||
|
test: ## Run tests
|
||||||
|
go test ./...
|
||||||
|
|
||||||
|
test-race: ## Run tests with race detector
|
||||||
|
go test -race ./...
|
||||||
|
|
||||||
|
fmt: ## Run gofmt linter
|
||||||
|
ifeq "$(GOVERSION)" "12"
|
||||||
|
@for d in `go list` ; do \
|
||||||
|
if [ "`gofmt -l -s $$GOPATH/src/$$d | tee /dev/stderr`" ]; then \
|
||||||
|
echo "^ improperly formatted go files" && echo && exit 1; \
|
||||||
|
fi \
|
||||||
|
done
|
||||||
|
endif
|
||||||
|
|
||||||
|
lint: ## Run golint linter
|
||||||
|
@for d in `go list` ; do \
|
||||||
|
if [ "`golint $$d | tee /dev/stderr`" ]; then \
|
||||||
|
echo "^ golint errors!" && echo && exit 1; \
|
||||||
|
fi \
|
||||||
|
done
|
||||||
|
|
||||||
|
vet: ## Run go vet linter
|
||||||
|
@if [ "`go vet | tee /dev/stderr`" ]; then \
|
||||||
|
echo "^ go vet errors!" && echo && exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
test-cover-html: ## Generate test coverage report
|
||||||
|
go test -coverprofile=coverage.out -covermode=count
|
||||||
|
go tool cover -func=coverage.out
|
||||||
|
|
||||||
|
help:
|
||||||
|
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user