mirror of
https://github.com/NotAShelf/catApi.git
synced 2025-12-11 22:54:08 +00:00
bump dependencies
This commit is contained in:
parent
bae551520a
commit
b7319e6bfc
466 changed files with 17912 additions and 12742 deletions
31
go.mod
31
go.mod
|
|
@ -1,33 +1,34 @@
|
||||||
module notashelf.dev/catApi
|
module notashelf.dev/catApi
|
||||||
|
|
||||||
go 1.20
|
go 1.22.0
|
||||||
|
|
||||||
|
toolchain go1.23.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/spf13/viper v1.17.0
|
github.com/spf13/viper v1.19.0
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.10.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/magiconair/properties v1.8.9 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
github.com/sagikazarmark/locafero v0.7.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
github.com/spf13/afero v1.10.0 // indirect
|
github.com/spf13/afero v1.12.0 // indirect
|
||||||
github.com/spf13/cast v1.5.1 // indirect
|
github.com/spf13/cast v1.7.1 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.6 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
go.uber.org/atomic v1.9.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/multierr v1.9.0 // indirect
|
golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
golang.org/x/sys v0.30.0 // indirect
|
||||||
golang.org/x/sys v0.12.0 // indirect
|
golang.org/x/text v0.22.0 // indirect
|
||||||
golang.org/x/text v0.13.0 // indirect
|
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
498
go.sum
498
go.sum
|
|
@ -1,496 +1,66 @@
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
|
||||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
|
||||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
|
||||||
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
|
||||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
|
||||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
|
||||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
|
||||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
|
||||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
|
||||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
|
||||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
|
||||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
|
||||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
|
||||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
|
||||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
|
||||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
|
||||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
|
||||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
|
||||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
|
||||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
|
||||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
|
||||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
|
||||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
|
||||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
|
||||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
|
||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
|
||||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
|
||||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
|
||||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
|
||||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
|
||||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
|
||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
|
||||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
|
||||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
|
||||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
|
||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
|
||||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
|
||||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
|
||||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
|
||||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
|
||||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
|
||||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
|
||||||
|
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
|
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
|
||||||
|
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||||
github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
|
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
|
||||||
github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
|
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
|
||||||
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
|
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||||
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
|
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
|
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||||
github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
|
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||||
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.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3 h1:qNgPs5exUA+G0C96DrPwNrvLSj7GT/9D+3WMWUcUg34=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|
||||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|
||||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
|
||||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
|
||||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
|
||||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
|
||||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
|
||||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
|
||||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
|
||||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
|
||||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
|
||||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
|
||||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
|
||||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
|
||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
|
||||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
||||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
|
||||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
|
||||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|
||||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
|
||||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
|
||||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
|
||||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
|
||||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
|
||||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
|
||||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
|
||||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
|
||||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
|
||||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
|
||||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
|
||||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
|
||||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
|
||||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
|
||||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
|
||||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
|
||||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
|
||||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
|
||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
|
||||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
|
||||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
|
||||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
|
||||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
|
||||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
|
||||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
|
||||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
|
||||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
|
||||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
|
||||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
|
||||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
|
||||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
|
||||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
|
||||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
|
||||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
|
||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
|
||||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
|
||||||
|
|
|
||||||
14
vendor/github.com/fsnotify/fsnotify/.cirrus.yml
generated
vendored
Normal file
14
vendor/github.com/fsnotify/fsnotify/.cirrus.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
freebsd_task:
|
||||||
|
name: 'FreeBSD'
|
||||||
|
freebsd_instance:
|
||||||
|
image_family: freebsd-14-1
|
||||||
|
install_script:
|
||||||
|
- pkg update -f
|
||||||
|
- pkg install -y go
|
||||||
|
test_script:
|
||||||
|
# run tests as user "cirrus" instead of root
|
||||||
|
- pw useradd cirrus -m
|
||||||
|
- chown -R cirrus:cirrus .
|
||||||
|
- FSNOTIFY_BUFFER=4096 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./...
|
||||||
|
- sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./...
|
||||||
|
- FSNOTIFY_DEBUG=1 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race -v ./...
|
||||||
1
vendor/github.com/fsnotify/fsnotify/.gitattributes
generated
vendored
1
vendor/github.com/fsnotify/fsnotify/.gitattributes
generated
vendored
|
|
@ -1 +0,0 @@
|
||||||
go.sum linguist-generated
|
|
||||||
4
vendor/github.com/fsnotify/fsnotify/.gitignore
generated
vendored
4
vendor/github.com/fsnotify/fsnotify/.gitignore
generated
vendored
|
|
@ -4,3 +4,7 @@
|
||||||
|
|
||||||
# Output of go build ./cmd/fsnotify
|
# Output of go build ./cmd/fsnotify
|
||||||
/fsnotify
|
/fsnotify
|
||||||
|
/fsnotify.exe
|
||||||
|
|
||||||
|
/test/kqueue
|
||||||
|
/test/a.out
|
||||||
|
|
|
||||||
111
vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
generated
vendored
111
vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
generated
vendored
|
|
@ -1,16 +1,115 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
1.8.0 2023-10-31
|
||||||
|
----------------
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
### Additions
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
||||||
|
|
||||||
## [Unreleased]
|
- all: add `FSNOTIFY_DEBUG` to print debug logs to stderr ([#619])
|
||||||
|
|
||||||
Nothing yet.
|
### Changes and fixes
|
||||||
|
|
||||||
## [1.6.0] - 2022-10-13
|
- windows: fix behaviour of `WatchList()` to be consistent with other platforms ([#610])
|
||||||
|
|
||||||
|
- kqueue: ignore events with Ident=0 ([#590])
|
||||||
|
|
||||||
|
- kqueue: set O_CLOEXEC to prevent passing file descriptors to children ([#617])
|
||||||
|
|
||||||
|
- kqueue: emit events as "/path/dir/file" instead of "path/link/file" when watching a symlink ([#625])
|
||||||
|
|
||||||
|
- inotify: don't send event for IN_DELETE_SELF when also watching the parent ([#620])
|
||||||
|
|
||||||
|
- inotify: fix panic when calling Remove() in a goroutine ([#650])
|
||||||
|
|
||||||
|
- fen: allow watching subdirectories of watched directories ([#621])
|
||||||
|
|
||||||
|
[#590]: https://github.com/fsnotify/fsnotify/pull/590
|
||||||
|
[#610]: https://github.com/fsnotify/fsnotify/pull/610
|
||||||
|
[#617]: https://github.com/fsnotify/fsnotify/pull/617
|
||||||
|
[#619]: https://github.com/fsnotify/fsnotify/pull/619
|
||||||
|
[#620]: https://github.com/fsnotify/fsnotify/pull/620
|
||||||
|
[#621]: https://github.com/fsnotify/fsnotify/pull/621
|
||||||
|
[#625]: https://github.com/fsnotify/fsnotify/pull/625
|
||||||
|
[#650]: https://github.com/fsnotify/fsnotify/pull/650
|
||||||
|
|
||||||
|
1.7.0 - 2023-10-22
|
||||||
|
------------------
|
||||||
|
This version of fsnotify needs Go 1.17.
|
||||||
|
|
||||||
|
### Additions
|
||||||
|
|
||||||
|
- illumos: add FEN backend to support illumos and Solaris. ([#371])
|
||||||
|
|
||||||
|
- all: add `NewBufferedWatcher()` to use a buffered channel, which can be useful
|
||||||
|
in cases where you can't control the kernel buffer and receive a large number
|
||||||
|
of events in bursts. ([#550], [#572])
|
||||||
|
|
||||||
|
- all: add `AddWith()`, which is identical to `Add()` but allows passing
|
||||||
|
options. ([#521])
|
||||||
|
|
||||||
|
- windows: allow setting the ReadDirectoryChangesW() buffer size with
|
||||||
|
`fsnotify.WithBufferSize()`; the default of 64K is the highest value that
|
||||||
|
works on all platforms and is enough for most purposes, but in some cases a
|
||||||
|
highest buffer is needed. ([#521])
|
||||||
|
|
||||||
|
### Changes and fixes
|
||||||
|
|
||||||
|
- inotify: remove watcher if a watched path is renamed ([#518])
|
||||||
|
|
||||||
|
After a rename the reported name wasn't updated, or even an empty string.
|
||||||
|
Inotify doesn't provide any good facilities to update it, so just remove the
|
||||||
|
watcher. This is already how it worked on kqueue and FEN.
|
||||||
|
|
||||||
|
On Windows this does work, and remains working.
|
||||||
|
|
||||||
|
- windows: don't listen for file attribute changes ([#520])
|
||||||
|
|
||||||
|
File attribute changes are sent as `FILE_ACTION_MODIFIED` by the Windows API,
|
||||||
|
with no way to see if they're a file write or attribute change, so would show
|
||||||
|
up as a fsnotify.Write event. This is never useful, and could result in many
|
||||||
|
spurious Write events.
|
||||||
|
|
||||||
|
- windows: return `ErrEventOverflow` if the buffer is full ([#525])
|
||||||
|
|
||||||
|
Before it would merely return "short read", making it hard to detect this
|
||||||
|
error.
|
||||||
|
|
||||||
|
- kqueue: make sure events for all files are delivered properly when removing a
|
||||||
|
watched directory ([#526])
|
||||||
|
|
||||||
|
Previously they would get sent with `""` (empty string) or `"."` as the path
|
||||||
|
name.
|
||||||
|
|
||||||
|
- kqueue: don't emit spurious Create events for symbolic links ([#524])
|
||||||
|
|
||||||
|
The link would get resolved but kqueue would "forget" it already saw the link
|
||||||
|
itself, resulting on a Create for every Write event for the directory.
|
||||||
|
|
||||||
|
- all: return `ErrClosed` on `Add()` when the watcher is closed ([#516])
|
||||||
|
|
||||||
|
- other: add `Watcher.Errors` and `Watcher.Events` to the no-op `Watcher` in
|
||||||
|
`backend_other.go`, making it easier to use on unsupported platforms such as
|
||||||
|
WASM, AIX, etc. ([#528])
|
||||||
|
|
||||||
|
- other: use the `backend_other.go` no-op if the `appengine` build tag is set;
|
||||||
|
Google AppEngine forbids usage of the unsafe package so the inotify backend
|
||||||
|
won't compile there.
|
||||||
|
|
||||||
|
[#371]: https://github.com/fsnotify/fsnotify/pull/371
|
||||||
|
[#516]: https://github.com/fsnotify/fsnotify/pull/516
|
||||||
|
[#518]: https://github.com/fsnotify/fsnotify/pull/518
|
||||||
|
[#520]: https://github.com/fsnotify/fsnotify/pull/520
|
||||||
|
[#521]: https://github.com/fsnotify/fsnotify/pull/521
|
||||||
|
[#524]: https://github.com/fsnotify/fsnotify/pull/524
|
||||||
|
[#525]: https://github.com/fsnotify/fsnotify/pull/525
|
||||||
|
[#526]: https://github.com/fsnotify/fsnotify/pull/526
|
||||||
|
[#528]: https://github.com/fsnotify/fsnotify/pull/528
|
||||||
|
[#537]: https://github.com/fsnotify/fsnotify/pull/537
|
||||||
|
[#550]: https://github.com/fsnotify/fsnotify/pull/550
|
||||||
|
[#572]: https://github.com/fsnotify/fsnotify/pull/572
|
||||||
|
|
||||||
|
1.6.0 - 2022-10-13
|
||||||
|
------------------
|
||||||
This version of fsnotify needs Go 1.16 (this was already the case since 1.5.1,
|
This version of fsnotify needs Go 1.16 (this was already the case since 1.5.1,
|
||||||
but not documented). It also increases the minimum Linux version to 2.6.32.
|
but not documented). It also increases the minimum Linux version to 2.6.32.
|
||||||
|
|
||||||
|
|
|
||||||
120
vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
generated
vendored
120
vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
generated
vendored
|
|
@ -1,7 +1,7 @@
|
||||||
Thank you for your interest in contributing to fsnotify! We try to review and
|
Thank you for your interest in contributing to fsnotify! We try to review and
|
||||||
merge PRs in a reasonable timeframe, but please be aware that:
|
merge PRs in a reasonable timeframe, but please be aware that:
|
||||||
|
|
||||||
- To avoid "wasted" work, please discus changes on the issue tracker first. You
|
- To avoid "wasted" work, please discuss changes on the issue tracker first. You
|
||||||
can just send PRs, but they may end up being rejected for one reason or the
|
can just send PRs, but they may end up being rejected for one reason or the
|
||||||
other.
|
other.
|
||||||
|
|
||||||
|
|
@ -20,6 +20,124 @@ platforms. Testing different platforms locally can be done with something like
|
||||||
|
|
||||||
Use the `-short` flag to make the "stress test" run faster.
|
Use the `-short` flag to make the "stress test" run faster.
|
||||||
|
|
||||||
|
Writing new tests
|
||||||
|
-----------------
|
||||||
|
Scripts in the testdata directory allow creating test cases in a "shell-like"
|
||||||
|
syntax. The basic format is:
|
||||||
|
|
||||||
|
script
|
||||||
|
|
||||||
|
Output:
|
||||||
|
desired output
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
# Create a new empty file with some data.
|
||||||
|
watch /
|
||||||
|
echo data >/file
|
||||||
|
|
||||||
|
Output:
|
||||||
|
create /file
|
||||||
|
write /file
|
||||||
|
|
||||||
|
Just create a new file to add a new test; select which tests to run with
|
||||||
|
`-run TestScript/[path]`.
|
||||||
|
|
||||||
|
script
|
||||||
|
------
|
||||||
|
The script is a "shell-like" script:
|
||||||
|
|
||||||
|
cmd arg arg
|
||||||
|
|
||||||
|
Comments are supported with `#`:
|
||||||
|
|
||||||
|
# Comment
|
||||||
|
cmd arg arg # Comment
|
||||||
|
|
||||||
|
All operations are done in a temp directory; a path like "/foo" is rewritten to
|
||||||
|
"/tmp/TestFoo/foo".
|
||||||
|
|
||||||
|
Arguments can be quoted with `"` or `'`; there are no escapes and they're
|
||||||
|
functionally identical right now, but this may change in the future, so best to
|
||||||
|
assume shell-like rules.
|
||||||
|
|
||||||
|
touch "/file with spaces"
|
||||||
|
|
||||||
|
End-of-line escapes with `\` are not supported.
|
||||||
|
|
||||||
|
### Supported commands
|
||||||
|
|
||||||
|
watch path [ops] # Watch the path, reporting events for it. Nothing is
|
||||||
|
# watched by default. Optionally a list of ops can be
|
||||||
|
# given, as with AddWith(path, WithOps(...)).
|
||||||
|
unwatch path # Stop watching the path.
|
||||||
|
watchlist n # Assert watchlist length.
|
||||||
|
|
||||||
|
stop # Stop running the script; for debugging.
|
||||||
|
debug [yes/no] # Enable/disable FSNOTIFY_DEBUG (tests are run in
|
||||||
|
parallel by default, so -parallel=1 is probably a good
|
||||||
|
idea).
|
||||||
|
|
||||||
|
touch path
|
||||||
|
mkdir [-p] dir
|
||||||
|
ln -s target link # Only ln -s supported.
|
||||||
|
mkfifo path
|
||||||
|
mknod dev path
|
||||||
|
mv src dst
|
||||||
|
rm [-r] path
|
||||||
|
chmod mode path # Octal only
|
||||||
|
sleep time-in-ms
|
||||||
|
|
||||||
|
cat path # Read path (does nothing with the data; just reads it).
|
||||||
|
echo str >>path # Append "str" to "path".
|
||||||
|
echo str >path # Truncate "path" and write "str".
|
||||||
|
|
||||||
|
require reason # Skip the test if "reason" is true; "skip" and
|
||||||
|
skip reason # "require" behave identical; it supports both for
|
||||||
|
# readability. Possible reasons are:
|
||||||
|
#
|
||||||
|
# always Always skip this test.
|
||||||
|
# symlink Symlinks are supported (requires admin
|
||||||
|
# permissions on Windows).
|
||||||
|
# mkfifo Platform doesn't support FIFO named sockets.
|
||||||
|
# mknod Platform doesn't support device nodes.
|
||||||
|
|
||||||
|
|
||||||
|
output
|
||||||
|
------
|
||||||
|
After `Output:` the desired output is given; this is indented by convention, but
|
||||||
|
that's not required.
|
||||||
|
|
||||||
|
The format of that is:
|
||||||
|
|
||||||
|
# Comment
|
||||||
|
event path # Comment
|
||||||
|
|
||||||
|
system:
|
||||||
|
event path
|
||||||
|
system2:
|
||||||
|
event path
|
||||||
|
|
||||||
|
Every event is one line, and any whitespace between the event and path are
|
||||||
|
ignored. The path can optionally be surrounded in ". Anything after a "#" is
|
||||||
|
ignored.
|
||||||
|
|
||||||
|
Platform-specific tests can be added after GOOS; for example:
|
||||||
|
|
||||||
|
watch /
|
||||||
|
touch /file
|
||||||
|
|
||||||
|
Output:
|
||||||
|
# Tested if nothing else matches
|
||||||
|
create /file
|
||||||
|
|
||||||
|
# Windows-specific test.
|
||||||
|
windows:
|
||||||
|
write /file
|
||||||
|
|
||||||
|
You can specify multiple platforms with a comma (e.g. "windows, linux:").
|
||||||
|
"kqueue" is a shortcut for all kqueue systems (BSD, macOS).
|
||||||
|
|
||||||
|
|
||||||
[goon]: https://github.com/arp242/goon
|
[goon]: https://github.com/arp242/goon
|
||||||
[Vagrant]: https://www.vagrantup.com/
|
[Vagrant]: https://www.vagrantup.com/
|
||||||
|
|
|
||||||
79
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
79
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
|
|
@ -1,29 +1,31 @@
|
||||||
fsnotify is a Go library to provide cross-platform filesystem notifications on
|
fsnotify is a Go library to provide cross-platform filesystem notifications on
|
||||||
Windows, Linux, macOS, and BSD systems.
|
Windows, Linux, macOS, BSD, and illumos.
|
||||||
|
|
||||||
Go 1.16 or newer is required; the full documentation is at
|
Go 1.17 or newer is required; the full documentation is at
|
||||||
https://pkg.go.dev/github.com/fsnotify/fsnotify
|
https://pkg.go.dev/github.com/fsnotify/fsnotify
|
||||||
|
|
||||||
**It's best to read the documentation at pkg.go.dev, as it's pinned to the last
|
|
||||||
released version, whereas this README is for the last development version which
|
|
||||||
may include additions/changes.**
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Platform support:
|
Platform support:
|
||||||
|
|
||||||
| Adapter | OS | Status |
|
| Backend | OS | Status |
|
||||||
| --------------------- | ---------------| -------------------------------------------------------------|
|
| :-------------------- | :--------- | :------------------------------------------------------------------------ |
|
||||||
| inotify | Linux 2.6.32+ | Supported |
|
| inotify | Linux | Supported |
|
||||||
| kqueue | BSD, macOS | Supported |
|
| kqueue | BSD, macOS | Supported |
|
||||||
| ReadDirectoryChangesW | Windows | Supported |
|
| ReadDirectoryChangesW | Windows | Supported |
|
||||||
| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) |
|
| FEN | illumos | Supported |
|
||||||
| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/pull/371) |
|
| fanotify | Linux 5.9+ | [Not yet](https://github.com/fsnotify/fsnotify/issues/114) |
|
||||||
| fanotify | Linux 5.9+ | [Maybe](https://github.com/fsnotify/fsnotify/issues/114) |
|
| AHAFS | AIX | [aix branch]; experimental due to lack of maintainer and test environment |
|
||||||
| USN Journals | Windows | [Maybe](https://github.com/fsnotify/fsnotify/issues/53) |
|
| FSEvents | macOS | [Needs support in x/sys/unix][fsevents] |
|
||||||
| Polling | *All* | [Maybe](https://github.com/fsnotify/fsnotify/issues/9) |
|
| USN Journals | Windows | [Needs support in x/sys/windows][usn] |
|
||||||
|
| Polling | *All* | [Not yet](https://github.com/fsnotify/fsnotify/issues/9) |
|
||||||
|
|
||||||
Linux and macOS should include Android and iOS, but these are currently untested.
|
Linux and illumos should include Android and Solaris, but these are currently
|
||||||
|
untested.
|
||||||
|
|
||||||
|
[fsevents]: https://github.com/fsnotify/fsnotify/issues/11#issuecomment-1279133120
|
||||||
|
[usn]: https://github.com/fsnotify/fsnotify/issues/53#issuecomment-1279829847
|
||||||
|
[aix branch]: https://github.com/fsnotify/fsnotify/issues/353#issuecomment-1284590129
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
@ -83,20 +85,23 @@ run with:
|
||||||
|
|
||||||
% go run ./cmd/fsnotify
|
% go run ./cmd/fsnotify
|
||||||
|
|
||||||
|
Further detailed documentation can be found in godoc:
|
||||||
|
https://pkg.go.dev/github.com/fsnotify/fsnotify
|
||||||
|
|
||||||
FAQ
|
FAQ
|
||||||
---
|
---
|
||||||
### Will a file still be watched when it's moved to another directory?
|
### Will a file still be watched when it's moved to another directory?
|
||||||
No, not unless you are watching the location it was moved to.
|
No, not unless you are watching the location it was moved to.
|
||||||
|
|
||||||
### Are subdirectories watched too?
|
### Are subdirectories watched?
|
||||||
No, you must add watches for any directory you want to watch (a recursive
|
No, you must add watches for any directory you want to watch (a recursive
|
||||||
watcher is on the roadmap: [#18]).
|
watcher is on the roadmap: [#18]).
|
||||||
|
|
||||||
[#18]: https://github.com/fsnotify/fsnotify/issues/18
|
[#18]: https://github.com/fsnotify/fsnotify/issues/18
|
||||||
|
|
||||||
### Do I have to watch the Error and Event channels in a goroutine?
|
### Do I have to watch the Error and Event channels in a goroutine?
|
||||||
As of now, yes (you can read both channels in the same goroutine using `select`,
|
Yes. You can read both channels in the same goroutine using `select` (you don't
|
||||||
you don't need a separate goroutine for both channels; see the example).
|
need a separate goroutine for both channels; see the example).
|
||||||
|
|
||||||
### Why don't notifications work with NFS, SMB, FUSE, /proc, or /sys?
|
### Why don't notifications work with NFS, SMB, FUSE, /proc, or /sys?
|
||||||
fsnotify requires support from underlying OS to work. The current NFS and SMB
|
fsnotify requires support from underlying OS to work. The current NFS and SMB
|
||||||
|
|
@ -107,6 +112,32 @@ This could be fixed with a polling watcher ([#9]), but it's not yet implemented.
|
||||||
|
|
||||||
[#9]: https://github.com/fsnotify/fsnotify/issues/9
|
[#9]: https://github.com/fsnotify/fsnotify/issues/9
|
||||||
|
|
||||||
|
### Why do I get many Chmod events?
|
||||||
|
Some programs may generate a lot of attribute changes; for example Spotlight on
|
||||||
|
macOS, anti-virus programs, backup applications, and some others are known to do
|
||||||
|
this. As a rule, it's typically best to ignore Chmod events. They're often not
|
||||||
|
useful, and tend to cause problems.
|
||||||
|
|
||||||
|
Spotlight indexing on macOS can result in multiple events (see [#15]). A
|
||||||
|
temporary workaround is to add your folder(s) to the *Spotlight Privacy
|
||||||
|
settings* until we have a native FSEvents implementation (see [#11]).
|
||||||
|
|
||||||
|
[#11]: https://github.com/fsnotify/fsnotify/issues/11
|
||||||
|
[#15]: https://github.com/fsnotify/fsnotify/issues/15
|
||||||
|
|
||||||
|
### Watching a file doesn't work well
|
||||||
|
Watching individual files (rather than directories) is generally not recommended
|
||||||
|
as many programs (especially editors) update files atomically: it will write to
|
||||||
|
a temporary file which is then moved to to destination, overwriting the original
|
||||||
|
(or some variant thereof). The watcher on the original file is now lost, as that
|
||||||
|
no longer exists.
|
||||||
|
|
||||||
|
The upshot of this is that a power failure or crash won't leave a half-written
|
||||||
|
file.
|
||||||
|
|
||||||
|
Watch the parent directory and use `Event.Name` to filter out files you're not
|
||||||
|
interested in. There is an example of this in `cmd/fsnotify/file.go`.
|
||||||
|
|
||||||
Platform-specific notes
|
Platform-specific notes
|
||||||
-----------------------
|
-----------------------
|
||||||
### Linux
|
### Linux
|
||||||
|
|
@ -151,11 +182,3 @@ these platforms.
|
||||||
|
|
||||||
The sysctl variables `kern.maxfiles` and `kern.maxfilesperproc` can be used to
|
The sysctl variables `kern.maxfiles` and `kern.maxfilesperproc` can be used to
|
||||||
control the maximum number of open files.
|
control the maximum number of open files.
|
||||||
|
|
||||||
### macOS
|
|
||||||
Spotlight indexing on macOS can result in multiple events (see [#15]). A temporary
|
|
||||||
workaround is to add your folder(s) to the *Spotlight Privacy settings* until we
|
|
||||||
have a native FSEvents implementation (see [#11]).
|
|
||||||
|
|
||||||
[#11]: https://github.com/fsnotify/fsnotify/issues/11
|
|
||||||
[#15]: https://github.com/fsnotify/fsnotify/issues/15
|
|
||||||
|
|
|
||||||
602
vendor/github.com/fsnotify/fsnotify/backend_fen.go
generated
vendored
602
vendor/github.com/fsnotify/fsnotify/backend_fen.go
generated
vendored
|
|
@ -1,162 +1,484 @@
|
||||||
//go:build solaris
|
//go:build solaris
|
||||||
// +build solaris
|
|
||||||
|
// FEN backend for illumos (supported) and Solaris (untested, but should work).
|
||||||
|
//
|
||||||
|
// See port_create(3c) etc. for docs. https://www.illumos.org/man/3C/port_create
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/fsnotify/fsnotify/internal"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Watcher watches a set of paths, delivering events on a channel.
|
type fen struct {
|
||||||
//
|
|
||||||
// A watcher should not be copied (e.g. pass it by pointer, rather than by
|
|
||||||
// value).
|
|
||||||
//
|
|
||||||
// # Linux notes
|
|
||||||
//
|
|
||||||
// When a file is removed a Remove event won't be emitted until all file
|
|
||||||
// descriptors are closed, and deletes will always emit a Chmod. For example:
|
|
||||||
//
|
|
||||||
// fp := os.Open("file")
|
|
||||||
// os.Remove("file") // Triggers Chmod
|
|
||||||
// fp.Close() // Triggers Remove
|
|
||||||
//
|
|
||||||
// This is the event that inotify sends, so not much can be changed about this.
|
|
||||||
//
|
|
||||||
// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
|
|
||||||
// for the number of watches per user, and fs.inotify.max_user_instances
|
|
||||||
// specifies the maximum number of inotify instances per user. Every Watcher you
|
|
||||||
// create is an "instance", and every path you add is a "watch".
|
|
||||||
//
|
|
||||||
// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
|
|
||||||
// /proc/sys/fs/inotify/max_user_instances
|
|
||||||
//
|
|
||||||
// To increase them you can use sysctl or write the value to the /proc file:
|
|
||||||
//
|
|
||||||
// # Default values on Linux 5.18
|
|
||||||
// sysctl fs.inotify.max_user_watches=124983
|
|
||||||
// sysctl fs.inotify.max_user_instances=128
|
|
||||||
//
|
|
||||||
// To make the changes persist on reboot edit /etc/sysctl.conf or
|
|
||||||
// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
|
|
||||||
// your distro's documentation):
|
|
||||||
//
|
|
||||||
// fs.inotify.max_user_watches=124983
|
|
||||||
// fs.inotify.max_user_instances=128
|
|
||||||
//
|
|
||||||
// Reaching the limit will result in a "no space left on device" or "too many open
|
|
||||||
// files" error.
|
|
||||||
//
|
|
||||||
// # kqueue notes (macOS, BSD)
|
|
||||||
//
|
|
||||||
// kqueue requires opening a file descriptor for every file that's being watched;
|
|
||||||
// so if you're watching a directory with five files then that's six file
|
|
||||||
// descriptors. You will run in to your system's "max open files" limit faster on
|
|
||||||
// these platforms.
|
|
||||||
//
|
|
||||||
// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
|
|
||||||
// control the maximum number of open files, as well as /etc/login.conf on BSD
|
|
||||||
// systems.
|
|
||||||
//
|
|
||||||
// # macOS notes
|
|
||||||
//
|
|
||||||
// Spotlight indexing on macOS can result in multiple events (see [#15]). A
|
|
||||||
// temporary workaround is to add your folder(s) to the "Spotlight Privacy
|
|
||||||
// Settings" until we have a native FSEvents implementation (see [#11]).
|
|
||||||
//
|
|
||||||
// [#11]: https://github.com/fsnotify/fsnotify/issues/11
|
|
||||||
// [#15]: https://github.com/fsnotify/fsnotify/issues/15
|
|
||||||
type Watcher struct {
|
|
||||||
// Events sends the filesystem change events.
|
|
||||||
//
|
|
||||||
// fsnotify can send the following events; a "path" here can refer to a
|
|
||||||
// file, directory, symbolic link, or special file like a FIFO.
|
|
||||||
//
|
|
||||||
// fsnotify.Create A new path was created; this may be followed by one
|
|
||||||
// or more Write events if data also gets written to a
|
|
||||||
// file.
|
|
||||||
//
|
|
||||||
// fsnotify.Remove A path was removed.
|
|
||||||
//
|
|
||||||
// fsnotify.Rename A path was renamed. A rename is always sent with the
|
|
||||||
// old path as Event.Name, and a Create event will be
|
|
||||||
// sent with the new name. Renames are only sent for
|
|
||||||
// paths that are currently watched; e.g. moving an
|
|
||||||
// unmonitored file into a monitored directory will
|
|
||||||
// show up as just a Create. Similarly, renaming a file
|
|
||||||
// to outside a monitored directory will show up as
|
|
||||||
// only a Rename.
|
|
||||||
//
|
|
||||||
// fsnotify.Write A file or named pipe was written to. A Truncate will
|
|
||||||
// also trigger a Write. A single "write action"
|
|
||||||
// initiated by the user may show up as one or multiple
|
|
||||||
// writes, depending on when the system syncs things to
|
|
||||||
// disk. For example when compiling a large Go program
|
|
||||||
// you may get hundreds of Write events, so you
|
|
||||||
// probably want to wait until you've stopped receiving
|
|
||||||
// them (see the dedup example in cmd/fsnotify).
|
|
||||||
//
|
|
||||||
// fsnotify.Chmod Attributes were changed. On Linux this is also sent
|
|
||||||
// when a file is removed (or more accurately, when a
|
|
||||||
// link to an inode is removed). On kqueue it's sent
|
|
||||||
// and on kqueue when a file is truncated. On Windows
|
|
||||||
// it's never sent.
|
|
||||||
Events chan Event
|
Events chan Event
|
||||||
|
|
||||||
// Errors sends any errors.
|
|
||||||
Errors chan error
|
Errors chan error
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
port *unix.EventPort
|
||||||
|
done chan struct{} // Channel for sending a "quit message" to the reader goroutine
|
||||||
|
dirs map[string]Op // Explicitly watched directories
|
||||||
|
watches map[string]Op // Explicitly watched non-directories
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWatcher creates a new Watcher.
|
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||||
func NewWatcher() (*Watcher, error) {
|
return newBufferedBackend(0, ev, errs)
|
||||||
return nil, errors.New("FEN based watcher not yet supported for fsnotify\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close removes all watches and closes the events channel.
|
func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
|
||||||
func (w *Watcher) Close() error {
|
w := &fen{
|
||||||
|
Events: ev,
|
||||||
|
Errors: errs,
|
||||||
|
dirs: make(map[string]Op),
|
||||||
|
watches: make(map[string]Op),
|
||||||
|
done: make(chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
w.port, err = unix.NewEventPort()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("fsnotify.NewWatcher: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go w.readEvents()
|
||||||
|
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 {
|
||||||
|
// Take the lock used by associateFile to prevent lingering events from
|
||||||
|
// being processed after the close
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
|
if w.isClosed() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
close(w.done)
|
||||||
|
return w.port.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *fen) Add(name string) error { return w.AddWith(name) }
|
||||||
|
|
||||||
|
func (w *fen) AddWith(name string, opts ...addOpt) error {
|
||||||
|
if w.isClosed() {
|
||||||
|
return ErrClosed
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n",
|
||||||
|
time.Now().Format("15:04:05.000000000"), name)
|
||||||
|
}
|
||||||
|
|
||||||
|
with := getOptions(opts...)
|
||||||
|
if !w.xSupports(with.op) {
|
||||||
|
return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently we resolve symlinks that were explicitly requested to be
|
||||||
|
// watched. Otherwise we would use LStat here.
|
||||||
|
stat, err := os.Stat(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Associate all files in the directory.
|
||||||
|
if stat.IsDir() {
|
||||||
|
err := w.handleDirectory(name, stat, true, w.associateFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.mu.Lock()
|
||||||
|
w.dirs[name] = with.op
|
||||||
|
w.mu.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = w.associateFile(name, stat, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.mu.Lock()
|
||||||
|
w.watches[name] = with.op
|
||||||
|
w.mu.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add starts monitoring the path for changes.
|
func (w *fen) Remove(name string) error {
|
||||||
//
|
if w.isClosed() {
|
||||||
// A path can only be watched once; attempting to watch it more than once will
|
return nil
|
||||||
// return an error. Paths that do not yet exist on the filesystem cannot be
|
}
|
||||||
// added. A watch will be automatically removed if the path is deleted.
|
if !w.port.PathIsWatched(name) {
|
||||||
//
|
return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
|
||||||
// A path will remain watched if it gets renamed to somewhere else on the same
|
}
|
||||||
// filesystem, but the monitor will get removed if the path gets deleted and
|
if debug {
|
||||||
// re-created, or if it's moved to a different filesystem.
|
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n",
|
||||||
//
|
time.Now().Format("15:04:05.000000000"), name)
|
||||||
// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
|
}
|
||||||
// filesystems (/proc, /sys, etc.) generally don't work.
|
|
||||||
//
|
// The user has expressed an intent. Immediately remove this name from
|
||||||
// # Watching directories
|
// whichever watch list it might be in. If it's not in there the delete
|
||||||
//
|
// doesn't cause harm.
|
||||||
// All files in a directory are monitored, including new files that are created
|
w.mu.Lock()
|
||||||
// after the watcher is started. Subdirectories are not watched (i.e. it's
|
delete(w.watches, name)
|
||||||
// non-recursive).
|
delete(w.dirs, name)
|
||||||
//
|
w.mu.Unlock()
|
||||||
// # Watching files
|
|
||||||
//
|
stat, err := os.Stat(name)
|
||||||
// Watching individual files (rather than directories) is generally not
|
if err != nil {
|
||||||
// recommended as many tools update files atomically. Instead of "just" writing
|
return err
|
||||||
// to the file a temporary file will be written to first, and if successful the
|
}
|
||||||
// temporary file is moved to to destination removing the original, or some
|
|
||||||
// variant thereof. The watcher on the original file is now lost, as it no
|
// Remove associations for every file in the directory.
|
||||||
// longer exists.
|
if stat.IsDir() {
|
||||||
//
|
err := w.handleDirectory(name, stat, false, w.dissociateFile)
|
||||||
// Instead, watch the parent directory and use Event.Name to filter out files
|
if err != nil {
|
||||||
// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
|
return err
|
||||||
func (w *Watcher) Add(name string) error {
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = w.port.DissociatePath(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove stops monitoring the path for changes.
|
// readEvents contains the main loop that runs in a goroutine watching for events.
|
||||||
//
|
func (w *fen) readEvents() {
|
||||||
// Directories are always removed non-recursively. For example, if you added
|
// If this function returns, the watcher has been closed and we can close
|
||||||
// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
|
// these channels
|
||||||
//
|
defer func() {
|
||||||
// Removing a path that has not yet been added returns [ErrNonExistentWatch].
|
close(w.Errors)
|
||||||
func (w *Watcher) Remove(name string) error {
|
close(w.Events)
|
||||||
|
}()
|
||||||
|
|
||||||
|
pevents := make([]unix.PortEvent, 8)
|
||||||
|
for {
|
||||||
|
count, err := w.port.Get(pevents, 1, nil)
|
||||||
|
if err != nil && err != unix.ETIME {
|
||||||
|
// Interrupted system call (count should be 0) ignore and continue
|
||||||
|
if errors.Is(err, unix.EINTR) && count == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Get failed because we called w.Close()
|
||||||
|
if errors.Is(err, unix.EBADF) && w.isClosed() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// There was an error not caused by calling w.Close()
|
||||||
|
if !w.sendError(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p := pevents[:count]
|
||||||
|
for _, pevent := range p {
|
||||||
|
if pevent.Source != unix.PORT_SOURCE_FILE {
|
||||||
|
// Event from unexpected source received; should never happen.
|
||||||
|
if !w.sendError(errors.New("Event from unexpected source received")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
internal.Debug(pevent.Path, pevent.Events)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = w.handleEvent(&pevent)
|
||||||
|
if !w.sendError(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *fen) handleDirectory(path string, stat os.FileInfo, follow bool, handler func(string, os.FileInfo, bool) error) error {
|
||||||
|
files, err := os.ReadDir(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle all children of the directory.
|
||||||
|
for _, entry := range files {
|
||||||
|
finfo, err := entry.Info()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = handler(filepath.Join(path, finfo.Name()), finfo, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// And finally handle the directory itself.
|
||||||
|
return handler(path, stat, follow)
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleEvent might need to emit more than one fsnotify event if the events
|
||||||
|
// bitmap matches more than one event type (e.g. the file was both modified and
|
||||||
|
// had the attributes changed between when the association was created and the
|
||||||
|
// when event was returned)
|
||||||
|
func (w *fen) handleEvent(event *unix.PortEvent) error {
|
||||||
|
var (
|
||||||
|
events = event.Events
|
||||||
|
path = event.Path
|
||||||
|
fmode = event.Cookie.(os.FileMode)
|
||||||
|
reRegister = true
|
||||||
|
)
|
||||||
|
|
||||||
|
w.mu.Lock()
|
||||||
|
_, watchedDir := w.dirs[path]
|
||||||
|
_, watchedPath := w.watches[path]
|
||||||
|
w.mu.Unlock()
|
||||||
|
isWatched := watchedDir || watchedPath
|
||||||
|
|
||||||
|
if events&unix.FILE_DELETE != 0 {
|
||||||
|
if !w.sendEvent(path, Remove) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
reRegister = false
|
||||||
|
}
|
||||||
|
if events&unix.FILE_RENAME_FROM != 0 {
|
||||||
|
if !w.sendEvent(path, Rename) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Don't keep watching the new file name
|
||||||
|
reRegister = false
|
||||||
|
}
|
||||||
|
if events&unix.FILE_RENAME_TO != 0 {
|
||||||
|
// We don't report a Rename event for this case, because Rename events
|
||||||
|
// are interpreted as referring to the _old_ name of the file, and in
|
||||||
|
// this case the event would refer to the new name of the file. This
|
||||||
|
// type of rename event is not supported by fsnotify.
|
||||||
|
|
||||||
|
// inotify reports a Remove event in this case, so we simulate this
|
||||||
|
// here.
|
||||||
|
if !w.sendEvent(path, Remove) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Don't keep watching the file that was removed
|
||||||
|
reRegister = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// The file is gone, nothing left to do.
|
||||||
|
if !reRegister {
|
||||||
|
if watchedDir {
|
||||||
|
w.mu.Lock()
|
||||||
|
delete(w.dirs, path)
|
||||||
|
w.mu.Unlock()
|
||||||
|
}
|
||||||
|
if watchedPath {
|
||||||
|
w.mu.Lock()
|
||||||
|
delete(w.watches, path)
|
||||||
|
w.mu.Unlock()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we didn't get a deletion the file still exists and we're going to have
|
||||||
|
// to watch it again. Let's Stat it now so that we can compare permissions
|
||||||
|
// and have what we need to continue watching the file
|
||||||
|
|
||||||
|
stat, err := os.Lstat(path)
|
||||||
|
if err != nil {
|
||||||
|
// This is unexpected, but we should still emit an event. This happens
|
||||||
|
// most often on "rm -r" of a subdirectory inside a watched directory We
|
||||||
|
// get a modify event of something happening inside, but by the time we
|
||||||
|
// 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
|
||||||
|
// removed.
|
||||||
|
if !w.sendEvent(path, Remove) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Suppress extra write events on removed directories; they are not
|
||||||
|
// informative and can be confusing.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve symlinks that were explicitly watched as we would have at Add()
|
||||||
|
// time. this helps suppress spurious Chmod events on watched symlinks
|
||||||
|
if isWatched {
|
||||||
|
stat, err = os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
// The symlink still exists, but the target is gone. Report the
|
||||||
|
// Remove similar to above.
|
||||||
|
if !w.sendEvent(path, Remove) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Don't return the error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if events&unix.FILE_MODIFIED != 0 {
|
||||||
|
if fmode.IsDir() && watchedDir {
|
||||||
|
if err := w.updateDirectory(path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !w.sendEvent(path, Write) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if events&unix.FILE_ATTRIB != 0 && stat != nil {
|
||||||
|
// Only send Chmod if perms changed
|
||||||
|
if stat.Mode().Perm() != fmode.Perm() {
|
||||||
|
if !w.sendEvent(path, Chmod) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if stat != nil {
|
||||||
|
// If we get here, it means we've hit an event above that requires us to
|
||||||
|
// continue watching the file or directory
|
||||||
|
return w.associateFile(path, stat, isWatched)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range files {
|
||||||
|
path := filepath.Join(path, entry.Name())
|
||||||
|
if w.port.PathIsWatched(path) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
finfo, err := entry.Info()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = w.associateFile(path, finfo, false)
|
||||||
|
if !w.sendError(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if !w.sendEvent(path, Create) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *fen) associateFile(path string, stat os.FileInfo, follow bool) error {
|
||||||
|
if w.isClosed() {
|
||||||
|
return ErrClosed
|
||||||
|
}
|
||||||
|
// This is primarily protecting the call to AssociatePath but it is
|
||||||
|
// important and intentional that the call to PathIsWatched is also
|
||||||
|
// protected by this mutex. Without this mutex, AssociatePath has been seen
|
||||||
|
// to error out that the path is already associated.
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
|
|
||||||
|
if w.port.PathIsWatched(path) {
|
||||||
|
// Remove the old association in favor of this one If we get ENOENT,
|
||||||
|
// then while the x/sys/unix wrapper still thought that this path was
|
||||||
|
// associated, the underlying event port did not. This call will have
|
||||||
|
// cleared up that discrepancy. The most likely cause is that the event
|
||||||
|
// has fired but we haven't processed it yet.
|
||||||
|
err := w.port.DissociatePath(path)
|
||||||
|
if err != nil && !errors.Is(err, unix.ENOENT) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var events int
|
||||||
|
if !follow {
|
||||||
|
// Watch symlinks themselves rather than their targets unless this entry
|
||||||
|
// is explicitly watched.
|
||||||
|
events |= unix.FILE_NOFOLLOW
|
||||||
|
}
|
||||||
|
if true { // TODO: implement withOps()
|
||||||
|
events |= unix.FILE_MODIFIED
|
||||||
|
}
|
||||||
|
if true {
|
||||||
|
events |= unix.FILE_ATTRIB
|
||||||
|
}
|
||||||
|
return w.port.AssociatePath(path, stat, events, stat.Mode())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *fen) dissociateFile(path string, stat os.FileInfo, unused bool) error {
|
||||||
|
if !w.port.PathIsWatched(path) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return w.port.DissociatePath(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *fen) WatchList() []string {
|
||||||
|
if w.isClosed() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
|
|
||||||
|
entries := make([]string, 0, len(w.watches)+len(w.dirs))
|
||||||
|
for pathname := range w.dirs {
|
||||||
|
entries = append(entries, pathname)
|
||||||
|
}
|
||||||
|
for pathname := range w.watches {
|
||||||
|
entries = append(entries, pathname)
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *fen) xSupports(op Op) bool {
|
||||||
|
if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
|
||||||
|
op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
||||||
741
vendor/github.com/fsnotify/fsnotify/backend_inotify.go
generated
vendored
741
vendor/github.com/fsnotify/fsnotify/backend_inotify.go
generated
vendored
|
|
@ -1,5 +1,4 @@
|
||||||
//go:build linux
|
//go:build linux && !appengine
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
|
||||||
|
|
@ -7,142 +6,188 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/fsnotify/fsnotify/internal"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Watcher watches a set of paths, delivering events on a channel.
|
type inotify struct {
|
||||||
//
|
|
||||||
// A watcher should not be copied (e.g. pass it by pointer, rather than by
|
|
||||||
// value).
|
|
||||||
//
|
|
||||||
// # Linux notes
|
|
||||||
//
|
|
||||||
// When a file is removed a Remove event won't be emitted until all file
|
|
||||||
// descriptors are closed, and deletes will always emit a Chmod. For example:
|
|
||||||
//
|
|
||||||
// fp := os.Open("file")
|
|
||||||
// os.Remove("file") // Triggers Chmod
|
|
||||||
// fp.Close() // Triggers Remove
|
|
||||||
//
|
|
||||||
// This is the event that inotify sends, so not much can be changed about this.
|
|
||||||
//
|
|
||||||
// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
|
|
||||||
// for the number of watches per user, and fs.inotify.max_user_instances
|
|
||||||
// specifies the maximum number of inotify instances per user. Every Watcher you
|
|
||||||
// create is an "instance", and every path you add is a "watch".
|
|
||||||
//
|
|
||||||
// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
|
|
||||||
// /proc/sys/fs/inotify/max_user_instances
|
|
||||||
//
|
|
||||||
// To increase them you can use sysctl or write the value to the /proc file:
|
|
||||||
//
|
|
||||||
// # Default values on Linux 5.18
|
|
||||||
// sysctl fs.inotify.max_user_watches=124983
|
|
||||||
// sysctl fs.inotify.max_user_instances=128
|
|
||||||
//
|
|
||||||
// To make the changes persist on reboot edit /etc/sysctl.conf or
|
|
||||||
// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
|
|
||||||
// your distro's documentation):
|
|
||||||
//
|
|
||||||
// fs.inotify.max_user_watches=124983
|
|
||||||
// fs.inotify.max_user_instances=128
|
|
||||||
//
|
|
||||||
// Reaching the limit will result in a "no space left on device" or "too many open
|
|
||||||
// files" error.
|
|
||||||
//
|
|
||||||
// # kqueue notes (macOS, BSD)
|
|
||||||
//
|
|
||||||
// kqueue requires opening a file descriptor for every file that's being watched;
|
|
||||||
// so if you're watching a directory with five files then that's six file
|
|
||||||
// descriptors. You will run in to your system's "max open files" limit faster on
|
|
||||||
// these platforms.
|
|
||||||
//
|
|
||||||
// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
|
|
||||||
// control the maximum number of open files, as well as /etc/login.conf on BSD
|
|
||||||
// systems.
|
|
||||||
//
|
|
||||||
// # macOS notes
|
|
||||||
//
|
|
||||||
// Spotlight indexing on macOS can result in multiple events (see [#15]). A
|
|
||||||
// temporary workaround is to add your folder(s) to the "Spotlight Privacy
|
|
||||||
// Settings" until we have a native FSEvents implementation (see [#11]).
|
|
||||||
//
|
|
||||||
// [#11]: https://github.com/fsnotify/fsnotify/issues/11
|
|
||||||
// [#15]: https://github.com/fsnotify/fsnotify/issues/15
|
|
||||||
type Watcher struct {
|
|
||||||
// Events sends the filesystem change events.
|
|
||||||
//
|
|
||||||
// fsnotify can send the following events; a "path" here can refer to a
|
|
||||||
// file, directory, symbolic link, or special file like a FIFO.
|
|
||||||
//
|
|
||||||
// fsnotify.Create A new path was created; this may be followed by one
|
|
||||||
// or more Write events if data also gets written to a
|
|
||||||
// file.
|
|
||||||
//
|
|
||||||
// fsnotify.Remove A path was removed.
|
|
||||||
//
|
|
||||||
// fsnotify.Rename A path was renamed. A rename is always sent with the
|
|
||||||
// old path as Event.Name, and a Create event will be
|
|
||||||
// sent with the new name. Renames are only sent for
|
|
||||||
// paths that are currently watched; e.g. moving an
|
|
||||||
// unmonitored file into a monitored directory will
|
|
||||||
// show up as just a Create. Similarly, renaming a file
|
|
||||||
// to outside a monitored directory will show up as
|
|
||||||
// only a Rename.
|
|
||||||
//
|
|
||||||
// fsnotify.Write A file or named pipe was written to. A Truncate will
|
|
||||||
// also trigger a Write. A single "write action"
|
|
||||||
// initiated by the user may show up as one or multiple
|
|
||||||
// writes, depending on when the system syncs things to
|
|
||||||
// disk. For example when compiling a large Go program
|
|
||||||
// you may get hundreds of Write events, so you
|
|
||||||
// probably want to wait until you've stopped receiving
|
|
||||||
// them (see the dedup example in cmd/fsnotify).
|
|
||||||
//
|
|
||||||
// fsnotify.Chmod Attributes were changed. On Linux this is also sent
|
|
||||||
// when a file is removed (or more accurately, when a
|
|
||||||
// link to an inode is removed). On kqueue it's sent
|
|
||||||
// and on kqueue when a file is truncated. On Windows
|
|
||||||
// it's never sent.
|
|
||||||
Events chan Event
|
Events chan Event
|
||||||
|
|
||||||
// Errors sends any errors.
|
|
||||||
Errors chan error
|
Errors chan error
|
||||||
|
|
||||||
// Store fd here as os.File.Read() will no longer return on close after
|
// Store fd here as os.File.Read() will no longer return on close after
|
||||||
// calling Fd(). See: https://github.com/golang/go/issues/26439
|
// calling Fd(). See: https://github.com/golang/go/issues/26439
|
||||||
fd int
|
fd int
|
||||||
mu sync.Mutex // Map access
|
|
||||||
inotifyFile *os.File
|
inotifyFile *os.File
|
||||||
watches map[string]*watch // Map of inotify watches (key: path)
|
watches *watches
|
||||||
paths map[int]string // Map of watched paths (key: watch descriptor)
|
done chan struct{} // Channel for sending a "quit message" to the reader goroutine
|
||||||
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
|
||||||
|
// all of the time what we get is a MOVED_FROM to set the cookie and the
|
||||||
|
// next event inotify sends will be MOVED_TO to read it. However, this is
|
||||||
|
// not guaranteed – as described in inotify(7) – and we may get other events
|
||||||
|
// between the two MOVED_* events (including other MOVED_* ones).
|
||||||
|
//
|
||||||
|
// A second issue is that moving a file outside the watched directory will
|
||||||
|
// trigger a MOVED_FROM to set the cookie, but we never see the MOVED_TO to
|
||||||
|
// read and delete it. So just storing it in a map would slowly leak memory.
|
||||||
|
//
|
||||||
|
// Doing it like this gives us a simple fast LRU-cache that won't allocate.
|
||||||
|
// Ten items should be more than enough for our purpose, and a loop over
|
||||||
|
// such a short array is faster than a map access anyway (not that it hugely
|
||||||
|
// matters since we're talking about hundreds of ns at the most, but still).
|
||||||
|
cookies [10]koekje
|
||||||
|
cookieIndex uint8
|
||||||
|
cookiesMu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWatcher creates a new Watcher.
|
type (
|
||||||
func NewWatcher() (*Watcher, error) {
|
watches struct {
|
||||||
// Create inotify fd
|
mu sync.RWMutex
|
||||||
// Need to set the FD to nonblocking mode in order for SetDeadline methods to work
|
wd map[uint32]*watch // wd → watch
|
||||||
// Otherwise, blocking i/o operations won't terminate on close
|
path map[string]uint32 // pathname → wd
|
||||||
|
}
|
||||||
|
watch struct {
|
||||||
|
wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
|
||||||
|
flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
|
||||||
|
path string // Watch path.
|
||||||
|
recurse bool // Recursion with ./...?
|
||||||
|
}
|
||||||
|
koekje struct {
|
||||||
|
cookie uint32
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newWatches() *watches {
|
||||||
|
return &watches{
|
||||||
|
wd: make(map[uint32]*watch),
|
||||||
|
path: make(map[string]uint32),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *watches) len() int {
|
||||||
|
w.mu.RLock()
|
||||||
|
defer w.mu.RUnlock()
|
||||||
|
return len(w.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) {
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
|
|
||||||
|
path, recurse := recursivePath(path)
|
||||||
|
wd, ok := w.path[path]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("%w: %s", ErrNonExistentWatch, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
watch := w.wd[wd]
|
||||||
|
if recurse && !watch.recurse {
|
||||||
|
return nil, fmt.Errorf("can't use /... with non-recursive watch %q", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(w.path, path)
|
||||||
|
delete(w.wd, wd)
|
||||||
|
if !watch.recurse {
|
||||||
|
return []uint32{wd}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
wds := make([]uint32, 0, 8)
|
||||||
|
wds = append(wds, wd)
|
||||||
|
for p, rwd := range w.path {
|
||||||
|
if filepath.HasPrefix(p, path) {
|
||||||
|
delete(w.path, p)
|
||||||
|
delete(w.wd, rwd)
|
||||||
|
wds = append(wds, rwd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
|
|
||||||
|
var existing *watch
|
||||||
|
wd, ok := w.path[path]
|
||||||
|
if ok {
|
||||||
|
existing = w.wd[wd]
|
||||||
|
}
|
||||||
|
|
||||||
|
upd, err := f(existing)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if upd != nil {
|
||||||
|
w.wd[upd.wd] = upd
|
||||||
|
w.path[upd.path] = upd.wd
|
||||||
|
|
||||||
|
if upd.wd != wd {
|
||||||
|
delete(w.wd, wd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||||
|
return newBufferedBackend(0, ev, errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
|
||||||
|
// Need to set nonblocking mode for SetDeadline to work, otherwise blocking
|
||||||
|
// 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)
|
||||||
if fd == -1 {
|
if fd == -1 {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
|
|
||||||
w := &Watcher{
|
w := &inotify{
|
||||||
|
Events: ev,
|
||||||
|
Errors: errs,
|
||||||
fd: fd,
|
fd: fd,
|
||||||
inotifyFile: os.NewFile(uintptr(fd), ""),
|
inotifyFile: os.NewFile(uintptr(fd), ""),
|
||||||
watches: make(map[string]*watch),
|
watches: newWatches(),
|
||||||
paths: make(map[int]string),
|
|
||||||
Events: make(chan Event),
|
|
||||||
Errors: make(chan error),
|
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
doneResp: make(chan struct{}),
|
doneResp: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
@ -152,26 +197,29 @@ func NewWatcher() (*Watcher, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the event was sent, or false if watcher is closed.
|
// Returns true if the event was sent, or false if watcher is closed.
|
||||||
func (w *Watcher) sendEvent(e Event) bool {
|
func (w *inotify) sendEvent(e Event) bool {
|
||||||
select {
|
select {
|
||||||
|
case <-w.done:
|
||||||
|
return false
|
||||||
case w.Events <- e:
|
case w.Events <- e:
|
||||||
return true
|
return true
|
||||||
case <-w.done:
|
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the error was sent, or false if watcher is closed.
|
// Returns true if the error was sent, or false if watcher is closed.
|
||||||
func (w *Watcher) sendError(err error) bool {
|
func (w *inotify) sendError(err error) bool {
|
||||||
select {
|
if err == nil {
|
||||||
case w.Errors <- err:
|
|
||||||
return true
|
return true
|
||||||
|
}
|
||||||
|
select {
|
||||||
case <-w.done:
|
case <-w.done:
|
||||||
return false
|
return false
|
||||||
|
case w.Errors <- err:
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) isClosed() bool {
|
func (w *inotify) isClosed() bool {
|
||||||
select {
|
select {
|
||||||
case <-w.done:
|
case <-w.done:
|
||||||
return true
|
return true
|
||||||
|
|
@ -180,17 +228,14 @@ func (w *Watcher) isClosed() bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close removes all watches and closes the events channel.
|
func (w *inotify) Close() error {
|
||||||
func (w *Watcher) Close() error {
|
w.doneMu.Lock()
|
||||||
w.mu.Lock()
|
|
||||||
if w.isClosed() {
|
if w.isClosed() {
|
||||||
w.mu.Unlock()
|
w.doneMu.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send 'close' signal to goroutine, and set the Watcher to closed.
|
|
||||||
close(w.done)
|
close(w.done)
|
||||||
w.mu.Unlock()
|
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.
|
||||||
|
|
@ -205,138 +250,168 @@ func (w *Watcher) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add starts monitoring the path for changes.
|
func (w *inotify) Add(name string) error { return w.AddWith(name) }
|
||||||
//
|
|
||||||
// A path can only be watched once; attempting to watch it more than once will
|
func (w *inotify) AddWith(path string, opts ...addOpt) error {
|
||||||
// return an error. Paths that do not yet exist on the filesystem cannot be
|
|
||||||
// added. A watch will be automatically removed if the path is deleted.
|
|
||||||
//
|
|
||||||
// A path will remain watched if it gets renamed to somewhere else on the same
|
|
||||||
// filesystem, but the monitor will get removed if the path gets deleted and
|
|
||||||
// re-created, or if it's moved to a different filesystem.
|
|
||||||
//
|
|
||||||
// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
|
|
||||||
// filesystems (/proc, /sys, etc.) generally don't work.
|
|
||||||
//
|
|
||||||
// # Watching directories
|
|
||||||
//
|
|
||||||
// All files in a directory are monitored, including new files that are created
|
|
||||||
// after the watcher is started. Subdirectories are not watched (i.e. it's
|
|
||||||
// non-recursive).
|
|
||||||
//
|
|
||||||
// # Watching files
|
|
||||||
//
|
|
||||||
// Watching individual files (rather than directories) is generally not
|
|
||||||
// recommended as many tools update files atomically. Instead of "just" writing
|
|
||||||
// to the file a temporary file will be written to first, and if successful the
|
|
||||||
// temporary file is moved to to destination removing the original, or some
|
|
||||||
// variant thereof. The watcher on the original file is now lost, as it no
|
|
||||||
// longer exists.
|
|
||||||
//
|
|
||||||
// Instead, watch the parent directory and use Event.Name to filter out files
|
|
||||||
// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
|
|
||||||
func (w *Watcher) Add(name string) error {
|
|
||||||
name = filepath.Clean(name)
|
|
||||||
if w.isClosed() {
|
if w.isClosed() {
|
||||||
return errors.New("inotify instance already closed")
|
return ErrClosed
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n",
|
||||||
|
time.Now().Format("15:04:05.000000000"), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
var flags uint32 = unix.IN_MOVED_TO | unix.IN_MOVED_FROM |
|
with := getOptions(opts...)
|
||||||
unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY |
|
if !w.xSupports(with.op) {
|
||||||
unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF
|
return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
|
||||||
|
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
watchEntry := w.watches[name]
|
|
||||||
if watchEntry != nil {
|
|
||||||
flags |= watchEntry.flags | unix.IN_MASK_ADD
|
|
||||||
}
|
|
||||||
wd, errno := unix.InotifyAddWatch(w.fd, name, flags)
|
|
||||||
if wd == -1 {
|
|
||||||
return errno
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if watchEntry == nil {
|
path, recurse := recursivePath(path)
|
||||||
w.watches[name] = &watch{wd: uint32(wd), flags: flags}
|
if recurse {
|
||||||
w.paths[wd] = name
|
return filepath.WalkDir(path, func(root string, d fs.DirEntry, err error) error {
|
||||||
} else {
|
if err != nil {
|
||||||
watchEntry.wd = uint32(wd)
|
return err
|
||||||
watchEntry.flags = flags
|
}
|
||||||
|
if !d.IsDir() {
|
||||||
|
if root == path {
|
||||||
|
return fmt.Errorf("fsnotify: not a directory: %q", path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a Create event when adding new directory from a recursive
|
||||||
|
// watch; this is for "mkdir -p one/two/three". Usually all those
|
||||||
|
// directories will be created before we can set up watchers on the
|
||||||
|
// subdirectories, so only "one" would be sent as a Create event and
|
||||||
|
// not "one/two" and "one/two/three" (inotifywait -r has the same
|
||||||
|
// problem).
|
||||||
|
if with.sendCreate && root != path {
|
||||||
|
w.sendEvent(Event{Name: root, Op: Create})
|
||||||
|
}
|
||||||
|
|
||||||
|
return w.add(root, with, true)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return w.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 {
|
||||||
|
return w.watches.updatePath(path, func(existing *watch) (*watch, error) {
|
||||||
|
if existing != nil {
|
||||||
|
flags |= existing.flags | unix.IN_MASK_ADD
|
||||||
|
}
|
||||||
|
|
||||||
|
wd, err := unix.InotifyAddWatch(w.fd, path, flags)
|
||||||
|
if wd == -1 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if existing == nil {
|
||||||
|
return &watch{
|
||||||
|
wd: uint32(wd),
|
||||||
|
path: path,
|
||||||
|
flags: flags,
|
||||||
|
recurse: recurse,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
existing.wd = uint32(wd)
|
||||||
|
existing.flags = flags
|
||||||
|
return existing, nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *inotify) Remove(name string) error {
|
||||||
|
if w.isClosed() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n",
|
||||||
|
time.Now().Format("15:04:05.000000000"), name)
|
||||||
|
}
|
||||||
|
return w.remove(filepath.Clean(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *inotify) remove(name string) error {
|
||||||
|
wds, err := w.watches.removePath(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, wd := range wds {
|
||||||
|
_, err := unix.InotifyRmWatch(w.fd, wd)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: Perhaps it's not helpful to return an error here in every
|
||||||
|
// case; the only two possible errors are:
|
||||||
|
//
|
||||||
|
// EBADF, which happens when w.fd is not a valid file descriptor of
|
||||||
|
// any kind.
|
||||||
|
//
|
||||||
|
// EINVAL, which is when fd is not an inotify descriptor or wd is
|
||||||
|
// not a valid watch descriptor. Watch descriptors are invalidated
|
||||||
|
// when they are removed explicitly or implicitly; explicitly by
|
||||||
|
// inotify_rm_watch, implicitly when the file they are watching is
|
||||||
|
// deleted.
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove stops monitoring the path for changes.
|
func (w *inotify) WatchList() []string {
|
||||||
//
|
if w.isClosed() {
|
||||||
// Directories are always removed non-recursively. For example, if you added
|
return nil
|
||||||
// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
|
|
||||||
//
|
|
||||||
// Removing a path that has not yet been added returns [ErrNonExistentWatch].
|
|
||||||
func (w *Watcher) Remove(name string) error {
|
|
||||||
name = filepath.Clean(name)
|
|
||||||
|
|
||||||
// Fetch the watch.
|
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
watch, ok := w.watches[name]
|
|
||||||
|
|
||||||
// Remove it from inotify.
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We successfully removed the watch if InotifyRmWatch doesn't return an
|
entries := make([]string, 0, w.watches.len())
|
||||||
// error, we need to clean up our internal state to ensure it matches
|
w.watches.mu.RLock()
|
||||||
// inotify's kernel state.
|
for pathname := range w.watches.path {
|
||||||
delete(w.paths, int(watch.wd))
|
|
||||||
delete(w.watches, name)
|
|
||||||
|
|
||||||
// inotify_rm_watch will return EINVAL if the file has been deleted;
|
|
||||||
// the inotify will already have been removed.
|
|
||||||
// watches and pathes are deleted in ignoreLinux() implicitly and asynchronously
|
|
||||||
// by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE
|
|
||||||
// so that EINVAL means that the wd is being rm_watch()ed or its file removed
|
|
||||||
// by another thread and we have not received IN_IGNORE event.
|
|
||||||
success, errno := unix.InotifyRmWatch(w.fd, watch.wd)
|
|
||||||
if success == -1 {
|
|
||||||
// TODO: Perhaps it's not helpful to return an error here in every case;
|
|
||||||
// The only two possible errors are:
|
|
||||||
//
|
|
||||||
// - EBADF, which happens when w.fd is not a valid file descriptor
|
|
||||||
// of any kind.
|
|
||||||
// - EINVAL, which is when fd is not an inotify descriptor or wd
|
|
||||||
// is not a valid watch descriptor. Watch descriptors are
|
|
||||||
// invalidated when they are removed explicitly or implicitly;
|
|
||||||
// explicitly by inotify_rm_watch, implicitly when the file they
|
|
||||||
// are watching is deleted.
|
|
||||||
return errno
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WatchList returns all paths added with [Add] (and are not yet removed).
|
|
||||||
func (w *Watcher) WatchList() []string {
|
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
|
|
||||||
entries := make([]string, 0, len(w.watches))
|
|
||||||
for pathname := range w.watches {
|
|
||||||
entries = append(entries, pathname)
|
entries = append(entries, pathname)
|
||||||
}
|
}
|
||||||
|
w.watches.mu.RUnlock()
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
type watch struct {
|
|
||||||
wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
|
|
||||||
flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
// readEvents reads from the inotify file descriptor, converts the
|
// readEvents reads from the inotify file descriptor, converts the
|
||||||
// received events into Event objects and sends them via the Events channel
|
// received events into Event objects and sends them via the Events channel
|
||||||
func (w *Watcher) readEvents() {
|
func (w *inotify) readEvents() {
|
||||||
defer func() {
|
defer func() {
|
||||||
close(w.doneResp)
|
close(w.doneResp)
|
||||||
close(w.Errors)
|
close(w.Errors)
|
||||||
|
|
@ -367,14 +442,11 @@ func (w *Watcher) readEvents() {
|
||||||
if n < unix.SizeofInotifyEvent {
|
if n < unix.SizeofInotifyEvent {
|
||||||
var err error
|
var err error
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
// If EOF is received. This should really never happen.
|
err = io.EOF // If EOF is received. This should really never happen.
|
||||||
err = io.EOF
|
|
||||||
} else if n < 0 {
|
} else if n < 0 {
|
||||||
// If an error occurred while reading.
|
err = errno // If an error occurred while reading.
|
||||||
err = errno
|
|
||||||
} else {
|
} else {
|
||||||
// Read was too short.
|
err = errors.New("notify: short read in readEvents()") // Read was too short.
|
||||||
err = errors.New("notify: short read in readEvents()")
|
|
||||||
}
|
}
|
||||||
if !w.sendError(err) {
|
if !w.sendError(err) {
|
||||||
return
|
return
|
||||||
|
|
@ -382,15 +454,17 @@ func (w *Watcher) readEvents() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var offset uint32
|
|
||||||
// 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 offset points to at least one whole event...
|
// While the offset points to at least one whole event...
|
||||||
|
var offset uint32
|
||||||
for offset <= uint32(n-unix.SizeofInotifyEvent) {
|
for offset <= uint32(n-unix.SizeofInotifyEvent) {
|
||||||
var (
|
var (
|
||||||
// Point "raw" to the event in the buffer
|
// Point "raw" to the event in the buffer
|
||||||
raw = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))
|
raw = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))
|
||||||
mask = uint32(raw.Mask)
|
mask = uint32(raw.Mask)
|
||||||
nameLen = uint32(raw.Len)
|
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 mask&unix.IN_Q_OVERFLOW != 0 {
|
||||||
|
|
@ -399,46 +473,124 @@ func (w *Watcher) readEvents() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the event happened to the watched directory or the watched file, the kernel
|
/// If the event happened to the watched directory or the watched
|
||||||
// doesn't append the filename to the event, but we would like to always fill the
|
/// file, the kernel doesn't append the filename to the event, but
|
||||||
// the "Name" field with a valid filename. We retrieve the path of the watch from
|
/// we would like to always fill the the "Name" field with a valid
|
||||||
// the "paths" map.
|
/// filename. We retrieve the path of the watch from the "paths"
|
||||||
w.mu.Lock()
|
/// map.
|
||||||
name, ok := w.paths[int(raw.Wd)]
|
watch := w.watches.byWd(uint32(raw.Wd))
|
||||||
// IN_DELETE_SELF occurs when the file/directory being watched is removed.
|
/// Can be nil if Remove() was called in another goroutine for this
|
||||||
// This is a sign to clean up the maps, otherwise we are no longer in sync
|
/// path inbetween reading the events from the kernel and reading
|
||||||
// with the inotify kernel state which has already deleted the watch
|
/// the internal state. Not much we can do about it, so just skip.
|
||||||
// automatically.
|
/// See #616.
|
||||||
if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
|
if watch == nil {
|
||||||
delete(w.paths, int(raw.Wd))
|
next()
|
||||||
delete(w.watches, name)
|
continue
|
||||||
}
|
}
|
||||||
w.mu.Unlock()
|
|
||||||
|
|
||||||
|
name := watch.path
|
||||||
if nameLen > 0 {
|
if nameLen > 0 {
|
||||||
// Point "bytes" at the first byte of the filename
|
/// Point "bytes" at the first byte of the filename
|
||||||
bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
|
bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
|
||||||
// The filename is padded with NULL bytes. TrimRight() gets rid of those.
|
/// The filename is padded with NULL bytes. TrimRight() gets rid of those.
|
||||||
name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
|
name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
|
||||||
}
|
}
|
||||||
|
|
||||||
event := w.newEvent(name, mask)
|
if debug {
|
||||||
|
internal.Debug(name, raw.Mask, raw.Cookie)
|
||||||
|
}
|
||||||
|
|
||||||
// Send the events that are not ignored on the events channel
|
if mask&unix.IN_IGNORED != 0 { //&& event.Op != 0
|
||||||
if mask&unix.IN_IGNORED == 0 {
|
next()
|
||||||
if !w.sendEvent(event) {
|
continue
|
||||||
return
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to the next event in the buffer
|
/// Skip if we're watching both this path and the parent; the parent
|
||||||
offset += unix.SizeofInotifyEvent + nameLen
|
/// 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) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// newEvent returns an platform-independent Event based on an inotify mask.
|
func (w *inotify) isRecursive(path string) bool {
|
||||||
func (w *Watcher) newEvent(name string, mask uint32) Event {
|
ww := w.watches.byPath(path)
|
||||||
|
if ww == nil { // path could be a file, so also check the Dir.
|
||||||
|
ww = w.watches.byPath(filepath.Dir(path))
|
||||||
|
}
|
||||||
|
return ww != nil && ww.recurse
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *inotify) newEvent(name string, mask, cookie uint32) Event {
|
||||||
e := Event{Name: name}
|
e := Event{Name: name}
|
||||||
if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
|
if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
|
||||||
e.Op |= Create
|
e.Op |= Create
|
||||||
|
|
@ -449,11 +601,58 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
|
||||||
if mask&unix.IN_MODIFY == unix.IN_MODIFY {
|
if mask&unix.IN_MODIFY == unix.IN_MODIFY {
|
||||||
e.Op |= Write
|
e.Op |= Write
|
||||||
}
|
}
|
||||||
|
if mask&unix.IN_OPEN == unix.IN_OPEN {
|
||||||
|
e.Op |= xUnportableOpen
|
||||||
|
}
|
||||||
|
if mask&unix.IN_ACCESS == unix.IN_ACCESS {
|
||||||
|
e.Op |= xUnportableRead
|
||||||
|
}
|
||||||
|
if mask&unix.IN_CLOSE_WRITE == unix.IN_CLOSE_WRITE {
|
||||||
|
e.Op |= xUnportableCloseWrite
|
||||||
|
}
|
||||||
|
if mask&unix.IN_CLOSE_NOWRITE == unix.IN_CLOSE_NOWRITE {
|
||||||
|
e.Op |= xUnportableCloseRead
|
||||||
|
}
|
||||||
if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
|
if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
|
||||||
e.Op |= Rename
|
e.Op |= Rename
|
||||||
}
|
}
|
||||||
if mask&unix.IN_ATTRIB == unix.IN_ATTRIB {
|
if mask&unix.IN_ATTRIB == unix.IN_ATTRIB {
|
||||||
e.Op |= Chmod
|
e.Op |= Chmod
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cookie != 0 {
|
||||||
|
if mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
|
||||||
|
w.cookiesMu.Lock()
|
||||||
|
w.cookies[w.cookieIndex] = koekje{cookie: cookie, path: e.Name}
|
||||||
|
w.cookieIndex++
|
||||||
|
if w.cookieIndex > 9 {
|
||||||
|
w.cookieIndex = 0
|
||||||
|
}
|
||||||
|
w.cookiesMu.Unlock()
|
||||||
|
} else if mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
|
||||||
|
w.cookiesMu.Lock()
|
||||||
|
var prev string
|
||||||
|
for _, c := range w.cookies {
|
||||||
|
if c.cookie == cookie {
|
||||||
|
prev = c.path
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.cookiesMu.Unlock()
|
||||||
|
e.renamedFrom = prev
|
||||||
|
}
|
||||||
|
}
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *inotify) xSupports(op Op) bool {
|
||||||
|
return true // Supports everything.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *inotify) state() {
|
||||||
|
w.watches.mu.Lock()
|
||||||
|
defer w.watches.mu.Unlock()
|
||||||
|
for wd, ww := range w.watches.wd {
|
||||||
|
fmt.Fprintf(os.Stderr, "%4d: recurse=%t %q\n", wd, ww.recurse, ww.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
824
vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
generated
vendored
824
vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
generated
vendored
File diff suppressed because it is too large
Load diff
73
vendor/github.com/fsnotify/fsnotify/backend_other.go
generated
vendored
73
vendor/github.com/fsnotify/fsnotify/backend_other.go
generated
vendored
|
|
@ -1,66 +1,23 @@
|
||||||
//go:build !darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows
|
//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
|
||||||
// +build !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows
|
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
|
||||||
import (
|
import "errors"
|
||||||
"fmt"
|
|
||||||
"runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Watcher watches a set of files, delivering events to a channel.
|
type other struct {
|
||||||
type Watcher struct{}
|
Events chan Event
|
||||||
|
Errors chan error
|
||||||
// NewWatcher creates a new Watcher.
|
|
||||||
func NewWatcher() (*Watcher, error) {
|
|
||||||
return nil, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close removes all watches and closes the events channel.
|
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||||
func (w *Watcher) Close() error {
|
return nil, errors.New("fsnotify not supported on the current platform")
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
|
||||||
// Add starts monitoring the path for changes.
|
return newBackend(ev, errs)
|
||||||
//
|
|
||||||
// A path can only be watched once; attempting to watch it more than once will
|
|
||||||
// return an error. Paths that do not yet exist on the filesystem cannot be
|
|
||||||
// added. A watch will be automatically removed if the path is deleted.
|
|
||||||
//
|
|
||||||
// A path will remain watched if it gets renamed to somewhere else on the same
|
|
||||||
// filesystem, but the monitor will get removed if the path gets deleted and
|
|
||||||
// re-created, or if it's moved to a different filesystem.
|
|
||||||
//
|
|
||||||
// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
|
|
||||||
// filesystems (/proc, /sys, etc.) generally don't work.
|
|
||||||
//
|
|
||||||
// # Watching directories
|
|
||||||
//
|
|
||||||
// All files in a directory are monitored, including new files that are created
|
|
||||||
// after the watcher is started. Subdirectories are not watched (i.e. it's
|
|
||||||
// non-recursive).
|
|
||||||
//
|
|
||||||
// # Watching files
|
|
||||||
//
|
|
||||||
// Watching individual files (rather than directories) is generally not
|
|
||||||
// recommended as many tools update files atomically. Instead of "just" writing
|
|
||||||
// to the file a temporary file will be written to first, and if successful the
|
|
||||||
// temporary file is moved to to destination removing the original, or some
|
|
||||||
// variant thereof. The watcher on the original file is now lost, as it no
|
|
||||||
// longer exists.
|
|
||||||
//
|
|
||||||
// Instead, watch the parent directory and use Event.Name to filter out files
|
|
||||||
// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
|
|
||||||
func (w *Watcher) Add(name string) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove stops monitoring the path for changes.
|
|
||||||
//
|
|
||||||
// Directories are always removed non-recursively. For example, if you added
|
|
||||||
// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
|
|
||||||
//
|
|
||||||
// Removing a path that has not yet been added returns [ErrNonExistentWatch].
|
|
||||||
func (w *Watcher) Remove(name string) error {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
func (w *other) Close() error { return nil }
|
||||||
|
func (w *other) WatchList() []string { return nil }
|
||||||
|
func (w *other) Add(name string) error { return nil }
|
||||||
|
func (w *other) AddWith(name string, opts ...addOpt) error { return nil }
|
||||||
|
func (w *other) Remove(name string) error { return nil }
|
||||||
|
func (w *other) xSupports(op Op) bool { return false }
|
||||||
|
|
|
||||||
374
vendor/github.com/fsnotify/fsnotify/backend_windows.go
generated
vendored
374
vendor/github.com/fsnotify/fsnotify/backend_windows.go
generated
vendored
|
|
@ -1,5 +1,8 @@
|
||||||
//go:build windows
|
//go:build windows
|
||||||
// +build windows
|
|
||||||
|
// Windows backend based on ReadDirectoryChangesW()
|
||||||
|
//
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
|
||||||
|
|
@ -12,143 +15,60 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/fsnotify/fsnotify/internal"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Watcher watches a set of paths, delivering events on a channel.
|
type readDirChangesW struct {
|
||||||
//
|
|
||||||
// A watcher should not be copied (e.g. pass it by pointer, rather than by
|
|
||||||
// value).
|
|
||||||
//
|
|
||||||
// # Linux notes
|
|
||||||
//
|
|
||||||
// When a file is removed a Remove event won't be emitted until all file
|
|
||||||
// descriptors are closed, and deletes will always emit a Chmod. For example:
|
|
||||||
//
|
|
||||||
// fp := os.Open("file")
|
|
||||||
// os.Remove("file") // Triggers Chmod
|
|
||||||
// fp.Close() // Triggers Remove
|
|
||||||
//
|
|
||||||
// This is the event that inotify sends, so not much can be changed about this.
|
|
||||||
//
|
|
||||||
// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
|
|
||||||
// for the number of watches per user, and fs.inotify.max_user_instances
|
|
||||||
// specifies the maximum number of inotify instances per user. Every Watcher you
|
|
||||||
// create is an "instance", and every path you add is a "watch".
|
|
||||||
//
|
|
||||||
// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
|
|
||||||
// /proc/sys/fs/inotify/max_user_instances
|
|
||||||
//
|
|
||||||
// To increase them you can use sysctl or write the value to the /proc file:
|
|
||||||
//
|
|
||||||
// # Default values on Linux 5.18
|
|
||||||
// sysctl fs.inotify.max_user_watches=124983
|
|
||||||
// sysctl fs.inotify.max_user_instances=128
|
|
||||||
//
|
|
||||||
// To make the changes persist on reboot edit /etc/sysctl.conf or
|
|
||||||
// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
|
|
||||||
// your distro's documentation):
|
|
||||||
//
|
|
||||||
// fs.inotify.max_user_watches=124983
|
|
||||||
// fs.inotify.max_user_instances=128
|
|
||||||
//
|
|
||||||
// Reaching the limit will result in a "no space left on device" or "too many open
|
|
||||||
// files" error.
|
|
||||||
//
|
|
||||||
// # kqueue notes (macOS, BSD)
|
|
||||||
//
|
|
||||||
// kqueue requires opening a file descriptor for every file that's being watched;
|
|
||||||
// so if you're watching a directory with five files then that's six file
|
|
||||||
// descriptors. You will run in to your system's "max open files" limit faster on
|
|
||||||
// these platforms.
|
|
||||||
//
|
|
||||||
// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
|
|
||||||
// control the maximum number of open files, as well as /etc/login.conf on BSD
|
|
||||||
// systems.
|
|
||||||
//
|
|
||||||
// # macOS notes
|
|
||||||
//
|
|
||||||
// Spotlight indexing on macOS can result in multiple events (see [#15]). A
|
|
||||||
// temporary workaround is to add your folder(s) to the "Spotlight Privacy
|
|
||||||
// Settings" until we have a native FSEvents implementation (see [#11]).
|
|
||||||
//
|
|
||||||
// [#11]: https://github.com/fsnotify/fsnotify/issues/11
|
|
||||||
// [#15]: https://github.com/fsnotify/fsnotify/issues/15
|
|
||||||
type Watcher struct {
|
|
||||||
// Events sends the filesystem change events.
|
|
||||||
//
|
|
||||||
// fsnotify can send the following events; a "path" here can refer to a
|
|
||||||
// file, directory, symbolic link, or special file like a FIFO.
|
|
||||||
//
|
|
||||||
// fsnotify.Create A new path was created; this may be followed by one
|
|
||||||
// or more Write events if data also gets written to a
|
|
||||||
// file.
|
|
||||||
//
|
|
||||||
// fsnotify.Remove A path was removed.
|
|
||||||
//
|
|
||||||
// fsnotify.Rename A path was renamed. A rename is always sent with the
|
|
||||||
// old path as Event.Name, and a Create event will be
|
|
||||||
// sent with the new name. Renames are only sent for
|
|
||||||
// paths that are currently watched; e.g. moving an
|
|
||||||
// unmonitored file into a monitored directory will
|
|
||||||
// show up as just a Create. Similarly, renaming a file
|
|
||||||
// to outside a monitored directory will show up as
|
|
||||||
// only a Rename.
|
|
||||||
//
|
|
||||||
// fsnotify.Write A file or named pipe was written to. A Truncate will
|
|
||||||
// also trigger a Write. A single "write action"
|
|
||||||
// initiated by the user may show up as one or multiple
|
|
||||||
// writes, depending on when the system syncs things to
|
|
||||||
// disk. For example when compiling a large Go program
|
|
||||||
// you may get hundreds of Write events, so you
|
|
||||||
// probably want to wait until you've stopped receiving
|
|
||||||
// them (see the dedup example in cmd/fsnotify).
|
|
||||||
//
|
|
||||||
// fsnotify.Chmod Attributes were changed. On Linux this is also sent
|
|
||||||
// when a file is removed (or more accurately, when a
|
|
||||||
// link to an inode is removed). On kqueue it's sent
|
|
||||||
// and on kqueue when a file is truncated. On Windows
|
|
||||||
// it's never sent.
|
|
||||||
Events chan Event
|
Events chan Event
|
||||||
|
|
||||||
// Errors sends any errors.
|
|
||||||
Errors chan error
|
Errors chan error
|
||||||
|
|
||||||
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
|
quit chan chan<- error
|
||||||
|
|
||||||
mu sync.Mutex // Protects access to watches, isClosed
|
mu sync.Mutex // Protects access to watches, closed
|
||||||
watches watchMap // Map of watches (key: i-number)
|
watches watchMap // Map of watches (key: i-number)
|
||||||
isClosed bool // Set to true when Close() is first called
|
closed bool // Set to true when Close() is first called
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWatcher creates a new Watcher.
|
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||||
func NewWatcher() (*Watcher, error) {
|
return newBufferedBackend(50, ev, errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBufferedBackend(sz uint, 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)
|
||||||
}
|
}
|
||||||
w := &Watcher{
|
w := &readDirChangesW{
|
||||||
|
Events: ev,
|
||||||
|
Errors: errs,
|
||||||
port: port,
|
port: port,
|
||||||
watches: make(watchMap),
|
watches: make(watchMap),
|
||||||
input: make(chan *input, 1),
|
input: make(chan *input, 1),
|
||||||
Events: make(chan Event, 50),
|
|
||||||
Errors: make(chan error),
|
|
||||||
quit: make(chan chan<- error, 1),
|
quit: make(chan chan<- error, 1),
|
||||||
}
|
}
|
||||||
go w.readEvents()
|
go w.readEvents()
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) sendEvent(name string, mask uint64) bool {
|
func (w *readDirChangesW) isClosed() bool {
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
|
return w.closed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *readDirChangesW) sendEvent(name, renamedFrom string, mask uint64) bool {
|
||||||
if mask == 0 {
|
if mask == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
event := w.newEvent(name, uint32(mask))
|
event := w.newEvent(name, uint32(mask))
|
||||||
|
event.renamedFrom = renamedFrom
|
||||||
select {
|
select {
|
||||||
case ch := <-w.quit:
|
case ch := <-w.quit:
|
||||||
w.quit <- ch
|
w.quit <- ch
|
||||||
|
|
@ -158,23 +78,25 @@ func (w *Watcher) sendEvent(name string, mask uint64) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the error was sent, or false if watcher is closed.
|
// Returns true if the error was sent, or false if watcher is closed.
|
||||||
func (w *Watcher) sendError(err error) bool {
|
func (w *readDirChangesW) sendError(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case w.Errors <- err:
|
case w.Errors <- err:
|
||||||
return true
|
return true
|
||||||
case <-w.quit:
|
case <-w.quit:
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close removes all watches and closes the events channel.
|
func (w *readDirChangesW) Close() error {
|
||||||
func (w *Watcher) Close() error {
|
if w.isClosed() {
|
||||||
w.mu.Lock()
|
|
||||||
if w.isClosed {
|
|
||||||
w.mu.Unlock()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
w.isClosed = true
|
|
||||||
|
w.mu.Lock()
|
||||||
|
w.closed = true
|
||||||
w.mu.Unlock()
|
w.mu.Unlock()
|
||||||
|
|
||||||
// Send "quit" message to the reader goroutine
|
// Send "quit" message to the reader goroutine
|
||||||
|
|
@ -186,49 +108,31 @@ func (w *Watcher) Close() error {
|
||||||
return <-ch
|
return <-ch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add starts monitoring the path for changes.
|
func (w *readDirChangesW) Add(name string) error { return w.AddWith(name) }
|
||||||
//
|
|
||||||
// A path can only be watched once; attempting to watch it more than once will
|
func (w *readDirChangesW) AddWith(name string, opts ...addOpt) error {
|
||||||
// return an error. Paths that do not yet exist on the filesystem cannot be
|
if w.isClosed() {
|
||||||
// added. A watch will be automatically removed if the path is deleted.
|
return ErrClosed
|
||||||
//
|
}
|
||||||
// A path will remain watched if it gets renamed to somewhere else on the same
|
if debug {
|
||||||
// filesystem, but the monitor will get removed if the path gets deleted and
|
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n",
|
||||||
// re-created, or if it's moved to a different filesystem.
|
time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name))
|
||||||
//
|
}
|
||||||
// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
|
|
||||||
// filesystems (/proc, /sys, etc.) generally don't work.
|
with := getOptions(opts...)
|
||||||
//
|
if !w.xSupports(with.op) {
|
||||||
// # Watching directories
|
return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
|
||||||
//
|
}
|
||||||
// All files in a directory are monitored, including new files that are created
|
if with.bufsize < 4096 {
|
||||||
// after the watcher is started. Subdirectories are not watched (i.e. it's
|
return fmt.Errorf("fsnotify.WithBufferSize: buffer size cannot be smaller than 4096 bytes")
|
||||||
// non-recursive).
|
|
||||||
//
|
|
||||||
// # Watching files
|
|
||||||
//
|
|
||||||
// Watching individual files (rather than directories) is generally not
|
|
||||||
// recommended as many tools update files atomically. Instead of "just" writing
|
|
||||||
// to the file a temporary file will be written to first, and if successful the
|
|
||||||
// temporary file is moved to to destination removing the original, or some
|
|
||||||
// variant thereof. The watcher on the original file is now lost, as it no
|
|
||||||
// longer exists.
|
|
||||||
//
|
|
||||||
// Instead, watch the parent directory and use Event.Name to filter out files
|
|
||||||
// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
|
|
||||||
func (w *Watcher) Add(name string) error {
|
|
||||||
w.mu.Lock()
|
|
||||||
if w.isClosed {
|
|
||||||
w.mu.Unlock()
|
|
||||||
return errors.New("watcher already closed")
|
|
||||||
}
|
}
|
||||||
w.mu.Unlock()
|
|
||||||
|
|
||||||
in := &input{
|
in := &input{
|
||||||
op: opAddWatch,
|
op: opAddWatch,
|
||||||
path: filepath.Clean(name),
|
path: filepath.Clean(name),
|
||||||
flags: sysFSALLEVENTS,
|
flags: sysFSALLEVENTS,
|
||||||
reply: make(chan error),
|
reply: make(chan error),
|
||||||
|
bufsize: with.bufsize,
|
||||||
}
|
}
|
||||||
w.input <- in
|
w.input <- in
|
||||||
if err := w.wakeupReader(); err != nil {
|
if err := w.wakeupReader(); err != nil {
|
||||||
|
|
@ -237,13 +141,15 @@ func (w *Watcher) Add(name string) error {
|
||||||
return <-in.reply
|
return <-in.reply
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove stops monitoring the path for changes.
|
func (w *readDirChangesW) Remove(name string) error {
|
||||||
//
|
if w.isClosed() {
|
||||||
// Directories are always removed non-recursively. For example, if you added
|
return nil
|
||||||
// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
|
}
|
||||||
//
|
if debug {
|
||||||
// Removing a path that has not yet been added returns [ErrNonExistentWatch].
|
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n",
|
||||||
func (w *Watcher) Remove(name string) error {
|
time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name))
|
||||||
|
}
|
||||||
|
|
||||||
in := &input{
|
in := &input{
|
||||||
op: opRemoveWatch,
|
op: opRemoveWatch,
|
||||||
path: filepath.Clean(name),
|
path: filepath.Clean(name),
|
||||||
|
|
@ -256,15 +162,24 @@ func (w *Watcher) Remove(name string) error {
|
||||||
return <-in.reply
|
return <-in.reply
|
||||||
}
|
}
|
||||||
|
|
||||||
// WatchList returns all paths added with [Add] (and are not yet removed).
|
func (w *readDirChangesW) WatchList() []string {
|
||||||
func (w *Watcher) WatchList() []string {
|
if w.isClosed() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
defer w.mu.Unlock()
|
defer w.mu.Unlock()
|
||||||
|
|
||||||
entries := make([]string, 0, len(w.watches))
|
entries := make([]string, 0, len(w.watches))
|
||||||
for _, entry := range w.watches {
|
for _, entry := range w.watches {
|
||||||
for _, watchEntry := range entry {
|
for _, watchEntry := range entry {
|
||||||
entries = append(entries, watchEntry.path)
|
for name := range watchEntry.names {
|
||||||
|
entries = append(entries, filepath.Join(watchEntry.path, name))
|
||||||
|
}
|
||||||
|
// the directory itself is being watched
|
||||||
|
if watchEntry.mask != 0 {
|
||||||
|
entries = append(entries, watchEntry.path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -279,7 +194,6 @@ func (w *Watcher) WatchList() []string {
|
||||||
// This should all be removed at some point, and just use windows.FILE_NOTIFY_*
|
// This should all be removed at some point, and just use windows.FILE_NOTIFY_*
|
||||||
const (
|
const (
|
||||||
sysFSALLEVENTS = 0xfff
|
sysFSALLEVENTS = 0xfff
|
||||||
sysFSATTRIB = 0x4
|
|
||||||
sysFSCREATE = 0x100
|
sysFSCREATE = 0x100
|
||||||
sysFSDELETE = 0x200
|
sysFSDELETE = 0x200
|
||||||
sysFSDELETESELF = 0x400
|
sysFSDELETESELF = 0x400
|
||||||
|
|
@ -291,7 +205,7 @@ const (
|
||||||
sysFSIGNORED = 0x8000
|
sysFSIGNORED = 0x8000
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w *Watcher) newEvent(name string, mask uint32) Event {
|
func (w *readDirChangesW) newEvent(name string, mask uint32) Event {
|
||||||
e := Event{Name: name}
|
e := Event{Name: name}
|
||||||
if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO {
|
if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO {
|
||||||
e.Op |= Create
|
e.Op |= Create
|
||||||
|
|
@ -305,9 +219,6 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
|
||||||
if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM {
|
if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM {
|
||||||
e.Op |= Rename
|
e.Op |= Rename
|
||||||
}
|
}
|
||||||
if mask&sysFSATTRIB == sysFSATTRIB {
|
|
||||||
e.Op |= Chmod
|
|
||||||
}
|
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -321,10 +232,11 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type input struct {
|
type input struct {
|
||||||
op int
|
op int
|
||||||
path string
|
path string
|
||||||
flags uint32
|
flags uint32
|
||||||
reply chan error
|
bufsize int
|
||||||
|
reply chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
type inode struct {
|
type inode struct {
|
||||||
|
|
@ -334,13 +246,14 @@ type inode struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type watch struct {
|
type watch struct {
|
||||||
ov windows.Overlapped
|
ov windows.Overlapped
|
||||||
ino *inode // i-number
|
ino *inode // i-number
|
||||||
path string // Directory path
|
recurse bool // Recursive watch?
|
||||||
mask uint64 // Directory itself is being watched with these notify flags
|
path string // Directory path
|
||||||
names map[string]uint64 // Map of names being watched and their notify flags
|
mask uint64 // Directory itself is being watched with these notify flags
|
||||||
rename string // Remembers the old name while renaming a file
|
names map[string]uint64 // Map of names being watched and their notify flags
|
||||||
buf [65536]byte // 64K buffer
|
rename string // Remembers the old name while renaming a file
|
||||||
|
buf []byte // buffer, allocated later
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
|
@ -348,7 +261,7 @@ type (
|
||||||
watchMap map[uint32]indexMap
|
watchMap map[uint32]indexMap
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w *Watcher) wakeupReader() error {
|
func (w *readDirChangesW) wakeupReader() error {
|
||||||
err := windows.PostQueuedCompletionStatus(w.port, 0, 0, nil)
|
err := windows.PostQueuedCompletionStatus(w.port, 0, 0, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return os.NewSyscallError("PostQueuedCompletionStatus", err)
|
return os.NewSyscallError("PostQueuedCompletionStatus", err)
|
||||||
|
|
@ -356,7 +269,7 @@ func (w *Watcher) wakeupReader() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) getDir(pathname string) (dir string, err error) {
|
func (w *readDirChangesW) getDir(pathname string) (dir string, err error) {
|
||||||
attr, err := windows.GetFileAttributes(windows.StringToUTF16Ptr(pathname))
|
attr, err := windows.GetFileAttributes(windows.StringToUTF16Ptr(pathname))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", os.NewSyscallError("GetFileAttributes", err)
|
return "", os.NewSyscallError("GetFileAttributes", err)
|
||||||
|
|
@ -370,7 +283,7 @@ func (w *Watcher) getDir(pathname string) (dir string, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) getIno(path string) (ino *inode, err error) {
|
func (w *readDirChangesW) getIno(path string) (ino *inode, err error) {
|
||||||
h, err := windows.CreateFile(windows.StringToUTF16Ptr(path),
|
h, err := windows.CreateFile(windows.StringToUTF16Ptr(path),
|
||||||
windows.FILE_LIST_DIRECTORY,
|
windows.FILE_LIST_DIRECTORY,
|
||||||
windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE,
|
windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE,
|
||||||
|
|
@ -413,7 +326,9 @@ func (m watchMap) set(ino *inode, watch *watch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must run within the I/O thread.
|
// Must run within the I/O thread.
|
||||||
func (w *Watcher) addWatch(pathname string, flags uint64) error {
|
func (w *readDirChangesW) addWatch(pathname string, flags uint64, bufsize int) error {
|
||||||
|
pathname, recurse := recursivePath(pathname)
|
||||||
|
|
||||||
dir, err := w.getDir(pathname)
|
dir, err := w.getDir(pathname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -433,9 +348,11 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error {
|
||||||
return os.NewSyscallError("CreateIoCompletionPort", err)
|
return os.NewSyscallError("CreateIoCompletionPort", err)
|
||||||
}
|
}
|
||||||
watchEntry = &watch{
|
watchEntry = &watch{
|
||||||
ino: ino,
|
ino: ino,
|
||||||
path: dir,
|
path: dir,
|
||||||
names: make(map[string]uint64),
|
names: make(map[string]uint64),
|
||||||
|
recurse: recurse,
|
||||||
|
buf: make([]byte, bufsize),
|
||||||
}
|
}
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
w.watches.set(ino, watchEntry)
|
w.watches.set(ino, watchEntry)
|
||||||
|
|
@ -464,7 +381,9 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must run within the I/O thread.
|
// Must run within the I/O thread.
|
||||||
func (w *Watcher) remWatch(pathname string) error {
|
func (w *readDirChangesW) remWatch(pathname string) error {
|
||||||
|
pathname, recurse := recursivePath(pathname)
|
||||||
|
|
||||||
dir, err := w.getDir(pathname)
|
dir, err := w.getDir(pathname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -478,6 +397,10 @@ func (w *Watcher) remWatch(pathname string) error {
|
||||||
watch := w.watches.get(ino)
|
watch := w.watches.get(ino)
|
||||||
w.mu.Unlock()
|
w.mu.Unlock()
|
||||||
|
|
||||||
|
if recurse && !watch.recurse {
|
||||||
|
return fmt.Errorf("can't use \\... with non-recursive watch %q", pathname)
|
||||||
|
}
|
||||||
|
|
||||||
err = windows.CloseHandle(ino.handle)
|
err = windows.CloseHandle(ino.handle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.sendError(os.NewSyscallError("CloseHandle", err))
|
w.sendError(os.NewSyscallError("CloseHandle", err))
|
||||||
|
|
@ -486,11 +409,11 @@ func (w *Watcher) remWatch(pathname string) error {
|
||||||
return fmt.Errorf("%w: %s", ErrNonExistentWatch, pathname)
|
return fmt.Errorf("%w: %s", ErrNonExistentWatch, pathname)
|
||||||
}
|
}
|
||||||
if pathname == dir {
|
if pathname == dir {
|
||||||
w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
|
w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED)
|
||||||
watch.mask = 0
|
watch.mask = 0
|
||||||
} else {
|
} else {
|
||||||
name := filepath.Base(pathname)
|
name := filepath.Base(pathname)
|
||||||
w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED)
|
w.sendEvent(filepath.Join(watch.path, name), "", watch.names[name]&sysFSIGNORED)
|
||||||
delete(watch.names, name)
|
delete(watch.names, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -498,23 +421,23 @@ func (w *Watcher) remWatch(pathname string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must run within the I/O thread.
|
// Must run within the I/O thread.
|
||||||
func (w *Watcher) deleteWatch(watch *watch) {
|
func (w *readDirChangesW) deleteWatch(watch *watch) {
|
||||||
for name, mask := range watch.names {
|
for name, mask := range watch.names {
|
||||||
if mask&provisional == 0 {
|
if mask&provisional == 0 {
|
||||||
w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED)
|
w.sendEvent(filepath.Join(watch.path, name), "", mask&sysFSIGNORED)
|
||||||
}
|
}
|
||||||
delete(watch.names, name)
|
delete(watch.names, name)
|
||||||
}
|
}
|
||||||
if watch.mask != 0 {
|
if watch.mask != 0 {
|
||||||
if watch.mask&provisional == 0 {
|
if watch.mask&provisional == 0 {
|
||||||
w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
|
w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED)
|
||||||
}
|
}
|
||||||
watch.mask = 0
|
watch.mask = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must run within the I/O thread.
|
// Must run within the I/O thread.
|
||||||
func (w *Watcher) startRead(watch *watch) error {
|
func (w *readDirChangesW) startRead(watch *watch) error {
|
||||||
err := windows.CancelIo(watch.ino.handle)
|
err := windows.CancelIo(watch.ino.handle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.sendError(os.NewSyscallError("CancelIo", err))
|
w.sendError(os.NewSyscallError("CancelIo", err))
|
||||||
|
|
@ -535,13 +458,16 @@ func (w *Watcher) startRead(watch *watch) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rdErr := windows.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0],
|
// We need to pass the array, rather than the slice.
|
||||||
uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0)
|
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&watch.buf))
|
||||||
|
rdErr := windows.ReadDirectoryChanges(watch.ino.handle,
|
||||||
|
(*byte)(unsafe.Pointer(hdr.Data)), uint32(hdr.Len),
|
||||||
|
watch.recurse, mask, nil, &watch.ov, 0)
|
||||||
if rdErr != nil {
|
if rdErr != nil {
|
||||||
err := os.NewSyscallError("ReadDirectoryChanges", rdErr)
|
err := os.NewSyscallError("ReadDirectoryChanges", rdErr)
|
||||||
if rdErr == windows.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
|
if rdErr == windows.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
|
||||||
// Watched directory was probably removed
|
// Watched directory was probably removed
|
||||||
w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
|
w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF)
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
w.deleteWatch(watch)
|
w.deleteWatch(watch)
|
||||||
|
|
@ -554,7 +480,7 @@ func (w *Watcher) startRead(watch *watch) error {
|
||||||
// readEvents reads from the I/O completion port, converts the
|
// readEvents reads from the I/O completion port, converts the
|
||||||
// received events into Event objects and sends them via the Events channel.
|
// received events into Event objects and sends them via the Events channel.
|
||||||
// Entry point to the I/O thread.
|
// Entry point to the I/O thread.
|
||||||
func (w *Watcher) readEvents() {
|
func (w *readDirChangesW) readEvents() {
|
||||||
var (
|
var (
|
||||||
n uint32
|
n uint32
|
||||||
key uintptr
|
key uintptr
|
||||||
|
|
@ -563,9 +489,8 @@ func (w *Watcher) readEvents() {
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
// This error is handled after the watch == nil check below.
|
||||||
qErr := windows.GetQueuedCompletionStatus(w.port, &n, &key, &ov, windows.INFINITE)
|
qErr := windows.GetQueuedCompletionStatus(w.port, &n, &key, &ov, windows.INFINITE)
|
||||||
// This error is handled after the watch == nil check below. NOTE: this
|
|
||||||
// seems odd, note sure if it's correct.
|
|
||||||
|
|
||||||
watch := (*watch)(unsafe.Pointer(ov))
|
watch := (*watch)(unsafe.Pointer(ov))
|
||||||
if watch == nil {
|
if watch == nil {
|
||||||
|
|
@ -595,7 +520,7 @@ func (w *Watcher) readEvents() {
|
||||||
case in := <-w.input:
|
case in := <-w.input:
|
||||||
switch in.op {
|
switch in.op {
|
||||||
case opAddWatch:
|
case opAddWatch:
|
||||||
in.reply <- w.addWatch(in.path, uint64(in.flags))
|
in.reply <- w.addWatch(in.path, uint64(in.flags), in.bufsize)
|
||||||
case opRemoveWatch:
|
case opRemoveWatch:
|
||||||
in.reply <- w.remWatch(in.path)
|
in.reply <- w.remWatch(in.path)
|
||||||
}
|
}
|
||||||
|
|
@ -605,6 +530,8 @@ func (w *Watcher) readEvents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch qErr {
|
switch qErr {
|
||||||
|
case nil:
|
||||||
|
// No error
|
||||||
case windows.ERROR_MORE_DATA:
|
case windows.ERROR_MORE_DATA:
|
||||||
if watch == nil {
|
if watch == nil {
|
||||||
w.sendError(errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer"))
|
w.sendError(errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer"))
|
||||||
|
|
@ -616,7 +543,7 @@ func (w *Watcher) readEvents() {
|
||||||
}
|
}
|
||||||
case windows.ERROR_ACCESS_DENIED:
|
case windows.ERROR_ACCESS_DENIED:
|
||||||
// Watched directory was probably removed
|
// Watched directory was probably removed
|
||||||
w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
|
w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF)
|
||||||
w.deleteWatch(watch)
|
w.deleteWatch(watch)
|
||||||
w.startRead(watch)
|
w.startRead(watch)
|
||||||
continue
|
continue
|
||||||
|
|
@ -626,13 +553,12 @@ func (w *Watcher) readEvents() {
|
||||||
default:
|
default:
|
||||||
w.sendError(os.NewSyscallError("GetQueuedCompletionPort", qErr))
|
w.sendError(os.NewSyscallError("GetQueuedCompletionPort", qErr))
|
||||||
continue
|
continue
|
||||||
case nil:
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var offset uint32
|
var offset uint32
|
||||||
for {
|
for {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
w.sendError(errors.New("short read in readEvents()"))
|
w.sendError(ErrEventOverflow)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -650,6 +576,10 @@ func (w *Watcher) readEvents() {
|
||||||
name := windows.UTF16ToString(buf)
|
name := windows.UTF16ToString(buf)
|
||||||
fullname := filepath.Join(watch.path, name)
|
fullname := filepath.Join(watch.path, name)
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
internal.Debug(fullname, raw.Action)
|
||||||
|
}
|
||||||
|
|
||||||
var mask uint64
|
var mask uint64
|
||||||
switch raw.Action {
|
switch raw.Action {
|
||||||
case windows.FILE_ACTION_REMOVED:
|
case windows.FILE_ACTION_REMOVED:
|
||||||
|
|
@ -678,21 +608,22 @@ func (w *Watcher) readEvents() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sendNameEvent := func() {
|
|
||||||
w.sendEvent(fullname, watch.names[name]&mask)
|
|
||||||
}
|
|
||||||
if raw.Action != windows.FILE_ACTION_RENAMED_NEW_NAME {
|
if raw.Action != windows.FILE_ACTION_RENAMED_NEW_NAME {
|
||||||
sendNameEvent()
|
w.sendEvent(fullname, "", watch.names[name]&mask)
|
||||||
}
|
}
|
||||||
if raw.Action == windows.FILE_ACTION_REMOVED {
|
if raw.Action == windows.FILE_ACTION_REMOVED {
|
||||||
w.sendEvent(fullname, watch.names[name]&sysFSIGNORED)
|
w.sendEvent(fullname, "", watch.names[name]&sysFSIGNORED)
|
||||||
delete(watch.names, name)
|
delete(watch.names, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.sendEvent(fullname, watch.mask&w.toFSnotifyFlags(raw.Action))
|
if watch.rename != "" && raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME {
|
||||||
|
w.sendEvent(fullname, filepath.Join(watch.path, watch.rename), watch.mask&w.toFSnotifyFlags(raw.Action))
|
||||||
|
} else {
|
||||||
|
w.sendEvent(fullname, "", watch.mask&w.toFSnotifyFlags(raw.Action))
|
||||||
|
}
|
||||||
|
|
||||||
if raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME {
|
if raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME {
|
||||||
fullname = filepath.Join(watch.path, watch.rename)
|
w.sendEvent(filepath.Join(watch.path, watch.rename), "", watch.names[name]&mask)
|
||||||
sendNameEvent()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to the next event in the buffer
|
// Move to the next event in the buffer
|
||||||
|
|
@ -703,8 +634,8 @@ func (w *Watcher) readEvents() {
|
||||||
|
|
||||||
// Error!
|
// Error!
|
||||||
if offset >= n {
|
if offset >= n {
|
||||||
w.sendError(errors.New(
|
//lint:ignore ST1005 Windows should be capitalized
|
||||||
"Windows system assumed buffer larger than it is, events have likely been missed."))
|
w.sendError(errors.New("Windows system assumed buffer larger than it is, events have likely been missed"))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -715,21 +646,18 @@ func (w *Watcher) readEvents() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) toWindowsFlags(mask uint64) uint32 {
|
func (w *readDirChangesW) toWindowsFlags(mask uint64) uint32 {
|
||||||
var m uint32
|
var m uint32
|
||||||
if mask&sysFSMODIFY != 0 {
|
if mask&sysFSMODIFY != 0 {
|
||||||
m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE
|
m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE
|
||||||
}
|
}
|
||||||
if mask&sysFSATTRIB != 0 {
|
|
||||||
m |= windows.FILE_NOTIFY_CHANGE_ATTRIBUTES
|
|
||||||
}
|
|
||||||
if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 {
|
if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 {
|
||||||
m |= windows.FILE_NOTIFY_CHANGE_FILE_NAME | windows.FILE_NOTIFY_CHANGE_DIR_NAME
|
m |= windows.FILE_NOTIFY_CHANGE_FILE_NAME | windows.FILE_NOTIFY_CHANGE_DIR_NAME
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) toFSnotifyFlags(action uint32) uint64 {
|
func (w *readDirChangesW) toFSnotifyFlags(action uint32) uint64 {
|
||||||
switch action {
|
switch action {
|
||||||
case windows.FILE_ACTION_ADDED:
|
case windows.FILE_ACTION_ADDED:
|
||||||
return sysFSCREATE
|
return sysFSCREATE
|
||||||
|
|
@ -744,3 +672,11 @@ func (w *Watcher) toFSnotifyFlags(action uint32) uint64 {
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *readDirChangesW) xSupports(op Op) bool {
|
||||||
|
if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
|
||||||
|
op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
||||||
439
vendor/github.com/fsnotify/fsnotify/fsnotify.go
generated
vendored
439
vendor/github.com/fsnotify/fsnotify/fsnotify.go
generated
vendored
|
|
@ -1,16 +1,148 @@
|
||||||
//go:build !plan9
|
|
||||||
// +build !plan9
|
|
||||||
|
|
||||||
// Package fsnotify provides a cross-platform interface for file system
|
// Package fsnotify provides a cross-platform interface for file system
|
||||||
// notifications.
|
// notifications.
|
||||||
|
//
|
||||||
|
// Currently supported systems:
|
||||||
|
//
|
||||||
|
// - Linux via inotify
|
||||||
|
// - BSD, macOS via kqueue
|
||||||
|
// - Windows via ReadDirectoryChangesW
|
||||||
|
// - illumos via FEN
|
||||||
|
//
|
||||||
|
// # FSNOTIFY_DEBUG
|
||||||
|
//
|
||||||
|
// Set the FSNOTIFY_DEBUG environment variable to "1" to print debug messages to
|
||||||
|
// stderr. This can be useful to track down some problems, especially in cases
|
||||||
|
// where fsnotify is used as an indirect dependency.
|
||||||
|
//
|
||||||
|
// Every event will be printed as soon as there's something useful to print,
|
||||||
|
// with as little processing from fsnotify.
|
||||||
|
//
|
||||||
|
// Example output:
|
||||||
|
//
|
||||||
|
// FSNOTIFY_DEBUG: 11:34:23.633087586 256:IN_CREATE → "/tmp/file-1"
|
||||||
|
// FSNOTIFY_DEBUG: 11:34:23.633202319 4:IN_ATTRIB → "/tmp/file-1"
|
||||||
|
// FSNOTIFY_DEBUG: 11:34:28.989728764 512:IN_DELETE → "/tmp/file-1"
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Watcher watches a set of paths, delivering events on a channel.
|
||||||
|
//
|
||||||
|
// A watcher should not be copied (e.g. pass it by pointer, rather than by
|
||||||
|
// value).
|
||||||
|
//
|
||||||
|
// # Linux notes
|
||||||
|
//
|
||||||
|
// When a file is removed a Remove event won't be emitted until all file
|
||||||
|
// descriptors are closed, and deletes will always emit a Chmod. For example:
|
||||||
|
//
|
||||||
|
// fp := os.Open("file")
|
||||||
|
// os.Remove("file") // Triggers Chmod
|
||||||
|
// fp.Close() // Triggers Remove
|
||||||
|
//
|
||||||
|
// This is the event that inotify sends, so not much can be changed about this.
|
||||||
|
//
|
||||||
|
// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
|
||||||
|
// for the number of watches per user, and fs.inotify.max_user_instances
|
||||||
|
// specifies the maximum number of inotify instances per user. Every Watcher you
|
||||||
|
// create is an "instance", and every path you add is a "watch".
|
||||||
|
//
|
||||||
|
// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
|
||||||
|
// /proc/sys/fs/inotify/max_user_instances
|
||||||
|
//
|
||||||
|
// To increase them you can use sysctl or write the value to the /proc file:
|
||||||
|
//
|
||||||
|
// # Default values on Linux 5.18
|
||||||
|
// sysctl fs.inotify.max_user_watches=124983
|
||||||
|
// sysctl fs.inotify.max_user_instances=128
|
||||||
|
//
|
||||||
|
// To make the changes persist on reboot edit /etc/sysctl.conf or
|
||||||
|
// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
|
||||||
|
// your distro's documentation):
|
||||||
|
//
|
||||||
|
// fs.inotify.max_user_watches=124983
|
||||||
|
// fs.inotify.max_user_instances=128
|
||||||
|
//
|
||||||
|
// Reaching the limit will result in a "no space left on device" or "too many open
|
||||||
|
// files" error.
|
||||||
|
//
|
||||||
|
// # kqueue notes (macOS, BSD)
|
||||||
|
//
|
||||||
|
// kqueue requires opening a file descriptor for every file that's being watched;
|
||||||
|
// so if you're watching a directory with five files then that's six file
|
||||||
|
// descriptors. You will run in to your system's "max open files" limit faster on
|
||||||
|
// these platforms.
|
||||||
|
//
|
||||||
|
// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
|
||||||
|
// control the maximum number of open files, as well as /etc/login.conf on BSD
|
||||||
|
// systems.
|
||||||
|
//
|
||||||
|
// # Windows notes
|
||||||
|
//
|
||||||
|
// Paths can be added as "C:\\path\\to\\dir", but forward slashes
|
||||||
|
// ("C:/path/to/dir") will also work.
|
||||||
|
//
|
||||||
|
// When a watched directory is removed it will always send an event for the
|
||||||
|
// directory itself, but may not send events for all files in that directory.
|
||||||
|
// Sometimes it will send events for all files, sometimes it will send no
|
||||||
|
// events, and often only for some files.
|
||||||
|
//
|
||||||
|
// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest
|
||||||
|
// value that is guaranteed to work with SMB filesystems. If you have many
|
||||||
|
// events in quick succession this may not be enough, and you will have to use
|
||||||
|
// [WithBufferSize] to increase the value.
|
||||||
|
type Watcher struct {
|
||||||
|
b backend
|
||||||
|
|
||||||
|
// Events sends the filesystem change events.
|
||||||
|
//
|
||||||
|
// fsnotify can send the following events; a "path" here can refer to a
|
||||||
|
// file, directory, symbolic link, or special file like a FIFO.
|
||||||
|
//
|
||||||
|
// fsnotify.Create A new path was created; this may be followed by one
|
||||||
|
// or more Write events if data also gets written to a
|
||||||
|
// file.
|
||||||
|
//
|
||||||
|
// fsnotify.Remove A path was removed.
|
||||||
|
//
|
||||||
|
// fsnotify.Rename A path was renamed. A rename is always sent with the
|
||||||
|
// old path as Event.Name, and a Create event will be
|
||||||
|
// sent with the new name. Renames are only sent for
|
||||||
|
// paths that are currently watched; e.g. moving an
|
||||||
|
// unmonitored file into a monitored directory will
|
||||||
|
// show up as just a Create. Similarly, renaming a file
|
||||||
|
// to outside a monitored directory will show up as
|
||||||
|
// only a Rename.
|
||||||
|
//
|
||||||
|
// fsnotify.Write A file or named pipe was written to. A Truncate will
|
||||||
|
// also trigger a Write. A single "write action"
|
||||||
|
// initiated by the user may show up as one or multiple
|
||||||
|
// writes, depending on when the system syncs things to
|
||||||
|
// disk. For example when compiling a large Go program
|
||||||
|
// you may get hundreds of Write events, and you may
|
||||||
|
// want to wait until you've stopped receiving them
|
||||||
|
// (see the dedup example in cmd/fsnotify).
|
||||||
|
//
|
||||||
|
// Some systems may send Write event for directories
|
||||||
|
// when the directory content changes.
|
||||||
|
//
|
||||||
|
// fsnotify.Chmod Attributes were changed. On Linux this is also sent
|
||||||
|
// when a file is removed (or more accurately, when a
|
||||||
|
// link to an inode is removed). On kqueue it's sent
|
||||||
|
// when a file is truncated. On Windows it's never
|
||||||
|
// sent.
|
||||||
|
Events chan Event
|
||||||
|
|
||||||
|
// Errors sends any errors.
|
||||||
|
Errors chan error
|
||||||
|
}
|
||||||
|
|
||||||
// Event represents a file system notification.
|
// Event represents a file system notification.
|
||||||
type Event struct {
|
type Event struct {
|
||||||
// Path to the file or directory.
|
// Path to the file or directory.
|
||||||
|
|
@ -25,6 +157,16 @@ type Event struct {
|
||||||
// This is a bitmask and some systems may send multiple operations at once.
|
// This is a bitmask and some systems may send multiple operations at once.
|
||||||
// Use the Event.Has() method instead of comparing with ==.
|
// Use the Event.Has() method instead of comparing with ==.
|
||||||
Op Op
|
Op Op
|
||||||
|
|
||||||
|
// Create events will have this set to the old path if it's a rename. This
|
||||||
|
// only works when both the source and destination are watched. It's not
|
||||||
|
// reliable when watching individual files, only directories.
|
||||||
|
//
|
||||||
|
// For example "mv /tmp/file /tmp/rename" will emit:
|
||||||
|
//
|
||||||
|
// Event{Op: Rename, Name: "/tmp/file"}
|
||||||
|
// Event{Op: Create, Name: "/tmp/rename", RenamedFrom: "/tmp/file"}
|
||||||
|
renamedFrom string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Op describes a set of file operations.
|
// Op describes a set of file operations.
|
||||||
|
|
@ -33,34 +175,204 @@ type Op uint32
|
||||||
// The operations fsnotify can trigger; see the documentation on [Watcher] for a
|
// The operations fsnotify can trigger; see the documentation on [Watcher] for a
|
||||||
// full description, and check them with [Event.Has].
|
// full description, and check them with [Event.Has].
|
||||||
const (
|
const (
|
||||||
|
// A new pathname was created.
|
||||||
Create Op = 1 << iota
|
Create Op = 1 << iota
|
||||||
|
|
||||||
|
// The pathname was written to; this does *not* mean the write has finished,
|
||||||
|
// and a write can be followed by more writes.
|
||||||
Write
|
Write
|
||||||
|
|
||||||
|
// The path was removed; any watches on it will be removed. Some "remove"
|
||||||
|
// operations may trigger a Rename if the file is actually moved (for
|
||||||
|
// example "remove to trash" is often a rename).
|
||||||
Remove
|
Remove
|
||||||
|
|
||||||
|
// The path was renamed to something else; any watches on it will be
|
||||||
|
// removed.
|
||||||
Rename
|
Rename
|
||||||
|
|
||||||
|
// File attributes were changed.
|
||||||
|
//
|
||||||
|
// It's generally not recommended to take action on this event, as it may
|
||||||
|
// get triggered very frequently by some software. For example, Spotlight
|
||||||
|
// indexing on macOS, anti-virus software, backup software, etc.
|
||||||
Chmod
|
Chmod
|
||||||
|
|
||||||
|
// File descriptor was opened.
|
||||||
|
//
|
||||||
|
// Only works on Linux and FreeBSD.
|
||||||
|
xUnportableOpen
|
||||||
|
|
||||||
|
// File was read from.
|
||||||
|
//
|
||||||
|
// Only works on Linux and FreeBSD.
|
||||||
|
xUnportableRead
|
||||||
|
|
||||||
|
// File opened for writing was closed.
|
||||||
|
//
|
||||||
|
// Only works on Linux and FreeBSD.
|
||||||
|
//
|
||||||
|
// The advantage of using this over Write is that it's more reliable than
|
||||||
|
// waiting for Write events to stop. It's also faster (if you're not
|
||||||
|
// listening to Write events): copying a file of a few GB can easily
|
||||||
|
// generate tens of thousands of Write events in a short span of time.
|
||||||
|
xUnportableCloseWrite
|
||||||
|
|
||||||
|
// File opened for reading was closed.
|
||||||
|
//
|
||||||
|
// Only works on Linux and FreeBSD.
|
||||||
|
xUnportableCloseRead
|
||||||
)
|
)
|
||||||
|
|
||||||
// Common errors that can be reported by a watcher
|
|
||||||
var (
|
var (
|
||||||
ErrNonExistentWatch = errors.New("can't remove non-existent watcher")
|
// ErrNonExistentWatch is used when Remove() is called on a path that's not
|
||||||
ErrEventOverflow = errors.New("fsnotify queue overflow")
|
// added.
|
||||||
|
ErrNonExistentWatch = errors.New("fsnotify: can't remove non-existent watch")
|
||||||
|
|
||||||
|
// ErrClosed is used when trying to operate on a closed Watcher.
|
||||||
|
ErrClosed = errors.New("fsnotify: watcher already closed")
|
||||||
|
|
||||||
|
// ErrEventOverflow is reported from the Errors channel when there are too
|
||||||
|
// many events:
|
||||||
|
//
|
||||||
|
// - inotify: inotify returns IN_Q_OVERFLOW – because there are too
|
||||||
|
// many queued events (the fs.inotify.max_queued_events
|
||||||
|
// sysctl can be used to increase this).
|
||||||
|
// - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
|
||||||
|
// - kqueue, fen: Not used.
|
||||||
|
ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow")
|
||||||
|
|
||||||
|
// ErrUnsupported is returned by AddWith() when WithOps() specified an
|
||||||
|
// Unportable event that's not supported on this platform.
|
||||||
|
xErrUnsupported = errors.New("fsnotify: not supported with this backend")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (op Op) String() string {
|
// NewWatcher creates a new Watcher.
|
||||||
|
func NewWatcher() (*Watcher, error) {
|
||||||
|
ev, errs := make(chan Event), make(chan error)
|
||||||
|
b, err := newBackend(ev, errs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Watcher{b: b, Events: ev, Errors: errs}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events
|
||||||
|
// channel.
|
||||||
|
//
|
||||||
|
// The main use case for this is situations with a very large number of events
|
||||||
|
// where the kernel buffer size can't be increased (e.g. due to lack of
|
||||||
|
// permissions). An unbuffered Watcher will perform better for almost all use
|
||||||
|
// cases, and whenever possible you will be better off increasing the kernel
|
||||||
|
// buffers instead of adding a large userspace buffer.
|
||||||
|
func NewBufferedWatcher(sz uint) (*Watcher, error) {
|
||||||
|
ev, errs := make(chan Event), make(chan error)
|
||||||
|
b, err := newBufferedBackend(sz, ev, errs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Watcher{b: b, Events: ev, Errors: errs}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add starts monitoring the path for changes.
|
||||||
|
//
|
||||||
|
// A path can only be watched once; watching it more than once is a no-op and will
|
||||||
|
// not return an error. Paths that do not yet exist on the filesystem cannot be
|
||||||
|
// watched.
|
||||||
|
//
|
||||||
|
// A watch will be automatically removed if the watched path is deleted or
|
||||||
|
// renamed. The exception is the Windows backend, which doesn't remove the
|
||||||
|
// watcher on renames.
|
||||||
|
//
|
||||||
|
// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
|
||||||
|
// filesystems (/proc, /sys, etc.) generally don't work.
|
||||||
|
//
|
||||||
|
// Returns [ErrClosed] if [Watcher.Close] was called.
|
||||||
|
//
|
||||||
|
// See [Watcher.AddWith] for a version that allows adding options.
|
||||||
|
//
|
||||||
|
// # Watching directories
|
||||||
|
//
|
||||||
|
// All files in a directory are monitored, including new files that are created
|
||||||
|
// after the watcher is started. Subdirectories are not watched (i.e. it's
|
||||||
|
// non-recursive).
|
||||||
|
//
|
||||||
|
// # Watching files
|
||||||
|
//
|
||||||
|
// Watching individual files (rather than directories) is generally not
|
||||||
|
// recommended as many programs (especially editors) update files atomically: it
|
||||||
|
// will write to a temporary file which is then moved to destination,
|
||||||
|
// overwriting the original (or some variant thereof). The watcher on the
|
||||||
|
// original file is now lost, as that no longer exists.
|
||||||
|
//
|
||||||
|
// The upshot of this is that a power failure or crash won't leave a
|
||||||
|
// half-written file.
|
||||||
|
//
|
||||||
|
// Watch the parent directory and use Event.Name to filter out files you're not
|
||||||
|
// interested in. There is an example of this in cmd/fsnotify/file.go.
|
||||||
|
func (w *Watcher) Add(path string) error { return w.b.Add(path) }
|
||||||
|
|
||||||
|
// AddWith is like [Watcher.Add], but allows adding options. When using Add()
|
||||||
|
// the defaults described below are used.
|
||||||
|
//
|
||||||
|
// Possible options are:
|
||||||
|
//
|
||||||
|
// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on
|
||||||
|
// other platforms. The default is 64K (65536 bytes).
|
||||||
|
func (w *Watcher) AddWith(path string, opts ...addOpt) error { return w.b.AddWith(path, opts...) }
|
||||||
|
|
||||||
|
// Remove stops monitoring the path for changes.
|
||||||
|
//
|
||||||
|
// Directories are always removed non-recursively. For example, if you added
|
||||||
|
// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
|
||||||
|
//
|
||||||
|
// Removing a path that has not yet been added returns [ErrNonExistentWatch].
|
||||||
|
//
|
||||||
|
// Returns nil if [Watcher.Close] was called.
|
||||||
|
func (w *Watcher) Remove(path string) error { return w.b.Remove(path) }
|
||||||
|
|
||||||
|
// Close removes all watches and closes the Events channel.
|
||||||
|
func (w *Watcher) Close() error { return w.b.Close() }
|
||||||
|
|
||||||
|
// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
|
||||||
|
// yet removed).
|
||||||
|
//
|
||||||
|
// Returns nil if [Watcher.Close] was called.
|
||||||
|
func (w *Watcher) WatchList() []string { return w.b.WatchList() }
|
||||||
|
|
||||||
|
// Supports reports if all the listed operations are supported by this platform.
|
||||||
|
//
|
||||||
|
// Create, Write, Remove, Rename, and Chmod are always supported. It can only
|
||||||
|
// return false for an Op starting with Unportable.
|
||||||
|
func (w *Watcher) xSupports(op Op) bool { return w.b.xSupports(op) }
|
||||||
|
|
||||||
|
func (o Op) String() string {
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
if op.Has(Create) {
|
if o.Has(Create) {
|
||||||
b.WriteString("|CREATE")
|
b.WriteString("|CREATE")
|
||||||
}
|
}
|
||||||
if op.Has(Remove) {
|
if o.Has(Remove) {
|
||||||
b.WriteString("|REMOVE")
|
b.WriteString("|REMOVE")
|
||||||
}
|
}
|
||||||
if op.Has(Write) {
|
if o.Has(Write) {
|
||||||
b.WriteString("|WRITE")
|
b.WriteString("|WRITE")
|
||||||
}
|
}
|
||||||
if op.Has(Rename) {
|
if o.Has(xUnportableOpen) {
|
||||||
|
b.WriteString("|OPEN")
|
||||||
|
}
|
||||||
|
if o.Has(xUnportableRead) {
|
||||||
|
b.WriteString("|READ")
|
||||||
|
}
|
||||||
|
if o.Has(xUnportableCloseWrite) {
|
||||||
|
b.WriteString("|CLOSE_WRITE")
|
||||||
|
}
|
||||||
|
if o.Has(xUnportableCloseRead) {
|
||||||
|
b.WriteString("|CLOSE_READ")
|
||||||
|
}
|
||||||
|
if o.Has(Rename) {
|
||||||
b.WriteString("|RENAME")
|
b.WriteString("|RENAME")
|
||||||
}
|
}
|
||||||
if op.Has(Chmod) {
|
if o.Has(Chmod) {
|
||||||
b.WriteString("|CHMOD")
|
b.WriteString("|CHMOD")
|
||||||
}
|
}
|
||||||
if b.Len() == 0 {
|
if b.Len() == 0 {
|
||||||
|
|
@ -70,12 +382,113 @@ func (op Op) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has reports if this operation has the given operation.
|
// Has reports if this operation has the given operation.
|
||||||
func (o Op) Has(h Op) bool { return o&h == h }
|
func (o Op) Has(h Op) bool { return o&h != 0 }
|
||||||
|
|
||||||
// Has reports if this event has the given operation.
|
// Has reports if this event has the given operation.
|
||||||
func (e Event) Has(op Op) bool { return e.Op.Has(op) }
|
func (e Event) Has(op Op) bool { return e.Op.Has(op) }
|
||||||
|
|
||||||
// String returns a string representation of the event with their path.
|
// String returns a string representation of the event with their path.
|
||||||
func (e Event) String() string {
|
func (e Event) String() string {
|
||||||
|
if e.renamedFrom != "" {
|
||||||
|
return fmt.Sprintf("%-13s %q ← %q", e.Op.String(), e.Name, e.renamedFrom)
|
||||||
|
}
|
||||||
return fmt.Sprintf("%-13s %q", e.Op.String(), e.Name)
|
return fmt.Sprintf("%-13s %q", e.Op.String(), e.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
backend interface {
|
||||||
|
Add(string) error
|
||||||
|
AddWith(string, ...addOpt) error
|
||||||
|
Remove(string) error
|
||||||
|
WatchList() []string
|
||||||
|
Close() error
|
||||||
|
xSupports(Op) bool
|
||||||
|
}
|
||||||
|
addOpt func(opt *withOpts)
|
||||||
|
withOpts struct {
|
||||||
|
bufsize int
|
||||||
|
op Op
|
||||||
|
noFollow bool
|
||||||
|
sendCreate bool
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var debug = func() bool {
|
||||||
|
// Check for exactly "1" (rather than mere existence) so we can add
|
||||||
|
// options/flags in the future. I don't know if we ever want that, but it's
|
||||||
|
// nice to leave the option open.
|
||||||
|
return os.Getenv("FSNOTIFY_DEBUG") == "1"
|
||||||
|
}()
|
||||||
|
|
||||||
|
var defaultOpts = withOpts{
|
||||||
|
bufsize: 65536, // 64K
|
||||||
|
op: Create | Write | Remove | Rename | Chmod,
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOptions(opts ...addOpt) withOpts {
|
||||||
|
with := defaultOpts
|
||||||
|
for _, o := range opts {
|
||||||
|
if o != nil {
|
||||||
|
o(&with)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return with
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithBufferSize sets the [ReadDirectoryChangesW] buffer size.
|
||||||
|
//
|
||||||
|
// This only has effect on Windows systems, and is a no-op for other backends.
|
||||||
|
//
|
||||||
|
// The default value is 64K (65536 bytes) which is the highest value that works
|
||||||
|
// on all filesystems and should be enough for most applications, but if you
|
||||||
|
// have a large burst of events it may not be enough. You can increase it if
|
||||||
|
// you're hitting "queue or buffer overflow" errors ([ErrEventOverflow]).
|
||||||
|
//
|
||||||
|
// [ReadDirectoryChangesW]: https://learn.microsoft.com/en-gb/windows/win32/api/winbase/nf-winbase-readdirectorychangesw
|
||||||
|
func WithBufferSize(bytes int) addOpt {
|
||||||
|
return func(opt *withOpts) { opt.bufsize = bytes }
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithOps sets which operations to listen for. The default is [Create],
|
||||||
|
// [Write], [Remove], [Rename], and [Chmod].
|
||||||
|
//
|
||||||
|
// Excluding operations you're not interested in can save quite a bit of CPU
|
||||||
|
// time; in some use cases there may be hundreds of thousands of useless Write
|
||||||
|
// or Chmod operations per second.
|
||||||
|
//
|
||||||
|
// This can also be used to add unportable operations not supported by all
|
||||||
|
// platforms; unportable operations all start with "Unportable":
|
||||||
|
// [UnportableOpen], [UnportableRead], [UnportableCloseWrite], and
|
||||||
|
// [UnportableCloseRead].
|
||||||
|
//
|
||||||
|
// AddWith returns an error when using an unportable operation that's not
|
||||||
|
// supported. Use [Watcher.Support] to check for support.
|
||||||
|
func withOps(op Op) addOpt {
|
||||||
|
return func(opt *withOpts) { opt.op = op }
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithNoFollow disables following symlinks, so the symlinks themselves are
|
||||||
|
// watched.
|
||||||
|
func withNoFollow() addOpt {
|
||||||
|
return func(opt *withOpts) { opt.noFollow = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Internal" option for recursive watches on inotify.
|
||||||
|
func withCreate() addOpt {
|
||||||
|
return func(opt *withOpts) { opt.sendCreate = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
var enableRecurse = false
|
||||||
|
|
||||||
|
// Check if this path is recursive (ends with "/..." or "\..."), and return the
|
||||||
|
// path with the /... stripped.
|
||||||
|
func recursivePath(path string) (string, bool) {
|
||||||
|
path = filepath.Clean(path)
|
||||||
|
if !enableRecurse { // Only enabled in tests for now.
|
||||||
|
return path, false
|
||||||
|
}
|
||||||
|
if filepath.Base(path) == "..." {
|
||||||
|
return filepath.Dir(path), true
|
||||||
|
}
|
||||||
|
return path, false
|
||||||
|
}
|
||||||
|
|
|
||||||
39
vendor/github.com/fsnotify/fsnotify/internal/darwin.go
generated
vendored
Normal file
39
vendor/github.com/fsnotify/fsnotify/internal/darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
//go:build darwin
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
SyscallEACCES = syscall.EACCES
|
||||||
|
UnixEACCES = unix.EACCES
|
||||||
|
)
|
||||||
|
|
||||||
|
var maxfiles uint64
|
||||||
|
|
||||||
|
// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
|
||||||
|
func SetRlimit() {
|
||||||
|
var l syscall.Rlimit
|
||||||
|
err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
|
||||||
|
if err == nil && l.Cur != l.Max {
|
||||||
|
l.Cur = l.Max
|
||||||
|
syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
|
||||||
|
}
|
||||||
|
maxfiles = l.Cur
|
||||||
|
|
||||||
|
if n, err := syscall.SysctlUint32("kern.maxfiles"); err == nil && uint64(n) < maxfiles {
|
||||||
|
maxfiles = uint64(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n, err := syscall.SysctlUint32("kern.maxfilesperproc"); err == nil && uint64(n) < maxfiles {
|
||||||
|
maxfiles = uint64(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Maxfiles() uint64 { return maxfiles }
|
||||||
|
func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) }
|
||||||
|
func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) }
|
||||||
57
vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go
generated
vendored
Normal file
57
vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
var names = []struct {
|
||||||
|
n string
|
||||||
|
m uint32
|
||||||
|
}{
|
||||||
|
{"NOTE_ABSOLUTE", unix.NOTE_ABSOLUTE},
|
||||||
|
{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
|
||||||
|
{"NOTE_BACKGROUND", unix.NOTE_BACKGROUND},
|
||||||
|
{"NOTE_CHILD", unix.NOTE_CHILD},
|
||||||
|
{"NOTE_CRITICAL", unix.NOTE_CRITICAL},
|
||||||
|
{"NOTE_DELETE", unix.NOTE_DELETE},
|
||||||
|
{"NOTE_EXEC", unix.NOTE_EXEC},
|
||||||
|
{"NOTE_EXIT", unix.NOTE_EXIT},
|
||||||
|
{"NOTE_EXITSTATUS", unix.NOTE_EXITSTATUS},
|
||||||
|
{"NOTE_EXIT_CSERROR", unix.NOTE_EXIT_CSERROR},
|
||||||
|
{"NOTE_EXIT_DECRYPTFAIL", unix.NOTE_EXIT_DECRYPTFAIL},
|
||||||
|
{"NOTE_EXIT_DETAIL", unix.NOTE_EXIT_DETAIL},
|
||||||
|
{"NOTE_EXIT_DETAIL_MASK", unix.NOTE_EXIT_DETAIL_MASK},
|
||||||
|
{"NOTE_EXIT_MEMORY", unix.NOTE_EXIT_MEMORY},
|
||||||
|
{"NOTE_EXIT_REPARENTED", unix.NOTE_EXIT_REPARENTED},
|
||||||
|
{"NOTE_EXTEND", unix.NOTE_EXTEND},
|
||||||
|
{"NOTE_FFAND", unix.NOTE_FFAND},
|
||||||
|
{"NOTE_FFCOPY", unix.NOTE_FFCOPY},
|
||||||
|
{"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
|
||||||
|
{"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
|
||||||
|
{"NOTE_FFNOP", unix.NOTE_FFNOP},
|
||||||
|
{"NOTE_FFOR", unix.NOTE_FFOR},
|
||||||
|
{"NOTE_FORK", unix.NOTE_FORK},
|
||||||
|
{"NOTE_FUNLOCK", unix.NOTE_FUNLOCK},
|
||||||
|
{"NOTE_LEEWAY", unix.NOTE_LEEWAY},
|
||||||
|
{"NOTE_LINK", unix.NOTE_LINK},
|
||||||
|
{"NOTE_LOWAT", unix.NOTE_LOWAT},
|
||||||
|
{"NOTE_MACHTIME", unix.NOTE_MACHTIME},
|
||||||
|
{"NOTE_MACH_CONTINUOUS_TIME", unix.NOTE_MACH_CONTINUOUS_TIME},
|
||||||
|
{"NOTE_NONE", unix.NOTE_NONE},
|
||||||
|
{"NOTE_NSECONDS", unix.NOTE_NSECONDS},
|
||||||
|
{"NOTE_OOB", unix.NOTE_OOB},
|
||||||
|
//{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, -0x100000 (?!)
|
||||||
|
{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
|
||||||
|
{"NOTE_REAP", unix.NOTE_REAP},
|
||||||
|
{"NOTE_RENAME", unix.NOTE_RENAME},
|
||||||
|
{"NOTE_REVOKE", unix.NOTE_REVOKE},
|
||||||
|
{"NOTE_SECONDS", unix.NOTE_SECONDS},
|
||||||
|
{"NOTE_SIGNAL", unix.NOTE_SIGNAL},
|
||||||
|
{"NOTE_TRACK", unix.NOTE_TRACK},
|
||||||
|
{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
|
||||||
|
{"NOTE_TRIGGER", unix.NOTE_TRIGGER},
|
||||||
|
{"NOTE_USECONDS", unix.NOTE_USECONDS},
|
||||||
|
{"NOTE_VM_ERROR", unix.NOTE_VM_ERROR},
|
||||||
|
{"NOTE_VM_PRESSURE", unix.NOTE_VM_PRESSURE},
|
||||||
|
{"NOTE_VM_PRESSURE_SUDDEN_TERMINATE", unix.NOTE_VM_PRESSURE_SUDDEN_TERMINATE},
|
||||||
|
{"NOTE_VM_PRESSURE_TERMINATE", unix.NOTE_VM_PRESSURE_TERMINATE},
|
||||||
|
{"NOTE_WRITE", unix.NOTE_WRITE},
|
||||||
|
}
|
||||||
33
vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go
generated
vendored
Normal file
33
vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
var names = []struct {
|
||||||
|
n string
|
||||||
|
m uint32
|
||||||
|
}{
|
||||||
|
{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
|
||||||
|
{"NOTE_CHILD", unix.NOTE_CHILD},
|
||||||
|
{"NOTE_DELETE", unix.NOTE_DELETE},
|
||||||
|
{"NOTE_EXEC", unix.NOTE_EXEC},
|
||||||
|
{"NOTE_EXIT", unix.NOTE_EXIT},
|
||||||
|
{"NOTE_EXTEND", unix.NOTE_EXTEND},
|
||||||
|
{"NOTE_FFAND", unix.NOTE_FFAND},
|
||||||
|
{"NOTE_FFCOPY", unix.NOTE_FFCOPY},
|
||||||
|
{"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
|
||||||
|
{"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
|
||||||
|
{"NOTE_FFNOP", unix.NOTE_FFNOP},
|
||||||
|
{"NOTE_FFOR", unix.NOTE_FFOR},
|
||||||
|
{"NOTE_FORK", unix.NOTE_FORK},
|
||||||
|
{"NOTE_LINK", unix.NOTE_LINK},
|
||||||
|
{"NOTE_LOWAT", unix.NOTE_LOWAT},
|
||||||
|
{"NOTE_OOB", unix.NOTE_OOB},
|
||||||
|
{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
|
||||||
|
{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
|
||||||
|
{"NOTE_RENAME", unix.NOTE_RENAME},
|
||||||
|
{"NOTE_REVOKE", unix.NOTE_REVOKE},
|
||||||
|
{"NOTE_TRACK", unix.NOTE_TRACK},
|
||||||
|
{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
|
||||||
|
{"NOTE_TRIGGER", unix.NOTE_TRIGGER},
|
||||||
|
{"NOTE_WRITE", unix.NOTE_WRITE},
|
||||||
|
}
|
||||||
42
vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go
generated
vendored
Normal file
42
vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
var names = []struct {
|
||||||
|
n string
|
||||||
|
m uint32
|
||||||
|
}{
|
||||||
|
{"NOTE_ABSTIME", unix.NOTE_ABSTIME},
|
||||||
|
{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
|
||||||
|
{"NOTE_CHILD", unix.NOTE_CHILD},
|
||||||
|
{"NOTE_CLOSE", unix.NOTE_CLOSE},
|
||||||
|
{"NOTE_CLOSE_WRITE", unix.NOTE_CLOSE_WRITE},
|
||||||
|
{"NOTE_DELETE", unix.NOTE_DELETE},
|
||||||
|
{"NOTE_EXEC", unix.NOTE_EXEC},
|
||||||
|
{"NOTE_EXIT", unix.NOTE_EXIT},
|
||||||
|
{"NOTE_EXTEND", unix.NOTE_EXTEND},
|
||||||
|
{"NOTE_FFAND", unix.NOTE_FFAND},
|
||||||
|
{"NOTE_FFCOPY", unix.NOTE_FFCOPY},
|
||||||
|
{"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
|
||||||
|
{"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
|
||||||
|
{"NOTE_FFNOP", unix.NOTE_FFNOP},
|
||||||
|
{"NOTE_FFOR", unix.NOTE_FFOR},
|
||||||
|
{"NOTE_FILE_POLL", unix.NOTE_FILE_POLL},
|
||||||
|
{"NOTE_FORK", unix.NOTE_FORK},
|
||||||
|
{"NOTE_LINK", unix.NOTE_LINK},
|
||||||
|
{"NOTE_LOWAT", unix.NOTE_LOWAT},
|
||||||
|
{"NOTE_MSECONDS", unix.NOTE_MSECONDS},
|
||||||
|
{"NOTE_NSECONDS", unix.NOTE_NSECONDS},
|
||||||
|
{"NOTE_OPEN", unix.NOTE_OPEN},
|
||||||
|
{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
|
||||||
|
{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
|
||||||
|
{"NOTE_READ", unix.NOTE_READ},
|
||||||
|
{"NOTE_RENAME", unix.NOTE_RENAME},
|
||||||
|
{"NOTE_REVOKE", unix.NOTE_REVOKE},
|
||||||
|
{"NOTE_SECONDS", unix.NOTE_SECONDS},
|
||||||
|
{"NOTE_TRACK", unix.NOTE_TRACK},
|
||||||
|
{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
|
||||||
|
{"NOTE_TRIGGER", unix.NOTE_TRIGGER},
|
||||||
|
{"NOTE_USECONDS", unix.NOTE_USECONDS},
|
||||||
|
{"NOTE_WRITE", unix.NOTE_WRITE},
|
||||||
|
}
|
||||||
32
vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go
generated
vendored
Normal file
32
vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
//go:build freebsd || openbsd || netbsd || dragonfly || darwin
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Debug(name string, kevent *unix.Kevent_t) {
|
||||||
|
mask := uint32(kevent.Fflags)
|
||||||
|
|
||||||
|
var (
|
||||||
|
l []string
|
||||||
|
unknown = mask
|
||||||
|
)
|
||||||
|
for _, n := range names {
|
||||||
|
if mask&n.m == n.m {
|
||||||
|
l = append(l, n.n)
|
||||||
|
unknown ^= n.m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if unknown > 0 {
|
||||||
|
l = append(l, fmt.Sprintf("0x%x", unknown))
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %10d:%-60s → %q\n",
|
||||||
|
time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name)
|
||||||
|
}
|
||||||
56
vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go
generated
vendored
Normal file
56
vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Debug(name string, mask, cookie uint32) {
|
||||||
|
names := []struct {
|
||||||
|
n string
|
||||||
|
m uint32
|
||||||
|
}{
|
||||||
|
{"IN_ACCESS", unix.IN_ACCESS},
|
||||||
|
{"IN_ATTRIB", unix.IN_ATTRIB},
|
||||||
|
{"IN_CLOSE", unix.IN_CLOSE},
|
||||||
|
{"IN_CLOSE_NOWRITE", unix.IN_CLOSE_NOWRITE},
|
||||||
|
{"IN_CLOSE_WRITE", unix.IN_CLOSE_WRITE},
|
||||||
|
{"IN_CREATE", unix.IN_CREATE},
|
||||||
|
{"IN_DELETE", unix.IN_DELETE},
|
||||||
|
{"IN_DELETE_SELF", unix.IN_DELETE_SELF},
|
||||||
|
{"IN_IGNORED", unix.IN_IGNORED},
|
||||||
|
{"IN_ISDIR", unix.IN_ISDIR},
|
||||||
|
{"IN_MODIFY", unix.IN_MODIFY},
|
||||||
|
{"IN_MOVE", unix.IN_MOVE},
|
||||||
|
{"IN_MOVED_FROM", unix.IN_MOVED_FROM},
|
||||||
|
{"IN_MOVED_TO", unix.IN_MOVED_TO},
|
||||||
|
{"IN_MOVE_SELF", unix.IN_MOVE_SELF},
|
||||||
|
{"IN_OPEN", unix.IN_OPEN},
|
||||||
|
{"IN_Q_OVERFLOW", unix.IN_Q_OVERFLOW},
|
||||||
|
{"IN_UNMOUNT", unix.IN_UNMOUNT},
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
l []string
|
||||||
|
unknown = mask
|
||||||
|
)
|
||||||
|
for _, n := range names {
|
||||||
|
if mask&n.m == n.m {
|
||||||
|
l = append(l, n.n)
|
||||||
|
unknown ^= n.m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if unknown > 0 {
|
||||||
|
l = append(l, fmt.Sprintf("0x%x", unknown))
|
||||||
|
}
|
||||||
|
var c string
|
||||||
|
if cookie > 0 {
|
||||||
|
c = fmt.Sprintf("(cookie: %d) ", cookie)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %-30s → %s%q\n",
|
||||||
|
time.Now().Format("15:04:05.000000000"), strings.Join(l, "|"), c, name)
|
||||||
|
}
|
||||||
25
vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go
generated
vendored
Normal file
25
vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
var names = []struct {
|
||||||
|
n string
|
||||||
|
m uint32
|
||||||
|
}{
|
||||||
|
{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
|
||||||
|
{"NOTE_CHILD", unix.NOTE_CHILD},
|
||||||
|
{"NOTE_DELETE", unix.NOTE_DELETE},
|
||||||
|
{"NOTE_EXEC", unix.NOTE_EXEC},
|
||||||
|
{"NOTE_EXIT", unix.NOTE_EXIT},
|
||||||
|
{"NOTE_EXTEND", unix.NOTE_EXTEND},
|
||||||
|
{"NOTE_FORK", unix.NOTE_FORK},
|
||||||
|
{"NOTE_LINK", unix.NOTE_LINK},
|
||||||
|
{"NOTE_LOWAT", unix.NOTE_LOWAT},
|
||||||
|
{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
|
||||||
|
{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
|
||||||
|
{"NOTE_RENAME", unix.NOTE_RENAME},
|
||||||
|
{"NOTE_REVOKE", unix.NOTE_REVOKE},
|
||||||
|
{"NOTE_TRACK", unix.NOTE_TRACK},
|
||||||
|
{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
|
||||||
|
{"NOTE_WRITE", unix.NOTE_WRITE},
|
||||||
|
}
|
||||||
28
vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go
generated
vendored
Normal file
28
vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
var names = []struct {
|
||||||
|
n string
|
||||||
|
m uint32
|
||||||
|
}{
|
||||||
|
{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
|
||||||
|
// {"NOTE_CHANGE", unix.NOTE_CHANGE}, // Not on 386?
|
||||||
|
{"NOTE_CHILD", unix.NOTE_CHILD},
|
||||||
|
{"NOTE_DELETE", unix.NOTE_DELETE},
|
||||||
|
{"NOTE_EOF", unix.NOTE_EOF},
|
||||||
|
{"NOTE_EXEC", unix.NOTE_EXEC},
|
||||||
|
{"NOTE_EXIT", unix.NOTE_EXIT},
|
||||||
|
{"NOTE_EXTEND", unix.NOTE_EXTEND},
|
||||||
|
{"NOTE_FORK", unix.NOTE_FORK},
|
||||||
|
{"NOTE_LINK", unix.NOTE_LINK},
|
||||||
|
{"NOTE_LOWAT", unix.NOTE_LOWAT},
|
||||||
|
{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
|
||||||
|
{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
|
||||||
|
{"NOTE_RENAME", unix.NOTE_RENAME},
|
||||||
|
{"NOTE_REVOKE", unix.NOTE_REVOKE},
|
||||||
|
{"NOTE_TRACK", unix.NOTE_TRACK},
|
||||||
|
{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
|
||||||
|
{"NOTE_TRUNCATE", unix.NOTE_TRUNCATE},
|
||||||
|
{"NOTE_WRITE", unix.NOTE_WRITE},
|
||||||
|
}
|
||||||
45
vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go
generated
vendored
Normal file
45
vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go
generated
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Debug(name string, mask int32) {
|
||||||
|
names := []struct {
|
||||||
|
n string
|
||||||
|
m int32
|
||||||
|
}{
|
||||||
|
{"FILE_ACCESS", unix.FILE_ACCESS},
|
||||||
|
{"FILE_MODIFIED", unix.FILE_MODIFIED},
|
||||||
|
{"FILE_ATTRIB", unix.FILE_ATTRIB},
|
||||||
|
{"FILE_TRUNC", unix.FILE_TRUNC},
|
||||||
|
{"FILE_NOFOLLOW", unix.FILE_NOFOLLOW},
|
||||||
|
{"FILE_DELETE", unix.FILE_DELETE},
|
||||||
|
{"FILE_RENAME_TO", unix.FILE_RENAME_TO},
|
||||||
|
{"FILE_RENAME_FROM", unix.FILE_RENAME_FROM},
|
||||||
|
{"UNMOUNTED", unix.UNMOUNTED},
|
||||||
|
{"MOUNTEDOVER", unix.MOUNTEDOVER},
|
||||||
|
{"FILE_EXCEPTION", unix.FILE_EXCEPTION},
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
l []string
|
||||||
|
unknown = mask
|
||||||
|
)
|
||||||
|
for _, n := range names {
|
||||||
|
if mask&n.m == n.m {
|
||||||
|
l = append(l, n.n)
|
||||||
|
unknown ^= n.m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if unknown > 0 {
|
||||||
|
l = append(l, fmt.Sprintf("0x%x", unknown))
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %10d:%-30s → %q\n",
|
||||||
|
time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name)
|
||||||
|
}
|
||||||
40
vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go
generated
vendored
Normal file
40
vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go
generated
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Debug(name string, mask uint32) {
|
||||||
|
names := []struct {
|
||||||
|
n string
|
||||||
|
m uint32
|
||||||
|
}{
|
||||||
|
{"FILE_ACTION_ADDED", windows.FILE_ACTION_ADDED},
|
||||||
|
{"FILE_ACTION_REMOVED", windows.FILE_ACTION_REMOVED},
|
||||||
|
{"FILE_ACTION_MODIFIED", windows.FILE_ACTION_MODIFIED},
|
||||||
|
{"FILE_ACTION_RENAMED_OLD_NAME", windows.FILE_ACTION_RENAMED_OLD_NAME},
|
||||||
|
{"FILE_ACTION_RENAMED_NEW_NAME", windows.FILE_ACTION_RENAMED_NEW_NAME},
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
l []string
|
||||||
|
unknown = mask
|
||||||
|
)
|
||||||
|
for _, n := range names {
|
||||||
|
if mask&n.m == n.m {
|
||||||
|
l = append(l, n.n)
|
||||||
|
unknown ^= n.m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if unknown > 0 {
|
||||||
|
l = append(l, fmt.Sprintf("0x%x", unknown))
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %-65s → %q\n",
|
||||||
|
time.Now().Format("15:04:05.000000000"), strings.Join(l, " | "), filepath.ToSlash(name))
|
||||||
|
}
|
||||||
31
vendor/github.com/fsnotify/fsnotify/internal/freebsd.go
generated
vendored
Normal file
31
vendor/github.com/fsnotify/fsnotify/internal/freebsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
//go:build freebsd
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
SyscallEACCES = syscall.EACCES
|
||||||
|
UnixEACCES = unix.EACCES
|
||||||
|
)
|
||||||
|
|
||||||
|
var maxfiles uint64
|
||||||
|
|
||||||
|
func SetRlimit() {
|
||||||
|
// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
|
||||||
|
var l syscall.Rlimit
|
||||||
|
err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
|
||||||
|
if err == nil && l.Cur != l.Max {
|
||||||
|
l.Cur = l.Max
|
||||||
|
syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
|
||||||
|
}
|
||||||
|
maxfiles = uint64(l.Cur)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Maxfiles() uint64 { return maxfiles }
|
||||||
|
func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) }
|
||||||
|
func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, uint64(dev)) }
|
||||||
2
vendor/github.com/fsnotify/fsnotify/internal/internal.go
generated
vendored
Normal file
2
vendor/github.com/fsnotify/fsnotify/internal/internal.go
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
// Package internal contains some helpers.
|
||||||
|
package internal
|
||||||
31
vendor/github.com/fsnotify/fsnotify/internal/unix.go
generated
vendored
Normal file
31
vendor/github.com/fsnotify/fsnotify/internal/unix.go
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
//go:build !windows && !darwin && !freebsd
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
SyscallEACCES = syscall.EACCES
|
||||||
|
UnixEACCES = unix.EACCES
|
||||||
|
)
|
||||||
|
|
||||||
|
var maxfiles uint64
|
||||||
|
|
||||||
|
func SetRlimit() {
|
||||||
|
// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
|
||||||
|
var l syscall.Rlimit
|
||||||
|
err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
|
||||||
|
if err == nil && l.Cur != l.Max {
|
||||||
|
l.Cur = l.Max
|
||||||
|
syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
|
||||||
|
}
|
||||||
|
maxfiles = uint64(l.Cur)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Maxfiles() uint64 { return maxfiles }
|
||||||
|
func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) }
|
||||||
|
func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) }
|
||||||
7
vendor/github.com/fsnotify/fsnotify/internal/unix2.go
generated
vendored
Normal file
7
vendor/github.com/fsnotify/fsnotify/internal/unix2.go
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
func HasPrivilegesForSymlink() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
41
vendor/github.com/fsnotify/fsnotify/internal/windows.go
generated
vendored
Normal file
41
vendor/github.com/fsnotify/fsnotify/internal/windows.go
generated
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Just a dummy.
|
||||||
|
var (
|
||||||
|
SyscallEACCES = errors.New("dummy")
|
||||||
|
UnixEACCES = errors.New("dummy")
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetRlimit() {}
|
||||||
|
func Maxfiles() uint64 { return 1<<64 - 1 }
|
||||||
|
func Mkfifo(path string, mode uint32) error { return errors.New("no FIFOs on Windows") }
|
||||||
|
func Mknod(path string, mode uint32, dev int) error { return errors.New("no device nodes on Windows") }
|
||||||
|
|
||||||
|
func HasPrivilegesForSymlink() bool {
|
||||||
|
var sid *windows.SID
|
||||||
|
err := windows.AllocateAndInitializeSid(
|
||||||
|
&windows.SECURITY_NT_AUTHORITY,
|
||||||
|
2,
|
||||||
|
windows.SECURITY_BUILTIN_DOMAIN_RID,
|
||||||
|
windows.DOMAIN_ALIAS_RID_ADMINS,
|
||||||
|
0, 0, 0, 0, 0, 0,
|
||||||
|
&sid)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer windows.FreeSid(sid)
|
||||||
|
token := windows.Token(0)
|
||||||
|
member, err := token.IsMember(sid)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return member || token.IsElevated()
|
||||||
|
}
|
||||||
208
vendor/github.com/fsnotify/fsnotify/mkdoc.zsh
generated
vendored
208
vendor/github.com/fsnotify/fsnotify/mkdoc.zsh
generated
vendored
|
|
@ -1,208 +0,0 @@
|
||||||
#!/usr/bin/env zsh
|
|
||||||
[ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1
|
|
||||||
setopt err_exit no_unset pipefail extended_glob
|
|
||||||
|
|
||||||
# Simple script to update the godoc comments on all watchers. Probably took me
|
|
||||||
# more time to write this than doing it manually, but ah well 🙃
|
|
||||||
|
|
||||||
watcher=$(<<EOF
|
|
||||||
// Watcher watches a set of paths, delivering events on a channel.
|
|
||||||
//
|
|
||||||
// A watcher should not be copied (e.g. pass it by pointer, rather than by
|
|
||||||
// value).
|
|
||||||
//
|
|
||||||
// # Linux notes
|
|
||||||
//
|
|
||||||
// When a file is removed a Remove event won't be emitted until all file
|
|
||||||
// descriptors are closed, and deletes will always emit a Chmod. For example:
|
|
||||||
//
|
|
||||||
// fp := os.Open("file")
|
|
||||||
// os.Remove("file") // Triggers Chmod
|
|
||||||
// fp.Close() // Triggers Remove
|
|
||||||
//
|
|
||||||
// This is the event that inotify sends, so not much can be changed about this.
|
|
||||||
//
|
|
||||||
// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
|
|
||||||
// for the number of watches per user, and fs.inotify.max_user_instances
|
|
||||||
// specifies the maximum number of inotify instances per user. Every Watcher you
|
|
||||||
// create is an "instance", and every path you add is a "watch".
|
|
||||||
//
|
|
||||||
// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
|
|
||||||
// /proc/sys/fs/inotify/max_user_instances
|
|
||||||
//
|
|
||||||
// To increase them you can use sysctl or write the value to the /proc file:
|
|
||||||
//
|
|
||||||
// # Default values on Linux 5.18
|
|
||||||
// sysctl fs.inotify.max_user_watches=124983
|
|
||||||
// sysctl fs.inotify.max_user_instances=128
|
|
||||||
//
|
|
||||||
// To make the changes persist on reboot edit /etc/sysctl.conf or
|
|
||||||
// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
|
|
||||||
// your distro's documentation):
|
|
||||||
//
|
|
||||||
// fs.inotify.max_user_watches=124983
|
|
||||||
// fs.inotify.max_user_instances=128
|
|
||||||
//
|
|
||||||
// Reaching the limit will result in a "no space left on device" or "too many open
|
|
||||||
// files" error.
|
|
||||||
//
|
|
||||||
// # kqueue notes (macOS, BSD)
|
|
||||||
//
|
|
||||||
// kqueue requires opening a file descriptor for every file that's being watched;
|
|
||||||
// so if you're watching a directory with five files then that's six file
|
|
||||||
// descriptors. You will run in to your system's "max open files" limit faster on
|
|
||||||
// these platforms.
|
|
||||||
//
|
|
||||||
// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
|
|
||||||
// control the maximum number of open files, as well as /etc/login.conf on BSD
|
|
||||||
// systems.
|
|
||||||
//
|
|
||||||
// # macOS notes
|
|
||||||
//
|
|
||||||
// Spotlight indexing on macOS can result in multiple events (see [#15]). A
|
|
||||||
// temporary workaround is to add your folder(s) to the "Spotlight Privacy
|
|
||||||
// Settings" until we have a native FSEvents implementation (see [#11]).
|
|
||||||
//
|
|
||||||
// [#11]: https://github.com/fsnotify/fsnotify/issues/11
|
|
||||||
// [#15]: https://github.com/fsnotify/fsnotify/issues/15
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
new=$(<<EOF
|
|
||||||
// NewWatcher creates a new Watcher.
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
add=$(<<EOF
|
|
||||||
// Add starts monitoring the path for changes.
|
|
||||||
//
|
|
||||||
// A path can only be watched once; attempting to watch it more than once will
|
|
||||||
// return an error. Paths that do not yet exist on the filesystem cannot be
|
|
||||||
// added. A watch will be automatically removed if the path is deleted.
|
|
||||||
//
|
|
||||||
// A path will remain watched if it gets renamed to somewhere else on the same
|
|
||||||
// filesystem, but the monitor will get removed if the path gets deleted and
|
|
||||||
// re-created, or if it's moved to a different filesystem.
|
|
||||||
//
|
|
||||||
// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
|
|
||||||
// filesystems (/proc, /sys, etc.) generally don't work.
|
|
||||||
//
|
|
||||||
// # Watching directories
|
|
||||||
//
|
|
||||||
// All files in a directory are monitored, including new files that are created
|
|
||||||
// after the watcher is started. Subdirectories are not watched (i.e. it's
|
|
||||||
// non-recursive).
|
|
||||||
//
|
|
||||||
// # Watching files
|
|
||||||
//
|
|
||||||
// Watching individual files (rather than directories) is generally not
|
|
||||||
// recommended as many tools update files atomically. Instead of "just" writing
|
|
||||||
// to the file a temporary file will be written to first, and if successful the
|
|
||||||
// temporary file is moved to to destination removing the original, or some
|
|
||||||
// variant thereof. The watcher on the original file is now lost, as it no
|
|
||||||
// longer exists.
|
|
||||||
//
|
|
||||||
// Instead, watch the parent directory and use Event.Name to filter out files
|
|
||||||
// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
remove=$(<<EOF
|
|
||||||
// Remove stops monitoring the path for changes.
|
|
||||||
//
|
|
||||||
// Directories are always removed non-recursively. For example, if you added
|
|
||||||
// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
|
|
||||||
//
|
|
||||||
// Removing a path that has not yet been added returns [ErrNonExistentWatch].
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
close=$(<<EOF
|
|
||||||
// Close removes all watches and closes the events channel.
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
watchlist=$(<<EOF
|
|
||||||
// WatchList returns all paths added with [Add] (and are not yet removed).
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
events=$(<<EOF
|
|
||||||
// Events sends the filesystem change events.
|
|
||||||
//
|
|
||||||
// fsnotify can send the following events; a "path" here can refer to a
|
|
||||||
// file, directory, symbolic link, or special file like a FIFO.
|
|
||||||
//
|
|
||||||
// fsnotify.Create A new path was created; this may be followed by one
|
|
||||||
// or more Write events if data also gets written to a
|
|
||||||
// file.
|
|
||||||
//
|
|
||||||
// fsnotify.Remove A path was removed.
|
|
||||||
//
|
|
||||||
// fsnotify.Rename A path was renamed. A rename is always sent with the
|
|
||||||
// old path as Event.Name, and a Create event will be
|
|
||||||
// sent with the new name. Renames are only sent for
|
|
||||||
// paths that are currently watched; e.g. moving an
|
|
||||||
// unmonitored file into a monitored directory will
|
|
||||||
// show up as just a Create. Similarly, renaming a file
|
|
||||||
// to outside a monitored directory will show up as
|
|
||||||
// only a Rename.
|
|
||||||
//
|
|
||||||
// fsnotify.Write A file or named pipe was written to. A Truncate will
|
|
||||||
// also trigger a Write. A single "write action"
|
|
||||||
// initiated by the user may show up as one or multiple
|
|
||||||
// writes, depending on when the system syncs things to
|
|
||||||
// disk. For example when compiling a large Go program
|
|
||||||
// you may get hundreds of Write events, so you
|
|
||||||
// probably want to wait until you've stopped receiving
|
|
||||||
// them (see the dedup example in cmd/fsnotify).
|
|
||||||
//
|
|
||||||
// fsnotify.Chmod Attributes were changed. On Linux this is also sent
|
|
||||||
// when a file is removed (or more accurately, when a
|
|
||||||
// link to an inode is removed). On kqueue it's sent
|
|
||||||
// and on kqueue when a file is truncated. On Windows
|
|
||||||
// it's never sent.
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
errors=$(<<EOF
|
|
||||||
// Errors sends any errors.
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
set-cmt() {
|
|
||||||
local pat=$1
|
|
||||||
local cmt=$2
|
|
||||||
|
|
||||||
IFS=$'\n' local files=($(grep -n $pat backend_*~*_test.go))
|
|
||||||
for f in $files; do
|
|
||||||
IFS=':' local fields=($=f)
|
|
||||||
local file=$fields[1]
|
|
||||||
local end=$(( $fields[2] - 1 ))
|
|
||||||
|
|
||||||
# Find start of comment.
|
|
||||||
local start=0
|
|
||||||
IFS=$'\n' local lines=($(head -n$end $file))
|
|
||||||
for (( i = 1; i <= $#lines; i++ )); do
|
|
||||||
local line=$lines[-$i]
|
|
||||||
if ! grep -q '^[[:space:]]*//' <<<$line; then
|
|
||||||
start=$(( end - (i - 2) ))
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
head -n $(( start - 1 )) $file >/tmp/x
|
|
||||||
print -r -- $cmt >>/tmp/x
|
|
||||||
tail -n+$(( end + 1 )) $file >>/tmp/x
|
|
||||||
mv /tmp/x $file
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
set-cmt '^type Watcher struct ' $watcher
|
|
||||||
set-cmt '^func NewWatcher(' $new
|
|
||||||
set-cmt '^func (w \*Watcher) Add(' $add
|
|
||||||
set-cmt '^func (w \*Watcher) Remove(' $remove
|
|
||||||
set-cmt '^func (w \*Watcher) Close(' $close
|
|
||||||
set-cmt '^func (w \*Watcher) WatchList(' $watchlist
|
|
||||||
set-cmt '^[[:space:]]*Events *chan Event$' $events
|
|
||||||
set-cmt '^[[:space:]]*Errors *chan error$' $errors
|
|
||||||
1
vendor/github.com/fsnotify/fsnotify/system_bsd.go
generated
vendored
1
vendor/github.com/fsnotify/fsnotify/system_bsd.go
generated
vendored
|
|
@ -1,5 +1,4 @@
|
||||||
//go:build freebsd || openbsd || netbsd || dragonfly
|
//go:build freebsd || openbsd || netbsd || dragonfly
|
||||||
// +build freebsd openbsd netbsd dragonfly
|
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
|
||||||
|
|
|
||||||
1
vendor/github.com/fsnotify/fsnotify/system_darwin.go
generated
vendored
1
vendor/github.com/fsnotify/fsnotify/system_darwin.go
generated
vendored
|
|
@ -1,5 +1,4 @@
|
||||||
//go:build darwin
|
//go:build darwin
|
||||||
// +build darwin
|
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
|
||||||
|
|
|
||||||
205
vendor/github.com/magiconair/properties/CHANGELOG.md
generated
vendored
205
vendor/github.com/magiconair/properties/CHANGELOG.md
generated
vendored
|
|
@ -1,205 +0,0 @@
|
||||||
## Changelog
|
|
||||||
|
|
||||||
### [1.8.7](https://github.com/magiconair/properties/tree/v1.8.7) - 08 Dec 2022
|
|
||||||
|
|
||||||
* [PR #65](https://github.com/magiconair/properties/pull/65): Speedup Merge
|
|
||||||
|
|
||||||
Thanks to [@AdityaVallabh](https://github.com/AdityaVallabh) for the patch.
|
|
||||||
|
|
||||||
* [PR #66](https://github.com/magiconair/properties/pull/66): use github actions
|
|
||||||
|
|
||||||
### [1.8.6](https://github.com/magiconair/properties/tree/v1.8.6) - 23 Feb 2022
|
|
||||||
|
|
||||||
* [PR #57](https://github.com/magiconair/properties/pull/57):Fix "unreachable code" lint error
|
|
||||||
|
|
||||||
Thanks to [@ellie](https://github.com/ellie) for the patch.
|
|
||||||
|
|
||||||
* [PR #63](https://github.com/magiconair/properties/pull/63): Make TestMustGetParsedDuration backwards compatible
|
|
||||||
|
|
||||||
This patch ensures that the `TestMustGetParsedDuration` still works with `go1.3` to make the
|
|
||||||
author happy until it affects real users.
|
|
||||||
|
|
||||||
Thanks to [@maage](https://github.com/maage) for the patch.
|
|
||||||
|
|
||||||
### [1.8.5](https://github.com/magiconair/properties/tree/v1.8.5) - 24 Mar 2021
|
|
||||||
|
|
||||||
* [PR #55](https://github.com/magiconair/properties/pull/55): Fix: Encoding Bug in Comments
|
|
||||||
|
|
||||||
When reading comments \ are loaded correctly, but when writing they are then
|
|
||||||
replaced by \\. This leads to wrong comments when writing and reading multiple times.
|
|
||||||
|
|
||||||
Thanks to [@doxsch](https://github.com/doxsch) for the patch.
|
|
||||||
|
|
||||||
### [1.8.4](https://github.com/magiconair/properties/tree/v1.8.4) - 23 Sep 2020
|
|
||||||
|
|
||||||
* [PR #50](https://github.com/magiconair/properties/pull/50): enhance error message for circular references
|
|
||||||
|
|
||||||
Thanks to [@sriv](https://github.com/sriv) for the patch.
|
|
||||||
|
|
||||||
### [1.8.3](https://github.com/magiconair/properties/tree/v1.8.3) - 14 Sep 2020
|
|
||||||
|
|
||||||
* [PR #49](https://github.com/magiconair/properties/pull/49): Include the key in error message causing the circular reference
|
|
||||||
|
|
||||||
The change is include the key in the error message which is causing the circular
|
|
||||||
reference when parsing/loading the properties files.
|
|
||||||
|
|
||||||
Thanks to [@haroon-sheikh](https://github.com/haroon-sheikh) for the patch.
|
|
||||||
|
|
||||||
### [1.8.2](https://github.com/magiconair/properties/tree/v1.8.2) - 25 Aug 2020
|
|
||||||
|
|
||||||
* [PR #36](https://github.com/magiconair/properties/pull/36): Escape backslash on write
|
|
||||||
|
|
||||||
This patch ensures that backslashes are escaped on write. Existing applications which
|
|
||||||
rely on the old behavior may need to be updated.
|
|
||||||
|
|
||||||
Thanks to [@apesternikov](https://github.com/apesternikov) for the patch.
|
|
||||||
|
|
||||||
* [PR #42](https://github.com/magiconair/properties/pull/42): Made Content-Type check whitespace agnostic in LoadURL()
|
|
||||||
|
|
||||||
Thanks to [@aliras1](https://github.com/aliras1) for the patch.
|
|
||||||
|
|
||||||
* [PR #41](https://github.com/magiconair/properties/pull/41): Make key/value separator configurable on Write()
|
|
||||||
|
|
||||||
Thanks to [@mkjor](https://github.com/mkjor) for the patch.
|
|
||||||
|
|
||||||
* [PR #40](https://github.com/magiconair/properties/pull/40): Add method to return a sorted list of keys
|
|
||||||
|
|
||||||
Thanks to [@mkjor](https://github.com/mkjor) for the patch.
|
|
||||||
|
|
||||||
### [1.8.1](https://github.com/magiconair/properties/tree/v1.8.1) - 10 May 2019
|
|
||||||
|
|
||||||
* [PR #35](https://github.com/magiconair/properties/pull/35): Close body always after request
|
|
||||||
|
|
||||||
This patch ensures that in `LoadURL` the response body is always closed.
|
|
||||||
|
|
||||||
Thanks to [@liubog2008](https://github.com/liubog2008) for the patch.
|
|
||||||
|
|
||||||
### [1.8](https://github.com/magiconair/properties/tree/v1.8) - 15 May 2018
|
|
||||||
|
|
||||||
* [PR #26](https://github.com/magiconair/properties/pull/26): Disable expansion during loading
|
|
||||||
|
|
||||||
This adds the option to disable property expansion during loading.
|
|
||||||
|
|
||||||
Thanks to [@kmala](https://github.com/kmala) for the patch.
|
|
||||||
|
|
||||||
### [1.7.6](https://github.com/magiconair/properties/tree/v1.7.6) - 14 Feb 2018
|
|
||||||
|
|
||||||
* [PR #29](https://github.com/magiconair/properties/pull/29): Reworked expansion logic to handle more complex cases.
|
|
||||||
|
|
||||||
See PR for an example.
|
|
||||||
|
|
||||||
Thanks to [@yobert](https://github.com/yobert) for the fix.
|
|
||||||
|
|
||||||
### [1.7.5](https://github.com/magiconair/properties/tree/v1.7.5) - 13 Feb 2018
|
|
||||||
|
|
||||||
* [PR #28](https://github.com/magiconair/properties/pull/28): Support duplicate expansions in the same value
|
|
||||||
|
|
||||||
Values which expand the same key multiple times (e.g. `key=${a} ${a}`) will no longer fail
|
|
||||||
with a `circular reference error`.
|
|
||||||
|
|
||||||
Thanks to [@yobert](https://github.com/yobert) for the fix.
|
|
||||||
|
|
||||||
### [1.7.4](https://github.com/magiconair/properties/tree/v1.7.4) - 31 Oct 2017
|
|
||||||
|
|
||||||
* [Issue #23](https://github.com/magiconair/properties/issues/23): Ignore blank lines with whitespaces
|
|
||||||
|
|
||||||
* [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled
|
|
||||||
|
|
||||||
Thanks to [@mgurov](https://github.com/mgurov) for the fix.
|
|
||||||
|
|
||||||
### [1.7.3](https://github.com/magiconair/properties/tree/v1.7.3) - 10 Jul 2017
|
|
||||||
|
|
||||||
* [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically
|
|
||||||
* [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map
|
|
||||||
|
|
||||||
### [1.7.2](https://github.com/magiconair/properties/tree/v1.7.2) - 20 Mar 2017
|
|
||||||
|
|
||||||
* [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency
|
|
||||||
* [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc)
|
|
||||||
|
|
||||||
### [1.7.1](https://github.com/magiconair/properties/tree/v1.7.1) - 13 Jan 2017
|
|
||||||
|
|
||||||
* [Issue #14](https://github.com/magiconair/properties/issues/14): Decouple TestLoadExpandedFile from `$USER`
|
|
||||||
* [PR #12](https://github.com/magiconair/properties/pull/12): Load from files and URLs
|
|
||||||
* [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy
|
|
||||||
* [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function
|
|
||||||
|
|
||||||
### [1.7.0](https://github.com/magiconair/properties/tree/v1.7.0) - 20 Mar 2016
|
|
||||||
|
|
||||||
* [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL.
|
|
||||||
* [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string.
|
|
||||||
* [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe)
|
|
||||||
|
|
||||||
### [1.6.0](https://github.com/magiconair/properties/tree/v1.6.0) - 11 Dec 2015
|
|
||||||
|
|
||||||
* Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags.
|
|
||||||
|
|
||||||
### [1.5.6](https://github.com/magiconair/properties/tree/v1.5.6) - 18 Oct 2015
|
|
||||||
|
|
||||||
* Vendored in gopkg.in/check.v1
|
|
||||||
|
|
||||||
### [1.5.5](https://github.com/magiconair/properties/tree/v1.5.5) - 31 Jul 2015
|
|
||||||
|
|
||||||
* [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs)
|
|
||||||
|
|
||||||
### [1.5.4](https://github.com/magiconair/properties/tree/v1.5.4) - 23 Jun 2015
|
|
||||||
|
|
||||||
* [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references.
|
|
||||||
|
|
||||||
### [1.5.3](https://github.com/magiconair/properties/tree/v1.5.3) - 02 Jun 2015
|
|
||||||
|
|
||||||
* [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp)
|
|
||||||
|
|
||||||
### [1.5.2](https://github.com/magiconair/properties/tree/v1.5.2) - 10 Apr 2015
|
|
||||||
|
|
||||||
* [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty
|
|
||||||
* Add clickable links to README
|
|
||||||
|
|
||||||
### [1.5.1](https://github.com/magiconair/properties/tree/v1.5.1) - 08 Dec 2014
|
|
||||||
|
|
||||||
* Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with
|
|
||||||
[time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration).
|
|
||||||
|
|
||||||
### [1.5.0](https://github.com/magiconair/properties/tree/v1.5.0) - 18 Nov 2014
|
|
||||||
|
|
||||||
* Added support for single and multi-line comments (reading, writing and updating)
|
|
||||||
* The order of keys is now preserved
|
|
||||||
* Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry
|
|
||||||
* Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method
|
|
||||||
* Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1)
|
|
||||||
|
|
||||||
### [1.4.2](https://github.com/magiconair/properties/tree/v1.4.2) - 15 Nov 2014
|
|
||||||
|
|
||||||
* [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one
|
|
||||||
|
|
||||||
### [1.4.1](https://github.com/magiconair/properties/tree/v1.4.1) - 13 Nov 2014
|
|
||||||
|
|
||||||
* [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string
|
|
||||||
|
|
||||||
### [1.4.0](https://github.com/magiconair/properties/tree/v1.4.0) - 23 Sep 2014
|
|
||||||
|
|
||||||
* Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys
|
|
||||||
* Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties
|
|
||||||
|
|
||||||
### [1.3.0](https://github.com/magiconair/properties/tree/v1.3.0) - 18 Mar 2014
|
|
||||||
|
|
||||||
* Added support for time.Duration
|
|
||||||
* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tree/vior configurable (log.Fatal, panic) - custom)
|
|
||||||
* Changed default of MustXXX() failure from panic to log.Fatal
|
|
||||||
|
|
||||||
### [1.2.0](https://github.com/magiconair/properties/tree/v1.2.0) - 05 Mar 2014
|
|
||||||
|
|
||||||
* Added MustGet... functions
|
|
||||||
* Added support for int and uint with range checks on 32 bit platforms
|
|
||||||
|
|
||||||
### [1.1.0](https://github.com/magiconair/properties/tree/v1.1.0) - 20 Jan 2014
|
|
||||||
|
|
||||||
* Renamed from goproperties to properties
|
|
||||||
* Added support for expansion of environment vars in
|
|
||||||
filenames and value expressions
|
|
||||||
* Fixed bug where value expressions were not at the
|
|
||||||
start of the string
|
|
||||||
|
|
||||||
### [1.0.0](https://github.com/magiconair/properties/tree/v1.0.0) - 7 Jan 2014
|
|
||||||
|
|
||||||
* Initial release
|
|
||||||
30
vendor/github.com/magiconair/properties/README.md
generated
vendored
30
vendor/github.com/magiconair/properties/README.md
generated
vendored
|
|
@ -1,12 +1,9 @@
|
||||||
[](https://github.com/magiconair/properties/releases)
|
[](https://github.com/magiconair/properties/releases)
|
||||||
[](https://travis-ci.org/magiconair/properties)
|
|
||||||
[](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE)
|
[](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE)
|
||||||
[](http://godoc.org/github.com/magiconair/properties)
|
[](http://godoc.org/github.com/magiconair/properties)
|
||||||
|
|
||||||
# Overview
|
# Overview
|
||||||
|
|
||||||
#### Please run `git pull --tags` to update the tags. See [below](#updated-git-tags) why.
|
|
||||||
|
|
||||||
properties is a Go library for reading and writing properties files.
|
properties is a Go library for reading and writing properties files.
|
||||||
|
|
||||||
It supports reading from multiple files or URLs and Spring style recursive
|
It supports reading from multiple files or URLs and Spring style recursive
|
||||||
|
|
@ -99,30 +96,3 @@ $ go get -u github.com/magiconair/properties
|
||||||
## ToDo
|
## ToDo
|
||||||
|
|
||||||
* Dump contents with passwords and secrets obscured
|
* Dump contents with passwords and secrets obscured
|
||||||
|
|
||||||
## Updated Git tags
|
|
||||||
|
|
||||||
#### 13 Feb 2018
|
|
||||||
|
|
||||||
I realized that all of the git tags I had pushed before v1.7.5 were lightweight tags
|
|
||||||
and I've only recently learned that this doesn't play well with `git describe` 😞
|
|
||||||
|
|
||||||
I have replaced all lightweight tags with signed tags using this script which should
|
|
||||||
retain the commit date, name and email address. Please run `git pull --tags` to update them.
|
|
||||||
|
|
||||||
Worst case you have to reclone the repo.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
#!/bin/bash
|
|
||||||
tag=$1
|
|
||||||
echo "Updating $tag"
|
|
||||||
date=$(git show ${tag}^0 --format=%aD | head -1)
|
|
||||||
email=$(git show ${tag}^0 --format=%aE | head -1)
|
|
||||||
name=$(git show ${tag}^0 --format=%aN | head -1)
|
|
||||||
GIT_COMMITTER_DATE="$date" GIT_COMMITTER_NAME="$name" GIT_COMMITTER_EMAIL="$email" git tag -s -f ${tag} ${tag}^0 -m ${tag}
|
|
||||||
```
|
|
||||||
|
|
||||||
I apologize for the inconvenience.
|
|
||||||
|
|
||||||
Frank
|
|
||||||
|
|
||||||
|
|
|
||||||
6
vendor/github.com/magiconair/properties/decode.go
generated
vendored
6
vendor/github.com/magiconair/properties/decode.go
generated
vendored
|
|
@ -189,12 +189,12 @@ func dec(p *Properties, key string, def *string, opts map[string]string, v refle
|
||||||
for i := 0; i < v.NumField(); i++ {
|
for i := 0; i < v.NumField(); i++ {
|
||||||
fv := v.Field(i)
|
fv := v.Field(i)
|
||||||
fk, def, opts := keydef(t.Field(i))
|
fk, def, opts := keydef(t.Field(i))
|
||||||
if !fv.CanSet() {
|
|
||||||
return fmt.Errorf("cannot set %s", t.Field(i).Name)
|
|
||||||
}
|
|
||||||
if fk == "-" {
|
if fk == "-" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if !fv.CanSet() {
|
||||||
|
return fmt.Errorf("cannot set %s", t.Field(i).Name)
|
||||||
|
}
|
||||||
if key != "" {
|
if key != "" {
|
||||||
fk = key + "." + fk
|
fk = key + "." + fk
|
||||||
}
|
}
|
||||||
|
|
|
||||||
27
vendor/github.com/magiconair/properties/load.go
generated
vendored
27
vendor/github.com/magiconair/properties/load.go
generated
vendored
|
|
@ -6,7 +6,7 @@ package properties
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -52,6 +52,15 @@ func (l *Loader) LoadBytes(buf []byte) (*Properties, error) {
|
||||||
return l.loadBytes(buf, l.Encoding)
|
return l.loadBytes(buf, l.Encoding)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadReader reads an io.Reader into a Properties struct.
|
||||||
|
func (l *Loader) LoadReader(r io.Reader) (*Properties, error) {
|
||||||
|
if buf, err := io.ReadAll(r); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return l.loadBytes(buf, l.Encoding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LoadAll reads the content of multiple URLs or files in the given order into
|
// LoadAll reads the content of multiple URLs or files in the given order into
|
||||||
// a Properties struct. If IgnoreMissing is true then a 404 status code or
|
// a Properties struct. If IgnoreMissing is true then a 404 status code or
|
||||||
// missing file will not be reported as error. Encoding sets the encoding for
|
// missing file will not be reported as error. Encoding sets the encoding for
|
||||||
|
|
@ -91,7 +100,7 @@ func (l *Loader) LoadAll(names []string) (*Properties, error) {
|
||||||
// If IgnoreMissing is true then a missing file will not be
|
// If IgnoreMissing is true then a missing file will not be
|
||||||
// reported as error.
|
// reported as error.
|
||||||
func (l *Loader) LoadFile(filename string) (*Properties, error) {
|
func (l *Loader) LoadFile(filename string) (*Properties, error) {
|
||||||
data, err := ioutil.ReadFile(filename)
|
data, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if l.IgnoreMissing && os.IsNotExist(err) {
|
if l.IgnoreMissing && os.IsNotExist(err) {
|
||||||
LogPrintf("properties: %s not found. skipping", filename)
|
LogPrintf("properties: %s not found. skipping", filename)
|
||||||
|
|
@ -126,7 +135,7 @@ func (l *Loader) LoadURL(url string) (*Properties, error) {
|
||||||
return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode)
|
return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
|
return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
|
||||||
}
|
}
|
||||||
|
|
@ -185,6 +194,12 @@ func LoadFile(filename string, enc Encoding) (*Properties, error) {
|
||||||
return l.LoadAll([]string{filename})
|
return l.LoadAll([]string{filename})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadReader reads an io.Reader into a Properties struct.
|
||||||
|
func LoadReader(r io.Reader, enc Encoding) (*Properties, error) {
|
||||||
|
l := &Loader{Encoding: enc}
|
||||||
|
return l.LoadReader(r)
|
||||||
|
}
|
||||||
|
|
||||||
// LoadFiles reads multiple files in the given order into
|
// LoadFiles reads multiple files in the given order into
|
||||||
// a Properties struct. If 'ignoreMissing' is true then
|
// a Properties struct. If 'ignoreMissing' is true then
|
||||||
// non-existent files will not be reported as error.
|
// non-existent files will not be reported as error.
|
||||||
|
|
@ -224,6 +239,12 @@ func MustLoadString(s string) *Properties {
|
||||||
return must(LoadString(s))
|
return must(LoadString(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MustLoadSReader reads an io.Reader into a Properties struct and
|
||||||
|
// panics on error.
|
||||||
|
func MustLoadReader(r io.Reader, enc Encoding) *Properties {
|
||||||
|
return must(LoadReader(r, enc))
|
||||||
|
}
|
||||||
|
|
||||||
// MustLoadFile reads a file into a Properties struct and
|
// MustLoadFile reads a file into a Properties struct and
|
||||||
// panics on error.
|
// panics on error.
|
||||||
func MustLoadFile(filename string, enc Encoding) *Properties {
|
func MustLoadFile(filename string, enc Encoding) *Properties {
|
||||||
|
|
|
||||||
3
vendor/github.com/pelletier/go-toml/v2/.gitignore
generated
vendored
3
vendor/github.com/pelletier/go-toml/v2/.gitignore
generated
vendored
|
|
@ -3,4 +3,5 @@ fuzz/
|
||||||
cmd/tomll/tomll
|
cmd/tomll/tomll
|
||||||
cmd/tomljson/tomljson
|
cmd/tomljson/tomljson
|
||||||
cmd/tomltestgen/tomltestgen
|
cmd/tomltestgen/tomltestgen
|
||||||
dist
|
dist
|
||||||
|
tests/
|
||||||
|
|
|
||||||
1
vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
generated
vendored
1
vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
generated
vendored
|
|
@ -1,3 +1,4 @@
|
||||||
|
version: 2
|
||||||
before:
|
before:
|
||||||
hooks:
|
hooks:
|
||||||
- go mod tidy
|
- go mod tidy
|
||||||
|
|
|
||||||
31
vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
generated
vendored
31
vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
generated
vendored
|
|
@ -165,25 +165,22 @@ Checklist:
|
||||||
|
|
||||||
### New release
|
### New release
|
||||||
|
|
||||||
1. Decide on the next version number. Use semver.
|
1. Decide on the next version number. Use semver. Review commits since last
|
||||||
2. Generate release notes using [`gh`][gh]. Example:
|
version to assess.
|
||||||
|
2. Tag release. For example:
|
||||||
```
|
```
|
||||||
$ gh api -X POST \
|
git checkout v2
|
||||||
-F tag_name='v2.0.0-beta.5' \
|
git pull
|
||||||
-F target_commitish='v2' \
|
git tag v2.2.0
|
||||||
-F previous_tag_name='v2.0.0-beta.4' \
|
git push --tags
|
||||||
--jq '.body' \
|
|
||||||
repos/pelletier/go-toml/releases/generate-notes
|
|
||||||
```
|
```
|
||||||
3. Look for "Other changes". That would indicate a pull request not labeled
|
3. CI automatically builds a draft Github release. Review it and edit as
|
||||||
properly. Tweak labels and pull request titles until changelog looks good for
|
necessary. Look for "Other changes". That would indicate a pull request not
|
||||||
users.
|
labeled properly. Tweak labels and pull request titles until changelog looks
|
||||||
4. [Draft new release][new-release].
|
good for users.
|
||||||
5. Fill tag and target with the same value used to generate the changelog.
|
4. Check "create discussion" box, in the "Releases" category.
|
||||||
6. Set title to the new tag value.
|
5. If new version is an alpha or beta only, check pre-release box.
|
||||||
7. Paste the generated changelog.
|
|
||||||
8. Check "create discussion", in the "Releases" category.
|
|
||||||
9. Check pre-release if new version is an alpha or beta.
|
|
||||||
|
|
||||||
[issues-tracker]: https://github.com/pelletier/go-toml/issues
|
[issues-tracker]: https://github.com/pelletier/go-toml/issues
|
||||||
[bug-report]: https://github.com/pelletier/go-toml/issues/new?template=bug_report.md
|
[bug-report]: https://github.com/pelletier/go-toml/issues/new?template=bug_report.md
|
||||||
|
|
|
||||||
117
vendor/github.com/pelletier/go-toml/v2/README.md
generated
vendored
117
vendor/github.com/pelletier/go-toml/v2/README.md
generated
vendored
|
|
@ -98,9 +98,9 @@ Given the following struct, let's see how to read it and write it as TOML:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type MyConfig struct {
|
type MyConfig struct {
|
||||||
Version int
|
Version int
|
||||||
Name string
|
Name string
|
||||||
Tags []string
|
Tags []string
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -119,7 +119,7 @@ tags = ["go", "toml"]
|
||||||
var cfg MyConfig
|
var cfg MyConfig
|
||||||
err := toml.Unmarshal([]byte(doc), &cfg)
|
err := toml.Unmarshal([]byte(doc), &cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
fmt.Println("version:", cfg.Version)
|
fmt.Println("version:", cfg.Version)
|
||||||
fmt.Println("name:", cfg.Name)
|
fmt.Println("name:", cfg.Name)
|
||||||
|
|
@ -140,14 +140,14 @@ as a TOML document:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
cfg := MyConfig{
|
cfg := MyConfig{
|
||||||
Version: 2,
|
Version: 2,
|
||||||
Name: "go-toml",
|
Name: "go-toml",
|
||||||
Tags: []string{"go", "toml"},
|
Tags: []string{"go", "toml"},
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := toml.Marshal(cfg)
|
b, err := toml.Marshal(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
fmt.Println(string(b))
|
fmt.Println(string(b))
|
||||||
|
|
||||||
|
|
@ -175,17 +175,17 @@ the AST level. See https://pkg.go.dev/github.com/pelletier/go-toml/v2/unstable.
|
||||||
Execution time speedup compared to other Go TOML libraries:
|
Execution time speedup compared to other Go TOML libraries:
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
|
<tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>Marshal/HugoFrontMatter-2</td><td>1.9x</td><td>1.9x</td></tr>
|
<tr><td>Marshal/HugoFrontMatter-2</td><td>1.9x</td><td>2.2x</td></tr>
|
||||||
<tr><td>Marshal/ReferenceFile/map-2</td><td>1.7x</td><td>1.8x</td></tr>
|
<tr><td>Marshal/ReferenceFile/map-2</td><td>1.7x</td><td>2.1x</td></tr>
|
||||||
<tr><td>Marshal/ReferenceFile/struct-2</td><td>2.2x</td><td>2.5x</td></tr>
|
<tr><td>Marshal/ReferenceFile/struct-2</td><td>2.2x</td><td>3.0x</td></tr>
|
||||||
<tr><td>Unmarshal/HugoFrontMatter-2</td><td>2.9x</td><td>2.9x</td></tr>
|
<tr><td>Unmarshal/HugoFrontMatter-2</td><td>2.9x</td><td>2.7x</td></tr>
|
||||||
<tr><td>Unmarshal/ReferenceFile/map-2</td><td>2.6x</td><td>2.9x</td></tr>
|
<tr><td>Unmarshal/ReferenceFile/map-2</td><td>2.6x</td><td>2.7x</td></tr>
|
||||||
<tr><td>Unmarshal/ReferenceFile/struct-2</td><td>4.4x</td><td>5.3x</td></tr>
|
<tr><td>Unmarshal/ReferenceFile/struct-2</td><td>4.6x</td><td>5.1x</td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<details><summary>See more</summary>
|
<details><summary>See more</summary>
|
||||||
<p>The table above has the results of the most common use-cases. The table below
|
<p>The table above has the results of the most common use-cases. The table below
|
||||||
|
|
@ -193,22 +193,22 @@ contains the results of all benchmarks, including unrealistic ones. It is
|
||||||
provided for completeness.</p>
|
provided for completeness.</p>
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
|
<tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>Marshal/SimpleDocument/map-2</td><td>1.8x</td><td>2.9x</td></tr>
|
<tr><td>Marshal/SimpleDocument/map-2</td><td>1.8x</td><td>2.7x</td></tr>
|
||||||
<tr><td>Marshal/SimpleDocument/struct-2</td><td>2.7x</td><td>4.2x</td></tr>
|
<tr><td>Marshal/SimpleDocument/struct-2</td><td>2.7x</td><td>3.8x</td></tr>
|
||||||
<tr><td>Unmarshal/SimpleDocument/map-2</td><td>4.5x</td><td>3.1x</td></tr>
|
<tr><td>Unmarshal/SimpleDocument/map-2</td><td>3.8x</td><td>3.0x</td></tr>
|
||||||
<tr><td>Unmarshal/SimpleDocument/struct-2</td><td>6.2x</td><td>3.9x</td></tr>
|
<tr><td>Unmarshal/SimpleDocument/struct-2</td><td>5.6x</td><td>4.1x</td></tr>
|
||||||
<tr><td>UnmarshalDataset/example-2</td><td>3.1x</td><td>3.5x</td></tr>
|
<tr><td>UnmarshalDataset/example-2</td><td>3.0x</td><td>3.2x</td></tr>
|
||||||
<tr><td>UnmarshalDataset/code-2</td><td>2.3x</td><td>3.1x</td></tr>
|
<tr><td>UnmarshalDataset/code-2</td><td>2.3x</td><td>2.9x</td></tr>
|
||||||
<tr><td>UnmarshalDataset/twitter-2</td><td>2.5x</td><td>2.6x</td></tr>
|
<tr><td>UnmarshalDataset/twitter-2</td><td>2.6x</td><td>2.7x</td></tr>
|
||||||
<tr><td>UnmarshalDataset/citm_catalog-2</td><td>2.1x</td><td>2.2x</td></tr>
|
<tr><td>UnmarshalDataset/citm_catalog-2</td><td>2.2x</td><td>2.3x</td></tr>
|
||||||
<tr><td>UnmarshalDataset/canada-2</td><td>1.6x</td><td>1.3x</td></tr>
|
<tr><td>UnmarshalDataset/canada-2</td><td>1.8x</td><td>1.5x</td></tr>
|
||||||
<tr><td>UnmarshalDataset/config-2</td><td>4.3x</td><td>3.2x</td></tr>
|
<tr><td>UnmarshalDataset/config-2</td><td>4.1x</td><td>2.9x</td></tr>
|
||||||
<tr><td>[Geo mean]</td><td>2.7x</td><td>2.8x</td></tr>
|
<tr><td>geomean</td><td>2.7x</td><td>2.8x</td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p>This table can be generated with <code>./ci.sh benchmark -a -html</code>.</p>
|
<p>This table can be generated with <code>./ci.sh benchmark -a -html</code>.</p>
|
||||||
</details>
|
</details>
|
||||||
|
|
@ -233,24 +233,24 @@ Go-toml provides three handy command line tools:
|
||||||
|
|
||||||
* `tomljson`: Reads a TOML file and outputs its JSON representation.
|
* `tomljson`: Reads a TOML file and outputs its JSON representation.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ go install github.com/pelletier/go-toml/v2/cmd/tomljson@latest
|
$ go install github.com/pelletier/go-toml/v2/cmd/tomljson@latest
|
||||||
$ tomljson --help
|
$ tomljson --help
|
||||||
```
|
```
|
||||||
|
|
||||||
* `jsontoml`: Reads a JSON file and outputs a TOML representation.
|
* `jsontoml`: Reads a JSON file and outputs a TOML representation.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ go install github.com/pelletier/go-toml/v2/cmd/jsontoml@latest
|
$ go install github.com/pelletier/go-toml/v2/cmd/jsontoml@latest
|
||||||
$ jsontoml --help
|
$ jsontoml --help
|
||||||
```
|
```
|
||||||
|
|
||||||
* `tomll`: Lints and reformats a TOML file.
|
* `tomll`: Lints and reformats a TOML file.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ go install github.com/pelletier/go-toml/v2/cmd/tomll@latest
|
$ go install github.com/pelletier/go-toml/v2/cmd/tomll@latest
|
||||||
$ tomll --help
|
$ tomll --help
|
||||||
```
|
```
|
||||||
|
|
||||||
### Docker image
|
### Docker image
|
||||||
|
|
||||||
|
|
@ -261,7 +261,7 @@ Those tools are also available as a [Docker image][docker]. For example, to use
|
||||||
docker run -i ghcr.io/pelletier/go-toml:v2 tomljson < example.toml
|
docker run -i ghcr.io/pelletier/go-toml:v2 tomljson < example.toml
|
||||||
```
|
```
|
||||||
|
|
||||||
Multiple versions are availble on [ghcr.io][docker].
|
Multiple versions are available on [ghcr.io][docker].
|
||||||
|
|
||||||
[docker]: https://github.com/pelletier/go-toml/pkgs/container/go-toml
|
[docker]: https://github.com/pelletier/go-toml/pkgs/container/go-toml
|
||||||
|
|
||||||
|
|
@ -293,16 +293,16 @@ element in the interface to decode the object. For example:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type inner struct {
|
type inner struct {
|
||||||
B interface{}
|
B interface{}
|
||||||
}
|
}
|
||||||
type doc struct {
|
type doc struct {
|
||||||
A interface{}
|
A interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
d := doc{
|
d := doc{
|
||||||
A: inner{
|
A: inner{
|
||||||
B: "Before",
|
B: "Before",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
data := `
|
data := `
|
||||||
|
|
@ -341,7 +341,7 @@ contained in the doc is superior to the capacity of the array. For example:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type doc struct {
|
type doc struct {
|
||||||
A [2]string
|
A [2]string
|
||||||
}
|
}
|
||||||
d := doc{}
|
d := doc{}
|
||||||
err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d)
|
err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d)
|
||||||
|
|
@ -565,10 +565,11 @@ complete solutions exist out there.
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|
||||||
Go-toml follows [Semantic Versioning](https://semver.org). The supported version
|
Expect for parts explicitly marked otherwise, go-toml follows [Semantic
|
||||||
of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of
|
Versioning](https://semver.org). The supported version of
|
||||||
this document. The last two major versions of Go are supported
|
[TOML](https://github.com/toml-lang/toml) is indicated at the beginning of this
|
||||||
(see [Go Release Policy](https://golang.org/doc/devel/release.html#policy)).
|
document. The last two major versions of Go are supported (see [Go Release
|
||||||
|
Policy](https://golang.org/doc/devel/release.html#policy)).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
||||||
3
vendor/github.com/pelletier/go-toml/v2/SECURITY.md
generated
vendored
3
vendor/github.com/pelletier/go-toml/v2/SECURITY.md
generated
vendored
|
|
@ -2,9 +2,6 @@
|
||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
Use this section to tell people about which versions of your project are
|
|
||||||
currently being supported with security updates.
|
|
||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ---------- | ------------------ |
|
| ---------- | ------------------ |
|
||||||
| Latest 2.x | :white_check_mark: |
|
| Latest 2.x | :white_check_mark: |
|
||||||
|
|
|
||||||
22
vendor/github.com/pelletier/go-toml/v2/ci.sh
generated
vendored
22
vendor/github.com/pelletier/go-toml/v2/ci.sh
generated
vendored
|
|
@ -77,7 +77,7 @@ cover() {
|
||||||
|
|
||||||
pushd "$dir"
|
pushd "$dir"
|
||||||
go test -covermode=atomic -coverpkg=./... -coverprofile=coverage.out.tmp ./...
|
go test -covermode=atomic -coverpkg=./... -coverprofile=coverage.out.tmp ./...
|
||||||
cat coverage.out.tmp | grep -v fuzz | grep -v testsuite | grep -v tomltestgen | grep -v gotoml-test-decoder > coverage.out
|
grep -Ev '(fuzz|testsuite|tomltestgen|gotoml-test-decoder|gotoml-test-encoder)' coverage.out.tmp > coverage.out
|
||||||
go tool cover -func=coverage.out
|
go tool cover -func=coverage.out
|
||||||
echo "Coverage profile for ${branch}: ${dir}/coverage.out" >&2
|
echo "Coverage profile for ${branch}: ${dir}/coverage.out" >&2
|
||||||
popd
|
popd
|
||||||
|
|
@ -152,7 +152,7 @@ bench() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export GOMAXPROCS=2
|
export GOMAXPROCS=2
|
||||||
nice -n -19 taskset --cpu-list 0,1 go test '-bench=^Benchmark(Un)?[mM]arshal' -count=5 -run=Nothing ./... | tee "${out}"
|
go test '-bench=^Benchmark(Un)?[mM]arshal' -count=10 -run=Nothing ./... | tee "${out}"
|
||||||
popd
|
popd
|
||||||
|
|
||||||
if [ "${branch}" != "HEAD" ]; then
|
if [ "${branch}" != "HEAD" ]; then
|
||||||
|
|
@ -161,10 +161,12 @@ bench() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fmktemp() {
|
fmktemp() {
|
||||||
if mktemp --version|grep GNU >/dev/null; then
|
if mktemp --version &> /dev/null; then
|
||||||
mktemp --suffix=-$1;
|
# GNU
|
||||||
|
mktemp --suffix=-$1
|
||||||
else
|
else
|
||||||
mktemp -t $1;
|
# BSD
|
||||||
|
mktemp -t $1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,12 +186,14 @@ with open(sys.argv[1]) as f:
|
||||||
lines.append(line.split(','))
|
lines.append(line.split(','))
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
for line in reversed(lines[1:]):
|
for line in reversed(lines[2:]):
|
||||||
|
if len(line) < 8 or line[0] == "":
|
||||||
|
continue
|
||||||
v2 = float(line[1])
|
v2 = float(line[1])
|
||||||
results.append([
|
results.append([
|
||||||
line[0].replace("-32", ""),
|
line[0].replace("-32", ""),
|
||||||
"%.1fx" % (float(line[3])/v2), # v1
|
"%.1fx" % (float(line[3])/v2), # v1
|
||||||
"%.1fx" % (float(line[5])/v2), # bs
|
"%.1fx" % (float(line[7])/v2), # bs
|
||||||
])
|
])
|
||||||
# move geomean to the end
|
# move geomean to the end
|
||||||
results.append(results[0])
|
results.append(results[0])
|
||||||
|
|
@ -260,10 +264,10 @@ benchmark() {
|
||||||
|
|
||||||
if [ "$1" = "-html" ]; then
|
if [ "$1" = "-html" ]; then
|
||||||
tmpcsv=`fmktemp csv`
|
tmpcsv=`fmktemp csv`
|
||||||
benchstat -csv -geomean go-toml-v2.txt go-toml-v1.txt bs-toml.txt > $tmpcsv
|
benchstat -format csv go-toml-v2.txt go-toml-v1.txt bs-toml.txt > $tmpcsv
|
||||||
benchstathtml $tmpcsv
|
benchstathtml $tmpcsv
|
||||||
else
|
else
|
||||||
benchstat -geomean go-toml-v2.txt go-toml-v1.txt bs-toml.txt
|
benchstat go-toml-v2.txt go-toml-v1.txt bs-toml.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -f go-toml-v2.txt go-toml-v1.txt bs-toml.txt
|
rm -f go-toml-v2.txt go-toml-v1.txt bs-toml.txt
|
||||||
|
|
|
||||||
74
vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
generated
vendored
74
vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
generated
vendored
|
|
@ -57,7 +57,11 @@ type SeenTracker struct {
|
||||||
currentIdx int
|
currentIdx int
|
||||||
}
|
}
|
||||||
|
|
||||||
var pool sync.Pool
|
var pool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return &SeenTracker{}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SeenTracker) reset() {
|
func (s *SeenTracker) reset() {
|
||||||
// Always contains a root element at index 0.
|
// Always contains a root element at index 0.
|
||||||
|
|
@ -149,8 +153,9 @@ func (s *SeenTracker) setExplicitFlag(parentIdx int) {
|
||||||
|
|
||||||
// CheckExpression takes a top-level node and checks that it does not contain
|
// CheckExpression takes a top-level node and checks that it does not contain
|
||||||
// keys that have been seen in previous calls, and validates that types are
|
// keys that have been seen in previous calls, and validates that types are
|
||||||
// consistent.
|
// consistent. It returns true if it is the first time this node's key is seen.
|
||||||
func (s *SeenTracker) CheckExpression(node *unstable.Node) error {
|
// Useful to clear array tables on first use.
|
||||||
|
func (s *SeenTracker) CheckExpression(node *unstable.Node) (bool, error) {
|
||||||
if s.entries == nil {
|
if s.entries == nil {
|
||||||
s.reset()
|
s.reset()
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +171,7 @@ func (s *SeenTracker) CheckExpression(node *unstable.Node) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SeenTracker) checkTable(node *unstable.Node) error {
|
func (s *SeenTracker) checkTable(node *unstable.Node) (bool, error) {
|
||||||
if s.currentIdx >= 0 {
|
if s.currentIdx >= 0 {
|
||||||
s.setExplicitFlag(s.currentIdx)
|
s.setExplicitFlag(s.currentIdx)
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +197,7 @@ func (s *SeenTracker) checkTable(node *unstable.Node) error {
|
||||||
} else {
|
} else {
|
||||||
entry := s.entries[idx]
|
entry := s.entries[idx]
|
||||||
if entry.kind == valueKind {
|
if entry.kind == valueKind {
|
||||||
return fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
|
return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parentIdx = idx
|
parentIdx = idx
|
||||||
|
|
@ -201,25 +206,27 @@ func (s *SeenTracker) checkTable(node *unstable.Node) error {
|
||||||
k := it.Node().Data
|
k := it.Node().Data
|
||||||
idx := s.find(parentIdx, k)
|
idx := s.find(parentIdx, k)
|
||||||
|
|
||||||
|
first := false
|
||||||
if idx >= 0 {
|
if idx >= 0 {
|
||||||
kind := s.entries[idx].kind
|
kind := s.entries[idx].kind
|
||||||
if kind != tableKind {
|
if kind != tableKind {
|
||||||
return fmt.Errorf("toml: key %s should be a table, not a %s", string(k), kind)
|
return false, fmt.Errorf("toml: key %s should be a table, not a %s", string(k), kind)
|
||||||
}
|
}
|
||||||
if s.entries[idx].explicit {
|
if s.entries[idx].explicit {
|
||||||
return fmt.Errorf("toml: table %s already exists", string(k))
|
return false, fmt.Errorf("toml: table %s already exists", string(k))
|
||||||
}
|
}
|
||||||
s.entries[idx].explicit = true
|
s.entries[idx].explicit = true
|
||||||
} else {
|
} else {
|
||||||
idx = s.create(parentIdx, k, tableKind, true, false)
|
idx = s.create(parentIdx, k, tableKind, true, false)
|
||||||
|
first = true
|
||||||
}
|
}
|
||||||
|
|
||||||
s.currentIdx = idx
|
s.currentIdx = idx
|
||||||
|
|
||||||
return nil
|
return first, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SeenTracker) checkArrayTable(node *unstable.Node) error {
|
func (s *SeenTracker) checkArrayTable(node *unstable.Node) (bool, error) {
|
||||||
if s.currentIdx >= 0 {
|
if s.currentIdx >= 0 {
|
||||||
s.setExplicitFlag(s.currentIdx)
|
s.setExplicitFlag(s.currentIdx)
|
||||||
}
|
}
|
||||||
|
|
@ -242,7 +249,7 @@ func (s *SeenTracker) checkArrayTable(node *unstable.Node) error {
|
||||||
} else {
|
} else {
|
||||||
entry := s.entries[idx]
|
entry := s.entries[idx]
|
||||||
if entry.kind == valueKind {
|
if entry.kind == valueKind {
|
||||||
return fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
|
return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,22 +259,23 @@ func (s *SeenTracker) checkArrayTable(node *unstable.Node) error {
|
||||||
k := it.Node().Data
|
k := it.Node().Data
|
||||||
idx := s.find(parentIdx, k)
|
idx := s.find(parentIdx, k)
|
||||||
|
|
||||||
if idx >= 0 {
|
firstTime := idx < 0
|
||||||
|
if firstTime {
|
||||||
|
idx = s.create(parentIdx, k, arrayTableKind, true, false)
|
||||||
|
} else {
|
||||||
kind := s.entries[idx].kind
|
kind := s.entries[idx].kind
|
||||||
if kind != arrayTableKind {
|
if kind != arrayTableKind {
|
||||||
return fmt.Errorf("toml: key %s already exists as a %s, but should be an array table", kind, string(k))
|
return false, fmt.Errorf("toml: key %s already exists as a %s, but should be an array table", kind, string(k))
|
||||||
}
|
}
|
||||||
s.clear(idx)
|
s.clear(idx)
|
||||||
} else {
|
|
||||||
idx = s.create(parentIdx, k, arrayTableKind, true, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s.currentIdx = idx
|
s.currentIdx = idx
|
||||||
|
|
||||||
return nil
|
return firstTime, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SeenTracker) checkKeyValue(node *unstable.Node) error {
|
func (s *SeenTracker) checkKeyValue(node *unstable.Node) (bool, error) {
|
||||||
parentIdx := s.currentIdx
|
parentIdx := s.currentIdx
|
||||||
it := node.Key()
|
it := node.Key()
|
||||||
|
|
||||||
|
|
@ -281,11 +289,11 @@ func (s *SeenTracker) checkKeyValue(node *unstable.Node) error {
|
||||||
} else {
|
} else {
|
||||||
entry := s.entries[idx]
|
entry := s.entries[idx]
|
||||||
if it.IsLast() {
|
if it.IsLast() {
|
||||||
return fmt.Errorf("toml: key %s is already defined", string(k))
|
return false, fmt.Errorf("toml: key %s is already defined", string(k))
|
||||||
} else if entry.kind != tableKind {
|
} else if entry.kind != tableKind {
|
||||||
return fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
|
return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
|
||||||
} else if entry.explicit {
|
} else if entry.explicit {
|
||||||
return fmt.Errorf("toml: cannot redefine table %s that has already been explicitly defined", string(k))
|
return false, fmt.Errorf("toml: cannot redefine table %s that has already been explicitly defined", string(k))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,45 +311,39 @@ func (s *SeenTracker) checkKeyValue(node *unstable.Node) error {
|
||||||
return s.checkArray(value)
|
return s.checkArray(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SeenTracker) checkArray(node *unstable.Node) error {
|
func (s *SeenTracker) checkArray(node *unstable.Node) (first bool, err error) {
|
||||||
it := node.Children()
|
it := node.Children()
|
||||||
for it.Next() {
|
for it.Next() {
|
||||||
n := it.Node()
|
n := it.Node()
|
||||||
switch n.Kind {
|
switch n.Kind {
|
||||||
case unstable.InlineTable:
|
case unstable.InlineTable:
|
||||||
err := s.checkInlineTable(n)
|
first, err = s.checkInlineTable(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return false, err
|
||||||
}
|
}
|
||||||
case unstable.Array:
|
case unstable.Array:
|
||||||
err := s.checkArray(n)
|
first, err = s.checkArray(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return first, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SeenTracker) checkInlineTable(node *unstable.Node) error {
|
func (s *SeenTracker) checkInlineTable(node *unstable.Node) (first bool, err error) {
|
||||||
if pool.New == nil {
|
|
||||||
pool.New = func() interface{} {
|
|
||||||
return &SeenTracker{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s = pool.Get().(*SeenTracker)
|
s = pool.Get().(*SeenTracker)
|
||||||
s.reset()
|
s.reset()
|
||||||
|
|
||||||
it := node.Children()
|
it := node.Children()
|
||||||
for it.Next() {
|
for it.Next() {
|
||||||
n := it.Node()
|
n := it.Node()
|
||||||
err := s.checkKeyValue(n)
|
first, err = s.checkKeyValue(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -352,5 +354,5 @@ func (s *SeenTracker) checkInlineTable(node *unstable.Node) error {
|
||||||
// redefinition of its keys: check* functions cannot walk into
|
// redefinition of its keys: check* functions cannot walk into
|
||||||
// a value.
|
// a value.
|
||||||
pool.Put(s)
|
pool.Put(s)
|
||||||
return nil
|
return first, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
61
vendor/github.com/pelletier/go-toml/v2/marshaler.go
generated
vendored
61
vendor/github.com/pelletier/go-toml/v2/marshaler.go
generated
vendored
|
|
@ -3,11 +3,12 @@ package toml
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding"
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -37,10 +38,11 @@ type Encoder struct {
|
||||||
w io.Writer
|
w io.Writer
|
||||||
|
|
||||||
// global settings
|
// global settings
|
||||||
tablesInline bool
|
tablesInline bool
|
||||||
arraysMultiline bool
|
arraysMultiline bool
|
||||||
indentSymbol string
|
indentSymbol string
|
||||||
indentTables bool
|
indentTables bool
|
||||||
|
marshalJsonNumbers bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEncoder returns a new Encoder that writes to w.
|
// NewEncoder returns a new Encoder that writes to w.
|
||||||
|
|
@ -87,6 +89,17 @@ func (enc *Encoder) SetIndentTables(indent bool) *Encoder {
|
||||||
return enc
|
return enc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetMarshalJsonNumbers forces the encoder to serialize `json.Number` as a
|
||||||
|
// float or integer instead of relying on TextMarshaler to emit a string.
|
||||||
|
//
|
||||||
|
// *Unstable:* This method does not follow the compatibility guarantees of
|
||||||
|
// semver. It can be changed or removed without a new major version being
|
||||||
|
// issued.
|
||||||
|
func (enc *Encoder) SetMarshalJsonNumbers(indent bool) *Encoder {
|
||||||
|
enc.marshalJsonNumbers = indent
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
// Encode writes a TOML representation of v to the stream.
|
// Encode writes a TOML representation of v to the stream.
|
||||||
//
|
//
|
||||||
// If v cannot be represented to TOML it returns an error.
|
// If v cannot be represented to TOML it returns an error.
|
||||||
|
|
@ -252,10 +265,22 @@ func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, e
|
||||||
return append(b, x.String()...), nil
|
return append(b, x.String()...), nil
|
||||||
case LocalDateTime:
|
case LocalDateTime:
|
||||||
return append(b, x.String()...), nil
|
return append(b, x.String()...), nil
|
||||||
|
case json.Number:
|
||||||
|
if enc.marshalJsonNumbers {
|
||||||
|
if x == "" { /// Useful zero value.
|
||||||
|
return append(b, "0"...), nil
|
||||||
|
} else if v, err := x.Int64(); err == nil {
|
||||||
|
return enc.encode(b, ctx, reflect.ValueOf(v))
|
||||||
|
} else if f, err := x.Float64(); err == nil {
|
||||||
|
return enc.encode(b, ctx, reflect.ValueOf(f))
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("toml: unable to convert %q to int64 or float64", x)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hasTextMarshaler := v.Type().Implements(textMarshalerType)
|
hasTextMarshaler := v.Type().Implements(textMarshalerType)
|
||||||
if hasTextMarshaler || (v.CanAddr() && reflect.PtrTo(v.Type()).Implements(textMarshalerType)) {
|
if hasTextMarshaler || (v.CanAddr() && reflect.PointerTo(v.Type()).Implements(textMarshalerType)) {
|
||||||
if !hasTextMarshaler {
|
if !hasTextMarshaler {
|
||||||
v = v.Addr()
|
v = v.Addr()
|
||||||
}
|
}
|
||||||
|
|
@ -606,6 +631,18 @@ func (enc *Encoder) keyToString(k reflect.Value) (string, error) {
|
||||||
return "", fmt.Errorf("toml: error marshalling key %v from text: %w", k, err)
|
return "", fmt.Errorf("toml: error marshalling key %v from text: %w", k, err)
|
||||||
}
|
}
|
||||||
return string(keyB), nil
|
return string(keyB), nil
|
||||||
|
|
||||||
|
case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64:
|
||||||
|
return strconv.FormatInt(k.Int(), 10), nil
|
||||||
|
|
||||||
|
case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64:
|
||||||
|
return strconv.FormatUint(k.Uint(), 10), nil
|
||||||
|
|
||||||
|
case keyType.Kind() == reflect.Float32:
|
||||||
|
return strconv.FormatFloat(k.Float(), 'f', -1, 32), nil
|
||||||
|
|
||||||
|
case keyType.Kind() == reflect.Float64:
|
||||||
|
return strconv.FormatFloat(k.Float(), 'f', -1, 64), nil
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("toml: type %s is not supported as a map key", keyType.Kind())
|
return "", fmt.Errorf("toml: type %s is not supported as a map key", keyType.Kind())
|
||||||
}
|
}
|
||||||
|
|
@ -643,8 +680,8 @@ func (enc *Encoder) encodeMap(b []byte, ctx encoderCtx, v reflect.Value) ([]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortEntriesByKey(e []entry) {
|
func sortEntriesByKey(e []entry) {
|
||||||
sort.Slice(e, func(i, j int) bool {
|
slices.SortFunc(e, func(a, b entry) int {
|
||||||
return e[i].Key < e[j].Key
|
return strings.Compare(a.Key, b.Key)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -707,6 +744,8 @@ func walkStruct(ctx encoderCtx, t *table, v reflect.Value) {
|
||||||
if fieldType.Anonymous {
|
if fieldType.Anonymous {
|
||||||
if fieldType.Type.Kind() == reflect.Struct {
|
if fieldType.Type.Kind() == reflect.Struct {
|
||||||
walkStruct(ctx, t, f)
|
walkStruct(ctx, t, f)
|
||||||
|
} else if fieldType.Type.Kind() == reflect.Ptr && !f.IsNil() && f.Elem().Kind() == reflect.Struct {
|
||||||
|
walkStruct(ctx, t, f.Elem())
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -924,7 +963,7 @@ func willConvertToTable(ctx encoderCtx, v reflect.Value) bool {
|
||||||
if !v.IsValid() {
|
if !v.IsValid() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if v.Type() == timeType || v.Type().Implements(textMarshalerType) || (v.Kind() != reflect.Ptr && v.CanAddr() && reflect.PtrTo(v.Type()).Implements(textMarshalerType)) {
|
if v.Type() == timeType || v.Type().Implements(textMarshalerType) || (v.Kind() != reflect.Ptr && v.CanAddr() && reflect.PointerTo(v.Type()).Implements(textMarshalerType)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -998,6 +1037,10 @@ func (enc *Encoder) encodeSliceAsArrayTable(b []byte, ctx encoderCtx, v reflect.
|
||||||
|
|
||||||
scratch = enc.commented(ctx.commented, scratch)
|
scratch = enc.commented(ctx.commented, scratch)
|
||||||
|
|
||||||
|
if enc.indentTables {
|
||||||
|
scratch = enc.indent(ctx.indent, scratch)
|
||||||
|
}
|
||||||
|
|
||||||
scratch = append(scratch, "[["...)
|
scratch = append(scratch, "[["...)
|
||||||
|
|
||||||
for i, k := range ctx.parentKey {
|
for i, k := range ctx.parentKey {
|
||||||
|
|
|
||||||
102
vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
generated
vendored
102
vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
generated
vendored
|
|
@ -5,9 +5,9 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -21,10 +21,8 @@ import (
|
||||||
//
|
//
|
||||||
// It is a shortcut for Decoder.Decode() with the default options.
|
// It is a shortcut for Decoder.Decode() with the default options.
|
||||||
func Unmarshal(data []byte, v interface{}) error {
|
func Unmarshal(data []byte, v interface{}) error {
|
||||||
p := unstable.Parser{}
|
d := decoder{}
|
||||||
p.Reset(data)
|
d.p.Reset(data)
|
||||||
d := decoder{p: &p}
|
|
||||||
|
|
||||||
return d.FromParser(v)
|
return d.FromParser(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,6 +33,9 @@ type Decoder struct {
|
||||||
|
|
||||||
// global settings
|
// global settings
|
||||||
strict bool
|
strict bool
|
||||||
|
|
||||||
|
// toggles unmarshaler interface
|
||||||
|
unmarshalerInterface bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDecoder creates a new Decoder that will read from r.
|
// NewDecoder creates a new Decoder that will read from r.
|
||||||
|
|
@ -54,6 +55,24 @@ func (d *Decoder) DisallowUnknownFields() *Decoder {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnableUnmarshalerInterface allows to enable unmarshaler interface.
|
||||||
|
//
|
||||||
|
// With this feature enabled, types implementing the unstable/Unmarshaler
|
||||||
|
// interface can be decoded from any structure of the document. It allows types
|
||||||
|
// that don't have a straightfoward TOML representation to provide their own
|
||||||
|
// decoding logic.
|
||||||
|
//
|
||||||
|
// Currently, types can only decode from a single value. Tables and array tables
|
||||||
|
// are not supported.
|
||||||
|
//
|
||||||
|
// *Unstable:* This method does not follow the compatibility guarantees of
|
||||||
|
// semver. It can be changed or removed without a new major version being
|
||||||
|
// issued.
|
||||||
|
func (d *Decoder) EnableUnmarshalerInterface() *Decoder {
|
||||||
|
d.unmarshalerInterface = true
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
// Decode the whole content of r into v.
|
// Decode the whole content of r into v.
|
||||||
//
|
//
|
||||||
// By default, values in the document that don't exist in the target Go value
|
// By default, values in the document that don't exist in the target Go value
|
||||||
|
|
@ -96,26 +115,25 @@ func (d *Decoder) DisallowUnknownFields() *Decoder {
|
||||||
// Inline Table -> same as Table
|
// Inline Table -> same as Table
|
||||||
// Array of Tables -> same as Array and Table
|
// Array of Tables -> same as Array and Table
|
||||||
func (d *Decoder) Decode(v interface{}) error {
|
func (d *Decoder) Decode(v interface{}) error {
|
||||||
b, err := ioutil.ReadAll(d.r)
|
b, err := io.ReadAll(d.r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("toml: %w", err)
|
return fmt.Errorf("toml: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
p := unstable.Parser{}
|
|
||||||
p.Reset(b)
|
|
||||||
dec := decoder{
|
dec := decoder{
|
||||||
p: &p,
|
|
||||||
strict: strict{
|
strict: strict{
|
||||||
Enabled: d.strict,
|
Enabled: d.strict,
|
||||||
},
|
},
|
||||||
|
unmarshalerInterface: d.unmarshalerInterface,
|
||||||
}
|
}
|
||||||
|
dec.p.Reset(b)
|
||||||
|
|
||||||
return dec.FromParser(v)
|
return dec.FromParser(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
type decoder struct {
|
type decoder struct {
|
||||||
// Which parser instance in use for this decoding session.
|
// Which parser instance in use for this decoding session.
|
||||||
p *unstable.Parser
|
p unstable.Parser
|
||||||
|
|
||||||
// Flag indicating that the current expression is stashed.
|
// Flag indicating that the current expression is stashed.
|
||||||
// If set to true, calling nextExpr will not actually pull a new expression
|
// If set to true, calling nextExpr will not actually pull a new expression
|
||||||
|
|
@ -127,6 +145,10 @@ type decoder struct {
|
||||||
// need to be skipped.
|
// need to be skipped.
|
||||||
skipUntilTable bool
|
skipUntilTable bool
|
||||||
|
|
||||||
|
// Flag indicating that the current array/slice table should be cleared because
|
||||||
|
// it is the first encounter of an array table.
|
||||||
|
clearArrayTable bool
|
||||||
|
|
||||||
// Tracks position in Go arrays.
|
// Tracks position in Go arrays.
|
||||||
// This is used when decoding [[array tables]] into Go arrays. Given array
|
// This is used when decoding [[array tables]] into Go arrays. Given array
|
||||||
// tables are separate TOML expression, we need to keep track of where we
|
// tables are separate TOML expression, we need to keep track of where we
|
||||||
|
|
@ -139,6 +161,9 @@ type decoder struct {
|
||||||
// Strict mode
|
// Strict mode
|
||||||
strict strict
|
strict strict
|
||||||
|
|
||||||
|
// Flag that enables/disables unmarshaler interface.
|
||||||
|
unmarshalerInterface bool
|
||||||
|
|
||||||
// Current context for the error.
|
// Current context for the error.
|
||||||
errorContext *errorContext
|
errorContext *errorContext
|
||||||
}
|
}
|
||||||
|
|
@ -246,9 +271,10 @@ Rules for the unmarshal code:
|
||||||
func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) error {
|
func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) error {
|
||||||
var x reflect.Value
|
var x reflect.Value
|
||||||
var err error
|
var err error
|
||||||
|
var first bool // used for to clear array tables on first use
|
||||||
|
|
||||||
if !(d.skipUntilTable && expr.Kind == unstable.KeyValue) {
|
if !(d.skipUntilTable && expr.Kind == unstable.KeyValue) {
|
||||||
err = d.seen.CheckExpression(expr)
|
first, err = d.seen.CheckExpression(expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -267,6 +293,7 @@ func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) err
|
||||||
case unstable.ArrayTable:
|
case unstable.ArrayTable:
|
||||||
d.skipUntilTable = false
|
d.skipUntilTable = false
|
||||||
d.strict.EnterArrayTable(expr)
|
d.strict.EnterArrayTable(expr)
|
||||||
|
d.clearArrayTable = first
|
||||||
x, err = d.handleArrayTable(expr.Key(), v)
|
x, err = d.handleArrayTable(expr.Key(), v)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("parser should not permit expression of kind %s at document root", expr.Kind))
|
panic(fmt.Errorf("parser should not permit expression of kind %s at document root", expr.Kind))
|
||||||
|
|
@ -307,6 +334,10 @@ func (d *decoder) handleArrayTableCollectionLast(key unstable.Iterator, v reflec
|
||||||
reflect.Copy(nelem, elem)
|
reflect.Copy(nelem, elem)
|
||||||
elem = nelem
|
elem = nelem
|
||||||
}
|
}
|
||||||
|
if d.clearArrayTable && elem.Len() > 0 {
|
||||||
|
elem.SetLen(0)
|
||||||
|
d.clearArrayTable = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return d.handleArrayTableCollectionLast(key, elem)
|
return d.handleArrayTableCollectionLast(key, elem)
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
|
|
@ -325,6 +356,10 @@ func (d *decoder) handleArrayTableCollectionLast(key unstable.Iterator, v reflec
|
||||||
|
|
||||||
return v, nil
|
return v, nil
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
|
if d.clearArrayTable && v.Len() > 0 {
|
||||||
|
v.SetLen(0)
|
||||||
|
d.clearArrayTable = false
|
||||||
|
}
|
||||||
elemType := v.Type().Elem()
|
elemType := v.Type().Elem()
|
||||||
var elem reflect.Value
|
var elem reflect.Value
|
||||||
if elemType.Kind() == reflect.Interface {
|
if elemType.Kind() == reflect.Interface {
|
||||||
|
|
@ -576,7 +611,7 @@ func (d *decoder) handleKeyValues(v reflect.Value) (reflect.Value, error) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
err := d.seen.CheckExpression(expr)
|
_, err := d.seen.CheckExpression(expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reflect.Value{}, err
|
return reflect.Value{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -634,6 +669,14 @@ func (d *decoder) handleValue(value *unstable.Node, v reflect.Value) error {
|
||||||
v = initAndDereferencePointer(v)
|
v = initAndDereferencePointer(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.unmarshalerInterface {
|
||||||
|
if v.CanAddr() && v.Addr().CanInterface() {
|
||||||
|
if outi, ok := v.Addr().Interface().(unstable.Unmarshaler); ok {
|
||||||
|
return outi.UnmarshalTOML(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ok, err := d.tryTextUnmarshaler(value, v)
|
ok, err := d.tryTextUnmarshaler(value, v)
|
||||||
if ok || err != nil {
|
if ok || err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -1031,12 +1074,39 @@ func (d *decoder) keyFromData(keyType reflect.Type, data []byte) (reflect.Value,
|
||||||
}
|
}
|
||||||
return mk, nil
|
return mk, nil
|
||||||
|
|
||||||
case reflect.PtrTo(keyType).Implements(textUnmarshalerType):
|
case reflect.PointerTo(keyType).Implements(textUnmarshalerType):
|
||||||
mk := reflect.New(keyType)
|
mk := reflect.New(keyType)
|
||||||
if err := mk.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
|
if err := mk.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
|
||||||
return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err)
|
return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err)
|
||||||
}
|
}
|
||||||
return mk.Elem(), nil
|
return mk.Elem(), nil
|
||||||
|
|
||||||
|
case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64:
|
||||||
|
key, err := strconv.ParseInt(string(data), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from integer: %w", stringType, err)
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(key).Convert(keyType), nil
|
||||||
|
case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64:
|
||||||
|
key, err := strconv.ParseUint(string(data), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from unsigned integer: %w", stringType, err)
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(key).Convert(keyType), nil
|
||||||
|
|
||||||
|
case keyType.Kind() == reflect.Float32:
|
||||||
|
key, err := strconv.ParseFloat(string(data), 32)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err)
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(float32(key)), nil
|
||||||
|
|
||||||
|
case keyType.Kind() == reflect.Float64:
|
||||||
|
key, err := strconv.ParseFloat(string(data), 64)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err)
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(float64(key)), nil
|
||||||
}
|
}
|
||||||
return reflect.Value{}, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", stringType, keyType)
|
return reflect.Value{}, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", stringType, keyType)
|
||||||
}
|
}
|
||||||
|
|
@ -1097,9 +1167,9 @@ func (d *decoder) handleKeyValuePart(key unstable.Iterator, value *unstable.Node
|
||||||
|
|
||||||
f := fieldByIndex(v, path)
|
f := fieldByIndex(v, path)
|
||||||
|
|
||||||
if !f.CanSet() {
|
if !f.CanAddr() {
|
||||||
// If the field is not settable, need to take a slower path and make a copy of
|
// If the field is not addressable, need to take a slower path and
|
||||||
// the struct itself to a new location.
|
// make a copy of the struct itself to a new location.
|
||||||
nvp := reflect.New(v.Type())
|
nvp := reflect.New(v.Type())
|
||||||
nvp.Elem().Set(v)
|
nvp.Elem().Set(v)
|
||||||
v = nvp.Elem()
|
v = nvp.Elem()
|
||||||
|
|
|
||||||
7
vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go
generated
vendored
Normal file
7
vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package unstable
|
||||||
|
|
||||||
|
// The Unmarshaler interface may be implemented by types to customize their
|
||||||
|
// behavior when being unmarshaled from a TOML document.
|
||||||
|
type Unmarshaler interface {
|
||||||
|
UnmarshalTOML(value *Node) error
|
||||||
|
}
|
||||||
4
vendor/github.com/sagikazarmark/locafero/.envrc
generated
vendored
4
vendor/github.com/sagikazarmark/locafero/.envrc
generated
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
|
if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
|
||||||
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
|
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
|
||||||
fi
|
fi
|
||||||
use flake . --impure
|
use flake . --impure
|
||||||
|
|
|
||||||
6
vendor/github.com/sagikazarmark/locafero/finder.go
generated
vendored
6
vendor/github.com/sagikazarmark/locafero/finder.go
generated
vendored
|
|
@ -27,7 +27,7 @@ type Finder struct {
|
||||||
// It provides the capability to search for entries with depth,
|
// It provides the capability to search for entries with depth,
|
||||||
// meaning it can target deeper locations within the directory structure.
|
// meaning it can target deeper locations within the directory structure.
|
||||||
//
|
//
|
||||||
// It also supports glob syntax (as defined by [filepat.Match]), offering greater flexibility in search patterns.
|
// It also supports glob syntax (as defined by [filepath.Match]), offering greater flexibility in search patterns.
|
||||||
//
|
//
|
||||||
// Examples:
|
// Examples:
|
||||||
// - config.yaml
|
// - config.yaml
|
||||||
|
|
@ -63,7 +63,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) {
|
||||||
|
|
||||||
// pool.Go(func() ([]string, error) {
|
// pool.Go(func() ([]string, error) {
|
||||||
// // If the name contains any glob character, perform a glob match
|
// // If the name contains any glob character, perform a glob match
|
||||||
// if strings.ContainsAny(searchName, "*?[]\\^") {
|
// if strings.ContainsAny(searchName, globMatch) {
|
||||||
// return globWalkSearch(fsys, searchPath, searchName, f.Type)
|
// return globWalkSearch(fsys, searchPath, searchName, f.Type)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
|
@ -79,7 +79,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) {
|
||||||
|
|
||||||
allResults, err := iter.MapErr(searchItems, func(item *searchItem) ([]string, error) {
|
allResults, err := iter.MapErr(searchItems, func(item *searchItem) ([]string, error) {
|
||||||
// If the name contains any glob character, perform a glob match
|
// If the name contains any glob character, perform a glob match
|
||||||
if strings.ContainsAny(item.name, "*?[]\\^") {
|
if strings.ContainsAny(item.name, globMatch) {
|
||||||
return globWalkSearch(fsys, item.path, item.name, f.Type)
|
return globWalkSearch(fsys, item.path, item.name, f.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
333
vendor/github.com/sagikazarmark/locafero/flake.lock
generated
vendored
333
vendor/github.com/sagikazarmark/locafero/flake.lock
generated
vendored
|
|
@ -1,22 +1,84 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"devenv": {
|
"cachix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat",
|
"devenv": "devenv_2",
|
||||||
"nix": "nix",
|
"flake-compat": [
|
||||||
"nixpkgs": "nixpkgs",
|
"devenv",
|
||||||
"pre-commit-hooks": "pre-commit-hooks"
|
"flake-compat"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"devenv",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"pre-commit-hooks": [
|
||||||
|
"devenv",
|
||||||
|
"pre-commit-hooks"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1694097209,
|
"lastModified": 1712055811,
|
||||||
"narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=",
|
"narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "devenv",
|
"repo": "cachix",
|
||||||
"rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189",
|
"rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
|
"repo": "cachix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"devenv": {
|
||||||
|
"inputs": {
|
||||||
|
"cachix": "cachix",
|
||||||
|
"flake-compat": "flake-compat_2",
|
||||||
|
"nix": "nix_2",
|
||||||
|
"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",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"poetry2nix": "poetry2nix",
|
||||||
|
"pre-commit-hooks": [
|
||||||
|
"devenv",
|
||||||
|
"cachix",
|
||||||
|
"pre-commit-hooks"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1708704632,
|
||||||
|
"narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "devenv",
|
||||||
|
"rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"ref": "python-rewrite",
|
||||||
"repo": "devenv",
|
"repo": "devenv",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|
@ -37,16 +99,32 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"flake-compat_2": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1696426674,
|
||||||
|
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-parts": {
|
"flake-parts": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs-lib": "nixpkgs-lib"
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1693611461,
|
"lastModified": 1725234343,
|
||||||
"narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=",
|
"narHash": "sha256-+ebgonl3NbiKD2UD0x4BszCZQ6sTfL4xioaM49o5B3Y=",
|
||||||
"owner": "hercules-ci",
|
"owner": "hercules-ci",
|
||||||
"repo": "flake-parts",
|
"repo": "flake-parts",
|
||||||
"rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca",
|
"rev": "567b938d64d4b4112ee253b9274472dc3a346eb6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -60,11 +138,29 @@
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1685518550,
|
"lastModified": 1689068808,
|
||||||
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
|
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
|
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"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"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -82,11 +178,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1660459072,
|
"lastModified": 1709087332,
|
||||||
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
|
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||||
"owner": "hercules-ci",
|
"owner": "hercules-ci",
|
||||||
"repo": "gitignore.nix",
|
"repo": "gitignore.nix",
|
||||||
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
|
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -95,53 +191,90 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lowdown-src": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1633514407,
|
|
||||||
"narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
|
|
||||||
"owner": "kristapsdz",
|
|
||||||
"repo": "lowdown",
|
|
||||||
"rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "kristapsdz",
|
|
||||||
"repo": "lowdown",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nix": {
|
"nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"lowdown-src": "lowdown-src",
|
"flake-compat": "flake-compat",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
"devenv",
|
||||||
|
"cachix",
|
||||||
"devenv",
|
"devenv",
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"nixpkgs-regression": "nixpkgs-regression"
|
"nixpkgs-regression": "nixpkgs-regression"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1676545802,
|
"lastModified": 1712911606,
|
||||||
"narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
|
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
|
||||||
"owner": "domenkozar",
|
"owner": "domenkozar",
|
||||||
"repo": "nix",
|
"repo": "nix",
|
||||||
"rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
|
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "domenkozar",
|
"owner": "domenkozar",
|
||||||
"ref": "relaxed-flakes",
|
"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": {
|
||||||
|
"flake-compat": [
|
||||||
|
"devenv",
|
||||||
|
"flake-compat"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"devenv",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"nixpkgs-regression": "nixpkgs-regression_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1712911606,
|
||||||
|
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
|
||||||
|
"owner": "domenkozar",
|
||||||
|
"repo": "nix",
|
||||||
|
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "domenkozar",
|
||||||
|
"ref": "devenv-2.21",
|
||||||
"repo": "nix",
|
"repo": "nix",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1678875422,
|
"lastModified": 1692808169,
|
||||||
"narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
|
"narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
|
"rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -153,20 +286,14 @@
|
||||||
},
|
},
|
||||||
"nixpkgs-lib": {
|
"nixpkgs-lib": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"dir": "lib",
|
"lastModified": 1725233747,
|
||||||
"lastModified": 1693471703,
|
"narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=",
|
||||||
"narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=",
|
"type": "tarball",
|
||||||
"owner": "NixOS",
|
"url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85",
|
|
||||||
"type": "github"
|
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"dir": "lib",
|
"type": "tarball",
|
||||||
"owner": "NixOS",
|
"url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-regression": {
|
"nixpkgs-regression": {
|
||||||
|
|
@ -185,29 +312,61 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs-regression_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1685801374,
|
"lastModified": 1643052045,
|
||||||
"narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
|
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
|
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-23.05",
|
"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",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1694343207,
|
"lastModified": 1713361204,
|
||||||
"narHash": "sha256-jWi7OwFxU5Owi4k2JmiL1sa/OuBCQtpaAesuj5LXC8w=",
|
"narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "devenv-nixpkgs",
|
||||||
|
"rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"ref": "rolling",
|
||||||
|
"repo": "devenv-nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_3": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1725910328,
|
||||||
|
"narHash": "sha256-n9pCtzGZ0httmTwMuEbi5E78UQ4ZbQMr1pzi5N0LAG8=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "78058d810644f5ed276804ce7ea9e82d92bee293",
|
"rev": "5775c2583f1801df7b790bf7f7d710a19bac66f4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -217,13 +376,38 @@
|
||||||
"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": {
|
"pre-commit-hooks": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": [
|
"flake-compat": [
|
||||||
"devenv",
|
"devenv",
|
||||||
"flake-compat"
|
"flake-compat"
|
||||||
],
|
],
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils_2",
|
||||||
"gitignore": "gitignore",
|
"gitignore": "gitignore",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"devenv",
|
"devenv",
|
||||||
|
|
@ -232,11 +416,11 @@
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
"nixpkgs-stable": "nixpkgs-stable"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1688056373,
|
"lastModified": 1713775815,
|
||||||
"narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=",
|
"narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "pre-commit-hooks.nix",
|
"repo": "pre-commit-hooks.nix",
|
||||||
"rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7",
|
"rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -249,7 +433,7 @@
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"devenv": "devenv",
|
"devenv": "devenv",
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts",
|
||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": "nixpkgs_3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
|
|
@ -266,6 +450,21 @@
|
||||||
"repo": "default",
|
"repo": "default",
|
||||||
"type": "github"
|
"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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|
|
||||||
21
vendor/github.com/sagikazarmark/locafero/flake.nix
generated
vendored
21
vendor/github.com/sagikazarmark/locafero/flake.nix
generated
vendored
|
|
@ -20,6 +20,7 @@
|
||||||
default = {
|
default = {
|
||||||
languages = {
|
languages = {
|
||||||
go.enable = true;
|
go.enable = true;
|
||||||
|
go.package = pkgs.lib.mkDefault pkgs.go_1_23;
|
||||||
};
|
};
|
||||||
|
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
|
|
@ -34,11 +35,27 @@
|
||||||
|
|
||||||
ci = devenv.shells.default;
|
ci = devenv.shells.default;
|
||||||
|
|
||||||
ci_1_20 = {
|
ci_1_21 = {
|
||||||
imports = [ devenv.shells.ci ];
|
imports = [ devenv.shells.ci ];
|
||||||
|
|
||||||
languages = {
|
languages = {
|
||||||
go.package = pkgs.go_1_20;
|
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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
5
vendor/github.com/sagikazarmark/locafero/glob.go
generated
vendored
Normal file
5
vendor/github.com/sagikazarmark/locafero/glob.go
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package locafero
|
||||||
|
|
||||||
|
const globMatch = "*?[]\\^"
|
||||||
8
vendor/github.com/sagikazarmark/locafero/glob_windows.go
generated
vendored
Normal file
8
vendor/github.com/sagikazarmark/locafero/glob_windows.go
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package locafero
|
||||||
|
|
||||||
|
// See [filepath.Match]:
|
||||||
|
//
|
||||||
|
// On Windows, escaping is disabled. Instead, '\\' is treated as path separator.
|
||||||
|
const globMatch = "*?[]^"
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
[*.go]
|
[*.go]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
indent_size = 4
|
|
||||||
insert_final_newline = true
|
|
||||||
|
|
||||||
[*.{yml,yaml}]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
18
vendor/github.com/spf13/afero/.golangci.yaml
generated
vendored
Normal file
18
vendor/github.com/spf13/afero/.golangci.yaml
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
linters-settings:
|
||||||
|
gci:
|
||||||
|
sections:
|
||||||
|
- standard
|
||||||
|
- default
|
||||||
|
- prefix(github.com/spf13/afero)
|
||||||
|
|
||||||
|
linters:
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- gci
|
||||||
|
- gofmt
|
||||||
|
- gofumpt
|
||||||
|
- staticcheck
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-dirs:
|
||||||
|
- gcsfs/internal/stiface
|
||||||
2
vendor/github.com/spf13/afero/README.md
generated
vendored
2
vendor/github.com/spf13/afero/README.md
generated
vendored
|
|
@ -12,7 +12,7 @@ types and methods. Afero has an exceptionally clean interface and simple design
|
||||||
without needless constructors or initialization methods.
|
without needless constructors or initialization methods.
|
||||||
|
|
||||||
Afero is also a library providing a base set of interoperable backend
|
Afero is also a library providing a base set of interoperable backend
|
||||||
filesystems that make it easy to work with afero while retaining all the power
|
filesystems that make it easy to work with, while retaining all the power
|
||||||
and benefit of the os and ioutil packages.
|
and benefit of the os and ioutil packages.
|
||||||
|
|
||||||
Afero provides significant improvements over using the os package alone, most
|
Afero provides significant improvements over using the os package alone, most
|
||||||
|
|
|
||||||
1
vendor/github.com/spf13/afero/iofs.go
generated
vendored
1
vendor/github.com/spf13/afero/iofs.go
generated
vendored
|
|
@ -255,7 +255,6 @@ func (f fromIOFSFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||||
ret := make([]os.FileInfo, len(entries))
|
ret := make([]os.FileInfo, len(entries))
|
||||||
for i := range entries {
|
for i := range entries {
|
||||||
ret[i], err = entries[i].Info()
|
ret[i], err = entries[i].Info()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
vendor/github.com/spf13/afero/memmap.go
generated
vendored
2
vendor/github.com/spf13/afero/memmap.go
generated
vendored
|
|
@ -16,11 +16,9 @@ package afero
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
|
||||||
4
vendor/github.com/spf13/cast/README.md
generated
vendored
4
vendor/github.com/spf13/cast/README.md
generated
vendored
|
|
@ -1,9 +1,9 @@
|
||||||
# cast
|
# cast
|
||||||
|
|
||||||
[](https://github.com/spf13/cast/actions/workflows/ci.yml)
|
[](https://github.com/spf13/cast/actions/workflows/test.yaml)
|
||||||
[](https://pkg.go.dev/mod/github.com/spf13/cast)
|
[](https://pkg.go.dev/mod/github.com/spf13/cast)
|
||||||

|

|
||||||
[](https://goreportcard.com/report/github.com/spf13/cast)
|
[](https://goreportcard.com/report/github.com/spf13/cast)
|
||||||
|
|
||||||
Easy and safe casting from one type to another in Go
|
Easy and safe casting from one type to another in Go
|
||||||
|
|
||||||
|
|
|
||||||
98
vendor/github.com/spf13/cast/caste.go
generated
vendored
98
vendor/github.com/spf13/cast/caste.go
generated
vendored
|
|
@ -18,6 +18,14 @@ import (
|
||||||
|
|
||||||
var errNegativeNotAllowed = errors.New("unable to cast negative value")
|
var errNegativeNotAllowed = errors.New("unable to cast negative value")
|
||||||
|
|
||||||
|
type float64EProvider interface {
|
||||||
|
Float64() (float64, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type float64Provider interface {
|
||||||
|
Float64() float64
|
||||||
|
}
|
||||||
|
|
||||||
// ToTimeE casts an interface to a time.Time type.
|
// ToTimeE casts an interface to a time.Time type.
|
||||||
func ToTimeE(i interface{}) (tim time.Time, err error) {
|
func ToTimeE(i interface{}) (tim time.Time, err error) {
|
||||||
return ToTimeInDefaultLocationE(i, time.UTC)
|
return ToTimeInDefaultLocationE(i, time.UTC)
|
||||||
|
|
@ -77,11 +85,14 @@ func ToDurationE(i interface{}) (d time.Duration, err error) {
|
||||||
d, err = time.ParseDuration(s + "ns")
|
d, err = time.ParseDuration(s + "ns")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
case json.Number:
|
case float64EProvider:
|
||||||
var v float64
|
var v float64
|
||||||
v, err = s.Float64()
|
v, err = s.Float64()
|
||||||
d = time.Duration(v)
|
d = time.Duration(v)
|
||||||
return
|
return
|
||||||
|
case float64Provider:
|
||||||
|
d = time.Duration(s.Float64())
|
||||||
|
return
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i)
|
err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i)
|
||||||
return
|
return
|
||||||
|
|
@ -174,12 +185,14 @@ func ToFloat64E(i interface{}) (float64, error) {
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
|
return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
|
||||||
case json.Number:
|
case float64EProvider:
|
||||||
v, err := s.Float64()
|
v, err := s.Float64()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
|
return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
|
||||||
|
case float64Provider:
|
||||||
|
return s.Float64(), nil
|
||||||
case bool:
|
case bool:
|
||||||
if s {
|
if s {
|
||||||
return 1, nil
|
return 1, nil
|
||||||
|
|
@ -230,12 +243,14 @@ func ToFloat32E(i interface{}) (float32, error) {
|
||||||
return float32(v), nil
|
return float32(v), nil
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
|
return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
|
||||||
case json.Number:
|
case float64EProvider:
|
||||||
v, err := s.Float64()
|
v, err := s.Float64()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return float32(v), nil
|
return float32(v), nil
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
|
return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
|
||||||
|
case float64Provider:
|
||||||
|
return float32(s.Float64()), nil
|
||||||
case bool:
|
case bool:
|
||||||
if s {
|
if s {
|
||||||
return 1, nil
|
return 1, nil
|
||||||
|
|
@ -598,12 +613,12 @@ func ToUint64E(i interface{}) (uint64, error) {
|
||||||
|
|
||||||
switch s := i.(type) {
|
switch s := i.(type) {
|
||||||
case string:
|
case string:
|
||||||
v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
|
v, err := strconv.ParseUint(trimZeroDecimal(s), 0, 0)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if v < 0 {
|
if v < 0 {
|
||||||
return 0, errNegativeNotAllowed
|
return 0, errNegativeNotAllowed
|
||||||
}
|
}
|
||||||
return uint64(v), nil
|
return v, nil
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i)
|
return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i)
|
||||||
case json.Number:
|
case json.Number:
|
||||||
|
|
@ -917,8 +932,8 @@ func indirectToStringerOrError(a interface{}) interface{} {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var errorType = reflect.TypeOf((*error)(nil)).Elem()
|
errorType := reflect.TypeOf((*error)(nil)).Elem()
|
||||||
var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
|
fmtStringerType := reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
|
||||||
|
|
||||||
v := reflect.ValueOf(a)
|
v := reflect.ValueOf(a)
|
||||||
for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
|
for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
|
||||||
|
|
@ -987,7 +1002,7 @@ func ToStringE(i interface{}) (string, error) {
|
||||||
|
|
||||||
// ToStringMapStringE casts an interface to a map[string]string type.
|
// ToStringMapStringE casts an interface to a map[string]string type.
|
||||||
func ToStringMapStringE(i interface{}) (map[string]string, error) {
|
func ToStringMapStringE(i interface{}) (map[string]string, error) {
|
||||||
var m = map[string]string{}
|
m := map[string]string{}
|
||||||
|
|
||||||
switch v := i.(type) {
|
switch v := i.(type) {
|
||||||
case map[string]string:
|
case map[string]string:
|
||||||
|
|
@ -1017,7 +1032,7 @@ func ToStringMapStringE(i interface{}) (map[string]string, error) {
|
||||||
|
|
||||||
// ToStringMapStringSliceE casts an interface to a map[string][]string type.
|
// ToStringMapStringSliceE casts an interface to a map[string][]string type.
|
||||||
func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
|
func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
|
||||||
var m = map[string][]string{}
|
m := map[string][]string{}
|
||||||
|
|
||||||
switch v := i.(type) {
|
switch v := i.(type) {
|
||||||
case map[string][]string:
|
case map[string][]string:
|
||||||
|
|
@ -1081,7 +1096,7 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
|
||||||
|
|
||||||
// ToStringMapBoolE casts an interface to a map[string]bool type.
|
// ToStringMapBoolE casts an interface to a map[string]bool type.
|
||||||
func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
|
func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
|
||||||
var m = map[string]bool{}
|
m := map[string]bool{}
|
||||||
|
|
||||||
switch v := i.(type) {
|
switch v := i.(type) {
|
||||||
case map[interface{}]interface{}:
|
case map[interface{}]interface{}:
|
||||||
|
|
@ -1106,7 +1121,7 @@ func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
|
||||||
|
|
||||||
// ToStringMapE casts an interface to a map[string]interface{} type.
|
// ToStringMapE casts an interface to a map[string]interface{} type.
|
||||||
func ToStringMapE(i interface{}) (map[string]interface{}, error) {
|
func ToStringMapE(i interface{}) (map[string]interface{}, error) {
|
||||||
var m = map[string]interface{}{}
|
m := map[string]interface{}{}
|
||||||
|
|
||||||
switch v := i.(type) {
|
switch v := i.(type) {
|
||||||
case map[interface{}]interface{}:
|
case map[interface{}]interface{}:
|
||||||
|
|
@ -1126,7 +1141,7 @@ func ToStringMapE(i interface{}) (map[string]interface{}, error) {
|
||||||
|
|
||||||
// ToStringMapIntE casts an interface to a map[string]int{} type.
|
// ToStringMapIntE casts an interface to a map[string]int{} type.
|
||||||
func ToStringMapIntE(i interface{}) (map[string]int, error) {
|
func ToStringMapIntE(i interface{}) (map[string]int, error) {
|
||||||
var m = map[string]int{}
|
m := map[string]int{}
|
||||||
if i == nil {
|
if i == nil {
|
||||||
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i)
|
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i)
|
||||||
}
|
}
|
||||||
|
|
@ -1167,7 +1182,7 @@ func ToStringMapIntE(i interface{}) (map[string]int, error) {
|
||||||
|
|
||||||
// ToStringMapInt64E casts an interface to a map[string]int64{} type.
|
// ToStringMapInt64E casts an interface to a map[string]int64{} type.
|
||||||
func ToStringMapInt64E(i interface{}) (map[string]int64, error) {
|
func ToStringMapInt64E(i interface{}) (map[string]int64, error) {
|
||||||
var m = map[string]int64{}
|
m := map[string]int64{}
|
||||||
if i == nil {
|
if i == nil {
|
||||||
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i)
|
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i)
|
||||||
}
|
}
|
||||||
|
|
@ -1404,38 +1419,35 @@ func (f timeFormat) hasTimezone() bool {
|
||||||
return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone
|
return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var timeFormats = []timeFormat{
|
||||||
timeFormats = []timeFormat{
|
// Keep common formats at the top.
|
||||||
// Keep common formats at the top.
|
{"2006-01-02", timeFormatNoTimezone},
|
||||||
{"2006-01-02", timeFormatNoTimezone},
|
{time.RFC3339, timeFormatNumericTimezone},
|
||||||
{time.RFC3339, timeFormatNumericTimezone},
|
{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
|
||||||
{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
|
{time.RFC1123Z, timeFormatNumericTimezone},
|
||||||
{time.RFC1123Z, timeFormatNumericTimezone},
|
{time.RFC1123, timeFormatNamedTimezone},
|
||||||
{time.RFC1123, timeFormatNamedTimezone},
|
{time.RFC822Z, timeFormatNumericTimezone},
|
||||||
{time.RFC822Z, timeFormatNumericTimezone},
|
{time.RFC822, timeFormatNamedTimezone},
|
||||||
{time.RFC822, timeFormatNamedTimezone},
|
{time.RFC850, timeFormatNamedTimezone},
|
||||||
{time.RFC850, timeFormatNamedTimezone},
|
{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
|
||||||
{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
|
{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon
|
||||||
{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon
|
{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon
|
||||||
{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon
|
{"2006-01-02 15:04:05", timeFormatNoTimezone},
|
||||||
{"2006-01-02 15:04:05", timeFormatNoTimezone},
|
{time.ANSIC, timeFormatNoTimezone},
|
||||||
{time.ANSIC, timeFormatNoTimezone},
|
{time.UnixDate, timeFormatNamedTimezone},
|
||||||
{time.UnixDate, timeFormatNamedTimezone},
|
{time.RubyDate, timeFormatNumericTimezone},
|
||||||
{time.RubyDate, timeFormatNumericTimezone},
|
{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
|
||||||
{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
|
{"02 Jan 2006", timeFormatNoTimezone},
|
||||||
{"02 Jan 2006", timeFormatNoTimezone},
|
{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
|
||||||
{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
|
{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
|
||||||
{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
|
{time.Kitchen, timeFormatTimeOnly},
|
||||||
{time.Kitchen, timeFormatTimeOnly},
|
{time.Stamp, timeFormatTimeOnly},
|
||||||
{time.Stamp, timeFormatTimeOnly},
|
{time.StampMilli, timeFormatTimeOnly},
|
||||||
{time.StampMilli, timeFormatTimeOnly},
|
{time.StampMicro, timeFormatTimeOnly},
|
||||||
{time.StampMicro, timeFormatTimeOnly},
|
{time.StampNano, timeFormatTimeOnly},
|
||||||
{time.StampNano, timeFormatTimeOnly},
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) {
|
func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) {
|
||||||
|
|
||||||
for _, format := range formats {
|
for _, format := range formats {
|
||||||
if d, e = time.Parse(format.format, s); e == nil {
|
if d, e = time.Parse(format.format, s); e == nil {
|
||||||
|
|
||||||
|
|
|
||||||
12
vendor/github.com/spf13/pflag/.editorconfig
generated
vendored
Normal file
12
vendor/github.com/spf13/pflag/.editorconfig
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.go]
|
||||||
|
indent_style = tab
|
||||||
4
vendor/github.com/spf13/pflag/.golangci.yaml
generated
vendored
Normal file
4
vendor/github.com/spf13/pflag/.golangci.yaml
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
linters:
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- nolintlint
|
||||||
29
vendor/github.com/spf13/pflag/flag.go
generated
vendored
29
vendor/github.com/spf13/pflag/flag.go
generated
vendored
|
|
@ -160,7 +160,7 @@ type FlagSet struct {
|
||||||
args []string // arguments after flags
|
args []string // arguments after flags
|
||||||
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
|
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
|
||||||
errorHandling ErrorHandling
|
errorHandling ErrorHandling
|
||||||
output io.Writer // nil means stderr; use out() accessor
|
output io.Writer // nil means stderr; use Output() accessor
|
||||||
interspersed bool // allow interspersed option/non-option args
|
interspersed bool // allow interspersed option/non-option args
|
||||||
normalizeNameFunc func(f *FlagSet, name string) NormalizedName
|
normalizeNameFunc func(f *FlagSet, name string) NormalizedName
|
||||||
|
|
||||||
|
|
@ -255,13 +255,20 @@ func (f *FlagSet) normalizeFlagName(name string) NormalizedName {
|
||||||
return n(f, name)
|
return n(f, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) out() io.Writer {
|
// Output returns the destination for usage and error messages. os.Stderr is returned if
|
||||||
|
// output was not set or was set to nil.
|
||||||
|
func (f *FlagSet) Output() io.Writer {
|
||||||
if f.output == nil {
|
if f.output == nil {
|
||||||
return os.Stderr
|
return os.Stderr
|
||||||
}
|
}
|
||||||
return f.output
|
return f.output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the flag set.
|
||||||
|
func (f *FlagSet) Name() string {
|
||||||
|
return f.name
|
||||||
|
}
|
||||||
|
|
||||||
// SetOutput sets the destination for usage and error messages.
|
// SetOutput sets the destination for usage and error messages.
|
||||||
// If output is nil, os.Stderr is used.
|
// If output is nil, os.Stderr is used.
|
||||||
func (f *FlagSet) SetOutput(output io.Writer) {
|
func (f *FlagSet) SetOutput(output io.Writer) {
|
||||||
|
|
@ -358,7 +365,7 @@ func (f *FlagSet) ShorthandLookup(name string) *Flag {
|
||||||
}
|
}
|
||||||
if len(name) > 1 {
|
if len(name) > 1 {
|
||||||
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
|
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
|
||||||
fmt.Fprintf(f.out(), msg)
|
fmt.Fprintf(f.Output(), msg)
|
||||||
panic(msg)
|
panic(msg)
|
||||||
}
|
}
|
||||||
c := name[0]
|
c := name[0]
|
||||||
|
|
@ -482,7 +489,7 @@ func (f *FlagSet) Set(name, value string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if flag.Deprecated != "" {
|
if flag.Deprecated != "" {
|
||||||
fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
|
fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -523,7 +530,7 @@ func Set(name, value string) error {
|
||||||
// otherwise, the default values of all defined flags in the set.
|
// otherwise, the default values of all defined flags in the set.
|
||||||
func (f *FlagSet) PrintDefaults() {
|
func (f *FlagSet) PrintDefaults() {
|
||||||
usages := f.FlagUsages()
|
usages := f.FlagUsages()
|
||||||
fmt.Fprint(f.out(), usages)
|
fmt.Fprint(f.Output(), usages)
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultIsZeroValue returns true if the default value for this flag represents
|
// defaultIsZeroValue returns true if the default value for this flag represents
|
||||||
|
|
@ -758,7 +765,7 @@ func PrintDefaults() {
|
||||||
|
|
||||||
// defaultUsage is the default function to print a usage message.
|
// defaultUsage is the default function to print a usage message.
|
||||||
func defaultUsage(f *FlagSet) {
|
func defaultUsage(f *FlagSet) {
|
||||||
fmt.Fprintf(f.out(), "Usage of %s:\n", f.name)
|
fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)
|
||||||
f.PrintDefaults()
|
f.PrintDefaults()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -844,7 +851,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
|
||||||
_, alreadyThere := f.formal[normalizedFlagName]
|
_, alreadyThere := f.formal[normalizedFlagName]
|
||||||
if alreadyThere {
|
if alreadyThere {
|
||||||
msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
|
msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
|
||||||
fmt.Fprintln(f.out(), msg)
|
fmt.Fprintln(f.Output(), msg)
|
||||||
panic(msg) // Happens only if flags are declared with identical names
|
panic(msg) // Happens only if flags are declared with identical names
|
||||||
}
|
}
|
||||||
if f.formal == nil {
|
if f.formal == nil {
|
||||||
|
|
@ -860,7 +867,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
|
||||||
}
|
}
|
||||||
if len(flag.Shorthand) > 1 {
|
if len(flag.Shorthand) > 1 {
|
||||||
msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
|
msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
|
||||||
fmt.Fprintf(f.out(), msg)
|
fmt.Fprintf(f.Output(), msg)
|
||||||
panic(msg)
|
panic(msg)
|
||||||
}
|
}
|
||||||
if f.shorthands == nil {
|
if f.shorthands == nil {
|
||||||
|
|
@ -870,7 +877,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
|
||||||
used, alreadyThere := f.shorthands[c]
|
used, alreadyThere := f.shorthands[c]
|
||||||
if alreadyThere {
|
if alreadyThere {
|
||||||
msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
|
msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
|
||||||
fmt.Fprintf(f.out(), msg)
|
fmt.Fprintf(f.Output(), msg)
|
||||||
panic(msg)
|
panic(msg)
|
||||||
}
|
}
|
||||||
f.shorthands[c] = flag
|
f.shorthands[c] = flag
|
||||||
|
|
@ -909,7 +916,7 @@ func VarP(value Value, name, shorthand, usage string) {
|
||||||
func (f *FlagSet) failf(format string, a ...interface{}) error {
|
func (f *FlagSet) failf(format string, a ...interface{}) error {
|
||||||
err := fmt.Errorf(format, a...)
|
err := fmt.Errorf(format, a...)
|
||||||
if f.errorHandling != ContinueOnError {
|
if f.errorHandling != ContinueOnError {
|
||||||
fmt.Fprintln(f.out(), err)
|
fmt.Fprintln(f.Output(), err)
|
||||||
f.usage()
|
f.usage()
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
@ -1060,7 +1067,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
|
||||||
}
|
}
|
||||||
|
|
||||||
if flag.ShorthandDeprecated != "" {
|
if flag.ShorthandDeprecated != "" {
|
||||||
fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
|
fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = fn(flag, value)
|
err = fn(flag, value)
|
||||||
|
|
|
||||||
3
vendor/github.com/spf13/pflag/ip.go
generated
vendored
3
vendor/github.com/spf13/pflag/ip.go
generated
vendored
|
|
@ -16,6 +16,9 @@ func newIPValue(val net.IP, p *net.IP) *ipValue {
|
||||||
|
|
||||||
func (i *ipValue) String() string { return net.IP(*i).String() }
|
func (i *ipValue) String() string { return net.IP(*i).String() }
|
||||||
func (i *ipValue) Set(s string) error {
|
func (i *ipValue) Set(s string) error {
|
||||||
|
if s == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
ip := net.ParseIP(strings.TrimSpace(s))
|
ip := net.ParseIP(strings.TrimSpace(s))
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
return fmt.Errorf("failed to parse IP: %q", s)
|
return fmt.Errorf("failed to parse IP: %q", s)
|
||||||
|
|
|
||||||
147
vendor/github.com/spf13/pflag/ipnet_slice.go
generated
vendored
Normal file
147
vendor/github.com/spf13/pflag/ipnet_slice.go
generated
vendored
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- ipNetSlice Value
|
||||||
|
type ipNetSliceValue struct {
|
||||||
|
value *[]net.IPNet
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newIPNetSliceValue(val []net.IPNet, p *[]net.IPNet) *ipNetSliceValue {
|
||||||
|
ipnsv := new(ipNetSliceValue)
|
||||||
|
ipnsv.value = p
|
||||||
|
*ipnsv.value = val
|
||||||
|
return ipnsv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set converts, and assigns, the comma-separated IPNet argument string representation as the []net.IPNet value of this flag.
|
||||||
|
// If Set is called on a flag that already has a []net.IPNet assigned, the newly converted values will be appended.
|
||||||
|
func (s *ipNetSliceValue) Set(val string) error {
|
||||||
|
|
||||||
|
// remove all quote characters
|
||||||
|
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
|
||||||
|
|
||||||
|
// read flag arguments with CSV parser
|
||||||
|
ipNetStrSlice, err := readAsCSV(rmQuote.Replace(val))
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse ip values into slice
|
||||||
|
out := make([]net.IPNet, 0, len(ipNetStrSlice))
|
||||||
|
for _, ipNetStr := range ipNetStrSlice {
|
||||||
|
_, n, err := net.ParseCIDR(strings.TrimSpace(ipNetStr))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid string being converted to CIDR: %s", ipNetStr)
|
||||||
|
}
|
||||||
|
out = append(out, *n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
*s.value = append(*s.value, out...)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.changed = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns a string that uniquely represents this flag's type.
|
||||||
|
func (s *ipNetSliceValue) Type() string {
|
||||||
|
return "ipNetSlice"
|
||||||
|
}
|
||||||
|
|
||||||
|
// String defines a "native" format for this net.IPNet slice flag value.
|
||||||
|
func (s *ipNetSliceValue) String() string {
|
||||||
|
|
||||||
|
ipNetStrSlice := make([]string, len(*s.value))
|
||||||
|
for i, n := range *s.value {
|
||||||
|
ipNetStrSlice[i] = n.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
out, _ := writeAsCSV(ipNetStrSlice)
|
||||||
|
return "[" + out + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func ipNetSliceConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// Emtpy string would cause a slice with one (empty) entry
|
||||||
|
if len(val) == 0 {
|
||||||
|
return []net.IPNet{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]net.IPNet, len(ss))
|
||||||
|
for i, sval := range ss {
|
||||||
|
_, n, err := net.ParseCIDR(strings.TrimSpace(sval))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid string being converted to CIDR: %s", sval)
|
||||||
|
}
|
||||||
|
out[i] = *n
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIPNetSlice returns the []net.IPNet value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetIPNetSlice(name string) ([]net.IPNet, error) {
|
||||||
|
val, err := f.getFlagType(name, "ipNetSlice", ipNetSliceConv)
|
||||||
|
if err != nil {
|
||||||
|
return []net.IPNet{}, err
|
||||||
|
}
|
||||||
|
return val.([]net.IPNet), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPNetSliceVar defines a ipNetSlice flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []net.IPNet variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) {
|
||||||
|
f.VarP(newIPNetSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) {
|
||||||
|
f.VarP(newIPNetSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPNetSliceVar defines a []net.IPNet flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []net.IPNet variable in which to store the value of the flag.
|
||||||
|
func IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) {
|
||||||
|
CommandLine.VarP(newIPNetSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) {
|
||||||
|
CommandLine.VarP(newIPNetSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []net.IPNet variable that stores the value of that flag.
|
||||||
|
func (f *FlagSet) IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet {
|
||||||
|
p := []net.IPNet{}
|
||||||
|
f.IPNetSliceVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet {
|
||||||
|
p := []net.IPNet{}
|
||||||
|
f.IPNetSliceVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []net.IP variable that stores the value of the flag.
|
||||||
|
func IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet {
|
||||||
|
return CommandLine.IPNetSliceP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet {
|
||||||
|
return CommandLine.IPNetSliceP(name, shorthand, value, usage)
|
||||||
|
}
|
||||||
4
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
4
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
|
|
@ -31,11 +31,7 @@ func (s *stringArrayValue) Append(val string) error {
|
||||||
func (s *stringArrayValue) Replace(val []string) error {
|
func (s *stringArrayValue) Replace(val []string) error {
|
||||||
out := make([]string, len(val))
|
out := make([]string, len(val))
|
||||||
for i, d := range val {
|
for i, d := range val {
|
||||||
var err error
|
|
||||||
out[i] = d
|
out[i] = d
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*s.value = out
|
*s.value = out
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
14
vendor/github.com/spf13/viper/.golangci.yaml
generated
vendored
14
vendor/github.com/spf13/viper/.golangci.yaml
generated
vendored
|
|
@ -7,6 +7,16 @@ linters-settings:
|
||||||
- standard
|
- standard
|
||||||
- default
|
- default
|
||||||
- prefix(github.com/spf13/viper)
|
- 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
|
||||||
golint:
|
golint:
|
||||||
min-confidence: 0
|
min-confidence: 0
|
||||||
goimports:
|
goimports:
|
||||||
|
|
@ -22,6 +32,8 @@ linters:
|
||||||
- exhaustive
|
- exhaustive
|
||||||
- exportloopref
|
- exportloopref
|
||||||
- gci
|
- gci
|
||||||
|
- gocritic
|
||||||
|
- godot
|
||||||
- gofmt
|
- gofmt
|
||||||
- gofumpt
|
- gofumpt
|
||||||
- goimports
|
- goimports
|
||||||
|
|
@ -62,9 +74,7 @@ linters:
|
||||||
# - gochecknoinits
|
# - gochecknoinits
|
||||||
# - gocognit
|
# - gocognit
|
||||||
# - goconst
|
# - goconst
|
||||||
# - gocritic
|
|
||||||
# - gocyclo
|
# - gocyclo
|
||||||
# - godot
|
|
||||||
# - gosec
|
# - gosec
|
||||||
# - gosimple
|
# - gosimple
|
||||||
# - ifshort
|
# - ifshort
|
||||||
|
|
|
||||||
13
vendor/github.com/spf13/viper/README.md
generated
vendored
13
vendor/github.com/spf13/viper/README.md
generated
vendored
|
|
@ -11,7 +11,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!**
|
||||||
|
|
@ -39,7 +39,7 @@ Many Go projects are built using Viper including:
|
||||||
go get github.com/spf13/viper
|
go get github.com/spf13/viper
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:** Viper uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies.
|
**Note:** Viper uses [Go Modules](https://go.dev/wiki/Modules) to manage dependencies.
|
||||||
|
|
||||||
|
|
||||||
## What is Viper?
|
## What is Viper?
|
||||||
|
|
@ -418,7 +418,9 @@ in a Key/Value store such as etcd or Consul. These values take precedence over
|
||||||
default values, but are overridden by configuration values retrieved from disk,
|
default values, but are overridden by configuration values retrieved from disk,
|
||||||
flags, or environment variables.
|
flags, or environment variables.
|
||||||
|
|
||||||
Viper uses [crypt](https://github.com/bketelsen/crypt) to retrieve
|
Viper supports multiple hosts. To use, pass a list of endpoints separated by `;`. For example `http://127.0.0.1:4001;http://127.0.0.1:4002`.
|
||||||
|
|
||||||
|
Viper uses [crypt](https://github.com/sagikazarmark/crypt) to retrieve
|
||||||
configuration from the K/V store, which means that you can store your
|
configuration from the K/V store, which means that you can store your
|
||||||
configuration values encrypted and have them automatically decrypted if you have
|
configuration values encrypted and have them automatically decrypted if you have
|
||||||
the correct gpg keyring. Encryption is optional.
|
the correct gpg keyring. Encryption is optional.
|
||||||
|
|
@ -430,7 +432,7 @@ independently of it.
|
||||||
K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001.
|
K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ go get github.com/bketelsen/crypt/bin/crypt
|
$ go get github.com/sagikazarmark/crypt/bin/crypt
|
||||||
$ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
|
$ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -563,6 +565,9 @@ One important thing to recognize is that each Get function will return a zero
|
||||||
value if it’s not found. To check if a given key exists, the `IsSet()` method
|
value if it’s not found. To check if a given key exists, the `IsSet()` method
|
||||||
has been provided.
|
has been provided.
|
||||||
|
|
||||||
|
The zero value will also be returned if the value is set, but fails to parse
|
||||||
|
as the requested type.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```go
|
```go
|
||||||
viper.GetString("logfile") // case-insensitive Setting & Getting
|
viper.GetString("logfile") // case-insensitive Setting & Getting
|
||||||
|
|
|
||||||
4
vendor/github.com/spf13/viper/TROUBLESHOOTING.md
generated
vendored
4
vendor/github.com/spf13/viper/TROUBLESHOOTING.md
generated
vendored
|
|
@ -15,10 +15,10 @@ cannot find package "github.com/hashicorp/hcl/tree/hcl1" in any of:
|
||||||
```
|
```
|
||||||
|
|
||||||
As the error message suggests, Go tries to look up dependencies in `GOPATH` mode (as it's commonly called) from the `GOPATH`.
|
As the error message suggests, Go tries to look up dependencies in `GOPATH` mode (as it's commonly called) from the `GOPATH`.
|
||||||
Viper opted to use [Go Modules](https://github.com/golang/go/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch).
|
Viper opted to use [Go Modules](https://go.dev/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch).
|
||||||
|
|
||||||
The solution is easy: switch to using Go Modules.
|
The solution is easy: switch to using Go Modules.
|
||||||
Please refer to the [wiki](https://github.com/golang/go/wiki/Modules) on how to do that.
|
Please refer to the [wiki](https://go.dev/wiki/Modules) on how to do that.
|
||||||
|
|
||||||
**tl;dr* `export GO111MODULE=on`
|
**tl;dr* `export GO111MODULE=on`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ func (v *Viper) searchInPath(in string) (filename string) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if file Exists
|
// exists checks if file exists.
|
||||||
func exists(fs afero.Fs, path string) (bool, error) {
|
func exists(fs afero.Fs, path string) (bool, error) {
|
||||||
stat, err := fs.Stat(path)
|
stat, err := fs.Stat(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
2
vendor/github.com/spf13/viper/flags.go
generated
vendored
2
vendor/github.com/spf13/viper/flags.go
generated
vendored
|
|
@ -31,7 +31,7 @@ func (p pflagValueSet) VisitAll(fn func(flag FlagValue)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// pflagValue is a wrapper around *pflag.flag
|
// pflagValue is a wrapper around *pflag.flag
|
||||||
// that implements FlagValue
|
// that implements FlagValue.
|
||||||
type pflagValue struct {
|
type pflagValue struct {
|
||||||
flag *pflag.Flag
|
flag *pflag.Flag
|
||||||
}
|
}
|
||||||
|
|
|
||||||
62
vendor/github.com/spf13/viper/flake.lock
generated
vendored
62
vendor/github.com/spf13/viper/flake.lock
generated
vendored
|
|
@ -8,11 +8,11 @@
|
||||||
"pre-commit-hooks": "pre-commit-hooks"
|
"pre-commit-hooks": "pre-commit-hooks"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1687972261,
|
"lastModified": 1707817777,
|
||||||
"narHash": "sha256-+mxvZfwMVoaZYETmuQWqTi/7T9UKoAE+WpdSQkOVJ2g=",
|
"narHash": "sha256-vHyIs1OULQ3/91wD6xOiuayfI71JXALGA5KLnDKAcy0=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "devenv",
|
"repo": "devenv",
|
||||||
"rev": "e85df562088573305e55906eaa964341f8cb0d9f",
|
"rev": "5a30b9e5ac7c6167e61b1f4193d5130bb9f8defa",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -42,11 +42,11 @@
|
||||||
"nixpkgs-lib": "nixpkgs-lib"
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1687762428,
|
"lastModified": 1706830856,
|
||||||
"narHash": "sha256-DIf7mi45PKo+s8dOYF+UlXHzE0Wl/+k3tXUyAoAnoGE=",
|
"narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=",
|
||||||
"owner": "hercules-ci",
|
"owner": "hercules-ci",
|
||||||
"repo": "flake-parts",
|
"repo": "flake-parts",
|
||||||
"rev": "37dd7bb15791c86d55c5121740a1887ab55ee836",
|
"rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -56,12 +56,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1667395993,
|
"lastModified": 1685518550,
|
||||||
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
|
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
|
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -151,11 +154,11 @@
|
||||||
"nixpkgs-lib": {
|
"nixpkgs-lib": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"dir": "lib",
|
"dir": "lib",
|
||||||
"lastModified": 1685564631,
|
"lastModified": 1706550542,
|
||||||
"narHash": "sha256-8ywr3AkblY4++3lIVxmrWZFzac7+f32ZEhH/A8pNscI=",
|
"narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "4f53efe34b3a8877ac923b9350c874e3dcd5dc0a",
|
"rev": "97b17f32362e475016f942bbdfda4a4a72a8a652",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -184,27 +187,27 @@
|
||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1678872516,
|
"lastModified": 1685801374,
|
||||||
"narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=",
|
"narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8",
|
"rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-22.11",
|
"ref": "nixos-23.05",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1687886075,
|
"lastModified": 1707939175,
|
||||||
"narHash": "sha256-PeayJDDDy+uw1Ats4moZnRdL1OFuZm1Tj+KiHlD67+o=",
|
"narHash": "sha256-D1xan0lgxbmXDyzVqXTiSYHLmAMrMRdD+alKzEO/p3w=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "a565059a348422af5af9026b5174dc5c0dcefdae",
|
"rev": "f7e8132daca31b1e3859ac0fb49741754375ac3d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -229,11 +232,11 @@
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
"nixpkgs-stable": "nixpkgs-stable"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1686050334,
|
"lastModified": 1704725188,
|
||||||
"narHash": "sha256-R0mczWjDzBpIvM3XXhO908X5e2CQqjyh/gFbwZk/7/Q=",
|
"narHash": "sha256-qq8NbkhRZF1vVYQFt1s8Mbgo8knj+83+QlL5LBnYGpI=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "pre-commit-hooks.nix",
|
"repo": "pre-commit-hooks.nix",
|
||||||
"rev": "6881eb2ae5d8a3516e34714e7a90d9d95914c4dc",
|
"rev": "ea96f0c05924341c551a797aaba8126334c505d2",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -248,6 +251,21 @@
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts",
|
||||||
"nixpkgs": "nixpkgs_2"
|
"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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|
|
||||||
1
vendor/github.com/spf13/viper/flake.nix
generated
vendored
1
vendor/github.com/spf13/viper/flake.nix
generated
vendored
|
|
@ -20,6 +20,7 @@
|
||||||
default = {
|
default = {
|
||||||
languages = {
|
languages = {
|
||||||
go.enable = true;
|
go.enable = true;
|
||||||
|
go.package = pkgs.go_1_22;
|
||||||
};
|
};
|
||||||
|
|
||||||
pre-commit.hooks = {
|
pre-commit.hooks = {
|
||||||
|
|
|
||||||
4
vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
generated
vendored
4
vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
generated
vendored
|
|
@ -8,8 +8,8 @@ import (
|
||||||
|
|
||||||
// flattenAndMergeMap recursively flattens the given map into a new map
|
// flattenAndMergeMap recursively flattens the given map into a new map
|
||||||
// Code is based on the function with the same name in the main package.
|
// Code is based on the function with the same name in the main package.
|
||||||
// TODO: move it to a common place
|
// TODO: move it to a common place.
|
||||||
func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any {
|
func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
|
||||||
if shadow != nil && prefix != "" && shadow[prefix] != nil {
|
if shadow != nil && prefix != "" && shadow[prefix] != nil {
|
||||||
// prefix is shadowed => nothing more to flatten
|
// prefix is shadowed => nothing more to flatten
|
||||||
return shadow
|
return shadow
|
||||||
|
|
|
||||||
4
vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go
generated
vendored
4
vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go
generated
vendored
|
|
@ -41,8 +41,8 @@ func deepSearch(m map[string]any, path []string) map[string]any {
|
||||||
|
|
||||||
// flattenAndMergeMap recursively flattens the given map into a new map
|
// flattenAndMergeMap recursively flattens the given map into a new map
|
||||||
// Code is based on the function with the same name in the main package.
|
// Code is based on the function with the same name in the main package.
|
||||||
// TODO: move it to a common place
|
// TODO: move it to a common place.
|
||||||
func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any {
|
func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
|
||||||
if shadow != nil && prefix != "" && shadow[prefix] != nil {
|
if shadow != nil && prefix != "" && shadow[prefix] != nil {
|
||||||
// prefix is shadowed => nothing more to flatten
|
// prefix is shadowed => nothing more to flatten
|
||||||
return shadow
|
return shadow
|
||||||
|
|
|
||||||
4
vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go
generated
vendored
4
vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go
generated
vendored
|
|
@ -41,8 +41,8 @@ func deepSearch(m map[string]any, path []string) map[string]any {
|
||||||
|
|
||||||
// flattenAndMergeMap recursively flattens the given map into a new map
|
// flattenAndMergeMap recursively flattens the given map into a new map
|
||||||
// Code is based on the function with the same name in the main package.
|
// Code is based on the function with the same name in the main package.
|
||||||
// TODO: move it to a common place
|
// TODO: move it to a common place.
|
||||||
func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any {
|
func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
|
||||||
if shadow != nil && prefix != "" && shadow[prefix] != nil {
|
if shadow != nil && prefix != "" && shadow[prefix] != nil {
|
||||||
// prefix is shadowed => nothing more to flatten
|
// prefix is shadowed => nothing more to flatten
|
||||||
return shadow
|
return shadow
|
||||||
|
|
|
||||||
5
vendor/github.com/spf13/viper/internal/features/bind_struct.go
generated
vendored
Normal file
5
vendor/github.com/spf13/viper/internal/features/bind_struct.go
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
//go:build viper_bind_struct
|
||||||
|
|
||||||
|
package features
|
||||||
|
|
||||||
|
const BindStruct = true
|
||||||
5
vendor/github.com/spf13/viper/internal/features/bind_struct_default.go
generated
vendored
Normal file
5
vendor/github.com/spf13/viper/internal/features/bind_struct_default.go
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
//go:build !viper_bind_struct
|
||||||
|
|
||||||
|
package features
|
||||||
|
|
||||||
|
const BindStruct = false
|
||||||
2
vendor/github.com/spf13/viper/util.go
generated
vendored
2
vendor/github.com/spf13/viper/util.go
generated
vendored
|
|
@ -156,7 +156,7 @@ func safeMul(a, b uint) uint {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes
|
// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes.
|
||||||
func parseSizeInBytes(sizeStr string) uint {
|
func parseSizeInBytes(sizeStr string) uint {
|
||||||
sizeStr = strings.TrimSpace(sizeStr)
|
sizeStr = strings.TrimSpace(sizeStr)
|
||||||
lastChar := len(sizeStr) - 1
|
lastChar := len(sizeStr) - 1
|
||||||
|
|
|
||||||
110
vendor/github.com/spf13/viper/viper.go
generated
vendored
110
vendor/github.com/spf13/viper/viper.go
generated
vendored
|
|
@ -48,6 +48,7 @@ import (
|
||||||
"github.com/spf13/viper/internal/encoding/json"
|
"github.com/spf13/viper/internal/encoding/json"
|
||||||
"github.com/spf13/viper/internal/encoding/toml"
|
"github.com/spf13/viper/internal/encoding/toml"
|
||||||
"github.com/spf13/viper/internal/encoding/yaml"
|
"github.com/spf13/viper/internal/encoding/yaml"
|
||||||
|
"github.com/spf13/viper/internal/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConfigMarshalError happens when failing to marshal the configuration.
|
// ConfigMarshalError happens when failing to marshal the configuration.
|
||||||
|
|
@ -77,7 +78,7 @@ type remoteConfigFactory interface {
|
||||||
WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool)
|
WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoteConfig is optional, see the remote package
|
// RemoteConfig is optional, see the remote package.
|
||||||
var RemoteConfig remoteConfigFactory
|
var RemoteConfig remoteConfigFactory
|
||||||
|
|
||||||
// UnsupportedConfigError denotes encountering an unsupported
|
// UnsupportedConfigError denotes encountering an unsupported
|
||||||
|
|
@ -102,7 +103,7 @@ func (str UnsupportedRemoteProviderError) Error() string {
|
||||||
// pull the configuration from the remote provider.
|
// pull the configuration from the remote provider.
|
||||||
type RemoteConfigError string
|
type RemoteConfigError string
|
||||||
|
|
||||||
// Error returns the formatted remote provider error
|
// Error returns the formatted remote provider error.
|
||||||
func (rce RemoteConfigError) Error() string {
|
func (rce RemoteConfigError) Error() string {
|
||||||
return fmt.Sprintf("Remote Configurations Error: %s", string(rce))
|
return fmt.Sprintf("Remote Configurations Error: %s", string(rce))
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +127,7 @@ func (faee ConfigFileAlreadyExistsError) Error() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A DecoderConfigOption can be passed to viper.Unmarshal to configure
|
// A DecoderConfigOption can be passed to viper.Unmarshal to configure
|
||||||
// mapstructure.DecoderConfig options
|
// mapstructure.DecoderConfig options.
|
||||||
type DecoderConfigOption func(*mapstructure.DecoderConfig)
|
type DecoderConfigOption func(*mapstructure.DecoderConfig)
|
||||||
|
|
||||||
// DecodeHook returns a DecoderConfigOption which overrides the default
|
// DecodeHook returns a DecoderConfigOption which overrides the default
|
||||||
|
|
@ -305,7 +306,7 @@ func Reset() {
|
||||||
SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
|
SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make this lazy initialization instead
|
// TODO: make this lazy initialization instead.
|
||||||
func (v *Viper) resetEncoding() {
|
func (v *Viper) resetEncoding() {
|
||||||
encoderRegistry := encoding.NewEncoderRegistry()
|
encoderRegistry := encoding.NewEncoderRegistry()
|
||||||
decoderRegistry := encoding.NewDecoderRegistry()
|
decoderRegistry := encoding.NewDecoderRegistry()
|
||||||
|
|
@ -439,7 +440,7 @@ func (v *Viper) WatchConfig() {
|
||||||
initWG := sync.WaitGroup{}
|
initWG := sync.WaitGroup{}
|
||||||
initWG.Add(1)
|
initWG.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
watcher, err := newWatcher()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
v.logger.Error(fmt.Sprintf("failed to create watcher: %s", err))
|
v.logger.Error(fmt.Sprintf("failed to create watcher: %s", err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
@ -590,7 +591,7 @@ func (v *Viper) AddConfigPath(in string) {
|
||||||
// path is the path in the k/v store to retrieve configuration
|
// path is the path in the k/v store to retrieve configuration
|
||||||
// To retrieve a config file called myapp.json from /configs/myapp.json
|
// To retrieve a config file called myapp.json from /configs/myapp.json
|
||||||
// you should set path to /configs and set config name (SetConfigName()) to
|
// you should set path to /configs and set config name (SetConfigName()) to
|
||||||
// "myapp"
|
// "myapp".
|
||||||
func AddRemoteProvider(provider, endpoint, path string) error {
|
func AddRemoteProvider(provider, endpoint, path string) error {
|
||||||
return v.AddRemoteProvider(provider, endpoint, path)
|
return v.AddRemoteProvider(provider, endpoint, path)
|
||||||
}
|
}
|
||||||
|
|
@ -622,8 +623,8 @@ func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
|
||||||
// path is the path in the k/v store to retrieve configuration
|
// path is the path in the k/v store to retrieve configuration
|
||||||
// To retrieve a config file called myapp.json from /configs/myapp.json
|
// To retrieve a config file called myapp.json from /configs/myapp.json
|
||||||
// you should set path to /configs and set config name (SetConfigName()) to
|
// you should set path to /configs and set config name (SetConfigName()) to
|
||||||
// "myapp"
|
// "myapp".
|
||||||
// Secure Remote Providers are implemented with github.com/bketelsen/crypt
|
// Secure Remote Providers are implemented with github.com/sagikazarmark/crypt.
|
||||||
func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
|
func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
|
||||||
return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring)
|
return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring)
|
||||||
}
|
}
|
||||||
|
|
@ -827,10 +828,12 @@ func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]any) string
|
||||||
// "foo.bar.baz" in a lower-priority map
|
// "foo.bar.baz" in a lower-priority map
|
||||||
func (v *Viper) isPathShadowedInFlatMap(path []string, mi any) string {
|
func (v *Viper) isPathShadowedInFlatMap(path []string, mi any) string {
|
||||||
// unify input map
|
// unify input map
|
||||||
var m map[string]any
|
var m map[string]interface{}
|
||||||
switch mi.(type) {
|
switch miv := mi.(type) {
|
||||||
case map[string]string, map[string]FlagValue:
|
case map[string]string:
|
||||||
m = cast.ToStringMap(mi)
|
m = castMapStringToMapInterface(miv)
|
||||||
|
case map[string]FlagValue:
|
||||||
|
m = castMapFlagToMapInterface(miv)
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
@ -957,7 +960,8 @@ func (v *Viper) Sub(key string) *Viper {
|
||||||
}
|
}
|
||||||
|
|
||||||
if reflect.TypeOf(data).Kind() == reflect.Map {
|
if reflect.TypeOf(data).Kind() == reflect.Map {
|
||||||
subv.parents = append(v.parents, strings.ToLower(key))
|
subv.parents = append([]string(nil), v.parents...)
|
||||||
|
subv.parents = append(subv.parents, strings.ToLower(key))
|
||||||
subv.automaticEnvApplied = v.automaticEnvApplied
|
subv.automaticEnvApplied = v.automaticEnvApplied
|
||||||
subv.envPrefix = v.envPrefix
|
subv.envPrefix = v.envPrefix
|
||||||
subv.envKeyReplacer = v.envKeyReplacer
|
subv.envKeyReplacer = v.envKeyReplacer
|
||||||
|
|
@ -1111,11 +1115,42 @@ func Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
|
func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
|
||||||
return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
|
keys := v.AllKeys()
|
||||||
|
|
||||||
|
if features.BindStruct {
|
||||||
|
// TODO: make this optional?
|
||||||
|
structKeys, err := v.decodeStructKeys(rawVal, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
keys = append(keys, structKeys...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: struct keys should be enough?
|
||||||
|
return decode(v.getSettings(keys), defaultDecoderConfig(rawVal, opts...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) {
|
||||||
|
var structKeyMap map[string]any
|
||||||
|
|
||||||
|
err := decode(input, defaultDecoderConfig(&structKeyMap, opts...))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
flattenedStructKeyMap := v.flattenAndMergeMap(map[string]bool{}, structKeyMap, "")
|
||||||
|
|
||||||
|
r := make([]string, 0, len(flattenedStructKeyMap))
|
||||||
|
for v := range flattenedStructKeyMap {
|
||||||
|
r = append(r, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultDecoderConfig returns default mapstructure.DecoderConfig with support
|
// defaultDecoderConfig returns default mapstructure.DecoderConfig with support
|
||||||
// of time.Duration values & string slices
|
// of time.Duration values & string slices.
|
||||||
func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
|
func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
|
||||||
c := &mapstructure.DecoderConfig{
|
c := &mapstructure.DecoderConfig{
|
||||||
Metadata: nil,
|
Metadata: nil,
|
||||||
|
|
@ -1132,7 +1167,7 @@ func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// A wrapper around mapstructure.Decode that mimics the WeakDecode functionality
|
// decode is a wrapper around mapstructure.Decode that mimics the WeakDecode functionality.
|
||||||
func decode(input any, config *mapstructure.DecoderConfig) error {
|
func decode(input any, config *mapstructure.DecoderConfig) error {
|
||||||
decoder, err := mapstructure.NewDecoder(config)
|
decoder, err := mapstructure.NewDecoder(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1151,7 +1186,20 @@ func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
|
||||||
config := defaultDecoderConfig(rawVal, opts...)
|
config := defaultDecoderConfig(rawVal, opts...)
|
||||||
config.ErrorUnused = true
|
config.ErrorUnused = true
|
||||||
|
|
||||||
return decode(v.AllSettings(), config)
|
keys := v.AllKeys()
|
||||||
|
|
||||||
|
if features.BindStruct {
|
||||||
|
// TODO: make this optional?
|
||||||
|
structKeys, err := v.decodeStructKeys(rawVal, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
keys = append(keys, structKeys...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: struct keys should be enough?
|
||||||
|
return decode(v.getSettings(keys), config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindPFlags binds a full flag set to the configuration, using each flag's long
|
// BindPFlags binds a full flag set to the configuration, using each flag's long
|
||||||
|
|
@ -1405,11 +1453,11 @@ func readAsCSV(val string) ([]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/master/string_to_string.go#L79
|
// mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/master/string_to_string.go#L79
|
||||||
// alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap
|
// alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap.
|
||||||
func stringToStringConv(val string) any {
|
func stringToStringConv(val string) any {
|
||||||
val = strings.Trim(val, "[]")
|
val = strings.Trim(val, "[]")
|
||||||
// An empty string would cause an empty map
|
// An empty string would cause an empty map
|
||||||
if len(val) == 0 {
|
if val == "" {
|
||||||
return map[string]any{}
|
return map[string]any{}
|
||||||
}
|
}
|
||||||
r := csv.NewReader(strings.NewReader(val))
|
r := csv.NewReader(strings.NewReader(val))
|
||||||
|
|
@ -1429,11 +1477,11 @@ func stringToStringConv(val string) any {
|
||||||
}
|
}
|
||||||
|
|
||||||
// mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/d5e0c0615acee7028e1e2740a11102313be88de1/string_to_int.go#L68
|
// mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/d5e0c0615acee7028e1e2740a11102313be88de1/string_to_int.go#L68
|
||||||
// alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap
|
// alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap.
|
||||||
func stringToIntConv(val string) any {
|
func stringToIntConv(val string) any {
|
||||||
val = strings.Trim(val, "[]")
|
val = strings.Trim(val, "[]")
|
||||||
// An empty string would cause an empty map
|
// An empty string would cause an empty map
|
||||||
if len(val) == 0 {
|
if val == "" {
|
||||||
return map[string]any{}
|
return map[string]any{}
|
||||||
}
|
}
|
||||||
ss := strings.Split(val, ",")
|
ss := strings.Split(val, ",")
|
||||||
|
|
@ -1481,13 +1529,13 @@ func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) {
|
||||||
|
|
||||||
// RegisterAlias creates an alias that provides another accessor for the same key.
|
// RegisterAlias creates an alias that provides another accessor for the same key.
|
||||||
// This enables one to change a name without breaking the application.
|
// This enables one to change a name without breaking the application.
|
||||||
func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) }
|
func RegisterAlias(alias, key string) { v.RegisterAlias(alias, key) }
|
||||||
|
|
||||||
func (v *Viper) RegisterAlias(alias string, key string) {
|
func (v *Viper) RegisterAlias(alias, key string) {
|
||||||
v.registerAlias(alias, strings.ToLower(key))
|
v.registerAlias(alias, strings.ToLower(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Viper) registerAlias(alias string, key string) {
|
func (v *Viper) registerAlias(alias, key string) {
|
||||||
alias = strings.ToLower(alias)
|
alias = strings.ToLower(alias)
|
||||||
if alias != key && alias != v.realKey(key) {
|
if alias != key && alias != v.realKey(key) {
|
||||||
_, exists := v.aliases[alias]
|
_, exists := v.aliases[alias]
|
||||||
|
|
@ -1743,12 +1791,6 @@ func (v *Viper) writeConfig(filename string, force bool) error {
|
||||||
return f.Sync()
|
return f.Sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal a Reader into a map.
|
|
||||||
// Should probably be an unexported function.
|
|
||||||
func unmarshalReader(in io.Reader, c map[string]any) error {
|
|
||||||
return v.unmarshalReader(in, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error {
|
func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
buf.ReadFrom(in)
|
buf.ReadFrom(in)
|
||||||
|
|
@ -2012,7 +2054,7 @@ func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllKeys returns all keys holding a value, regardless of where they are set.
|
// AllKeys returns all keys holding a value, regardless of where they are set.
|
||||||
// Nested keys are returned with a v.keyDelim separator
|
// Nested keys are returned with a v.keyDelim separator.
|
||||||
func AllKeys() []string { return v.AllKeys() }
|
func AllKeys() []string { return v.AllKeys() }
|
||||||
|
|
||||||
func (v *Viper) AllKeys() []string {
|
func (v *Viper) AllKeys() []string {
|
||||||
|
|
@ -2098,9 +2140,13 @@ outer:
|
||||||
func AllSettings() map[string]any { return v.AllSettings() }
|
func AllSettings() map[string]any { return v.AllSettings() }
|
||||||
|
|
||||||
func (v *Viper) AllSettings() map[string]any {
|
func (v *Viper) AllSettings() map[string]any {
|
||||||
|
return v.getSettings(v.AllKeys())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Viper) getSettings(keys []string) map[string]any {
|
||||||
m := map[string]any{}
|
m := map[string]any{}
|
||||||
// start from the list of keys, and construct the map one value at a time
|
// start from the list of keys, and construct the map one value at a time
|
||||||
for _, k := range v.AllKeys() {
|
for _, k := range keys {
|
||||||
value := v.Get(k)
|
value := v.Get(k)
|
||||||
if value == nil {
|
if value == nil {
|
||||||
// should not happen, since AllKeys() returns only keys holding a value,
|
// should not happen, since AllKeys() returns only keys holding a value,
|
||||||
|
|
|
||||||
11
vendor/github.com/spf13/viper/watch.go
generated
vendored
11
vendor/github.com/spf13/viper/watch.go
generated
vendored
|
|
@ -1,11 +0,0 @@
|
||||||
//go:build darwin || dragonfly || freebsd || openbsd || linux || netbsd || solaris || windows
|
|
||||||
|
|
||||||
package viper
|
|
||||||
|
|
||||||
import "github.com/fsnotify/fsnotify"
|
|
||||||
|
|
||||||
type watcher = fsnotify.Watcher
|
|
||||||
|
|
||||||
func newWatcher() (*watcher, error) {
|
|
||||||
return fsnotify.NewWatcher()
|
|
||||||
}
|
|
||||||
31
vendor/github.com/spf13/viper/watch_unsupported.go
generated
vendored
31
vendor/github.com/spf13/viper/watch_unsupported.go
generated
vendored
|
|
@ -1,31 +0,0 @@
|
||||||
//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
|
|
||||||
|
|
||||||
package viper
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
|
||||||
)
|
|
||||||
|
|
||||||
func newWatcher() (*watcher, error) {
|
|
||||||
return &watcher{}, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS)
|
|
||||||
}
|
|
||||||
|
|
||||||
type watcher struct {
|
|
||||||
Events chan fsnotify.Event
|
|
||||||
Errors chan error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*watcher) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*watcher) Add(name string) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*watcher) Remove(name string) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
63
vendor/github.com/stretchr/testify/assert/assertion_compare.go
generated
vendored
63
vendor/github.com/stretchr/testify/assert/assertion_compare.go
generated
vendored
|
|
@ -7,10 +7,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CompareType int
|
// Deprecated: CompareType has only ever been for internal use and has accidentally been published since v1.6.0. Do not use it.
|
||||||
|
type CompareType = compareResult
|
||||||
|
|
||||||
|
type compareResult int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
compareLess CompareType = iota - 1
|
compareLess compareResult = iota - 1
|
||||||
compareEqual
|
compareEqual
|
||||||
compareGreater
|
compareGreater
|
||||||
)
|
)
|
||||||
|
|
@ -28,6 +31,8 @@ var (
|
||||||
uint32Type = reflect.TypeOf(uint32(1))
|
uint32Type = reflect.TypeOf(uint32(1))
|
||||||
uint64Type = reflect.TypeOf(uint64(1))
|
uint64Type = reflect.TypeOf(uint64(1))
|
||||||
|
|
||||||
|
uintptrType = reflect.TypeOf(uintptr(1))
|
||||||
|
|
||||||
float32Type = reflect.TypeOf(float32(1))
|
float32Type = reflect.TypeOf(float32(1))
|
||||||
float64Type = reflect.TypeOf(float64(1))
|
float64Type = reflect.TypeOf(float64(1))
|
||||||
|
|
||||||
|
|
@ -37,7 +42,7 @@ var (
|
||||||
bytesType = reflect.TypeOf([]byte{})
|
bytesType = reflect.TypeOf([]byte{})
|
||||||
)
|
)
|
||||||
|
|
||||||
func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, bool) {
|
||||||
obj1Value := reflect.ValueOf(obj1)
|
obj1Value := reflect.ValueOf(obj1)
|
||||||
obj2Value := reflect.ValueOf(obj2)
|
obj2Value := reflect.ValueOf(obj2)
|
||||||
|
|
||||||
|
|
@ -308,11 +313,11 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
{
|
{
|
||||||
// All structs enter here. We're not interested in most types.
|
// All structs enter here. We're not interested in most types.
|
||||||
if !canConvert(obj1Value, timeType) {
|
if !obj1Value.CanConvert(timeType) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// time.Time can compared!
|
// time.Time can be compared!
|
||||||
timeObj1, ok := obj1.(time.Time)
|
timeObj1, ok := obj1.(time.Time)
|
||||||
if !ok {
|
if !ok {
|
||||||
timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time)
|
timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time)
|
||||||
|
|
@ -323,12 +328,18 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||||
timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time)
|
timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time)
|
||||||
}
|
}
|
||||||
|
|
||||||
return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64)
|
if timeObj1.Before(timeObj2) {
|
||||||
|
return compareLess, true
|
||||||
|
}
|
||||||
|
if timeObj1.Equal(timeObj2) {
|
||||||
|
return compareEqual, true
|
||||||
|
}
|
||||||
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
{
|
{
|
||||||
// We only care about the []byte type.
|
// We only care about the []byte type.
|
||||||
if !canConvert(obj1Value, bytesType) {
|
if !obj1Value.CanConvert(bytesType) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -343,7 +354,27 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||||
bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte)
|
bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true
|
return compareResult(bytes.Compare(bytesObj1, bytesObj2)), true
|
||||||
|
}
|
||||||
|
case reflect.Uintptr:
|
||||||
|
{
|
||||||
|
uintptrObj1, ok := obj1.(uintptr)
|
||||||
|
if !ok {
|
||||||
|
uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr)
|
||||||
|
}
|
||||||
|
uintptrObj2, ok := obj2.(uintptr)
|
||||||
|
if !ok {
|
||||||
|
uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr)
|
||||||
|
}
|
||||||
|
if uintptrObj1 > uintptrObj2 {
|
||||||
|
return compareGreater, true
|
||||||
|
}
|
||||||
|
if uintptrObj1 == uintptrObj2 {
|
||||||
|
return compareEqual, true
|
||||||
|
}
|
||||||
|
if uintptrObj1 < uintptrObj2 {
|
||||||
|
return compareLess, true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -359,7 +390,7 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
|
return compareTwoValues(t, e1, e2, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GreaterOrEqual asserts that the first element is greater than or equal to the second
|
// GreaterOrEqual asserts that the first element is greater than or equal to the second
|
||||||
|
|
@ -372,7 +403,7 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
|
return compareTwoValues(t, e1, e2, []compareResult{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Less asserts that the first element is less than the second
|
// Less asserts that the first element is less than the second
|
||||||
|
|
@ -384,7 +415,7 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
|
return compareTwoValues(t, e1, e2, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LessOrEqual asserts that the first element is less than or equal to the second
|
// LessOrEqual asserts that the first element is less than or equal to the second
|
||||||
|
|
@ -397,7 +428,7 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
|
return compareTwoValues(t, e1, e2, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Positive asserts that the specified element is positive
|
// Positive asserts that the specified element is positive
|
||||||
|
|
@ -409,7 +440,7 @@ func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
zero := reflect.Zero(reflect.TypeOf(e))
|
zero := reflect.Zero(reflect.TypeOf(e))
|
||||||
return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...)
|
return compareTwoValues(t, e, zero.Interface(), []compareResult{compareGreater}, "\"%v\" is not positive", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negative asserts that the specified element is negative
|
// Negative asserts that the specified element is negative
|
||||||
|
|
@ -421,10 +452,10 @@ func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
zero := reflect.Zero(reflect.TypeOf(e))
|
zero := reflect.Zero(reflect.TypeOf(e))
|
||||||
return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...)
|
return compareTwoValues(t, e, zero.Interface(), []compareResult{compareLess}, "\"%v\" is not negative", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
|
func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
|
@ -447,7 +478,7 @@ func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedCompare
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func containsValue(values []CompareType, value CompareType) bool {
|
func containsValue(values []compareResult, value compareResult) bool {
|
||||||
for _, v := range values {
|
for _, v := range values {
|
||||||
if v == value {
|
if v == value {
|
||||||
return true
|
return true
|
||||||
|
|
|
||||||
16
vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
generated
vendored
16
vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
generated
vendored
|
|
@ -1,16 +0,0 @@
|
||||||
//go:build go1.17
|
|
||||||
// +build go1.17
|
|
||||||
|
|
||||||
// TODO: once support for Go 1.16 is dropped, this file can be
|
|
||||||
// merged/removed with assertion_compare_go1.17_test.go and
|
|
||||||
// assertion_compare_legacy.go
|
|
||||||
|
|
||||||
package assert
|
|
||||||
|
|
||||||
import "reflect"
|
|
||||||
|
|
||||||
// Wrapper around reflect.Value.CanConvert, for compatibility
|
|
||||||
// reasons.
|
|
||||||
func canConvert(value reflect.Value, to reflect.Type) bool {
|
|
||||||
return value.CanConvert(to)
|
|
||||||
}
|
|
||||||
16
vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go
generated
vendored
16
vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go
generated
vendored
|
|
@ -1,16 +0,0 @@
|
||||||
//go:build !go1.17
|
|
||||||
// +build !go1.17
|
|
||||||
|
|
||||||
// TODO: once support for Go 1.16 is dropped, this file can be
|
|
||||||
// merged/removed with assertion_compare_go1.17_test.go and
|
|
||||||
// assertion_compare_can_convert.go
|
|
||||||
|
|
||||||
package assert
|
|
||||||
|
|
||||||
import "reflect"
|
|
||||||
|
|
||||||
// Older versions of Go does not have the reflect.Value.CanConvert
|
|
||||||
// method.
|
|
||||||
func canConvert(value reflect.Value, to reflect.Type) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
64
vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
64
vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
|
|
@ -1,7 +1,4 @@
|
||||||
/*
|
// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
|
||||||
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
|
|
||||||
* THIS FILE MUST NOT BE EDITED BY HAND
|
|
||||||
*/
|
|
||||||
|
|
||||||
package assert
|
package assert
|
||||||
|
|
||||||
|
|
@ -107,8 +104,8 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{},
|
||||||
return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
// EqualValuesf asserts that two objects are equal or convertible to the larger
|
||||||
// and equal.
|
// type and equal.
|
||||||
//
|
//
|
||||||
// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
|
// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
|
||||||
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
|
@ -189,7 +186,7 @@ func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick
|
||||||
// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") {
|
// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") {
|
||||||
// // add assertions as needed; any assertion failure will fail the current tick
|
// // add assertions as needed; any assertion failure will fail the current tick
|
||||||
// assert.True(c, externalValue, "expected 'externalValue' to be true")
|
// assert.True(c, externalValue, "expected 'externalValue' to be true")
|
||||||
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
|
// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
|
||||||
func EventuallyWithTf(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
|
func EventuallyWithTf(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
|
@ -571,6 +568,23 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a
|
||||||
return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
|
return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified
|
||||||
|
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
|
||||||
|
// the number of appearances of each of them in both lists should not match.
|
||||||
|
// This is an inverse of ElementsMatch.
|
||||||
|
//
|
||||||
|
// assert.NotElementsMatchf(t, [1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false
|
||||||
|
//
|
||||||
|
// assert.NotElementsMatchf(t, [1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true
|
||||||
|
//
|
||||||
|
// assert.NotElementsMatchf(t, [1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true
|
||||||
|
func NotElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return NotElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
||||||
// a slice or a channel with len == 0.
|
// a slice or a channel with len == 0.
|
||||||
//
|
//
|
||||||
|
|
@ -607,7 +621,16 @@ func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg s
|
||||||
return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotErrorIsf asserts that at none of the errors in err's chain matches target.
|
// NotErrorAsf asserts that none of the errors in err's chain matches target,
|
||||||
|
// but if so, sets target to that error value.
|
||||||
|
func NotErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return NotErrorAs(t, err, target, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotErrorIsf asserts that none of the errors in err's chain matches target.
|
||||||
// This is a wrapper for errors.Is.
|
// This is a wrapper for errors.Is.
|
||||||
func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
|
func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
|
|
@ -616,6 +639,16 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf
|
||||||
return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
|
return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotImplementsf asserts that an object does not implement the specified interface.
|
||||||
|
//
|
||||||
|
// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
|
||||||
|
func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotNilf asserts that the specified object is not nil.
|
// NotNilf asserts that the specified object is not nil.
|
||||||
//
|
//
|
||||||
// assert.NotNilf(t, err, "error message %s", "formatted")
|
// assert.NotNilf(t, err, "error message %s", "formatted")
|
||||||
|
|
@ -660,10 +693,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string,
|
||||||
return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...)
|
return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotSubsetf asserts that the specified list(array, slice...) contains not all
|
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
|
||||||
// elements given in the specified subset(array, slice...).
|
// contain all elements given in the specified subset list(array, slice...) or
|
||||||
|
// map.
|
||||||
//
|
//
|
||||||
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted")
|
||||||
|
// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
|
||||||
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
|
@ -747,10 +782,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg
|
||||||
return Same(t, expected, actual, append([]interface{}{msg}, args...)...)
|
return Same(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subsetf asserts that the specified list(array, slice...) contains all
|
// Subsetf asserts that the specified list(array, slice...) or map contains all
|
||||||
// elements given in the specified subset(array, slice...).
|
// elements given in the specified subset list(array, slice...) or map.
|
||||||
//
|
//
|
||||||
// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted")
|
||||||
|
// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
|
||||||
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
|
|
||||||
123
vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
123
vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
|
|
@ -1,7 +1,4 @@
|
||||||
/*
|
// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
|
||||||
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
|
|
||||||
* THIS FILE MUST NOT BE EDITED BY HAND
|
|
||||||
*/
|
|
||||||
|
|
||||||
package assert
|
package assert
|
||||||
|
|
||||||
|
|
@ -189,8 +186,8 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface
|
||||||
return EqualExportedValuesf(a.t, expected, actual, msg, args...)
|
return EqualExportedValuesf(a.t, expected, actual, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EqualValues asserts that two objects are equal or convertable to the same types
|
// EqualValues asserts that two objects are equal or convertible to the larger
|
||||||
// and equal.
|
// type and equal.
|
||||||
//
|
//
|
||||||
// a.EqualValues(uint32(123), int32(123))
|
// a.EqualValues(uint32(123), int32(123))
|
||||||
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
|
@ -200,8 +197,8 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
|
||||||
return EqualValues(a.t, expected, actual, msgAndArgs...)
|
return EqualValues(a.t, expected, actual, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
// EqualValuesf asserts that two objects are equal or convertible to the larger
|
||||||
// and equal.
|
// type and equal.
|
||||||
//
|
//
|
||||||
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
|
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
|
||||||
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
|
@ -339,7 +336,7 @@ func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, ti
|
||||||
// a.EventuallyWithT(func(c *assert.CollectT) {
|
// a.EventuallyWithT(func(c *assert.CollectT) {
|
||||||
// // add assertions as needed; any assertion failure will fail the current tick
|
// // add assertions as needed; any assertion failure will fail the current tick
|
||||||
// assert.True(c, externalValue, "expected 'externalValue' to be true")
|
// assert.True(c, externalValue, "expected 'externalValue' to be true")
|
||||||
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
|
// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
|
||||||
func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
|
@ -364,7 +361,7 @@ func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor
|
||||||
// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
|
// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
|
||||||
// // add assertions as needed; any assertion failure will fail the current tick
|
// // add assertions as needed; any assertion failure will fail the current tick
|
||||||
// assert.True(c, externalValue, "expected 'externalValue' to be true")
|
// assert.True(c, externalValue, "expected 'externalValue' to be true")
|
||||||
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
|
// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
|
||||||
func (a *Assertions) EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
|
func (a *Assertions) EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
|
@ -1131,6 +1128,40 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin
|
||||||
return NotContainsf(a.t, s, contains, msg, args...)
|
return NotContainsf(a.t, s, contains, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified
|
||||||
|
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
|
||||||
|
// the number of appearances of each of them in both lists should not match.
|
||||||
|
// This is an inverse of ElementsMatch.
|
||||||
|
//
|
||||||
|
// a.NotElementsMatch([1, 1, 2, 3], [1, 1, 2, 3]) -> false
|
||||||
|
//
|
||||||
|
// a.NotElementsMatch([1, 1, 2, 3], [1, 2, 3]) -> true
|
||||||
|
//
|
||||||
|
// a.NotElementsMatch([1, 2, 3], [1, 2, 4]) -> true
|
||||||
|
func (a *Assertions) NotElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return NotElementsMatch(a.t, listA, listB, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified
|
||||||
|
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
|
||||||
|
// the number of appearances of each of them in both lists should not match.
|
||||||
|
// This is an inverse of ElementsMatch.
|
||||||
|
//
|
||||||
|
// a.NotElementsMatchf([1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false
|
||||||
|
//
|
||||||
|
// a.NotElementsMatchf([1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true
|
||||||
|
//
|
||||||
|
// a.NotElementsMatchf([1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true
|
||||||
|
func (a *Assertions) NotElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return NotElementsMatchf(a.t, listA, listB, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
||||||
// a slice or a channel with len == 0.
|
// a slice or a channel with len == 0.
|
||||||
//
|
//
|
||||||
|
|
@ -1203,7 +1234,25 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str
|
||||||
return NotEqualf(a.t, expected, actual, msg, args...)
|
return NotEqualf(a.t, expected, actual, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotErrorIs asserts that at none of the errors in err's chain matches target.
|
// NotErrorAs asserts that none of the errors in err's chain matches target,
|
||||||
|
// but if so, sets target to that error value.
|
||||||
|
func (a *Assertions) NotErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return NotErrorAs(a.t, err, target, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotErrorAsf asserts that none of the errors in err's chain matches target,
|
||||||
|
// but if so, sets target to that error value.
|
||||||
|
func (a *Assertions) NotErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return NotErrorAsf(a.t, err, target, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotErrorIs asserts that none of the errors in err's chain matches target.
|
||||||
// This is a wrapper for errors.Is.
|
// This is a wrapper for errors.Is.
|
||||||
func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
|
@ -1212,7 +1261,7 @@ func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface
|
||||||
return NotErrorIs(a.t, err, target, msgAndArgs...)
|
return NotErrorIs(a.t, err, target, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotErrorIsf asserts that at none of the errors in err's chain matches target.
|
// NotErrorIsf asserts that none of the errors in err's chain matches target.
|
||||||
// This is a wrapper for errors.Is.
|
// This is a wrapper for errors.Is.
|
||||||
func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool {
|
func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
|
@ -1221,6 +1270,26 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in
|
||||||
return NotErrorIsf(a.t, err, target, msg, args...)
|
return NotErrorIsf(a.t, err, target, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotImplements asserts that an object does not implement the specified interface.
|
||||||
|
//
|
||||||
|
// a.NotImplements((*MyInterface)(nil), new(MyObject))
|
||||||
|
func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return NotImplements(a.t, interfaceObject, object, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotImplementsf asserts that an object does not implement the specified interface.
|
||||||
|
//
|
||||||
|
// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
|
||||||
|
func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return NotImplementsf(a.t, interfaceObject, object, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotNil asserts that the specified object is not nil.
|
// NotNil asserts that the specified object is not nil.
|
||||||
//
|
//
|
||||||
// a.NotNil(err)
|
// a.NotNil(err)
|
||||||
|
|
@ -1309,10 +1378,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri
|
||||||
return NotSamef(a.t, expected, actual, msg, args...)
|
return NotSamef(a.t, expected, actual, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotSubset asserts that the specified list(array, slice...) contains not all
|
// NotSubset asserts that the specified list(array, slice...) or map does NOT
|
||||||
// elements given in the specified subset(array, slice...).
|
// contain all elements given in the specified subset list(array, slice...) or
|
||||||
|
// map.
|
||||||
//
|
//
|
||||||
// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
// a.NotSubset([1, 3, 4], [1, 2])
|
||||||
|
// a.NotSubset({"x": 1, "y": 2}, {"z": 3})
|
||||||
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
|
@ -1320,10 +1391,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs
|
||||||
return NotSubset(a.t, list, subset, msgAndArgs...)
|
return NotSubset(a.t, list, subset, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotSubsetf asserts that the specified list(array, slice...) contains not all
|
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
|
||||||
// elements given in the specified subset(array, slice...).
|
// contain all elements given in the specified subset list(array, slice...) or
|
||||||
|
// map.
|
||||||
//
|
//
|
||||||
// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted")
|
||||||
|
// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
|
||||||
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
|
@ -1483,10 +1556,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string,
|
||||||
return Samef(a.t, expected, actual, msg, args...)
|
return Samef(a.t, expected, actual, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subset asserts that the specified list(array, slice...) contains all
|
// Subset asserts that the specified list(array, slice...) or map contains all
|
||||||
// elements given in the specified subset(array, slice...).
|
// elements given in the specified subset list(array, slice...) or map.
|
||||||
//
|
//
|
||||||
// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
// a.Subset([1, 2, 3], [1, 2])
|
||||||
|
// a.Subset({"x": 1, "y": 2}, {"x": 1})
|
||||||
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
|
@ -1494,10 +1568,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...
|
||||||
return Subset(a.t, list, subset, msgAndArgs...)
|
return Subset(a.t, list, subset, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subsetf asserts that the specified list(array, slice...) contains all
|
// Subsetf asserts that the specified list(array, slice...) or map contains all
|
||||||
// elements given in the specified subset(array, slice...).
|
// elements given in the specified subset list(array, slice...) or map.
|
||||||
//
|
//
|
||||||
// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted")
|
||||||
|
// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
|
||||||
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
|
|
||||||
10
vendor/github.com/stretchr/testify/assert/assertion_order.go
generated
vendored
10
vendor/github.com/stretchr/testify/assert/assertion_order.go
generated
vendored
|
|
@ -6,7 +6,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// isOrdered checks that collection contains orderable elements.
|
// isOrdered checks that collection contains orderable elements.
|
||||||
func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
|
func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool {
|
||||||
objKind := reflect.TypeOf(object).Kind()
|
objKind := reflect.TypeOf(object).Kind()
|
||||||
if objKind != reflect.Slice && objKind != reflect.Array {
|
if objKind != reflect.Slice && objKind != reflect.Array {
|
||||||
return false
|
return false
|
||||||
|
|
@ -50,7 +50,7 @@ func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareT
|
||||||
// assert.IsIncreasing(t, []float{1, 2})
|
// assert.IsIncreasing(t, []float{1, 2})
|
||||||
// assert.IsIncreasing(t, []string{"a", "b"})
|
// assert.IsIncreasing(t, []string{"a", "b"})
|
||||||
func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
|
return isOrdered(t, object, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNonIncreasing asserts that the collection is not increasing
|
// IsNonIncreasing asserts that the collection is not increasing
|
||||||
|
|
@ -59,7 +59,7 @@ func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) boo
|
||||||
// assert.IsNonIncreasing(t, []float{2, 1})
|
// assert.IsNonIncreasing(t, []float{2, 1})
|
||||||
// assert.IsNonIncreasing(t, []string{"b", "a"})
|
// assert.IsNonIncreasing(t, []string{"b", "a"})
|
||||||
func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
|
return isOrdered(t, object, []compareResult{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDecreasing asserts that the collection is decreasing
|
// IsDecreasing asserts that the collection is decreasing
|
||||||
|
|
@ -68,7 +68,7 @@ func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{})
|
||||||
// assert.IsDecreasing(t, []float{2, 1})
|
// assert.IsDecreasing(t, []float{2, 1})
|
||||||
// assert.IsDecreasing(t, []string{"b", "a"})
|
// assert.IsDecreasing(t, []string{"b", "a"})
|
||||||
func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
|
return isOrdered(t, object, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNonDecreasing asserts that the collection is not decreasing
|
// IsNonDecreasing asserts that the collection is not decreasing
|
||||||
|
|
@ -77,5 +77,5 @@ func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) boo
|
||||||
// assert.IsNonDecreasing(t, []float{1, 2})
|
// assert.IsNonDecreasing(t, []float{1, 2})
|
||||||
// assert.IsNonDecreasing(t, []string{"a", "b"})
|
// assert.IsNonDecreasing(t, []string{"a", "b"})
|
||||||
func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
|
return isOrdered(t, object, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
326
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
326
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
|
|
@ -19,7 +19,9 @@ import (
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/pmezard/go-difflib/difflib"
|
"github.com/pmezard/go-difflib/difflib"
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
|
// Wrapper around gopkg.in/yaml.v3
|
||||||
|
"github.com/stretchr/testify/assert/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
|
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
|
||||||
|
|
@ -45,6 +47,10 @@ type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool
|
||||||
// for table driven tests.
|
// for table driven tests.
|
||||||
type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool
|
type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool
|
||||||
|
|
||||||
|
// PanicAssertionFunc is a common function prototype when validating a panic value. Can be useful
|
||||||
|
// for table driven tests.
|
||||||
|
type PanicAssertionFunc = func(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool
|
||||||
|
|
||||||
// Comparison is a custom function that returns true on success and false on failure
|
// Comparison is a custom function that returns true on success and false on failure
|
||||||
type Comparison func() (success bool)
|
type Comparison func() (success bool)
|
||||||
|
|
||||||
|
|
@ -110,7 +116,12 @@ func copyExportedFields(expected interface{}) interface{} {
|
||||||
return result.Interface()
|
return result.Interface()
|
||||||
|
|
||||||
case reflect.Array, reflect.Slice:
|
case reflect.Array, reflect.Slice:
|
||||||
result := reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len())
|
var result reflect.Value
|
||||||
|
if expectedKind == reflect.Array {
|
||||||
|
result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem()
|
||||||
|
} else {
|
||||||
|
result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len())
|
||||||
|
}
|
||||||
for i := 0; i < expectedValue.Len(); i++ {
|
for i := 0; i < expectedValue.Len(); i++ {
|
||||||
index := expectedValue.Index(i)
|
index := expectedValue.Index(i)
|
||||||
if isNil(index) {
|
if isNil(index) {
|
||||||
|
|
@ -140,6 +151,8 @@ func copyExportedFields(expected interface{}) interface{} {
|
||||||
// structures.
|
// structures.
|
||||||
//
|
//
|
||||||
// This function does no assertion of any kind.
|
// This function does no assertion of any kind.
|
||||||
|
//
|
||||||
|
// Deprecated: Use [EqualExportedValues] instead.
|
||||||
func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool {
|
func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool {
|
||||||
expectedCleaned := copyExportedFields(expected)
|
expectedCleaned := copyExportedFields(expected)
|
||||||
actualCleaned := copyExportedFields(actual)
|
actualCleaned := copyExportedFields(actual)
|
||||||
|
|
@ -153,17 +166,40 @@ func ObjectsAreEqualValues(expected, actual interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
actualType := reflect.TypeOf(actual)
|
expectedValue := reflect.ValueOf(expected)
|
||||||
if actualType == nil {
|
actualValue := reflect.ValueOf(actual)
|
||||||
|
if !expectedValue.IsValid() || !actualValue.IsValid() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
expectedValue := reflect.ValueOf(expected)
|
|
||||||
if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
|
expectedType := expectedValue.Type()
|
||||||
// Attempt comparison after type conversion
|
actualType := actualValue.Type()
|
||||||
return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
|
if !expectedType.ConvertibleTo(actualType) {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
if !isNumericType(expectedType) || !isNumericType(actualType) {
|
||||||
|
// Attempt comparison after type conversion
|
||||||
|
return reflect.DeepEqual(
|
||||||
|
expectedValue.Convert(actualType).Interface(), actual,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If BOTH values are numeric, there are chances of false positives due
|
||||||
|
// to overflow or underflow. So, we need to make sure to always convert
|
||||||
|
// the smaller type to a larger type before comparing.
|
||||||
|
if expectedType.Size() >= actualType.Size() {
|
||||||
|
return actualValue.Convert(expectedType).Interface() == expected
|
||||||
|
}
|
||||||
|
|
||||||
|
return expectedValue.Convert(actualType).Interface() == actual
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNumericType returns true if the type is one of:
|
||||||
|
// int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64,
|
||||||
|
// float32, float64, complex64, complex128
|
||||||
|
func isNumericType(t reflect.Type) bool {
|
||||||
|
return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CallerInfo is necessary because the assert functions use the testing object
|
/* CallerInfo is necessary because the assert functions use the testing object
|
||||||
|
|
@ -266,7 +302,7 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
|
||||||
|
|
||||||
// Aligns the provided message so that all lines after the first line start at the same location as the first line.
|
// Aligns the provided message so that all lines after the first line start at the same location as the first line.
|
||||||
// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab).
|
// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab).
|
||||||
// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the
|
// The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the
|
||||||
// basis on which the alignment occurs).
|
// basis on which the alignment occurs).
|
||||||
func indentMessageLines(message string, longestLabelLen int) string {
|
func indentMessageLines(message string, longestLabelLen int) string {
|
||||||
outBuf := new(bytes.Buffer)
|
outBuf := new(bytes.Buffer)
|
||||||
|
|
@ -382,6 +418,25 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotImplements asserts that an object does not implement the specified interface.
|
||||||
|
//
|
||||||
|
// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject))
|
||||||
|
func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
interfaceType := reflect.TypeOf(interfaceObject).Elem()
|
||||||
|
|
||||||
|
if object == nil {
|
||||||
|
return Fail(t, fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...)
|
||||||
|
}
|
||||||
|
if reflect.TypeOf(object).Implements(interfaceType) {
|
||||||
|
return Fail(t, fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// IsType asserts that the specified objects are of the same type.
|
// IsType asserts that the specified objects are of the same type.
|
||||||
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
|
|
@ -447,7 +502,13 @@ func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) b
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !samePointers(expected, actual) {
|
same, ok := samePointers(expected, actual)
|
||||||
|
if !ok {
|
||||||
|
return Fail(t, "Both arguments must be pointers", msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !same {
|
||||||
|
// both are pointers but not the same type & pointing to the same address
|
||||||
return Fail(t, fmt.Sprintf("Not same: \n"+
|
return Fail(t, fmt.Sprintf("Not same: \n"+
|
||||||
"expected: %p %#v\n"+
|
"expected: %p %#v\n"+
|
||||||
"actual : %p %#v", expected, expected, actual, actual), msgAndArgs...)
|
"actual : %p %#v", expected, expected, actual, actual), msgAndArgs...)
|
||||||
|
|
@ -467,7 +528,13 @@ func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
if samePointers(expected, actual) {
|
same, ok := samePointers(expected, actual)
|
||||||
|
if !ok {
|
||||||
|
//fails when the arguments are not pointers
|
||||||
|
return !(Fail(t, "Both arguments must be pointers", msgAndArgs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
if same {
|
||||||
return Fail(t, fmt.Sprintf(
|
return Fail(t, fmt.Sprintf(
|
||||||
"Expected and actual point to the same object: %p %#v",
|
"Expected and actual point to the same object: %p %#v",
|
||||||
expected, expected), msgAndArgs...)
|
expected, expected), msgAndArgs...)
|
||||||
|
|
@ -475,28 +542,30 @@ func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// samePointers compares two generic interface objects and returns whether
|
// samePointers checks if two generic interface objects are pointers of the same
|
||||||
// they point to the same object
|
// type pointing to the same object. It returns two values: same indicating if
|
||||||
func samePointers(first, second interface{}) bool {
|
// they are the same type and point to the same object, and ok indicating that
|
||||||
|
// both inputs are pointers.
|
||||||
|
func samePointers(first, second interface{}) (same bool, ok bool) {
|
||||||
firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second)
|
firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second)
|
||||||
if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr {
|
if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr {
|
||||||
return false
|
return false, false //not both are pointers
|
||||||
}
|
}
|
||||||
|
|
||||||
firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second)
|
firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second)
|
||||||
if firstType != secondType {
|
if firstType != secondType {
|
||||||
return false
|
return false, true // both are pointers, but of different types
|
||||||
}
|
}
|
||||||
|
|
||||||
// compare pointer addresses
|
// compare pointer addresses
|
||||||
return first == second
|
return first == second, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// formatUnequalValues takes two values of arbitrary types and returns string
|
// formatUnequalValues takes two values of arbitrary types and returns string
|
||||||
// representations appropriate to be presented to the user.
|
// representations appropriate to be presented to the user.
|
||||||
//
|
//
|
||||||
// If the values are not of like type, the returned strings will be prefixed
|
// If the values are not of like type, the returned strings will be prefixed
|
||||||
// with the type name, and the value will be enclosed in parenthesis similar
|
// with the type name, and the value will be enclosed in parentheses similar
|
||||||
// to a type conversion in the Go grammar.
|
// to a type conversion in the Go grammar.
|
||||||
func formatUnequalValues(expected, actual interface{}) (e string, a string) {
|
func formatUnequalValues(expected, actual interface{}) (e string, a string) {
|
||||||
if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
|
if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
|
||||||
|
|
@ -523,8 +592,8 @@ func truncatingFormat(data interface{}) string {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
// EqualValues asserts that two objects are equal or convertable to the same types
|
// EqualValues asserts that two objects are equal or convertible to the larger
|
||||||
// and equal.
|
// type and equal.
|
||||||
//
|
//
|
||||||
// assert.EqualValues(t, uint32(123), int32(123))
|
// assert.EqualValues(t, uint32(123), int32(123))
|
||||||
func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
|
@ -566,14 +635,6 @@ func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs ..
|
||||||
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if aType.Kind() != reflect.Struct {
|
|
||||||
return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if bType.Kind() != reflect.Struct {
|
|
||||||
return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
expected = copyExportedFields(expected)
|
expected = copyExportedFields(expected)
|
||||||
actual = copyExportedFields(actual)
|
actual = copyExportedFields(actual)
|
||||||
|
|
||||||
|
|
@ -620,17 +681,6 @@ func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return Fail(t, "Expected value not to be nil.", msgAndArgs...)
|
return Fail(t, "Expected value not to be nil.", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// containsKind checks if a specified kind in the slice of kinds.
|
|
||||||
func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool {
|
|
||||||
for i := 0; i < len(kinds); i++ {
|
|
||||||
if kind == kinds[i] {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// isNil checks if a specified object is nil or not, without Failing.
|
// isNil checks if a specified object is nil or not, without Failing.
|
||||||
func isNil(object interface{}) bool {
|
func isNil(object interface{}) bool {
|
||||||
if object == nil {
|
if object == nil {
|
||||||
|
|
@ -638,16 +688,13 @@ func isNil(object interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
value := reflect.ValueOf(object)
|
value := reflect.ValueOf(object)
|
||||||
kind := value.Kind()
|
switch value.Kind() {
|
||||||
isNilableKind := containsKind(
|
case
|
||||||
[]reflect.Kind{
|
reflect.Chan, reflect.Func,
|
||||||
reflect.Chan, reflect.Func,
|
reflect.Interface, reflect.Map,
|
||||||
reflect.Interface, reflect.Map,
|
reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
|
||||||
reflect.Ptr, reflect.Slice, reflect.UnsafePointer},
|
|
||||||
kind)
|
|
||||||
|
|
||||||
if isNilableKind && value.IsNil() {
|
return value.IsNil()
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|
@ -731,16 +778,14 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getLen try to get length of object.
|
// getLen tries to get the length of an object.
|
||||||
// return (false, 0) if impossible.
|
// It returns (0, false) if impossible.
|
||||||
func getLen(x interface{}) (ok bool, length int) {
|
func getLen(x interface{}) (length int, ok bool) {
|
||||||
v := reflect.ValueOf(x)
|
v := reflect.ValueOf(x)
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
ok = recover() == nil
|
||||||
ok = false
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
return true, v.Len()
|
return v.Len(), true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Len asserts that the specified object has specific length.
|
// Len asserts that the specified object has specific length.
|
||||||
|
|
@ -751,13 +796,13 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{})
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
ok, l := getLen(object)
|
l, ok := getLen(object)
|
||||||
if !ok {
|
if !ok {
|
||||||
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if l != length {
|
if l != length {
|
||||||
return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -919,10 +964,11 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subset asserts that the specified list(array, slice...) contains all
|
// Subset asserts that the specified list(array, slice...) or map contains all
|
||||||
// elements given in the specified subset(array, slice...).
|
// elements given in the specified subset list(array, slice...) or map.
|
||||||
//
|
//
|
||||||
// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
// assert.Subset(t, [1, 2, 3], [1, 2])
|
||||||
|
// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1})
|
||||||
func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
|
@ -975,10 +1021,12 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotSubset asserts that the specified list(array, slice...) contains not all
|
// NotSubset asserts that the specified list(array, slice...) or map does NOT
|
||||||
// elements given in the specified subset(array, slice...).
|
// contain all elements given in the specified subset list(array, slice...) or
|
||||||
|
// map.
|
||||||
//
|
//
|
||||||
// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
// assert.NotSubset(t, [1, 3, 4], [1, 2])
|
||||||
|
// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3})
|
||||||
func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
|
|
@ -1127,6 +1175,39 @@ func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) stri
|
||||||
return msg.String()
|
return msg.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified
|
||||||
|
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
|
||||||
|
// the number of appearances of each of them in both lists should not match.
|
||||||
|
// This is an inverse of ElementsMatch.
|
||||||
|
//
|
||||||
|
// assert.NotElementsMatch(t, [1, 1, 2, 3], [1, 1, 2, 3]) -> false
|
||||||
|
//
|
||||||
|
// assert.NotElementsMatch(t, [1, 1, 2, 3], [1, 2, 3]) -> true
|
||||||
|
//
|
||||||
|
// assert.NotElementsMatch(t, [1, 2, 3], [1, 2, 4]) -> true
|
||||||
|
func NotElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
if isEmpty(listA) && isEmpty(listB) {
|
||||||
|
return Fail(t, "listA and listB contain the same elements", msgAndArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isList(t, listA, msgAndArgs...) {
|
||||||
|
return Fail(t, "listA is not a list type", msgAndArgs...)
|
||||||
|
}
|
||||||
|
if !isList(t, listB, msgAndArgs...) {
|
||||||
|
return Fail(t, "listB is not a list type", msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
extraA, extraB := diffLists(listA, listB)
|
||||||
|
if len(extraA) == 0 && len(extraB) == 0 {
|
||||||
|
return Fail(t, "listA and listB contain the same elements", msgAndArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Condition uses a Comparison to assert a complex condition.
|
// Condition uses a Comparison to assert a complex condition.
|
||||||
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
|
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
|
|
@ -1439,12 +1520,15 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
if math.IsNaN(epsilon) {
|
if math.IsNaN(epsilon) {
|
||||||
return Fail(t, "epsilon must not be NaN")
|
return Fail(t, "epsilon must not be NaN", msgAndArgs...)
|
||||||
}
|
}
|
||||||
actualEpsilon, err := calcRelativeError(expected, actual)
|
actualEpsilon, err := calcRelativeError(expected, actual)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Fail(t, err.Error(), msgAndArgs...)
|
return Fail(t, err.Error(), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
if math.IsNaN(actualEpsilon) {
|
||||||
|
return Fail(t, "relative error is NaN", msgAndArgs...)
|
||||||
|
}
|
||||||
if actualEpsilon > epsilon {
|
if actualEpsilon > epsilon {
|
||||||
return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
|
return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
|
||||||
" < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...)
|
" < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...)
|
||||||
|
|
@ -1458,19 +1542,26 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
if expected == nil || actual == nil ||
|
|
||||||
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
if expected == nil || actual == nil {
|
||||||
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
|
||||||
return Fail(t, "Parameters must be slice", msgAndArgs...)
|
return Fail(t, "Parameters must be slice", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
actualSlice := reflect.ValueOf(actual)
|
|
||||||
expectedSlice := reflect.ValueOf(expected)
|
expectedSlice := reflect.ValueOf(expected)
|
||||||
|
actualSlice := reflect.ValueOf(actual)
|
||||||
|
|
||||||
for i := 0; i < actualSlice.Len(); i++ {
|
if expectedSlice.Type().Kind() != reflect.Slice {
|
||||||
result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon)
|
return Fail(t, "Expected value must be slice", msgAndArgs...)
|
||||||
if !result {
|
}
|
||||||
return result
|
|
||||||
|
expectedLen := expectedSlice.Len()
|
||||||
|
if !IsType(t, expected, actual) || !Len(t, actual, expectedLen) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < expectedLen; i++ {
|
||||||
|
if !InEpsilon(t, expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1561,7 +1652,6 @@ func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...in
|
||||||
|
|
||||||
// matchRegexp return true if a specified regexp matches a string.
|
// matchRegexp return true if a specified regexp matches a string.
|
||||||
func matchRegexp(rx interface{}, str interface{}) bool {
|
func matchRegexp(rx interface{}, str interface{}) bool {
|
||||||
|
|
||||||
var r *regexp.Regexp
|
var r *regexp.Regexp
|
||||||
if rr, ok := rx.(*regexp.Regexp); ok {
|
if rr, ok := rx.(*regexp.Regexp); ok {
|
||||||
r = rr
|
r = rr
|
||||||
|
|
@ -1569,7 +1659,14 @@ func matchRegexp(rx interface{}, str interface{}) bool {
|
||||||
r = regexp.MustCompile(fmt.Sprint(rx))
|
r = regexp.MustCompile(fmt.Sprint(rx))
|
||||||
}
|
}
|
||||||
|
|
||||||
return (r.FindStringIndex(fmt.Sprint(str)) != nil)
|
switch v := str.(type) {
|
||||||
|
case []byte:
|
||||||
|
return r.Match(v)
|
||||||
|
case string:
|
||||||
|
return r.MatchString(v)
|
||||||
|
default:
|
||||||
|
return r.MatchString(fmt.Sprint(v))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1822,7 +1919,7 @@ var spewConfigStringerEnabled = spew.ConfigState{
|
||||||
MaxDepth: 10,
|
MaxDepth: 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
type tHelper interface {
|
type tHelper = interface {
|
||||||
Helper()
|
Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1861,6 +1958,9 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
|
||||||
|
|
||||||
// CollectT implements the TestingT interface and collects all errors.
|
// CollectT implements the TestingT interface and collects all errors.
|
||||||
type CollectT struct {
|
type CollectT struct {
|
||||||
|
// A slice of errors. Non-nil slice denotes a failure.
|
||||||
|
// If it's non-nil but len(c.errors) == 0, this is also a failure
|
||||||
|
// obtained by direct c.FailNow() call.
|
||||||
errors []error
|
errors []error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1869,26 +1969,32 @@ func (c *CollectT) Errorf(format string, args ...interface{}) {
|
||||||
c.errors = append(c.errors, fmt.Errorf(format, args...))
|
c.errors = append(c.errors, fmt.Errorf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailNow panics.
|
// FailNow stops execution by calling runtime.Goexit.
|
||||||
func (c *CollectT) FailNow() {
|
func (c *CollectT) FailNow() {
|
||||||
panic("Assertion failed")
|
c.fail()
|
||||||
|
runtime.Goexit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset clears the collected errors.
|
// Deprecated: That was a method for internal usage that should not have been published. Now just panics.
|
||||||
func (c *CollectT) Reset() {
|
func (*CollectT) Reset() {
|
||||||
c.errors = nil
|
panic("Reset() is deprecated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy copies the collected errors to the supplied t.
|
// Deprecated: That was a method for internal usage that should not have been published. Now just panics.
|
||||||
func (c *CollectT) Copy(t TestingT) {
|
func (*CollectT) Copy(TestingT) {
|
||||||
if tt, ok := t.(tHelper); ok {
|
panic("Copy() is deprecated")
|
||||||
tt.Helper()
|
}
|
||||||
}
|
|
||||||
for _, err := range c.errors {
|
func (c *CollectT) fail() {
|
||||||
t.Errorf("%v", err)
|
if !c.failed() {
|
||||||
|
c.errors = []error{} // Make it non-nil to mark a failure.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CollectT) failed() bool {
|
||||||
|
return c.errors != nil
|
||||||
|
}
|
||||||
|
|
||||||
// EventuallyWithT asserts that given condition will be met in waitFor time,
|
// EventuallyWithT asserts that given condition will be met in waitFor time,
|
||||||
// periodically checking target function each tick. In contrast to Eventually,
|
// periodically checking target function each tick. In contrast to Eventually,
|
||||||
// it supplies a CollectT to the condition function, so that the condition
|
// it supplies a CollectT to the condition function, so that the condition
|
||||||
|
|
@ -1906,14 +2012,14 @@ func (c *CollectT) Copy(t TestingT) {
|
||||||
// assert.EventuallyWithT(t, func(c *assert.CollectT) {
|
// assert.EventuallyWithT(t, func(c *assert.CollectT) {
|
||||||
// // add assertions as needed; any assertion failure will fail the current tick
|
// // add assertions as needed; any assertion failure will fail the current tick
|
||||||
// assert.True(c, externalValue, "expected 'externalValue' to be true")
|
// assert.True(c, externalValue, "expected 'externalValue' to be true")
|
||||||
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
|
// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
|
||||||
func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
|
func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
collect := new(CollectT)
|
var lastFinishedTickErrs []error
|
||||||
ch := make(chan bool, 1)
|
ch := make(chan *CollectT, 1)
|
||||||
|
|
||||||
timer := time.NewTimer(waitFor)
|
timer := time.NewTimer(waitFor)
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
@ -1924,19 +2030,25 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time
|
||||||
for tick := ticker.C; ; {
|
for tick := ticker.C; ; {
|
||||||
select {
|
select {
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
collect.Copy(t)
|
for _, err := range lastFinishedTickErrs {
|
||||||
|
t.Errorf("%v", err)
|
||||||
|
}
|
||||||
return Fail(t, "Condition never satisfied", msgAndArgs...)
|
return Fail(t, "Condition never satisfied", msgAndArgs...)
|
||||||
case <-tick:
|
case <-tick:
|
||||||
tick = nil
|
tick = nil
|
||||||
collect.Reset()
|
|
||||||
go func() {
|
go func() {
|
||||||
|
collect := new(CollectT)
|
||||||
|
defer func() {
|
||||||
|
ch <- collect
|
||||||
|
}()
|
||||||
condition(collect)
|
condition(collect)
|
||||||
ch <- len(collect.errors) == 0
|
|
||||||
}()
|
}()
|
||||||
case v := <-ch:
|
case collect := <-ch:
|
||||||
if v {
|
if !collect.failed() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached.
|
||||||
|
lastFinishedTickErrs = collect.errors
|
||||||
tick = ticker.C
|
tick = ticker.C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1998,7 +2110,7 @@ func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
|
||||||
), msgAndArgs...)
|
), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotErrorIs asserts that at none of the errors in err's chain matches target.
|
// NotErrorIs asserts that none of the errors in err's chain matches target.
|
||||||
// This is a wrapper for errors.Is.
|
// This is a wrapper for errors.Is.
|
||||||
func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
|
func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
|
|
@ -2039,6 +2151,24 @@ func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{
|
||||||
), msgAndArgs...)
|
), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotErrorAs asserts that none of the errors in err's chain matches target,
|
||||||
|
// but if so, sets target to that error value.
|
||||||
|
func NotErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
if !errors.As(err, target) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
chain := buildErrorChainString(err)
|
||||||
|
|
||||||
|
return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+
|
||||||
|
"found: %q\n"+
|
||||||
|
"in chain: %s", target, chain,
|
||||||
|
), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
func buildErrorChainString(err error) string {
|
func buildErrorChainString(err error) string {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return ""
|
return ""
|
||||||
|
|
|
||||||
27
vendor/github.com/stretchr/testify/assert/http_assertions.go
generated
vendored
27
vendor/github.com/stretchr/testify/assert/http_assertions.go
generated
vendored
|
|
@ -12,7 +12,7 @@ import (
|
||||||
// an error if building a new request fails.
|
// an error if building a new request fails.
|
||||||
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
|
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
req, err := http.NewRequest(method, url, nil)
|
req, err := http.NewRequest(method, url, http.NoBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
@ -32,12 +32,12 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
|
||||||
}
|
}
|
||||||
code, err := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
|
isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
|
||||||
if !isSuccessCode {
|
if !isSuccessCode {
|
||||||
Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code))
|
Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return isSuccessCode
|
return isSuccessCode
|
||||||
|
|
@ -54,12 +54,12 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
|
||||||
}
|
}
|
||||||
code, err := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
|
isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
|
||||||
if !isRedirectCode {
|
if !isRedirectCode {
|
||||||
Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code))
|
Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return isRedirectCode
|
return isRedirectCode
|
||||||
|
|
@ -76,12 +76,12 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values
|
||||||
}
|
}
|
||||||
code, err := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
isErrorCode := code >= http.StatusBadRequest
|
isErrorCode := code >= http.StatusBadRequest
|
||||||
if !isErrorCode {
|
if !isErrorCode {
|
||||||
Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code))
|
Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return isErrorCode
|
return isErrorCode
|
||||||
|
|
@ -98,12 +98,12 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va
|
||||||
}
|
}
|
||||||
code, err := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
successful := code == statuscode
|
successful := code == statuscode
|
||||||
if !successful {
|
if !successful {
|
||||||
Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code))
|
Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return successful
|
return successful
|
||||||
|
|
@ -113,7 +113,10 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va
|
||||||
// empty string if building a new request fails.
|
// empty string if building a new request fails.
|
||||||
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
|
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
|
if len(values) > 0 {
|
||||||
|
url += "?" + values.Encode()
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest(method, url, http.NoBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
@ -135,7 +138,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string,
|
||||||
|
|
||||||
contains := strings.Contains(body, fmt.Sprint(str))
|
contains := strings.Contains(body, fmt.Sprint(str))
|
||||||
if !contains {
|
if !contains {
|
||||||
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
|
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return contains
|
return contains
|
||||||
|
|
@ -155,7 +158,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin
|
||||||
|
|
||||||
contains := strings.Contains(body, fmt.Sprint(str))
|
contains := strings.Contains(body, fmt.Sprint(str))
|
||||||
if contains {
|
if contains {
|
||||||
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
|
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return !contains
|
return !contains
|
||||||
|
|
|
||||||
25
vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go
generated
vendored
Normal file
25
vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
//go:build testify_yaml_custom && !testify_yaml_fail && !testify_yaml_default
|
||||||
|
// +build testify_yaml_custom,!testify_yaml_fail,!testify_yaml_default
|
||||||
|
|
||||||
|
// Package yaml is an implementation of YAML functions that calls a pluggable implementation.
|
||||||
|
//
|
||||||
|
// This implementation is selected with the testify_yaml_custom build tag.
|
||||||
|
//
|
||||||
|
// go test -tags testify_yaml_custom
|
||||||
|
//
|
||||||
|
// This implementation can be used at build time to replace the default implementation
|
||||||
|
// to avoid linking with [gopkg.in/yaml.v3].
|
||||||
|
//
|
||||||
|
// In your test package:
|
||||||
|
//
|
||||||
|
// import assertYaml "github.com/stretchr/testify/assert/yaml"
|
||||||
|
//
|
||||||
|
// func init() {
|
||||||
|
// assertYaml.Unmarshal = func (in []byte, out interface{}) error {
|
||||||
|
// // ...
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
var Unmarshal func(in []byte, out interface{}) error
|
||||||
37
vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go
generated
vendored
Normal file
37
vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go
generated
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
//go:build !testify_yaml_fail && !testify_yaml_custom
|
||||||
|
// +build !testify_yaml_fail,!testify_yaml_custom
|
||||||
|
|
||||||
|
// Package yaml is just an indirection to handle YAML deserialization.
|
||||||
|
//
|
||||||
|
// This package is just an indirection that allows the builder to override the
|
||||||
|
// indirection with an alternative implementation of this package that uses
|
||||||
|
// another implementation of YAML deserialization. This allows to not either not
|
||||||
|
// use YAML deserialization at all, or to use another implementation than
|
||||||
|
// [gopkg.in/yaml.v3] (for example for license compatibility reasons, see [PR #1120]).
|
||||||
|
//
|
||||||
|
// Alternative implementations are selected using build tags:
|
||||||
|
//
|
||||||
|
// - testify_yaml_fail: [Unmarshal] always fails with an error
|
||||||
|
// - testify_yaml_custom: [Unmarshal] is a variable. Caller must initialize it
|
||||||
|
// before calling any of [github.com/stretchr/testify/assert.YAMLEq] or
|
||||||
|
// [github.com/stretchr/testify/assert.YAMLEqf].
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
//
|
||||||
|
// go test -tags testify_yaml_fail
|
||||||
|
//
|
||||||
|
// You can check with "go list" which implementation is linked:
|
||||||
|
//
|
||||||
|
// go list -f '{{.Imports}}' github.com/stretchr/testify/assert/yaml
|
||||||
|
// go list -tags testify_yaml_fail -f '{{.Imports}}' github.com/stretchr/testify/assert/yaml
|
||||||
|
// go list -tags testify_yaml_custom -f '{{.Imports}}' github.com/stretchr/testify/assert/yaml
|
||||||
|
//
|
||||||
|
// [PR #1120]: https://github.com/stretchr/testify/pull/1120
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import goyaml "gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
// Unmarshal is just a wrapper of [gopkg.in/yaml.v3.Unmarshal].
|
||||||
|
func Unmarshal(in []byte, out interface{}) error {
|
||||||
|
return goyaml.Unmarshal(in, out)
|
||||||
|
}
|
||||||
18
vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go
generated
vendored
Normal file
18
vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
//go:build testify_yaml_fail && !testify_yaml_custom && !testify_yaml_default
|
||||||
|
// +build testify_yaml_fail,!testify_yaml_custom,!testify_yaml_default
|
||||||
|
|
||||||
|
// Package yaml is an implementation of YAML functions that always fail.
|
||||||
|
//
|
||||||
|
// This implementation can be used at build time to replace the default implementation
|
||||||
|
// to avoid linking with [gopkg.in/yaml.v3]:
|
||||||
|
//
|
||||||
|
// go test -tags testify_yaml_fail
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var errNotImplemented = errors.New("YAML functions are not available (see https://pkg.go.dev/github.com/stretchr/testify/assert/yaml)")
|
||||||
|
|
||||||
|
func Unmarshal([]byte, interface{}) error {
|
||||||
|
return errNotImplemented
|
||||||
|
}
|
||||||
19
vendor/go.uber.org/atomic/.codecov.yml
generated
vendored
19
vendor/go.uber.org/atomic/.codecov.yml
generated
vendored
|
|
@ -1,19 +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
|
|
||||||
|
|
||||||
# Also update COVER_IGNORE_PKGS in the Makefile.
|
|
||||||
ignore:
|
|
||||||
- /internal/gen-atomicint/
|
|
||||||
- /internal/gen-valuewrapper/
|
|
||||||
15
vendor/go.uber.org/atomic/.gitignore
generated
vendored
15
vendor/go.uber.org/atomic/.gitignore
generated
vendored
|
|
@ -1,15 +0,0 @@
|
||||||
/bin
|
|
||||||
.DS_Store
|
|
||||||
/vendor
|
|
||||||
cover.html
|
|
||||||
cover.out
|
|
||||||
lint.log
|
|
||||||
|
|
||||||
# Binaries
|
|
||||||
*.test
|
|
||||||
|
|
||||||
# Profiling output
|
|
||||||
*.prof
|
|
||||||
|
|
||||||
# Output of fossa analyzer
|
|
||||||
/fossa
|
|
||||||
100
vendor/go.uber.org/atomic/CHANGELOG.md
generated
vendored
100
vendor/go.uber.org/atomic/CHANGELOG.md
generated
vendored
|
|
@ -1,100 +0,0 @@
|
||||||
# Changelog
|
|
||||||
All notable changes to this project will be documented in this file.
|
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
||||||
|
|
||||||
## [1.9.0] - 2021-07-15
|
|
||||||
### Added
|
|
||||||
- Add `Float64.Swap` to match int atomic operations.
|
|
||||||
- Add `atomic.Time` type for atomic operations on `time.Time` values.
|
|
||||||
|
|
||||||
[1.9.0]: https://github.com/uber-go/atomic/compare/v1.8.0...v1.9.0
|
|
||||||
|
|
||||||
## [1.8.0] - 2021-06-09
|
|
||||||
### Added
|
|
||||||
- Add `atomic.Uintptr` type for atomic operations on `uintptr` values.
|
|
||||||
- Add `atomic.UnsafePointer` type for atomic operations on `unsafe.Pointer` values.
|
|
||||||
|
|
||||||
[1.8.0]: https://github.com/uber-go/atomic/compare/v1.7.0...v1.8.0
|
|
||||||
|
|
||||||
## [1.7.0] - 2020-09-14
|
|
||||||
### Added
|
|
||||||
- Support JSON serialization and deserialization of primitive atomic types.
|
|
||||||
- Support Text marshalling and unmarshalling for string atomics.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Disallow incorrect comparison of atomic values in a non-atomic way.
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
- Remove dependency on `golang.org/x/{lint, tools}`.
|
|
||||||
|
|
||||||
[1.7.0]: https://github.com/uber-go/atomic/compare/v1.6.0...v1.7.0
|
|
||||||
|
|
||||||
## [1.6.0] - 2020-02-24
|
|
||||||
### Changed
|
|
||||||
- Drop library dependency on `golang.org/x/{lint, tools}`.
|
|
||||||
|
|
||||||
[1.6.0]: https://github.com/uber-go/atomic/compare/v1.5.1...v1.6.0
|
|
||||||
|
|
||||||
## [1.5.1] - 2019-11-19
|
|
||||||
- Fix bug where `Bool.CAS` and `Bool.Toggle` do work correctly together
|
|
||||||
causing `CAS` to fail even though the old value matches.
|
|
||||||
|
|
||||||
[1.5.1]: https://github.com/uber-go/atomic/compare/v1.5.0...v1.5.1
|
|
||||||
|
|
||||||
## [1.5.0] - 2019-10-29
|
|
||||||
### Changed
|
|
||||||
- With Go modules, only the `go.uber.org/atomic` import path is supported now.
|
|
||||||
If you need to use the old import path, please add a `replace` directive to
|
|
||||||
your `go.mod`.
|
|
||||||
|
|
||||||
[1.5.0]: https://github.com/uber-go/atomic/compare/v1.4.0...v1.5.0
|
|
||||||
|
|
||||||
## [1.4.0] - 2019-05-01
|
|
||||||
### Added
|
|
||||||
- Add `atomic.Error` type for atomic operations on `error` values.
|
|
||||||
|
|
||||||
[1.4.0]: https://github.com/uber-go/atomic/compare/v1.3.2...v1.4.0
|
|
||||||
|
|
||||||
## [1.3.2] - 2018-05-02
|
|
||||||
### Added
|
|
||||||
- Add `atomic.Duration` type for atomic operations on `time.Duration` values.
|
|
||||||
|
|
||||||
[1.3.2]: https://github.com/uber-go/atomic/compare/v1.3.1...v1.3.2
|
|
||||||
|
|
||||||
## [1.3.1] - 2017-11-14
|
|
||||||
### Fixed
|
|
||||||
- Revert optimization for `atomic.String.Store("")` which caused data races.
|
|
||||||
|
|
||||||
[1.3.1]: https://github.com/uber-go/atomic/compare/v1.3.0...v1.3.1
|
|
||||||
|
|
||||||
## [1.3.0] - 2017-11-13
|
|
||||||
### Added
|
|
||||||
- Add `atomic.Bool.CAS` for compare-and-swap semantics on bools.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Optimize `atomic.String.Store("")` by avoiding an allocation.
|
|
||||||
|
|
||||||
[1.3.0]: https://github.com/uber-go/atomic/compare/v1.2.0...v1.3.0
|
|
||||||
|
|
||||||
## [1.2.0] - 2017-04-12
|
|
||||||
### Added
|
|
||||||
- Shadow `atomic.Value` from `sync/atomic`.
|
|
||||||
|
|
||||||
[1.2.0]: https://github.com/uber-go/atomic/compare/v1.1.0...v1.2.0
|
|
||||||
|
|
||||||
## [1.1.0] - 2017-03-10
|
|
||||||
### Added
|
|
||||||
- Add atomic `Float64` type.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Support new `go.uber.org/atomic` import path.
|
|
||||||
|
|
||||||
[1.1.0]: https://github.com/uber-go/atomic/compare/v1.0.0...v1.1.0
|
|
||||||
|
|
||||||
## [1.0.0] - 2016-07-18
|
|
||||||
|
|
||||||
- Initial release.
|
|
||||||
|
|
||||||
[1.0.0]: https://github.com/uber-go/atomic/releases/tag/v1.0.0
|
|
||||||
19
vendor/go.uber.org/atomic/LICENSE.txt
generated
vendored
19
vendor/go.uber.org/atomic/LICENSE.txt
generated
vendored
|
|
@ -1,19 +0,0 @@
|
||||||
Copyright (c) 2016 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.
|
|
||||||
79
vendor/go.uber.org/atomic/Makefile
generated
vendored
79
vendor/go.uber.org/atomic/Makefile
generated
vendored
|
|
@ -1,79 +0,0 @@
|
||||||
# Directory to place `go install`ed binaries into.
|
|
||||||
export GOBIN ?= $(shell pwd)/bin
|
|
||||||
|
|
||||||
GOLINT = $(GOBIN)/golint
|
|
||||||
GEN_ATOMICINT = $(GOBIN)/gen-atomicint
|
|
||||||
GEN_ATOMICWRAPPER = $(GOBIN)/gen-atomicwrapper
|
|
||||||
STATICCHECK = $(GOBIN)/staticcheck
|
|
||||||
|
|
||||||
GO_FILES ?= $(shell find . '(' -path .git -o -path vendor ')' -prune -o -name '*.go' -print)
|
|
||||||
|
|
||||||
# Also update ignore section in .codecov.yml.
|
|
||||||
COVER_IGNORE_PKGS = \
|
|
||||||
go.uber.org/atomic/internal/gen-atomicint \
|
|
||||||
go.uber.org/atomic/internal/gen-atomicwrapper
|
|
||||||
|
|
||||||
.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)
|
|
||||||
|
|
||||||
$(GOLINT):
|
|
||||||
cd tools && go install golang.org/x/lint/golint
|
|
||||||
|
|
||||||
$(STATICCHECK):
|
|
||||||
cd tools && go install honnef.co/go/tools/cmd/staticcheck
|
|
||||||
|
|
||||||
$(GEN_ATOMICWRAPPER): $(wildcard ./internal/gen-atomicwrapper/*)
|
|
||||||
go build -o $@ ./internal/gen-atomicwrapper
|
|
||||||
|
|
||||||
$(GEN_ATOMICINT): $(wildcard ./internal/gen-atomicint/*)
|
|
||||||
go build -o $@ ./internal/gen-atomicint
|
|
||||||
|
|
||||||
.PHONY: golint
|
|
||||||
golint: $(GOLINT)
|
|
||||||
$(GOLINT) ./...
|
|
||||||
|
|
||||||
.PHONY: staticcheck
|
|
||||||
staticcheck: $(STATICCHECK)
|
|
||||||
$(STATICCHECK) ./...
|
|
||||||
|
|
||||||
.PHONY: lint
|
|
||||||
lint: gofmt golint staticcheck generatenodirty
|
|
||||||
|
|
||||||
# comma separated list of packages to consider for code coverage.
|
|
||||||
COVER_PKG = $(shell \
|
|
||||||
go list -find ./... | \
|
|
||||||
grep -v $(foreach pkg,$(COVER_IGNORE_PKGS),-e "^$(pkg)$$") | \
|
|
||||||
paste -sd, -)
|
|
||||||
|
|
||||||
.PHONY: cover
|
|
||||||
cover:
|
|
||||||
go test -coverprofile=cover.out -coverpkg $(COVER_PKG) -v ./...
|
|
||||||
go tool cover -html=cover.out -o cover.html
|
|
||||||
|
|
||||||
.PHONY: generate
|
|
||||||
generate: $(GEN_ATOMICINT) $(GEN_ATOMICWRAPPER)
|
|
||||||
go generate ./...
|
|
||||||
|
|
||||||
.PHONY: generatenodirty
|
|
||||||
generatenodirty:
|
|
||||||
@[ -z "$$(git status --porcelain)" ] || ( \
|
|
||||||
echo "Working tree is dirty. Commit your changes first."; \
|
|
||||||
git status; \
|
|
||||||
exit 1 )
|
|
||||||
@make generate
|
|
||||||
@status=$$(git status --porcelain); \
|
|
||||||
[ -z "$$status" ] || ( \
|
|
||||||
echo "Working tree is dirty after `make generate`:"; \
|
|
||||||
echo "$$status"; \
|
|
||||||
echo "Please ensure that the generated code is up-to-date." )
|
|
||||||
63
vendor/go.uber.org/atomic/README.md
generated
vendored
63
vendor/go.uber.org/atomic/README.md
generated
vendored
|
|
@ -1,63 +0,0 @@
|
||||||
# atomic [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] [![Go Report Card][reportcard-img]][reportcard]
|
|
||||||
|
|
||||||
Simple wrappers for primitive types to enforce atomic access.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
```shell
|
|
||||||
$ go get -u go.uber.org/atomic@v1
|
|
||||||
```
|
|
||||||
|
|
||||||
### Legacy Import Path
|
|
||||||
|
|
||||||
As of v1.5.0, the import path `go.uber.org/atomic` is the only supported way
|
|
||||||
of using this package. If you are using Go modules, this package will fail to
|
|
||||||
compile with the legacy import path path `github.com/uber-go/atomic`.
|
|
||||||
|
|
||||||
We recommend migrating your code to the new import path but if you're unable
|
|
||||||
to do so, or if your dependencies are still using the old import path, you
|
|
||||||
will have to add a `replace` directive to your `go.mod` file downgrading the
|
|
||||||
legacy import path to an older version.
|
|
||||||
|
|
||||||
```
|
|
||||||
replace github.com/uber-go/atomic => github.com/uber-go/atomic v1.4.0
|
|
||||||
```
|
|
||||||
|
|
||||||
You can do so automatically by running the following command.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
$ go mod edit -replace github.com/uber-go/atomic=github.com/uber-go/atomic@v1.4.0
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
The standard library's `sync/atomic` is powerful, but it's easy to forget which
|
|
||||||
variables must be accessed atomically. `go.uber.org/atomic` preserves all the
|
|
||||||
functionality of the standard library, but wraps the primitive types to
|
|
||||||
provide a safer, more convenient API.
|
|
||||||
|
|
||||||
```go
|
|
||||||
var atom atomic.Uint32
|
|
||||||
atom.Store(42)
|
|
||||||
atom.Sub(2)
|
|
||||||
atom.CAS(40, 11)
|
|
||||||
```
|
|
||||||
|
|
||||||
See the [documentation][doc] for a complete API specification.
|
|
||||||
|
|
||||||
## Development Status
|
|
||||||
|
|
||||||
Stable.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Released under the [MIT License](LICENSE.txt).
|
|
||||||
|
|
||||||
[doc-img]: https://godoc.org/github.com/uber-go/atomic?status.svg
|
|
||||||
[doc]: https://godoc.org/go.uber.org/atomic
|
|
||||||
[ci-img]: https://github.com/uber-go/atomic/actions/workflows/go.yml/badge.svg
|
|
||||||
[ci]: https://github.com/uber-go/atomic/actions/workflows/go.yml
|
|
||||||
[cov-img]: https://codecov.io/gh/uber-go/atomic/branch/master/graph/badge.svg
|
|
||||||
[cov]: https://codecov.io/gh/uber-go/atomic
|
|
||||||
[reportcard-img]: https://goreportcard.com/badge/go.uber.org/atomic
|
|
||||||
[reportcard]: https://goreportcard.com/report/go.uber.org/atomic
|
|
||||||
81
vendor/go.uber.org/atomic/bool.go
generated
vendored
81
vendor/go.uber.org/atomic/bool.go
generated
vendored
|
|
@ -1,81 +0,0 @@
|
||||||
// @generated Code generated by gen-atomicwrapper.
|
|
||||||
|
|
||||||
// Copyright (c) 2020-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.
|
|
||||||
|
|
||||||
package atomic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bool is an atomic type-safe wrapper for bool values.
|
|
||||||
type Bool struct {
|
|
||||||
_ nocmp // disallow non-atomic comparison
|
|
||||||
|
|
||||||
v Uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
var _zeroBool bool
|
|
||||||
|
|
||||||
// NewBool creates a new Bool.
|
|
||||||
func NewBool(val bool) *Bool {
|
|
||||||
x := &Bool{}
|
|
||||||
if val != _zeroBool {
|
|
||||||
x.Store(val)
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load atomically loads the wrapped bool.
|
|
||||||
func (x *Bool) Load() bool {
|
|
||||||
return truthy(x.v.Load())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store atomically stores the passed bool.
|
|
||||||
func (x *Bool) Store(val bool) {
|
|
||||||
x.v.Store(boolToInt(val))
|
|
||||||
}
|
|
||||||
|
|
||||||
// CAS is an atomic compare-and-swap for bool values.
|
|
||||||
func (x *Bool) CAS(old, new bool) (swapped bool) {
|
|
||||||
return x.v.CAS(boolToInt(old), boolToInt(new))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap atomically stores the given bool and returns the old
|
|
||||||
// value.
|
|
||||||
func (x *Bool) Swap(val bool) (old bool) {
|
|
||||||
return truthy(x.v.Swap(boolToInt(val)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON encodes the wrapped bool into JSON.
|
|
||||||
func (x *Bool) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(x.Load())
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON decodes a bool from JSON.
|
|
||||||
func (x *Bool) UnmarshalJSON(b []byte) error {
|
|
||||||
var v bool
|
|
||||||
if err := json.Unmarshal(b, &v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
x.Store(v)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue