chore: update deps

pull/1411/head
iwilltry42 3 months ago
parent bf695e533e
commit 5cd9aa1d08
No known key found for this signature in database
GPG Key ID: FD4E78FBAD6B1550
  1. 4
      .gitignore
  2. 2
      Makefile
  3. 24
      go.mod
  4. 56
      go.sum
  5. 16
      go.work.sum
  6. 14
      vendor/github.com/docker/cli/cli/command/cli_options.go
  7. 4
      vendor/github.com/docker/cli/cli/command/events_utils.go
  8. 52
      vendor/github.com/docker/cli/cli/command/utils.go
  9. 2
      vendor/github.com/docker/cli/opts/mount.go
  10. 13
      vendor/github.com/docker/docker/api/common.go
  11. 32
      vendor/github.com/docker/docker/api/swagger.yaml
  12. 47
      vendor/github.com/docker/docker/api/types/client.go
  13. 2
      vendor/github.com/docker/docker/api/types/container/config.go
  14. 58
      vendor/github.com/docker/docker/api/types/image/opts.go
  15. 1
      vendor/github.com/docker/docker/api/types/mount/mount.go
  16. 2
      vendor/github.com/docker/docker/api/types/registry/registry.go
  17. 9
      vendor/github.com/docker/docker/api/types/types.go
  18. 139
      vendor/github.com/docker/docker/api/types/types_deprecated.go
  19. 14
      vendor/github.com/docker/docker/api/types/versions/README.md
  20. 10
      vendor/github.com/docker/docker/api/types/volume/cluster_volume.go
  21. 19
      vendor/github.com/docker/docker/client/client.go
  22. 4
      vendor/github.com/docker/docker/client/container_create.go
  23. 4
      vendor/github.com/docker/docker/client/container_exec.go
  24. 4
      vendor/github.com/docker/docker/client/container_restart.go
  25. 4
      vendor/github.com/docker/docker/client/container_stop.go
  26. 11
      vendor/github.com/docker/docker/client/container_wait.go
  27. 8
      vendor/github.com/docker/docker/client/distribution_inspect.go
  28. 25
      vendor/github.com/docker/docker/client/errors.go
  29. 4
      vendor/github.com/docker/docker/client/image_create.go
  30. 3
      vendor/github.com/docker/docker/client/image_import.go
  31. 10
      vendor/github.com/docker/docker/client/image_list.go
  32. 4
      vendor/github.com/docker/docker/client/image_pull.go
  33. 4
      vendor/github.com/docker/docker/client/image_push.go
  34. 3
      vendor/github.com/docker/docker/client/image_remove.go
  35. 12
      vendor/github.com/docker/docker/client/interface.go
  36. 7
      vendor/github.com/docker/docker/client/network_create.go
  37. 5
      vendor/github.com/docker/docker/client/ping.go
  38. 10
      vendor/github.com/docker/docker/client/request.go
  39. 4
      vendor/github.com/docker/docker/client/service_create.go
  40. 12
      vendor/github.com/docker/docker/client/service_update.go
  41. 4
      vendor/github.com/docker/docker/client/volume_remove.go
  42. 16
      vendor/github.com/docker/docker/pkg/homedir/homedir.go
  43. 8
      vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go
  44. 6
      vendor/github.com/docker/docker/pkg/homedir/homedir_windows.go
  45. 19
      vendor/github.com/docker/docker/pkg/system/image_os_deprecated.go
  46. 17
      vendor/github.com/docker/docker/registry/search.go
  47. 3
      vendor/github.com/goodhosts/hostsfile/.gitignore
  48. 5
      vendor/github.com/goodhosts/hostsfile/Makefile
  49. 62
      vendor/github.com/goodhosts/hostsfile/README.md
  50. 6
      vendor/github.com/goodhosts/hostsfile/build.go
  51. 460
      vendor/github.com/goodhosts/hostsfile/hosts.go
  52. 54
      vendor/github.com/goodhosts/hostsfile/hostsline.go
  53. 42
      vendor/github.com/goodhosts/hostsfile/lookup.go
  54. 27
      vendor/github.com/goodhosts/hostsfile/mage/install/install.go
  55. 41
      vendor/github.com/goodhosts/hostsfile/mage/test/test.go
  56. 35
      vendor/github.com/goodhosts/hostsfile/magefile.go
  57. 27
      vendor/github.com/goodhosts/hostsfile/make.bat
  58. 5
      vendor/github.com/goodhosts/hostsfile/os.go
  59. 5
      vendor/github.com/goodhosts/hostsfile/os_windows.go
  60. 8
      vendor/github.com/goodhosts/hostsfile/slice.go
  61. 2
      vendor/github.com/google/go-containerregistry/pkg/authn/keychain.go
  62. 137
      vendor/github.com/google/go-containerregistry/pkg/v1/layout/gc.go
  63. 5
      vendor/github.com/google/go-containerregistry/pkg/v1/remote/write.go
  64. 33
      vendor/github.com/google/go-containerregistry/pkg/v1/tarball/image.go
  65. 201
      vendor/github.com/magefile/mage/LICENSE
  66. 80
      vendor/github.com/magefile/mage/mg/color.go
  67. 38
      vendor/github.com/magefile/mage/mg/color_string.go
  68. 211
      vendor/github.com/magefile/mage/mg/deps.go
  69. 51
      vendor/github.com/magefile/mage/mg/errors.go
  70. 192
      vendor/github.com/magefile/mage/mg/fn.go
  71. 136
      vendor/github.com/magefile/mage/mg/runtime.go
  72. 184
      vendor/github.com/magefile/mage/sh/cmd.go
  73. 40
      vendor/github.com/magefile/mage/sh/helpers.go
  74. 201
      vendor/github.com/moby/docker-image-spec/LICENSE
  75. 0
      vendor/github.com/moby/docker-image-spec/specs-go/v1/image.go
  76. 15
      vendor/go4.org/netipx/netipx.go
  77. 11
      vendor/golang.org/x/net/http2/frame.go
  78. 2
      vendor/golang.org/x/sys/unix/aliases.go
  79. 2
      vendor/golang.org/x/sys/unix/mmap_nomremap.go
  80. 2
      vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go
  81. 12
      vendor/golang.org/x/sys/unix/syscall_freebsd.go
  82. 99
      vendor/golang.org/x/sys/unix/syscall_linux.go
  83. 8
      vendor/golang.org/x/sys/unix/syscall_zos_s390x.go
  84. 10
      vendor/golang.org/x/sys/unix/zsyscall_linux.go
  85. 60
      vendor/golang.org/x/sys/unix/ztypes_linux.go
  86. 82
      vendor/golang.org/x/sys/windows/syscall_windows.go
  87. 24
      vendor/golang.org/x/sys/windows/types_windows.go
  88. 126
      vendor/golang.org/x/sys/windows/zsyscall_windows.go
  89. 38
      vendor/modules.txt

4
.gitignore vendored

@ -22,7 +22,9 @@ site/
.vscode/
.local/
.idea/
qodana.yaml
*.iml
# Pipenv
Pipfile*
Pipfile*

@ -66,7 +66,7 @@ K3D_HELPER_VERSION ?=
# Go options
GO ?= go
GOENVPATH := $(shell go env GOPATH)
PKG := $(shell go mod vendor)
PKG := $(shell go work vendor)
TAGS :=
TESTS := ./...
TESTFLAGS :=

@ -4,9 +4,9 @@ go 1.22.0
require (
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/containerd/containerd v1.7.13
github.com/docker/cli v25.0.3+incompatible
github.com/docker/docker v25.0.3+incompatible
github.com/containerd/containerd v1.7.15
github.com/docker/cli v26.0.0+incompatible
github.com/docker/docker v26.0.0+incompatible
github.com/docker/docker-credential-helpers v0.8.1 // indirect
github.com/docker/go-connections v0.5.0
github.com/docker/go-metrics v0.0.1 // indirect
@ -25,8 +25,8 @@ require (
github.com/theupdateframework/notary v0.7.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonschema v1.2.0
golang.org/x/sync v0.6.0
golang.org/x/sys v0.17.0 // indirect
golang.org/x/sync v0.7.0
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/yaml.v2 v2.4.0
gotest.tools v2.2.0+incompatible
@ -35,11 +35,11 @@ require (
)
require (
github.com/goodhosts/hostsfile v0.1.1
github.com/google/go-containerregistry v0.16.1
github.com/goodhosts/hostsfile v0.1.6
github.com/google/go-containerregistry v0.19.1
github.com/rancher/wharfie v0.6.2
github.com/spf13/pflag v1.0.5
go4.org/netipx v0.0.0-20230728184502-ec4c8b891b28
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
k8s.io/utils v0.0.0-20240310230437-4693a0247e57
)
@ -69,11 +69,13 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/magefile/mage v1.15.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/patternmatcher v0.5.0 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/user v0.1.0 // indirect
@ -100,12 +102,12 @@ require (
go.opentelemetry.io/otel/trace v1.19.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.16.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/oauth2 v0.15.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.16.1 // indirect
google.golang.org/appengine v1.6.7 // indirect

@ -35,14 +35,14 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ=
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
github.com/containerd/containerd v1.7.13 h1:wPYKIeGMN8vaggSKuV1X0wZulpMz4CrgEsZdaCyB6Is=
github.com/containerd/containerd v1.7.13/go.mod h1:zT3up6yTRfEUa6+GsITYIJNgSVL9NQ4x4h1RPzk0Wu4=
github.com/containerd/containerd v1.7.15 h1:afEHXdil9iAm03BmhjzKyXnnEBtjaLJefdU7DV0IFes=
github.com/containerd/containerd v1.7.15/go.mod h1:ISzRRTMF8EXNpJlTzyr2XMhN+j9K302C21/+cr3kUnY=
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/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
github.com/corpix/uarand v0.1.1 h1:RMr1TWc9F4n5jiPDzFHtmaUXLKLNUFK0SgCLo4BhX/U=
github.com/corpix/uarand v0.1.1/go.mod h1:SFKZvkcRoLqVRFZ4u25xPmp6m9ktANfbpXZ7SJ0/FNU=
github.com/corpix/uarand v0.0.0-20170723150923-031be390f409 h1:9A+mfQmwzZ6KwUXPc8nHxFtKgn9VIvO3gXAOspIcE3s=
github.com/corpix/uarand v0.0.0-20170723150923-031be390f409/go.mod h1:JSm890tOkDN+M1jqN8pUGDKnzJrsVbJwSMHBY4zwz7M=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@ -57,13 +57,13 @@ github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v25.0.3+incompatible h1:KLeNs7zws74oFuVhgZQ5ONGZiXUUdgsdy6/EsX/6284=
github.com/docker/cli v25.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I=
github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v25.0.3+incompatible h1:D5fy/lYmY7bvZa0XTZ5/UJPljor41F+vdyJG5luQLfQ=
github.com/docker/docker v25.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU=
github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo=
github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
@ -122,8 +122,8 @@ github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/goodhosts/hostsfile v0.1.1 h1:SqRUTFOshOCon0ZSXDrW1bkKZvs4+5pRgYFWySdaLno=
github.com/goodhosts/hostsfile v0.1.1/go.mod h1:lXcUP8xO4WR5vvuQ3F/N0bMQoclOtYKEEUnyY2jTusY=
github.com/goodhosts/hostsfile v0.1.6 h1:aK6DxpNV6pZ1NbdvNE2vYBMTnvIJF5O2J/8ZOlp2eMY=
github.com/goodhosts/hostsfile v0.1.6/go.mod h1:bkCocEIf3Ca0hcBustUZoWYhOgKUaIK+47m8fBjoBx8=
github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93 h1:jc2UWq7CbdszqeH6qu1ougXMIUBfSy8Pbh/anURYbGI=
github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
@ -133,8 +133,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.16.1 h1:rUEt426sR6nyrL3gt+18ibRcvYpKYdpsa5ZW7MA08dQ=
github.com/google/go-containerregistry v0.16.1/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
github.com/google/go-containerregistry v0.19.1 h1:yMQ62Al6/V0Z7CqIrrS1iYoA5/oQCm88DeNujc7C1KY=
github.com/google/go-containerregistry v0.19.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -150,8 +150,8 @@ github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMW
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 h1:Mo9W14pwbO9VfRe+ygqZ8dFbPpoIK1HFrG/zjTuQ+nc=
github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428/go.mod h1:uhpZMVGznybq1itEKXj6RYw9I71qK4kH+OGMjRC4KEo=
github.com/icrowley/fake v0.0.0-20221112152111-d7b7e2276db2 h1:qU3v73XG4QAqCPHA4HOpfC1EfUvtLIDvQK4mNQ0LvgI=
github.com/icrowley/fake v0.0.0-20221112152111-d7b7e2276db2/go.mod h1:dQ6TM/OGAe+cMws81eTe4Btv1dKxfPZ2CX+YaAFAPN4=
github.com/imdario/mergo v0.3.14 h1:fOqeC1+nCuuk6PKQdg9YmosXX7Y7mHX6R/0ZldI9iHo=
github.com/imdario/mergo v0.3.14/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
@ -187,6 +187,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
@ -208,6 +210,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
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.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo=
github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
@ -357,8 +361,8 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go4.org/netipx v0.0.0-20230728184502-ec4c8b891b28 h1:zLxFnORHDFTSkJPawMU7LzsuGQJ4MUFS653jJHpORow=
go4.org/netipx v0.0.0-20230728184502-ec4c8b891b28/go.mod h1:TQvodOM+hJTioNQJilmLXu08JNb8i+ccq418+KWu1/Y=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -366,8 +370,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@ -382,8 +386,8 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -392,8 +396,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -407,11 +411,11 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=

@ -585,6 +585,9 @@ github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+Lv
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Masterminds/glide v0.13.2/go.mod h1:STyF5vcenH/rUqTEv+/hBXlSTo7KYwg2oc2f4tzPWic=
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/vcs v1.13.0/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA=
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
@ -645,6 +648,7 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWH
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
github.com/codegangsta/cli v1.20.0/go.mod h1:/qJNoX69yVSKu5o4jLyXAENLRyk1uhi7zkbQ3slBdOA=
github.com/container-orchestrated-devices/container-device-interface v0.5.4/go.mod h1:DjE95rfPiiSmG7uVXtg0z6MnPm/Lx4wxKCIts0ZE0vg=
github.com/containerd/btrfs/v2 v2.0.0/go.mod h1:swkD/7j9HApWpzl8OHfrHNxppPd9l44DFZdF94BUj9k=
github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8=
@ -670,9 +674,11 @@ github.com/containerd/imgcrypt v1.1.4/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO
github.com/containerd/imgcrypt v1.1.7/go.mod h1:FD8gqIcX5aTotCtOmjeCsi3A1dHmTZpnMISGKSczt4k=
github.com/containerd/nri v0.3.0/go.mod h1:Zw9q2lP16sdg0zYybemZ9yTDy8g7fPCIB3KXOGlggXI=
github.com/containerd/nri v0.4.0/go.mod h1:Zw9q2lP16sdg0zYybemZ9yTDy8g7fPCIB3KXOGlggXI=
github.com/containerd/nri v0.6.0/go.mod h1:F7OZfO4QTPqw5r87aq+syZJwiVvRYLIlHZiZDBV1W3A=
github.com/containerd/ttrpc v1.1.2/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
github.com/containerd/ttrpc v1.2.1/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak=
github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak=
github.com/containerd/ttrpc v1.2.3/go.mod h1:ieWsXucbb8Mj9PH0rXCw1i8IunRbbAiDkpXkbfflWBM=
github.com/containerd/typeurl/v2 v2.1.0/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
github.com/containerd/zfs v1.1.0/go.mod h1:oZF9wBnrnQjpWLaPKEinrx3TQ9a+W/RJO7Zb41d8YLE=
@ -943,6 +949,7 @@ github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8
github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs=
github.com/ngdinhtoan/glide-cleanup v0.2.0/go.mod h1:UQzsmiDOb8YV3nOsCxK/c9zPpCZVNoHScRE3EO9pVMM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
@ -1170,6 +1177,8 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
@ -1221,6 +1230,7 @@ golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
@ -1316,6 +1326,7 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -1326,6 +1337,8 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
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/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
@ -1491,6 +1504,7 @@ google.golang.org/genproto/googleapis/bytestream v0.0.0-20231120223509-83a465c02
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE=
@ -1519,6 +1533,7 @@ google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
google.golang.org/grpc v1.57.1/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
@ -1531,6 +1546,7 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
honnef.co/go/tools v0.4.2/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA=
honnef.co/go/tools v0.4.5/go.mod h1:GUV+uIBCLpdf0/v6UhHHG/yzI/z6qPskBeQCjcNB96k=
k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs=
k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg=
k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU=

@ -11,19 +11,11 @@ import (
"github.com/moby/term"
)
// CLIOption applies a modification on a DockerCli.
// CLIOption is a functional argument to apply options to a [DockerCli]. These
// options can be passed to [NewDockerCli] to initialize a new CLI, or
// applied with [DockerCli.Initialize] or [DockerCli.Apply].
type CLIOption func(cli *DockerCli) error
// DockerCliOption applies a modification on a DockerCli.
//
// Deprecated: use [CLIOption] instead.
type DockerCliOption = CLIOption
// InitializeOpt is the type of the functional options passed to DockerCli.Initialize
//
// Deprecated: use [CLIOption] instead.
type InitializeOpt = CLIOption
// WithStandardStreams sets a cli in, out and err streams with the standard streams.
func WithStandardStreams() CLIOption {
return func(cli *DockerCli) error {

@ -9,12 +9,16 @@ import (
// EventHandler is abstract interface for user to customize
// own handle functions of each type of events
//
// Deprecated: EventHandler is no longer used, and will be removed in the next release.
type EventHandler interface {
Handle(action events.Action, h func(events.Message))
Watch(c <-chan events.Message)
}
// InitEventHandler initializes and returns an EventHandler
//
// Deprecated: InitEventHandler is no longer used, and will be removed in the next release.
func InitEventHandler() EventHandler {
return &eventHandler{handlers: make(map[events.Action]func(events.Message))}
}

@ -5,12 +5,15 @@ package command
import (
"bufio"
"context"
"fmt"
"io"
"os"
"os/signal"
"path/filepath"
"runtime"
"strings"
"syscall"
"github.com/docker/cli/cli/streams"
"github.com/docker/docker/api/types/filters"
@ -72,12 +75,21 @@ func PrettyPrint(i any) string {
}
}
// PromptForConfirmation requests and checks confirmation from user.
// This will display the provided message followed by ' [y/N] '. If
// the user input 'y' or 'Y' it returns true other false. If no
// message is provided "Are you sure you want to proceed? [y/N] "
// will be used instead.
func PromptForConfirmation(ins io.Reader, outs io.Writer, message string) bool {
type PromptError error
var ErrPromptTerminated = PromptError(errors.New("prompt terminated"))
// PromptForConfirmation requests and checks confirmation from the user.
// This will display the provided message followed by ' [y/N] '. If the user
// input 'y' or 'Y' it returns true otherwise false. If no message is provided,
// "Are you sure you want to proceed? [y/N] " will be used instead.
//
// If the user terminates the CLI with SIGINT or SIGTERM while the prompt is
// active, the prompt will return false with an ErrPromptTerminated error.
// When the prompt returns an error, the caller should propagate the error up
// the stack and close the io.Reader used for the prompt which will prevent the
// background goroutine from blocking indefinitely.
func PromptForConfirmation(ctx context.Context, ins io.Reader, outs io.Writer, message string) (bool, error) {
if message == "" {
message = "Are you sure you want to proceed?"
}
@ -90,9 +102,31 @@ func PromptForConfirmation(ins io.Reader, outs io.Writer, message string) bool {
ins = streams.NewIn(os.Stdin)
}
reader := bufio.NewReader(ins)
answer, _, _ := reader.ReadLine()
return strings.ToLower(string(answer)) == "y"
result := make(chan bool)
// Catch the termination signal and exit the prompt gracefully.
// The caller is responsible for properly handling the termination.
notifyCtx, notifyCancel := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
defer notifyCancel()
go func() {
var res bool
scanner := bufio.NewScanner(ins)
if scanner.Scan() {
answer := strings.TrimSpace(scanner.Text())
if strings.EqualFold(answer, "y") {
res = true
}
}
result <- res
}()
select {
case <-notifyCtx.Done():
return false, ErrPromptTerminated
case r := <-result:
return r, nil
}
}
// PruneFilters returns consolidated prune filters obtained from config.json and cli

@ -131,6 +131,8 @@ func (m *MountOpt) Set(value string) error {
return fmt.Errorf("invalid value for %s: %s (must be \"enabled\", \"disabled\", \"writable\", or \"readonly\")",
key, val)
}
case "volume-subpath":
volumeOptions().Subpath = val
case "volume-nocopy":
volumeOptions().NoCopy, err = strconv.ParseBool(val)
if err != nil {

@ -2,8 +2,17 @@ package api // import "github.com/docker/docker/api"
// Common constants for daemon and client.
const (
// DefaultVersion of Current REST API
DefaultVersion = "1.44"
// DefaultVersion of the current REST API.
DefaultVersion = "1.45"
// MinSupportedAPIVersion is the minimum API version that can be supported
// by the API server, specified as "major.minor". Note that the daemon
// may be configured with a different minimum API version, as returned
// in [github.com/docker/docker/api/types.Version.MinAPIVersion].
//
// API requests for API versions lower than the configured version produce
// an error.
MinSupportedAPIVersion = "1.24"
// NoBaseImageSpecifier is the symbol used by the FROM
// command to specify that no base image is to be used.

@ -19,10 +19,10 @@ produces:
consumes:
- "application/json"
- "text/plain"
basePath: "/v1.44"
basePath: "/v1.45"
info:
title: "Docker Engine API"
version: "1.44"
version: "1.45"
x-logo:
url: "https://docs.docker.com/assets/images/logo-docker-main.png"
description: |
@ -55,8 +55,8 @@ info:
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
is returned.
If you omit the version-prefix, the current version of the API (v1.44) is used.
For example, calling `/info` is the same as calling `/v1.44/info`. Using the
If you omit the version-prefix, the current version of the API (v1.45) is used.
For example, calling `/info` is the same as calling `/v1.45/info`. Using the
API without a version-prefix is deprecated and will be removed in a future release.
Engine releases in the near future should support this version of the API,
@ -391,7 +391,11 @@ definitions:
ReadOnlyNonRecursive:
description: |
Make the mount non-recursively read-only, but still leave the mount recursive
(unless NonRecursive is set to true in conjunction).
(unless NonRecursive is set to `true` in conjunction).
Addded in v1.44, before that version all read-only mounts were
non-recursive by default. To match the previous behaviour this
will default to `true` for clients on versions prior to v1.44.
type: "boolean"
default: false
ReadOnlyForceRecursive:
@ -423,6 +427,10 @@ definitions:
type: "object"
additionalProperties:
type: "string"
Subpath:
description: "Source path inside the volume. Must be relative without any back traversals."
type: "string"
example: "dir-inside-volume/subdirectory"
TmpfsOptions:
description: "Optional configuration for the `tmpfs` type."
type: "object"
@ -1743,8 +1751,12 @@ definitions:
description: |
Date and time at which the image was created, formatted in
[RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds.
This information is only available if present in the image,
and omitted otherwise.
type: "string"
x-nullable: false
format: "dateTime"
x-nullable: true
example: "2022-02-04T21:20:12.497794809Z"
Container:
description: |
@ -8762,8 +8774,7 @@ paths:
<p><br /></p>
> **Deprecated**: This field is deprecated and will always
> be "false" in future.
> **Deprecated**: This field is deprecated and will always be "false".
type: "boolean"
example: false
name:
@ -8806,13 +8817,8 @@ paths:
description: |
A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters:
- `is-automated=(true|false)` (deprecated, see below)
- `is-official=(true|false)`
- `stars=<number>` Matches images that has at least 'number' stars.
The `is-automated` filter is deprecated. The `is_automated` field has
been deprecated by Docker Hub's search API. Consequently, searching
for `is-automated=true` will yield no results.
type: "string"
tags: ["Image"]
/images/prune:

@ -157,42 +157,12 @@ type ImageBuildResponse struct {
OSType string
}
// ImageCreateOptions holds information to create images.
type ImageCreateOptions struct {
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry.
Platform string // Platform is the target platform of the image if it needs to be pulled from the registry.
}
// ImageImportSource holds source information for ImageImport
type ImageImportSource struct {
Source io.Reader // Source is the data to send to the server to create this image from. You must set SourceName to "-" to leverage this.
SourceName string // SourceName is the name of the image to pull. Set to "-" to leverage the Source attribute.
}
// ImageImportOptions holds information to import images from the client host.
type ImageImportOptions struct {
Tag string // Tag is the name to tag this image with. This attribute is deprecated.
Message string // Message is the message to tag the image with
Changes []string // Changes are the raw changes to apply to this image
Platform string // Platform is the target platform of the image
}
// ImageListOptions holds parameters to list images with.
type ImageListOptions struct {
// All controls whether all images in the graph are filtered, or just
// the heads.
All bool
// Filters is a JSON-encoded set of filter arguments.
Filters filters.Args
// SharedSize indicates whether the shared size of images should be computed.
SharedSize bool
// ContainerCount indicates whether container count should be computed.
ContainerCount bool
}
// ImageLoadResponse returns information to the client about a load process.
type ImageLoadResponse struct {
// Body must be closed to avoid a resource leak
@ -200,14 +170,6 @@ type ImageLoadResponse struct {
JSON bool
}
// ImagePullOptions holds information to pull images.
type ImagePullOptions struct {
All bool
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
PrivilegeFunc RequestPrivilegeFunc
Platform string
}
// RequestPrivilegeFunc is a function interface that
// clients can supply to retry operations after
// getting an authorization error.
@ -216,15 +178,6 @@ type ImagePullOptions struct {
// if the privilege request fails.
type RequestPrivilegeFunc func() (string, error)
// ImagePushOptions holds information to push images.
type ImagePushOptions ImagePullOptions
// ImageRemoveOptions holds parameters to remove images.
type ImageRemoveOptions struct {
Force bool
PruneChildren bool
}
// ImageSearchOptions holds parameters to search images with.
type ImageSearchOptions struct {
RegistryAuth string

@ -5,8 +5,8 @@ import (
"time"
"github.com/docker/docker/api/types/strslice"
dockerspec "github.com/docker/docker/image/spec/specs-go/v1"
"github.com/docker/go-connections/nat"
dockerspec "github.com/moby/docker-image-spec/specs-go/v1"
)
// MinimumDuration puts a minimum on user configured duration.

@ -1,9 +1,57 @@
package image
import ocispec "github.com/opencontainers/image-spec/specs-go/v1"
import "github.com/docker/docker/api/types/filters"
// GetImageOpts holds parameters to inspect an image.
type GetImageOpts struct {
Platform *ocispec.Platform
Details bool
// ImportOptions holds information to import images from the client host.
type ImportOptions struct {
Tag string // Tag is the name to tag this image with. This attribute is deprecated.
Message string // Message is the message to tag the image with
Changes []string // Changes are the raw changes to apply to this image
Platform string // Platform is the target platform of the image
}
// CreateOptions holds information to create images.
type CreateOptions struct {
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry.
Platform string // Platform is the target platform of the image if it needs to be pulled from the registry.
}
// PullOptions holds information to pull images.
type PullOptions struct {
All bool
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
// PrivilegeFunc is a function that clients can supply to retry operations
// after getting an authorization error. This function returns the registry
// authentication header value in base64 encoded format, or an error if the
// privilege request fails.
//
// Also see [github.com/docker/docker/api/types.RequestPrivilegeFunc].
PrivilegeFunc func() (string, error)
Platform string
}
// PushOptions holds information to push images.
type PushOptions PullOptions
// ListOptions holds parameters to list images with.
type ListOptions struct {
// All controls whether all images in the graph are filtered, or just
// the heads.
All bool
// Filters is a JSON-encoded set of filter arguments.
Filters filters.Args
// SharedSize indicates whether the shared size of images should be computed.
SharedSize bool
// ContainerCount indicates whether container count should be computed.
ContainerCount bool
}
// RemoveOptions holds parameters to remove images.
type RemoveOptions struct {
Force bool
PruneChildren bool
}

@ -96,6 +96,7 @@ type BindOptions struct {
type VolumeOptions struct {
NoCopy bool `json:",omitempty"`
Labels map[string]string `json:",omitempty"`
Subpath string `json:",omitempty"`
DriverConfig *Driver `json:",omitempty"`
}

@ -94,7 +94,7 @@ type SearchResult struct {
Name string `json:"name"`
// IsAutomated indicates whether the result is automated.
//
// Deprecated: the "is_automated" field is deprecated and will always be "false" in the future.
// Deprecated: the "is_automated" field is deprecated and will always be "false".
IsAutomated bool `json:"is_automated"`
// Description is a textual description of the repository
Description string `json:"description"`

@ -72,14 +72,17 @@ type ImageInspect struct {
// Created is the date and time at which the image was created, formatted in
// RFC 3339 nano-seconds (time.RFC3339Nano).
Created string
//
// This information is only available if present in the image,
// and omitted otherwise.
Created string `json:",omitempty"`
// Container is the ID of the container that was used to create the image.
//
// Depending on how the image was created, this field may be empty.
//
// Deprecated: this field is omitted in API v1.45, but kept for backward compatibility.
Container string
Container string `json:",omitempty"`
// ContainerConfig is an optional field containing the configuration of the
// container that was last committed when creating the image.
@ -88,7 +91,7 @@ type ImageInspect struct {
// and it is not in active use anymore.
//
// Deprecated: this field is omitted in API v1.45, but kept for backward compatibility.
ContainerConfig *container.Config
ContainerConfig *container.Config `json:",omitempty"`
// DockerVersion is the version of Docker that was used to build the image.
//

@ -1,138 +1,35 @@
package types
import (
"github.com/docker/docker/api/types/checkpoint"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/api/types/system"
)
// CheckpointCreateOptions holds parameters to create a checkpoint from a container.
// ImageImportOptions holds information to import images from the client host.
//
// Deprecated: use [checkpoint.CreateOptions].
type CheckpointCreateOptions = checkpoint.CreateOptions
// Deprecated: use [image.ImportOptions].
type ImageImportOptions = image.ImportOptions
// CheckpointListOptions holds parameters to list checkpoints for a container
// ImageCreateOptions holds information to create images.
//
// Deprecated: use [checkpoint.ListOptions].
type CheckpointListOptions = checkpoint.ListOptions
// Deprecated: use [image.CreateOptions].
type ImageCreateOptions = image.CreateOptions
// CheckpointDeleteOptions holds parameters to delete a checkpoint from a container
// ImagePullOptions holds information to pull images.
//
// Deprecated: use [checkpoint.DeleteOptions].
type CheckpointDeleteOptions = checkpoint.DeleteOptions
// Deprecated: use [image.PullOptions].
type ImagePullOptions = image.PullOptions
// Checkpoint represents the details of a checkpoint when listing endpoints.
// ImagePushOptions holds information to push images.
//
// Deprecated: use [checkpoint.Summary].
type Checkpoint = checkpoint.Summary
// Deprecated: use [image.PushOptions].
type ImagePushOptions = image.PushOptions
// Info contains response of Engine API:
// GET "/info"
// ImageListOptions holds parameters to list images with.
//
// Deprecated: use [system.Info].
type Info = system.Info
// Deprecated: use [image.ListOptions].
type ImageListOptions = image.ListOptions
// Commit holds the Git-commit (SHA1) that a binary was built from, as reported
// in the version-string of external tools, such as containerd, or runC.
// ImageRemoveOptions holds parameters to remove images.
//
// Deprecated: use [system.Commit].
type Commit = system.Commit
// PluginsInfo is a temp struct holding Plugins name
// registered with docker daemon. It is used by [system.Info] struct
//
// Deprecated: use [system.PluginsInfo].
type PluginsInfo = system.PluginsInfo
// NetworkAddressPool is a temp struct used by [system.Info] struct.
//
// Deprecated: use [system.NetworkAddressPool].
type NetworkAddressPool = system.NetworkAddressPool
// Runtime describes an OCI runtime.
//
// Deprecated: use [system.Runtime].
type Runtime = system.Runtime
// SecurityOpt contains the name and options of a security option.
//
// Deprecated: use [system.SecurityOpt].
type SecurityOpt = system.SecurityOpt
// KeyValue holds a key/value pair.
//
// Deprecated: use [system.KeyValue].
type KeyValue = system.KeyValue
// ImageDeleteResponseItem image delete response item.
//
// Deprecated: use [image.DeleteResponse].
type ImageDeleteResponseItem = image.DeleteResponse
// ImageSummary image summary.
//
// Deprecated: use [image.Summary].
type ImageSummary = image.Summary
// ImageMetadata contains engine-local data about the image.
//
// Deprecated: use [image.Metadata].
type ImageMetadata = image.Metadata
// ServiceCreateResponse contains the information returned to a client
// on the creation of a new service.
//
// Deprecated: use [swarm.ServiceCreateResponse].
type ServiceCreateResponse = swarm.ServiceCreateResponse
// ServiceUpdateResponse service update response.
//
// Deprecated: use [swarm.ServiceUpdateResponse].
type ServiceUpdateResponse = swarm.ServiceUpdateResponse
// ContainerStartOptions holds parameters to start containers.
//
// Deprecated: use [container.StartOptions].
type ContainerStartOptions = container.StartOptions
// ResizeOptions holds parameters to resize a TTY.
// It can be used to resize container TTYs and
// exec process TTYs too.
//
// Deprecated: use [container.ResizeOptions].
type ResizeOptions = container.ResizeOptions
// ContainerAttachOptions holds parameters to attach to a container.
//
// Deprecated: use [container.AttachOptions].
type ContainerAttachOptions = container.AttachOptions
// ContainerCommitOptions holds parameters to commit changes into a container.
//
// Deprecated: use [container.CommitOptions].
type ContainerCommitOptions = container.CommitOptions
// ContainerListOptions holds parameters to list containers with.
//
// Deprecated: use [container.ListOptions].
type ContainerListOptions = container.ListOptions
// ContainerLogsOptions holds parameters to filter logs with.
//
// Deprecated: use [container.LogsOptions].
type ContainerLogsOptions = container.LogsOptions
// ContainerRemoveOptions holds parameters to remove containers.
//
// Deprecated: use [container.RemoveOptions].
type ContainerRemoveOptions = container.RemoveOptions
// DecodeSecurityOptions decodes a security options string slice to a type safe
// [system.SecurityOpt].
//
// Deprecated: use [system.DecodeSecurityOptions].
func DecodeSecurityOptions(opts []string) ([]system.SecurityOpt, error) {
return system.DecodeSecurityOptions(opts)
}
// Deprecated: use [image.RemoveOptions].
type ImageRemoveOptions = image.RemoveOptions

@ -1,14 +0,0 @@
# Legacy API type versions
This package includes types for legacy API versions. The stable version of the API types live in `api/types/*.go`.
Consider moving a type here when you need to keep backwards compatibility in the API. This legacy types are organized by the latest API version they appear in. For instance, types in the `v1p19` package are valid for API versions below or equal `1.19`. Types in the `v1p20` package are valid for the API version `1.20`, since the versions below that will use the legacy types in `v1p19`.
## Package name conventions
The package name convention is to use `v` as a prefix for the version number and `p`(patch) as a separator. We use this nomenclature due to a few restrictions in the Go package name convention:
1. We cannot use `.` because it's interpreted by the language, think of `v1.20.CallFunction`.
2. We cannot use `_` because golint complains about it. The code is actually valid, but it looks probably more weird: `v1_20.CallFunction`.
For instance, if you want to modify a type that was available in the version `1.21` of the API but it will have different fields in the version `1.22`, you want to create a new package under `api/types/versions/v1p21`.

@ -238,13 +238,13 @@ type TopologyRequirement struct {
// If requisite is specified, all topologies in preferred list MUST
// also be present in the list of requisite topologies.
//
// If the SP is unable to to make the provisioned volume available
// If the SP is unable to make the provisioned volume available
// from any of the preferred topologies, the SP MAY choose a topology
// from the list of requisite topologies.
// If the list of requisite topologies is not specified, then the SP
// MAY choose from the list of all possible topologies.
// If the list of requisite topologies is specified and the SP is
// unable to to make the provisioned volume available from any of the
// unable to make the provisioned volume available from any of the
// requisite topologies it MUST fail the CreateVolume call.
//
// Example 1:
@ -254,7 +254,7 @@ type TopologyRequirement struct {
// {"region": "R1", "zone": "Z3"}
// preferred =
// {"region": "R1", "zone": "Z3"}
// then the the SP SHOULD first attempt to make the provisioned volume
// then the SP SHOULD first attempt to make the provisioned volume
// available from "zone" "Z3" in the "region" "R1" and fall back to
// "zone" "Z2" in the "region" "R1" if that is not possible.
//
@ -268,7 +268,7 @@ type TopologyRequirement struct {
// preferred =
// {"region": "R1", "zone": "Z4"},
// {"region": "R1", "zone": "Z2"}
// then the the SP SHOULD first attempt to make the provisioned volume
// then the SP SHOULD first attempt to make the provisioned volume
// accessible from "zone" "Z4" in the "region" "R1" and fall back to
// "zone" "Z2" in the "region" "R1" if that is not possible. If that
// is not possible, the SP may choose between either the "zone"
@ -287,7 +287,7 @@ type TopologyRequirement struct {
// preferred =
// {"region": "R1", "zone": "Z5"},
// {"region": "R1", "zone": "Z3"}
// then the the SP SHOULD first attempt to make the provisioned volume
// then the SP SHOULD first attempt to make the provisioned volume
// accessible from the combination of the two "zones" "Z5" and "Z3" in
// the "region" "R1". If that's not possible, it should fall back to
// a combination of "Z5" and other possibilities from the list of

@ -265,17 +265,22 @@ func (cli *Client) Close() error {
// This allows for version-dependent code to use the same version as will
// be negotiated when making the actual requests, and for which cases
// we cannot do the negotiation lazily.
func (cli *Client) checkVersion(ctx context.Context) {
if cli.negotiateVersion && !cli.negotiated {
cli.NegotiateAPIVersion(ctx)
func (cli *Client) checkVersion(ctx context.Context) error {
if !cli.manualOverride && cli.negotiateVersion && !cli.negotiated {
ping, err := cli.Ping(ctx)
if err != nil {
return err
}
cli.negotiateAPIVersionPing(ping)
}
return nil
}
// getAPIPath returns the versioned request path to call the API.
// It appends the query parameters to the path if they are not empty.
func (cli *Client) getAPIPath(ctx context.Context, p string, query url.Values) string {
var apiPath string
cli.checkVersion(ctx)
_ = cli.checkVersion(ctx)
if cli.version != "" {
v := strings.TrimPrefix(cli.version, "v")
apiPath = path.Join(cli.basePath, "/v"+v, p)
@ -307,7 +312,11 @@ func (cli *Client) ClientVersion() string {
// added (1.24).
func (cli *Client) NegotiateAPIVersion(ctx context.Context) {
if !cli.manualOverride {
ping, _ := cli.Ping(ctx)
ping, err := cli.Ping(ctx)
if err != nil {
// FIXME(thaJeztah): Ping returns an error when failing to connect to the API; we should not swallow the error here, and instead returning it.
return
}
cli.negotiateAPIVersionPing(ping)
}
}

@ -28,7 +28,9 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if err := cli.checkVersion(ctx); err != nil {
return response, err
}
if err := cli.NewVersionError(ctx, "1.25", "stop timeout"); config != nil && config.StopTimeout != nil && err != nil {
return response, err

@ -18,7 +18,9 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, container string, co
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if err := cli.checkVersion(ctx); err != nil {
return response, err
}
if err := cli.NewVersionError(ctx, "1.25", "env"); len(config.Env) != 0 && err != nil {
return response, err

@ -23,7 +23,9 @@ func (cli *Client) ContainerRestart(ctx context.Context, containerID string, opt
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if err := cli.checkVersion(ctx); err != nil {
return err
}
if versions.GreaterThanOrEqualTo(cli.version, "1.42") {
query.Set("signal", options.Signal)
}

@ -27,7 +27,9 @@ func (cli *Client) ContainerStop(ctx context.Context, containerID string, option
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if err := cli.checkVersion(ctx); err != nil {
return err
}
if versions.GreaterThanOrEqualTo(cli.version, "1.42") {
query.Set("signal", options.Signal)
}

@ -30,19 +30,22 @@ const containerWaitErrorMsgLimit = 2 * 1024 /* Max: 2KiB */
// synchronize ContainerWait with other calls, such as specifying a
// "next-exit" condition before issuing a ContainerStart request.
func (cli *Client) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error) {
resultC := make(chan container.WaitResponse)
errC := make(chan error, 1)
// Make sure we negotiated (if the client is configured to do so),
// as code below contains API-version specific handling of options.
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if err := cli.checkVersion(ctx); err != nil {
errC <- err
return resultC, errC
}
if versions.LessThan(cli.ClientVersion(), "1.30") {
return cli.legacyContainerWait(ctx, containerID)
}
resultC := make(chan container.WaitResponse)
errC := make(chan error, 1)
query := url.Values{}
if condition != "" {
query.Set("condition", string(condition))

@ -10,11 +10,11 @@ import (
)
// DistributionInspect returns the image digest with the full manifest.
func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registry.DistributionInspect, error) {
func (cli *Client) DistributionInspect(ctx context.Context, imageRef, encodedRegistryAuth string) (registry.DistributionInspect, error) {
// Contact the registry to retrieve digest and platform information
var distributionInspect registry.DistributionInspect
if image == "" {
return distributionInspect, objectNotFoundError{object: "distribution", id: image}
if imageRef == "" {
return distributionInspect, objectNotFoundError{object: "distribution", id: imageRef}
}
if err := cli.NewVersionError(ctx, "1.30", "distribution inspect"); err != nil {
@ -28,7 +28,7 @@ func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegist
}
}
resp, err := cli.get(ctx, "/distribution/"+image+"/json", url.Values{}, headers)
resp, err := cli.get(ctx, "/distribution/"+imageRef+"/json", url.Values{}, headers)
defer ensureReaderClosed(resp)
if err != nil {
return distributionInspect, err

@ -11,15 +11,16 @@ import (
// errConnectionFailed implements an error returned when connection failed.
type errConnectionFailed struct {
host string
error
}
// Error returns a string representation of an errConnectionFailed
func (err errConnectionFailed) Error() string {
if err.host == "" {
return "Cannot connect to the Docker daemon. Is the docker daemon running on this host?"
}
return fmt.Sprintf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", err.host)
func (e errConnectionFailed) Error() string {
return e.error.Error()
}
func (e errConnectionFailed) Unwrap() error {
return e.error
}
// IsErrConnectionFailed returns true if the error is caused by connection failed.
@ -29,7 +30,13 @@ func IsErrConnectionFailed(err error) bool {
// ErrorConnectionFailed returns an error with host in the error message when connection to docker daemon failed.
func ErrorConnectionFailed(host string) error {
return errConnectionFailed{host: host}
var err error
if host == "" {
err = fmt.Errorf("Cannot connect to the Docker daemon. Is the docker daemon running on this host?")
} else {
err = fmt.Errorf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", host)
}
return errConnectionFailed{error: err}
}
// IsErrNotFound returns true if the error is a NotFound error, which is returned
@ -60,7 +67,9 @@ func (cli *Client) NewVersionError(ctx context.Context, APIrequired, feature str
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if err := cli.checkVersion(ctx); err != nil {
return err
}
if cli.version != "" && versions.LessThan(cli.version, APIrequired) {
return fmt.Errorf("%q requires API version %s, but the Docker daemon API version is %s", feature, APIrequired, cli.version)
}

@ -8,13 +8,13 @@ import (
"strings"
"github.com/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/registry"
)
// ImageCreate creates a new image based on the parent options.
// It returns the JSON content in the response body.
func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) {
func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options image.CreateOptions) (io.ReadCloser, error) {
ref, err := reference.ParseNormalizedNamed(parentReference)
if err != nil {
return nil, err

@ -8,11 +8,12 @@ import (
"github.com/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/image"
)
// ImageImport creates a new image based on the source options.
// It returns the JSON content in the response body.
func (cli *Client) ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
func (cli *Client) ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options image.ImportOptions) (io.ReadCloser, error) {
if ref != "" {
// Check if the given image name can be resolved
if _, err := reference.ParseNormalizedNamed(ref); err != nil {

@ -5,22 +5,24 @@ import (
"encoding/json"
"net/url"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/versions"
)
// ImageList returns a list of images in the docker host.
func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions) ([]image.Summary, error) {
func (cli *Client) ImageList(ctx context.Context, options image.ListOptions) ([]image.Summary, error) {
var images []image.Summary
// Make sure we negotiated (if the client is configured to do so),
// as code below contains API-version specific handling of options.
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if err := cli.checkVersion(ctx); err != nil {
return images, err
}
var images []image.Summary
query := url.Values{}
optionFilters := options.Filters

@ -7,7 +7,7 @@ import (
"strings"
"github.com/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/errdefs"
)
@ -19,7 +19,7 @@ import (
// FIXME(vdemeester): there is currently used in a few way in docker/docker
// - if not in trusted content, ref is used to pass the whole reference, and tag is empty
// - if in trusted content, ref is used to pass the reference name, and tag for the digest
func (cli *Client) ImagePull(ctx context.Context, refStr string, options types.ImagePullOptions) (io.ReadCloser, error) {
func (cli *Client) ImagePull(ctx context.Context, refStr string, options image.PullOptions) (io.ReadCloser, error) {
ref, err := reference.ParseNormalizedNamed(refStr)
if err != nil {
return nil, err

@ -8,7 +8,7 @@ import (
"net/url"
"github.com/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/errdefs"
)
@ -17,7 +17,7 @@ import (
// It executes the privileged function if the operation is unauthorized
// and it tries one more time.
// It's up to the caller to handle the io.ReadCloser and close it properly.
func (cli *Client) ImagePush(ctx context.Context, image string, options types.ImagePushOptions) (io.ReadCloser, error) {
func (cli *Client) ImagePush(ctx context.Context, image string, options image.PushOptions) (io.ReadCloser, error) {
ref, err := reference.ParseNormalizedNamed(image)
if err != nil {
return nil, err

@ -5,12 +5,11 @@ import (
"encoding/json"
"net/url"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/image"
)
// ImageRemove removes an image from the docker host.
func (cli *Client) ImageRemove(ctx context.Context, imageID string, options types.ImageRemoveOptions) ([]image.DeleteResponse, error) {
func (cli *Client) ImageRemove(ctx context.Context, imageID string, options image.RemoveOptions) ([]image.DeleteResponse, error) {
query := url.Values{}
if options.Force {

@ -90,15 +90,15 @@ type ImageAPIClient interface {
ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error)
BuildCancel(ctx context.Context, id string) error
ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
ImageCreate(ctx context.Context, parentReference string, options image.CreateOptions) (io.ReadCloser, error)
ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error)
ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options image.ImportOptions) (io.ReadCloser, error)
ImageInspectWithRaw(ctx context.Context, image string) (types.ImageInspect, []byte, error)
ImageList(ctx context.Context, options types.ImageListOptions) ([]image.Summary, error)
ImageList(ctx context.Context, options image.ListOptions) ([]image.Summary, error)
ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error)
ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error)
ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error)
ImageRemove(ctx context.Context, image string, options types.ImageRemoveOptions) ([]image.DeleteResponse, error)
ImagePull(ctx context.Context, ref string, options image.PullOptions) (io.ReadCloser, error)
ImagePush(ctx context.Context, ref string, options image.PushOptions) (io.ReadCloser, error)
ImageRemove(ctx context.Context, image string, options image.RemoveOptions) ([]image.DeleteResponse, error)
ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error)
ImageSave(ctx context.Context, images []string) (io.ReadCloser, error)
ImageTag(ctx context.Context, image, ref string) error

@ -10,12 +10,16 @@ import (
// NetworkCreate creates a new network in the docker host.
func (cli *Client) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) {
var response types.NetworkCreateResponse
// Make sure we negotiated (if the client is configured to do so),
// as code below contains API-version specific handling of options.
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if err := cli.checkVersion(ctx); err != nil {
return response, err
}
networkCreateRequest := types.NetworkCreateRequest{
NetworkCreate: options,
@ -25,7 +29,6 @@ func (cli *Client) NetworkCreate(ctx context.Context, name string, options types
networkCreateRequest.CheckDuplicate = true //nolint:staticcheck // ignore SA1019: CheckDuplicate is deprecated since API v1.44.
}
var response types.NetworkCreateResponse
serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil)
defer ensureReaderClosed(serverResp)
if err != nil {

@ -14,7 +14,10 @@ import (
// Ping pings the server and returns the value of the "Docker-Experimental",
// "Builder-Version", "OS-Type" & "API-Version" headers. It attempts to use
// a HEAD request on the endpoint, but falls back to GET if HEAD is not supported
// by the daemon.
// by the daemon. It ignores internal server errors returned by the API, which
// may be returned if the daemon is in an unhealthy state, but returns errors
// for other non-success status codes, failing to connect to the API, or failing
// to parse the API response.
func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
var ping types.Ping

@ -134,17 +134,18 @@ func (cli *Client) sendRequest(ctx context.Context, method, path string, query u
return resp, errdefs.FromStatusCode(err, resp.statusCode)
}
// FIXME(thaJeztah): Should this actually return a serverResp when a connection error occurred?
func (cli *Client) doRequest(req *http.Request) (serverResponse, error) {
serverResp := serverResponse{statusCode: -1, reqURL: req.URL}
resp, err := cli.client.Do(req)
if err != nil {
if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") {
return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)
return serverResp, errConnectionFailed{fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)}
}
if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") {
return serverResp, errors.Wrap(err, "the server probably has client authentication (--tlsverify) enabled; check your TLS client certification settings")
return serverResp, errConnectionFailed{errors.Wrap(err, "the server probably has client authentication (--tlsverify) enabled; check your TLS client certification settings")}
}
// Don't decorate context sentinel errors; users may be comparing to
@ -156,12 +157,13 @@ func (cli *Client) doRequest(req *http.Request) (serverResponse, error) {
if uErr, ok := err.(*url.Error); ok {
if nErr, ok := uErr.Err.(*net.OpError); ok {
if os.IsPermission(nErr.Err) {
return serverResp, errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)
return serverResp, errConnectionFailed{errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)}
}
}
}
if nErr, ok := err.(net.Error); ok {
// FIXME(thaJeztah): any net.Error should be considered a connection error (but we should include the original error)?
if nErr.Timeout() {
return serverResp, ErrorConnectionFailed(cli.host)
}
@ -190,7 +192,7 @@ func (cli *Client) doRequest(req *http.Request) (serverResponse, error) {
}
}
return serverResp, errors.Wrap(err, "error during connect")
return serverResp, errConnectionFailed{errors.Wrap(err, "error during connect")}
}
if resp != nil {

@ -25,7 +25,9 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec,
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if err := cli.checkVersion(ctx); err != nil {
return response, err
}
// Make sure containerSpec is not nil when no runtime is set or the runtime is set to container
if service.TaskTemplate.ContainerSpec == nil && (service.TaskTemplate.Runtime == "" || service.TaskTemplate.Runtime == swarm.RuntimeContainer) {

@ -16,18 +16,18 @@ import (
// It should be the value as set *before* the update. You can find this value in the Meta field
// of swarm.Service, which can be found using ServiceInspectWithRaw.
func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (swarm.ServiceUpdateResponse, error) {
response := swarm.ServiceUpdateResponse{}
// Make sure we negotiated (if the client is configured to do so),
// as code below contains API-version specific handling of options.
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
var (
query = url.Values{}
response = swarm.ServiceUpdateResponse{}
)
if err := cli.checkVersion(ctx); err != nil {
return response, err
}
query := url.Values{}
if options.RegistryAuthFrom != "" {
query.Set("registryAuthFrom", options.RegistryAuthFrom)
}

@ -16,7 +16,9 @@ func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if err := cli.checkVersion(ctx); err != nil {
return err
}
if versions.GreaterThanOrEqualTo(cli.version, "1.25") {
query.Set("force", "1")
}

@ -6,14 +6,6 @@ import (
"runtime"
)
// Key returns the env var name for the user's home dir based on
// the platform being run on.
//
// Deprecated: this function is no longer used, and will be removed in the next release.
func Key() string {
return envKeyName
}
// Get returns the home directory of the current user with the help of
// environment variables depending on the target operating system.
// Returned path should be used with "path/filepath" to form new paths.
@ -34,11 +26,3 @@ func Get() string {
}
return home
}
// GetShortcutString returns the string that is shortcut to user's home directory
// in the native shell of the platform running on.
//
// Deprecated: this function is no longer used, and will be removed in the next release.
func GetShortcutString() string {
return homeShortCut
}

@ -1,8 +0,0 @@
//go:build !windows
package homedir // import "github.com/docker/docker/pkg/homedir"
const (
envKeyName = "HOME"
homeShortCut = "~"
)

@ -1,6 +0,0 @@
package homedir // import "github.com/docker/docker/pkg/homedir"
const (
envKeyName = "USERPROFILE"
homeShortCut = "%USERPROFILE%" // be careful while using in format functions
)

@ -1,19 +0,0 @@
package system
import (
"errors"
"runtime"
"strings"
)
// ErrNotSupportedOperatingSystem means the operating system is not supported.
//
// Deprecated: use [github.com/docker/docker/image.CheckOS] and check the error returned.
var ErrNotSupportedOperatingSystem = errors.New("operating system is not supported")
// IsOSSupported determines if an operating system is supported by the host.
//
// Deprecated: use [github.com/docker/docker/image.CheckOS] and check the error returned.
func IsOSSupported(os string) bool {
return strings.EqualFold(runtime.GOOS, os)
}

@ -27,11 +27,16 @@ func (s *Service) Search(ctx context.Context, searchFilters filters.Args, term s
return nil, err
}
// TODO(thaJeztah): the "is-automated" field is deprecated; reset the field for the next release (v26.0.0). Return early when using "is-automated=true", and ignore "is-automated=false".
isAutomated, err := searchFilters.GetBoolOrDefault("is-automated", false)
if err != nil {
return nil, err
}
// "is-automated" is deprecated and filtering for `true` will yield no results.
if isAutomated {
return []registry.SearchResult{}, nil
}
isOfficial, err := searchFilters.GetBoolOrDefault("is-official", false)
if err != nil {
return nil, err
@ -51,7 +56,6 @@ func (s *Service) Search(ctx context.Context, searchFilters filters.Args, term s
}
}
// TODO(thaJeztah): the "is-automated" field is deprecated. Reset the field for the next release (v26.0.0) if any "true" values are present.
unfilteredResult, err := s.searchUnfiltered(ctx, term, limit, authConfig, headers)
if err != nil {
return nil, err
@ -59,11 +63,6 @@ func (s *Service) Search(ctx context.Context, searchFilters filters.Args, term s
filteredResults := []registry.SearchResult{}
for _, result := range unfilteredResult.Results {
if searchFilters.Contains("is-automated") {
if isAutomated != result.IsAutomated { //nolint:staticcheck // ignore SA1019 for old API versions.
continue
}
}
if searchFilters.Contains("is-official") {
if isOfficial != result.IsOfficial {
continue
@ -74,6 +73,10 @@ func (s *Service) Search(ctx context.Context, searchFilters filters.Args, term s
continue
}
}
// "is-automated" is deprecated and the value in Docker Hub search
// results is untrustworthy. Force it to false so as to not mislead our
// clients.
result.IsAutomated = false //nolint:staticcheck // ignore SA1019 (field is deprecated)
filteredResults = append(filteredResults, result)
}

@ -1 +1,2 @@
.idea
.idea
coverage.txt

@ -1,5 +0,0 @@
ci:
@goimports -l . || (goimports -d . && exit 1)
@golangci-lint run
@go test -v .
.DEFAULT_GOAL := ci

@ -0,0 +1,62 @@
# Go package for working with a system's hostsfile
[![codecov](https://codecov.io/gh/goodhosts/hostsfile/branch/main/graph/badge.svg?token=BJQH16QQEH)](https://codecov.io/gh/goodhosts/hostsfile)
[![Go Reference](https://pkg.go.dev/badge/github.com/goodhosts/hostsfile.svg)](https://pkg.go.dev/github.com/goodhosts/hostsfile)
Reads the content of a file in the [hosts format](https://en.wikipedia.org/wiki/Hosts_(file)) into go structs for easy manipulation in go programs. When all changes are complete you can `Flush` the hosts file back to disk to save your changes. Supports an indexing system on both ips and hosts for quick management of large hosts files.
## Simple Usage
Simple usage reading in your system's hosts file and adding an entry for the ip `192.168.1.1` and the host `my-hostname`
```go
package main
import (
"log"
"github.com/goodhosts/hostsfile"
)
func main() {
hosts, err := hostsfile.NewHosts()
if err != nil {
log.Fatal(err.Error())
}
if err := hosts.Add("192.168.1.1", "my-hostname"); err != nil {
log.Fatal(err.Error())
}
if err := hosts.Flush(); err != nil {
log.Fatal(err.Error())
}
}
```
### Other Usage
Read in a hosts file from a custom location which is not the system default, this is useful for tests or systems with non-standard hosts file locations.
```
hosts, err := hostsfile.NewCustomHosts("./my-custom-hostsfile")
```
Use `Add` to put an ip and host combination in the hosts file
```
err := hosts.Add("192.168.1.1", "my-hostname")
```
`Add` is variadic and can take multiple hosts to add for the same ip
```
err := hosts.Add("192.168.1.1", "my-hostname", "another-hostname")
```
Use `Remove` to drop an ip and host combination from the hosts file
```
err := hosts.Remove("192.168.1.1", "my-hostname")
```
`Remove` is variadic and can take multiple hosts to remove from the same ip
```
err := hosts.Remove("192.168.1.1", "my-hostname", "another-hostname")
```
Flush the hosts file changes back to disk
```
err := hosts.Flush()
```

@ -0,0 +1,6 @@
//go:build test
// +build test
package hostsfile
func main() {}

@ -8,25 +8,22 @@ import (
"os"
"path/filepath"
"sort"
"sync"
"strings"
"github.com/asaskevich/govalidator"
"github.com/dimchansky/utfbom"
)
type lookup struct {
sync.RWMutex
l map[string][]int
}
// Hosts represents hosts file with the path and parsed contents of each line
type Hosts struct {
Path string
Lines []HostsLine
Path string // Path to the location of the hosts file that will be loaded/flushed
Lines []HostsLine // Slice containing all the lines parsed from the hosts file
ips lookup
hosts lookup
}
// NewHosts return a new instance of ``Hosts`` using the default hosts file path.
// NewHosts return a new instance of Hosts using the default hosts file path.
func NewHosts() (*Hosts, error) {
osHostsFilePath := os.ExpandEnv(filepath.FromSlash(HostsFilePath))
@ -37,12 +34,12 @@ func NewHosts() (*Hosts, error) {
return NewCustomHosts(osHostsFilePath)
}
// NewCustomHosts return a new instance of ``Hosts`` using a custom hosts file path.
// NewCustomHosts return a new instance of Hosts using a custom hosts file path.
func NewCustomHosts(osHostsFilePath string) (*Hosts, error) {
hosts := &Hosts{
Path: osHostsFilePath,
ips: lookup{l: make(map[string][]int)},
hosts: lookup{l: make(map[string][]int)},
ips: newLookup(),
hosts: newLookup(),
}
if err := hosts.Load(); err != nil {
@ -52,7 +49,28 @@ func NewCustomHosts(osHostsFilePath string) (*Hosts, error) {
return hosts, nil
}
// IsWritable return ```true``` if hosts file is writable.
// String get a string of the contents of the contents to put in the hosts file
func (h *Hosts) String() string {
buf := new(bytes.Buffer)
for _, line := range h.Lines {
// bytes buffers doesn't actually throw errors but the io.Writer interface requires it
fmt.Fprintf(buf, "%s%s", line.ToRaw(), eol)
}
return buf.String()
}
// loadString is a helper function for testing but if we want to expose it somehow it's probably safe
func (h *Hosts) loadString(content string) error {
h.Clear()
rdr := strings.NewReader(content)
scanner := bufio.NewScanner(utfbom.SkipOnly(rdr))
for scanner.Scan() {
h.addLine(NewHostsLine(scanner.Text()))
}
return scanner.Err()
}
// IsWritable return true if hosts file is writable.
func (h *Hosts) IsWritable() bool {
file, err := os.OpenFile(h.Path, os.O_WRONLY, 0660)
if err != nil {
@ -62,9 +80,7 @@ func (h *Hosts) IsWritable() bool {
return true
}
// Load the hosts file into ```l.Lines```.
// ```Load()``` is called by ```NewHosts()``` and ```Hosts.Flush()``` so you
// generally you won't need to call this yourself.
// Load the hosts file from the Path into Lines, called by NewHosts() and Hosts.Flush() and you should not need to call this yourself.
func (h *Hosts) Load() error {
file, err := os.Open(h.Path)
if err != nil {
@ -72,35 +88,26 @@ func (h *Hosts) Load() error {
}
defer file.Close()
// if you're reloading from disk confirm you refresh the hash maps and lines
if len(h.Lines) != 0 {
h.ips = lookup{l: make(map[string][]int)}
h.hosts = lookup{l: make(map[string][]int)}
h.Lines = []HostsLine{}
}
h.Clear() // reset the lines and lookups in case anything was previously set
scanner := bufio.NewScanner(utfbom.SkipOnly(file))
for scanner.Scan() {
hl := NewHostsLine(scanner.Text())
h.Lines = append(h.Lines, hl)
pos := len(h.Lines) - 1
h.addIpPosition(hl.IP, pos)
for _, host := range hl.Hosts {
h.addHostPositions(host, pos)
}
h.addLine(NewHostsLine(scanner.Text()))
}
return scanner.Err()
}
// Flush any changes made to hosts file.
// Flush writes to the file located at Path the contents of Lines in a hostsfile format
func (h *Hosts) Flush() error {
h.preFlushClean()
if err := h.preFlush(); err != nil {
return err
}
file, err := os.Create(h.Path)
if err != nil {
return err
}
defer file.Close()
w := bufio.NewWriter(file)
@ -110,8 +117,11 @@ func (h *Hosts) Flush() error {
}
}
err = w.Flush()
if err != nil {
if err := w.Flush(); err != nil {
return err
}
if err := h.postFlush(); err != nil {
return err
}
@ -131,13 +141,7 @@ func (h *Hosts) AddRaw(raw ...string) error {
return fmt.Errorf("hostname is not a valid dns name: %s", host)
}
}
h.Lines = append(h.Lines, nl)
pos := len(h.Lines) - 1
h.addIpPosition(nl.IP, pos)
for _, host := range nl.Hosts {
h.addHostPositions(host, pos)
}
h.addLine(nl)
}
return nil
@ -149,40 +153,46 @@ func (h *Hosts) Add(ip string, hosts ...string) error {
return fmt.Errorf("%q is an invalid IP address", ip)
}
position := h.getIpPositions(ip)
// remove hosts from other ips if it already exists
for _, host := range hosts {
for _, p := range h.hosts.get(host) {
if h.Lines[p].IP == ip {
continue
}
if err := h.Remove(h.Lines[p].IP, host); err != nil {
return err
}
}
}
position := h.ips.get(ip)
if len(position) == 0 {
nl := HostsLine{
Raw: buildRawLine(ip, hosts),
h.addLine(HostsLine{
Raw: fmt.Sprintf("%s %s", ip, strings.Join(hosts, " ")),
IP: ip,
Hosts: hosts,
}
h.Lines = append(h.Lines, nl)
pos := len(h.Lines) - 1
h.addIpPosition(ip, pos)
for _, host := range nl.Hosts {
h.addHostPositions(host, pos)
}
})
} else {
// add new host to the first one we find
hostsCopy := h.Lines[position[0]].Hosts
loc := position[len(position)-1] // last element
hostsCopy := make([]string, len(h.Lines[loc].Hosts))
copy(hostsCopy, h.Lines[loc].Hosts)
for _, addHost := range hosts {
if h.Has(ip, addHost) {
// this combo already exists
continue
continue // this combo already exists
}
if !govalidator.IsDNSName(addHost) {
return fmt.Errorf("hostname is not a valid dns name: %s", addHost)
}
if itemInSliceString(addHost, hostsCopy) {
continue // host exists for ip already
}
hostsCopy = append(hostsCopy, addHost)
h.addHostPositions(addHost, position[0])
h.hosts.add(addHost, loc)
}
h.Lines[position[0]].Hosts = hostsCopy
h.Lines[position[0]].Raw = h.Lines[position[0]].ToRaw() // reset raw
h.Lines[loc].Hosts = hostsCopy
h.Lines[loc].RegenRaw()
}
return nil
@ -190,21 +200,23 @@ func (h *Hosts) Add(ip string, hosts ...string) error {
func (h *Hosts) Clear() {
h.Lines = []HostsLine{}
h.ips.reset()
h.hosts.reset()
}
// Clean merge duplicate ips and hosts per ip
func (h *Hosts) Clean() {
h.RemoveDuplicateIps()
h.CombineDuplicateIPs()
h.RemoveDuplicateHosts()
h.SortHosts()
h.SortByIp()
h.SortIPs()
h.HostsPerLine(HostsPerLine)
}
// Has return a bool if ip/host combo in hosts file.
// Has return a bool if ip/host combo exists in the Lines
func (h *Hosts) Has(ip string, host string) bool {
ippos := h.getIpPositions(ip)
hostpos := h.getHostPositions(host)
ippos := h.ips.get(ip)
hostpos := h.hosts.get(host)
for _, pos := range ippos {
if itemInSliceInt(pos, hostpos) {
// if ip and host have matching lookup positions we have a combo match
@ -217,24 +229,38 @@ func (h *Hosts) Has(ip string, host string) bool {
// HasHostname return a bool if hostname in hosts file.
func (h *Hosts) HasHostname(host string) bool {
return len(h.getHostPositions(host)) > 0
return len(h.hosts.get(host)) > 0
}
// Deprecated: HasIp will be replaced by HasIP
func (h *Hosts) HasIp(ip string) bool {
return len(h.getIpPositions(ip)) > 0
return h.HasIP(ip)
}
// Remove an entry from the hosts file.
// HasIP will check if the ip exists
func (h *Hosts) HasIP(ip string) bool {
return len(h.ips.get(ip)) > 0
}
// Remove takes an ip and an optional host(s), if only an ip is passed the whole line is removed
// when the optional hosts param is passed it will remove only those specific hosts from that ip
func (h *Hosts) Remove(ip string, hosts ...string) error {
var outputLines []HostsLine
if net.ParseIP(ip) == nil {
return fmt.Errorf("%q is an invalid IP address", ip)
}
for _, line := range h.Lines {
// Bad lines or comments just get readded.
if line.Err != nil || line.IsComment() || line.IP != ip {
outputLines = append(outputLines, line)
if len(hosts) == 0 {
return nil // no point in trying
}
lines := make([]HostsLine, len(h.Lines))
copy(lines, h.Lines)
h.Clear()
for _, line := range lines {
// add back all lines which were not the passed ip
if line.IP != ip {
h.addLine(line)
continue
}
@ -246,206 +272,258 @@ func (h *Hosts) Remove(ip string, hosts ...string) error {
}
// If hosts is empty, skip the line completely.
if len(newHosts) > 0 {
newLineRaw := line.IP
for _, host := range newHosts {
newLineRaw = fmt.Sprintf("%s %s", newLineRaw, host)
}
newLine := NewHostsLine(newLineRaw)
outputLines = append(outputLines, newLine)
if len(newHosts) == 0 {
continue
}
// ip still has hosts, add it back
line.Hosts = newHosts
line.RegenRaw()
h.addLine(line)
}
h.Lines = outputLines
return nil
}
// RemoveByHostname remove entries by hostname from the hosts file.
// RemoveByHostname go through all lines and remove a hostname if it exists
func (h *Hosts) RemoveByHostname(host string) error {
for _, p := range h.getHostPositions(host) {
line := &h.Lines[p]
if len(line.Hosts) > 0 {
line.Hosts = removeFromSliceString(host, line.Hosts)
line.RegenRaw()
restart := true
for restart {
restart = false
for _, p := range h.hosts.get(host) {
line := &h.Lines[p]
if len(line.Hosts) > 0 {
line.Hosts = removeFromSliceString(host, line.Hosts)
line.RegenRaw()
}
h.hosts.remove(host, p)
// cleanup the whole line if there remains an IP address
// without hostname/alias
if len(line.Hosts) == 0 {
h.removeByPosition(p)
// when an entry in the lines array is removed
// the range from hosts.get() above is
// outdated. Therefore, the whole procedure needs
// to restart over again
restart = true
break
}
}
h.removeHostPositions(host, p)
}
h.reindex()
return nil
}
func (h *Hosts) RemoveByIp(ip string) error {
pos := h.getIpPositions(ip)
for len(pos) > 0 {
for _, p := range pos {
h.removeByPosition(p)
}
func (h *Hosts) RemoveByIP(ip string) {
pos := h.ips.get(ip)
for _, p := range pos {
h.removeByPosition(p)
}
}
// Deprecated: RemoveByIp this got refactored and wont return an error any more
// leaving it for stable api purposes, will be removed in a major release
func (h *Hosts) RemoveByIp(ip string) error {
h.RemoveByIP(ip)
return nil
}
// Deprecated: RemoveDuplicateIps deprecated will be deprecated, use Combine
func (h *Hosts) RemoveDuplicateIps() {
h.CombineDuplicateIPs()
}
// CombineDuplicateIPs finds all duplicate ips and combines all their hosts into one line
func (h *Hosts) CombineDuplicateIPs() {
ipCount := make(map[string]int)
for _, line := range h.Lines {
if line.IP == "" {
continue // ignore comments
}
ipCount[line.IP]++
}
for ip, count := range ipCount {
if count > 1 {
h.combineIp(ip)
// todo: combine will rebuild lines and indexes, maybe rewrite to do the rebuild and call reindex?
h.combineIP(ip)
}
}
}
func (h *Hosts) combineIP(ip string) {
newLine := HostsLine{
IP: ip,
}
lines := make([]HostsLine, len(h.Lines))
copy(lines, h.Lines)
// clear the lines and position indexes to start over
h.Clear()
for _, line := range lines {
if line.IP == ip {
// if you find the ip combine it into newline
newLine.combine(line)
continue
}
// add everyone else
h.addLine(line)
}
// sort the hosts and add it to the end of Lines
newLine.SortHosts()
h.addLine(newLine)
}
// RemoveDuplicateHosts will check each line and remove hosts if they are the same
func (h *Hosts) RemoveDuplicateHosts() {
for pos, line := range h.Lines {
line.RemoveDuplicateHosts()
h.Lines[pos] = line
for pos := range h.Lines {
if h.Lines[pos].IsComment() {
continue // skip comments
}
h.Lines[pos].RemoveDuplicateHosts()
for _, host := range h.Lines[pos].Hosts {
h.hosts.remove(host, pos)
}
}
}
// SortHosts will go through each line and sort the hosts in alpha order
func (h *Hosts) SortHosts() {
for pos, line := range h.Lines {
line.SortHosts()
h.Lines[pos] = line
for pos := range h.Lines {
h.Lines[pos].SortHosts()
}
}
// SortByIp convert to net.IP and byte.Compare
// Deprecated: SortByIp switch to SortByIP
func (h *Hosts) SortByIp() {
sortedIps := make([]net.IP, 0, len(h.Lines))
h.SortIPs()
}
// SortByIP convert to net.IP and byte.Compare, maintains all comment only lines at the top
func (h *Hosts) SortIPs() {
// create a new list of unique ips, if dupe ips they will still get grouped together
uniqueIPs := make([]net.IP, 0, len(h.Lines))
unique := make(map[string]struct{})
for _, l := range h.Lines {
sortedIps = append(sortedIps, net.ParseIP(l.IP))
if _, ok := unique[l.IP]; !ok {
unique[l.IP] = struct{}{}
uniqueIPs = append(uniqueIPs, net.ParseIP(l.IP))
}
}
sort.Slice(sortedIps, func(i, j int) bool {
return bytes.Compare(sortedIps[i], sortedIps[j]) < 0
// sort the new unique list
sort.Slice(uniqueIPs, func(i, j int) bool {
return bytes.Compare(uniqueIPs[i], uniqueIPs[j]) < 0
})
var sortedLines []HostsLine
for _, ip := range sortedIps {
for _, l := range h.Lines {
// create a copy of the lines and Clear
lines := make([]HostsLine, len(h.Lines))
copy(lines, h.Lines)
// clear the lines and position indexes to start over
h.Clear()
// put all the comments back at the top
for _, l := range lines {
if l.IP == "" {
h.addLine(l)
}
}
// loop over the sorted ips and find their line and add it
for _, ip := range uniqueIPs {
for _, l := range lines {
if ip.String() == l.IP {
sortedLines = append(sortedLines, l)
h.addLine(l) // no continue to group duplicate ips
}
}
}
h.Lines = sortedLines
}
// HostsPerLine checks all ips and if their host count is greater than count will split into multiple lines with max of count hosts per line
func (h *Hosts) HostsPerLine(count int) {
// restacks everything into 1 ip again so we can do the split, do this even if count is -1 so it can reset the slice
h.RemoveDuplicateIps()
if count <= 0 {
return
}
var newLines []HostsLine
for _, line := range h.Lines {
// make a local copy
lines := make([]HostsLine, len(h.Lines))
copy(lines, h.Lines)
// clear the lines and position indexes to start over
h.Clear()
for ln, line := range lines {
if len(line.Hosts) <= count {
newLines = append(newLines, line)
for _, host := range line.Hosts {
h.hosts.add(host, ln)
}
h.ips.add(line.IP, ln)
h.Lines = append(h.Lines, line)
continue
}
for i := 0; i < len(line.Hosts); i += count {
// i: index of the host, j: offset for line number
for i, j := 0, 0; i < len(line.Hosts); i, j = i+count, j+1 {
lineCopy := line
end := len(line.Hosts)
if end > i+count {
end = i + count
}
for _, host := range line.Hosts {
h.hosts.add(host, ln+j)
}
h.ips.add(line.IP, ln+j)
lineCopy.Hosts = line.Hosts[i:end]
lineCopy.Raw = lineCopy.ToRaw()
newLines = append(newLines, lineCopy)
lineCopy.RegenRaw()
h.Lines = append(h.Lines, lineCopy)
}
}
h.Lines = newLines
}
func (h *Hosts) combineIp(ip string) {
newLine := HostsLine{
IP: ip,
// addLine ill append a new HostsLine and add it to the indexes
func (h *Hosts) addLine(line HostsLine) {
h.Lines = append(h.Lines, line)
if line.IsComment() {
return // don't index comments
}
linesCopy := make([]HostsLine, len(h.Lines))
copy(linesCopy, h.Lines)
for _, line := range linesCopy {
if line.IP == ip {
newLine.Combine(line)
}
pos := len(h.Lines) - 1
h.ips.add(line.IP, pos)
for _, host := range line.Hosts {
h.hosts.add(host, pos)
}
newLine.SortHosts()
h.removeIp(ip)
h.Lines = append(h.Lines, newLine)
}
// removeByPosition will drop a line located at pos and reindex all lookups
func (h *Hosts) removeByPosition(pos int) {
if pos == 0 && len(h.Lines) == 1 {
h.Clear()
return
}
if pos == len(h.Lines) {
h.Lines = h.Lines[:pos-1]
return
}
h.Lines = append(h.Lines[:pos], h.Lines[pos+1:]...)
h.reindex()
}
func (h *Hosts) removeIp(ip string) {
var newLines []HostsLine
for _, line := range h.Lines {
if line.IP != ip {
newLines = append(newLines, line)
}
}
h.Lines = newLines
}
func (h *Hosts) getHostPositions(host string) []int {
h.hosts.RLock()
defer h.hosts.RUnlock()
i, ok := h.hosts.l[host]
if ok {
return i
}
return []int{}
}
func (h *Hosts) addHostPositions(host string, pos int) {
h.hosts.Lock()
defer h.hosts.Unlock()
h.hosts.l[host] = append(h.hosts.l[host], pos)
}
func (h *Hosts) removeHostPositions(host string, pos int) {
// reindex will reset the internal position arrays for host/ips and rerun the add commands and should be run everytime
// a HostLine is removed. During the add process it's faster to just call the adds instead of reindex as it's more expensive.
func (h *Hosts) reindex() {
h.hosts.Lock()
defer h.hosts.Unlock()
positions := h.hosts.l[host]
h.hosts.l[host] = removeFromSliceInt(pos, positions)
}
func (h *Hosts) getIpPositions(ip string) []int {
h.ips.RLock()
defer h.ips.RUnlock()
i, ok := h.ips.l[ip]
if ok {
return i
}
h.hosts.l = make(map[string][]int)
h.hosts.Unlock()
return []int{}
}
func (h *Hosts) addIpPosition(ip string, pos int) {
h.ips.Lock()
defer h.ips.Unlock()
h.ips.l[ip] = append(h.ips.l[ip], pos)
}
h.ips.l = make(map[string][]int)
h.ips.Unlock()
func buildRawLine(ip string, hosts []string) string {
output := ip
for _, host := range hosts {
output = fmt.Sprintf("%s %s", output, host)
for pos, line := range h.Lines {
h.ips.add(line.IP, pos)
for _, host := range line.Hosts {
h.hosts.add(host, pos)
}
}
return output
}

@ -7,22 +7,21 @@ import (
"strings"
)
// HostsLine represents a line of the hosts file after being parsed into their respective parts
type HostsLine struct {
IP string
Hosts []string
Raw string
Err error
Comment string
IP string // IP found at the beginning of the line
Hosts []string // Hosts split into a slice on the space char
Comment string // Contents of everything after the comment char in the line
Raw string // Raw contents of the line as parsed in or updated after changes
Err error // Used for error checking during parsing
}
const commentChar string = "#"
// NewHostsLine return a new instance of ```HostsLine```.
// NewHostsLine takes a raw line as a string and parses it into a new instance of HostsLine e.g. "192.168.1.1 host1 host2 # comments"
func NewHostsLine(raw string) HostsLine {
output := HostsLine{Raw: raw}
if output.IsComment() { //whole line is comment
return output
}
if output.HasComment() { //trailing comment
commentSplit := strings.Split(output.Raw, commentChar)
@ -30,6 +29,10 @@ func NewHostsLine(raw string) HostsLine {
output.Comment = commentSplit[1]
}
if output.IsComment() { //whole line is comment
return output
}
fields := strings.Fields(raw)
if len(fields) == 0 {
return output
@ -46,6 +49,12 @@ func NewHostsLine(raw string) HostsLine {
return output
}
// String to make HostsLine a fmt.Stringer
func (l *HostsLine) String() string {
return l.ToRaw()
}
// ToRaw returns the HostsLine's contents as a raw string
func (l *HostsLine) ToRaw() string {
var comment string
if l.IsComment() { //Whole line is comment
@ -59,32 +68,41 @@ func (l *HostsLine) ToRaw() string {
return fmt.Sprintf("%s %s%s", l.IP, strings.Join(l.Hosts, " "), comment)
}
// RemoveDuplicateHosts checks all hosts in a line and removes duplicates
func (l *HostsLine) RemoveDuplicateHosts() {
unique := make(map[string]struct{})
for _, h := range l.Hosts {
unique[h] = struct{}{}
}
hosts := make([]string, len(l.Hosts))
copy(hosts, l.Hosts)
l.Hosts = []string{}
for k := range unique {
l.Hosts = append(l.Hosts, k)
for _, host := range hosts {
if _, ok := unique[host]; !ok {
unique[host] = struct{}{}
l.Hosts = append(l.Hosts, host)
}
}
l.Raw = l.ToRaw()
l.RegenRaw()
}
// Deprecated: will be made internal, combines the hosts and comments of two lines together,
func (l *HostsLine) Combine(hostline HostsLine) {
l.combine(hostline)
}
func (l *HostsLine) combine(hostline HostsLine) {
l.Hosts = append(l.Hosts, hostline.Hosts...)
if l.Comment == "" {
l.Comment = hostline.Comment
} else {
l.Comment = fmt.Sprintf("%s %s", l.Comment, hostline.Comment)
}
l.Raw = l.ToRaw()
l.RegenRaw()
}
func (l *HostsLine) SortHosts() {
sort.Strings(l.Hosts)
l.Raw = l.ToRaw()
l.RegenRaw()
}
func (l *HostsLine) IsComment() bool {
@ -104,5 +122,5 @@ func (l *HostsLine) IsMalformed() bool {
}
func (l *HostsLine) RegenRaw() {
l.Raw = fmt.Sprintf("%s %s", l.IP, strings.Join(l.Hosts, " "))
l.Raw = l.ToRaw()
}

@ -0,0 +1,42 @@
package hostsfile
import "sync"
func newLookup() lookup {
return lookup{l: make(map[string][]int)}
}
// lookup a rw mutex with a hashmap to keep track of keys (ips/hosts) and their position in the hostsfile
type lookup struct {
sync.RWMutex
l map[string][]int
}
func (lo *lookup) add(key string, pos int) {
lo.Lock()
defer lo.Unlock()
lo.l[key] = append(lo.l[key], pos)
}
func (lo *lookup) remove(key string, pos int) {
lo.Lock()
defer lo.Unlock()
// remove one entry from the lookup because we add one at a time
lo.l[key] = removeOneFromSliceInt(pos, lo.l[key])
}
func (lo *lookup) get(key string) []int {
lo.RLock()
defer lo.RUnlock()
if i, ok := lo.l[key]; ok {
return i
}
return []int{}
}
func (lo *lookup) reset() {
lo.Lock()
defer lo.Unlock()
lo.l = make(map[string][]int)
}

@ -0,0 +1,27 @@
package install
import (
"fmt"
"os/exec"
"github.com/magefile/mage/mg"
)
const (
GolangCILintVersion = "v1.54.2"
)
// Dependencies install all dependencies
func Dependencies() error {
fmt.Println("Installing Dependencies...")
mg.Deps(Golangcilint)
return nil
}
// Golangcilint install golangci-lint
func Golangcilint() error {
fmt.Println("Installing GolangCI Lint...")
cmd := exec.Command("go", "install", "github.com/golangci/golangci-lint/cmd/golangci-lint@"+GolangCILintVersion)
return cmd.Run()
}

@ -0,0 +1,41 @@
package test
import (
"fmt"
"github.com/magefile/mage/sh"
)
// Unit run all unit tests
func Unit() error {
fmt.Println("Running Tests...")
return sh.RunV("go", "test")
}
// Build run a test build to confirm no compilation errors
func Build() error {
fmt.Println("Running Build...")
return sh.RunV("go", "build", "-tags", "test")
}
// Coverage run all unit tests and output coverage
func Coverage() error {
fmt.Println("Running Tests with Coverage...")
return sh.RunV("go", "test", "-v", "-coverprofile=coverage.txt", ".")
}
// HTML display the html coverage report from the cover tool
func HTML() error {
if err := Coverage(); err != nil {
return err
}
return sh.RunV("go", "tool", "cover", "-html", "coverage.txt")
}
// Func display the func coverage report from the cover tool
func Func() error {
if err := Coverage(); err != nil {
return err
}
return sh.RunV("go", "tool", "cover", "-func", "coverage.txt")
}

@ -0,0 +1,35 @@
//go:build mage
// +build mage
package main
import (
"fmt"
"github.com/magefile/mage/mg"
"github.com/magefile/mage/sh"
//mage:import install
"github.com/goodhosts/hostsfile/mage/install"
//mage:import test
"github.com/goodhosts/hostsfile/mage/test"
)
// run everything for ci process (install deps, lint, coverage, build)
func Ci() error {
fmt.Println("Running Continuous Integration...")
mg.Deps(
install.Dependencies,
Lint,
test.Coverage,
test.Build)
return nil
}
// run the linter
func Lint() error {
mg.Deps(install.Golangcilint)
fmt.Println("Running Linter...")
return sh.RunV("golangci-lint", "run")
}

@ -1,27 +0,0 @@
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set LF=^
echo %1%
if "%1%"=="" (
set cmd=ci
) else (
set cmd=%1%
)
if "%cmd%" == "ci" (
for /F %%i in ('goimports -l .') do (
set "line=%%i"
set goimports=%goimports%!line!!LF!
)
if not "!goimports!" == "" (
goimports -d .
goto :eof
)
golangci-lint run || goto :eof
go test -v . || goto :eof
goto :eof
)

@ -1,5 +1,5 @@
//go:build !windows
//+build !windows
// +build !windows
package hostsfile
@ -9,4 +9,5 @@ var (
eol = "\n"
)
func (h *Hosts) preFlushClean() {} // no op
func (h *Hosts) preFlush() error { return nil }
func (h *Hosts) postFlush() error { return nil }

@ -6,7 +6,10 @@ var (
eol = "\r\n"
)
func (h *Hosts) preFlushClean() {
func (h *Hosts) preFlush() error {
// need to force hosts per line always on windows see https://github.com/goodhosts/hostsfile/issues/18
h.HostsPerLine(HostsPerLine)
return nil
}
func (h *Hosts) postFlush() error { return nil }

@ -45,6 +45,14 @@ func removeFromSliceInt(s int, slice []int) []int {
return slice
}
func removeOneFromSliceInt(s int, slice []int) []int {
pos := findPositionInSliceInt(s, slice)
if pos > -1 {
slice = append(slice[:pos], slice[pos+1:]...)
}
return slice
}
func findPositionInSliceInt(s int, slice []int) int {
for index, v := range slice {
if v == s {

@ -53,7 +53,7 @@ type defaultKeychain struct {
var (
// DefaultKeychain implements Keychain by interpreting the docker config file.
DefaultKeychain = RefreshingKeychain(&defaultKeychain{}, 5*time.Minute)
DefaultKeychain = &defaultKeychain{}
)
const (

@ -0,0 +1,137 @@
// Copyright 2018 Google LLC All Rights Reserved.
//
// 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.
// This is an EXPERIMENTAL package, and may change in arbitrary ways without notice.
package layout
import (
"fmt"
"io/fs"
"path/filepath"
"strings"
v1 "github.com/google/go-containerregistry/pkg/v1"
)
// GarbageCollect removes unreferenced blobs from the oci-layout
//
// This is an experimental api, and not subject to any stability guarantees
// We may abandon it at any time, without prior notice.
// Deprecated: Use it at your own risk!
func (l Path) GarbageCollect() ([]v1.Hash, error) {
idx, err := l.ImageIndex()
if err != nil {
return nil, err
}
blobsToKeep := map[string]bool{}
if err := l.garbageCollectImageIndex(idx, blobsToKeep); err != nil {
return nil, err
}
blobsDir := l.path("blobs")
removedBlobs := []v1.Hash{}
err = filepath.WalkDir(blobsDir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
rel, err := filepath.Rel(blobsDir, path)
if err != nil {
return err
}
hashString := strings.Replace(rel, "/", ":", 1)
if present := blobsToKeep[hashString]; !present {
h, err := v1.NewHash(hashString)
if err != nil {
return err
}
removedBlobs = append(removedBlobs, h)
}
return nil
})
if err != nil {
return nil, err
}
return removedBlobs, nil
}
func (l Path) garbageCollectImageIndex(index v1.ImageIndex, blobsToKeep map[string]bool) error {
idxm, err := index.IndexManifest()
if err != nil {
return err
}
h, err := index.Digest()
if err != nil {
return err
}
blobsToKeep[h.String()] = true
for _, descriptor := range idxm.Manifests {
if descriptor.MediaType.IsImage() {
img, err := index.Image(descriptor.Digest)
if err != nil {
return err
}
if err := l.garbageCollectImage(img, blobsToKeep); err != nil {
return err
}
} else if descriptor.MediaType.IsIndex() {
idx, err := index.ImageIndex(descriptor.Digest)
if err != nil {
return err
}
if err := l.garbageCollectImageIndex(idx, blobsToKeep); err != nil {
return err
}
} else {
return fmt.Errorf("gc: unknown media type: %s", descriptor.MediaType)
}
}
return nil
}
func (l Path) garbageCollectImage(image v1.Image, blobsToKeep map[string]bool) error {
h, err := image.Digest()
if err != nil {
return err
}
blobsToKeep[h.String()] = true
h, err = image.ConfigName()
if err != nil {
return err
}
blobsToKeep[h.String()] = true
ls, err := image.Layers()
if err != nil {
return err
}
for _, l := range ls {
h, err := l.Digest()
if err != nil {
return err
}
blobsToKeep[h.String()] = true
}
return nil
}

@ -280,6 +280,11 @@ func (w *writer) streamBlob(ctx context.Context, layer v1.Layer, streamLocation
if _, ok := layer.(*stream.Layer); !ok {
// We can't retry streaming layers.
req.GetBody = getBody
// If we know the size, set it.
if size, err := layer.Size(); err == nil {
req.ContentLength = size
}
}
req.Header.Set("Content-Type", "application/octet-stream")

@ -299,18 +299,29 @@ func (i *uncompressedImage) LayerByDiffID(h v1.Hash) (partial.UncompressedLayer,
// v1.Layer doesn't force consumers to care about whether the layer is compressed
// we should be fine returning the DockerLayer media type
mt := types.DockerLayer
if bd, ok := i.imgDescriptor.LayerSources[h]; ok {
// Overwrite the mediaType for foreign layers.
return &foreignUncompressedLayer{
uncompressedLayerFromTarball: uncompressedLayerFromTarball{
diffID: diffID,
mediaType: bd.MediaType,
opener: i.opener,
filePath: i.imgDescriptor.Layers[idx],
},
desc: bd,
}, nil
bd, ok := i.imgDescriptor.LayerSources[h]
if ok {
// This is janky, but we don't want to implement Descriptor for
// uncompressed layers because it breaks a bunch of assumptions in partial.
// See https://github.com/google/go-containerregistry/issues/1870
docker25workaround := bd.MediaType == types.DockerUncompressedLayer || bd.MediaType == types.OCIUncompressedLayer
if !docker25workaround {
// Overwrite the mediaType for foreign layers.
return &foreignUncompressedLayer{
uncompressedLayerFromTarball: uncompressedLayerFromTarball{
diffID: diffID,
mediaType: bd.MediaType,
opener: i.opener,
filePath: i.imgDescriptor.Layers[idx],
},
desc: bd,
}, nil
}
// Intentional fall through.
}
return &uncompressedLayerFromTarball{
diffID: diffID,
mediaType: mt,

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://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
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 the Mage 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.

@ -0,0 +1,80 @@
package mg
// Color is ANSI color type
type Color int
// If you add/change/remove any items in this constant,
// you will need to run "stringer -type=Color" in this directory again.
// NOTE: Please keep the list in an alphabetical order.
const (
Black Color = iota
Red
Green
Yellow
Blue
Magenta
Cyan
White
BrightBlack
BrightRed
BrightGreen
BrightYellow
BrightBlue
BrightMagenta
BrightCyan
BrightWhite
)
// AnsiColor are ANSI color codes for supported terminal colors.
var ansiColor = map[Color]string{
Black: "\u001b[30m",
Red: "\u001b[31m",
Green: "\u001b[32m",
Yellow: "\u001b[33m",
Blue: "\u001b[34m",
Magenta: "\u001b[35m",
Cyan: "\u001b[36m",
White: "\u001b[37m",
BrightBlack: "\u001b[30;1m",
BrightRed: "\u001b[31;1m",
BrightGreen: "\u001b[32;1m",
BrightYellow: "\u001b[33;1m",
BrightBlue: "\u001b[34;1m",
BrightMagenta: "\u001b[35;1m",
BrightCyan: "\u001b[36;1m",
BrightWhite: "\u001b[37;1m",
}
// AnsiColorReset is an ANSI color code to reset the terminal color.
const AnsiColorReset = "\033[0m"
// DefaultTargetAnsiColor is a default ANSI color for colorizing targets.
// It is set to Cyan as an arbitrary color, because it has a neutral meaning
var DefaultTargetAnsiColor = ansiColor[Cyan]
func toLowerCase(s string) string {
// this is a naive implementation
// borrowed from https://golang.org/src/strings/strings.go
// and only considers alphabetical characters [a-zA-Z]
// so that we don't depend on the "strings" package
buf := make([]byte, len(s))
for i := 0; i < len(s); i++ {
c := s[i]
if 'A' <= c && c <= 'Z' {
c += 'a' - 'A'
}
buf[i] = c
}
return string(buf)
}
func getAnsiColor(color string) (string, bool) {
colorLower := toLowerCase(color)
for k, v := range ansiColor {
colorConstLower := toLowerCase(k.String())
if colorConstLower == colorLower {
return v, true
}
}
return "", false
}

@ -0,0 +1,38 @@
// Code generated by "stringer -type=Color"; DO NOT EDIT.
package mg
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[Black-0]
_ = x[Red-1]
_ = x[Green-2]
_ = x[Yellow-3]
_ = x[Blue-4]
_ = x[Magenta-5]
_ = x[Cyan-6]
_ = x[White-7]
_ = x[BrightBlack-8]
_ = x[BrightRed-9]
_ = x[BrightGreen-10]
_ = x[BrightYellow-11]
_ = x[BrightBlue-12]
_ = x[BrightMagenta-13]
_ = x[BrightCyan-14]
_ = x[BrightWhite-15]
}
const _Color_name = "BlackRedGreenYellowBlueMagentaCyanWhiteBrightBlackBrightRedBrightGreenBrightYellowBrightBlueBrightMagentaBrightCyanBrightWhite"
var _Color_index = [...]uint8{0, 5, 8, 13, 19, 23, 30, 34, 39, 50, 59, 70, 82, 92, 105, 115, 126}
func (i Color) String() string {
if i < 0 || i >= Color(len(_Color_index)-1) {
return "Color(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Color_name[_Color_index[i]:_Color_index[i+1]]
}

@ -0,0 +1,211 @@
package mg
import (
"context"
"fmt"
"log"
"os"
"reflect"
"runtime"
"strings"
"sync"
)
var logger = log.New(os.Stderr, "", 0)
type onceMap struct {
mu *sync.Mutex
m map[onceKey]*onceFun
}
type onceKey struct {
Name string
ID string
}
func (o *onceMap) LoadOrStore(f Fn) *onceFun {
defer o.mu.Unlock()
o.mu.Lock()
key := onceKey{
Name: f.Name(),
ID: f.ID(),
}
existing, ok := o.m[key]
if ok {
return existing
}
one := &onceFun{
once: &sync.Once{},
fn: f,
displayName: displayName(f.Name()),
}
o.m[key] = one
return one
}
var onces = &onceMap{
mu: &sync.Mutex{},
m: map[onceKey]*onceFun{},
}
// SerialDeps is like Deps except it runs each dependency serially, instead of
// in parallel. This can be useful for resource intensive dependencies that
// shouldn't be run at the same time.
func SerialDeps(fns ...interface{}) {
funcs := checkFns(fns)
ctx := context.Background()
for i := range fns {
runDeps(ctx, funcs[i:i+1])
}
}
// SerialCtxDeps is like CtxDeps except it runs each dependency serially,
// instead of in parallel. This can be useful for resource intensive
// dependencies that shouldn't be run at the same time.
func SerialCtxDeps(ctx context.Context, fns ...interface{}) {
funcs := checkFns(fns)
for i := range fns {
runDeps(ctx, funcs[i:i+1])
}
}
// CtxDeps runs the given functions as dependencies of the calling function.
// Dependencies must only be of type:
// func()
// func() error
// func(context.Context)
// func(context.Context) error
// Or a similar method on a mg.Namespace type.
// Or an mg.Fn interface.
//
// The function calling Deps is guaranteed that all dependent functions will be
// run exactly once when Deps returns. Dependent functions may in turn declare
// their own dependencies using Deps. Each dependency is run in their own
// goroutines. Each function is given the context provided if the function
// prototype allows for it.
func CtxDeps(ctx context.Context, fns ...interface{}) {
funcs := checkFns(fns)
runDeps(ctx, funcs)
}
// runDeps assumes you've already called checkFns.
func runDeps(ctx context.Context, fns []Fn) {
mu := &sync.Mutex{}
var errs []string
var exit int
wg := &sync.WaitGroup{}
for _, f := range fns {
fn := onces.LoadOrStore(f)
wg.Add(1)
go func() {
defer func() {
if v := recover(); v != nil {
mu.Lock()
if err, ok := v.(error); ok {
exit = changeExit(exit, ExitStatus(err))
} else {
exit = changeExit(exit, 1)
}
errs = append(errs, fmt.Sprint(v))
mu.Unlock()
}
wg.Done()
}()
if err := fn.run(ctx); err != nil {
mu.Lock()
errs = append(errs, fmt.Sprint(err))
exit = changeExit(exit, ExitStatus(err))
mu.Unlock()
}
}()
}
wg.Wait()
if len(errs) > 0 {
panic(Fatal(exit, strings.Join(errs, "\n")))
}
}
func checkFns(fns []interface{}) []Fn {
funcs := make([]Fn, len(fns))
for i, f := range fns {
if fn, ok := f.(Fn); ok {
funcs[i] = fn
continue
}
// Check if the target provided is a not function so we can give a clear warning
t := reflect.TypeOf(f)
if t == nil || t.Kind() != reflect.Func {
panic(fmt.Errorf("non-function used as a target dependency: %T. The mg.Deps, mg.SerialDeps and mg.CtxDeps functions accept function names, such as mg.Deps(TargetA, TargetB)", f))
}
funcs[i] = F(f)
}
return funcs
}
// Deps runs the given functions in parallel, exactly once. Dependencies must
// only be of type:
// func()
// func() error
// func(context.Context)
// func(context.Context) error
// Or a similar method on a mg.Namespace type.
// Or an mg.Fn interface.
//
// This is a way to build up a tree of dependencies with each dependency
// defining its own dependencies. Functions must have the same signature as a
// Mage target, i.e. optional context argument, optional error return.
func Deps(fns ...interface{}) {
CtxDeps(context.Background(), fns...)
}
func changeExit(old, new int) int {
if new == 0 {
return old
}
if old == 0 {
return new
}
if old == new {
return old
}
// both different and both non-zero, just set
// exit to 1. Nothing more we can do.
return 1
}
// funcName returns the unique name for the function
func funcName(i interface{}) string {
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}
func displayName(name string) string {
splitByPackage := strings.Split(name, ".")
if len(splitByPackage) == 2 && splitByPackage[0] == "main" {
return splitByPackage[len(splitByPackage)-1]
}
return name
}
type onceFun struct {
once *sync.Once
fn Fn
err error
displayName string
}
// run will run the function exactly once and capture the error output. Further runs simply return
// the same error output.
func (o *onceFun) run(ctx context.Context) error {
o.once.Do(func() {
if Verbose() {
logger.Println("Running dependency:", displayName(o.fn.Name()))
}
o.err = o.fn.Run(ctx)
})
return o.err
}

@ -0,0 +1,51 @@
package mg
import (
"errors"
"fmt"
)
type fatalErr struct {
code int
error
}
func (f fatalErr) ExitStatus() int {
return f.code
}
type exitStatus interface {
ExitStatus() int
}
// Fatal returns an error that will cause mage to print out the
// given args and exit with the given exit code.
func Fatal(code int, args ...interface{}) error {
return fatalErr{
code: code,
error: errors.New(fmt.Sprint(args...)),
}
}
// Fatalf returns an error that will cause mage to print out the
// given message and exit with the given exit code.
func Fatalf(code int, format string, args ...interface{}) error {
return fatalErr{
code: code,
error: fmt.Errorf(format, args...),
}
}
// ExitStatus queries the error for an exit status. If the error is nil, it
// returns 0. If the error does not implement ExitStatus() int, it returns 1.
// Otherwise it retiurns the value from ExitStatus().
func ExitStatus(err error) int {
if err == nil {
return 0
}
exit, ok := err.(exitStatus)
if !ok {
return 1
}
return exit.ExitStatus()
}

@ -0,0 +1,192 @@
package mg
import (
"context"
"encoding/json"
"fmt"
"reflect"
"time"
)
// Fn represents a function that can be run with mg.Deps. Package, Name, and ID must combine to
// uniquely identify a function, while ensuring the "same" function has identical values. These are
// used as a map key to find and run (or not run) the function.
type Fn interface {
// Name should return the fully qualified name of the function. Usually
// it's best to use runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name().
Name() string
// ID should be an additional uniqueness qualifier in case the name is insufficiently unique.
// This can be the case for functions that take arguments (mg.F json-encodes an array of the
// args).
ID() string
// Run should run the function.
Run(ctx context.Context) error
}
// F takes a function that is compatible as a mage target, and any args that need to be passed to
// it, and wraps it in an mg.Fn that mg.Deps can run. Args must be passed in the same order as they
// are declared by the function. Note that you do not need to and should not pass a context.Context
// to F, even if the target takes a context. Compatible args are int, bool, string, and
// time.Duration.
func F(target interface{}, args ...interface{}) Fn {
hasContext, isNamespace, err := checkF(target, args)
if err != nil {
panic(err)
}
id, err := json.Marshal(args)
if err != nil {
panic(fmt.Errorf("can't convert args into a mage-compatible id for mg.Deps: %s", err))
}
return fn{
name: funcName(target),
id: string(id),
f: func(ctx context.Context) error {
v := reflect.ValueOf(target)
count := len(args)
if hasContext {
count++
}
if isNamespace {
count++
}
vargs := make([]reflect.Value, count)
x := 0
if isNamespace {
vargs[0] = reflect.ValueOf(struct{}{})
x++
}
if hasContext {
vargs[x] = reflect.ValueOf(ctx)
x++
}
for y := range args {
vargs[x+y] = reflect.ValueOf(args[y])
}
ret := v.Call(vargs)
if len(ret) > 0 {
// we only allow functions with a single error return, so this should be safe.
if ret[0].IsNil() {
return nil
}
return ret[0].Interface().(error)
}
return nil
},
}
}
type fn struct {
name string
id string
f func(ctx context.Context) error
}
// Name returns the fully qualified name of the function.
func (f fn) Name() string {
return f.name
}
// ID returns a hash of the argument values passed in
func (f fn) ID() string {
return f.id
}
// Run runs the function.
func (f fn) Run(ctx context.Context) error {
return f.f(ctx)
}
func checkF(target interface{}, args []interface{}) (hasContext, isNamespace bool, _ error) {
t := reflect.TypeOf(target)
if t == nil || t.Kind() != reflect.Func {
return false, false, fmt.Errorf("non-function passed to mg.F: %T. The mg.F function accepts function names, such as mg.F(TargetA, \"arg1\", \"arg2\")", target)
}
if t.NumOut() > 1 {
return false, false, fmt.Errorf("target has too many return values, must be zero or just an error: %T", target)
}
if t.NumOut() == 1 && t.Out(0) != errType {
return false, false, fmt.Errorf("target's return value is not an error")
}
// more inputs than slots is an error if not variadic
if len(args) > t.NumIn() && !t.IsVariadic() {
return false, false, fmt.Errorf("too many arguments for target, got %d for %T", len(args), target)
}
if t.NumIn() == 0 {
return false, false, nil
}
x := 0
inputs := t.NumIn()
if t.In(0).AssignableTo(emptyType) {
// nameSpace func
isNamespace = true
x++
// callers must leave off the namespace value
inputs--
}
if t.NumIn() > x && t.In(x) == ctxType {
// callers must leave off the context
inputs--
// let the upper function know it should pass us a context.
hasContext = true
// skip checking the first argument in the below loop if it's a context, since first arg is
// special.
x++
}
if t.IsVariadic() {
if len(args) < inputs-1 {
return false, false, fmt.Errorf("too few arguments for target, got %d for %T", len(args), target)
}
} else if len(args) != inputs {
return false, false, fmt.Errorf("wrong number of arguments for target, got %d for %T", len(args), target)
}
for _, arg := range args {
argT := t.In(x)
if t.IsVariadic() && x == t.NumIn()-1 {
// For the variadic argument, use the slice element type.
argT = argT.Elem()
}
if !argTypes[argT] {
return false, false, fmt.Errorf("argument %d (%s), is not a supported argument type", x, argT)
}
passedT := reflect.TypeOf(arg)
if argT != passedT {
return false, false, fmt.Errorf("argument %d expected to be %s, but is %s", x, argT, passedT)
}
if x < t.NumIn()-1 {
x++
}
}
return hasContext, isNamespace, nil
}
// Here we define the types that are supported as arguments/returns
var (
ctxType = reflect.TypeOf(func(context.Context) {}).In(0)
errType = reflect.TypeOf(func() error { return nil }).Out(0)
emptyType = reflect.TypeOf(struct{}{})
intType = reflect.TypeOf(int(0))
stringType = reflect.TypeOf(string(""))
boolType = reflect.TypeOf(bool(false))
durType = reflect.TypeOf(time.Second)
// don't put ctx in here, this is for non-context types
argTypes = map[reflect.Type]bool{
intType: true,
boolType: true,
stringType: true,
durType: true,
}
)

@ -0,0 +1,136 @@
package mg
import (
"os"
"path/filepath"
"runtime"
"strconv"
)
// CacheEnv is the environment variable that users may set to change the
// location where mage stores its compiled binaries.
const CacheEnv = "MAGEFILE_CACHE"
// VerboseEnv is the environment variable that indicates the user requested
// verbose mode when running a magefile.
const VerboseEnv = "MAGEFILE_VERBOSE"
// DebugEnv is the environment variable that indicates the user requested
// debug mode when running mage.
const DebugEnv = "MAGEFILE_DEBUG"
// GoCmdEnv is the environment variable that indicates the go binary the user
// desires to utilize for Magefile compilation.
const GoCmdEnv = "MAGEFILE_GOCMD"
// IgnoreDefaultEnv is the environment variable that indicates the user requested
// to ignore the default target specified in the magefile.
const IgnoreDefaultEnv = "MAGEFILE_IGNOREDEFAULT"
// HashFastEnv is the environment variable that indicates the user requested to
// use a quick hash of magefiles to determine whether or not the magefile binary
// needs to be rebuilt. This results in faster runtimes, but means that mage
// will fail to rebuild if a dependency has changed. To force a rebuild, run
// mage with the -f flag.
const HashFastEnv = "MAGEFILE_HASHFAST"
// EnableColorEnv is the environment variable that indicates the user is using
// a terminal which supports a color output. The default is false for backwards
// compatibility. When the value is true and the detected terminal does support colors
// then the list of mage targets will be displayed in ANSI color. When the value
// is true but the detected terminal does not support colors, then the list of
// mage targets will be displayed in the default colors (e.g. black and white).
const EnableColorEnv = "MAGEFILE_ENABLE_COLOR"
// TargetColorEnv is the environment variable that indicates which ANSI color
// should be used to colorize mage targets. This is only applicable when
// the MAGEFILE_ENABLE_COLOR environment variable is true.
// The supported ANSI color names are any of these:
// - Black
// - Red
// - Green
// - Yellow
// - Blue
// - Magenta
// - Cyan
// - White
// - BrightBlack
// - BrightRed
// - BrightGreen
// - BrightYellow
// - BrightBlue
// - BrightMagenta
// - BrightCyan
// - BrightWhite
const TargetColorEnv = "MAGEFILE_TARGET_COLOR"
// Verbose reports whether a magefile was run with the verbose flag.
func Verbose() bool {
b, _ := strconv.ParseBool(os.Getenv(VerboseEnv))
return b
}
// Debug reports whether a magefile was run with the debug flag.
func Debug() bool {
b, _ := strconv.ParseBool(os.Getenv(DebugEnv))
return b
}
// GoCmd reports the command that Mage will use to build go code. By default mage runs
// the "go" binary in the PATH.
func GoCmd() string {
if cmd := os.Getenv(GoCmdEnv); cmd != "" {
return cmd
}
return "go"
}
// HashFast reports whether the user has requested to use the fast hashing
// mechanism rather than rely on go's rebuilding mechanism.
func HashFast() bool {
b, _ := strconv.ParseBool(os.Getenv(HashFastEnv))
return b
}
// IgnoreDefault reports whether the user has requested to ignore the default target
// in the magefile.
func IgnoreDefault() bool {
b, _ := strconv.ParseBool(os.Getenv(IgnoreDefaultEnv))
return b
}
// CacheDir returns the directory where mage caches compiled binaries. It
// defaults to $HOME/.magefile, but may be overridden by the MAGEFILE_CACHE
// environment variable.
func CacheDir() string {
d := os.Getenv(CacheEnv)
if d != "" {
return d
}
switch runtime.GOOS {
case "windows":
return filepath.Join(os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH"), "magefile")
default:
return filepath.Join(os.Getenv("HOME"), ".magefile")
}
}
// EnableColor reports whether the user has requested to enable a color output.
func EnableColor() bool {
b, _ := strconv.ParseBool(os.Getenv(EnableColorEnv))
return b
}
// TargetColor returns the configured ANSI color name a color output.
func TargetColor() string {
s, exists := os.LookupEnv(TargetColorEnv)
if exists {
if c, ok := getAnsiColor(s); ok {
return c
}
}
return DefaultTargetAnsiColor
}
// Namespace allows for the grouping of similar commands
type Namespace struct{}

@ -0,0 +1,184 @@
package sh
import (
"bytes"
"fmt"
"io"
"log"
"os"
"os/exec"
"strings"
"github.com/magefile/mage/mg"
)
// RunCmd returns a function that will call Run with the given command. This is
// useful for creating command aliases to make your scripts easier to read, like
// this:
//
// // in a helper file somewhere
// var g0 = sh.RunCmd("go") // go is a keyword :(
//
// // somewhere in your main code
// if err := g0("install", "github.com/gohugo/hugo"); err != nil {
// return err
// }
//
// Args passed to command get baked in as args to the command when you run it.
// Any args passed in when you run the returned function will be appended to the
// original args. For example, this is equivalent to the above:
//
// var goInstall = sh.RunCmd("go", "install") goInstall("github.com/gohugo/hugo")
//
// RunCmd uses Exec underneath, so see those docs for more details.
func RunCmd(cmd string, args ...string) func(args ...string) error {
return func(args2 ...string) error {
return Run(cmd, append(args, args2...)...)
}
}
// OutCmd is like RunCmd except the command returns the output of the
// command.
func OutCmd(cmd string, args ...string) func(args ...string) (string, error) {
return func(args2 ...string) (string, error) {
return Output(cmd, append(args, args2...)...)
}
}
// Run is like RunWith, but doesn't specify any environment variables.
func Run(cmd string, args ...string) error {
return RunWith(nil, cmd, args...)
}
// RunV is like Run, but always sends the command's stdout to os.Stdout.
func RunV(cmd string, args ...string) error {
_, err := Exec(nil, os.Stdout, os.Stderr, cmd, args...)
return err
}
// RunWith runs the given command, directing stderr to this program's stderr and
// printing stdout to stdout if mage was run with -v. It adds adds env to the
// environment variables for the command being run. Environment variables should
// be in the format name=value.
func RunWith(env map[string]string, cmd string, args ...string) error {
var output io.Writer
if mg.Verbose() {
output = os.Stdout
}
_, err := Exec(env, output, os.Stderr, cmd, args...)
return err
}
// RunWithV is like RunWith, but always sends the command's stdout to os.Stdout.
func RunWithV(env map[string]string, cmd string, args ...string) error {
_, err := Exec(env, os.Stdout, os.Stderr, cmd, args...)
return err
}
// Output runs the command and returns the text from stdout.
func Output(cmd string, args ...string) (string, error) {
buf := &bytes.Buffer{}
_, err := Exec(nil, buf, os.Stderr, cmd, args...)
return strings.TrimSuffix(buf.String(), "\n"), err
}
// OutputWith is like RunWith, but returns what is written to stdout.
func OutputWith(env map[string]string, cmd string, args ...string) (string, error) {
buf := &bytes.Buffer{}
_, err := Exec(env, buf, os.Stderr, cmd, args...)
return strings.TrimSuffix(buf.String(), "\n"), err
}
// Exec executes the command, piping its stdout and stderr to the given
// writers. If the command fails, it will return an error that, if returned
// from a target or mg.Deps call, will cause mage to exit with the same code as
// the command failed with. Env is a list of environment variables to set when
// running the command, these override the current environment variables set
// (which are also passed to the command). cmd and args may include references
// to environment variables in $FOO format, in which case these will be
// expanded before the command is run.
//
// Ran reports if the command ran (rather than was not found or not executable).
// Code reports the exit code the command returned if it ran. If err == nil, ran
// is always true and code is always 0.
func Exec(env map[string]string, stdout, stderr io.Writer, cmd string, args ...string) (ran bool, err error) {
expand := func(s string) string {
s2, ok := env[s]
if ok {
return s2
}
return os.Getenv(s)
}
cmd = os.Expand(cmd, expand)
for i := range args {
args[i] = os.Expand(args[i], expand)
}
ran, code, err := run(env, stdout, stderr, cmd, args...)
if err == nil {
return true, nil
}
if ran {
return ran, mg.Fatalf(code, `running "%s %s" failed with exit code %d`, cmd, strings.Join(args, " "), code)
}
return ran, fmt.Errorf(`failed to run "%s %s: %v"`, cmd, strings.Join(args, " "), err)
}
func run(env map[string]string, stdout, stderr io.Writer, cmd string, args ...string) (ran bool, code int, err error) {
c := exec.Command(cmd, args...)
c.Env = os.Environ()
for k, v := range env {
c.Env = append(c.Env, k+"="+v)
}
c.Stderr = stderr
c.Stdout = stdout
c.Stdin = os.Stdin
var quoted []string
for i := range args {
quoted = append(quoted, fmt.Sprintf("%q", args[i]));
}
// To protect against logging from doing exec in global variables
if mg.Verbose() {
log.Println("exec:", cmd, strings.Join(quoted, " "))
}
err = c.Run()
return CmdRan(err), ExitStatus(err), err
}
// CmdRan examines the error to determine if it was generated as a result of a
// command running via os/exec.Command. If the error is nil, or the command ran
// (even if it exited with a non-zero exit code), CmdRan reports true. If the
// error is an unrecognized type, or it is an error from exec.Command that says
// the command failed to run (usually due to the command not existing or not
// being executable), it reports false.
func CmdRan(err error) bool {
if err == nil {
return true
}
ee, ok := err.(*exec.ExitError)
if ok {
return ee.Exited()
}
return false
}
type exitStatus interface {
ExitStatus() int
}
// ExitStatus returns the exit status of the error if it is an exec.ExitError
// or if it implements ExitStatus() int.
// 0 if it is nil or 1 if it is a different error.
func ExitStatus(err error) int {
if err == nil {
return 0
}
if e, ok := err.(exitStatus); ok {
return e.ExitStatus()
}
if e, ok := err.(*exec.ExitError); ok {
if ex, ok := e.Sys().(exitStatus); ok {
return ex.ExitStatus()
}
}
return 1
}

@ -0,0 +1,40 @@
package sh
import (
"fmt"
"io"
"os"
)
// Rm removes the given file or directory even if non-empty. It will not return
// an error if the target doesn't exist, only if the target cannot be removed.
func Rm(path string) error {
err := os.RemoveAll(path)
if err == nil || os.IsNotExist(err) {
return nil
}
return fmt.Errorf(`failed to remove %s: %v`, path, err)
}
// Copy robustly copies the source file to the destination, overwriting the destination if necessary.
func Copy(dst string, src string) error {
from, err := os.Open(src)
if err != nil {
return fmt.Errorf(`can't copy %s: %v`, src, err)
}
defer from.Close()
finfo, err := from.Stat()
if err != nil {
return fmt.Errorf(`can't stat %s: %v`, src, err)
}
to, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, finfo.Mode())
if err != nil {
return fmt.Errorf(`can't copy to %s: %v`, dst, err)
}
defer to.Close()
_, err = io.Copy(to, from)
if err != nil {
return fmt.Errorf(`error copying %s to %s: %v`, src, dst, err)
}
return nil
}

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://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
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

15
vendor/go4.org/netipx/netipx.go generated vendored

@ -51,6 +51,21 @@ func FromStdIPRaw(std net.IP) (ip netip.Addr, ok bool) {
return netip.AddrFromSlice(std)
}
// ParsePrefixOrAddr parses s as an IP address prefix or IP address. If s parses
// as an IP address prefix, its [net/netip.Prefix.Addr] is returned. The string
// s can be an IPv4 address ("192.0.2.1"), IPv6 address ("2001:db8::68"), IPv4
// prefix ("192.0.2.1/32"), or IPv6 prefix ("2001:db:68/96").
func ParsePrefixOrAddr(s string) (netip.Addr, error) {
// Factored out of netip.ParsePrefix to avoid allocating an empty netip.Prefix in case it's
// an address and not a prefix.
i := strings.LastIndexByte(s, '/')
if i < 0 {
return netip.ParseAddr(s)
}
prefix, err := netip.ParsePrefix(s)
return prefix.Addr(), err
}
// AddrNext returns the IP following ip.
// If there is none, it returns the IP zero value.
//

@ -1510,13 +1510,12 @@ func (mh *MetaHeadersFrame) checkPseudos() error {
}
func (fr *Framer) maxHeaderStringLen() int {
v := fr.maxHeaderListSize()
if uint32(int(v)) == v {
return int(v)
v := int(fr.maxHeaderListSize())
if v < 0 {
// If maxHeaderListSize overflows an int, use no limit (0).
return 0
}
// They had a crazy big number for MaxHeaderBytes anyway,
// so give them unlimited header lengths:
return 0
return v
}
// readMetaFrame returns 0 or more CONTINUATION frames from fr and

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
package unix

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris
//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris || zos
package unix

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build darwin && go1.12
//go:build darwin
package unix

@ -13,6 +13,7 @@
package unix
import (
"errors"
"sync"
"unsafe"
)
@ -169,25 +170,26 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
func Uname(uname *Utsname) error {
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
n := unsafe.Sizeof(uname.Sysname)
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil {
// Suppress ENOMEM errors to be compatible with the C library __xuname() implementation.
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
n = unsafe.Sizeof(uname.Nodename)
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil {
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
n = unsafe.Sizeof(uname.Release)
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil {
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
mib = []_C_int{CTL_KERN, KERN_VERSION}
n = unsafe.Sizeof(uname.Version)
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil {
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
@ -205,7 +207,7 @@ func Uname(uname *Utsname) error {
mib = []_C_int{CTL_HW, HW_MACHINE}
n = unsafe.Sizeof(uname.Machine)
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil {
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}

@ -1849,6 +1849,105 @@ func Dup2(oldfd, newfd int) error {
//sys Fsmount(fd int, flags int, mountAttrs int) (fsfd int, err error)
//sys Fsopen(fsName string, flags int) (fd int, err error)
//sys Fspick(dirfd int, pathName string, flags int) (fd int, err error)
//sys fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error)
func fsconfigCommon(fd int, cmd uint, key string, value *byte, aux int) (err error) {
var keyp *byte
if keyp, err = BytePtrFromString(key); err != nil {
return
}
return fsconfig(fd, cmd, keyp, value, aux)
}
// FsconfigSetFlag is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_FLAG.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
func FsconfigSetFlag(fd int, key string) (err error) {
return fsconfigCommon(fd, FSCONFIG_SET_FLAG, key, nil, 0)
}
// FsconfigSetString is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_STRING.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
// value is the parameter value to set.
func FsconfigSetString(fd int, key string, value string) (err error) {
var valuep *byte
if valuep, err = BytePtrFromString(value); err != nil {
return
}
return fsconfigCommon(fd, FSCONFIG_SET_STRING, key, valuep, 0)
}
// FsconfigSetBinary is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_BINARY.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
// value is the parameter value to set.
func FsconfigSetBinary(fd int, key string, value []byte) (err error) {
if len(value) == 0 {
return EINVAL
}
return fsconfigCommon(fd, FSCONFIG_SET_BINARY, key, &value[0], len(value))
}
// FsconfigSetPath is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_PATH.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
// path is a non-empty path for specified key.
// atfd is a file descriptor at which to start lookup from or AT_FDCWD.
func FsconfigSetPath(fd int, key string, path string, atfd int) (err error) {
var valuep *byte
if valuep, err = BytePtrFromString(path); err != nil {
return
}
return fsconfigCommon(fd, FSCONFIG_SET_PATH, key, valuep, atfd)
}
// FsconfigSetPathEmpty is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_PATH_EMPTY. The same as
// FconfigSetPath but with AT_PATH_EMPTY implied.
func FsconfigSetPathEmpty(fd int, key string, path string, atfd int) (err error) {
var valuep *byte
if valuep, err = BytePtrFromString(path); err != nil {
return
}
return fsconfigCommon(fd, FSCONFIG_SET_PATH_EMPTY, key, valuep, atfd)
}
// FsconfigSetFd is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_FD.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
// value is a file descriptor to be assigned to specified key.
func FsconfigSetFd(fd int, key string, value int) (err error) {
return fsconfigCommon(fd, FSCONFIG_SET_FD, key, nil, value)
}
// FsconfigCreate is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_CMD_CREATE.
//
// fd is the filesystem context to act upon.
func FsconfigCreate(fd int) (err error) {
return fsconfig(fd, FSCONFIG_CMD_CREATE, nil, nil, 0)
}
// FsconfigReconfigure is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_CMD_RECONFIGURE.
//
// fd is the filesystem context to act upon.
func FsconfigReconfigure(fd int) (err error) {
return fsconfig(fd, FSCONFIG_CMD_RECONFIGURE, nil, nil, 0)
}
//sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
//sysnb Getpgid(pid int) (pgid int, err error)

@ -1520,6 +1520,14 @@ func (m *mmapper) Munmap(data []byte) (err error) {
return nil
}
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
return mapper.Mmap(fd, offset, length, prot, flags)
}
func Munmap(b []byte) (err error) {
return mapper.Munmap(b)
}
func Read(fd int, p []byte) (n int, err error) {
n, err = read(fd, p)
if raceenabled {

@ -906,6 +906,16 @@ func Fspick(dirfd int, pathName string, flags int) (fd int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error) {
_, _, e1 := Syscall6(SYS_FSCONFIG, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(value)), uintptr(aux), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getdents(fd int, buf []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(buf) > 0 {

@ -836,6 +836,15 @@ const (
FSPICK_EMPTY_PATH = 0x8
FSMOUNT_CLOEXEC = 0x1
FSCONFIG_SET_FLAG = 0x0
FSCONFIG_SET_STRING = 0x1
FSCONFIG_SET_BINARY = 0x2
FSCONFIG_SET_PATH = 0x3
FSCONFIG_SET_PATH_EMPTY = 0x4
FSCONFIG_SET_FD = 0x5
FSCONFIG_CMD_CREATE = 0x6
FSCONFIG_CMD_RECONFIGURE = 0x7
)
type OpenHow struct {
@ -1550,6 +1559,7 @@ const (
IFLA_DEVLINK_PORT = 0x3e
IFLA_GSO_IPV4_MAX_SIZE = 0x3f
IFLA_GRO_IPV4_MAX_SIZE = 0x40
IFLA_DPLL_PIN = 0x41
IFLA_PROTO_DOWN_REASON_UNSPEC = 0x0
IFLA_PROTO_DOWN_REASON_MASK = 0x1
IFLA_PROTO_DOWN_REASON_VALUE = 0x2
@ -1565,6 +1575,7 @@ const (
IFLA_INET6_ICMP6STATS = 0x6
IFLA_INET6_TOKEN = 0x7
IFLA_INET6_ADDR_GEN_MODE = 0x8
IFLA_INET6_RA_MTU = 0x9
IFLA_BR_UNSPEC = 0x0
IFLA_BR_FORWARD_DELAY = 0x1
IFLA_BR_HELLO_TIME = 0x2
@ -1612,6 +1623,9 @@ const (
IFLA_BR_MCAST_MLD_VERSION = 0x2c
IFLA_BR_VLAN_STATS_PER_PORT = 0x2d
IFLA_BR_MULTI_BOOLOPT = 0x2e
IFLA_BR_MCAST_QUERIER_STATE = 0x2f
IFLA_BR_FDB_N_LEARNED = 0x30
IFLA_BR_FDB_MAX_LEARNED = 0x31
IFLA_BRPORT_UNSPEC = 0x0
IFLA_BRPORT_STATE = 0x1
IFLA_BRPORT_PRIORITY = 0x2
@ -1649,6 +1663,14 @@ const (
IFLA_BRPORT_BACKUP_PORT = 0x22
IFLA_BRPORT_MRP_RING_OPEN = 0x23
IFLA_BRPORT_MRP_IN_OPEN = 0x24
IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT = 0x25
IFLA_BRPORT_MCAST_EHT_HOSTS_CNT = 0x26
IFLA_BRPORT_LOCKED = 0x27
IFLA_BRPORT_MAB = 0x28
IFLA_BRPORT_MCAST_N_GROUPS = 0x29
IFLA_BRPORT_MCAST_MAX_GROUPS = 0x2a
IFLA_BRPORT_NEIGH_VLAN_SUPPRESS = 0x2b
IFLA_BRPORT_BACKUP_NHID = 0x2c
IFLA_INFO_UNSPEC = 0x0
IFLA_INFO_KIND = 0x1
IFLA_INFO_DATA = 0x2
@ -1670,6 +1692,9 @@ const (
IFLA_MACVLAN_MACADDR = 0x4
IFLA_MACVLAN_MACADDR_DATA = 0x5
IFLA_MACVLAN_MACADDR_COUNT = 0x6
IFLA_MACVLAN_BC_QUEUE_LEN = 0x7
IFLA_MACVLAN_BC_QUEUE_LEN_USED = 0x8
IFLA_MACVLAN_BC_CUTOFF = 0x9
IFLA_VRF_UNSPEC = 0x0
IFLA_VRF_TABLE = 0x1
IFLA_VRF_PORT_UNSPEC = 0x0
@ -1693,9 +1718,22 @@ const (
IFLA_XFRM_UNSPEC = 0x0
IFLA_XFRM_LINK = 0x1
IFLA_XFRM_IF_ID = 0x2
IFLA_XFRM_COLLECT_METADATA = 0x3
IFLA_IPVLAN_UNSPEC = 0x0
IFLA_IPVLAN_MODE = 0x1
IFLA_IPVLAN_FLAGS = 0x2
NETKIT_NEXT = -0x1
NETKIT_PASS = 0x0
NETKIT_DROP = 0x2
NETKIT_REDIRECT = 0x7
NETKIT_L2 = 0x0
NETKIT_L3 = 0x1
IFLA_NETKIT_UNSPEC = 0x0
IFLA_NETKIT_PEER_INFO = 0x1
IFLA_NETKIT_PRIMARY = 0x2
IFLA_NETKIT_POLICY = 0x3
IFLA_NETKIT_PEER_POLICY = 0x4
IFLA_NETKIT_MODE = 0x5
IFLA_VXLAN_UNSPEC = 0x0
IFLA_VXLAN_ID = 0x1
IFLA_VXLAN_GROUP = 0x2
@ -1726,6 +1764,8 @@ const (
IFLA_VXLAN_GPE = 0x1b
IFLA_VXLAN_TTL_INHERIT = 0x1c
IFLA_VXLAN_DF = 0x1d
IFLA_VXLAN_VNIFILTER = 0x1e
IFLA_VXLAN_LOCALBYPASS = 0x1f
IFLA_GENEVE_UNSPEC = 0x0
IFLA_GENEVE_ID = 0x1
IFLA_GENEVE_REMOTE = 0x2
@ -1740,6 +1780,7 @@ const (
IFLA_GENEVE_LABEL = 0xb
IFLA_GENEVE_TTL_INHERIT = 0xc
IFLA_GENEVE_DF = 0xd
IFLA_GENEVE_INNER_PROTO_INHERIT = 0xe
IFLA_BAREUDP_UNSPEC = 0x0
IFLA_BAREUDP_PORT = 0x1
IFLA_BAREUDP_ETHERTYPE = 0x2
@ -1752,6 +1793,8 @@ const (
IFLA_GTP_FD1 = 0x2
IFLA_GTP_PDP_HASHSIZE = 0x3
IFLA_GTP_ROLE = 0x4
IFLA_GTP_CREATE_SOCKETS = 0x5
IFLA_GTP_RESTART_COUNT = 0x6
IFLA_BOND_UNSPEC = 0x0
IFLA_BOND_MODE = 0x1
IFLA_BOND_ACTIVE_SLAVE = 0x2
@ -1781,6 +1824,9 @@ const (
IFLA_BOND_AD_ACTOR_SYSTEM = 0x1a
IFLA_BOND_TLB_DYNAMIC_LB = 0x1b
IFLA_BOND_PEER_NOTIF_DELAY = 0x1c
IFLA_BOND_AD_LACP_ACTIVE = 0x1d
IFLA_BOND_MISSED_MAX = 0x1e
IFLA_BOND_NS_IP6_TARGET = 0x1f
IFLA_BOND_AD_INFO_UNSPEC = 0x0
IFLA_BOND_AD_INFO_AGGREGATOR = 0x1
IFLA_BOND_AD_INFO_NUM_PORTS = 0x2
@ -1796,6 +1842,7 @@ const (
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID = 0x6
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE = 0x7
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE = 0x8
IFLA_BOND_SLAVE_PRIO = 0x9
IFLA_VF_INFO_UNSPEC = 0x0
IFLA_VF_INFO = 0x1
IFLA_VF_UNSPEC = 0x0
@ -1854,8 +1901,16 @@ const (
IFLA_STATS_LINK_XSTATS_SLAVE = 0x3
IFLA_STATS_LINK_OFFLOAD_XSTATS = 0x4
IFLA_STATS_AF_SPEC = 0x5
IFLA_STATS_GETSET_UNSPEC = 0x0
IFLA_STATS_GET_FILTERS = 0x1
IFLA_STATS_SET_OFFLOAD_XSTATS_L3_STATS = 0x2
IFLA_OFFLOAD_XSTATS_UNSPEC = 0x0
IFLA_OFFLOAD_XSTATS_CPU_HIT = 0x1
IFLA_OFFLOAD_XSTATS_HW_S_INFO = 0x2
IFLA_OFFLOAD_XSTATS_L3_STATS = 0x3
IFLA_OFFLOAD_XSTATS_HW_S_INFO_UNSPEC = 0x0
IFLA_OFFLOAD_XSTATS_HW_S_INFO_REQUEST = 0x1
IFLA_OFFLOAD_XSTATS_HW_S_INFO_USED = 0x2
IFLA_XDP_UNSPEC = 0x0
IFLA_XDP_FD = 0x1
IFLA_XDP_ATTACHED = 0x2
@ -1885,6 +1940,11 @@ const (
IFLA_RMNET_UNSPEC = 0x0
IFLA_RMNET_MUX_ID = 0x1
IFLA_RMNET_FLAGS = 0x2
IFLA_MCTP_UNSPEC = 0x0
IFLA_MCTP_NET = 0x1
IFLA_DSA_UNSPEC = 0x0
IFLA_DSA_CONDUIT = 0x1
IFLA_DSA_MASTER = 0x1
)
const (

@ -165,6 +165,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile Handle) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
//sys CreateNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *SecurityAttributes) (handle Handle, err error) [failretval==InvalidHandle] = CreateNamedPipeW
//sys ConnectNamedPipe(pipe Handle, overlapped *Overlapped) (err error)
//sys DisconnectNamedPipe(pipe Handle) (err error)
//sys GetNamedPipeInfo(pipe Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error)
//sys GetNamedPipeHandleState(pipe Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
//sys SetNamedPipeHandleState(pipe Handle, state *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32) (err error) = SetNamedPipeHandleState
@ -348,8 +349,19 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys SetProcessPriorityBoost(process Handle, disable bool) (err error) = kernel32.SetProcessPriorityBoost
//sys GetProcessWorkingSetSizeEx(hProcess Handle, lpMinimumWorkingSetSize *uintptr, lpMaximumWorkingSetSize *uintptr, flags *uint32)
//sys SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr, dwMaximumWorkingSetSize uintptr, flags uint32) (err error)
//sys ClearCommBreak(handle Handle) (err error)
//sys ClearCommError(handle Handle, lpErrors *uint32, lpStat *ComStat) (err error)
//sys EscapeCommFunction(handle Handle, dwFunc uint32) (err error)
//sys GetCommState(handle Handle, lpDCB *DCB) (err error)
//sys GetCommModemStatus(handle Handle, lpModemStat *uint32) (err error)
//sys GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error)
//sys PurgeComm(handle Handle, dwFlags uint32) (err error)
//sys SetCommBreak(handle Handle) (err error)
//sys SetCommMask(handle Handle, dwEvtMask uint32) (err error)
//sys SetCommState(handle Handle, lpDCB *DCB) (err error)
//sys SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error)
//sys SetupComm(handle Handle, dwInQueue uint32, dwOutQueue uint32) (err error)
//sys WaitCommEvent(handle Handle, lpEvtMask *uint32, lpOverlapped *Overlapped) (err error)
//sys GetActiveProcessorCount(groupNumber uint16) (ret uint32)
//sys GetMaximumProcessorCount(groupNumber uint16) (ret uint32)
//sys EnumWindows(enumFunc uintptr, param unsafe.Pointer) (err error) = user32.EnumWindows
@ -1834,3 +1846,73 @@ func ResizePseudoConsole(pconsole Handle, size Coord) error {
// accept arguments that can be casted to uintptr, and Coord can't.
return resizePseudoConsole(pconsole, *((*uint32)(unsafe.Pointer(&size))))
}
// DCB constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-dcb.
const (
CBR_110 = 110
CBR_300 = 300
CBR_600 = 600
CBR_1200 = 1200
CBR_2400 = 2400
CBR_4800 = 4800
CBR_9600 = 9600
CBR_14400 = 14400
CBR_19200 = 19200
CBR_38400 = 38400
CBR_57600 = 57600
CBR_115200 = 115200
CBR_128000 = 128000
CBR_256000 = 256000
DTR_CONTROL_DISABLE = 0x00000000
DTR_CONTROL_ENABLE = 0x00000010
DTR_CONTROL_HANDSHAKE = 0x00000020
RTS_CONTROL_DISABLE = 0x00000000
RTS_CONTROL_ENABLE = 0x00001000
RTS_CONTROL_HANDSHAKE = 0x00002000
RTS_CONTROL_TOGGLE = 0x00003000
NOPARITY = 0
ODDPARITY = 1
EVENPARITY = 2
MARKPARITY = 3
SPACEPARITY = 4
ONESTOPBIT = 0
ONE5STOPBITS = 1
TWOSTOPBITS = 2
)
// EscapeCommFunction constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-escapecommfunction.
const (
SETXOFF = 1
SETXON = 2
SETRTS = 3
CLRRTS = 4
SETDTR = 5
CLRDTR = 6
SETBREAK = 8
CLRBREAK = 9
)
// PurgeComm constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-purgecomm.
const (
PURGE_TXABORT = 0x0001
PURGE_RXABORT = 0x0002
PURGE_TXCLEAR = 0x0004
PURGE_RXCLEAR = 0x0008
)
// SetCommMask constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setcommmask.
const (
EV_RXCHAR = 0x0001
EV_RXFLAG = 0x0002
EV_TXEMPTY = 0x0004
EV_CTS = 0x0008
EV_DSR = 0x0010
EV_RLSD = 0x0020
EV_BREAK = 0x0040
EV_ERR = 0x0080
EV_RING = 0x0100
)

@ -3380,3 +3380,27 @@ type BLOB struct {
Size uint32
BlobData *byte
}
type ComStat struct {
Flags uint32
CBInQue uint32
CBOutQue uint32
}
type DCB struct {
DCBlength uint32
BaudRate uint32
Flags uint32
wReserved uint16
XonLim uint16
XoffLim uint16
ByteSize uint8
Parity uint8
StopBits uint8
XonChar byte
XoffChar byte
ErrorChar byte
EofChar byte
EvtChar byte
wReserved1 uint16
}

@ -188,6 +188,8 @@ var (
procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject")
procCancelIo = modkernel32.NewProc("CancelIo")
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
procClearCommBreak = modkernel32.NewProc("ClearCommBreak")
procClearCommError = modkernel32.NewProc("ClearCommError")
procCloseHandle = modkernel32.NewProc("CloseHandle")
procClosePseudoConsole = modkernel32.NewProc("ClosePseudoConsole")
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
@ -212,7 +214,9 @@ var (
procDeleteProcThreadAttributeList = modkernel32.NewProc("DeleteProcThreadAttributeList")
procDeleteVolumeMountPointW = modkernel32.NewProc("DeleteVolumeMountPointW")
procDeviceIoControl = modkernel32.NewProc("DeviceIoControl")
procDisconnectNamedPipe = modkernel32.NewProc("DisconnectNamedPipe")
procDuplicateHandle = modkernel32.NewProc("DuplicateHandle")
procEscapeCommFunction = modkernel32.NewProc("EscapeCommFunction")
procExitProcess = modkernel32.NewProc("ExitProcess")
procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW")
procFindClose = modkernel32.NewProc("FindClose")
@ -236,6 +240,8 @@ var (
procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent")
procGetACP = modkernel32.NewProc("GetACP")
procGetActiveProcessorCount = modkernel32.NewProc("GetActiveProcessorCount")
procGetCommModemStatus = modkernel32.NewProc("GetCommModemStatus")
procGetCommState = modkernel32.NewProc("GetCommState")
procGetCommTimeouts = modkernel32.NewProc("GetCommTimeouts")
procGetCommandLineW = modkernel32.NewProc("GetCommandLineW")
procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
@ -322,6 +328,7 @@ var (
procProcess32NextW = modkernel32.NewProc("Process32NextW")
procProcessIdToSessionId = modkernel32.NewProc("ProcessIdToSessionId")
procPulseEvent = modkernel32.NewProc("PulseEvent")
procPurgeComm = modkernel32.NewProc("PurgeComm")
procQueryDosDeviceW = modkernel32.NewProc("QueryDosDeviceW")
procQueryFullProcessImageNameW = modkernel32.NewProc("QueryFullProcessImageNameW")
procQueryInformationJobObject = modkernel32.NewProc("QueryInformationJobObject")
@ -335,6 +342,9 @@ var (
procResetEvent = modkernel32.NewProc("ResetEvent")
procResizePseudoConsole = modkernel32.NewProc("ResizePseudoConsole")
procResumeThread = modkernel32.NewProc("ResumeThread")
procSetCommBreak = modkernel32.NewProc("SetCommBreak")
procSetCommMask = modkernel32.NewProc("SetCommMask")
procSetCommState = modkernel32.NewProc("SetCommState")
procSetCommTimeouts = modkernel32.NewProc("SetCommTimeouts")
procSetConsoleCursorPosition = modkernel32.NewProc("SetConsoleCursorPosition")
procSetConsoleMode = modkernel32.NewProc("SetConsoleMode")
@ -342,7 +352,6 @@ var (
procSetDefaultDllDirectories = modkernel32.NewProc("SetDefaultDllDirectories")
procSetDllDirectoryW = modkernel32.NewProc("SetDllDirectoryW")
procSetEndOfFile = modkernel32.NewProc("SetEndOfFile")
procSetFileValidData = modkernel32.NewProc("SetFileValidData")
procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW")
procSetErrorMode = modkernel32.NewProc("SetErrorMode")
procSetEvent = modkernel32.NewProc("SetEvent")
@ -351,6 +360,7 @@ var (
procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle")
procSetFilePointer = modkernel32.NewProc("SetFilePointer")
procSetFileTime = modkernel32.NewProc("SetFileTime")
procSetFileValidData = modkernel32.NewProc("SetFileValidData")
procSetHandleInformation = modkernel32.NewProc("SetHandleInformation")
procSetInformationJobObject = modkernel32.NewProc("SetInformationJobObject")
procSetNamedPipeHandleState = modkernel32.NewProc("SetNamedPipeHandleState")
@ -361,6 +371,7 @@ var (
procSetStdHandle = modkernel32.NewProc("SetStdHandle")
procSetVolumeLabelW = modkernel32.NewProc("SetVolumeLabelW")
procSetVolumeMountPointW = modkernel32.NewProc("SetVolumeMountPointW")
procSetupComm = modkernel32.NewProc("SetupComm")
procSizeofResource = modkernel32.NewProc("SizeofResource")
procSleepEx = modkernel32.NewProc("SleepEx")
procTerminateJobObject = modkernel32.NewProc("TerminateJobObject")
@ -379,6 +390,7 @@ var (
procVirtualQueryEx = modkernel32.NewProc("VirtualQueryEx")
procVirtualUnlock = modkernel32.NewProc("VirtualUnlock")
procWTSGetActiveConsoleSessionId = modkernel32.NewProc("WTSGetActiveConsoleSessionId")
procWaitCommEvent = modkernel32.NewProc("WaitCommEvent")
procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects")
procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject")
procWriteConsoleW = modkernel32.NewProc("WriteConsoleW")
@ -1641,6 +1653,22 @@ func CancelIoEx(s Handle, o *Overlapped) (err error) {
return
}
func ClearCommBreak(handle Handle) (err error) {
r1, _, e1 := syscall.Syscall(procClearCommBreak.Addr(), 1, uintptr(handle), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func ClearCommError(handle Handle, lpErrors *uint32, lpStat *ComStat) (err error) {
r1, _, e1 := syscall.Syscall(procClearCommError.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(lpErrors)), uintptr(unsafe.Pointer(lpStat)))
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func CloseHandle(handle Handle) (err error) {
r1, _, e1 := syscall.Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0)
if r1 == 0 {
@ -1845,6 +1873,14 @@ func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBuff
return
}
func DisconnectNamedPipe(pipe Handle) (err error) {
r1, _, e1 := syscall.Syscall(procDisconnectNamedPipe.Addr(), 1, uintptr(pipe), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) {
var _p0 uint32
if bInheritHandle {
@ -1857,6 +1893,14 @@ func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetP
return
}
func EscapeCommFunction(handle Handle, dwFunc uint32) (err error) {
r1, _, e1 := syscall.Syscall(procEscapeCommFunction.Addr(), 2, uintptr(handle), uintptr(dwFunc), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func ExitProcess(exitcode uint32) {
syscall.Syscall(procExitProcess.Addr(), 1, uintptr(exitcode), 0, 0)
return
@ -2058,6 +2102,22 @@ func GetActiveProcessorCount(groupNumber uint16) (ret uint32) {
return
}
func GetCommModemStatus(handle Handle, lpModemStat *uint32) (err error) {
r1, _, e1 := syscall.Syscall(procGetCommModemStatus.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpModemStat)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func GetCommState(handle Handle, lpDCB *DCB) (err error) {
r1, _, e1 := syscall.Syscall(procGetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpDCB)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) {
r1, _, e1 := syscall.Syscall(procGetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0)
if r1 == 0 {
@ -2810,6 +2870,14 @@ func PulseEvent(event Handle) (err error) {
return
}
func PurgeComm(handle Handle, dwFlags uint32) (err error) {
r1, _, e1 := syscall.Syscall(procPurgeComm.Addr(), 2, uintptr(handle), uintptr(dwFlags), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) {
r0, _, e1 := syscall.Syscall(procQueryDosDeviceW.Addr(), 3, uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath)), uintptr(max))
n = uint32(r0)
@ -2924,6 +2992,30 @@ func ResumeThread(thread Handle) (ret uint32, err error) {
return
}
func SetCommBreak(handle Handle) (err error) {
r1, _, e1 := syscall.Syscall(procSetCommBreak.Addr(), 1, uintptr(handle), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SetCommMask(handle Handle, dwEvtMask uint32) (err error) {
r1, _, e1 := syscall.Syscall(procSetCommMask.Addr(), 2, uintptr(handle), uintptr(dwEvtMask), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SetCommState(handle Handle, lpDCB *DCB) (err error) {
r1, _, e1 := syscall.Syscall(procSetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpDCB)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) {
r1, _, e1 := syscall.Syscall(procSetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0)
if r1 == 0 {
@ -2989,14 +3081,6 @@ func SetEndOfFile(handle Handle) (err error) {
return
}
func SetFileValidData(handle Handle, validDataLength int64) (err error) {
r1, _, e1 := syscall.Syscall(procSetFileValidData.Addr(), 2, uintptr(handle), uintptr(validDataLength), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SetEnvironmentVariable(name *uint16, value *uint16) (err error) {
r1, _, e1 := syscall.Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0)
if r1 == 0 {
@ -3060,6 +3144,14 @@ func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetim
return
}
func SetFileValidData(handle Handle, validDataLength int64) (err error) {
r1, _, e1 := syscall.Syscall(procSetFileValidData.Addr(), 2, uintptr(handle), uintptr(validDataLength), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) {
r1, _, e1 := syscall.Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags))
if r1 == 0 {
@ -3145,6 +3237,14 @@ func SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err erro
return
}
func SetupComm(handle Handle, dwInQueue uint32, dwOutQueue uint32) (err error) {
r1, _, e1 := syscall.Syscall(procSetupComm.Addr(), 3, uintptr(handle), uintptr(dwInQueue), uintptr(dwOutQueue))
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SizeofResource(module Handle, resInfo Handle) (size uint32, err error) {
r0, _, e1 := syscall.Syscall(procSizeofResource.Addr(), 2, uintptr(module), uintptr(resInfo), 0)
size = uint32(r0)
@ -3291,6 +3391,14 @@ func WTSGetActiveConsoleSessionId() (sessionID uint32) {
return
}
func WaitCommEvent(handle Handle, lpEvtMask *uint32, lpOverlapped *Overlapped) (err error) {
r1, _, e1 := syscall.Syscall(procWaitCommEvent.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(lpEvtMask)), uintptr(unsafe.Pointer(lpOverlapped)))
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMilliseconds uint32) (event uint32, err error) {
var _p0 uint32
if waitAll {

38
vendor/modules.txt vendored

@ -34,9 +34,9 @@ github.com/cespare/xxhash/v2
# github.com/containerd/cgroups v1.0.4
## explicit; go 1.17
# github.com/containerd/containerd v1.6.18
## explicit; go 1.19
# github.com/containerd/containerd v1.7.13
## explicit; go 1.19
## explicit; go 1.21
# github.com/containerd/containerd v1.7.15
## explicit; go 1.21
github.com/containerd/containerd/log
github.com/containerd/containerd/pkg/userns
# github.com/containerd/log v0.1.0
@ -64,7 +64,7 @@ github.com/dimchansky/utfbom
github.com/distribution/reference
# github.com/docker/cli v20.10.17+incompatible
## explicit
# github.com/docker/cli v25.0.3+incompatible
# github.com/docker/cli v26.0.0+incompatible
## explicit
github.com/docker/cli/cli/command
github.com/docker/cli/cli/config
@ -110,7 +110,7 @@ github.com/docker/distribution/uuid
## explicit
# github.com/docker/docker v24.0.5+incompatible
## explicit
# github.com/docker/docker v25.0.3+incompatible
# github.com/docker/docker v26.0.0+incompatible
## explicit
github.com/docker/docker/api
github.com/docker/docker/api/types
@ -132,7 +132,6 @@ github.com/docker/docker/api/types/versions
github.com/docker/docker/api/types/volume
github.com/docker/docker/client
github.com/docker/docker/errdefs
github.com/docker/docker/image/spec/specs-go/v1
github.com/docker/docker/internal/multierror
github.com/docker/docker/pkg/archive
github.com/docker/docker/pkg/homedir
@ -206,8 +205,12 @@ github.com/gogo/protobuf/sortkeys
## explicit; go 1.17
github.com/golang/protobuf/proto
# github.com/goodhosts/hostsfile v0.1.1
## explicit; go 1.17
## explicit; go 1.21
# github.com/goodhosts/hostsfile v0.1.6
## explicit; go 1.21
github.com/goodhosts/hostsfile
github.com/goodhosts/hostsfile/mage/install
github.com/goodhosts/hostsfile/mage/test
# github.com/google/go-cmp v0.5.9
## explicit; go 1.13
# github.com/google/go-cmp v0.6.0
@ -217,7 +220,7 @@ github.com/google/go-cmp/cmp/internal/diff
github.com/google/go-cmp/cmp/internal/flags
github.com/google/go-cmp/cmp/internal/function
github.com/google/go-cmp/cmp/internal/value
# github.com/google/go-containerregistry v0.16.1
# github.com/google/go-containerregistry v0.19.1
## explicit; go 1.18
github.com/google/go-containerregistry/internal/and
github.com/google/go-containerregistry/internal/compression
@ -293,6 +296,10 @@ github.com/klauspost/compress/zstd/internal/xxhash
# github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de
## explicit
github.com/liggitt/tabwriter
# github.com/magefile/mage v1.15.0
## explicit; go 1.12
github.com/magefile/mage/mg
github.com/magefile/mage/sh
# github.com/magiconair/properties v1.8.6
## explicit; go 1.19
# github.com/magiconair/properties v1.8.7
@ -316,6 +323,9 @@ github.com/mitchellh/mapstructure
# github.com/mitchellh/reflectwalk v1.0.2
## explicit
github.com/mitchellh/reflectwalk
# github.com/moby/docker-image-spec v1.3.1
## explicit; go 1.18
github.com/moby/docker-image-spec/specs-go/v1
# github.com/moby/patternmatcher v0.5.0
## explicit; go 1.19
github.com/moby/patternmatcher
@ -528,14 +538,14 @@ go.uber.org/atomic
go.uber.org/multierr
# go4.org/intern v0.0.0-20211027215823-ae77deb06f29
## explicit; go 1.13
# go4.org/netipx v0.0.0-20230728184502-ec4c8b891b28
# go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
## explicit; go 1.18
go4.org/netipx
# go4.org/unsafe/assume-no-moving-gc v0.0.0-20230209150437-ee73d164e760
## explicit; go 1.11
# golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
## explicit; go 1.18
# golang.org/x/crypto v0.16.0
# golang.org/x/crypto v0.22.0
## explicit; go 1.18
golang.org/x/crypto/ed25519
golang.org/x/crypto/pbkdf2
@ -555,7 +565,7 @@ golang.org/x/mod/semver
## explicit; go 1.18
# golang.org/x/net v0.9.0
## explicit; go 1.18
# golang.org/x/net v0.19.0
# golang.org/x/net v0.21.0
## explicit; go 1.18
golang.org/x/net/context
golang.org/x/net/http/httpguts
@ -570,21 +580,21 @@ golang.org/x/oauth2
golang.org/x/oauth2/internal
# golang.org/x/sync v0.0.0-20220513210516-0976fa681c29
## explicit; go 1.18
# golang.org/x/sync v0.6.0
# golang.org/x/sync v0.7.0
## explicit; go 1.18
golang.org/x/sync/errgroup
# golang.org/x/sys v0.5.0
## explicit; go 1.18
# golang.org/x/sys v0.10.0
## explicit; go 1.18
# golang.org/x/sys v0.17.0
# golang.org/x/sys v0.19.0
## explicit; go 1.18
golang.org/x/sys/plan9
golang.org/x/sys/unix
golang.org/x/sys/windows
# golang.org/x/term v0.5.0
## explicit; go 1.18
# golang.org/x/term v0.15.0
# golang.org/x/term v0.19.0
## explicit; go 1.18
golang.org/x/term
# golang.org/x/text v0.7.0

Loading…
Cancel
Save