mirror of
https://git.uploadfilter24.eu/lerentis/terraform-provider-gitea.git
synced 2024-12-04 21:08:11 +00:00
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
210 changed files with 32649 additions and 2138 deletions
26
go.mod
26
go.mod
|
@ -4,24 +4,24 @@ go 1.18
|
|||
|
||||
require (
|
||||
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
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Masterminds/goutils v1.1.0 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.1.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
|
||||
github.com/agext/levenshtein v1.2.2 // 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/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/go-cmp v0.5.8 // indirect
|
||||
github.com/google/uuid v1.1.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // 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/yamux v0.0.0-20181012175058-2f1d1f20f75d // 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-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/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // 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/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 v4.3.12 // indirect
|
||||
github.com/vmihailenco/tagparser v0.1.1 // 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/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
|
||||
google.golang.org/appengine v1.6.6 // 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/go.mod h1:klY2LVI3s3NChzIk/MzMn7G1FHrfU7qd63iSMVoHRBA=
|
||||
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/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
||||
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.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
|
||||
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/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
|
||||
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 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/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
||||
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/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
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/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
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.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
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.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/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.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/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
|
||||
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-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s=
|
||||
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.7.0/go.mod h1:57CICKfW7/KbW4lPhKOledyT6vu1LeAOzuvWXsVaxUE=
|
||||
github.com/hashicorp/terraform-plugin-docs v0.13.0 h1:6e+VIWsVGb6jYJewfzq2ok2smPzZrt1Wlm9koLeKazY=
|
||||
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/go.mod h1:kwhmaWHNDvT1B3QiSJdAtrB/D4RaKSY/v3r2BuoWK4M=
|
||||
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/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
|
||||
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/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.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
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/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
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/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.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
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/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
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.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
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.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
|
||||
github.com/mitchellh/cli v1.1.4 h1:qj8czE26AU4PbiaPXK5uVmMSM+V5BYsFBiM9HhGRLUA=
|
||||
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.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
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.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/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/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
|
||||
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.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/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.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
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-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-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-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-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-20220517005047-85d78b3ac167 h1:O8uGbHCqlTp2P6QJSLmCojM4mN6UemYv8K+dCnmHmu0=
|
||||
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
||||
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/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=
|
||||
|
@ -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-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-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-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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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.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.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
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=
|
||||
|
|
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"
|
||||
"math"
|
||||
"math/big"
|
||||
"regexp"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
|
@ -99,27 +98,7 @@ Returns:
|
|||
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||
*/
|
||||
func CryptoRandomAlphaNumeric(count int) (string, error) {
|
||||
if count == 0 {
|
||||
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
|
||||
|
||||
return CryptoRandom(count, 0, 0, true, true)
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -204,7 +183,7 @@ func CryptoRandom(count int, start int, end int, letters bool, numbers bool, cha
|
|||
if chars == nil {
|
||||
ch = rune(getCryptoRandomInt(gap) + int64(start))
|
||||
} else {
|
||||
ch = chars[getCryptoRandomInt(gap) + int64(start)]
|
||||
ch = chars[getCryptoRandomInt(gap)+int64(start)]
|
||||
}
|
||||
|
||||
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"
|
||||
"math"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"time"
|
||||
"unicode"
|
||||
)
|
||||
|
@ -75,12 +74,10 @@ func RandomNumeric(count int) (string, error) {
|
|||
|
||||
/*
|
||||
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:
|
||||
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:
|
||||
string - the random string
|
||||
|
@ -102,24 +99,7 @@ Returns:
|
|||
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
|
||||
*/
|
||||
func RandomAlphaNumeric(count int) (string, error) {
|
||||
RandomString, err := 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
|
||||
|
||||
return Random(count, 0, 0, true, true)
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
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 {
|
||||
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 (
|
||||
"bytes"
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -13,13 +14,23 @@ import (
|
|||
// The compiled version of the regex created at init() is cached here so it
|
||||
// only needs to be created once.
|
||||
var versionRegex *regexp.Regexp
|
||||
var validPrereleaseRegex *regexp.Regexp
|
||||
|
||||
var (
|
||||
// ErrInvalidSemVer is returned a version is found to be invalid when
|
||||
// being parsed.
|
||||
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 = errors.New("Invalid Metadata string")
|
||||
|
||||
|
@ -27,30 +38,121 @@ var (
|
|||
ErrInvalidPrerelease = errors.New("Invalid Prerelease string")
|
||||
)
|
||||
|
||||
// SemVerRegex is the regular expression used to parse a semantic version.
|
||||
const SemVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` +
|
||||
// semVerRegex is the regular expression used to parse a semantic version.
|
||||
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\-]+)*))?`
|
||||
|
||||
// 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.
|
||||
type Version struct {
|
||||
major, minor, patch int64
|
||||
major, minor, patch uint64
|
||||
pre string
|
||||
metadata string
|
||||
original string
|
||||
}
|
||||
|
||||
func init() {
|
||||
versionRegex = regexp.MustCompile("^" + SemVerRegex + "$")
|
||||
validPrereleaseRegex = regexp.MustCompile(ValidPrerelease)
|
||||
versionRegex = regexp.MustCompile("^" + semVerRegex + "$")
|
||||
}
|
||||
|
||||
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
|
||||
// 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) {
|
||||
m := versionRegex.FindStringSubmatch(v)
|
||||
if m == nil {
|
||||
|
@ -63,33 +165,45 @@ func NewVersion(v string) (*Version, error) {
|
|||
original: v,
|
||||
}
|
||||
|
||||
var temp int64
|
||||
temp, err := strconv.ParseInt(m[1], 10, 64)
|
||||
var err error
|
||||
sv.major, err = strconv.ParseUint(m[1], 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
||||
}
|
||||
sv.major = temp
|
||||
|
||||
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 {
|
||||
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
||||
}
|
||||
sv.minor = temp
|
||||
} else {
|
||||
sv.minor = 0
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
||||
}
|
||||
sv.patch = temp
|
||||
} else {
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -107,7 +221,7 @@ func MustParse(v string) *Version {
|
|||
// 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
|
||||
// implementation.
|
||||
func (v *Version) String() string {
|
||||
func (v Version) String() string {
|
||||
var buf bytes.Buffer
|
||||
|
||||
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.
|
||||
func (v *Version) Major() int64 {
|
||||
func (v Version) Major() uint64 {
|
||||
return v.major
|
||||
}
|
||||
|
||||
// Minor returns the minor version.
|
||||
func (v *Version) Minor() int64 {
|
||||
func (v Version) Minor() uint64 {
|
||||
return v.minor
|
||||
}
|
||||
|
||||
// Patch returns the patch version.
|
||||
func (v *Version) Patch() int64 {
|
||||
func (v Version) Patch() uint64 {
|
||||
return v.patch
|
||||
}
|
||||
|
||||
// Prerelease returns the pre-release version.
|
||||
func (v *Version) Prerelease() string {
|
||||
func (v Version) Prerelease() string {
|
||||
return v.pre
|
||||
}
|
||||
|
||||
// Metadata returns the metadata on the version.
|
||||
func (v *Version) Metadata() string {
|
||||
func (v Version) Metadata() string {
|
||||
return v.metadata
|
||||
}
|
||||
|
||||
// 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.
|
||||
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,
|
||||
// it unsets metadata and prerelease values, increments patch number.
|
||||
// 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 {
|
||||
vNext := v
|
||||
// according to http://semver.org/#spec-item-9
|
||||
|
@ -217,11 +331,13 @@ func (v Version) IncMajor() Version {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
vNext := v
|
||||
if len(prerelease) > 0 && !validPrereleaseRegex.MatchString(prerelease) {
|
||||
return vNext, ErrInvalidPrerelease
|
||||
if len(prerelease) > 0 {
|
||||
if err := validatePrerelease(prerelease); err != nil {
|
||||
return vNext, err
|
||||
}
|
||||
}
|
||||
vNext.pre = prerelease
|
||||
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.
|
||||
func (v Version) SetMetadata(metadata string) (Version, error) {
|
||||
vNext := v
|
||||
if len(metadata) > 0 && !validPrereleaseRegex.MatchString(metadata) {
|
||||
return vNext, ErrInvalidMetadata
|
||||
if len(metadata) > 0 {
|
||||
if err := validateMetadata(metadata); err != nil {
|
||||
return vNext, err
|
||||
}
|
||||
}
|
||||
vNext.metadata = metadata
|
||||
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.
|
||||
//
|
||||
// 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 {
|
||||
// Compare the major, minor, and patch version for differences. If a
|
||||
// difference is found return the comparison.
|
||||
|
@ -308,16 +428,37 @@ func (v *Version) UnmarshalJSON(b []byte) error {
|
|||
v.pre = temp.pre
|
||||
v.metadata = temp.metadata
|
||||
v.original = temp.original
|
||||
temp = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements JSON.Marshaler interface.
|
||||
func (v *Version) MarshalJSON() ([]byte, error) {
|
||||
func (v Version) MarshalJSON() ([]byte, error) {
|
||||
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 {
|
||||
return -1
|
||||
}
|
||||
|
@ -423,3 +564,43 @@ func comparePrePart(s, o string) int {
|
|||
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
|
||||
|
||||
## 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)
|
||||
|
||||
### Added
|
|
@ -1,5 +1,4 @@
|
|||
Sprig
|
||||
Copyright (C) 2013 Masterminds
|
||||
Copyright (C) 2013-2020 Masterminds
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
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
|
||||
|
||||
[![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)
|
||||
[![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
|
||||
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
|
||||
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
|
||||
|
||||
**Template developers**: Please use Sprig's [function documentation](http://masterminds.github.io/sprig/) for
|
|
@ -2,10 +2,12 @@ package sprig
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/elliptic"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
|
@ -21,13 +23,16 @@ import (
|
|||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"hash/adler32"
|
||||
"io"
|
||||
"math/big"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
bcrypt_lib "golang.org/x/crypto/bcrypt"
|
||||
"golang.org/x/crypto/scrypt"
|
||||
)
|
||||
|
||||
|
@ -46,14 +51,38 @@ func adler32sum(input string) string {
|
|||
return fmt.Sprintf("%d", hash)
|
||||
}
|
||||
|
||||
// uuidv4 provides a safe and secure UUID v4 implementation
|
||||
func uuidv4() string {
|
||||
return fmt.Sprintf("%s", uuid.New())
|
||||
func bcrypt(input string) string {
|
||||
hash, err := bcrypt_lib.GenerateFromPassword([]byte(input), bcrypt_lib.DefaultCost)
|
||||
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")},
|
||||
"long": {[]byte("CvcvnoCvcvCvcv"), []byte("CvcvCvcvnoCvcv"), []byte("CvcvCvcvCvcvno"), []byte("CvccnoCvcvCvcv"), []byte("CvccCvcvnoCvcv"),
|
||||
[]byte("CvccCvcvCvcvno"), []byte("CvcvnoCvccCvcv"), []byte("CvcvCvccnoCvcv"), []byte("CvcvCvccCvcvno"), []byte("CvcvnoCvcvCvcc"),
|
||||
|
@ -66,7 +95,7 @@ var password_type_templates = map[string][][]byte{
|
|||
"pin": {[]byte("nnnn")},
|
||||
}
|
||||
|
||||
var template_characters = map[byte]string{
|
||||
var templateCharacters = map[byte]string{
|
||||
'V': "AEIOU",
|
||||
'C': "BCDFGHJKLMNPQRSTVWXYZ",
|
||||
'v': "aeiou",
|
||||
|
@ -78,14 +107,14 @@ var template_characters = map[byte]string{
|
|||
'x': "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()",
|
||||
}
|
||||
|
||||
func derivePassword(counter uint32, password_type, password, user, site string) string {
|
||||
var templates = password_type_templates[password_type]
|
||||
func derivePassword(counter uint32, passwordType, password, user, site string) string {
|
||||
var templates = passwordTypeTemplates[passwordType]
|
||||
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
|
||||
buffer.WriteString(master_password_seed)
|
||||
buffer.WriteString(masterPasswordSeed)
|
||||
binary.Write(&buffer, binary.BigEndian, uint32(len(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)
|
||||
}
|
||||
|
||||
buffer.Truncate(len(master_password_seed))
|
||||
buffer.Truncate(len(masterPasswordSeed))
|
||||
binary.Write(&buffer, binary.BigEndian, uint32(len(site)))
|
||||
buffer.WriteString(site)
|
||||
binary.Write(&buffer, binary.BigEndian, counter)
|
||||
|
@ -107,9 +136,9 @@ func derivePassword(counter uint32, password_type, password, user, site string)
|
|||
|
||||
buffer.Truncate(0)
|
||||
for i, element := range temp {
|
||||
pass_chars := template_characters[element]
|
||||
pass_char := pass_chars[int(seed[i+1])%len(pass_chars)]
|
||||
buffer.WriteByte(pass_char)
|
||||
passChars := templateCharacters[element]
|
||||
passChar := passChars[int(seed[i+1])%len(passChars)]
|
||||
buffer.WriteByte(passChar)
|
||||
}
|
||||
|
||||
return buffer.String()
|
||||
|
@ -133,6 +162,8 @@ func generatePrivateKey(typ string) string {
|
|||
case "ecdsa":
|
||||
// again, good enough for government work
|
||||
priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
case "ed25519":
|
||||
_, priv, err = ed25519.GenerateKey(rand.Reader)
|
||||
default:
|
||||
return "Unknown type " + typ
|
||||
}
|
||||
|
@ -143,6 +174,8 @@ func generatePrivateKey(typ string) string {
|
|||
return string(pem.EncodeToMemory(pemBlockForKey(priv)))
|
||||
}
|
||||
|
||||
// DSAKeyFormat stores the format for DSA keys.
|
||||
// Used by pemBlockForKey
|
||||
type DSAKeyFormat struct {
|
||||
Version int
|
||||
P, Q, G, Y, X *big.Int
|
||||
|
@ -163,7 +196,73 @@ func pemBlockForKey(priv interface{}) *pem.Block {
|
|||
b, _ := x509.MarshalECPrivateKey(k)
|
||||
return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
|
||||
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)
|
||||
if decodedKey == nil {
|
||||
return crt, errors.New("unable to decode key")
|
||||
}
|
||||
_, err = x509.ParsePKCS1PrivateKey(decodedKey.Bytes)
|
||||
_, err = parsePrivateKeyPEM(string(key))
|
||||
if err != nil {
|
||||
return crt, fmt.Errorf(
|
||||
"error parsing prive key: decodedKey.Bytes: %s",
|
||||
"error parsing private key: %s",
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
@ -218,6 +313,31 @@ func buildCustomCertificate(b64cert string, b64key string) (certificate, error)
|
|||
func generateCertificateAuthority(
|
||||
cn string,
|
||||
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) {
|
||||
ca := certificate{}
|
||||
|
||||
|
@ -231,17 +351,9 @@ func generateCertificateAuthority(
|
|||
x509.KeyUsageCertSign
|
||||
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)
|
||||
if err != nil {
|
||||
return ca, err
|
||||
}
|
||||
|
||||
return ca, nil
|
||||
return ca, err
|
||||
}
|
||||
|
||||
func generateSelfSignedCertificate(
|
||||
|
@ -249,6 +361,34 @@ func generateSelfSignedCertificate(
|
|||
ips []interface{},
|
||||
alternateDNS []interface{},
|
||||
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) {
|
||||
cert := certificate{}
|
||||
|
||||
|
@ -257,17 +397,9 @@ func generateSelfSignedCertificate(
|
|||
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)
|
||||
if err != nil {
|
||||
return cert, err
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
return cert, err
|
||||
}
|
||||
|
||||
func generateSignedCertificate(
|
||||
|
@ -276,6 +408,36 @@ func generateSignedCertificate(
|
|||
alternateDNS []interface{},
|
||||
daysValid int,
|
||||
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) {
|
||||
cert := certificate{}
|
||||
|
||||
|
@ -290,14 +452,10 @@ func generateSignedCertificate(
|
|||
err,
|
||||
)
|
||||
}
|
||||
decodedSignerKey, _ := pem.Decode([]byte(ca.Key))
|
||||
if decodedSignerKey == nil {
|
||||
return cert, errors.New("unable to decode key")
|
||||
}
|
||||
signerKey, err := x509.ParsePKCS1PrivateKey(decodedSignerKey.Bytes)
|
||||
signerKey, err := parsePrivateKeyPEM(ca.Key)
|
||||
if err != nil {
|
||||
return cert, fmt.Errorf(
|
||||
"error parsing prive key: decodedSignerKey.Bytes: %s",
|
||||
"error parsing private key: %s",
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
@ -307,35 +465,31 @@ func generateSignedCertificate(
|
|||
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,
|
||||
signerCert,
|
||||
signerKey,
|
||||
)
|
||||
if err != nil {
|
||||
return cert, err
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
return cert, err
|
||||
}
|
||||
|
||||
func getCertAndKey(
|
||||
template *x509.Certificate,
|
||||
signeeKey *rsa.PrivateKey,
|
||||
signeeKey crypto.PrivateKey,
|
||||
parent *x509.Certificate,
|
||||
signingKey *rsa.PrivateKey,
|
||||
signingKey crypto.PrivateKey,
|
||||
) (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(
|
||||
rand.Reader,
|
||||
template,
|
||||
parent,
|
||||
&signeeKey.PublicKey,
|
||||
signeePubKey,
|
||||
signingKey,
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -353,15 +507,12 @@ func getCertAndKey(
|
|||
keyBuffer := bytes.Buffer{}
|
||||
if err := pem.Encode(
|
||||
&keyBuffer,
|
||||
&pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(signeeKey),
|
||||
},
|
||||
pemBlockForKey(signeeKey),
|
||||
); err != nil {
|
||||
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(
|
|
@ -55,6 +55,14 @@ func dateModify(fmt string, date time.Time) time.Time {
|
|||
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 {
|
||||
var t time.Time
|
||||
|
||||
|
@ -73,11 +81,72 @@ func dateAgo(date interface{}) 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 {
|
||||
t, _ := time.ParseInLocation(fmt, str, time.Local)
|
||||
return t
|
||||
}
|
||||
|
||||
func mustToDate(fmt, str string) (time.Time, error) {
|
||||
return time.ParseInLocation(fmt, str, time.Local)
|
||||
}
|
||||
|
||||
func unixEpoch(date time.Time) string {
|
||||
return strconv.FormatInt(date.Unix(), 10)
|
||||
}
|
|
@ -1,10 +1,18 @@
|
|||
package sprig
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
@ -37,7 +45,7 @@ func empty(given interface{}) bool {
|
|||
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
|
||||
return g.Len() == 0
|
||||
case reflect.Bool:
|
||||
return g.Bool() == false
|
||||
return !g.Bool()
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
return g.Complex() == 0
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
|
@ -61,18 +69,90 @@ func coalesce(v ...interface{}) interface{} {
|
|||
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
|
||||
func toJson(v interface{}) string {
|
||||
output, _ := json.Marshal(v)
|
||||
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
|
||||
func toPrettyJson(v interface{}) string {
|
||||
output, _ := json.MarshalIndent(v, "", " ")
|
||||
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.
|
||||
func ternary(vt interface{}, vf interface{}, v bool) interface{} {
|
||||
if v {
|
|
@ -5,6 +5,13 @@ import (
|
|||
"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{} {
|
||||
d[key] = value
|
||||
return d
|
||||
|
@ -90,6 +97,15 @@ func merge(dst map[string]interface{}, srcs ...map[string]interface{}) interface
|
|||
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{} {
|
||||
for _, src := range srcs {
|
||||
if err := mergo.MergeWithOverwrite(&dst, src); err != nil {
|
||||
|
@ -100,6 +116,15 @@ func mergeOverwrite(dst map[string]interface{}, srcs ...map[string]interface{})
|
|||
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{} {
|
||||
values := []interface{}{}
|
||||
for _, value := range dict {
|
||||
|
@ -110,10 +135,40 @@ func values(dict map[string]interface{}) []interface{} {
|
|||
}
|
||||
|
||||
func deepCopy(i interface{}) interface{} {
|
||||
c, err := copystructure.Copy(i)
|
||||
c, err := mustDeepCopy(i)
|
||||
if err != nil {
|
||||
panic("deepCopy error: " + err.Error())
|
||||
}
|
||||
|
||||
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
|
||||
inside of Go `html/template` and `text/template` files.
|
|
@ -3,8 +3,10 @@ package sprig
|
|||
import (
|
||||
"errors"
|
||||
"html/template"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -13,9 +15,10 @@ import (
|
|||
|
||||
util "github.com/Masterminds/goutils"
|
||||
"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:
|
||||
//
|
||||
|
@ -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
|
||||
// refer to the environemnt or global state.
|
||||
// refer to the environment or global state.
|
||||
var nonhermeticFunctions = []string{
|
||||
// Date functions
|
||||
"date",
|
||||
|
@ -80,6 +83,7 @@ var nonhermeticFunctions = []string{
|
|||
"randAlpha",
|
||||
"randAscii",
|
||||
"randNumeric",
|
||||
"randBytes",
|
||||
"uuidv4",
|
||||
|
||||
// OS
|
||||
|
@ -94,17 +98,22 @@ var genericMap = map[string]interface{}{
|
|||
"hello": func() string { return "Hello!" },
|
||||
|
||||
// Date functions
|
||||
"date": date,
|
||||
"date_in_zone": dateInZone,
|
||||
"date_modify": dateModify,
|
||||
"now": func() time.Time { return time.Now() },
|
||||
"htmlDate": htmlDate,
|
||||
"htmlDateInZone": htmlDateInZone,
|
||||
"dateInZone": dateInZone,
|
||||
"dateModify": dateModify,
|
||||
"ago": dateAgo,
|
||||
"toDate": toDate,
|
||||
"unixEpoch": unixEpoch,
|
||||
"ago": dateAgo,
|
||||
"date": date,
|
||||
"date_in_zone": dateInZone,
|
||||
"date_modify": dateModify,
|
||||
"dateInZone": dateInZone,
|
||||
"dateModify": dateModify,
|
||||
"duration": duration,
|
||||
"durationRound": durationRound,
|
||||
"htmlDate": htmlDate,
|
||||
"htmlDateInZone": htmlDateInZone,
|
||||
"must_date_modify": mustDateModify,
|
||||
"mustDateModify": mustDateModify,
|
||||
"mustToDate": mustToDate,
|
||||
"now": time.Now,
|
||||
"toDate": toDate,
|
||||
"unixEpoch": unixEpoch,
|
||||
|
||||
// Strings
|
||||
"abbrev": abbrev,
|
||||
|
@ -158,6 +167,7 @@ var genericMap = map[string]interface{}{
|
|||
"int64": toInt64,
|
||||
"int": toInt,
|
||||
"float64": toFloat64,
|
||||
"seq": seq,
|
||||
"toDecimal": toDecimal,
|
||||
|
||||
//"gt": func(a, b int) bool {return a > b},
|
||||
|
@ -194,9 +204,28 @@ var genericMap = map[string]interface{}{
|
|||
}
|
||||
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,
|
||||
"max": max,
|
||||
"min": min,
|
||||
"maxf": maxf,
|
||||
"minf": minf,
|
||||
"ceil": ceil,
|
||||
"floor": floor,
|
||||
"round": round,
|
||||
|
@ -207,14 +236,24 @@ var genericMap = map[string]interface{}{
|
|||
"sortAlpha": sortAlpha,
|
||||
|
||||
// Defaults
|
||||
"default": dfault,
|
||||
"empty": empty,
|
||||
"coalesce": coalesce,
|
||||
"compact": compact,
|
||||
"deepCopy": deepCopy,
|
||||
"toJson": toJson,
|
||||
"toPrettyJson": toPrettyJson,
|
||||
"ternary": ternary,
|
||||
"default": dfault,
|
||||
"empty": empty,
|
||||
"coalesce": coalesce,
|
||||
"all": all,
|
||||
"any": any,
|
||||
"compact": compact,
|
||||
"mustCompact": mustCompact,
|
||||
"fromJson": fromJson,
|
||||
"toJson": toJson,
|
||||
"toPrettyJson": toPrettyJson,
|
||||
"toRawJson": toRawJson,
|
||||
"mustFromJson": mustFromJson,
|
||||
"mustToJson": mustToJson,
|
||||
"mustToPrettyJson": mustToPrettyJson,
|
||||
"mustToRawJson": mustToRawJson,
|
||||
"ternary": ternary,
|
||||
"deepCopy": deepCopy,
|
||||
"mustDeepCopy": mustDeepCopy,
|
||||
|
||||
// Reflection
|
||||
"typeOf": typeOf,
|
||||
|
@ -225,19 +264,26 @@ var genericMap = map[string]interface{}{
|
|||
"deepEqual": reflect.DeepEqual,
|
||||
|
||||
// OS:
|
||||
"env": func(s string) string { return os.Getenv(s) },
|
||||
"expandenv": func(s string) string { return os.ExpandEnv(s) },
|
||||
"env": os.Getenv,
|
||||
"expandenv": os.ExpandEnv,
|
||||
|
||||
// Network:
|
||||
"getHostByName": getHostByName,
|
||||
|
||||
// File Paths:
|
||||
// Paths:
|
||||
"base": path.Base,
|
||||
"dir": path.Dir,
|
||||
"clean": path.Clean,
|
||||
"ext": path.Ext,
|
||||
"isAbs": path.IsAbs,
|
||||
|
||||
// Filepaths:
|
||||
"osBase": filepath.Base,
|
||||
"osClean": filepath.Clean,
|
||||
"osDir": filepath.Dir,
|
||||
"osExt": filepath.Ext,
|
||||
"osIsAbs": filepath.IsAbs,
|
||||
|
||||
// Encoding:
|
||||
"b64enc": base64encode,
|
||||
"b64dec": base64decode,
|
||||
|
@ -245,42 +291,65 @@ var genericMap = map[string]interface{}{
|
|||
"b32dec": base32decode,
|
||||
|
||||
// Data Structures:
|
||||
"tuple": list, // FIXME: with the addition of append/prepend these are no longer immutable.
|
||||
"list": list,
|
||||
"dict": dict,
|
||||
"set": set,
|
||||
"unset": unset,
|
||||
"hasKey": hasKey,
|
||||
"pluck": pluck,
|
||||
"keys": keys,
|
||||
"pick": pick,
|
||||
"omit": omit,
|
||||
"merge": merge,
|
||||
"mergeOverwrite": mergeOverwrite,
|
||||
"values": values,
|
||||
"tuple": list, // FIXME: with the addition of append/prepend these are no longer immutable.
|
||||
"list": list,
|
||||
"dict": dict,
|
||||
"get": get,
|
||||
"set": set,
|
||||
"unset": unset,
|
||||
"hasKey": hasKey,
|
||||
"pluck": pluck,
|
||||
"keys": keys,
|
||||
"pick": pick,
|
||||
"omit": omit,
|
||||
"merge": merge,
|
||||
"mergeOverwrite": mergeOverwrite,
|
||||
"mustMerge": mustMerge,
|
||||
"mustMergeOverwrite": mustMergeOverwrite,
|
||||
"values": values,
|
||||
|
||||
"append": push, "push": push,
|
||||
"prepend": prepend,
|
||||
"first": first,
|
||||
"rest": rest,
|
||||
"last": last,
|
||||
"initial": initial,
|
||||
"reverse": reverse,
|
||||
"uniq": uniq,
|
||||
"without": without,
|
||||
"has": has,
|
||||
"slice": slice,
|
||||
"concat": concat,
|
||||
"mustAppend": mustPush, "mustPush": mustPush,
|
||||
"prepend": prepend,
|
||||
"mustPrepend": mustPrepend,
|
||||
"first": first,
|
||||
"mustFirst": mustFirst,
|
||||
"rest": rest,
|
||||
"mustRest": mustRest,
|
||||
"last": last,
|
||||
"mustLast": mustLast,
|
||||
"initial": initial,
|
||||
"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:
|
||||
"bcrypt": bcrypt,
|
||||
"htpasswd": htpasswd,
|
||||
"genPrivateKey": generatePrivateKey,
|
||||
"derivePassword": derivePassword,
|
||||
"buildCustomCert": buildCustomCertificate,
|
||||
"genCA": generateCertificateAuthority,
|
||||
"genCAWithKey": generateCertificateAuthorityWithPEMKey,
|
||||
"genSelfSignedCert": generateSelfSignedCertificate,
|
||||
"genSelfSignedCertWithKey": generateSelfSignedCertificateWithPEMKey,
|
||||
"genSignedCert": generateSignedCertificate,
|
||||
"genSignedCertWithKey": generateSignedCertificateWithPEMKey,
|
||||
"encryptAES": encryptAES,
|
||||
"decryptAES": decryptAES,
|
||||
"randBytes": randBytes,
|
||||
|
||||
// UUIDs:
|
||||
"uuidv4": uuidv4,
|
||||
|
@ -293,12 +362,19 @@ var genericMap = map[string]interface{}{
|
|||
"fail": func(msg string) (string, error) { return "", errors.New(msg) },
|
||||
|
||||
// Regex
|
||||
"regexMatch": regexMatch,
|
||||
"regexFindAll": regexFindAll,
|
||||
"regexFind": regexFind,
|
||||
"regexReplaceAll": regexReplaceAll,
|
||||
"regexReplaceAllLiteral": regexReplaceAllLiteral,
|
||||
"regexSplit": regexSplit,
|
||||
"regexMatch": regexMatch,
|
||||
"mustRegexMatch": mustRegexMatch,
|
||||
"regexFindAll": regexFindAll,
|
||||
"mustRegexFindAll": mustRegexFindAll,
|
||||
"regexFind": regexFind,
|
||||
"mustRegexFind": mustRegexFind,
|
||||
"regexReplaceAll": regexReplaceAll,
|
||||
"mustRegexReplaceAll": mustRegexReplaceAll,
|
||||
"regexReplaceAllLiteral": regexReplaceAllLiteral,
|
||||
"mustRegexReplaceAllLiteral": mustRegexReplaceAllLiteral,
|
||||
"regexSplit": regexSplit,
|
||||
"mustRegexSplit": mustRegexSplit,
|
||||
"regexQuoteMeta": regexQuoteMeta,
|
||||
|
||||
// URLs:
|
||||
"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 (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
@ -15,6 +16,15 @@ func list(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()
|
||||
switch tp {
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
@ -26,14 +36,23 @@ func push(list interface{}, v interface{}) []interface{} {
|
|||
nl[i] = l2.Index(i).Interface()
|
||||
}
|
||||
|
||||
return append(nl, v)
|
||||
return append(nl, v), nil
|
||||
|
||||
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{} {
|
||||
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...)
|
||||
|
||||
tp := reflect.TypeOf(list).Kind()
|
||||
|
@ -47,14 +66,67 @@ func prepend(list interface{}, v interface{}) []interface{} {
|
|||
nl[i] = l2.Index(i).Interface()
|
||||
}
|
||||
|
||||
return append([]interface{}{v}, nl...)
|
||||
return append([]interface{}{v}, nl...), nil
|
||||
|
||||
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{} {
|
||||
l, err := mustLast(list)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func mustLast(list interface{}) (interface{}, error) {
|
||||
tp := reflect.TypeOf(list).Kind()
|
||||
switch tp {
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
@ -62,16 +134,25 @@ func last(list interface{}) interface{} {
|
|||
|
||||
l := l2.Len()
|
||||
if l == 0 {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return l2.Index(l - 1).Interface()
|
||||
return l2.Index(l - 1).Interface(), nil
|
||||
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{} {
|
||||
l, err := mustFirst(list)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func mustFirst(list interface{}) (interface{}, error) {
|
||||
tp := reflect.TypeOf(list).Kind()
|
||||
switch tp {
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
@ -79,16 +160,25 @@ func first(list interface{}) interface{} {
|
|||
|
||||
l := l2.Len()
|
||||
if l == 0 {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return l2.Index(0).Interface()
|
||||
return l2.Index(0).Interface(), nil
|
||||
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{} {
|
||||
l, err := mustRest(list)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func mustRest(list interface{}) ([]interface{}, error) {
|
||||
tp := reflect.TypeOf(list).Kind()
|
||||
switch tp {
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
@ -96,7 +186,7 @@ func rest(list interface{}) []interface{} {
|
|||
|
||||
l := l2.Len()
|
||||
if l == 0 {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
nl := make([]interface{}, l-1)
|
||||
|
@ -104,13 +194,22 @@ func rest(list interface{}) []interface{} {
|
|||
nl[i-1] = l2.Index(i).Interface()
|
||||
}
|
||||
|
||||
return nl
|
||||
return nl, nil
|
||||
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{} {
|
||||
l, err := mustInitial(list)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func mustInitial(list interface{}) ([]interface{}, error) {
|
||||
tp := reflect.TypeOf(list).Kind()
|
||||
switch tp {
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
@ -118,7 +217,7 @@ func initial(list interface{}) []interface{} {
|
|||
|
||||
l := l2.Len()
|
||||
if l == 0 {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
nl := make([]interface{}, l-1)
|
||||
|
@ -126,9 +225,9 @@ func initial(list interface{}) []interface{} {
|
|||
nl[i] = l2.Index(i).Interface()
|
||||
}
|
||||
|
||||
return nl
|
||||
return nl, nil
|
||||
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{} {
|
||||
l, err := mustReverse(v)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func mustReverse(v interface{}) ([]interface{}, error) {
|
||||
tp := reflect.TypeOf(v).Kind()
|
||||
switch tp {
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
@ -157,13 +265,22 @@ func reverse(v interface{}) []interface{} {
|
|||
nl[l-i-1] = l2.Index(i).Interface()
|
||||
}
|
||||
|
||||
return nl
|
||||
return nl, nil
|
||||
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{} {
|
||||
l, err := mustCompact(list)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func mustCompact(list interface{}) ([]interface{}, error) {
|
||||
tp := reflect.TypeOf(list).Kind()
|
||||
switch tp {
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
@ -179,13 +296,22 @@ func compact(list interface{}) []interface{} {
|
|||
}
|
||||
}
|
||||
|
||||
return nl
|
||||
return nl, nil
|
||||
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{} {
|
||||
l, err := mustUniq(list)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func mustUniq(list interface{}) ([]interface{}, error) {
|
||||
tp := reflect.TypeOf(list).Kind()
|
||||
switch tp {
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
@ -201,9 +327,9 @@ func uniq(list interface{}) []interface{} {
|
|||
}
|
||||
}
|
||||
|
||||
return dest
|
||||
return dest, nil
|
||||
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{} {
|
||||
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()
|
||||
switch tp {
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
@ -232,15 +367,24 @@ func without(list interface{}, omit ...interface{}) []interface{} {
|
|||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return res, nil
|
||||
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 {
|
||||
l, err := mustHas(needle, haystack)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func mustHas(needle interface{}, haystack interface{}) (bool, error) {
|
||||
if haystack == nil {
|
||||
return false
|
||||
return false, nil
|
||||
}
|
||||
tp := reflect.TypeOf(haystack).Kind()
|
||||
switch tp {
|
||||
|
@ -251,13 +395,13 @@ func has(needle interface{}, haystack interface{}) bool {
|
|||
for i := 0; i < l; i++ {
|
||||
item = l2.Index(i).Interface()
|
||||
if reflect.DeepEqual(needle, item) {
|
||||
return true
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return false, nil
|
||||
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 -> list[3:5] = list[3:]
|
||||
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()
|
||||
switch tp {
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
@ -274,7 +427,7 @@ func slice(list interface{}, indices ...interface{}) interface{} {
|
|||
|
||||
l := l2.Len()
|
||||
if l == 0 {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var start, end int
|
||||
|
@ -287,9 +440,9 @@ func slice(list interface{}, indices ...interface{}) interface{} {
|
|||
end = toInt(indices[1])
|
||||
}
|
||||
|
||||
return l2.Slice(start, end).Interface()
|
||||
return l2.Slice(start, end).Interface(), nil
|
||||
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 {
|
||||
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))]
|
||||
}
|
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
|
||||
|
||||
import (
|
||||
sv2 "github.com/Masterminds/semver"
|
||||
sv2 "github.com/Masterminds/semver/v3"
|
||||
)
|
||||
|
||||
func semverCompare(constraint, version string) (bool, error) {
|
|
@ -154,9 +154,9 @@ func strslice(v interface{}) []string {
|
|||
default:
|
||||
if v == nil {
|
||||
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 {
|
||||
if len(s) <= c {
|
||||
return s
|
||||
if c < 0 && len(s)+c > 0 {
|
||||
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 {
|
|
@ -7,7 +7,8 @@ import (
|
|||
)
|
||||
|
||||
func dictGetOrEmpty(dict map[string]interface{}, key string) string {
|
||||
value, ok := dict[key]; if !ok {
|
||||
value, ok := dict[key]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
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
|
||||
func urlParse(v string) map[string]interface{} {
|
||||
dict := map[string]interface{}{}
|
||||
parsedUrl, err := url.Parse(v)
|
||||
parsedURL, err := url.Parse(v)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("unable to parse url: %s", err))
|
||||
}
|
||||
dict["scheme"] = parsedUrl.Scheme
|
||||
dict["host"] = parsedUrl.Host
|
||||
dict["hostname"] = parsedUrl.Hostname()
|
||||
dict["path"] = parsedUrl.Path
|
||||
dict["query"] = parsedUrl.RawQuery
|
||||
dict["opaque"] = parsedUrl.Opaque
|
||||
dict["fragment"] = parsedUrl.Fragment
|
||||
if parsedUrl.User != nil {
|
||||
dict["userinfo"] = parsedUrl.User.String()
|
||||
dict["scheme"] = parsedURL.Scheme
|
||||
dict["host"] = parsedURL.Host
|
||||
dict["hostname"] = parsedURL.Hostname()
|
||||
dict["path"] = parsedURL.Path
|
||||
dict["query"] = parsedURL.RawQuery
|
||||
dict["opaque"] = parsedURL.Opaque
|
||||
dict["fragment"] = parsedURL.Fragment
|
||||
if parsedURL.User != nil {
|
||||
dict["userinfo"] = parsedURL.User.String()
|
||||
} else {
|
||||
dict["userinfo"] = ""
|
||||
}
|
||||
|
@ -42,25 +43,24 @@ func urlParse(v string) map[string]interface{} {
|
|||
|
||||
// join given dict to URL string
|
||||
func urlJoin(d map[string]interface{}) string {
|
||||
resUrl := url.URL{
|
||||
resURL := url.URL{
|
||||
Scheme: dictGetOrEmpty(d, "scheme"),
|
||||
Host: dictGetOrEmpty(d, "host"),
|
||||
Path: dictGetOrEmpty(d, "path"),
|
||||
RawQuery: dictGetOrEmpty(d, "query"),
|
||||
Opaque: dictGetOrEmpty(d, "opaque"),
|
||||
Fragment: dictGetOrEmpty(d, "fragment"),
|
||||
|
||||
}
|
||||
userinfo := dictGetOrEmpty(d, "userinfo")
|
||||
var user *url.Userinfo = nil
|
||||
var user *url.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 {
|
||||
panic(fmt.Sprintf("unable to parse userinfo in dict: %s", err))
|
||||
}
|
||||
user = tempUrl.User
|
||||
user = tempURL.User
|
||||
}
|
||||
|
||||
resUrl.User = user
|
||||
return resUrl.String()
|
||||
resURL.User = user
|
||||
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.
|
||||
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
|
||||
h.Reset()
|
||||
h.Write(space[:])
|
||||
h.Write(data)
|
||||
h.Write(space[:]) //nolint:errcheck
|
||||
h.Write(data) //nolint:errcheck
|
||||
s := h.Sum(nil)
|
||||
var uuid UUID
|
||||
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"
|
||||
)
|
||||
|
||||
// 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
|
||||
// consult database-specific driver documentation for matching types.
|
||||
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"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 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.
|
||||
)
|
||||
|
||||
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
|
||||
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
||||
|
@ -68,7 +89,7 @@ func Parse(s string) (UUID, error) {
|
|||
}
|
||||
return uuid, nil
|
||||
default:
|
||||
return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
|
||||
return uuid, invalidLengthError{len(s)}
|
||||
}
|
||||
// s is now at least 36 bytes long
|
||||
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
|
@ -112,7 +133,7 @@ func ParseBytes(b []byte) (UUID, error) {
|
|||
}
|
||||
return uuid, nil
|
||||
default:
|
||||
return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
|
||||
return uuid, invalidLengthError{len(b)}
|
||||
}
|
||||
// s is now at least 36 bytes long
|
||||
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
|
@ -243,3 +264,31 @@ func SetRand(r io.Reader) {
|
|||
}
|
||||
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())
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// The strength of the UUIDs is based on the strength of the crypto/rand
|
||||
// package.
|
||||
//
|
||||
// Uses the randomness pool if it was enabled with EnableRandPool.
|
||||
//
|
||||
// A note about uniqueness derived from the UUID Wikipedia entry:
|
||||
//
|
||||
// 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
|
||||
// year and having one duplicate.
|
||||
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.
|
||||
|
@ -41,3 +54,23 @@ func NewRandomFromReader(r io.Reader) (UUID, error) {
|
|||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
|
||||
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
|
||||
// be replaced with the original error message.
|
||||
//
|
||||
// Deprecated: Use fmt.Errorf()
|
||||
func Wrapf(format string, err error) error {
|
||||
outerMsg := "<nil>"
|
||||
if err != nil {
|
||||
|
@ -148,6 +150,9 @@ func Walk(err error, cb WalkFunc) {
|
|||
for _, err := range e.WrappedErrors() {
|
||||
Walk(err, cb)
|
||||
}
|
||||
case interface{ Unwrap() error }:
|
||||
cb(err)
|
||||
Walk(e.Unwrap(), cb)
|
||||
default:
|
||||
cb(err)
|
||||
}
|
||||
|
@ -167,3 +172,7 @@ func (w *wrappedError) Error() string {
|
|||
func (w *wrappedError) WrappedErrors() []error {
|
||||
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 (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-docs/internal/provider"
|
||||
)
|
||||
|
@ -10,8 +11,17 @@ import (
|
|||
type generateCmd struct {
|
||||
commonCmd
|
||||
|
||||
flagLegacySidebar bool
|
||||
tfVersion string
|
||||
flagLegacySidebar bool
|
||||
flagIgnoreDeprecated bool
|
||||
|
||||
flagProviderName string
|
||||
flagRenderedProviderName string
|
||||
|
||||
flagRenderedWebsiteDir string
|
||||
flagExamplesDir string
|
||||
flagWebsiteTmpDir string
|
||||
flagWebsiteSourceDir string
|
||||
tfVersion string
|
||||
}
|
||||
|
||||
func (cmd *generateCmd) Synopsis() string {
|
||||
|
@ -19,13 +29,54 @@ func (cmd *generateCmd) Synopsis() 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 {
|
||||
fs := flag.NewFlagSet("generate", flag.ExitOnError)
|
||||
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.BoolVar(&cmd.flagIgnoreDeprecated, "ignore-deprecated", false, "don't generate documentation for deprecated resources and data-sources")
|
||||
return fs
|
||||
}
|
||||
|
||||
|
@ -41,7 +92,18 @@ func (cmd *generateCmd) Run(args []string) int {
|
|||
}
|
||||
|
||||
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 {
|
||||
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 (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-docs/internal/provider"
|
||||
)
|
||||
|
@ -16,7 +17,41 @@ func (cmd *validateCmd) Synopsis() 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 {
|
||||
|
|
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"
|
||||
)
|
||||
|
||||
// TODO: convert these to flags?
|
||||
var (
|
||||
providerName string
|
||||
|
||||
// rendered website dir
|
||||
renderedWebsiteDir = "docs"
|
||||
|
||||
// examples directory defaults
|
||||
examplesDir = "examples"
|
||||
// relative to examples dir
|
||||
examplesResourceFileTemplate = resourceFileTemplate("resources/{{.Name}}/resource.tf")
|
||||
examplesResourceImportTemplate = resourceFileTemplate("resources/{{.Name}}/import.sh")
|
||||
examplesDataSourceFileTemplate = resourceFileTemplate("data-sources/{{ .Name }}/data-source.tf")
|
||||
examplesProviderFileTemplate = providerFileTemplate("provider/provider.tf")
|
||||
|
||||
// templated website directory defaults
|
||||
websiteTmp = ""
|
||||
|
||||
websiteSourceDir = "templates" // used for override content
|
||||
websiteResourceFileTemplate = resourceFileTemplate("resources/{{ .ShortName }}.md.tmpl")
|
||||
websiteResourceFallbackFileTemplate = resourceFileTemplate("resources.md.tmpl")
|
||||
websiteResourceFileStatic = []resourceFileTemplate{
|
||||
|
@ -77,8 +64,16 @@ var (
|
|||
)
|
||||
|
||||
type generator struct {
|
||||
legacySidebar bool
|
||||
tfVersion string
|
||||
ignoreDeprecated bool
|
||||
legacySidebar bool
|
||||
tfVersion string
|
||||
|
||||
providerName string
|
||||
renderedProviderName string
|
||||
renderedWebsiteDir string
|
||||
examplesDir string
|
||||
websiteTmpDir string
|
||||
websiteSourceDir string
|
||||
|
||||
ui cli.Ui
|
||||
}
|
||||
|
@ -91,10 +86,18 @@ func (g *generator) warnf(format string, a ...interface{}) {
|
|||
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{
|
||||
legacySidebar: legacySidebar,
|
||||
tfVersion: tfVersion,
|
||||
ignoreDeprecated: ignoreDeprecated,
|
||||
legacySidebar: legacySidebar,
|
||||
tfVersion: tfVersion,
|
||||
|
||||
providerName: providerName,
|
||||
renderedProviderName: renderedProviderName,
|
||||
renderedWebsiteDir: renderedWebsiteDir,
|
||||
examplesDir: examplesDir,
|
||||
websiteTmpDir: websiteTmpDir,
|
||||
websiteSourceDir: websiteSourceDir,
|
||||
|
||||
ui: ui,
|
||||
}
|
||||
|
@ -112,34 +115,39 @@ func (g *generator) Generate(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if providerName == "" {
|
||||
providerName := g.providerName
|
||||
if g.providerName == "" {
|
||||
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 {
|
||||
case websiteTmp == "":
|
||||
websiteTmp, err = ioutil.TempDir("", "tfws")
|
||||
case g.websiteTmpDir == "":
|
||||
g.websiteTmpDir, err = ioutil.TempDir("", "tfws")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(websiteTmp)
|
||||
defer os.RemoveAll(g.websiteTmpDir)
|
||||
default:
|
||||
g.infof("cleaning tmp dir %q", websiteTmp)
|
||||
err = os.RemoveAll(websiteTmp)
|
||||
g.infof("cleaning tmp dir %q", g.websiteTmpDir)
|
||||
err = os.RemoveAll(g.websiteTmpDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g.infof("creating tmp dir %q", websiteTmp)
|
||||
err = os.MkdirAll(websiteTmp, 0755)
|
||||
g.infof("creating tmp dir %q", g.websiteTmpDir)
|
||||
err = os.MkdirAll(g.websiteTmpDir, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
websiteSourceDirInfo, err := os.Stat(websiteSourceDir)
|
||||
websiteSourceDirInfo, err := os.Stat(g.websiteSourceDir)
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
// do nothing, no template dir
|
||||
|
@ -147,11 +155,11 @@ func (g *generator) Generate(ctx context.Context) error {
|
|||
return err
|
||||
default:
|
||||
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")
|
||||
err = cp(websiteSourceDir, filepath.Join(websiteTmp, "templates"))
|
||||
err = cp(g.websiteSourceDir, filepath.Join(g.websiteTmpDir, "templates"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -189,7 +197,7 @@ func (g *generator) renderMissingResourceDoc(providerName, name, typeName string
|
|||
if err != nil {
|
||||
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) {
|
||||
g.infof("resource %q template exists, skipping", name)
|
||||
return nil
|
||||
|
@ -200,7 +208,7 @@ func (g *generator) renderMissingResourceDoc(providerName, name, typeName string
|
|||
if err != nil {
|
||||
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) {
|
||||
g.infof("resource %q static file exists, skipping", name)
|
||||
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)
|
||||
}
|
||||
if examplePath != "" {
|
||||
examplePath = filepath.Join(examplesDir, examplePath)
|
||||
examplePath = filepath.Join(g.examplesDir, examplePath)
|
||||
}
|
||||
if !fileExists(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)
|
||||
}
|
||||
if importPath != "" {
|
||||
importPath = filepath.Join(examplesDir, importPath)
|
||||
importPath = filepath.Join(g.examplesDir, importPath)
|
||||
}
|
||||
if !fileExists(importPath) {
|
||||
importPath = ""
|
||||
|
@ -238,7 +246,7 @@ func (g *generator) renderMissingResourceDoc(providerName, name, typeName string
|
|||
if err != nil {
|
||||
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) {
|
||||
g.infof("resource %q fallback template exists", name)
|
||||
tmplData, err := ioutil.ReadFile(fallbackTmplPath)
|
||||
|
@ -249,7 +257,7 @@ func (g *generator) renderMissingResourceDoc(providerName, name, typeName string
|
|||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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) {
|
||||
g.infof("provider %q template exists, skipping", providerName)
|
||||
return nil
|
||||
|
@ -278,7 +286,7 @@ func (g *generator) renderMissingProviderDoc(providerName string, schema *tfjson
|
|||
if err != nil {
|
||||
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) {
|
||||
g.infof("provider %q static file exists, skipping", providerName)
|
||||
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)
|
||||
}
|
||||
if examplePath != "" {
|
||||
examplePath = filepath.Join(examplesDir, examplePath)
|
||||
examplePath = filepath.Join(g.examplesDir, examplePath)
|
||||
}
|
||||
if !fileExists(examplePath) {
|
||||
examplePath = ""
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
g.infof("generating missing resource content")
|
||||
for name, schema := range providerSchema.ResourceSchemas {
|
||||
if g.ignoreDeprecated && schema.Block.Deprecated {
|
||||
continue
|
||||
}
|
||||
|
||||
err := g.renderMissingResourceDoc(providerName, name, "Resource", schema,
|
||||
websiteResourceFileTemplate,
|
||||
websiteResourceFallbackFileTemplate,
|
||||
|
@ -326,6 +338,10 @@ func (g *generator) renderMissingDocs(providerName string, providerSchema *tfjso
|
|||
|
||||
g.infof("generating missing data source content")
|
||||
for name, schema := range providerSchema.DataSourceSchemas {
|
||||
if g.ignoreDeprecated && schema.Block.Deprecated {
|
||||
continue
|
||||
}
|
||||
|
||||
err := g.renderMissingResourceDoc(providerName, name, "Data Source", schema,
|
||||
websiteDataSourceFileTemplate,
|
||||
websiteDataSourceFallbackFileTemplate,
|
||||
|
@ -352,7 +368,7 @@ func (g *generator) renderMissingDocs(providerName string, providerSchema *tfjso
|
|||
|
||||
func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfjson.ProviderSchema) error {
|
||||
g.infof("cleaning rendered website dir")
|
||||
err := os.RemoveAll(renderedWebsiteDir)
|
||||
err := os.RemoveAll(g.renderedWebsiteDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -361,13 +377,13 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj
|
|||
|
||||
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() {
|
||||
// skip directories
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
@ -380,7 +396,7 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj
|
|||
return nil
|
||||
}
|
||||
|
||||
renderedPath := filepath.Join(renderedWebsiteDir, rel)
|
||||
renderedPath := filepath.Join(g.renderedWebsiteDir, rel)
|
||||
err = os.MkdirAll(filepath.Dir(renderedPath), 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -408,11 +424,11 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj
|
|||
g.infof("rendering %q", rel)
|
||||
switch relDir {
|
||||
case "data-sources/":
|
||||
resName := shortName + "_" + removeAllExt(relFile)
|
||||
resSchema, ok := providerSchema.DataSourceSchemas[resName]
|
||||
if ok {
|
||||
resSchema, resName := resourceSchema(providerSchema.DataSourceSchemas, shortName, relFile)
|
||||
exampleFilePath := filepath.Join(g.examplesDir, "data-sources", resName, "data-source.tf")
|
||||
if resSchema != nil {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
g.warnf("data source entitled %q, or %q does not exist", shortName, resName)
|
||||
case "resources/":
|
||||
resName := shortName + "_" + removeAllExt(relFile)
|
||||
resSchema, ok := providerSchema.ResourceSchemas[resName]
|
||||
if ok {
|
||||
resSchema, resName := resourceSchema(providerSchema.ResourceSchemas, shortName, relFile)
|
||||
exampleFilePath := filepath.Join(g.examplesDir, "resources", resName, "resource.tf")
|
||||
importFilePath := filepath.Join(g.examplesDir, "resources", resName, "import.sh")
|
||||
|
||||
if resSchema != nil {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
g.warnf("resource entitled %q, or %q does not exist", shortName, resName)
|
||||
case "": // provider
|
||||
if relFile == "index.md.tmpl" {
|
||||
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 {
|
||||
return fmt.Errorf("unable to render provider template %q: %w", rel, err)
|
||||
}
|
||||
|
@ -505,7 +526,7 @@ provider %[1]q {
|
|||
}
|
||||
|
||||
i := install.NewInstaller()
|
||||
sources := []src.Source{}
|
||||
var sources []src.Source
|
||||
if g.tfVersion != "" {
|
||||
g.infof("downloading Terraform CLI binary version from releases.hashicorp.com: %s", g.tfVersion)
|
||||
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"
|
||||
"text/template"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
tfjson "github.com/hashicorp/terraform-json"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-docs/internal/mdplain"
|
||||
"github.com/hashicorp/terraform-plugin-docs/internal/tmplfuncs"
|
||||
"github.com/hashicorp/terraform-plugin-docs/schemamd"
|
||||
|
@ -30,17 +34,19 @@ type (
|
|||
|
||||
func newTemplate(name, text string) (*template.Template, error) {
|
||||
tmpl := template.New(name)
|
||||
titleCaser := cases.Title(language.Und)
|
||||
|
||||
tmpl.Funcs(template.FuncMap(map[string]interface{}{
|
||||
tmpl.Funcs(map[string]interface{}{
|
||||
"codefile": tmplfuncs.CodeFile,
|
||||
"lower": strings.ToLower,
|
||||
"plainmarkdown": mdplain.PlainMarkdown,
|
||||
"prefixlines": tmplfuncs.PrefixLines,
|
||||
"tffile": func(file string) (string, error) {
|
||||
// TODO: omit comment handling
|
||||
return tmplfuncs.CodeFile("terraform", file)
|
||||
},
|
||||
"trimspace": strings.TrimSpace,
|
||||
}))
|
||||
"split": strings.Split,
|
||||
"tffile": terraformCodeFile,
|
||||
"title": titleCaser.String,
|
||||
"trimspace": strings.TrimSpace,
|
||||
"upper": strings.ToUpper,
|
||||
})
|
||||
|
||||
var err error
|
||||
tmpl, err = tmpl.Parse(text)
|
||||
|
@ -51,6 +57,11 @@ func newTemplate(name, text string) (*template.Template, error) {
|
|||
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 {
|
||||
tmpl, err := newTemplate(name, text)
|
||||
if err != nil {
|
||||
|
@ -116,7 +127,7 @@ func (t providerFileTemplate) Render(name string) (string, error) {
|
|||
}{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)
|
||||
err := schemamd.Render(schema, schemaBuffer)
|
||||
if err != nil {
|
||||
|
@ -128,34 +139,33 @@ func (t providerTemplate) Render(providerName, exampleFile string, schema *tfjso
|
|||
return "", nil
|
||||
}
|
||||
return renderStringTemplate("providerTemplate", s, struct {
|
||||
Type string
|
||||
Name string
|
||||
Description string
|
||||
|
||||
HasExample bool
|
||||
ExampleFile string
|
||||
|
||||
HasImport bool
|
||||
ImportFile string
|
||||
|
||||
ProviderName string
|
||||
ProviderShortName string
|
||||
|
||||
SchemaMarkdown string
|
||||
|
||||
RenderedProviderName string
|
||||
}{
|
||||
Description: schema.Block.Description,
|
||||
|
||||
HasExample: exampleFile != "",
|
||||
HasExample: exampleFile != "" && fileExists(exampleFile),
|
||||
ExampleFile: exampleFile,
|
||||
|
||||
ProviderName: providerName,
|
||||
ProviderShortName: providerShortName(providerName),
|
||||
|
||||
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)
|
||||
err := schemamd.Render(schema, schemaBuffer)
|
||||
if err != nil {
|
||||
|
@ -182,21 +192,25 @@ func (t resourceTemplate) Render(name, providerName, typeName, exampleFile, impo
|
|||
ProviderShortName string
|
||||
|
||||
SchemaMarkdown string
|
||||
|
||||
RenderedProviderName string
|
||||
}{
|
||||
Type: typeName,
|
||||
Name: name,
|
||||
Description: schema.Block.Description,
|
||||
|
||||
HasExample: exampleFile != "",
|
||||
HasExample: exampleFile != "" && fileExists(exampleFile),
|
||||
ExampleFile: exampleFile,
|
||||
|
||||
HasImport: importFile != "",
|
||||
HasImport: importFile != "" && fileExists(importFile),
|
||||
ImportFile: importFile,
|
||||
|
||||
ProviderName: providerName,
|
||||
ProviderShortName: providerShortName(providerName),
|
||||
|
||||
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"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
tfjson "github.com/hashicorp/terraform-json"
|
||||
)
|
||||
|
||||
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 {
|
||||
dir, _ := filepath.Split(path)
|
||||
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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if block.MinItems > 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(block.Block.NestedBlocks) == 0 && len(block.Block.Attributes) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, childBlock := range block.Block.NestedBlocks {
|
||||
if childBlockIsRequired(childBlock) {
|
||||
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
|
||||
}
|
||||
|
||||
if name == "id" && att.Description == "" {
|
||||
att.Description = "The ID of this resource."
|
||||
}
|
||||
|
||||
if att.AttributeNestedType == nil {
|
||||
err = WriteAttributeDescription(w, att, false)
|
||||
} else {
|
||||
|
@ -225,7 +221,18 @@ nameLoop:
|
|||
}
|
||||
} else if childAtt, ok := block.Attributes[n]; ok {
|
||||
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)
|
||||
continue nameLoop
|
||||
}
|
||||
|
@ -286,7 +293,9 @@ nameLoop:
|
|||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
_, err := io.WriteString(w, group.nestedTitle+"\n\n")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sortedNames := []string{}
|
||||
for n := range nestedAttributes.Attributes {
|
||||
sortedNames = append(sortedNames, n)
|
||||
}
|
||||
sort.Strings(sortedNames)
|
||||
nestedTypes := []nestedType{}
|
||||
|
||||
groups := map[int][]string{}
|
||||
for _, name := range sortedNames {
|
||||
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)
|
||||
for i, gf := range groupFilters {
|
||||
if gf.filterAttribute(att) {
|
||||
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")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = writeNestedTypes(w, nestedTypes)
|
||||
err := writeNestedTypes(w, nestedTypes)
|
||||
if err != nil {
|
||||
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]
|
||||
[![Sourcegraph][11]][12]
|
||||
[![FOSSA Status][13]][14]
|
||||
|
||||
[![GoCenter Kudos][15]][16]
|
||||
[![Become my sponsor][15]][16]
|
||||
|
||||
[1]: https://travis-ci.org/imdario/mergo.png
|
||||
[2]: https://travis-ci.org/imdario/mergo
|
||||
|
@ -25,8 +24,8 @@
|
|||
[12]: https://sourcegraph.com/github.com/imdario/mergo?badge
|
||||
[13]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=shield
|
||||
[14]: https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_shield
|
||||
[15]: https://search.gocenter.io/api/ui/badge/github.com%2Fimdario%2Fmergo
|
||||
[16]: https://search.gocenter.io/github.com/imdario/mergo
|
||||
[15]: https://img.shields.io/github/sponsors/imdario
|
||||
[16]: https://github.com/sponsors/imdario
|
||||
|
||||
A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements.
|
||||
|
||||
|
@ -36,11 +35,11 @@ Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the
|
|||
|
||||
## Status
|
||||
|
||||
It is ready for production use. [It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, etc](https://github.com/imdario/mergo#mergo-in-the-wild).
|
||||
It is ready for production use. [It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, Microsoft, etc](https://github.com/imdario/mergo#mergo-in-the-wild).
|
||||
|
||||
### Important note
|
||||
|
||||
Please keep in mind that a problematic PR broke [0.3.9](//github.com/imdario/mergo/releases/tag/0.3.9). I reverted it in [0.3.10](//github.com/imdario/mergo/releases/tag/0.3.10), and I consider it stable but not bug-free. Also, this version adds suppot for go modules.
|
||||
Please keep in mind that a problematic PR broke [0.3.9](//github.com/imdario/mergo/releases/tag/0.3.9). I reverted it in [0.3.10](//github.com/imdario/mergo/releases/tag/0.3.10), and I consider it stable but not bug-free. Also, this version adds support for go modules.
|
||||
|
||||
Keep in mind that in [0.3.2](//github.com/imdario/mergo/releases/tag/0.3.2), Mergo changed `Merge()`and `Map()` signatures to support [transformers](#transformers). I added an optional/variadic argument so that it won't break the existing code.
|
||||
|
||||
|
@ -51,12 +50,12 @@ If you were using Mergo before April 6th, 2015, please check your project works
|
|||
If Mergo is useful to you, consider buying me a coffee, a beer, or making a monthly donation to allow me to keep building great free software. :heart_eyes:
|
||||
|
||||
<a href='https://ko-fi.com/B0B58839' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=0' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
||||
[![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://github.com/sponsors/imdario' target='_blank'><img alt="Become my sponsor" src="https://img.shields.io/github/sponsors/imdario?style=for-the-badge" /></a>
|
||||
|
||||
### Mergo in the wild
|
||||
|
||||
- [cli/cli](https://github.com/cli/cli)
|
||||
- [moby/moby](https://github.com/moby/moby)
|
||||
- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
|
||||
- [vmware/dispatch](https://github.com/vmware/dispatch)
|
||||
|
@ -98,6 +97,8 @@ If Mergo is useful to you, consider buying me a coffee, a beer, or making a mont
|
|||
- [jnuthong/item_search](https://github.com/jnuthong/item_search)
|
||||
- [bukalapak/snowboard](https://github.com/bukalapak/snowboard)
|
||||
- [containerssh/containerssh](https://github.com/containerssh/containerssh)
|
||||
- [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
|
||||
- [tjpnz/structbot](https://github.com/tjpnz/structbot)
|
||||
|
||||
## Install
|
||||
|
||||
|
@ -168,7 +169,7 @@ func main() {
|
|||
|
||||
Note: if test are failing due missing package, please execute:
|
||||
|
||||
go get gopkg.in/yaml.v2
|
||||
go get gopkg.in/yaml.v3
|
||||
|
||||
### Transformers
|
||||
|
||||
|
@ -218,7 +219,6 @@ func main() {
|
|||
}
|
||||
```
|
||||
|
||||
|
||||
## Contact me
|
||||
|
||||
If I can help you, you have an idea or you are using Mergo in your projects, don't hesitate to drop me a line (or a pull request): [@im_dario](https://twitter.com/im_dario)
|
||||
|
@ -227,18 +227,6 @@ If I can help you, you have an idea or you are using Mergo in your projects, don
|
|||
|
||||
Written by [Dario Castañé](http://dario.im).
|
||||
|
||||
## Top Contributors
|
||||
|
||||
[![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
|
||||
|
||||
[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE).
|
||||
|
|
2
vendor/github.com/imdario/mergo/merge.go
generated
vendored
2
vendor/github.com/imdario/mergo/merge.go
generated
vendored
|
@ -79,7 +79,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
|||
visited[h] = &visit{addr, typ, seen}
|
||||
}
|
||||
|
||||
if config.Transformers != nil && !isEmptyValue(dst) {
|
||||
if config.Transformers != nil && !isReflectNil(dst) && dst.IsValid() {
|
||||
if fn := config.Transformers.Transformer(dst.Type()); fn != nil {
|
||||
err = fn(dst, src)
|
||||
return
|
||||
|
|
4
vendor/github.com/imdario/mergo/mergo.go
generated
vendored
4
vendor/github.com/imdario/mergo/mergo.go
generated
vendored
|
@ -17,7 +17,7 @@ import (
|
|||
var (
|
||||
ErrNilArguments = errors.New("src and dst must not be nil")
|
||||
ErrDifferentArgumentsTypes = errors.New("src and dst must be of same type")
|
||||
ErrNotSupported = errors.New("only structs and maps are supported")
|
||||
ErrNotSupported = errors.New("only structs, maps, and slices are supported")
|
||||
ErrExpectedMapAsDestination = errors.New("dst was expected to be a map")
|
||||
ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct")
|
||||
ErrNonPointerAgument = errors.New("dst must be a pointer")
|
||||
|
@ -65,7 +65,7 @@ func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err error) {
|
|||
return
|
||||
}
|
||||
vDst = reflect.ValueOf(dst).Elem()
|
||||
if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map {
|
||||
if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map && vDst.Kind() != reflect.Slice {
|
||||
err = ErrNotSupported
|
||||
return
|
||||
}
|
||||
|
|
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
|
||||
[Packer](https://github.com/mitchellh/packer),
|
||||
[Serf](https://github.com/hashicorp/serf),
|
||||
[Consul](https://github.com/hashicorp/consul),
|
||||
[Vault](https://github.com/hashicorp/vault),
|
||||
[Terraform](https://github.com/hashicorp/terraform), and
|
||||
[Nomad](https://github.com/hashicorp/nomad).
|
||||
[Terraform](https://github.com/hashicorp/terraform),
|
||||
[Nomad](https://github.com/hashicorp/nomad), and more.
|
||||
|
||||
## Features
|
||||
|
||||
|
@ -21,7 +20,7 @@ cli is the library that powers the CLI for
|
|||
* Support for shell autocompletion of subcommands, flags, and arguments
|
||||
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.
|
||||
|
||||
|
|
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"
|
||||
"text/template"
|
||||
|
||||
"github.com/Masterminds/sprig"
|
||||
"github.com/Masterminds/sprig/v3"
|
||||
"github.com/armon/go-radix"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
@ -680,12 +680,13 @@ func (c *CLI) processArgs() {
|
|||
}
|
||||
|
||||
// Determine the argument we look to to end subcommands.
|
||||
// We look at all arguments until one has a space. This
|
||||
// disallows commands like: ./cli foo "bar baz". An argument
|
||||
// with a space is always an argument.
|
||||
// We look at all arguments until one is a flag or has a space.
|
||||
// This disallows commands like: ./cli foo "bar baz". An
|
||||
// argument with a space is always an argument. A blank
|
||||
// argument is always an argument.
|
||||
j := 0
|
||||
for k, v := range c.Args[i:] {
|
||||
if strings.ContainsRune(v, ' ') {
|
||||
if strings.ContainsRune(v, ' ') || v == "" || v[0] == '-' {
|
||||
break
|
||||
}
|
||||
|
||||
|
|
2
vendor/github.com/posener/complete/.gitignore
generated
vendored
2
vendor/github.com/posener/complete/.gitignore
generated
vendored
|
@ -1,2 +1,4 @@
|
|||
.idea
|
||||
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
|
||||
sudo: false
|
||||
go:
|
||||
- 1.9
|
||||
- 1.8
|
||||
|
||||
before_install:
|
||||
- go get -u -t ./...
|
||||
- go get -u gopkg.in/alecthomas/gometalinter.v1
|
||||
- gometalinter.v1 --install
|
||||
- tip
|
||||
- 1.12.x
|
||||
- 1.11.x
|
||||
- 1.10.x
|
||||
|
||||
script:
|
||||
- gometalinter.v1 --config metalinter.json ./...
|
||||
- ./test.sh
|
||||
- go test -race -coverprofile=coverage.txt -covermode=atomic ./...
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
|
@ -1,27 +1,29 @@
|
|||
# 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)
|
||||
[![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)
|
||||
[![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
|
||||
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
|
||||
#### 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
|
||||
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:
|
||||
```
|
||||
|
||||
```go
|
||||
go get -u github.com/posener/complete/gocomplete
|
||||
gocomplete -install
|
||||
```
|
||||
|
@ -30,13 +32,13 @@ gocomplete -install
|
|||
|
||||
Uninstall by `gocomplete -uninstall`
|
||||
|
||||
### Features
|
||||
#### 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
|
||||
#### Complete package
|
||||
|
||||
Supported shells:
|
||||
|
||||
|
@ -44,7 +46,7 @@ Supported shells:
|
|||
- [x] zsh
|
||||
- [x] fish
|
||||
|
||||
### Usage
|
||||
#### 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,
|
||||
|
@ -52,7 +54,7 @@ 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
|
||||
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`.
|
||||
|
||||
|
@ -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
|
||||
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
|
||||
// last argument if it represents a file name being written.
|
||||
// in case that it is not, we fall back to the current directory.
|
||||
//
|
||||
// Deprecated.
|
||||
func (a Args) Directory() string {
|
||||
if info, err := os.Stat(a.Last); err == nil && info.IsDir() {
|
||||
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 {
|
||||
parts := strings.Fields(line)
|
||||
|
||||
// Add empty field if the last field was completed.
|
||||
if len(line) > 0 && unicode.IsSpace(rune(line[len(line)-1])) {
|
||||
parts = append(parts, "")
|
||||
}
|
||||
|
||||
// Treat the last field if it is of the form "a=b"
|
||||
parts = splitLastEqual(parts)
|
||||
return parts
|
||||
}
|
||||
|
@ -74,16 +85,17 @@ func splitLastEqual(line []string) []string {
|
|||
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 {
|
||||
if i > len(a.All) {
|
||||
i = len(a.All)
|
||||
if 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) {
|
||||
i = len(a.Completed)
|
||||
if i >= len(a.Completed) {
|
||||
i = len(a.Completed) - 1
|
||||
}
|
||||
a.Completed = a.Completed[i:]
|
||||
a.Completed = a.Completed[i+1:]
|
||||
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))
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
func (b bash) Install(cmd, bin string) error {
|
||||
func (b bash) IsInstalled(cmd, bin string) bool {
|
||||
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)
|
||||
}
|
||||
completeCmd := b.cmd(cmd, bin)
|
||||
return appendToFile(b.rc, completeCmd)
|
||||
}
|
||||
|
||||
func (b bash) Uninstall(cmd, bin string) error {
|
||||
completeCmd := b.cmd(cmd, bin)
|
||||
if !lineInFile(b.rc, completeCmd) {
|
||||
if !b.IsInstalled(cmd, bin) {
|
||||
return fmt.Errorf("does not installed in %s", b.rc)
|
||||
}
|
||||
|
||||
completeCmd := b.cmd(cmd, bin)
|
||||
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
|
||||
}
|
||||
|
||||
func (f fish) Install(cmd, bin string) error {
|
||||
completionFile := filepath.Join(f.configDir, "completions", fmt.Sprintf("%s.fish", cmd))
|
||||
completeCmd := f.cmd(cmd, bin)
|
||||
func (f fish) IsInstalled(cmd, bin string) bool {
|
||||
completionFile := f.getCompletionFilePath(cmd)
|
||||
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)
|
||||
}
|
||||
|
||||
func (f fish) Uninstall(cmd, bin string) error {
|
||||
completionFile := filepath.Join(f.configDir, "completions", fmt.Sprintf("%s.fish", cmd))
|
||||
if _, err := os.Stat(completionFile); err != nil {
|
||||
if !f.IsInstalled(cmd, bin) {
|
||||
return fmt.Errorf("does not installed in %s", f.configDir)
|
||||
}
|
||||
|
||||
completionFile := f.getCompletionFilePath(cmd)
|
||||
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
|
||||
params := struct{ Cmd, Bin string }{cmd, bin}
|
||||
template.Must(template.New("cmd").Parse(`
|
||||
tmpl := template.Must(template.New("cmd").Parse(`
|
||||
function __complete_{{.Cmd}}
|
||||
set -lx COMP_LINE (string join ' ' (commandline -o))
|
||||
test (commandline -ct) = ""
|
||||
set -lx COMP_LINE (commandline -cp)
|
||||
test -z (commandline -ct)
|
||||
and set COMP_LINE "$COMP_LINE "
|
||||
{{.Bin}}
|
||||
end
|
||||
complete -c {{.Cmd}} -a "(__complete_{{.Cmd}})"
|
||||
`)).Execute(&buf, params)
|
||||
|
||||
return string(buf.Bytes())
|
||||
complete -f -c {{.Cmd}} -a "(__complete_{{.Cmd}})"
|
||||
`))
|
||||
err := tmpl.Execute(&buf, params)
|
||||
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/user"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
)
|
||||
|
||||
type installer interface {
|
||||
IsInstalled(cmd, bin string) bool
|
||||
Install(cmd, bin string) error
|
||||
Uninstall(cmd, bin string) error
|
||||
}
|
||||
|
@ -36,6 +38,24 @@ func Install(cmd string) error {
|
|||
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:
|
||||
// cmd: is the command name
|
||||
func Uninstall(cmd string) error {
|
||||
|
@ -51,7 +71,7 @@ func Uninstall(cmd string) error {
|
|||
for _, i := range is {
|
||||
errI := i.Uninstall(cmd, bin)
|
||||
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) {
|
||||
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 != "" {
|
||||
i = append(i, bash{f})
|
||||
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 {
|
||||
continue
|
||||
}
|
||||
wf.WriteString(str + "\n")
|
||||
_, err = wf.WriteString(str + "\n")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
prefix = prefix[:0]
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
func (z zsh) Install(cmd, bin string) error {
|
||||
func (z zsh) IsInstalled(cmd, bin string) bool {
|
||||
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)
|
||||
}
|
||||
|
||||
completeCmd := z.cmd(cmd, bin)
|
||||
bashCompInit := "autoload -U +X bashcompinit && bashcompinit"
|
||||
if !lineInFile(z.rc, bashCompInit) {
|
||||
completeCmd = bashCompInit + "\n" + completeCmd
|
||||
|
@ -26,11 +31,11 @@ func (z zsh) Install(cmd, bin string) error {
|
|||
}
|
||||
|
||||
func (z zsh) Uninstall(cmd, bin string) error {
|
||||
completeCmd := z.cmd(cmd, bin)
|
||||
if !lineInFile(z.rc, completeCmd) {
|
||||
if !z.IsInstalled(cmd, bin) {
|
||||
return fmt.Errorf("does not installed in %s", z.rc)
|
||||
}
|
||||
|
||||
completeCmd := z.cmd(cmd, bin)
|
||||
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
|
||||
|
||||
import (
|
||||
|
@ -10,14 +5,16 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/posener/complete/cmd"
|
||||
"github.com/posener/complete/match"
|
||||
)
|
||||
|
||||
const (
|
||||
envComplete = "COMP_LINE"
|
||||
envDebug = "COMP_DEBUG"
|
||||
envLine = "COMP_LINE"
|
||||
envPoint = "COMP_POINT"
|
||||
envDebug = "COMP_DEBUG"
|
||||
)
|
||||
|
||||
// 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
|
||||
// it was called.
|
||||
func (c *Complete) Complete() bool {
|
||||
line, ok := getLine()
|
||||
line, point, ok := getEnv()
|
||||
if !ok {
|
||||
// make sure flags parsed,
|
||||
// in case they were not added in the main program
|
||||
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)
|
||||
Log("Completing last field: %s", a.Last)
|
||||
options := c.Command.Predict(a)
|
||||
|
@ -70,7 +72,7 @@ func (c *Complete) Complete() bool {
|
|||
// filter only options that match the last argument
|
||||
matches := []string{}
|
||||
for _, option := range options {
|
||||
if match.Prefix(option, a.Last) {
|
||||
if strings.HasPrefix(option, a.Last) {
|
||||
matches = append(matches, option)
|
||||
}
|
||||
}
|
||||
|
@ -79,12 +81,19 @@ func (c *Complete) Complete() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func getLine() (string, bool) {
|
||||
line := os.Getenv(envComplete)
|
||||
func getEnv() (line string, point int, ok bool) {
|
||||
line = os.Getenv(envLine)
|
||||
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) {
|
||||
|
|
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
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
@ -15,7 +14,7 @@ import (
|
|||
var Log = getLogger()
|
||||
|
||||
func getLogger() func(format string, args ...interface{}) {
|
||||
var logfile io.Writer = ioutil.Discard
|
||||
var logfile = ioutil.Discard
|
||||
if os.Getenv(envDebug) != "" {
|
||||
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"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/posener/complete/match"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
dir := a.Directory()
|
||||
dir := directory(a.Last)
|
||||
files := listFiles(dir, pattern, allowFiles)
|
||||
|
||||
// add dir if match
|
||||
|
@ -62,6 +60,19 @@ func predictFiles(a Args, pattern string, allowFiles bool) []string {
|
|||
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
|
||||
func PredictFilesSet(files []string) PredictFunc {
|
||||
return func(a Args) (prediction []string) {
|
||||
|
@ -70,7 +81,7 @@ func PredictFilesSet(files []string) PredictFunc {
|
|||
f = fixPathForm(a.Last, f)
|
||||
|
||||
// test matching of file to the argument
|
||||
if match.File(f, a.Last) {
|
||||
if matchFile(f, a.Last) {
|
||||
prediction = append(prediction, f)
|
||||
}
|
||||
}
|
||||
|
@ -106,3 +117,58 @@ func listFiles(dir, pattern string, allowFiles bool) []string {
|
|||
}
|
||||
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 a new issue