mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-10-29 10:42:27 -05:00
[chore] update dependencies (#4423)
- codeberg.org/gruf/go-ffmpreg: v0.6.10 -> v0.6.11 - github.com/spf13/cast: v1.9.2 -> v1.10.0 - github.com/spf13/viper: v1.20.1 -> v1.21.0 - golang.org/x/crypto: v0.41.0 -> v0.42.0 - golang.org/x/image: v0.30.0 -> v0.31.0 Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4423 Co-authored-by: kim <grufwub@gmail.com> Co-committed-by: kim <grufwub@gmail.com>
This commit is contained in:
parent
a6429b5410
commit
c949b9f2d1
97 changed files with 14611 additions and 3494 deletions
22
go.mod
22
go.mod
|
|
@ -22,7 +22,7 @@ require (
|
||||||
codeberg.org/gruf/go-errors/v2 v2.3.2
|
codeberg.org/gruf/go-errors/v2 v2.3.2
|
||||||
codeberg.org/gruf/go-fastcopy v1.1.3
|
codeberg.org/gruf/go-fastcopy v1.1.3
|
||||||
codeberg.org/gruf/go-fastpath/v2 v2.0.0
|
codeberg.org/gruf/go-fastpath/v2 v2.0.0
|
||||||
codeberg.org/gruf/go-ffmpreg v0.6.10
|
codeberg.org/gruf/go-ffmpreg v0.6.11
|
||||||
codeberg.org/gruf/go-iotools v0.0.0-20240710125620-934ae9c654cf
|
codeberg.org/gruf/go-iotools v0.0.0-20240710125620-934ae9c654cf
|
||||||
codeberg.org/gruf/go-kv/v2 v2.0.7
|
codeberg.org/gruf/go-kv/v2 v2.0.7
|
||||||
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f
|
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f
|
||||||
|
|
@ -58,10 +58,10 @@ require (
|
||||||
github.com/oklog/ulid v1.3.1
|
github.com/oklog/ulid v1.3.1
|
||||||
github.com/pquerna/otp v1.5.0
|
github.com/pquerna/otp v1.5.0
|
||||||
github.com/rivo/uniseg v0.4.7
|
github.com/rivo/uniseg v0.4.7
|
||||||
github.com/spf13/cast v1.9.2
|
github.com/spf13/cast v1.10.0
|
||||||
github.com/spf13/cobra v1.10.1
|
github.com/spf13/cobra v1.10.1
|
||||||
github.com/spf13/pflag v1.0.10
|
github.com/spf13/pflag v1.0.10
|
||||||
github.com/spf13/viper v1.20.1
|
github.com/spf13/viper v1.21.0
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/tdewolff/minify/v2 v2.24.3
|
github.com/tdewolff/minify/v2 v2.24.3
|
||||||
github.com/technologize/otel-go-contrib v1.1.1
|
github.com/technologize/otel-go-contrib v1.1.1
|
||||||
|
|
@ -83,8 +83,8 @@ require (
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.38.0
|
go.opentelemetry.io/otel/sdk/metric v1.38.0
|
||||||
go.opentelemetry.io/otel/trace v1.38.0
|
go.opentelemetry.io/otel/trace v1.38.0
|
||||||
go.uber.org/automaxprocs v1.6.0
|
go.uber.org/automaxprocs v1.6.0
|
||||||
golang.org/x/crypto v0.41.0
|
golang.org/x/crypto v0.42.0
|
||||||
golang.org/x/image v0.30.0
|
golang.org/x/image v0.31.0
|
||||||
golang.org/x/net v0.43.0
|
golang.org/x/net v0.43.0
|
||||||
golang.org/x/oauth2 v0.31.0
|
golang.org/x/oauth2 v0.31.0
|
||||||
golang.org/x/sys v0.36.0
|
golang.org/x/sys v0.36.0
|
||||||
|
|
@ -122,7 +122,7 @@ require (
|
||||||
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e // indirect
|
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
||||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||||
github.com/go-errors/errors v1.1.1 // indirect
|
github.com/go-errors/errors v1.1.1 // indirect
|
||||||
|
|
@ -144,7 +144,7 @@ require (
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.26.0 // indirect
|
github.com/go-playground/validator/v10 v10.26.0 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||||
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b // indirect
|
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b // indirect
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
||||||
|
|
@ -197,10 +197,10 @@ require (
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a // indirect
|
github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a // indirect
|
||||||
github.com/rs/xid v1.6.0 // indirect
|
github.com/rs/xid v1.6.0 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.7.0 // indirect
|
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||||
github.com/shopspring/decimal v1.3.1 // indirect
|
github.com/shopspring/decimal v1.3.1 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||||
github.com/spf13/afero v1.12.0 // indirect
|
github.com/spf13/afero v1.15.0 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/tdewolff/parse/v2 v2.8.3 // indirect
|
github.com/tdewolff/parse/v2 v2.8.3 // indirect
|
||||||
github.com/tinylib/msgp v1.3.0 // indirect
|
github.com/tinylib/msgp v1.3.0 // indirect
|
||||||
|
|
@ -228,7 +228,7 @@ require (
|
||||||
go.opentelemetry.io/otel/log v0.14.0 // indirect
|
go.opentelemetry.io/otel/log v0.14.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk/log v0.14.0 // indirect
|
go.opentelemetry.io/otel/sdk/log v0.14.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||||
golang.org/x/arch v0.18.0 // indirect
|
golang.org/x/arch v0.18.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
||||||
golang.org/x/mod v0.27.0 // indirect
|
golang.org/x/mod v0.27.0 // indirect
|
||||||
|
|
|
||||||
48
go.sum
generated
48
go.sum
generated
|
|
@ -28,8 +28,8 @@ codeberg.org/gruf/go-fastcopy v1.1.3 h1:Jo9VTQjI6KYimlw25PPc7YLA3Xm+XMQhaHwKnM7x
|
||||||
codeberg.org/gruf/go-fastcopy v1.1.3/go.mod h1:GDDYR0Cnb3U/AIfGM3983V/L+GN+vuwVMvrmVABo21s=
|
codeberg.org/gruf/go-fastcopy v1.1.3/go.mod h1:GDDYR0Cnb3U/AIfGM3983V/L+GN+vuwVMvrmVABo21s=
|
||||||
codeberg.org/gruf/go-fastpath/v2 v2.0.0 h1:iAS9GZahFhyWEH0KLhFEJR+txx1ZhMXxYzu2q5Qo9c0=
|
codeberg.org/gruf/go-fastpath/v2 v2.0.0 h1:iAS9GZahFhyWEH0KLhFEJR+txx1ZhMXxYzu2q5Qo9c0=
|
||||||
codeberg.org/gruf/go-fastpath/v2 v2.0.0/go.mod h1:3pPqu5nZjpbRrOqvLyAK7puS1OfEtQvjd6342Cwz56Q=
|
codeberg.org/gruf/go-fastpath/v2 v2.0.0/go.mod h1:3pPqu5nZjpbRrOqvLyAK7puS1OfEtQvjd6342Cwz56Q=
|
||||||
codeberg.org/gruf/go-ffmpreg v0.6.10 h1:02QvdA4p7UExT/Df+x7omnZbQtdjUf6RmXt5NsvR+LE=
|
codeberg.org/gruf/go-ffmpreg v0.6.11 h1:+lvB5Loy0KUAKfv6nOZRWHFVgN08cpHhUlYcZxL8M20=
|
||||||
codeberg.org/gruf/go-ffmpreg v0.6.10/go.mod h1:tGqIMh/I2cizqauxxNAN+WGkICI0j5G3xwF1uBkyw1E=
|
codeberg.org/gruf/go-ffmpreg v0.6.11/go.mod h1:tGqIMh/I2cizqauxxNAN+WGkICI0j5G3xwF1uBkyw1E=
|
||||||
codeberg.org/gruf/go-iotools v0.0.0-20240710125620-934ae9c654cf h1:84s/ii8N6lYlskZjHH+DG6jyia8w2mXMZlRwFn8Gs3A=
|
codeberg.org/gruf/go-iotools v0.0.0-20240710125620-934ae9c654cf h1:84s/ii8N6lYlskZjHH+DG6jyia8w2mXMZlRwFn8Gs3A=
|
||||||
codeberg.org/gruf/go-iotools v0.0.0-20240710125620-934ae9c654cf/go.mod h1:zZAICsp5rY7+hxnws2V0ePrWxE0Z2Z/KXcN3p/RQCfk=
|
codeberg.org/gruf/go-iotools v0.0.0-20240710125620-934ae9c654cf/go.mod h1:zZAICsp5rY7+hxnws2V0ePrWxE0Z2Z/KXcN3p/RQCfk=
|
||||||
codeberg.org/gruf/go-kv v1.6.5 h1:ttPf0NA8F79pDqBttSudPTVCZmGncumeNIxmeM9ztz0=
|
codeberg.org/gruf/go-kv v1.6.5 h1:ttPf0NA8F79pDqBttSudPTVCZmGncumeNIxmeM9ztz0=
|
||||||
|
|
@ -139,8 +139,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/fxamacker/cbor v1.5.1 h1:XjQWBgdmQyqimslUh5r4tUGmoqzHmBFQOImkWGi2awg=
|
github.com/fxamacker/cbor v1.5.1 h1:XjQWBgdmQyqimslUh5r4tUGmoqzHmBFQOImkWGi2awg=
|
||||||
github.com/fxamacker/cbor v1.5.1/go.mod h1:3aPGItF174ni7dDzd6JZ206H8cmr4GDNBGpPa971zsU=
|
github.com/fxamacker/cbor v1.5.1/go.mod h1:3aPGItF174ni7dDzd6JZ206H8cmr4GDNBGpPa971zsU=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
||||||
|
|
@ -205,8 +205,8 @@ github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc
|
||||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||||
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
||||||
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||||
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo=
|
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo=
|
||||||
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
|
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
|
||||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||||
|
|
@ -388,8 +388,8 @@ github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a/go.mod h1:
|
||||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
|
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||||
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
|
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||||
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
|
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
|
||||||
github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
|
github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
|
||||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||||
|
|
@ -403,20 +403,20 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
|
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
|
||||||
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
|
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
|
||||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
||||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
|
||||||
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
|
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||||
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
|
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
|
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||||
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||||
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
|
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
|
||||||
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
|
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
|
||||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
|
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||||
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
|
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
|
@ -566,8 +566,8 @@ go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
golang.org/x/arch v0.18.0 h1:WN9poc33zL4AzGxqf8VtpKUnGvMi8O9lhNyBMF/85qc=
|
golang.org/x/arch v0.18.0 h1:WN9poc33zL4AzGxqf8VtpKUnGvMi8O9lhNyBMF/85qc=
|
||||||
golang.org/x/arch v0.18.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
golang.org/x/arch v0.18.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
|
@ -577,12 +577,12 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
||||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
||||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
|
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
|
||||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
|
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
|
||||||
golang.org/x/image v0.30.0 h1:jD5RhkmVAnjqaCUXfbGBrn3lpxbknfN9w2UhHHU+5B4=
|
golang.org/x/image v0.31.0 h1:mLChjE2MV6g1S7oqbXC0/UcKijjm5fnJLUYKIYrLESA=
|
||||||
golang.org/x/image v0.30.0/go.mod h1:SAEUTxCCMWSrJcCy/4HwavEsfZZJlYxeHLc6tTiAe/c=
|
golang.org/x/image v0.31.0/go.mod h1:R9ec5Lcp96v9FTF+ajwaH3uGxPH4fKfHHAVbUILxghA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
|
@ -645,8 +645,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
|
||||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
|
|
||||||
BIN
vendor/codeberg.org/gruf/go-ffmpreg/embed/ffmpreg.wasm.gz
generated
vendored
BIN
vendor/codeberg.org/gruf/go-ffmpreg/embed/ffmpreg.wasm.gz
generated
vendored
Binary file not shown.
2
vendor/github.com/fsnotify/fsnotify/.cirrus.yml
generated
vendored
2
vendor/github.com/fsnotify/fsnotify/.cirrus.yml
generated
vendored
|
|
@ -1,7 +1,7 @@
|
||||||
freebsd_task:
|
freebsd_task:
|
||||||
name: 'FreeBSD'
|
name: 'FreeBSD'
|
||||||
freebsd_instance:
|
freebsd_instance:
|
||||||
image_family: freebsd-14-1
|
image_family: freebsd-14-2
|
||||||
install_script:
|
install_script:
|
||||||
- pkg update -f
|
- pkg update -f
|
||||||
- pkg install -y go
|
- pkg install -y go
|
||||||
|
|
|
||||||
35
vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
generated
vendored
35
vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
generated
vendored
|
|
@ -1,6 +1,39 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
1.8.0 2023-10-31
|
1.9.0 2024-04-04
|
||||||
|
----------------
|
||||||
|
|
||||||
|
### Changes and fixes
|
||||||
|
|
||||||
|
- all: make BufferedWatcher buffered again ([#657])
|
||||||
|
|
||||||
|
- inotify: fix race when adding/removing watches while a watched path is being
|
||||||
|
deleted ([#678], [#686])
|
||||||
|
|
||||||
|
- inotify: don't send empty event if a watched path is unmounted ([#655])
|
||||||
|
|
||||||
|
- inotify: don't register duplicate watches when watching both a symlink and its
|
||||||
|
target; previously that would get "half-added" and removing the second would
|
||||||
|
panic ([#679])
|
||||||
|
|
||||||
|
- kqueue: fix watching relative symlinks ([#681])
|
||||||
|
|
||||||
|
- kqueue: correctly mark pre-existing entries when watching a link to a dir on
|
||||||
|
kqueue ([#682])
|
||||||
|
|
||||||
|
- illumos: don't send error if changed file is deleted while processing the
|
||||||
|
event ([#678])
|
||||||
|
|
||||||
|
|
||||||
|
[#657]: https://github.com/fsnotify/fsnotify/pull/657
|
||||||
|
[#678]: https://github.com/fsnotify/fsnotify/pull/678
|
||||||
|
[#686]: https://github.com/fsnotify/fsnotify/pull/686
|
||||||
|
[#655]: https://github.com/fsnotify/fsnotify/pull/655
|
||||||
|
[#681]: https://github.com/fsnotify/fsnotify/pull/681
|
||||||
|
[#679]: https://github.com/fsnotify/fsnotify/pull/679
|
||||||
|
[#682]: https://github.com/fsnotify/fsnotify/pull/682
|
||||||
|
|
||||||
|
1.8.0 2024-10-31
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
### Additions
|
### Additions
|
||||||
|
|
|
||||||
1
vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
generated
vendored
1
vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
generated
vendored
|
|
@ -77,6 +77,7 @@ End-of-line escapes with `\` are not supported.
|
||||||
debug [yes/no] # Enable/disable FSNOTIFY_DEBUG (tests are run in
|
debug [yes/no] # Enable/disable FSNOTIFY_DEBUG (tests are run in
|
||||||
parallel by default, so -parallel=1 is probably a good
|
parallel by default, so -parallel=1 is probably a good
|
||||||
idea).
|
idea).
|
||||||
|
print [any strings] # Print text to stdout; for debugging.
|
||||||
|
|
||||||
touch path
|
touch path
|
||||||
mkdir [-p] dir
|
mkdir [-p] dir
|
||||||
|
|
|
||||||
2
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
2
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
|
|
@ -15,7 +15,6 @@ Platform support:
|
||||||
| ReadDirectoryChangesW | Windows | Supported |
|
| ReadDirectoryChangesW | Windows | Supported |
|
||||||
| FEN | illumos | Supported |
|
| FEN | illumos | Supported |
|
||||||
| fanotify | Linux 5.9+ | [Not yet](https://github.com/fsnotify/fsnotify/issues/114) |
|
| fanotify | Linux 5.9+ | [Not yet](https://github.com/fsnotify/fsnotify/issues/114) |
|
||||||
| AHAFS | AIX | [aix branch]; experimental due to lack of maintainer and test environment |
|
|
||||||
| FSEvents | macOS | [Needs support in x/sys/unix][fsevents] |
|
| FSEvents | macOS | [Needs support in x/sys/unix][fsevents] |
|
||||||
| USN Journals | Windows | [Needs support in x/sys/windows][usn] |
|
| USN Journals | Windows | [Needs support in x/sys/windows][usn] |
|
||||||
| Polling | *All* | [Not yet](https://github.com/fsnotify/fsnotify/issues/9) |
|
| Polling | *All* | [Not yet](https://github.com/fsnotify/fsnotify/issues/9) |
|
||||||
|
|
@ -25,7 +24,6 @@ untested.
|
||||||
|
|
||||||
[fsevents]: https://github.com/fsnotify/fsnotify/issues/11#issuecomment-1279133120
|
[fsevents]: https://github.com/fsnotify/fsnotify/issues/11#issuecomment-1279133120
|
||||||
[usn]: https://github.com/fsnotify/fsnotify/issues/53#issuecomment-1279829847
|
[usn]: https://github.com/fsnotify/fsnotify/issues/53#issuecomment-1279829847
|
||||||
[aix branch]: https://github.com/fsnotify/fsnotify/issues/353#issuecomment-1284590129
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
|
||||||
107
vendor/github.com/fsnotify/fsnotify/backend_fen.go
generated
vendored
107
vendor/github.com/fsnotify/fsnotify/backend_fen.go
generated
vendored
|
|
@ -9,6 +9,7 @@ package fsnotify
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -19,27 +20,25 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type fen struct {
|
type fen struct {
|
||||||
|
*shared
|
||||||
Events chan Event
|
Events chan Event
|
||||||
Errors chan error
|
Errors chan error
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
port *unix.EventPort
|
port *unix.EventPort
|
||||||
done chan struct{} // Channel for sending a "quit message" to the reader goroutine
|
|
||||||
dirs map[string]Op // Explicitly watched directories
|
dirs map[string]Op // Explicitly watched directories
|
||||||
watches map[string]Op // Explicitly watched non-directories
|
watches map[string]Op // Explicitly watched non-directories
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
var defaultBufferSize = 0
|
||||||
return newBufferedBackend(0, ev, errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
|
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||||
w := &fen{
|
w := &fen{
|
||||||
|
shared: newShared(ev, errs),
|
||||||
Events: ev,
|
Events: ev,
|
||||||
Errors: errs,
|
Errors: errs,
|
||||||
dirs: make(map[string]Op),
|
dirs: make(map[string]Op),
|
||||||
watches: make(map[string]Op),
|
watches: make(map[string]Op),
|
||||||
done: make(chan struct{}),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
@ -52,49 +51,10 @@ func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendEvent attempts to send an event to the user, returning true if the event
|
|
||||||
// was put in the channel successfully and false if the watcher has been closed.
|
|
||||||
func (w *fen) sendEvent(name string, op Op) (sent bool) {
|
|
||||||
select {
|
|
||||||
case <-w.done:
|
|
||||||
return false
|
|
||||||
case w.Events <- Event{Name: name, Op: op}:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendError attempts to send an error to the user, returning true if the error
|
|
||||||
// was put in the channel successfully and false if the watcher has been closed.
|
|
||||||
func (w *fen) sendError(err error) (sent bool) {
|
|
||||||
if err == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-w.done:
|
|
||||||
return false
|
|
||||||
case w.Errors <- err:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *fen) isClosed() bool {
|
|
||||||
select {
|
|
||||||
case <-w.done:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *fen) Close() error {
|
func (w *fen) Close() error {
|
||||||
// Take the lock used by associateFile to prevent lingering events from
|
if w.shared.close() {
|
||||||
// being processed after the close
|
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
if w.isClosed() {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
close(w.done)
|
|
||||||
return w.port.Close()
|
return w.port.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,7 +169,7 @@ func (w *fen) readEvents() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// There was an error not caused by calling w.Close()
|
// There was an error not caused by calling w.Close()
|
||||||
if !w.sendError(err) {
|
if !w.sendError(fmt.Errorf("port.Get: %w", err)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -277,13 +237,13 @@ func (w *fen) handleEvent(event *unix.PortEvent) error {
|
||||||
isWatched := watchedDir || watchedPath
|
isWatched := watchedDir || watchedPath
|
||||||
|
|
||||||
if events&unix.FILE_DELETE != 0 {
|
if events&unix.FILE_DELETE != 0 {
|
||||||
if !w.sendEvent(path, Remove) {
|
if !w.sendEvent(Event{Name: path, Op: Remove}) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
reRegister = false
|
reRegister = false
|
||||||
}
|
}
|
||||||
if events&unix.FILE_RENAME_FROM != 0 {
|
if events&unix.FILE_RENAME_FROM != 0 {
|
||||||
if !w.sendEvent(path, Rename) {
|
if !w.sendEvent(Event{Name: path, Op: Rename}) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Don't keep watching the new file name
|
// Don't keep watching the new file name
|
||||||
|
|
@ -297,7 +257,7 @@ func (w *fen) handleEvent(event *unix.PortEvent) error {
|
||||||
|
|
||||||
// inotify reports a Remove event in this case, so we simulate this
|
// inotify reports a Remove event in this case, so we simulate this
|
||||||
// here.
|
// here.
|
||||||
if !w.sendEvent(path, Remove) {
|
if !w.sendEvent(Event{Name: path, Op: Remove}) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Don't keep watching the file that was removed
|
// Don't keep watching the file that was removed
|
||||||
|
|
@ -331,7 +291,7 @@ func (w *fen) handleEvent(event *unix.PortEvent) error {
|
||||||
// get here, the sudirectory is already gone. Clearly we were watching
|
// get here, the sudirectory is already gone. Clearly we were watching
|
||||||
// this path but now it is gone. Let's tell the user that it was
|
// this path but now it is gone. Let's tell the user that it was
|
||||||
// removed.
|
// removed.
|
||||||
if !w.sendEvent(path, Remove) {
|
if !w.sendEvent(Event{Name: path, Op: Remove}) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Suppress extra write events on removed directories; they are not
|
// Suppress extra write events on removed directories; they are not
|
||||||
|
|
@ -346,7 +306,7 @@ func (w *fen) handleEvent(event *unix.PortEvent) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// The symlink still exists, but the target is gone. Report the
|
// The symlink still exists, but the target is gone. Report the
|
||||||
// Remove similar to above.
|
// Remove similar to above.
|
||||||
if !w.sendEvent(path, Remove) {
|
if !w.sendEvent(Event{Name: path, Op: Remove}) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Don't return the error
|
// Don't return the error
|
||||||
|
|
@ -359,7 +319,7 @@ func (w *fen) handleEvent(event *unix.PortEvent) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !w.sendEvent(path, Write) {
|
if !w.sendEvent(Event{Name: path, Op: Write}) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -367,7 +327,7 @@ func (w *fen) handleEvent(event *unix.PortEvent) error {
|
||||||
if events&unix.FILE_ATTRIB != 0 && stat != nil {
|
if events&unix.FILE_ATTRIB != 0 && stat != nil {
|
||||||
// Only send Chmod if perms changed
|
// Only send Chmod if perms changed
|
||||||
if stat.Mode().Perm() != fmode.Perm() {
|
if stat.Mode().Perm() != fmode.Perm() {
|
||||||
if !w.sendEvent(path, Chmod) {
|
if !w.sendEvent(Event{Name: path, Op: Chmod}) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -376,17 +336,27 @@ func (w *fen) handleEvent(event *unix.PortEvent) error {
|
||||||
if stat != nil {
|
if stat != nil {
|
||||||
// If we get here, it means we've hit an event above that requires us to
|
// If we get here, it means we've hit an event above that requires us to
|
||||||
// continue watching the file or directory
|
// continue watching the file or directory
|
||||||
return w.associateFile(path, stat, isWatched)
|
err := w.associateFile(path, stat, isWatched)
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
// Path may have been removed since the stat.
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The directory was modified, so we must find unwatched entities and watch
|
||||||
|
// them. If something was removed from the directory, nothing will happen, as
|
||||||
|
// everything else should still be watched.
|
||||||
func (w *fen) updateDirectory(path string) error {
|
func (w *fen) updateDirectory(path string) error {
|
||||||
// The directory was modified, so we must find unwatched entities and watch
|
|
||||||
// them. If something was removed from the directory, nothing will happen,
|
|
||||||
// as everything else should still be watched.
|
|
||||||
files, err := os.ReadDir(path)
|
files, err := os.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Directory no longer exists: probably just deleted since we got the
|
||||||
|
// event.
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -401,10 +371,15 @@ func (w *fen) updateDirectory(path string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = w.associateFile(path, finfo, false)
|
err = w.associateFile(path, finfo, false)
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
// File may have disappeared between getting the dir listing and
|
||||||
|
// adding the port: that's okay to ignore.
|
||||||
|
continue
|
||||||
|
}
|
||||||
if !w.sendError(err) {
|
if !w.sendError(err) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if !w.sendEvent(path, Create) {
|
if !w.sendEvent(Event{Name: path, Op: Create}) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -430,7 +405,7 @@ func (w *fen) associateFile(path string, stat os.FileInfo, follow bool) error {
|
||||||
// has fired but we haven't processed it yet.
|
// has fired but we haven't processed it yet.
|
||||||
err := w.port.DissociatePath(path)
|
err := w.port.DissociatePath(path)
|
||||||
if err != nil && !errors.Is(err, unix.ENOENT) {
|
if err != nil && !errors.Is(err, unix.ENOENT) {
|
||||||
return err
|
return fmt.Errorf("port.DissociatePath(%q): %w", path, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -446,14 +421,22 @@ func (w *fen) associateFile(path string, stat os.FileInfo, follow bool) error {
|
||||||
if true {
|
if true {
|
||||||
events |= unix.FILE_ATTRIB
|
events |= unix.FILE_ATTRIB
|
||||||
}
|
}
|
||||||
return w.port.AssociatePath(path, stat, events, stat.Mode())
|
err := w.port.AssociatePath(path, stat, events, stat.Mode())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("port.AssociatePath(%q): %w", path, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *fen) dissociateFile(path string, stat os.FileInfo, unused bool) error {
|
func (w *fen) dissociateFile(path string, stat os.FileInfo, unused bool) error {
|
||||||
if !w.port.PathIsWatched(path) {
|
if !w.port.PathIsWatched(path) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return w.port.DissociatePath(path)
|
err := w.port.DissociatePath(path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("port.DissociatePath(%q): %w", path, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *fen) WatchList() []string {
|
func (w *fen) WatchList() []string {
|
||||||
|
|
|
||||||
441
vendor/github.com/fsnotify/fsnotify/backend_inotify.go
generated
vendored
441
vendor/github.com/fsnotify/fsnotify/backend_inotify.go
generated
vendored
|
|
@ -19,6 +19,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type inotify struct {
|
type inotify struct {
|
||||||
|
*shared
|
||||||
Events chan Event
|
Events chan Event
|
||||||
Errors chan error
|
Errors chan error
|
||||||
|
|
||||||
|
|
@ -27,8 +28,6 @@ type inotify struct {
|
||||||
fd int
|
fd int
|
||||||
inotifyFile *os.File
|
inotifyFile *os.File
|
||||||
watches *watches
|
watches *watches
|
||||||
done chan struct{} // Channel for sending a "quit message" to the reader goroutine
|
|
||||||
doneMu sync.Mutex
|
|
||||||
doneResp chan struct{} // Channel to respond to Close
|
doneResp chan struct{} // Channel to respond to Close
|
||||||
|
|
||||||
// Store rename cookies in an array, with the index wrapping to 0. Almost
|
// Store rename cookies in an array, with the index wrapping to 0. Almost
|
||||||
|
|
@ -52,7 +51,6 @@ type inotify struct {
|
||||||
|
|
||||||
type (
|
type (
|
||||||
watches struct {
|
watches struct {
|
||||||
mu sync.RWMutex
|
|
||||||
wd map[uint32]*watch // wd → watch
|
wd map[uint32]*watch // wd → watch
|
||||||
path map[string]uint32 // pathname → wd
|
path map[string]uint32 // pathname → wd
|
||||||
}
|
}
|
||||||
|
|
@ -75,34 +73,13 @@ func newWatches() *watches {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *watches) len() int {
|
func (w *watches) byPath(path string) *watch { return w.wd[w.path[path]] }
|
||||||
w.mu.RLock()
|
func (w *watches) byWd(wd uint32) *watch { return w.wd[wd] }
|
||||||
defer w.mu.RUnlock()
|
func (w *watches) len() int { return len(w.wd) }
|
||||||
return len(w.wd)
|
func (w *watches) add(ww *watch) { w.wd[ww.wd] = ww; w.path[ww.path] = ww.wd }
|
||||||
}
|
func (w *watches) remove(watch *watch) { delete(w.path, watch.path); delete(w.wd, watch.wd) }
|
||||||
|
|
||||||
func (w *watches) add(ww *watch) {
|
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
w.wd[ww.wd] = ww
|
|
||||||
w.path[ww.path] = ww.wd
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *watches) remove(wd uint32) {
|
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
watch := w.wd[wd] // Could have had Remove() called. See #616.
|
|
||||||
if watch == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
delete(w.path, watch.path)
|
|
||||||
delete(w.wd, wd)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *watches) removePath(path string) ([]uint32, error) {
|
func (w *watches) removePath(path string) ([]uint32, error) {
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
|
|
||||||
path, recurse := recursivePath(path)
|
path, recurse := recursivePath(path)
|
||||||
wd, ok := w.path[path]
|
wd, ok := w.path[path]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -123,7 +100,7 @@ func (w *watches) removePath(path string) ([]uint32, error) {
|
||||||
wds := make([]uint32, 0, 8)
|
wds := make([]uint32, 0, 8)
|
||||||
wds = append(wds, wd)
|
wds = append(wds, wd)
|
||||||
for p, rwd := range w.path {
|
for p, rwd := range w.path {
|
||||||
if filepath.HasPrefix(p, path) {
|
if strings.HasPrefix(p, path) {
|
||||||
delete(w.path, p)
|
delete(w.path, p)
|
||||||
delete(w.wd, rwd)
|
delete(w.wd, rwd)
|
||||||
wds = append(wds, rwd)
|
wds = append(wds, rwd)
|
||||||
|
|
@ -132,22 +109,7 @@ func (w *watches) removePath(path string) ([]uint32, error) {
|
||||||
return wds, nil
|
return wds, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *watches) byPath(path string) *watch {
|
|
||||||
w.mu.RLock()
|
|
||||||
defer w.mu.RUnlock()
|
|
||||||
return w.wd[w.path[path]]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *watches) byWd(wd uint32) *watch {
|
|
||||||
w.mu.RLock()
|
|
||||||
defer w.mu.RUnlock()
|
|
||||||
return w.wd[wd]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error {
|
func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error {
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
|
|
||||||
var existing *watch
|
var existing *watch
|
||||||
wd, ok := w.path[path]
|
wd, ok := w.path[path]
|
||||||
if ok {
|
if ok {
|
||||||
|
|
@ -170,11 +132,9 @@ func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
var defaultBufferSize = 0
|
||||||
return newBufferedBackend(0, ev, errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
|
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||||
// Need to set nonblocking mode for SetDeadline to work, otherwise blocking
|
// Need to set nonblocking mode for SetDeadline to work, otherwise blocking
|
||||||
// I/O operations won't terminate on close.
|
// I/O operations won't terminate on close.
|
||||||
fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
|
fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
|
||||||
|
|
@ -183,12 +143,12 @@ func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error
|
||||||
}
|
}
|
||||||
|
|
||||||
w := &inotify{
|
w := &inotify{
|
||||||
|
shared: newShared(ev, errs),
|
||||||
Events: ev,
|
Events: ev,
|
||||||
Errors: errs,
|
Errors: errs,
|
||||||
fd: fd,
|
fd: fd,
|
||||||
inotifyFile: os.NewFile(uintptr(fd), ""),
|
inotifyFile: os.NewFile(uintptr(fd), ""),
|
||||||
watches: newWatches(),
|
watches: newWatches(),
|
||||||
done: make(chan struct{}),
|
|
||||||
doneResp: make(chan struct{}),
|
doneResp: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -196,46 +156,10 @@ func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the event was sent, or false if watcher is closed.
|
|
||||||
func (w *inotify) sendEvent(e Event) bool {
|
|
||||||
select {
|
|
||||||
case <-w.done:
|
|
||||||
return false
|
|
||||||
case w.Events <- e:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if the error was sent, or false if watcher is closed.
|
|
||||||
func (w *inotify) sendError(err error) bool {
|
|
||||||
if err == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-w.done:
|
|
||||||
return false
|
|
||||||
case w.Errors <- err:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *inotify) isClosed() bool {
|
|
||||||
select {
|
|
||||||
case <-w.done:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *inotify) Close() error {
|
func (w *inotify) Close() error {
|
||||||
w.doneMu.Lock()
|
if w.shared.close() {
|
||||||
if w.isClosed() {
|
|
||||||
w.doneMu.Unlock()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
close(w.done)
|
|
||||||
w.doneMu.Unlock()
|
|
||||||
|
|
||||||
// Causes any blocking reads to return with an error, provided the file
|
// Causes any blocking reads to return with an error, provided the file
|
||||||
// still supports deadline operations.
|
// still supports deadline operations.
|
||||||
|
|
@ -244,9 +168,7 @@ func (w *inotify) Close() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for goroutine to close
|
<-w.doneResp // Wait for readEvents() to finish.
|
||||||
<-w.doneResp
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -266,6 +188,43 @@ func (w *inotify) AddWith(path string, opts ...addOpt) error {
|
||||||
return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
|
return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add := func(path string, with withOpts, recurse bool) error {
|
||||||
|
var flags uint32
|
||||||
|
if with.noFollow {
|
||||||
|
flags |= unix.IN_DONT_FOLLOW
|
||||||
|
}
|
||||||
|
if with.op.Has(Create) {
|
||||||
|
flags |= unix.IN_CREATE
|
||||||
|
}
|
||||||
|
if with.op.Has(Write) {
|
||||||
|
flags |= unix.IN_MODIFY
|
||||||
|
}
|
||||||
|
if with.op.Has(Remove) {
|
||||||
|
flags |= unix.IN_DELETE | unix.IN_DELETE_SELF
|
||||||
|
}
|
||||||
|
if with.op.Has(Rename) {
|
||||||
|
flags |= unix.IN_MOVED_TO | unix.IN_MOVED_FROM | unix.IN_MOVE_SELF
|
||||||
|
}
|
||||||
|
if with.op.Has(Chmod) {
|
||||||
|
flags |= unix.IN_ATTRIB
|
||||||
|
}
|
||||||
|
if with.op.Has(xUnportableOpen) {
|
||||||
|
flags |= unix.IN_OPEN
|
||||||
|
}
|
||||||
|
if with.op.Has(xUnportableRead) {
|
||||||
|
flags |= unix.IN_ACCESS
|
||||||
|
}
|
||||||
|
if with.op.Has(xUnportableCloseWrite) {
|
||||||
|
flags |= unix.IN_CLOSE_WRITE
|
||||||
|
}
|
||||||
|
if with.op.Has(xUnportableCloseRead) {
|
||||||
|
flags |= unix.IN_CLOSE_NOWRITE
|
||||||
|
}
|
||||||
|
return w.register(path, flags, recurse)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
path, recurse := recursivePath(path)
|
path, recurse := recursivePath(path)
|
||||||
if recurse {
|
if recurse {
|
||||||
return filepath.WalkDir(path, func(root string, d fs.DirEntry, err error) error {
|
return filepath.WalkDir(path, func(root string, d fs.DirEntry, err error) error {
|
||||||
|
|
@ -289,46 +248,11 @@ func (w *inotify) AddWith(path string, opts ...addOpt) error {
|
||||||
w.sendEvent(Event{Name: root, Op: Create})
|
w.sendEvent(Event{Name: root, Op: Create})
|
||||||
}
|
}
|
||||||
|
|
||||||
return w.add(root, with, true)
|
return add(root, with, true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return w.add(path, with, false)
|
return add(path, with, false)
|
||||||
}
|
|
||||||
|
|
||||||
func (w *inotify) add(path string, with withOpts, recurse bool) error {
|
|
||||||
var flags uint32
|
|
||||||
if with.noFollow {
|
|
||||||
flags |= unix.IN_DONT_FOLLOW
|
|
||||||
}
|
|
||||||
if with.op.Has(Create) {
|
|
||||||
flags |= unix.IN_CREATE
|
|
||||||
}
|
|
||||||
if with.op.Has(Write) {
|
|
||||||
flags |= unix.IN_MODIFY
|
|
||||||
}
|
|
||||||
if with.op.Has(Remove) {
|
|
||||||
flags |= unix.IN_DELETE | unix.IN_DELETE_SELF
|
|
||||||
}
|
|
||||||
if with.op.Has(Rename) {
|
|
||||||
flags |= unix.IN_MOVED_TO | unix.IN_MOVED_FROM | unix.IN_MOVE_SELF
|
|
||||||
}
|
|
||||||
if with.op.Has(Chmod) {
|
|
||||||
flags |= unix.IN_ATTRIB
|
|
||||||
}
|
|
||||||
if with.op.Has(xUnportableOpen) {
|
|
||||||
flags |= unix.IN_OPEN
|
|
||||||
}
|
|
||||||
if with.op.Has(xUnportableRead) {
|
|
||||||
flags |= unix.IN_ACCESS
|
|
||||||
}
|
|
||||||
if with.op.Has(xUnportableCloseWrite) {
|
|
||||||
flags |= unix.IN_CLOSE_WRITE
|
|
||||||
}
|
|
||||||
if with.op.Has(xUnportableCloseRead) {
|
|
||||||
flags |= unix.IN_CLOSE_NOWRITE
|
|
||||||
}
|
|
||||||
return w.register(path, flags, recurse)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *inotify) register(path string, flags uint32, recurse bool) error {
|
func (w *inotify) register(path string, flags uint32, recurse bool) error {
|
||||||
|
|
@ -342,6 +266,10 @@ func (w *inotify) register(path string, flags uint32, recurse bool) error {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if e, ok := w.watches.wd[uint32(wd)]; ok {
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
|
||||||
if existing == nil {
|
if existing == nil {
|
||||||
return &watch{
|
return &watch{
|
||||||
wd: uint32(wd),
|
wd: uint32(wd),
|
||||||
|
|
@ -365,6 +293,9 @@ func (w *inotify) Remove(name string) error {
|
||||||
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n",
|
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n",
|
||||||
time.Now().Format("15:04:05.000000000"), name)
|
time.Now().Format("15:04:05.000000000"), name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
return w.remove(filepath.Clean(name))
|
return w.remove(filepath.Clean(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -399,13 +330,12 @@ func (w *inotify) WatchList() []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
entries := make([]string, 0, w.watches.len())
|
entries := make([]string, 0, w.watches.len())
|
||||||
w.watches.mu.RLock()
|
|
||||||
for pathname := range w.watches.path {
|
for pathname := range w.watches.path {
|
||||||
entries = append(entries, pathname)
|
entries = append(entries, pathname)
|
||||||
}
|
}
|
||||||
w.watches.mu.RUnlock()
|
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -418,21 +348,17 @@ func (w *inotify) readEvents() {
|
||||||
close(w.Events)
|
close(w.Events)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var (
|
var buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
|
||||||
buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
|
|
||||||
errno error // Syscall errno
|
|
||||||
)
|
|
||||||
for {
|
for {
|
||||||
// See if we have been closed.
|
|
||||||
if w.isClosed() {
|
if w.isClosed() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err := w.inotifyFile.Read(buf[:])
|
n, err := w.inotifyFile.Read(buf[:])
|
||||||
switch {
|
if err != nil {
|
||||||
case errors.Unwrap(err) == os.ErrClosed:
|
if errors.Is(err, os.ErrClosed) {
|
||||||
return
|
return
|
||||||
case err != nil:
|
}
|
||||||
if !w.sendError(err) {
|
if !w.sendError(err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -440,13 +366,9 @@ func (w *inotify) readEvents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < unix.SizeofInotifyEvent {
|
if n < unix.SizeofInotifyEvent {
|
||||||
var err error
|
err := errors.New("notify: short read in readEvents()") // Read was too short.
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
err = io.EOF // If EOF is received. This should really never happen.
|
err = io.EOF // If EOF is received. This should really never happen.
|
||||||
} else if n < 0 {
|
|
||||||
err = errno // If an error occurred while reading.
|
|
||||||
} else {
|
|
||||||
err = errors.New("notify: short read in readEvents()") // Read was too short.
|
|
||||||
}
|
}
|
||||||
if !w.sendError(err) {
|
if !w.sendError(err) {
|
||||||
return
|
return
|
||||||
|
|
@ -454,134 +376,137 @@ func (w *inotify) readEvents() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't know how many events we just read into the buffer
|
// We don't know how many events we just read into the buffer While the
|
||||||
// While the offset points to at least one whole event...
|
// offset points to at least one whole event.
|
||||||
var offset uint32
|
var offset uint32
|
||||||
for offset <= uint32(n-unix.SizeofInotifyEvent) {
|
for offset <= uint32(n-unix.SizeofInotifyEvent) {
|
||||||
var (
|
// Point to the event in the buffer.
|
||||||
// Point "raw" to the event in the buffer
|
inEvent := (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))
|
||||||
raw = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))
|
|
||||||
mask = uint32(raw.Mask)
|
|
||||||
nameLen = uint32(raw.Len)
|
|
||||||
// Move to the next event in the buffer
|
|
||||||
next = func() { offset += unix.SizeofInotifyEvent + nameLen }
|
|
||||||
)
|
|
||||||
|
|
||||||
if mask&unix.IN_Q_OVERFLOW != 0 {
|
if inEvent.Mask&unix.IN_Q_OVERFLOW != 0 {
|
||||||
if !w.sendError(ErrEventOverflow) {
|
if !w.sendError(ErrEventOverflow) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the event happened to the watched directory or the watched
|
ev, ok := w.handleEvent(inEvent, &buf, offset)
|
||||||
/// file, the kernel doesn't append the filename to the event, but
|
if !ok {
|
||||||
/// we would like to always fill the the "Name" field with a valid
|
return
|
||||||
/// filename. We retrieve the path of the watch from the "paths"
|
|
||||||
/// map.
|
|
||||||
watch := w.watches.byWd(uint32(raw.Wd))
|
|
||||||
/// Can be nil if Remove() was called in another goroutine for this
|
|
||||||
/// path inbetween reading the events from the kernel and reading
|
|
||||||
/// the internal state. Not much we can do about it, so just skip.
|
|
||||||
/// See #616.
|
|
||||||
if watch == nil {
|
|
||||||
next()
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
name := watch.path
|
|
||||||
if nameLen > 0 {
|
|
||||||
/// Point "bytes" at the first byte of the filename
|
|
||||||
bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
|
|
||||||
/// The filename is padded with NULL bytes. TrimRight() gets rid of those.
|
|
||||||
name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
|
|
||||||
}
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
internal.Debug(name, raw.Mask, raw.Cookie)
|
|
||||||
}
|
|
||||||
|
|
||||||
if mask&unix.IN_IGNORED != 0 { //&& event.Op != 0
|
|
||||||
next()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// inotify will automatically remove the watch on deletes; just need
|
|
||||||
// to clean our state here.
|
|
||||||
if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
|
|
||||||
w.watches.remove(watch.wd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We can't really update the state when a watched path is moved;
|
|
||||||
// only IN_MOVE_SELF is sent and not IN_MOVED_{FROM,TO}. So remove
|
|
||||||
// the watch.
|
|
||||||
if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF {
|
|
||||||
if watch.recurse {
|
|
||||||
next() // Do nothing
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err := w.remove(watch.path)
|
|
||||||
if err != nil && !errors.Is(err, ErrNonExistentWatch) {
|
|
||||||
if !w.sendError(err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Skip if we're watching both this path and the parent; the parent
|
|
||||||
/// will already send a delete so no need to do it twice.
|
|
||||||
if mask&unix.IN_DELETE_SELF != 0 {
|
|
||||||
if _, ok := w.watches.path[filepath.Dir(watch.path)]; ok {
|
|
||||||
next()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ev := w.newEvent(name, mask, raw.Cookie)
|
|
||||||
// Need to update watch path for recurse.
|
|
||||||
if watch.recurse {
|
|
||||||
isDir := mask&unix.IN_ISDIR == unix.IN_ISDIR
|
|
||||||
/// New directory created: set up watch on it.
|
|
||||||
if isDir && ev.Has(Create) {
|
|
||||||
err := w.register(ev.Name, watch.flags, true)
|
|
||||||
if !w.sendError(err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// This was a directory rename, so we need to update all
|
|
||||||
// the children.
|
|
||||||
//
|
|
||||||
// TODO: this is of course pretty slow; we should use a
|
|
||||||
// better data structure for storing all of this, e.g. store
|
|
||||||
// children in the watch. I have some code for this in my
|
|
||||||
// kqueue refactor we can use in the future. For now I'm
|
|
||||||
// okay with this as it's not publicly available.
|
|
||||||
// Correctness first, performance second.
|
|
||||||
if ev.renamedFrom != "" {
|
|
||||||
w.watches.mu.Lock()
|
|
||||||
for k, ww := range w.watches.wd {
|
|
||||||
if k == watch.wd || ww.path == ev.Name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(ww.path, ev.renamedFrom) {
|
|
||||||
ww.path = strings.Replace(ww.path, ev.renamedFrom, ev.Name, 1)
|
|
||||||
w.watches.wd[k] = ww
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.watches.mu.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Send the events that are not ignored on the events channel
|
|
||||||
if !w.sendEvent(ev) {
|
if !w.sendEvent(ev) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
next()
|
|
||||||
|
// Move to the next event in the buffer
|
||||||
|
offset += unix.SizeofInotifyEvent + inEvent.Len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *inotify) handleEvent(inEvent *unix.InotifyEvent, buf *[65536]byte, offset uint32) (Event, bool) {
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
|
|
||||||
|
/// If the event happened to the watched directory or the watched file, the
|
||||||
|
/// kernel doesn't append the filename to the event, but we would like to
|
||||||
|
/// always fill the the "Name" field with a valid filename. We retrieve the
|
||||||
|
/// path of the watch from the "paths" map.
|
||||||
|
///
|
||||||
|
/// Can be nil if Remove() was called in another goroutine for this path
|
||||||
|
/// inbetween reading the events from the kernel and reading the internal
|
||||||
|
/// state. Not much we can do about it, so just skip. See #616.
|
||||||
|
watch := w.watches.byWd(uint32(inEvent.Wd))
|
||||||
|
if watch == nil {
|
||||||
|
return Event{}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
name = watch.path
|
||||||
|
nameLen = uint32(inEvent.Len)
|
||||||
|
)
|
||||||
|
if nameLen > 0 {
|
||||||
|
/// Point "bytes" at the first byte of the filename
|
||||||
|
bb := *buf
|
||||||
|
bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&bb[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
|
||||||
|
/// The filename is padded with NULL bytes. TrimRight() gets rid of those.
|
||||||
|
name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\x00")
|
||||||
|
}
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
internal.Debug(name, inEvent.Mask, inEvent.Cookie)
|
||||||
|
}
|
||||||
|
|
||||||
|
if inEvent.Mask&unix.IN_IGNORED != 0 || inEvent.Mask&unix.IN_UNMOUNT != 0 {
|
||||||
|
w.watches.remove(watch)
|
||||||
|
return Event{}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// inotify will automatically remove the watch on deletes; just need
|
||||||
|
// to clean our state here.
|
||||||
|
if inEvent.Mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
|
||||||
|
w.watches.remove(watch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can't really update the state when a watched path is moved; only
|
||||||
|
// IN_MOVE_SELF is sent and not IN_MOVED_{FROM,TO}. So remove the watch.
|
||||||
|
if inEvent.Mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF {
|
||||||
|
if watch.recurse { // Do nothing
|
||||||
|
return Event{}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
err := w.remove(watch.path)
|
||||||
|
if err != nil && !errors.Is(err, ErrNonExistentWatch) {
|
||||||
|
if !w.sendError(err) {
|
||||||
|
return Event{}, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Skip if we're watching both this path and the parent; the parent will
|
||||||
|
/// already send a delete so no need to do it twice.
|
||||||
|
if inEvent.Mask&unix.IN_DELETE_SELF != 0 {
|
||||||
|
_, ok := w.watches.path[filepath.Dir(watch.path)]
|
||||||
|
if ok {
|
||||||
|
return Event{}, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ev := w.newEvent(name, inEvent.Mask, inEvent.Cookie)
|
||||||
|
// Need to update watch path for recurse.
|
||||||
|
if watch.recurse {
|
||||||
|
isDir := inEvent.Mask&unix.IN_ISDIR == unix.IN_ISDIR
|
||||||
|
/// New directory created: set up watch on it.
|
||||||
|
if isDir && ev.Has(Create) {
|
||||||
|
err := w.register(ev.Name, watch.flags, true)
|
||||||
|
if !w.sendError(err) {
|
||||||
|
return Event{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// This was a directory rename, so we need to update all the
|
||||||
|
// children.
|
||||||
|
//
|
||||||
|
// TODO: this is of course pretty slow; we should use a better data
|
||||||
|
// structure for storing all of this, e.g. store children in the
|
||||||
|
// watch. I have some code for this in my kqueue refactor we can use
|
||||||
|
// in the future. For now I'm okay with this as it's not publicly
|
||||||
|
// available. Correctness first, performance second.
|
||||||
|
if ev.renamedFrom != "" {
|
||||||
|
for k, ww := range w.watches.wd {
|
||||||
|
if k == watch.wd || ww.path == ev.Name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(ww.path, ev.renamedFrom) {
|
||||||
|
ww.path = strings.Replace(ww.path, ev.renamedFrom, ev.Name, 1)
|
||||||
|
w.watches.wd[k] = ww
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ev, true
|
||||||
|
}
|
||||||
|
|
||||||
func (w *inotify) isRecursive(path string) bool {
|
func (w *inotify) isRecursive(path string) bool {
|
||||||
ww := w.watches.byPath(path)
|
ww := w.watches.byPath(path)
|
||||||
if ww == nil { // path could be a file, so also check the Dir.
|
if ww == nil { // path could be a file, so also check the Dir.
|
||||||
|
|
@ -650,8 +575,8 @@ func (w *inotify) xSupports(op Op) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *inotify) state() {
|
func (w *inotify) state() {
|
||||||
w.watches.mu.Lock()
|
w.mu.Lock()
|
||||||
defer w.watches.mu.Unlock()
|
defer w.mu.Unlock()
|
||||||
for wd, ww := range w.watches.wd {
|
for wd, ww := range w.watches.wd {
|
||||||
fmt.Fprintf(os.Stderr, "%4d: recurse=%t %q\n", wd, ww.recurse, ww.path)
|
fmt.Fprintf(os.Stderr, "%4d: recurse=%t %q\n", wd, ww.recurse, ww.path)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
112
vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
generated
vendored
112
vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
generated
vendored
|
|
@ -16,14 +16,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type kqueue struct {
|
type kqueue struct {
|
||||||
|
*shared
|
||||||
Events chan Event
|
Events chan Event
|
||||||
Errors chan error
|
Errors chan error
|
||||||
|
|
||||||
kq int // File descriptor (as returned by the kqueue() syscall).
|
kq int // File descriptor (as returned by the kqueue() syscall).
|
||||||
closepipe [2]int // Pipe used for closing kq.
|
closepipe [2]int // Pipe used for closing kq.
|
||||||
watches *watches
|
watches *watches
|
||||||
done chan struct{}
|
|
||||||
doneMu sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
|
@ -132,14 +131,18 @@ func (w *watches) byPath(path string) (watch, bool) {
|
||||||
return info, ok
|
return info, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *watches) updateDirFlags(path string, flags uint32) {
|
func (w *watches) updateDirFlags(path string, flags uint32) bool {
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
defer w.mu.Unlock()
|
defer w.mu.Unlock()
|
||||||
|
|
||||||
fd := w.path[path]
|
fd, ok := w.path[path]
|
||||||
|
if !ok { // Already deleted: don't re-set it here.
|
||||||
|
return false
|
||||||
|
}
|
||||||
info := w.wd[fd]
|
info := w.wd[fd]
|
||||||
info.dirFlags = flags
|
info.dirFlags = flags
|
||||||
w.wd[fd] = info
|
w.wd[fd] = info
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *watches) remove(fd int, path string) bool {
|
func (w *watches) remove(fd int, path string) bool {
|
||||||
|
|
@ -179,22 +182,20 @@ func (w *watches) seenBefore(path string) bool {
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
var defaultBufferSize = 0
|
||||||
return newBufferedBackend(0, ev, errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
|
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||||
kq, closepipe, err := newKqueue()
|
kq, closepipe, err := newKqueue()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
w := &kqueue{
|
w := &kqueue{
|
||||||
|
shared: newShared(ev, errs),
|
||||||
Events: ev,
|
Events: ev,
|
||||||
Errors: errs,
|
Errors: errs,
|
||||||
kq: kq,
|
kq: kq,
|
||||||
closepipe: closepipe,
|
closepipe: closepipe,
|
||||||
done: make(chan struct{}),
|
|
||||||
watches: newWatches(),
|
watches: newWatches(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,7 +211,7 @@ func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error
|
||||||
// all.
|
// all.
|
||||||
func newKqueue() (kq int, closepipe [2]int, err error) {
|
func newKqueue() (kq int, closepipe [2]int, err error) {
|
||||||
kq, err = unix.Kqueue()
|
kq, err = unix.Kqueue()
|
||||||
if kq == -1 {
|
if err != nil {
|
||||||
return kq, closepipe, err
|
return kq, closepipe, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -239,54 +240,17 @@ func newKqueue() (kq int, closepipe [2]int, err error) {
|
||||||
return kq, closepipe, nil
|
return kq, closepipe, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the event was sent, or false if watcher is closed.
|
|
||||||
func (w *kqueue) sendEvent(e Event) bool {
|
|
||||||
select {
|
|
||||||
case <-w.done:
|
|
||||||
return false
|
|
||||||
case w.Events <- e:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if the error was sent, or false if watcher is closed.
|
|
||||||
func (w *kqueue) sendError(err error) bool {
|
|
||||||
if err == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-w.done:
|
|
||||||
return false
|
|
||||||
case w.Errors <- err:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *kqueue) isClosed() bool {
|
|
||||||
select {
|
|
||||||
case <-w.done:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *kqueue) Close() error {
|
func (w *kqueue) Close() error {
|
||||||
w.doneMu.Lock()
|
if w.shared.close() {
|
||||||
if w.isClosed() {
|
|
||||||
w.doneMu.Unlock()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
close(w.done)
|
|
||||||
w.doneMu.Unlock()
|
|
||||||
|
|
||||||
pathsToRemove := w.watches.listPaths(false)
|
pathsToRemove := w.watches.listPaths(false)
|
||||||
for _, name := range pathsToRemove {
|
for _, name := range pathsToRemove {
|
||||||
w.Remove(name)
|
w.Remove(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send "quit" message to the reader goroutine.
|
unix.Close(w.closepipe[1]) // Send "quit" message to readEvents
|
||||||
unix.Close(w.closepipe[1])
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,7 +267,7 @@ func (w *kqueue) AddWith(name string, opts ...addOpt) error {
|
||||||
return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
|
return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := w.addWatch(name, noteAllEvents)
|
_, err := w.addWatch(name, noteAllEvents, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -366,7 +330,7 @@ const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | un
|
||||||
// described in kevent(2).
|
// described in kevent(2).
|
||||||
//
|
//
|
||||||
// Returns the real path to the file which was added, with symlinks resolved.
|
// Returns the real path to the file which was added, with symlinks resolved.
|
||||||
func (w *kqueue) addWatch(name string, flags uint32) (string, error) {
|
func (w *kqueue) addWatch(name string, flags uint32, listDir bool) (string, error) {
|
||||||
if w.isClosed() {
|
if w.isClosed() {
|
||||||
return "", ErrClosed
|
return "", ErrClosed
|
||||||
}
|
}
|
||||||
|
|
@ -385,15 +349,15 @@ func (w *kqueue) addWatch(name string, flags uint32) (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Follow symlinks.
|
// Follow symlinks, but only for paths added with Add(), and not paths
|
||||||
if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
|
// we're adding from internalWatch from a listdir.
|
||||||
|
if !listDir && fi.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||||
link, err := os.Readlink(name)
|
link, err := os.Readlink(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Return nil because Linux can add unresolvable symlinks to the
|
return "", err
|
||||||
// watch list without problems, so maintain consistency with
|
}
|
||||||
// that. There will be no file events for broken symlinks.
|
if !filepath.IsAbs(link) {
|
||||||
// TODO: more specific check; returns os.PathError; ENOENT?
|
link = filepath.Join(filepath.Dir(name), link)
|
||||||
return "", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, alreadyWatching = w.watches.byPath(link)
|
_, alreadyWatching = w.watches.byPath(link)
|
||||||
|
|
@ -408,7 +372,7 @@ func (w *kqueue) addWatch(name string, flags uint32) (string, error) {
|
||||||
name = link
|
name = link
|
||||||
fi, err = os.Lstat(name)
|
fi, err = os.Lstat(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -422,7 +386,6 @@ func (w *kqueue) addWatch(name string, flags uint32) (string, error) {
|
||||||
if errors.Is(err, unix.EINTR) {
|
if errors.Is(err, unix.EINTR) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -444,10 +407,16 @@ func (w *kqueue) addWatch(name string, flags uint32) (string, error) {
|
||||||
if info.isDir {
|
if info.isDir {
|
||||||
watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE &&
|
watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE &&
|
||||||
(!alreadyWatching || (info.dirFlags&unix.NOTE_WRITE) != unix.NOTE_WRITE)
|
(!alreadyWatching || (info.dirFlags&unix.NOTE_WRITE) != unix.NOTE_WRITE)
|
||||||
w.watches.updateDirFlags(name, flags)
|
if !w.watches.updateDirFlags(name, flags) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
if watchDir {
|
if watchDir {
|
||||||
if err := w.watchDirectoryFiles(name); err != nil {
|
d := name
|
||||||
|
if info.linkName != "" {
|
||||||
|
d = info.linkName
|
||||||
|
}
|
||||||
|
if err := w.watchDirectoryFiles(d); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -644,19 +613,22 @@ func (w *kqueue) dirChange(dir string) error {
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("fsnotify.dirChange: %w", err)
|
return fmt.Errorf("fsnotify.dirChange %q: %w", dir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
fi, err := f.Info()
|
fi, err := f.Info()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return fmt.Errorf("fsnotify.dirChange: %w", err)
|
return fmt.Errorf("fsnotify.dirChange: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = w.sendCreateIfNew(filepath.Join(dir, fi.Name()), fi)
|
err = w.sendCreateIfNew(filepath.Join(dir, fi.Name()), fi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't need to send an error if this file isn't readable.
|
// Don't need to send an error if this file isn't readable.
|
||||||
if errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM) {
|
if errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM) || errors.Is(err, os.ErrNotExist) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("fsnotify.dirChange: %w", err)
|
return fmt.Errorf("fsnotify.dirChange: %w", err)
|
||||||
|
|
@ -688,11 +660,11 @@ func (w *kqueue) internalWatch(name string, fi os.FileInfo) (string, error) {
|
||||||
// mimic Linux providing delete events for subdirectories, but preserve
|
// mimic Linux providing delete events for subdirectories, but preserve
|
||||||
// the flags used if currently watching subdirectory
|
// the flags used if currently watching subdirectory
|
||||||
info, _ := w.watches.byPath(name)
|
info, _ := w.watches.byPath(name)
|
||||||
return w.addWatch(name, info.dirFlags|unix.NOTE_DELETE|unix.NOTE_RENAME)
|
return w.addWatch(name, info.dirFlags|unix.NOTE_DELETE|unix.NOTE_RENAME, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// watch file to mimic Linux inotify
|
// Watch file to mimic Linux inotify.
|
||||||
return w.addWatch(name, noteAllEvents)
|
return w.addWatch(name, noteAllEvents, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register events with the queue.
|
// Register events with the queue.
|
||||||
|
|
@ -722,9 +694,9 @@ func (w *kqueue) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *kqueue) xSupports(op Op) bool {
|
func (w *kqueue) xSupports(op Op) bool {
|
||||||
if runtime.GOOS == "freebsd" {
|
//if runtime.GOOS == "freebsd" {
|
||||||
//return true // Supports everything.
|
// return true // Supports everything.
|
||||||
}
|
//}
|
||||||
if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
|
if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
|
||||||
op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
|
op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
5
vendor/github.com/fsnotify/fsnotify/backend_other.go
generated
vendored
5
vendor/github.com/fsnotify/fsnotify/backend_other.go
generated
vendored
|
|
@ -9,12 +9,11 @@ type other struct {
|
||||||
Errors chan error
|
Errors chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var defaultBufferSize = 0
|
||||||
|
|
||||||
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||||
return nil, errors.New("fsnotify not supported on the current platform")
|
return nil, errors.New("fsnotify not supported on the current platform")
|
||||||
}
|
}
|
||||||
func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
|
|
||||||
return newBackend(ev, errs)
|
|
||||||
}
|
|
||||||
func (w *other) Close() error { return nil }
|
func (w *other) Close() error { return nil }
|
||||||
func (w *other) WatchList() []string { return nil }
|
func (w *other) WatchList() []string { return nil }
|
||||||
func (w *other) Add(name string) error { return nil }
|
func (w *other) Add(name string) error { return nil }
|
||||||
|
|
|
||||||
24
vendor/github.com/fsnotify/fsnotify/backend_windows.go
generated
vendored
24
vendor/github.com/fsnotify/fsnotify/backend_windows.go
generated
vendored
|
|
@ -28,18 +28,16 @@ type readDirChangesW struct {
|
||||||
|
|
||||||
port windows.Handle // Handle to completion port
|
port windows.Handle // Handle to completion port
|
||||||
input chan *input // Inputs to the reader are sent on this channel
|
input chan *input // Inputs to the reader are sent on this channel
|
||||||
quit chan chan<- error
|
done chan chan<- error
|
||||||
|
|
||||||
mu sync.Mutex // Protects access to watches, closed
|
mu sync.Mutex // Protects access to watches, closed
|
||||||
watches watchMap // Map of watches (key: i-number)
|
watches watchMap // Map of watches (key: i-number)
|
||||||
closed bool // Set to true when Close() is first called
|
closed bool // Set to true when Close() is first called
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
var defaultBufferSize = 50
|
||||||
return newBufferedBackend(50, ev, errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
|
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||||
port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0)
|
port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, os.NewSyscallError("CreateIoCompletionPort", err)
|
return nil, os.NewSyscallError("CreateIoCompletionPort", err)
|
||||||
|
|
@ -50,7 +48,7 @@ func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error
|
||||||
port: port,
|
port: port,
|
||||||
watches: make(watchMap),
|
watches: make(watchMap),
|
||||||
input: make(chan *input, 1),
|
input: make(chan *input, 1),
|
||||||
quit: make(chan chan<- error, 1),
|
done: make(chan chan<- error, 1),
|
||||||
}
|
}
|
||||||
go w.readEvents()
|
go w.readEvents()
|
||||||
return w, nil
|
return w, nil
|
||||||
|
|
@ -70,8 +68,8 @@ func (w *readDirChangesW) sendEvent(name, renamedFrom string, mask uint64) bool
|
||||||
event := w.newEvent(name, uint32(mask))
|
event := w.newEvent(name, uint32(mask))
|
||||||
event.renamedFrom = renamedFrom
|
event.renamedFrom = renamedFrom
|
||||||
select {
|
select {
|
||||||
case ch := <-w.quit:
|
case ch := <-w.done:
|
||||||
w.quit <- ch
|
w.done <- ch
|
||||||
case w.Events <- event:
|
case w.Events <- event:
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
@ -83,10 +81,10 @@ func (w *readDirChangesW) sendError(err error) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
|
case <-w.done:
|
||||||
|
return false
|
||||||
case w.Errors <- err:
|
case w.Errors <- err:
|
||||||
return true
|
return true
|
||||||
case <-w.quit:
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,9 +97,9 @@ func (w *readDirChangesW) Close() error {
|
||||||
w.closed = true
|
w.closed = true
|
||||||
w.mu.Unlock()
|
w.mu.Unlock()
|
||||||
|
|
||||||
// Send "quit" message to the reader goroutine
|
// Send "done" message to the reader goroutine
|
||||||
ch := make(chan error)
|
ch := make(chan error)
|
||||||
w.quit <- ch
|
w.done <- ch
|
||||||
if err := w.wakeupReader(); err != nil {
|
if err := w.wakeupReader(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -495,7 +493,7 @@ func (w *readDirChangesW) readEvents() {
|
||||||
watch := (*watch)(unsafe.Pointer(ov))
|
watch := (*watch)(unsafe.Pointer(ov))
|
||||||
if watch == nil {
|
if watch == nil {
|
||||||
select {
|
select {
|
||||||
case ch := <-w.quit:
|
case ch := <-w.done:
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
var indexes []indexMap
|
var indexes []indexMap
|
||||||
for _, index := range w.watches {
|
for _, index := range w.watches {
|
||||||
|
|
|
||||||
10
vendor/github.com/fsnotify/fsnotify/fsnotify.go
generated
vendored
10
vendor/github.com/fsnotify/fsnotify/fsnotify.go
generated
vendored
|
|
@ -244,12 +244,13 @@ var (
|
||||||
|
|
||||||
// ErrUnsupported is returned by AddWith() when WithOps() specified an
|
// ErrUnsupported is returned by AddWith() when WithOps() specified an
|
||||||
// Unportable event that's not supported on this platform.
|
// Unportable event that's not supported on this platform.
|
||||||
|
//lint:ignore ST1012 not relevant
|
||||||
xErrUnsupported = errors.New("fsnotify: not supported with this backend")
|
xErrUnsupported = errors.New("fsnotify: not supported with this backend")
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewWatcher creates a new Watcher.
|
// NewWatcher creates a new Watcher.
|
||||||
func NewWatcher() (*Watcher, error) {
|
func NewWatcher() (*Watcher, error) {
|
||||||
ev, errs := make(chan Event), make(chan error)
|
ev, errs := make(chan Event, defaultBufferSize), make(chan error)
|
||||||
b, err := newBackend(ev, errs)
|
b, err := newBackend(ev, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -266,8 +267,8 @@ func NewWatcher() (*Watcher, error) {
|
||||||
// cases, and whenever possible you will be better off increasing the kernel
|
// cases, and whenever possible you will be better off increasing the kernel
|
||||||
// buffers instead of adding a large userspace buffer.
|
// buffers instead of adding a large userspace buffer.
|
||||||
func NewBufferedWatcher(sz uint) (*Watcher, error) {
|
func NewBufferedWatcher(sz uint) (*Watcher, error) {
|
||||||
ev, errs := make(chan Event), make(chan error)
|
ev, errs := make(chan Event, sz), make(chan error)
|
||||||
b, err := newBufferedBackend(sz, ev, errs)
|
b, err := newBackend(ev, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -337,7 +338,8 @@ func (w *Watcher) Close() error { return w.b.Close() }
|
||||||
// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
|
// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
|
||||||
// yet removed).
|
// yet removed).
|
||||||
//
|
//
|
||||||
// Returns nil if [Watcher.Close] was called.
|
// The order is undefined, and may differ per call. Returns nil if
|
||||||
|
// [Watcher.Close] was called.
|
||||||
func (w *Watcher) WatchList() []string { return w.b.WatchList() }
|
func (w *Watcher) WatchList() []string { return w.b.WatchList() }
|
||||||
|
|
||||||
// Supports reports if all the listed operations are supported by this platform.
|
// Supports reports if all the listed operations are supported by this platform.
|
||||||
|
|
|
||||||
6
vendor/github.com/fsnotify/fsnotify/internal/darwin.go
generated
vendored
6
vendor/github.com/fsnotify/fsnotify/internal/darwin.go
generated
vendored
|
|
@ -9,14 +9,14 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
SyscallEACCES = syscall.EACCES
|
ErrSyscallEACCES = syscall.EACCES
|
||||||
UnixEACCES = unix.EACCES
|
ErrUnixEACCES = unix.EACCES
|
||||||
)
|
)
|
||||||
|
|
||||||
var maxfiles uint64
|
var maxfiles uint64
|
||||||
|
|
||||||
// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
|
|
||||||
func SetRlimit() {
|
func SetRlimit() {
|
||||||
|
// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
|
||||||
var l syscall.Rlimit
|
var l syscall.Rlimit
|
||||||
err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
|
err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
|
||||||
if err == nil && l.Cur != l.Max {
|
if err == nil && l.Cur != l.Max {
|
||||||
|
|
|
||||||
4
vendor/github.com/fsnotify/fsnotify/internal/freebsd.go
generated
vendored
4
vendor/github.com/fsnotify/fsnotify/internal/freebsd.go
generated
vendored
|
|
@ -9,8 +9,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
SyscallEACCES = syscall.EACCES
|
ErrSyscallEACCES = syscall.EACCES
|
||||||
UnixEACCES = unix.EACCES
|
ErrUnixEACCES = unix.EACCES
|
||||||
)
|
)
|
||||||
|
|
||||||
var maxfiles uint64
|
var maxfiles uint64
|
||||||
|
|
|
||||||
6
vendor/github.com/fsnotify/fsnotify/internal/unix.go
generated
vendored
6
vendor/github.com/fsnotify/fsnotify/internal/unix.go
generated
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
//go:build !windows && !darwin && !freebsd
|
//go:build !windows && !darwin && !freebsd && !plan9
|
||||||
|
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
|
|
@ -9,8 +9,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
SyscallEACCES = syscall.EACCES
|
ErrSyscallEACCES = syscall.EACCES
|
||||||
UnixEACCES = unix.EACCES
|
ErrUnixEACCES = unix.EACCES
|
||||||
)
|
)
|
||||||
|
|
||||||
var maxfiles uint64
|
var maxfiles uint64
|
||||||
|
|
|
||||||
4
vendor/github.com/fsnotify/fsnotify/internal/windows.go
generated
vendored
4
vendor/github.com/fsnotify/fsnotify/internal/windows.go
generated
vendored
|
|
@ -10,8 +10,8 @@ import (
|
||||||
|
|
||||||
// Just a dummy.
|
// Just a dummy.
|
||||||
var (
|
var (
|
||||||
SyscallEACCES = errors.New("dummy")
|
ErrSyscallEACCES = errors.New("dummy")
|
||||||
UnixEACCES = errors.New("dummy")
|
ErrUnixEACCES = errors.New("dummy")
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetRlimit() {}
|
func SetRlimit() {}
|
||||||
|
|
|
||||||
64
vendor/github.com/fsnotify/fsnotify/shared.go
generated
vendored
Normal file
64
vendor/github.com/fsnotify/fsnotify/shared.go
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
package fsnotify
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
type shared struct {
|
||||||
|
Events chan Event
|
||||||
|
Errors chan error
|
||||||
|
done chan struct{}
|
||||||
|
mu sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func newShared(ev chan Event, errs chan error) *shared {
|
||||||
|
return &shared{
|
||||||
|
Events: ev,
|
||||||
|
Errors: errs,
|
||||||
|
done: make(chan struct{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the event was sent, or false if watcher is closed.
|
||||||
|
func (w *shared) sendEvent(e Event) bool {
|
||||||
|
if e.Op == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-w.done:
|
||||||
|
return false
|
||||||
|
case w.Events <- e:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the error was sent, or false if watcher is closed.
|
||||||
|
func (w *shared) sendError(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-w.done:
|
||||||
|
return false
|
||||||
|
case w.Errors <- err:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *shared) isClosed() bool {
|
||||||
|
select {
|
||||||
|
case <-w.done:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark as closed; returns true if it was already closed.
|
||||||
|
func (w *shared) close() bool {
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
|
if w.isClosed() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
close(w.done)
|
||||||
|
return false
|
||||||
|
}
|
||||||
3
vendor/github.com/fsnotify/fsnotify/staticcheck.conf
generated
vendored
Normal file
3
vendor/github.com/fsnotify/fsnotify/staticcheck.conf
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
checks = ['all',
|
||||||
|
'-U1000', # Don't complain about unused functions.
|
||||||
|
]
|
||||||
3
vendor/github.com/go-viper/mapstructure/v2/.editorconfig
generated
vendored
3
vendor/github.com/go-viper/mapstructure/v2/.editorconfig
generated
vendored
|
|
@ -16,3 +16,6 @@ indent_style = tab
|
||||||
|
|
||||||
[*.nix]
|
[*.nix]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
[.golangci.yaml]
|
||||||
|
indent_size = 2
|
||||||
|
|
|
||||||
55
vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
generated
vendored
55
vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
generated
vendored
|
|
@ -1,23 +1,48 @@
|
||||||
run:
|
version: "2"
|
||||||
timeout: 5m
|
|
||||||
|
|
||||||
linters-settings:
|
run:
|
||||||
gci:
|
timeout: 10m
|
||||||
sections:
|
|
||||||
- standard
|
|
||||||
- default
|
|
||||||
- prefix(github.com/go-viper/mapstructure)
|
|
||||||
golint:
|
|
||||||
min-confidence: 0
|
|
||||||
goimports:
|
|
||||||
local-prefixes: github.com/go-viper/maptstructure
|
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
disable-all: true
|
enable:
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
# - misspell
|
||||||
|
- nolintlint
|
||||||
|
# - revive
|
||||||
|
|
||||||
|
disable:
|
||||||
|
- errcheck
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
|
||||||
|
settings:
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
nolintlint:
|
||||||
|
allow-unused: false # report any unused nolint directives
|
||||||
|
require-specific: false # don't require nolint directives to be specific about which linter is being skipped
|
||||||
|
|
||||||
|
formatters:
|
||||||
enable:
|
enable:
|
||||||
- gci
|
- gci
|
||||||
- gofmt
|
- gofmt
|
||||||
- gofumpt
|
- gofumpt
|
||||||
- goimports
|
- goimports
|
||||||
- staticcheck
|
# - golines
|
||||||
# - stylecheck
|
|
||||||
|
settings:
|
||||||
|
gci:
|
||||||
|
sections:
|
||||||
|
- standard
|
||||||
|
- default
|
||||||
|
- localmodule
|
||||||
|
gofmt:
|
||||||
|
simplify: true
|
||||||
|
rewrite-rules:
|
||||||
|
- pattern: interface{}
|
||||||
|
replacement: any
|
||||||
|
|
||||||
|
exclusions:
|
||||||
|
paths:
|
||||||
|
- internal/
|
||||||
|
|
|
||||||
7
vendor/github.com/go-viper/mapstructure/v2/README.md
generated
vendored
7
vendor/github.com/go-viper/mapstructure/v2/README.md
generated
vendored
|
|
@ -1,8 +1,9 @@
|
||||||
# mapstructure
|
# mapstructure
|
||||||
|
|
||||||
[](https://github.com/go-viper/mapstructure/actions?query=workflow%3ACI)
|
[](https://github.com/go-viper/mapstructure/actions/workflows/ci.yaml)
|
||||||
[](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2)
|
[](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2)
|
||||||

|

|
||||||
|
[](https://deps.dev/go/github.com%252Fgo-viper%252Fmapstructure%252Fv2)
|
||||||
|
|
||||||
mapstructure is a Go library for decoding generic map values to structures
|
mapstructure is a Go library for decoding generic map values to structures
|
||||||
and vice versa, while providing helpful error handling.
|
and vice versa, while providing helpful error handling.
|
||||||
|
|
@ -29,7 +30,7 @@ The API is the same, so you don't need to change anything else.
|
||||||
Here is a script that can help you with the migration:
|
Here is a script that can help you with the migration:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sed -i 's/github.com\/mitchellh\/mapstructure/github.com\/go-viper\/mapstructure\/v2/g' $(find . -type f -name '*.go')
|
sed -i 's|github.com/mitchellh/mapstructure|github.com/go-viper/mapstructure/v2|g' $(find . -type f -name '*.go')
|
||||||
```
|
```
|
||||||
|
|
||||||
If you need more time to migrate your code, that is absolutely fine.
|
If you need more time to migrate your code, that is absolutely fine.
|
||||||
|
|
|
||||||
234
vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
generated
vendored
234
vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
generated
vendored
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
|
// typedDecodeHook takes a raw DecodeHookFunc (an any) and turns
|
||||||
// it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
|
// it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
|
||||||
func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
|
func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
|
||||||
// Create variables here so we can reference them with the reflect pkg
|
// Create variables here so we can reference them with the reflect pkg
|
||||||
|
|
@ -23,7 +23,7 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
|
||||||
|
|
||||||
// Fill in the variables into this interface and the rest is done
|
// Fill in the variables into this interface and the rest is done
|
||||||
// automatically using the reflect package.
|
// automatically using the reflect package.
|
||||||
potential := []interface{}{f1, f2, f3}
|
potential := []any{f1, f2, f3}
|
||||||
|
|
||||||
v := reflect.ValueOf(h)
|
v := reflect.ValueOf(h)
|
||||||
vt := v.Type()
|
vt := v.Type()
|
||||||
|
|
@ -37,25 +37,25 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// cachedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
|
// cachedDecodeHook takes a raw DecodeHookFunc (an any) and turns
|
||||||
// it into a closure to be used directly
|
// it into a closure to be used directly
|
||||||
// if the type fails to convert we return a closure always erroring to keep the previous behaviour
|
// if the type fails to convert we return a closure always erroring to keep the previous behaviour
|
||||||
func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (interface{}, error) {
|
func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (any, error) {
|
||||||
switch f := typedDecodeHook(raw).(type) {
|
switch f := typedDecodeHook(raw).(type) {
|
||||||
case DecodeHookFuncType:
|
case DecodeHookFuncType:
|
||||||
return func(from reflect.Value, to reflect.Value) (interface{}, error) {
|
return func(from reflect.Value, to reflect.Value) (any, error) {
|
||||||
return f(from.Type(), to.Type(), from.Interface())
|
return f(from.Type(), to.Type(), from.Interface())
|
||||||
}
|
}
|
||||||
case DecodeHookFuncKind:
|
case DecodeHookFuncKind:
|
||||||
return func(from reflect.Value, to reflect.Value) (interface{}, error) {
|
return func(from reflect.Value, to reflect.Value) (any, error) {
|
||||||
return f(from.Kind(), to.Kind(), from.Interface())
|
return f(from.Kind(), to.Kind(), from.Interface())
|
||||||
}
|
}
|
||||||
case DecodeHookFuncValue:
|
case DecodeHookFuncValue:
|
||||||
return func(from reflect.Value, to reflect.Value) (interface{}, error) {
|
return func(from reflect.Value, to reflect.Value) (any, error) {
|
||||||
return f(from, to)
|
return f(from, to)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return func(from reflect.Value, to reflect.Value) (interface{}, error) {
|
return func(from reflect.Value, to reflect.Value) (any, error) {
|
||||||
return nil, errors.New("invalid decode hook signature")
|
return nil, errors.New("invalid decode hook signature")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +67,7 @@ func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Va
|
||||||
func DecodeHookExec(
|
func DecodeHookExec(
|
||||||
raw DecodeHookFunc,
|
raw DecodeHookFunc,
|
||||||
from reflect.Value, to reflect.Value,
|
from reflect.Value, to reflect.Value,
|
||||||
) (interface{}, error) {
|
) (any, error) {
|
||||||
switch f := typedDecodeHook(raw).(type) {
|
switch f := typedDecodeHook(raw).(type) {
|
||||||
case DecodeHookFuncType:
|
case DecodeHookFuncType:
|
||||||
return f(from.Type(), to.Type(), from.Interface())
|
return f(from.Type(), to.Type(), from.Interface())
|
||||||
|
|
@ -86,11 +86,11 @@ func DecodeHookExec(
|
||||||
// The composed funcs are called in order, with the result of the
|
// The composed funcs are called in order, with the result of the
|
||||||
// previous transformation.
|
// previous transformation.
|
||||||
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
||||||
cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(fs))
|
cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(fs))
|
||||||
for _, f := range fs {
|
for _, f := range fs {
|
||||||
cached = append(cached, cachedDecodeHook(f))
|
cached = append(cached, cachedDecodeHook(f))
|
||||||
}
|
}
|
||||||
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
|
return func(f reflect.Value, t reflect.Value) (any, error) {
|
||||||
var err error
|
var err error
|
||||||
data := f.Interface()
|
data := f.Interface()
|
||||||
|
|
||||||
|
|
@ -100,7 +100,11 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
newFrom = reflect.ValueOf(data)
|
if v, ok := data.(reflect.Value); ok {
|
||||||
|
newFrom = v
|
||||||
|
} else {
|
||||||
|
newFrom = reflect.ValueOf(data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
|
|
@ -110,13 +114,13 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
||||||
// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
|
// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
|
||||||
// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
|
// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
|
||||||
func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
|
func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
|
||||||
cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(ff))
|
cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(ff))
|
||||||
for _, f := range ff {
|
for _, f := range ff {
|
||||||
cached = append(cached, cachedDecodeHook(f))
|
cached = append(cached, cachedDecodeHook(f))
|
||||||
}
|
}
|
||||||
return func(a, b reflect.Value) (interface{}, error) {
|
return func(a, b reflect.Value) (any, error) {
|
||||||
var allErrs string
|
var allErrs string
|
||||||
var out interface{}
|
var out any
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
for _, c := range cached {
|
for _, c := range cached {
|
||||||
|
|
@ -139,8 +143,8 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc {
|
||||||
return func(
|
return func(
|
||||||
f reflect.Type,
|
f reflect.Type,
|
||||||
t reflect.Type,
|
t reflect.Type,
|
||||||
data interface{},
|
data any,
|
||||||
) (interface{}, error) {
|
) (any, error) {
|
||||||
if f.Kind() != reflect.String {
|
if f.Kind() != reflect.String {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
@ -157,14 +161,37 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StringToWeakSliceHookFunc brings back the old (pre-v2) behavior of [StringToSliceHookFunc].
|
||||||
|
//
|
||||||
|
// As of mapstructure v2.0.0 [StringToSliceHookFunc] checks if the return type is a string slice.
|
||||||
|
// This function removes that check.
|
||||||
|
func StringToWeakSliceHookFunc(sep string) DecodeHookFunc {
|
||||||
|
return func(
|
||||||
|
f reflect.Type,
|
||||||
|
t reflect.Type,
|
||||||
|
data any,
|
||||||
|
) (any, error) {
|
||||||
|
if f.Kind() != reflect.String || t.Kind() != reflect.Slice {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
raw := data.(string)
|
||||||
|
if raw == "" {
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Split(raw, sep), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
|
// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to time.Duration.
|
// strings to time.Duration.
|
||||||
func StringToTimeDurationHookFunc() DecodeHookFunc {
|
func StringToTimeDurationHookFunc() DecodeHookFunc {
|
||||||
return func(
|
return func(
|
||||||
f reflect.Type,
|
f reflect.Type,
|
||||||
t reflect.Type,
|
t reflect.Type,
|
||||||
data interface{},
|
data any,
|
||||||
) (interface{}, error) {
|
) (any, error) {
|
||||||
if f.Kind() != reflect.String {
|
if f.Kind() != reflect.String {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
@ -173,7 +200,29 @@ func StringToTimeDurationHookFunc() DecodeHookFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
return time.ParseDuration(data.(string))
|
d, err := time.ParseDuration(data.(string))
|
||||||
|
|
||||||
|
return d, wrapTimeParseDurationError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToTimeLocationHookFunc returns a DecodeHookFunc that converts
|
||||||
|
// strings to *time.Location.
|
||||||
|
func StringToTimeLocationHookFunc() DecodeHookFunc {
|
||||||
|
return func(
|
||||||
|
f reflect.Type,
|
||||||
|
t reflect.Type,
|
||||||
|
data any,
|
||||||
|
) (any, error) {
|
||||||
|
if f.Kind() != reflect.String {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
if t != reflect.TypeOf(time.Local) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
d, err := time.LoadLocation(data.(string))
|
||||||
|
|
||||||
|
return d, wrapTimeParseLocationError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -183,8 +232,8 @@ func StringToURLHookFunc() DecodeHookFunc {
|
||||||
return func(
|
return func(
|
||||||
f reflect.Type,
|
f reflect.Type,
|
||||||
t reflect.Type,
|
t reflect.Type,
|
||||||
data interface{},
|
data any,
|
||||||
) (interface{}, error) {
|
) (any, error) {
|
||||||
if f.Kind() != reflect.String {
|
if f.Kind() != reflect.String {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
@ -193,7 +242,9 @@ func StringToURLHookFunc() DecodeHookFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
return url.Parse(data.(string))
|
u, err := url.Parse(data.(string))
|
||||||
|
|
||||||
|
return u, wrapUrlError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,8 +254,8 @@ func StringToIPHookFunc() DecodeHookFunc {
|
||||||
return func(
|
return func(
|
||||||
f reflect.Type,
|
f reflect.Type,
|
||||||
t reflect.Type,
|
t reflect.Type,
|
||||||
data interface{},
|
data any,
|
||||||
) (interface{}, error) {
|
) (any, error) {
|
||||||
if f.Kind() != reflect.String {
|
if f.Kind() != reflect.String {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
@ -215,7 +266,7 @@ func StringToIPHookFunc() DecodeHookFunc {
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
ip := net.ParseIP(data.(string))
|
ip := net.ParseIP(data.(string))
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
return net.IP{}, fmt.Errorf("failed parsing ip %v", data)
|
return net.IP{}, fmt.Errorf("failed parsing ip")
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip, nil
|
return ip, nil
|
||||||
|
|
@ -228,8 +279,8 @@ func StringToIPNetHookFunc() DecodeHookFunc {
|
||||||
return func(
|
return func(
|
||||||
f reflect.Type,
|
f reflect.Type,
|
||||||
t reflect.Type,
|
t reflect.Type,
|
||||||
data interface{},
|
data any,
|
||||||
) (interface{}, error) {
|
) (any, error) {
|
||||||
if f.Kind() != reflect.String {
|
if f.Kind() != reflect.String {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
@ -239,7 +290,7 @@ func StringToIPNetHookFunc() DecodeHookFunc {
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
_, net, err := net.ParseCIDR(data.(string))
|
_, net, err := net.ParseCIDR(data.(string))
|
||||||
return net, err
|
return net, wrapNetParseError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -249,8 +300,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
|
||||||
return func(
|
return func(
|
||||||
f reflect.Type,
|
f reflect.Type,
|
||||||
t reflect.Type,
|
t reflect.Type,
|
||||||
data interface{},
|
data any,
|
||||||
) (interface{}, error) {
|
) (any, error) {
|
||||||
if f.Kind() != reflect.String {
|
if f.Kind() != reflect.String {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
@ -259,7 +310,9 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
return time.Parse(layout, data.(string))
|
ti, err := time.Parse(layout, data.(string))
|
||||||
|
|
||||||
|
return ti, wrapTimeParseError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -271,8 +324,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
|
||||||
func WeaklyTypedHook(
|
func WeaklyTypedHook(
|
||||||
f reflect.Kind,
|
f reflect.Kind,
|
||||||
t reflect.Kind,
|
t reflect.Kind,
|
||||||
data interface{},
|
data any,
|
||||||
) (interface{}, error) {
|
) (any, error) {
|
||||||
dataVal := reflect.ValueOf(data)
|
dataVal := reflect.ValueOf(data)
|
||||||
switch t {
|
switch t {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
|
|
@ -301,17 +354,17 @@ func WeaklyTypedHook(
|
||||||
}
|
}
|
||||||
|
|
||||||
func RecursiveStructToMapHookFunc() DecodeHookFunc {
|
func RecursiveStructToMapHookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
|
return func(f reflect.Value, t reflect.Value) (any, error) {
|
||||||
if f.Kind() != reflect.Struct {
|
if f.Kind() != reflect.Struct {
|
||||||
return f.Interface(), nil
|
return f.Interface(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var i interface{} = struct{}{}
|
var i any = struct{}{}
|
||||||
if t.Type() != reflect.TypeOf(&i).Elem() {
|
if t.Type() != reflect.TypeOf(&i).Elem() {
|
||||||
return f.Interface(), nil
|
return f.Interface(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
m := make(map[string]interface{})
|
m := make(map[string]any)
|
||||||
t.Set(reflect.ValueOf(m))
|
t.Set(reflect.ValueOf(m))
|
||||||
|
|
||||||
return f.Interface(), nil
|
return f.Interface(), nil
|
||||||
|
|
@ -325,8 +378,8 @@ func TextUnmarshallerHookFunc() DecodeHookFuncType {
|
||||||
return func(
|
return func(
|
||||||
f reflect.Type,
|
f reflect.Type,
|
||||||
t reflect.Type,
|
t reflect.Type,
|
||||||
data interface{},
|
data any,
|
||||||
) (interface{}, error) {
|
) (any, error) {
|
||||||
if f.Kind() != reflect.String {
|
if f.Kind() != reflect.String {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
@ -352,8 +405,8 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc {
|
||||||
return func(
|
return func(
|
||||||
f reflect.Type,
|
f reflect.Type,
|
||||||
t reflect.Type,
|
t reflect.Type,
|
||||||
data interface{},
|
data any,
|
||||||
) (interface{}, error) {
|
) (any, error) {
|
||||||
if f.Kind() != reflect.String {
|
if f.Kind() != reflect.String {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
@ -362,7 +415,9 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
return netip.ParseAddr(data.(string))
|
addr, err := netip.ParseAddr(data.(string))
|
||||||
|
|
||||||
|
return addr, wrapNetIPParseAddrError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -372,8 +427,8 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc {
|
||||||
return func(
|
return func(
|
||||||
f reflect.Type,
|
f reflect.Type,
|
||||||
t reflect.Type,
|
t reflect.Type,
|
||||||
data interface{},
|
data any,
|
||||||
) (interface{}, error) {
|
) (any, error) {
|
||||||
if f.Kind() != reflect.String {
|
if f.Kind() != reflect.String {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
@ -382,7 +437,31 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
return netip.ParseAddrPort(data.(string))
|
addrPort, err := netip.ParseAddrPort(data.(string))
|
||||||
|
|
||||||
|
return addrPort, wrapNetIPParseAddrPortError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToNetIPPrefixHookFunc returns a DecodeHookFunc that converts
|
||||||
|
// strings to netip.Prefix.
|
||||||
|
func StringToNetIPPrefixHookFunc() DecodeHookFunc {
|
||||||
|
return func(
|
||||||
|
f reflect.Type,
|
||||||
|
t reflect.Type,
|
||||||
|
data any,
|
||||||
|
) (any, error) {
|
||||||
|
if f.Kind() != reflect.String {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
if t != reflect.TypeOf(netip.Prefix{}) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert it by parsing
|
||||||
|
prefix, err := netip.ParsePrefix(data.(string))
|
||||||
|
|
||||||
|
return prefix, wrapNetIPParsePrefixError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -415,178 +494,182 @@ func StringToBasicTypeHookFunc() DecodeHookFunc {
|
||||||
// StringToInt8HookFunc returns a DecodeHookFunc that converts
|
// StringToInt8HookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to int8.
|
// strings to int8.
|
||||||
func StringToInt8HookFunc() DecodeHookFunc {
|
func StringToInt8HookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Int8 {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Int8 {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
i64, err := strconv.ParseInt(data.(string), 0, 8)
|
i64, err := strconv.ParseInt(data.(string), 0, 8)
|
||||||
return int8(i64), err
|
return int8(i64), wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToUint8HookFunc returns a DecodeHookFunc that converts
|
// StringToUint8HookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to uint8.
|
// strings to uint8.
|
||||||
func StringToUint8HookFunc() DecodeHookFunc {
|
func StringToUint8HookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Uint8 {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Uint8 {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
u64, err := strconv.ParseUint(data.(string), 0, 8)
|
u64, err := strconv.ParseUint(data.(string), 0, 8)
|
||||||
return uint8(u64), err
|
return uint8(u64), wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToInt16HookFunc returns a DecodeHookFunc that converts
|
// StringToInt16HookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to int16.
|
// strings to int16.
|
||||||
func StringToInt16HookFunc() DecodeHookFunc {
|
func StringToInt16HookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Int16 {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Int16 {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
i64, err := strconv.ParseInt(data.(string), 0, 16)
|
i64, err := strconv.ParseInt(data.(string), 0, 16)
|
||||||
return int16(i64), err
|
return int16(i64), wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToUint16HookFunc returns a DecodeHookFunc that converts
|
// StringToUint16HookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to uint16.
|
// strings to uint16.
|
||||||
func StringToUint16HookFunc() DecodeHookFunc {
|
func StringToUint16HookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Uint16 {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Uint16 {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
u64, err := strconv.ParseUint(data.(string), 0, 16)
|
u64, err := strconv.ParseUint(data.(string), 0, 16)
|
||||||
return uint16(u64), err
|
return uint16(u64), wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToInt32HookFunc returns a DecodeHookFunc that converts
|
// StringToInt32HookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to int32.
|
// strings to int32.
|
||||||
func StringToInt32HookFunc() DecodeHookFunc {
|
func StringToInt32HookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Int32 {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Int32 {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
i64, err := strconv.ParseInt(data.(string), 0, 32)
|
i64, err := strconv.ParseInt(data.(string), 0, 32)
|
||||||
return int32(i64), err
|
return int32(i64), wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToUint32HookFunc returns a DecodeHookFunc that converts
|
// StringToUint32HookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to uint32.
|
// strings to uint32.
|
||||||
func StringToUint32HookFunc() DecodeHookFunc {
|
func StringToUint32HookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Uint32 {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Uint32 {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
u64, err := strconv.ParseUint(data.(string), 0, 32)
|
u64, err := strconv.ParseUint(data.(string), 0, 32)
|
||||||
return uint32(u64), err
|
return uint32(u64), wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToInt64HookFunc returns a DecodeHookFunc that converts
|
// StringToInt64HookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to int64.
|
// strings to int64.
|
||||||
func StringToInt64HookFunc() DecodeHookFunc {
|
func StringToInt64HookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Int64 {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Int64 {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
return strconv.ParseInt(data.(string), 0, 64)
|
i64, err := strconv.ParseInt(data.(string), 0, 64)
|
||||||
|
return int64(i64), wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToUint64HookFunc returns a DecodeHookFunc that converts
|
// StringToUint64HookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to uint64.
|
// strings to uint64.
|
||||||
func StringToUint64HookFunc() DecodeHookFunc {
|
func StringToUint64HookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Uint64 {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Uint64 {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
return strconv.ParseUint(data.(string), 0, 64)
|
u64, err := strconv.ParseUint(data.(string), 0, 64)
|
||||||
|
return uint64(u64), wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToIntHookFunc returns a DecodeHookFunc that converts
|
// StringToIntHookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to int.
|
// strings to int.
|
||||||
func StringToIntHookFunc() DecodeHookFunc {
|
func StringToIntHookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Int {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Int {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
i64, err := strconv.ParseInt(data.(string), 0, 0)
|
i64, err := strconv.ParseInt(data.(string), 0, 0)
|
||||||
return int(i64), err
|
return int(i64), wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToUintHookFunc returns a DecodeHookFunc that converts
|
// StringToUintHookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to uint.
|
// strings to uint.
|
||||||
func StringToUintHookFunc() DecodeHookFunc {
|
func StringToUintHookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Uint {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Uint {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
u64, err := strconv.ParseUint(data.(string), 0, 0)
|
u64, err := strconv.ParseUint(data.(string), 0, 0)
|
||||||
return uint(u64), err
|
return uint(u64), wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToFloat32HookFunc returns a DecodeHookFunc that converts
|
// StringToFloat32HookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to float32.
|
// strings to float32.
|
||||||
func StringToFloat32HookFunc() DecodeHookFunc {
|
func StringToFloat32HookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Float32 {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Float32 {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
f64, err := strconv.ParseFloat(data.(string), 32)
|
f64, err := strconv.ParseFloat(data.(string), 32)
|
||||||
return float32(f64), err
|
return float32(f64), wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToFloat64HookFunc returns a DecodeHookFunc that converts
|
// StringToFloat64HookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to float64.
|
// strings to float64.
|
||||||
func StringToFloat64HookFunc() DecodeHookFunc {
|
func StringToFloat64HookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Float64 {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Float64 {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
return strconv.ParseFloat(data.(string), 64)
|
f64, err := strconv.ParseFloat(data.(string), 64)
|
||||||
|
return f64, wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToBoolHookFunc returns a DecodeHookFunc that converts
|
// StringToBoolHookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to bool.
|
// strings to bool.
|
||||||
func StringToBoolHookFunc() DecodeHookFunc {
|
func StringToBoolHookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Bool {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Bool {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
return strconv.ParseBool(data.(string))
|
b, err := strconv.ParseBool(data.(string))
|
||||||
|
return b, wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -605,26 +688,27 @@ func StringToRuneHookFunc() DecodeHookFunc {
|
||||||
// StringToComplex64HookFunc returns a DecodeHookFunc that converts
|
// StringToComplex64HookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to complex64.
|
// strings to complex64.
|
||||||
func StringToComplex64HookFunc() DecodeHookFunc {
|
func StringToComplex64HookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Complex64 {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Complex64 {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
c128, err := strconv.ParseComplex(data.(string), 64)
|
c128, err := strconv.ParseComplex(data.(string), 64)
|
||||||
return complex64(c128), err
|
return complex64(c128), wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToComplex128HookFunc returns a DecodeHookFunc that converts
|
// StringToComplex128HookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to complex128.
|
// strings to complex128.
|
||||||
func StringToComplex128HookFunc() DecodeHookFunc {
|
func StringToComplex128HookFunc() DecodeHookFunc {
|
||||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||||
if f.Kind() != reflect.String || t.Kind() != reflect.Complex128 {
|
if f.Kind() != reflect.String || t.Kind() != reflect.Complex128 {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert it by parsing
|
// Convert it by parsing
|
||||||
return strconv.ParseComplex(data.(string), 128)
|
c128, err := strconv.ParseComplex(data.(string), 128)
|
||||||
|
return c128, wrapStrconvNumError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
244
vendor/github.com/go-viper/mapstructure/v2/errors.go
generated
vendored
Normal file
244
vendor/github.com/go-viper/mapstructure/v2/errors.go
generated
vendored
Normal file
|
|
@ -0,0 +1,244 @@
|
||||||
|
package mapstructure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Error interface is implemented by all errors emitted by mapstructure.
|
||||||
|
//
|
||||||
|
// Use [errors.As] to check if an error implements this interface.
|
||||||
|
type Error interface {
|
||||||
|
error
|
||||||
|
|
||||||
|
mapstructure()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeError is a generic error type that holds information about
|
||||||
|
// a decoding error together with the name of the field that caused the error.
|
||||||
|
type DecodeError struct {
|
||||||
|
name string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDecodeError(name string, err error) *DecodeError {
|
||||||
|
return &DecodeError{
|
||||||
|
name: name,
|
||||||
|
err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DecodeError) Name() string {
|
||||||
|
return e.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DecodeError) Unwrap() error {
|
||||||
|
return e.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DecodeError) Error() string {
|
||||||
|
return fmt.Sprintf("'%s' %s", e.name, e.err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*DecodeError) mapstructure() {}
|
||||||
|
|
||||||
|
// ParseError is an error type that indicates a value could not be parsed
|
||||||
|
// into the expected type.
|
||||||
|
type ParseError struct {
|
||||||
|
Expected reflect.Value
|
||||||
|
Value any
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ParseError) Error() string {
|
||||||
|
return fmt.Sprintf("cannot parse value as '%s': %s", e.Expected.Type(), e.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ParseError) mapstructure() {}
|
||||||
|
|
||||||
|
// UnconvertibleTypeError is an error type that indicates a value could not be
|
||||||
|
// converted to the expected type.
|
||||||
|
type UnconvertibleTypeError struct {
|
||||||
|
Expected reflect.Value
|
||||||
|
Value any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *UnconvertibleTypeError) Error() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"expected type '%s', got unconvertible type '%s'",
|
||||||
|
e.Expected.Type(),
|
||||||
|
reflect.TypeOf(e.Value),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UnconvertibleTypeError) mapstructure() {}
|
||||||
|
|
||||||
|
func wrapStrconvNumError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err, ok := err.(*strconv.NumError); ok {
|
||||||
|
return &strconvNumError{Err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type strconvNumError struct {
|
||||||
|
Err *strconv.NumError
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *strconvNumError) Error() string {
|
||||||
|
return "strconv." + e.Err.Func + ": " + e.Err.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *strconvNumError) Unwrap() error { return e.Err }
|
||||||
|
|
||||||
|
func wrapUrlError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err, ok := err.(*url.Error); ok {
|
||||||
|
return &urlError{Err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type urlError struct {
|
||||||
|
Err *url.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *urlError) Error() string {
|
||||||
|
return fmt.Sprintf("%s", e.Err.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *urlError) Unwrap() error { return e.Err }
|
||||||
|
|
||||||
|
func wrapNetParseError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err, ok := err.(*net.ParseError); ok {
|
||||||
|
return &netParseError{Err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type netParseError struct {
|
||||||
|
Err *net.ParseError
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *netParseError) Error() string {
|
||||||
|
return "invalid " + e.Err.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *netParseError) Unwrap() error { return e.Err }
|
||||||
|
|
||||||
|
func wrapTimeParseError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err, ok := err.(*time.ParseError); ok {
|
||||||
|
return &timeParseError{Err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type timeParseError struct {
|
||||||
|
Err *time.ParseError
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *timeParseError) Error() string {
|
||||||
|
if e.Err.Message == "" {
|
||||||
|
return fmt.Sprintf("parsing time as %q: cannot parse as %q", e.Err.Layout, e.Err.LayoutElem)
|
||||||
|
}
|
||||||
|
|
||||||
|
return "parsing time " + e.Err.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *timeParseError) Unwrap() error { return e.Err }
|
||||||
|
|
||||||
|
func wrapNetIPParseAddrError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if errMsg := err.Error(); strings.HasPrefix(errMsg, "ParseAddr") {
|
||||||
|
errPieces := strings.Split(errMsg, ": ")
|
||||||
|
|
||||||
|
return fmt.Errorf("ParseAddr: %s", errPieces[len(errPieces)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrapNetIPParseAddrPortError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
errMsg := err.Error()
|
||||||
|
if strings.HasPrefix(errMsg, "invalid port ") {
|
||||||
|
return errors.New("invalid port")
|
||||||
|
} else if strings.HasPrefix(errMsg, "invalid ip:port ") {
|
||||||
|
return errors.New("invalid ip:port")
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrapNetIPParsePrefixError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if errMsg := err.Error(); strings.HasPrefix(errMsg, "netip.ParsePrefix") {
|
||||||
|
errPieces := strings.Split(errMsg, ": ")
|
||||||
|
|
||||||
|
return fmt.Errorf("netip.ParsePrefix: %s", errPieces[len(errPieces)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrapTimeParseDurationError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
errMsg := err.Error()
|
||||||
|
if strings.HasPrefix(errMsg, "time: unknown unit ") {
|
||||||
|
return errors.New("time: unknown unit")
|
||||||
|
} else if strings.HasPrefix(errMsg, "time: ") {
|
||||||
|
idx := strings.LastIndex(errMsg, " ")
|
||||||
|
|
||||||
|
return errors.New(errMsg[:idx])
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrapTimeParseLocationError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
errMsg := err.Error()
|
||||||
|
if strings.Contains(errMsg, "unknown time zone") || strings.HasPrefix(errMsg, "time: unknown format") {
|
||||||
|
return fmt.Errorf("invalid time zone format: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
430
vendor/github.com/go-viper/mapstructure/v2/flake.lock
generated
vendored
430
vendor/github.com/go-viper/mapstructure/v2/flake.lock
generated
vendored
|
|
@ -2,30 +2,28 @@
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"cachix": {
|
"cachix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"devenv": "devenv_2",
|
"devenv": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
"flake-compat": [
|
"flake-compat": [
|
||||||
"devenv",
|
"devenv"
|
||||||
"flake-compat"
|
|
||||||
],
|
],
|
||||||
"nixpkgs": [
|
"git-hooks": [
|
||||||
"devenv",
|
"devenv"
|
||||||
"nixpkgs"
|
|
||||||
],
|
],
|
||||||
"pre-commit-hooks": [
|
"nixpkgs": "nixpkgs"
|
||||||
"devenv",
|
|
||||||
"pre-commit-hooks"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712055811,
|
"lastModified": 1742042642,
|
||||||
"narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
|
"narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "cachix",
|
"repo": "cachix",
|
||||||
"rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
|
"rev": "a624d3eaf4b1d225f918de8543ed739f2f574203",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
|
"ref": "latest",
|
||||||
"repo": "cachix",
|
"repo": "cachix",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|
@ -33,52 +31,21 @@
|
||||||
"devenv": {
|
"devenv": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"cachix": "cachix",
|
"cachix": "cachix",
|
||||||
"flake-compat": "flake-compat_2",
|
"flake-compat": "flake-compat",
|
||||||
"nix": "nix_2",
|
"git-hooks": "git-hooks",
|
||||||
"nixpkgs": "nixpkgs_2",
|
|
||||||
"pre-commit-hooks": "pre-commit-hooks"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1717245169,
|
|
||||||
"narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv",
|
|
||||||
"rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"devenv_2": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"flake-compat"
|
|
||||||
],
|
|
||||||
"nix": "nix",
|
"nix": "nix",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs_3"
|
||||||
"poetry2nix": "poetry2nix",
|
|
||||||
"pre-commit-hooks": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"pre-commit-hooks"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1708704632,
|
"lastModified": 1744876578,
|
||||||
"narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
|
"narHash": "sha256-8MTBj2REB8t29sIBLpxbR0+AEGJ7f+RkzZPAGsFd40c=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "devenv",
|
"repo": "devenv",
|
||||||
"rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
|
"rev": "7ff7c351bba20d0615be25ecdcbcf79b57b85fe1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"ref": "python-rewrite",
|
|
||||||
"repo": "devenv",
|
"repo": "devenv",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|
@ -86,27 +53,11 @@
|
||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1673956053,
|
"lastModified": 1733328505,
|
||||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
|
||||||
"owner": "edolstra",
|
"owner": "edolstra",
|
||||||
"repo": "flake-compat",
|
"repo": "flake-compat",
|
||||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-compat_2": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1696426674,
|
|
||||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -116,15 +67,37 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-parts": {
|
"flake-parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": [
|
||||||
|
"devenv",
|
||||||
|
"nix",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1712014858,
|
||||||
|
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts_2": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs-lib": "nixpkgs-lib"
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1717285511,
|
"lastModified": 1743550720,
|
||||||
"narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=",
|
"narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
|
||||||
"owner": "hercules-ci",
|
"owner": "hercules-ci",
|
||||||
"repo": "flake-parts",
|
"repo": "flake-parts",
|
||||||
"rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8",
|
"rev": "c621e8422220273271f52058f618c94e405bb0f5",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -133,39 +106,28 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils": {
|
"git-hooks": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems"
|
"flake-compat": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"nixpkgs": [
|
||||||
|
"devenv",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1689068808,
|
"lastModified": 1742649964,
|
||||||
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
"narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
|
||||||
"owner": "numtide",
|
"owner": "cachix",
|
||||||
"repo": "flake-utils",
|
"repo": "git-hooks.nix",
|
||||||
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
"rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "numtide",
|
"owner": "cachix",
|
||||||
"repo": "flake-utils",
|
"repo": "git-hooks.nix",
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils_2": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1710146030,
|
|
||||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -173,7 +135,7 @@
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"devenv",
|
"devenv",
|
||||||
"pre-commit-hooks",
|
"git-hooks",
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -191,166 +153,109 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nix": {
|
"libgit2": {
|
||||||
"inputs": {
|
"flake": false,
|
||||||
"flake-compat": "flake-compat",
|
|
||||||
"nixpkgs": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"devenv",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"nixpkgs-regression": "nixpkgs-regression"
|
|
||||||
},
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712911606,
|
"lastModified": 1697646580,
|
||||||
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
|
"narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
|
||||||
"owner": "domenkozar",
|
"owner": "libgit2",
|
||||||
"repo": "nix",
|
"repo": "libgit2",
|
||||||
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
|
"rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "domenkozar",
|
"owner": "libgit2",
|
||||||
"ref": "devenv-2.21",
|
"repo": "libgit2",
|
||||||
"repo": "nix",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nix-github-actions": {
|
"nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"flake-compat": [
|
||||||
"devenv",
|
"devenv"
|
||||||
"cachix",
|
],
|
||||||
"devenv",
|
"flake-parts": "flake-parts",
|
||||||
"poetry2nix",
|
"libgit2": "libgit2",
|
||||||
"nixpkgs"
|
"nixpkgs": "nixpkgs_2",
|
||||||
|
"nixpkgs-23-11": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"nixpkgs-regression": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"pre-commit-hooks": [
|
||||||
|
"devenv"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1688870561,
|
"lastModified": 1741798497,
|
||||||
"narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
|
"narHash": "sha256-E3j+3MoY8Y96mG1dUIiLFm2tZmNbRvSiyN7CrSKuAVg=",
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nix-github-actions",
|
|
||||||
"rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nix-github-actions",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix_2": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": [
|
|
||||||
"devenv",
|
|
||||||
"flake-compat"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"devenv",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"nixpkgs-regression": "nixpkgs-regression_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1712911606,
|
|
||||||
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
|
|
||||||
"owner": "domenkozar",
|
"owner": "domenkozar",
|
||||||
"repo": "nix",
|
"repo": "nix",
|
||||||
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
|
"rev": "f3f44b2baaf6c4c6e179de8cbb1cc6db031083cd",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "domenkozar",
|
"owner": "domenkozar",
|
||||||
"ref": "devenv-2.21",
|
"ref": "devenv-2.24",
|
||||||
"repo": "nix",
|
"repo": "nix",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1692808169,
|
"lastModified": 1733212471,
|
||||||
"narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
|
"narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
|
"rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixpkgs-unstable",
|
"ref": "nixos-unstable",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-lib": {
|
"nixpkgs-lib": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1717284937,
|
"lastModified": 1743296961,
|
||||||
"narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=",
|
"narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
|
||||||
"type": "tarball",
|
"owner": "nix-community",
|
||||||
"url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz"
|
"repo": "nixpkgs.lib",
|
||||||
},
|
"rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa",
|
||||||
"original": {
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-regression": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1643052045,
|
|
||||||
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "nix-community",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs.lib",
|
||||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-regression_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1643052045,
|
|
||||||
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-stable": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1710695816,
|
|
||||||
"narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "614b4613980a522ba49f0d194531beddbb7220d3",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-23.11",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1713361204,
|
"lastModified": 1717432640,
|
||||||
"narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
|
"narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "88269ab3044128b7c2f4c7d68448b2fb50456870",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "release-24.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_3": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1733477122,
|
||||||
|
"narHash": "sha256-qamMCz5mNpQmgBwc8SB5tVMlD5sbwVIToVZtSxMph9s=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "devenv-nixpkgs",
|
"repo": "devenv-nixpkgs",
|
||||||
"rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
|
"rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -360,13 +265,13 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_3": {
|
"nixpkgs_4": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1717112898,
|
"lastModified": 1744536153,
|
||||||
"narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=",
|
"narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0",
|
"rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -376,94 +281,11 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"poetry2nix": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nix-github-actions": "nix-github-actions",
|
|
||||||
"nixpkgs": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"devenv",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1692876271,
|
|
||||||
"narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "poetry2nix",
|
|
||||||
"rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "poetry2nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pre-commit-hooks": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": [
|
|
||||||
"devenv",
|
|
||||||
"flake-compat"
|
|
||||||
],
|
|
||||||
"flake-utils": "flake-utils_2",
|
|
||||||
"gitignore": "gitignore",
|
|
||||||
"nixpkgs": [
|
|
||||||
"devenv",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1713775815,
|
|
||||||
"narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "pre-commit-hooks.nix",
|
|
||||||
"rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "pre-commit-hooks.nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"devenv": "devenv",
|
"devenv": "devenv",
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts_2",
|
||||||
"nixpkgs": "nixpkgs_3"
|
"nixpkgs": "nixpkgs_4"
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
47
vendor/github.com/go-viper/mapstructure/v2/flake.nix
generated
vendored
47
vendor/github.com/go-viper/mapstructure/v2/flake.nix
generated
vendored
|
|
@ -5,35 +5,42 @@
|
||||||
devenv.url = "github:cachix/devenv";
|
devenv.url = "github:cachix/devenv";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs@{ flake-parts, ... }:
|
outputs =
|
||||||
|
inputs@{ flake-parts, ... }:
|
||||||
flake-parts.lib.mkFlake { inherit inputs; } {
|
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||||
imports = [
|
imports = [
|
||||||
inputs.devenv.flakeModule
|
inputs.devenv.flakeModule
|
||||||
];
|
];
|
||||||
|
|
||||||
systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ];
|
systems = [
|
||||||
|
"x86_64-linux"
|
||||||
|
"x86_64-darwin"
|
||||||
|
"aarch64-darwin"
|
||||||
|
];
|
||||||
|
|
||||||
perSystem = { config, self', inputs', pkgs, system, ... }: rec {
|
perSystem =
|
||||||
devenv.shells = {
|
{ pkgs, ... }:
|
||||||
default = {
|
rec {
|
||||||
languages = {
|
devenv.shells = {
|
||||||
go.enable = true;
|
default = {
|
||||||
|
languages = {
|
||||||
|
go.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
pre-commit.hooks = {
|
||||||
|
nixpkgs-fmt.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
packages = with pkgs; [
|
||||||
|
golangci-lint
|
||||||
|
];
|
||||||
|
|
||||||
|
# https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
|
||||||
|
containers = pkgs.lib.mkForce { };
|
||||||
};
|
};
|
||||||
|
|
||||||
pre-commit.hooks = {
|
ci = devenv.shells.default;
|
||||||
nixpkgs-fmt.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
packages = with pkgs; [
|
|
||||||
golangci-lint
|
|
||||||
];
|
|
||||||
|
|
||||||
# https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
|
|
||||||
containers = pkgs.lib.mkForce { };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ci = devenv.shells.default;
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
308
vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
generated
vendored
308
vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
generated
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
// Package mapstructure exposes functionality to convert one arbitrary
|
// Package mapstructure exposes functionality to convert one arbitrary
|
||||||
// Go type into another, typically to convert a map[string]interface{}
|
// Go type into another, typically to convert a map[string]any
|
||||||
// into a native Go structure.
|
// into a native Go structure.
|
||||||
//
|
//
|
||||||
// The Go structure can be arbitrarily complex, containing slices,
|
// The Go structure can be arbitrarily complex, containing slices,
|
||||||
|
|
@ -54,8 +54,8 @@
|
||||||
//
|
//
|
||||||
// This would require an input that looks like below:
|
// This would require an input that looks like below:
|
||||||
//
|
//
|
||||||
// map[string]interface{}{
|
// map[string]any{
|
||||||
// "person": map[string]interface{}{"name": "alice"},
|
// "person": map[string]any{"name": "alice"},
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// If your "person" value is NOT nested, then you can append ",squash" to
|
// If your "person" value is NOT nested, then you can append ",squash" to
|
||||||
|
|
@ -68,7 +68,7 @@
|
||||||
//
|
//
|
||||||
// Now the following input would be accepted:
|
// Now the following input would be accepted:
|
||||||
//
|
//
|
||||||
// map[string]interface{}{
|
// map[string]any{
|
||||||
// "name": "alice",
|
// "name": "alice",
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
|
@ -79,7 +79,7 @@
|
||||||
//
|
//
|
||||||
// Will be decoded into a map:
|
// Will be decoded into a map:
|
||||||
//
|
//
|
||||||
// map[string]interface{}{
|
// map[string]any{
|
||||||
// "name": "alice",
|
// "name": "alice",
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
|
@ -95,18 +95,18 @@
|
||||||
//
|
//
|
||||||
// You can also use the ",remain" suffix on your tag to collect all unused
|
// You can also use the ",remain" suffix on your tag to collect all unused
|
||||||
// values in a map. The field with this tag MUST be a map type and should
|
// values in a map. The field with this tag MUST be a map type and should
|
||||||
// probably be a "map[string]interface{}" or "map[interface{}]interface{}".
|
// probably be a "map[string]any" or "map[any]any".
|
||||||
// See example below:
|
// See example below:
|
||||||
//
|
//
|
||||||
// type Friend struct {
|
// type Friend struct {
|
||||||
// Name string
|
// Name string
|
||||||
// Other map[string]interface{} `mapstructure:",remain"`
|
// Other map[string]any `mapstructure:",remain"`
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Given the input below, Other would be populated with the other
|
// Given the input below, Other would be populated with the other
|
||||||
// values that weren't used (everything but "name"):
|
// values that weren't used (everything but "name"):
|
||||||
//
|
//
|
||||||
// map[string]interface{}{
|
// map[string]any{
|
||||||
// "name": "bob",
|
// "name": "bob",
|
||||||
// "address": "123 Maple St.",
|
// "address": "123 Maple St.",
|
||||||
// }
|
// }
|
||||||
|
|
@ -115,15 +115,36 @@
|
||||||
//
|
//
|
||||||
// When decoding from a struct to any other value, you may use the
|
// When decoding from a struct to any other value, you may use the
|
||||||
// ",omitempty" suffix on your tag to omit that value if it equates to
|
// ",omitempty" suffix on your tag to omit that value if it equates to
|
||||||
// the zero value. The zero value of all types is specified in the Go
|
// the zero value, or a zero-length element. The zero value of all types is
|
||||||
// specification.
|
// specified in the Go specification.
|
||||||
//
|
//
|
||||||
// For example, the zero type of a numeric type is zero ("0"). If the struct
|
// For example, the zero type of a numeric type is zero ("0"). If the struct
|
||||||
// field value is zero and a numeric type, the field is empty, and it won't
|
// field value is zero and a numeric type, the field is empty, and it won't
|
||||||
// be encoded into the destination type.
|
// be encoded into the destination type. And likewise for the URLs field, if the
|
||||||
|
// slice is nil or empty, it won't be encoded into the destination type.
|
||||||
//
|
//
|
||||||
// type Source struct {
|
// type Source struct {
|
||||||
// Age int `mapstructure:",omitempty"`
|
// Age int `mapstructure:",omitempty"`
|
||||||
|
// URLs []string `mapstructure:",omitempty"`
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// # Omit Zero Values
|
||||||
|
//
|
||||||
|
// When decoding from a struct to any other value, you may use the
|
||||||
|
// ",omitzero" suffix on your tag to omit that value if it equates to the zero
|
||||||
|
// value. The zero value of all types is specified in the Go specification.
|
||||||
|
//
|
||||||
|
// For example, the zero type of a numeric type is zero ("0"). If the struct
|
||||||
|
// field value is zero and a numeric type, the field is empty, and it won't
|
||||||
|
// be encoded into the destination type. And likewise for the URLs field, if the
|
||||||
|
// slice is nil, it won't be encoded into the destination type.
|
||||||
|
//
|
||||||
|
// Note that if the field is a slice, and it is empty but not nil, it will
|
||||||
|
// still be encoded into the destination type.
|
||||||
|
//
|
||||||
|
// type Source struct {
|
||||||
|
// Age int `mapstructure:",omitzero"`
|
||||||
|
// URLs []string `mapstructure:",omitzero"`
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// # Unexported fields
|
// # Unexported fields
|
||||||
|
|
@ -140,7 +161,7 @@
|
||||||
//
|
//
|
||||||
// Using this map as input:
|
// Using this map as input:
|
||||||
//
|
//
|
||||||
// map[string]interface{}{
|
// map[string]any{
|
||||||
// "private": "I will be ignored",
|
// "private": "I will be ignored",
|
||||||
// "Public": "I made it through!",
|
// "Public": "I made it through!",
|
||||||
// }
|
// }
|
||||||
|
|
@ -183,19 +204,19 @@ import (
|
||||||
// we started with Kinds and then realized Types were the better solution,
|
// we started with Kinds and then realized Types were the better solution,
|
||||||
// but have a promise to not break backwards compat so we now support
|
// but have a promise to not break backwards compat so we now support
|
||||||
// both.
|
// both.
|
||||||
type DecodeHookFunc interface{}
|
type DecodeHookFunc any
|
||||||
|
|
||||||
// DecodeHookFuncType is a DecodeHookFunc which has complete information about
|
// DecodeHookFuncType is a DecodeHookFunc which has complete information about
|
||||||
// the source and target types.
|
// the source and target types.
|
||||||
type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
|
type DecodeHookFuncType func(reflect.Type, reflect.Type, any) (any, error)
|
||||||
|
|
||||||
// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
|
// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
|
||||||
// source and target types.
|
// source and target types.
|
||||||
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
|
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, any) (any, error)
|
||||||
|
|
||||||
// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
|
// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
|
||||||
// values.
|
// values.
|
||||||
type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
|
type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (any, error)
|
||||||
|
|
||||||
// DecoderConfig is the configuration that is used to create a new decoder
|
// DecoderConfig is the configuration that is used to create a new decoder
|
||||||
// and allows customization of various aspects of decoding.
|
// and allows customization of various aspects of decoding.
|
||||||
|
|
@ -222,6 +243,12 @@ type DecoderConfig struct {
|
||||||
// will affect all nested structs as well.
|
// will affect all nested structs as well.
|
||||||
ErrorUnset bool
|
ErrorUnset bool
|
||||||
|
|
||||||
|
// AllowUnsetPointer, if set to true, will prevent fields with pointer types
|
||||||
|
// from being reported as unset, even if ErrorUnset is true and the field was
|
||||||
|
// not present in the input data. This allows pointer fields to be optional
|
||||||
|
// without triggering an error when they are missing.
|
||||||
|
AllowUnsetPointer bool
|
||||||
|
|
||||||
// ZeroFields, if set to true, will zero fields before writing them.
|
// ZeroFields, if set to true, will zero fields before writing them.
|
||||||
// For example, a map will be emptied before decoded values are put in
|
// For example, a map will be emptied before decoded values are put in
|
||||||
// it. If this is false, a map will be merged.
|
// it. If this is false, a map will be merged.
|
||||||
|
|
@ -260,7 +287,7 @@ type DecoderConfig struct {
|
||||||
|
|
||||||
// Result is a pointer to the struct that will contain the decoded
|
// Result is a pointer to the struct that will contain the decoded
|
||||||
// value.
|
// value.
|
||||||
Result interface{}
|
Result any
|
||||||
|
|
||||||
// The tag name that mapstructure reads for field names. This
|
// The tag name that mapstructure reads for field names. This
|
||||||
// defaults to "mapstructure"
|
// defaults to "mapstructure"
|
||||||
|
|
@ -292,7 +319,7 @@ type DecoderConfig struct {
|
||||||
// up the most basic Decoder.
|
// up the most basic Decoder.
|
||||||
type Decoder struct {
|
type Decoder struct {
|
||||||
config *DecoderConfig
|
config *DecoderConfig
|
||||||
cachedDecodeHook func(from reflect.Value, to reflect.Value) (interface{}, error)
|
cachedDecodeHook func(from reflect.Value, to reflect.Value) (any, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metadata contains information about decoding a structure that
|
// Metadata contains information about decoding a structure that
|
||||||
|
|
@ -313,7 +340,7 @@ type Metadata struct {
|
||||||
|
|
||||||
// Decode takes an input structure and uses reflection to translate it to
|
// Decode takes an input structure and uses reflection to translate it to
|
||||||
// the output structure. output must be a pointer to a map or struct.
|
// the output structure. output must be a pointer to a map or struct.
|
||||||
func Decode(input interface{}, output interface{}) error {
|
func Decode(input any, output any) error {
|
||||||
config := &DecoderConfig{
|
config := &DecoderConfig{
|
||||||
Metadata: nil,
|
Metadata: nil,
|
||||||
Result: output,
|
Result: output,
|
||||||
|
|
@ -329,7 +356,7 @@ func Decode(input interface{}, output interface{}) error {
|
||||||
|
|
||||||
// WeakDecode is the same as Decode but is shorthand to enable
|
// WeakDecode is the same as Decode but is shorthand to enable
|
||||||
// WeaklyTypedInput. See DecoderConfig for more info.
|
// WeaklyTypedInput. See DecoderConfig for more info.
|
||||||
func WeakDecode(input, output interface{}) error {
|
func WeakDecode(input, output any) error {
|
||||||
config := &DecoderConfig{
|
config := &DecoderConfig{
|
||||||
Metadata: nil,
|
Metadata: nil,
|
||||||
Result: output,
|
Result: output,
|
||||||
|
|
@ -346,7 +373,7 @@ func WeakDecode(input, output interface{}) error {
|
||||||
|
|
||||||
// DecodeMetadata is the same as Decode, but is shorthand to
|
// DecodeMetadata is the same as Decode, but is shorthand to
|
||||||
// enable metadata collection. See DecoderConfig for more info.
|
// enable metadata collection. See DecoderConfig for more info.
|
||||||
func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
|
func DecodeMetadata(input any, output any, metadata *Metadata) error {
|
||||||
config := &DecoderConfig{
|
config := &DecoderConfig{
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
Result: output,
|
Result: output,
|
||||||
|
|
@ -363,7 +390,7 @@ func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) e
|
||||||
// WeakDecodeMetadata is the same as Decode, but is shorthand to
|
// WeakDecodeMetadata is the same as Decode, but is shorthand to
|
||||||
// enable both WeaklyTypedInput and metadata collection. See
|
// enable both WeaklyTypedInput and metadata collection. See
|
||||||
// DecoderConfig for more info.
|
// DecoderConfig for more info.
|
||||||
func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
|
func WeakDecodeMetadata(input any, output any, metadata *Metadata) error {
|
||||||
config := &DecoderConfig{
|
config := &DecoderConfig{
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
Result: output,
|
Result: output,
|
||||||
|
|
@ -430,7 +457,7 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
|
||||||
|
|
||||||
// Decode decodes the given raw interface to the target pointer specified
|
// Decode decodes the given raw interface to the target pointer specified
|
||||||
// by the configuration.
|
// by the configuration.
|
||||||
func (d *Decoder) Decode(input interface{}) error {
|
func (d *Decoder) Decode(input any) error {
|
||||||
err := d.decode("", input, reflect.ValueOf(d.config.Result).Elem())
|
err := d.decode("", input, reflect.ValueOf(d.config.Result).Elem())
|
||||||
|
|
||||||
// Retain some of the original behavior when multiple errors ocurr
|
// Retain some of the original behavior when multiple errors ocurr
|
||||||
|
|
@ -443,7 +470,7 @@ func (d *Decoder) Decode(input interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// isNil returns true if the input is nil or a typed nil pointer.
|
// isNil returns true if the input is nil or a typed nil pointer.
|
||||||
func isNil(input interface{}) bool {
|
func isNil(input any) bool {
|
||||||
if input == nil {
|
if input == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -452,7 +479,7 @@ func isNil(input interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decodes an unknown data type into a specific reflection value.
|
// Decodes an unknown data type into a specific reflection value.
|
||||||
func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error {
|
func (d *Decoder) decode(name string, input any, outVal reflect.Value) error {
|
||||||
var (
|
var (
|
||||||
inputVal = reflect.ValueOf(input)
|
inputVal = reflect.ValueOf(input)
|
||||||
outputKind = getKind(outVal)
|
outputKind = getKind(outVal)
|
||||||
|
|
@ -489,10 +516,10 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
|
||||||
// Hooks need a valid inputVal, so reset it to zero value of outVal type.
|
// Hooks need a valid inputVal, so reset it to zero value of outVal type.
|
||||||
switch outputKind {
|
switch outputKind {
|
||||||
case reflect.Struct, reflect.Map:
|
case reflect.Struct, reflect.Map:
|
||||||
var mapVal map[string]interface{}
|
var mapVal map[string]any
|
||||||
inputVal = reflect.ValueOf(mapVal) // create nil map pointer
|
inputVal = reflect.ValueOf(mapVal) // create nil map pointer
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
var sliceVal []interface{}
|
var sliceVal []any
|
||||||
inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer
|
inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer
|
||||||
default:
|
default:
|
||||||
inputVal = reflect.Zero(outVal.Type())
|
inputVal = reflect.Zero(outVal.Type())
|
||||||
|
|
@ -504,7 +531,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
|
||||||
var err error
|
var err error
|
||||||
input, err = d.cachedDecodeHook(inputVal, outVal)
|
input, err = d.cachedDecodeHook(inputVal, outVal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error decoding '%s': %w", name, err)
|
return newDecodeError(name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isNil(input) {
|
if isNil(input) {
|
||||||
|
|
@ -542,7 +569,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
|
||||||
err = d.decodeFunc(name, input, outVal)
|
err = d.decodeFunc(name, input, outVal)
|
||||||
default:
|
default:
|
||||||
// If we reached this point then we weren't able to decode it
|
// If we reached this point then we weren't able to decode it
|
||||||
return fmt.Errorf("%s: unsupported type: %s", name, outputKind)
|
return newDecodeError(name, fmt.Errorf("unsupported type: %s", outputKind))
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we reached here, then we successfully decoded SOMETHING, so
|
// If we reached here, then we successfully decoded SOMETHING, so
|
||||||
|
|
@ -556,7 +583,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
|
||||||
|
|
||||||
// This decodes a basic type (bool, int, string, etc.) and sets the
|
// This decodes a basic type (bool, int, string, etc.) and sets the
|
||||||
// value to "data" of that type.
|
// value to "data" of that type.
|
||||||
func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error {
|
func (d *Decoder) decodeBasic(name string, data any, val reflect.Value) error {
|
||||||
if val.IsValid() && val.Elem().IsValid() {
|
if val.IsValid() && val.Elem().IsValid() {
|
||||||
elem := val.Elem()
|
elem := val.Elem()
|
||||||
|
|
||||||
|
|
@ -603,16 +630,17 @@ func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value)
|
||||||
|
|
||||||
dataValType := dataVal.Type()
|
dataValType := dataVal.Type()
|
||||||
if !dataValType.AssignableTo(val.Type()) {
|
if !dataValType.AssignableTo(val.Type()) {
|
||||||
return fmt.Errorf(
|
return newDecodeError(name, &UnconvertibleTypeError{
|
||||||
"'%s' expected type '%s', got '%s'",
|
Expected: val,
|
||||||
name, val.Type(), dataValType)
|
Value: data,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
val.Set(dataVal)
|
val.Set(dataVal)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error {
|
func (d *Decoder) decodeString(name string, data any, val reflect.Value) error {
|
||||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||||
dataKind := getKind(dataVal)
|
dataKind := getKind(dataVal)
|
||||||
|
|
||||||
|
|
@ -656,15 +684,16 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !converted {
|
if !converted {
|
||||||
return fmt.Errorf(
|
return newDecodeError(name, &UnconvertibleTypeError{
|
||||||
"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
|
Expected: val,
|
||||||
name, val.Type(), dataVal.Type(), data)
|
Value: data,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error {
|
func (d *Decoder) decodeInt(name string, data any, val reflect.Value) error {
|
||||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||||
dataKind := getKind(dataVal)
|
dataKind := getKind(dataVal)
|
||||||
dataType := dataVal.Type()
|
dataType := dataVal.Type()
|
||||||
|
|
@ -692,26 +721,34 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er
|
||||||
if err == nil {
|
if err == nil {
|
||||||
val.SetInt(i)
|
val.SetInt(i)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("cannot parse '%s' as int: %s", name, err)
|
return newDecodeError(name, &ParseError{
|
||||||
|
Expected: val,
|
||||||
|
Value: data,
|
||||||
|
Err: wrapStrconvNumError(err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
|
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
|
||||||
jn := data.(json.Number)
|
jn := data.(json.Number)
|
||||||
i, err := jn.Int64()
|
i, err := jn.Int64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return newDecodeError(name, &ParseError{
|
||||||
"error decoding json.Number into %s: %s", name, err)
|
Expected: val,
|
||||||
|
Value: data,
|
||||||
|
Err: err,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
val.SetInt(i)
|
val.SetInt(i)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf(
|
return newDecodeError(name, &UnconvertibleTypeError{
|
||||||
"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
|
Expected: val,
|
||||||
name, val.Type(), dataVal.Type(), data)
|
Value: data,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error {
|
func (d *Decoder) decodeUint(name string, data any, val reflect.Value) error {
|
||||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||||
dataKind := getKind(dataVal)
|
dataKind := getKind(dataVal)
|
||||||
dataType := dataVal.Type()
|
dataType := dataVal.Type()
|
||||||
|
|
@ -720,8 +757,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
|
||||||
case dataKind == reflect.Int:
|
case dataKind == reflect.Int:
|
||||||
i := dataVal.Int()
|
i := dataVal.Int()
|
||||||
if i < 0 && !d.config.WeaklyTypedInput {
|
if i < 0 && !d.config.WeaklyTypedInput {
|
||||||
return fmt.Errorf("cannot parse '%s', %d overflows uint",
|
return newDecodeError(name, &ParseError{
|
||||||
name, i)
|
Expected: val,
|
||||||
|
Value: data,
|
||||||
|
Err: fmt.Errorf("%d overflows uint", i),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
val.SetUint(uint64(i))
|
val.SetUint(uint64(i))
|
||||||
case dataKind == reflect.Uint:
|
case dataKind == reflect.Uint:
|
||||||
|
|
@ -729,8 +769,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
|
||||||
case dataKind == reflect.Float32:
|
case dataKind == reflect.Float32:
|
||||||
f := dataVal.Float()
|
f := dataVal.Float()
|
||||||
if f < 0 && !d.config.WeaklyTypedInput {
|
if f < 0 && !d.config.WeaklyTypedInput {
|
||||||
return fmt.Errorf("cannot parse '%s', %f overflows uint",
|
return newDecodeError(name, &ParseError{
|
||||||
name, f)
|
Expected: val,
|
||||||
|
Value: data,
|
||||||
|
Err: fmt.Errorf("%f overflows uint", f),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
val.SetUint(uint64(f))
|
val.SetUint(uint64(f))
|
||||||
case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
|
case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
|
||||||
|
|
@ -749,26 +792,34 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
|
||||||
if err == nil {
|
if err == nil {
|
||||||
val.SetUint(i)
|
val.SetUint(i)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("cannot parse '%s' as uint: %s", name, err)
|
return newDecodeError(name, &ParseError{
|
||||||
|
Expected: val,
|
||||||
|
Value: data,
|
||||||
|
Err: wrapStrconvNumError(err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
|
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
|
||||||
jn := data.(json.Number)
|
jn := data.(json.Number)
|
||||||
i, err := strconv.ParseUint(string(jn), 0, 64)
|
i, err := strconv.ParseUint(string(jn), 0, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return newDecodeError(name, &ParseError{
|
||||||
"error decoding json.Number into %s: %s", name, err)
|
Expected: val,
|
||||||
|
Value: data,
|
||||||
|
Err: wrapStrconvNumError(err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
val.SetUint(i)
|
val.SetUint(i)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf(
|
return newDecodeError(name, &UnconvertibleTypeError{
|
||||||
"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
|
Expected: val,
|
||||||
name, val.Type(), dataVal.Type(), data)
|
Value: data,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error {
|
func (d *Decoder) decodeBool(name string, data any, val reflect.Value) error {
|
||||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||||
dataKind := getKind(dataVal)
|
dataKind := getKind(dataVal)
|
||||||
|
|
||||||
|
|
@ -788,18 +839,23 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e
|
||||||
} else if dataVal.String() == "" {
|
} else if dataVal.String() == "" {
|
||||||
val.SetBool(false)
|
val.SetBool(false)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("cannot parse '%s' as bool: %s", name, err)
|
return newDecodeError(name, &ParseError{
|
||||||
|
Expected: val,
|
||||||
|
Value: data,
|
||||||
|
Err: wrapStrconvNumError(err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf(
|
return newDecodeError(name, &UnconvertibleTypeError{
|
||||||
"'%s' expected type '%s', got unconvertible type '%#v', value: '%#v'",
|
Expected: val,
|
||||||
name, val, dataVal, data)
|
Value: data,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error {
|
func (d *Decoder) decodeFloat(name string, data any, val reflect.Value) error {
|
||||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||||
dataKind := getKind(dataVal)
|
dataKind := getKind(dataVal)
|
||||||
dataType := dataVal.Type()
|
dataType := dataVal.Type()
|
||||||
|
|
@ -827,26 +883,34 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
val.SetFloat(f)
|
val.SetFloat(f)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("cannot parse '%s' as float: %s", name, err)
|
return newDecodeError(name, &ParseError{
|
||||||
|
Expected: val,
|
||||||
|
Value: data,
|
||||||
|
Err: wrapStrconvNumError(err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
|
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
|
||||||
jn := data.(json.Number)
|
jn := data.(json.Number)
|
||||||
i, err := jn.Float64()
|
i, err := jn.Float64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return newDecodeError(name, &ParseError{
|
||||||
"error decoding json.Number into %s: %s", name, err)
|
Expected: val,
|
||||||
|
Value: data,
|
||||||
|
Err: err,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
val.SetFloat(i)
|
val.SetFloat(i)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf(
|
return newDecodeError(name, &UnconvertibleTypeError{
|
||||||
"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
|
Expected: val,
|
||||||
name, val.Type(), dataVal.Type(), data)
|
Value: data,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value) error {
|
func (d *Decoder) decodeComplex(name string, data any, val reflect.Value) error {
|
||||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||||
dataKind := getKind(dataVal)
|
dataKind := getKind(dataVal)
|
||||||
|
|
||||||
|
|
@ -854,15 +918,16 @@ func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value
|
||||||
case dataKind == reflect.Complex64:
|
case dataKind == reflect.Complex64:
|
||||||
val.SetComplex(dataVal.Complex())
|
val.SetComplex(dataVal.Complex())
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf(
|
return newDecodeError(name, &UnconvertibleTypeError{
|
||||||
"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
|
Expected: val,
|
||||||
name, val.Type(), dataVal.Type(), data)
|
Value: data,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error {
|
func (d *Decoder) decodeMap(name string, data any, val reflect.Value) error {
|
||||||
valType := val.Type()
|
valType := val.Type()
|
||||||
valKeyType := valType.Key()
|
valKeyType := valType.Key()
|
||||||
valElemType := valType.Elem()
|
valElemType := valType.Elem()
|
||||||
|
|
@ -900,7 +965,10 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
|
return newDecodeError(name, &UnconvertibleTypeError{
|
||||||
|
Expected: val,
|
||||||
|
Value: data,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -986,7 +1054,10 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
|
||||||
// to the map value.
|
// to the map value.
|
||||||
v := dataVal.Field(i)
|
v := dataVal.Field(i)
|
||||||
if !v.Type().AssignableTo(valMap.Type().Elem()) {
|
if !v.Type().AssignableTo(valMap.Type().Elem()) {
|
||||||
return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem())
|
return newDecodeError(
|
||||||
|
name+"."+f.Name,
|
||||||
|
fmt.Errorf("cannot assign type %q to map value field of type %q", v.Type(), valMap.Type().Elem()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
tagValue := f.Tag.Get(d.config.TagName)
|
tagValue := f.Tag.Get(d.config.TagName)
|
||||||
|
|
@ -1011,6 +1082,11 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If "omitzero" is specified in the tag, it ignores zero values.
|
||||||
|
if strings.Index(tagValue[index+1:], "omitzero") != -1 && v.IsZero() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// If "squash" is specified in the tag, we squash the field down.
|
// If "squash" is specified in the tag, we squash the field down.
|
||||||
squash = squash || strings.Contains(tagValue[index+1:], d.config.SquashTagOption)
|
squash = squash || strings.Contains(tagValue[index+1:], d.config.SquashTagOption)
|
||||||
if squash {
|
if squash {
|
||||||
|
|
@ -1021,12 +1097,18 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
|
||||||
|
|
||||||
// The final type must be a struct
|
// The final type must be a struct
|
||||||
if v.Kind() != reflect.Struct {
|
if v.Kind() != reflect.Struct {
|
||||||
return fmt.Errorf("cannot squash non-struct type '%s'", v.Type())
|
return newDecodeError(
|
||||||
|
name+"."+f.Name,
|
||||||
|
fmt.Errorf("cannot squash non-struct type %q", v.Type()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if strings.Index(tagValue[index+1:], "remain") != -1 {
|
if strings.Index(tagValue[index+1:], "remain") != -1 {
|
||||||
if v.Kind() != reflect.Map {
|
if v.Kind() != reflect.Map {
|
||||||
return fmt.Errorf("error remain-tag field with invalid type: '%s'", v.Type())
|
return newDecodeError(
|
||||||
|
name+"."+f.Name,
|
||||||
|
fmt.Errorf("error remain-tag field with invalid type: %q", v.Type()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr := v.MapRange()
|
ptr := v.MapRange()
|
||||||
|
|
@ -1094,7 +1176,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) {
|
func (d *Decoder) decodePtr(name string, data any, val reflect.Value) (bool, error) {
|
||||||
// If the input data is nil, then we want to just set the output
|
// If the input data is nil, then we want to just set the output
|
||||||
// pointer to be nil as well.
|
// pointer to be nil as well.
|
||||||
isNil := data == nil
|
isNil := data == nil
|
||||||
|
|
@ -1141,20 +1223,21 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (b
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error {
|
func (d *Decoder) decodeFunc(name string, data any, val reflect.Value) error {
|
||||||
// Create an element of the concrete (non pointer) type and decode
|
// Create an element of the concrete (non pointer) type and decode
|
||||||
// into that. Then set the value of the pointer to this type.
|
// into that. Then set the value of the pointer to this type.
|
||||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||||
if val.Type() != dataVal.Type() {
|
if val.Type() != dataVal.Type() {
|
||||||
return fmt.Errorf(
|
return newDecodeError(name, &UnconvertibleTypeError{
|
||||||
"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
|
Expected: val,
|
||||||
name, val.Type(), dataVal.Type(), data)
|
Value: data,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
val.Set(dataVal)
|
val.Set(dataVal)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
|
func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error {
|
||||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||||
dataValKind := dataVal.Kind()
|
dataValKind := dataVal.Kind()
|
||||||
valType := val.Type()
|
valType := val.Type()
|
||||||
|
|
@ -1176,7 +1259,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Create slice of maps of other sizes
|
// Create slice of maps of other sizes
|
||||||
return d.decodeSlice(name, []interface{}{data}, val)
|
return d.decodeSlice(name, []any{data}, val)
|
||||||
|
|
||||||
case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8:
|
case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8:
|
||||||
return d.decodeSlice(name, []byte(dataVal.String()), val)
|
return d.decodeSlice(name, []byte(dataVal.String()), val)
|
||||||
|
|
@ -1185,12 +1268,12 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
|
||||||
// and "lift" it into it. i.e. a string becomes a string slice.
|
// and "lift" it into it. i.e. a string becomes a string slice.
|
||||||
default:
|
default:
|
||||||
// Just re-try this function with data as a slice.
|
// Just re-try this function with data as a slice.
|
||||||
return d.decodeSlice(name, []interface{}{data}, val)
|
return d.decodeSlice(name, []any{data}, val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf(
|
return newDecodeError(name,
|
||||||
"'%s': source data must be an array or slice, got %s", name, dataValKind)
|
fmt.Errorf("source data must be an array or slice, got %s", dataValKind))
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the input value is nil, then don't allocate since empty != nil
|
// If the input value is nil, then don't allocate since empty != nil
|
||||||
|
|
@ -1228,7 +1311,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
|
||||||
return errors.Join(errs...)
|
return errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error {
|
func (d *Decoder) decodeArray(name string, data any, val reflect.Value) error {
|
||||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||||
dataValKind := dataVal.Kind()
|
dataValKind := dataVal.Kind()
|
||||||
valType := val.Type()
|
valType := val.Type()
|
||||||
|
|
@ -1253,17 +1336,17 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value)
|
||||||
// and "lift" it into it. i.e. a string becomes a string array.
|
// and "lift" it into it. i.e. a string becomes a string array.
|
||||||
default:
|
default:
|
||||||
// Just re-try this function with data as a slice.
|
// Just re-try this function with data as a slice.
|
||||||
return d.decodeArray(name, []interface{}{data}, val)
|
return d.decodeArray(name, []any{data}, val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf(
|
return newDecodeError(name,
|
||||||
"'%s': source data must be an array or slice, got %s", name, dataValKind)
|
fmt.Errorf("source data must be an array or slice, got %s", dataValKind))
|
||||||
|
|
||||||
}
|
}
|
||||||
if dataVal.Len() > arrayType.Len() {
|
if dataVal.Len() > arrayType.Len() {
|
||||||
return fmt.Errorf(
|
return newDecodeError(name,
|
||||||
"'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len())
|
fmt.Errorf("expected source data to have length less or equal to %d, got %d", arrayType.Len(), dataVal.Len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a new array to hold our result, same size as the original data.
|
// Make a new array to hold our result, same size as the original data.
|
||||||
|
|
@ -1289,7 +1372,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value)
|
||||||
return errors.Join(errs...)
|
return errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error {
|
func (d *Decoder) decodeStruct(name string, data any, val reflect.Value) error {
|
||||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||||
|
|
||||||
// If the type of the value to write to and the data match directly,
|
// If the type of the value to write to and the data match directly,
|
||||||
|
|
@ -1310,7 +1393,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
|
||||||
// as an intermediary.
|
// as an intermediary.
|
||||||
|
|
||||||
// Make a new map to hold our result
|
// Make a new map to hold our result
|
||||||
mapType := reflect.TypeOf((map[string]interface{})(nil))
|
mapType := reflect.TypeOf((map[string]any)(nil))
|
||||||
mval := reflect.MakeMap(mapType)
|
mval := reflect.MakeMap(mapType)
|
||||||
|
|
||||||
// Creating a pointer to a map so that other methods can completely
|
// Creating a pointer to a map so that other methods can completely
|
||||||
|
|
@ -1328,26 +1411,26 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
|
return newDecodeError(name,
|
||||||
|
fmt.Errorf("expected a map or struct, got %q", dataValKind))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error {
|
func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error {
|
||||||
dataValType := dataVal.Type()
|
dataValType := dataVal.Type()
|
||||||
if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface {
|
if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface {
|
||||||
return fmt.Errorf(
|
return newDecodeError(name,
|
||||||
"'%s' needs a map with string keys, has '%s' keys",
|
fmt.Errorf("needs a map with string keys, has %q keys", kind))
|
||||||
name, dataValType.Key().Kind())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dataValKeys := make(map[reflect.Value]struct{})
|
dataValKeys := make(map[reflect.Value]struct{})
|
||||||
dataValKeysUnused := make(map[interface{}]struct{})
|
dataValKeysUnused := make(map[any]struct{})
|
||||||
for _, dataValKey := range dataVal.MapKeys() {
|
for _, dataValKey := range dataVal.MapKeys() {
|
||||||
dataValKeys[dataValKey] = struct{}{}
|
dataValKeys[dataValKey] = struct{}{}
|
||||||
dataValKeysUnused[dataValKey.Interface()] = struct{}{}
|
dataValKeysUnused[dataValKey.Interface()] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
targetValKeysUnused := make(map[interface{}]struct{})
|
targetValKeysUnused := make(map[any]struct{})
|
||||||
|
|
||||||
var errs []error
|
var errs []error
|
||||||
|
|
||||||
|
|
@ -1410,7 +1493,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
|
||||||
structs = append(structs, fieldVal.Elem().Elem())
|
structs = append(structs, fieldVal.Elem().Elem())
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind()))
|
errs = append(errs, newDecodeError(
|
||||||
|
name+"."+fieldType.Name,
|
||||||
|
fmt.Errorf("unsupported type for squash: %s", fieldVal.Kind()),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -1461,7 +1547,9 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
|
||||||
if !rawMapVal.IsValid() {
|
if !rawMapVal.IsValid() {
|
||||||
// There was no matching key in the map for the value in
|
// There was no matching key in the map for the value in
|
||||||
// the struct. Remember it for potential errors and metadata.
|
// the struct. Remember it for potential errors and metadata.
|
||||||
targetValKeysUnused[fieldName] = struct{}{}
|
if !(d.config.AllowUnsetPointer && fieldValue.Kind() == reflect.Ptr) {
|
||||||
|
targetValKeysUnused[fieldName] = struct{}{}
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1495,7 +1583,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
|
||||||
// we put the unused keys directly into the remain field.
|
// we put the unused keys directly into the remain field.
|
||||||
if remainField != nil && len(dataValKeysUnused) > 0 {
|
if remainField != nil && len(dataValKeysUnused) > 0 {
|
||||||
// Build a map of only the unused values
|
// Build a map of only the unused values
|
||||||
remain := map[interface{}]interface{}{}
|
remain := map[any]any{}
|
||||||
for key := range dataValKeysUnused {
|
for key := range dataValKeysUnused {
|
||||||
remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface()
|
remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface()
|
||||||
}
|
}
|
||||||
|
|
@ -1517,8 +1605,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|
||||||
err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", "))
|
errs = append(errs, newDecodeError(
|
||||||
errs = append(errs, err)
|
name,
|
||||||
|
fmt.Errorf("has invalid keys: %s", strings.Join(keys, ", ")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.config.ErrorUnset && len(targetValKeysUnused) > 0 {
|
if d.config.ErrorUnset && len(targetValKeysUnused) > 0 {
|
||||||
|
|
@ -1528,8 +1618,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|
||||||
err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", "))
|
errs = append(errs, newDecodeError(
|
||||||
errs = append(errs, err)
|
name,
|
||||||
|
fmt.Errorf("has unset fields: %s", strings.Join(keys, ", ")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := errors.Join(errs...); err != nil {
|
if err := errors.Join(errs...); err != nil {
|
||||||
|
|
|
||||||
48
vendor/github.com/sagikazarmark/locafero/.golangci.yaml
generated
vendored
48
vendor/github.com/sagikazarmark/locafero/.golangci.yaml
generated
vendored
|
|
@ -1,27 +1,37 @@
|
||||||
|
version: "2"
|
||||||
|
|
||||||
run:
|
run:
|
||||||
timeout: 10m
|
timeout: 10m
|
||||||
|
|
||||||
linters-settings:
|
|
||||||
gci:
|
|
||||||
sections:
|
|
||||||
- standard
|
|
||||||
- default
|
|
||||||
- prefix(github.com/sagikazarmark/locafero)
|
|
||||||
goimports:
|
|
||||||
local-prefixes: github.com/sagikazarmark/locafero
|
|
||||||
misspell:
|
|
||||||
locale: US
|
|
||||||
nolintlint:
|
|
||||||
allow-leading-space: false # require machine-readable nolint directives (with no leading space)
|
|
||||||
allow-unused: false # report any unused nolint directives
|
|
||||||
require-specific: false # don't require nolint directives to be specific about which linter is being skipped
|
|
||||||
revive:
|
|
||||||
confidence: 0
|
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- gci
|
- errcheck
|
||||||
- goimports
|
- govet
|
||||||
|
- ineffassign
|
||||||
- misspell
|
- misspell
|
||||||
- nolintlint
|
- nolintlint
|
||||||
- revive
|
- revive
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
|
||||||
|
settings:
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
nolintlint:
|
||||||
|
allow-unused: false # report any unused nolint directives
|
||||||
|
require-specific: false # don't require nolint directives to be specific about which linter is being skipped
|
||||||
|
|
||||||
|
formatters:
|
||||||
|
enable:
|
||||||
|
- gci
|
||||||
|
- gofmt
|
||||||
|
- gofumpt
|
||||||
|
- goimports
|
||||||
|
- golines
|
||||||
|
|
||||||
|
settings:
|
||||||
|
gci:
|
||||||
|
sections:
|
||||||
|
- standard
|
||||||
|
- default
|
||||||
|
- localmodule
|
||||||
|
|
|
||||||
4
vendor/github.com/sagikazarmark/locafero/README.md
generated
vendored
4
vendor/github.com/sagikazarmark/locafero/README.md
generated
vendored
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
[](https://github.com/sagikazarmark/locafero/actions/workflows/ci.yaml)
|
[](https://github.com/sagikazarmark/locafero/actions/workflows/ci.yaml)
|
||||||
[](https://pkg.go.dev/mod/github.com/sagikazarmark/locafero)
|
[](https://pkg.go.dev/mod/github.com/sagikazarmark/locafero)
|
||||||

|

|
||||||
[](https://builtwithnix.org)
|
[](https://deps.dev/go/github.com%252Fsagikazarmark%252Flocafero)
|
||||||
|
|
||||||
**Finder library for [Afero](https://github.com/spf13/afero) ported from [go-finder](https://github.com/sagikazarmark/go-finder).**
|
**Finder library for [Afero](https://github.com/spf13/afero) ported from [go-finder](https://github.com/sagikazarmark/go-finder).**
|
||||||
|
|
||||||
|
|
|
||||||
12
vendor/github.com/sagikazarmark/locafero/file_type.go
generated
vendored
12
vendor/github.com/sagikazarmark/locafero/file_type.go
generated
vendored
|
|
@ -5,19 +5,23 @@ import "io/fs"
|
||||||
// FileType represents the kind of entries [Finder] can return.
|
// FileType represents the kind of entries [Finder] can return.
|
||||||
type FileType int
|
type FileType int
|
||||||
|
|
||||||
|
// FileType represents the kind of entries [Finder] can return.
|
||||||
const (
|
const (
|
||||||
FileTypeAll FileType = iota
|
FileTypeAny FileType = iota
|
||||||
FileTypeFile
|
FileTypeFile
|
||||||
FileTypeDir
|
FileTypeDir
|
||||||
|
|
||||||
|
// Deprecated: Use [FileTypeAny] instead.
|
||||||
|
FileTypeAll = FileTypeAny
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ft FileType) matchFileInfo(info fs.FileInfo) bool {
|
func (ft FileType) match(info fs.FileInfo) bool {
|
||||||
switch ft {
|
switch ft {
|
||||||
case FileTypeAll:
|
case FileTypeAny:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case FileTypeFile:
|
case FileTypeFile:
|
||||||
return !info.IsDir()
|
return info.Mode().IsRegular()
|
||||||
|
|
||||||
case FileTypeDir:
|
case FileTypeDir:
|
||||||
return info.IsDir()
|
return info.IsDir()
|
||||||
|
|
|
||||||
104
vendor/github.com/sagikazarmark/locafero/finder.go
generated
vendored
104
vendor/github.com/sagikazarmark/locafero/finder.go
generated
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
// Package finder looks for files and directories in an {fs.Fs} filesystem.
|
// Package locafero looks for files and directories in an {fs.Fs} filesystem.
|
||||||
package locafero
|
package locafero
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/sourcegraph/conc/iter"
|
"github.com/sourcegraph/conc/pool"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -44,65 +44,66 @@ type Finder struct {
|
||||||
// Find looks for files and directories in an [afero.Fs] filesystem.
|
// Find looks for files and directories in an [afero.Fs] filesystem.
|
||||||
func (f Finder) Find(fsys afero.Fs) ([]string, error) {
|
func (f Finder) Find(fsys afero.Fs) ([]string, error) {
|
||||||
// Arbitrary go routine limit (TODO: make this a parameter)
|
// Arbitrary go routine limit (TODO: make this a parameter)
|
||||||
// pool := pool.NewWithResults[[]string]().WithMaxGoroutines(5).WithErrors().WithFirstError()
|
p := pool.NewWithResults[[]searchResult]().WithMaxGoroutines(5).WithErrors().WithFirstError()
|
||||||
|
|
||||||
type searchItem struct {
|
|
||||||
path string
|
|
||||||
name string
|
|
||||||
}
|
|
||||||
|
|
||||||
var searchItems []searchItem
|
|
||||||
|
|
||||||
for _, searchPath := range f.Paths {
|
for _, searchPath := range f.Paths {
|
||||||
searchPath := searchPath
|
|
||||||
|
|
||||||
for _, searchName := range f.Names {
|
for _, searchName := range f.Names {
|
||||||
searchName := searchName
|
p.Go(func() ([]searchResult, error) {
|
||||||
|
// If the name contains any glob character, perform a glob match
|
||||||
|
if strings.ContainsAny(searchName, globMatch) {
|
||||||
|
return globWalkSearch(fsys, searchPath, searchName, f.Type)
|
||||||
|
}
|
||||||
|
|
||||||
searchItems = append(searchItems, searchItem{searchPath, searchName})
|
return statSearch(fsys, searchPath, searchName, f.Type)
|
||||||
|
})
|
||||||
// pool.Go(func() ([]string, error) {
|
|
||||||
// // If the name contains any glob character, perform a glob match
|
|
||||||
// if strings.ContainsAny(searchName, globMatch) {
|
|
||||||
// return globWalkSearch(fsys, searchPath, searchName, f.Type)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return statSearch(fsys, searchPath, searchName, f.Type)
|
|
||||||
// })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// allResults, err := pool.Wait()
|
searchResults, err := flatten(p.Wait())
|
||||||
// if err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
|
|
||||||
allResults, err := iter.MapErr(searchItems, func(item *searchItem) ([]string, error) {
|
|
||||||
// If the name contains any glob character, perform a glob match
|
|
||||||
if strings.ContainsAny(item.name, globMatch) {
|
|
||||||
return globWalkSearch(fsys, item.path, item.name, f.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
return statSearch(fsys, item.path, item.name, f.Type)
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var results []string
|
// Return early if no results were found
|
||||||
|
if len(searchResults) == 0 {
|
||||||
for _, r := range allResults {
|
return nil, nil
|
||||||
results = append(results, r...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort results in alphabetical order for now
|
results := make([]string, 0, len(searchResults))
|
||||||
// sort.Strings(results)
|
|
||||||
|
for _, searchResult := range searchResults {
|
||||||
|
results = append(results, searchResult.path)
|
||||||
|
}
|
||||||
|
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func globWalkSearch(fsys afero.Fs, searchPath string, searchName string, searchType FileType) ([]string, error) {
|
type searchResult struct {
|
||||||
var results []string
|
path string
|
||||||
|
info fs.FileInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func flatten[T any](results [][]T, err error) ([]T, error) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var flattened []T
|
||||||
|
|
||||||
|
for _, r := range results {
|
||||||
|
flattened = append(flattened, r...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return flattened, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func globWalkSearch(
|
||||||
|
fsys afero.Fs,
|
||||||
|
searchPath string,
|
||||||
|
searchName string,
|
||||||
|
searchType FileType,
|
||||||
|
) ([]searchResult, error) {
|
||||||
|
var results []searchResult
|
||||||
|
|
||||||
err := afero.Walk(fsys, searchPath, func(p string, fileInfo fs.FileInfo, err error) error {
|
err := afero.Walk(fsys, searchPath, func(p string, fileInfo fs.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -123,7 +124,7 @@ func globWalkSearch(fsys afero.Fs, searchPath string, searchName string, searchT
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip unmatching type
|
// Skip unmatching type
|
||||||
if !searchType.matchFileInfo(fileInfo) {
|
if !searchType.match(fileInfo) {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,7 +134,7 @@ func globWalkSearch(fsys afero.Fs, searchPath string, searchName string, searchT
|
||||||
}
|
}
|
||||||
|
|
||||||
if match {
|
if match {
|
||||||
results = append(results, p)
|
results = append(results, searchResult{p, fileInfo})
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
@ -145,7 +146,12 @@ func globWalkSearch(fsys afero.Fs, searchPath string, searchName string, searchT
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func statSearch(fsys afero.Fs, searchPath string, searchName string, searchType FileType) ([]string, error) {
|
func statSearch(
|
||||||
|
fsys afero.Fs,
|
||||||
|
searchPath string,
|
||||||
|
searchName string,
|
||||||
|
searchType FileType,
|
||||||
|
) ([]searchResult, error) {
|
||||||
filePath := filepath.Join(searchPath, searchName)
|
filePath := filepath.Join(searchPath, searchName)
|
||||||
|
|
||||||
fileInfo, err := fsys.Stat(filePath)
|
fileInfo, err := fsys.Stat(filePath)
|
||||||
|
|
@ -157,9 +163,9 @@ func statSearch(fsys afero.Fs, searchPath string, searchName string, searchType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip unmatching type
|
// Skip unmatching type
|
||||||
if !searchType.matchFileInfo(fileInfo) {
|
if !searchType.match(fileInfo) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return []string{filePath}, nil
|
return []searchResult{{filePath, fileInfo}}, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
417
vendor/github.com/sagikazarmark/locafero/flake.lock
generated
vendored
417
vendor/github.com/sagikazarmark/locafero/flake.lock
generated
vendored
|
|
@ -2,30 +2,32 @@
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"cachix": {
|
"cachix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"devenv": "devenv_2",
|
"devenv": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
"flake-compat": [
|
"flake-compat": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"git-hooks": [
|
||||||
"devenv",
|
"devenv",
|
||||||
"flake-compat"
|
"git-hooks"
|
||||||
],
|
],
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"devenv",
|
"devenv",
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
|
||||||
"pre-commit-hooks": [
|
|
||||||
"devenv",
|
|
||||||
"pre-commit-hooks"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712055811,
|
"lastModified": 1748883665,
|
||||||
"narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
|
"narHash": "sha256-R0W7uAg+BLoHjMRMQ8+oiSbTq8nkGz5RDpQ+ZfxxP3A=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "cachix",
|
"repo": "cachix",
|
||||||
"rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
|
"rev": "f707778d902af4d62d8dd92c269f8e70de09acbe",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
|
"ref": "latest",
|
||||||
"repo": "cachix",
|
"repo": "cachix",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|
@ -33,52 +35,21 @@
|
||||||
"devenv": {
|
"devenv": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"cachix": "cachix",
|
"cachix": "cachix",
|
||||||
"flake-compat": "flake-compat_2",
|
"flake-compat": "flake-compat",
|
||||||
"nix": "nix_2",
|
"git-hooks": "git-hooks",
|
||||||
"nixpkgs": "nixpkgs_2",
|
|
||||||
"pre-commit-hooks": "pre-commit-hooks"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1725907707,
|
|
||||||
"narHash": "sha256-s3pbtzZmVPHzc86WQjK7MGZMNvvw6hWnFMljEkllAfM=",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv",
|
|
||||||
"rev": "2bbbbc468fc02257265a79652a8350651cca495a",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"devenv_2": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"flake-compat"
|
|
||||||
],
|
|
||||||
"nix": "nix",
|
"nix": "nix",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs"
|
||||||
"poetry2nix": "poetry2nix",
|
|
||||||
"pre-commit-hooks": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"pre-commit-hooks"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1708704632,
|
"lastModified": 1753981111,
|
||||||
"narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
|
"narHash": "sha256-uBJOyMxOkGRmxhD2M5rbN2aV6oP1T2AKq5oBaHHC4mw=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "devenv",
|
"repo": "devenv",
|
||||||
"rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
|
"rev": "d4d70df706b153b601a87ab8e81c88a0b1a373b6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"ref": "python-rewrite",
|
|
||||||
"repo": "devenv",
|
"repo": "devenv",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|
@ -86,27 +57,11 @@
|
||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1673956053,
|
"lastModified": 1747046372,
|
||||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||||
"owner": "edolstra",
|
"owner": "edolstra",
|
||||||
"repo": "flake-compat",
|
"repo": "flake-compat",
|
||||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-compat_2": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1696426674,
|
|
||||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -116,15 +71,37 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-parts": {
|
"flake-parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": [
|
||||||
|
"devenv",
|
||||||
|
"nix",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1733312601,
|
||||||
|
"narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts_2": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs-lib": "nixpkgs-lib"
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1725234343,
|
"lastModified": 1753121425,
|
||||||
"narHash": "sha256-+ebgonl3NbiKD2UD0x4BszCZQ6sTfL4xioaM49o5B3Y=",
|
"narHash": "sha256-TVcTNvOeWWk1DXljFxVRp+E0tzG1LhrVjOGGoMHuXio=",
|
||||||
"owner": "hercules-ci",
|
"owner": "hercules-ci",
|
||||||
"repo": "flake-parts",
|
"repo": "flake-parts",
|
||||||
"rev": "567b938d64d4b4112ee253b9274472dc3a346eb6",
|
"rev": "644e0fc48951a860279da645ba77fe4a6e814c5e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -133,39 +110,29 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils": {
|
"git-hooks": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems"
|
"flake-compat": [
|
||||||
|
"devenv",
|
||||||
|
"flake-compat"
|
||||||
|
],
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"nixpkgs": [
|
||||||
|
"devenv",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1689068808,
|
"lastModified": 1750779888,
|
||||||
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
"narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=",
|
||||||
"owner": "numtide",
|
"owner": "cachix",
|
||||||
"repo": "flake-utils",
|
"repo": "git-hooks.nix",
|
||||||
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
"rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "numtide",
|
"owner": "cachix",
|
||||||
"repo": "flake-utils",
|
"repo": "git-hooks.nix",
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils_2": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1710146030,
|
|
||||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -173,7 +140,7 @@
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"devenv",
|
"devenv",
|
||||||
"pre-commit-hooks",
|
"git-hooks",
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -192,165 +159,49 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nix": {
|
"nix": {
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat",
|
|
||||||
"nixpkgs": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"devenv",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"nixpkgs-regression": "nixpkgs-regression"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1712911606,
|
|
||||||
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
|
|
||||||
"owner": "domenkozar",
|
|
||||||
"repo": "nix",
|
|
||||||
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "domenkozar",
|
|
||||||
"ref": "devenv-2.21",
|
|
||||||
"repo": "nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix-github-actions": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"devenv",
|
|
||||||
"poetry2nix",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1688870561,
|
|
||||||
"narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nix-github-actions",
|
|
||||||
"rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nix-github-actions",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix_2": {
|
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": [
|
"flake-compat": [
|
||||||
"devenv",
|
"devenv",
|
||||||
"flake-compat"
|
"flake-compat"
|
||||||
],
|
],
|
||||||
|
"flake-parts": "flake-parts",
|
||||||
|
"git-hooks-nix": [
|
||||||
|
"devenv",
|
||||||
|
"git-hooks"
|
||||||
|
],
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"devenv",
|
"devenv",
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"nixpkgs-regression": "nixpkgs-regression_2"
|
"nixpkgs-23-11": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"nixpkgs-regression": [
|
||||||
|
"devenv"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712911606,
|
"lastModified": 1752773918,
|
||||||
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
|
"narHash": "sha256-dOi/M6yNeuJlj88exI+7k154z+hAhFcuB8tZktiW7rg=",
|
||||||
"owner": "domenkozar",
|
"owner": "cachix",
|
||||||
"repo": "nix",
|
"repo": "nix",
|
||||||
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
|
"rev": "031c3cf42d2e9391eee373507d8c12e0f9606779",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "domenkozar",
|
"owner": "cachix",
|
||||||
"ref": "devenv-2.21",
|
"ref": "devenv-2.30",
|
||||||
"repo": "nix",
|
"repo": "nix",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1692808169,
|
"lastModified": 1750441195,
|
||||||
"narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
|
"narHash": "sha256-yke+pm+MdgRb6c0dPt8MgDhv7fcBbdjmv1ZceNTyzKg=",
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixpkgs-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-lib": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1725233747,
|
|
||||||
"narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=",
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-regression": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1643052045,
|
|
||||||
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-regression_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1643052045,
|
|
||||||
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-stable": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1710695816,
|
|
||||||
"narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "614b4613980a522ba49f0d194531beddbb7220d3",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-23.11",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1713361204,
|
|
||||||
"narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
|
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "devenv-nixpkgs",
|
"repo": "devenv-nixpkgs",
|
||||||
"rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
|
"rev": "0ceffe312871b443929ff3006960d29b120dc627",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -360,110 +211,42 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_3": {
|
"nixpkgs-lib": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1725910328,
|
"lastModified": 1751159883,
|
||||||
"narHash": "sha256-n9pCtzGZ0httmTwMuEbi5E78UQ4ZbQMr1pzi5N0LAG8=",
|
"narHash": "sha256-urW/Ylk9FIfvXfliA1ywh75yszAbiTEVgpPeinFyVZo=",
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "5775c2583f1801df7b790bf7f7d710a19bac66f4",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixpkgs-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"poetry2nix": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nix-github-actions": "nix-github-actions",
|
|
||||||
"nixpkgs": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"devenv",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1692876271,
|
|
||||||
"narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
|
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "poetry2nix",
|
"repo": "nixpkgs.lib",
|
||||||
"rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
|
"rev": "14a40a1d7fb9afa4739275ac642ed7301a9ba1ab",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "poetry2nix",
|
"repo": "nixpkgs.lib",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pre-commit-hooks": {
|
"nixpkgs_2": {
|
||||||
"inputs": {
|
|
||||||
"flake-compat": [
|
|
||||||
"devenv",
|
|
||||||
"flake-compat"
|
|
||||||
],
|
|
||||||
"flake-utils": "flake-utils_2",
|
|
||||||
"gitignore": "gitignore",
|
|
||||||
"nixpkgs": [
|
|
||||||
"devenv",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
|
||||||
},
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1713775815,
|
"lastModified": 1753939845,
|
||||||
"narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
|
"narHash": "sha256-K2ViRJfdVGE8tpJejs8Qpvvejks1+A4GQej/lBk5y7I=",
|
||||||
"owner": "cachix",
|
"owner": "NixOS",
|
||||||
"repo": "pre-commit-hooks.nix",
|
"repo": "nixpkgs",
|
||||||
"rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
|
"rev": "94def634a20494ee057c76998843c015909d6311",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "cachix",
|
"owner": "NixOS",
|
||||||
"repo": "pre-commit-hooks.nix",
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"devenv": "devenv",
|
"devenv": "devenv",
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts_2",
|
||||||
"nixpkgs": "nixpkgs_3"
|
"nixpkgs": "nixpkgs_2"
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
66
vendor/github.com/sagikazarmark/locafero/flake.nix
generated
vendored
66
vendor/github.com/sagikazarmark/locafero/flake.nix
generated
vendored
|
|
@ -1,64 +1,42 @@
|
||||||
{
|
{
|
||||||
description = "Finder library for Afero";
|
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||||
devenv.url = "github:cachix/devenv";
|
devenv.url = "github:cachix/devenv";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs@{ flake-parts, ... }:
|
outputs =
|
||||||
|
inputs@{ flake-parts, ... }:
|
||||||
flake-parts.lib.mkFlake { inherit inputs; } {
|
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||||
imports = [
|
imports = [
|
||||||
inputs.devenv.flakeModule
|
inputs.devenv.flakeModule
|
||||||
];
|
];
|
||||||
|
|
||||||
systems = [ "x86_64-linux" "aarch64-darwin" ];
|
systems = [
|
||||||
|
"x86_64-linux"
|
||||||
|
"aarch64-darwin"
|
||||||
|
];
|
||||||
|
|
||||||
perSystem = { config, self', inputs', pkgs, system, ... }: rec {
|
perSystem =
|
||||||
devenv.shells = {
|
{ pkgs, ... }:
|
||||||
default = {
|
{
|
||||||
languages = {
|
devenv.shells = {
|
||||||
go.enable = true;
|
default = {
|
||||||
go.package = pkgs.lib.mkDefault pkgs.go_1_23;
|
languages = {
|
||||||
};
|
go.enable = true;
|
||||||
|
go.package = pkgs.lib.mkDefault pkgs.go_1_24;
|
||||||
|
};
|
||||||
|
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
just
|
just
|
||||||
|
|
||||||
golangci-lint
|
golangci-lint
|
||||||
];
|
];
|
||||||
|
|
||||||
# https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
|
# https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
|
||||||
containers = pkgs.lib.mkForce { };
|
containers = pkgs.lib.mkForce { };
|
||||||
};
|
|
||||||
|
|
||||||
ci = devenv.shells.default;
|
|
||||||
|
|
||||||
ci_1_21 = {
|
|
||||||
imports = [ devenv.shells.ci ];
|
|
||||||
|
|
||||||
languages = {
|
|
||||||
go.package = pkgs.go_1_21;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
ci_1_22 = {
|
|
||||||
imports = [ devenv.shells.ci ];
|
|
||||||
|
|
||||||
languages = {
|
|
||||||
go.package = pkgs.go_1_22;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
ci_1_23 = {
|
|
||||||
imports = [ devenv.shells.ci ];
|
|
||||||
|
|
||||||
languages = {
|
|
||||||
go.package = pkgs.go_1_23;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
7
vendor/github.com/sagikazarmark/locafero/justfile
generated
vendored
7
vendor/github.com/sagikazarmark/locafero/justfile
generated
vendored
|
|
@ -2,10 +2,13 @@ default:
|
||||||
just --list
|
just --list
|
||||||
|
|
||||||
test:
|
test:
|
||||||
go test -race -v ./...
|
go test -count 10 -shuffle on -race -v ./...
|
||||||
|
|
||||||
|
fuzz:
|
||||||
|
go test -race -v -fuzz=Fuzz -fuzztime=60s ./...
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
golangci-lint run
|
golangci-lint run
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
golangci-lint run --fix
|
golangci-lint fmt
|
||||||
|
|
|
||||||
24
vendor/github.com/sourcegraph/conc/Makefile
generated
vendored
Normal file
24
vendor/github.com/sourcegraph/conc/Makefile
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
|
|
||||||
|
GO_BIN ?= $(shell go env GOPATH)/bin
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
|
help:
|
||||||
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||||
|
|
||||||
|
$(GO_BIN)/golangci-lint:
|
||||||
|
@echo "==> Installing golangci-lint within "${GO_BIN}""
|
||||||
|
@go install -v github.com/golangci/golangci-lint/cmd/golangci-lint@latest
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint: $(GO_BIN)/golangci-lint ## Run linting on Go files
|
||||||
|
@echo "==> Linting Go source files"
|
||||||
|
@golangci-lint run -v --fix -c .golangci.yml ./...
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: ## Run tests
|
||||||
|
go test -race -v ./... -coverprofile ./coverage.txt
|
||||||
|
|
||||||
|
.PHONY: bench
|
||||||
|
bench: ## Run benchmarks. See https://pkg.go.dev/cmd/go#hdr-Testing_flags
|
||||||
|
go test ./... -bench . -benchtime 5s -timeout 0 -run=XXX -cpu 1 -benchmem
|
||||||
10
vendor/github.com/sourcegraph/conc/internal/multierror/multierror_go119.go
generated
vendored
10
vendor/github.com/sourcegraph/conc/internal/multierror/multierror_go119.go
generated
vendored
|
|
@ -1,10 +0,0 @@
|
||||||
//go:build !go1.20
|
|
||||||
// +build !go1.20
|
|
||||||
|
|
||||||
package multierror
|
|
||||||
|
|
||||||
import "go.uber.org/multierr"
|
|
||||||
|
|
||||||
var (
|
|
||||||
Join = multierr.Combine
|
|
||||||
)
|
|
||||||
10
vendor/github.com/sourcegraph/conc/internal/multierror/multierror_go120.go
generated
vendored
10
vendor/github.com/sourcegraph/conc/internal/multierror/multierror_go120.go
generated
vendored
|
|
@ -1,10 +0,0 @@
|
||||||
//go:build go1.20
|
|
||||||
// +build go1.20
|
|
||||||
|
|
||||||
package multierror
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
var (
|
|
||||||
Join = errors.Join
|
|
||||||
)
|
|
||||||
85
vendor/github.com/sourcegraph/conc/iter/iter.go
generated
vendored
85
vendor/github.com/sourcegraph/conc/iter/iter.go
generated
vendored
|
|
@ -1,85 +0,0 @@
|
||||||
package iter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
"github.com/sourcegraph/conc"
|
|
||||||
)
|
|
||||||
|
|
||||||
// defaultMaxGoroutines returns the default maximum number of
|
|
||||||
// goroutines to use within this package.
|
|
||||||
func defaultMaxGoroutines() int { return runtime.GOMAXPROCS(0) }
|
|
||||||
|
|
||||||
// Iterator can be used to configure the behaviour of ForEach
|
|
||||||
// and ForEachIdx. The zero value is safe to use with reasonable
|
|
||||||
// defaults.
|
|
||||||
//
|
|
||||||
// Iterator is also safe for reuse and concurrent use.
|
|
||||||
type Iterator[T any] struct {
|
|
||||||
// MaxGoroutines controls the maximum number of goroutines
|
|
||||||
// to use on this Iterator's methods.
|
|
||||||
//
|
|
||||||
// If unset, MaxGoroutines defaults to runtime.GOMAXPROCS(0).
|
|
||||||
MaxGoroutines int
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForEach executes f in parallel over each element in input.
|
|
||||||
//
|
|
||||||
// It is safe to mutate the input parameter, which makes it
|
|
||||||
// possible to map in place.
|
|
||||||
//
|
|
||||||
// ForEach always uses at most runtime.GOMAXPROCS goroutines.
|
|
||||||
// It takes roughly 2µs to start up the goroutines and adds
|
|
||||||
// an overhead of roughly 50ns per element of input. For
|
|
||||||
// a configurable goroutine limit, use a custom Iterator.
|
|
||||||
func ForEach[T any](input []T, f func(*T)) { Iterator[T]{}.ForEach(input, f) }
|
|
||||||
|
|
||||||
// ForEach executes f in parallel over each element in input,
|
|
||||||
// using up to the Iterator's configured maximum number of
|
|
||||||
// goroutines.
|
|
||||||
//
|
|
||||||
// It is safe to mutate the input parameter, which makes it
|
|
||||||
// possible to map in place.
|
|
||||||
//
|
|
||||||
// It takes roughly 2µs to start up the goroutines and adds
|
|
||||||
// an overhead of roughly 50ns per element of input.
|
|
||||||
func (iter Iterator[T]) ForEach(input []T, f func(*T)) {
|
|
||||||
iter.ForEachIdx(input, func(_ int, t *T) {
|
|
||||||
f(t)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForEachIdx is the same as ForEach except it also provides the
|
|
||||||
// index of the element to the callback.
|
|
||||||
func ForEachIdx[T any](input []T, f func(int, *T)) { Iterator[T]{}.ForEachIdx(input, f) }
|
|
||||||
|
|
||||||
// ForEachIdx is the same as ForEach except it also provides the
|
|
||||||
// index of the element to the callback.
|
|
||||||
func (iter Iterator[T]) ForEachIdx(input []T, f func(int, *T)) {
|
|
||||||
if iter.MaxGoroutines == 0 {
|
|
||||||
// iter is a value receiver and is hence safe to mutate
|
|
||||||
iter.MaxGoroutines = defaultMaxGoroutines()
|
|
||||||
}
|
|
||||||
|
|
||||||
numInput := len(input)
|
|
||||||
if iter.MaxGoroutines > numInput {
|
|
||||||
// No more concurrent tasks than the number of input items.
|
|
||||||
iter.MaxGoroutines = numInput
|
|
||||||
}
|
|
||||||
|
|
||||||
var idx atomic.Int64
|
|
||||||
// Create the task outside the loop to avoid extra closure allocations.
|
|
||||||
task := func() {
|
|
||||||
i := int(idx.Add(1) - 1)
|
|
||||||
for ; i < numInput; i = int(idx.Add(1) - 1) {
|
|
||||||
f(i, &input[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var wg conc.WaitGroup
|
|
||||||
for i := 0; i < iter.MaxGoroutines; i++ {
|
|
||||||
wg.Go(task)
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
65
vendor/github.com/sourcegraph/conc/iter/map.go
generated
vendored
65
vendor/github.com/sourcegraph/conc/iter/map.go
generated
vendored
|
|
@ -1,65 +0,0 @@
|
||||||
package iter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/sourcegraph/conc/internal/multierror"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Mapper is an Iterator with a result type R. It can be used to configure
|
|
||||||
// the behaviour of Map and MapErr. The zero value is safe to use with
|
|
||||||
// reasonable defaults.
|
|
||||||
//
|
|
||||||
// Mapper is also safe for reuse and concurrent use.
|
|
||||||
type Mapper[T, R any] Iterator[T]
|
|
||||||
|
|
||||||
// Map applies f to each element of input, returning the mapped result.
|
|
||||||
//
|
|
||||||
// Map always uses at most runtime.GOMAXPROCS goroutines. For a configurable
|
|
||||||
// goroutine limit, use a custom Mapper.
|
|
||||||
func Map[T, R any](input []T, f func(*T) R) []R {
|
|
||||||
return Mapper[T, R]{}.Map(input, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map applies f to each element of input, returning the mapped result.
|
|
||||||
//
|
|
||||||
// Map uses up to the configured Mapper's maximum number of goroutines.
|
|
||||||
func (m Mapper[T, R]) Map(input []T, f func(*T) R) []R {
|
|
||||||
res := make([]R, len(input))
|
|
||||||
Iterator[T](m).ForEachIdx(input, func(i int, t *T) {
|
|
||||||
res[i] = f(t)
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// MapErr applies f to each element of the input, returning the mapped result
|
|
||||||
// and a combined error of all returned errors.
|
|
||||||
//
|
|
||||||
// Map always uses at most runtime.GOMAXPROCS goroutines. For a configurable
|
|
||||||
// goroutine limit, use a custom Mapper.
|
|
||||||
func MapErr[T, R any](input []T, f func(*T) (R, error)) ([]R, error) {
|
|
||||||
return Mapper[T, R]{}.MapErr(input, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MapErr applies f to each element of the input, returning the mapped result
|
|
||||||
// and a combined error of all returned errors.
|
|
||||||
//
|
|
||||||
// Map uses up to the configured Mapper's maximum number of goroutines.
|
|
||||||
func (m Mapper[T, R]) MapErr(input []T, f func(*T) (R, error)) ([]R, error) {
|
|
||||||
var (
|
|
||||||
res = make([]R, len(input))
|
|
||||||
errMux sync.Mutex
|
|
||||||
errs error
|
|
||||||
)
|
|
||||||
Iterator[T](m).ForEachIdx(input, func(i int, t *T) {
|
|
||||||
var err error
|
|
||||||
res[i], err = f(t)
|
|
||||||
if err != nil {
|
|
||||||
errMux.Lock()
|
|
||||||
// TODO: use stdlib errors once multierrors land in go 1.20
|
|
||||||
errs = multierror.Join(errs, err)
|
|
||||||
errMux.Unlock()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return res, errs
|
|
||||||
}
|
|
||||||
104
vendor/github.com/sourcegraph/conc/pool/context_pool.go
generated
vendored
Normal file
104
vendor/github.com/sourcegraph/conc/pool/context_pool.go
generated
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
package pool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ContextPool is a pool that runs tasks that take a context.
|
||||||
|
// A new ContextPool should be created with `New().WithContext(ctx)`.
|
||||||
|
//
|
||||||
|
// The configuration methods (With*) will panic if they are used after calling
|
||||||
|
// Go() for the first time.
|
||||||
|
type ContextPool struct {
|
||||||
|
errorPool ErrorPool
|
||||||
|
|
||||||
|
ctx context.Context
|
||||||
|
cancel context.CancelFunc
|
||||||
|
|
||||||
|
cancelOnError bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go submits a task. If it returns an error, the error will be
|
||||||
|
// collected and returned by Wait(). If all goroutines in the pool
|
||||||
|
// are busy, a call to Go() will block until the task can be started.
|
||||||
|
func (p *ContextPool) Go(f func(ctx context.Context) error) {
|
||||||
|
p.errorPool.Go(func() error {
|
||||||
|
if p.cancelOnError {
|
||||||
|
// If we are cancelling on error, then we also want to cancel if a
|
||||||
|
// panic is raised. To do this, we need to recover, cancel, and then
|
||||||
|
// re-throw the caught panic.
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
p.cancel()
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
err := f(p.ctx)
|
||||||
|
if err != nil && p.cancelOnError {
|
||||||
|
// Leaky abstraction warning: We add the error directly because
|
||||||
|
// otherwise, canceling could cause another goroutine to exit and
|
||||||
|
// return an error before this error was added, which breaks the
|
||||||
|
// expectations of WithFirstError().
|
||||||
|
p.errorPool.addErr(err)
|
||||||
|
p.cancel()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait cleans up all spawned goroutines, propagates any panics, and
|
||||||
|
// returns an error if any of the tasks errored.
|
||||||
|
func (p *ContextPool) Wait() error {
|
||||||
|
// Make sure we call cancel after pool is done to avoid memory leakage.
|
||||||
|
defer p.cancel()
|
||||||
|
return p.errorPool.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFirstError configures the pool to only return the first error
|
||||||
|
// returned by a task. By default, Wait() will return a combined error.
|
||||||
|
// This is particularly useful for (*ContextPool).WithCancelOnError(),
|
||||||
|
// where all errors after the first are likely to be context.Canceled.
|
||||||
|
func (p *ContextPool) WithFirstError() *ContextPool {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.errorPool.WithFirstError()
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCancelOnError configures the pool to cancel its context as soon as
|
||||||
|
// any task returns an error or panics. By default, the pool's context is not
|
||||||
|
// canceled until the parent context is canceled.
|
||||||
|
//
|
||||||
|
// In this case, all errors returned from the pool after the first will
|
||||||
|
// likely be context.Canceled - you may want to also use
|
||||||
|
// (*ContextPool).WithFirstError() to configure the pool to only return
|
||||||
|
// the first error.
|
||||||
|
func (p *ContextPool) WithCancelOnError() *ContextPool {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.cancelOnError = true
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFailFast is an alias for the combination of WithFirstError and
|
||||||
|
// WithCancelOnError. By default, the errors from all tasks are returned and
|
||||||
|
// the pool's context is not canceled until the parent context is canceled.
|
||||||
|
func (p *ContextPool) WithFailFast() *ContextPool {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.WithFirstError()
|
||||||
|
p.WithCancelOnError()
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMaxGoroutines limits the number of goroutines in a pool.
|
||||||
|
// Defaults to unlimited. Panics if n < 1.
|
||||||
|
func (p *ContextPool) WithMaxGoroutines(n int) *ContextPool {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.errorPool.WithMaxGoroutines(n)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ContextPool) panicIfInitialized() {
|
||||||
|
p.errorPool.panicIfInitialized()
|
||||||
|
}
|
||||||
100
vendor/github.com/sourcegraph/conc/pool/error_pool.go
generated
vendored
Normal file
100
vendor/github.com/sourcegraph/conc/pool/error_pool.go
generated
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
package pool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrorPool is a pool that runs tasks that may return an error.
|
||||||
|
// Errors are collected and returned by Wait().
|
||||||
|
//
|
||||||
|
// The configuration methods (With*) will panic if they are used after calling
|
||||||
|
// Go() for the first time.
|
||||||
|
//
|
||||||
|
// A new ErrorPool should be created using `New().WithErrors()`.
|
||||||
|
type ErrorPool struct {
|
||||||
|
pool Pool
|
||||||
|
|
||||||
|
onlyFirstError bool
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
errs []error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go submits a task to the pool. If all goroutines in the pool
|
||||||
|
// are busy, a call to Go() will block until the task can be started.
|
||||||
|
func (p *ErrorPool) Go(f func() error) {
|
||||||
|
p.pool.Go(func() {
|
||||||
|
p.addErr(f())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait cleans up any spawned goroutines, propagating any panics and
|
||||||
|
// returning any errors from tasks.
|
||||||
|
func (p *ErrorPool) Wait() error {
|
||||||
|
p.pool.Wait()
|
||||||
|
|
||||||
|
errs := p.errs
|
||||||
|
p.errs = nil // reset errs
|
||||||
|
|
||||||
|
if len(errs) == 0 {
|
||||||
|
return nil
|
||||||
|
} else if p.onlyFirstError {
|
||||||
|
return errs[0]
|
||||||
|
} else {
|
||||||
|
return errors.Join(errs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithContext converts the pool to a ContextPool for tasks that should
|
||||||
|
// run under the same context, such that they each respect shared cancellation.
|
||||||
|
// For example, WithCancelOnError can be configured on the returned pool to
|
||||||
|
// signal that all goroutines should be cancelled upon the first error.
|
||||||
|
func (p *ErrorPool) WithContext(ctx context.Context) *ContextPool {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
return &ContextPool{
|
||||||
|
errorPool: p.deref(),
|
||||||
|
ctx: ctx,
|
||||||
|
cancel: cancel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFirstError configures the pool to only return the first error
|
||||||
|
// returned by a task. By default, Wait() will return a combined error.
|
||||||
|
func (p *ErrorPool) WithFirstError() *ErrorPool {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.onlyFirstError = true
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMaxGoroutines limits the number of goroutines in a pool.
|
||||||
|
// Defaults to unlimited. Panics if n < 1.
|
||||||
|
func (p *ErrorPool) WithMaxGoroutines(n int) *ErrorPool {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.pool.WithMaxGoroutines(n)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// deref is a helper that creates a shallow copy of the pool with the same
|
||||||
|
// settings. We don't want to just dereference the pointer because that makes
|
||||||
|
// the copylock lint angry.
|
||||||
|
func (p *ErrorPool) deref() ErrorPool {
|
||||||
|
return ErrorPool{
|
||||||
|
pool: p.pool.deref(),
|
||||||
|
onlyFirstError: p.onlyFirstError,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ErrorPool) panicIfInitialized() {
|
||||||
|
p.pool.panicIfInitialized()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ErrorPool) addErr(err error) {
|
||||||
|
if err != nil {
|
||||||
|
p.mu.Lock()
|
||||||
|
p.errs = append(p.errs, err)
|
||||||
|
p.mu.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
174
vendor/github.com/sourcegraph/conc/pool/pool.go
generated
vendored
Normal file
174
vendor/github.com/sourcegraph/conc/pool/pool.go
generated
vendored
Normal file
|
|
@ -0,0 +1,174 @@
|
||||||
|
package pool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/sourcegraph/conc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// New creates a new Pool.
|
||||||
|
func New() *Pool {
|
||||||
|
return &Pool{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pool is a pool of goroutines used to execute tasks concurrently.
|
||||||
|
//
|
||||||
|
// Tasks are submitted with Go(). Once all your tasks have been submitted, you
|
||||||
|
// must call Wait() to clean up any spawned goroutines and propagate any
|
||||||
|
// panics.
|
||||||
|
//
|
||||||
|
// Goroutines are started lazily, so creating a new pool is cheap. There will
|
||||||
|
// never be more goroutines spawned than there are tasks submitted.
|
||||||
|
//
|
||||||
|
// The configuration methods (With*) will panic if they are used after calling
|
||||||
|
// Go() for the first time.
|
||||||
|
//
|
||||||
|
// Pool is efficient, but not zero cost. It should not be used for very short
|
||||||
|
// tasks. Startup and teardown come with an overhead of around 1µs, and each
|
||||||
|
// task has an overhead of around 300ns.
|
||||||
|
type Pool struct {
|
||||||
|
handle conc.WaitGroup
|
||||||
|
limiter limiter
|
||||||
|
tasks chan func()
|
||||||
|
initOnce sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go submits a task to be run in the pool. If all goroutines in the pool
|
||||||
|
// are busy, a call to Go() will block until the task can be started.
|
||||||
|
func (p *Pool) Go(f func()) {
|
||||||
|
p.init()
|
||||||
|
|
||||||
|
if p.limiter == nil {
|
||||||
|
// No limit on the number of goroutines.
|
||||||
|
select {
|
||||||
|
case p.tasks <- f:
|
||||||
|
// A goroutine was available to handle the task.
|
||||||
|
default:
|
||||||
|
// No goroutine was available to handle the task.
|
||||||
|
// Spawn a new one and send it the task.
|
||||||
|
p.handle.Go(func() {
|
||||||
|
p.worker(f)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
select {
|
||||||
|
case p.limiter <- struct{}{}:
|
||||||
|
// If we are below our limit, spawn a new worker rather
|
||||||
|
// than waiting for one to become available.
|
||||||
|
p.handle.Go(func() {
|
||||||
|
p.worker(f)
|
||||||
|
})
|
||||||
|
case p.tasks <- f:
|
||||||
|
// A worker is available and has accepted the task.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait cleans up spawned goroutines, propagating any panics that were
|
||||||
|
// raised by a tasks.
|
||||||
|
func (p *Pool) Wait() {
|
||||||
|
p.init()
|
||||||
|
|
||||||
|
close(p.tasks)
|
||||||
|
|
||||||
|
// After Wait() returns, reset the struct so tasks will be reinitialized on
|
||||||
|
// next use. This better matches the behavior of sync.WaitGroup
|
||||||
|
defer func() { p.initOnce = sync.Once{} }()
|
||||||
|
|
||||||
|
p.handle.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxGoroutines returns the maximum size of the pool.
|
||||||
|
func (p *Pool) MaxGoroutines() int {
|
||||||
|
return p.limiter.limit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMaxGoroutines limits the number of goroutines in a pool.
|
||||||
|
// Defaults to unlimited. Panics if n < 1.
|
||||||
|
func (p *Pool) WithMaxGoroutines(n int) *Pool {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
if n < 1 {
|
||||||
|
panic("max goroutines in a pool must be greater than zero")
|
||||||
|
}
|
||||||
|
p.limiter = make(limiter, n)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// init ensures that the pool is initialized before use. This makes the
|
||||||
|
// zero value of the pool usable.
|
||||||
|
func (p *Pool) init() {
|
||||||
|
p.initOnce.Do(func() {
|
||||||
|
p.tasks = make(chan func())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// panicIfInitialized will trigger a panic if a configuration method is called
|
||||||
|
// after the pool has started any goroutines for the first time. In the case that
|
||||||
|
// new settings are needed, a new pool should be created.
|
||||||
|
func (p *Pool) panicIfInitialized() {
|
||||||
|
if p.tasks != nil {
|
||||||
|
panic("pool can not be reconfigured after calling Go() for the first time")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithErrors converts the pool to an ErrorPool so the submitted tasks can
|
||||||
|
// return errors.
|
||||||
|
func (p *Pool) WithErrors() *ErrorPool {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
return &ErrorPool{
|
||||||
|
pool: p.deref(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// deref is a helper that creates a shallow copy of the pool with the same
|
||||||
|
// settings. We don't want to just dereference the pointer because that makes
|
||||||
|
// the copylock lint angry.
|
||||||
|
func (p *Pool) deref() Pool {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
return Pool{
|
||||||
|
limiter: p.limiter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithContext converts the pool to a ContextPool for tasks that should
|
||||||
|
// run under the same context, such that they each respect shared cancellation.
|
||||||
|
// For example, WithCancelOnError can be configured on the returned pool to
|
||||||
|
// signal that all goroutines should be cancelled upon the first error.
|
||||||
|
func (p *Pool) WithContext(ctx context.Context) *ContextPool {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
return &ContextPool{
|
||||||
|
errorPool: p.WithErrors().deref(),
|
||||||
|
ctx: ctx,
|
||||||
|
cancel: cancel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pool) worker(initialFunc func()) {
|
||||||
|
// The only time this matters is if the task panics.
|
||||||
|
// This makes it possible to spin up new workers in that case.
|
||||||
|
defer p.limiter.release()
|
||||||
|
|
||||||
|
if initialFunc != nil {
|
||||||
|
initialFunc()
|
||||||
|
}
|
||||||
|
|
||||||
|
for f := range p.tasks {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type limiter chan struct{}
|
||||||
|
|
||||||
|
func (l limiter) limit() int {
|
||||||
|
return cap(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l limiter) release() {
|
||||||
|
if l != nil {
|
||||||
|
<-l
|
||||||
|
}
|
||||||
|
}
|
||||||
85
vendor/github.com/sourcegraph/conc/pool/result_context_pool.go
generated
vendored
Normal file
85
vendor/github.com/sourcegraph/conc/pool/result_context_pool.go
generated
vendored
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
package pool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ResultContextPool is a pool that runs tasks that take a context and return a
|
||||||
|
// result. The context passed to the task will be canceled if any of the tasks
|
||||||
|
// return an error, which makes its functionality different than just capturing
|
||||||
|
// a context with the task closure.
|
||||||
|
//
|
||||||
|
// The configuration methods (With*) will panic if they are used after calling
|
||||||
|
// Go() for the first time.
|
||||||
|
type ResultContextPool[T any] struct {
|
||||||
|
contextPool ContextPool
|
||||||
|
agg resultAggregator[T]
|
||||||
|
collectErrored bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go submits a task to the pool. If all goroutines in the pool
|
||||||
|
// are busy, a call to Go() will block until the task can be started.
|
||||||
|
func (p *ResultContextPool[T]) Go(f func(context.Context) (T, error)) {
|
||||||
|
idx := p.agg.nextIndex()
|
||||||
|
p.contextPool.Go(func(ctx context.Context) error {
|
||||||
|
res, err := f(ctx)
|
||||||
|
p.agg.save(idx, res, err != nil)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait cleans up all spawned goroutines, propagates any panics, and
|
||||||
|
// returns an error if any of the tasks errored.
|
||||||
|
func (p *ResultContextPool[T]) Wait() ([]T, error) {
|
||||||
|
err := p.contextPool.Wait()
|
||||||
|
results := p.agg.collect(p.collectErrored)
|
||||||
|
p.agg = resultAggregator[T]{}
|
||||||
|
return results, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCollectErrored configures the pool to still collect the result of a task
|
||||||
|
// even if the task returned an error. By default, the result of tasks that errored
|
||||||
|
// are ignored and only the error is collected.
|
||||||
|
func (p *ResultContextPool[T]) WithCollectErrored() *ResultContextPool[T] {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.collectErrored = true
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFirstError configures the pool to only return the first error
|
||||||
|
// returned by a task. By default, Wait() will return a combined error.
|
||||||
|
func (p *ResultContextPool[T]) WithFirstError() *ResultContextPool[T] {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.contextPool.WithFirstError()
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCancelOnError configures the pool to cancel its context as soon as
|
||||||
|
// any task returns an error. By default, the pool's context is not
|
||||||
|
// canceled until the parent context is canceled.
|
||||||
|
func (p *ResultContextPool[T]) WithCancelOnError() *ResultContextPool[T] {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.contextPool.WithCancelOnError()
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFailFast is an alias for the combination of WithFirstError and
|
||||||
|
// WithCancelOnError. By default, the errors from all tasks are returned and
|
||||||
|
// the pool's context is not canceled until the parent context is canceled.
|
||||||
|
func (p *ResultContextPool[T]) WithFailFast() *ResultContextPool[T] {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.contextPool.WithFailFast()
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMaxGoroutines limits the number of goroutines in a pool.
|
||||||
|
// Defaults to unlimited. Panics if n < 1.
|
||||||
|
func (p *ResultContextPool[T]) WithMaxGoroutines(n int) *ResultContextPool[T] {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.contextPool.WithMaxGoroutines(n)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ResultContextPool[T]) panicIfInitialized() {
|
||||||
|
p.contextPool.panicIfInitialized()
|
||||||
|
}
|
||||||
80
vendor/github.com/sourcegraph/conc/pool/result_error_pool.go
generated
vendored
Normal file
80
vendor/github.com/sourcegraph/conc/pool/result_error_pool.go
generated
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
package pool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ResultErrorPool is a pool that executes tasks that return a generic result
|
||||||
|
// type and an error. Tasks are executed in the pool with Go(), then the
|
||||||
|
// results of the tasks are returned by Wait().
|
||||||
|
//
|
||||||
|
// The order of the results is guaranteed to be the same as the order the
|
||||||
|
// tasks were submitted.
|
||||||
|
//
|
||||||
|
// The configuration methods (With*) will panic if they are used after calling
|
||||||
|
// Go() for the first time.
|
||||||
|
type ResultErrorPool[T any] struct {
|
||||||
|
errorPool ErrorPool
|
||||||
|
agg resultAggregator[T]
|
||||||
|
collectErrored bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go submits a task to the pool. If all goroutines in the pool
|
||||||
|
// are busy, a call to Go() will block until the task can be started.
|
||||||
|
func (p *ResultErrorPool[T]) Go(f func() (T, error)) {
|
||||||
|
idx := p.agg.nextIndex()
|
||||||
|
p.errorPool.Go(func() error {
|
||||||
|
res, err := f()
|
||||||
|
p.agg.save(idx, res, err != nil)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait cleans up any spawned goroutines, propagating any panics and
|
||||||
|
// returning the results and any errors from tasks.
|
||||||
|
func (p *ResultErrorPool[T]) Wait() ([]T, error) {
|
||||||
|
err := p.errorPool.Wait()
|
||||||
|
results := p.agg.collect(p.collectErrored)
|
||||||
|
p.agg = resultAggregator[T]{} // reset for reuse
|
||||||
|
return results, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCollectErrored configures the pool to still collect the result of a task
|
||||||
|
// even if the task returned an error. By default, the result of tasks that errored
|
||||||
|
// are ignored and only the error is collected.
|
||||||
|
func (p *ResultErrorPool[T]) WithCollectErrored() *ResultErrorPool[T] {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.collectErrored = true
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithContext converts the pool to a ResultContextPool for tasks that should
|
||||||
|
// run under the same context, such that they each respect shared cancellation.
|
||||||
|
// For example, WithCancelOnError can be configured on the returned pool to
|
||||||
|
// signal that all goroutines should be cancelled upon the first error.
|
||||||
|
func (p *ResultErrorPool[T]) WithContext(ctx context.Context) *ResultContextPool[T] {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
return &ResultContextPool[T]{
|
||||||
|
contextPool: *p.errorPool.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFirstError configures the pool to only return the first error
|
||||||
|
// returned by a task. By default, Wait() will return a combined error.
|
||||||
|
func (p *ResultErrorPool[T]) WithFirstError() *ResultErrorPool[T] {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.errorPool.WithFirstError()
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMaxGoroutines limits the number of goroutines in a pool.
|
||||||
|
// Defaults to unlimited. Panics if n < 1.
|
||||||
|
func (p *ResultErrorPool[T]) WithMaxGoroutines(n int) *ResultErrorPool[T] {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.errorPool.WithMaxGoroutines(n)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ResultErrorPool[T]) panicIfInitialized() {
|
||||||
|
p.errorPool.panicIfInitialized()
|
||||||
|
}
|
||||||
142
vendor/github.com/sourcegraph/conc/pool/result_pool.go
generated
vendored
Normal file
142
vendor/github.com/sourcegraph/conc/pool/result_pool.go
generated
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
package pool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewWithResults creates a new ResultPool for tasks with a result of type T.
|
||||||
|
//
|
||||||
|
// The configuration methods (With*) will panic if they are used after calling
|
||||||
|
// Go() for the first time.
|
||||||
|
func NewWithResults[T any]() *ResultPool[T] {
|
||||||
|
return &ResultPool[T]{
|
||||||
|
pool: *New(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResultPool is a pool that executes tasks that return a generic result type.
|
||||||
|
// Tasks are executed in the pool with Go(), then the results of the tasks are
|
||||||
|
// returned by Wait().
|
||||||
|
//
|
||||||
|
// The order of the results is guaranteed to be the same as the order the
|
||||||
|
// tasks were submitted.
|
||||||
|
type ResultPool[T any] struct {
|
||||||
|
pool Pool
|
||||||
|
agg resultAggregator[T]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go submits a task to the pool. If all goroutines in the pool
|
||||||
|
// are busy, a call to Go() will block until the task can be started.
|
||||||
|
func (p *ResultPool[T]) Go(f func() T) {
|
||||||
|
idx := p.agg.nextIndex()
|
||||||
|
p.pool.Go(func() {
|
||||||
|
p.agg.save(idx, f(), false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait cleans up all spawned goroutines, propagating any panics, and returning
|
||||||
|
// a slice of results from tasks that did not panic.
|
||||||
|
func (p *ResultPool[T]) Wait() []T {
|
||||||
|
p.pool.Wait()
|
||||||
|
results := p.agg.collect(true)
|
||||||
|
p.agg = resultAggregator[T]{} // reset for reuse
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxGoroutines returns the maximum size of the pool.
|
||||||
|
func (p *ResultPool[T]) MaxGoroutines() int {
|
||||||
|
return p.pool.MaxGoroutines()
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithErrors converts the pool to an ResultErrorPool so the submitted tasks
|
||||||
|
// can return errors.
|
||||||
|
func (p *ResultPool[T]) WithErrors() *ResultErrorPool[T] {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
return &ResultErrorPool[T]{
|
||||||
|
errorPool: *p.pool.WithErrors(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithContext converts the pool to a ResultContextPool for tasks that should
|
||||||
|
// run under the same context, such that they each respect shared cancellation.
|
||||||
|
// For example, WithCancelOnError can be configured on the returned pool to
|
||||||
|
// signal that all goroutines should be cancelled upon the first error.
|
||||||
|
func (p *ResultPool[T]) WithContext(ctx context.Context) *ResultContextPool[T] {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
return &ResultContextPool[T]{
|
||||||
|
contextPool: *p.pool.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMaxGoroutines limits the number of goroutines in a pool.
|
||||||
|
// Defaults to unlimited. Panics if n < 1.
|
||||||
|
func (p *ResultPool[T]) WithMaxGoroutines(n int) *ResultPool[T] {
|
||||||
|
p.panicIfInitialized()
|
||||||
|
p.pool.WithMaxGoroutines(n)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ResultPool[T]) panicIfInitialized() {
|
||||||
|
p.pool.panicIfInitialized()
|
||||||
|
}
|
||||||
|
|
||||||
|
// resultAggregator is a utility type that lets us safely append from multiple
|
||||||
|
// goroutines. The zero value is valid and ready to use.
|
||||||
|
type resultAggregator[T any] struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
len int
|
||||||
|
results []T
|
||||||
|
errored []int
|
||||||
|
}
|
||||||
|
|
||||||
|
// nextIndex reserves a slot for a result. The returned value should be passed
|
||||||
|
// to save() when adding a result to the aggregator.
|
||||||
|
func (r *resultAggregator[T]) nextIndex() int {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
nextIdx := r.len
|
||||||
|
r.len += 1
|
||||||
|
return nextIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resultAggregator[T]) save(i int, res T, errored bool) {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
if i >= len(r.results) {
|
||||||
|
old := r.results
|
||||||
|
r.results = make([]T, r.len)
|
||||||
|
copy(r.results, old)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.results[i] = res
|
||||||
|
|
||||||
|
if errored {
|
||||||
|
r.errored = append(r.errored, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect returns the set of aggregated results.
|
||||||
|
func (r *resultAggregator[T]) collect(collectErrored bool) []T {
|
||||||
|
if !r.mu.TryLock() {
|
||||||
|
panic("collect should not be called until all goroutines have exited")
|
||||||
|
}
|
||||||
|
|
||||||
|
if collectErrored || len(r.errored) == 0 {
|
||||||
|
return r.results
|
||||||
|
}
|
||||||
|
|
||||||
|
filtered := r.results[:0]
|
||||||
|
sort.Ints(r.errored)
|
||||||
|
for i, e := range r.errored {
|
||||||
|
if i == 0 {
|
||||||
|
filtered = append(filtered, r.results[:e]...)
|
||||||
|
} else {
|
||||||
|
filtered = append(filtered, r.results[r.errored[i-1]+1:e]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered
|
||||||
|
}
|
||||||
3
vendor/github.com/spf13/afero/.editorconfig
generated
vendored
3
vendor/github.com/spf13/afero/.editorconfig
generated
vendored
|
|
@ -10,3 +10,6 @@ trim_trailing_whitespace = true
|
||||||
|
|
||||||
[*.go]
|
[*.go]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
|
|
||||||
|
[{*.yml,*.yaml}]
|
||||||
|
indent_size = 2
|
||||||
|
|
|
||||||
60
vendor/github.com/spf13/afero/.golangci.yaml
generated
vendored
60
vendor/github.com/spf13/afero/.golangci.yaml
generated
vendored
|
|
@ -1,18 +1,48 @@
|
||||||
linters-settings:
|
version: "2"
|
||||||
gci:
|
|
||||||
sections:
|
run:
|
||||||
- standard
|
timeout: 10m
|
||||||
- default
|
|
||||||
- prefix(github.com/spf13/afero)
|
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
disable-all: true
|
enable:
|
||||||
enable:
|
- govet
|
||||||
- gci
|
- ineffassign
|
||||||
- gofmt
|
- misspell
|
||||||
- gofumpt
|
- nolintlint
|
||||||
- staticcheck
|
# - revive
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
|
||||||
issues:
|
disable:
|
||||||
exclude-dirs:
|
- errcheck
|
||||||
- gcsfs/internal/stiface
|
# - staticcheck
|
||||||
|
|
||||||
|
settings:
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
nolintlint:
|
||||||
|
allow-unused: false # report any unused nolint directives
|
||||||
|
require-specific: false # don't require nolint directives to be specific about which linter is being skipped
|
||||||
|
|
||||||
|
exclusions:
|
||||||
|
paths:
|
||||||
|
- gcsfs/internal/stiface
|
||||||
|
|
||||||
|
formatters:
|
||||||
|
enable:
|
||||||
|
- gci
|
||||||
|
- gofmt
|
||||||
|
- gofumpt
|
||||||
|
- goimports
|
||||||
|
- golines
|
||||||
|
|
||||||
|
settings:
|
||||||
|
gci:
|
||||||
|
sections:
|
||||||
|
- standard
|
||||||
|
- default
|
||||||
|
- localmodule
|
||||||
|
|
||||||
|
exclusions:
|
||||||
|
paths:
|
||||||
|
- gcsfs/internal/stiface
|
||||||
|
|
|
||||||
728
vendor/github.com/spf13/afero/README.md
generated
vendored
728
vendor/github.com/spf13/afero/README.md
generated
vendored
|
|
@ -1,442 +1,474 @@
|
||||||

|
<img src="https://cloud.githubusercontent.com/assets/173412/11490338/d50e16dc-97a5-11e5-8b12-019a300d0fcb.png" alt="afero logo-sm"/>
|
||||||
|
|
||||||
A FileSystem Abstraction System for Go
|
|
||||||
|
|
||||||
[](https://github.com/spf13/afero/actions/workflows/test.yml) [](https://godoc.org/github.com/spf13/afero) [](https://gitter.im/spf13/afero?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
||||||
|
|
||||||
# Overview
|
|
||||||
|
|
||||||
Afero is a filesystem framework providing a simple, uniform and universal API
|
|
||||||
interacting with any filesystem, as an abstraction layer providing interfaces,
|
|
||||||
types and methods. Afero has an exceptionally clean interface and simple design
|
|
||||||
without needless constructors or initialization methods.
|
|
||||||
|
|
||||||
Afero is also a library providing a base set of interoperable backend
|
|
||||||
filesystems that make it easy to work with, while retaining all the power
|
|
||||||
and benefit of the os and ioutil packages.
|
|
||||||
|
|
||||||
Afero provides significant improvements over using the os package alone, most
|
|
||||||
notably the ability to create mock and testing filesystems without relying on the disk.
|
|
||||||
|
|
||||||
It is suitable for use in any situation where you would consider using the OS
|
|
||||||
package as it provides an additional abstraction that makes it easy to use a
|
|
||||||
memory backed file system during testing. It also adds support for the http
|
|
||||||
filesystem for full interoperability.
|
|
||||||
|
|
||||||
|
|
||||||
## Afero Features
|
[](https://github.com/spf13/afero/actions?query=workflow%3ACI)
|
||||||
|
[](https://pkg.go.dev/mod/github.com/spf13/afero)
|
||||||
|
[](https://goreportcard.com/report/github.com/spf13/afero)
|
||||||
|

|
||||||
|
|
||||||
* A single consistent API for accessing a variety of filesystems
|
|
||||||
* Interoperation between a variety of file system types
|
|
||||||
* A set of interfaces to encourage and enforce interoperability between backends
|
|
||||||
* An atomic cross platform memory backed file system
|
|
||||||
* Support for compositional (union) file systems by combining multiple file systems acting as one
|
|
||||||
* Specialized backends which modify existing filesystems (Read Only, Regexp filtered)
|
|
||||||
* A set of utility functions ported from io, ioutil & hugo to be afero aware
|
|
||||||
* Wrapper for go 1.16 filesystem abstraction `io/fs.FS`
|
|
||||||
|
|
||||||
# Using Afero
|
# Afero: The Universal Filesystem Abstraction for Go
|
||||||
|
|
||||||
Afero is easy to use and easier to adopt.
|
Afero is a powerful and extensible filesystem abstraction system for Go. It provides a single, unified API for interacting with diverse filesystems—including the local disk, memory, archives, and network storage.
|
||||||
|
|
||||||
A few different ways you could use Afero:
|
Afero acts as a drop-in replacement for the standard `os` package, enabling you to write modular code that is agnostic to the underlying storage, dramatically simplifies testing, and allows for sophisticated architectural patterns through filesystem composition.
|
||||||
|
|
||||||
* Use the interfaces alone to define your own file system.
|
## Why Afero?
|
||||||
* Wrapper for the OS packages.
|
|
||||||
* Define different filesystems for different parts of your application.
|
|
||||||
* Use Afero for mock filesystems while testing
|
|
||||||
|
|
||||||
## Step 1: Install Afero
|
Afero elevates filesystem interaction beyond simple file reading and writing, offering solutions for testability, flexibility, and advanced architecture.
|
||||||
|
|
||||||
First use go get to install the latest version of the library.
|
🔑 **Key Features:**
|
||||||
|
|
||||||
$ go get github.com/spf13/afero
|
* **Universal API:** Write your code once. Run it against the local OS, in-memory storage, ZIP/TAR archives, or remote systems (SFTP, GCS).
|
||||||
|
* **Ultimate Testability:** Utilize `MemMapFs`, a fully concurrent-safe, read/write in-memory filesystem. Write fast, isolated, and reliable unit tests without touching the physical disk or worrying about cleanup.
|
||||||
|
* **Powerful Composition:** Afero's hidden superpower. Layer filesystems on top of each other to create sophisticated behaviors:
|
||||||
|
* **Sandboxing:** Use `CopyOnWriteFs` to create temporary scratch spaces that isolate changes from the base filesystem.
|
||||||
|
* **Caching:** Use `CacheOnReadFs` to automatically layer a fast cache (like memory) over a slow backend (like a network drive).
|
||||||
|
* **Security Jails:** Use `BasePathFs` to restrict application access to a specific subdirectory (chroot).
|
||||||
|
* **`os` Package Compatibility:** Afero mirrors the functions in the standard `os` package, making adoption and refactoring seamless.
|
||||||
|
* **`io/fs` Compatibility:** Fully compatible with the Go standard library's `io/fs` interfaces.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go get github.com/spf13/afero
|
||||||
|
```
|
||||||
|
|
||||||
Next include Afero in your application.
|
|
||||||
```go
|
```go
|
||||||
import "github.com/spf13/afero"
|
import "github.com/spf13/afero"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 2: Declare a backend
|
## Quick Start: The Power of Abstraction
|
||||||
|
|
||||||
First define a package variable and set it to a pointer to a filesystem.
|
The core of Afero is the `afero.Fs` interface. By designing your functions to accept this interface rather than calling `os.*` functions directly, your code instantly becomes more flexible and testable.
|
||||||
```go
|
|
||||||
var AppFs = afero.NewMemMapFs()
|
|
||||||
|
|
||||||
or
|
### 1. Refactor Your Code
|
||||||
|
|
||||||
var AppFs = afero.NewOsFs()
|
Change functions that rely on the `os` package to accept `afero.Fs`.
|
||||||
```
|
|
||||||
It is important to note that if you repeat the composite literal you
|
|
||||||
will be using a completely new and isolated filesystem. In the case of
|
|
||||||
OsFs it will still use the same underlying filesystem but will reduce
|
|
||||||
the ability to drop in other filesystems as desired.
|
|
||||||
|
|
||||||
## Step 3: Use it like you would the OS package
|
|
||||||
|
|
||||||
Throughout your application use any function and method like you normally
|
|
||||||
would.
|
|
||||||
|
|
||||||
So if my application before had:
|
|
||||||
```go
|
|
||||||
os.Open("/tmp/foo")
|
|
||||||
```
|
|
||||||
We would replace it with:
|
|
||||||
```go
|
|
||||||
AppFs.Open("/tmp/foo")
|
|
||||||
```
|
|
||||||
|
|
||||||
`AppFs` being the variable we defined above.
|
|
||||||
|
|
||||||
|
|
||||||
## List of all available functions
|
|
||||||
|
|
||||||
File System Methods Available:
|
|
||||||
```go
|
|
||||||
Chmod(name string, mode os.FileMode) : error
|
|
||||||
Chown(name string, uid, gid int) : error
|
|
||||||
Chtimes(name string, atime time.Time, mtime time.Time) : error
|
|
||||||
Create(name string) : File, error
|
|
||||||
Mkdir(name string, perm os.FileMode) : error
|
|
||||||
MkdirAll(path string, perm os.FileMode) : error
|
|
||||||
Name() : string
|
|
||||||
Open(name string) : File, error
|
|
||||||
OpenFile(name string, flag int, perm os.FileMode) : File, error
|
|
||||||
Remove(name string) : error
|
|
||||||
RemoveAll(path string) : error
|
|
||||||
Rename(oldname, newname string) : error
|
|
||||||
Stat(name string) : os.FileInfo, error
|
|
||||||
```
|
|
||||||
File Interfaces and Methods Available:
|
|
||||||
```go
|
|
||||||
io.Closer
|
|
||||||
io.Reader
|
|
||||||
io.ReaderAt
|
|
||||||
io.Seeker
|
|
||||||
io.Writer
|
|
||||||
io.WriterAt
|
|
||||||
|
|
||||||
Name() : string
|
|
||||||
Readdir(count int) : []os.FileInfo, error
|
|
||||||
Readdirnames(n int) : []string, error
|
|
||||||
Stat() : os.FileInfo, error
|
|
||||||
Sync() : error
|
|
||||||
Truncate(size int64) : error
|
|
||||||
WriteString(s string) : ret int, err error
|
|
||||||
```
|
|
||||||
In some applications it may make sense to define a new package that
|
|
||||||
simply exports the file system variable for easy access from anywhere.
|
|
||||||
|
|
||||||
## Using Afero's utility functions
|
|
||||||
|
|
||||||
Afero provides a set of functions to make it easier to use the underlying file systems.
|
|
||||||
These functions have been primarily ported from io & ioutil with some developed for Hugo.
|
|
||||||
|
|
||||||
The afero utilities support all afero compatible backends.
|
|
||||||
|
|
||||||
The list of utilities includes:
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
DirExists(path string) (bool, error)
|
// Before: Coupled to the OS and difficult to test
|
||||||
Exists(path string) (bool, error)
|
// func ProcessConfiguration(path string) error {
|
||||||
FileContainsBytes(filename string, subslice []byte) (bool, error)
|
// data, err := os.ReadFile(path)
|
||||||
GetTempDir(subPath string) string
|
// ...
|
||||||
IsDir(path string) (bool, error)
|
// }
|
||||||
IsEmpty(path string) (bool, error)
|
|
||||||
ReadDir(dirname string) ([]os.FileInfo, error)
|
|
||||||
ReadFile(filename string) ([]byte, error)
|
|
||||||
SafeWriteReader(path string, r io.Reader) (err error)
|
|
||||||
TempDir(dir, prefix string) (name string, err error)
|
|
||||||
TempFile(dir, prefix string) (f File, err error)
|
|
||||||
Walk(root string, walkFn filepath.WalkFunc) error
|
|
||||||
WriteFile(filename string, data []byte, perm os.FileMode) error
|
|
||||||
WriteReader(path string, r io.Reader) (err error)
|
|
||||||
```
|
|
||||||
For a complete list see [Afero's GoDoc](https://godoc.org/github.com/spf13/afero)
|
|
||||||
|
|
||||||
They are available under two different approaches to use. You can either call
|
import "github.com/spf13/afero"
|
||||||
them directly where the first parameter of each function will be the file
|
|
||||||
system, or you can declare a new `Afero`, a custom type used to bind these
|
|
||||||
functions as methods to a given filesystem.
|
|
||||||
|
|
||||||
### Calling utilities directly
|
// After: Decoupled, flexible, and testable
|
||||||
|
func ProcessConfiguration(fs afero.Fs, path string) error {
|
||||||
```go
|
// Use Afero utility functions which mirror os/ioutil
|
||||||
fs := new(afero.MemMapFs)
|
data, err := afero.ReadFile(fs, path)
|
||||||
f, err := afero.TempFile(fs,"", "ioutil-test")
|
// ... process the data
|
||||||
|
return err
|
||||||
```
|
|
||||||
|
|
||||||
### Calling via Afero
|
|
||||||
|
|
||||||
```go
|
|
||||||
fs := afero.NewMemMapFs()
|
|
||||||
afs := &afero.Afero{Fs: fs}
|
|
||||||
f, err := afs.TempFile("", "ioutil-test")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using Afero for Testing
|
|
||||||
|
|
||||||
There is a large benefit to using a mock filesystem for testing. It has a
|
|
||||||
completely blank state every time it is initialized and can be easily
|
|
||||||
reproducible regardless of OS. You could create files to your heart’s content
|
|
||||||
and the file access would be fast while also saving you from all the annoying
|
|
||||||
issues with deleting temporary files, Windows file locking, etc. The MemMapFs
|
|
||||||
backend is perfect for testing.
|
|
||||||
|
|
||||||
* Much faster than performing I/O operations on disk
|
|
||||||
* Avoid security issues and permissions
|
|
||||||
* Far more control. 'rm -rf /' with confidence
|
|
||||||
* Test setup is far more easier to do
|
|
||||||
* No test cleanup needed
|
|
||||||
|
|
||||||
One way to accomplish this is to define a variable as mentioned above.
|
|
||||||
In your application this will be set to afero.NewOsFs() during testing you
|
|
||||||
can set it to afero.NewMemMapFs().
|
|
||||||
|
|
||||||
It wouldn't be uncommon to have each test initialize a blank slate memory
|
|
||||||
backend. To do this I would define my `appFS = afero.NewOsFs()` somewhere
|
|
||||||
appropriate in my application code. This approach ensures that Tests are order
|
|
||||||
independent, with no test relying on the state left by an earlier test.
|
|
||||||
|
|
||||||
Then in my tests I would initialize a new MemMapFs for each test:
|
|
||||||
```go
|
|
||||||
func TestExist(t *testing.T) {
|
|
||||||
appFS := afero.NewMemMapFs()
|
|
||||||
// create test files and directories
|
|
||||||
appFS.MkdirAll("src/a", 0755)
|
|
||||||
afero.WriteFile(appFS, "src/a/b", []byte("file b"), 0644)
|
|
||||||
afero.WriteFile(appFS, "src/c", []byte("file c"), 0644)
|
|
||||||
name := "src/c"
|
|
||||||
_, err := appFS.Stat(name)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
t.Errorf("file \"%s\" does not exist.\n", name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
# Available Backends
|
### 2. Usage in Production
|
||||||
|
|
||||||
## Operating System Native
|
In your production environment, inject the `OsFs` backend, which wraps the standard operating system calls.
|
||||||
|
|
||||||
### OsFs
|
|
||||||
|
|
||||||
The first is simply a wrapper around the native OS calls. This makes it
|
|
||||||
very easy to use as all of the calls are the same as the existing OS
|
|
||||||
calls. It also makes it trivial to have your code use the OS during
|
|
||||||
operation and a mock filesystem during testing or as needed.
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
appfs := afero.NewOsFs()
|
func main() {
|
||||||
appfs.MkdirAll("src/a", 0755)
|
// Use the real OS filesystem
|
||||||
|
AppFs := afero.NewOsFs()
|
||||||
|
ProcessConfiguration(AppFs, "/etc/myapp.conf")
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Memory Backed Storage
|
### 3. Usage in Testing
|
||||||
|
|
||||||
### MemMapFs
|
In your tests, inject `MemMapFs`. This provides a blazing-fast, isolated, in-memory filesystem that requires no disk I/O and no cleanup.
|
||||||
|
|
||||||
Afero also provides a fully atomic memory backed filesystem perfect for use in
|
|
||||||
mocking and to speed up unnecessary disk io when persistence isn’t
|
|
||||||
necessary. It is fully concurrent and will work within go routines
|
|
||||||
safely.
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
mm := afero.NewMemMapFs()
|
func TestProcessConfiguration(t *testing.T) {
|
||||||
mm.MkdirAll("src/a", 0755)
|
// Use the in-memory filesystem
|
||||||
|
AppFs := afero.NewMemMapFs()
|
||||||
|
|
||||||
|
// Pre-populate the memory filesystem for the test
|
||||||
|
configPath := "/test/config.json"
|
||||||
|
afero.WriteFile(AppFs, configPath, []byte(`{"feature": true}`), 0644)
|
||||||
|
|
||||||
|
// Run the test entirely in memory
|
||||||
|
err := ProcessConfiguration(AppFs, configPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### InMemoryFile
|
## Afero's Superpower: Composition
|
||||||
|
|
||||||
As part of MemMapFs, Afero also provides an atomic, fully concurrent memory
|
Afero's most unique feature is its ability to combine filesystems. This allows you to build complex behaviors out of simple components, keeping your application logic clean.
|
||||||
backed file implementation. This can be used in other memory backed file
|
|
||||||
systems with ease. Plans are to add a radix tree memory stored file
|
|
||||||
system using InMemoryFile.
|
|
||||||
|
|
||||||
## Network Interfaces
|
### Example 1: Sandboxing with Copy-on-Write
|
||||||
|
|
||||||
### SftpFs
|
Create a temporary environment where an application can "modify" system files without affecting the actual disk.
|
||||||
|
|
||||||
Afero has experimental support for secure file transfer protocol (sftp). Which can
|
|
||||||
be used to perform file operations over a encrypted channel.
|
|
||||||
|
|
||||||
### GCSFs
|
|
||||||
|
|
||||||
Afero has experimental support for Google Cloud Storage (GCS). You can either set the
|
|
||||||
`GOOGLE_APPLICATION_CREDENTIALS_JSON` env variable to your JSON credentials or use `opts` in
|
|
||||||
`NewGcsFS` to configure access to your GCS bucket.
|
|
||||||
|
|
||||||
Some known limitations of the existing implementation:
|
|
||||||
* No Chmod support - The GCS ACL could probably be mapped to *nix style permissions but that would add another level of complexity and is ignored in this version.
|
|
||||||
* No Chtimes support - Could be simulated with attributes (gcs a/m-times are set implicitly) but that's is left for another version.
|
|
||||||
* Not thread safe - Also assumes all file operations are done through the same instance of the GcsFs. File operations between different GcsFs instances are not guaranteed to be consistent.
|
|
||||||
|
|
||||||
|
|
||||||
## Filtering Backends
|
|
||||||
|
|
||||||
### BasePathFs
|
|
||||||
|
|
||||||
The BasePathFs restricts all operations to a given path within an Fs.
|
|
||||||
The given file name to the operations on this Fs will be prepended with
|
|
||||||
the base path before calling the source Fs.
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
bp := afero.NewBasePathFs(afero.NewOsFs(), "/base/path")
|
// 1. The base layer is the real OS, made read-only for safety.
|
||||||
|
baseFs := afero.NewReadOnlyFs(afero.NewOsFs())
|
||||||
|
|
||||||
|
// 2. The overlay layer is a temporary in-memory filesystem for changes.
|
||||||
|
overlayFs := afero.NewMemMapFs()
|
||||||
|
|
||||||
|
// 3. Combine them. Reads fall through to the base; writes only hit the overlay.
|
||||||
|
sandboxFs := afero.NewCopyOnWriteFs(baseFs, overlayFs)
|
||||||
|
|
||||||
|
// The application can now "modify" /etc/hosts, but the changes are isolated in memory.
|
||||||
|
afero.WriteFile(sandboxFs, "/etc/hosts", []byte("127.0.0.1 sandboxed-app"), 0644)
|
||||||
|
|
||||||
|
// The real /etc/hosts on disk is untouched.
|
||||||
```
|
```
|
||||||
|
|
||||||
### ReadOnlyFs
|
### Example 2: Caching a Slow Filesystem
|
||||||
|
|
||||||
A thin wrapper around the source Fs providing a read only view.
|
Improve performance by layering a fast cache (like memory) over a slow backend (like a network drive or cloud storage).
|
||||||
|
|
||||||
```go
|
```go
|
||||||
fs := afero.NewReadOnlyFs(afero.NewOsFs())
|
import "time"
|
||||||
_, err := fs.Create("/file.txt")
|
|
||||||
// err = syscall.EPERM
|
// Assume 'remoteFs' is a slow backend (e.g., SFTP or GCS)
|
||||||
|
var remoteFs afero.Fs
|
||||||
|
|
||||||
|
// 'cacheFs' is a fast in-memory backend
|
||||||
|
cacheFs := afero.NewMemMapFs()
|
||||||
|
|
||||||
|
// Create the caching layer. Cache items for 5 minutes upon first read.
|
||||||
|
cachedFs := afero.NewCacheOnReadFs(remoteFs, cacheFs, 5*time.Minute)
|
||||||
|
|
||||||
|
// The first read is slow (fetches from remote, then caches)
|
||||||
|
data1, _ := afero.ReadFile(cachedFs, "data.json")
|
||||||
|
|
||||||
|
// The second read is instant (serves from memory cache)
|
||||||
|
data2, _ := afero.ReadFile(cachedFs, "data.json")
|
||||||
```
|
```
|
||||||
|
|
||||||
# RegexpFs
|
### Example 3: Security Jails (chroot)
|
||||||
|
|
||||||
A filtered view on file names, any file NOT matching
|
Restrict an application component's access to a specific subdirectory.
|
||||||
the passed regexp will be treated as non-existing.
|
|
||||||
Files not matching the regexp provided will not be created.
|
|
||||||
Directories are not filtered.
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
fs := afero.NewRegexpFs(afero.NewMemMapFs(), regexp.MustCompile(`\.txt$`))
|
osFs := afero.NewOsFs()
|
||||||
_, err := fs.Create("/file.html")
|
|
||||||
// err = syscall.ENOENT
|
// Create a filesystem rooted at /home/user/public
|
||||||
|
// The application cannot access anything above this directory.
|
||||||
|
jailedFs := afero.NewBasePathFs(osFs, "/home/user/public")
|
||||||
|
|
||||||
|
// To the application, this is reading "/"
|
||||||
|
// In reality, it's reading "/home/user/public/"
|
||||||
|
dirInfo, err := afero.ReadDir(jailedFs, "/")
|
||||||
|
|
||||||
|
// Attempts to access parent directories fail
|
||||||
|
_, err = jailedFs.Open("../secrets.txt") // Returns an error
|
||||||
```
|
```
|
||||||
|
|
||||||
### HttpFs
|
## Real-World Use Cases
|
||||||
|
|
||||||
Afero provides an http compatible backend which can wrap any of the existing
|
### Build Cloud-Agnostic Applications
|
||||||
backends.
|
|
||||||
|
|
||||||
The Http package requires a slightly specific version of Open which
|
Write applications that seamlessly work with different storage backends:
|
||||||
returns an http.File type.
|
|
||||||
|
|
||||||
Afero provides an httpFs file system which satisfies this requirement.
|
|
||||||
Any Afero FileSystem can be used as an httpFs.
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
httpFs := afero.NewHttpFs(<ExistingFS>)
|
type DocumentProcessor struct {
|
||||||
fileserver := http.FileServer(httpFs.Dir(<PATH>))
|
fs afero.Fs
|
||||||
http.Handle("/", fileserver)
|
}
|
||||||
|
|
||||||
|
func NewDocumentProcessor(fs afero.Fs) *DocumentProcessor {
|
||||||
|
return &DocumentProcessor{fs: fs}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DocumentProcessor) Process(inputPath, outputPath string) error {
|
||||||
|
// This code works whether fs is local disk, cloud storage, or memory
|
||||||
|
content, err := afero.ReadFile(p.fs, inputPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
processed := processContent(content)
|
||||||
|
return afero.WriteFile(p.fs, outputPath, processed, 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use with local filesystem
|
||||||
|
processor := NewDocumentProcessor(afero.NewOsFs())
|
||||||
|
|
||||||
|
// Use with Google Cloud Storage
|
||||||
|
processor := NewDocumentProcessor(gcsFS)
|
||||||
|
|
||||||
|
// Use with in-memory filesystem for testing
|
||||||
|
processor := NewDocumentProcessor(afero.NewMemMapFs())
|
||||||
```
|
```
|
||||||
|
|
||||||
## Composite Backends
|
### Treating Archives as Filesystems
|
||||||
|
|
||||||
Afero provides the ability have two filesystems (or more) act as a single
|
Read files directly from `.zip` or `.tar` archives without unpacking them to disk first.
|
||||||
file system.
|
|
||||||
|
|
||||||
### CacheOnReadFs
|
|
||||||
|
|
||||||
The CacheOnReadFs will lazily make copies of any accessed files from the base
|
|
||||||
layer into the overlay. Subsequent reads will be pulled from the overlay
|
|
||||||
directly permitting the request is within the cache duration of when it was
|
|
||||||
created in the overlay.
|
|
||||||
|
|
||||||
If the base filesystem is writeable, any changes to files will be
|
|
||||||
done first to the base, then to the overlay layer. Write calls to open file
|
|
||||||
handles like `Write()` or `Truncate()` to the overlay first.
|
|
||||||
|
|
||||||
To writing files to the overlay only, you can use the overlay Fs directly (not
|
|
||||||
via the union Fs).
|
|
||||||
|
|
||||||
Cache files in the layer for the given time.Duration, a cache duration of 0
|
|
||||||
means "forever" meaning the file will not be re-requested from the base ever.
|
|
||||||
|
|
||||||
A read-only base will make the overlay also read-only but still copy files
|
|
||||||
from the base to the overlay when they're not present (or outdated) in the
|
|
||||||
caching layer.
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
base := afero.NewOsFs()
|
import (
|
||||||
layer := afero.NewMemMapFs()
|
"archive/zip"
|
||||||
ufs := afero.NewCacheOnReadFs(base, layer, 100 * time.Second)
|
"github.com/spf13/afero/zipfs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Assume 'zipReader' is a *zip.Reader initialized from a file or memory
|
||||||
|
var zipReader *zip.Reader
|
||||||
|
|
||||||
|
// Create a read-only ZipFs
|
||||||
|
archiveFS := zipfs.New(zipReader)
|
||||||
|
|
||||||
|
// Read a file from within the archive using the standard Afero API
|
||||||
|
content, err := afero.ReadFile(archiveFS, "/docs/readme.md")
|
||||||
```
|
```
|
||||||
|
|
||||||
### CopyOnWriteFs()
|
### Serving Any Filesystem over HTTP
|
||||||
|
|
||||||
The CopyOnWriteFs is a read only base file system with a potentially
|
Use `HttpFs` to expose any Afero filesystem—even one created dynamically in memory—through a standard Go web server.
|
||||||
writeable layer on top.
|
|
||||||
|
|
||||||
Read operations will first look in the overlay and if not found there, will
|
|
||||||
serve the file from the base.
|
|
||||||
|
|
||||||
Changes to the file system will only be made in the overlay.
|
|
||||||
|
|
||||||
Any attempt to modify a file found only in the base will copy the file to the
|
|
||||||
overlay layer before modification (including opening a file with a writable
|
|
||||||
handle).
|
|
||||||
|
|
||||||
Removing and Renaming files present only in the base layer is not currently
|
|
||||||
permitted. If a file is present in the base layer and the overlay, only the
|
|
||||||
overlay will be removed/renamed.
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
base := afero.NewOsFs()
|
import (
|
||||||
roBase := afero.NewReadOnlyFs(base)
|
"net/http"
|
||||||
ufs := afero.NewCopyOnWriteFs(roBase, afero.NewMemMapFs())
|
"github.com/spf13/afero"
|
||||||
|
)
|
||||||
|
|
||||||
fh, _ = ufs.Create("/home/test/file2.txt")
|
func main() {
|
||||||
fh.WriteString("This is a test")
|
memFS := afero.NewMemMapFs()
|
||||||
fh.Close()
|
afero.WriteFile(memFS, "index.html", []byte("<h1>Hello from Memory!</h1>"), 0644)
|
||||||
|
|
||||||
|
// Wrap the memory filesystem to make it compatible with http.FileServer.
|
||||||
|
httpFS := afero.NewHttpFs(memFS)
|
||||||
|
|
||||||
|
http.Handle("/", http.FileServer(httpFS.Dir("/")))
|
||||||
|
http.ListenAndServe(":8080", nil)
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example all write operations will only occur in memory (MemMapFs)
|
### Testing Made Simple
|
||||||
leaving the base filesystem (OsFs) untouched.
|
|
||||||
|
|
||||||
|
One of Afero's greatest strengths is making filesystem-dependent code easily testable:
|
||||||
|
|
||||||
## Desired/possible backends
|
```go
|
||||||
|
func SaveUserData(fs afero.Fs, userID string, data []byte) error {
|
||||||
|
filename := fmt.Sprintf("users/%s.json", userID)
|
||||||
|
return afero.WriteFile(fs, filename, data, 0644)
|
||||||
|
}
|
||||||
|
|
||||||
The following is a short list of possible backends we hope someone will
|
func TestSaveUserData(t *testing.T) {
|
||||||
implement:
|
// Create a clean, fast, in-memory filesystem for testing
|
||||||
|
testFS := afero.NewMemMapFs()
|
||||||
|
|
||||||
* SSH
|
userData := []byte(`{"name": "John", "email": "john@example.com"}`)
|
||||||
* S3
|
err := SaveUserData(testFS, "123", userData)
|
||||||
|
|
||||||
# About the project
|
if err != nil {
|
||||||
|
t.Fatalf("SaveUserData failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
## What's in the name
|
// Verify the file was saved correctly
|
||||||
|
saved, err := afero.ReadFile(testFS, "users/123.json")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to read saved file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
Afero comes from the latin roots Ad-Facere.
|
if string(saved) != string(userData) {
|
||||||
|
t.Errorf("Data mismatch: got %s, want %s", saved, userData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
**"Ad"** is a prefix meaning "to".
|
**Benefits of testing with Afero:**
|
||||||
|
- ⚡ **Fast** - No disk I/O, tests run in memory
|
||||||
|
- 🔄 **Reliable** - Each test starts with a clean slate
|
||||||
|
- 🧹 **No cleanup** - Memory is automatically freed
|
||||||
|
- 🔒 **Safe** - Can't accidentally modify real files
|
||||||
|
- 🏃 **Parallel** - Tests can run concurrently without conflicts
|
||||||
|
|
||||||
**"Facere"** is a form of the root "faciō" making "make or do".
|
## Backend Reference
|
||||||
|
|
||||||
The literal meaning of afero is "to make" or "to do" which seems very fitting
|
| Type | Backend | Constructor | Description | Status |
|
||||||
for a library that allows one to make files and directories and do things with them.
|
| :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| **Core** | **OsFs** | `afero.NewOsFs()` | Interacts with the real operating system filesystem. Use in production. | ✅ Official |
|
||||||
|
| | **MemMapFs** | `afero.NewMemMapFs()` | A fast, atomic, concurrent-safe, in-memory filesystem. Ideal for testing. | ✅ Official |
|
||||||
|
| **Composition** | **CopyOnWriteFs**| `afero.NewCopyOnWriteFs(base, overlay)` | A read-only base with a writable overlay. Ideal for sandboxing. | ✅ Official |
|
||||||
|
| | **CacheOnReadFs**| `afero.NewCacheOnReadFs(base, cache, ttl)` | Lazily caches files from a slow base into a fast layer on first read. | ✅ Official |
|
||||||
|
| | **BasePathFs** | `afero.NewBasePathFs(source, path)` | Restricts operations to a subdirectory (chroot/jail). | ✅ Official |
|
||||||
|
| | **ReadOnlyFs** | `afero.NewReadOnlyFs(source)` | Provides a read-only view, preventing any modifications. | ✅ Official |
|
||||||
|
| | **RegexpFs** | `afero.NewRegexpFs(source, regexp)` | Filters a filesystem, only showing files that match a regex. | ✅ Official |
|
||||||
|
| **Utility** | **HttpFs** | `afero.NewHttpFs(source)` | Wraps any Afero filesystem to be served via `http.FileServer`. | ✅ Official |
|
||||||
|
| **Archives** | **ZipFs** | `zipfs.New(zipReader)` | Read-only access to files within a ZIP archive. | ✅ Official |
|
||||||
|
| | **TarFs** | `tarfs.New(tarReader)` | Read-only access to files within a TAR archive. | ✅ Official |
|
||||||
|
| **Network** | **GcsFs** | `gcsfs.NewGcsFs(...)` | Google Cloud Storage backend. | ⚡ Experimental |
|
||||||
|
| | **SftpFs** | `sftpfs.New(...)` | SFTP backend. | ⚡ Experimental |
|
||||||
|
| **3rd Party Cloud** | **S3Fs** | [`fclairamb/afero-s3`](https://github.com/fclairamb/afero-s3) | Production-ready S3 backend built on official AWS SDK. | 🔹 3rd Party |
|
||||||
|
| | **MinioFs** | [`cpyun/afero-minio`](https://github.com/cpyun/afero-minio) | MinIO object storage backend with S3 compatibility. | 🔹 3rd Party |
|
||||||
|
| | **DriveFs** | [`fclairamb/afero-gdrive`](https://github.com/fclairamb/afero-gdrive) | Google Drive backend with streaming support. | 🔹 3rd Party |
|
||||||
|
| | **DropboxFs** | [`fclairamb/afero-dropbox`](https://github.com/fclairamb/afero-dropbox) | Dropbox backend with streaming support. | 🔹 3rd Party |
|
||||||
|
| **3rd Party Specialized** | **GitFs** | [`tobiash/go-gitfs`](https://github.com/tobiash/go-gitfs) | Git repository filesystem (read-only, Afero compatible). | 🔹 3rd Party |
|
||||||
|
| | **DockerFs** | [`unmango/aferox`](https://github.com/unmango/aferox) | Docker container filesystem access. | 🔹 3rd Party |
|
||||||
|
| | **GitHubFs** | [`unmango/aferox`](https://github.com/unmango/aferox) | GitHub repository and releases filesystem. | 🔹 3rd Party |
|
||||||
|
| | **FilterFs** | [`unmango/aferox`](https://github.com/unmango/aferox) | Filesystem filtering with predicates. | 🔹 3rd Party |
|
||||||
|
| | **IgnoreFs** | [`unmango/aferox`](https://github.com/unmango/aferox) | .gitignore-aware filtering filesystem. | 🔹 3rd Party |
|
||||||
|
| | **FUSEFs** | [`JakWai01/sile-fystem`](https://github.com/JakWai01/sile-fystem) | Generic FUSE implementation using any Afero backend. | 🔹 3rd Party |
|
||||||
|
|
||||||
The English word that shares the same roots as Afero is "affair". Affair shares
|
## Afero vs. `io/fs` (Go 1.16+)
|
||||||
the same concept but as a noun it means "something that is made or done" or "an
|
|
||||||
object of a particular type".
|
|
||||||
|
|
||||||
It's also nice that unlike some of my other libraries (hugo, cobra, viper) it
|
Go 1.16 introduced the `io/fs` package, which provides a standard abstraction for **read-only** filesystems.
|
||||||
Googles very well.
|
|
||||||
|
|
||||||
## Release Notes
|
Afero complements `io/fs` by focusing on different needs:
|
||||||
|
|
||||||
See the [Releases Page](https://github.com/spf13/afero/releases).
|
* **Use `io/fs` when:** You only need to read files and want to conform strictly to the standard library interfaces.
|
||||||
|
* **Use Afero when:**
|
||||||
|
* Your application needs to **create, write, modify, or delete** files.
|
||||||
|
* You need to test complex read/write interactions (e.g., renaming, concurrent writes).
|
||||||
|
* You need advanced compositional features (Copy-on-Write, Caching, etc.).
|
||||||
|
|
||||||
|
Afero is fully compatible with `io/fs`. You can wrap any Afero filesystem to satisfy the `fs.FS` interface using `afero.NewIOFS`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "io/fs"
|
||||||
|
|
||||||
|
// Create an Afero filesystem (writable)
|
||||||
|
var myAferoFs afero.Fs = afero.NewMemMapFs()
|
||||||
|
|
||||||
|
// Convert it to a standard library fs.FS (read-only view)
|
||||||
|
var myIoFs fs.FS = afero.NewIOFS(myAferoFs)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Third-Party Backends & Ecosystem
|
||||||
|
|
||||||
|
The Afero community has developed numerous backends and tools that extend the library's capabilities. Below are curated, well-maintained options organized by maturity and reliability.
|
||||||
|
|
||||||
|
### Featured Community Backends
|
||||||
|
|
||||||
|
These are mature, reliable backends that we can confidently recommend for production use:
|
||||||
|
|
||||||
|
#### **Amazon S3** - [`fclairamb/afero-s3`](https://github.com/fclairamb/afero-s3)
|
||||||
|
Production-ready S3 backend built on the official AWS SDK for Go.
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/fclairamb/afero-s3"
|
||||||
|
|
||||||
|
s3fs := s3.NewFs(bucket, session)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **MinIO** - [`cpyun/afero-minio`](https://github.com/cpyun/afero-minio)
|
||||||
|
MinIO object storage backend providing S3-compatible object storage with deduplication and optimization features.
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/cpyun/afero-minio"
|
||||||
|
|
||||||
|
minioFs := miniofs.NewMinioFs(ctx, "minio://endpoint/bucket")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Community & Specialized Backends
|
||||||
|
|
||||||
|
#### Cloud Storage
|
||||||
|
|
||||||
|
- **Google Drive** - [`fclairamb/afero-gdrive`](https://github.com/fclairamb/afero-gdrive)
|
||||||
|
Streaming support; no write-seeking or POSIX permissions; no files listing cache
|
||||||
|
|
||||||
|
- **Dropbox** - [`fclairamb/afero-dropbox`](https://github.com/fclairamb/afero-dropbox)
|
||||||
|
Streaming support; no write-seeking or POSIX permissions
|
||||||
|
|
||||||
|
#### Version Control Systems
|
||||||
|
|
||||||
|
- **Git Repositories** - [`tobiash/go-gitfs`](https://github.com/tobiash/go-gitfs)
|
||||||
|
Read-only filesystem abstraction for Git repositories. Works with bare repositories and provides filesystem view of any git reference. Uses go-git for repository access.
|
||||||
|
|
||||||
|
#### Container and Remote Systems
|
||||||
|
|
||||||
|
- **Docker Containers** - [`unmango/aferox`](https://github.com/unmango/aferox)
|
||||||
|
Access Docker container filesystems as if they were local filesystems
|
||||||
|
|
||||||
|
- **GitHub API** - [`unmango/aferox`](https://github.com/unmango/aferox)
|
||||||
|
Turn GitHub repositories, releases, and assets into browsable filesystems
|
||||||
|
|
||||||
|
#### FUSE Integration
|
||||||
|
|
||||||
|
- **Generic FUSE** - [`JakWai01/sile-fystem`](https://github.com/JakWai01/sile-fystem)
|
||||||
|
Mount any Afero filesystem as a FUSE filesystem, allowing any Afero backend to be used as a real mounted filesystem
|
||||||
|
|
||||||
|
#### Specialized Filesystems
|
||||||
|
|
||||||
|
- **FAT32 Support** - [`aligator/GoFAT`](https://github.com/aligator/GoFAT)
|
||||||
|
Pure Go FAT filesystem implementation (currently read-only)
|
||||||
|
|
||||||
|
### Interface Adapters & Utilities
|
||||||
|
|
||||||
|
**Cross-Interface Compatibility:**
|
||||||
|
- [`jfontan/go-billy-desfacer`](https://github.com/jfontan/go-billy-desfacer) - Adapter between Afero and go-billy interfaces (for go-git compatibility)
|
||||||
|
- [`Maldris/go-billy-afero`](https://github.com/Maldris/go-billy-afero) - Alternative wrapper for using Afero with go-billy
|
||||||
|
- [`c4milo/afero2billy`](https://github.com/c4milo/afero2billy) - Another Afero to billy filesystem adapter
|
||||||
|
|
||||||
|
**Working Directory Management:**
|
||||||
|
- [`carolynvs/aferox`](https://github.com/carolynvs/aferox) - Working directory-aware filesystem wrapper
|
||||||
|
|
||||||
|
**Advanced Filtering:**
|
||||||
|
- [`unmango/aferox`](https://github.com/unmango/aferox) includes multiple specialized filesystems:
|
||||||
|
- **FilterFs** - Predicate-based file filtering
|
||||||
|
- **IgnoreFs** - .gitignore-aware filtering
|
||||||
|
- **WriterFs** - Dump writes to io.Writer for debugging
|
||||||
|
|
||||||
|
#### Developer Tools & Utilities
|
||||||
|
|
||||||
|
**nhatthm Utility Suite** - Essential tools for Afero development:
|
||||||
|
- [`nhatthm/aferocopy`](https://github.com/nhatthm/aferocopy) - Copy files between any Afero filesystems
|
||||||
|
- [`nhatthm/aferomock`](https://github.com/nhatthm/aferomock) - Mocking toolkit for testing
|
||||||
|
- [`nhatthm/aferoassert`](https://github.com/nhatthm/aferoassert) - Assertion helpers for filesystem testing
|
||||||
|
|
||||||
|
### Ecosystem Showcase
|
||||||
|
|
||||||
|
**Windows Virtual Drives** - [`balazsgrill/potatodrive`](https://github.com/balazsgrill/potatodrive)
|
||||||
|
Mount any Afero filesystem as a Windows drive letter. Brilliant demonstration of Afero's power!
|
||||||
|
|
||||||
|
### Modern Asset Embedding (Go 1.16+)
|
||||||
|
|
||||||
|
Instead of third-party tools, use Go's native `//go:embed` with Afero:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed assets/*
|
||||||
|
var assetsFS embed.FS
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Convert embedded files to Afero filesystem
|
||||||
|
fs := afero.FromIOFS(assetsFS)
|
||||||
|
|
||||||
|
// Use like any other Afero filesystem
|
||||||
|
content, _ := afero.ReadFile(fs, "assets/config.json")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
1. Fork it
|
We welcome contributions! The project is mature, but we are actively looking for contributors to help implement and stabilize network/cloud backends.
|
||||||
|
|
||||||
|
* 🔥 **Microsoft Azure Blob Storage**
|
||||||
|
* 🔒 **Modern Encryption Backend** - Built on secure, contemporary crypto (not legacy EncFS)
|
||||||
|
* 🐙 **Canonical go-git Adapter** - Unified solution for Git integration
|
||||||
|
* 📡 **SSH/SCP Backend** - Secure remote file operations
|
||||||
|
* Stabilization of existing experimental backends (GCS, SFTP)
|
||||||
|
|
||||||
|
To contribute:
|
||||||
|
1. Fork the repository
|
||||||
2. Create your feature branch (`git checkout -b my-new-feature`)
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
||||||
3. Commit your changes (`git commit -am 'Add some feature'`)
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
||||||
4. Push to the branch (`git push origin my-new-feature`)
|
4. Push to the branch (`git push origin my-new-feature`)
|
||||||
5. Create new Pull Request
|
5. Create a new Pull Request
|
||||||
|
|
||||||
## Contributors
|
## 📄 License
|
||||||
|
|
||||||
Names in no particular order:
|
Afero is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/afero/blob/master/LICENSE.txt) for details.
|
||||||
|
|
||||||
* [spf13](https://github.com/spf13)
|
## 🔗 Additional Resources
|
||||||
* [jaqx0r](https://github.com/jaqx0r)
|
|
||||||
* [mbertschler](https://github.com/mbertschler)
|
|
||||||
* [xor-gate](https://github.com/xor-gate)
|
|
||||||
|
|
||||||
## License
|
- [📖 Full API Documentation](https://pkg.go.dev/github.com/spf13/afero)
|
||||||
|
- [🎯 Examples Repository](https://github.com/spf13/afero/tree/master/examples)
|
||||||
|
- [📋 Release Notes](https://github.com/spf13/afero/releases)
|
||||||
|
- [❓ GitHub Discussions](https://github.com/spf13/afero/discussions)
|
||||||
|
|
||||||
Afero is released under the Apache 2.0 license. See
|
---
|
||||||
[LICENSE.txt](https://github.com/spf13/afero/blob/master/LICENSE.txt)
|
|
||||||
|
*Afero comes from the Latin roots Ad-Facere, meaning "to make" or "to do" - fitting for a library that empowers you to make and do amazing things with filesystems.*
|
||||||
|
|
|
||||||
9
vendor/github.com/spf13/afero/copyOnWriteFs.go
generated
vendored
9
vendor/github.com/spf13/afero/copyOnWriteFs.go
generated
vendored
|
|
@ -34,7 +34,8 @@ func (u *CopyOnWriteFs) isBaseFile(name string) (bool, error) {
|
||||||
_, err := u.base.Stat(name)
|
_, err := u.base.Stat(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if oerr, ok := err.(*os.PathError); ok {
|
if oerr, ok := err.(*os.PathError); ok {
|
||||||
if oerr.Err == os.ErrNotExist || oerr.Err == syscall.ENOENT || oerr.Err == syscall.ENOTDIR {
|
if oerr.Err == os.ErrNotExist || oerr.Err == syscall.ENOENT ||
|
||||||
|
oerr.Err == syscall.ENOTDIR {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -237,7 +238,11 @@ func (u *CopyOnWriteFs) OpenFile(name string, flag int, perm os.FileMode) (File,
|
||||||
return u.layer.OpenFile(name, flag, perm)
|
return u.layer.OpenFile(name, flag, perm)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOTDIR} // ...or os.ErrNotExist?
|
return nil, &os.PathError{
|
||||||
|
Op: "open",
|
||||||
|
Path: name,
|
||||||
|
Err: syscall.ENOTDIR,
|
||||||
|
} // ...or os.ErrNotExist?
|
||||||
}
|
}
|
||||||
if b {
|
if b {
|
||||||
return u.base.OpenFile(name, flag, perm)
|
return u.base.OpenFile(name, flag, perm)
|
||||||
|
|
|
||||||
9
vendor/github.com/spf13/afero/iofs.go
generated
vendored
9
vendor/github.com/spf13/afero/iofs.go
generated
vendored
|
|
@ -137,7 +137,7 @@ type readDirFile struct {
|
||||||
var _ fs.ReadDirFile = readDirFile{}
|
var _ fs.ReadDirFile = readDirFile{}
|
||||||
|
|
||||||
func (r readDirFile) ReadDir(n int) ([]fs.DirEntry, error) {
|
func (r readDirFile) ReadDir(n int) ([]fs.DirEntry, error) {
|
||||||
items, err := r.File.Readdir(n)
|
items, err := r.Readdir(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -161,7 +161,12 @@ var _ Fs = FromIOFS{}
|
||||||
|
|
||||||
func (f FromIOFS) Create(name string) (File, error) { return nil, notImplemented("create", name) }
|
func (f FromIOFS) Create(name string) (File, error) { return nil, notImplemented("create", name) }
|
||||||
|
|
||||||
func (f FromIOFS) Mkdir(name string, perm os.FileMode) error { return notImplemented("mkdir", name) }
|
func (f FromIOFS) Mkdir(
|
||||||
|
name string,
|
||||||
|
perm os.FileMode,
|
||||||
|
) error {
|
||||||
|
return notImplemented("mkdir", name)
|
||||||
|
}
|
||||||
|
|
||||||
func (f FromIOFS) MkdirAll(path string, perm os.FileMode) error {
|
func (f FromIOFS) MkdirAll(path string, perm os.FileMode) error {
|
||||||
return notImplemented("mkdirall", path)
|
return notImplemented("mkdirall", path)
|
||||||
|
|
|
||||||
4
vendor/github.com/spf13/afero/lstater.go
generated
vendored
4
vendor/github.com/spf13/afero/lstater.go
generated
vendored
|
|
@ -19,9 +19,9 @@ import (
|
||||||
|
|
||||||
// Lstater is an optional interface in Afero. It is only implemented by the
|
// Lstater is an optional interface in Afero. It is only implemented by the
|
||||||
// filesystems saying so.
|
// filesystems saying so.
|
||||||
// It will call Lstat if the filesystem iself is, or it delegates to, the os filesystem.
|
// It will call Lstat if the filesystem itself is, or it delegates to, the os filesystem.
|
||||||
// Else it will call Stat.
|
// Else it will call Stat.
|
||||||
// In addtion to the FileInfo, it will return a boolean telling whether Lstat was called or not.
|
// In addition to the FileInfo, it will return a boolean telling whether Lstat was called or not.
|
||||||
type Lstater interface {
|
type Lstater interface {
|
||||||
LstatIfPossible(name string) (os.FileInfo, bool, error)
|
LstatIfPossible(name string) (os.FileInfo, bool, error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
vendor/github.com/spf13/afero/mem/file.go
generated
vendored
22
vendor/github.com/spf13/afero/mem/file.go
generated
vendored
|
|
@ -150,7 +150,11 @@ func (f *File) Sync() error {
|
||||||
|
|
||||||
func (f *File) Readdir(count int) (res []os.FileInfo, err error) {
|
func (f *File) Readdir(count int) (res []os.FileInfo, err error) {
|
||||||
if !f.fileData.dir {
|
if !f.fileData.dir {
|
||||||
return nil, &os.PathError{Op: "readdir", Path: f.fileData.name, Err: errors.New("not a dir")}
|
return nil, &os.PathError{
|
||||||
|
Op: "readdir",
|
||||||
|
Path: f.fileData.name,
|
||||||
|
Err: errors.New("not a dir"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var outLength int64
|
var outLength int64
|
||||||
|
|
||||||
|
|
@ -236,7 +240,11 @@ func (f *File) Truncate(size int64) error {
|
||||||
return ErrFileClosed
|
return ErrFileClosed
|
||||||
}
|
}
|
||||||
if f.readOnly {
|
if f.readOnly {
|
||||||
return &os.PathError{Op: "truncate", Path: f.fileData.name, Err: errors.New("file handle is read only")}
|
return &os.PathError{
|
||||||
|
Op: "truncate",
|
||||||
|
Path: f.fileData.name,
|
||||||
|
Err: errors.New("file handle is read only"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if size < 0 {
|
if size < 0 {
|
||||||
return ErrOutOfRange
|
return ErrOutOfRange
|
||||||
|
|
@ -273,7 +281,11 @@ func (f *File) Write(b []byte) (n int, err error) {
|
||||||
return 0, ErrFileClosed
|
return 0, ErrFileClosed
|
||||||
}
|
}
|
||||||
if f.readOnly {
|
if f.readOnly {
|
||||||
return 0, &os.PathError{Op: "write", Path: f.fileData.name, Err: errors.New("file handle is read only")}
|
return 0, &os.PathError{
|
||||||
|
Op: "write",
|
||||||
|
Path: f.fileData.name,
|
||||||
|
Err: errors.New("file handle is read only"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
n = len(b)
|
n = len(b)
|
||||||
cur := atomic.LoadInt64(&f.at)
|
cur := atomic.LoadInt64(&f.at)
|
||||||
|
|
@ -285,7 +297,9 @@ func (f *File) Write(b []byte) (n int, err error) {
|
||||||
tail = f.fileData.data[n+int(cur):]
|
tail = f.fileData.data[n+int(cur):]
|
||||||
}
|
}
|
||||||
if diff > 0 {
|
if diff > 0 {
|
||||||
f.fileData.data = append(f.fileData.data, append(bytes.Repeat([]byte{0o0}, int(diff)), b...)...)
|
f.fileData.data = append(
|
||||||
|
f.fileData.data,
|
||||||
|
append(bytes.Repeat([]byte{0o0}, int(diff)), b...)...)
|
||||||
f.fileData.data = append(f.fileData.data, tail...)
|
f.fileData.data = append(f.fileData.data, tail...)
|
||||||
} else {
|
} else {
|
||||||
f.fileData.data = append(f.fileData.data[:cur], b...)
|
f.fileData.data = append(f.fileData.data[:cur], b...)
|
||||||
|
|
|
||||||
5
vendor/github.com/spf13/afero/unionFile.go
generated
vendored
5
vendor/github.com/spf13/afero/unionFile.go
generated
vendored
|
|
@ -92,7 +92,8 @@ func (f *UnionFile) Seek(o int64, w int) (pos int64, err error) {
|
||||||
func (f *UnionFile) Write(s []byte) (n int, err error) {
|
func (f *UnionFile) Write(s []byte) (n int, err error) {
|
||||||
if f.Layer != nil {
|
if f.Layer != nil {
|
||||||
n, err = f.Layer.Write(s)
|
n, err = f.Layer.Write(s)
|
||||||
if err == nil && f.Base != nil { // hmm, do we have fixed size files where a write may hit the EOF mark?
|
if err == nil &&
|
||||||
|
f.Base != nil { // hmm, do we have fixed size files where a write may hit the EOF mark?
|
||||||
_, err = f.Base.Write(s)
|
_, err = f.Base.Write(s)
|
||||||
}
|
}
|
||||||
return n, err
|
return n, err
|
||||||
|
|
@ -157,7 +158,7 @@ var defaultUnionMergeDirsFn = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, err
|
||||||
// return a single view of the overlayed directories.
|
// return a single view of the overlayed directories.
|
||||||
// At the end of the directory view, the error is io.EOF if c > 0.
|
// At the end of the directory view, the error is io.EOF if c > 0.
|
||||||
func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) {
|
func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) {
|
||||||
var merge DirsMerger = f.Merger
|
merge := f.Merger
|
||||||
if merge == nil {
|
if merge == nil {
|
||||||
merge = defaultUnionMergeDirsFn
|
merge = defaultUnionMergeDirsFn
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
vendor/github.com/spf13/afero/util.go
generated
vendored
4
vendor/github.com/spf13/afero/util.go
generated
vendored
|
|
@ -113,11 +113,11 @@ func GetTempDir(fs Fs, subPath string) string {
|
||||||
if subPath != "" {
|
if subPath != "" {
|
||||||
// preserve windows backslash :-(
|
// preserve windows backslash :-(
|
||||||
if FilePathSeparator == "\\" {
|
if FilePathSeparator == "\\" {
|
||||||
subPath = strings.Replace(subPath, "\\", "____", -1)
|
subPath = strings.ReplaceAll(subPath, "\\", "____")
|
||||||
}
|
}
|
||||||
dir = dir + UnicodeSanitize((subPath))
|
dir = dir + UnicodeSanitize((subPath))
|
||||||
if FilePathSeparator == "\\" {
|
if FilePathSeparator == "\\" {
|
||||||
dir = strings.Replace(dir, "____", "\\", -1)
|
dir = strings.ReplaceAll(dir, "____", "\\")
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists, _ := Exists(fs, dir); exists {
|
if exists, _ := Exists(fs, dir); exists {
|
||||||
|
|
|
||||||
30
vendor/github.com/spf13/cast/map.go
generated
vendored
30
vendor/github.com/spf13/cast/map.go
generated
vendored
|
|
@ -15,7 +15,7 @@ func toMapE[K comparable, V any](i any, keyFn func(any) K, valFn func(any) V) (m
|
||||||
m := map[K]V{}
|
m := map[K]V{}
|
||||||
|
|
||||||
if i == nil {
|
if i == nil {
|
||||||
return nil, fmt.Errorf(errorMsg, i, i, m)
|
return m, fmt.Errorf(errorMsg, i, i, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch v := i.(type) {
|
switch v := i.(type) {
|
||||||
|
|
@ -45,14 +45,10 @@ func toMapE[K comparable, V any](i any, keyFn func(any) K, valFn func(any) V) (m
|
||||||
|
|
||||||
case string:
|
case string:
|
||||||
err := jsonStringToObject(v, &m)
|
err := jsonStringToObject(v, &m)
|
||||||
if err != nil {
|
return m, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return m, nil
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf(errorMsg, i, i, m)
|
return m, fmt.Errorf(errorMsg, i, i, m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,23 +108,19 @@ func ToStringMapStringSliceE(i any) (map[string][]string, error) {
|
||||||
for k, val := range v {
|
for k, val := range v {
|
||||||
key, err := ToStringE(k)
|
key, err := ToStringE(k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf(errorMsg, i, i, m)
|
return m, fmt.Errorf(errorMsg, i, i, m)
|
||||||
}
|
}
|
||||||
value, err := ToStringSliceE(val)
|
value, err := ToStringSliceE(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf(errorMsg, i, i, m)
|
return m, fmt.Errorf(errorMsg, i, i, m)
|
||||||
}
|
}
|
||||||
m[key] = value
|
m[key] = value
|
||||||
}
|
}
|
||||||
case string:
|
case string:
|
||||||
err := jsonStringToObject(v, &m)
|
err := jsonStringToObject(v, &m)
|
||||||
if err != nil {
|
return m, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return m, nil
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf(errorMsg, i, i, m)
|
return m, fmt.Errorf(errorMsg, i, i, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
@ -180,15 +172,11 @@ func toStringMapIntE[T int | int64](i any, fn func(any) T, fnE func(any) (T, err
|
||||||
|
|
||||||
case string:
|
case string:
|
||||||
err := jsonStringToObject(v, &m)
|
err := jsonStringToObject(v, &m)
|
||||||
if err != nil {
|
return m, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return m, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if reflect.TypeOf(i).Kind() != reflect.Map {
|
if reflect.TypeOf(i).Kind() != reflect.Map {
|
||||||
return nil, fmt.Errorf(errorMsg, i, i, m)
|
return m, fmt.Errorf(errorMsg, i, i, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
mVal := reflect.ValueOf(m)
|
mVal := reflect.ValueOf(m)
|
||||||
|
|
|
||||||
3
vendor/github.com/spf13/viper/.editorconfig
generated
vendored
3
vendor/github.com/spf13/viper/.editorconfig
generated
vendored
|
|
@ -16,3 +16,6 @@ indent_style = tab
|
||||||
|
|
||||||
[*.nix]
|
[*.nix]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
[.golangci.yaml]
|
||||||
|
indent_size = 2
|
||||||
|
|
|
||||||
209
vendor/github.com/spf13/viper/.golangci.yaml
generated
vendored
209
vendor/github.com/spf13/viper/.golangci.yaml
generated
vendored
|
|
@ -1,105 +1,118 @@
|
||||||
run:
|
version: "2"
|
||||||
timeout: 5m
|
|
||||||
|
|
||||||
linters-settings:
|
run:
|
||||||
gci:
|
timeout: 5m
|
||||||
sections:
|
|
||||||
- standard
|
|
||||||
- default
|
|
||||||
- prefix(github.com/spf13/viper)
|
|
||||||
gocritic:
|
|
||||||
# Enable multiple checks by tags. See "Tags" section in https://github.com/go-critic/go-critic#usage.
|
|
||||||
enabled-tags:
|
|
||||||
- diagnostic
|
|
||||||
- experimental
|
|
||||||
- opinionated
|
|
||||||
- style
|
|
||||||
disabled-checks:
|
|
||||||
- importShadow
|
|
||||||
- unnamedResult
|
|
||||||
goimports:
|
|
||||||
local-prefixes: github.com/spf13/viper
|
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
disable-all: true
|
enable:
|
||||||
enable:
|
- bodyclose
|
||||||
- bodyclose
|
- dogsled
|
||||||
- dogsled
|
- dupl
|
||||||
- dupl
|
- durationcheck
|
||||||
- durationcheck
|
- exhaustive
|
||||||
- exhaustive
|
- gocritic
|
||||||
- gci
|
- godot
|
||||||
- gocritic
|
- gomoddirectives
|
||||||
- godot
|
- goprintffuncname
|
||||||
- gofmt
|
- govet
|
||||||
- gofumpt
|
- importas
|
||||||
- goimports
|
- ineffassign
|
||||||
- gomoddirectives
|
- makezero
|
||||||
- goprintffuncname
|
- misspell
|
||||||
- govet
|
- nakedret
|
||||||
- importas
|
- nilerr
|
||||||
- ineffassign
|
- noctx
|
||||||
- makezero
|
- nolintlint
|
||||||
- misspell
|
- prealloc
|
||||||
- nakedret
|
- predeclared
|
||||||
- nilerr
|
- revive
|
||||||
|
- rowserrcheck
|
||||||
|
- sqlclosecheck
|
||||||
|
- staticcheck
|
||||||
|
- tparallel
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- unused
|
||||||
|
- wastedassign
|
||||||
|
- whitespace
|
||||||
|
|
||||||
|
# fixme
|
||||||
|
# - cyclop
|
||||||
|
# - errcheck
|
||||||
|
# - errorlint
|
||||||
|
# - exhaustivestruct
|
||||||
|
# - forbidigo
|
||||||
|
# - forcetypeassert
|
||||||
|
# - gochecknoglobals
|
||||||
|
# - gochecknoinits
|
||||||
|
# - gocognit
|
||||||
|
# - goconst
|
||||||
|
# - gocyclo
|
||||||
|
# - gosec
|
||||||
|
# - gosimple
|
||||||
|
# - ifshort
|
||||||
|
# - lll
|
||||||
|
# - nlreturn
|
||||||
|
# - paralleltest
|
||||||
|
# - scopelint
|
||||||
|
# - thelper
|
||||||
|
# - wrapcheck
|
||||||
|
|
||||||
|
# unused
|
||||||
|
# - depguard
|
||||||
|
# - goheader
|
||||||
|
# - gomodguard
|
||||||
|
|
||||||
|
# don't enable:
|
||||||
|
# - asciicheck
|
||||||
|
# - funlen
|
||||||
|
# - godox
|
||||||
|
# - goerr113
|
||||||
|
# - gomnd
|
||||||
|
# - interfacer
|
||||||
|
# - maligned
|
||||||
|
# - nestif
|
||||||
|
# - testpackage
|
||||||
|
# - wsl
|
||||||
|
|
||||||
|
exclusions:
|
||||||
|
rules:
|
||||||
|
- linters:
|
||||||
|
- errcheck
|
||||||
- noctx
|
- noctx
|
||||||
- nolintlint
|
path: _test.go
|
||||||
- prealloc
|
presets:
|
||||||
- predeclared
|
- comments
|
||||||
- revive
|
- std-error-handling
|
||||||
- rowserrcheck
|
|
||||||
- sqlclosecheck
|
|
||||||
- staticcheck
|
|
||||||
- stylecheck
|
|
||||||
- tparallel
|
|
||||||
- typecheck
|
|
||||||
- unconvert
|
|
||||||
- unparam
|
|
||||||
- unused
|
|
||||||
- wastedassign
|
|
||||||
- whitespace
|
|
||||||
|
|
||||||
# fixme
|
settings:
|
||||||
# - cyclop
|
misspell:
|
||||||
# - errcheck
|
locale: US
|
||||||
# - errorlint
|
nolintlint:
|
||||||
# - exhaustivestruct
|
allow-unused: false # report any unused nolint directives
|
||||||
# - forbidigo
|
require-specific: false # don't require nolint directives to be specific about which linter is being skipped
|
||||||
# - forcetypeassert
|
gocritic:
|
||||||
# - gochecknoglobals
|
# Enable multiple checks by tags. See "Tags" section in https://github.com/go-critic/go-critic#usage.
|
||||||
# - gochecknoinits
|
enabled-tags:
|
||||||
# - gocognit
|
- diagnostic
|
||||||
# - goconst
|
- experimental
|
||||||
# - gocyclo
|
- opinionated
|
||||||
# - gosec
|
- style
|
||||||
# - gosimple
|
disabled-checks:
|
||||||
# - ifshort
|
- importShadow
|
||||||
# - lll
|
- unnamedResult
|
||||||
# - nlreturn
|
|
||||||
# - paralleltest
|
|
||||||
# - scopelint
|
|
||||||
# - thelper
|
|
||||||
# - wrapcheck
|
|
||||||
|
|
||||||
# unused
|
formatters:
|
||||||
# - depguard
|
enable:
|
||||||
# - goheader
|
- gci
|
||||||
# - gomodguard
|
- gofmt
|
||||||
|
- gofumpt
|
||||||
|
- goimports
|
||||||
|
# - golines
|
||||||
|
|
||||||
# deprecated
|
settings:
|
||||||
# - deadcode
|
gci:
|
||||||
# - structcheck
|
sections:
|
||||||
# - varcheck
|
- standard
|
||||||
|
- default
|
||||||
# don't enable:
|
- localmodule
|
||||||
# - asciicheck
|
|
||||||
# - funlen
|
|
||||||
# - godox
|
|
||||||
# - goerr113
|
|
||||||
# - gomnd
|
|
||||||
# - interfacer
|
|
||||||
# - maligned
|
|
||||||
# - nestif
|
|
||||||
# - testpackage
|
|
||||||
# - wsl
|
|
||||||
|
|
|
||||||
4
vendor/github.com/spf13/viper/README.md
generated
vendored
4
vendor/github.com/spf13/viper/README.md
generated
vendored
|
|
@ -12,7 +12,7 @@
|
||||||
[](https://github.com/spf13/viper/actions?query=workflow%3ACI)
|
[](https://github.com/spf13/viper/actions?query=workflow%3ACI)
|
||||||
[](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
[](https://goreportcard.com/report/github.com/spf13/viper)
|
[](https://goreportcard.com/report/github.com/spf13/viper)
|
||||||

|

|
||||||
[](https://pkg.go.dev/mod/github.com/spf13/viper)
|
[](https://pkg.go.dev/mod/github.com/spf13/viper)
|
||||||
|
|
||||||
**Go configuration with fangs!**
|
**Go configuration with fangs!**
|
||||||
|
|
@ -821,7 +821,7 @@ You can use your favorite format's marshaller with the config returned by `AllSe
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "go.yaml.in/yaml/v3"
|
||||||
// ...
|
// ...
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
21
vendor/github.com/spf13/viper/UPDATES.md → vendor/github.com/spf13/viper/UPGRADE.md
generated
vendored
21
vendor/github.com/spf13/viper/UPDATES.md → vendor/github.com/spf13/viper/UPGRADE.md
generated
vendored
|
|
@ -83,6 +83,27 @@ v := viper.NewWithOptions(
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### BREAKING: "github.com/mitchellh/mapstructure" depedency replaced
|
||||||
|
|
||||||
|
The original [mapstructure](https://github.com/mitchellh/mapstructure) has been [archived](https://github.com/mitchellh/mapstructure/issues/349) and was replaced with a [fork](https://github.com/go-viper/mapstructure) maintained by Viper ([#1723](https://github.com/spf13/viper/pull/1723)).
|
||||||
|
|
||||||
|
As a result, the package import path needs to be changed in cases where `mapstructure` is directly referenced in your code.
|
||||||
|
|
||||||
|
For example, when providing a custom decoder config:
|
||||||
|
|
||||||
|
```go
|
||||||
|
err := viper.Unmarshal(&appConfig, func(config *mapstructure.DecoderConfig) {
|
||||||
|
config.TagName = "yaml"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The change is fairly straightforward, just replace all occurrences of the import path `github.com/mitchellh/mapstructure` with `github.com/go-viper/mapstructure/v2`:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- import "github.com/mitchellh/mapstructure"
|
||||||
|
+ import "github.com/go-viper/mapstructure/v2"
|
||||||
|
```
|
||||||
|
|
||||||
### BREAKING: HCL, Java properties, INI removed from core
|
### BREAKING: HCL, Java properties, INI removed from core
|
||||||
|
|
||||||
In order to reduce third-party dependencies, Viper dropped support for the following formats from the core:
|
In order to reduce third-party dependencies, Viper dropped support for the following formats from the core:
|
||||||
425
vendor/github.com/spf13/viper/flake.lock
generated
vendored
425
vendor/github.com/spf13/viper/flake.lock
generated
vendored
|
|
@ -2,30 +2,32 @@
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"cachix": {
|
"cachix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"devenv": "devenv_2",
|
"devenv": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
"flake-compat": [
|
"flake-compat": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"git-hooks": [
|
||||||
"devenv",
|
"devenv",
|
||||||
"flake-compat"
|
"git-hooks"
|
||||||
],
|
],
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"devenv",
|
"devenv",
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
|
||||||
"pre-commit-hooks": [
|
|
||||||
"devenv",
|
|
||||||
"pre-commit-hooks"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712055811,
|
"lastModified": 1748883665,
|
||||||
"narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
|
"narHash": "sha256-R0W7uAg+BLoHjMRMQ8+oiSbTq8nkGz5RDpQ+ZfxxP3A=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "cachix",
|
"repo": "cachix",
|
||||||
"rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
|
"rev": "f707778d902af4d62d8dd92c269f8e70de09acbe",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
|
"ref": "latest",
|
||||||
"repo": "cachix",
|
"repo": "cachix",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|
@ -33,52 +35,21 @@
|
||||||
"devenv": {
|
"devenv": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"cachix": "cachix",
|
"cachix": "cachix",
|
||||||
"flake-compat": "flake-compat_2",
|
"flake-compat": "flake-compat",
|
||||||
"nix": "nix_2",
|
"git-hooks": "git-hooks",
|
||||||
"nixpkgs": "nixpkgs_2",
|
|
||||||
"pre-commit-hooks": "pre-commit-hooks"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1724763216,
|
|
||||||
"narHash": "sha256-oW2bwCrJpIzibCNK6zfIDaIQw765yMAuMSG2gyZfGv0=",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv",
|
|
||||||
"rev": "1e4ef61205b9aa20fe04bf1c468b6a316281c4f1",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"devenv_2": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"flake-compat"
|
|
||||||
],
|
|
||||||
"nix": "nix",
|
"nix": "nix",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs"
|
||||||
"poetry2nix": "poetry2nix",
|
|
||||||
"pre-commit-hooks": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"pre-commit-hooks"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1708704632,
|
"lastModified": 1755257397,
|
||||||
"narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
|
"narHash": "sha256-VU+OHexL2y6y7yrpEc6bZvYYwoQg6aZK1b4YxT0yZCk=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "devenv",
|
"repo": "devenv",
|
||||||
"rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
|
"rev": "6f9c3d4722aa253631644329f7bda60b1d3d1b97",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"ref": "python-rewrite",
|
|
||||||
"repo": "devenv",
|
"repo": "devenv",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|
@ -86,27 +57,11 @@
|
||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1673956053,
|
"lastModified": 1747046372,
|
||||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||||
"owner": "edolstra",
|
"owner": "edolstra",
|
||||||
"repo": "flake-compat",
|
"repo": "flake-compat",
|
||||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-compat_2": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1696426674,
|
|
||||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -116,15 +71,37 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-parts": {
|
"flake-parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": [
|
||||||
|
"devenv",
|
||||||
|
"nix",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1733312601,
|
||||||
|
"narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts_2": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs-lib": "nixpkgs-lib"
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1722555600,
|
"lastModified": 1754487366,
|
||||||
"narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
|
"narHash": "sha256-pHYj8gUBapuUzKV/kN/tR3Zvqc7o6gdFB9XKXIp1SQ8=",
|
||||||
"owner": "hercules-ci",
|
"owner": "hercules-ci",
|
||||||
"repo": "flake-parts",
|
"repo": "flake-parts",
|
||||||
"rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
|
"rev": "af66ad14b28a127c5c0f3bbb298218fc63528a18",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -133,39 +110,29 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils": {
|
"git-hooks": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems"
|
"flake-compat": [
|
||||||
|
"devenv",
|
||||||
|
"flake-compat"
|
||||||
|
],
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"nixpkgs": [
|
||||||
|
"devenv",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1689068808,
|
"lastModified": 1750779888,
|
||||||
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
"narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=",
|
||||||
"owner": "numtide",
|
"owner": "cachix",
|
||||||
"repo": "flake-utils",
|
"repo": "git-hooks.nix",
|
||||||
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
"rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "numtide",
|
"owner": "cachix",
|
||||||
"repo": "flake-utils",
|
"repo": "git-hooks.nix",
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils_2": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1710146030,
|
|
||||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -173,7 +140,7 @@
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"devenv",
|
"devenv",
|
||||||
"pre-commit-hooks",
|
"git-hooks",
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -192,165 +159,49 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nix": {
|
"nix": {
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat",
|
|
||||||
"nixpkgs": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"devenv",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"nixpkgs-regression": "nixpkgs-regression"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1712911606,
|
|
||||||
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
|
|
||||||
"owner": "domenkozar",
|
|
||||||
"repo": "nix",
|
|
||||||
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "domenkozar",
|
|
||||||
"ref": "devenv-2.21",
|
|
||||||
"repo": "nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix-github-actions": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"devenv",
|
|
||||||
"poetry2nix",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1688870561,
|
|
||||||
"narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nix-github-actions",
|
|
||||||
"rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nix-github-actions",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix_2": {
|
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": [
|
"flake-compat": [
|
||||||
"devenv",
|
"devenv",
|
||||||
"flake-compat"
|
"flake-compat"
|
||||||
],
|
],
|
||||||
|
"flake-parts": "flake-parts",
|
||||||
|
"git-hooks-nix": [
|
||||||
|
"devenv",
|
||||||
|
"git-hooks"
|
||||||
|
],
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"devenv",
|
"devenv",
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"nixpkgs-regression": "nixpkgs-regression_2"
|
"nixpkgs-23-11": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"nixpkgs-regression": [
|
||||||
|
"devenv"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712911606,
|
"lastModified": 1755029779,
|
||||||
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
|
"narHash": "sha256-3+GHIYGg4U9XKUN4rg473frIVNn8YD06bjwxKS1IPrU=",
|
||||||
"owner": "domenkozar",
|
"owner": "cachix",
|
||||||
"repo": "nix",
|
"repo": "nix",
|
||||||
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
|
"rev": "b0972b0eee6726081d10b1199f54de6d2917f861",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "domenkozar",
|
"owner": "cachix",
|
||||||
"ref": "devenv-2.21",
|
"ref": "devenv-2.30",
|
||||||
"repo": "nix",
|
"repo": "nix",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1692808169,
|
"lastModified": 1750441195,
|
||||||
"narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
|
"narHash": "sha256-yke+pm+MdgRb6c0dPt8MgDhv7fcBbdjmv1ZceNTyzKg=",
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixpkgs-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-lib": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1722555339,
|
|
||||||
"narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=",
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "tarball",
|
|
||||||
"url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-regression": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1643052045,
|
|
||||||
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-regression_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1643052045,
|
|
||||||
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-stable": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1710695816,
|
|
||||||
"narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "614b4613980a522ba49f0d194531beddbb7220d3",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-23.11",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1713361204,
|
|
||||||
"narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
|
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "devenv-nixpkgs",
|
"repo": "devenv-nixpkgs",
|
||||||
"rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
|
"rev": "0ceffe312871b443929ff3006960d29b120dc627",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -360,13 +211,28 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_3": {
|
"nixpkgs-lib": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1724748588,
|
"lastModified": 1753579242,
|
||||||
"narHash": "sha256-NlpGA4+AIf1dKNq76ps90rxowlFXUsV9x7vK/mN37JM=",
|
"narHash": "sha256-zvaMGVn14/Zz8hnp4VWT9xVnhc8vuL3TStRqwk22biA=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"rev": "0f36c44e01a6129be94e3ade315a5883f0228a6e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1755268003,
|
||||||
|
"narHash": "sha256-nNaeJjo861wFR0tjHDyCnHs1rbRtrMgxAKMoig9Sj/w=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "a6292e34000dc93d43bccf78338770c1c5ec8a99",
|
"rev": "32f313e49e42f715491e1ea7b306a87c16fe0388",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -376,94 +242,11 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"poetry2nix": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nix-github-actions": "nix-github-actions",
|
|
||||||
"nixpkgs": [
|
|
||||||
"devenv",
|
|
||||||
"cachix",
|
|
||||||
"devenv",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1692876271,
|
|
||||||
"narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "poetry2nix",
|
|
||||||
"rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "poetry2nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pre-commit-hooks": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": [
|
|
||||||
"devenv",
|
|
||||||
"flake-compat"
|
|
||||||
],
|
|
||||||
"flake-utils": "flake-utils_2",
|
|
||||||
"gitignore": "gitignore",
|
|
||||||
"nixpkgs": [
|
|
||||||
"devenv",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1713775815,
|
|
||||||
"narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "pre-commit-hooks.nix",
|
|
||||||
"rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "pre-commit-hooks.nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"devenv": "devenv",
|
"devenv": "devenv",
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts_2",
|
||||||
"nixpkgs": "nixpkgs_3"
|
"nixpkgs": "nixpkgs_2"
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
68
vendor/github.com/spf13/viper/flake.nix
generated
vendored
68
vendor/github.com/spf13/viper/flake.nix
generated
vendored
|
|
@ -7,51 +7,55 @@
|
||||||
devenv.url = "github:cachix/devenv";
|
devenv.url = "github:cachix/devenv";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs@{ flake-parts, ... }:
|
outputs =
|
||||||
|
inputs@{ flake-parts, ... }:
|
||||||
flake-parts.lib.mkFlake { inherit inputs; } {
|
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||||
imports = [
|
imports = [
|
||||||
inputs.devenv.flakeModule
|
inputs.devenv.flakeModule
|
||||||
];
|
];
|
||||||
|
|
||||||
systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ];
|
systems = [
|
||||||
|
"x86_64-linux"
|
||||||
|
"x86_64-darwin"
|
||||||
|
"aarch64-darwin"
|
||||||
|
];
|
||||||
|
|
||||||
perSystem = { config, self', inputs', pkgs, system, ... }: rec {
|
perSystem =
|
||||||
devenv.shells = {
|
{ pkgs, ... }:
|
||||||
default = {
|
{
|
||||||
languages = {
|
devenv.shells = {
|
||||||
go.enable = true;
|
default = {
|
||||||
go.package = pkgs.go_1_23;
|
languages = {
|
||||||
};
|
go.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
pre-commit.hooks = {
|
git-hooks.hooks = {
|
||||||
nixpkgs-fmt.enable = true;
|
nixpkgs-fmt.enable = true;
|
||||||
yamllint.enable = true;
|
yamllint.enable = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
gnumake
|
gnumake
|
||||||
|
|
||||||
golangci-lint
|
golangci-lint
|
||||||
yamllint
|
yamllint
|
||||||
];
|
];
|
||||||
|
|
||||||
scripts = {
|
scripts = {
|
||||||
versions.exec = ''
|
versions.exec = ''
|
||||||
go version
|
go version
|
||||||
golangci-lint version
|
golangci-lint version
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
enterShell = ''
|
||||||
|
versions
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
|
||||||
|
containers = pkgs.lib.mkForce { };
|
||||||
};
|
};
|
||||||
|
|
||||||
enterShell = ''
|
|
||||||
versions
|
|
||||||
'';
|
|
||||||
|
|
||||||
# https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
|
|
||||||
containers = pkgs.lib.mkForce { };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ci = devenv.shells.default;
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go
generated
vendored
2
vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go
generated
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
package yaml
|
package yaml
|
||||||
|
|
||||||
import "gopkg.in/yaml.v3"
|
import "go.yaml.in/yaml/v3"
|
||||||
|
|
||||||
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for YAML encoding.
|
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for YAML encoding.
|
||||||
type Codec struct{}
|
type Codec struct{}
|
||||||
|
|
|
||||||
5
vendor/github.com/spf13/viper/remote.go
generated
vendored
5
vendor/github.com/spf13/viper/remote.go
generated
vendored
|
|
@ -219,7 +219,10 @@ func (v *Viper) watchKeyValueConfigOnChannel() error {
|
||||||
for {
|
for {
|
||||||
b := <-rc
|
b := <-rc
|
||||||
reader := bytes.NewReader(b.Value)
|
reader := bytes.NewReader(b.Value)
|
||||||
v.unmarshalReader(reader, v.kvstore)
|
err := v.unmarshalReader(reader, v.kvstore)
|
||||||
|
if err != nil {
|
||||||
|
v.logger.Error(fmt.Errorf("failed to unmarshal remote config: %w", err).Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}(respc)
|
}(respc)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
5
vendor/github.com/spf13/viper/util.go
generated
vendored
5
vendor/github.com/spf13/viper/util.go
generated
vendored
|
|
@ -174,10 +174,7 @@ func parseSizeInBytes(sizeStr string) uint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size := cast.ToInt(sizeStr)
|
size := max(cast.ToInt(sizeStr), 0)
|
||||||
if size < 0 {
|
|
||||||
size = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return safeMul(uint(size), multiplier)
|
return safeMul(uint(size), multiplier)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
vendor/github.com/spf13/viper/viper.go
generated
vendored
42
vendor/github.com/spf13/viper/viper.go
generated
vendored
|
|
@ -376,7 +376,12 @@ func (v *Viper) WatchConfig() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
watcher.Add(configDir)
|
err = watcher.Add(configDir)
|
||||||
|
if err != nil {
|
||||||
|
v.logger.Error(fmt.Sprintf("failed to add watcher: %s", err))
|
||||||
|
initWG.Done()
|
||||||
|
return
|
||||||
|
}
|
||||||
initWG.Done() // done initializing the watch in this go routine, so the parent routine can move on...
|
initWG.Done() // done initializing the watch in this go routine, so the parent routine can move on...
|
||||||
eventsWG.Wait() // now, wait for event loop to end in this go-routine...
|
eventsWG.Wait() // now, wait for event loop to end in this go-routine...
|
||||||
}()
|
}()
|
||||||
|
|
@ -1181,11 +1186,26 @@ func (v *Viper) find(lcaseKey string, flagDefault bool) any {
|
||||||
s = strings.TrimSuffix(s, "]")
|
s = strings.TrimSuffix(s, "]")
|
||||||
res, _ := readAsCSV(s)
|
res, _ := readAsCSV(s)
|
||||||
return res
|
return res
|
||||||
|
case "boolSlice":
|
||||||
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
|
s = strings.TrimSuffix(s, "]")
|
||||||
|
res, _ := readAsCSV(s)
|
||||||
|
return cast.ToBoolSlice(res)
|
||||||
case "intSlice":
|
case "intSlice":
|
||||||
s := strings.TrimPrefix(flag.ValueString(), "[")
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
s = strings.TrimSuffix(s, "]")
|
s = strings.TrimSuffix(s, "]")
|
||||||
res, _ := readAsCSV(s)
|
res, _ := readAsCSV(s)
|
||||||
return cast.ToIntSlice(res)
|
return cast.ToIntSlice(res)
|
||||||
|
case "uintSlice":
|
||||||
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
|
s = strings.TrimSuffix(s, "]")
|
||||||
|
res, _ := readAsCSV(s)
|
||||||
|
return cast.ToUintSlice(res)
|
||||||
|
case "float64Slice":
|
||||||
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
|
s = strings.TrimSuffix(s, "]")
|
||||||
|
res, _ := readAsCSV(s)
|
||||||
|
return cast.ToFloat64Slice(res)
|
||||||
case "durationSlice":
|
case "durationSlice":
|
||||||
s := strings.TrimPrefix(flag.ValueString(), "[")
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
s = strings.TrimSuffix(s, "]")
|
s = strings.TrimSuffix(s, "]")
|
||||||
|
|
@ -1268,11 +1288,26 @@ func (v *Viper) find(lcaseKey string, flagDefault bool) any {
|
||||||
s = strings.TrimSuffix(s, "]")
|
s = strings.TrimSuffix(s, "]")
|
||||||
res, _ := readAsCSV(s)
|
res, _ := readAsCSV(s)
|
||||||
return res
|
return res
|
||||||
|
case "boolSlice":
|
||||||
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
|
s = strings.TrimSuffix(s, "]")
|
||||||
|
res, _ := readAsCSV(s)
|
||||||
|
return cast.ToBoolSlice(res)
|
||||||
case "intSlice":
|
case "intSlice":
|
||||||
s := strings.TrimPrefix(flag.ValueString(), "[")
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
s = strings.TrimSuffix(s, "]")
|
s = strings.TrimSuffix(s, "]")
|
||||||
res, _ := readAsCSV(s)
|
res, _ := readAsCSV(s)
|
||||||
return cast.ToIntSlice(res)
|
return cast.ToIntSlice(res)
|
||||||
|
case "uintSlice":
|
||||||
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
|
s = strings.TrimSuffix(s, "]")
|
||||||
|
res, _ := readAsCSV(s)
|
||||||
|
return cast.ToUintSlice(res)
|
||||||
|
case "float64Slice":
|
||||||
|
s := strings.TrimPrefix(flag.ValueString(), "[")
|
||||||
|
s = strings.TrimSuffix(s, "]")
|
||||||
|
res, _ := readAsCSV(s)
|
||||||
|
return cast.ToFloat64Slice(res)
|
||||||
case "stringToString":
|
case "stringToString":
|
||||||
return stringToStringConv(flag.ValueString())
|
return stringToStringConv(flag.ValueString())
|
||||||
case "stringToInt":
|
case "stringToInt":
|
||||||
|
|
@ -1670,7 +1705,10 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
buf.ReadFrom(in)
|
_, err := buf.ReadFrom(in)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read configuration from input: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: remove this once SupportedExts is deprecated/removed
|
// TODO: remove this once SupportedExts is deprecated/removed
|
||||||
if !slices.Contains(SupportedExts, format) {
|
if !slices.Contains(SupportedExts, format) {
|
||||||
|
|
|
||||||
15
vendor/go.uber.org/multierr/.codecov.yml
generated
vendored
15
vendor/go.uber.org/multierr/.codecov.yml
generated
vendored
|
|
@ -1,15 +0,0 @@
|
||||||
coverage:
|
|
||||||
range: 80..100
|
|
||||||
round: down
|
|
||||||
precision: 2
|
|
||||||
|
|
||||||
status:
|
|
||||||
project: # measuring the overall project coverage
|
|
||||||
default: # context, you can create multiple ones with custom titles
|
|
||||||
enabled: yes # must be yes|true to enable this status
|
|
||||||
target: 100 # specify the target coverage for each commit status
|
|
||||||
# option: "auto" (must increase from parent commit or pull request base)
|
|
||||||
# option: "X%" a static target percentage to hit
|
|
||||||
if_not_found: success # if parent is not found report status as success, error, or failure
|
|
||||||
if_ci_failed: error # if ci fails report status as success, error, or failure
|
|
||||||
|
|
||||||
4
vendor/go.uber.org/multierr/.gitignore
generated
vendored
4
vendor/go.uber.org/multierr/.gitignore
generated
vendored
|
|
@ -1,4 +0,0 @@
|
||||||
/vendor
|
|
||||||
cover.html
|
|
||||||
cover.out
|
|
||||||
/bin
|
|
||||||
95
vendor/go.uber.org/multierr/CHANGELOG.md
generated
vendored
95
vendor/go.uber.org/multierr/CHANGELOG.md
generated
vendored
|
|
@ -1,95 +0,0 @@
|
||||||
Releases
|
|
||||||
========
|
|
||||||
|
|
||||||
v1.11.0 (2023-03-28)
|
|
||||||
====================
|
|
||||||
- `Errors` now supports any error that implements multiple-error
|
|
||||||
interface.
|
|
||||||
- Add `Every` function to allow checking if all errors in the chain
|
|
||||||
satisfies `errors.Is` against the target error.
|
|
||||||
|
|
||||||
v1.10.0 (2023-03-08)
|
|
||||||
====================
|
|
||||||
|
|
||||||
- Comply with Go 1.20's multiple-error interface.
|
|
||||||
- Drop Go 1.18 support.
|
|
||||||
Per the support policy, only Go 1.19 and 1.20 are supported now.
|
|
||||||
- Drop all non-test external dependencies.
|
|
||||||
|
|
||||||
v1.9.0 (2022-12-12)
|
|
||||||
===================
|
|
||||||
|
|
||||||
- Add `AppendFunc` that allow passsing functions to similar to
|
|
||||||
`AppendInvoke`.
|
|
||||||
|
|
||||||
- Bump up yaml.v3 dependency to 3.0.1.
|
|
||||||
|
|
||||||
v1.8.0 (2022-02-28)
|
|
||||||
===================
|
|
||||||
|
|
||||||
- `Combine`: perform zero allocations when there are no errors.
|
|
||||||
|
|
||||||
|
|
||||||
v1.7.0 (2021-05-06)
|
|
||||||
===================
|
|
||||||
|
|
||||||
- Add `AppendInvoke` to append into errors from `defer` blocks.
|
|
||||||
|
|
||||||
|
|
||||||
v1.6.0 (2020-09-14)
|
|
||||||
===================
|
|
||||||
|
|
||||||
- Actually drop library dependency on development-time tooling.
|
|
||||||
|
|
||||||
|
|
||||||
v1.5.0 (2020-02-24)
|
|
||||||
===================
|
|
||||||
|
|
||||||
- Drop library dependency on development-time tooling.
|
|
||||||
|
|
||||||
|
|
||||||
v1.4.0 (2019-11-04)
|
|
||||||
===================
|
|
||||||
|
|
||||||
- Add `AppendInto` function to more ergonomically build errors inside a
|
|
||||||
loop.
|
|
||||||
|
|
||||||
|
|
||||||
v1.3.0 (2019-10-29)
|
|
||||||
===================
|
|
||||||
|
|
||||||
- Switch to Go modules.
|
|
||||||
|
|
||||||
|
|
||||||
v1.2.0 (2019-09-26)
|
|
||||||
===================
|
|
||||||
|
|
||||||
- Support extracting and matching against wrapped errors with `errors.As`
|
|
||||||
and `errors.Is`.
|
|
||||||
|
|
||||||
|
|
||||||
v1.1.0 (2017-06-30)
|
|
||||||
===================
|
|
||||||
|
|
||||||
- Added an `Errors(error) []error` function to extract the underlying list of
|
|
||||||
errors for a multierr error.
|
|
||||||
|
|
||||||
|
|
||||||
v1.0.0 (2017-05-31)
|
|
||||||
===================
|
|
||||||
|
|
||||||
No changes since v0.2.0. This release is committing to making no breaking
|
|
||||||
changes to the current API in the 1.X series.
|
|
||||||
|
|
||||||
|
|
||||||
v0.2.0 (2017-04-11)
|
|
||||||
===================
|
|
||||||
|
|
||||||
- Repeatedly appending to the same error is now faster due to fewer
|
|
||||||
allocations.
|
|
||||||
|
|
||||||
|
|
||||||
v0.1.0 (2017-31-03)
|
|
||||||
===================
|
|
||||||
|
|
||||||
- Initial release
|
|
||||||
19
vendor/go.uber.org/multierr/LICENSE.txt
generated
vendored
19
vendor/go.uber.org/multierr/LICENSE.txt
generated
vendored
|
|
@ -1,19 +0,0 @@
|
||||||
Copyright (c) 2017-2021 Uber Technologies, 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.
|
|
||||||
38
vendor/go.uber.org/multierr/Makefile
generated
vendored
38
vendor/go.uber.org/multierr/Makefile
generated
vendored
|
|
@ -1,38 +0,0 @@
|
||||||
# Directory to put `go install`ed binaries in.
|
|
||||||
export GOBIN ?= $(shell pwd)/bin
|
|
||||||
|
|
||||||
GO_FILES := $(shell \
|
|
||||||
find . '(' -path '*/.*' -o -path './vendor' ')' -prune \
|
|
||||||
-o -name '*.go' -print | cut -b3-)
|
|
||||||
|
|
||||||
.PHONY: build
|
|
||||||
build:
|
|
||||||
go build ./...
|
|
||||||
|
|
||||||
.PHONY: test
|
|
||||||
test:
|
|
||||||
go test -race ./...
|
|
||||||
|
|
||||||
.PHONY: gofmt
|
|
||||||
gofmt:
|
|
||||||
$(eval FMT_LOG := $(shell mktemp -t gofmt.XXXXX))
|
|
||||||
@gofmt -e -s -l $(GO_FILES) > $(FMT_LOG) || true
|
|
||||||
@[ ! -s "$(FMT_LOG)" ] || (echo "gofmt failed:" | cat - $(FMT_LOG) && false)
|
|
||||||
|
|
||||||
.PHONY: golint
|
|
||||||
golint:
|
|
||||||
@cd tools && go install golang.org/x/lint/golint
|
|
||||||
@$(GOBIN)/golint ./...
|
|
||||||
|
|
||||||
.PHONY: staticcheck
|
|
||||||
staticcheck:
|
|
||||||
@cd tools && go install honnef.co/go/tools/cmd/staticcheck
|
|
||||||
@$(GOBIN)/staticcheck ./...
|
|
||||||
|
|
||||||
.PHONY: lint
|
|
||||||
lint: gofmt golint staticcheck
|
|
||||||
|
|
||||||
.PHONY: cover
|
|
||||||
cover:
|
|
||||||
go test -race -coverprofile=cover.out -coverpkg=./... -v ./...
|
|
||||||
go tool cover -html=cover.out -o cover.html
|
|
||||||
43
vendor/go.uber.org/multierr/README.md
generated
vendored
43
vendor/go.uber.org/multierr/README.md
generated
vendored
|
|
@ -1,43 +0,0 @@
|
||||||
# multierr [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
|
|
||||||
|
|
||||||
`multierr` allows combining one or more Go `error`s together.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- **Idiomatic**:
|
|
||||||
multierr follows best practices in Go, and keeps your code idiomatic.
|
|
||||||
- It keeps the underlying error type hidden,
|
|
||||||
allowing you to deal in `error` values exclusively.
|
|
||||||
- It provides APIs to safely append into an error from a `defer` statement.
|
|
||||||
- **Performant**:
|
|
||||||
multierr is optimized for performance:
|
|
||||||
- It avoids allocations where possible.
|
|
||||||
- It utilizes slice resizing semantics to optimize common cases
|
|
||||||
like appending into the same error object from a loop.
|
|
||||||
- **Interoperable**:
|
|
||||||
multierr interoperates with the Go standard library's error APIs seamlessly:
|
|
||||||
- The `errors.Is` and `errors.As` functions *just work*.
|
|
||||||
- **Lightweight**:
|
|
||||||
multierr comes with virtually no dependencies.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go get -u go.uber.org/multierr@latest
|
|
||||||
```
|
|
||||||
|
|
||||||
## Status
|
|
||||||
|
|
||||||
Stable: No breaking changes will be made before 2.0.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Released under the [MIT License].
|
|
||||||
|
|
||||||
[MIT License]: LICENSE.txt
|
|
||||||
[doc-img]: https://pkg.go.dev/badge/go.uber.org/multierr
|
|
||||||
[doc]: https://pkg.go.dev/go.uber.org/multierr
|
|
||||||
[ci-img]: https://github.com/uber-go/multierr/actions/workflows/go.yml/badge.svg
|
|
||||||
[cov-img]: https://codecov.io/gh/uber-go/multierr/branch/master/graph/badge.svg
|
|
||||||
[ci]: https://github.com/uber-go/multierr/actions/workflows/go.yml
|
|
||||||
[cov]: https://codecov.io/gh/uber-go/multierr
|
|
||||||
646
vendor/go.uber.org/multierr/error.go
generated
vendored
646
vendor/go.uber.org/multierr/error.go
generated
vendored
|
|
@ -1,646 +0,0 @@
|
||||||
// Copyright (c) 2017-2023 Uber Technologies, 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.
|
|
||||||
|
|
||||||
// Package multierr allows combining one or more errors together.
|
|
||||||
//
|
|
||||||
// # Overview
|
|
||||||
//
|
|
||||||
// Errors can be combined with the use of the Combine function.
|
|
||||||
//
|
|
||||||
// multierr.Combine(
|
|
||||||
// reader.Close(),
|
|
||||||
// writer.Close(),
|
|
||||||
// conn.Close(),
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// If only two errors are being combined, the Append function may be used
|
|
||||||
// instead.
|
|
||||||
//
|
|
||||||
// err = multierr.Append(reader.Close(), writer.Close())
|
|
||||||
//
|
|
||||||
// The underlying list of errors for a returned error object may be retrieved
|
|
||||||
// with the Errors function.
|
|
||||||
//
|
|
||||||
// errors := multierr.Errors(err)
|
|
||||||
// if len(errors) > 0 {
|
|
||||||
// fmt.Println("The following errors occurred:", errors)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// # Appending from a loop
|
|
||||||
//
|
|
||||||
// You sometimes need to append into an error from a loop.
|
|
||||||
//
|
|
||||||
// var err error
|
|
||||||
// for _, item := range items {
|
|
||||||
// err = multierr.Append(err, process(item))
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Cases like this may require knowledge of whether an individual instance
|
|
||||||
// failed. This usually requires introduction of a new variable.
|
|
||||||
//
|
|
||||||
// var err error
|
|
||||||
// for _, item := range items {
|
|
||||||
// if perr := process(item); perr != nil {
|
|
||||||
// log.Warn("skipping item", item)
|
|
||||||
// err = multierr.Append(err, perr)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// multierr includes AppendInto to simplify cases like this.
|
|
||||||
//
|
|
||||||
// var err error
|
|
||||||
// for _, item := range items {
|
|
||||||
// if multierr.AppendInto(&err, process(item)) {
|
|
||||||
// log.Warn("skipping item", item)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// This will append the error into the err variable, and return true if that
|
|
||||||
// individual error was non-nil.
|
|
||||||
//
|
|
||||||
// See [AppendInto] for more information.
|
|
||||||
//
|
|
||||||
// # Deferred Functions
|
|
||||||
//
|
|
||||||
// Go makes it possible to modify the return value of a function in a defer
|
|
||||||
// block if the function was using named returns. This makes it possible to
|
|
||||||
// record resource cleanup failures from deferred blocks.
|
|
||||||
//
|
|
||||||
// func sendRequest(req Request) (err error) {
|
|
||||||
// conn, err := openConnection()
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// defer func() {
|
|
||||||
// err = multierr.Append(err, conn.Close())
|
|
||||||
// }()
|
|
||||||
// // ...
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// multierr provides the Invoker type and AppendInvoke function to make cases
|
|
||||||
// like the above simpler and obviate the need for a closure. The following is
|
|
||||||
// roughly equivalent to the example above.
|
|
||||||
//
|
|
||||||
// func sendRequest(req Request) (err error) {
|
|
||||||
// conn, err := openConnection()
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Close(conn))
|
|
||||||
// // ...
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// See [AppendInvoke] and [Invoker] for more information.
|
|
||||||
//
|
|
||||||
// NOTE: If you're modifying an error from inside a defer, you MUST use a named
|
|
||||||
// return value for that function.
|
|
||||||
//
|
|
||||||
// # Advanced Usage
|
|
||||||
//
|
|
||||||
// Errors returned by Combine and Append MAY implement the following
|
|
||||||
// interface.
|
|
||||||
//
|
|
||||||
// type errorGroup interface {
|
|
||||||
// // Returns a slice containing the underlying list of errors.
|
|
||||||
// //
|
|
||||||
// // This slice MUST NOT be modified by the caller.
|
|
||||||
// Errors() []error
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Note that if you need access to list of errors behind a multierr error, you
|
|
||||||
// should prefer using the Errors function. That said, if you need cheap
|
|
||||||
// read-only access to the underlying errors slice, you can attempt to cast
|
|
||||||
// the error to this interface. You MUST handle the failure case gracefully
|
|
||||||
// because errors returned by Combine and Append are not guaranteed to
|
|
||||||
// implement this interface.
|
|
||||||
//
|
|
||||||
// var errors []error
|
|
||||||
// group, ok := err.(errorGroup)
|
|
||||||
// if ok {
|
|
||||||
// errors = group.Errors()
|
|
||||||
// } else {
|
|
||||||
// errors = []error{err}
|
|
||||||
// }
|
|
||||||
package multierr // import "go.uber.org/multierr"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Separator for single-line error messages.
|
|
||||||
_singlelineSeparator = []byte("; ")
|
|
||||||
|
|
||||||
// Prefix for multi-line messages
|
|
||||||
_multilinePrefix = []byte("the following errors occurred:")
|
|
||||||
|
|
||||||
// Prefix for the first and following lines of an item in a list of
|
|
||||||
// multi-line error messages.
|
|
||||||
//
|
|
||||||
// For example, if a single item is:
|
|
||||||
//
|
|
||||||
// foo
|
|
||||||
// bar
|
|
||||||
//
|
|
||||||
// It will become,
|
|
||||||
//
|
|
||||||
// - foo
|
|
||||||
// bar
|
|
||||||
_multilineSeparator = []byte("\n - ")
|
|
||||||
_multilineIndent = []byte(" ")
|
|
||||||
)
|
|
||||||
|
|
||||||
// _bufferPool is a pool of bytes.Buffers.
|
|
||||||
var _bufferPool = sync.Pool{
|
|
||||||
New: func() interface{} {
|
|
||||||
return &bytes.Buffer{}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
type errorGroup interface {
|
|
||||||
Errors() []error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errors returns a slice containing zero or more errors that the supplied
|
|
||||||
// error is composed of. If the error is nil, a nil slice is returned.
|
|
||||||
//
|
|
||||||
// err := multierr.Append(r.Close(), w.Close())
|
|
||||||
// errors := multierr.Errors(err)
|
|
||||||
//
|
|
||||||
// If the error is not composed of other errors, the returned slice contains
|
|
||||||
// just the error that was passed in.
|
|
||||||
//
|
|
||||||
// Callers of this function are free to modify the returned slice.
|
|
||||||
func Errors(err error) []error {
|
|
||||||
return extractErrors(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// multiError is an error that holds one or more errors.
|
|
||||||
//
|
|
||||||
// An instance of this is guaranteed to be non-empty and flattened. That is,
|
|
||||||
// none of the errors inside multiError are other multiErrors.
|
|
||||||
//
|
|
||||||
// multiError formats to a semi-colon delimited list of error messages with
|
|
||||||
// %v and with a more readable multi-line format with %+v.
|
|
||||||
type multiError struct {
|
|
||||||
copyNeeded atomic.Bool
|
|
||||||
errors []error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errors returns the list of underlying errors.
|
|
||||||
//
|
|
||||||
// This slice MUST NOT be modified.
|
|
||||||
func (merr *multiError) Errors() []error {
|
|
||||||
if merr == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return merr.errors
|
|
||||||
}
|
|
||||||
|
|
||||||
func (merr *multiError) Error() string {
|
|
||||||
if merr == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
buff := _bufferPool.Get().(*bytes.Buffer)
|
|
||||||
buff.Reset()
|
|
||||||
|
|
||||||
merr.writeSingleline(buff)
|
|
||||||
|
|
||||||
result := buff.String()
|
|
||||||
_bufferPool.Put(buff)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Every compares every error in the given err against the given target error
|
|
||||||
// using [errors.Is], and returns true only if every comparison returned true.
|
|
||||||
func Every(err error, target error) bool {
|
|
||||||
for _, e := range extractErrors(err) {
|
|
||||||
if !errors.Is(e, target) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (merr *multiError) Format(f fmt.State, c rune) {
|
|
||||||
if c == 'v' && f.Flag('+') {
|
|
||||||
merr.writeMultiline(f)
|
|
||||||
} else {
|
|
||||||
merr.writeSingleline(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (merr *multiError) writeSingleline(w io.Writer) {
|
|
||||||
first := true
|
|
||||||
for _, item := range merr.errors {
|
|
||||||
if first {
|
|
||||||
first = false
|
|
||||||
} else {
|
|
||||||
w.Write(_singlelineSeparator)
|
|
||||||
}
|
|
||||||
io.WriteString(w, item.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (merr *multiError) writeMultiline(w io.Writer) {
|
|
||||||
w.Write(_multilinePrefix)
|
|
||||||
for _, item := range merr.errors {
|
|
||||||
w.Write(_multilineSeparator)
|
|
||||||
writePrefixLine(w, _multilineIndent, fmt.Sprintf("%+v", item))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes s to the writer with the given prefix added before each line after
|
|
||||||
// the first.
|
|
||||||
func writePrefixLine(w io.Writer, prefix []byte, s string) {
|
|
||||||
first := true
|
|
||||||
for len(s) > 0 {
|
|
||||||
if first {
|
|
||||||
first = false
|
|
||||||
} else {
|
|
||||||
w.Write(prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
idx := strings.IndexByte(s, '\n')
|
|
||||||
if idx < 0 {
|
|
||||||
idx = len(s) - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
io.WriteString(w, s[:idx+1])
|
|
||||||
s = s[idx+1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type inspectResult struct {
|
|
||||||
// Number of top-level non-nil errors
|
|
||||||
Count int
|
|
||||||
|
|
||||||
// Total number of errors including multiErrors
|
|
||||||
Capacity int
|
|
||||||
|
|
||||||
// Index of the first non-nil error in the list. Value is meaningless if
|
|
||||||
// Count is zero.
|
|
||||||
FirstErrorIdx int
|
|
||||||
|
|
||||||
// Whether the list contains at least one multiError
|
|
||||||
ContainsMultiError bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inspects the given slice of errors so that we can efficiently allocate
|
|
||||||
// space for it.
|
|
||||||
func inspect(errors []error) (res inspectResult) {
|
|
||||||
first := true
|
|
||||||
for i, err := range errors {
|
|
||||||
if err == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
res.Count++
|
|
||||||
if first {
|
|
||||||
first = false
|
|
||||||
res.FirstErrorIdx = i
|
|
||||||
}
|
|
||||||
|
|
||||||
if merr, ok := err.(*multiError); ok {
|
|
||||||
res.Capacity += len(merr.errors)
|
|
||||||
res.ContainsMultiError = true
|
|
||||||
} else {
|
|
||||||
res.Capacity++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// fromSlice converts the given list of errors into a single error.
|
|
||||||
func fromSlice(errors []error) error {
|
|
||||||
// Don't pay to inspect small slices.
|
|
||||||
switch len(errors) {
|
|
||||||
case 0:
|
|
||||||
return nil
|
|
||||||
case 1:
|
|
||||||
return errors[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
res := inspect(errors)
|
|
||||||
switch res.Count {
|
|
||||||
case 0:
|
|
||||||
return nil
|
|
||||||
case 1:
|
|
||||||
// only one non-nil entry
|
|
||||||
return errors[res.FirstErrorIdx]
|
|
||||||
case len(errors):
|
|
||||||
if !res.ContainsMultiError {
|
|
||||||
// Error list is flat. Make a copy of it
|
|
||||||
// Otherwise "errors" escapes to the heap
|
|
||||||
// unconditionally for all other cases.
|
|
||||||
// This lets us optimize for the "no errors" case.
|
|
||||||
out := append(([]error)(nil), errors...)
|
|
||||||
return &multiError{errors: out}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nonNilErrs := make([]error, 0, res.Capacity)
|
|
||||||
for _, err := range errors[res.FirstErrorIdx:] {
|
|
||||||
if err == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if nested, ok := err.(*multiError); ok {
|
|
||||||
nonNilErrs = append(nonNilErrs, nested.errors...)
|
|
||||||
} else {
|
|
||||||
nonNilErrs = append(nonNilErrs, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &multiError{errors: nonNilErrs}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Combine combines the passed errors into a single error.
|
|
||||||
//
|
|
||||||
// If zero arguments were passed or if all items are nil, a nil error is
|
|
||||||
// returned.
|
|
||||||
//
|
|
||||||
// Combine(nil, nil) // == nil
|
|
||||||
//
|
|
||||||
// If only a single error was passed, it is returned as-is.
|
|
||||||
//
|
|
||||||
// Combine(err) // == err
|
|
||||||
//
|
|
||||||
// Combine skips over nil arguments so this function may be used to combine
|
|
||||||
// together errors from operations that fail independently of each other.
|
|
||||||
//
|
|
||||||
// multierr.Combine(
|
|
||||||
// reader.Close(),
|
|
||||||
// writer.Close(),
|
|
||||||
// pipe.Close(),
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// If any of the passed errors is a multierr error, it will be flattened along
|
|
||||||
// with the other errors.
|
|
||||||
//
|
|
||||||
// multierr.Combine(multierr.Combine(err1, err2), err3)
|
|
||||||
// // is the same as
|
|
||||||
// multierr.Combine(err1, err2, err3)
|
|
||||||
//
|
|
||||||
// The returned error formats into a readable multi-line error message if
|
|
||||||
// formatted with %+v.
|
|
||||||
//
|
|
||||||
// fmt.Sprintf("%+v", multierr.Combine(err1, err2))
|
|
||||||
func Combine(errors ...error) error {
|
|
||||||
return fromSlice(errors)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append appends the given errors together. Either value may be nil.
|
|
||||||
//
|
|
||||||
// This function is a specialization of Combine for the common case where
|
|
||||||
// there are only two errors.
|
|
||||||
//
|
|
||||||
// err = multierr.Append(reader.Close(), writer.Close())
|
|
||||||
//
|
|
||||||
// The following pattern may also be used to record failure of deferred
|
|
||||||
// operations without losing information about the original error.
|
|
||||||
//
|
|
||||||
// func doSomething(..) (err error) {
|
|
||||||
// f := acquireResource()
|
|
||||||
// defer func() {
|
|
||||||
// err = multierr.Append(err, f.Close())
|
|
||||||
// }()
|
|
||||||
//
|
|
||||||
// Note that the variable MUST be a named return to append an error to it from
|
|
||||||
// the defer statement. See also [AppendInvoke].
|
|
||||||
func Append(left error, right error) error {
|
|
||||||
switch {
|
|
||||||
case left == nil:
|
|
||||||
return right
|
|
||||||
case right == nil:
|
|
||||||
return left
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := right.(*multiError); !ok {
|
|
||||||
if l, ok := left.(*multiError); ok && !l.copyNeeded.Swap(true) {
|
|
||||||
// Common case where the error on the left is constantly being
|
|
||||||
// appended to.
|
|
||||||
errs := append(l.errors, right)
|
|
||||||
return &multiError{errors: errs}
|
|
||||||
} else if !ok {
|
|
||||||
// Both errors are single errors.
|
|
||||||
return &multiError{errors: []error{left, right}}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Either right or both, left and right, are multiErrors. Rely on usual
|
|
||||||
// expensive logic.
|
|
||||||
errors := [2]error{left, right}
|
|
||||||
return fromSlice(errors[0:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppendInto appends an error into the destination of an error pointer and
|
|
||||||
// returns whether the error being appended was non-nil.
|
|
||||||
//
|
|
||||||
// var err error
|
|
||||||
// multierr.AppendInto(&err, r.Close())
|
|
||||||
// multierr.AppendInto(&err, w.Close())
|
|
||||||
//
|
|
||||||
// The above is equivalent to,
|
|
||||||
//
|
|
||||||
// err := multierr.Append(r.Close(), w.Close())
|
|
||||||
//
|
|
||||||
// As AppendInto reports whether the provided error was non-nil, it may be
|
|
||||||
// used to build a multierr error in a loop more ergonomically. For example:
|
|
||||||
//
|
|
||||||
// var err error
|
|
||||||
// for line := range lines {
|
|
||||||
// var item Item
|
|
||||||
// if multierr.AppendInto(&err, parse(line, &item)) {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// items = append(items, item)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Compare this with a version that relies solely on Append:
|
|
||||||
//
|
|
||||||
// var err error
|
|
||||||
// for line := range lines {
|
|
||||||
// var item Item
|
|
||||||
// if parseErr := parse(line, &item); parseErr != nil {
|
|
||||||
// err = multierr.Append(err, parseErr)
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// items = append(items, item)
|
|
||||||
// }
|
|
||||||
func AppendInto(into *error, err error) (errored bool) {
|
|
||||||
if into == nil {
|
|
||||||
// We panic if 'into' is nil. This is not documented above
|
|
||||||
// because suggesting that the pointer must be non-nil may
|
|
||||||
// confuse users into thinking that the error that it points
|
|
||||||
// to must be non-nil.
|
|
||||||
panic("misuse of multierr.AppendInto: into pointer must not be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
*into = Append(*into, err)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoker is an operation that may fail with an error. Use it with
|
|
||||||
// AppendInvoke to append the result of calling the function into an error.
|
|
||||||
// This allows you to conveniently defer capture of failing operations.
|
|
||||||
//
|
|
||||||
// See also, [Close] and [Invoke].
|
|
||||||
type Invoker interface {
|
|
||||||
Invoke() error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoke wraps a function which may fail with an error to match the Invoker
|
|
||||||
// interface. Use it to supply functions matching this signature to
|
|
||||||
// AppendInvoke.
|
|
||||||
//
|
|
||||||
// For example,
|
|
||||||
//
|
|
||||||
// func processReader(r io.Reader) (err error) {
|
|
||||||
// scanner := bufio.NewScanner(r)
|
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
|
|
||||||
// for scanner.Scan() {
|
|
||||||
// // ...
|
|
||||||
// }
|
|
||||||
// // ...
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// In this example, the following line will construct the Invoker right away,
|
|
||||||
// but defer the invocation of scanner.Err() until the function returns.
|
|
||||||
//
|
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
|
|
||||||
//
|
|
||||||
// Note that the error you're appending to from the defer statement MUST be a
|
|
||||||
// named return.
|
|
||||||
type Invoke func() error
|
|
||||||
|
|
||||||
// Invoke calls the supplied function and returns its result.
|
|
||||||
func (i Invoke) Invoke() error { return i() }
|
|
||||||
|
|
||||||
// Close builds an Invoker that closes the provided io.Closer. Use it with
|
|
||||||
// AppendInvoke to close io.Closers and append their results into an error.
|
|
||||||
//
|
|
||||||
// For example,
|
|
||||||
//
|
|
||||||
// func processFile(path string) (err error) {
|
|
||||||
// f, err := os.Open(path)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Close(f))
|
|
||||||
// return processReader(f)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// In this example, multierr.Close will construct the Invoker right away, but
|
|
||||||
// defer the invocation of f.Close until the function returns.
|
|
||||||
//
|
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Close(f))
|
|
||||||
//
|
|
||||||
// Note that the error you're appending to from the defer statement MUST be a
|
|
||||||
// named return.
|
|
||||||
func Close(closer io.Closer) Invoker {
|
|
||||||
return Invoke(closer.Close)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppendInvoke appends the result of calling the given Invoker into the
|
|
||||||
// provided error pointer. Use it with named returns to safely defer
|
|
||||||
// invocation of fallible operations until a function returns, and capture the
|
|
||||||
// resulting errors.
|
|
||||||
//
|
|
||||||
// func doSomething(...) (err error) {
|
|
||||||
// // ...
|
|
||||||
// f, err := openFile(..)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // multierr will call f.Close() when this function returns and
|
|
||||||
// // if the operation fails, its append its error into the
|
|
||||||
// // returned error.
|
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Close(f))
|
|
||||||
//
|
|
||||||
// scanner := bufio.NewScanner(f)
|
|
||||||
// // Similarly, this scheduled scanner.Err to be called and
|
|
||||||
// // inspected when the function returns and append its error
|
|
||||||
// // into the returned error.
|
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
|
|
||||||
//
|
|
||||||
// // ...
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// NOTE: If used with a defer, the error variable MUST be a named return.
|
|
||||||
//
|
|
||||||
// Without defer, AppendInvoke behaves exactly like AppendInto.
|
|
||||||
//
|
|
||||||
// err := // ...
|
|
||||||
// multierr.AppendInvoke(&err, mutltierr.Invoke(foo))
|
|
||||||
//
|
|
||||||
// // ...is roughly equivalent to...
|
|
||||||
//
|
|
||||||
// err := // ...
|
|
||||||
// multierr.AppendInto(&err, foo())
|
|
||||||
//
|
|
||||||
// The advantage of the indirection introduced by Invoker is to make it easy
|
|
||||||
// to defer the invocation of a function. Without this indirection, the
|
|
||||||
// invoked function will be evaluated at the time of the defer block rather
|
|
||||||
// than when the function returns.
|
|
||||||
//
|
|
||||||
// // BAD: This is likely not what the caller intended. This will evaluate
|
|
||||||
// // foo() right away and append its result into the error when the
|
|
||||||
// // function returns.
|
|
||||||
// defer multierr.AppendInto(&err, foo())
|
|
||||||
//
|
|
||||||
// // GOOD: This will defer invocation of foo unutil the function returns.
|
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Invoke(foo))
|
|
||||||
//
|
|
||||||
// multierr provides a few Invoker implementations out of the box for
|
|
||||||
// convenience. See [Invoker] for more information.
|
|
||||||
func AppendInvoke(into *error, invoker Invoker) {
|
|
||||||
AppendInto(into, invoker.Invoke())
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppendFunc is a shorthand for [AppendInvoke].
|
|
||||||
// It allows using function or method value directly
|
|
||||||
// without having to wrap it into an [Invoker] interface.
|
|
||||||
//
|
|
||||||
// func doSomething(...) (err error) {
|
|
||||||
// w, err := startWorker(...)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // multierr will call w.Stop() when this function returns and
|
|
||||||
// // if the operation fails, it appends its error into the
|
|
||||||
// // returned error.
|
|
||||||
// defer multierr.AppendFunc(&err, w.Stop)
|
|
||||||
// }
|
|
||||||
func AppendFunc(into *error, fn func() error) {
|
|
||||||
AppendInvoke(into, Invoke(fn))
|
|
||||||
}
|
|
||||||
48
vendor/go.uber.org/multierr/error_post_go120.go
generated
vendored
48
vendor/go.uber.org/multierr/error_post_go120.go
generated
vendored
|
|
@ -1,48 +0,0 @@
|
||||||
// Copyright (c) 2017-2023 Uber Technologies, 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.
|
|
||||||
|
|
||||||
//go:build go1.20
|
|
||||||
// +build go1.20
|
|
||||||
|
|
||||||
package multierr
|
|
||||||
|
|
||||||
// Unwrap returns a list of errors wrapped by this multierr.
|
|
||||||
func (merr *multiError) Unwrap() []error {
|
|
||||||
return merr.Errors()
|
|
||||||
}
|
|
||||||
|
|
||||||
type multipleErrors interface {
|
|
||||||
Unwrap() []error
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractErrors(err error) []error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the given err is an Unwrapable error that
|
|
||||||
// implements multipleErrors interface.
|
|
||||||
eg, ok := err.(multipleErrors)
|
|
||||||
if !ok {
|
|
||||||
return []error{err}
|
|
||||||
}
|
|
||||||
|
|
||||||
return append(([]error)(nil), eg.Unwrap()...)
|
|
||||||
}
|
|
||||||
79
vendor/go.uber.org/multierr/error_pre_go120.go
generated
vendored
79
vendor/go.uber.org/multierr/error_pre_go120.go
generated
vendored
|
|
@ -1,79 +0,0 @@
|
||||||
// Copyright (c) 2017-2023 Uber Technologies, 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.
|
|
||||||
|
|
||||||
//go:build !go1.20
|
|
||||||
// +build !go1.20
|
|
||||||
|
|
||||||
package multierr
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
// Versions of Go before 1.20 did not support the Unwrap() []error method.
|
|
||||||
// This provides a similar behavior by implementing the Is(..) and As(..)
|
|
||||||
// methods.
|
|
||||||
// See the errors.Join proposal for details:
|
|
||||||
// https://github.com/golang/go/issues/53435
|
|
||||||
|
|
||||||
// As attempts to find the first error in the error list that matches the type
|
|
||||||
// of the value that target points to.
|
|
||||||
//
|
|
||||||
// This function allows errors.As to traverse the values stored on the
|
|
||||||
// multierr error.
|
|
||||||
func (merr *multiError) As(target interface{}) bool {
|
|
||||||
for _, err := range merr.Errors() {
|
|
||||||
if errors.As(err, target) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is attempts to match the provided error against errors in the error list.
|
|
||||||
//
|
|
||||||
// This function allows errors.Is to traverse the values stored on the
|
|
||||||
// multierr error.
|
|
||||||
func (merr *multiError) Is(target error) bool {
|
|
||||||
for _, err := range merr.Errors() {
|
|
||||||
if errors.Is(err, target) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractErrors(err error) []error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that we're casting to multiError, not errorGroup. Our contract is
|
|
||||||
// that returned errors MAY implement errorGroup. Errors, however, only
|
|
||||||
// has special behavior for multierr-specific error objects.
|
|
||||||
//
|
|
||||||
// This behavior can be expanded in the future but I think it's prudent to
|
|
||||||
// start with as little as possible in terms of contract and possibility
|
|
||||||
// of misuse.
|
|
||||||
eg, ok := err.(*multiError)
|
|
||||||
if !ok {
|
|
||||||
return []error{err}
|
|
||||||
}
|
|
||||||
|
|
||||||
return append(([]error)(nil), eg.Errors()...)
|
|
||||||
}
|
|
||||||
50
vendor/go.yaml.in/yaml/v3/LICENSE
generated
vendored
Normal file
50
vendor/go.yaml.in/yaml/v3/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
This project is covered by two different licenses: MIT and Apache.
|
||||||
|
|
||||||
|
#### MIT License ####
|
||||||
|
|
||||||
|
The following files were ported to Go from C files of libyaml, and thus
|
||||||
|
are still covered by their original MIT license, with the additional
|
||||||
|
copyright staring in 2011 when the project was ported over:
|
||||||
|
|
||||||
|
apic.go emitterc.go parserc.go readerc.go scannerc.go
|
||||||
|
writerc.go yamlh.go yamlprivateh.go
|
||||||
|
|
||||||
|
Copyright (c) 2006-2010 Kirill Simonov
|
||||||
|
Copyright (c) 2006-2011 Kirill Simonov
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Apache License ###
|
||||||
|
|
||||||
|
All the remaining project files are covered by the Apache license:
|
||||||
|
|
||||||
|
Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
13
vendor/go.yaml.in/yaml/v3/NOTICE
generated
vendored
Normal file
13
vendor/go.yaml.in/yaml/v3/NOTICE
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
Copyright 2011-2016 Canonical Ltd.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
171
vendor/go.yaml.in/yaml/v3/README.md
generated
vendored
Normal file
171
vendor/go.yaml.in/yaml/v3/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
go.yaml.in/yaml
|
||||||
|
===============
|
||||||
|
|
||||||
|
YAML Support for the Go Language
|
||||||
|
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
The `yaml` package enables [Go](https://go.dev/) programs to comfortably encode
|
||||||
|
and decode [YAML](https://yaml.org/) values.
|
||||||
|
|
||||||
|
It was originally developed within [Canonical](https://www.canonical.com) as
|
||||||
|
part of the [juju](https://juju.ubuntu.com) project, and is based on a pure Go
|
||||||
|
port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) C library to
|
||||||
|
parse and generate YAML data quickly and reliably.
|
||||||
|
|
||||||
|
|
||||||
|
## Project Status
|
||||||
|
|
||||||
|
This project started as a fork of the extremely popular [go-yaml](
|
||||||
|
https://github.com/go-yaml/yaml/)
|
||||||
|
project, and is being maintained by the official [YAML organization](
|
||||||
|
https://github.com/yaml/).
|
||||||
|
|
||||||
|
The YAML team took over ongoing maintenance and development of the project after
|
||||||
|
discussion with go-yaml's author, @niemeyer, following his decision to
|
||||||
|
[label the project repository as "unmaintained"](
|
||||||
|
https://github.com/go-yaml/yaml/blob/944c86a7d2/README.md) in April 2025.
|
||||||
|
|
||||||
|
We have put together a team of dedicated maintainers including representatives
|
||||||
|
of go-yaml's most important downstream projects.
|
||||||
|
|
||||||
|
We will strive to earn the trust of the various go-yaml forks to switch back to
|
||||||
|
this repository as their upstream.
|
||||||
|
|
||||||
|
Please [contact us](https://cloud-native.slack.com/archives/C08PPAT8PS7) if you
|
||||||
|
would like to contribute or be involved.
|
||||||
|
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
The `yaml` package supports most of YAML 1.2, but preserves some behavior from
|
||||||
|
1.1 for backwards compatibility.
|
||||||
|
|
||||||
|
Specifically, v3 of the `yaml` package:
|
||||||
|
|
||||||
|
* Supports YAML 1.1 bools (`yes`/`no`, `on`/`off`) as long as they are being
|
||||||
|
decoded into a typed bool value.
|
||||||
|
Otherwise they behave as a string.
|
||||||
|
Booleans in YAML 1.2 are `true`/`false` only.
|
||||||
|
* Supports octals encoded and decoded as `0777` per YAML 1.1, rather than
|
||||||
|
`0o777` as specified in YAML 1.2, because most parsers still use the old
|
||||||
|
format.
|
||||||
|
Octals in the `0o777` format are supported though, so new files work.
|
||||||
|
* Does not support base-60 floats.
|
||||||
|
These are gone from YAML 1.2, and were actually never supported by this
|
||||||
|
package as it's clearly a poor choice.
|
||||||
|
|
||||||
|
|
||||||
|
## Installation and Usage
|
||||||
|
|
||||||
|
The import path for the package is *go.yaml.in/yaml/v3*.
|
||||||
|
|
||||||
|
To install it, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go get go.yaml.in/yaml/v3
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## API Documentation
|
||||||
|
|
||||||
|
See: <https://pkg.go.dev/go.yaml.in/yaml/v3>
|
||||||
|
|
||||||
|
|
||||||
|
## API Stability
|
||||||
|
|
||||||
|
The package API for yaml v3 will remain stable as described in [gopkg.in](
|
||||||
|
https://gopkg.in).
|
||||||
|
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"go.yaml.in/yaml/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var data = `
|
||||||
|
a: Easy!
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
d: [3, 4]
|
||||||
|
`
|
||||||
|
|
||||||
|
// Note: struct fields must be public in order for unmarshal to
|
||||||
|
// correctly populate the data.
|
||||||
|
type T struct {
|
||||||
|
A string
|
||||||
|
B struct {
|
||||||
|
RenamedC int `yaml:"c"`
|
||||||
|
D []int `yaml:",flow"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := T{}
|
||||||
|
|
||||||
|
err := yaml.Unmarshal([]byte(data), &t)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("--- t:\n%v\n\n", t)
|
||||||
|
|
||||||
|
d, err := yaml.Marshal(&t)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("--- t dump:\n%s\n\n", string(d))
|
||||||
|
|
||||||
|
m := make(map[interface{}]interface{})
|
||||||
|
|
||||||
|
err = yaml.Unmarshal([]byte(data), &m)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("--- m:\n%v\n\n", m)
|
||||||
|
|
||||||
|
d, err = yaml.Marshal(&m)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("--- m dump:\n%s\n\n", string(d))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This example will generate the following output:
|
||||||
|
|
||||||
|
```
|
||||||
|
--- t:
|
||||||
|
{Easy! {2 [3 4]}}
|
||||||
|
|
||||||
|
--- t dump:
|
||||||
|
a: Easy!
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
d: [3, 4]
|
||||||
|
|
||||||
|
|
||||||
|
--- m:
|
||||||
|
map[a:Easy! b:map[c:2 d:[3 4]]]
|
||||||
|
|
||||||
|
--- m dump:
|
||||||
|
a: Easy!
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
d:
|
||||||
|
- 3
|
||||||
|
- 4
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
The yaml package is licensed under the MIT and Apache License 2.0 licenses.
|
||||||
|
Please see the LICENSE file for details.
|
||||||
747
vendor/go.yaml.in/yaml/v3/apic.go
generated
vendored
Normal file
747
vendor/go.yaml.in/yaml/v3/apic.go
generated
vendored
Normal file
|
|
@ -0,0 +1,747 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
|
||||||
|
//fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
|
||||||
|
|
||||||
|
// Check if we can move the queue at the beginning of the buffer.
|
||||||
|
if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
|
||||||
|
if parser.tokens_head != len(parser.tokens) {
|
||||||
|
copy(parser.tokens, parser.tokens[parser.tokens_head:])
|
||||||
|
}
|
||||||
|
parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
|
||||||
|
parser.tokens_head = 0
|
||||||
|
}
|
||||||
|
parser.tokens = append(parser.tokens, *token)
|
||||||
|
if pos < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
|
||||||
|
parser.tokens[parser.tokens_head+pos] = *token
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new parser object.
|
||||||
|
func yaml_parser_initialize(parser *yaml_parser_t) bool {
|
||||||
|
*parser = yaml_parser_t{
|
||||||
|
raw_buffer: make([]byte, 0, input_raw_buffer_size),
|
||||||
|
buffer: make([]byte, 0, input_buffer_size),
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy a parser object.
|
||||||
|
func yaml_parser_delete(parser *yaml_parser_t) {
|
||||||
|
*parser = yaml_parser_t{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String read handler.
|
||||||
|
func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
|
||||||
|
if parser.input_pos == len(parser.input) {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
n = copy(buffer, parser.input[parser.input_pos:])
|
||||||
|
parser.input_pos += n
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader read handler.
|
||||||
|
func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
|
||||||
|
return parser.input_reader.Read(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a string input.
|
||||||
|
func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
|
||||||
|
if parser.read_handler != nil {
|
||||||
|
panic("must set the input source only once")
|
||||||
|
}
|
||||||
|
parser.read_handler = yaml_string_read_handler
|
||||||
|
parser.input = input
|
||||||
|
parser.input_pos = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a file input.
|
||||||
|
func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
|
||||||
|
if parser.read_handler != nil {
|
||||||
|
panic("must set the input source only once")
|
||||||
|
}
|
||||||
|
parser.read_handler = yaml_reader_read_handler
|
||||||
|
parser.input_reader = r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the source encoding.
|
||||||
|
func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
|
||||||
|
if parser.encoding != yaml_ANY_ENCODING {
|
||||||
|
panic("must set the encoding only once")
|
||||||
|
}
|
||||||
|
parser.encoding = encoding
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new emitter object.
|
||||||
|
func yaml_emitter_initialize(emitter *yaml_emitter_t) {
|
||||||
|
*emitter = yaml_emitter_t{
|
||||||
|
buffer: make([]byte, output_buffer_size),
|
||||||
|
raw_buffer: make([]byte, 0, output_raw_buffer_size),
|
||||||
|
states: make([]yaml_emitter_state_t, 0, initial_stack_size),
|
||||||
|
events: make([]yaml_event_t, 0, initial_queue_size),
|
||||||
|
best_width: -1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy an emitter object.
|
||||||
|
func yaml_emitter_delete(emitter *yaml_emitter_t) {
|
||||||
|
*emitter = yaml_emitter_t{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String write handler.
|
||||||
|
func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
|
||||||
|
*emitter.output_buffer = append(*emitter.output_buffer, buffer...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// yaml_writer_write_handler uses emitter.output_writer to write the
|
||||||
|
// emitted text.
|
||||||
|
func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
|
||||||
|
_, err := emitter.output_writer.Write(buffer)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a string output.
|
||||||
|
func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
|
||||||
|
if emitter.write_handler != nil {
|
||||||
|
panic("must set the output target only once")
|
||||||
|
}
|
||||||
|
emitter.write_handler = yaml_string_write_handler
|
||||||
|
emitter.output_buffer = output_buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a file output.
|
||||||
|
func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
|
||||||
|
if emitter.write_handler != nil {
|
||||||
|
panic("must set the output target only once")
|
||||||
|
}
|
||||||
|
emitter.write_handler = yaml_writer_write_handler
|
||||||
|
emitter.output_writer = w
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the output encoding.
|
||||||
|
func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
|
||||||
|
if emitter.encoding != yaml_ANY_ENCODING {
|
||||||
|
panic("must set the output encoding only once")
|
||||||
|
}
|
||||||
|
emitter.encoding = encoding
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the canonical output style.
|
||||||
|
func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
|
||||||
|
emitter.canonical = canonical
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the indentation increment.
|
||||||
|
func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
|
||||||
|
if indent < 2 || indent > 9 {
|
||||||
|
indent = 2
|
||||||
|
}
|
||||||
|
emitter.best_indent = indent
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the preferred line width.
|
||||||
|
func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
|
||||||
|
if width < 0 {
|
||||||
|
width = -1
|
||||||
|
}
|
||||||
|
emitter.best_width = width
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set if unescaped non-ASCII characters are allowed.
|
||||||
|
func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
|
||||||
|
emitter.unicode = unicode
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the preferred line break character.
|
||||||
|
func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
|
||||||
|
emitter.line_break = line_break
|
||||||
|
}
|
||||||
|
|
||||||
|
///*
|
||||||
|
// * Destroy a token object.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(void)
|
||||||
|
//yaml_token_delete(yaml_token_t *token)
|
||||||
|
//{
|
||||||
|
// assert(token); // Non-NULL token object expected.
|
||||||
|
//
|
||||||
|
// switch (token.type)
|
||||||
|
// {
|
||||||
|
// case YAML_TAG_DIRECTIVE_TOKEN:
|
||||||
|
// yaml_free(token.data.tag_directive.handle);
|
||||||
|
// yaml_free(token.data.tag_directive.prefix);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case YAML_ALIAS_TOKEN:
|
||||||
|
// yaml_free(token.data.alias.value);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case YAML_ANCHOR_TOKEN:
|
||||||
|
// yaml_free(token.data.anchor.value);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case YAML_TAG_TOKEN:
|
||||||
|
// yaml_free(token.data.tag.handle);
|
||||||
|
// yaml_free(token.data.tag.suffix);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case YAML_SCALAR_TOKEN:
|
||||||
|
// yaml_free(token.data.scalar.value);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// memset(token, 0, sizeof(yaml_token_t));
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Check if a string is a valid UTF-8 sequence.
|
||||||
|
// *
|
||||||
|
// * Check 'reader.c' for more details on UTF-8 encoding.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//static int
|
||||||
|
//yaml_check_utf8(yaml_char_t *start, size_t length)
|
||||||
|
//{
|
||||||
|
// yaml_char_t *end = start+length;
|
||||||
|
// yaml_char_t *pointer = start;
|
||||||
|
//
|
||||||
|
// while (pointer < end) {
|
||||||
|
// unsigned char octet;
|
||||||
|
// unsigned int width;
|
||||||
|
// unsigned int value;
|
||||||
|
// size_t k;
|
||||||
|
//
|
||||||
|
// octet = pointer[0];
|
||||||
|
// width = (octet & 0x80) == 0x00 ? 1 :
|
||||||
|
// (octet & 0xE0) == 0xC0 ? 2 :
|
||||||
|
// (octet & 0xF0) == 0xE0 ? 3 :
|
||||||
|
// (octet & 0xF8) == 0xF0 ? 4 : 0;
|
||||||
|
// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
|
||||||
|
// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
|
||||||
|
// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
|
||||||
|
// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
|
||||||
|
// if (!width) return 0;
|
||||||
|
// if (pointer+width > end) return 0;
|
||||||
|
// for (k = 1; k < width; k ++) {
|
||||||
|
// octet = pointer[k];
|
||||||
|
// if ((octet & 0xC0) != 0x80) return 0;
|
||||||
|
// value = (value << 6) + (octet & 0x3F);
|
||||||
|
// }
|
||||||
|
// if (!((width == 1) ||
|
||||||
|
// (width == 2 && value >= 0x80) ||
|
||||||
|
// (width == 3 && value >= 0x800) ||
|
||||||
|
// (width == 4 && value >= 0x10000))) return 0;
|
||||||
|
//
|
||||||
|
// pointer += width;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return 1;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
|
||||||
|
// Create STREAM-START.
|
||||||
|
func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_STREAM_START_EVENT,
|
||||||
|
encoding: encoding,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create STREAM-END.
|
||||||
|
func yaml_stream_end_event_initialize(event *yaml_event_t) {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_STREAM_END_EVENT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create DOCUMENT-START.
|
||||||
|
func yaml_document_start_event_initialize(
|
||||||
|
event *yaml_event_t,
|
||||||
|
version_directive *yaml_version_directive_t,
|
||||||
|
tag_directives []yaml_tag_directive_t,
|
||||||
|
implicit bool,
|
||||||
|
) {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_DOCUMENT_START_EVENT,
|
||||||
|
version_directive: version_directive,
|
||||||
|
tag_directives: tag_directives,
|
||||||
|
implicit: implicit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create DOCUMENT-END.
|
||||||
|
func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_DOCUMENT_END_EVENT,
|
||||||
|
implicit: implicit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create ALIAS.
|
||||||
|
func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_ALIAS_EVENT,
|
||||||
|
anchor: anchor,
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create SCALAR.
|
||||||
|
func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_SCALAR_EVENT,
|
||||||
|
anchor: anchor,
|
||||||
|
tag: tag,
|
||||||
|
value: value,
|
||||||
|
implicit: plain_implicit,
|
||||||
|
quoted_implicit: quoted_implicit,
|
||||||
|
style: yaml_style_t(style),
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create SEQUENCE-START.
|
||||||
|
func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_SEQUENCE_START_EVENT,
|
||||||
|
anchor: anchor,
|
||||||
|
tag: tag,
|
||||||
|
implicit: implicit,
|
||||||
|
style: yaml_style_t(style),
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create SEQUENCE-END.
|
||||||
|
func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_SEQUENCE_END_EVENT,
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create MAPPING-START.
|
||||||
|
func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_MAPPING_START_EVENT,
|
||||||
|
anchor: anchor,
|
||||||
|
tag: tag,
|
||||||
|
implicit: implicit,
|
||||||
|
style: yaml_style_t(style),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create MAPPING-END.
|
||||||
|
func yaml_mapping_end_event_initialize(event *yaml_event_t) {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_MAPPING_END_EVENT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy an event object.
|
||||||
|
func yaml_event_delete(event *yaml_event_t) {
|
||||||
|
*event = yaml_event_t{}
|
||||||
|
}
|
||||||
|
|
||||||
|
///*
|
||||||
|
// * Create a document object.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_initialize(document *yaml_document_t,
|
||||||
|
// version_directive *yaml_version_directive_t,
|
||||||
|
// tag_directives_start *yaml_tag_directive_t,
|
||||||
|
// tag_directives_end *yaml_tag_directive_t,
|
||||||
|
// start_implicit int, end_implicit int)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// struct {
|
||||||
|
// start *yaml_node_t
|
||||||
|
// end *yaml_node_t
|
||||||
|
// top *yaml_node_t
|
||||||
|
// } nodes = { NULL, NULL, NULL }
|
||||||
|
// version_directive_copy *yaml_version_directive_t = NULL
|
||||||
|
// struct {
|
||||||
|
// start *yaml_tag_directive_t
|
||||||
|
// end *yaml_tag_directive_t
|
||||||
|
// top *yaml_tag_directive_t
|
||||||
|
// } tag_directives_copy = { NULL, NULL, NULL }
|
||||||
|
// value yaml_tag_directive_t = { NULL, NULL }
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
// assert((tag_directives_start && tag_directives_end) ||
|
||||||
|
// (tag_directives_start == tag_directives_end))
|
||||||
|
// // Valid tag directives are expected.
|
||||||
|
//
|
||||||
|
// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
|
||||||
|
//
|
||||||
|
// if (version_directive) {
|
||||||
|
// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
|
||||||
|
// if (!version_directive_copy) goto error
|
||||||
|
// version_directive_copy.major = version_directive.major
|
||||||
|
// version_directive_copy.minor = version_directive.minor
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (tag_directives_start != tag_directives_end) {
|
||||||
|
// tag_directive *yaml_tag_directive_t
|
||||||
|
// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
|
||||||
|
// goto error
|
||||||
|
// for (tag_directive = tag_directives_start
|
||||||
|
// tag_directive != tag_directives_end; tag_directive ++) {
|
||||||
|
// assert(tag_directive.handle)
|
||||||
|
// assert(tag_directive.prefix)
|
||||||
|
// if (!yaml_check_utf8(tag_directive.handle,
|
||||||
|
// strlen((char *)tag_directive.handle)))
|
||||||
|
// goto error
|
||||||
|
// if (!yaml_check_utf8(tag_directive.prefix,
|
||||||
|
// strlen((char *)tag_directive.prefix)))
|
||||||
|
// goto error
|
||||||
|
// value.handle = yaml_strdup(tag_directive.handle)
|
||||||
|
// value.prefix = yaml_strdup(tag_directive.prefix)
|
||||||
|
// if (!value.handle || !value.prefix) goto error
|
||||||
|
// if (!PUSH(&context, tag_directives_copy, value))
|
||||||
|
// goto error
|
||||||
|
// value.handle = NULL
|
||||||
|
// value.prefix = NULL
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
|
||||||
|
// tag_directives_copy.start, tag_directives_copy.top,
|
||||||
|
// start_implicit, end_implicit, mark, mark)
|
||||||
|
//
|
||||||
|
// return 1
|
||||||
|
//
|
||||||
|
//error:
|
||||||
|
// STACK_DEL(&context, nodes)
|
||||||
|
// yaml_free(version_directive_copy)
|
||||||
|
// while (!STACK_EMPTY(&context, tag_directives_copy)) {
|
||||||
|
// value yaml_tag_directive_t = POP(&context, tag_directives_copy)
|
||||||
|
// yaml_free(value.handle)
|
||||||
|
// yaml_free(value.prefix)
|
||||||
|
// }
|
||||||
|
// STACK_DEL(&context, tag_directives_copy)
|
||||||
|
// yaml_free(value.handle)
|
||||||
|
// yaml_free(value.prefix)
|
||||||
|
//
|
||||||
|
// return 0
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Destroy a document object.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(void)
|
||||||
|
//yaml_document_delete(document *yaml_document_t)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// tag_directive *yaml_tag_directive_t
|
||||||
|
//
|
||||||
|
// context.error = YAML_NO_ERROR // Eliminate a compiler warning.
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// while (!STACK_EMPTY(&context, document.nodes)) {
|
||||||
|
// node yaml_node_t = POP(&context, document.nodes)
|
||||||
|
// yaml_free(node.tag)
|
||||||
|
// switch (node.type) {
|
||||||
|
// case YAML_SCALAR_NODE:
|
||||||
|
// yaml_free(node.data.scalar.value)
|
||||||
|
// break
|
||||||
|
// case YAML_SEQUENCE_NODE:
|
||||||
|
// STACK_DEL(&context, node.data.sequence.items)
|
||||||
|
// break
|
||||||
|
// case YAML_MAPPING_NODE:
|
||||||
|
// STACK_DEL(&context, node.data.mapping.pairs)
|
||||||
|
// break
|
||||||
|
// default:
|
||||||
|
// assert(0) // Should not happen.
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// STACK_DEL(&context, document.nodes)
|
||||||
|
//
|
||||||
|
// yaml_free(document.version_directive)
|
||||||
|
// for (tag_directive = document.tag_directives.start
|
||||||
|
// tag_directive != document.tag_directives.end
|
||||||
|
// tag_directive++) {
|
||||||
|
// yaml_free(tag_directive.handle)
|
||||||
|
// yaml_free(tag_directive.prefix)
|
||||||
|
// }
|
||||||
|
// yaml_free(document.tag_directives.start)
|
||||||
|
//
|
||||||
|
// memset(document, 0, sizeof(yaml_document_t))
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * Get a document node.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(yaml_node_t *)
|
||||||
|
//yaml_document_get_node(document *yaml_document_t, index int)
|
||||||
|
//{
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
|
||||||
|
// return document.nodes.start + index - 1
|
||||||
|
// }
|
||||||
|
// return NULL
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * Get the root object.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(yaml_node_t *)
|
||||||
|
//yaml_document_get_root_node(document *yaml_document_t)
|
||||||
|
//{
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// if (document.nodes.top != document.nodes.start) {
|
||||||
|
// return document.nodes.start
|
||||||
|
// }
|
||||||
|
// return NULL
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Add a scalar node to a document.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_add_scalar(document *yaml_document_t,
|
||||||
|
// tag *yaml_char_t, value *yaml_char_t, length int,
|
||||||
|
// style yaml_scalar_style_t)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
// tag_copy *yaml_char_t = NULL
|
||||||
|
// value_copy *yaml_char_t = NULL
|
||||||
|
// node yaml_node_t
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
// assert(value) // Non-NULL value is expected.
|
||||||
|
//
|
||||||
|
// if (!tag) {
|
||||||
|
// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
|
||||||
|
// tag_copy = yaml_strdup(tag)
|
||||||
|
// if (!tag_copy) goto error
|
||||||
|
//
|
||||||
|
// if (length < 0) {
|
||||||
|
// length = strlen((char *)value)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(value, length)) goto error
|
||||||
|
// value_copy = yaml_malloc(length+1)
|
||||||
|
// if (!value_copy) goto error
|
||||||
|
// memcpy(value_copy, value, length)
|
||||||
|
// value_copy[length] = '\0'
|
||||||
|
//
|
||||||
|
// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
|
||||||
|
// if (!PUSH(&context, document.nodes, node)) goto error
|
||||||
|
//
|
||||||
|
// return document.nodes.top - document.nodes.start
|
||||||
|
//
|
||||||
|
//error:
|
||||||
|
// yaml_free(tag_copy)
|
||||||
|
// yaml_free(value_copy)
|
||||||
|
//
|
||||||
|
// return 0
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Add a sequence node to a document.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_add_sequence(document *yaml_document_t,
|
||||||
|
// tag *yaml_char_t, style yaml_sequence_style_t)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
// tag_copy *yaml_char_t = NULL
|
||||||
|
// struct {
|
||||||
|
// start *yaml_node_item_t
|
||||||
|
// end *yaml_node_item_t
|
||||||
|
// top *yaml_node_item_t
|
||||||
|
// } items = { NULL, NULL, NULL }
|
||||||
|
// node yaml_node_t
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// if (!tag) {
|
||||||
|
// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
|
||||||
|
// tag_copy = yaml_strdup(tag)
|
||||||
|
// if (!tag_copy) goto error
|
||||||
|
//
|
||||||
|
// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
|
||||||
|
//
|
||||||
|
// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
|
||||||
|
// style, mark, mark)
|
||||||
|
// if (!PUSH(&context, document.nodes, node)) goto error
|
||||||
|
//
|
||||||
|
// return document.nodes.top - document.nodes.start
|
||||||
|
//
|
||||||
|
//error:
|
||||||
|
// STACK_DEL(&context, items)
|
||||||
|
// yaml_free(tag_copy)
|
||||||
|
//
|
||||||
|
// return 0
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Add a mapping node to a document.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_add_mapping(document *yaml_document_t,
|
||||||
|
// tag *yaml_char_t, style yaml_mapping_style_t)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
// tag_copy *yaml_char_t = NULL
|
||||||
|
// struct {
|
||||||
|
// start *yaml_node_pair_t
|
||||||
|
// end *yaml_node_pair_t
|
||||||
|
// top *yaml_node_pair_t
|
||||||
|
// } pairs = { NULL, NULL, NULL }
|
||||||
|
// node yaml_node_t
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// if (!tag) {
|
||||||
|
// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
|
||||||
|
// tag_copy = yaml_strdup(tag)
|
||||||
|
// if (!tag_copy) goto error
|
||||||
|
//
|
||||||
|
// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
|
||||||
|
//
|
||||||
|
// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
|
||||||
|
// style, mark, mark)
|
||||||
|
// if (!PUSH(&context, document.nodes, node)) goto error
|
||||||
|
//
|
||||||
|
// return document.nodes.top - document.nodes.start
|
||||||
|
//
|
||||||
|
//error:
|
||||||
|
// STACK_DEL(&context, pairs)
|
||||||
|
// yaml_free(tag_copy)
|
||||||
|
//
|
||||||
|
// return 0
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Append an item to a sequence node.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_append_sequence_item(document *yaml_document_t,
|
||||||
|
// sequence int, item int)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document is required.
|
||||||
|
// assert(sequence > 0
|
||||||
|
// && document.nodes.start + sequence <= document.nodes.top)
|
||||||
|
// // Valid sequence id is required.
|
||||||
|
// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
|
||||||
|
// // A sequence node is required.
|
||||||
|
// assert(item > 0 && document.nodes.start + item <= document.nodes.top)
|
||||||
|
// // Valid item id is required.
|
||||||
|
//
|
||||||
|
// if (!PUSH(&context,
|
||||||
|
// document.nodes.start[sequence-1].data.sequence.items, item))
|
||||||
|
// return 0
|
||||||
|
//
|
||||||
|
// return 1
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Append a pair of a key and a value to a mapping node.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_append_mapping_pair(document *yaml_document_t,
|
||||||
|
// mapping int, key int, value int)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
//
|
||||||
|
// pair yaml_node_pair_t
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document is required.
|
||||||
|
// assert(mapping > 0
|
||||||
|
// && document.nodes.start + mapping <= document.nodes.top)
|
||||||
|
// // Valid mapping id is required.
|
||||||
|
// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
|
||||||
|
// // A mapping node is required.
|
||||||
|
// assert(key > 0 && document.nodes.start + key <= document.nodes.top)
|
||||||
|
// // Valid key id is required.
|
||||||
|
// assert(value > 0 && document.nodes.start + value <= document.nodes.top)
|
||||||
|
// // Valid value id is required.
|
||||||
|
//
|
||||||
|
// pair.key = key
|
||||||
|
// pair.value = value
|
||||||
|
//
|
||||||
|
// if (!PUSH(&context,
|
||||||
|
// document.nodes.start[mapping-1].data.mapping.pairs, pair))
|
||||||
|
// return 0
|
||||||
|
//
|
||||||
|
// return 1
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
||||||
1018
vendor/go.yaml.in/yaml/v3/decode.go
generated
vendored
Normal file
1018
vendor/go.yaml.in/yaml/v3/decode.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
2054
vendor/go.yaml.in/yaml/v3/emitterc.go
generated
vendored
Normal file
2054
vendor/go.yaml.in/yaml/v3/emitterc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
577
vendor/go.yaml.in/yaml/v3/encode.go
generated
vendored
Normal file
577
vendor/go.yaml.in/yaml/v3/encode.go
generated
vendored
Normal file
|
|
@ -0,0 +1,577 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
type encoder struct {
|
||||||
|
emitter yaml_emitter_t
|
||||||
|
event yaml_event_t
|
||||||
|
out []byte
|
||||||
|
flow bool
|
||||||
|
indent int
|
||||||
|
doneInit bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEncoder() *encoder {
|
||||||
|
e := &encoder{}
|
||||||
|
yaml_emitter_initialize(&e.emitter)
|
||||||
|
yaml_emitter_set_output_string(&e.emitter, &e.out)
|
||||||
|
yaml_emitter_set_unicode(&e.emitter, true)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEncoderWithWriter(w io.Writer) *encoder {
|
||||||
|
e := &encoder{}
|
||||||
|
yaml_emitter_initialize(&e.emitter)
|
||||||
|
yaml_emitter_set_output_writer(&e.emitter, w)
|
||||||
|
yaml_emitter_set_unicode(&e.emitter, true)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) init() {
|
||||||
|
if e.doneInit {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if e.indent == 0 {
|
||||||
|
e.indent = 4
|
||||||
|
}
|
||||||
|
e.emitter.best_indent = e.indent
|
||||||
|
yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
|
||||||
|
e.emit()
|
||||||
|
e.doneInit = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) finish() {
|
||||||
|
e.emitter.open_ended = false
|
||||||
|
yaml_stream_end_event_initialize(&e.event)
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) destroy() {
|
||||||
|
yaml_emitter_delete(&e.emitter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) emit() {
|
||||||
|
// This will internally delete the e.event value.
|
||||||
|
e.must(yaml_emitter_emit(&e.emitter, &e.event))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) must(ok bool) {
|
||||||
|
if !ok {
|
||||||
|
msg := e.emitter.problem
|
||||||
|
if msg == "" {
|
||||||
|
msg = "unknown problem generating YAML content"
|
||||||
|
}
|
||||||
|
failf("%s", msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) marshalDoc(tag string, in reflect.Value) {
|
||||||
|
e.init()
|
||||||
|
var node *Node
|
||||||
|
if in.IsValid() {
|
||||||
|
node, _ = in.Interface().(*Node)
|
||||||
|
}
|
||||||
|
if node != nil && node.Kind == DocumentNode {
|
||||||
|
e.nodev(in)
|
||||||
|
} else {
|
||||||
|
yaml_document_start_event_initialize(&e.event, nil, nil, true)
|
||||||
|
e.emit()
|
||||||
|
e.marshal(tag, in)
|
||||||
|
yaml_document_end_event_initialize(&e.event, true)
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) marshal(tag string, in reflect.Value) {
|
||||||
|
tag = shortTag(tag)
|
||||||
|
if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
|
||||||
|
e.nilv()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
iface := in.Interface()
|
||||||
|
switch value := iface.(type) {
|
||||||
|
case *Node:
|
||||||
|
e.nodev(in)
|
||||||
|
return
|
||||||
|
case Node:
|
||||||
|
if !in.CanAddr() {
|
||||||
|
var n = reflect.New(in.Type()).Elem()
|
||||||
|
n.Set(in)
|
||||||
|
in = n
|
||||||
|
}
|
||||||
|
e.nodev(in.Addr())
|
||||||
|
return
|
||||||
|
case time.Time:
|
||||||
|
e.timev(tag, in)
|
||||||
|
return
|
||||||
|
case *time.Time:
|
||||||
|
e.timev(tag, in.Elem())
|
||||||
|
return
|
||||||
|
case time.Duration:
|
||||||
|
e.stringv(tag, reflect.ValueOf(value.String()))
|
||||||
|
return
|
||||||
|
case Marshaler:
|
||||||
|
v, err := value.MarshalYAML()
|
||||||
|
if err != nil {
|
||||||
|
fail(err)
|
||||||
|
}
|
||||||
|
if v == nil {
|
||||||
|
e.nilv()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.marshal(tag, reflect.ValueOf(v))
|
||||||
|
return
|
||||||
|
case encoding.TextMarshaler:
|
||||||
|
text, err := value.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
fail(err)
|
||||||
|
}
|
||||||
|
in = reflect.ValueOf(string(text))
|
||||||
|
case nil:
|
||||||
|
e.nilv()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch in.Kind() {
|
||||||
|
case reflect.Interface:
|
||||||
|
e.marshal(tag, in.Elem())
|
||||||
|
case reflect.Map:
|
||||||
|
e.mapv(tag, in)
|
||||||
|
case reflect.Ptr:
|
||||||
|
e.marshal(tag, in.Elem())
|
||||||
|
case reflect.Struct:
|
||||||
|
e.structv(tag, in)
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
e.slicev(tag, in)
|
||||||
|
case reflect.String:
|
||||||
|
e.stringv(tag, in)
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
e.intv(tag, in)
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
e.uintv(tag, in)
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
e.floatv(tag, in)
|
||||||
|
case reflect.Bool:
|
||||||
|
e.boolv(tag, in)
|
||||||
|
default:
|
||||||
|
panic("cannot marshal type: " + in.Type().String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) mapv(tag string, in reflect.Value) {
|
||||||
|
e.mappingv(tag, func() {
|
||||||
|
keys := keyList(in.MapKeys())
|
||||||
|
sort.Sort(keys)
|
||||||
|
for _, k := range keys {
|
||||||
|
e.marshal("", k)
|
||||||
|
e.marshal("", in.MapIndex(k))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) {
|
||||||
|
for _, num := range index {
|
||||||
|
for {
|
||||||
|
if v.Kind() == reflect.Ptr {
|
||||||
|
if v.IsNil() {
|
||||||
|
return reflect.Value{}
|
||||||
|
}
|
||||||
|
v = v.Elem()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v = v.Field(num)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) structv(tag string, in reflect.Value) {
|
||||||
|
sinfo, err := getStructInfo(in.Type())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
e.mappingv(tag, func() {
|
||||||
|
for _, info := range sinfo.FieldsList {
|
||||||
|
var value reflect.Value
|
||||||
|
if info.Inline == nil {
|
||||||
|
value = in.Field(info.Num)
|
||||||
|
} else {
|
||||||
|
value = e.fieldByIndex(in, info.Inline)
|
||||||
|
if !value.IsValid() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if info.OmitEmpty && isZero(value) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
e.marshal("", reflect.ValueOf(info.Key))
|
||||||
|
e.flow = info.Flow
|
||||||
|
e.marshal("", value)
|
||||||
|
}
|
||||||
|
if sinfo.InlineMap >= 0 {
|
||||||
|
m := in.Field(sinfo.InlineMap)
|
||||||
|
if m.Len() > 0 {
|
||||||
|
e.flow = false
|
||||||
|
keys := keyList(m.MapKeys())
|
||||||
|
sort.Sort(keys)
|
||||||
|
for _, k := range keys {
|
||||||
|
if _, found := sinfo.FieldsMap[k.String()]; found {
|
||||||
|
panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String()))
|
||||||
|
}
|
||||||
|
e.marshal("", k)
|
||||||
|
e.flow = false
|
||||||
|
e.marshal("", m.MapIndex(k))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) mappingv(tag string, f func()) {
|
||||||
|
implicit := tag == ""
|
||||||
|
style := yaml_BLOCK_MAPPING_STYLE
|
||||||
|
if e.flow {
|
||||||
|
e.flow = false
|
||||||
|
style = yaml_FLOW_MAPPING_STYLE
|
||||||
|
}
|
||||||
|
yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
|
||||||
|
e.emit()
|
||||||
|
f()
|
||||||
|
yaml_mapping_end_event_initialize(&e.event)
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) slicev(tag string, in reflect.Value) {
|
||||||
|
implicit := tag == ""
|
||||||
|
style := yaml_BLOCK_SEQUENCE_STYLE
|
||||||
|
if e.flow {
|
||||||
|
e.flow = false
|
||||||
|
style = yaml_FLOW_SEQUENCE_STYLE
|
||||||
|
}
|
||||||
|
e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
|
||||||
|
e.emit()
|
||||||
|
n := in.Len()
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
e.marshal("", in.Index(i))
|
||||||
|
}
|
||||||
|
e.must(yaml_sequence_end_event_initialize(&e.event))
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
|
||||||
|
//
|
||||||
|
// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
|
||||||
|
// in YAML 1.2 and by this package, but these should be marshalled quoted for
|
||||||
|
// the time being for compatibility with other parsers.
|
||||||
|
func isBase60Float(s string) (result bool) {
|
||||||
|
// Fast path.
|
||||||
|
if s == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
c := s[0]
|
||||||
|
if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Do the full match.
|
||||||
|
return base60float.MatchString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// From http://yaml.org/type/float.html, except the regular expression there
|
||||||
|
// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
|
||||||
|
var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
|
||||||
|
|
||||||
|
// isOldBool returns whether s is bool notation as defined in YAML 1.1.
|
||||||
|
//
|
||||||
|
// We continue to force strings that YAML 1.1 would interpret as booleans to be
|
||||||
|
// rendered as quotes strings so that the marshalled output valid for YAML 1.1
|
||||||
|
// parsing.
|
||||||
|
func isOldBool(s string) (result bool) {
|
||||||
|
switch s {
|
||||||
|
case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON",
|
||||||
|
"n", "N", "no", "No", "NO", "off", "Off", "OFF":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) stringv(tag string, in reflect.Value) {
|
||||||
|
var style yaml_scalar_style_t
|
||||||
|
s := in.String()
|
||||||
|
canUsePlain := true
|
||||||
|
switch {
|
||||||
|
case !utf8.ValidString(s):
|
||||||
|
if tag == binaryTag {
|
||||||
|
failf("explicitly tagged !!binary data must be base64-encoded")
|
||||||
|
}
|
||||||
|
if tag != "" {
|
||||||
|
failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
|
||||||
|
}
|
||||||
|
// It can't be encoded directly as YAML so use a binary tag
|
||||||
|
// and encode it as base64.
|
||||||
|
tag = binaryTag
|
||||||
|
s = encodeBase64(s)
|
||||||
|
case tag == "":
|
||||||
|
// Check to see if it would resolve to a specific
|
||||||
|
// tag when encoded unquoted. If it doesn't,
|
||||||
|
// there's no need to quote it.
|
||||||
|
rtag, _ := resolve("", s)
|
||||||
|
canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s))
|
||||||
|
}
|
||||||
|
// Note: it's possible for user code to emit invalid YAML
|
||||||
|
// if they explicitly specify a tag and a string containing
|
||||||
|
// text that's incompatible with that tag.
|
||||||
|
switch {
|
||||||
|
case strings.Contains(s, "\n"):
|
||||||
|
if e.flow {
|
||||||
|
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||||
|
} else {
|
||||||
|
style = yaml_LITERAL_SCALAR_STYLE
|
||||||
|
}
|
||||||
|
case canUsePlain:
|
||||||
|
style = yaml_PLAIN_SCALAR_STYLE
|
||||||
|
default:
|
||||||
|
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||||
|
}
|
||||||
|
e.emitScalar(s, "", tag, style, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) boolv(tag string, in reflect.Value) {
|
||||||
|
var s string
|
||||||
|
if in.Bool() {
|
||||||
|
s = "true"
|
||||||
|
} else {
|
||||||
|
s = "false"
|
||||||
|
}
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) intv(tag string, in reflect.Value) {
|
||||||
|
s := strconv.FormatInt(in.Int(), 10)
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) uintv(tag string, in reflect.Value) {
|
||||||
|
s := strconv.FormatUint(in.Uint(), 10)
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) timev(tag string, in reflect.Value) {
|
||||||
|
t := in.Interface().(time.Time)
|
||||||
|
s := t.Format(time.RFC3339Nano)
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) floatv(tag string, in reflect.Value) {
|
||||||
|
// Issue #352: When formatting, use the precision of the underlying value
|
||||||
|
precision := 64
|
||||||
|
if in.Kind() == reflect.Float32 {
|
||||||
|
precision = 32
|
||||||
|
}
|
||||||
|
|
||||||
|
s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
|
||||||
|
switch s {
|
||||||
|
case "+Inf":
|
||||||
|
s = ".inf"
|
||||||
|
case "-Inf":
|
||||||
|
s = "-.inf"
|
||||||
|
case "NaN":
|
||||||
|
s = ".nan"
|
||||||
|
}
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) nilv() {
|
||||||
|
e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) {
|
||||||
|
// TODO Kill this function. Replace all initialize calls by their underlining Go literals.
|
||||||
|
implicit := tag == ""
|
||||||
|
if !implicit {
|
||||||
|
tag = longTag(tag)
|
||||||
|
}
|
||||||
|
e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
|
||||||
|
e.event.head_comment = head
|
||||||
|
e.event.line_comment = line
|
||||||
|
e.event.foot_comment = foot
|
||||||
|
e.event.tail_comment = tail
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) nodev(in reflect.Value) {
|
||||||
|
e.node(in.Interface().(*Node), "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) node(node *Node, tail string) {
|
||||||
|
// Zero nodes behave as nil.
|
||||||
|
if node.Kind == 0 && node.IsZero() {
|
||||||
|
e.nilv()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the tag was not explicitly requested, and dropping it won't change the
|
||||||
|
// implicit tag of the value, don't include it in the presentation.
|
||||||
|
var tag = node.Tag
|
||||||
|
var stag = shortTag(tag)
|
||||||
|
var forceQuoting bool
|
||||||
|
if tag != "" && node.Style&TaggedStyle == 0 {
|
||||||
|
if node.Kind == ScalarNode {
|
||||||
|
if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 {
|
||||||
|
tag = ""
|
||||||
|
} else {
|
||||||
|
rtag, _ := resolve("", node.Value)
|
||||||
|
if rtag == stag {
|
||||||
|
tag = ""
|
||||||
|
} else if stag == strTag {
|
||||||
|
tag = ""
|
||||||
|
forceQuoting = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var rtag string
|
||||||
|
switch node.Kind {
|
||||||
|
case MappingNode:
|
||||||
|
rtag = mapTag
|
||||||
|
case SequenceNode:
|
||||||
|
rtag = seqTag
|
||||||
|
}
|
||||||
|
if rtag == stag {
|
||||||
|
tag = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch node.Kind {
|
||||||
|
case DocumentNode:
|
||||||
|
yaml_document_start_event_initialize(&e.event, nil, nil, true)
|
||||||
|
e.event.head_comment = []byte(node.HeadComment)
|
||||||
|
e.emit()
|
||||||
|
for _, node := range node.Content {
|
||||||
|
e.node(node, "")
|
||||||
|
}
|
||||||
|
yaml_document_end_event_initialize(&e.event, true)
|
||||||
|
e.event.foot_comment = []byte(node.FootComment)
|
||||||
|
e.emit()
|
||||||
|
|
||||||
|
case SequenceNode:
|
||||||
|
style := yaml_BLOCK_SEQUENCE_STYLE
|
||||||
|
if node.Style&FlowStyle != 0 {
|
||||||
|
style = yaml_FLOW_SEQUENCE_STYLE
|
||||||
|
}
|
||||||
|
e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style))
|
||||||
|
e.event.head_comment = []byte(node.HeadComment)
|
||||||
|
e.emit()
|
||||||
|
for _, node := range node.Content {
|
||||||
|
e.node(node, "")
|
||||||
|
}
|
||||||
|
e.must(yaml_sequence_end_event_initialize(&e.event))
|
||||||
|
e.event.line_comment = []byte(node.LineComment)
|
||||||
|
e.event.foot_comment = []byte(node.FootComment)
|
||||||
|
e.emit()
|
||||||
|
|
||||||
|
case MappingNode:
|
||||||
|
style := yaml_BLOCK_MAPPING_STYLE
|
||||||
|
if node.Style&FlowStyle != 0 {
|
||||||
|
style = yaml_FLOW_MAPPING_STYLE
|
||||||
|
}
|
||||||
|
yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)
|
||||||
|
e.event.tail_comment = []byte(tail)
|
||||||
|
e.event.head_comment = []byte(node.HeadComment)
|
||||||
|
e.emit()
|
||||||
|
|
||||||
|
// The tail logic below moves the foot comment of prior keys to the following key,
|
||||||
|
// since the value for each key may be a nested structure and the foot needs to be
|
||||||
|
// processed only the entirety of the value is streamed. The last tail is processed
|
||||||
|
// with the mapping end event.
|
||||||
|
var tail string
|
||||||
|
for i := 0; i+1 < len(node.Content); i += 2 {
|
||||||
|
k := node.Content[i]
|
||||||
|
foot := k.FootComment
|
||||||
|
if foot != "" {
|
||||||
|
kopy := *k
|
||||||
|
kopy.FootComment = ""
|
||||||
|
k = &kopy
|
||||||
|
}
|
||||||
|
e.node(k, tail)
|
||||||
|
tail = foot
|
||||||
|
|
||||||
|
v := node.Content[i+1]
|
||||||
|
e.node(v, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
yaml_mapping_end_event_initialize(&e.event)
|
||||||
|
e.event.tail_comment = []byte(tail)
|
||||||
|
e.event.line_comment = []byte(node.LineComment)
|
||||||
|
e.event.foot_comment = []byte(node.FootComment)
|
||||||
|
e.emit()
|
||||||
|
|
||||||
|
case AliasNode:
|
||||||
|
yaml_alias_event_initialize(&e.event, []byte(node.Value))
|
||||||
|
e.event.head_comment = []byte(node.HeadComment)
|
||||||
|
e.event.line_comment = []byte(node.LineComment)
|
||||||
|
e.event.foot_comment = []byte(node.FootComment)
|
||||||
|
e.emit()
|
||||||
|
|
||||||
|
case ScalarNode:
|
||||||
|
value := node.Value
|
||||||
|
if !utf8.ValidString(value) {
|
||||||
|
if stag == binaryTag {
|
||||||
|
failf("explicitly tagged !!binary data must be base64-encoded")
|
||||||
|
}
|
||||||
|
if stag != "" {
|
||||||
|
failf("cannot marshal invalid UTF-8 data as %s", stag)
|
||||||
|
}
|
||||||
|
// It can't be encoded directly as YAML so use a binary tag
|
||||||
|
// and encode it as base64.
|
||||||
|
tag = binaryTag
|
||||||
|
value = encodeBase64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
style := yaml_PLAIN_SCALAR_STYLE
|
||||||
|
switch {
|
||||||
|
case node.Style&DoubleQuotedStyle != 0:
|
||||||
|
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||||
|
case node.Style&SingleQuotedStyle != 0:
|
||||||
|
style = yaml_SINGLE_QUOTED_SCALAR_STYLE
|
||||||
|
case node.Style&LiteralStyle != 0:
|
||||||
|
style = yaml_LITERAL_SCALAR_STYLE
|
||||||
|
case node.Style&FoldedStyle != 0:
|
||||||
|
style = yaml_FOLDED_SCALAR_STYLE
|
||||||
|
case strings.Contains(value, "\n"):
|
||||||
|
style = yaml_LITERAL_SCALAR_STYLE
|
||||||
|
case forceQuoting:
|
||||||
|
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||||
|
}
|
||||||
|
|
||||||
|
e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail))
|
||||||
|
default:
|
||||||
|
failf("cannot encode node with unknown kind %d", node.Kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
1274
vendor/go.yaml.in/yaml/v3/parserc.go
generated
vendored
Normal file
1274
vendor/go.yaml.in/yaml/v3/parserc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
434
vendor/go.yaml.in/yaml/v3/readerc.go
generated
vendored
Normal file
434
vendor/go.yaml.in/yaml/v3/readerc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,434 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set the reader error and return 0.
|
||||||
|
func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
|
||||||
|
parser.error = yaml_READER_ERROR
|
||||||
|
parser.problem = problem
|
||||||
|
parser.problem_offset = offset
|
||||||
|
parser.problem_value = value
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Byte order marks.
|
||||||
|
const (
|
||||||
|
bom_UTF8 = "\xef\xbb\xbf"
|
||||||
|
bom_UTF16LE = "\xff\xfe"
|
||||||
|
bom_UTF16BE = "\xfe\xff"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Determine the input stream encoding by checking the BOM symbol. If no BOM is
|
||||||
|
// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
|
||||||
|
func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
|
||||||
|
// Ensure that we had enough bytes in the raw buffer.
|
||||||
|
for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
|
||||||
|
if !yaml_parser_update_raw_buffer(parser) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the encoding.
|
||||||
|
buf := parser.raw_buffer
|
||||||
|
pos := parser.raw_buffer_pos
|
||||||
|
avail := len(buf) - pos
|
||||||
|
if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
|
||||||
|
parser.encoding = yaml_UTF16LE_ENCODING
|
||||||
|
parser.raw_buffer_pos += 2
|
||||||
|
parser.offset += 2
|
||||||
|
} else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
|
||||||
|
parser.encoding = yaml_UTF16BE_ENCODING
|
||||||
|
parser.raw_buffer_pos += 2
|
||||||
|
parser.offset += 2
|
||||||
|
} else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
|
||||||
|
parser.encoding = yaml_UTF8_ENCODING
|
||||||
|
parser.raw_buffer_pos += 3
|
||||||
|
parser.offset += 3
|
||||||
|
} else {
|
||||||
|
parser.encoding = yaml_UTF8_ENCODING
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the raw buffer.
|
||||||
|
func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
|
||||||
|
size_read := 0
|
||||||
|
|
||||||
|
// Return if the raw buffer is full.
|
||||||
|
if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return on EOF.
|
||||||
|
if parser.eof {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the remaining bytes in the raw buffer to the beginning.
|
||||||
|
if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
|
||||||
|
copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
|
||||||
|
}
|
||||||
|
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
|
||||||
|
parser.raw_buffer_pos = 0
|
||||||
|
|
||||||
|
// Call the read handler to fill the buffer.
|
||||||
|
size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
|
||||||
|
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
|
||||||
|
if err == io.EOF {
|
||||||
|
parser.eof = true
|
||||||
|
} else if err != nil {
|
||||||
|
return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the buffer contains at least `length` characters.
|
||||||
|
// Return true on success, false on failure.
|
||||||
|
//
|
||||||
|
// The length is supposed to be significantly less that the buffer size.
|
||||||
|
func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
|
||||||
|
if parser.read_handler == nil {
|
||||||
|
panic("read handler must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
// [Go] This function was changed to guarantee the requested length size at EOF.
|
||||||
|
// The fact we need to do this is pretty awful, but the description above implies
|
||||||
|
// for that to be the case, and there are tests
|
||||||
|
|
||||||
|
// If the EOF flag is set and the raw buffer is empty, do nothing.
|
||||||
|
if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
|
||||||
|
// [Go] ACTUALLY! Read the documentation of this function above.
|
||||||
|
// This is just broken. To return true, we need to have the
|
||||||
|
// given length in the buffer. Not doing that means every single
|
||||||
|
// check that calls this function to make sure the buffer has a
|
||||||
|
// given length is Go) panicking; or C) accessing invalid memory.
|
||||||
|
//return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return if the buffer contains enough characters.
|
||||||
|
if parser.unread >= length {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the input encoding if it is not known yet.
|
||||||
|
if parser.encoding == yaml_ANY_ENCODING {
|
||||||
|
if !yaml_parser_determine_encoding(parser) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the unread characters to the beginning of the buffer.
|
||||||
|
buffer_len := len(parser.buffer)
|
||||||
|
if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
|
||||||
|
copy(parser.buffer, parser.buffer[parser.buffer_pos:])
|
||||||
|
buffer_len -= parser.buffer_pos
|
||||||
|
parser.buffer_pos = 0
|
||||||
|
} else if parser.buffer_pos == buffer_len {
|
||||||
|
buffer_len = 0
|
||||||
|
parser.buffer_pos = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the whole buffer for writing, and cut it before returning.
|
||||||
|
parser.buffer = parser.buffer[:cap(parser.buffer)]
|
||||||
|
|
||||||
|
// Fill the buffer until it has enough characters.
|
||||||
|
first := true
|
||||||
|
for parser.unread < length {
|
||||||
|
|
||||||
|
// Fill the raw buffer if necessary.
|
||||||
|
if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
|
||||||
|
if !yaml_parser_update_raw_buffer(parser) {
|
||||||
|
parser.buffer = parser.buffer[:buffer_len]
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first = false
|
||||||
|
|
||||||
|
// Decode the raw buffer.
|
||||||
|
inner:
|
||||||
|
for parser.raw_buffer_pos != len(parser.raw_buffer) {
|
||||||
|
var value rune
|
||||||
|
var width int
|
||||||
|
|
||||||
|
raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
|
||||||
|
|
||||||
|
// Decode the next character.
|
||||||
|
switch parser.encoding {
|
||||||
|
case yaml_UTF8_ENCODING:
|
||||||
|
// Decode a UTF-8 character. Check RFC 3629
|
||||||
|
// (http://www.ietf.org/rfc/rfc3629.txt) for more details.
|
||||||
|
//
|
||||||
|
// The following table (taken from the RFC) is used for
|
||||||
|
// decoding.
|
||||||
|
//
|
||||||
|
// Char. number range | UTF-8 octet sequence
|
||||||
|
// (hexadecimal) | (binary)
|
||||||
|
// --------------------+------------------------------------
|
||||||
|
// 0000 0000-0000 007F | 0xxxxxxx
|
||||||
|
// 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
||||||
|
// 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
|
// 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
|
//
|
||||||
|
// Additionally, the characters in the range 0xD800-0xDFFF
|
||||||
|
// are prohibited as they are reserved for use with UTF-16
|
||||||
|
// surrogate pairs.
|
||||||
|
|
||||||
|
// Determine the length of the UTF-8 sequence.
|
||||||
|
octet := parser.raw_buffer[parser.raw_buffer_pos]
|
||||||
|
switch {
|
||||||
|
case octet&0x80 == 0x00:
|
||||||
|
width = 1
|
||||||
|
case octet&0xE0 == 0xC0:
|
||||||
|
width = 2
|
||||||
|
case octet&0xF0 == 0xE0:
|
||||||
|
width = 3
|
||||||
|
case octet&0xF8 == 0xF0:
|
||||||
|
width = 4
|
||||||
|
default:
|
||||||
|
// The leading octet is invalid.
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"invalid leading UTF-8 octet",
|
||||||
|
parser.offset, int(octet))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the raw buffer contains an incomplete character.
|
||||||
|
if width > raw_unread {
|
||||||
|
if parser.eof {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"incomplete UTF-8 octet sequence",
|
||||||
|
parser.offset, -1)
|
||||||
|
}
|
||||||
|
break inner
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the leading octet.
|
||||||
|
switch {
|
||||||
|
case octet&0x80 == 0x00:
|
||||||
|
value = rune(octet & 0x7F)
|
||||||
|
case octet&0xE0 == 0xC0:
|
||||||
|
value = rune(octet & 0x1F)
|
||||||
|
case octet&0xF0 == 0xE0:
|
||||||
|
value = rune(octet & 0x0F)
|
||||||
|
case octet&0xF8 == 0xF0:
|
||||||
|
value = rune(octet & 0x07)
|
||||||
|
default:
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check and decode the trailing octets.
|
||||||
|
for k := 1; k < width; k++ {
|
||||||
|
octet = parser.raw_buffer[parser.raw_buffer_pos+k]
|
||||||
|
|
||||||
|
// Check if the octet is valid.
|
||||||
|
if (octet & 0xC0) != 0x80 {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"invalid trailing UTF-8 octet",
|
||||||
|
parser.offset+k, int(octet))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the octet.
|
||||||
|
value = (value << 6) + rune(octet&0x3F)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the length of the sequence against the value.
|
||||||
|
switch {
|
||||||
|
case width == 1:
|
||||||
|
case width == 2 && value >= 0x80:
|
||||||
|
case width == 3 && value >= 0x800:
|
||||||
|
case width == 4 && value >= 0x10000:
|
||||||
|
default:
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"invalid length of a UTF-8 sequence",
|
||||||
|
parser.offset, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the range of the value.
|
||||||
|
if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"invalid Unicode character",
|
||||||
|
parser.offset, int(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
|
||||||
|
var low, high int
|
||||||
|
if parser.encoding == yaml_UTF16LE_ENCODING {
|
||||||
|
low, high = 0, 1
|
||||||
|
} else {
|
||||||
|
low, high = 1, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// The UTF-16 encoding is not as simple as one might
|
||||||
|
// naively think. Check RFC 2781
|
||||||
|
// (http://www.ietf.org/rfc/rfc2781.txt).
|
||||||
|
//
|
||||||
|
// Normally, two subsequent bytes describe a Unicode
|
||||||
|
// character. However a special technique (called a
|
||||||
|
// surrogate pair) is used for specifying character
|
||||||
|
// values larger than 0xFFFF.
|
||||||
|
//
|
||||||
|
// A surrogate pair consists of two pseudo-characters:
|
||||||
|
// high surrogate area (0xD800-0xDBFF)
|
||||||
|
// low surrogate area (0xDC00-0xDFFF)
|
||||||
|
//
|
||||||
|
// The following formulas are used for decoding
|
||||||
|
// and encoding characters using surrogate pairs:
|
||||||
|
//
|
||||||
|
// U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
|
||||||
|
// U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
|
||||||
|
// W1 = 110110yyyyyyyyyy
|
||||||
|
// W2 = 110111xxxxxxxxxx
|
||||||
|
//
|
||||||
|
// where U is the character value, W1 is the high surrogate
|
||||||
|
// area, W2 is the low surrogate area.
|
||||||
|
|
||||||
|
// Check for incomplete UTF-16 character.
|
||||||
|
if raw_unread < 2 {
|
||||||
|
if parser.eof {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"incomplete UTF-16 character",
|
||||||
|
parser.offset, -1)
|
||||||
|
}
|
||||||
|
break inner
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the character.
|
||||||
|
value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
|
||||||
|
(rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
|
||||||
|
|
||||||
|
// Check for unexpected low surrogate area.
|
||||||
|
if value&0xFC00 == 0xDC00 {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"unexpected low surrogate area",
|
||||||
|
parser.offset, int(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a high surrogate area.
|
||||||
|
if value&0xFC00 == 0xD800 {
|
||||||
|
width = 4
|
||||||
|
|
||||||
|
// Check for incomplete surrogate pair.
|
||||||
|
if raw_unread < 4 {
|
||||||
|
if parser.eof {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"incomplete UTF-16 surrogate pair",
|
||||||
|
parser.offset, -1)
|
||||||
|
}
|
||||||
|
break inner
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next character.
|
||||||
|
value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
|
||||||
|
(rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
|
||||||
|
|
||||||
|
// Check for a low surrogate area.
|
||||||
|
if value2&0xFC00 != 0xDC00 {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"expected low surrogate area",
|
||||||
|
parser.offset+2, int(value2))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the value of the surrogate pair.
|
||||||
|
value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
|
||||||
|
} else {
|
||||||
|
width = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("impossible")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is in the allowed range:
|
||||||
|
// #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
|
||||||
|
// | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
|
||||||
|
// | [#x10000-#x10FFFF] (32 bit)
|
||||||
|
switch {
|
||||||
|
case value == 0x09:
|
||||||
|
case value == 0x0A:
|
||||||
|
case value == 0x0D:
|
||||||
|
case value >= 0x20 && value <= 0x7E:
|
||||||
|
case value == 0x85:
|
||||||
|
case value >= 0xA0 && value <= 0xD7FF:
|
||||||
|
case value >= 0xE000 && value <= 0xFFFD:
|
||||||
|
case value >= 0x10000 && value <= 0x10FFFF:
|
||||||
|
default:
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"control characters are not allowed",
|
||||||
|
parser.offset, int(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the raw pointers.
|
||||||
|
parser.raw_buffer_pos += width
|
||||||
|
parser.offset += width
|
||||||
|
|
||||||
|
// Finally put the character into the buffer.
|
||||||
|
if value <= 0x7F {
|
||||||
|
// 0000 0000-0000 007F . 0xxxxxxx
|
||||||
|
parser.buffer[buffer_len+0] = byte(value)
|
||||||
|
buffer_len += 1
|
||||||
|
} else if value <= 0x7FF {
|
||||||
|
// 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
|
||||||
|
parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
|
||||||
|
parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
|
||||||
|
buffer_len += 2
|
||||||
|
} else if value <= 0xFFFF {
|
||||||
|
// 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
|
parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
|
||||||
|
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
|
||||||
|
parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
|
||||||
|
buffer_len += 3
|
||||||
|
} else {
|
||||||
|
// 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
|
parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
|
||||||
|
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
|
||||||
|
parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
|
||||||
|
parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
|
||||||
|
buffer_len += 4
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.unread++
|
||||||
|
}
|
||||||
|
|
||||||
|
// On EOF, put NUL into the buffer and return.
|
||||||
|
if parser.eof {
|
||||||
|
parser.buffer[buffer_len] = 0
|
||||||
|
buffer_len++
|
||||||
|
parser.unread++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// [Go] Read the documentation of this function above. To return true,
|
||||||
|
// we need to have the given length in the buffer. Not doing that means
|
||||||
|
// every single check that calls this function to make sure the buffer
|
||||||
|
// has a given length is Go) panicking; or C) accessing invalid memory.
|
||||||
|
// This happens here due to the EOF above breaking early.
|
||||||
|
for buffer_len < length {
|
||||||
|
parser.buffer[buffer_len] = 0
|
||||||
|
buffer_len++
|
||||||
|
}
|
||||||
|
parser.buffer = parser.buffer[:buffer_len]
|
||||||
|
return true
|
||||||
|
}
|
||||||
326
vendor/go.yaml.in/yaml/v3/resolve.go
generated
vendored
Normal file
326
vendor/go.yaml.in/yaml/v3/resolve.go
generated
vendored
Normal file
|
|
@ -0,0 +1,326 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"math"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type resolveMapItem struct {
|
||||||
|
value interface{}
|
||||||
|
tag string
|
||||||
|
}
|
||||||
|
|
||||||
|
var resolveTable = make([]byte, 256)
|
||||||
|
var resolveMap = make(map[string]resolveMapItem)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
t := resolveTable
|
||||||
|
t[int('+')] = 'S' // Sign
|
||||||
|
t[int('-')] = 'S'
|
||||||
|
for _, c := range "0123456789" {
|
||||||
|
t[int(c)] = 'D' // Digit
|
||||||
|
}
|
||||||
|
for _, c := range "yYnNtTfFoO~" {
|
||||||
|
t[int(c)] = 'M' // In map
|
||||||
|
}
|
||||||
|
t[int('.')] = '.' // Float (potentially in map)
|
||||||
|
|
||||||
|
var resolveMapList = []struct {
|
||||||
|
v interface{}
|
||||||
|
tag string
|
||||||
|
l []string
|
||||||
|
}{
|
||||||
|
{true, boolTag, []string{"true", "True", "TRUE"}},
|
||||||
|
{false, boolTag, []string{"false", "False", "FALSE"}},
|
||||||
|
{nil, nullTag, []string{"", "~", "null", "Null", "NULL"}},
|
||||||
|
{math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}},
|
||||||
|
{math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}},
|
||||||
|
{math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}},
|
||||||
|
{math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}},
|
||||||
|
{"<<", mergeTag, []string{"<<"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
m := resolveMap
|
||||||
|
for _, item := range resolveMapList {
|
||||||
|
for _, s := range item.l {
|
||||||
|
m[s] = resolveMapItem{item.v, item.tag}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
nullTag = "!!null"
|
||||||
|
boolTag = "!!bool"
|
||||||
|
strTag = "!!str"
|
||||||
|
intTag = "!!int"
|
||||||
|
floatTag = "!!float"
|
||||||
|
timestampTag = "!!timestamp"
|
||||||
|
seqTag = "!!seq"
|
||||||
|
mapTag = "!!map"
|
||||||
|
binaryTag = "!!binary"
|
||||||
|
mergeTag = "!!merge"
|
||||||
|
)
|
||||||
|
|
||||||
|
var longTags = make(map[string]string)
|
||||||
|
var shortTags = make(map[string]string)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} {
|
||||||
|
ltag := longTag(stag)
|
||||||
|
longTags[stag] = ltag
|
||||||
|
shortTags[ltag] = stag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const longTagPrefix = "tag:yaml.org,2002:"
|
||||||
|
|
||||||
|
func shortTag(tag string) string {
|
||||||
|
if strings.HasPrefix(tag, longTagPrefix) {
|
||||||
|
if stag, ok := shortTags[tag]; ok {
|
||||||
|
return stag
|
||||||
|
}
|
||||||
|
return "!!" + tag[len(longTagPrefix):]
|
||||||
|
}
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func longTag(tag string) string {
|
||||||
|
if strings.HasPrefix(tag, "!!") {
|
||||||
|
if ltag, ok := longTags[tag]; ok {
|
||||||
|
return ltag
|
||||||
|
}
|
||||||
|
return longTagPrefix + tag[2:]
|
||||||
|
}
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolvableTag(tag string) bool {
|
||||||
|
switch tag {
|
||||||
|
case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`)
|
||||||
|
|
||||||
|
func resolve(tag string, in string) (rtag string, out interface{}) {
|
||||||
|
tag = shortTag(tag)
|
||||||
|
if !resolvableTag(tag) {
|
||||||
|
return tag, in
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
switch tag {
|
||||||
|
case "", rtag, strTag, binaryTag:
|
||||||
|
return
|
||||||
|
case floatTag:
|
||||||
|
if rtag == intTag {
|
||||||
|
switch v := out.(type) {
|
||||||
|
case int64:
|
||||||
|
rtag = floatTag
|
||||||
|
out = float64(v)
|
||||||
|
return
|
||||||
|
case int:
|
||||||
|
rtag = floatTag
|
||||||
|
out = float64(v)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Any data is accepted as a !!str or !!binary.
|
||||||
|
// Otherwise, the prefix is enough of a hint about what it might be.
|
||||||
|
hint := byte('N')
|
||||||
|
if in != "" {
|
||||||
|
hint = resolveTable[in[0]]
|
||||||
|
}
|
||||||
|
if hint != 0 && tag != strTag && tag != binaryTag {
|
||||||
|
// Handle things we can lookup in a map.
|
||||||
|
if item, ok := resolveMap[in]; ok {
|
||||||
|
return item.tag, item.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base 60 floats are a bad idea, were dropped in YAML 1.2, and
|
||||||
|
// are purposefully unsupported here. They're still quoted on
|
||||||
|
// the way out for compatibility with other parser, though.
|
||||||
|
|
||||||
|
switch hint {
|
||||||
|
case 'M':
|
||||||
|
// We've already checked the map above.
|
||||||
|
|
||||||
|
case '.':
|
||||||
|
// Not in the map, so maybe a normal float.
|
||||||
|
floatv, err := strconv.ParseFloat(in, 64)
|
||||||
|
if err == nil {
|
||||||
|
return floatTag, floatv
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'D', 'S':
|
||||||
|
// Int, float, or timestamp.
|
||||||
|
// Only try values as a timestamp if the value is unquoted or there's an explicit
|
||||||
|
// !!timestamp tag.
|
||||||
|
if tag == "" || tag == timestampTag {
|
||||||
|
t, ok := parseTimestamp(in)
|
||||||
|
if ok {
|
||||||
|
return timestampTag, t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plain := strings.Replace(in, "_", "", -1)
|
||||||
|
intv, err := strconv.ParseInt(plain, 0, 64)
|
||||||
|
if err == nil {
|
||||||
|
if intv == int64(int(intv)) {
|
||||||
|
return intTag, int(intv)
|
||||||
|
} else {
|
||||||
|
return intTag, intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uintv, err := strconv.ParseUint(plain, 0, 64)
|
||||||
|
if err == nil {
|
||||||
|
return intTag, uintv
|
||||||
|
}
|
||||||
|
if yamlStyleFloat.MatchString(plain) {
|
||||||
|
floatv, err := strconv.ParseFloat(plain, 64)
|
||||||
|
if err == nil {
|
||||||
|
return floatTag, floatv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(plain, "0b") {
|
||||||
|
intv, err := strconv.ParseInt(plain[2:], 2, 64)
|
||||||
|
if err == nil {
|
||||||
|
if intv == int64(int(intv)) {
|
||||||
|
return intTag, int(intv)
|
||||||
|
} else {
|
||||||
|
return intTag, intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uintv, err := strconv.ParseUint(plain[2:], 2, 64)
|
||||||
|
if err == nil {
|
||||||
|
return intTag, uintv
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(plain, "-0b") {
|
||||||
|
intv, err := strconv.ParseInt("-"+plain[3:], 2, 64)
|
||||||
|
if err == nil {
|
||||||
|
if true || intv == int64(int(intv)) {
|
||||||
|
return intTag, int(intv)
|
||||||
|
} else {
|
||||||
|
return intTag, intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Octals as introduced in version 1.2 of the spec.
|
||||||
|
// Octals from the 1.1 spec, spelled as 0777, are still
|
||||||
|
// decoded by default in v3 as well for compatibility.
|
||||||
|
// May be dropped in v4 depending on how usage evolves.
|
||||||
|
if strings.HasPrefix(plain, "0o") {
|
||||||
|
intv, err := strconv.ParseInt(plain[2:], 8, 64)
|
||||||
|
if err == nil {
|
||||||
|
if intv == int64(int(intv)) {
|
||||||
|
return intTag, int(intv)
|
||||||
|
} else {
|
||||||
|
return intTag, intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uintv, err := strconv.ParseUint(plain[2:], 8, 64)
|
||||||
|
if err == nil {
|
||||||
|
return intTag, uintv
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(plain, "-0o") {
|
||||||
|
intv, err := strconv.ParseInt("-"+plain[3:], 8, 64)
|
||||||
|
if err == nil {
|
||||||
|
if true || intv == int64(int(intv)) {
|
||||||
|
return intTag, int(intv)
|
||||||
|
} else {
|
||||||
|
return intTag, intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strTag, in
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodeBase64 encodes s as base64 that is broken up into multiple lines
|
||||||
|
// as appropriate for the resulting length.
|
||||||
|
func encodeBase64(s string) string {
|
||||||
|
const lineLen = 70
|
||||||
|
encLen := base64.StdEncoding.EncodedLen(len(s))
|
||||||
|
lines := encLen/lineLen + 1
|
||||||
|
buf := make([]byte, encLen*2+lines)
|
||||||
|
in := buf[0:encLen]
|
||||||
|
out := buf[encLen:]
|
||||||
|
base64.StdEncoding.Encode(in, []byte(s))
|
||||||
|
k := 0
|
||||||
|
for i := 0; i < len(in); i += lineLen {
|
||||||
|
j := i + lineLen
|
||||||
|
if j > len(in) {
|
||||||
|
j = len(in)
|
||||||
|
}
|
||||||
|
k += copy(out[k:], in[i:j])
|
||||||
|
if lines > 1 {
|
||||||
|
out[k] = '\n'
|
||||||
|
k++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(out[:k])
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a subset of the formats allowed by the regular expression
|
||||||
|
// defined at http://yaml.org/type/timestamp.html.
|
||||||
|
var allowedTimestampFormats = []string{
|
||||||
|
"2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
|
||||||
|
"2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
|
||||||
|
"2006-1-2 15:4:5.999999999", // space separated with no time zone
|
||||||
|
"2006-1-2", // date only
|
||||||
|
// Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
|
||||||
|
// from the set of examples.
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseTimestamp parses s as a timestamp string and
|
||||||
|
// returns the timestamp and reports whether it succeeded.
|
||||||
|
// Timestamp formats are defined at http://yaml.org/type/timestamp.html
|
||||||
|
func parseTimestamp(s string) (time.Time, bool) {
|
||||||
|
// TODO write code to check all the formats supported by
|
||||||
|
// http://yaml.org/type/timestamp.html instead of using time.Parse.
|
||||||
|
|
||||||
|
// Quick check: all date formats start with YYYY-.
|
||||||
|
i := 0
|
||||||
|
for ; i < len(s); i++ {
|
||||||
|
if c := s[i]; c < '0' || c > '9' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i != 4 || i == len(s) || s[i] != '-' {
|
||||||
|
return time.Time{}, false
|
||||||
|
}
|
||||||
|
for _, format := range allowedTimestampFormats {
|
||||||
|
if t, err := time.Parse(format, s); err == nil {
|
||||||
|
return t, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return time.Time{}, false
|
||||||
|
}
|
||||||
3040
vendor/go.yaml.in/yaml/v3/scannerc.go
generated
vendored
Normal file
3040
vendor/go.yaml.in/yaml/v3/scannerc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
134
vendor/go.yaml.in/yaml/v3/sorter.go
generated
vendored
Normal file
134
vendor/go.yaml.in/yaml/v3/sorter.go
generated
vendored
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
type keyList []reflect.Value
|
||||||
|
|
||||||
|
func (l keyList) Len() int { return len(l) }
|
||||||
|
func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||||
|
func (l keyList) Less(i, j int) bool {
|
||||||
|
a := l[i]
|
||||||
|
b := l[j]
|
||||||
|
ak := a.Kind()
|
||||||
|
bk := b.Kind()
|
||||||
|
for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
|
||||||
|
a = a.Elem()
|
||||||
|
ak = a.Kind()
|
||||||
|
}
|
||||||
|
for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
|
||||||
|
b = b.Elem()
|
||||||
|
bk = b.Kind()
|
||||||
|
}
|
||||||
|
af, aok := keyFloat(a)
|
||||||
|
bf, bok := keyFloat(b)
|
||||||
|
if aok && bok {
|
||||||
|
if af != bf {
|
||||||
|
return af < bf
|
||||||
|
}
|
||||||
|
if ak != bk {
|
||||||
|
return ak < bk
|
||||||
|
}
|
||||||
|
return numLess(a, b)
|
||||||
|
}
|
||||||
|
if ak != reflect.String || bk != reflect.String {
|
||||||
|
return ak < bk
|
||||||
|
}
|
||||||
|
ar, br := []rune(a.String()), []rune(b.String())
|
||||||
|
digits := false
|
||||||
|
for i := 0; i < len(ar) && i < len(br); i++ {
|
||||||
|
if ar[i] == br[i] {
|
||||||
|
digits = unicode.IsDigit(ar[i])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
al := unicode.IsLetter(ar[i])
|
||||||
|
bl := unicode.IsLetter(br[i])
|
||||||
|
if al && bl {
|
||||||
|
return ar[i] < br[i]
|
||||||
|
}
|
||||||
|
if al || bl {
|
||||||
|
if digits {
|
||||||
|
return al
|
||||||
|
} else {
|
||||||
|
return bl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var ai, bi int
|
||||||
|
var an, bn int64
|
||||||
|
if ar[i] == '0' || br[i] == '0' {
|
||||||
|
for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
|
||||||
|
if ar[j] != '0' {
|
||||||
|
an = 1
|
||||||
|
bn = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
|
||||||
|
an = an*10 + int64(ar[ai]-'0')
|
||||||
|
}
|
||||||
|
for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
|
||||||
|
bn = bn*10 + int64(br[bi]-'0')
|
||||||
|
}
|
||||||
|
if an != bn {
|
||||||
|
return an < bn
|
||||||
|
}
|
||||||
|
if ai != bi {
|
||||||
|
return ai < bi
|
||||||
|
}
|
||||||
|
return ar[i] < br[i]
|
||||||
|
}
|
||||||
|
return len(ar) < len(br)
|
||||||
|
}
|
||||||
|
|
||||||
|
// keyFloat returns a float value for v if it is a number/bool
|
||||||
|
// and whether it is a number/bool or not.
|
||||||
|
func keyFloat(v reflect.Value) (f float64, ok bool) {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return float64(v.Int()), true
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return v.Float(), true
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return float64(v.Uint()), true
|
||||||
|
case reflect.Bool:
|
||||||
|
if v.Bool() {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// numLess returns whether a < b.
|
||||||
|
// a and b must necessarily have the same kind.
|
||||||
|
func numLess(a, b reflect.Value) bool {
|
||||||
|
switch a.Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return a.Int() < b.Int()
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return a.Float() < b.Float()
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return a.Uint() < b.Uint()
|
||||||
|
case reflect.Bool:
|
||||||
|
return !a.Bool() && b.Bool()
|
||||||
|
}
|
||||||
|
panic("not a number")
|
||||||
|
}
|
||||||
48
vendor/go.yaml.in/yaml/v3/writerc.go
generated
vendored
Normal file
48
vendor/go.yaml.in/yaml/v3/writerc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
// Set the writer error and return false.
|
||||||
|
func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
|
||||||
|
emitter.error = yaml_WRITER_ERROR
|
||||||
|
emitter.problem = problem
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush the output buffer.
|
||||||
|
func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
|
||||||
|
if emitter.write_handler == nil {
|
||||||
|
panic("write handler not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the buffer is empty.
|
||||||
|
if emitter.buffer_pos == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
|
||||||
|
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
|
||||||
|
}
|
||||||
|
emitter.buffer_pos = 0
|
||||||
|
return true
|
||||||
|
}
|
||||||
703
vendor/go.yaml.in/yaml/v3/yaml.go
generated
vendored
Normal file
703
vendor/go.yaml.in/yaml/v3/yaml.go
generated
vendored
Normal file
|
|
@ -0,0 +1,703 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package yaml implements YAML support for the Go language.
|
||||||
|
//
|
||||||
|
// Source code and other details for the project are available at GitHub:
|
||||||
|
//
|
||||||
|
// https://github.com/yaml/go-yaml
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The Unmarshaler interface may be implemented by types to customize their
|
||||||
|
// behavior when being unmarshaled from a YAML document.
|
||||||
|
type Unmarshaler interface {
|
||||||
|
UnmarshalYAML(value *Node) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type obsoleteUnmarshaler interface {
|
||||||
|
UnmarshalYAML(unmarshal func(interface{}) error) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Marshaler interface may be implemented by types to customize their
|
||||||
|
// behavior when being marshaled into a YAML document. The returned value
|
||||||
|
// is marshaled in place of the original value implementing Marshaler.
|
||||||
|
//
|
||||||
|
// If an error is returned by MarshalYAML, the marshaling procedure stops
|
||||||
|
// and returns with the provided error.
|
||||||
|
type Marshaler interface {
|
||||||
|
MarshalYAML() (interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal decodes the first document found within the in byte slice
|
||||||
|
// and assigns decoded values into the out value.
|
||||||
|
//
|
||||||
|
// Maps and pointers (to a struct, string, int, etc) are accepted as out
|
||||||
|
// values. If an internal pointer within a struct is not initialized,
|
||||||
|
// the yaml package will initialize it if necessary for unmarshalling
|
||||||
|
// the provided data. The out parameter must not be nil.
|
||||||
|
//
|
||||||
|
// The type of the decoded values should be compatible with the respective
|
||||||
|
// values in out. If one or more values cannot be decoded due to a type
|
||||||
|
// mismatches, decoding continues partially until the end of the YAML
|
||||||
|
// content, and a *yaml.TypeError is returned with details for all
|
||||||
|
// missed values.
|
||||||
|
//
|
||||||
|
// Struct fields are only unmarshalled if they are exported (have an
|
||||||
|
// upper case first letter), and are unmarshalled using the field name
|
||||||
|
// lowercased as the default key. Custom keys may be defined via the
|
||||||
|
// "yaml" name in the field tag: the content preceding the first comma
|
||||||
|
// is used as the key, and the following comma-separated options are
|
||||||
|
// used to tweak the marshalling process (see Marshal).
|
||||||
|
// Conflicting names result in a runtime error.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// type T struct {
|
||||||
|
// F int `yaml:"a,omitempty"`
|
||||||
|
// B int
|
||||||
|
// }
|
||||||
|
// var t T
|
||||||
|
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
|
||||||
|
//
|
||||||
|
// See the documentation of Marshal for the format of tags and a list of
|
||||||
|
// supported tag options.
|
||||||
|
func Unmarshal(in []byte, out interface{}) (err error) {
|
||||||
|
return unmarshal(in, out, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Decoder reads and decodes YAML values from an input stream.
|
||||||
|
type Decoder struct {
|
||||||
|
parser *parser
|
||||||
|
knownFields bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDecoder returns a new decoder that reads from r.
|
||||||
|
//
|
||||||
|
// The decoder introduces its own buffering and may read
|
||||||
|
// data from r beyond the YAML values requested.
|
||||||
|
func NewDecoder(r io.Reader) *Decoder {
|
||||||
|
return &Decoder{
|
||||||
|
parser: newParserFromReader(r),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// KnownFields ensures that the keys in decoded mappings to
|
||||||
|
// exist as fields in the struct being decoded into.
|
||||||
|
func (dec *Decoder) KnownFields(enable bool) {
|
||||||
|
dec.knownFields = enable
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode reads the next YAML-encoded value from its input
|
||||||
|
// and stores it in the value pointed to by v.
|
||||||
|
//
|
||||||
|
// See the documentation for Unmarshal for details about the
|
||||||
|
// conversion of YAML into a Go value.
|
||||||
|
func (dec *Decoder) Decode(v interface{}) (err error) {
|
||||||
|
d := newDecoder()
|
||||||
|
d.knownFields = dec.knownFields
|
||||||
|
defer handleErr(&err)
|
||||||
|
node := dec.parser.parse()
|
||||||
|
if node == nil {
|
||||||
|
return io.EOF
|
||||||
|
}
|
||||||
|
out := reflect.ValueOf(v)
|
||||||
|
if out.Kind() == reflect.Ptr && !out.IsNil() {
|
||||||
|
out = out.Elem()
|
||||||
|
}
|
||||||
|
d.unmarshal(node, out)
|
||||||
|
if len(d.terrors) > 0 {
|
||||||
|
return &TypeError{d.terrors}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode decodes the node and stores its data into the value pointed to by v.
|
||||||
|
//
|
||||||
|
// See the documentation for Unmarshal for details about the
|
||||||
|
// conversion of YAML into a Go value.
|
||||||
|
func (n *Node) Decode(v interface{}) (err error) {
|
||||||
|
d := newDecoder()
|
||||||
|
defer handleErr(&err)
|
||||||
|
out := reflect.ValueOf(v)
|
||||||
|
if out.Kind() == reflect.Ptr && !out.IsNil() {
|
||||||
|
out = out.Elem()
|
||||||
|
}
|
||||||
|
d.unmarshal(n, out)
|
||||||
|
if len(d.terrors) > 0 {
|
||||||
|
return &TypeError{d.terrors}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshal(in []byte, out interface{}, strict bool) (err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
d := newDecoder()
|
||||||
|
p := newParser(in)
|
||||||
|
defer p.destroy()
|
||||||
|
node := p.parse()
|
||||||
|
if node != nil {
|
||||||
|
v := reflect.ValueOf(out)
|
||||||
|
if v.Kind() == reflect.Ptr && !v.IsNil() {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
d.unmarshal(node, v)
|
||||||
|
}
|
||||||
|
if len(d.terrors) > 0 {
|
||||||
|
return &TypeError{d.terrors}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal serializes the value provided into a YAML document. The structure
|
||||||
|
// of the generated document will reflect the structure of the value itself.
|
||||||
|
// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
|
||||||
|
//
|
||||||
|
// Struct fields are only marshalled if they are exported (have an upper case
|
||||||
|
// first letter), and are marshalled using the field name lowercased as the
|
||||||
|
// default key. Custom keys may be defined via the "yaml" name in the field
|
||||||
|
// tag: the content preceding the first comma is used as the key, and the
|
||||||
|
// following comma-separated options are used to tweak the marshalling process.
|
||||||
|
// Conflicting names result in a runtime error.
|
||||||
|
//
|
||||||
|
// The field tag format accepted is:
|
||||||
|
//
|
||||||
|
// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
|
||||||
|
//
|
||||||
|
// The following flags are currently supported:
|
||||||
|
//
|
||||||
|
// omitempty Only include the field if it's not set to the zero
|
||||||
|
// value for the type or to empty slices or maps.
|
||||||
|
// Zero valued structs will be omitted if all their public
|
||||||
|
// fields are zero, unless they implement an IsZero
|
||||||
|
// method (see the IsZeroer interface type), in which
|
||||||
|
// case the field will be excluded if IsZero returns true.
|
||||||
|
//
|
||||||
|
// flow Marshal using a flow style (useful for structs,
|
||||||
|
// sequences and maps).
|
||||||
|
//
|
||||||
|
// inline Inline the field, which must be a struct or a map,
|
||||||
|
// causing all of its fields or keys to be processed as if
|
||||||
|
// they were part of the outer struct. For maps, keys must
|
||||||
|
// not conflict with the yaml keys of other struct fields.
|
||||||
|
//
|
||||||
|
// In addition, if the key is "-", the field is ignored.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// type T struct {
|
||||||
|
// F int `yaml:"a,omitempty"`
|
||||||
|
// B int
|
||||||
|
// }
|
||||||
|
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
|
||||||
|
// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
|
||||||
|
func Marshal(in interface{}) (out []byte, err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
e := newEncoder()
|
||||||
|
defer e.destroy()
|
||||||
|
e.marshalDoc("", reflect.ValueOf(in))
|
||||||
|
e.finish()
|
||||||
|
out = e.out
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Encoder writes YAML values to an output stream.
|
||||||
|
type Encoder struct {
|
||||||
|
encoder *encoder
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEncoder returns a new encoder that writes to w.
|
||||||
|
// The Encoder should be closed after use to flush all data
|
||||||
|
// to w.
|
||||||
|
func NewEncoder(w io.Writer) *Encoder {
|
||||||
|
return &Encoder{
|
||||||
|
encoder: newEncoderWithWriter(w),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode writes the YAML encoding of v to the stream.
|
||||||
|
// If multiple items are encoded to the stream, the
|
||||||
|
// second and subsequent document will be preceded
|
||||||
|
// with a "---" document separator, but the first will not.
|
||||||
|
//
|
||||||
|
// See the documentation for Marshal for details about the conversion of Go
|
||||||
|
// values to YAML.
|
||||||
|
func (e *Encoder) Encode(v interface{}) (err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
e.encoder.marshalDoc("", reflect.ValueOf(v))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode encodes value v and stores its representation in n.
|
||||||
|
//
|
||||||
|
// See the documentation for Marshal for details about the
|
||||||
|
// conversion of Go values into YAML.
|
||||||
|
func (n *Node) Encode(v interface{}) (err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
e := newEncoder()
|
||||||
|
defer e.destroy()
|
||||||
|
e.marshalDoc("", reflect.ValueOf(v))
|
||||||
|
e.finish()
|
||||||
|
p := newParser(e.out)
|
||||||
|
p.textless = true
|
||||||
|
defer p.destroy()
|
||||||
|
doc := p.parse()
|
||||||
|
*n = *doc.Content[0]
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIndent changes the used indentation used when encoding.
|
||||||
|
func (e *Encoder) SetIndent(spaces int) {
|
||||||
|
if spaces < 0 {
|
||||||
|
panic("yaml: cannot indent to a negative number of spaces")
|
||||||
|
}
|
||||||
|
e.encoder.indent = spaces
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompactSeqIndent makes it so that '- ' is considered part of the indentation.
|
||||||
|
func (e *Encoder) CompactSeqIndent() {
|
||||||
|
e.encoder.emitter.compact_sequence_indent = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultSeqIndent makes it so that '- ' is not considered part of the indentation.
|
||||||
|
func (e *Encoder) DefaultSeqIndent() {
|
||||||
|
e.encoder.emitter.compact_sequence_indent = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the encoder by writing any remaining data.
|
||||||
|
// It does not write a stream terminating string "...".
|
||||||
|
func (e *Encoder) Close() (err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
e.encoder.finish()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleErr(err *error) {
|
||||||
|
if v := recover(); v != nil {
|
||||||
|
if e, ok := v.(yamlError); ok {
|
||||||
|
*err = e.err
|
||||||
|
} else {
|
||||||
|
panic(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type yamlError struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func fail(err error) {
|
||||||
|
panic(yamlError{err})
|
||||||
|
}
|
||||||
|
|
||||||
|
func failf(format string, args ...interface{}) {
|
||||||
|
panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// A TypeError is returned by Unmarshal when one or more fields in
|
||||||
|
// the YAML document cannot be properly decoded into the requested
|
||||||
|
// types. When this error is returned, the value is still
|
||||||
|
// unmarshaled partially.
|
||||||
|
type TypeError struct {
|
||||||
|
Errors []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *TypeError) Error() string {
|
||||||
|
return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Kind uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
DocumentNode Kind = 1 << iota
|
||||||
|
SequenceNode
|
||||||
|
MappingNode
|
||||||
|
ScalarNode
|
||||||
|
AliasNode
|
||||||
|
)
|
||||||
|
|
||||||
|
type Style uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
TaggedStyle Style = 1 << iota
|
||||||
|
DoubleQuotedStyle
|
||||||
|
SingleQuotedStyle
|
||||||
|
LiteralStyle
|
||||||
|
FoldedStyle
|
||||||
|
FlowStyle
|
||||||
|
)
|
||||||
|
|
||||||
|
// Node represents an element in the YAML document hierarchy. While documents
|
||||||
|
// are typically encoded and decoded into higher level types, such as structs
|
||||||
|
// and maps, Node is an intermediate representation that allows detailed
|
||||||
|
// control over the content being decoded or encoded.
|
||||||
|
//
|
||||||
|
// It's worth noting that although Node offers access into details such as
|
||||||
|
// line numbers, colums, and comments, the content when re-encoded will not
|
||||||
|
// have its original textual representation preserved. An effort is made to
|
||||||
|
// render the data plesantly, and to preserve comments near the data they
|
||||||
|
// describe, though.
|
||||||
|
//
|
||||||
|
// Values that make use of the Node type interact with the yaml package in the
|
||||||
|
// same way any other type would do, by encoding and decoding yaml data
|
||||||
|
// directly or indirectly into them.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// var person struct {
|
||||||
|
// Name string
|
||||||
|
// Address yaml.Node
|
||||||
|
// }
|
||||||
|
// err := yaml.Unmarshal(data, &person)
|
||||||
|
//
|
||||||
|
// Or by itself:
|
||||||
|
//
|
||||||
|
// var person Node
|
||||||
|
// err := yaml.Unmarshal(data, &person)
|
||||||
|
type Node struct {
|
||||||
|
// Kind defines whether the node is a document, a mapping, a sequence,
|
||||||
|
// a scalar value, or an alias to another node. The specific data type of
|
||||||
|
// scalar nodes may be obtained via the ShortTag and LongTag methods.
|
||||||
|
Kind Kind
|
||||||
|
|
||||||
|
// Style allows customizing the apperance of the node in the tree.
|
||||||
|
Style Style
|
||||||
|
|
||||||
|
// Tag holds the YAML tag defining the data type for the value.
|
||||||
|
// When decoding, this field will always be set to the resolved tag,
|
||||||
|
// even when it wasn't explicitly provided in the YAML content.
|
||||||
|
// When encoding, if this field is unset the value type will be
|
||||||
|
// implied from the node properties, and if it is set, it will only
|
||||||
|
// be serialized into the representation if TaggedStyle is used or
|
||||||
|
// the implicit tag diverges from the provided one.
|
||||||
|
Tag string
|
||||||
|
|
||||||
|
// Value holds the unescaped and unquoted represenation of the value.
|
||||||
|
Value string
|
||||||
|
|
||||||
|
// Anchor holds the anchor name for this node, which allows aliases to point to it.
|
||||||
|
Anchor string
|
||||||
|
|
||||||
|
// Alias holds the node that this alias points to. Only valid when Kind is AliasNode.
|
||||||
|
Alias *Node
|
||||||
|
|
||||||
|
// Content holds contained nodes for documents, mappings, and sequences.
|
||||||
|
Content []*Node
|
||||||
|
|
||||||
|
// HeadComment holds any comments in the lines preceding the node and
|
||||||
|
// not separated by an empty line.
|
||||||
|
HeadComment string
|
||||||
|
|
||||||
|
// LineComment holds any comments at the end of the line where the node is in.
|
||||||
|
LineComment string
|
||||||
|
|
||||||
|
// FootComment holds any comments following the node and before empty lines.
|
||||||
|
FootComment string
|
||||||
|
|
||||||
|
// Line and Column hold the node position in the decoded YAML text.
|
||||||
|
// These fields are not respected when encoding the node.
|
||||||
|
Line int
|
||||||
|
Column int
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsZero returns whether the node has all of its fields unset.
|
||||||
|
func (n *Node) IsZero() bool {
|
||||||
|
return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil &&
|
||||||
|
n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// LongTag returns the long form of the tag that indicates the data type for
|
||||||
|
// the node. If the Tag field isn't explicitly defined, one will be computed
|
||||||
|
// based on the node properties.
|
||||||
|
func (n *Node) LongTag() string {
|
||||||
|
return longTag(n.ShortTag())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShortTag returns the short form of the YAML tag that indicates data type for
|
||||||
|
// the node. If the Tag field isn't explicitly defined, one will be computed
|
||||||
|
// based on the node properties.
|
||||||
|
func (n *Node) ShortTag() string {
|
||||||
|
if n.indicatedString() {
|
||||||
|
return strTag
|
||||||
|
}
|
||||||
|
if n.Tag == "" || n.Tag == "!" {
|
||||||
|
switch n.Kind {
|
||||||
|
case MappingNode:
|
||||||
|
return mapTag
|
||||||
|
case SequenceNode:
|
||||||
|
return seqTag
|
||||||
|
case AliasNode:
|
||||||
|
if n.Alias != nil {
|
||||||
|
return n.Alias.ShortTag()
|
||||||
|
}
|
||||||
|
case ScalarNode:
|
||||||
|
tag, _ := resolve("", n.Value)
|
||||||
|
return tag
|
||||||
|
case 0:
|
||||||
|
// Special case to make the zero value convenient.
|
||||||
|
if n.IsZero() {
|
||||||
|
return nullTag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return shortTag(n.Tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) indicatedString() bool {
|
||||||
|
return n.Kind == ScalarNode &&
|
||||||
|
(shortTag(n.Tag) == strTag ||
|
||||||
|
(n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetString is a convenience function that sets the node to a string value
|
||||||
|
// and defines its style in a pleasant way depending on its content.
|
||||||
|
func (n *Node) SetString(s string) {
|
||||||
|
n.Kind = ScalarNode
|
||||||
|
if utf8.ValidString(s) {
|
||||||
|
n.Value = s
|
||||||
|
n.Tag = strTag
|
||||||
|
} else {
|
||||||
|
n.Value = encodeBase64(s)
|
||||||
|
n.Tag = binaryTag
|
||||||
|
}
|
||||||
|
if strings.Contains(n.Value, "\n") {
|
||||||
|
n.Style = LiteralStyle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Maintain a mapping of keys to structure field indexes
|
||||||
|
|
||||||
|
// The code in this section was copied from mgo/bson.
|
||||||
|
|
||||||
|
// structInfo holds details for the serialization of fields of
|
||||||
|
// a given struct.
|
||||||
|
type structInfo struct {
|
||||||
|
FieldsMap map[string]fieldInfo
|
||||||
|
FieldsList []fieldInfo
|
||||||
|
|
||||||
|
// InlineMap is the number of the field in the struct that
|
||||||
|
// contains an ,inline map, or -1 if there's none.
|
||||||
|
InlineMap int
|
||||||
|
|
||||||
|
// InlineUnmarshalers holds indexes to inlined fields that
|
||||||
|
// contain unmarshaler values.
|
||||||
|
InlineUnmarshalers [][]int
|
||||||
|
}
|
||||||
|
|
||||||
|
type fieldInfo struct {
|
||||||
|
Key string
|
||||||
|
Num int
|
||||||
|
OmitEmpty bool
|
||||||
|
Flow bool
|
||||||
|
// Id holds the unique field identifier, so we can cheaply
|
||||||
|
// check for field duplicates without maintaining an extra map.
|
||||||
|
Id int
|
||||||
|
|
||||||
|
// Inline holds the field index if the field is part of an inlined struct.
|
||||||
|
Inline []int
|
||||||
|
}
|
||||||
|
|
||||||
|
var structMap = make(map[reflect.Type]*structInfo)
|
||||||
|
var fieldMapMutex sync.RWMutex
|
||||||
|
var unmarshalerType reflect.Type
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var v Unmarshaler
|
||||||
|
unmarshalerType = reflect.ValueOf(&v).Elem().Type()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStructInfo(st reflect.Type) (*structInfo, error) {
|
||||||
|
fieldMapMutex.RLock()
|
||||||
|
sinfo, found := structMap[st]
|
||||||
|
fieldMapMutex.RUnlock()
|
||||||
|
if found {
|
||||||
|
return sinfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
n := st.NumField()
|
||||||
|
fieldsMap := make(map[string]fieldInfo)
|
||||||
|
fieldsList := make([]fieldInfo, 0, n)
|
||||||
|
inlineMap := -1
|
||||||
|
inlineUnmarshalers := [][]int(nil)
|
||||||
|
for i := 0; i != n; i++ {
|
||||||
|
field := st.Field(i)
|
||||||
|
if field.PkgPath != "" && !field.Anonymous {
|
||||||
|
continue // Private field
|
||||||
|
}
|
||||||
|
|
||||||
|
info := fieldInfo{Num: i}
|
||||||
|
|
||||||
|
tag := field.Tag.Get("yaml")
|
||||||
|
if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
|
||||||
|
tag = string(field.Tag)
|
||||||
|
}
|
||||||
|
if tag == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
inline := false
|
||||||
|
fields := strings.Split(tag, ",")
|
||||||
|
if len(fields) > 1 {
|
||||||
|
for _, flag := range fields[1:] {
|
||||||
|
switch flag {
|
||||||
|
case "omitempty":
|
||||||
|
info.OmitEmpty = true
|
||||||
|
case "flow":
|
||||||
|
info.Flow = true
|
||||||
|
case "inline":
|
||||||
|
inline = true
|
||||||
|
default:
|
||||||
|
return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tag = fields[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if inline {
|
||||||
|
switch field.Type.Kind() {
|
||||||
|
case reflect.Map:
|
||||||
|
if inlineMap >= 0 {
|
||||||
|
return nil, errors.New("multiple ,inline maps in struct " + st.String())
|
||||||
|
}
|
||||||
|
if field.Type.Key() != reflect.TypeOf("") {
|
||||||
|
return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String())
|
||||||
|
}
|
||||||
|
inlineMap = info.Num
|
||||||
|
case reflect.Struct, reflect.Ptr:
|
||||||
|
ftype := field.Type
|
||||||
|
for ftype.Kind() == reflect.Ptr {
|
||||||
|
ftype = ftype.Elem()
|
||||||
|
}
|
||||||
|
if ftype.Kind() != reflect.Struct {
|
||||||
|
return nil, errors.New("option ,inline may only be used on a struct or map field")
|
||||||
|
}
|
||||||
|
if reflect.PtrTo(ftype).Implements(unmarshalerType) {
|
||||||
|
inlineUnmarshalers = append(inlineUnmarshalers, []int{i})
|
||||||
|
} else {
|
||||||
|
sinfo, err := getStructInfo(ftype)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, index := range sinfo.InlineUnmarshalers {
|
||||||
|
inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...))
|
||||||
|
}
|
||||||
|
for _, finfo := range sinfo.FieldsList {
|
||||||
|
if _, found := fieldsMap[finfo.Key]; found {
|
||||||
|
msg := "duplicated key '" + finfo.Key + "' in struct " + st.String()
|
||||||
|
return nil, errors.New(msg)
|
||||||
|
}
|
||||||
|
if finfo.Inline == nil {
|
||||||
|
finfo.Inline = []int{i, finfo.Num}
|
||||||
|
} else {
|
||||||
|
finfo.Inline = append([]int{i}, finfo.Inline...)
|
||||||
|
}
|
||||||
|
finfo.Id = len(fieldsList)
|
||||||
|
fieldsMap[finfo.Key] = finfo
|
||||||
|
fieldsList = append(fieldsList, finfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, errors.New("option ,inline may only be used on a struct or map field")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag != "" {
|
||||||
|
info.Key = tag
|
||||||
|
} else {
|
||||||
|
info.Key = strings.ToLower(field.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, found = fieldsMap[info.Key]; found {
|
||||||
|
msg := "duplicated key '" + info.Key + "' in struct " + st.String()
|
||||||
|
return nil, errors.New(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
info.Id = len(fieldsList)
|
||||||
|
fieldsList = append(fieldsList, info)
|
||||||
|
fieldsMap[info.Key] = info
|
||||||
|
}
|
||||||
|
|
||||||
|
sinfo = &structInfo{
|
||||||
|
FieldsMap: fieldsMap,
|
||||||
|
FieldsList: fieldsList,
|
||||||
|
InlineMap: inlineMap,
|
||||||
|
InlineUnmarshalers: inlineUnmarshalers,
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldMapMutex.Lock()
|
||||||
|
structMap[st] = sinfo
|
||||||
|
fieldMapMutex.Unlock()
|
||||||
|
return sinfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsZeroer is used to check whether an object is zero to
|
||||||
|
// determine whether it should be omitted when marshaling
|
||||||
|
// with the omitempty flag. One notable implementation
|
||||||
|
// is time.Time.
|
||||||
|
type IsZeroer interface {
|
||||||
|
IsZero() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func isZero(v reflect.Value) bool {
|
||||||
|
kind := v.Kind()
|
||||||
|
if z, ok := v.Interface().(IsZeroer); ok {
|
||||||
|
if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return z.IsZero()
|
||||||
|
}
|
||||||
|
switch kind {
|
||||||
|
case reflect.String:
|
||||||
|
return len(v.String()) == 0
|
||||||
|
case reflect.Interface, reflect.Ptr:
|
||||||
|
return v.IsNil()
|
||||||
|
case reflect.Slice:
|
||||||
|
return v.Len() == 0
|
||||||
|
case reflect.Map:
|
||||||
|
return v.Len() == 0
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return v.Int() == 0
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return v.Float() == 0
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return v.Uint() == 0
|
||||||
|
case reflect.Bool:
|
||||||
|
return !v.Bool()
|
||||||
|
case reflect.Struct:
|
||||||
|
vt := v.Type()
|
||||||
|
for i := v.NumField() - 1; i >= 0; i-- {
|
||||||
|
if vt.Field(i).PkgPath != "" {
|
||||||
|
continue // Private field
|
||||||
|
}
|
||||||
|
if !isZero(v.Field(i)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
811
vendor/go.yaml.in/yaml/v3/yamlh.go
generated
vendored
Normal file
811
vendor/go.yaml.in/yaml/v3/yamlh.go
generated
vendored
Normal file
|
|
@ -0,0 +1,811 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The version directive data.
|
||||||
|
type yaml_version_directive_t struct {
|
||||||
|
major int8 // The major version number.
|
||||||
|
minor int8 // The minor version number.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The tag directive data.
|
||||||
|
type yaml_tag_directive_t struct {
|
||||||
|
handle []byte // The tag handle.
|
||||||
|
prefix []byte // The tag prefix.
|
||||||
|
}
|
||||||
|
|
||||||
|
type yaml_encoding_t int
|
||||||
|
|
||||||
|
// The stream encoding.
|
||||||
|
const (
|
||||||
|
// Let the parser choose the encoding.
|
||||||
|
yaml_ANY_ENCODING yaml_encoding_t = iota
|
||||||
|
|
||||||
|
yaml_UTF8_ENCODING // The default UTF-8 encoding.
|
||||||
|
yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
|
||||||
|
yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_break_t int
|
||||||
|
|
||||||
|
// Line break types.
|
||||||
|
const (
|
||||||
|
// Let the parser choose the break type.
|
||||||
|
yaml_ANY_BREAK yaml_break_t = iota
|
||||||
|
|
||||||
|
yaml_CR_BREAK // Use CR for line breaks (Mac style).
|
||||||
|
yaml_LN_BREAK // Use LN for line breaks (Unix style).
|
||||||
|
yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style).
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_error_type_t int
|
||||||
|
|
||||||
|
// Many bad things could happen with the parser and emitter.
|
||||||
|
const (
|
||||||
|
// No error is produced.
|
||||||
|
yaml_NO_ERROR yaml_error_type_t = iota
|
||||||
|
|
||||||
|
yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory.
|
||||||
|
yaml_READER_ERROR // Cannot read or decode the input stream.
|
||||||
|
yaml_SCANNER_ERROR // Cannot scan the input stream.
|
||||||
|
yaml_PARSER_ERROR // Cannot parse the input stream.
|
||||||
|
yaml_COMPOSER_ERROR // Cannot compose a YAML document.
|
||||||
|
yaml_WRITER_ERROR // Cannot write to the output stream.
|
||||||
|
yaml_EMITTER_ERROR // Cannot emit a YAML stream.
|
||||||
|
)
|
||||||
|
|
||||||
|
// The pointer position.
|
||||||
|
type yaml_mark_t struct {
|
||||||
|
index int // The position index.
|
||||||
|
line int // The position line.
|
||||||
|
column int // The position column.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node Styles
|
||||||
|
|
||||||
|
type yaml_style_t int8
|
||||||
|
|
||||||
|
type yaml_scalar_style_t yaml_style_t
|
||||||
|
|
||||||
|
// Scalar styles.
|
||||||
|
const (
|
||||||
|
// Let the emitter choose the style.
|
||||||
|
yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0
|
||||||
|
|
||||||
|
yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style.
|
||||||
|
yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
|
||||||
|
yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
|
||||||
|
yaml_LITERAL_SCALAR_STYLE // The literal scalar style.
|
||||||
|
yaml_FOLDED_SCALAR_STYLE // The folded scalar style.
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_sequence_style_t yaml_style_t
|
||||||
|
|
||||||
|
// Sequence styles.
|
||||||
|
const (
|
||||||
|
// Let the emitter choose the style.
|
||||||
|
yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
|
||||||
|
|
||||||
|
yaml_BLOCK_SEQUENCE_STYLE // The block sequence style.
|
||||||
|
yaml_FLOW_SEQUENCE_STYLE // The flow sequence style.
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_mapping_style_t yaml_style_t
|
||||||
|
|
||||||
|
// Mapping styles.
|
||||||
|
const (
|
||||||
|
// Let the emitter choose the style.
|
||||||
|
yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
|
||||||
|
|
||||||
|
yaml_BLOCK_MAPPING_STYLE // The block mapping style.
|
||||||
|
yaml_FLOW_MAPPING_STYLE // The flow mapping style.
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tokens
|
||||||
|
|
||||||
|
type yaml_token_type_t int
|
||||||
|
|
||||||
|
// Token types.
|
||||||
|
const (
|
||||||
|
// An empty token.
|
||||||
|
yaml_NO_TOKEN yaml_token_type_t = iota
|
||||||
|
|
||||||
|
yaml_STREAM_START_TOKEN // A STREAM-START token.
|
||||||
|
yaml_STREAM_END_TOKEN // A STREAM-END token.
|
||||||
|
|
||||||
|
yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
|
||||||
|
yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token.
|
||||||
|
yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token.
|
||||||
|
yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token.
|
||||||
|
|
||||||
|
yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
|
||||||
|
yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token.
|
||||||
|
yaml_BLOCK_END_TOKEN // A BLOCK-END token.
|
||||||
|
|
||||||
|
yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
|
||||||
|
yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token.
|
||||||
|
yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token.
|
||||||
|
yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token.
|
||||||
|
|
||||||
|
yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
|
||||||
|
yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token.
|
||||||
|
yaml_KEY_TOKEN // A KEY token.
|
||||||
|
yaml_VALUE_TOKEN // A VALUE token.
|
||||||
|
|
||||||
|
yaml_ALIAS_TOKEN // An ALIAS token.
|
||||||
|
yaml_ANCHOR_TOKEN // An ANCHOR token.
|
||||||
|
yaml_TAG_TOKEN // A TAG token.
|
||||||
|
yaml_SCALAR_TOKEN // A SCALAR token.
|
||||||
|
)
|
||||||
|
|
||||||
|
func (tt yaml_token_type_t) String() string {
|
||||||
|
switch tt {
|
||||||
|
case yaml_NO_TOKEN:
|
||||||
|
return "yaml_NO_TOKEN"
|
||||||
|
case yaml_STREAM_START_TOKEN:
|
||||||
|
return "yaml_STREAM_START_TOKEN"
|
||||||
|
case yaml_STREAM_END_TOKEN:
|
||||||
|
return "yaml_STREAM_END_TOKEN"
|
||||||
|
case yaml_VERSION_DIRECTIVE_TOKEN:
|
||||||
|
return "yaml_VERSION_DIRECTIVE_TOKEN"
|
||||||
|
case yaml_TAG_DIRECTIVE_TOKEN:
|
||||||
|
return "yaml_TAG_DIRECTIVE_TOKEN"
|
||||||
|
case yaml_DOCUMENT_START_TOKEN:
|
||||||
|
return "yaml_DOCUMENT_START_TOKEN"
|
||||||
|
case yaml_DOCUMENT_END_TOKEN:
|
||||||
|
return "yaml_DOCUMENT_END_TOKEN"
|
||||||
|
case yaml_BLOCK_SEQUENCE_START_TOKEN:
|
||||||
|
return "yaml_BLOCK_SEQUENCE_START_TOKEN"
|
||||||
|
case yaml_BLOCK_MAPPING_START_TOKEN:
|
||||||
|
return "yaml_BLOCK_MAPPING_START_TOKEN"
|
||||||
|
case yaml_BLOCK_END_TOKEN:
|
||||||
|
return "yaml_BLOCK_END_TOKEN"
|
||||||
|
case yaml_FLOW_SEQUENCE_START_TOKEN:
|
||||||
|
return "yaml_FLOW_SEQUENCE_START_TOKEN"
|
||||||
|
case yaml_FLOW_SEQUENCE_END_TOKEN:
|
||||||
|
return "yaml_FLOW_SEQUENCE_END_TOKEN"
|
||||||
|
case yaml_FLOW_MAPPING_START_TOKEN:
|
||||||
|
return "yaml_FLOW_MAPPING_START_TOKEN"
|
||||||
|
case yaml_FLOW_MAPPING_END_TOKEN:
|
||||||
|
return "yaml_FLOW_MAPPING_END_TOKEN"
|
||||||
|
case yaml_BLOCK_ENTRY_TOKEN:
|
||||||
|
return "yaml_BLOCK_ENTRY_TOKEN"
|
||||||
|
case yaml_FLOW_ENTRY_TOKEN:
|
||||||
|
return "yaml_FLOW_ENTRY_TOKEN"
|
||||||
|
case yaml_KEY_TOKEN:
|
||||||
|
return "yaml_KEY_TOKEN"
|
||||||
|
case yaml_VALUE_TOKEN:
|
||||||
|
return "yaml_VALUE_TOKEN"
|
||||||
|
case yaml_ALIAS_TOKEN:
|
||||||
|
return "yaml_ALIAS_TOKEN"
|
||||||
|
case yaml_ANCHOR_TOKEN:
|
||||||
|
return "yaml_ANCHOR_TOKEN"
|
||||||
|
case yaml_TAG_TOKEN:
|
||||||
|
return "yaml_TAG_TOKEN"
|
||||||
|
case yaml_SCALAR_TOKEN:
|
||||||
|
return "yaml_SCALAR_TOKEN"
|
||||||
|
}
|
||||||
|
return "<unknown token>"
|
||||||
|
}
|
||||||
|
|
||||||
|
// The token structure.
|
||||||
|
type yaml_token_t struct {
|
||||||
|
// The token type.
|
||||||
|
typ yaml_token_type_t
|
||||||
|
|
||||||
|
// The start/end of the token.
|
||||||
|
start_mark, end_mark yaml_mark_t
|
||||||
|
|
||||||
|
// The stream encoding (for yaml_STREAM_START_TOKEN).
|
||||||
|
encoding yaml_encoding_t
|
||||||
|
|
||||||
|
// The alias/anchor/scalar value or tag/tag directive handle
|
||||||
|
// (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN).
|
||||||
|
value []byte
|
||||||
|
|
||||||
|
// The tag suffix (for yaml_TAG_TOKEN).
|
||||||
|
suffix []byte
|
||||||
|
|
||||||
|
// The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN).
|
||||||
|
prefix []byte
|
||||||
|
|
||||||
|
// The scalar style (for yaml_SCALAR_TOKEN).
|
||||||
|
style yaml_scalar_style_t
|
||||||
|
|
||||||
|
// The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN).
|
||||||
|
major, minor int8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Events
|
||||||
|
|
||||||
|
type yaml_event_type_t int8
|
||||||
|
|
||||||
|
// Event types.
|
||||||
|
const (
|
||||||
|
// An empty event.
|
||||||
|
yaml_NO_EVENT yaml_event_type_t = iota
|
||||||
|
|
||||||
|
yaml_STREAM_START_EVENT // A STREAM-START event.
|
||||||
|
yaml_STREAM_END_EVENT // A STREAM-END event.
|
||||||
|
yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event.
|
||||||
|
yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event.
|
||||||
|
yaml_ALIAS_EVENT // An ALIAS event.
|
||||||
|
yaml_SCALAR_EVENT // A SCALAR event.
|
||||||
|
yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event.
|
||||||
|
yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event.
|
||||||
|
yaml_MAPPING_START_EVENT // A MAPPING-START event.
|
||||||
|
yaml_MAPPING_END_EVENT // A MAPPING-END event.
|
||||||
|
yaml_TAIL_COMMENT_EVENT
|
||||||
|
)
|
||||||
|
|
||||||
|
var eventStrings = []string{
|
||||||
|
yaml_NO_EVENT: "none",
|
||||||
|
yaml_STREAM_START_EVENT: "stream start",
|
||||||
|
yaml_STREAM_END_EVENT: "stream end",
|
||||||
|
yaml_DOCUMENT_START_EVENT: "document start",
|
||||||
|
yaml_DOCUMENT_END_EVENT: "document end",
|
||||||
|
yaml_ALIAS_EVENT: "alias",
|
||||||
|
yaml_SCALAR_EVENT: "scalar",
|
||||||
|
yaml_SEQUENCE_START_EVENT: "sequence start",
|
||||||
|
yaml_SEQUENCE_END_EVENT: "sequence end",
|
||||||
|
yaml_MAPPING_START_EVENT: "mapping start",
|
||||||
|
yaml_MAPPING_END_EVENT: "mapping end",
|
||||||
|
yaml_TAIL_COMMENT_EVENT: "tail comment",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e yaml_event_type_t) String() string {
|
||||||
|
if e < 0 || int(e) >= len(eventStrings) {
|
||||||
|
return fmt.Sprintf("unknown event %d", e)
|
||||||
|
}
|
||||||
|
return eventStrings[e]
|
||||||
|
}
|
||||||
|
|
||||||
|
// The event structure.
|
||||||
|
type yaml_event_t struct {
|
||||||
|
|
||||||
|
// The event type.
|
||||||
|
typ yaml_event_type_t
|
||||||
|
|
||||||
|
// The start and end of the event.
|
||||||
|
start_mark, end_mark yaml_mark_t
|
||||||
|
|
||||||
|
// The document encoding (for yaml_STREAM_START_EVENT).
|
||||||
|
encoding yaml_encoding_t
|
||||||
|
|
||||||
|
// The version directive (for yaml_DOCUMENT_START_EVENT).
|
||||||
|
version_directive *yaml_version_directive_t
|
||||||
|
|
||||||
|
// The list of tag directives (for yaml_DOCUMENT_START_EVENT).
|
||||||
|
tag_directives []yaml_tag_directive_t
|
||||||
|
|
||||||
|
// The comments
|
||||||
|
head_comment []byte
|
||||||
|
line_comment []byte
|
||||||
|
foot_comment []byte
|
||||||
|
tail_comment []byte
|
||||||
|
|
||||||
|
// The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
|
||||||
|
anchor []byte
|
||||||
|
|
||||||
|
// The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
|
||||||
|
tag []byte
|
||||||
|
|
||||||
|
// The scalar value (for yaml_SCALAR_EVENT).
|
||||||
|
value []byte
|
||||||
|
|
||||||
|
// Is the document start/end indicator implicit, or the tag optional?
|
||||||
|
// (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT).
|
||||||
|
implicit bool
|
||||||
|
|
||||||
|
// Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT).
|
||||||
|
quoted_implicit bool
|
||||||
|
|
||||||
|
// The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
|
||||||
|
style yaml_style_t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) }
|
||||||
|
func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) }
|
||||||
|
func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) }
|
||||||
|
|
||||||
|
// Nodes
|
||||||
|
|
||||||
|
const (
|
||||||
|
yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null.
|
||||||
|
yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false.
|
||||||
|
yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values.
|
||||||
|
yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values.
|
||||||
|
yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values.
|
||||||
|
yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
|
||||||
|
|
||||||
|
yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
|
||||||
|
yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
|
||||||
|
|
||||||
|
// Not in original libyaml.
|
||||||
|
yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
|
||||||
|
yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
|
||||||
|
|
||||||
|
yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str.
|
||||||
|
yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
|
||||||
|
yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map.
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_node_type_t int
|
||||||
|
|
||||||
|
// Node types.
|
||||||
|
const (
|
||||||
|
// An empty node.
|
||||||
|
yaml_NO_NODE yaml_node_type_t = iota
|
||||||
|
|
||||||
|
yaml_SCALAR_NODE // A scalar node.
|
||||||
|
yaml_SEQUENCE_NODE // A sequence node.
|
||||||
|
yaml_MAPPING_NODE // A mapping node.
|
||||||
|
)
|
||||||
|
|
||||||
|
// An element of a sequence node.
|
||||||
|
type yaml_node_item_t int
|
||||||
|
|
||||||
|
// An element of a mapping node.
|
||||||
|
type yaml_node_pair_t struct {
|
||||||
|
key int // The key of the element.
|
||||||
|
value int // The value of the element.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The node structure.
|
||||||
|
type yaml_node_t struct {
|
||||||
|
typ yaml_node_type_t // The node type.
|
||||||
|
tag []byte // The node tag.
|
||||||
|
|
||||||
|
// The node data.
|
||||||
|
|
||||||
|
// The scalar parameters (for yaml_SCALAR_NODE).
|
||||||
|
scalar struct {
|
||||||
|
value []byte // The scalar value.
|
||||||
|
length int // The length of the scalar value.
|
||||||
|
style yaml_scalar_style_t // The scalar style.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The sequence parameters (for YAML_SEQUENCE_NODE).
|
||||||
|
sequence struct {
|
||||||
|
items_data []yaml_node_item_t // The stack of sequence items.
|
||||||
|
style yaml_sequence_style_t // The sequence style.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The mapping parameters (for yaml_MAPPING_NODE).
|
||||||
|
mapping struct {
|
||||||
|
pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value).
|
||||||
|
pairs_start *yaml_node_pair_t // The beginning of the stack.
|
||||||
|
pairs_end *yaml_node_pair_t // The end of the stack.
|
||||||
|
pairs_top *yaml_node_pair_t // The top of the stack.
|
||||||
|
style yaml_mapping_style_t // The mapping style.
|
||||||
|
}
|
||||||
|
|
||||||
|
start_mark yaml_mark_t // The beginning of the node.
|
||||||
|
end_mark yaml_mark_t // The end of the node.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// The document structure.
|
||||||
|
type yaml_document_t struct {
|
||||||
|
|
||||||
|
// The document nodes.
|
||||||
|
nodes []yaml_node_t
|
||||||
|
|
||||||
|
// The version directive.
|
||||||
|
version_directive *yaml_version_directive_t
|
||||||
|
|
||||||
|
// The list of tag directives.
|
||||||
|
tag_directives_data []yaml_tag_directive_t
|
||||||
|
tag_directives_start int // The beginning of the tag directives list.
|
||||||
|
tag_directives_end int // The end of the tag directives list.
|
||||||
|
|
||||||
|
start_implicit int // Is the document start indicator implicit?
|
||||||
|
end_implicit int // Is the document end indicator implicit?
|
||||||
|
|
||||||
|
// The start/end of the document.
|
||||||
|
start_mark, end_mark yaml_mark_t
|
||||||
|
}
|
||||||
|
|
||||||
|
// The prototype of a read handler.
|
||||||
|
//
|
||||||
|
// The read handler is called when the parser needs to read more bytes from the
|
||||||
|
// source. The handler should write not more than size bytes to the buffer.
|
||||||
|
// The number of written bytes should be set to the size_read variable.
|
||||||
|
//
|
||||||
|
// [in,out] data A pointer to an application data specified by
|
||||||
|
//
|
||||||
|
// yaml_parser_set_input().
|
||||||
|
//
|
||||||
|
// [out] buffer The buffer to write the data from the source.
|
||||||
|
// [in] size The size of the buffer.
|
||||||
|
// [out] size_read The actual number of bytes read from the source.
|
||||||
|
//
|
||||||
|
// On success, the handler should return 1. If the handler failed,
|
||||||
|
// the returned value should be 0. On EOF, the handler should set the
|
||||||
|
// size_read to 0 and return 1.
|
||||||
|
type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
|
||||||
|
|
||||||
|
// This structure holds information about a potential simple key.
|
||||||
|
type yaml_simple_key_t struct {
|
||||||
|
possible bool // Is a simple key possible?
|
||||||
|
required bool // Is a simple key required?
|
||||||
|
token_number int // The number of the token.
|
||||||
|
mark yaml_mark_t // The position mark.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The states of the parser.
|
||||||
|
type yaml_parser_state_t int
|
||||||
|
|
||||||
|
const (
|
||||||
|
yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
|
||||||
|
|
||||||
|
yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document.
|
||||||
|
yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START.
|
||||||
|
yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document.
|
||||||
|
yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END.
|
||||||
|
yaml_PARSE_BLOCK_NODE_STATE // Expect a block node.
|
||||||
|
yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence.
|
||||||
|
yaml_PARSE_FLOW_NODE_STATE // Expect a flow node.
|
||||||
|
yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence.
|
||||||
|
yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence.
|
||||||
|
yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence.
|
||||||
|
yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
|
||||||
|
yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key.
|
||||||
|
yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry.
|
||||||
|
yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
|
||||||
|
yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
|
||||||
|
yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
|
||||||
|
yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping.
|
||||||
|
yaml_PARSE_END_STATE // Expect nothing.
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ps yaml_parser_state_t) String() string {
|
||||||
|
switch ps {
|
||||||
|
case yaml_PARSE_STREAM_START_STATE:
|
||||||
|
return "yaml_PARSE_STREAM_START_STATE"
|
||||||
|
case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
|
||||||
|
return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE"
|
||||||
|
case yaml_PARSE_DOCUMENT_START_STATE:
|
||||||
|
return "yaml_PARSE_DOCUMENT_START_STATE"
|
||||||
|
case yaml_PARSE_DOCUMENT_CONTENT_STATE:
|
||||||
|
return "yaml_PARSE_DOCUMENT_CONTENT_STATE"
|
||||||
|
case yaml_PARSE_DOCUMENT_END_STATE:
|
||||||
|
return "yaml_PARSE_DOCUMENT_END_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_NODE_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_NODE_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE"
|
||||||
|
case yaml_PARSE_FLOW_NODE_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_NODE_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
|
||||||
|
case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_MAPPING_KEY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE"
|
||||||
|
case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
|
||||||
|
case yaml_PARSE_END_STATE:
|
||||||
|
return "yaml_PARSE_END_STATE"
|
||||||
|
}
|
||||||
|
return "<unknown parser state>"
|
||||||
|
}
|
||||||
|
|
||||||
|
// This structure holds aliases data.
|
||||||
|
type yaml_alias_data_t struct {
|
||||||
|
anchor []byte // The anchor.
|
||||||
|
index int // The node id.
|
||||||
|
mark yaml_mark_t // The anchor mark.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The parser structure.
|
||||||
|
//
|
||||||
|
// All members are internal. Manage the structure using the
|
||||||
|
// yaml_parser_ family of functions.
|
||||||
|
type yaml_parser_t struct {
|
||||||
|
|
||||||
|
// Error handling
|
||||||
|
|
||||||
|
error yaml_error_type_t // Error type.
|
||||||
|
|
||||||
|
problem string // Error description.
|
||||||
|
|
||||||
|
// The byte about which the problem occurred.
|
||||||
|
problem_offset int
|
||||||
|
problem_value int
|
||||||
|
problem_mark yaml_mark_t
|
||||||
|
|
||||||
|
// The error context.
|
||||||
|
context string
|
||||||
|
context_mark yaml_mark_t
|
||||||
|
|
||||||
|
// Reader stuff
|
||||||
|
|
||||||
|
read_handler yaml_read_handler_t // Read handler.
|
||||||
|
|
||||||
|
input_reader io.Reader // File input data.
|
||||||
|
input []byte // String input data.
|
||||||
|
input_pos int
|
||||||
|
|
||||||
|
eof bool // EOF flag
|
||||||
|
|
||||||
|
buffer []byte // The working buffer.
|
||||||
|
buffer_pos int // The current position of the buffer.
|
||||||
|
|
||||||
|
unread int // The number of unread characters in the buffer.
|
||||||
|
|
||||||
|
newlines int // The number of line breaks since last non-break/non-blank character
|
||||||
|
|
||||||
|
raw_buffer []byte // The raw buffer.
|
||||||
|
raw_buffer_pos int // The current position of the buffer.
|
||||||
|
|
||||||
|
encoding yaml_encoding_t // The input encoding.
|
||||||
|
|
||||||
|
offset int // The offset of the current position (in bytes).
|
||||||
|
mark yaml_mark_t // The mark of the current position.
|
||||||
|
|
||||||
|
// Comments
|
||||||
|
|
||||||
|
head_comment []byte // The current head comments
|
||||||
|
line_comment []byte // The current line comments
|
||||||
|
foot_comment []byte // The current foot comments
|
||||||
|
tail_comment []byte // Foot comment that happens at the end of a block.
|
||||||
|
stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc)
|
||||||
|
|
||||||
|
comments []yaml_comment_t // The folded comments for all parsed tokens
|
||||||
|
comments_head int
|
||||||
|
|
||||||
|
// Scanner stuff
|
||||||
|
|
||||||
|
stream_start_produced bool // Have we started to scan the input stream?
|
||||||
|
stream_end_produced bool // Have we reached the end of the input stream?
|
||||||
|
|
||||||
|
flow_level int // The number of unclosed '[' and '{' indicators.
|
||||||
|
|
||||||
|
tokens []yaml_token_t // The tokens queue.
|
||||||
|
tokens_head int // The head of the tokens queue.
|
||||||
|
tokens_parsed int // The number of tokens fetched from the queue.
|
||||||
|
token_available bool // Does the tokens queue contain a token ready for dequeueing.
|
||||||
|
|
||||||
|
indent int // The current indentation level.
|
||||||
|
indents []int // The indentation levels stack.
|
||||||
|
|
||||||
|
simple_key_allowed bool // May a simple key occur at the current position?
|
||||||
|
simple_keys []yaml_simple_key_t // The stack of simple keys.
|
||||||
|
simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number
|
||||||
|
|
||||||
|
// Parser stuff
|
||||||
|
|
||||||
|
state yaml_parser_state_t // The current parser state.
|
||||||
|
states []yaml_parser_state_t // The parser states stack.
|
||||||
|
marks []yaml_mark_t // The stack of marks.
|
||||||
|
tag_directives []yaml_tag_directive_t // The list of TAG directives.
|
||||||
|
|
||||||
|
// Dumper stuff
|
||||||
|
|
||||||
|
aliases []yaml_alias_data_t // The alias data.
|
||||||
|
|
||||||
|
document *yaml_document_t // The currently parsed document.
|
||||||
|
}
|
||||||
|
|
||||||
|
type yaml_comment_t struct {
|
||||||
|
scan_mark yaml_mark_t // Position where scanning for comments started
|
||||||
|
token_mark yaml_mark_t // Position after which tokens will be associated with this comment
|
||||||
|
start_mark yaml_mark_t // Position of '#' comment mark
|
||||||
|
end_mark yaml_mark_t // Position where comment terminated
|
||||||
|
|
||||||
|
head []byte
|
||||||
|
line []byte
|
||||||
|
foot []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emitter Definitions
|
||||||
|
|
||||||
|
// The prototype of a write handler.
|
||||||
|
//
|
||||||
|
// The write handler is called when the emitter needs to flush the accumulated
|
||||||
|
// characters to the output. The handler should write @a size bytes of the
|
||||||
|
// @a buffer to the output.
|
||||||
|
//
|
||||||
|
// @param[in,out] data A pointer to an application data specified by
|
||||||
|
//
|
||||||
|
// yaml_emitter_set_output().
|
||||||
|
//
|
||||||
|
// @param[in] buffer The buffer with bytes to be written.
|
||||||
|
// @param[in] size The size of the buffer.
|
||||||
|
//
|
||||||
|
// @returns On success, the handler should return @c 1. If the handler failed,
|
||||||
|
// the returned value should be @c 0.
|
||||||
|
type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
|
||||||
|
|
||||||
|
type yaml_emitter_state_t int
|
||||||
|
|
||||||
|
// The emitter states.
|
||||||
|
const (
|
||||||
|
// Expect STREAM-START.
|
||||||
|
yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
|
||||||
|
|
||||||
|
yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END.
|
||||||
|
yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END.
|
||||||
|
yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document.
|
||||||
|
yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END.
|
||||||
|
yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence.
|
||||||
|
yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out
|
||||||
|
yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence.
|
||||||
|
yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
|
||||||
|
yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out
|
||||||
|
yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
|
||||||
|
yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping.
|
||||||
|
yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
|
||||||
|
yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence.
|
||||||
|
yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence.
|
||||||
|
yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
|
||||||
|
yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping.
|
||||||
|
yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
|
||||||
|
yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping.
|
||||||
|
yaml_EMIT_END_STATE // Expect nothing.
|
||||||
|
)
|
||||||
|
|
||||||
|
// The emitter structure.
|
||||||
|
//
|
||||||
|
// All members are internal. Manage the structure using the @c yaml_emitter_
|
||||||
|
// family of functions.
|
||||||
|
type yaml_emitter_t struct {
|
||||||
|
|
||||||
|
// Error handling
|
||||||
|
|
||||||
|
error yaml_error_type_t // Error type.
|
||||||
|
problem string // Error description.
|
||||||
|
|
||||||
|
// Writer stuff
|
||||||
|
|
||||||
|
write_handler yaml_write_handler_t // Write handler.
|
||||||
|
|
||||||
|
output_buffer *[]byte // String output data.
|
||||||
|
output_writer io.Writer // File output data.
|
||||||
|
|
||||||
|
buffer []byte // The working buffer.
|
||||||
|
buffer_pos int // The current position of the buffer.
|
||||||
|
|
||||||
|
raw_buffer []byte // The raw buffer.
|
||||||
|
raw_buffer_pos int // The current position of the buffer.
|
||||||
|
|
||||||
|
encoding yaml_encoding_t // The stream encoding.
|
||||||
|
|
||||||
|
// Emitter stuff
|
||||||
|
|
||||||
|
canonical bool // If the output is in the canonical style?
|
||||||
|
best_indent int // The number of indentation spaces.
|
||||||
|
best_width int // The preferred width of the output lines.
|
||||||
|
unicode bool // Allow unescaped non-ASCII characters?
|
||||||
|
line_break yaml_break_t // The preferred line break.
|
||||||
|
|
||||||
|
state yaml_emitter_state_t // The current emitter state.
|
||||||
|
states []yaml_emitter_state_t // The stack of states.
|
||||||
|
|
||||||
|
events []yaml_event_t // The event queue.
|
||||||
|
events_head int // The head of the event queue.
|
||||||
|
|
||||||
|
indents []int // The stack of indentation levels.
|
||||||
|
|
||||||
|
tag_directives []yaml_tag_directive_t // The list of tag directives.
|
||||||
|
|
||||||
|
indent int // The current indentation level.
|
||||||
|
|
||||||
|
compact_sequence_indent bool // Is '- ' is considered part of the indentation for sequence elements?
|
||||||
|
|
||||||
|
flow_level int // The current flow level.
|
||||||
|
|
||||||
|
root_context bool // Is it the document root context?
|
||||||
|
sequence_context bool // Is it a sequence context?
|
||||||
|
mapping_context bool // Is it a mapping context?
|
||||||
|
simple_key_context bool // Is it a simple mapping key context?
|
||||||
|
|
||||||
|
line int // The current line.
|
||||||
|
column int // The current column.
|
||||||
|
whitespace bool // If the last character was a whitespace?
|
||||||
|
indention bool // If the last character was an indentation character (' ', '-', '?', ':')?
|
||||||
|
open_ended bool // If an explicit document end is required?
|
||||||
|
|
||||||
|
space_above bool // Is there's an empty line above?
|
||||||
|
foot_indent int // The indent used to write the foot comment above, or -1 if none.
|
||||||
|
|
||||||
|
// Anchor analysis.
|
||||||
|
anchor_data struct {
|
||||||
|
anchor []byte // The anchor value.
|
||||||
|
alias bool // Is it an alias?
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tag analysis.
|
||||||
|
tag_data struct {
|
||||||
|
handle []byte // The tag handle.
|
||||||
|
suffix []byte // The tag suffix.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scalar analysis.
|
||||||
|
scalar_data struct {
|
||||||
|
value []byte // The scalar value.
|
||||||
|
multiline bool // Does the scalar contain line breaks?
|
||||||
|
flow_plain_allowed bool // Can the scalar be expessed in the flow plain style?
|
||||||
|
block_plain_allowed bool // Can the scalar be expressed in the block plain style?
|
||||||
|
single_quoted_allowed bool // Can the scalar be expressed in the single quoted style?
|
||||||
|
block_allowed bool // Can the scalar be expressed in the literal or folded styles?
|
||||||
|
style yaml_scalar_style_t // The output style.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comments
|
||||||
|
head_comment []byte
|
||||||
|
line_comment []byte
|
||||||
|
foot_comment []byte
|
||||||
|
tail_comment []byte
|
||||||
|
|
||||||
|
key_line_comment []byte
|
||||||
|
|
||||||
|
// Dumper stuff
|
||||||
|
|
||||||
|
opened bool // If the stream was already opened?
|
||||||
|
closed bool // If the stream was already closed?
|
||||||
|
|
||||||
|
// The information associated with the document nodes.
|
||||||
|
anchors *struct {
|
||||||
|
references int // The number of references.
|
||||||
|
anchor int // The anchor id.
|
||||||
|
serialized bool // If the node has been emitted?
|
||||||
|
}
|
||||||
|
|
||||||
|
last_anchor_id int // The last assigned anchor id.
|
||||||
|
|
||||||
|
document *yaml_document_t // The currently emitted document.
|
||||||
|
}
|
||||||
198
vendor/go.yaml.in/yaml/v3/yamlprivateh.go
generated
vendored
Normal file
198
vendor/go.yaml.in/yaml/v3/yamlprivateh.go
generated
vendored
Normal file
|
|
@ -0,0 +1,198 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
const (
|
||||||
|
// The size of the input raw buffer.
|
||||||
|
input_raw_buffer_size = 512
|
||||||
|
|
||||||
|
// The size of the input buffer.
|
||||||
|
// It should be possible to decode the whole raw buffer.
|
||||||
|
input_buffer_size = input_raw_buffer_size * 3
|
||||||
|
|
||||||
|
// The size of the output buffer.
|
||||||
|
output_buffer_size = 128
|
||||||
|
|
||||||
|
// The size of the output raw buffer.
|
||||||
|
// It should be possible to encode the whole output buffer.
|
||||||
|
output_raw_buffer_size = (output_buffer_size*2 + 2)
|
||||||
|
|
||||||
|
// The size of other stacks and queues.
|
||||||
|
initial_stack_size = 16
|
||||||
|
initial_queue_size = 16
|
||||||
|
initial_string_size = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check if the character at the specified position is an alphabetical
|
||||||
|
// character, a digit, '_', or '-'.
|
||||||
|
func is_alpha(b []byte, i int) bool {
|
||||||
|
return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is a digit.
|
||||||
|
func is_digit(b []byte, i int) bool {
|
||||||
|
return b[i] >= '0' && b[i] <= '9'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the value of a digit.
|
||||||
|
func as_digit(b []byte, i int) int {
|
||||||
|
return int(b[i]) - '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is a hex-digit.
|
||||||
|
func is_hex(b []byte, i int) bool {
|
||||||
|
return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the value of a hex-digit.
|
||||||
|
func as_hex(b []byte, i int) int {
|
||||||
|
bi := b[i]
|
||||||
|
if bi >= 'A' && bi <= 'F' {
|
||||||
|
return int(bi) - 'A' + 10
|
||||||
|
}
|
||||||
|
if bi >= 'a' && bi <= 'f' {
|
||||||
|
return int(bi) - 'a' + 10
|
||||||
|
}
|
||||||
|
return int(bi) - '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is ASCII.
|
||||||
|
func is_ascii(b []byte, i int) bool {
|
||||||
|
return b[i] <= 0x7F
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the start of the buffer can be printed unescaped.
|
||||||
|
func is_printable(b []byte, i int) bool {
|
||||||
|
return ((b[i] == 0x0A) || // . == #x0A
|
||||||
|
(b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
|
||||||
|
(b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
|
||||||
|
(b[i] > 0xC2 && b[i] < 0xED) ||
|
||||||
|
(b[i] == 0xED && b[i+1] < 0xA0) ||
|
||||||
|
(b[i] == 0xEE) ||
|
||||||
|
(b[i] == 0xEF && // #xE000 <= . <= #xFFFD
|
||||||
|
!(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
|
||||||
|
!(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is NUL.
|
||||||
|
func is_z(b []byte, i int) bool {
|
||||||
|
return b[i] == 0x00
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the beginning of the buffer is a BOM.
|
||||||
|
func is_bom(b []byte, i int) bool {
|
||||||
|
return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is space.
|
||||||
|
func is_space(b []byte, i int) bool {
|
||||||
|
return b[i] == ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is tab.
|
||||||
|
func is_tab(b []byte, i int) bool {
|
||||||
|
return b[i] == '\t'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is blank (space or tab).
|
||||||
|
func is_blank(b []byte, i int) bool {
|
||||||
|
//return is_space(b, i) || is_tab(b, i)
|
||||||
|
return b[i] == ' ' || b[i] == '\t'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is a line break.
|
||||||
|
func is_break(b []byte, i int) bool {
|
||||||
|
return (b[i] == '\r' || // CR (#xD)
|
||||||
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
|
||||||
|
}
|
||||||
|
|
||||||
|
func is_crlf(b []byte, i int) bool {
|
||||||
|
return b[i] == '\r' && b[i+1] == '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is a line break or NUL.
|
||||||
|
func is_breakz(b []byte, i int) bool {
|
||||||
|
//return is_break(b, i) || is_z(b, i)
|
||||||
|
return (
|
||||||
|
// is_break:
|
||||||
|
b[i] == '\r' || // CR (#xD)
|
||||||
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||||
|
// is_z:
|
||||||
|
b[i] == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is a line break, space, or NUL.
|
||||||
|
func is_spacez(b []byte, i int) bool {
|
||||||
|
//return is_space(b, i) || is_breakz(b, i)
|
||||||
|
return (
|
||||||
|
// is_space:
|
||||||
|
b[i] == ' ' ||
|
||||||
|
// is_breakz:
|
||||||
|
b[i] == '\r' || // CR (#xD)
|
||||||
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||||
|
b[i] == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is a line break, space, tab, or NUL.
|
||||||
|
func is_blankz(b []byte, i int) bool {
|
||||||
|
//return is_blank(b, i) || is_breakz(b, i)
|
||||||
|
return (
|
||||||
|
// is_blank:
|
||||||
|
b[i] == ' ' || b[i] == '\t' ||
|
||||||
|
// is_breakz:
|
||||||
|
b[i] == '\r' || // CR (#xD)
|
||||||
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||||
|
b[i] == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the width of the character.
|
||||||
|
func width(b byte) int {
|
||||||
|
// Don't replace these by a switch without first
|
||||||
|
// confirming that it is being inlined.
|
||||||
|
if b&0x80 == 0x00 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if b&0xE0 == 0xC0 {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
if b&0xF0 == 0xE0 {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
if b&0xF8 == 0xF0 {
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
|
||||||
|
}
|
||||||
4
vendor/golang.org/x/crypto/acme/rfc8555.go
generated
vendored
4
vendor/golang.org/x/crypto/acme/rfc8555.go
generated
vendored
|
|
@ -272,7 +272,7 @@ func (c *Client) WaitOrder(ctx context.Context, url string) (*Order, error) {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
// Skip and retry.
|
// Skip and retry.
|
||||||
case o.Status == StatusInvalid:
|
case o.Status == StatusInvalid:
|
||||||
return nil, &OrderError{OrderURL: o.URI, Status: o.Status}
|
return nil, &OrderError{OrderURL: o.URI, Status: o.Status, Problem: o.Error}
|
||||||
case o.Status == StatusReady || o.Status == StatusValid:
|
case o.Status == StatusReady || o.Status == StatusValid:
|
||||||
return o, nil
|
return o, nil
|
||||||
}
|
}
|
||||||
|
|
@ -369,7 +369,7 @@ func (c *Client) CreateOrderCert(ctx context.Context, url string, csr []byte, bu
|
||||||
}
|
}
|
||||||
// The only acceptable status post finalize and WaitOrder is "valid".
|
// The only acceptable status post finalize and WaitOrder is "valid".
|
||||||
if o.Status != StatusValid {
|
if o.Status != StatusValid {
|
||||||
return nil, "", &OrderError{OrderURL: o.URI, Status: o.Status}
|
return nil, "", &OrderError{OrderURL: o.URI, Status: o.Status, Problem: o.Error}
|
||||||
}
|
}
|
||||||
crt, err := c.fetchCertRFC(ctx, o.CertURL, bundle)
|
crt, err := c.fetchCertRFC(ctx, o.CertURL, bundle)
|
||||||
return crt, o.CertURL, err
|
return crt, o.CertURL, err
|
||||||
|
|
|
||||||
5
vendor/golang.org/x/crypto/acme/types.go
generated
vendored
5
vendor/golang.org/x/crypto/acme/types.go
generated
vendored
|
|
@ -154,13 +154,16 @@ func (a *AuthorizationError) Error() string {
|
||||||
|
|
||||||
// OrderError is returned from Client's order related methods.
|
// OrderError is returned from Client's order related methods.
|
||||||
// It indicates the order is unusable and the clients should start over with
|
// It indicates the order is unusable and the clients should start over with
|
||||||
// AuthorizeOrder.
|
// AuthorizeOrder. A Problem description may be provided with details on
|
||||||
|
// what caused the order to become unusable.
|
||||||
//
|
//
|
||||||
// The clients can still fetch the order object from CA using GetOrder
|
// The clients can still fetch the order object from CA using GetOrder
|
||||||
// to inspect its state.
|
// to inspect its state.
|
||||||
type OrderError struct {
|
type OrderError struct {
|
||||||
OrderURL string
|
OrderURL string
|
||||||
Status string
|
Status string
|
||||||
|
// Problem is the error that occurred while processing the order.
|
||||||
|
Problem *Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (oe *OrderError) Error() string {
|
func (oe *OrderError) Error() string {
|
||||||
|
|
|
||||||
2
vendor/golang.org/x/crypto/curve25519/curve25519.go
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/curve25519.go
generated
vendored
|
|
@ -36,7 +36,7 @@ func ScalarBaseMult(dst, scalar *[32]byte) {
|
||||||
curve := ecdh.X25519()
|
curve := ecdh.X25519()
|
||||||
priv, err := curve.NewPrivateKey(scalar[:])
|
priv, err := curve.NewPrivateKey(scalar[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("curve25519: internal error: scalarBaseMult was not 32 bytes")
|
panic("curve25519: " + err.Error())
|
||||||
}
|
}
|
||||||
copy(dst[:], priv.PublicKey().Bytes())
|
copy(dst[:], priv.PublicKey().Bytes())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
|
|
@ -83,6 +83,7 @@ var (
|
||||||
// supportedKexAlgos specifies key-exchange algorithms implemented by this
|
// supportedKexAlgos specifies key-exchange algorithms implemented by this
|
||||||
// package in preference order, excluding those with security issues.
|
// package in preference order, excluding those with security issues.
|
||||||
supportedKexAlgos = []string{
|
supportedKexAlgos = []string{
|
||||||
|
KeyExchangeMLKEM768X25519,
|
||||||
KeyExchangeCurve25519,
|
KeyExchangeCurve25519,
|
||||||
KeyExchangeECDHP256,
|
KeyExchangeECDHP256,
|
||||||
KeyExchangeECDHP384,
|
KeyExchangeECDHP384,
|
||||||
|
|
@ -94,6 +95,7 @@ var (
|
||||||
// defaultKexAlgos specifies the default preference for key-exchange
|
// defaultKexAlgos specifies the default preference for key-exchange
|
||||||
// algorithms in preference order.
|
// algorithms in preference order.
|
||||||
defaultKexAlgos = []string{
|
defaultKexAlgos = []string{
|
||||||
|
KeyExchangeMLKEM768X25519,
|
||||||
KeyExchangeCurve25519,
|
KeyExchangeCurve25519,
|
||||||
KeyExchangeECDHP256,
|
KeyExchangeECDHP256,
|
||||||
KeyExchangeECDHP384,
|
KeyExchangeECDHP384,
|
||||||
|
|
|
||||||
32
vendor/golang.org/x/crypto/ssh/kex.go
generated
vendored
32
vendor/golang.org/x/crypto/ssh/kex.go
generated
vendored
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/subtle"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -439,6 +438,7 @@ func init() {
|
||||||
kexAlgoMap[keyExchangeCurve25519LibSSH] = &curve25519sha256{}
|
kexAlgoMap[keyExchangeCurve25519LibSSH] = &curve25519sha256{}
|
||||||
kexAlgoMap[InsecureKeyExchangeDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
|
kexAlgoMap[InsecureKeyExchangeDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
|
||||||
kexAlgoMap[KeyExchangeDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
|
kexAlgoMap[KeyExchangeDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
|
||||||
|
kexAlgoMap[KeyExchangeMLKEM768X25519] = &mlkem768WithCurve25519sha256{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// curve25519sha256 implements the curve25519-sha256 (formerly known as
|
// curve25519sha256 implements the curve25519-sha256 (formerly known as
|
||||||
|
|
@ -454,15 +454,17 @@ func (kp *curve25519KeyPair) generate(rand io.Reader) error {
|
||||||
if _, err := io.ReadFull(rand, kp.priv[:]); err != nil {
|
if _, err := io.ReadFull(rand, kp.priv[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
curve25519.ScalarBaseMult(&kp.pub, &kp.priv)
|
p, err := curve25519.X25519(kp.priv[:], curve25519.Basepoint)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("curve25519: %w", err)
|
||||||
|
}
|
||||||
|
if len(p) != 32 {
|
||||||
|
return fmt.Errorf("curve25519: internal error: X25519 returned %d bytes, expected 32", len(p))
|
||||||
|
}
|
||||||
|
copy(kp.pub[:], p)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// curve25519Zeros is just an array of 32 zero bytes so that we have something
|
|
||||||
// convenient to compare against in order to reject curve25519 points with the
|
|
||||||
// wrong order.
|
|
||||||
var curve25519Zeros [32]byte
|
|
||||||
|
|
||||||
func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
|
func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
|
||||||
var kp curve25519KeyPair
|
var kp curve25519KeyPair
|
||||||
if err := kp.generate(rand); err != nil {
|
if err := kp.generate(rand); err != nil {
|
||||||
|
|
@ -485,11 +487,9 @@ func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handsh
|
||||||
return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
|
return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
|
||||||
}
|
}
|
||||||
|
|
||||||
var servPub, secret [32]byte
|
secret, err := curve25519.X25519(kp.priv[:], reply.EphemeralPubKey)
|
||||||
copy(servPub[:], reply.EphemeralPubKey)
|
if err != nil {
|
||||||
curve25519.ScalarMult(&secret, &kp.priv, &servPub)
|
return nil, fmt.Errorf("ssh: peer's curve25519 public value is not valid: %w", err)
|
||||||
if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
|
|
||||||
return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h := crypto.SHA256.New()
|
h := crypto.SHA256.New()
|
||||||
|
|
@ -531,11 +531,9 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var clientPub, secret [32]byte
|
secret, err := curve25519.X25519(kp.priv[:], kexInit.ClientPubKey)
|
||||||
copy(clientPub[:], kexInit.ClientPubKey)
|
if err != nil {
|
||||||
curve25519.ScalarMult(&secret, &kp.priv, &clientPub)
|
return nil, fmt.Errorf("ssh: peer's curve25519 public value is not valid: %w", err)
|
||||||
if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
|
|
||||||
return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hostKeyBytes := priv.PublicKey().Marshal()
|
hostKeyBytes := priv.PublicKey().Marshal()
|
||||||
|
|
|
||||||
15
vendor/golang.org/x/crypto/ssh/mlkem.go
generated
vendored
15
vendor/golang.org/x/crypto/ssh/mlkem.go
generated
vendored
|
|
@ -2,8 +2,6 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build go1.24
|
|
||||||
|
|
||||||
package ssh
|
package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -13,23 +11,10 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"runtime"
|
|
||||||
"slices"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/curve25519"
|
"golang.org/x/crypto/curve25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
// After Go 1.24rc1 mlkem swapped the order of return values of Encapsulate.
|
|
||||||
// See #70950.
|
|
||||||
if runtime.Version() == "go1.24rc1" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
supportedKexAlgos = slices.Insert(supportedKexAlgos, 0, KeyExchangeMLKEM768X25519)
|
|
||||||
defaultKexAlgos = slices.Insert(defaultKexAlgos, 0, KeyExchangeMLKEM768X25519)
|
|
||||||
kexAlgoMap[KeyExchangeMLKEM768X25519] = &mlkem768WithCurve25519sha256{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mlkem768WithCurve25519sha256 implements the hybrid ML-KEM768 with
|
// mlkem768WithCurve25519sha256 implements the hybrid ML-KEM768 with
|
||||||
// curve25519-sha256 key exchange method, as described by
|
// curve25519-sha256 key exchange method, as described by
|
||||||
// draft-kampanakis-curdle-ssh-pq-ke-05 section 2.3.3.
|
// draft-kampanakis-curdle-ssh-pq-ke-05 section 2.3.3.
|
||||||
|
|
|
||||||
41
vendor/modules.txt
vendored
41
vendor/modules.txt
vendored
|
|
@ -247,7 +247,7 @@ codeberg.org/gruf/go-fastcopy
|
||||||
# codeberg.org/gruf/go-fastpath/v2 v2.0.0
|
# codeberg.org/gruf/go-fastpath/v2 v2.0.0
|
||||||
## explicit; go 1.14
|
## explicit; go 1.14
|
||||||
codeberg.org/gruf/go-fastpath/v2
|
codeberg.org/gruf/go-fastpath/v2
|
||||||
# codeberg.org/gruf/go-ffmpreg v0.6.10
|
# codeberg.org/gruf/go-ffmpreg v0.6.11
|
||||||
## explicit; go 1.22.0
|
## explicit; go 1.22.0
|
||||||
codeberg.org/gruf/go-ffmpreg/embed
|
codeberg.org/gruf/go-ffmpreg/embed
|
||||||
codeberg.org/gruf/go-ffmpreg/wasm
|
codeberg.org/gruf/go-ffmpreg/wasm
|
||||||
|
|
@ -420,7 +420,7 @@ github.com/dustin/go-humanize
|
||||||
# github.com/felixge/httpsnoop v1.0.4
|
# github.com/felixge/httpsnoop v1.0.4
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/felixge/httpsnoop
|
github.com/felixge/httpsnoop
|
||||||
# github.com/fsnotify/fsnotify v1.8.0
|
# github.com/fsnotify/fsnotify v1.9.0
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
github.com/fsnotify/fsnotify
|
github.com/fsnotify/fsnotify
|
||||||
github.com/fsnotify/fsnotify/internal
|
github.com/fsnotify/fsnotify/internal
|
||||||
|
|
@ -537,7 +537,7 @@ github.com/go-swagger/go-swagger/cmd/swagger/commands/generate
|
||||||
github.com/go-swagger/go-swagger/cmd/swagger/commands/initcmd
|
github.com/go-swagger/go-swagger/cmd/swagger/commands/initcmd
|
||||||
github.com/go-swagger/go-swagger/codescan
|
github.com/go-swagger/go-swagger/codescan
|
||||||
github.com/go-swagger/go-swagger/generator
|
github.com/go-swagger/go-swagger/generator
|
||||||
# github.com/go-viper/mapstructure/v2 v2.2.1
|
# github.com/go-viper/mapstructure/v2 v2.4.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
github.com/go-viper/mapstructure/v2
|
github.com/go-viper/mapstructure/v2
|
||||||
github.com/go-viper/mapstructure/v2/internal/errors
|
github.com/go-viper/mapstructure/v2/internal/errors
|
||||||
|
|
@ -814,24 +814,23 @@ github.com/rogpeppe/go-internal/fmtsort
|
||||||
# github.com/rs/xid v1.6.0
|
# github.com/rs/xid v1.6.0
|
||||||
## explicit; go 1.16
|
## explicit; go 1.16
|
||||||
github.com/rs/xid
|
github.com/rs/xid
|
||||||
# github.com/sagikazarmark/locafero v0.7.0
|
# github.com/sagikazarmark/locafero v0.11.0
|
||||||
## explicit; go 1.21
|
## explicit; go 1.23.0
|
||||||
github.com/sagikazarmark/locafero
|
github.com/sagikazarmark/locafero
|
||||||
# github.com/shopspring/decimal v1.3.1
|
# github.com/shopspring/decimal v1.3.1
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/shopspring/decimal
|
github.com/shopspring/decimal
|
||||||
# github.com/sourcegraph/conc v0.3.0
|
# github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8
|
||||||
## explicit; go 1.19
|
## explicit; go 1.20
|
||||||
github.com/sourcegraph/conc
|
github.com/sourcegraph/conc
|
||||||
github.com/sourcegraph/conc/internal/multierror
|
|
||||||
github.com/sourcegraph/conc/iter
|
|
||||||
github.com/sourcegraph/conc/panics
|
github.com/sourcegraph/conc/panics
|
||||||
# github.com/spf13/afero v1.12.0
|
github.com/sourcegraph/conc/pool
|
||||||
## explicit; go 1.21
|
# github.com/spf13/afero v1.15.0
|
||||||
|
## explicit; go 1.23.0
|
||||||
github.com/spf13/afero
|
github.com/spf13/afero
|
||||||
github.com/spf13/afero/internal/common
|
github.com/spf13/afero/internal/common
|
||||||
github.com/spf13/afero/mem
|
github.com/spf13/afero/mem
|
||||||
# github.com/spf13/cast v1.9.2
|
# github.com/spf13/cast v1.10.0
|
||||||
## explicit; go 1.21.0
|
## explicit; go 1.21.0
|
||||||
github.com/spf13/cast
|
github.com/spf13/cast
|
||||||
github.com/spf13/cast/internal
|
github.com/spf13/cast/internal
|
||||||
|
|
@ -841,8 +840,8 @@ github.com/spf13/cobra
|
||||||
# github.com/spf13/pflag v1.0.10
|
# github.com/spf13/pflag v1.0.10
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/spf13/pflag
|
github.com/spf13/pflag
|
||||||
# github.com/spf13/viper v1.20.1
|
# github.com/spf13/viper v1.21.0
|
||||||
## explicit; go 1.21.0
|
## explicit; go 1.23.0
|
||||||
github.com/spf13/viper
|
github.com/spf13/viper
|
||||||
github.com/spf13/viper/internal/encoding/dotenv
|
github.com/spf13/viper/internal/encoding/dotenv
|
||||||
github.com/spf13/viper/internal/encoding/json
|
github.com/spf13/viper/internal/encoding/json
|
||||||
|
|
@ -1154,14 +1153,14 @@ go.opentelemetry.io/proto/otlp/trace/v1
|
||||||
go.uber.org/automaxprocs/internal/cgroups
|
go.uber.org/automaxprocs/internal/cgroups
|
||||||
go.uber.org/automaxprocs/internal/runtime
|
go.uber.org/automaxprocs/internal/runtime
|
||||||
go.uber.org/automaxprocs/maxprocs
|
go.uber.org/automaxprocs/maxprocs
|
||||||
# go.uber.org/multierr v1.11.0
|
# go.yaml.in/yaml/v3 v3.0.4
|
||||||
## explicit; go 1.19
|
## explicit; go 1.16
|
||||||
go.uber.org/multierr
|
go.yaml.in/yaml/v3
|
||||||
# golang.org/x/arch v0.18.0
|
# golang.org/x/arch v0.18.0
|
||||||
## explicit; go 1.23.0
|
## explicit; go 1.23.0
|
||||||
golang.org/x/arch/x86/x86asm
|
golang.org/x/arch/x86/x86asm
|
||||||
# golang.org/x/crypto v0.41.0
|
# golang.org/x/crypto v0.42.0
|
||||||
## explicit; go 1.23.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/crypto/acme
|
golang.org/x/crypto/acme
|
||||||
golang.org/x/crypto/acme/autocert
|
golang.org/x/crypto/acme/autocert
|
||||||
golang.org/x/crypto/argon2
|
golang.org/x/crypto/argon2
|
||||||
|
|
@ -1184,8 +1183,8 @@ golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
|
||||||
# golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
|
# golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
|
||||||
## explicit; go 1.23.0
|
## explicit; go 1.23.0
|
||||||
golang.org/x/exp/constraints
|
golang.org/x/exp/constraints
|
||||||
# golang.org/x/image v0.30.0
|
# golang.org/x/image v0.31.0
|
||||||
## explicit; go 1.23.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/image/riff
|
golang.org/x/image/riff
|
||||||
golang.org/x/image/vp8
|
golang.org/x/image/vp8
|
||||||
golang.org/x/image/vp8l
|
golang.org/x/image/vp8l
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue