mirror of
https://github.com/podman-container-tools/podman.git
synced 2026-10-16 02:47:41 +00:00
Merge pull request #24447 from Luap99/vendor
vendor latest c/{buildah,common,image,storage}
This commit is contained in:
commit
6598a36e6b
158 changed files with 6405 additions and 3079 deletions
27
go.mod
27
go.mod
|
|
@ -13,15 +13,15 @@ require (
|
|||
github.com/checkpoint-restore/checkpointctl v1.3.0
|
||||
github.com/checkpoint-restore/go-criu/v7 v7.2.0
|
||||
github.com/containernetworking/plugins v1.5.1
|
||||
github.com/containers/buildah v1.37.1-0.20241018144937-2551c8f3d110
|
||||
github.com/containers/common v0.60.1-0.20241018183244-7e6f2b4d6de7
|
||||
github.com/containers/buildah v1.37.1-0.20241104213057-0dc5f958934a
|
||||
github.com/containers/common v0.60.1-0.20241106101802-8130e31c0832
|
||||
github.com/containers/conmon v2.0.20+incompatible
|
||||
github.com/containers/gvisor-tap-vsock v0.8.0
|
||||
github.com/containers/image/v5 v5.32.3-0.20241016192323-a66152c1cdf6
|
||||
github.com/containers/image/v5 v5.32.3-0.20241105183637-59417aed3db1
|
||||
github.com/containers/libhvee v0.7.1
|
||||
github.com/containers/ocicrypt v1.2.0
|
||||
github.com/containers/psgo v1.9.0
|
||||
github.com/containers/storage v1.55.1-0.20241017155235-4db236377c55
|
||||
github.com/containers/storage v1.55.2-0.20241104201357-ad5f2a48e9e9
|
||||
github.com/containers/winquit v1.1.0
|
||||
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09
|
||||
github.com/coreos/stream-metadata-go v0.4.4
|
||||
|
|
@ -89,7 +89,7 @@ require (
|
|||
require (
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
github.com/Microsoft/hcsshim v0.12.7 // indirect
|
||||
github.com/Microsoft/hcsshim v0.12.9 // indirect
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
|
||||
github.com/aead/serpent v0.0.0-20160714141033-fba169763ea6 // indirect
|
||||
|
|
@ -99,7 +99,8 @@ require (
|
|||
github.com/chenzhuoyu/iasm v0.9.1 // indirect
|
||||
github.com/chzyer/readline v1.5.1 // indirect
|
||||
github.com/containerd/cgroups/v3 v3.0.3 // indirect
|
||||
github.com/containerd/errdefs v0.1.0 // indirect
|
||||
github.com/containerd/errdefs v0.3.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/platforms v0.2.1 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
|
||||
|
|
@ -117,7 +118,7 @@ require (
|
|||
github.com/docker/docker-credential-helpers v0.8.2 // indirect
|
||||
github.com/ebitengine/purego v0.8.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/fsouza/go-dockerclient v1.12.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
|
|
@ -170,11 +171,11 @@ require (
|
|||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||
github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/buildkit v0.16.0 // indirect
|
||||
github.com/moby/buildkit v0.17.0 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.2 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/moby/sys/sequential v0.6.0 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
|
|
@ -184,7 +185,8 @@ require (
|
|||
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/sftp v1.13.6 // indirect
|
||||
github.com/pkg/sftp v1.13.7 // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/proglottis/gpgme v0.1.3 // indirect
|
||||
|
|
@ -195,6 +197,7 @@ require (
|
|||
github.com/sigstore/fulcio v1.6.4 // indirect
|
||||
github.com/sigstore/rekor v1.3.6 // indirect
|
||||
github.com/sigstore/sigstore v1.8.9 // indirect
|
||||
github.com/skeema/knownhosts v1.3.0 // indirect
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect
|
||||
github.com/sylabs/sif/v2 v2.19.1 // indirect
|
||||
|
|
@ -222,8 +225,8 @@ require (
|
|||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
golang.org/x/tools v0.26.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240823204242-4ba0660f739c // indirect
|
||||
google.golang.org/grpc v1.66.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/grpc v1.67.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect
|
||||
|
|
|
|||
61
go.sum
61
go.sum
|
|
@ -12,8 +12,8 @@ github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0
|
|||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/Microsoft/hcsshim v0.12.7 h1:MP6R1spmjxTE4EU4J3YsrTxn8CjvN9qwjTKJXldFaRg=
|
||||
github.com/Microsoft/hcsshim v0.12.7/go.mod h1:HPbAuJ9BvQYYZbB4yEQcyGIsTP5L4yHKeO9XO149AEM=
|
||||
github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg=
|
||||
github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
||||
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
||||
|
|
@ -63,8 +63,10 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
|||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
|
||||
github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=
|
||||
github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM=
|
||||
github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0=
|
||||
github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4=
|
||||
github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
|
||||
|
|
@ -77,16 +79,16 @@ github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8F
|
|||
github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M=
|
||||
github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ=
|
||||
github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM=
|
||||
github.com/containers/buildah v1.37.1-0.20241018144937-2551c8f3d110 h1:YcrjUM1CwDTEnaPHgpVmjid/R3zAVXRRHcgknQsajlI=
|
||||
github.com/containers/buildah v1.37.1-0.20241018144937-2551c8f3d110/go.mod h1:SVyERMThmMXGTdle/9MdRuX2Ae7eVY9qDVartYXIx7E=
|
||||
github.com/containers/common v0.60.1-0.20241018183244-7e6f2b4d6de7 h1:EFzq3sjwy0vBr9RoZPzTbtoGZR4hoZsmgxuIs5Uc5FA=
|
||||
github.com/containers/common v0.60.1-0.20241018183244-7e6f2b4d6de7/go.mod h1:T8vpUWd7AspK7CMELf/c+NCZB6bKrRkLriRCspdFGyQ=
|
||||
github.com/containers/buildah v1.37.1-0.20241104213057-0dc5f958934a h1:0ZkxeT5b46pyfvwnplL3yxI4XscQXFoXWVpn619qIYA=
|
||||
github.com/containers/buildah v1.37.1-0.20241104213057-0dc5f958934a/go.mod h1:zyzg/OC40RZUl6NxvPkBHjaPHKFNGsAMyd8JrbseNwE=
|
||||
github.com/containers/common v0.60.1-0.20241106101802-8130e31c0832 h1:bu0QHPZns2JbbaEArh+Khs9ajAoX8/biSdBYWAD+/Ec=
|
||||
github.com/containers/common v0.60.1-0.20241106101802-8130e31c0832/go.mod h1:7MOGFZ12UTBYSPxvQpBBJHTbHho0qizdMR6MlDZwGBA=
|
||||
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
|
||||
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
|
||||
github.com/containers/gvisor-tap-vsock v0.8.0 h1:Z8ZEWb+Lio0d+lXexONdUWT4rm9lF91vH0g3ARnMy7o=
|
||||
github.com/containers/gvisor-tap-vsock v0.8.0/go.mod h1:LVwnMiNvhxyGfhaMEQcXKJhNnN4h8woB9U3wf8rYOPc=
|
||||
github.com/containers/image/v5 v5.32.3-0.20241016192323-a66152c1cdf6 h1:kDsMVMhEFmWFLN6QEn0ul0MbpXCxLiIL5pqxADOqB8g=
|
||||
github.com/containers/image/v5 v5.32.3-0.20241016192323-a66152c1cdf6/go.mod h1:Ulwf/jQO4757C/uOJyNiZ10dRiXRwVnyhF9wYFno3GQ=
|
||||
github.com/containers/image/v5 v5.32.3-0.20241105183637-59417aed3db1 h1:QOxFuqs21puYp9EnMaAEMgygtSORUYKn0felPS4rXa0=
|
||||
github.com/containers/image/v5 v5.32.3-0.20241105183637-59417aed3db1/go.mod h1:qsONoo3ZvAnrwa2+49bY6m3ewtJO5+A1AaELCtGuDKc=
|
||||
github.com/containers/libhvee v0.7.1 h1:dWGF5GLq9DZvXo3P8aDp3cNieL5eCaSell4UmeA/jY4=
|
||||
github.com/containers/libhvee v0.7.1/go.mod h1:fRKB3AyIqHMvq6xaeYhTpckM2cdoq0oecolyoiuLP7M=
|
||||
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=
|
||||
|
|
@ -97,8 +99,8 @@ github.com/containers/ocicrypt v1.2.0 h1:X14EgRK3xNFvJEfI5O4Qn4T3E25ANudSOZz/sir
|
|||
github.com/containers/ocicrypt v1.2.0/go.mod h1:ZNviigQajtdlxIZGibvblVuIFBKIuUI2M0QM12SD31U=
|
||||
github.com/containers/psgo v1.9.0 h1:eJ74jzSaCHnWt26OlKZROSyUyRcGDf+gYBdXnxrMW4g=
|
||||
github.com/containers/psgo v1.9.0/go.mod h1:0YoluUm43Mz2UnBIh1P+6V6NWcbpTL5uRtXyOcH0B5A=
|
||||
github.com/containers/storage v1.55.1-0.20241017155235-4db236377c55 h1:lqNa07muv5Gkfyw8aivrLwy8cCZgewHN2OxB0cuNNyY=
|
||||
github.com/containers/storage v1.55.1-0.20241017155235-4db236377c55/go.mod h1:iq56tOFXnj8kA8DAytN28fhUm77eKLWrashQrImaqBs=
|
||||
github.com/containers/storage v1.55.2-0.20241104201357-ad5f2a48e9e9 h1:qB+KgM08F5GEGzdzrWLUHs41NU6d/+TUMEP2xMeyjGs=
|
||||
github.com/containers/storage v1.55.2-0.20241104201357-ad5f2a48e9e9/go.mod h1:c6WKowcAlED/DkWGNuL9bvGYqIWCVy7isRMdCSKWNjk=
|
||||
github.com/containers/winquit v1.1.0 h1:jArun04BNDQvt2W0Y78kh9TazN2EIEMG5Im6/JY7+pE=
|
||||
github.com/containers/winquit v1.1.0/go.mod h1:PsPeZlnbkmGGIToMPHF1zhWjBUkd8aHjMOr/vFcPxw8=
|
||||
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
|
||||
|
|
@ -161,8 +163,8 @@ github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4Nij
|
|||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fsouza/go-dockerclient v1.12.0 h1:S2f2crEUbBNCFiF06kR/GvioEB8EMsb3Td/bpawD+aU=
|
||||
github.com/fsouza/go-dockerclient v1.12.0/go.mod h1:YWUtjg8japrqD/80L98nTtCoxQFp5B5wrSsnyeB5lFo=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
|
|
@ -359,8 +361,8 @@ github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPn
|
|||
github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
|
||||
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/moby/buildkit v0.16.0 h1:wOVBj1o5YNVad/txPQNXUXdelm7Hs/i0PUFjzbK0VKE=
|
||||
github.com/moby/buildkit v0.16.0/go.mod h1:Xqx/5GlrqE1yIRORk0NSCVDFpQAU1WjlT6KHYZdisIQ=
|
||||
github.com/moby/buildkit v0.17.0 h1:ZA/4AxwBbve1f3ZaNNJQiCBtTV62R6YweWNwq4A+sTc=
|
||||
github.com/moby/buildkit v0.17.0/go.mod h1:ru8NFyDHD8HbuKaLXJIjK9nr3x6FZR+IWjtF07S+wdM=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||
|
|
@ -369,8 +371,8 @@ github.com/moby/sys/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jR
|
|||
github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
|
||||
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
|
||||
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
|
||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
|
||||
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
|
||||
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||
|
|
@ -418,8 +420,10 @@ github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ
|
|||
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
|
||||
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
||||
github.com/pkg/sftp v1.13.7 h1:uv+I3nNJvlKZIQGSr8JVQLNHFU9YhhNpvC14Y6KgmSM=
|
||||
github.com/pkg/sftp v1.13.7/go.mod h1:KMKI0t3T6hfA+lTR/ssZdunHo+uwq7ghoN09/FSu3DY=
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
|
||||
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
|
|
@ -464,6 +468,8 @@ github.com/sigstore/sigstore v1.8.9 h1:NiUZIVWywgYuVTxXmRoTT4O4QAGiTEKup4N1wdxFa
|
|||
github.com/sigstore/sigstore v1.8.9/go.mod h1:d9ZAbNDs8JJfxJrYmulaTazU3Pwr8uLL9+mii4BNR3w=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
|
||||
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
|
|
@ -573,7 +579,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
|
|
@ -602,7 +608,6 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
|
|
@ -646,21 +651,21 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
|
|
@ -693,15 +698,15 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY
|
|||
google.golang.org/genproto v0.0.0-20240823204242-4ba0660f739c h1:TYOEhrQMrNDTAd2rX9m+WgGr8Ku6YNuj1D7OX6rWSok=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240823204242-4ba0660f739c h1:Kqjm4WpoWvwhMPcrAczoTyMySQmYa9Wy2iL6Con4zn8=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240823204242-4ba0660f739c/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
|
||||
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
|
||||
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
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=
|
||||
|
|
|
|||
|
|
@ -177,11 +177,13 @@ if [[ -n $do_checkout ]]; then
|
|||
# the set of patches
|
||||
(set -x;git tag $BASE_TAG)
|
||||
|
||||
# Build buildah and the copy helper
|
||||
# Build buildah and the copy and inet helpers
|
||||
failhint="error building buildah. This should never happen."
|
||||
(set -x;make bin/buildah)
|
||||
failhint="error building buildah's copy helper. This should never happen."
|
||||
(set -x;make bin/copy)
|
||||
failhint="error building buildah's inet helper. This should never happen."
|
||||
(set -x;make bin/inet)
|
||||
|
||||
# The upcoming patch may fail. Before we try it, create a helper script
|
||||
# for a developer to push a new set of diffs to podman-land.
|
||||
|
|
@ -259,5 +261,6 @@ review the test failure and double-check your changes.
|
|||
REMOTE=$REMOTE \
|
||||
BUILDAH_BINARY=$(pwd)/bin/buildah \
|
||||
COPY_BINARY=$(pwd)/bin/copy \
|
||||
INET_BINARY=$(pwd)/bin/inet \
|
||||
bats "${bats_filter[@]}" tests/bud.bats)
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -534,6 +534,11 @@ json-file | f
|
|||
expect="$output"
|
||||
TZ=Pacific/Chatham run_podman run --rm --tz=local $IMAGE date -Iseconds -r $testfile
|
||||
is "$output" "$expect" "podman run with --tz=local, matches host"
|
||||
|
||||
# Force a TZDIR env as local should not try to use the TZDIR at all, #23550.
|
||||
# This used to fail with: stat /usr/share/zoneinfo/local: no such file or directory.
|
||||
TZDIR=/usr/share/zoneinfo run_podman run --rm --tz=local $IMAGE date -Iseconds -r $testfile
|
||||
is "$output" "$expect" "podman run with --tz=local ignored TZDIR"
|
||||
}
|
||||
|
||||
# bats test_tags=ci:parallel
|
||||
|
|
|
|||
2
vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go
generated
vendored
2
vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go
generated
vendored
|
|
@ -29,7 +29,7 @@ const (
|
|||
)
|
||||
|
||||
func (es EndpointState) String() string {
|
||||
return [...]string{"Uninitialized", "Attached", "AttachedSharing", "Detached", "Degraded", "Destroyed"}[es]
|
||||
return [...]string{"Uninitialized", "Created", "Attached", "AttachedSharing", "Detached", "Degraded", "Destroyed"}[es]
|
||||
}
|
||||
|
||||
// HNSEndpoint represents a network endpoint in HNS
|
||||
|
|
|
|||
11
vendor/github.com/Microsoft/hcsshim/internal/jobobject/jobobject.go
generated
vendored
11
vendor/github.com/Microsoft/hcsshim/internal/jobobject/jobobject.go
generated
vendored
|
|
@ -188,7 +188,7 @@ func Open(ctx context.Context, options *Options) (_ *JobObject, err error) {
|
|||
return nil, winapi.RtlNtStatusToDosError(status)
|
||||
}
|
||||
} else {
|
||||
jobHandle, err = winapi.OpenJobObject(winapi.JOB_OBJECT_ALL_ACCESS, 0, unicodeJobName.Buffer)
|
||||
jobHandle, err = winapi.OpenJobObject(winapi.JOB_OBJECT_ALL_ACCESS, false, unicodeJobName.Buffer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -523,12 +523,9 @@ func (job *JobObject) ApplyFileBinding(root, target string, readOnly bool) error
|
|||
func isJobSilo(h windows.Handle) bool {
|
||||
// None of the information from the structure that this info class expects will be used, this is just used as
|
||||
// the call will fail if the job hasn't been upgraded to a silo so we can use this to tell when we open a job
|
||||
// if it's a silo or not. Because none of the info matters simply define a dummy struct with the size that the call
|
||||
// expects which is 16 bytes.
|
||||
type isSiloObj struct {
|
||||
_ [16]byte
|
||||
}
|
||||
var siloInfo isSiloObj
|
||||
// if it's a silo or not. We still need to define the struct layout as expected by Win32, else the struct
|
||||
// alignment might be different and the call will fail.
|
||||
var siloInfo winapi.SILOOBJECT_BASIC_INFORMATION
|
||||
err := winapi.QueryInformationJobObject(
|
||||
h,
|
||||
winapi.JobObjectSiloBasicInformation,
|
||||
|
|
|
|||
2
vendor/github.com/Microsoft/hcsshim/internal/oc/errors.go
generated
vendored
2
vendor/github.com/Microsoft/hcsshim/internal/oc/errors.go
generated
vendored
|
|
@ -6,7 +6,7 @@ import (
|
|||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/containerd/errdefs"
|
||||
errdefs "github.com/containerd/errdefs/pkg/errgrpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
|
|
|||
19
vendor/github.com/Microsoft/hcsshim/internal/winapi/jobobject.go
generated
vendored
19
vendor/github.com/Microsoft/hcsshim/internal/winapi/jobobject.go
generated
vendored
|
|
@ -28,7 +28,7 @@ const (
|
|||
// https://docs.microsoft.com/en-us/windows/win32/procthread/job-object-security-and-access-rights
|
||||
const (
|
||||
JOB_OBJECT_QUERY = 0x0004
|
||||
JOB_OBJECT_ALL_ACCESS = 0x1F001F
|
||||
JOB_OBJECT_ALL_ACCESS = 0x1F003F
|
||||
)
|
||||
|
||||
// IO limit flags
|
||||
|
|
@ -160,6 +160,21 @@ type JOBOBJECT_ASSOCIATE_COMPLETION_PORT struct {
|
|||
CompletionPort windows.Handle
|
||||
}
|
||||
|
||||
// typedef struct _SILOOBJECT_BASIC_INFORMATION {
|
||||
// DWORD SiloId;
|
||||
// DWORD SiloParentId;
|
||||
// DWORD NumberOfProcesses;
|
||||
// BOOLEAN IsInServerSilo;
|
||||
// BYTE Reserved[3];
|
||||
// } SILOOBJECT_BASIC_INFORMATION, *PSILOOBJECT_BASIC_INFORMATION;
|
||||
type SILOOBJECT_BASIC_INFORMATION struct {
|
||||
SiloID uint32
|
||||
SiloParentID uint32
|
||||
NumberOfProcesses uint32
|
||||
IsInServerSilo bool
|
||||
Reserved [3]uint8
|
||||
}
|
||||
|
||||
// BOOL IsProcessInJob(
|
||||
// HANDLE ProcessHandle,
|
||||
// HANDLE JobHandle,
|
||||
|
|
@ -184,7 +199,7 @@ type JOBOBJECT_ASSOCIATE_COMPLETION_PORT struct {
|
|||
// LPCWSTR lpName
|
||||
// );
|
||||
//
|
||||
//sys OpenJobObject(desiredAccess uint32, inheritHandle int32, lpName *uint16) (handle windows.Handle, err error) = kernel32.OpenJobObjectW
|
||||
//sys OpenJobObject(desiredAccess uint32, inheritHandle bool, lpName *uint16) (handle windows.Handle, err error) = kernel32.OpenJobObjectW
|
||||
|
||||
// DWORD SetIoRateControlInformationJobObject(
|
||||
// HANDLE hJob,
|
||||
|
|
|
|||
8
vendor/github.com/Microsoft/hcsshim/internal/winapi/zsyscall_windows.go
generated
vendored
8
vendor/github.com/Microsoft/hcsshim/internal/winapi/zsyscall_windows.go
generated
vendored
|
|
@ -470,8 +470,12 @@ func LocalFree(ptr uintptr) {
|
|||
return
|
||||
}
|
||||
|
||||
func OpenJobObject(desiredAccess uint32, inheritHandle int32, lpName *uint16) (handle windows.Handle, err error) {
|
||||
r0, _, e1 := syscall.SyscallN(procOpenJobObjectW.Addr(), uintptr(desiredAccess), uintptr(inheritHandle), uintptr(unsafe.Pointer(lpName)))
|
||||
func OpenJobObject(desiredAccess uint32, inheritHandle bool, lpName *uint16) (handle windows.Handle, err error) {
|
||||
var _p0 uint32
|
||||
if inheritHandle {
|
||||
_p0 = 1
|
||||
}
|
||||
r0, _, e1 := syscall.SyscallN(procOpenJobObjectW.Addr(), uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(lpName)))
|
||||
handle = windows.Handle(r0)
|
||||
if handle == 0 {
|
||||
err = errnoErr(e1)
|
||||
|
|
|
|||
439
vendor/github.com/containerd/errdefs/errors.go
generated
vendored
439
vendor/github.com/containerd/errdefs/errors.go
generated
vendored
|
|
@ -21,9 +21,6 @@
|
|||
//
|
||||
// To detect an error class, use the IsXXX functions to tell whether an error
|
||||
// is of a certain type.
|
||||
//
|
||||
// The functions ToGRPC and FromGRPC can be used to map server-side and
|
||||
// client-side errors to the correct types.
|
||||
package errdefs
|
||||
|
||||
import (
|
||||
|
|
@ -36,57 +33,411 @@ import (
|
|||
// Packages should return errors of these types when they want to instruct a
|
||||
// client to take a particular action.
|
||||
//
|
||||
// For the most part, we just try to provide local grpc errors. Most conditions
|
||||
// map very well to those defined by grpc.
|
||||
// These errors map closely to grpc errors.
|
||||
var (
|
||||
ErrUnknown = errors.New("unknown") // used internally to represent a missed mapping.
|
||||
ErrInvalidArgument = errors.New("invalid argument")
|
||||
ErrNotFound = errors.New("not found")
|
||||
ErrAlreadyExists = errors.New("already exists")
|
||||
ErrFailedPrecondition = errors.New("failed precondition")
|
||||
ErrUnavailable = errors.New("unavailable")
|
||||
ErrNotImplemented = errors.New("not implemented") // represents not supported and unimplemented
|
||||
ErrUnknown = errUnknown{}
|
||||
ErrInvalidArgument = errInvalidArgument{}
|
||||
ErrNotFound = errNotFound{}
|
||||
ErrAlreadyExists = errAlreadyExists{}
|
||||
ErrPermissionDenied = errPermissionDenied{}
|
||||
ErrResourceExhausted = errResourceExhausted{}
|
||||
ErrFailedPrecondition = errFailedPrecondition{}
|
||||
ErrConflict = errConflict{}
|
||||
ErrNotModified = errNotModified{}
|
||||
ErrAborted = errAborted{}
|
||||
ErrOutOfRange = errOutOfRange{}
|
||||
ErrNotImplemented = errNotImplemented{}
|
||||
ErrInternal = errInternal{}
|
||||
ErrUnavailable = errUnavailable{}
|
||||
ErrDataLoss = errDataLoss{}
|
||||
ErrUnauthenticated = errUnauthorized{}
|
||||
)
|
||||
|
||||
// IsInvalidArgument returns true if the error is due to an invalid argument
|
||||
func IsInvalidArgument(err error) bool {
|
||||
return errors.Is(err, ErrInvalidArgument)
|
||||
}
|
||||
|
||||
// IsNotFound returns true if the error is due to a missing object
|
||||
func IsNotFound(err error) bool {
|
||||
return errors.Is(err, ErrNotFound)
|
||||
}
|
||||
|
||||
// IsAlreadyExists returns true if the error is due to an already existing
|
||||
// metadata item
|
||||
func IsAlreadyExists(err error) bool {
|
||||
return errors.Is(err, ErrAlreadyExists)
|
||||
}
|
||||
|
||||
// IsFailedPrecondition returns true if an operation could not proceed to the
|
||||
// lack of a particular condition
|
||||
func IsFailedPrecondition(err error) bool {
|
||||
return errors.Is(err, ErrFailedPrecondition)
|
||||
}
|
||||
|
||||
// IsUnavailable returns true if the error is due to a resource being unavailable
|
||||
func IsUnavailable(err error) bool {
|
||||
return errors.Is(err, ErrUnavailable)
|
||||
}
|
||||
|
||||
// IsNotImplemented returns true if the error is due to not being implemented
|
||||
func IsNotImplemented(err error) bool {
|
||||
return errors.Is(err, ErrNotImplemented)
|
||||
// cancelled maps to Moby's "ErrCancelled"
|
||||
type cancelled interface {
|
||||
Cancelled()
|
||||
}
|
||||
|
||||
// IsCanceled returns true if the error is due to `context.Canceled`.
|
||||
func IsCanceled(err error) bool {
|
||||
return errors.Is(err, context.Canceled)
|
||||
return errors.Is(err, context.Canceled) || isInterface[cancelled](err)
|
||||
}
|
||||
|
||||
type errUnknown struct{}
|
||||
|
||||
func (errUnknown) Error() string { return "unknown" }
|
||||
|
||||
func (errUnknown) Unknown() {}
|
||||
|
||||
func (e errUnknown) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
// unknown maps to Moby's "ErrUnknown"
|
||||
type unknown interface {
|
||||
Unknown()
|
||||
}
|
||||
|
||||
// IsUnknown returns true if the error is due to an unknown error,
|
||||
// unhandled condition or unexpected response.
|
||||
func IsUnknown(err error) bool {
|
||||
return errors.Is(err, errUnknown{}) || isInterface[unknown](err)
|
||||
}
|
||||
|
||||
type errInvalidArgument struct{}
|
||||
|
||||
func (errInvalidArgument) Error() string { return "invalid argument" }
|
||||
|
||||
func (errInvalidArgument) InvalidParameter() {}
|
||||
|
||||
func (e errInvalidArgument) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
// invalidParameter maps to Moby's "ErrInvalidParameter"
|
||||
type invalidParameter interface {
|
||||
InvalidParameter()
|
||||
}
|
||||
|
||||
// IsInvalidArgument returns true if the error is due to an invalid argument
|
||||
func IsInvalidArgument(err error) bool {
|
||||
return errors.Is(err, ErrInvalidArgument) || isInterface[invalidParameter](err)
|
||||
}
|
||||
|
||||
// deadlineExceed maps to Moby's "ErrDeadline"
|
||||
type deadlineExceeded interface {
|
||||
DeadlineExceeded()
|
||||
}
|
||||
|
||||
// IsDeadlineExceeded returns true if the error is due to
|
||||
// `context.DeadlineExceeded`.
|
||||
func IsDeadlineExceeded(err error) bool {
|
||||
return errors.Is(err, context.DeadlineExceeded)
|
||||
return errors.Is(err, context.DeadlineExceeded) || isInterface[deadlineExceeded](err)
|
||||
}
|
||||
|
||||
type errNotFound struct{}
|
||||
|
||||
func (errNotFound) Error() string { return "not found" }
|
||||
|
||||
func (errNotFound) NotFound() {}
|
||||
|
||||
func (e errNotFound) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
// notFound maps to Moby's "ErrNotFound"
|
||||
type notFound interface {
|
||||
NotFound()
|
||||
}
|
||||
|
||||
// IsNotFound returns true if the error is due to a missing object
|
||||
func IsNotFound(err error) bool {
|
||||
return errors.Is(err, ErrNotFound) || isInterface[notFound](err)
|
||||
}
|
||||
|
||||
type errAlreadyExists struct{}
|
||||
|
||||
func (errAlreadyExists) Error() string { return "already exists" }
|
||||
|
||||
func (errAlreadyExists) AlreadyExists() {}
|
||||
|
||||
func (e errAlreadyExists) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
type alreadyExists interface {
|
||||
AlreadyExists()
|
||||
}
|
||||
|
||||
// IsAlreadyExists returns true if the error is due to an already existing
|
||||
// metadata item
|
||||
func IsAlreadyExists(err error) bool {
|
||||
return errors.Is(err, ErrAlreadyExists) || isInterface[alreadyExists](err)
|
||||
}
|
||||
|
||||
type errPermissionDenied struct{}
|
||||
|
||||
func (errPermissionDenied) Error() string { return "permission denied" }
|
||||
|
||||
func (errPermissionDenied) Forbidden() {}
|
||||
|
||||
func (e errPermissionDenied) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
// forbidden maps to Moby's "ErrForbidden"
|
||||
type forbidden interface {
|
||||
Forbidden()
|
||||
}
|
||||
|
||||
// IsPermissionDenied returns true if the error is due to permission denied
|
||||
// or forbidden (403) response
|
||||
func IsPermissionDenied(err error) bool {
|
||||
return errors.Is(err, ErrPermissionDenied) || isInterface[forbidden](err)
|
||||
}
|
||||
|
||||
type errResourceExhausted struct{}
|
||||
|
||||
func (errResourceExhausted) Error() string { return "resource exhausted" }
|
||||
|
||||
func (errResourceExhausted) ResourceExhausted() {}
|
||||
|
||||
func (e errResourceExhausted) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
type resourceExhausted interface {
|
||||
ResourceExhausted()
|
||||
}
|
||||
|
||||
// IsResourceExhausted returns true if the error is due to
|
||||
// a lack of resources or too many attempts.
|
||||
func IsResourceExhausted(err error) bool {
|
||||
return errors.Is(err, errResourceExhausted{}) || isInterface[resourceExhausted](err)
|
||||
}
|
||||
|
||||
type errFailedPrecondition struct{}
|
||||
|
||||
func (e errFailedPrecondition) Error() string { return "failed precondition" }
|
||||
|
||||
func (errFailedPrecondition) FailedPrecondition() {}
|
||||
|
||||
func (e errFailedPrecondition) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
type failedPrecondition interface {
|
||||
FailedPrecondition()
|
||||
}
|
||||
|
||||
// IsFailedPrecondition returns true if an operation could not proceed due to
|
||||
// the lack of a particular condition
|
||||
func IsFailedPrecondition(err error) bool {
|
||||
return errors.Is(err, errFailedPrecondition{}) || isInterface[failedPrecondition](err)
|
||||
}
|
||||
|
||||
type errConflict struct{}
|
||||
|
||||
func (errConflict) Error() string { return "conflict" }
|
||||
|
||||
func (errConflict) Conflict() {}
|
||||
|
||||
func (e errConflict) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
// conflict maps to Moby's "ErrConflict"
|
||||
type conflict interface {
|
||||
Conflict()
|
||||
}
|
||||
|
||||
// IsConflict returns true if an operation could not proceed due to
|
||||
// a conflict.
|
||||
func IsConflict(err error) bool {
|
||||
return errors.Is(err, errConflict{}) || isInterface[conflict](err)
|
||||
}
|
||||
|
||||
type errNotModified struct{}
|
||||
|
||||
func (errNotModified) Error() string { return "not modified" }
|
||||
|
||||
func (errNotModified) NotModified() {}
|
||||
|
||||
func (e errNotModified) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
// notModified maps to Moby's "ErrNotModified"
|
||||
type notModified interface {
|
||||
NotModified()
|
||||
}
|
||||
|
||||
// IsNotModified returns true if an operation could not proceed due
|
||||
// to an object not modified from a previous state.
|
||||
func IsNotModified(err error) bool {
|
||||
return errors.Is(err, errNotModified{}) || isInterface[notModified](err)
|
||||
}
|
||||
|
||||
type errAborted struct{}
|
||||
|
||||
func (errAborted) Error() string { return "aborted" }
|
||||
|
||||
func (errAborted) Aborted() {}
|
||||
|
||||
func (e errAborted) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
type aborted interface {
|
||||
Aborted()
|
||||
}
|
||||
|
||||
// IsAborted returns true if an operation was aborted.
|
||||
func IsAborted(err error) bool {
|
||||
return errors.Is(err, errAborted{}) || isInterface[aborted](err)
|
||||
}
|
||||
|
||||
type errOutOfRange struct{}
|
||||
|
||||
func (errOutOfRange) Error() string { return "out of range" }
|
||||
|
||||
func (errOutOfRange) OutOfRange() {}
|
||||
|
||||
func (e errOutOfRange) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
type outOfRange interface {
|
||||
OutOfRange()
|
||||
}
|
||||
|
||||
// IsOutOfRange returns true if an operation could not proceed due
|
||||
// to data being out of the expected range.
|
||||
func IsOutOfRange(err error) bool {
|
||||
return errors.Is(err, errOutOfRange{}) || isInterface[outOfRange](err)
|
||||
}
|
||||
|
||||
type errNotImplemented struct{}
|
||||
|
||||
func (errNotImplemented) Error() string { return "not implemented" }
|
||||
|
||||
func (errNotImplemented) NotImplemented() {}
|
||||
|
||||
func (e errNotImplemented) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
// notImplemented maps to Moby's "ErrNotImplemented"
|
||||
type notImplemented interface {
|
||||
NotImplemented()
|
||||
}
|
||||
|
||||
// IsNotImplemented returns true if the error is due to not being implemented
|
||||
func IsNotImplemented(err error) bool {
|
||||
return errors.Is(err, errNotImplemented{}) || isInterface[notImplemented](err)
|
||||
}
|
||||
|
||||
type errInternal struct{}
|
||||
|
||||
func (errInternal) Error() string { return "internal" }
|
||||
|
||||
func (errInternal) System() {}
|
||||
|
||||
func (e errInternal) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
// system maps to Moby's "ErrSystem"
|
||||
type system interface {
|
||||
System()
|
||||
}
|
||||
|
||||
// IsInternal returns true if the error returns to an internal or system error
|
||||
func IsInternal(err error) bool {
|
||||
return errors.Is(err, errInternal{}) || isInterface[system](err)
|
||||
}
|
||||
|
||||
type errUnavailable struct{}
|
||||
|
||||
func (errUnavailable) Error() string { return "unavailable" }
|
||||
|
||||
func (errUnavailable) Unavailable() {}
|
||||
|
||||
func (e errUnavailable) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
// unavailable maps to Moby's "ErrUnavailable"
|
||||
type unavailable interface {
|
||||
Unavailable()
|
||||
}
|
||||
|
||||
// IsUnavailable returns true if the error is due to a resource being unavailable
|
||||
func IsUnavailable(err error) bool {
|
||||
return errors.Is(err, errUnavailable{}) || isInterface[unavailable](err)
|
||||
}
|
||||
|
||||
type errDataLoss struct{}
|
||||
|
||||
func (errDataLoss) Error() string { return "data loss" }
|
||||
|
||||
func (errDataLoss) DataLoss() {}
|
||||
|
||||
func (e errDataLoss) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
// dataLoss maps to Moby's "ErrDataLoss"
|
||||
type dataLoss interface {
|
||||
DataLoss()
|
||||
}
|
||||
|
||||
// IsDataLoss returns true if data during an operation was lost or corrupted
|
||||
func IsDataLoss(err error) bool {
|
||||
return errors.Is(err, errDataLoss{}) || isInterface[dataLoss](err)
|
||||
}
|
||||
|
||||
type errUnauthorized struct{}
|
||||
|
||||
func (errUnauthorized) Error() string { return "unauthorized" }
|
||||
|
||||
func (errUnauthorized) Unauthorized() {}
|
||||
|
||||
func (e errUnauthorized) WithMessage(msg string) error {
|
||||
return customMessage{e, msg}
|
||||
}
|
||||
|
||||
// unauthorized maps to Moby's "ErrUnauthorized"
|
||||
type unauthorized interface {
|
||||
Unauthorized()
|
||||
}
|
||||
|
||||
// IsUnauthorized returns true if the error indicates that the user was
|
||||
// unauthenticated or unauthorized.
|
||||
func IsUnauthorized(err error) bool {
|
||||
return errors.Is(err, errUnauthorized{}) || isInterface[unauthorized](err)
|
||||
}
|
||||
|
||||
func isInterface[T any](err error) bool {
|
||||
for {
|
||||
switch x := err.(type) {
|
||||
case T:
|
||||
return true
|
||||
case customMessage:
|
||||
err = x.err
|
||||
case interface{ Unwrap() error }:
|
||||
err = x.Unwrap()
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
case interface{ Unwrap() []error }:
|
||||
for _, err := range x.Unwrap() {
|
||||
if isInterface[T](err) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// customMessage is used to provide a defined error with a custom message.
|
||||
// The message is not wrapped but can be compared by the `Is(error) bool` interface.
|
||||
type customMessage struct {
|
||||
err error
|
||||
msg string
|
||||
}
|
||||
|
||||
func (c customMessage) Is(err error) bool {
|
||||
return c.err == err
|
||||
}
|
||||
|
||||
func (c customMessage) As(target any) bool {
|
||||
return errors.As(c.err, target)
|
||||
}
|
||||
|
||||
func (c customMessage) Error() string {
|
||||
return c.msg
|
||||
}
|
||||
|
|
|
|||
147
vendor/github.com/containerd/errdefs/grpc.go
generated
vendored
147
vendor/github.com/containerd/errdefs/grpc.go
generated
vendored
|
|
@ -1,147 +0,0 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package errdefs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// ToGRPC will attempt to map the backend containerd error into a grpc error,
|
||||
// using the original error message as a description.
|
||||
//
|
||||
// Further information may be extracted from certain errors depending on their
|
||||
// type.
|
||||
//
|
||||
// If the error is unmapped, the original error will be returned to be handled
|
||||
// by the regular grpc error handling stack.
|
||||
func ToGRPC(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if isGRPCError(err) {
|
||||
// error has already been mapped to grpc
|
||||
return err
|
||||
}
|
||||
|
||||
switch {
|
||||
case IsInvalidArgument(err):
|
||||
return status.Errorf(codes.InvalidArgument, err.Error())
|
||||
case IsNotFound(err):
|
||||
return status.Errorf(codes.NotFound, err.Error())
|
||||
case IsAlreadyExists(err):
|
||||
return status.Errorf(codes.AlreadyExists, err.Error())
|
||||
case IsFailedPrecondition(err):
|
||||
return status.Errorf(codes.FailedPrecondition, err.Error())
|
||||
case IsUnavailable(err):
|
||||
return status.Errorf(codes.Unavailable, err.Error())
|
||||
case IsNotImplemented(err):
|
||||
return status.Errorf(codes.Unimplemented, err.Error())
|
||||
case IsCanceled(err):
|
||||
return status.Errorf(codes.Canceled, err.Error())
|
||||
case IsDeadlineExceeded(err):
|
||||
return status.Errorf(codes.DeadlineExceeded, err.Error())
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// ToGRPCf maps the error to grpc error codes, assembling the formatting string
|
||||
// and combining it with the target error string.
|
||||
//
|
||||
// This is equivalent to errdefs.ToGRPC(fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err))
|
||||
func ToGRPCf(err error, format string, args ...interface{}) error {
|
||||
return ToGRPC(fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err))
|
||||
}
|
||||
|
||||
// FromGRPC returns the underlying error from a grpc service based on the grpc error code
|
||||
func FromGRPC(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var cls error // divide these into error classes, becomes the cause
|
||||
|
||||
switch code(err) {
|
||||
case codes.InvalidArgument:
|
||||
cls = ErrInvalidArgument
|
||||
case codes.AlreadyExists:
|
||||
cls = ErrAlreadyExists
|
||||
case codes.NotFound:
|
||||
cls = ErrNotFound
|
||||
case codes.Unavailable:
|
||||
cls = ErrUnavailable
|
||||
case codes.FailedPrecondition:
|
||||
cls = ErrFailedPrecondition
|
||||
case codes.Unimplemented:
|
||||
cls = ErrNotImplemented
|
||||
case codes.Canceled:
|
||||
cls = context.Canceled
|
||||
case codes.DeadlineExceeded:
|
||||
cls = context.DeadlineExceeded
|
||||
default:
|
||||
cls = ErrUnknown
|
||||
}
|
||||
|
||||
msg := rebaseMessage(cls, err)
|
||||
if msg != "" {
|
||||
err = fmt.Errorf("%s: %w", msg, cls)
|
||||
} else {
|
||||
err = cls
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// rebaseMessage removes the repeats for an error at the end of an error
|
||||
// string. This will happen when taking an error over grpc then remapping it.
|
||||
//
|
||||
// Effectively, we just remove the string of cls from the end of err if it
|
||||
// appears there.
|
||||
func rebaseMessage(cls error, err error) string {
|
||||
desc := errDesc(err)
|
||||
clss := cls.Error()
|
||||
if desc == clss {
|
||||
return ""
|
||||
}
|
||||
|
||||
return strings.TrimSuffix(desc, ": "+clss)
|
||||
}
|
||||
|
||||
func isGRPCError(err error) bool {
|
||||
_, ok := status.FromError(err)
|
||||
return ok
|
||||
}
|
||||
|
||||
func code(err error) codes.Code {
|
||||
if s, ok := status.FromError(err); ok {
|
||||
return s.Code()
|
||||
}
|
||||
return codes.Unknown
|
||||
}
|
||||
|
||||
func errDesc(err error) string {
|
||||
if s, ok := status.FromError(err); ok {
|
||||
return s.Message()
|
||||
}
|
||||
return err.Error()
|
||||
}
|
||||
191
vendor/github.com/containerd/errdefs/pkg/LICENSE
generated
vendored
Normal file
191
vendor/github.com/containerd/errdefs/pkg/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright The containerd Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
353
vendor/github.com/containerd/errdefs/pkg/errgrpc/grpc.go
generated
vendored
Normal file
353
vendor/github.com/containerd/errdefs/pkg/errgrpc/grpc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package errgrpc provides utility functions for translating errors to
|
||||
// and from a gRPC context.
|
||||
//
|
||||
// The functions ToGRPC and ToNative can be used to map server-side and
|
||||
// client-side errors to the correct types.
|
||||
package errgrpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
spb "google.golang.org/genproto/googleapis/rpc/status"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/protoadapt"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
|
||||
"github.com/containerd/typeurl/v2"
|
||||
|
||||
"github.com/containerd/errdefs"
|
||||
"github.com/containerd/errdefs/pkg/internal/cause"
|
||||
"github.com/containerd/errdefs/pkg/internal/types"
|
||||
)
|
||||
|
||||
// ToGRPC will attempt to map the error into a grpc error, from the error types
|
||||
// defined in the the errdefs package and attempign to preserve the original
|
||||
// description. Any type which does not resolve to a defined error type will
|
||||
// be assigned the unknown error code.
|
||||
//
|
||||
// Further information may be extracted from certain errors depending on their
|
||||
// type. The grpc error details will be used to attempt to preserve as much of
|
||||
// the error structures and types as possible.
|
||||
//
|
||||
// Errors which can be marshaled using protobuf or typeurl will be considered
|
||||
// for including as GRPC error details.
|
||||
// Additionally, use the following interfaces in errors to preserve custom types:
|
||||
//
|
||||
// WrapError(error) error - Used to wrap the previous error
|
||||
// JoinErrors(...error) error - Used to join all previous errors
|
||||
// CollapseError() - Used for errors which carry information but
|
||||
// should not have their error message shown.
|
||||
func ToGRPC(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, ok := status.FromError(err); ok {
|
||||
// error has already been mapped to grpc
|
||||
return err
|
||||
}
|
||||
st := statusFromError(err)
|
||||
if st != nil {
|
||||
if details := errorDetails(err, false); len(details) > 0 {
|
||||
if ds, _ := st.WithDetails(details...); ds != nil {
|
||||
st = ds
|
||||
}
|
||||
}
|
||||
err = st.Err()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func statusFromError(err error) *status.Status {
|
||||
switch errdefs.Resolve(err) {
|
||||
case errdefs.ErrInvalidArgument:
|
||||
return status.New(codes.InvalidArgument, err.Error())
|
||||
case errdefs.ErrNotFound:
|
||||
return status.New(codes.NotFound, err.Error())
|
||||
case errdefs.ErrAlreadyExists:
|
||||
return status.New(codes.AlreadyExists, err.Error())
|
||||
case errdefs.ErrPermissionDenied:
|
||||
return status.New(codes.PermissionDenied, err.Error())
|
||||
case errdefs.ErrResourceExhausted:
|
||||
return status.New(codes.ResourceExhausted, err.Error())
|
||||
case errdefs.ErrFailedPrecondition, errdefs.ErrConflict, errdefs.ErrNotModified:
|
||||
return status.New(codes.FailedPrecondition, err.Error())
|
||||
case errdefs.ErrAborted:
|
||||
return status.New(codes.Aborted, err.Error())
|
||||
case errdefs.ErrOutOfRange:
|
||||
return status.New(codes.OutOfRange, err.Error())
|
||||
case errdefs.ErrNotImplemented:
|
||||
return status.New(codes.Unimplemented, err.Error())
|
||||
case errdefs.ErrInternal:
|
||||
return status.New(codes.Internal, err.Error())
|
||||
case errdefs.ErrUnavailable:
|
||||
return status.New(codes.Unavailable, err.Error())
|
||||
case errdefs.ErrDataLoss:
|
||||
return status.New(codes.DataLoss, err.Error())
|
||||
case errdefs.ErrUnauthenticated:
|
||||
return status.New(codes.Unauthenticated, err.Error())
|
||||
case context.DeadlineExceeded:
|
||||
return status.New(codes.DeadlineExceeded, err.Error())
|
||||
case context.Canceled:
|
||||
return status.New(codes.Canceled, err.Error())
|
||||
case errdefs.ErrUnknown:
|
||||
return status.New(codes.Unknown, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// errorDetails returns an array of errors which make up the provided error.
|
||||
// If firstIncluded is true, then all encodable errors will be used, otherwise
|
||||
// the first error in an error list will be not be used, to account for the
|
||||
// the base status error which details are added to via wrap or join.
|
||||
//
|
||||
// The errors are ordered in way that they can be applied in order by either
|
||||
// wrapping or joining the errors to recreate an error with the same structure
|
||||
// when `WrapError` and `JoinErrors` interfaces are used.
|
||||
//
|
||||
// The intent is that when re-applying the errors to create a single error, the
|
||||
// results of calls to `Error()`, `errors.Is`, `errors.As`, and "%+v" formatting
|
||||
// is the same as the original error.
|
||||
func errorDetails(err error, firstIncluded bool) []protoadapt.MessageV1 {
|
||||
switch uerr := err.(type) {
|
||||
case interface{ Unwrap() error }:
|
||||
details := errorDetails(uerr.Unwrap(), firstIncluded)
|
||||
|
||||
// If the type is able to wrap, then include if proto
|
||||
if _, ok := err.(interface{ WrapError(error) error }); ok {
|
||||
// Get proto message
|
||||
if protoErr := toProtoMessage(err); protoErr != nil {
|
||||
details = append(details, protoErr)
|
||||
}
|
||||
}
|
||||
|
||||
return details
|
||||
case interface{ Unwrap() []error }:
|
||||
var details []protoadapt.MessageV1
|
||||
for i, e := range uerr.Unwrap() {
|
||||
details = append(details, errorDetails(e, firstIncluded || i > 0)...)
|
||||
}
|
||||
|
||||
if _, ok := err.(interface{ JoinErrors(...error) error }); ok {
|
||||
// Get proto message
|
||||
if protoErr := toProtoMessage(err); protoErr != nil {
|
||||
details = append(details, protoErr)
|
||||
}
|
||||
}
|
||||
return details
|
||||
}
|
||||
|
||||
if firstIncluded {
|
||||
if protoErr := toProtoMessage(err); protoErr != nil {
|
||||
return []protoadapt.MessageV1{protoErr}
|
||||
}
|
||||
if gs, ok := status.FromError(ToGRPC(err)); ok {
|
||||
return []protoadapt.MessageV1{gs.Proto()}
|
||||
}
|
||||
// TODO: Else include unknown extra error type?
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func toProtoMessage(err error) protoadapt.MessageV1 {
|
||||
// Do not double encode proto messages, otherwise use Any
|
||||
if pm, ok := err.(protoadapt.MessageV1); ok {
|
||||
return pm
|
||||
}
|
||||
if pm, ok := err.(proto.Message); ok {
|
||||
return protoadapt.MessageV1Of(pm)
|
||||
}
|
||||
|
||||
if reflect.TypeOf(err).Kind() == reflect.Ptr {
|
||||
a, aerr := typeurl.MarshalAny(err)
|
||||
if aerr == nil {
|
||||
return &anypb.Any{
|
||||
TypeUrl: a.GetTypeUrl(),
|
||||
Value: a.GetValue(),
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToGRPCf maps the error to grpc error codes, assembling the formatting string
|
||||
// and combining it with the target error string.
|
||||
//
|
||||
// This is equivalent to grpc.ToGRPC(fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err))
|
||||
func ToGRPCf(err error, format string, args ...interface{}) error {
|
||||
return ToGRPC(fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err))
|
||||
}
|
||||
|
||||
// ToNative returns the underlying error from a grpc service based on the grpc
|
||||
// error code. The grpc details are used to add wrap the error in more context
|
||||
// or support multiple errors.
|
||||
func ToNative(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
s, isGRPC := status.FromError(err)
|
||||
|
||||
var (
|
||||
desc string
|
||||
code codes.Code
|
||||
)
|
||||
|
||||
if isGRPC {
|
||||
desc = s.Message()
|
||||
code = s.Code()
|
||||
} else {
|
||||
desc = err.Error()
|
||||
code = codes.Unknown
|
||||
}
|
||||
|
||||
var cls error // divide these into error classes, becomes the cause
|
||||
|
||||
switch code {
|
||||
case codes.InvalidArgument:
|
||||
cls = errdefs.ErrInvalidArgument
|
||||
case codes.AlreadyExists:
|
||||
cls = errdefs.ErrAlreadyExists
|
||||
case codes.NotFound:
|
||||
cls = errdefs.ErrNotFound
|
||||
case codes.Unavailable:
|
||||
cls = errdefs.ErrUnavailable
|
||||
case codes.FailedPrecondition:
|
||||
// TODO: Has suffix is not sufficient for conflict and not modified
|
||||
// Message should start with ": " or be at beginning of a line
|
||||
// Message should end with ": " or be at the end of a line
|
||||
// Compile a regex
|
||||
if desc == errdefs.ErrConflict.Error() || strings.HasSuffix(desc, ": "+errdefs.ErrConflict.Error()) {
|
||||
cls = errdefs.ErrConflict
|
||||
} else if desc == errdefs.ErrNotModified.Error() || strings.HasSuffix(desc, ": "+errdefs.ErrNotModified.Error()) {
|
||||
cls = errdefs.ErrNotModified
|
||||
} else {
|
||||
cls = errdefs.ErrFailedPrecondition
|
||||
}
|
||||
case codes.Unimplemented:
|
||||
cls = errdefs.ErrNotImplemented
|
||||
case codes.Canceled:
|
||||
cls = context.Canceled
|
||||
case codes.DeadlineExceeded:
|
||||
cls = context.DeadlineExceeded
|
||||
case codes.Aborted:
|
||||
cls = errdefs.ErrAborted
|
||||
case codes.Unauthenticated:
|
||||
cls = errdefs.ErrUnauthenticated
|
||||
case codes.PermissionDenied:
|
||||
cls = errdefs.ErrPermissionDenied
|
||||
case codes.Internal:
|
||||
cls = errdefs.ErrInternal
|
||||
case codes.DataLoss:
|
||||
cls = errdefs.ErrDataLoss
|
||||
case codes.OutOfRange:
|
||||
cls = errdefs.ErrOutOfRange
|
||||
case codes.ResourceExhausted:
|
||||
cls = errdefs.ErrResourceExhausted
|
||||
default:
|
||||
if idx := strings.LastIndex(desc, cause.UnexpectedStatusPrefix); idx > 0 {
|
||||
if status, uerr := strconv.Atoi(desc[idx+len(cause.UnexpectedStatusPrefix):]); uerr == nil && status >= 200 && status < 600 {
|
||||
cls = cause.ErrUnexpectedStatus{Status: status}
|
||||
}
|
||||
}
|
||||
if cls == nil {
|
||||
cls = errdefs.ErrUnknown
|
||||
}
|
||||
}
|
||||
|
||||
msg := rebaseMessage(cls, desc)
|
||||
if msg == "" {
|
||||
err = cls
|
||||
} else if msg != desc {
|
||||
err = fmt.Errorf("%s: %w", msg, cls)
|
||||
} else if wm, ok := cls.(interface{ WithMessage(string) error }); ok {
|
||||
err = wm.WithMessage(msg)
|
||||
} else {
|
||||
err = fmt.Errorf("%s: %w", msg, cls)
|
||||
}
|
||||
|
||||
if isGRPC {
|
||||
errs := []error{err}
|
||||
for _, a := range s.Details() {
|
||||
var derr error
|
||||
|
||||
// First decode error if needed
|
||||
if s, ok := a.(*spb.Status); ok {
|
||||
derr = ToNative(status.ErrorProto(s))
|
||||
} else if e, ok := a.(error); ok {
|
||||
derr = e
|
||||
} else if dany, ok := a.(typeurl.Any); ok {
|
||||
i, uerr := typeurl.UnmarshalAny(dany)
|
||||
if uerr == nil {
|
||||
if e, ok = i.(error); ok {
|
||||
derr = e
|
||||
} else {
|
||||
derr = fmt.Errorf("non-error unmarshalled detail: %v", i)
|
||||
}
|
||||
} else {
|
||||
derr = fmt.Errorf("error of type %q with failure to unmarshal: %v", dany.GetTypeUrl(), uerr)
|
||||
}
|
||||
} else {
|
||||
derr = fmt.Errorf("non-error detail: %v", a)
|
||||
}
|
||||
|
||||
switch werr := derr.(type) {
|
||||
case interface{ WrapError(error) error }:
|
||||
errs[len(errs)-1] = werr.WrapError(errs[len(errs)-1])
|
||||
case interface{ JoinErrors(...error) error }:
|
||||
// TODO: Consider whether this should support joining a subset
|
||||
errs[0] = werr.JoinErrors(errs...)
|
||||
case interface{ CollapseError() }:
|
||||
errs[len(errs)-1] = types.CollapsedError(errs[len(errs)-1], derr)
|
||||
default:
|
||||
errs = append(errs, derr)
|
||||
}
|
||||
|
||||
}
|
||||
if len(errs) > 1 {
|
||||
err = errors.Join(errs...)
|
||||
} else {
|
||||
err = errs[0]
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// rebaseMessage removes the repeats for an error at the end of an error
|
||||
// string. This will happen when taking an error over grpc then remapping it.
|
||||
//
|
||||
// Effectively, we just remove the string of cls from the end of err if it
|
||||
// appears there.
|
||||
func rebaseMessage(cls error, desc string) string {
|
||||
clss := cls.Error()
|
||||
if desc == clss {
|
||||
return ""
|
||||
}
|
||||
|
||||
return strings.TrimSuffix(desc, ": "+clss)
|
||||
}
|
||||
33
vendor/github.com/containerd/errdefs/pkg/internal/cause/cause.go
generated
vendored
Normal file
33
vendor/github.com/containerd/errdefs/pkg/internal/cause/cause.go
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package cause is used to define root causes for errors
|
||||
// common to errors packages like grpc and http.
|
||||
package cause
|
||||
|
||||
import "fmt"
|
||||
|
||||
type ErrUnexpectedStatus struct {
|
||||
Status int
|
||||
}
|
||||
|
||||
const UnexpectedStatusPrefix = "unexpected status "
|
||||
|
||||
func (e ErrUnexpectedStatus) Error() string {
|
||||
return fmt.Sprintf("%s%d", UnexpectedStatusPrefix, e.Status)
|
||||
}
|
||||
|
||||
func (ErrUnexpectedStatus) Unknown() {}
|
||||
57
vendor/github.com/containerd/errdefs/pkg/internal/types/collapsible.go
generated
vendored
Normal file
57
vendor/github.com/containerd/errdefs/pkg/internal/types/collapsible.go
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package types
|
||||
|
||||
import "fmt"
|
||||
|
||||
// CollapsibleError indicates the error should be collapsed
|
||||
type CollapsibleError interface {
|
||||
CollapseError()
|
||||
}
|
||||
|
||||
// CollapsedError returns a new error with the collapsed
|
||||
// error returned on unwrapped or when formatted with "%+v"
|
||||
func CollapsedError(err error, collapsed ...error) error {
|
||||
return collapsedError{err, collapsed}
|
||||
}
|
||||
|
||||
type collapsedError struct {
|
||||
error
|
||||
collapsed []error
|
||||
}
|
||||
|
||||
func (c collapsedError) Unwrap() []error {
|
||||
return append([]error{c.error}, c.collapsed...)
|
||||
}
|
||||
|
||||
func (c collapsedError) Format(s fmt.State, verb rune) {
|
||||
switch verb {
|
||||
case 'v':
|
||||
if s.Flag('+') {
|
||||
fmt.Fprintf(s, "%+v", c.error)
|
||||
for _, err := range c.collapsed {
|
||||
fmt.Fprintf(s, "\n%+v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 's':
|
||||
fmt.Fprint(s, c.Error())
|
||||
case 'q':
|
||||
fmt.Fprintf(s, "%q", c.Error())
|
||||
}
|
||||
}
|
||||
147
vendor/github.com/containerd/errdefs/resolve.go
generated
vendored
Normal file
147
vendor/github.com/containerd/errdefs/resolve.go
generated
vendored
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package errdefs
|
||||
|
||||
import "context"
|
||||
|
||||
// Resolve returns the first error found in the error chain which matches an
|
||||
// error defined in this package or context error. A raw, unwrapped error is
|
||||
// returned or ErrUnknown if no matching error is found.
|
||||
//
|
||||
// This is useful for determining a response code based on the outermost wrapped
|
||||
// error rather than the original cause. For example, a not found error deep
|
||||
// in the code may be wrapped as an invalid argument. When determining status
|
||||
// code from Is* functions, the depth or ordering of the error is not
|
||||
// considered.
|
||||
//
|
||||
// The search order is depth first, a wrapped error returned from any part of
|
||||
// the chain from `Unwrap() error` will be returned before any joined errors
|
||||
// as returned by `Unwrap() []error`.
|
||||
func Resolve(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
err = firstError(err)
|
||||
if err == nil {
|
||||
err = ErrUnknown
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func firstError(err error) error {
|
||||
for {
|
||||
switch err {
|
||||
case ErrUnknown,
|
||||
ErrInvalidArgument,
|
||||
ErrNotFound,
|
||||
ErrAlreadyExists,
|
||||
ErrPermissionDenied,
|
||||
ErrResourceExhausted,
|
||||
ErrFailedPrecondition,
|
||||
ErrConflict,
|
||||
ErrNotModified,
|
||||
ErrAborted,
|
||||
ErrOutOfRange,
|
||||
ErrNotImplemented,
|
||||
ErrInternal,
|
||||
ErrUnavailable,
|
||||
ErrDataLoss,
|
||||
ErrUnauthenticated,
|
||||
context.DeadlineExceeded,
|
||||
context.Canceled:
|
||||
return err
|
||||
}
|
||||
switch e := err.(type) {
|
||||
case customMessage:
|
||||
err = e.err
|
||||
case unknown:
|
||||
return ErrUnknown
|
||||
case invalidParameter:
|
||||
return ErrInvalidArgument
|
||||
case notFound:
|
||||
return ErrNotFound
|
||||
case alreadyExists:
|
||||
return ErrAlreadyExists
|
||||
case forbidden:
|
||||
return ErrPermissionDenied
|
||||
case resourceExhausted:
|
||||
return ErrResourceExhausted
|
||||
case failedPrecondition:
|
||||
return ErrFailedPrecondition
|
||||
case conflict:
|
||||
return ErrConflict
|
||||
case notModified:
|
||||
return ErrNotModified
|
||||
case aborted:
|
||||
return ErrAborted
|
||||
case errOutOfRange:
|
||||
return ErrOutOfRange
|
||||
case notImplemented:
|
||||
return ErrNotImplemented
|
||||
case system:
|
||||
return ErrInternal
|
||||
case unavailable:
|
||||
return ErrUnavailable
|
||||
case dataLoss:
|
||||
return ErrDataLoss
|
||||
case unauthorized:
|
||||
return ErrUnauthenticated
|
||||
case deadlineExceeded:
|
||||
return context.DeadlineExceeded
|
||||
case cancelled:
|
||||
return context.Canceled
|
||||
case interface{ Unwrap() error }:
|
||||
err = e.Unwrap()
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
case interface{ Unwrap() []error }:
|
||||
for _, ue := range e.Unwrap() {
|
||||
if fe := firstError(ue); fe != nil {
|
||||
return fe
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case interface{ Is(error) bool }:
|
||||
for _, target := range []error{ErrUnknown,
|
||||
ErrInvalidArgument,
|
||||
ErrNotFound,
|
||||
ErrAlreadyExists,
|
||||
ErrPermissionDenied,
|
||||
ErrResourceExhausted,
|
||||
ErrFailedPrecondition,
|
||||
ErrConflict,
|
||||
ErrNotModified,
|
||||
ErrAborted,
|
||||
ErrOutOfRange,
|
||||
ErrNotImplemented,
|
||||
ErrInternal,
|
||||
ErrUnavailable,
|
||||
ErrDataLoss,
|
||||
ErrUnauthenticated,
|
||||
context.DeadlineExceeded,
|
||||
context.Canceled} {
|
||||
if e.Is(target) {
|
||||
return target
|
||||
}
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
5
vendor/github.com/containers/buildah/Makefile
generated
vendored
5
vendor/github.com/containers/buildah/Makefile
generated
vendored
|
|
@ -53,7 +53,7 @@ endif
|
|||
# Note: Uses the -N -l go compiler options to disable compiler optimizations
|
||||
# and inlining. Using these build options allows you to subsequently
|
||||
# use source debugging tools like delve.
|
||||
all: bin/buildah bin/imgtype bin/copy bin/tutorial docs
|
||||
all: bin/buildah bin/imgtype bin/copy bin/inet bin/tutorial docs
|
||||
|
||||
# Update nix/nixpkgs.json its latest stable commit
|
||||
.PHONY: nixpkgs
|
||||
|
|
@ -110,6 +110,9 @@ bin/copy: $(SOURCES) tests/copy/copy.go
|
|||
bin/tutorial: $(SOURCES) tests/tutorial/tutorial.go
|
||||
$(GO_BUILD) $(BUILDAH_LDFLAGS) -o $@ $(BUILDFLAGS) ./tests/tutorial/tutorial.go
|
||||
|
||||
bin/inet: tests/inet/inet.go
|
||||
$(GO_BUILD) $(BUILDAH_LDFLAGS) -o $@ $(BUILDFLAGS) ./tests/inet/inet.go
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) -r bin tests/testreport/testreport
|
||||
|
|
|
|||
5
vendor/github.com/containers/buildah/add.go
generated
vendored
5
vendor/github.com/containers/buildah/add.go
generated
vendored
|
|
@ -30,6 +30,7 @@ import (
|
|||
"github.com/containers/storage/pkg/regexp"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/moby/sys/userns"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
|
@ -545,7 +546,7 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption
|
|||
ChmodDirs: nil,
|
||||
ChownFiles: nil,
|
||||
ChmodFiles: nil,
|
||||
IgnoreDevices: runningInUserNS(),
|
||||
IgnoreDevices: userns.RunningInUserNS(),
|
||||
}
|
||||
putErr = copier.Put(extractDirectory, extractDirectory, putOptions, io.TeeReader(pipeReader, hasher))
|
||||
}
|
||||
|
|
@ -686,7 +687,7 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption
|
|||
ChmodDirs: nil,
|
||||
ChownFiles: nil,
|
||||
ChmodFiles: nil,
|
||||
IgnoreDevices: runningInUserNS(),
|
||||
IgnoreDevices: userns.RunningInUserNS(),
|
||||
}
|
||||
putErr = copier.Put(extractDirectory, extractDirectory, putOptions, io.TeeReader(pipeReader, hasher))
|
||||
}
|
||||
|
|
|
|||
7
vendor/github.com/containers/buildah/add_common.go
generated
vendored
7
vendor/github.com/containers/buildah/add_common.go
generated
vendored
|
|
@ -1,7 +0,0 @@
|
|||
//go:build !linux
|
||||
|
||||
package buildah
|
||||
|
||||
func runningInUserNS() bool {
|
||||
return false
|
||||
}
|
||||
9
vendor/github.com/containers/buildah/add_linux.go
generated
vendored
9
vendor/github.com/containers/buildah/add_linux.go
generated
vendored
|
|
@ -1,9 +0,0 @@
|
|||
package buildah
|
||||
|
||||
import (
|
||||
"github.com/opencontainers/runc/libcontainer/userns"
|
||||
)
|
||||
|
||||
func runningInUserNS() bool {
|
||||
return userns.RunningInUserNS()
|
||||
}
|
||||
16
vendor/github.com/containers/buildah/chroot/run_common.go
generated
vendored
16
vendor/github.com/containers/buildah/chroot/run_common.go
generated
vendored
|
|
@ -498,7 +498,7 @@ func runUsingChroot(spec *specs.Spec, bundlePath string, ctty *os.File, stdin io
|
|||
BundlePath: bundlePath,
|
||||
})
|
||||
if conferr != nil {
|
||||
fmt.Fprintf(os.Stderr, "error re-encoding configuration for %q", runUsingChrootExecCommand)
|
||||
fmt.Fprintf(os.Stderr, "error re-encoding configuration for %q\n", runUsingChrootExecCommand)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -567,7 +567,7 @@ func runUsingChroot(spec *specs.Spec, bundlePath string, ctty *os.File, stdin io
|
|||
}
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "process exited with error: %v", err)
|
||||
fmt.Fprintf(os.Stderr, "process exited with error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -695,7 +695,7 @@ func runUsingChrootExecMain() {
|
|||
}
|
||||
logrus.Debugf("setting supplemental groups")
|
||||
if err = syscall.Setgroups(gids); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error setting supplemental groups list: %v", err)
|
||||
fmt.Fprintf(os.Stderr, "error setting supplemental groups list: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -703,7 +703,7 @@ func runUsingChrootExecMain() {
|
|||
if strings.Trim(string(setgroups), "\n") != "deny" {
|
||||
logrus.Debugf("clearing supplemental groups")
|
||||
if err = syscall.Setgroups([]int{}); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error clearing supplemental groups list: %v", err)
|
||||
fmt.Fprintf(os.Stderr, "error clearing supplemental groups list: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
|
@ -711,7 +711,7 @@ func runUsingChrootExecMain() {
|
|||
|
||||
logrus.Debugf("setting gid")
|
||||
if err = unix.Setresgid(int(user.GID), int(user.GID), int(user.GID)); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error setting GID: %v", err)
|
||||
fmt.Fprintf(os.Stderr, "error setting GID: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -732,7 +732,7 @@ func runUsingChrootExecMain() {
|
|||
|
||||
logrus.Debugf("setting uid")
|
||||
if err = unix.Setresuid(int(user.UID), int(user.UID), int(user.UID)); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error setting UID: %v", err)
|
||||
fmt.Fprintf(os.Stderr, "error setting UID: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -745,7 +745,7 @@ func runUsingChrootExecMain() {
|
|||
logrus.Debugf("Running %#v (PATH = %q)", cmd, os.Getenv("PATH"))
|
||||
interrupted := make(chan os.Signal, 100)
|
||||
if err = cmd.Start(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "process failed to start with error: %v", err)
|
||||
fmt.Fprintf(os.Stderr, "process failed to start with error: %v\n", err)
|
||||
}
|
||||
go func() {
|
||||
for range interrupted {
|
||||
|
|
@ -772,7 +772,7 @@ func runUsingChrootExecMain() {
|
|||
}
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "process exited with error: %v", err)
|
||||
fmt.Fprintf(os.Stderr, "process exited with error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
13
vendor/github.com/containers/buildah/internal/volumes/volumes.go
generated
vendored
13
vendor/github.com/containers/buildah/internal/volumes/volumes.go
generated
vendored
|
|
@ -531,6 +531,7 @@ func GetVolumes(ctx *types.SystemContext, store storage.Store, volumes []string,
|
|||
// getMounts takes user-provided input from the --mount flag and creates OCI
|
||||
// spec mounts.
|
||||
// buildah run --mount type=bind,src=/etc/resolv.conf,target=/etc/resolv.conf ...
|
||||
// buildah run --mount type=cache,target=/var/cache ...
|
||||
// buildah run --mount type=tmpfs,target=/dev/shm ...
|
||||
//
|
||||
// If this function succeeds, the caller must unlock the returned *lockfile.LockFile s if any (when??).
|
||||
|
|
@ -590,7 +591,7 @@ func getMounts(ctx *types.SystemContext, store storage.Store, mounts []string, c
|
|||
}
|
||||
finalMounts[mount.Destination] = mount
|
||||
case TypeTmpfs:
|
||||
mount, err := GetTmpfsMount(tokens)
|
||||
mount, err := GetTmpfsMount(tokens, workDir)
|
||||
if err != nil {
|
||||
return nil, mountedImages, nil, err
|
||||
}
|
||||
|
|
@ -608,7 +609,7 @@ func getMounts(ctx *types.SystemContext, store storage.Store, mounts []string, c
|
|||
}
|
||||
|
||||
// GetTmpfsMount parses a single tmpfs mount entry from the --mount flag
|
||||
func GetTmpfsMount(args []string) (specs.Mount, error) {
|
||||
func GetTmpfsMount(args []string, workDir string) (specs.Mount, error) {
|
||||
newMount := specs.Mount{
|
||||
Type: TypeTmpfs,
|
||||
Source: TypeTmpfs,
|
||||
|
|
@ -646,10 +647,14 @@ func GetTmpfsMount(args []string) (specs.Mount, error) {
|
|||
if !hasArgValue {
|
||||
return newMount, fmt.Errorf("%v: %w", argName, errBadOptionArg)
|
||||
}
|
||||
if err := parse.ValidateVolumeCtrDir(argValue); err != nil {
|
||||
targetPath := argValue
|
||||
if !path.IsAbs(targetPath) {
|
||||
targetPath = filepath.Join(workDir, targetPath)
|
||||
}
|
||||
if err := parse.ValidateVolumeCtrDir(targetPath); err != nil {
|
||||
return newMount, err
|
||||
}
|
||||
newMount.Destination = argValue
|
||||
newMount.Destination = targetPath
|
||||
setDest = true
|
||||
default:
|
||||
return newMount, fmt.Errorf("%v: %w", argName, errBadMntOption)
|
||||
|
|
|
|||
6
vendor/github.com/containers/buildah/run_common.go
generated
vendored
6
vendor/github.com/containers/buildah/run_common.go
generated
vendored
|
|
@ -1605,7 +1605,7 @@ func (b *Builder) runSetupRunMounts(mountPoint string, mounts []string, sources
|
|||
mountImages = append(mountImages, image)
|
||||
}
|
||||
case "tmpfs":
|
||||
mountSpec, err = b.getTmpfsMount(tokens, idMaps)
|
||||
mountSpec, err = b.getTmpfsMount(tokens, idMaps, sources.WorkDir)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
@ -1665,9 +1665,9 @@ func (b *Builder) getBindMount(tokens []string, context *imageTypes.SystemContex
|
|||
return &volumes[0], image, nil
|
||||
}
|
||||
|
||||
func (b *Builder) getTmpfsMount(tokens []string, idMaps IDMaps) (*specs.Mount, error) {
|
||||
func (b *Builder) getTmpfsMount(tokens []string, idMaps IDMaps, workDir string) (*specs.Mount, error) {
|
||||
var optionMounts []specs.Mount
|
||||
mount, err := volumes.GetTmpfsMount(tokens)
|
||||
mount, err := volumes.GetTmpfsMount(tokens, workDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
7
vendor/github.com/containers/buildah/run_freebsd.go
generated
vendored
7
vendor/github.com/containers/buildah/run_freebsd.go
generated
vendored
|
|
@ -124,10 +124,16 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
|||
return err
|
||||
}
|
||||
|
||||
workDir := b.WorkDir()
|
||||
if options.WorkingDir != "" {
|
||||
g.SetProcessCwd(options.WorkingDir)
|
||||
workDir = options.WorkingDir
|
||||
} else if b.WorkDir() != "" {
|
||||
g.SetProcessCwd(b.WorkDir())
|
||||
workDir = b.WorkDir()
|
||||
}
|
||||
if workDir == "" {
|
||||
workDir = string(os.PathSeparator)
|
||||
}
|
||||
mountPoint, err := b.Mount(b.MountLabel)
|
||||
if err != nil {
|
||||
|
|
@ -249,6 +255,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
|||
}
|
||||
|
||||
runMountInfo := runMountInfo{
|
||||
WorkDir: workDir,
|
||||
ContextDir: options.ContextDir,
|
||||
Secrets: options.Secrets,
|
||||
SSHSources: options.SSHSources,
|
||||
|
|
|
|||
4
vendor/github.com/containers/buildah/run_linux.go
generated
vendored
4
vendor/github.com/containers/buildah/run_linux.go
generated
vendored
|
|
@ -237,6 +237,10 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
|||
workDir = options.WorkingDir
|
||||
} else if b.WorkDir() != "" {
|
||||
g.SetProcessCwd(b.WorkDir())
|
||||
workDir = b.WorkDir()
|
||||
}
|
||||
if workDir == "" {
|
||||
workDir = string(os.PathSeparator)
|
||||
}
|
||||
setupSelinux(g, b.ProcessLabel, b.MountLabel)
|
||||
mountPoint, err := b.Mount(b.MountLabel)
|
||||
|
|
|
|||
7
vendor/github.com/containers/common/libimage/copier.go
generated
vendored
7
vendor/github.com/containers/common/libimage/copier.go
generated
vendored
|
|
@ -175,8 +175,8 @@ type Copier struct {
|
|||
// newCopier creates a Copier based on a runtime's system context.
|
||||
// Note that fields in options *may* overwrite the counterparts of
|
||||
// the specified system context. Please make sure to call `(*Copier).Close()`.
|
||||
func (r *Runtime) newCopier(options *CopyOptions) (*Copier, error) {
|
||||
return NewCopier(options, r.SystemContext())
|
||||
func (r *Runtime) newCopier(options *CopyOptions, reportResolvedReference *types.ImageReference) (*Copier, error) {
|
||||
return NewCopier(options, r.SystemContext(), reportResolvedReference)
|
||||
}
|
||||
|
||||
// storageAllowedPolicyScopes overrides the policy for local storage
|
||||
|
|
@ -223,7 +223,7 @@ func getDockerAuthConfig(name, passwd, creds, idToken string) (*types.DockerAuth
|
|||
// NewCopier creates a Copier based on a provided system context.
|
||||
// Note that fields in options *may* overwrite the counterparts of
|
||||
// the specified system context. Please make sure to call `(*Copier).Close()`.
|
||||
func NewCopier(options *CopyOptions, sc *types.SystemContext) (*Copier, error) {
|
||||
func NewCopier(options *CopyOptions, sc *types.SystemContext, reportResolvedReference *types.ImageReference) (*Copier, error) {
|
||||
c := Copier{extendTimeoutSocket: options.extendTimeoutSocket}
|
||||
sysContextCopy := *sc
|
||||
c.systemContext = &sysContextCopy
|
||||
|
|
@ -330,6 +330,7 @@ func NewCopier(options *CopyOptions, sc *types.SystemContext) (*Copier, error) {
|
|||
c.imageCopyOptions.SignBySigstorePrivateKeyFile = options.SignBySigstorePrivateKeyFile
|
||||
c.imageCopyOptions.SignSigstorePrivateKeyPassphrase = options.SignSigstorePrivateKeyPassphrase
|
||||
c.imageCopyOptions.ReportWriter = options.Writer
|
||||
c.imageCopyOptions.ReportResolvedReference = reportResolvedReference
|
||||
|
||||
defaultContainerConfig, err := config.Default()
|
||||
if err != nil {
|
||||
|
|
|
|||
2
vendor/github.com/containers/common/libimage/import.go
generated
vendored
2
vendor/github.com/containers/common/libimage/import.go
generated
vendored
|
|
@ -104,7 +104,7 @@ func (r *Runtime) Import(ctx context.Context, path string, options *ImportOption
|
|||
return "", err
|
||||
}
|
||||
|
||||
c, err := r.newCopier(&options.CopyOptions)
|
||||
c, err := r.newCopier(&options.CopyOptions, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/containers/common/libimage/manifest_list.go
generated
vendored
2
vendor/github.com/containers/common/libimage/manifest_list.go
generated
vendored
|
|
@ -792,7 +792,7 @@ func (m *ManifestList) Push(ctx context.Context, destination string, options *Ma
|
|||
// NOTE: we're using the logic in copier to create a proper
|
||||
// types.SystemContext. This prevents us from having an error prone
|
||||
// code duplicate here.
|
||||
copier, err := m.image.runtime.newCopier(&options.CopyOptions)
|
||||
copier, err := m.image.runtime.newCopier(&options.CopyOptions, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
|||
124
vendor/github.com/containers/common/libimage/pull.go
generated
vendored
124
vendor/github.com/containers/common/libimage/pull.go
generated
vendored
|
|
@ -17,15 +17,14 @@ import (
|
|||
dockerArchiveTransport "github.com/containers/image/v5/docker/archive"
|
||||
dockerDaemonTransport "github.com/containers/image/v5/docker/daemon"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
ociArchiveTransport "github.com/containers/image/v5/oci/archive"
|
||||
ociTransport "github.com/containers/image/v5/oci/layout"
|
||||
"github.com/containers/image/v5/pkg/shortnames"
|
||||
storageTransport "github.com/containers/image/v5/storage"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/transports/alltransports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ociSpec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
|
@ -231,7 +230,7 @@ func nameFromAnnotations(annotations map[string]string) string {
|
|||
// copyFromDefault is the default copier for a number of transports. Other
|
||||
// transports require some specific dancing, sometimes Yoga.
|
||||
func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference, options *CopyOptions) ([]string, error) {
|
||||
c, err := r.newCopier(options)
|
||||
c, err := r.newCopier(options, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -387,7 +386,7 @@ func (r *Runtime) copyFromDockerArchive(ctx context.Context, ref types.ImageRefe
|
|||
|
||||
// copyFromDockerArchiveReaderReference copies the specified readerRef from reader.
|
||||
func (r *Runtime) copyFromDockerArchiveReaderReference(ctx context.Context, reader *dockerArchiveTransport.Reader, readerRef types.ImageReference, options *CopyOptions) ([]string, error) {
|
||||
c, err := r.newCopier(options)
|
||||
c, err := r.newCopier(options, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -421,7 +420,11 @@ func (r *Runtime) copyFromRegistry(ctx context.Context, ref types.ImageReference
|
|||
}
|
||||
|
||||
if !options.AllTags {
|
||||
return r.copySingleImageFromRegistry(ctx, inputName, pullPolicy, options)
|
||||
pulled, err := r.copySingleImageFromRegistry(ctx, inputName, pullPolicy, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []string{pulled}, nil
|
||||
}
|
||||
|
||||
// Copy all tags
|
||||
|
|
@ -447,68 +450,19 @@ func (r *Runtime) copyFromRegistry(ctx context.Context, ref types.ImageReference
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pulledIDs = append(pulledIDs, pulled...)
|
||||
pulledIDs = append(pulledIDs, pulled)
|
||||
}
|
||||
|
||||
return pulledIDs, nil
|
||||
}
|
||||
|
||||
// imageIDsForManifest() parses the manifest of the copied image and then looks
|
||||
// up the IDs of the matching image. There's a small slice of time, between
|
||||
// when we copy the image into local storage and when we go to look for it
|
||||
// using the name that we gave it when we copied it, when the name we wanted to
|
||||
// assign to the image could have been moved, but the image's ID will remain
|
||||
// the same until it is deleted.
|
||||
func (r *Runtime) imagesIDsForManifest(manifestBytes []byte, sys *types.SystemContext) ([]string, error) {
|
||||
var imageDigest digest.Digest
|
||||
manifestType := manifest.GuessMIMEType(manifestBytes)
|
||||
if manifest.MIMETypeIsMultiImage(manifestType) {
|
||||
list, err := manifest.ListFromBlob(manifestBytes, manifestType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing manifest list: %w", err)
|
||||
}
|
||||
d, err := list.ChooseInstance(sys)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("choosing instance from manifest list: %w", err)
|
||||
}
|
||||
imageDigest = d
|
||||
} else {
|
||||
d, err := manifest.Digest(manifestBytes)
|
||||
if err != nil {
|
||||
return nil, errors.New("digesting manifest")
|
||||
}
|
||||
imageDigest = d
|
||||
}
|
||||
images, err := r.store.ImagesByDigest(imageDigest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listing images by manifest digest: %w", err)
|
||||
}
|
||||
|
||||
// If you have additionStores defined and the same image stored in
|
||||
// both storage and additional store, it can be output twice.
|
||||
// Fixes github.com/containers/podman/issues/18647
|
||||
results := []string{}
|
||||
imageMap := map[string]bool{}
|
||||
for _, image := range images {
|
||||
if imageMap[image.ID] {
|
||||
continue
|
||||
}
|
||||
imageMap[image.ID] = true
|
||||
results = append(results, image.ID)
|
||||
}
|
||||
if len(results) == 0 {
|
||||
return nil, fmt.Errorf("identifying new image by manifest digest: %w", storage.ErrImageUnknown)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// copySingleImageFromRegistry pulls the specified, possibly unqualified, name
|
||||
// from a registry. On successful pull it returns the ID of the image in local
|
||||
// storage.
|
||||
func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName string, pullPolicy config.PullPolicy, options *PullOptions) ([]string, error) { //nolint:gocyclo
|
||||
// storage (or, FIXME, a name/ID? that could be resolved in local storage)
|
||||
func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName string, pullPolicy config.PullPolicy, options *PullOptions) (string, error) { //nolint:gocyclo
|
||||
// Sanity check.
|
||||
if err := pullPolicy.Validate(); err != nil {
|
||||
return nil, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -533,6 +487,14 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
|
|||
if options.OS != runtime.GOOS {
|
||||
lookupImageOptions.OS = options.OS
|
||||
}
|
||||
// FIXME: We sometimes return resolvedImageName from this function.
|
||||
// The function documentation says this returns an image ID, resolvedImageName is frequently not an image ID.
|
||||
//
|
||||
// Ultimately Runtime.Pull looks up the returned name... again, possibly finding some other match
|
||||
// than we did.
|
||||
//
|
||||
// This should be restructured so that the image we found here is returned to the caller of Pull
|
||||
// directly, without another image -> name -> image round-trip and possible inconsistency.
|
||||
localImage, resolvedImageName, err = r.LookupImage(imageName, lookupImageOptions)
|
||||
if err != nil && !errors.Is(err, storage.ErrImageUnknown) {
|
||||
logrus.Errorf("Looking up %s in local storage: %v", imageName, err)
|
||||
|
|
@ -563,23 +525,23 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
|
|||
if pullPolicy == config.PullPolicyNever {
|
||||
if localImage != nil {
|
||||
logrus.Debugf("Pull policy %q and %s resolved to local image %s", pullPolicy, imageName, resolvedImageName)
|
||||
return []string{resolvedImageName}, nil
|
||||
return resolvedImageName, nil
|
||||
}
|
||||
logrus.Debugf("Pull policy %q but no local image has been found for %s", pullPolicy, imageName)
|
||||
return nil, fmt.Errorf("%s: %w", imageName, storage.ErrImageUnknown)
|
||||
return "", fmt.Errorf("%s: %w", imageName, storage.ErrImageUnknown)
|
||||
}
|
||||
|
||||
if pullPolicy == config.PullPolicyMissing && localImage != nil {
|
||||
return []string{resolvedImageName}, nil
|
||||
return resolvedImageName, nil
|
||||
}
|
||||
|
||||
// If we looked up the image by ID, we cannot really pull from anywhere.
|
||||
if localImage != nil && strings.HasPrefix(localImage.ID(), imageName) {
|
||||
switch pullPolicy {
|
||||
case config.PullPolicyAlways:
|
||||
return nil, fmt.Errorf("pull policy is always but image has been referred to by ID (%s)", imageName)
|
||||
return "", fmt.Errorf("pull policy is always but image has been referred to by ID (%s)", imageName)
|
||||
default:
|
||||
return []string{resolvedImageName}, nil
|
||||
return resolvedImageName, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -604,9 +566,9 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
|
|||
resolved, err := shortnames.Resolve(sys, imageName)
|
||||
if err != nil {
|
||||
if localImage != nil && pullPolicy == config.PullPolicyNewer {
|
||||
return []string{resolvedImageName}, nil
|
||||
return resolvedImageName, nil
|
||||
}
|
||||
return nil, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
// NOTE: Below we print the description from the short-name resolution.
|
||||
|
|
@ -636,9 +598,10 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
|
|||
if socketPath, ok := os.LookupEnv("NOTIFY_SOCKET"); ok {
|
||||
options.extendTimeoutSocket = socketPath
|
||||
}
|
||||
c, err := r.newCopier(&options.CopyOptions)
|
||||
var resolvedReference types.ImageReference
|
||||
c, err := r.newCopier(&options.CopyOptions, &resolvedReference)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return "", err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
|
|
@ -648,7 +611,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
|
|||
logrus.Debugf("Attempting to pull candidate %s for %s", candidateString, imageName)
|
||||
srcRef, err := registryTransport.NewReference(candidate.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
if pullPolicy == config.PullPolicyNewer && localImage != nil {
|
||||
|
|
@ -666,19 +629,18 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
|
|||
|
||||
destRef, err := storageTransport.Transport.ParseStoreReference(r.store, candidate.Value.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := writeDesc(); err != nil {
|
||||
return nil, err
|
||||
return "", err
|
||||
}
|
||||
if options.Writer != nil {
|
||||
if _, err := io.WriteString(options.Writer, fmt.Sprintf("Trying to pull %s...\n", candidateString)); err != nil {
|
||||
return nil, err
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
var manifestBytes []byte
|
||||
if manifestBytes, err = c.Copy(ctx, srcRef, destRef); err != nil {
|
||||
if _, err := c.Copy(ctx, srcRef, destRef); err != nil {
|
||||
logrus.Debugf("Error pulling candidate %s: %v", candidateString, err)
|
||||
pullErrors = append(pullErrors, err)
|
||||
continue
|
||||
|
|
@ -691,19 +653,23 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
|
|||
}
|
||||
|
||||
logrus.Debugf("Pulled candidate %s successfully", candidateString)
|
||||
if ids, err := r.imagesIDsForManifest(manifestBytes, sys); err == nil {
|
||||
return ids, nil
|
||||
if resolvedReference == nil { // resolvedReference should always be set for storageTransport destinations
|
||||
return "", fmt.Errorf("internal error: After pulling %s, resolvedReference is nil", candidateString)
|
||||
}
|
||||
return []string{candidate.Value.String()}, nil
|
||||
_, image, err := storageTransport.ResolveReference(resolvedReference)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("resolving an already-resolved reference %q to the pulled image: %w", transports.ImageName(resolvedReference), err)
|
||||
}
|
||||
return image.ID, nil
|
||||
}
|
||||
|
||||
if localImage != nil && pullPolicy == config.PullPolicyNewer {
|
||||
return []string{resolvedImageName}, nil
|
||||
return resolvedImageName, nil
|
||||
}
|
||||
|
||||
if len(pullErrors) == 0 {
|
||||
return nil, fmt.Errorf("internal error: no image pulled (pull policy %s)", pullPolicy)
|
||||
return "", fmt.Errorf("internal error: no image pulled (pull policy %s)", pullPolicy)
|
||||
}
|
||||
|
||||
return nil, resolved.FormatPullErrors(pullErrors)
|
||||
return "", resolved.FormatPullErrors(pullErrors)
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/containers/common/libimage/push.go
generated
vendored
2
vendor/github.com/containers/common/libimage/push.go
generated
vendored
|
|
@ -109,7 +109,7 @@ func (r *Runtime) Push(ctx context.Context, source, destination string, options
|
|||
}
|
||||
}
|
||||
|
||||
c, err := r.newCopier(&options.CopyOptions)
|
||||
c, err := r.newCopier(&options.CopyOptions, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
4
vendor/github.com/containers/common/libimage/save.go
generated
vendored
4
vendor/github.com/containers/common/libimage/save.go
generated
vendored
|
|
@ -119,7 +119,7 @@ func (r *Runtime) saveSingleImage(ctx context.Context, name, format, path string
|
|||
return err
|
||||
}
|
||||
|
||||
c, err := r.newCopier(&options.CopyOptions)
|
||||
c, err := r.newCopier(&options.CopyOptions, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -204,7 +204,7 @@ func (r *Runtime) saveDockerArchive(ctx context.Context, names []string, path st
|
|||
copyOpts := options.CopyOptions
|
||||
copyOpts.dockerArchiveAdditionalTags = local.tags
|
||||
|
||||
c, err := r.newCopier(©Opts)
|
||||
c, err := r.newCopier(©Opts, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go
generated
vendored
2
vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go
generated
vendored
|
|
@ -201,7 +201,7 @@ func (n *Netns) setupPasta(nsPath string) error {
|
|||
Netns: nsPath,
|
||||
ExtraOptions: []string{"--pid", pidPath},
|
||||
}
|
||||
res, err := pasta.Setup2(&pastaOpts)
|
||||
res, err := pasta.Setup(&pastaOpts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("setting up Pasta: %w", err)
|
||||
}
|
||||
|
|
|
|||
5
vendor/github.com/containers/common/libnetwork/pasta/pasta_linux.go
generated
vendored
5
vendor/github.com/containers/common/libnetwork/pasta/pasta_linux.go
generated
vendored
|
|
@ -50,11 +50,6 @@ type SetupOptions struct {
|
|||
ExtraOptions []string
|
||||
}
|
||||
|
||||
// Setup2 alias for Setup()
|
||||
func Setup2(opts *SetupOptions) (*SetupResult, error) {
|
||||
return Setup(opts)
|
||||
}
|
||||
|
||||
// Setup start the pasta process for the given netns.
|
||||
// The pasta binary is looked up in the HelperBinariesDir and $PATH.
|
||||
// Note that there is no need for any special cleanup logic, the pasta
|
||||
|
|
|
|||
73
vendor/github.com/containers/common/pkg/ssh/connection_golang.go
generated
vendored
73
vendor/github.com/containers/common/pkg/ssh/connection_golang.go
generated
vendored
|
|
@ -16,14 +16,20 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
// We are using skeema/knownhosts rather than
|
||||
// golang.org/x/crypto/ssh/knownhosts because the
|
||||
// latter has an issue when the first key returned
|
||||
// by the server doesn't match the one in known_hosts:
|
||||
// https://github.com/golang/go/issues/29286
|
||||
// https://github.com/containers/podman/issues/23575
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/storage/pkg/fileutils"
|
||||
"github.com/containers/storage/pkg/homedir"
|
||||
"github.com/pkg/sftp"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/skeema/knownhosts"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
"golang.org/x/crypto/ssh/knownhosts"
|
||||
"golang.org/x/exp/maps"
|
||||
)
|
||||
|
||||
|
|
@ -301,46 +307,44 @@ func ValidateAndConfigure(uri *url.URL, iden string, insecureIsMachineConnection
|
|||
return nil, err
|
||||
}
|
||||
|
||||
keyFilePath := filepath.Join(homedir.Get(), ".ssh", "known_hosts")
|
||||
known, err := knownhosts.NewDB(keyFilePath)
|
||||
if err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
return nil, err
|
||||
}
|
||||
keyDir := path.Dir(keyFilePath)
|
||||
if err := fileutils.Exists(keyDir); errors.Is(err, os.ErrNotExist) {
|
||||
if err := os.Mkdir(keyDir, 0o700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
k, err := os.OpenFile(keyFilePath, os.O_RDWR|os.O_CREATE, 0o600)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k.Close()
|
||||
known, err = knownhosts.NewDB(keyFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var callback ssh.HostKeyCallback
|
||||
if insecureIsMachineConnection {
|
||||
callback = ssh.InsecureIgnoreHostKey()
|
||||
} else {
|
||||
callback = ssh.HostKeyCallback(func(host string, remote net.Addr, pubKey ssh.PublicKey) error {
|
||||
keyFilePath := filepath.Join(homedir.Get(), ".ssh", "known_hosts")
|
||||
known, err := knownhosts.New(keyFilePath)
|
||||
if err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
keyDir := path.Dir(keyFilePath)
|
||||
if err := fileutils.Exists(keyDir); errors.Is(err, os.ErrNotExist) {
|
||||
if err := os.Mkdir(keyDir, 0o700); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
k, err := os.OpenFile(keyFilePath, os.O_RDWR|os.O_CREATE, 0o600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
k.Close()
|
||||
known, err = knownhosts.New(keyFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// we need to check if there is an error from reading known hosts for this public key and if there is an error, what is it, and why is it happening?
|
||||
// if it is a key mismatch we want to error since we know the host using another key
|
||||
// however, if it is a general error not because of a known key, we want to add our key to the known_hosts file
|
||||
hErr := known(host, remote, pubKey)
|
||||
var keyErr *knownhosts.KeyError
|
||||
// if keyErr.Want is not empty, we are receiving a different key meaning the host is known but we are using the wrong key
|
||||
as := errors.As(hErr, &keyErr)
|
||||
hErr := known.HostKeyCallback()(host, remote, pubKey)
|
||||
switch {
|
||||
case as && len(keyErr.Want) > 0:
|
||||
case knownhosts.IsHostKeyChanged(hErr):
|
||||
logrus.Warnf("ssh host key mismatch for host %s, got key %s of type %s", host, ssh.FingerprintSHA256(pubKey), pubKey.Type())
|
||||
return keyErr
|
||||
return hErr
|
||||
// if keyErr.Want is empty that just means we do not know this host yet, add it.
|
||||
case as && len(keyErr.Want) == 0:
|
||||
case knownhosts.IsHostUnknown(hErr):
|
||||
// write to known_hosts
|
||||
err := addKnownHostsEntry(host, pubKey)
|
||||
if err != nil {
|
||||
|
|
@ -358,10 +362,11 @@ func ValidateAndConfigure(uri *url.URL, iden string, insecureIsMachineConnection
|
|||
}
|
||||
|
||||
cfg := &ssh.ClientConfig{
|
||||
User: uri.User.Username(),
|
||||
Auth: authMethods,
|
||||
HostKeyCallback: callback,
|
||||
Timeout: tick,
|
||||
User: uri.User.Username(),
|
||||
Auth: authMethods,
|
||||
HostKeyCallback: callback,
|
||||
Timeout: tick,
|
||||
HostKeyAlgorithms: known.HostKeyAlgorithms(uri.Host),
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
|
|
|||
14
vendor/github.com/containers/common/pkg/timezone/timezone.go
generated
vendored
14
vendor/github.com/containers/common/pkg/timezone/timezone.go
generated
vendored
|
|
@ -23,18 +23,20 @@ func ConfigureContainerTimeZone(timezone, containerRunDir, mountPoint, etcPath,
|
|||
switch {
|
||||
case timezone == "":
|
||||
return "", nil
|
||||
case os.Getenv("TZDIR") != "":
|
||||
// Allow using TZDIR per:
|
||||
// https://sourceware.org/git/?p=glibc.git;a=blob;f=time/tzfile.c;h=8a923d0cccc927a106dc3e3c641be310893bab4e;hb=HEAD#l149
|
||||
|
||||
timezonePath = filepath.Join(os.Getenv("TZDIR"), timezone)
|
||||
case timezone == "local":
|
||||
timezonePath, err = filepath.EvalSymlinks("/etc/localtime")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("finding local timezone for container %s: %w", containerID, err)
|
||||
}
|
||||
default:
|
||||
timezonePath = filepath.Join("/usr/share/zoneinfo", timezone)
|
||||
// Allow using TZDIR per:
|
||||
// https://sourceware.org/git/?p=glibc.git;a=blob;f=time/tzfile.c;h=8a923d0cccc927a106dc3e3c641be310893bab4e;hb=HEAD#l149
|
||||
zoneinfo := os.Getenv("TZDIR")
|
||||
if zoneinfo == "" {
|
||||
// default zoneinfo location
|
||||
zoneinfo = "/usr/share/zoneinfo"
|
||||
}
|
||||
timezonePath = filepath.Join(zoneinfo, timezone)
|
||||
}
|
||||
|
||||
etcFd, err := openDirectory(etcPath)
|
||||
|
|
|
|||
19
vendor/github.com/containers/image/v5/copy/copy.go
generated
vendored
19
vendor/github.com/containers/image/v5/copy/copy.go
generated
vendored
|
|
@ -137,6 +137,17 @@ type Options struct {
|
|||
// DestinationCtx.CompressionFormat is used exclusively, and blobs of other
|
||||
// compression algorithms are not reused.
|
||||
ForceCompressionFormat bool
|
||||
|
||||
// ReportResolvedReference, if set, asks the destination transport to store
|
||||
// a “resolved” (more detailed) reference to the created image
|
||||
// into the value this option points to.
|
||||
// What “resolved” means is transport-specific.
|
||||
// Most transports don’t support this, and cause the value to be set to nil.
|
||||
//
|
||||
// For the containers-storage: transport, the reference contains an image ID,
|
||||
// so that storage.ResolveReference returns exactly the created image.
|
||||
// WARNING: It is unspecified whether the reference also contains a reference.Named element.
|
||||
ReportResolvedReference *types.ImageReference
|
||||
}
|
||||
|
||||
// OptionCompressionVariant allows to supply information about
|
||||
|
|
@ -337,7 +348,13 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef,
|
|||
}
|
||||
}
|
||||
|
||||
if err := c.dest.Commit(ctx, c.unparsedToplevel); err != nil {
|
||||
if options.ReportResolvedReference != nil {
|
||||
*options.ReportResolvedReference = nil // The default outcome, if not specifically supported by the transport.
|
||||
}
|
||||
if err := c.dest.CommitWithOptions(ctx, private.CommitOptions{
|
||||
UnparsedToplevel: c.unparsedToplevel,
|
||||
ReportResolvedReference: options.ReportResolvedReference,
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("committing the finished image: %w", err)
|
||||
}
|
||||
|
||||
|
|
|
|||
2
vendor/github.com/containers/image/v5/copy/single.go
generated
vendored
2
vendor/github.com/containers/image/v5/copy/single.go
generated
vendored
|
|
@ -828,7 +828,7 @@ func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, to
|
|||
return false, types.BlobInfo{}, err
|
||||
}()
|
||||
if err != nil {
|
||||
return types.BlobInfo{}, "", fmt.Errorf("reading blob %s: %w", srcInfo.Digest, err)
|
||||
return types.BlobInfo{}, "", fmt.Errorf("partial pull of blob %s: %w", srcInfo.Digest, err)
|
||||
}
|
||||
if reused {
|
||||
return blobInfo, cachedDiffID, nil
|
||||
|
|
|
|||
11
vendor/github.com/containers/image/v5/directory/directory_dest.go
generated
vendored
11
vendor/github.com/containers/image/v5/directory/directory_dest.go
generated
vendored
|
|
@ -251,14 +251,11 @@ func (d *dirImageDestination) PutSignaturesWithFormat(ctx context.Context, signa
|
|||
return nil
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// unparsedToplevel contains data about the top-level manifest of the source (which may be a single-arch image or a manifest list
|
||||
// if PutManifest was only called for the single-arch image with instanceDigest == nil), primarily to allow lookups by the
|
||||
// original manifest list digest, if desired.
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *dirImageDestination) Commit(context.Context, types.UnparsedImage) error {
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *dirImageDestination) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
26
vendor/github.com/containers/image/v5/docker/archive/dest.go
generated
vendored
26
vendor/github.com/containers/image/v5/docker/archive/dest.go
generated
vendored
|
|
@ -34,16 +34,17 @@ func newImageDestination(sys *types.SystemContext, ref archiveReference) (privat
|
|||
writer = w
|
||||
closeWriter = true
|
||||
}
|
||||
tarDest := tarfile.NewDestination(sys, writer.archive, ref.Transport().Name(), ref.ref)
|
||||
if sys != nil && sys.DockerArchiveAdditionalTags != nil {
|
||||
tarDest.AddRepoTags(sys.DockerArchiveAdditionalTags)
|
||||
}
|
||||
return &archiveImageDestination{
|
||||
Destination: tarDest,
|
||||
d := &archiveImageDestination{
|
||||
ref: ref,
|
||||
writer: writer,
|
||||
closeWriter: closeWriter,
|
||||
}, nil
|
||||
}
|
||||
tarDest := tarfile.NewDestination(sys, writer.archive, ref.Transport().Name(), ref.ref, d.CommitWithOptions)
|
||||
if sys != nil && sys.DockerArchiveAdditionalTags != nil {
|
||||
tarDest.AddRepoTags(sys.DockerArchiveAdditionalTags)
|
||||
}
|
||||
d.Destination = tarDest
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// Reference returns the reference used to set up this destination. Note that this should directly correspond to user's intent,
|
||||
|
|
@ -60,14 +61,11 @@ func (d *archiveImageDestination) Close() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// unparsedToplevel contains data about the top-level manifest of the source (which may be a single-arch image or a manifest list
|
||||
// if PutManifest was only called for the single-arch image with instanceDigest == nil), primarily to allow lookups by the
|
||||
// original manifest list digest, if desired.
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *archiveImageDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *archiveImageDestination) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
|
||||
d.writer.imageCommitted()
|
||||
if d.closeWriter {
|
||||
// We could do this only in .Close(), but failures in .Close() are much more likely to be
|
||||
|
|
|
|||
2
vendor/github.com/containers/image/v5/docker/body_reader.go
generated
vendored
2
vendor/github.com/containers/image/v5/docker/body_reader.go
generated
vendored
|
|
@ -197,7 +197,7 @@ func (br *bodyReader) Read(p []byte) (int, error) {
|
|||
consumedBody = true
|
||||
br.body = res.Body
|
||||
br.lastRetryOffset = br.offset
|
||||
br.lastRetryTime = time.Time{}
|
||||
br.lastRetryTime = time.Now()
|
||||
return n, nil
|
||||
|
||||
default:
|
||||
|
|
|
|||
20
vendor/github.com/containers/image/v5/docker/daemon/daemon_dest.go
generated
vendored
20
vendor/github.com/containers/image/v5/docker/daemon/daemon_dest.go
generated
vendored
|
|
@ -56,16 +56,17 @@ func newImageDestination(ctx context.Context, sys *types.SystemContext, ref daem
|
|||
goroutineContext, goroutineCancel := context.WithCancel(ctx)
|
||||
go imageLoadGoroutine(goroutineContext, c, reader, statusChannel)
|
||||
|
||||
return &daemonImageDestination{
|
||||
d := &daemonImageDestination{
|
||||
ref: ref,
|
||||
mustMatchRuntimeOS: mustMatchRuntimeOS,
|
||||
Destination: tarfile.NewDestination(sys, archive, ref.Transport().Name(), namedTaggedRef),
|
||||
archive: archive,
|
||||
goroutineCancel: goroutineCancel,
|
||||
statusChannel: statusChannel,
|
||||
writer: writer,
|
||||
committed: false,
|
||||
}, nil
|
||||
}
|
||||
d.Destination = tarfile.NewDestination(sys, archive, ref.Transport().Name(), namedTaggedRef, d.CommitWithOptions)
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// imageLoadGoroutine accepts tar stream on reader, sends it to c, and reports error or success by writing to statusChannel
|
||||
|
|
@ -146,7 +147,7 @@ func (d *daemonImageDestination) Close() error {
|
|||
// immediately, and hopefully, through terminating the sending which uses "Transfer-Encoding: chunked"" without sending
|
||||
// the terminating zero-length chunk, prevent the docker daemon from processing the tar stream at all.
|
||||
// Whether that works or not, closing the PipeWriter seems desirable in any case.
|
||||
if err := d.writer.CloseWithError(errors.New("Aborting upload, daemonImageDestination closed without a previous .Commit()")); err != nil {
|
||||
if err := d.writer.CloseWithError(errors.New("Aborting upload, daemonImageDestination closed without a previous .CommitWithOptions()")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -159,14 +160,11 @@ func (d *daemonImageDestination) Reference() types.ImageReference {
|
|||
return d.ref
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// unparsedToplevel contains data about the top-level manifest of the source (which may be a single-arch image or a manifest list
|
||||
// if PutManifest was only called for the single-arch image with instanceDigest == nil), primarily to allow lookups by the
|
||||
// original manifest list digest, if desired.
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *daemonImageDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *daemonImageDestination) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
|
||||
logrus.Debugf("docker-daemon: Closing tar stream")
|
||||
if err := d.archive.Close(); err != nil {
|
||||
return err
|
||||
|
|
|
|||
11
vendor/github.com/containers/image/v5/docker/docker_image_dest.go
generated
vendored
11
vendor/github.com/containers/image/v5/docker/docker_image_dest.go
generated
vendored
|
|
@ -923,13 +923,10 @@ func (d *dockerImageDestination) putSignaturesToAPIExtension(ctx context.Context
|
|||
return nil
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// unparsedToplevel contains data about the top-level manifest of the source (which may be a single-arch image or a manifest list
|
||||
// if PutManifest was only called for the single-arch image with instanceDigest == nil), primarily to allow lookups by the
|
||||
// original manifest list digest, if desired.
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *dockerImageDestination) Commit(context.Context, types.UnparsedImage) error {
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *dockerImageDestination) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
28
vendor/github.com/containers/image/v5/docker/internal/tarfile/dest.go
generated
vendored
28
vendor/github.com/containers/image/v5/docker/internal/tarfile/dest.go
generated
vendored
|
|
@ -20,22 +20,25 @@ import (
|
|||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Destination is a partial implementation of private.ImageDestination for writing to an io.Writer.
|
||||
// Destination is a partial implementation of private.ImageDestination for writing to a Writer.
|
||||
type Destination struct {
|
||||
impl.Compat
|
||||
impl.PropertyMethodsInitialize
|
||||
stubs.NoPutBlobPartialInitialize
|
||||
stubs.NoSignaturesInitialize
|
||||
|
||||
archive *Writer
|
||||
repoTags []reference.NamedTagged
|
||||
archive *Writer
|
||||
commitWithOptions func(ctx context.Context, options private.CommitOptions) error
|
||||
repoTags []reference.NamedTagged
|
||||
// Other state.
|
||||
config []byte
|
||||
sysCtx *types.SystemContext
|
||||
}
|
||||
|
||||
// NewDestination returns a tarfile.Destination adding images to the specified Writer.
|
||||
func NewDestination(sys *types.SystemContext, archive *Writer, transportName string, ref reference.NamedTagged) *Destination {
|
||||
// commitWithOptions implements ImageDestination.CommitWithOptions.
|
||||
func NewDestination(sys *types.SystemContext, archive *Writer, transportName string, ref reference.NamedTagged,
|
||||
commitWithOptions func(ctx context.Context, options private.CommitOptions) error) *Destination {
|
||||
repoTags := []reference.NamedTagged{}
|
||||
if ref != nil {
|
||||
repoTags = append(repoTags, ref)
|
||||
|
|
@ -57,9 +60,10 @@ func NewDestination(sys *types.SystemContext, archive *Writer, transportName str
|
|||
NoPutBlobPartialInitialize: stubs.NoPutBlobPartialRaw(transportName),
|
||||
NoSignaturesInitialize: stubs.NoSignatures("Storing signatures for docker tar files is not supported"),
|
||||
|
||||
archive: archive,
|
||||
repoTags: repoTags,
|
||||
sysCtx: sys,
|
||||
archive: archive,
|
||||
commitWithOptions: commitWithOptions,
|
||||
repoTags: repoTags,
|
||||
sysCtx: sys,
|
||||
}
|
||||
dest.Compat = impl.AddCompat(dest)
|
||||
return dest
|
||||
|
|
@ -179,3 +183,13 @@ func (d *Destination) PutManifest(ctx context.Context, m []byte, instanceDigest
|
|||
|
||||
return d.archive.ensureManifestItemLocked(man.LayersDescriptors, man.ConfigDescriptor.Digest, d.repoTags)
|
||||
}
|
||||
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *Destination) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
|
||||
// This indirection exists because impl.Compat expects all ImageDestinationInternalOnly methods
|
||||
// to be implemented in one place.
|
||||
return d.commitWithOptions(ctx, options)
|
||||
}
|
||||
|
|
|
|||
13
vendor/github.com/containers/image/v5/internal/imagedestination/impl/compat.go
generated
vendored
13
vendor/github.com/containers/image/v5/internal/imagedestination/impl/compat.go
generated
vendored
|
|
@ -99,3 +99,16 @@ func (c *Compat) PutSignatures(ctx context.Context, signatures [][]byte, instanc
|
|||
}
|
||||
return c.dest.PutSignaturesWithFormat(ctx, withFormat, instanceDigest)
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// unparsedToplevel contains data about the top-level manifest of the source (which may be a single-arch image or a manifest list
|
||||
// if PutManifest was only called for the single-arch image with instanceDigest == nil), primarily to allow lookups by the
|
||||
// original manifest list digest, if desired.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (c *Compat) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
return c.dest.CommitWithOptions(ctx, private.CommitOptions{
|
||||
UnparsedToplevel: unparsedToplevel,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
8
vendor/github.com/containers/image/v5/internal/imagedestination/wrapper.go
generated
vendored
8
vendor/github.com/containers/image/v5/internal/imagedestination/wrapper.go
generated
vendored
|
|
@ -97,3 +97,11 @@ func (w *wrapped) PutSignaturesWithFormat(ctx context.Context, signatures []sign
|
|||
}
|
||||
return w.PutSignatures(ctx, simpleSigs, instanceDigest)
|
||||
}
|
||||
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
func (w *wrapped) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
|
||||
return w.Commit(ctx, options.UnparsedToplevel)
|
||||
}
|
||||
|
|
|
|||
19
vendor/github.com/containers/image/v5/internal/private/private.go
generated
vendored
19
vendor/github.com/containers/image/v5/internal/private/private.go
generated
vendored
|
|
@ -70,6 +70,12 @@ type ImageDestinationInternalOnly interface {
|
|||
// (when the primary manifest is a manifest list); this should always be nil if the primary manifest is not a manifest list.
|
||||
// MUST be called after PutManifest (signatures may reference manifest contents).
|
||||
PutSignaturesWithFormat(ctx context.Context, signatures []signature.Signature, instanceDigest *digest.Digest) error
|
||||
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
CommitWithOptions(ctx context.Context, options CommitOptions) error
|
||||
}
|
||||
|
||||
// ImageDestination is an internal extension to the types.ImageDestination
|
||||
|
|
@ -146,6 +152,19 @@ type ReusedBlob struct {
|
|||
MatchedByTOCDigest bool // Whether the layer was reused/matched by TOC digest. Used only for UI purposes.
|
||||
}
|
||||
|
||||
// CommitOptions are used in CommitWithOptions
|
||||
type CommitOptions struct {
|
||||
// UnparsedToplevel contains data about the top-level manifest of the source (which may be a single-arch image or a manifest list
|
||||
// if PutManifest was only called for the single-arch image with instanceDigest == nil), primarily to allow lookups by the
|
||||
// original manifest list digest, if desired.
|
||||
UnparsedToplevel types.UnparsedImage
|
||||
// ReportResolvedReference, if set, asks the transport to store a “resolved” (more detailed) reference to the created image
|
||||
// into the value this option points to.
|
||||
// What “resolved” means is transport-specific.
|
||||
// Transports which don’t support reporting resolved references can ignore the field; the generic copy code writes "nil" into the value.
|
||||
ReportResolvedReference *types.ImageReference
|
||||
}
|
||||
|
||||
// ImageSourceChunk is a portion of a blob.
|
||||
// This API is experimental and can be changed without bumping the major version number.
|
||||
type ImageSourceChunk struct {
|
||||
|
|
|
|||
13
vendor/github.com/containers/image/v5/oci/archive/oci_dest.go
generated
vendored
13
vendor/github.com/containers/image/v5/oci/archive/oci_dest.go
generated
vendored
|
|
@ -150,13 +150,12 @@ func (d *ociArchiveImageDestination) PutSignaturesWithFormat(ctx context.Context
|
|||
return d.unpackedDest.PutSignaturesWithFormat(ctx, signatures, instanceDigest)
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted
|
||||
// unparsedToplevel contains data about the top-level manifest of the source (which may be a single-arch image or a manifest list
|
||||
// if PutManifest was only called for the single-arch image with instanceDigest == nil), primarily to allow lookups by the
|
||||
// original manifest list digest, if desired.
|
||||
// after the directory is made, it is tarred up into a file and the directory is deleted
|
||||
func (d *ociArchiveImageDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
if err := d.unpackedDest.Commit(ctx, unparsedToplevel); err != nil {
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *ociArchiveImageDestination) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
|
||||
if err := d.unpackedDest.CommitWithOptions(ctx, options); err != nil {
|
||||
return fmt.Errorf("storing image %q: %w", d.ref.image, err)
|
||||
}
|
||||
|
||||
|
|
|
|||
11
vendor/github.com/containers/image/v5/oci/layout/oci_dest.go
generated
vendored
11
vendor/github.com/containers/image/v5/oci/layout/oci_dest.go
generated
vendored
|
|
@ -278,14 +278,11 @@ func (d *ociImageDestination) addManifest(desc *imgspecv1.Descriptor) {
|
|||
d.index.Manifests = append(slices.Clone(d.index.Manifests), *desc)
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// unparsedToplevel contains data about the top-level manifest of the source (which may be a single-arch image or a manifest list
|
||||
// if PutManifest was only called for the single-arch image with instanceDigest == nil), primarily to allow lookups by the
|
||||
// original manifest list digest, if desired.
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *ociImageDestination) Commit(context.Context, types.UnparsedImage) error {
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *ociImageDestination) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
|
||||
layoutBytes, err := json.Marshal(imgspecv1.ImageLayout{
|
||||
Version: imgspecv1.ImageLayoutVersion,
|
||||
})
|
||||
|
|
|
|||
13
vendor/github.com/containers/image/v5/openshift/openshift_dest.go
generated
vendored
13
vendor/github.com/containers/image/v5/openshift/openshift_dest.go
generated
vendored
|
|
@ -236,13 +236,10 @@ func (d *openshiftImageDestination) PutSignaturesWithFormat(ctx context.Context,
|
|||
return nil
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// unparsedToplevel contains data about the top-level manifest of the source (which may be a single-arch image or a manifest list
|
||||
// if PutManifest was only called for the single-arch image with instanceDigest == nil), primarily to allow lookups by the
|
||||
// original manifest list digest, if desired.
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *openshiftImageDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
return d.docker.Commit(ctx, unparsedToplevel)
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *openshiftImageDestination) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
|
||||
return d.docker.CommitWithOptions(ctx, options)
|
||||
}
|
||||
|
|
|
|||
6
vendor/github.com/containers/image/v5/ostree/ostree_dest.go
generated
vendored
6
vendor/github.com/containers/image/v5/ostree/ostree_dest.go
generated
vendored
|
|
@ -435,7 +435,11 @@ func (d *ostreeImageDestination) PutSignaturesWithFormat(ctx context.Context, si
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *ostreeImageDestination) Commit(context.Context, types.UnparsedImage) error {
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *ostreeImageDestination) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
|
|
|
|||
8
vendor/github.com/containers/image/v5/pkg/blobcache/dest.go
generated
vendored
8
vendor/github.com/containers/image/v5/pkg/blobcache/dest.go
generated
vendored
|
|
@ -307,6 +307,10 @@ func (d *blobCacheDestination) PutSignaturesWithFormat(ctx context.Context, sign
|
|||
return d.destination.PutSignaturesWithFormat(ctx, signatures, instanceDigest)
|
||||
}
|
||||
|
||||
func (d *blobCacheDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
return d.destination.Commit(ctx, unparsedToplevel)
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *blobCacheDestination) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
|
||||
return d.destination.CommitWithOptions(ctx, options)
|
||||
}
|
||||
|
|
|
|||
14
vendor/github.com/containers/image/v5/pkg/compression/compression.go
generated
vendored
14
vendor/github.com/containers/image/v5/pkg/compression/compression.go
generated
vendored
|
|
@ -99,8 +99,18 @@ func CompressStream(dest io.Writer, algo Algorithm, level *int) (io.WriteCloser,
|
|||
return internal.AlgorithmCompressor(algo)(dest, m, level)
|
||||
}
|
||||
|
||||
// CompressStreamWithMetadata returns the compressor by its name. If the compression
|
||||
// generates any metadata, it is written to the provided metadata map.
|
||||
// CompressStreamWithMetadata returns the compressor by its name.
|
||||
//
|
||||
// Compressing a stream may create integrity data that allows consuming the compressed byte stream
|
||||
// while only using subsets of the compressed data (if the compressed data is seekable and most
|
||||
// of the uncompressed data is already present via other means), while still protecting integrity
|
||||
// of the compressed stream against unwanted modification. (In OCI container images, this metadata
|
||||
// is usually carried in manifest annotations.)
|
||||
//
|
||||
// Such a partial decompression is not implemented by this package; it is consumed e.g. by
|
||||
// github.com/containers/storage/pkg/chunked .
|
||||
//
|
||||
// If the compression generates such metadata, it is written to the provided metadata map.
|
||||
func CompressStreamWithMetadata(dest io.Writer, metadata map[string]string, algo Algorithm, level *int) (io.WriteCloser, error) {
|
||||
return internal.AlgorithmCompressor(algo)(dest, metadata, level)
|
||||
}
|
||||
|
|
|
|||
9
vendor/github.com/containers/image/v5/pkg/compression/internal/types.go
generated
vendored
9
vendor/github.com/containers/image/v5/pkg/compression/internal/types.go
generated
vendored
|
|
@ -3,6 +3,15 @@ package internal
|
|||
import "io"
|
||||
|
||||
// CompressorFunc writes the compressed stream to the given writer using the specified compression level.
|
||||
//
|
||||
// Compressing a stream may create integrity data that allows consuming the compressed byte stream
|
||||
// while only using subsets of the compressed data (if the compressed data is seekable and most
|
||||
// of the uncompressed data is already present via other means), while still protecting integrity
|
||||
// of the compressed stream against unwanted modification. (In OCI container images, this metadata
|
||||
// is usually carried in manifest annotations.)
|
||||
//
|
||||
// If the compression generates such metadata, it is written to the provided metadata map.
|
||||
//
|
||||
// The caller must call Close() on the stream (even if the input stream does not need closing!).
|
||||
type CompressorFunc func(io.Writer, map[string]string, *int) (io.WriteCloser, error)
|
||||
|
||||
|
|
|
|||
72
vendor/github.com/containers/image/v5/storage/storage_dest.go
generated
vendored
72
vendor/github.com/containers/image/v5/storage/storage_dest.go
generated
vendored
|
|
@ -335,7 +335,7 @@ func (s *storageImageDestination) PutBlobPartial(ctx context.Context, chunkAcces
|
|||
|
||||
out, err := s.imageRef.transport.store.PrepareStagedLayer(nil, differ)
|
||||
if err != nil {
|
||||
return private.UploadedBlob{}, err
|
||||
return private.UploadedBlob{}, fmt.Errorf("staging a partially-pulled layer: %w", err)
|
||||
}
|
||||
succeeded := false
|
||||
defer func() {
|
||||
|
|
@ -930,7 +930,7 @@ func (s *storageImageDestination) createNewLayer(index int, layerDigest digest.D
|
|||
|
||||
flags := make(map[string]interface{})
|
||||
if untrustedUncompressedDigest != "" {
|
||||
flags[expectedLayerDiffIDFlag] = untrustedUncompressedDigest
|
||||
flags[expectedLayerDiffIDFlag] = untrustedUncompressedDigest.String()
|
||||
logrus.Debugf("Setting uncompressed digest to %q for layer %q", untrustedUncompressedDigest, newLayerID)
|
||||
}
|
||||
|
||||
|
|
@ -1124,26 +1124,23 @@ func (s *storageImageDestination) untrustedLayerDiffID(layerIndex int) (digest.D
|
|||
return s.untrustedDiffIDValues[layerIndex], nil
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// unparsedToplevel contains data about the top-level manifest of the source (which may be a single-arch image or a manifest list
|
||||
// if PutManifest was only called for the single-arch image with instanceDigest == nil), primarily to allow lookups by the
|
||||
// original manifest list digest, if desired.
|
||||
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without CommitWithOptions() (i.e. rollback is allowed but not guaranteed)
|
||||
func (s *storageImageDestination) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
|
||||
// This function is outside of the scope of HasThreadSafePutBlob, so we don’t need to hold s.lock.
|
||||
|
||||
if len(s.manifest) == 0 {
|
||||
return errors.New("Internal error: storageImageDestination.Commit() called without PutManifest()")
|
||||
return errors.New("Internal error: storageImageDestination.CommitWithOptions() called without PutManifest()")
|
||||
}
|
||||
toplevelManifest, _, err := unparsedToplevel.Manifest(ctx)
|
||||
toplevelManifest, _, err := options.UnparsedToplevel.Manifest(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("retrieving top-level manifest: %w", err)
|
||||
}
|
||||
// If the name we're saving to includes a digest, then check that the
|
||||
// manifests that we're about to save all either match the one from the
|
||||
// unparsedToplevel, or match the digest in the name that we're using.
|
||||
// options.UnparsedToplevel, or match the digest in the name that we're using.
|
||||
if s.imageRef.named != nil {
|
||||
if digested, ok := s.imageRef.named.(reference.Digested); ok {
|
||||
matches, err := manifest.MatchesDigest(s.manifest, digested.Digest())
|
||||
|
|
@ -1176,24 +1173,24 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
|
|||
}, blob.Size); err != nil {
|
||||
return err
|
||||
} else if stopQueue {
|
||||
return fmt.Errorf("Internal error: storageImageDestination.Commit(): commitLayer() not ready to commit for layer %q", blob.Digest)
|
||||
return fmt.Errorf("Internal error: storageImageDestination.CommitWithOptions(): commitLayer() not ready to commit for layer %q", blob.Digest)
|
||||
}
|
||||
}
|
||||
var lastLayer string
|
||||
if len(layerBlobs) > 0 { // Zero-layer images rarely make sense, but it is technically possible, and may happen for non-image artifacts.
|
||||
prev, ok := s.indexToStorageID[len(layerBlobs)-1]
|
||||
if !ok {
|
||||
return fmt.Errorf("Internal error: storageImageDestination.Commit(): previous layer %d hasn't been committed (lastLayer == nil)", len(layerBlobs)-1)
|
||||
return fmt.Errorf("Internal error: storageImageDestination.CommitWithOptions(): previous layer %d hasn't been committed (lastLayer == nil)", len(layerBlobs)-1)
|
||||
}
|
||||
lastLayer = prev
|
||||
}
|
||||
|
||||
// If one of those blobs was a configuration blob, then we can try to dig out the date when the image
|
||||
// was originally created, in case we're just copying it. If not, no harm done.
|
||||
options := &storage.ImageOptions{}
|
||||
imgOptions := &storage.ImageOptions{}
|
||||
if inspect, err := man.Inspect(s.getConfigBlob); err == nil && inspect.Created != nil {
|
||||
logrus.Debugf("setting image creation date to %s", inspect.Created)
|
||||
options.CreationDate = *inspect.Created
|
||||
imgOptions.CreationDate = *inspect.Created
|
||||
}
|
||||
|
||||
// Set up to save the non-layer blobs as data items. Since we only share layers, they should all be in files, so
|
||||
|
|
@ -1210,13 +1207,13 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
|
|||
if err != nil {
|
||||
return fmt.Errorf("copying non-layer blob %q to image: %w", blob, err)
|
||||
}
|
||||
options.BigData = append(options.BigData, storage.ImageBigDataOption{
|
||||
imgOptions.BigData = append(imgOptions.BigData, storage.ImageBigDataOption{
|
||||
Key: blob.String(),
|
||||
Data: v,
|
||||
Digest: digest.Canonical.FromBytes(v),
|
||||
})
|
||||
}
|
||||
// Set up to save the unparsedToplevel's manifest if it differs from
|
||||
// Set up to save the options.UnparsedToplevel's manifest if it differs from
|
||||
// the per-platform one, which is saved below.
|
||||
if len(toplevelManifest) != 0 && !bytes.Equal(toplevelManifest, s.manifest) {
|
||||
manifestDigest, err := manifest.Digest(toplevelManifest)
|
||||
|
|
@ -1227,7 +1224,7 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
options.BigData = append(options.BigData, storage.ImageBigDataOption{
|
||||
imgOptions.BigData = append(imgOptions.BigData, storage.ImageBigDataOption{
|
||||
Key: key,
|
||||
Data: toplevelManifest,
|
||||
Digest: manifestDigest,
|
||||
|
|
@ -1240,19 +1237,19 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
options.BigData = append(options.BigData, storage.ImageBigDataOption{
|
||||
imgOptions.BigData = append(imgOptions.BigData, storage.ImageBigDataOption{
|
||||
Key: key,
|
||||
Data: s.manifest,
|
||||
Digest: s.manifestDigest,
|
||||
})
|
||||
options.BigData = append(options.BigData, storage.ImageBigDataOption{
|
||||
imgOptions.BigData = append(imgOptions.BigData, storage.ImageBigDataOption{
|
||||
Key: storage.ImageDigestBigDataKey,
|
||||
Data: s.manifest,
|
||||
Digest: s.manifestDigest,
|
||||
})
|
||||
// Set up to save the signatures, if we have any.
|
||||
if len(s.signatures) > 0 {
|
||||
options.BigData = append(options.BigData, storage.ImageBigDataOption{
|
||||
imgOptions.BigData = append(imgOptions.BigData, storage.ImageBigDataOption{
|
||||
Key: "signatures",
|
||||
Data: s.signatures,
|
||||
Digest: digest.Canonical.FromBytes(s.signatures),
|
||||
|
|
@ -1263,7 +1260,7 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
options.BigData = append(options.BigData, storage.ImageBigDataOption{
|
||||
imgOptions.BigData = append(imgOptions.BigData, storage.ImageBigDataOption{
|
||||
Key: key,
|
||||
Data: signatures,
|
||||
Digest: digest.Canonical.FromBytes(signatures),
|
||||
|
|
@ -1276,7 +1273,7 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
|
|||
return fmt.Errorf("encoding metadata for image: %w", err)
|
||||
}
|
||||
if len(metadata) != 0 {
|
||||
options.Metadata = string(metadata)
|
||||
imgOptions.Metadata = string(metadata)
|
||||
}
|
||||
|
||||
// Create the image record, pointing to the most-recently added layer.
|
||||
|
|
@ -1288,7 +1285,7 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
|
|||
}
|
||||
}
|
||||
oldNames := []string{}
|
||||
img, err := s.imageRef.transport.store.CreateImage(intendedID, nil, lastLayer, "", options)
|
||||
img, err := s.imageRef.transport.store.CreateImage(intendedID, nil, lastLayer, "", imgOptions)
|
||||
if err != nil {
|
||||
if !errors.Is(err, storage.ErrDuplicateID) {
|
||||
logrus.Debugf("error creating image: %q", err)
|
||||
|
|
@ -1309,21 +1306,21 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
|
|||
// sizes (tracked in the metadata) which might have already
|
||||
// been present with new values, when ideally we'd find a way
|
||||
// to merge them since they all apply to the same image
|
||||
for _, data := range options.BigData {
|
||||
for _, data := range imgOptions.BigData {
|
||||
if err := s.imageRef.transport.store.SetImageBigData(img.ID, data.Key, data.Data, manifest.Digest); err != nil {
|
||||
logrus.Debugf("error saving big data %q for image %q: %v", data.Key, img.ID, err)
|
||||
return fmt.Errorf("saving big data %q for image %q: %w", data.Key, img.ID, err)
|
||||
}
|
||||
}
|
||||
if options.Metadata != "" {
|
||||
if err := s.imageRef.transport.store.SetMetadata(img.ID, options.Metadata); err != nil {
|
||||
if imgOptions.Metadata != "" {
|
||||
if err := s.imageRef.transport.store.SetMetadata(img.ID, imgOptions.Metadata); err != nil {
|
||||
logrus.Debugf("error saving metadata for image %q: %v", img.ID, err)
|
||||
return fmt.Errorf("saving metadata for image %q: %w", img.ID, err)
|
||||
}
|
||||
logrus.Debugf("saved image metadata %q", options.Metadata)
|
||||
logrus.Debugf("saved image metadata %q", imgOptions.Metadata)
|
||||
}
|
||||
} else {
|
||||
logrus.Debugf("created new image ID %q with metadata %q", img.ID, options.Metadata)
|
||||
logrus.Debugf("created new image ID %q with metadata %q", img.ID, imgOptions.Metadata)
|
||||
}
|
||||
|
||||
// Clean up the unfinished image on any error.
|
||||
|
|
@ -1346,6 +1343,21 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
|
|||
}
|
||||
logrus.Debugf("added name %q to image %q", name, img.ID)
|
||||
}
|
||||
if options.ReportResolvedReference != nil {
|
||||
// FIXME? This is using nil for the named reference.
|
||||
// It would be better to also use s.imageRef.named, because that allows us to resolve to the right
|
||||
// digest / manifest (and corresponding signatures).
|
||||
// The problem with that is that resolving such a reference fails if the s.imageRef.named name is moved to a different image
|
||||
// (because it is a tag that moved, or because we have pulled “the same” image for a different architecture).
|
||||
// Right now (2024-11), ReportResolvedReference is only used in c/common/libimage, where the caller only extracts the image ID,
|
||||
// so the name does not matter; to give us options, copy.Options.ReportResolvedReference is explicitly refusing to document
|
||||
// whether the value contains a name.
|
||||
resolved, err := newReference(s.imageRef.transport, nil, intendedID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating a resolved reference for (%s, %s): %w", s.imageRef.StringWithinTransport(), intendedID, err)
|
||||
}
|
||||
*options.ReportResolvedReference = resolved
|
||||
}
|
||||
|
||||
commitSucceeded = true
|
||||
return nil
|
||||
|
|
|
|||
23
vendor/github.com/containers/storage/containers.go
generated
vendored
23
vendor/github.com/containers/storage/containers.go
generated
vendored
|
|
@ -3,7 +3,6 @@ package storage
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
|
|
@ -164,17 +163,17 @@ type containerStore struct {
|
|||
func copyContainer(c *Container) *Container {
|
||||
return &Container{
|
||||
ID: c.ID,
|
||||
Names: copyStringSlice(c.Names),
|
||||
Names: copySlicePreferringNil(c.Names),
|
||||
ImageID: c.ImageID,
|
||||
LayerID: c.LayerID,
|
||||
Metadata: c.Metadata,
|
||||
BigDataNames: copyStringSlice(c.BigDataNames),
|
||||
BigDataSizes: maps.Clone(c.BigDataSizes),
|
||||
BigDataDigests: maps.Clone(c.BigDataDigests),
|
||||
BigDataNames: copySlicePreferringNil(c.BigDataNames),
|
||||
BigDataSizes: copyMapPreferringNil(c.BigDataSizes),
|
||||
BigDataDigests: copyMapPreferringNil(c.BigDataDigests),
|
||||
Created: c.Created,
|
||||
UIDMap: copyIDMap(c.UIDMap),
|
||||
GIDMap: copyIDMap(c.GIDMap),
|
||||
Flags: maps.Clone(c.Flags),
|
||||
UIDMap: copySlicePreferringNil(c.UIDMap),
|
||||
GIDMap: copySlicePreferringNil(c.GIDMap),
|
||||
Flags: copyMapPreferringNil(c.Flags),
|
||||
volatileStore: c.volatileStore,
|
||||
}
|
||||
}
|
||||
|
|
@ -692,9 +691,9 @@ func (r *containerStore) create(id string, names []string, image, layer string,
|
|||
BigDataSizes: make(map[string]int64),
|
||||
BigDataDigests: make(map[string]digest.Digest),
|
||||
Created: time.Now().UTC(),
|
||||
Flags: copyStringInterfaceMap(options.Flags),
|
||||
UIDMap: copyIDMap(options.UIDMap),
|
||||
GIDMap: copyIDMap(options.GIDMap),
|
||||
Flags: newMapFrom(options.Flags),
|
||||
UIDMap: copySlicePreferringNil(options.UIDMap),
|
||||
GIDMap: copySlicePreferringNil(options.GIDMap),
|
||||
volatileStore: options.Volatile,
|
||||
}
|
||||
if options.MountOpts != nil {
|
||||
|
|
@ -906,7 +905,7 @@ func (r *containerStore) BigDataNames(id string) ([]string, error) {
|
|||
if !ok {
|
||||
return nil, ErrContainerUnknown
|
||||
}
|
||||
return copyStringSlice(c.BigDataNames), nil
|
||||
return copySlicePreferringNil(c.BigDataNames), nil
|
||||
}
|
||||
|
||||
// Requires startWriting.
|
||||
|
|
|
|||
5
vendor/github.com/containers/storage/drivers/copy/copy_linux.go
generated
vendored
5
vendor/github.com/containers/storage/drivers/copy/copy_linux.go
generated
vendored
|
|
@ -16,7 +16,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -199,11 +198,9 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error {
|
|||
}
|
||||
|
||||
case mode&os.ModeSocket != 0:
|
||||
s, err := net.Listen("unix", dstPath)
|
||||
if err != nil {
|
||||
if err := unix.Mknod(dstPath, stat.Mode, int(stat.Rdev)); err != nil {
|
||||
return err
|
||||
}
|
||||
s.Close()
|
||||
|
||||
case mode&os.ModeDevice != 0:
|
||||
if unshare.IsRootless() {
|
||||
|
|
|
|||
5
vendor/github.com/containers/storage/drivers/fsdiff.go
generated
vendored
5
vendor/github.com/containers/storage/drivers/fsdiff.go
generated
vendored
|
|
@ -128,6 +128,7 @@ func (gdw *NaiveDiffDriver) Changes(id string, idMappings *idtools.IDMappings, p
|
|||
|
||||
options := MountOpts{
|
||||
MountLabel: mountLabel,
|
||||
Options: []string{"ro"},
|
||||
}
|
||||
layerFs, err := driver.Get(id, options)
|
||||
if err != nil {
|
||||
|
|
@ -138,10 +139,6 @@ func (gdw *NaiveDiffDriver) Changes(id string, idMappings *idtools.IDMappings, p
|
|||
parentFs := ""
|
||||
|
||||
if parent != "" {
|
||||
options := MountOpts{
|
||||
MountLabel: mountLabel,
|
||||
Options: []string{"ro"},
|
||||
}
|
||||
parentFs, err = driver.Get(parent, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
49
vendor/github.com/containers/storage/drivers/overlay/composefs.go
generated
vendored
49
vendor/github.com/containers/storage/drivers/overlay/composefs.go
generated
vendored
|
|
@ -12,6 +12,7 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/containers/storage/pkg/chunked/dump"
|
||||
"github.com/containers/storage/pkg/fsverity"
|
||||
|
|
@ -24,6 +25,10 @@ var (
|
|||
composeFsHelperOnce sync.Once
|
||||
composeFsHelperPath string
|
||||
composeFsHelperErr error
|
||||
|
||||
// skipMountViaFile is used to avoid trying to mount EROFS directly via the file if we already know the current kernel
|
||||
// does not support it. Mounting directly via a file will be supported in kernel 6.12.
|
||||
skipMountViaFile atomic.Bool
|
||||
)
|
||||
|
||||
func getComposeFsHelper() (string, error) {
|
||||
|
|
@ -136,17 +141,15 @@ func hasACL(path string) (bool, error) {
|
|||
return binary.LittleEndian.Uint32(flags)&LCFS_EROFS_FLAGS_HAS_ACL != 0, nil
|
||||
}
|
||||
|
||||
func openComposefsMount(dataDir string) (int, error) {
|
||||
blobFile := getComposefsBlob(dataDir)
|
||||
loop, err := loopback.AttachLoopDeviceRO(blobFile)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer loop.Close()
|
||||
func openBlobFile(blobFile string, hasACL, useLoopDevice bool) (int, error) {
|
||||
if useLoopDevice {
|
||||
loop, err := loopback.AttachLoopDeviceRO(blobFile)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer loop.Close()
|
||||
|
||||
hasACL, err := hasACL(blobFile)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
blobFile = loop.Name()
|
||||
}
|
||||
|
||||
fsfd, err := unix.Fsopen("erofs", 0)
|
||||
|
|
@ -155,7 +158,7 @@ func openComposefsMount(dataDir string) (int, error) {
|
|||
}
|
||||
defer unix.Close(fsfd)
|
||||
|
||||
if err := unix.FsconfigSetString(fsfd, "source", loop.Name()); err != nil {
|
||||
if err := unix.FsconfigSetString(fsfd, "source", blobFile); err != nil {
|
||||
return -1, fmt.Errorf("failed to set source for erofs filesystem: %w", err)
|
||||
}
|
||||
|
||||
|
|
@ -172,7 +175,7 @@ func openComposefsMount(dataDir string) (int, error) {
|
|||
if err := unix.FsconfigCreate(fsfd); err != nil {
|
||||
buffer := make([]byte, 4096)
|
||||
if n, _ := unix.Read(fsfd, buffer); n > 0 {
|
||||
return -1, fmt.Errorf("failed to create erofs filesystem: %s: %w", string(buffer[:n]), err)
|
||||
return -1, fmt.Errorf("failed to create erofs filesystem: %s: %w", strings.TrimSuffix(string(buffer[:n]), "\n"), err)
|
||||
}
|
||||
return -1, fmt.Errorf("failed to create erofs filesystem: %w", err)
|
||||
}
|
||||
|
|
@ -188,6 +191,26 @@ func openComposefsMount(dataDir string) (int, error) {
|
|||
return mfd, nil
|
||||
}
|
||||
|
||||
func openComposefsMount(dataDir string) (int, error) {
|
||||
blobFile := getComposefsBlob(dataDir)
|
||||
|
||||
hasACL, err := hasACL(blobFile)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
if !skipMountViaFile.Load() {
|
||||
fd, err := openBlobFile(blobFile, hasACL, false)
|
||||
if err == nil || !errors.Is(err, unix.ENOTBLK) {
|
||||
return fd, err
|
||||
}
|
||||
logrus.Debugf("The current kernel doesn't support mounting EROFS directly from a file, fallback to a loopback device")
|
||||
skipMountViaFile.Store(true)
|
||||
}
|
||||
|
||||
return openBlobFile(blobFile, hasACL, true)
|
||||
}
|
||||
|
||||
func mountComposefsBlob(dataDir, mountPoint string) error {
|
||||
mfd, err := openComposefsMount(dataDir)
|
||||
if err != nil {
|
||||
|
|
@ -196,7 +219,7 @@ func mountComposefsBlob(dataDir, mountPoint string) error {
|
|||
defer unix.Close(mfd)
|
||||
|
||||
if err := unix.MoveMount(mfd, "", unix.AT_FDCWD, mountPoint, unix.MOVE_MOUNT_F_EMPTY_PATH); err != nil {
|
||||
return fmt.Errorf("failed to move mount: %w", err)
|
||||
return fmt.Errorf("failed to move mount to %q: %w", mountPoint, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
20
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
20
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
|
|
@ -589,7 +589,7 @@ func parseOptions(options []string) (*overlayOptions, error) {
|
|||
m := os.FileMode(mask)
|
||||
o.forceMask = &m
|
||||
default:
|
||||
return nil, fmt.Errorf("overlay: Unknown option %s", key)
|
||||
return nil, fmt.Errorf("overlay: unknown option %s", key)
|
||||
}
|
||||
}
|
||||
return o, nil
|
||||
|
|
@ -1579,7 +1579,6 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
|||
}()
|
||||
|
||||
composeFsLayers := []string{}
|
||||
composeFsLayersDir := filepath.Join(dir, "composefs-layers")
|
||||
maybeAddComposefsMount := func(lowerID string, i int, readWrite bool) (string, error) {
|
||||
composefsBlob := d.getComposefsData(lowerID)
|
||||
if err := fileutils.Exists(composefsBlob); err != nil {
|
||||
|
|
@ -1594,7 +1593,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
|||
return "", fmt.Errorf("cannot mount a composefs layer as writeable")
|
||||
}
|
||||
|
||||
dest := filepath.Join(composeFsLayersDir, strconv.Itoa(i))
|
||||
dest := d.getStorePrivateDirectory(id, dir, fmt.Sprintf("composefs-layers/%d", i), inAdditionalStore)
|
||||
if err := os.MkdirAll(dest, 0o700); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -1878,6 +1877,16 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
|||
return mergedDir, nil
|
||||
}
|
||||
|
||||
// getStorePrivateDirectory returns a directory path for storing data that requires exclusive access.
|
||||
// If 'inAdditionalStore' is true, the path will be under the rundir, otherwise it will be placed in
|
||||
// the primary store.
|
||||
func (d *Driver) getStorePrivateDirectory(id, layerDir, subdir string, inAdditionalStore bool) string {
|
||||
if inAdditionalStore {
|
||||
return path.Join(d.runhome, id, subdir)
|
||||
}
|
||||
return path.Join(layerDir, subdir)
|
||||
}
|
||||
|
||||
// getMergedDir returns the directory path that should be used as the mount point for the overlayfs.
|
||||
func (d *Driver) getMergedDir(id, dir string, inAdditionalStore bool) string {
|
||||
// Ordinarily, .Get() (layer mounting) callers are supposed to guarantee exclusion.
|
||||
|
|
@ -1897,10 +1906,7 @@ func (d *Driver) getMergedDir(id, dir string, inAdditionalStore bool) string {
|
|||
// TO DO: LOCKING BUG: the .DiffSize operation does not currently hold an exclusive lock on the primary store.
|
||||
// (_Some_ of the callers might be better ported to use a metadata-only size computation instead of DiffSize,
|
||||
// but DiffSize probably needs to remain for computing sizes of container’s RW layers.)
|
||||
if inAdditionalStore {
|
||||
return path.Join(d.runhome, id, "merged")
|
||||
}
|
||||
return path.Join(dir, "merged")
|
||||
return d.getStorePrivateDirectory(id, dir, "merged", inAdditionalStore)
|
||||
}
|
||||
|
||||
// Put unmounts the mount path created for the give id.
|
||||
|
|
|
|||
23
vendor/github.com/containers/storage/images.go
generated
vendored
23
vendor/github.com/containers/storage/images.go
generated
vendored
|
|
@ -2,7 +2,6 @@ package storage
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
|
|
@ -183,18 +182,18 @@ func copyImage(i *Image) *Image {
|
|||
return &Image{
|
||||
ID: i.ID,
|
||||
Digest: i.Digest,
|
||||
Digests: copyDigestSlice(i.Digests),
|
||||
Names: copyStringSlice(i.Names),
|
||||
NamesHistory: copyStringSlice(i.NamesHistory),
|
||||
Digests: copySlicePreferringNil(i.Digests),
|
||||
Names: copySlicePreferringNil(i.Names),
|
||||
NamesHistory: copySlicePreferringNil(i.NamesHistory),
|
||||
TopLayer: i.TopLayer,
|
||||
MappedTopLayers: copyStringSlice(i.MappedTopLayers),
|
||||
MappedTopLayers: copySlicePreferringNil(i.MappedTopLayers),
|
||||
Metadata: i.Metadata,
|
||||
BigDataNames: copyStringSlice(i.BigDataNames),
|
||||
BigDataSizes: maps.Clone(i.BigDataSizes),
|
||||
BigDataDigests: maps.Clone(i.BigDataDigests),
|
||||
BigDataNames: copySlicePreferringNil(i.BigDataNames),
|
||||
BigDataSizes: copyMapPreferringNil(i.BigDataSizes),
|
||||
BigDataDigests: copyMapPreferringNil(i.BigDataDigests),
|
||||
Created: i.Created,
|
||||
ReadOnly: i.ReadOnly,
|
||||
Flags: maps.Clone(i.Flags),
|
||||
Flags: copyMapPreferringNil(i.Flags),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -718,14 +717,14 @@ func (r *imageStore) create(id string, names []string, layer string, options Ima
|
|||
Digest: options.Digest,
|
||||
Digests: dedupeDigests(options.Digests),
|
||||
Names: names,
|
||||
NamesHistory: copyStringSlice(options.NamesHistory),
|
||||
NamesHistory: copySlicePreferringNil(options.NamesHistory),
|
||||
TopLayer: layer,
|
||||
Metadata: options.Metadata,
|
||||
BigDataNames: []string{},
|
||||
BigDataSizes: make(map[string]int64),
|
||||
BigDataDigests: make(map[string]digest.Digest),
|
||||
Created: options.CreationDate,
|
||||
Flags: copyStringInterfaceMap(options.Flags),
|
||||
Flags: newMapFrom(options.Flags),
|
||||
}
|
||||
if image.Created.IsZero() {
|
||||
image.Created = time.Now().UTC()
|
||||
|
|
@ -967,7 +966,7 @@ func (r *imageStore) BigDataNames(id string) ([]string, error) {
|
|||
if !ok {
|
||||
return nil, fmt.Errorf("locating image with ID %q: %w", id, ErrImageUnknown)
|
||||
}
|
||||
return copyStringSlice(image.BigDataNames), nil
|
||||
return copySlicePreferringNil(image.BigDataNames), nil
|
||||
}
|
||||
|
||||
// Requires startWriting.
|
||||
|
|
|
|||
22
vendor/github.com/containers/storage/layers.go
generated
vendored
22
vendor/github.com/containers/storage/layers.go
generated
vendored
|
|
@ -439,7 +439,7 @@ func layerLocation(l *Layer) layerLocations {
|
|||
func copyLayer(l *Layer) *Layer {
|
||||
return &Layer{
|
||||
ID: l.ID,
|
||||
Names: copyStringSlice(l.Names),
|
||||
Names: copySlicePreferringNil(l.Names),
|
||||
Parent: l.Parent,
|
||||
Metadata: l.Metadata,
|
||||
MountLabel: l.MountLabel,
|
||||
|
|
@ -454,12 +454,12 @@ func copyLayer(l *Layer) *Layer {
|
|||
CompressionType: l.CompressionType,
|
||||
ReadOnly: l.ReadOnly,
|
||||
volatileStore: l.volatileStore,
|
||||
BigDataNames: copyStringSlice(l.BigDataNames),
|
||||
Flags: maps.Clone(l.Flags),
|
||||
UIDMap: copyIDMap(l.UIDMap),
|
||||
GIDMap: copyIDMap(l.GIDMap),
|
||||
UIDs: copyUint32Slice(l.UIDs),
|
||||
GIDs: copyUint32Slice(l.GIDs),
|
||||
BigDataNames: copySlicePreferringNil(l.BigDataNames),
|
||||
Flags: copyMapPreferringNil(l.Flags),
|
||||
UIDMap: copySlicePreferringNil(l.UIDMap),
|
||||
GIDMap: copySlicePreferringNil(l.GIDMap),
|
||||
UIDs: copySlicePreferringNil(l.UIDs),
|
||||
GIDs: copySlicePreferringNil(l.GIDs),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1406,9 +1406,9 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
|
|||
CompressionType: templateCompressionType,
|
||||
UIDs: templateUIDs,
|
||||
GIDs: templateGIDs,
|
||||
Flags: copyStringInterfaceMap(moreOptions.Flags),
|
||||
UIDMap: copyIDMap(moreOptions.UIDMap),
|
||||
GIDMap: copyIDMap(moreOptions.GIDMap),
|
||||
Flags: newMapFrom(moreOptions.Flags),
|
||||
UIDMap: copySlicePreferringNil(moreOptions.UIDMap),
|
||||
GIDMap: copySlicePreferringNil(moreOptions.GIDMap),
|
||||
BigDataNames: []string{},
|
||||
volatileStore: moreOptions.Volatile,
|
||||
}
|
||||
|
|
@ -1843,7 +1843,7 @@ func (r *layerStore) BigDataNames(id string) ([]string, error) {
|
|||
if !ok {
|
||||
return nil, fmt.Errorf("locating layer with ID %q to retrieve bigdata names: %w", id, ErrImageUnknown)
|
||||
}
|
||||
return copyStringSlice(layer.BigDataNames), nil
|
||||
return copySlicePreferringNil(layer.BigDataNames), nil
|
||||
}
|
||||
|
||||
// Requires startReading or startWriting.
|
||||
|
|
|
|||
117
vendor/github.com/containers/storage/pkg/chunked/storage_linux.go
generated
vendored
117
vendor/github.com/containers/storage/pkg/chunked/storage_linux.go
generated
vendored
|
|
@ -149,62 +149,90 @@ func (c *chunkedDiffer) convertTarToZstdChunked(destDirectory string, payload *o
|
|||
func GetDiffer(ctx context.Context, store storage.Store, blobDigest digest.Digest, blobSize int64, annotations map[string]string, iss ImageSourceSeekable) (graphdriver.Differ, error) {
|
||||
pullOptions := store.PullOptions()
|
||||
|
||||
if !parseBooleanPullOption(pullOptions, "enable_partial_images", true) {
|
||||
if !parseBooleanPullOption(pullOptions, "enable_partial_images", false) {
|
||||
// If convertImages is set, the two options disagree whether fallback is permissible.
|
||||
// Right now, we enable it, but that’s not a promise; rather, such a configuration should ideally be rejected.
|
||||
return nil, newErrFallbackToOrdinaryLayerDownload(errors.New("partial images are disabled"))
|
||||
}
|
||||
// convertImages also serves as a “must not fallback to non-partial pull” option (?!)
|
||||
convertImages := parseBooleanPullOption(pullOptions, "convert_images", false)
|
||||
|
||||
graphDriver, err := store.GraphDriver()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, partialSupported := graphDriver.(graphdriver.DriverWithDiffer); !partialSupported {
|
||||
if convertImages {
|
||||
return nil, fmt.Errorf("graph driver %s does not support partial pull but convert_images requires that", graphDriver.String())
|
||||
}
|
||||
return nil, newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("graph driver %s does not support partial pull", graphDriver.String()))
|
||||
}
|
||||
|
||||
differ, canFallback, err := getProperDiffer(store, blobDigest, blobSize, annotations, iss, pullOptions)
|
||||
if err != nil {
|
||||
if !canFallback {
|
||||
return nil, err
|
||||
}
|
||||
// If convert_images is enabled, always attempt to convert it instead of returning an error or falling back to a different method.
|
||||
if convertImages {
|
||||
logrus.Debugf("Created differ to convert blob %q", blobDigest)
|
||||
return makeConvertFromRawDiffer(store, blobDigest, blobSize, iss, pullOptions)
|
||||
}
|
||||
return nil, newErrFallbackToOrdinaryLayerDownload(err)
|
||||
}
|
||||
|
||||
return differ, nil
|
||||
}
|
||||
|
||||
// getProperDiffer is an implementation detail of GetDiffer.
|
||||
// It returns a “proper” differ (not a convert_images one) if possible.
|
||||
// On error, the second parameter is true if a fallback to an alternative (either the makeConverToRaw differ, or a non-partial pull)
|
||||
// is permissible.
|
||||
func getProperDiffer(store storage.Store, blobDigest digest.Digest, blobSize int64, annotations map[string]string, iss ImageSourceSeekable, pullOptions map[string]string) (graphdriver.Differ, bool, error) {
|
||||
zstdChunkedTOCDigestString, hasZstdChunkedTOC := annotations[internal.ManifestChecksumKey]
|
||||
estargzTOCDigestString, hasEstargzTOC := annotations[estargz.TOCJSONDigestAnnotation]
|
||||
|
||||
if hasZstdChunkedTOC && hasEstargzTOC {
|
||||
return nil, errors.New("both zstd:chunked and eStargz TOC found")
|
||||
}
|
||||
switch {
|
||||
case hasZstdChunkedTOC && hasEstargzTOC:
|
||||
return nil, false, errors.New("both zstd:chunked and eStargz TOC found")
|
||||
|
||||
convertImages := parseBooleanPullOption(pullOptions, "convert_images", false)
|
||||
|
||||
if !hasZstdChunkedTOC && !hasEstargzTOC && !convertImages {
|
||||
return nil, newErrFallbackToOrdinaryLayerDownload(errors.New("no TOC found and convert_images is not configured"))
|
||||
}
|
||||
|
||||
var err error
|
||||
var differ graphdriver.Differ
|
||||
// At this point one of hasZstdChunkedTOC, hasEstargzTOC or convertImages is true.
|
||||
if hasZstdChunkedTOC {
|
||||
zstdChunkedTOCDigest, err2 := digest.Parse(zstdChunkedTOCDigestString)
|
||||
if err2 != nil {
|
||||
return nil, err2
|
||||
case hasZstdChunkedTOC:
|
||||
zstdChunkedTOCDigest, err := digest.Parse(zstdChunkedTOCDigestString)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
differ, err = makeZstdChunkedDiffer(store, blobSize, zstdChunkedTOCDigest, annotations, iss, pullOptions)
|
||||
if err == nil {
|
||||
logrus.Debugf("Created zstd:chunked differ for blob %q", blobDigest)
|
||||
return differ, err
|
||||
differ, err := makeZstdChunkedDiffer(store, blobSize, zstdChunkedTOCDigest, annotations, iss, pullOptions)
|
||||
if err != nil {
|
||||
logrus.Debugf("Could not create zstd:chunked differ for blob %q: %v", blobDigest, err)
|
||||
// If the error is a bad request to the server, then signal to the caller that it can try a different method.
|
||||
var badRequestErr ErrBadRequest
|
||||
return nil, errors.As(err, &badRequestErr), err
|
||||
}
|
||||
} else if hasEstargzTOC {
|
||||
estargzTOCDigest, err2 := digest.Parse(estargzTOCDigestString)
|
||||
if err2 != nil {
|
||||
return nil, err
|
||||
}
|
||||
differ, err = makeEstargzChunkedDiffer(store, blobSize, estargzTOCDigest, iss, pullOptions)
|
||||
if err == nil {
|
||||
logrus.Debugf("Created eStargz differ for blob %q", blobDigest)
|
||||
return differ, err
|
||||
}
|
||||
}
|
||||
// If convert_images is enabled, always attempt to convert it instead of returning an error or falling back to a different method.
|
||||
if convertImages {
|
||||
logrus.Debugf("Created differ to convert blob %q", blobDigest)
|
||||
return makeConvertFromRawDiffer(store, blobDigest, blobSize, iss, pullOptions)
|
||||
}
|
||||
logrus.Debugf("Created zstd:chunked differ for blob %q", blobDigest)
|
||||
return differ, false, nil
|
||||
|
||||
logrus.Debugf("Could not create differ for blob %q: %v", blobDigest, err)
|
||||
case hasEstargzTOC:
|
||||
estargzTOCDigest, err := digest.Parse(estargzTOCDigestString)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
differ, err := makeEstargzChunkedDiffer(store, blobSize, estargzTOCDigest, iss, pullOptions)
|
||||
if err != nil {
|
||||
logrus.Debugf("Could not create estargz differ for blob %q: %v", blobDigest, err)
|
||||
// If the error is a bad request to the server, then signal to the caller that it can try a different method.
|
||||
var badRequestErr ErrBadRequest
|
||||
return nil, errors.As(err, &badRequestErr), err
|
||||
}
|
||||
logrus.Debugf("Created eStargz differ for blob %q", blobDigest)
|
||||
return differ, false, nil
|
||||
|
||||
// If the error is a bad request to the server, then signal to the caller that it can try a different method. This can be done
|
||||
// only when convert_images is disabled.
|
||||
var badRequestErr ErrBadRequest
|
||||
if errors.As(err, &badRequestErr) {
|
||||
err = newErrFallbackToOrdinaryLayerDownload(err)
|
||||
default: // no TOC
|
||||
convertImages := parseBooleanPullOption(pullOptions, "convert_images", false)
|
||||
if !convertImages {
|
||||
return nil, true, errors.New("no TOC found and convert_images is not configured")
|
||||
}
|
||||
return nil, true, errors.New("no TOC found")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func makeConvertFromRawDiffer(store storage.Store, blobDigest digest.Digest, blobSize int64, iss ImageSourceSeekable, pullOptions map[string]string) (*chunkedDiffer, error) {
|
||||
|
|
@ -1139,6 +1167,7 @@ func (c *chunkedDiffer) copyAllBlobToFile(destination *os.File) (digest.Digest,
|
|||
if payload == nil {
|
||||
return "", errors.New("invalid stream returned")
|
||||
}
|
||||
defer payload.Close()
|
||||
|
||||
originalRawDigester := digest.Canonical.Digester()
|
||||
|
||||
|
|
|
|||
18
vendor/github.com/containers/storage/storage.conf
generated
vendored
18
vendor/github.com/containers/storage/storage.conf
generated
vendored
|
|
@ -8,12 +8,12 @@
|
|||
# /usr/containers/storage.conf
|
||||
# /etc/containers/storage.conf
|
||||
# $HOME/.config/containers/storage.conf
|
||||
# $XDG_CONFIG_HOME/containers/storage.conf (If XDG_CONFIG_HOME is set)
|
||||
# $XDG_CONFIG_HOME/containers/storage.conf (if XDG_CONFIG_HOME is set)
|
||||
# See man 5 containers-storage.conf for more information
|
||||
# The "container storage" table contains all of the server options.
|
||||
# The "storage" table contains all of the server options.
|
||||
[storage]
|
||||
|
||||
# Default Storage Driver, Must be set for proper operation.
|
||||
# Default storage driver, must be set for proper operation.
|
||||
driver = "overlay"
|
||||
|
||||
# Temporary storage location
|
||||
|
|
@ -24,8 +24,8 @@ runroot = "/run/containers/storage"
|
|||
# driver_priority = ["overlay", "btrfs"]
|
||||
|
||||
# Primary Read/Write location of container storage
|
||||
# When changing the graphroot location on an SELINUX system, you must
|
||||
# ensure the labeling matches the default locations labels with the
|
||||
# When changing the graphroot location on an SELinux system, you must
|
||||
# ensure the labeling matches the default location's labels with the
|
||||
# following commands:
|
||||
# semanage fcontext -a -e /var/lib/containers/storage /NEWSTORAGEPATH
|
||||
# restorecon -R -v /NEWSTORAGEPATH
|
||||
|
|
@ -54,14 +54,14 @@ graphroot = "/var/lib/containers/storage"
|
|||
additionalimagestores = [
|
||||
]
|
||||
|
||||
# Options controlling how storage is populated when pulling images.
|
||||
# Options controlling how storage is populated when pulling images.
|
||||
[storage.options.pull_options]
|
||||
# Enable the "zstd:chunked" feature, which allows partial pulls, reusing
|
||||
# content that already exists on the system. This is enabled by default,
|
||||
# but can be explicitly disabled. For more on zstd:chunked, see
|
||||
# content that already exists on the system. This is disabled by default,
|
||||
# and must be explicitly enabled to be used. For more on zstd:chunked, see
|
||||
# https://github.com/containers/storage/blob/main/docs/containers-storage-zstd-chunked.md
|
||||
# This is a "string bool": "false" | "true" (cannot be native TOML boolean)
|
||||
# enable_partial_images = "true"
|
||||
# enable_partial_images = "false"
|
||||
|
||||
# Tells containers/storage to use hard links rather then create new files in
|
||||
# the image, if an identical file already existed in storage.
|
||||
|
|
|
|||
138
vendor/github.com/containers/storage/store.go
generated
vendored
138
vendor/github.com/containers/storage/store.go
generated
vendored
|
|
@ -877,8 +877,8 @@ func GetStore(options types.StoreOptions) (Store, error) {
|
|||
graphOptions: options.GraphDriverOptions,
|
||||
imageStoreDir: options.ImageStore,
|
||||
pullOptions: options.PullOptions,
|
||||
uidMap: copyIDMap(options.UIDMap),
|
||||
gidMap: copyIDMap(options.GIDMap),
|
||||
uidMap: copySlicePreferringNil(options.UIDMap),
|
||||
gidMap: copySlicePreferringNil(options.GIDMap),
|
||||
autoUsernsUser: options.RootAutoNsUser,
|
||||
autoNsMinSize: autoNsMinSize,
|
||||
autoNsMaxSize: autoNsMaxSize,
|
||||
|
|
@ -897,30 +897,6 @@ func GetStore(options types.StoreOptions) (Store, error) {
|
|||
return s, nil
|
||||
}
|
||||
|
||||
func copyUint32Slice(slice []uint32) []uint32 {
|
||||
m := []uint32{}
|
||||
if slice != nil {
|
||||
m = make([]uint32, len(slice))
|
||||
copy(m, slice)
|
||||
}
|
||||
if len(m) > 0 {
|
||||
return m[:]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyIDMap(idmap []idtools.IDMap) []idtools.IDMap {
|
||||
m := []idtools.IDMap{}
|
||||
if idmap != nil {
|
||||
m = make([]idtools.IDMap, len(idmap))
|
||||
copy(m, idmap)
|
||||
}
|
||||
if len(m) > 0 {
|
||||
return m[:]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *store) RunRoot() string {
|
||||
return s.runRoot
|
||||
}
|
||||
|
|
@ -952,11 +928,11 @@ func (s *store) PullOptions() map[string]string {
|
|||
}
|
||||
|
||||
func (s *store) UIDMap() []idtools.IDMap {
|
||||
return copyIDMap(s.uidMap)
|
||||
return copySlicePreferringNil(s.uidMap)
|
||||
}
|
||||
|
||||
func (s *store) GIDMap() []idtools.IDMap {
|
||||
return copyIDMap(s.gidMap)
|
||||
return copySlicePreferringNil(s.gidMap)
|
||||
}
|
||||
|
||||
// This must only be called when constructing store; it writes to fields that are assumed to be constant after construction.
|
||||
|
|
@ -1469,8 +1445,8 @@ func (s *store) putLayer(rlstore rwLayerStore, rlstores []roLayerStore, id, pare
|
|||
var options LayerOptions
|
||||
if lOptions != nil {
|
||||
options = *lOptions
|
||||
options.BigData = copyLayerBigDataOptionSlice(lOptions.BigData)
|
||||
options.Flags = maps.Clone(lOptions.Flags)
|
||||
options.BigData = slices.Clone(lOptions.BigData)
|
||||
options.Flags = copyMapPreferringNil(lOptions.Flags)
|
||||
}
|
||||
if options.HostUIDMapping {
|
||||
options.UIDMap = nil
|
||||
|
|
@ -1541,8 +1517,8 @@ func (s *store) putLayer(rlstore rwLayerStore, rlstores []roLayerStore, id, pare
|
|||
options.IDMappingOptions = types.IDMappingOptions{
|
||||
HostUIDMapping: options.HostUIDMapping,
|
||||
HostGIDMapping: options.HostGIDMapping,
|
||||
UIDMap: copyIDMap(uidMap),
|
||||
GIDMap: copyIDMap(gidMap),
|
||||
UIDMap: copySlicePreferringNil(uidMap),
|
||||
GIDMap: copySlicePreferringNil(gidMap),
|
||||
}
|
||||
}
|
||||
return rlstore.create(id, parentLayer, names, mountLabel, nil, &options, writeable, diff, slo)
|
||||
|
|
@ -1610,8 +1586,8 @@ func (s *store) CreateImage(id string, names []string, layer, metadata string, i
|
|||
Metadata: i.Metadata,
|
||||
CreationDate: i.Created,
|
||||
Digest: i.Digest,
|
||||
Digests: copyDigestSlice(i.Digests),
|
||||
NamesHistory: copyStringSlice(i.NamesHistory),
|
||||
Digests: copySlicePreferringNil(i.Digests),
|
||||
NamesHistory: copySlicePreferringNil(i.NamesHistory),
|
||||
}
|
||||
for _, key := range i.BigDataNames {
|
||||
data, err := store.BigData(id, key)
|
||||
|
|
@ -1760,8 +1736,8 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore roImageStore, rlst
|
|||
layerOptions.IDMappingOptions = types.IDMappingOptions{
|
||||
HostUIDMapping: options.HostUIDMapping,
|
||||
HostGIDMapping: options.HostGIDMapping,
|
||||
UIDMap: copyIDMap(options.UIDMap),
|
||||
GIDMap: copyIDMap(options.GIDMap),
|
||||
UIDMap: copySlicePreferringNil(options.UIDMap),
|
||||
GIDMap: copySlicePreferringNil(options.GIDMap),
|
||||
}
|
||||
}
|
||||
layerOptions.TemplateLayer = layer.ID
|
||||
|
|
@ -1783,12 +1759,12 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
|
|||
var options ContainerOptions
|
||||
if cOptions != nil {
|
||||
options = *cOptions
|
||||
options.IDMappingOptions.UIDMap = copyIDMap(cOptions.IDMappingOptions.UIDMap)
|
||||
options.IDMappingOptions.GIDMap = copyIDMap(cOptions.IDMappingOptions.GIDMap)
|
||||
options.LabelOpts = copyStringSlice(cOptions.LabelOpts)
|
||||
options.Flags = maps.Clone(cOptions.Flags)
|
||||
options.MountOpts = copyStringSlice(cOptions.MountOpts)
|
||||
options.StorageOpt = copyStringStringMap(cOptions.StorageOpt)
|
||||
options.IDMappingOptions.UIDMap = copySlicePreferringNil(cOptions.IDMappingOptions.UIDMap)
|
||||
options.IDMappingOptions.GIDMap = copySlicePreferringNil(cOptions.IDMappingOptions.GIDMap)
|
||||
options.LabelOpts = copySlicePreferringNil(cOptions.LabelOpts)
|
||||
options.Flags = copyMapPreferringNil(cOptions.Flags)
|
||||
options.MountOpts = copySlicePreferringNil(cOptions.MountOpts)
|
||||
options.StorageOpt = copyMapPreferringNil(cOptions.StorageOpt)
|
||||
options.BigData = copyContainerBigDataOptionSlice(cOptions.BigData)
|
||||
}
|
||||
if options.HostUIDMapping {
|
||||
|
|
@ -1913,8 +1889,8 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
|
|||
layerOptions.IDMappingOptions = types.IDMappingOptions{
|
||||
HostUIDMapping: idMappingsOptions.HostUIDMapping,
|
||||
HostGIDMapping: idMappingsOptions.HostGIDMapping,
|
||||
UIDMap: copyIDMap(uidMap),
|
||||
GIDMap: copyIDMap(gidMap),
|
||||
UIDMap: copySlicePreferringNil(uidMap),
|
||||
GIDMap: copySlicePreferringNil(gidMap),
|
||||
}
|
||||
}
|
||||
if options.Flags == nil {
|
||||
|
|
@ -1951,8 +1927,8 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
|
|||
options.IDMappingOptions = types.IDMappingOptions{
|
||||
HostUIDMapping: len(options.UIDMap) == 0,
|
||||
HostGIDMapping: len(options.GIDMap) == 0,
|
||||
UIDMap: copyIDMap(options.UIDMap),
|
||||
GIDMap: copyIDMap(options.GIDMap),
|
||||
UIDMap: copySlicePreferringNil(options.UIDMap),
|
||||
GIDMap: copySlicePreferringNil(options.GIDMap),
|
||||
}
|
||||
container, err := s.containerStore.create(id, names, imageID, layer, &options)
|
||||
if err != nil || container == nil {
|
||||
|
|
@ -2450,10 +2426,10 @@ func (s *store) updateNames(id string, names []string, op updateNameOperation) e
|
|||
options := ImageOptions{
|
||||
CreationDate: i.Created,
|
||||
Digest: i.Digest,
|
||||
Digests: copyDigestSlice(i.Digests),
|
||||
Digests: copySlicePreferringNil(i.Digests),
|
||||
Metadata: i.Metadata,
|
||||
NamesHistory: copyStringSlice(i.NamesHistory),
|
||||
Flags: copyStringInterfaceMap(i.Flags),
|
||||
NamesHistory: copySlicePreferringNil(i.NamesHistory),
|
||||
Flags: copyMapPreferringNil(i.Flags),
|
||||
}
|
||||
for _, key := range i.BigDataNames {
|
||||
data, err := store.BigData(id, key)
|
||||
|
|
@ -3674,58 +3650,42 @@ func makeBigDataBaseName(key string) string {
|
|||
}
|
||||
|
||||
func stringSliceWithoutValue(slice []string, value string) []string {
|
||||
modified := make([]string, 0, len(slice))
|
||||
for _, v := range slice {
|
||||
if v == value {
|
||||
continue
|
||||
}
|
||||
modified = append(modified, v)
|
||||
}
|
||||
return modified
|
||||
return slices.DeleteFunc(slices.Clone(slice), func(v string) bool {
|
||||
return v == value
|
||||
})
|
||||
}
|
||||
|
||||
func copyStringSlice(slice []string) []string {
|
||||
if len(slice) == 0 {
|
||||
// copySlicePreferringNil returns a copy of the slice.
|
||||
// If s is empty, a nil is returned.
|
||||
func copySlicePreferringNil[S ~[]E, E any](s S) S {
|
||||
if len(s) == 0 {
|
||||
return nil
|
||||
}
|
||||
ret := make([]string, len(slice))
|
||||
copy(ret, slice)
|
||||
return ret
|
||||
return slices.Clone(s)
|
||||
}
|
||||
|
||||
func copyStringStringMap(m map[string]string) map[string]string {
|
||||
ret := make(map[string]string, len(m))
|
||||
// copyMapPreferringNil returns a shallow clone of map m.
|
||||
// If m is empty, a nil is returned.
|
||||
//
|
||||
// (As of, e.g., Go 1.23, maps.Clone preserves nil, but that’s not a documented promise;
|
||||
// and this function turns even non-nil empty maps into nil.)
|
||||
func copyMapPreferringNil[K comparable, V any](m map[K]V) map[K]V {
|
||||
if len(m) == 0 {
|
||||
return nil
|
||||
}
|
||||
return maps.Clone(m)
|
||||
}
|
||||
|
||||
// newMapFrom returns a shallow clone of map m.
|
||||
// If m is empty, an empty map is allocated and returned.
|
||||
func newMapFrom[K comparable, V any](m map[K]V) map[K]V {
|
||||
ret := make(map[K]V, len(m))
|
||||
for k, v := range m {
|
||||
ret[k] = v
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func copyDigestSlice(slice []digest.Digest) []digest.Digest {
|
||||
if len(slice) == 0 {
|
||||
return nil
|
||||
}
|
||||
ret := make([]digest.Digest, len(slice))
|
||||
copy(ret, slice)
|
||||
return ret
|
||||
}
|
||||
|
||||
// copyStringInterfaceMap still forces us to assume that the interface{} is
|
||||
// a non-pointer scalar value
|
||||
func copyStringInterfaceMap(m map[string]interface{}) map[string]interface{} {
|
||||
ret := make(map[string]interface{}, len(m))
|
||||
for k, v := range m {
|
||||
ret[k] = v
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func copyLayerBigDataOptionSlice(slice []LayerBigDataOption) []LayerBigDataOption {
|
||||
ret := make([]LayerBigDataOption, len(slice))
|
||||
copy(ret, slice)
|
||||
return ret
|
||||
}
|
||||
|
||||
func copyImageBigDataOptionSlice(slice []ImageBigDataOption) []ImageBigDataOption {
|
||||
ret := make([]ImageBigDataOption, len(slice))
|
||||
for i := range slice {
|
||||
|
|
|
|||
7
vendor/github.com/fsnotify/fsnotify/.cirrus.yml
generated
vendored
7
vendor/github.com/fsnotify/fsnotify/.cirrus.yml
generated
vendored
|
|
@ -1,7 +1,7 @@
|
|||
freebsd_task:
|
||||
name: 'FreeBSD'
|
||||
freebsd_instance:
|
||||
image_family: freebsd-13-2
|
||||
image_family: freebsd-14-1
|
||||
install_script:
|
||||
- pkg update -f
|
||||
- pkg install -y go
|
||||
|
|
@ -9,5 +9,6 @@ freebsd_task:
|
|||
# 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_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 ./...
|
||||
|
|
|
|||
12
vendor/github.com/fsnotify/fsnotify/.editorconfig
generated
vendored
12
vendor/github.com/fsnotify/fsnotify/.editorconfig
generated
vendored
|
|
@ -1,12 +0,0 @@
|
|||
root = true
|
||||
|
||||
[*.go]
|
||||
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
|
||||
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
|
||||
3
vendor/github.com/fsnotify/fsnotify/.gitignore
generated
vendored
3
vendor/github.com/fsnotify/fsnotify/.gitignore
generated
vendored
|
|
@ -5,3 +5,6 @@
|
|||
# Output of go build ./cmd/fsnotify
|
||||
/fsnotify
|
||||
/fsnotify.exe
|
||||
|
||||
/test/kqueue
|
||||
/test/a.out
|
||||
|
|
|
|||
34
vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
generated
vendored
34
vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
generated
vendored
|
|
@ -1,8 +1,36 @@
|
|||
# Changelog
|
||||
|
||||
Unreleased
|
||||
----------
|
||||
Nothing yet.
|
||||
1.8.0 2023-10-31
|
||||
----------------
|
||||
|
||||
### Additions
|
||||
|
||||
- all: add `FSNOTIFY_DEBUG` to print debug logs to stderr ([#619])
|
||||
|
||||
### Changes and fixes
|
||||
|
||||
- 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
|
||||
------------------
|
||||
|
|
|
|||
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
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
[Vagrant]: https://www.vagrantup.com/
|
||||
|
|
|
|||
324
vendor/github.com/fsnotify/fsnotify/backend_fen.go
generated
vendored
324
vendor/github.com/fsnotify/fsnotify/backend_fen.go
generated
vendored
|
|
@ -1,8 +1,8 @@
|
|||
//go:build solaris
|
||||
// +build solaris
|
||||
|
||||
// Note: the documentation on the Watcher type and methods is generated from
|
||||
// mkdoc.zsh
|
||||
// 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
|
||||
|
||||
|
|
@ -12,150 +12,33 @@ import (
|
|||
"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.
|
||||
//
|
||||
// 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 times, 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 {
|
||||
// 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.
|
||||
type fen struct {
|
||||
Events chan Event
|
||||
|
||||
// Errors sends any errors.
|
||||
//
|
||||
// ErrEventOverflow is used to indicate there are too many events:
|
||||
//
|
||||
// - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl)
|
||||
// - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
|
||||
// - kqueue, fen: Not used.
|
||||
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]struct{} // Explicitly watched directories
|
||||
watches map[string]struct{} // Explicitly watched non-directories
|
||||
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 NewWatcher() (*Watcher, error) {
|
||||
return NewBufferedWatcher(0)
|
||||
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||
return newBufferedBackend(0, ev, errs)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
w := &Watcher{
|
||||
Events: make(chan Event, sz),
|
||||
Errors: make(chan error),
|
||||
dirs: make(map[string]struct{}),
|
||||
watches: make(map[string]struct{}),
|
||||
func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
|
||||
w := &fen{
|
||||
Events: ev,
|
||||
Errors: errs,
|
||||
dirs: make(map[string]Op),
|
||||
watches: make(map[string]Op),
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
|
||||
|
|
@ -171,27 +54,30 @@ func NewBufferedWatcher(sz uint) (*Watcher, error) {
|
|||
|
||||
// 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 *Watcher) sendEvent(name string, op Op) (sent bool) {
|
||||
func (w *fen) sendEvent(name string, op Op) (sent bool) {
|
||||
select {
|
||||
case w.Events <- Event{Name: name, Op: op}:
|
||||
return true
|
||||
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 *Watcher) sendError(err error) (sent bool) {
|
||||
select {
|
||||
case w.Errors <- err:
|
||||
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 *Watcher) isClosed() bool {
|
||||
func (w *fen) isClosed() bool {
|
||||
select {
|
||||
case <-w.done:
|
||||
return true
|
||||
|
|
@ -200,8 +86,7 @@ func (w *Watcher) isClosed() bool {
|
|||
}
|
||||
}
|
||||
|
||||
// Close removes all watches and closes the Events channel.
|
||||
func (w *Watcher) Close() error {
|
||||
func (w *fen) Close() error {
|
||||
// Take the lock used by associateFile to prevent lingering events from
|
||||
// being processed after the close
|
||||
w.mu.Lock()
|
||||
|
|
@ -213,60 +98,21 @@ func (w *Watcher) Close() error {
|
|||
return w.port.Close()
|
||||
}
|
||||
|
||||
// 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 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(name string) error { return w.AddWith(name) }
|
||||
func (w *fen) Add(name string) error { return w.AddWith(name) }
|
||||
|
||||
// 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(name string, opts ...addOpt) error {
|
||||
func (w *fen) AddWith(name string, opts ...addOpt) error {
|
||||
if w.isClosed() {
|
||||
return ErrClosed
|
||||
}
|
||||
if w.port.PathIsWatched(name) {
|
||||
return nil
|
||||
if debug {
|
||||
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n",
|
||||
time.Now().Format("15:04:05.000000000"), name)
|
||||
}
|
||||
|
||||
_ = getOptions(opts...)
|
||||
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.
|
||||
|
|
@ -283,7 +129,7 @@ func (w *Watcher) AddWith(name string, opts ...addOpt) error {
|
|||
}
|
||||
|
||||
w.mu.Lock()
|
||||
w.dirs[name] = struct{}{}
|
||||
w.dirs[name] = with.op
|
||||
w.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
|
@ -294,26 +140,22 @@ func (w *Watcher) AddWith(name string, opts ...addOpt) error {
|
|||
}
|
||||
|
||||
w.mu.Lock()
|
||||
w.watches[name] = struct{}{}
|
||||
w.watches[name] = with.op
|
||||
w.mu.Unlock()
|
||||
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].
|
||||
//
|
||||
// Returns nil if [Watcher.Close] was called.
|
||||
func (w *Watcher) Remove(name string) error {
|
||||
func (w *fen) Remove(name string) error {
|
||||
if w.isClosed() {
|
||||
return nil
|
||||
}
|
||||
if !w.port.PathIsWatched(name) {
|
||||
return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
|
||||
}
|
||||
if debug {
|
||||
fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n",
|
||||
time.Now().Format("15:04:05.000000000"), name)
|
||||
}
|
||||
|
||||
// The user has expressed an intent. Immediately remove this name from
|
||||
// whichever watch list it might be in. If it's not in there the delete
|
||||
|
|
@ -346,7 +188,7 @@ func (w *Watcher) Remove(name string) error {
|
|||
}
|
||||
|
||||
// readEvents contains the main loop that runs in a goroutine watching for events.
|
||||
func (w *Watcher) readEvents() {
|
||||
func (w *fen) readEvents() {
|
||||
// If this function returns, the watcher has been closed and we can close
|
||||
// these channels
|
||||
defer func() {
|
||||
|
|
@ -382,17 +224,19 @@ func (w *Watcher) readEvents() {
|
|||
continue
|
||||
}
|
||||
|
||||
if debug {
|
||||
internal.Debug(pevent.Path, pevent.Events)
|
||||
}
|
||||
|
||||
err = w.handleEvent(&pevent)
|
||||
if err != nil {
|
||||
if !w.sendError(err) {
|
||||
return
|
||||
}
|
||||
if !w.sendError(err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Watcher) handleDirectory(path string, stat os.FileInfo, follow bool, handler func(string, os.FileInfo, bool) error) error {
|
||||
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
|
||||
|
|
@ -418,7 +262,7 @@ func (w *Watcher) handleDirectory(path string, stat os.FileInfo, follow bool, ha
|
|||
// 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 *Watcher) handleEvent(event *unix.PortEvent) error {
|
||||
func (w *fen) handleEvent(event *unix.PortEvent) error {
|
||||
var (
|
||||
events = event.Events
|
||||
path = event.Path
|
||||
|
|
@ -510,15 +354,9 @@ func (w *Watcher) handleEvent(event *unix.PortEvent) error {
|
|||
}
|
||||
|
||||
if events&unix.FILE_MODIFIED != 0 {
|
||||
if fmode.IsDir() {
|
||||
if watchedDir {
|
||||
if err := w.updateDirectory(path); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if !w.sendEvent(path, Write) {
|
||||
return nil
|
||||
}
|
||||
if fmode.IsDir() && watchedDir {
|
||||
if err := w.updateDirectory(path); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if !w.sendEvent(path, Write) {
|
||||
|
|
@ -543,7 +381,7 @@ func (w *Watcher) handleEvent(event *unix.PortEvent) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (w *Watcher) updateDirectory(path string) error {
|
||||
func (w *fen) updateDirectory(path string) error {
|
||||
// The directory was modified, so we must find unwatched entities and watch
|
||||
// them. If something was removed from the directory, nothing will happen,
|
||||
// as everything else should still be watched.
|
||||
|
|
@ -563,10 +401,8 @@ func (w *Watcher) updateDirectory(path string) error {
|
|||
return err
|
||||
}
|
||||
err = w.associateFile(path, finfo, false)
|
||||
if err != nil {
|
||||
if !w.sendError(err) {
|
||||
return nil
|
||||
}
|
||||
if !w.sendError(err) {
|
||||
return nil
|
||||
}
|
||||
if !w.sendEvent(path, Create) {
|
||||
return nil
|
||||
|
|
@ -575,7 +411,7 @@ func (w *Watcher) updateDirectory(path string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (w *Watcher) associateFile(path string, stat os.FileInfo, follow bool) error {
|
||||
func (w *fen) associateFile(path string, stat os.FileInfo, follow bool) error {
|
||||
if w.isClosed() {
|
||||
return ErrClosed
|
||||
}
|
||||
|
|
@ -593,34 +429,34 @@ func (w *Watcher) associateFile(path string, stat os.FileInfo, follow bool) erro
|
|||
// 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 && err != unix.ENOENT {
|
||||
if err != nil && !errors.Is(err, unix.ENOENT) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// FILE_NOFOLLOW means we watch symlinks themselves rather than their
|
||||
// targets.
|
||||
events := unix.FILE_MODIFIED | unix.FILE_ATTRIB | unix.FILE_NOFOLLOW
|
||||
if follow {
|
||||
// We *DO* follow symlinks for explicitly watched entries.
|
||||
events = unix.FILE_MODIFIED | unix.FILE_ATTRIB
|
||||
|
||||
var events int
|
||||
if !follow {
|
||||
// Watch symlinks themselves rather than their targets unless this entry
|
||||
// is explicitly watched.
|
||||
events |= unix.FILE_NOFOLLOW
|
||||
}
|
||||
return w.port.AssociatePath(path, stat,
|
||||
events,
|
||||
stat.Mode())
|
||||
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 *Watcher) dissociateFile(path string, stat os.FileInfo, unused bool) error {
|
||||
func (w *fen) dissociateFile(path string, stat os.FileInfo, unused bool) error {
|
||||
if !w.port.PathIsWatched(path) {
|
||||
return nil
|
||||
}
|
||||
return w.port.DissociatePath(path)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
func (w *fen) WatchList() []string {
|
||||
if w.isClosed() {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -638,3 +474,11 @@ func (w *Watcher) WatchList() []string {
|
|||
|
||||
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
|
||||
}
|
||||
|
|
|
|||
594
vendor/github.com/fsnotify/fsnotify/backend_inotify.go
generated
vendored
594
vendor/github.com/fsnotify/fsnotify/backend_inotify.go
generated
vendored
|
|
@ -1,8 +1,4 @@
|
|||
//go:build linux && !appengine
|
||||
// +build linux,!appengine
|
||||
|
||||
// Note: the documentation on the Watcher type and methods is generated from
|
||||
// mkdoc.zsh
|
||||
|
||||
package fsnotify
|
||||
|
||||
|
|
@ -10,127 +6,20 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/fsnotify/fsnotify/internal"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// 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 times, 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 {
|
||||
// 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.
|
||||
type inotify struct {
|
||||
Events chan Event
|
||||
|
||||
// Errors sends any errors.
|
||||
//
|
||||
// ErrEventOverflow is used to indicate there are too many events:
|
||||
//
|
||||
// - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl)
|
||||
// - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
|
||||
// - kqueue, fen: Not used.
|
||||
Errors chan error
|
||||
|
||||
// Store fd here as os.File.Read() will no longer return on close after
|
||||
|
|
@ -139,8 +28,26 @@ type Watcher struct {
|
|||
inotifyFile *os.File
|
||||
watches *watches
|
||||
done chan struct{} // Channel for sending a "quit message" to the reader goroutine
|
||||
closeMu sync.Mutex
|
||||
doneMu sync.Mutex
|
||||
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
|
||||
}
|
||||
|
||||
type (
|
||||
|
|
@ -150,9 +57,14 @@ type (
|
|||
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.
|
||||
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
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -179,23 +91,45 @@ func (w *watches) add(ww *watch) {
|
|||
func (w *watches) remove(wd uint32) {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
delete(w.path, w.wd[wd].path)
|
||||
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, bool) {
|
||||
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 0, false
|
||||
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
|
||||
}
|
||||
|
||||
return wd, true
|
||||
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 {
|
||||
|
|
@ -236,20 +170,11 @@ func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error
|
|||
return nil
|
||||
}
|
||||
|
||||
// NewWatcher creates a new Watcher.
|
||||
func NewWatcher() (*Watcher, error) {
|
||||
return NewBufferedWatcher(0)
|
||||
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||
return newBufferedBackend(0, ev, errs)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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)
|
||||
|
|
@ -257,12 +182,12 @@ func NewBufferedWatcher(sz uint) (*Watcher, error) {
|
|||
return nil, errno
|
||||
}
|
||||
|
||||
w := &Watcher{
|
||||
w := &inotify{
|
||||
Events: ev,
|
||||
Errors: errs,
|
||||
fd: fd,
|
||||
inotifyFile: os.NewFile(uintptr(fd), ""),
|
||||
watches: newWatches(),
|
||||
Events: make(chan Event, sz),
|
||||
Errors: make(chan error),
|
||||
done: make(chan struct{}),
|
||||
doneResp: make(chan struct{}),
|
||||
}
|
||||
|
|
@ -272,26 +197,29 @@ func NewBufferedWatcher(sz uint) (*Watcher, error) {
|
|||
}
|
||||
|
||||
// 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 {
|
||||
case w.Events <- e:
|
||||
return true
|
||||
case <-w.done:
|
||||
return false
|
||||
case w.Events <- e:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the error was sent, or false if watcher is closed.
|
||||
func (w *Watcher) sendError(err error) bool {
|
||||
select {
|
||||
case w.Errors <- err:
|
||||
func (w *inotify) sendError(err error) bool {
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
select {
|
||||
case <-w.done:
|
||||
return false
|
||||
case w.Errors <- err:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Watcher) isClosed() bool {
|
||||
func (w *inotify) isClosed() bool {
|
||||
select {
|
||||
case <-w.done:
|
||||
return true
|
||||
|
|
@ -300,15 +228,14 @@ func (w *Watcher) isClosed() bool {
|
|||
}
|
||||
}
|
||||
|
||||
// Close removes all watches and closes the Events channel.
|
||||
func (w *Watcher) Close() error {
|
||||
w.closeMu.Lock()
|
||||
func (w *inotify) Close() error {
|
||||
w.doneMu.Lock()
|
||||
if w.isClosed() {
|
||||
w.closeMu.Unlock()
|
||||
w.doneMu.Unlock()
|
||||
return nil
|
||||
}
|
||||
close(w.done)
|
||||
w.closeMu.Unlock()
|
||||
w.doneMu.Unlock()
|
||||
|
||||
// Causes any blocking reads to return with an error, provided the file
|
||||
// still supports deadline operations.
|
||||
|
|
@ -323,78 +250,104 @@ func (w *Watcher) Close() error {
|
|||
return 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 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(name string) error { return w.AddWith(name) }
|
||||
func (w *inotify) Add(name string) error { return w.AddWith(name) }
|
||||
|
||||
// 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(name string, opts ...addOpt) error {
|
||||
func (w *inotify) AddWith(path 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"), path)
|
||||
}
|
||||
|
||||
name = filepath.Clean(name)
|
||||
_ = getOptions(opts...)
|
||||
with := getOptions(opts...)
|
||||
if !w.xSupports(with.op) {
|
||||
return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
|
||||
}
|
||||
|
||||
var flags uint32 = unix.IN_MOVED_TO | unix.IN_MOVED_FROM |
|
||||
unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY |
|
||||
unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF
|
||||
path, recurse := recursivePath(path)
|
||||
if recurse {
|
||||
return filepath.WalkDir(path, func(root string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !d.IsDir() {
|
||||
if root == path {
|
||||
return fmt.Errorf("fsnotify: not a directory: %q", path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return w.watches.updatePath(name, func(existing *watch) (*watch, error) {
|
||||
// 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, name, flags)
|
||||
wd, err := unix.InotifyAddWatch(w.fd, path, flags)
|
||||
if wd == -1 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existing == nil {
|
||||
return &watch{
|
||||
wd: uint32(wd),
|
||||
path: name,
|
||||
flags: flags,
|
||||
wd: uint32(wd),
|
||||
path: path,
|
||||
flags: flags,
|
||||
recurse: recurse,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -404,49 +357,44 @@ func (w *Watcher) AddWith(name string, opts ...addOpt) error {
|
|||
})
|
||||
}
|
||||
|
||||
// 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(name string) error {
|
||||
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 *Watcher) remove(name string) error {
|
||||
wd, ok := w.watches.removePath(name)
|
||||
if !ok {
|
||||
return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
|
||||
func (w *inotify) remove(name string) error {
|
||||
wds, err := w.watches.removePath(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
success, errno := unix.InotifyRmWatch(w.fd, 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
|
||||
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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
func (w *inotify) WatchList() []string {
|
||||
if w.isClosed() {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -463,7 +411,7 @@ func (w *Watcher) WatchList() []string {
|
|||
|
||||
// readEvents reads from the inotify file descriptor, converts the
|
||||
// received events into Event objects and sends them via the Events channel
|
||||
func (w *Watcher) readEvents() {
|
||||
func (w *inotify) readEvents() {
|
||||
defer func() {
|
||||
close(w.doneResp)
|
||||
close(w.Errors)
|
||||
|
|
@ -506,15 +454,17 @@ func (w *Watcher) readEvents() {
|
|||
continue
|
||||
}
|
||||
|
||||
var offset uint32
|
||||
// We don't know how many events we just read into the buffer
|
||||
// While the offset points to at least one whole event...
|
||||
var offset uint32
|
||||
for offset <= uint32(n-unix.SizeofInotifyEvent) {
|
||||
var (
|
||||
// Point "raw" to the event in the buffer
|
||||
raw = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))
|
||||
mask = uint32(raw.Mask)
|
||||
nameLen = uint32(raw.Len)
|
||||
// Move to the next event in the buffer
|
||||
next = func() { offset += unix.SizeofInotifyEvent + nameLen }
|
||||
)
|
||||
|
||||
if mask&unix.IN_Q_OVERFLOW != 0 {
|
||||
|
|
@ -523,21 +473,53 @@ func (w *Watcher) readEvents() {
|
|||
}
|
||||
}
|
||||
|
||||
// If the event happened to the watched directory or the watched file, the kernel
|
||||
// doesn't append the filename to the event, but we would like to always fill the
|
||||
// the "Name" field with a valid filename. We retrieve the path of the watch from
|
||||
// the "paths" map.
|
||||
/// If the event happened to the watched directory or the watched
|
||||
/// file, the kernel doesn't append the filename to the event, but
|
||||
/// we would like to always fill the the "Name" field with a valid
|
||||
/// filename. We retrieve the path of the watch from the "paths"
|
||||
/// map.
|
||||
watch := w.watches.byWd(uint32(raw.Wd))
|
||||
/// Can be nil if Remove() was called in another goroutine for this
|
||||
/// path inbetween reading the events from the kernel and reading
|
||||
/// the internal state. Not much we can do about it, so just skip.
|
||||
/// See #616.
|
||||
if watch == nil {
|
||||
next()
|
||||
continue
|
||||
}
|
||||
|
||||
name := watch.path
|
||||
if nameLen > 0 {
|
||||
/// Point "bytes" at the first byte of the filename
|
||||
bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
|
||||
/// The filename is padded with NULL bytes. TrimRight() gets rid of those.
|
||||
name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
|
||||
}
|
||||
|
||||
if debug {
|
||||
internal.Debug(name, raw.Mask, raw.Cookie)
|
||||
}
|
||||
|
||||
if mask&unix.IN_IGNORED != 0 { //&& event.Op != 0
|
||||
next()
|
||||
continue
|
||||
}
|
||||
|
||||
// inotify will automatically remove the watch on deletes; just need
|
||||
// to clean our state here.
|
||||
if watch != nil && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
|
||||
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 watch != nil && mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF {
|
||||
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) {
|
||||
|
|
@ -546,34 +528,69 @@ func (w *Watcher) readEvents() {
|
|||
}
|
||||
}
|
||||
|
||||
var name string
|
||||
if watch != nil {
|
||||
name = watch.path
|
||||
}
|
||||
if nameLen > 0 {
|
||||
// Point "bytes" at the first byte of the filename
|
||||
bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
|
||||
// The filename is padded with NULL bytes. TrimRight() gets rid of those.
|
||||
name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
|
||||
}
|
||||
|
||||
event := w.newEvent(name, mask)
|
||||
|
||||
// Send the events that are not ignored on the events channel
|
||||
if mask&unix.IN_IGNORED == 0 {
|
||||
if !w.sendEvent(event) {
|
||||
return
|
||||
/// Skip if we're watching both this path and the parent; the parent
|
||||
/// will already send a delete so no need to do it twice.
|
||||
if mask&unix.IN_DELETE_SELF != 0 {
|
||||
if _, ok := w.watches.path[filepath.Dir(watch.path)]; ok {
|
||||
next()
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Move to the next event in the buffer
|
||||
offset += unix.SizeofInotifyEvent + nameLen
|
||||
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 *Watcher) newEvent(name string, mask uint32) Event {
|
||||
func (w *inotify) isRecursive(path string) bool {
|
||||
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}
|
||||
if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
|
||||
e.Op |= Create
|
||||
|
|
@ -584,11 +601,58 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
|
|||
if mask&unix.IN_MODIFY == unix.IN_MODIFY {
|
||||
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 {
|
||||
e.Op |= Rename
|
||||
}
|
||||
if mask&unix.IN_ATTRIB == unix.IN_ATTRIB {
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
747
vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
generated
vendored
747
vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
generated
vendored
File diff suppressed because it is too large
Load diff
204
vendor/github.com/fsnotify/fsnotify/backend_other.go
generated
vendored
204
vendor/github.com/fsnotify/fsnotify/backend_other.go
generated
vendored
|
|
@ -1,205 +1,23 @@
|
|||
//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
|
||||
// +build appengine !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows
|
||||
|
||||
// Note: the documentation on the Watcher type and methods is generated from
|
||||
// mkdoc.zsh
|
||||
|
||||
package fsnotify
|
||||
|
||||
import "errors"
|
||||
|
||||
// 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 times, 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 {
|
||||
// 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.
|
||||
type other struct {
|
||||
Events chan Event
|
||||
|
||||
// Errors sends any errors.
|
||||
//
|
||||
// ErrEventOverflow is used to indicate there are too many events:
|
||||
//
|
||||
// - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl)
|
||||
// - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
|
||||
// - kqueue, fen: Not used.
|
||||
Errors chan error
|
||||
}
|
||||
|
||||
// NewWatcher creates a new Watcher.
|
||||
func NewWatcher() (*Watcher, error) {
|
||||
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||
return nil, errors.New("fsnotify not supported on the current platform")
|
||||
}
|
||||
|
||||
// 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) { return NewWatcher() }
|
||||
|
||||
// Close removes all watches and closes the Events channel.
|
||||
func (w *Watcher) Close() error { return nil }
|
||||
|
||||
// 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 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 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(name string) error { return nil }
|
||||
|
||||
// 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(name string, opts ...addOpt) 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].
|
||||
//
|
||||
// Returns nil if [Watcher.Close] was called.
|
||||
func (w *Watcher) Remove(name string) error { return nil }
|
||||
func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
|
||||
return newBackend(ev, errs)
|
||||
}
|
||||
func (w *other) Close() error { return nil }
|
||||
func (w *other) 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 }
|
||||
|
|
|
|||
305
vendor/github.com/fsnotify/fsnotify/backend_windows.go
generated
vendored
305
vendor/github.com/fsnotify/fsnotify/backend_windows.go
generated
vendored
|
|
@ -1,12 +1,8 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
// Windows backend based on ReadDirectoryChangesW()
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw
|
||||
//
|
||||
// Note: the documentation on the Watcher type and methods is generated from
|
||||
// mkdoc.zsh
|
||||
|
||||
package fsnotify
|
||||
|
||||
|
|
@ -19,123 +15,15 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/fsnotify/fsnotify/internal"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// 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 times, 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 {
|
||||
// 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.
|
||||
type readDirChangesW struct {
|
||||
Events chan Event
|
||||
|
||||
// Errors sends any errors.
|
||||
//
|
||||
// ErrEventOverflow is used to indicate there are too many events:
|
||||
//
|
||||
// - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl)
|
||||
// - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
|
||||
// - kqueue, fen: Not used.
|
||||
Errors chan error
|
||||
|
||||
port windows.Handle // Handle to completion port
|
||||
|
|
@ -147,48 +35,40 @@ type Watcher struct {
|
|||
closed bool // Set to true when Close() is first called
|
||||
}
|
||||
|
||||
// NewWatcher creates a new Watcher.
|
||||
func NewWatcher() (*Watcher, error) {
|
||||
return NewBufferedWatcher(50)
|
||||
func newBackend(ev chan Event, errs chan error) (backend, error) {
|
||||
return newBufferedBackend(50, ev, errs)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
|
||||
port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("CreateIoCompletionPort", err)
|
||||
}
|
||||
w := &Watcher{
|
||||
w := &readDirChangesW{
|
||||
Events: ev,
|
||||
Errors: errs,
|
||||
port: port,
|
||||
watches: make(watchMap),
|
||||
input: make(chan *input, 1),
|
||||
Events: make(chan Event, sz),
|
||||
Errors: make(chan error),
|
||||
quit: make(chan chan<- error, 1),
|
||||
}
|
||||
go w.readEvents()
|
||||
return w, nil
|
||||
}
|
||||
|
||||
func (w *Watcher) isClosed() bool {
|
||||
func (w *readDirChangesW) isClosed() bool {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
return w.closed
|
||||
}
|
||||
|
||||
func (w *Watcher) sendEvent(name string, mask uint64) bool {
|
||||
func (w *readDirChangesW) sendEvent(name, renamedFrom string, mask uint64) bool {
|
||||
if mask == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
event := w.newEvent(name, uint32(mask))
|
||||
event.renamedFrom = renamedFrom
|
||||
select {
|
||||
case ch := <-w.quit:
|
||||
w.quit <- ch
|
||||
|
|
@ -198,17 +78,19 @@ func (w *Watcher) sendEvent(name string, mask uint64) bool {
|
|||
}
|
||||
|
||||
// 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 {
|
||||
case w.Errors <- err:
|
||||
return true
|
||||
case <-w.quit:
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Close removes all watches and closes the Events channel.
|
||||
func (w *Watcher) Close() error {
|
||||
func (w *readDirChangesW) Close() error {
|
||||
if w.isClosed() {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -226,57 +108,21 @@ func (w *Watcher) Close() error {
|
|||
return <-ch
|
||||
}
|
||||
|
||||
// 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 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(name string) error { return w.AddWith(name) }
|
||||
func (w *readDirChangesW) Add(name string) error { return w.AddWith(name) }
|
||||
|
||||
// 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(name string, opts ...addOpt) error {
|
||||
func (w *readDirChangesW) 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"), filepath.ToSlash(name))
|
||||
}
|
||||
|
||||
with := getOptions(opts...)
|
||||
if !w.xSupports(with.op) {
|
||||
return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
|
||||
}
|
||||
if with.bufsize < 4096 {
|
||||
return fmt.Errorf("fsnotify.WithBufferSize: buffer size cannot be smaller than 4096 bytes")
|
||||
}
|
||||
|
|
@ -295,18 +141,14 @@ func (w *Watcher) AddWith(name string, opts ...addOpt) error {
|
|||
return <-in.reply
|
||||
}
|
||||
|
||||
// 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(name string) error {
|
||||
func (w *readDirChangesW) 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"), filepath.ToSlash(name))
|
||||
}
|
||||
|
||||
in := &input{
|
||||
op: opRemoveWatch,
|
||||
|
|
@ -320,11 +162,7 @@ func (w *Watcher) Remove(name string) error {
|
|||
return <-in.reply
|
||||
}
|
||||
|
||||
// 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 {
|
||||
func (w *readDirChangesW) WatchList() []string {
|
||||
if w.isClosed() {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -335,7 +173,13 @@ func (w *Watcher) WatchList() []string {
|
|||
entries := make([]string, 0, len(w.watches))
|
||||
for _, entry := range w.watches {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -361,7 +205,7 @@ const (
|
|||
sysFSIGNORED = 0x8000
|
||||
)
|
||||
|
||||
func (w *Watcher) newEvent(name string, mask uint32) Event {
|
||||
func (w *readDirChangesW) newEvent(name string, mask uint32) Event {
|
||||
e := Event{Name: name}
|
||||
if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO {
|
||||
e.Op |= Create
|
||||
|
|
@ -417,7 +261,7 @@ type (
|
|||
watchMap map[uint32]indexMap
|
||||
)
|
||||
|
||||
func (w *Watcher) wakeupReader() error {
|
||||
func (w *readDirChangesW) wakeupReader() error {
|
||||
err := windows.PostQueuedCompletionStatus(w.port, 0, 0, nil)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("PostQueuedCompletionStatus", err)
|
||||
|
|
@ -425,7 +269,7 @@ func (w *Watcher) wakeupReader() error {
|
|||
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))
|
||||
if err != nil {
|
||||
return "", os.NewSyscallError("GetFileAttributes", err)
|
||||
|
|
@ -439,7 +283,7 @@ func (w *Watcher) getDir(pathname string) (dir string, err error) {
|
|||
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),
|
||||
windows.FILE_LIST_DIRECTORY,
|
||||
windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE,
|
||||
|
|
@ -482,9 +326,8 @@ func (m watchMap) set(ino *inode, watch *watch) {
|
|||
}
|
||||
|
||||
// Must run within the I/O thread.
|
||||
func (w *Watcher) addWatch(pathname string, flags uint64, bufsize int) error {
|
||||
//pathname, recurse := recursivePath(pathname)
|
||||
recurse := false
|
||||
func (w *readDirChangesW) addWatch(pathname string, flags uint64, bufsize int) error {
|
||||
pathname, recurse := recursivePath(pathname)
|
||||
|
||||
dir, err := w.getDir(pathname)
|
||||
if err != nil {
|
||||
|
|
@ -538,7 +381,7 @@ func (w *Watcher) addWatch(pathname string, flags uint64, bufsize int) error {
|
|||
}
|
||||
|
||||
// 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)
|
||||
|
|
@ -566,11 +409,11 @@ func (w *Watcher) remWatch(pathname string) error {
|
|||
return fmt.Errorf("%w: %s", ErrNonExistentWatch, pathname)
|
||||
}
|
||||
if pathname == dir {
|
||||
w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
|
||||
w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED)
|
||||
watch.mask = 0
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
@ -578,23 +421,23 @@ func (w *Watcher) remWatch(pathname string) error {
|
|||
}
|
||||
|
||||
// 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 {
|
||||
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)
|
||||
}
|
||||
if watch.mask != 0 {
|
||||
if watch.mask&provisional == 0 {
|
||||
w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
|
||||
w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED)
|
||||
}
|
||||
watch.mask = 0
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
w.sendError(os.NewSyscallError("CancelIo", err))
|
||||
|
|
@ -624,7 +467,7 @@ func (w *Watcher) startRead(watch *watch) error {
|
|||
err := os.NewSyscallError("ReadDirectoryChanges", rdErr)
|
||||
if rdErr == windows.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
|
||||
// Watched directory was probably removed
|
||||
w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
|
||||
w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF)
|
||||
err = nil
|
||||
}
|
||||
w.deleteWatch(watch)
|
||||
|
|
@ -637,7 +480,7 @@ func (w *Watcher) startRead(watch *watch) error {
|
|||
// readEvents reads from the I/O completion port, converts the
|
||||
// received events into Event objects and sends them via the Events channel.
|
||||
// Entry point to the I/O thread.
|
||||
func (w *Watcher) readEvents() {
|
||||
func (w *readDirChangesW) readEvents() {
|
||||
var (
|
||||
n uint32
|
||||
key uintptr
|
||||
|
|
@ -700,7 +543,7 @@ func (w *Watcher) readEvents() {
|
|||
}
|
||||
case windows.ERROR_ACCESS_DENIED:
|
||||
// Watched directory was probably removed
|
||||
w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
|
||||
w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF)
|
||||
w.deleteWatch(watch)
|
||||
w.startRead(watch)
|
||||
continue
|
||||
|
|
@ -733,6 +576,10 @@ func (w *Watcher) readEvents() {
|
|||
name := windows.UTF16ToString(buf)
|
||||
fullname := filepath.Join(watch.path, name)
|
||||
|
||||
if debug {
|
||||
internal.Debug(fullname, raw.Action)
|
||||
}
|
||||
|
||||
var mask uint64
|
||||
switch raw.Action {
|
||||
case windows.FILE_ACTION_REMOVED:
|
||||
|
|
@ -761,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 {
|
||||
sendNameEvent()
|
||||
w.sendEvent(fullname, "", watch.names[name]&mask)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
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 {
|
||||
fullname = filepath.Join(watch.path, watch.rename)
|
||||
sendNameEvent()
|
||||
w.sendEvent(filepath.Join(watch.path, watch.rename), "", watch.names[name]&mask)
|
||||
}
|
||||
|
||||
// Move to the next event in the buffer
|
||||
|
|
@ -787,8 +635,7 @@ func (w *Watcher) readEvents() {
|
|||
// Error!
|
||||
if offset >= n {
|
||||
//lint:ignore ST1005 Windows should be capitalized
|
||||
w.sendError(errors.New(
|
||||
"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
|
||||
}
|
||||
}
|
||||
|
|
@ -799,7 +646,7 @@ func (w *Watcher) readEvents() {
|
|||
}
|
||||
}
|
||||
|
||||
func (w *Watcher) toWindowsFlags(mask uint64) uint32 {
|
||||
func (w *readDirChangesW) toWindowsFlags(mask uint64) uint32 {
|
||||
var m uint32
|
||||
if mask&sysFSMODIFY != 0 {
|
||||
m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE
|
||||
|
|
@ -810,7 +657,7 @@ func (w *Watcher) toWindowsFlags(mask uint64) uint32 {
|
|||
return m
|
||||
}
|
||||
|
||||
func (w *Watcher) toFSnotifyFlags(action uint32) uint64 {
|
||||
func (w *readDirChangesW) toFSnotifyFlags(action uint32) uint64 {
|
||||
switch action {
|
||||
case windows.FILE_ACTION_ADDED:
|
||||
return sysFSCREATE
|
||||
|
|
@ -825,3 +672,11 @@ func (w *Watcher) toFSnotifyFlags(action uint32) uint64 {
|
|||
}
|
||||
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
|
||||
}
|
||||
|
|
|
|||
368
vendor/github.com/fsnotify/fsnotify/fsnotify.go
generated
vendored
368
vendor/github.com/fsnotify/fsnotify/fsnotify.go
generated
vendored
|
|
@ -3,19 +3,146 @@
|
|||
//
|
||||
// Currently supported systems:
|
||||
//
|
||||
// Linux 2.6.32+ via inotify
|
||||
// BSD, macOS via kqueue
|
||||
// Windows via ReadDirectoryChangesW
|
||||
// illumos via FEN
|
||||
// - 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
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"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.
|
||||
type Event struct {
|
||||
// Path to the file or directory.
|
||||
|
|
@ -30,6 +157,16 @@ type Event struct {
|
|||
// This is a bitmask and some systems may send multiple operations at once.
|
||||
// Use the Event.Has() method instead of comparing with ==.
|
||||
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.
|
||||
|
|
@ -50,7 +187,7 @@ const (
|
|||
// example "remove to trash" is often a rename).
|
||||
Remove
|
||||
|
||||
// The path was renamed to something else; any watched on it will be
|
||||
// The path was renamed to something else; any watches on it will be
|
||||
// removed.
|
||||
Rename
|
||||
|
||||
|
|
@ -60,15 +197,155 @@ const (
|
|||
// get triggered very frequently by some software. For example, Spotlight
|
||||
// indexing on macOS, anti-virus software, backup software, etc.
|
||||
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.
|
||||
var (
|
||||
// ErrNonExistentWatch is used when Remove() is called on a path that's not
|
||||
// added.
|
||||
ErrNonExistentWatch = errors.New("fsnotify: can't remove non-existent watch")
|
||||
ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow")
|
||||
ErrClosed = errors.New("fsnotify: watcher already closed")
|
||||
|
||||
// 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")
|
||||
)
|
||||
|
||||
// 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
|
||||
if o.Has(Create) {
|
||||
|
|
@ -80,6 +357,18 @@ func (o Op) String() string {
|
|||
if o.Has(Write) {
|
||||
b.WriteString("|WRITE")
|
||||
}
|
||||
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")
|
||||
}
|
||||
|
|
@ -100,24 +389,48 @@ func (e Event) Has(op Op) bool { return e.Op.Has(op) }
|
|||
|
||||
// String returns a string representation of the event with their path.
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
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 {
|
||||
o(&with)
|
||||
if o != nil {
|
||||
o(&with)
|
||||
}
|
||||
}
|
||||
return with
|
||||
}
|
||||
|
|
@ -136,9 +449,44 @@ 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
|
||||
}
|
||||
|
|
|
|||
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()
|
||||
}
|
||||
259
vendor/github.com/fsnotify/fsnotify/mkdoc.zsh
generated
vendored
259
vendor/github.com/fsnotify/fsnotify/mkdoc.zsh
generated
vendored
|
|
@ -1,259 +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 so you don't need
|
||||
# to update the same comment 5 times.
|
||||
|
||||
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.
|
||||
//
|
||||
// # 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 times, 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.
|
||||
EOF
|
||||
)
|
||||
|
||||
new=$(<<EOF
|
||||
// NewWatcher creates a new Watcher.
|
||||
EOF
|
||||
)
|
||||
|
||||
newbuffered=$(<<EOF
|
||||
// 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.
|
||||
EOF
|
||||
)
|
||||
|
||||
add=$(<<EOF
|
||||
// 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 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.
|
||||
EOF
|
||||
)
|
||||
|
||||
addwith=$(<<EOF
|
||||
// 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).
|
||||
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].
|
||||
//
|
||||
// Returns nil if [Watcher.Close] was called.
|
||||
EOF
|
||||
)
|
||||
|
||||
close=$(<<EOF
|
||||
// Close removes all watches and closes the Events channel.
|
||||
EOF
|
||||
)
|
||||
|
||||
watchlist=$(<<EOF
|
||||
// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
|
||||
// yet removed).
|
||||
//
|
||||
// Returns nil if [Watcher.Close] was called.
|
||||
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, 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.
|
||||
EOF
|
||||
)
|
||||
|
||||
errors=$(<<EOF
|
||||
// Errors sends any errors.
|
||||
//
|
||||
// ErrEventOverflow is used to indicate there are too many events:
|
||||
//
|
||||
// - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl)
|
||||
// - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
|
||||
// - kqueue, fen: Not used.
|
||||
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 NewBufferedWatcher(' $newbuffered
|
||||
set-cmt '^func (w \*Watcher) Add(' $add
|
||||
set-cmt '^func (w \*Watcher) AddWith(' $addwith
|
||||
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
|
||||
// +build freebsd openbsd netbsd dragonfly
|
||||
|
||||
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
|
||||
// +build darwin
|
||||
|
||||
package fsnotify
|
||||
|
||||
|
|
|
|||
14
vendor/github.com/moby/buildkit/frontend/dockerfile/parser/errors.go
generated
vendored
14
vendor/github.com/moby/buildkit/frontend/dockerfile/parser/errors.go
generated
vendored
|
|
@ -34,12 +34,24 @@ func withLocation(err error, start, end int) error {
|
|||
|
||||
// WithLocation extends an error with a source code location
|
||||
func WithLocation(err error, location []Range) error {
|
||||
return setLocation(err, location, true)
|
||||
}
|
||||
|
||||
func SetLocation(err error, location []Range) error {
|
||||
return setLocation(err, location, false)
|
||||
}
|
||||
|
||||
func setLocation(err error, location []Range, add bool) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
var el *ErrorLocation
|
||||
if errors.As(err, &el) {
|
||||
el.Locations = append(el.Locations, location)
|
||||
if add {
|
||||
el.Locations = append(el.Locations, location)
|
||||
} else {
|
||||
el.Locations = [][]Range{location}
|
||||
}
|
||||
return err
|
||||
}
|
||||
return stack.Enable(&ErrorLocation{
|
||||
|
|
|
|||
26
vendor/github.com/moby/buildkit/frontend/dockerfile/parser/parser.go
generated
vendored
26
vendor/github.com/moby/buildkit/frontend/dockerfile/parser/parser.go
generated
vendored
|
|
@ -167,16 +167,17 @@ func (d *directives) setEscapeToken(s string) error {
|
|||
|
||||
// possibleParserDirective looks for parser directives, eg '# escapeToken=<char>'.
|
||||
// Parser directives must precede any builder instruction or other comments,
|
||||
// and cannot be repeated.
|
||||
func (d *directives) possibleParserDirective(line []byte) error {
|
||||
// and cannot be repeated. Returns true if a parser directive was found.
|
||||
func (d *directives) possibleParserDirective(line []byte) (bool, error) {
|
||||
directive, err := d.parser.ParseLine(line)
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
if directive != nil && directive.Name == keyEscape {
|
||||
return d.setEscapeToken(directive.Value)
|
||||
err := d.setEscapeToken(directive.Value)
|
||||
return err == nil, err
|
||||
}
|
||||
return nil
|
||||
return directive != nil, nil
|
||||
}
|
||||
|
||||
// newDefaultDirectives returns a new directives structure with the default escapeToken token
|
||||
|
|
@ -300,7 +301,13 @@ func Parse(rwc io.Reader) (*Result, error) {
|
|||
comments = append(comments, comment)
|
||||
}
|
||||
}
|
||||
bytesRead, err = processLine(d, bytesRead, true)
|
||||
var directiveOk bool
|
||||
bytesRead, directiveOk, err = processLine(d, bytesRead, true)
|
||||
// If the line is a directive, strip it from the comments
|
||||
// so it doesn't get added to the AST.
|
||||
if directiveOk {
|
||||
comments = comments[:len(comments)-1]
|
||||
}
|
||||
if err != nil {
|
||||
return nil, withLocation(err, currentLine, 0)
|
||||
}
|
||||
|
|
@ -316,7 +323,7 @@ func Parse(rwc io.Reader) (*Result, error) {
|
|||
|
||||
var hasEmptyContinuationLine bool
|
||||
for !isEndOfLine && scanner.Scan() {
|
||||
bytesRead, err := processLine(d, scanner.Bytes(), false)
|
||||
bytesRead, _, err := processLine(d, scanner.Bytes(), false)
|
||||
if err != nil {
|
||||
return nil, withLocation(err, currentLine, 0)
|
||||
}
|
||||
|
|
@ -527,12 +534,13 @@ func trimContinuationCharacter(line []byte, d *directives) ([]byte, bool) {
|
|||
|
||||
// TODO: remove stripLeftWhitespace after deprecation period. It seems silly
|
||||
// to preserve whitespace on continuation lines. Why is that done?
|
||||
func processLine(d *directives, token []byte, stripLeftWhitespace bool) ([]byte, error) {
|
||||
func processLine(d *directives, token []byte, stripLeftWhitespace bool) ([]byte, bool, error) {
|
||||
token = trimNewline(token)
|
||||
if stripLeftWhitespace {
|
||||
token = trimLeadingWhitespace(token)
|
||||
}
|
||||
return trimComments(token), d.possibleParserDirective(token)
|
||||
directiveOk, err := d.possibleParserDirective(token)
|
||||
return trimComments(token), directiveOk, err
|
||||
}
|
||||
|
||||
// Variation of bufio.ScanLines that preserves the line endings
|
||||
|
|
|
|||
3
vendor/github.com/moby/buildkit/util/stack/generate.go
generated
vendored
3
vendor/github.com/moby/buildkit/util/stack/generate.go
generated
vendored
|
|
@ -1,3 +0,0 @@
|
|||
package stack
|
||||
|
||||
//go:generate protoc -I=. -I=../../vendor/ --go_out=. --go_opt=paths=source_relative --go_opt=Mstack.proto=/util/stack stack.proto
|
||||
138
vendor/github.com/moby/buildkit/util/stack/stack.pb.go
generated
vendored
138
vendor/github.com/moby/buildkit/util/stack/stack.pb.go
generated
vendored
|
|
@ -1,8 +1,8 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc-gen-go v1.35.1
|
||||
// protoc v3.11.4
|
||||
// source: stack.proto
|
||||
// source: github.com/moby/buildkit/util/stack/stack.proto
|
||||
|
||||
package stack
|
||||
|
||||
|
|
@ -34,11 +34,9 @@ type Stack struct {
|
|||
|
||||
func (x *Stack) Reset() {
|
||||
*x = Stack{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_stack_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
mi := &file_github_com_moby_buildkit_util_stack_stack_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Stack) String() string {
|
||||
|
|
@ -48,8 +46,8 @@ func (x *Stack) String() string {
|
|||
func (*Stack) ProtoMessage() {}
|
||||
|
||||
func (x *Stack) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_stack_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
mi := &file_github_com_moby_buildkit_util_stack_stack_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
|
|
@ -61,7 +59,7 @@ func (x *Stack) ProtoReflect() protoreflect.Message {
|
|||
|
||||
// Deprecated: Use Stack.ProtoReflect.Descriptor instead.
|
||||
func (*Stack) Descriptor() ([]byte, []int) {
|
||||
return file_stack_proto_rawDescGZIP(), []int{0}
|
||||
return file_github_com_moby_buildkit_util_stack_stack_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Stack) GetFrames() []*Frame {
|
||||
|
|
@ -111,11 +109,9 @@ type Frame struct {
|
|||
|
||||
func (x *Frame) Reset() {
|
||||
*x = Frame{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_stack_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
mi := &file_github_com_moby_buildkit_util_stack_stack_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Frame) String() string {
|
||||
|
|
@ -125,8 +121,8 @@ func (x *Frame) String() string {
|
|||
func (*Frame) ProtoMessage() {}
|
||||
|
||||
func (x *Frame) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_stack_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
mi := &file_github_com_moby_buildkit_util_stack_stack_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
|
|
@ -138,7 +134,7 @@ func (x *Frame) ProtoReflect() protoreflect.Message {
|
|||
|
||||
// Deprecated: Use Frame.ProtoReflect.Descriptor instead.
|
||||
func (*Frame) Descriptor() ([]byte, []int) {
|
||||
return file_stack_proto_rawDescGZIP(), []int{1}
|
||||
return file_github_com_moby_buildkit_util_stack_stack_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *Frame) GetName() string {
|
||||
|
|
@ -162,45 +158,49 @@ func (x *Frame) GetLine() int32 {
|
|||
return 0
|
||||
}
|
||||
|
||||
var File_stack_proto protoreflect.FileDescriptor
|
||||
var File_github_com_moby_buildkit_util_stack_stack_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_stack_proto_rawDesc = []byte{
|
||||
0x0a, 0x0b, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x73,
|
||||
0x74, 0x61, 0x63, 0x6b, 0x22, 0x8f, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x12, 0x24,
|
||||
0x0a, 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c,
|
||||
0x2e, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x06, 0x66, 0x72,
|
||||
0x61, 0x6d, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18,
|
||||
0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x10,
|
||||
0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x70, 0x69, 0x64,
|
||||
0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65,
|
||||
0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65,
|
||||
0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x43, 0x0a, 0x05, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
|
||||
0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e,
|
||||
0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x65, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x4c, 0x69, 0x6e, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
var file_github_com_moby_buildkit_util_stack_stack_proto_rawDesc = []byte{
|
||||
0x0a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x6f, 0x62,
|
||||
0x79, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x2f,
|
||||
0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x12, 0x05, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x22, 0x8f, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61,
|
||||
0x63, 0x6b, 0x12, 0x24, 0x0a, 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65,
|
||||
0x52, 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6d, 0x64, 0x6c,
|
||||
0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6d, 0x64, 0x6c, 0x69,
|
||||
0x6e, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
|
||||
0x03, 0x70, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
|
||||
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a,
|
||||
0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x43, 0x0a, 0x05, 0x46, 0x72,
|
||||
0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4c,
|
||||
0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x4c, 0x69, 0x6e, 0x65, 0x42,
|
||||
0x25, 0x5a, 0x23, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x6f,
|
||||
0x62, 0x79, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2f, 0x75, 0x74, 0x69, 0x6c,
|
||||
0x2f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_stack_proto_rawDescOnce sync.Once
|
||||
file_stack_proto_rawDescData = file_stack_proto_rawDesc
|
||||
file_github_com_moby_buildkit_util_stack_stack_proto_rawDescOnce sync.Once
|
||||
file_github_com_moby_buildkit_util_stack_stack_proto_rawDescData = file_github_com_moby_buildkit_util_stack_stack_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_stack_proto_rawDescGZIP() []byte {
|
||||
file_stack_proto_rawDescOnce.Do(func() {
|
||||
file_stack_proto_rawDescData = protoimpl.X.CompressGZIP(file_stack_proto_rawDescData)
|
||||
func file_github_com_moby_buildkit_util_stack_stack_proto_rawDescGZIP() []byte {
|
||||
file_github_com_moby_buildkit_util_stack_stack_proto_rawDescOnce.Do(func() {
|
||||
file_github_com_moby_buildkit_util_stack_stack_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_moby_buildkit_util_stack_stack_proto_rawDescData)
|
||||
})
|
||||
return file_stack_proto_rawDescData
|
||||
return file_github_com_moby_buildkit_util_stack_stack_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_stack_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_stack_proto_goTypes = []interface{}{
|
||||
var file_github_com_moby_buildkit_util_stack_stack_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_github_com_moby_buildkit_util_stack_stack_proto_goTypes = []any{
|
||||
(*Stack)(nil), // 0: stack.Stack
|
||||
(*Frame)(nil), // 1: stack.Frame
|
||||
}
|
||||
var file_stack_proto_depIdxs = []int32{
|
||||
var file_github_com_moby_buildkit_util_stack_stack_proto_depIdxs = []int32{
|
||||
1, // 0: stack.Stack.frames:type_name -> stack.Frame
|
||||
1, // [1:1] is the sub-list for method output_type
|
||||
1, // [1:1] is the sub-list for method input_type
|
||||
|
|
@ -209,53 +209,27 @@ var file_stack_proto_depIdxs = []int32{
|
|||
0, // [0:1] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_stack_proto_init() }
|
||||
func file_stack_proto_init() {
|
||||
if File_stack_proto != nil {
|
||||
func init() { file_github_com_moby_buildkit_util_stack_stack_proto_init() }
|
||||
func file_github_com_moby_buildkit_util_stack_stack_proto_init() {
|
||||
if File_github_com_moby_buildkit_util_stack_stack_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_stack_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Stack); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_stack_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Frame); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_stack_proto_rawDesc,
|
||||
RawDescriptor: file_github_com_moby_buildkit_util_stack_stack_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_stack_proto_goTypes,
|
||||
DependencyIndexes: file_stack_proto_depIdxs,
|
||||
MessageInfos: file_stack_proto_msgTypes,
|
||||
GoTypes: file_github_com_moby_buildkit_util_stack_stack_proto_goTypes,
|
||||
DependencyIndexes: file_github_com_moby_buildkit_util_stack_stack_proto_depIdxs,
|
||||
MessageInfos: file_github_com_moby_buildkit_util_stack_stack_proto_msgTypes,
|
||||
}.Build()
|
||||
File_stack_proto = out.File
|
||||
file_stack_proto_rawDesc = nil
|
||||
file_stack_proto_goTypes = nil
|
||||
file_stack_proto_depIdxs = nil
|
||||
File_github_com_moby_buildkit_util_stack_stack_proto = out.File
|
||||
file_github_com_moby_buildkit_util_stack_stack_proto_rawDesc = nil
|
||||
file_github_com_moby_buildkit_util_stack_stack_proto_goTypes = nil
|
||||
file_github_com_moby_buildkit_util_stack_stack_proto_depIdxs = nil
|
||||
}
|
||||
|
|
|
|||
4
vendor/github.com/moby/buildkit/util/stack/stack.proto
generated
vendored
4
vendor/github.com/moby/buildkit/util/stack/stack.proto
generated
vendored
|
|
@ -2,6 +2,8 @@ syntax = "proto3";
|
|||
|
||||
package stack;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/util/stack";
|
||||
|
||||
message Stack {
|
||||
repeated Frame frames = 1;
|
||||
repeated string cmdline = 2;
|
||||
|
|
@ -14,4 +16,4 @@ message Frame {
|
|||
string Name = 1;
|
||||
string File = 2;
|
||||
int32 Line = 3;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
660
vendor/github.com/moby/buildkit/util/stack/stack_vtproto.pb.go
generated
vendored
Normal file
660
vendor/github.com/moby/buildkit/util/stack/stack_vtproto.pb.go
generated
vendored
Normal file
|
|
@ -0,0 +1,660 @@
|
|||
// Code generated by protoc-gen-go-vtproto. DO NOT EDIT.
|
||||
// protoc-gen-go-vtproto version: v0.6.1-0.20240319094008-0393e58bdf10
|
||||
// source: github.com/moby/buildkit/util/stack/stack.proto
|
||||
|
||||
package stack
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
protohelpers "github.com/planetscale/vtprotobuf/protohelpers"
|
||||
proto "google.golang.org/protobuf/proto"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
io "io"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
func (m *Stack) CloneVT() *Stack {
|
||||
if m == nil {
|
||||
return (*Stack)(nil)
|
||||
}
|
||||
r := new(Stack)
|
||||
r.Pid = m.Pid
|
||||
r.Version = m.Version
|
||||
r.Revision = m.Revision
|
||||
if rhs := m.Frames; rhs != nil {
|
||||
tmpContainer := make([]*Frame, len(rhs))
|
||||
for k, v := range rhs {
|
||||
tmpContainer[k] = v.CloneVT()
|
||||
}
|
||||
r.Frames = tmpContainer
|
||||
}
|
||||
if rhs := m.Cmdline; rhs != nil {
|
||||
tmpContainer := make([]string, len(rhs))
|
||||
copy(tmpContainer, rhs)
|
||||
r.Cmdline = tmpContainer
|
||||
}
|
||||
if len(m.unknownFields) > 0 {
|
||||
r.unknownFields = make([]byte, len(m.unknownFields))
|
||||
copy(r.unknownFields, m.unknownFields)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (m *Stack) CloneMessageVT() proto.Message {
|
||||
return m.CloneVT()
|
||||
}
|
||||
|
||||
func (m *Frame) CloneVT() *Frame {
|
||||
if m == nil {
|
||||
return (*Frame)(nil)
|
||||
}
|
||||
r := new(Frame)
|
||||
r.Name = m.Name
|
||||
r.File = m.File
|
||||
r.Line = m.Line
|
||||
if len(m.unknownFields) > 0 {
|
||||
r.unknownFields = make([]byte, len(m.unknownFields))
|
||||
copy(r.unknownFields, m.unknownFields)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (m *Frame) CloneMessageVT() proto.Message {
|
||||
return m.CloneVT()
|
||||
}
|
||||
|
||||
func (this *Stack) EqualVT(that *Stack) bool {
|
||||
if this == that {
|
||||
return true
|
||||
} else if this == nil || that == nil {
|
||||
return false
|
||||
}
|
||||
if len(this.Frames) != len(that.Frames) {
|
||||
return false
|
||||
}
|
||||
for i, vx := range this.Frames {
|
||||
vy := that.Frames[i]
|
||||
if p, q := vx, vy; p != q {
|
||||
if p == nil {
|
||||
p = &Frame{}
|
||||
}
|
||||
if q == nil {
|
||||
q = &Frame{}
|
||||
}
|
||||
if !p.EqualVT(q) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(this.Cmdline) != len(that.Cmdline) {
|
||||
return false
|
||||
}
|
||||
for i, vx := range this.Cmdline {
|
||||
vy := that.Cmdline[i]
|
||||
if vx != vy {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if this.Pid != that.Pid {
|
||||
return false
|
||||
}
|
||||
if this.Version != that.Version {
|
||||
return false
|
||||
}
|
||||
if this.Revision != that.Revision {
|
||||
return false
|
||||
}
|
||||
return string(this.unknownFields) == string(that.unknownFields)
|
||||
}
|
||||
|
||||
func (this *Stack) EqualMessageVT(thatMsg proto.Message) bool {
|
||||
that, ok := thatMsg.(*Stack)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return this.EqualVT(that)
|
||||
}
|
||||
func (this *Frame) EqualVT(that *Frame) bool {
|
||||
if this == that {
|
||||
return true
|
||||
} else if this == nil || that == nil {
|
||||
return false
|
||||
}
|
||||
if this.Name != that.Name {
|
||||
return false
|
||||
}
|
||||
if this.File != that.File {
|
||||
return false
|
||||
}
|
||||
if this.Line != that.Line {
|
||||
return false
|
||||
}
|
||||
return string(this.unknownFields) == string(that.unknownFields)
|
||||
}
|
||||
|
||||
func (this *Frame) EqualMessageVT(thatMsg proto.Message) bool {
|
||||
that, ok := thatMsg.(*Frame)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return this.EqualVT(that)
|
||||
}
|
||||
func (m *Stack) MarshalVT() (dAtA []byte, err error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
size := m.SizeVT()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Stack) MarshalToVT(dAtA []byte) (int, error) {
|
||||
size := m.SizeVT()
|
||||
return m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Stack) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
if m == nil {
|
||||
return 0, nil
|
||||
}
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.unknownFields != nil {
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if len(m.Revision) > 0 {
|
||||
i -= len(m.Revision)
|
||||
copy(dAtA[i:], m.Revision)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Revision)))
|
||||
i--
|
||||
dAtA[i] = 0x2a
|
||||
}
|
||||
if len(m.Version) > 0 {
|
||||
i -= len(m.Version)
|
||||
copy(dAtA[i:], m.Version)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Version)))
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
}
|
||||
if m.Pid != 0 {
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Pid))
|
||||
i--
|
||||
dAtA[i] = 0x18
|
||||
}
|
||||
if len(m.Cmdline) > 0 {
|
||||
for iNdEx := len(m.Cmdline) - 1; iNdEx >= 0; iNdEx-- {
|
||||
i -= len(m.Cmdline[iNdEx])
|
||||
copy(dAtA[i:], m.Cmdline[iNdEx])
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Cmdline[iNdEx])))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
}
|
||||
if len(m.Frames) > 0 {
|
||||
for iNdEx := len(m.Frames) - 1; iNdEx >= 0; iNdEx-- {
|
||||
size, err := m.Frames[iNdEx].MarshalToSizedBufferVT(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *Frame) MarshalVT() (dAtA []byte, err error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
size := m.SizeVT()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Frame) MarshalToVT(dAtA []byte) (int, error) {
|
||||
size := m.SizeVT()
|
||||
return m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Frame) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
if m == nil {
|
||||
return 0, nil
|
||||
}
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.unknownFields != nil {
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if m.Line != 0 {
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Line))
|
||||
i--
|
||||
dAtA[i] = 0x18
|
||||
}
|
||||
if len(m.File) > 0 {
|
||||
i -= len(m.File)
|
||||
copy(dAtA[i:], m.File)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.File)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if len(m.Name) > 0 {
|
||||
i -= len(m.Name)
|
||||
copy(dAtA[i:], m.Name)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Name)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *Stack) SizeVT() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Frames) > 0 {
|
||||
for _, e := range m.Frames {
|
||||
l = e.SizeVT()
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
}
|
||||
if len(m.Cmdline) > 0 {
|
||||
for _, s := range m.Cmdline {
|
||||
l = len(s)
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.Pid != 0 {
|
||||
n += 1 + protohelpers.SizeOfVarint(uint64(m.Pid))
|
||||
}
|
||||
l = len(m.Version)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
l = len(m.Revision)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Frame) SizeVT() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Name)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
l = len(m.File)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
if m.Line != 0 {
|
||||
n += 1 + protohelpers.SizeOfVarint(uint64(m.Line))
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Stack) UnmarshalVT(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Stack: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Stack: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Frames", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Frames = append(m.Frames, &Frame{})
|
||||
if err := m.Frames[len(m.Frames)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Cmdline", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Cmdline = append(m.Cmdline, string(dAtA[iNdEx:postIndex]))
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Pid", wireType)
|
||||
}
|
||||
m.Pid = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Pid |= int32(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Version = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Revision = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Frame) UnmarshalVT(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Frame: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Frame: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Name = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field File", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.File = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Line", wireType)
|
||||
}
|
||||
m.Line = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Line |= int32(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue