From 3540b21b80506b23b125e1b3f706fca5ef0e4070 Mon Sep 17 00:00:00 2001
From: "cluster-stack-bot[bot]"
<143188378+cluster-stack-bot[bot]@users.noreply.github.com>
Date: Mon, 8 Sep 2025 11:21:31 +0000
Subject: [PATCH] :seedling: Update Update Golang Dependencies group
| datasource | package | from | to |
| -------------- | ---------------------- | ------- | ------- |
| go | github.com/spf13/cobra | v1.8.1 | v1.10.1 |
| golang-version | go | 1.22.9 | 1.25.1 |
| go | golang.org/x/mod | v0.22.0 | v0.28.0 |
| go | oras.land/oras-go/v2 | v2.5.0 | v2.6.0 |
---
go.mod | 16 +-
go.sum | 30 +-
.../image-spec/specs-go/version.go | 2 +-
vendor/github.com/spf13/cobra/.golangci.yml | 28 +-
vendor/github.com/spf13/cobra/README.md | 25 +-
vendor/github.com/spf13/cobra/SECURITY.md | 105 ++++++
vendor/github.com/spf13/cobra/active_help.go | 2 +-
.../spf13/cobra/bash_completionsV2.go | 152 ++++++--
vendor/github.com/spf13/cobra/cobra.go | 16 +-
vendor/github.com/spf13/cobra/command.go | 340 +++++++++++++-----
vendor/github.com/spf13/cobra/completions.go | 143 ++++++--
.../spf13/cobra/powershell_completions.go | 35 +-
vendor/github.com/spf13/pflag/.editorconfig | 12 +
vendor/github.com/spf13/pflag/.golangci.yaml | 4 +
vendor/github.com/spf13/pflag/README.md | 27 ++
vendor/github.com/spf13/pflag/bool_func.go | 40 +++
vendor/github.com/spf13/pflag/count.go | 2 +-
vendor/github.com/spf13/pflag/errors.go | 149 ++++++++
vendor/github.com/spf13/pflag/flag.go | 146 +++++---
vendor/github.com/spf13/pflag/func.go | 37 ++
vendor/github.com/spf13/pflag/golangflag.go | 56 +++
vendor/github.com/spf13/pflag/ip.go | 3 +
vendor/github.com/spf13/pflag/ipnet_slice.go | 147 ++++++++
vendor/github.com/spf13/pflag/string_array.go | 4 -
.../spf13/pflag/string_to_string.go | 10 +-
vendor/github.com/spf13/pflag/text.go | 81 +++++
vendor/github.com/spf13/pflag/time.go | 124 +++++++
vendor/golang.org/x/mod/sumdb/dirhash/hash.go | 6 +-
vendor/golang.org/x/sync/errgroup/errgroup.go | 113 ++++--
vendor/modules.txt | 18 +-
.../oras.land/oras-go/v2/MIGRATION_GUIDE.md | 36 +-
vendor/oras.land/oras-go/v2/README.md | 76 ++--
.../oras.land/oras-go/v2/content/file/file.go | 16 +-
.../oras-go/v2/content/file/utils.go | 67 +++-
vendor/oras.land/oras-go/v2/content/reader.go | 5 +
vendor/oras.land/oras-go/v2/copy.go | 61 ++--
vendor/oras.land/oras-go/v2/copyerror.go | 78 ++++
vendor/oras.land/oras-go/v2/extendedcopy.go | 25 +-
.../oras-go/v2/internal/platform/platform.go | 2 +-
.../oras-go/v2/internal/resolver/memory.go | 3 +-
.../oras-go/v2/internal/syncutil/limit.go | 37 +-
.../v2/internal/syncutil/limitgroup.go | 2 +-
vendor/oras.land/oras-go/v2/pack.go | 27 +-
.../oras-go/v2/registry/reference.go | 4 +-
.../oras.land/oras-go/v2/registry/registry.go | 2 +-
.../v2/registry/remote/auth/challenge.go | 2 +-
.../oras-go/v2/registry/remote/auth/client.go | 16 +-
.../v2/registry/remote/auth/credential.go | 4 +-
.../oras-go/v2/registry/remote/auth/scope.go | 10 +-
.../v2/registry/remote/errcode/errors.go | 12 +-
.../oras-go/v2/registry/remote/referrers.go | 10 +-
.../oras-go/v2/registry/remote/registry.go | 8 +-
.../oras-go/v2/registry/remote/repository.go | 78 ++--
.../v2/registry/remote/retry/policy.go | 8 +-
.../oras-go/v2/registry/remote/url.go | 16 +-
.../oras-go/v2/registry/remote/warning.go | 4 +-
.../oras-go/v2/registry/repository.go | 10 +-
57 files changed, 2012 insertions(+), 480 deletions(-)
create mode 100644 vendor/github.com/spf13/cobra/SECURITY.md
create mode 100644 vendor/github.com/spf13/pflag/.editorconfig
create mode 100644 vendor/github.com/spf13/pflag/.golangci.yaml
create mode 100644 vendor/github.com/spf13/pflag/bool_func.go
create mode 100644 vendor/github.com/spf13/pflag/errors.go
create mode 100644 vendor/github.com/spf13/pflag/func.go
create mode 100644 vendor/github.com/spf13/pflag/ipnet_slice.go
create mode 100644 vendor/github.com/spf13/pflag/text.go
create mode 100644 vendor/github.com/spf13/pflag/time.go
create mode 100644 vendor/oras.land/oras-go/v2/copyerror.go
diff --git a/go.mod b/go.mod
index e084bced..75270d95 100644
--- a/go.mod
+++ b/go.mod
@@ -1,21 +1,21 @@
module github.com/SovereignCloudStack/csctl
-go 1.22.0
+go 1.24.0
-toolchain go1.22.9
+toolchain go1.25.1
require (
github.com/SovereignCloudStack/cluster-stack-operator v0.1.0-alpha.5
github.com/google/go-github/v56 v56.0.0
- github.com/opencontainers/image-spec v1.1.0
- github.com/spf13/cobra v1.8.1
+ github.com/opencontainers/image-spec v1.1.1
+ github.com/spf13/cobra v1.10.1
github.com/valyala/fasttemplate v1.2.2
- golang.org/x/mod v0.22.0
+ golang.org/x/mod v0.28.0
golang.org/x/oauth2 v0.24.0
gopkg.in/src-d/go-git.v4 v4.13.1
gopkg.in/yaml.v3 v3.0.1
helm.sh/helm/v3 v3.16.3
- oras.land/oras-go/v2 v2.5.0
+ oras.land/oras-go/v2 v2.6.0
)
require (
@@ -118,7 +118,7 @@ require (
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/cast v1.7.0 // indirect
- github.com/spf13/pflag v1.0.5 // indirect
+ github.com/spf13/pflag v1.0.9 // indirect
github.com/src-d/gcfg v1.4.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
@@ -134,7 +134,7 @@ require (
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/net v0.26.0 // indirect
- golang.org/x/sync v0.8.0 // indirect
+ golang.org/x/sync v0.14.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/term v0.24.0 // indirect
golang.org/x/text v0.18.0 // indirect
diff --git a/go.sum b/go.sum
index a84ad895..cb21c239 100644
--- a/go.sum
+++ b/go.sum
@@ -75,7 +75,7 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
-github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
@@ -318,8 +318,8 @@ github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
-github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
-github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
+github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
+github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
@@ -369,10 +369,10 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
-github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
-github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
+github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
+github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
+github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -444,8 +444,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
-golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
+golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
+golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -468,8 +468,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.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
-golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
+golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -508,8 +508,8 @@ golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDq
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
-golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
+golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
+golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -593,8 +593,8 @@ k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo=
oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo=
-oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c=
-oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg=
+oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc=
+oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g=
diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/version.go b/vendor/github.com/opencontainers/image-spec/specs-go/version.go
index 7069ae44..c3897c7c 100644
--- a/vendor/github.com/opencontainers/image-spec/specs-go/version.go
+++ b/vendor/github.com/opencontainers/image-spec/specs-go/version.go
@@ -22,7 +22,7 @@ const (
// VersionMinor is for functionality in a backwards-compatible manner
VersionMinor = 1
// VersionPatch is for backwards-compatible bug fixes
- VersionPatch = 0
+ VersionPatch = 1
// VersionDev indicates development branch. Releases will be empty string.
VersionDev = ""
diff --git a/vendor/github.com/spf13/cobra/.golangci.yml b/vendor/github.com/spf13/cobra/.golangci.yml
index 2c8f4808..6acf8ab1 100644
--- a/vendor/github.com/spf13/cobra/.golangci.yml
+++ b/vendor/github.com/spf13/cobra/.golangci.yml
@@ -12,14 +12,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+version: "2"
+
run:
- deadline: 5m
+ timeout: 5m
+
+formatters:
+ enable:
+ - gofmt
+ - goimports
linters:
- disable-all: true
+ default: none
enable:
#- bodyclose
- # - deadcode ! deprecated since v1.49.0; replaced by 'unused'
#- depguard
#- dogsled
#- dupl
@@ -30,28 +36,24 @@ linters:
- goconst
- gocritic
#- gocyclo
- - gofmt
- - goimports
- #- gomnd
#- goprintffuncname
- gosec
- - gosimple
- govet
- ineffassign
#- lll
- misspell
+ #- mnd
#- nakedret
#- noctx
- nolintlint
#- rowserrcheck
- #- scopelint
- staticcheck
- #- structcheck ! deprecated since v1.49.0; replaced by 'unused'
- - stylecheck
- #- typecheck
- unconvert
#- unparam
- unused
- # - varcheck ! deprecated since v1.49.0; replaced by 'unused'
#- whitespace
- fast: false
+ exclusions:
+ presets:
+ - common-false-positives
+ - legacy
+ - std-error-handling
diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md
index 6444f4b7..8416275f 100644
--- a/vendor/github.com/spf13/cobra/README.md
+++ b/vendor/github.com/spf13/cobra/README.md
@@ -1,7 +1,14 @@
-
+
Cobra is a library for creating powerful modern CLI applications.
+Visit Cobra.dev for extensive documentation
+
+
Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/),
[Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to
name a few. [This list](site/content/projects_using_cobra.md) contains a more extensive list of projects using Cobra.
@@ -10,6 +17,20 @@ name a few. [This list](site/content/projects_using_cobra.md) contains a more ex
[](https://pkg.go.dev/github.com/spf13/cobra)
[](https://goreportcard.com/report/github.com/spf13/cobra)
[](https://gophers.slack.com/archives/CD3LP1199)
+
+
+
Supported by:
+
+
+
+
+
+
+### [Warp, the AI terminal for devs](https://www.warp.dev/cobra)
+[Try Cobra in Warp today](https://www.warp.dev/cobra)
+
+
+
# Overview
@@ -105,7 +126,7 @@ go install github.com/spf13/cobra-cli@latest
For complete details on using the Cobra-CLI generator, please read [The Cobra Generator README](https://github.com/spf13/cobra-cli/blob/main/README.md)
-For complete details on using the Cobra library, please read the [The Cobra User Guide](site/content/user_guide.md).
+For complete details on using the Cobra library, please read [The Cobra User Guide](site/content/user_guide.md).
# License
diff --git a/vendor/github.com/spf13/cobra/SECURITY.md b/vendor/github.com/spf13/cobra/SECURITY.md
new file mode 100644
index 00000000..54e60c28
--- /dev/null
+++ b/vendor/github.com/spf13/cobra/SECURITY.md
@@ -0,0 +1,105 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+The `cobra` maintainers take security issues seriously and
+we appreciate your efforts to _**responsibly**_ disclose your findings.
+We will make every effort to swiftly respond and address concerns.
+
+To report a security vulnerability:
+
+1. **DO NOT** create a public GitHub issue for the vulnerability!
+2. **DO NOT** create a public GitHub Pull Request with a fix for the vulnerability!
+3. Send an email to `cobra-security@googlegroups.com`.
+4. Include the following details in your report:
+ - Description of the vulnerability
+ - Steps to reproduce
+ - Potential impact of the vulnerability (to your downstream project, to the Go ecosystem, etc.)
+ - Any potential mitigations you've already identified
+5. Allow up to 7 days for an initial response.
+ You should receive an acknowledgment of your report and an estimated timeline for a fix.
+6. (Optional) If you have a fix and would like to contribute your patch, please work
+ directly with the maintainers via `cobra-security@googlegroups.com` to
+ coordinate pushing the patch to GitHub, cutting a new release, and disclosing the change.
+
+## Response Process
+
+When a security vulnerability report is received, the `cobra` maintainers will:
+
+1. Confirm receipt of the vulnerability report within 7 days.
+2. Assess the report to determine if it constitutes a security vulnerability.
+3. If confirmed, assign the vulnerability a severity level and create a timeline for addressing it.
+4. Develop and test a fix.
+5. Patch the vulnerability and make a new GitHub release: the maintainers will coordinate disclosure with the reporter.
+6. Create a new GitHub Security Advisory to inform the broader Go ecosystem
+
+## Disclosure Policy
+
+The `cobra` maintainers follow a coordinated disclosure process:
+
+1. Security vulnerabilities will be addressed as quickly as possible.
+2. A CVE (Common Vulnerabilities and Exposures) identifier will be requested for significant vulnerabilities
+ that are within `cobra` itself.
+3. Once a fix is ready, the maintainers will:
+ - Release a new version containing the fix.
+ - Update the security advisory with details about the vulnerability.
+ - Credit the reporter (unless they wish to remain anonymous).
+ - Credit the fixer (unless they wish to remain anonymous, this may be the same as the reporter).
+ - Announce the vulnerability through appropriate channels
+ (GitHub Security Advisory, mailing lists, GitHub Releases, etc.)
+
+## Supported Versions
+
+Security fixes will typically only be released for the most recent major release.
+
+## Upstream Security Issues
+
+`cobra` generally will not accept vulnerability reports that originate in upstream
+dependencies. I.e., if there is a problem in Go code that `cobra` depends on,
+it is best to engage that project's maintainers and owners.
+
+This security policy primarily pertains only to `cobra` itself but if you believe you've
+identified a problem that originates in an upstream dependency and is being widely
+distributed by `cobra`, please follow the disclosure procedure above: the `cobra`
+maintainers will work with you to determine the severity and ecosystem impact.
+
+## Security Updates and CVEs
+
+Information about known security vulnerabilities and CVEs affecting `cobra` will
+be published as GitHub Security Advisories at
+https://github.com/spf13/cobra/security/advisories.
+
+All users are encouraged to watch the repository and upgrade promptly when
+security releases are published.
+
+## `cobra` Security Best Practices for Users
+
+When using `cobra` in your CLIs, the `cobra` maintainers recommend the following:
+
+1. Always use the latest version of `cobra`.
+2. [Use Go modules](https://go.dev/blog/using-go-modules) for dependency management.
+3. Always use the latest possible version of Go.
+
+## Security Best Practices for Contributors
+
+When contributing to `cobra`:
+
+1. Be mindful of security implications when adding new features or modifying existing ones.
+2. Be aware of `cobra`'s extremely large reach: it is used in nearly every Go CLI
+ (like Kubernetes, Docker, Prometheus, etc. etc.)
+3. Write tests that explicitly cover edge cases and potential issues.
+4. If you discover a security issue while working on `cobra`, please report it
+ following the process above rather than opening a public pull request or issue that
+ addresses the vulnerability.
+5. Take personal sec-ops seriously and secure your GitHub account: use [two-factor authentication](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa),
+ [sign your commits with a GPG or SSH key](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification),
+ etc.
+
+## Acknowledgments
+
+The `cobra` maintainers would like to thank all security researchers and
+community members who help keep cobra, its users, and the entire Go ecosystem secure through responsible disclosures!!
+
+---
+
+*This security policy is inspired by the [Open Web Application Security Project (OWASP)](https://owasp.org/) guidelines and security best practices.*
diff --git a/vendor/github.com/spf13/cobra/active_help.go b/vendor/github.com/spf13/cobra/active_help.go
index 25c30e3c..b3e2dadf 100644
--- a/vendor/github.com/spf13/cobra/active_help.go
+++ b/vendor/github.com/spf13/cobra/active_help.go
@@ -35,7 +35,7 @@ const (
// This function can be called multiple times before and/or after completions are added to
// the array. Each time this function is called with the same array, the new
// ActiveHelp line will be shown below the previous ones when completion is triggered.
-func AppendActiveHelp(compArray []string, activeHelpStr string) []string {
+func AppendActiveHelp(compArray []Completion, activeHelpStr string) []Completion {
return append(compArray, fmt.Sprintf("%s%s", activeHelpMarker, activeHelpStr))
}
diff --git a/vendor/github.com/spf13/cobra/bash_completionsV2.go b/vendor/github.com/spf13/cobra/bash_completionsV2.go
index 1cce5c32..d2397aa3 100644
--- a/vendor/github.com/spf13/cobra/bash_completionsV2.go
+++ b/vendor/github.com/spf13/cobra/bash_completionsV2.go
@@ -146,7 +146,7 @@ __%[1]s_process_completion_results() {
if (((directive & shellCompDirectiveFilterFileExt) != 0)); then
# File extension filtering
- local fullFilter filter filteringCmd
+ local fullFilter="" filter filteringCmd
# Do not use quotes around the $completions variable or else newline
# characters will be kept.
@@ -177,20 +177,71 @@ __%[1]s_process_completion_results() {
__%[1]s_handle_special_char "$cur" =
# Print the activeHelp statements before we finish
+ __%[1]s_handle_activeHelp
+}
+
+__%[1]s_handle_activeHelp() {
+ # Print the activeHelp statements
if ((${#activeHelp[*]} != 0)); then
- printf "\n";
- printf "%%s\n" "${activeHelp[@]}"
- printf "\n"
-
- # The prompt format is only available from bash 4.4.
- # We test if it is available before using it.
- if (x=${PS1@P}) 2> /dev/null; then
- printf "%%s" "${PS1@P}${COMP_LINE[@]}"
- else
- # Can't print the prompt. Just print the
- # text the user had typed, it is workable enough.
- printf "%%s" "${COMP_LINE[@]}"
+ if [ -z $COMP_TYPE ]; then
+ # Bash v3 does not set the COMP_TYPE variable.
+ printf "\n";
+ printf "%%s\n" "${activeHelp[@]}"
+ printf "\n"
+ __%[1]s_reprint_commandLine
+ return
fi
+
+ # Only print ActiveHelp on the second TAB press
+ if [ $COMP_TYPE -eq 63 ]; then
+ printf "\n"
+ printf "%%s\n" "${activeHelp[@]}"
+
+ if ((${#COMPREPLY[*]} == 0)); then
+ # When there are no completion choices from the program, file completion
+ # may kick in if the program has not disabled it; in such a case, we want
+ # to know if any files will match what the user typed, so that we know if
+ # there will be completions presented, so that we know how to handle ActiveHelp.
+ # To find out, we actually trigger the file completion ourselves;
+ # the call to _filedir will fill COMPREPLY if files match.
+ if (((directive & shellCompDirectiveNoFileComp) == 0)); then
+ __%[1]s_debug "Listing files"
+ _filedir
+ fi
+ fi
+
+ if ((${#COMPREPLY[*]} != 0)); then
+ # If there are completion choices to be shown, print a delimiter.
+ # Re-printing the command-line will automatically be done
+ # by the shell when it prints the completion choices.
+ printf -- "--"
+ else
+ # When there are no completion choices at all, we need
+ # to re-print the command-line since the shell will
+ # not be doing it itself.
+ __%[1]s_reprint_commandLine
+ fi
+ elif [ $COMP_TYPE -eq 37 ] || [ $COMP_TYPE -eq 42 ]; then
+ # For completion type: menu-complete/menu-complete-backward and insert-completions
+ # the completions are immediately inserted into the command-line, so we first
+ # print the activeHelp message and reprint the command-line since the shell won't.
+ printf "\n"
+ printf "%%s\n" "${activeHelp[@]}"
+
+ __%[1]s_reprint_commandLine
+ fi
+ fi
+}
+
+__%[1]s_reprint_commandLine() {
+ # The prompt format is only available from bash 4.4.
+ # We test if it is available before using it.
+ if (x=${PS1@P}) 2> /dev/null; then
+ printf "%%s" "${PS1@P}${COMP_LINE[@]}"
+ else
+ # Can't print the prompt. Just print the
+ # text the user had typed, it is workable enough.
+ printf "%%s" "${COMP_LINE[@]}"
fi
}
@@ -201,6 +252,8 @@ __%[1]s_extract_activeHelp() {
local endIndex=${#activeHelpMarker}
while IFS='' read -r comp; do
+ [[ -z $comp ]] && continue
+
if [[ ${comp:0:endIndex} == $activeHelpMarker ]]; then
comp=${comp:endIndex}
__%[1]s_debug "ActiveHelp found: $comp"
@@ -223,16 +276,21 @@ __%[1]s_handle_completion_types() {
# If the user requested inserting one completion at a time, or all
# completions at once on the command-line we must remove the descriptions.
# https://github.com/spf13/cobra/issues/1508
- local tab=$'\t' comp
- while IFS='' read -r comp; do
- [[ -z $comp ]] && continue
- # Strip any description
- comp=${comp%%%%$tab*}
- # Only consider the completions that match
- if [[ $comp == "$cur"* ]]; then
- COMPREPLY+=("$comp")
- fi
- done < <(printf "%%s\n" "${completions[@]}")
+
+ # If there are no completions, we don't need to do anything
+ (( ${#completions[@]} == 0 )) && return 0
+
+ local tab=$'\t'
+
+ # Strip any description and escape the completion to handled special characters
+ IFS=$'\n' read -ra completions -d '' < <(printf "%%q\n" "${completions[@]%%%%$tab*}")
+
+ # Only consider the completions that match
+ IFS=$'\n' read -ra COMPREPLY -d '' < <(IFS=$'\n'; compgen -W "${completions[*]}" -- "${cur}")
+
+ # compgen looses the escaping so we need to escape all completions again since they will
+ # all be inserted on the command-line.
+ IFS=$'\n' read -ra COMPREPLY -d '' < <(printf "%%q\n" "${COMPREPLY[@]}")
;;
*)
@@ -243,11 +301,25 @@ __%[1]s_handle_completion_types() {
}
__%[1]s_handle_standard_completion_case() {
- local tab=$'\t' comp
+ local tab=$'\t'
+
+ # If there are no completions, we don't need to do anything
+ (( ${#completions[@]} == 0 )) && return 0
# Short circuit to optimize if we don't have descriptions
if [[ "${completions[*]}" != *$tab* ]]; then
- IFS=$'\n' read -ra COMPREPLY -d '' < <(compgen -W "${completions[*]}" -- "$cur")
+ # First, escape the completions to handle special characters
+ IFS=$'\n' read -ra completions -d '' < <(printf "%%q\n" "${completions[@]}")
+ # Only consider the completions that match what the user typed
+ IFS=$'\n' read -ra COMPREPLY -d '' < <(IFS=$'\n'; compgen -W "${completions[*]}" -- "${cur}")
+
+ # compgen looses the escaping so, if there is only a single completion, we need to
+ # escape it again because it will be inserted on the command-line. If there are multiple
+ # completions, we don't want to escape them because they will be printed in a list
+ # and we don't want to show escape characters in that list.
+ if (( ${#COMPREPLY[@]} == 1 )); then
+ COMPREPLY[0]=$(printf "%%q" "${COMPREPLY[0]}")
+ fi
return 0
fi
@@ -256,23 +328,39 @@ __%[1]s_handle_standard_completion_case() {
# Look for the longest completion so that we can format things nicely
while IFS='' read -r compline; do
[[ -z $compline ]] && continue
- # Strip any description before checking the length
- comp=${compline%%%%$tab*}
+
+ # Before checking if the completion matches what the user typed,
+ # we need to strip any description and escape the completion to handle special
+ # characters because those escape characters are part of what the user typed.
+ # Don't call "printf" in a sub-shell because it will be much slower
+ # since we are in a loop.
+ printf -v comp "%%q" "${compline%%%%$tab*}" &>/dev/null || comp=$(printf "%%q" "${compline%%%%$tab*}")
+
# Only consider the completions that match
[[ $comp == "$cur"* ]] || continue
+
+ # The completions matches. Add it to the list of full completions including
+ # its description. We don't escape the completion because it may get printed
+ # in a list if there are more than one and we don't want show escape characters
+ # in that list.
COMPREPLY+=("$compline")
+
+ # Strip any description before checking the length, and again, don't escape
+ # the completion because this length is only used when printing the completions
+ # in a list and we don't want show escape characters in that list.
+ comp=${compline%%%%$tab*}
if ((${#comp}>longest)); then
longest=${#comp}
fi
done < <(printf "%%s\n" "${completions[@]}")
- # If there is a single completion left, remove the description text
+ # If there is a single completion left, remove the description text and escape any special characters
if ((${#COMPREPLY[*]} == 1)); then
__%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}"
- comp="${COMPREPLY[0]%%%%$tab*}"
- __%[1]s_debug "Removed description from single completion, which is now: ${comp}"
- COMPREPLY[0]=$comp
- else # Format the descriptions
+ COMPREPLY[0]=$(printf "%%q" "${COMPREPLY[0]%%%%$tab*}")
+ __%[1]s_debug "Removed description from single completion, which is now: ${COMPREPLY[0]}"
+ else
+ # Format the descriptions
__%[1]s_format_comp_descriptions $longest
fi
}
diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go
index e0b0947b..d9cd2414 100644
--- a/vendor/github.com/spf13/cobra/cobra.go
+++ b/vendor/github.com/spf13/cobra/cobra.go
@@ -176,12 +176,16 @@ func rpad(s string, padding int) string {
return fmt.Sprintf(formattedString, s)
}
-// tmpl executes the given template text on data, writing the result to w.
-func tmpl(w io.Writer, text string, data interface{}) error {
- t := template.New("top")
- t.Funcs(templateFuncs)
- template.Must(t.Parse(text))
- return t.Execute(w, data)
+func tmpl(text string) *tmplFunc {
+ return &tmplFunc{
+ tmpl: text,
+ fn: func(w io.Writer, data interface{}) error {
+ t := template.New("top")
+ t.Funcs(templateFuncs)
+ template.Must(t.Parse(text))
+ return t.Execute(w, data)
+ },
+ }
}
// ld compares two strings and returns the levenshtein distance between them.
diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go
index 54748fc6..78088db6 100644
--- a/vendor/github.com/spf13/cobra/command.go
+++ b/vendor/github.com/spf13/cobra/command.go
@@ -33,10 +33,13 @@ import (
const (
FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra"
CommandDisplayNameAnnotation = "cobra_annotation_command_display_name"
+
+ helpFlagName = "help"
+ helpCommandName = "help"
)
// FParseErrWhitelist configures Flag parse errors to be ignored
-type FParseErrWhitelist flag.ParseErrorsWhitelist
+type FParseErrWhitelist flag.ParseErrorsAllowlist
// Group Structure to manage groups for commands
type Group struct {
@@ -80,11 +83,11 @@ type Command struct {
Example string
// ValidArgs is list of all valid non-flag arguments that are accepted in shell completions
- ValidArgs []string
+ ValidArgs []Completion
// ValidArgsFunction is an optional function that provides valid non-flag arguments for shell completion.
// It is a dynamic version of using ValidArgs.
// Only one of ValidArgs and ValidArgsFunction can be used for a command.
- ValidArgsFunction func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
+ ValidArgsFunction CompletionFunc
// Expected arguments
Args PositionalArgs
@@ -168,12 +171,12 @@ type Command struct {
// usageFunc is usage func defined by user.
usageFunc func(*Command) error
// usageTemplate is usage template defined by user.
- usageTemplate string
+ usageTemplate *tmplFunc
// flagErrorFunc is func defined by user and it's called when the parsing of
// flags returns an error.
flagErrorFunc func(*Command, error) error
// helpTemplate is help template defined by user.
- helpTemplate string
+ helpTemplate *tmplFunc
// helpFunc is help func defined by user.
helpFunc func(*Command, []string)
// helpCommand is command with usage 'help'. If it's not defined by user,
@@ -186,7 +189,7 @@ type Command struct {
completionCommandGroupID string
// versionTemplate is the version template defined by user.
- versionTemplate string
+ versionTemplate *tmplFunc
// errPrefix is the error message prefix defined by user.
errPrefix string
@@ -281,6 +284,7 @@ func (c *Command) SetArgs(a []string) {
// SetOutput sets the destination for usage and error messages.
// If output is nil, os.Stderr is used.
+//
// Deprecated: Use SetOut and/or SetErr instead
func (c *Command) SetOutput(output io.Writer) {
c.outWriter = output
@@ -312,7 +316,11 @@ func (c *Command) SetUsageFunc(f func(*Command) error) {
// SetUsageTemplate sets usage template. Can be defined by Application.
func (c *Command) SetUsageTemplate(s string) {
- c.usageTemplate = s
+ if s == "" {
+ c.usageTemplate = nil
+ return
+ }
+ c.usageTemplate = tmpl(s)
}
// SetFlagErrorFunc sets a function to generate an error when flag parsing
@@ -348,12 +356,20 @@ func (c *Command) SetCompletionCommandGroupID(groupID string) {
// SetHelpTemplate sets help template to be used. Application can use it to set custom template.
func (c *Command) SetHelpTemplate(s string) {
- c.helpTemplate = s
+ if s == "" {
+ c.helpTemplate = nil
+ return
+ }
+ c.helpTemplate = tmpl(s)
}
// SetVersionTemplate sets version template to be used. Application can use it to set custom template.
func (c *Command) SetVersionTemplate(s string) {
- c.versionTemplate = s
+ if s == "" {
+ c.versionTemplate = nil
+ return
+ }
+ c.versionTemplate = tmpl(s)
}
// SetErrPrefix sets error message prefix to be used. Application can use it to set custom prefix.
@@ -434,7 +450,8 @@ func (c *Command) UsageFunc() (f func(*Command) error) {
}
return func(c *Command) error {
c.mergePersistentFlags()
- err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c)
+ fn := c.getUsageTemplateFunc()
+ err := fn(c.OutOrStderr(), c)
if err != nil {
c.PrintErrln(err)
}
@@ -442,6 +459,19 @@ func (c *Command) UsageFunc() (f func(*Command) error) {
}
}
+// getUsageTemplateFunc returns the usage template function for the command
+// going up the command tree if necessary.
+func (c *Command) getUsageTemplateFunc() func(w io.Writer, data interface{}) error {
+ if c.usageTemplate != nil {
+ return c.usageTemplate.fn
+ }
+
+ if c.HasParent() {
+ return c.parent.getUsageTemplateFunc()
+ }
+ return defaultUsageFunc
+}
+
// Usage puts out the usage for the command.
// Used when a user provides invalid input.
// Can be defined by user by overriding UsageFunc.
@@ -460,15 +490,30 @@ func (c *Command) HelpFunc() func(*Command, []string) {
}
return func(c *Command, a []string) {
c.mergePersistentFlags()
+ fn := c.getHelpTemplateFunc()
// The help should be sent to stdout
// See https://github.com/spf13/cobra/issues/1002
- err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
+ err := fn(c.OutOrStdout(), c)
if err != nil {
c.PrintErrln(err)
}
}
}
+// getHelpTemplateFunc returns the help template function for the command
+// going up the command tree if necessary.
+func (c *Command) getHelpTemplateFunc() func(w io.Writer, data interface{}) error {
+ if c.helpTemplate != nil {
+ return c.helpTemplate.fn
+ }
+
+ if c.HasParent() {
+ return c.parent.getHelpTemplateFunc()
+ }
+
+ return defaultHelpFunc
+}
+
// Help puts out the help for the command.
// Used when a user calls help [command].
// Can be defined by user by overriding HelpFunc.
@@ -543,71 +588,55 @@ func (c *Command) NamePadding() int {
}
// UsageTemplate returns usage template for the command.
+// This function is kept for backwards-compatibility reasons.
func (c *Command) UsageTemplate() string {
- if c.usageTemplate != "" {
- return c.usageTemplate
+ if c.usageTemplate != nil {
+ return c.usageTemplate.tmpl
}
if c.HasParent() {
return c.parent.UsageTemplate()
}
- return `Usage:{{if .Runnable}}
- {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
- {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}
-
-Aliases:
- {{.NameAndAliases}}{{end}}{{if .HasExample}}
-
-Examples:
-{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}}
-
-Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
- {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}}
-
-{{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}}
- {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}}
-
-Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}}
- {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
-
-Flags:
-{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
-
-Global Flags:
-{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
-
-Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
- {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
-
-Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
-`
+ return defaultUsageTemplate
}
// HelpTemplate return help template for the command.
+// This function is kept for backwards-compatibility reasons.
func (c *Command) HelpTemplate() string {
- if c.helpTemplate != "" {
- return c.helpTemplate
+ if c.helpTemplate != nil {
+ return c.helpTemplate.tmpl
}
if c.HasParent() {
return c.parent.HelpTemplate()
}
- return `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}}
-
-{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
+ return defaultHelpTemplate
}
// VersionTemplate return version template for the command.
+// This function is kept for backwards-compatibility reasons.
func (c *Command) VersionTemplate() string {
- if c.versionTemplate != "" {
- return c.versionTemplate
+ if c.versionTemplate != nil {
+ return c.versionTemplate.tmpl
}
if c.HasParent() {
return c.parent.VersionTemplate()
}
- return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}
-`
+ return defaultVersionTemplate
+}
+
+// getVersionTemplateFunc returns the version template function for the command
+// going up the command tree if necessary.
+func (c *Command) getVersionTemplateFunc() func(w io.Writer, data interface{}) error {
+ if c.versionTemplate != nil {
+ return c.versionTemplate.fn
+ }
+
+ if c.HasParent() {
+ return c.parent.getVersionTemplateFunc()
+ }
+ return defaultVersionFunc
}
// ErrPrefix return error message prefix for the command
@@ -894,7 +923,7 @@ func (c *Command) execute(a []string) (err error) {
// If help is called, regardless of other flags, return we want help.
// Also say we need help if the command isn't runnable.
- helpVal, err := c.Flags().GetBool("help")
+ helpVal, err := c.Flags().GetBool(helpFlagName)
if err != nil {
// should be impossible to get here as we always declare a help
// flag in InitDefaultHelpFlag()
@@ -914,7 +943,8 @@ func (c *Command) execute(a []string) (err error) {
return err
}
if versionVal {
- err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c)
+ fn := c.getVersionTemplateFunc()
+ err := fn(c.OutOrStdout(), c)
if err != nil {
c.Println(err)
}
@@ -1068,12 +1098,6 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
// initialize help at the last point to allow for user overriding
c.InitDefaultHelpCmd()
- // initialize completion at the last point to allow for user overriding
- c.InitDefaultCompletionCmd()
-
- // Now that all commands have been created, let's make sure all groups
- // are properly created also
- c.checkCommandGroups()
args := c.args
@@ -1082,9 +1106,16 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
args = os.Args[1:]
}
- // initialize the hidden command to be used for shell completion
+ // initialize the __complete command to be used for shell completion
c.initCompleteCmd(args)
+ // initialize the default completion command
+ c.InitDefaultCompletionCmd(args...)
+
+ // Now that all commands have been created, let's make sure all groups
+ // are properly created also
+ c.checkCommandGroups()
+
var flags []string
if c.TraverseChildren {
cmd, flags, err = c.Traverse(args)
@@ -1187,16 +1218,16 @@ func (c *Command) checkCommandGroups() {
// If c already has help flag, it will do nothing.
func (c *Command) InitDefaultHelpFlag() {
c.mergePersistentFlags()
- if c.Flags().Lookup("help") == nil {
+ if c.Flags().Lookup(helpFlagName) == nil {
usage := "help for "
- name := c.displayName()
+ name := c.DisplayName()
if name == "" {
usage += "this command"
} else {
usage += name
}
- c.Flags().BoolP("help", "h", false, usage)
- _ = c.Flags().SetAnnotation("help", FlagSetByCobraAnnotation, []string{"true"})
+ c.Flags().BoolP(helpFlagName, "h", false, usage)
+ _ = c.Flags().SetAnnotation(helpFlagName, FlagSetByCobraAnnotation, []string{"true"})
}
}
@@ -1215,7 +1246,7 @@ func (c *Command) InitDefaultVersionFlag() {
if c.Name() == "" {
usage += "this command"
} else {
- usage += c.Name()
+ usage += c.DisplayName()
}
if c.Flags().ShorthandLookup("v") == nil {
c.Flags().BoolP("version", "v", false, usage)
@@ -1239,9 +1270,9 @@ func (c *Command) InitDefaultHelpCmd() {
Use: "help [command]",
Short: "Help about any command",
Long: `Help provides help for any command in the application.
-Simply type ` + c.displayName() + ` help [path to command] for full details.`,
- ValidArgsFunction: func(c *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
- var completions []string
+Simply type ` + c.DisplayName() + ` help [path to command] for full details.`,
+ ValidArgsFunction: func(c *Command, args []string, toComplete string) ([]Completion, ShellCompDirective) {
+ var completions []Completion
cmd, _, e := c.Root().Find(args)
if e != nil {
return nil, ShellCompDirectiveNoFileComp
@@ -1253,7 +1284,7 @@ Simply type ` + c.displayName() + ` help [path to command] for full details.`,
for _, subCmd := range cmd.Commands() {
if subCmd.IsAvailableCommand() || subCmd == cmd.helpCommand {
if strings.HasPrefix(subCmd.Name(), toComplete) {
- completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short))
+ completions = append(completions, CompletionWithDesc(subCmd.Name(), subCmd.Short))
}
}
}
@@ -1265,6 +1296,11 @@ Simply type ` + c.displayName() + ` help [path to command] for full details.`,
c.Printf("Unknown help topic %#q\n", args)
CheckErr(c.Root().Usage())
} else {
+ // FLow the context down to be used in help text
+ if cmd.ctx == nil {
+ cmd.ctx = c.ctx
+ }
+
cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown
cmd.InitDefaultVersionFlag() // make possible 'version' flag to be shown
CheckErr(cmd.Help())
@@ -1430,10 +1466,12 @@ func (c *Command) CommandPath() string {
if c.HasParent() {
return c.Parent().CommandPath() + " " + c.Name()
}
- return c.displayName()
+ return c.DisplayName()
}
-func (c *Command) displayName() string {
+// DisplayName returns the name to display in help text. Returns command Name()
+// If CommandDisplayNameAnnoation is not set
+func (c *Command) DisplayName() string {
if displayName, ok := c.Annotations[CommandDisplayNameAnnotation]; ok {
return displayName
}
@@ -1443,7 +1481,7 @@ func (c *Command) displayName() string {
// UseLine puts out the full usage for a given command (including parents).
func (c *Command) UseLine() string {
var useline string
- use := strings.Replace(c.Use, c.Name(), c.displayName(), 1)
+ use := strings.Replace(c.Use, c.Name(), c.DisplayName(), 1)
if c.HasParent() {
useline = c.parent.CommandPath() + " " + use
} else {
@@ -1649,7 +1687,7 @@ func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) f
// to this command (local and persistent declared here and by all parents).
func (c *Command) Flags() *flag.FlagSet {
if c.flags == nil {
- c.flags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError)
+ c.flags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
if c.flagErrorBuf == nil {
c.flagErrorBuf = new(bytes.Buffer)
}
@@ -1664,7 +1702,7 @@ func (c *Command) Flags() *flag.FlagSet {
func (c *Command) LocalNonPersistentFlags() *flag.FlagSet {
persistentFlags := c.PersistentFlags()
- out := flag.NewFlagSet(c.displayName(), flag.ContinueOnError)
+ out := flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
c.LocalFlags().VisitAll(func(f *flag.Flag) {
if persistentFlags.Lookup(f.Name) == nil {
out.AddFlag(f)
@@ -1679,7 +1717,7 @@ func (c *Command) LocalFlags() *flag.FlagSet {
c.mergePersistentFlags()
if c.lflags == nil {
- c.lflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError)
+ c.lflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
if c.flagErrorBuf == nil {
c.flagErrorBuf = new(bytes.Buffer)
}
@@ -1707,7 +1745,7 @@ func (c *Command) InheritedFlags() *flag.FlagSet {
c.mergePersistentFlags()
if c.iflags == nil {
- c.iflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError)
+ c.iflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
if c.flagErrorBuf == nil {
c.flagErrorBuf = new(bytes.Buffer)
}
@@ -1736,7 +1774,7 @@ func (c *Command) NonInheritedFlags() *flag.FlagSet {
// PersistentFlags returns the persistent FlagSet specifically set in the current command.
func (c *Command) PersistentFlags() *flag.FlagSet {
if c.pflags == nil {
- c.pflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError)
+ c.pflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
if c.flagErrorBuf == nil {
c.flagErrorBuf = new(bytes.Buffer)
}
@@ -1749,9 +1787,9 @@ func (c *Command) PersistentFlags() *flag.FlagSet {
func (c *Command) ResetFlags() {
c.flagErrorBuf = new(bytes.Buffer)
c.flagErrorBuf.Reset()
- c.flags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError)
+ c.flags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
c.flags.SetOutput(c.flagErrorBuf)
- c.pflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError)
+ c.pflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
c.pflags.SetOutput(c.flagErrorBuf)
c.lflags = nil
@@ -1839,7 +1877,7 @@ func (c *Command) ParseFlags(args []string) error {
c.mergePersistentFlags()
// do it here after merging all flags and just before parse
- c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)
+ c.Flags().ParseErrorsAllowlist = flag.ParseErrorsAllowlist(c.FParseErrWhitelist)
err := c.Flags().Parse(args)
// Print warnings if they occurred (e.g. deprecated flag messages).
@@ -1868,7 +1906,7 @@ func (c *Command) mergePersistentFlags() {
// If c.parentsPflags == nil, it makes new.
func (c *Command) updateParentsPflags() {
if c.parentsPflags == nil {
- c.parentsPflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError)
+ c.parentsPflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError)
c.parentsPflags.SetOutput(c.flagErrorBuf)
c.parentsPflags.SortFlags = false
}
@@ -1894,3 +1932,141 @@ func commandNameMatches(s string, t string) bool {
return s == t
}
+
+// tmplFunc holds a template and a function that will execute said template.
+type tmplFunc struct {
+ tmpl string
+ fn func(io.Writer, interface{}) error
+}
+
+var defaultUsageTemplate = `Usage:{{if .Runnable}}
+ {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
+ {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}
+
+Aliases:
+ {{.NameAndAliases}}{{end}}{{if .HasExample}}
+
+Examples:
+{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}}
+
+Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}}
+
+{{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}}
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}}
+
+Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}}
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
+
+Flags:
+{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
+
+Global Flags:
+{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
+
+Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
+ {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
+
+Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
+`
+
+// defaultUsageFunc is equivalent to executing defaultUsageTemplate. The two should be changed in sync.
+func defaultUsageFunc(w io.Writer, in interface{}) error {
+ c := in.(*Command)
+ fmt.Fprint(w, "Usage:")
+ if c.Runnable() {
+ fmt.Fprintf(w, "\n %s", c.UseLine())
+ }
+ if c.HasAvailableSubCommands() {
+ fmt.Fprintf(w, "\n %s [command]", c.CommandPath())
+ }
+ if len(c.Aliases) > 0 {
+ fmt.Fprintf(w, "\n\nAliases:\n")
+ fmt.Fprintf(w, " %s", c.NameAndAliases())
+ }
+ if c.HasExample() {
+ fmt.Fprintf(w, "\n\nExamples:\n")
+ fmt.Fprintf(w, "%s", c.Example)
+ }
+ if c.HasAvailableSubCommands() {
+ cmds := c.Commands()
+ if len(c.Groups()) == 0 {
+ fmt.Fprintf(w, "\n\nAvailable Commands:")
+ for _, subcmd := range cmds {
+ if subcmd.IsAvailableCommand() || subcmd.Name() == helpCommandName {
+ fmt.Fprintf(w, "\n %s %s", rpad(subcmd.Name(), subcmd.NamePadding()), subcmd.Short)
+ }
+ }
+ } else {
+ for _, group := range c.Groups() {
+ fmt.Fprintf(w, "\n\n%s", group.Title)
+ for _, subcmd := range cmds {
+ if subcmd.GroupID == group.ID && (subcmd.IsAvailableCommand() || subcmd.Name() == helpCommandName) {
+ fmt.Fprintf(w, "\n %s %s", rpad(subcmd.Name(), subcmd.NamePadding()), subcmd.Short)
+ }
+ }
+ }
+ if !c.AllChildCommandsHaveGroup() {
+ fmt.Fprintf(w, "\n\nAdditional Commands:")
+ for _, subcmd := range cmds {
+ if subcmd.GroupID == "" && (subcmd.IsAvailableCommand() || subcmd.Name() == helpCommandName) {
+ fmt.Fprintf(w, "\n %s %s", rpad(subcmd.Name(), subcmd.NamePadding()), subcmd.Short)
+ }
+ }
+ }
+ }
+ }
+ if c.HasAvailableLocalFlags() {
+ fmt.Fprintf(w, "\n\nFlags:\n")
+ fmt.Fprint(w, trimRightSpace(c.LocalFlags().FlagUsages()))
+ }
+ if c.HasAvailableInheritedFlags() {
+ fmt.Fprintf(w, "\n\nGlobal Flags:\n")
+ fmt.Fprint(w, trimRightSpace(c.InheritedFlags().FlagUsages()))
+ }
+ if c.HasHelpSubCommands() {
+ fmt.Fprintf(w, "\n\nAdditional help topics:")
+ for _, subcmd := range c.Commands() {
+ if subcmd.IsAdditionalHelpTopicCommand() {
+ fmt.Fprintf(w, "\n %s %s", rpad(subcmd.CommandPath(), subcmd.CommandPathPadding()), subcmd.Short)
+ }
+ }
+ }
+ if c.HasAvailableSubCommands() {
+ fmt.Fprintf(w, "\n\nUse \"%s [command] --help\" for more information about a command.", c.CommandPath())
+ }
+ fmt.Fprintln(w)
+ return nil
+}
+
+var defaultHelpTemplate = `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}}
+
+{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
+
+// defaultHelpFunc is equivalent to executing defaultHelpTemplate. The two should be changed in sync.
+func defaultHelpFunc(w io.Writer, in interface{}) error {
+ c := in.(*Command)
+ usage := c.Long
+ if usage == "" {
+ usage = c.Short
+ }
+ usage = trimRightSpace(usage)
+ if usage != "" {
+ fmt.Fprintln(w, usage)
+ fmt.Fprintln(w)
+ }
+ if c.Runnable() || c.HasSubCommands() {
+ fmt.Fprint(w, c.UsageString())
+ }
+ return nil
+}
+
+var defaultVersionTemplate = `{{with .DisplayName}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}
+`
+
+// defaultVersionFunc is equivalent to executing defaultVersionTemplate. The two should be changed in sync.
+func defaultVersionFunc(w io.Writer, in interface{}) error {
+ c := in.(*Command)
+ _, err := fmt.Fprintf(w, "%s version %s\n", c.DisplayName(), c.Version)
+ return err
+}
diff --git a/vendor/github.com/spf13/cobra/completions.go b/vendor/github.com/spf13/cobra/completions.go
index c0c08b05..d3607c2d 100644
--- a/vendor/github.com/spf13/cobra/completions.go
+++ b/vendor/github.com/spf13/cobra/completions.go
@@ -35,7 +35,7 @@ const (
)
// Global map of flag completion functions. Make sure to use flagCompletionMutex before you try to read and write from it.
-var flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){}
+var flagCompletionFunctions = map[*pflag.Flag]CompletionFunc{}
// lock for reading and writing from flagCompletionFunctions
var flagCompletionMutex = &sync.RWMutex{}
@@ -115,24 +115,59 @@ type CompletionOptions struct {
DisableDescriptions bool
// HiddenDefaultCmd makes the default 'completion' command hidden
HiddenDefaultCmd bool
+ // DefaultShellCompDirective sets the ShellCompDirective that is returned
+ // if no special directive can be determined
+ DefaultShellCompDirective *ShellCompDirective
+}
+
+func (receiver *CompletionOptions) SetDefaultShellCompDirective(directive ShellCompDirective) {
+ receiver.DefaultShellCompDirective = &directive
+}
+
+// Completion is a string that can be used for completions
+//
+// two formats are supported:
+// - the completion choice
+// - the completion choice with a textual description (separated by a TAB).
+//
+// [CompletionWithDesc] can be used to create a completion string with a textual description.
+//
+// Note: Go type alias is used to provide a more descriptive name in the documentation, but any string can be used.
+type Completion = string
+
+// CompletionFunc is a function that provides completion results.
+type CompletionFunc = func(cmd *Command, args []string, toComplete string) ([]Completion, ShellCompDirective)
+
+// CompletionWithDesc returns a [Completion] with a description by using the TAB delimited format.
+func CompletionWithDesc(choice string, description string) Completion {
+ return choice + "\t" + description
}
// NoFileCompletions can be used to disable file completion for commands that should
// not trigger file completions.
-func NoFileCompletions(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
+//
+// This method satisfies [CompletionFunc].
+// It can be used with [Command.RegisterFlagCompletionFunc] and for [Command.ValidArgsFunction].
+func NoFileCompletions(cmd *Command, args []string, toComplete string) ([]Completion, ShellCompDirective) {
return nil, ShellCompDirectiveNoFileComp
}
// FixedCompletions can be used to create a completion function which always
// returns the same results.
-func FixedCompletions(choices []string, directive ShellCompDirective) func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
- return func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
+//
+// This method returns a function that satisfies [CompletionFunc]
+// It can be used with [Command.RegisterFlagCompletionFunc] and for [Command.ValidArgsFunction].
+func FixedCompletions(choices []Completion, directive ShellCompDirective) CompletionFunc {
+ return func(cmd *Command, args []string, toComplete string) ([]Completion, ShellCompDirective) {
return choices, directive
}
}
// RegisterFlagCompletionFunc should be called to register a function to provide completion for a flag.
-func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)) error {
+//
+// You can use pre-defined completion functions such as [FixedCompletions] or [NoFileCompletions],
+// or you can define your own.
+func (c *Command) RegisterFlagCompletionFunc(flagName string, f CompletionFunc) error {
flag := c.Flag(flagName)
if flag == nil {
return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' does not exist", flagName)
@@ -148,7 +183,7 @@ func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Comman
}
// GetFlagCompletionFunc returns the completion function for the given flag of the command, if available.
-func (c *Command) GetFlagCompletionFunc(flagName string) (func(*Command, []string, string) ([]string, ShellCompDirective), bool) {
+func (c *Command) GetFlagCompletionFunc(flagName string) (CompletionFunc, bool) {
flag := c.Flag(flagName)
if flag == nil {
return nil, false
@@ -270,7 +305,15 @@ func (c *Command) initCompleteCmd(args []string) {
}
}
-func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDirective, error) {
+// SliceValue is a reduced version of [pflag.SliceValue]. It is used to detect
+// flags that accept multiple values and therefore can provide completion
+// multiple times.
+type SliceValue interface {
+ // GetSlice returns the flag value list as an array of strings.
+ GetSlice() []string
+}
+
+func (c *Command) getCompletions(args []string) (*Command, []Completion, ShellCompDirective, error) {
// The last argument, which is not completely typed by the user,
// should not be part of the list of arguments
toComplete := args[len(args)-1]
@@ -298,7 +341,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
}
if err != nil {
// Unable to find the real command. E.g., someInvalidCmd
- return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("unable to find a command for arguments: %v", trimmedArgs)
+ return c, []Completion{}, ShellCompDirectiveDefault, fmt.Errorf("unable to find a command for arguments: %v", trimmedArgs)
}
finalCmd.ctx = c.ctx
@@ -328,7 +371,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
// Parse the flags early so we can check if required flags are set
if err = finalCmd.ParseFlags(finalArgs); err != nil {
- return finalCmd, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Error while parsing flags from args %v: %s", finalArgs, err.Error())
+ return finalCmd, []Completion{}, ShellCompDirectiveDefault, fmt.Errorf("Error while parsing flags from args %v: %s", finalArgs, err.Error())
}
realArgCount := finalCmd.Flags().NArg()
@@ -339,15 +382,15 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
// Error while attempting to parse flags
if flagErr != nil {
// If error type is flagCompError and we don't want flagCompletion we should ignore the error
- if _, ok := flagErr.(*flagCompError); !(ok && !flagCompletion) {
- return finalCmd, []string{}, ShellCompDirectiveDefault, flagErr
+ if _, ok := flagErr.(*flagCompError); !ok || flagCompletion {
+ return finalCmd, []Completion{}, ShellCompDirectiveDefault, flagErr
}
}
// Look for the --help or --version flags. If they are present,
// there should be no further completions.
if helpOrVersionFlagPresent(finalCmd) {
- return finalCmd, []string{}, ShellCompDirectiveNoFileComp, nil
+ return finalCmd, []Completion{}, ShellCompDirectiveNoFileComp, nil
}
// We only remove the flags from the arguments if DisableFlagParsing is not set.
@@ -376,11 +419,11 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
return finalCmd, subDir, ShellCompDirectiveFilterDirs, nil
}
// Directory completion
- return finalCmd, []string{}, ShellCompDirectiveFilterDirs, nil
+ return finalCmd, []Completion{}, ShellCompDirectiveFilterDirs, nil
}
}
- var completions []string
+ var completions []Completion
var directive ShellCompDirective
// Enforce flag groups before doing flag completions
@@ -399,10 +442,14 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
// If we have not found any required flags, only then can we show regular flags
if len(completions) == 0 {
doCompleteFlags := func(flag *pflag.Flag) {
- if !flag.Changed ||
+ _, acceptsMultiple := flag.Value.(SliceValue)
+ acceptsMultiple = acceptsMultiple ||
strings.Contains(flag.Value.Type(), "Slice") ||
- strings.Contains(flag.Value.Type(), "Array") {
- // If the flag is not already present, or if it can be specified multiple times (Array or Slice)
+ strings.Contains(flag.Value.Type(), "Array") ||
+ strings.HasPrefix(flag.Value.Type(), "stringTo")
+
+ if !flag.Changed || acceptsMultiple {
+ // If the flag is not already present, or if it can be specified multiple times (Array, Slice, or stringTo)
// we suggest it as a completion
completions = append(completions, getFlagNameCompletions(flag, toComplete)...)
}
@@ -440,6 +487,14 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
}
} else {
directive = ShellCompDirectiveDefault
+ // check current and parent commands for a custom DefaultShellCompDirective
+ for cmd := finalCmd; cmd != nil; cmd = cmd.parent {
+ if cmd.CompletionOptions.DefaultShellCompDirective != nil {
+ directive = *cmd.CompletionOptions.DefaultShellCompDirective
+ break
+ }
+ }
+
if flag == nil {
foundLocalNonPersistentFlag := false
// If TraverseChildren is true on the root command we don't check for
@@ -462,7 +517,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
for _, subCmd := range finalCmd.Commands() {
if subCmd.IsAvailableCommand() || subCmd == finalCmd.helpCommand {
if strings.HasPrefix(subCmd.Name(), toComplete) {
- completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short))
+ completions = append(completions, CompletionWithDesc(subCmd.Name(), subCmd.Short))
}
directive = ShellCompDirectiveNoFileComp
}
@@ -507,7 +562,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
}
// Find the completion function for the flag or command
- var completionFn func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
+ var completionFn CompletionFunc
if flag != nil && flagCompletion {
flagCompletionMutex.RLock()
completionFn = flagCompletionFunctions[flag]
@@ -518,7 +573,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
if completionFn != nil {
// Go custom completion defined for this flag or command.
// Call the registered completion function to get the completions.
- var comps []string
+ var comps []Completion
comps, directive = completionFn(finalCmd, finalArgs, toComplete)
completions = append(completions, comps...)
}
@@ -531,23 +586,23 @@ func helpOrVersionFlagPresent(cmd *Command) bool {
len(versionFlag.Annotations[FlagSetByCobraAnnotation]) > 0 && versionFlag.Changed {
return true
}
- if helpFlag := cmd.Flags().Lookup("help"); helpFlag != nil &&
+ if helpFlag := cmd.Flags().Lookup(helpFlagName); helpFlag != nil &&
len(helpFlag.Annotations[FlagSetByCobraAnnotation]) > 0 && helpFlag.Changed {
return true
}
return false
}
-func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []string {
+func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []Completion {
if nonCompletableFlag(flag) {
- return []string{}
+ return []Completion{}
}
- var completions []string
+ var completions []Completion
flagName := "--" + flag.Name
if strings.HasPrefix(flagName, toComplete) {
// Flag without the =
- completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage))
+ completions = append(completions, CompletionWithDesc(flagName, flag.Usage))
// Why suggest both long forms: --flag and --flag= ?
// This forces the user to *always* have to type either an = or a space after the flag name.
@@ -559,20 +614,20 @@ func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []string {
// if len(flag.NoOptDefVal) == 0 {
// // Flag requires a value, so it can be suffixed with =
// flagName += "="
- // completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage))
+ // completions = append(completions, CompletionWithDesc(flagName, flag.Usage))
// }
}
flagName = "-" + flag.Shorthand
if len(flag.Shorthand) > 0 && strings.HasPrefix(flagName, toComplete) {
- completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage))
+ completions = append(completions, CompletionWithDesc(flagName, flag.Usage))
}
return completions
}
-func completeRequireFlags(finalCmd *Command, toComplete string) []string {
- var completions []string
+func completeRequireFlags(finalCmd *Command, toComplete string) []Completion {
+ var completions []Completion
doCompleteRequiredFlags := func(flag *pflag.Flag) {
if _, present := flag.Annotations[BashCompOneRequiredFlag]; present {
@@ -687,8 +742,8 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
// 1- the feature has been explicitly disabled by the program,
// 2- c has no subcommands (to avoid creating one),
// 3- c already has a 'completion' command provided by the program.
-func (c *Command) InitDefaultCompletionCmd() {
- if c.CompletionOptions.DisableDefaultCmd || !c.HasSubCommands() {
+func (c *Command) InitDefaultCompletionCmd(args ...string) {
+ if c.CompletionOptions.DisableDefaultCmd {
return
}
@@ -701,6 +756,16 @@ func (c *Command) InitDefaultCompletionCmd() {
haveNoDescFlag := !c.CompletionOptions.DisableNoDescFlag && !c.CompletionOptions.DisableDescriptions
+ // Special case to know if there are sub-commands or not.
+ hasSubCommands := false
+ for _, cmd := range c.commands {
+ if cmd.Name() != ShellCompRequestCmd && cmd.Name() != helpCommandName {
+ // We found a real sub-command (not 'help' or '__complete')
+ hasSubCommands = true
+ break
+ }
+ }
+
completionCmd := &Command{
Use: compCmdName,
Short: "Generate the autocompletion script for the specified shell",
@@ -714,6 +779,22 @@ See each sub-command's help for details on how to use the generated script.
}
c.AddCommand(completionCmd)
+ if !hasSubCommands {
+ // If the 'completion' command will be the only sub-command,
+ // we only create it if it is actually being called.
+ // This avoids breaking programs that would suddenly find themselves with
+ // a subcommand, which would prevent them from accepting arguments.
+ // We also create the 'completion' command if the user is triggering
+ // shell completion for it (prog __complete completion '')
+ subCmd, cmdArgs, err := c.Find(args)
+ if err != nil || subCmd.Name() != compCmdName &&
+ (subCmd.Name() != ShellCompRequestCmd || len(cmdArgs) <= 1 || cmdArgs[0] != compCmdName) {
+ // The completion command is not being called or being completed so we remove it.
+ c.RemoveCommand(completionCmd)
+ return
+ }
+ }
+
out := c.OutOrStdout()
noDesc := c.CompletionOptions.DisableDescriptions
shortDesc := "Generate the autocompletion script for %s"
diff --git a/vendor/github.com/spf13/cobra/powershell_completions.go b/vendor/github.com/spf13/cobra/powershell_completions.go
index a830b7bc..746dcb92 100644
--- a/vendor/github.com/spf13/cobra/powershell_completions.go
+++ b/vendor/github.com/spf13/cobra/powershell_completions.go
@@ -162,7 +162,10 @@ filter __%[1]s_escapeStringWithSpecialChars {
if (-Not $Description) {
$Description = " "
}
- @{Name="$Name";Description="$Description"}
+ New-Object -TypeName PSCustomObject -Property @{
+ Name = "$Name"
+ Description = "$Description"
+ }
}
@@ -240,7 +243,12 @@ filter __%[1]s_escapeStringWithSpecialChars {
__%[1]s_debug "Only one completion left"
# insert space after value
- [System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars) + $Space, "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
+ $CompletionText = $($comp.Name | __%[1]s_escapeStringWithSpecialChars) + $Space
+ if ($ExecutionContext.SessionState.LanguageMode -eq "FullLanguage"){
+ [System.Management.Automation.CompletionResult]::new($CompletionText, "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
+ } else {
+ $CompletionText
+ }
} else {
# Add the proper number of spaces to align the descriptions
@@ -255,7 +263,12 @@ filter __%[1]s_escapeStringWithSpecialChars {
$Description = " ($($comp.Description))"
}
- [System.Management.Automation.CompletionResult]::new("$($comp.Name)$Description", "$($comp.Name)$Description", 'ParameterValue', "$($comp.Description)")
+ $CompletionText = "$($comp.Name)$Description"
+ if ($ExecutionContext.SessionState.LanguageMode -eq "FullLanguage"){
+ [System.Management.Automation.CompletionResult]::new($CompletionText, "$($comp.Name)$Description", 'ParameterValue', "$($comp.Description)")
+ } else {
+ $CompletionText
+ }
}
}
@@ -264,7 +277,13 @@ filter __%[1]s_escapeStringWithSpecialChars {
# insert space after value
# MenuComplete will automatically show the ToolTip of
# the highlighted value at the bottom of the suggestions.
- [System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars) + $Space, "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
+
+ $CompletionText = $($comp.Name | __%[1]s_escapeStringWithSpecialChars) + $Space
+ if ($ExecutionContext.SessionState.LanguageMode -eq "FullLanguage"){
+ [System.Management.Automation.CompletionResult]::new($CompletionText, "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
+ } else {
+ $CompletionText
+ }
}
# TabCompleteNext and in case we get something unknown
@@ -272,7 +291,13 @@ filter __%[1]s_escapeStringWithSpecialChars {
# Like MenuComplete but we don't want to add a space here because
# the user need to press space anyway to get the completion.
# Description will not be shown because that's not possible with TabCompleteNext
- [System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars), "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
+
+ $CompletionText = $($comp.Name | __%[1]s_escapeStringWithSpecialChars)
+ if ($ExecutionContext.SessionState.LanguageMode -eq "FullLanguage"){
+ [System.Management.Automation.CompletionResult]::new($CompletionText, "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
+ } else {
+ $CompletionText
+ }
}
}
diff --git a/vendor/github.com/spf13/pflag/.editorconfig b/vendor/github.com/spf13/pflag/.editorconfig
new file mode 100644
index 00000000..4492e9f9
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/.editorconfig
@@ -0,0 +1,12 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.go]
+indent_style = tab
diff --git a/vendor/github.com/spf13/pflag/.golangci.yaml b/vendor/github.com/spf13/pflag/.golangci.yaml
new file mode 100644
index 00000000..b274f248
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/.golangci.yaml
@@ -0,0 +1,4 @@
+linters:
+ disable-all: true
+ enable:
+ - nolintlint
diff --git a/vendor/github.com/spf13/pflag/README.md b/vendor/github.com/spf13/pflag/README.md
index 7eacc5bd..388c4e5e 100644
--- a/vendor/github.com/spf13/pflag/README.md
+++ b/vendor/github.com/spf13/pflag/README.md
@@ -284,6 +284,33 @@ func main() {
}
```
+### Using pflag with go test
+`pflag` does not parse the shorthand versions of go test's built-in flags (i.e., those starting with `-test.`).
+For more context, see issues [#63](https://github.com/spf13/pflag/issues/63) and [#238](https://github.com/spf13/pflag/issues/238) for more details.
+
+For example, if you use pflag in your `TestMain` function and call `pflag.Parse()` after defining your custom flags, running a test like this:
+```bash
+go test /your/tests -run ^YourTest -v --your-test-pflags
+```
+will result in the `-v` flag being ignored. This happens because of the way pflag handles flag parsing, skipping over go test's built-in shorthand flags.
+To work around this, you can use the `ParseSkippedFlags` function, which ensures that go test's flags are parsed separately using the standard flag package.
+
+**Example**: You want to parse go test flags that are otherwise ignore by `pflag.Parse()`
+```go
+import (
+ goflag "flag"
+ flag "github.com/spf13/pflag"
+)
+
+var ip *int = flag.Int("flagname", 1234, "help message for flagname")
+
+func main() {
+ flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
+ flag.ParseSkippedFlags(os.Args[1:], goflag.CommandLine)
+ flag.Parse()
+}
+```
+
## More info
You can see the full reference documentation of the pflag package
diff --git a/vendor/github.com/spf13/pflag/bool_func.go b/vendor/github.com/spf13/pflag/bool_func.go
new file mode 100644
index 00000000..83d77afa
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/bool_func.go
@@ -0,0 +1,40 @@
+package pflag
+
+// -- func Value
+type boolfuncValue func(string) error
+
+func (f boolfuncValue) Set(s string) error { return f(s) }
+
+func (f boolfuncValue) Type() string { return "boolfunc" }
+
+func (f boolfuncValue) String() string { return "" } // same behavior as stdlib 'flag' package
+
+func (f boolfuncValue) IsBoolFlag() bool { return true }
+
+// BoolFunc defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed
+// on the command line.
+func (f *FlagSet) BoolFunc(name string, usage string, fn func(string) error) {
+ f.BoolFuncP(name, "", usage, fn)
+}
+
+// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) BoolFuncP(name, shorthand string, usage string, fn func(string) error) {
+ var val Value = boolfuncValue(fn)
+ flag := f.VarPF(val, name, shorthand, usage)
+ flag.NoOptDefVal = "true"
+}
+
+// BoolFunc defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed
+// on the command line.
+func BoolFunc(name string, usage string, fn func(string) error) {
+ CommandLine.BoolFuncP(name, "", usage, fn)
+}
+
+// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash.
+func BoolFuncP(name, shorthand string, usage string, fn func(string) error) {
+ CommandLine.BoolFuncP(name, shorthand, usage, fn)
+}
diff --git a/vendor/github.com/spf13/pflag/count.go b/vendor/github.com/spf13/pflag/count.go
index a0b2679f..d49c0143 100644
--- a/vendor/github.com/spf13/pflag/count.go
+++ b/vendor/github.com/spf13/pflag/count.go
@@ -85,7 +85,7 @@ func (f *FlagSet) CountP(name, shorthand string, usage string) *int {
// Count defines a count flag with specified name, default value, and usage string.
// The return value is the address of an int variable that stores the value of the flag.
-// A count flag will add 1 to its value evey time it is found on the command line
+// A count flag will add 1 to its value every time it is found on the command line
func Count(name string, usage string) *int {
return CommandLine.CountP(name, "", usage)
}
diff --git a/vendor/github.com/spf13/pflag/errors.go b/vendor/github.com/spf13/pflag/errors.go
new file mode 100644
index 00000000..ff11b66b
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/errors.go
@@ -0,0 +1,149 @@
+package pflag
+
+import "fmt"
+
+// notExistErrorMessageType specifies which flavor of "flag does not exist"
+// is printed by NotExistError. This allows the related errors to be grouped
+// under a single NotExistError struct without making a breaking change to
+// the error message text.
+type notExistErrorMessageType int
+
+const (
+ flagNotExistMessage notExistErrorMessageType = iota
+ flagNotDefinedMessage
+ flagNoSuchFlagMessage
+ flagUnknownFlagMessage
+ flagUnknownShorthandFlagMessage
+)
+
+// NotExistError is the error returned when trying to access a flag that
+// does not exist in the FlagSet.
+type NotExistError struct {
+ name string
+ specifiedShorthands string
+ messageType notExistErrorMessageType
+}
+
+// Error implements error.
+func (e *NotExistError) Error() string {
+ switch e.messageType {
+ case flagNotExistMessage:
+ return fmt.Sprintf("flag %q does not exist", e.name)
+
+ case flagNotDefinedMessage:
+ return fmt.Sprintf("flag accessed but not defined: %s", e.name)
+
+ case flagNoSuchFlagMessage:
+ return fmt.Sprintf("no such flag -%v", e.name)
+
+ case flagUnknownFlagMessage:
+ return fmt.Sprintf("unknown flag: --%s", e.name)
+
+ case flagUnknownShorthandFlagMessage:
+ c := rune(e.name[0])
+ return fmt.Sprintf("unknown shorthand flag: %q in -%s", c, e.specifiedShorthands)
+ }
+
+ panic(fmt.Errorf("unknown flagNotExistErrorMessageType: %v", e.messageType))
+}
+
+// GetSpecifiedName returns the name of the flag (without dashes) as it
+// appeared in the parsed arguments.
+func (e *NotExistError) GetSpecifiedName() string {
+ return e.name
+}
+
+// GetSpecifiedShortnames returns the group of shorthand arguments
+// (without dashes) that the flag appeared within. If the flag was not in a
+// shorthand group, this will return an empty string.
+func (e *NotExistError) GetSpecifiedShortnames() string {
+ return e.specifiedShorthands
+}
+
+// ValueRequiredError is the error returned when a flag needs an argument but
+// no argument was provided.
+type ValueRequiredError struct {
+ flag *Flag
+ specifiedName string
+ specifiedShorthands string
+}
+
+// Error implements error.
+func (e *ValueRequiredError) Error() string {
+ if len(e.specifiedShorthands) > 0 {
+ c := rune(e.specifiedName[0])
+ return fmt.Sprintf("flag needs an argument: %q in -%s", c, e.specifiedShorthands)
+ }
+
+ return fmt.Sprintf("flag needs an argument: --%s", e.specifiedName)
+}
+
+// GetFlag returns the flag for which the error occurred.
+func (e *ValueRequiredError) GetFlag() *Flag {
+ return e.flag
+}
+
+// GetSpecifiedName returns the name of the flag (without dashes) as it
+// appeared in the parsed arguments.
+func (e *ValueRequiredError) GetSpecifiedName() string {
+ return e.specifiedName
+}
+
+// GetSpecifiedShortnames returns the group of shorthand arguments
+// (without dashes) that the flag appeared within. If the flag was not in a
+// shorthand group, this will return an empty string.
+func (e *ValueRequiredError) GetSpecifiedShortnames() string {
+ return e.specifiedShorthands
+}
+
+// InvalidValueError is the error returned when an invalid value is used
+// for a flag.
+type InvalidValueError struct {
+ flag *Flag
+ value string
+ cause error
+}
+
+// Error implements error.
+func (e *InvalidValueError) Error() string {
+ flag := e.flag
+ var flagName string
+ if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
+ flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
+ } else {
+ flagName = fmt.Sprintf("--%s", flag.Name)
+ }
+ return fmt.Sprintf("invalid argument %q for %q flag: %v", e.value, flagName, e.cause)
+}
+
+// Unwrap implements errors.Unwrap.
+func (e *InvalidValueError) Unwrap() error {
+ return e.cause
+}
+
+// GetFlag returns the flag for which the error occurred.
+func (e *InvalidValueError) GetFlag() *Flag {
+ return e.flag
+}
+
+// GetValue returns the invalid value that was provided.
+func (e *InvalidValueError) GetValue() string {
+ return e.value
+}
+
+// InvalidSyntaxError is the error returned when a bad flag name is passed on
+// the command line.
+type InvalidSyntaxError struct {
+ specifiedFlag string
+}
+
+// Error implements error.
+func (e *InvalidSyntaxError) Error() string {
+ return fmt.Sprintf("bad flag syntax: %s", e.specifiedFlag)
+}
+
+// GetSpecifiedName returns the exact flag (with dashes) as it
+// appeared in the parsed arguments.
+func (e *InvalidSyntaxError) GetSpecifiedFlag() string {
+ return e.specifiedFlag
+}
diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go
index 24a5036e..eeed1e92 100644
--- a/vendor/github.com/spf13/pflag/flag.go
+++ b/vendor/github.com/spf13/pflag/flag.go
@@ -27,23 +27,32 @@ unaffected.
Define flags using flag.String(), Bool(), Int(), etc.
This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
+
var ip = flag.Int("flagname", 1234, "help message for flagname")
+
If you like, you can bind the flag to a variable using the Var() functions.
+
var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}
+
Or you can create custom flags that satisfy the Value interface (with
pointer receivers) and couple them to flag parsing by
+
flag.Var(&flagVal, "name", "help message for flagname")
+
For such flags, the default value is just the initial value of the variable.
After all flags are defined, call
+
flag.Parse()
+
to parse the command line into the defined flags.
Flags may then be used directly. If you're using the flags themselves,
they are all pointers; if you bind to variables, they're values.
+
fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar)
@@ -54,22 +63,26 @@ The arguments are indexed from 0 through flag.NArg()-1.
The pflag package also defines some new functions that are not in flag,
that give one-letter shorthands for flags. You can use these by appending
'P' to the name of any function that defines a flag.
+
var ip = flag.IntP("flagname", "f", 1234, "help message")
var flagvar bool
func init() {
flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
}
flag.VarP(&flagval, "varname", "v", "help message")
+
Shorthand letters can be used with single dashes on the command line.
Boolean shorthand flags can be combined with other shorthand flags.
Command line flag syntax:
+
--flag // boolean flags only
--flag=x
Unlike the flag package, a single dash before an option means something
different than a double dash. Single dashes signify a series of shorthand
letters for flags. All but the last shorthand letter must be boolean flags.
+
// boolean flags
-f
-abc
@@ -124,12 +137,16 @@ const (
PanicOnError
)
-// ParseErrorsWhitelist defines the parsing errors that can be ignored
-type ParseErrorsWhitelist struct {
+// ParseErrorsAllowlist defines the parsing errors that can be ignored
+type ParseErrorsAllowlist struct {
// UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags
UnknownFlags bool
}
+// DEPRECATED: please use ParseErrorsAllowlist instead
+// This type will be removed in a future release
+type ParseErrorsWhitelist = ParseErrorsAllowlist
+
// NormalizedName is a flag name that has been normalized according to rules
// for the FlagSet (e.g. making '-' and '_' equivalent).
type NormalizedName string
@@ -145,8 +162,12 @@ type FlagSet struct {
// help/usage messages.
SortFlags bool
- // ParseErrorsWhitelist is used to configure a whitelist of errors
- ParseErrorsWhitelist ParseErrorsWhitelist
+ // ParseErrorsAllowlist is used to configure an allowlist of errors
+ ParseErrorsAllowlist ParseErrorsAllowlist
+
+ // DEPRECATED: please use ParseErrorsAllowlist instead
+ // This field will be removed in a future release
+ ParseErrorsWhitelist ParseErrorsAllowlist
name string
parsed bool
@@ -160,7 +181,7 @@ type FlagSet struct {
args []string // arguments after flags
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
errorHandling ErrorHandling
- output io.Writer // nil means stderr; use out() accessor
+ output io.Writer // nil means stderr; use Output() accessor
interspersed bool // allow interspersed option/non-option args
normalizeNameFunc func(f *FlagSet, name string) NormalizedName
@@ -255,13 +276,20 @@ func (f *FlagSet) normalizeFlagName(name string) NormalizedName {
return n(f, name)
}
-func (f *FlagSet) out() io.Writer {
+// Output returns the destination for usage and error messages. os.Stderr is returned if
+// output was not set or was set to nil.
+func (f *FlagSet) Output() io.Writer {
if f.output == nil {
return os.Stderr
}
return f.output
}
+// Name returns the name of the flag set.
+func (f *FlagSet) Name() string {
+ return f.name
+}
+
// SetOutput sets the destination for usage and error messages.
// If output is nil, os.Stderr is used.
func (f *FlagSet) SetOutput(output io.Writer) {
@@ -358,7 +386,7 @@ func (f *FlagSet) ShorthandLookup(name string) *Flag {
}
if len(name) > 1 {
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
- fmt.Fprintf(f.out(), msg)
+ fmt.Fprintf(f.Output(), msg)
panic(msg)
}
c := name[0]
@@ -374,7 +402,7 @@ func (f *FlagSet) lookup(name NormalizedName) *Flag {
func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) {
flag := f.Lookup(name)
if flag == nil {
- err := fmt.Errorf("flag accessed but not defined: %s", name)
+ err := &NotExistError{name: name, messageType: flagNotDefinedMessage}
return nil, err
}
@@ -404,7 +432,7 @@ func (f *FlagSet) ArgsLenAtDash() int {
func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
flag := f.Lookup(name)
if flag == nil {
- return fmt.Errorf("flag %q does not exist", name)
+ return &NotExistError{name: name, messageType: flagNotExistMessage}
}
if usageMessage == "" {
return fmt.Errorf("deprecated message for flag %q must be set", name)
@@ -420,7 +448,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error {
flag := f.Lookup(name)
if flag == nil {
- return fmt.Errorf("flag %q does not exist", name)
+ return &NotExistError{name: name, messageType: flagNotExistMessage}
}
if usageMessage == "" {
return fmt.Errorf("deprecated message for flag %q must be set", name)
@@ -434,7 +462,7 @@ func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) erro
func (f *FlagSet) MarkHidden(name string) error {
flag := f.Lookup(name)
if flag == nil {
- return fmt.Errorf("flag %q does not exist", name)
+ return &NotExistError{name: name, messageType: flagNotExistMessage}
}
flag.Hidden = true
return nil
@@ -457,18 +485,16 @@ func (f *FlagSet) Set(name, value string) error {
normalName := f.normalizeFlagName(name)
flag, ok := f.formal[normalName]
if !ok {
- return fmt.Errorf("no such flag -%v", name)
+ return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
}
err := flag.Value.Set(value)
if err != nil {
- var flagName string
- if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
- flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
- } else {
- flagName = fmt.Sprintf("--%s", flag.Name)
+ return &InvalidValueError{
+ flag: flag,
+ value: value,
+ cause: err,
}
- return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err)
}
if !flag.Changed {
@@ -482,7 +508,7 @@ func (f *FlagSet) Set(name, value string) error {
}
if flag.Deprecated != "" {
- fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
+ fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
}
return nil
}
@@ -494,7 +520,7 @@ func (f *FlagSet) SetAnnotation(name, key string, values []string) error {
normalName := f.normalizeFlagName(name)
flag, ok := f.formal[normalName]
if !ok {
- return fmt.Errorf("no such flag -%v", name)
+ return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
}
if flag.Annotations == nil {
flag.Annotations = map[string][]string{}
@@ -523,7 +549,7 @@ func Set(name, value string) error {
// otherwise, the default values of all defined flags in the set.
func (f *FlagSet) PrintDefaults() {
usages := f.FlagUsages()
- fmt.Fprint(f.out(), usages)
+ fmt.Fprint(f.Output(), usages)
}
// defaultIsZeroValue returns true if the default value for this flag represents
@@ -531,7 +557,7 @@ func (f *FlagSet) PrintDefaults() {
func (f *Flag) defaultIsZeroValue() bool {
switch f.Value.(type) {
case boolFlag:
- return f.DefValue == "false"
+ return f.DefValue == "false" || f.DefValue == ""
case *durationValue:
// Beginning in Go 1.7, duration zero values are "0s"
return f.DefValue == "0" || f.DefValue == "0s"
@@ -544,7 +570,7 @@ func (f *Flag) defaultIsZeroValue() bool {
case *intSliceValue, *stringSliceValue, *stringArrayValue:
return f.DefValue == "[]"
default:
- switch f.Value.String() {
+ switch f.DefValue {
case "false":
return true
case "":
@@ -581,8 +607,10 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
name = flag.Value.Type()
switch name {
- case "bool":
+ case "bool", "boolfunc":
name = ""
+ case "func":
+ name = "value"
case "float64":
name = "float"
case "int64":
@@ -700,7 +728,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
switch flag.Value.Type() {
case "string":
line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
- case "bool":
+ case "bool", "boolfunc":
if flag.NoOptDefVal != "true" {
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
}
@@ -758,7 +786,7 @@ func PrintDefaults() {
// defaultUsage is the default function to print a usage message.
func defaultUsage(f *FlagSet) {
- fmt.Fprintf(f.out(), "Usage of %s:\n", f.name)
+ fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)
f.PrintDefaults()
}
@@ -844,7 +872,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
_, alreadyThere := f.formal[normalizedFlagName]
if alreadyThere {
msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
- fmt.Fprintln(f.out(), msg)
+ fmt.Fprintln(f.Output(), msg)
panic(msg) // Happens only if flags are declared with identical names
}
if f.formal == nil {
@@ -860,7 +888,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
}
if len(flag.Shorthand) > 1 {
msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
- fmt.Fprintf(f.out(), msg)
+ fmt.Fprintf(f.Output(), msg)
panic(msg)
}
if f.shorthands == nil {
@@ -870,7 +898,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
used, alreadyThere := f.shorthands[c]
if alreadyThere {
msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
- fmt.Fprintf(f.out(), msg)
+ fmt.Fprintf(f.Output(), msg)
panic(msg)
}
f.shorthands[c] = flag
@@ -904,12 +932,10 @@ func VarP(value Value, name, shorthand, usage string) {
CommandLine.VarP(value, name, shorthand, usage)
}
-// failf prints to standard error a formatted error and usage message and
+// fail prints an error message and usage message to standard error and
// returns the error.
-func (f *FlagSet) failf(format string, a ...interface{}) error {
- err := fmt.Errorf(format, a...)
+func (f *FlagSet) fail(err error) error {
if f.errorHandling != ContinueOnError {
- fmt.Fprintln(f.out(), err)
f.usage()
}
return err
@@ -927,9 +953,9 @@ func (f *FlagSet) usage() {
}
}
-//--unknown (args will be empty)
-//--unknown --next-flag ... (args will be --next-flag ...)
-//--unknown arg ... (args will be arg ...)
+// --unknown (args will be empty)
+// --unknown --next-flag ... (args will be --next-flag ...)
+// --unknown arg ... (args will be arg ...)
func stripUnknownFlagValue(args []string) []string {
if len(args) == 0 {
//--unknown
@@ -953,7 +979,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
a = args
name := s[2:]
if len(name) == 0 || name[0] == '-' || name[0] == '=' {
- err = f.failf("bad flag syntax: %s", s)
+ err = f.fail(&InvalidSyntaxError{specifiedFlag: s})
return
}
@@ -967,6 +993,8 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
f.usage()
return a, ErrHelp
case f.ParseErrorsWhitelist.UnknownFlags:
+ fallthrough
+ case f.ParseErrorsAllowlist.UnknownFlags:
// --unknown=unknownval arg ...
// we do not want to lose arg in this case
if len(split) >= 2 {
@@ -975,7 +1003,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
return stripUnknownFlagValue(a), nil
default:
- err = f.failf("unknown flag: --%s", name)
+ err = f.fail(&NotExistError{name: name, messageType: flagUnknownFlagMessage})
return
}
}
@@ -993,13 +1021,16 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
a = a[1:]
} else {
// '--flag' (arg was required)
- err = f.failf("flag needs an argument: %s", s)
+ err = f.fail(&ValueRequiredError{
+ flag: flag,
+ specifiedName: name,
+ })
return
}
err = fn(flag, value)
if err != nil {
- f.failf(err.Error())
+ f.fail(err)
}
return
}
@@ -1007,7 +1038,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
outArgs = args
- if strings.HasPrefix(shorthands, "test.") {
+ if isGotestShorthandFlag(shorthands) {
return
}
@@ -1022,6 +1053,8 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
err = ErrHelp
return
case f.ParseErrorsWhitelist.UnknownFlags:
+ fallthrough
+ case f.ParseErrorsAllowlist.UnknownFlags:
// '-f=arg arg ...'
// we do not want to lose arg in this case
if len(shorthands) > 2 && shorthands[1] == '=' {
@@ -1032,7 +1065,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
outArgs = stripUnknownFlagValue(outArgs)
return
default:
- err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
+ err = f.fail(&NotExistError{
+ name: string(c),
+ specifiedShorthands: shorthands,
+ messageType: flagUnknownShorthandFlagMessage,
+ })
return
}
}
@@ -1055,17 +1092,21 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
outArgs = args[1:]
} else {
// '-f' (arg was required)
- err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
+ err = f.fail(&ValueRequiredError{
+ flag: flag,
+ specifiedName: string(c),
+ specifiedShorthands: shorthands,
+ })
return
}
if flag.ShorthandDeprecated != "" {
- fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
+ fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
}
err = fn(flag, value)
if err != nil {
- f.failf(err.Error())
+ f.fail(err)
}
return
}
@@ -1128,12 +1169,12 @@ func (f *FlagSet) Parse(arguments []string) error {
}
f.parsed = true
- if len(arguments) < 0 {
+ f.args = make([]string, 0, len(arguments))
+
+ if len(arguments) == 0 {
return nil
}
- f.args = make([]string, 0, len(arguments))
-
set := func(flag *Flag, value string) error {
return f.Set(flag.Name, value)
}
@@ -1144,7 +1185,10 @@ func (f *FlagSet) Parse(arguments []string) error {
case ContinueOnError:
return err
case ExitOnError:
- fmt.Println(err)
+ if errors.Is(err, ErrHelp) {
+ os.Exit(0)
+ }
+ fmt.Fprintln(f.Output(), err)
os.Exit(2)
case PanicOnError:
panic(err)
@@ -1170,6 +1214,10 @@ func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string)
case ContinueOnError:
return err
case ExitOnError:
+ if errors.Is(err, ErrHelp) {
+ os.Exit(0)
+ }
+ fmt.Fprintln(f.Output(), err)
os.Exit(2)
case PanicOnError:
panic(err)
diff --git a/vendor/github.com/spf13/pflag/func.go b/vendor/github.com/spf13/pflag/func.go
new file mode 100644
index 00000000..9f4d88f2
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/func.go
@@ -0,0 +1,37 @@
+package pflag
+
+// -- func Value
+type funcValue func(string) error
+
+func (f funcValue) Set(s string) error { return f(s) }
+
+func (f funcValue) Type() string { return "func" }
+
+func (f funcValue) String() string { return "" } // same behavior as stdlib 'flag' package
+
+// Func defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}={value}" (or equivalent) is
+// parsed on the command line, with "{value}" as an argument.
+func (f *FlagSet) Func(name string, usage string, fn func(string) error) {
+ f.FuncP(name, "", usage, fn)
+}
+
+// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) FuncP(name string, shorthand string, usage string, fn func(string) error) {
+ var val Value = funcValue(fn)
+ f.VarP(val, name, shorthand, usage)
+}
+
+// Func defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}={value}" (or equivalent) is
+// parsed on the command line, with "{value}" as an argument.
+func Func(name string, usage string, fn func(string) error) {
+ CommandLine.FuncP(name, "", usage, fn)
+}
+
+// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash.
+func FuncP(name, shorthand string, usage string, fn func(string) error) {
+ CommandLine.FuncP(name, shorthand, usage, fn)
+}
diff --git a/vendor/github.com/spf13/pflag/golangflag.go b/vendor/github.com/spf13/pflag/golangflag.go
index d3dd72b7..e62eab53 100644
--- a/vendor/github.com/spf13/pflag/golangflag.go
+++ b/vendor/github.com/spf13/pflag/golangflag.go
@@ -8,8 +8,18 @@ import (
goflag "flag"
"reflect"
"strings"
+ "time"
)
+// go test flags prefixes
+func isGotestFlag(flag string) bool {
+ return strings.HasPrefix(flag, "-test.")
+}
+
+func isGotestShorthandFlag(flag string) bool {
+ return strings.HasPrefix(flag, "test.")
+}
+
// flagValueWrapper implements pflag.Value around a flag.Value. The main
// difference here is the addition of the Type method that returns a string
// name of the type. As this is generally unknown, we approximate that with
@@ -103,3 +113,49 @@ func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) {
}
f.addedGoFlagSets = append(f.addedGoFlagSets, newSet)
}
+
+// CopyToGoFlagSet will add all current flags to the given Go flag set.
+// Deprecation remarks get copied into the usage description.
+// Whenever possible, a flag gets added for which Go flags shows
+// a proper type in the help message.
+func (f *FlagSet) CopyToGoFlagSet(newSet *goflag.FlagSet) {
+ f.VisitAll(func(flag *Flag) {
+ usage := flag.Usage
+ if flag.Deprecated != "" {
+ usage += " (DEPRECATED: " + flag.Deprecated + ")"
+ }
+
+ switch value := flag.Value.(type) {
+ case *stringValue:
+ newSet.StringVar((*string)(value), flag.Name, flag.DefValue, usage)
+ case *intValue:
+ newSet.IntVar((*int)(value), flag.Name, *(*int)(value), usage)
+ case *int64Value:
+ newSet.Int64Var((*int64)(value), flag.Name, *(*int64)(value), usage)
+ case *uintValue:
+ newSet.UintVar((*uint)(value), flag.Name, *(*uint)(value), usage)
+ case *uint64Value:
+ newSet.Uint64Var((*uint64)(value), flag.Name, *(*uint64)(value), usage)
+ case *durationValue:
+ newSet.DurationVar((*time.Duration)(value), flag.Name, *(*time.Duration)(value), usage)
+ case *float64Value:
+ newSet.Float64Var((*float64)(value), flag.Name, *(*float64)(value), usage)
+ default:
+ newSet.Var(flag.Value, flag.Name, usage)
+ }
+ })
+}
+
+// ParseSkippedFlags explicitly Parses go test flags (i.e. the one starting with '-test.') with goflag.Parse(),
+// since by default those are skipped by pflag.Parse().
+// Typical usage example: `ParseGoTestFlags(os.Args[1:], goflag.CommandLine)`
+func ParseSkippedFlags(osArgs []string, goFlagSet *goflag.FlagSet) error {
+ var skippedFlags []string
+ for _, f := range osArgs {
+ if isGotestFlag(f) {
+ skippedFlags = append(skippedFlags, f)
+ }
+ }
+ return goFlagSet.Parse(skippedFlags)
+}
+
diff --git a/vendor/github.com/spf13/pflag/ip.go b/vendor/github.com/spf13/pflag/ip.go
index 3d414ba6..06b8bcb5 100644
--- a/vendor/github.com/spf13/pflag/ip.go
+++ b/vendor/github.com/spf13/pflag/ip.go
@@ -16,6 +16,9 @@ func newIPValue(val net.IP, p *net.IP) *ipValue {
func (i *ipValue) String() string { return net.IP(*i).String() }
func (i *ipValue) Set(s string) error {
+ if s == "" {
+ return nil
+ }
ip := net.ParseIP(strings.TrimSpace(s))
if ip == nil {
return fmt.Errorf("failed to parse IP: %q", s)
diff --git a/vendor/github.com/spf13/pflag/ipnet_slice.go b/vendor/github.com/spf13/pflag/ipnet_slice.go
new file mode 100644
index 00000000..c6e89da1
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/ipnet_slice.go
@@ -0,0 +1,147 @@
+package pflag
+
+import (
+ "fmt"
+ "io"
+ "net"
+ "strings"
+)
+
+// -- ipNetSlice Value
+type ipNetSliceValue struct {
+ value *[]net.IPNet
+ changed bool
+}
+
+func newIPNetSliceValue(val []net.IPNet, p *[]net.IPNet) *ipNetSliceValue {
+ ipnsv := new(ipNetSliceValue)
+ ipnsv.value = p
+ *ipnsv.value = val
+ return ipnsv
+}
+
+// Set converts, and assigns, the comma-separated IPNet argument string representation as the []net.IPNet value of this flag.
+// If Set is called on a flag that already has a []net.IPNet assigned, the newly converted values will be appended.
+func (s *ipNetSliceValue) Set(val string) error {
+
+ // remove all quote characters
+ rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
+
+ // read flag arguments with CSV parser
+ ipNetStrSlice, err := readAsCSV(rmQuote.Replace(val))
+ if err != nil && err != io.EOF {
+ return err
+ }
+
+ // parse ip values into slice
+ out := make([]net.IPNet, 0, len(ipNetStrSlice))
+ for _, ipNetStr := range ipNetStrSlice {
+ _, n, err := net.ParseCIDR(strings.TrimSpace(ipNetStr))
+ if err != nil {
+ return fmt.Errorf("invalid string being converted to CIDR: %s", ipNetStr)
+ }
+ out = append(out, *n)
+ }
+
+ if !s.changed {
+ *s.value = out
+ } else {
+ *s.value = append(*s.value, out...)
+ }
+
+ s.changed = true
+
+ return nil
+}
+
+// Type returns a string that uniquely represents this flag's type.
+func (s *ipNetSliceValue) Type() string {
+ return "ipNetSlice"
+}
+
+// String defines a "native" format for this net.IPNet slice flag value.
+func (s *ipNetSliceValue) String() string {
+
+ ipNetStrSlice := make([]string, len(*s.value))
+ for i, n := range *s.value {
+ ipNetStrSlice[i] = n.String()
+ }
+
+ out, _ := writeAsCSV(ipNetStrSlice)
+ return "[" + out + "]"
+}
+
+func ipNetSliceConv(val string) (interface{}, error) {
+ val = strings.Trim(val, "[]")
+ // Empty string would cause a slice with one (empty) entry
+ if len(val) == 0 {
+ return []net.IPNet{}, nil
+ }
+ ss := strings.Split(val, ",")
+ out := make([]net.IPNet, len(ss))
+ for i, sval := range ss {
+ _, n, err := net.ParseCIDR(strings.TrimSpace(sval))
+ if err != nil {
+ return nil, fmt.Errorf("invalid string being converted to CIDR: %s", sval)
+ }
+ out[i] = *n
+ }
+ return out, nil
+}
+
+// GetIPNetSlice returns the []net.IPNet value of a flag with the given name
+func (f *FlagSet) GetIPNetSlice(name string) ([]net.IPNet, error) {
+ val, err := f.getFlagType(name, "ipNetSlice", ipNetSliceConv)
+ if err != nil {
+ return []net.IPNet{}, err
+ }
+ return val.([]net.IPNet), nil
+}
+
+// IPNetSliceVar defines a ipNetSlice flag with specified name, default value, and usage string.
+// The argument p points to a []net.IPNet variable in which to store the value of the flag.
+func (f *FlagSet) IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) {
+ f.VarP(newIPNetSliceValue(value, p), name, "", usage)
+}
+
+// IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) {
+ f.VarP(newIPNetSliceValue(value, p), name, shorthand, usage)
+}
+
+// IPNetSliceVar defines a []net.IPNet flag with specified name, default value, and usage string.
+// The argument p points to a []net.IPNet variable in which to store the value of the flag.
+func IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) {
+ CommandLine.VarP(newIPNetSliceValue(value, p), name, "", usage)
+}
+
+// IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) {
+ CommandLine.VarP(newIPNetSliceValue(value, p), name, shorthand, usage)
+}
+
+// IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string.
+// The return value is the address of a []net.IPNet variable that stores the value of that flag.
+func (f *FlagSet) IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet {
+ p := []net.IPNet{}
+ f.IPNetSliceVarP(&p, name, "", value, usage)
+ return &p
+}
+
+// IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet {
+ p := []net.IPNet{}
+ f.IPNetSliceVarP(&p, name, shorthand, value, usage)
+ return &p
+}
+
+// IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string.
+// The return value is the address of a []net.IP variable that stores the value of the flag.
+func IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet {
+ return CommandLine.IPNetSliceP(name, "", value, usage)
+}
+
+// IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash.
+func IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet {
+ return CommandLine.IPNetSliceP(name, shorthand, value, usage)
+}
diff --git a/vendor/github.com/spf13/pflag/string_array.go b/vendor/github.com/spf13/pflag/string_array.go
index 4894af81..d1ff0a96 100644
--- a/vendor/github.com/spf13/pflag/string_array.go
+++ b/vendor/github.com/spf13/pflag/string_array.go
@@ -31,11 +31,7 @@ func (s *stringArrayValue) Append(val string) error {
func (s *stringArrayValue) Replace(val []string) error {
out := make([]string, len(val))
for i, d := range val {
- var err error
out[i] = d
- if err != nil {
- return err
- }
}
*s.value = out
return nil
diff --git a/vendor/github.com/spf13/pflag/string_to_string.go b/vendor/github.com/spf13/pflag/string_to_string.go
index 890a01af..1d1e3bf9 100644
--- a/vendor/github.com/spf13/pflag/string_to_string.go
+++ b/vendor/github.com/spf13/pflag/string_to_string.go
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/csv"
"fmt"
+ "sort"
"strings"
)
@@ -62,8 +63,15 @@ func (s *stringToStringValue) Type() string {
}
func (s *stringToStringValue) String() string {
+ keys := make([]string, 0, len(*s.value))
+ for k := range *s.value {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+
records := make([]string, 0, len(*s.value)>>1)
- for k, v := range *s.value {
+ for _, k := range keys {
+ v := (*s.value)[k]
records = append(records, k+"="+v)
}
diff --git a/vendor/github.com/spf13/pflag/text.go b/vendor/github.com/spf13/pflag/text.go
new file mode 100644
index 00000000..886d5a3d
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/text.go
@@ -0,0 +1,81 @@
+package pflag
+
+import (
+ "encoding"
+ "fmt"
+ "reflect"
+)
+
+// following is copied from go 1.23.4 flag.go
+type textValue struct{ p encoding.TextUnmarshaler }
+
+func newTextValue(val encoding.TextMarshaler, p encoding.TextUnmarshaler) textValue {
+ ptrVal := reflect.ValueOf(p)
+ if ptrVal.Kind() != reflect.Ptr {
+ panic("variable value type must be a pointer")
+ }
+ defVal := reflect.ValueOf(val)
+ if defVal.Kind() == reflect.Ptr {
+ defVal = defVal.Elem()
+ }
+ if defVal.Type() != ptrVal.Type().Elem() {
+ panic(fmt.Sprintf("default type does not match variable type: %v != %v", defVal.Type(), ptrVal.Type().Elem()))
+ }
+ ptrVal.Elem().Set(defVal)
+ return textValue{p}
+}
+
+func (v textValue) Set(s string) error {
+ return v.p.UnmarshalText([]byte(s))
+}
+
+func (v textValue) Get() interface{} {
+ return v.p
+}
+
+func (v textValue) String() string {
+ if m, ok := v.p.(encoding.TextMarshaler); ok {
+ if b, err := m.MarshalText(); err == nil {
+ return string(b)
+ }
+ }
+ return ""
+}
+
+//end of copy
+
+func (v textValue) Type() string {
+ return reflect.ValueOf(v.p).Type().Name()
+}
+
+// GetText set out, which implements encoding.UnmarshalText, to the value of a flag with given name
+func (f *FlagSet) GetText(name string, out encoding.TextUnmarshaler) error {
+ flag := f.Lookup(name)
+ if flag == nil {
+ return fmt.Errorf("flag accessed but not defined: %s", name)
+ }
+ if flag.Value.Type() != reflect.TypeOf(out).Name() {
+ return fmt.Errorf("trying to get %s value of flag of type %s", reflect.TypeOf(out).Name(), flag.Value.Type())
+ }
+ return out.UnmarshalText([]byte(flag.Value.String()))
+}
+
+// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p.
+func (f *FlagSet) TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
+ f.VarP(newTextValue(value, p), name, "", usage)
+}
+
+// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) {
+ f.VarP(newTextValue(value, p), name, shorthand, usage)
+}
+
+// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p.
+func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
+ CommandLine.VarP(newTextValue(value, p), name, "", usage)
+}
+
+// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash.
+func TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) {
+ CommandLine.VarP(newTextValue(value, p), name, shorthand, usage)
+}
diff --git a/vendor/github.com/spf13/pflag/time.go b/vendor/github.com/spf13/pflag/time.go
new file mode 100644
index 00000000..3dee4247
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/time.go
@@ -0,0 +1,124 @@
+package pflag
+
+import (
+ "fmt"
+ "strings"
+ "time"
+)
+
+// TimeValue adapts time.Time for use as a flag.
+type timeValue struct {
+ *time.Time
+ formats []string
+}
+
+func newTimeValue(val time.Time, p *time.Time, formats []string) *timeValue {
+ *p = val
+ return &timeValue{
+ Time: p,
+ formats: formats,
+ }
+}
+
+// Set time.Time value from string based on accepted formats.
+func (d *timeValue) Set(s string) error {
+ s = strings.TrimSpace(s)
+ for _, f := range d.formats {
+ v, err := time.Parse(f, s)
+ if err != nil {
+ continue
+ }
+ *d.Time = v
+ return nil
+ }
+
+ formatsString := ""
+ for i, f := range d.formats {
+ if i > 0 {
+ formatsString += ", "
+ }
+ formatsString += fmt.Sprintf("`%s`", f)
+ }
+
+ return fmt.Errorf("invalid time format `%s` must be one of: %s", s, formatsString)
+}
+
+// Type name for time.Time flags.
+func (d *timeValue) Type() string {
+ return "time"
+}
+
+func (d *timeValue) String() string {
+ if d.Time.IsZero() {
+ return ""
+ } else {
+ return d.Time.Format(time.RFC3339Nano)
+ }
+}
+
+// GetTime return the time value of a flag with the given name
+func (f *FlagSet) GetTime(name string) (time.Time, error) {
+ flag := f.Lookup(name)
+ if flag == nil {
+ err := fmt.Errorf("flag accessed but not defined: %s", name)
+ return time.Time{}, err
+ }
+
+ if flag.Value.Type() != "time" {
+ err := fmt.Errorf("trying to get %s value of flag of type %s", "time", flag.Value.Type())
+ return time.Time{}, err
+ }
+
+ val, ok := flag.Value.(*timeValue)
+ if !ok {
+ return time.Time{}, fmt.Errorf("value %s is not a time", flag.Value)
+ }
+
+ return *val.Time, nil
+}
+
+// TimeVar defines a time.Time flag with specified name, default value, and usage string.
+// The argument p points to a time.Time variable in which to store the value of the flag.
+func (f *FlagSet) TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) {
+ f.TimeVarP(p, name, "", value, formats, usage)
+}
+
+// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) {
+ f.VarP(newTimeValue(value, p, formats), name, shorthand, usage)
+}
+
+// TimeVar defines a time.Time flag with specified name, default value, and usage string.
+// The argument p points to a time.Time variable in which to store the value of the flag.
+func TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) {
+ CommandLine.TimeVarP(p, name, "", value, formats, usage)
+}
+
+// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash.
+func TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) {
+ CommandLine.VarP(newTimeValue(value, p, formats), name, shorthand, usage)
+}
+
+// Time defines a time.Time flag with specified name, default value, and usage string.
+// The return value is the address of a time.Time variable that stores the value of the flag.
+func (f *FlagSet) Time(name string, value time.Time, formats []string, usage string) *time.Time {
+ return f.TimeP(name, "", value, formats, usage)
+}
+
+// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time {
+ p := new(time.Time)
+ f.TimeVarP(p, name, shorthand, value, formats, usage)
+ return p
+}
+
+// Time defines a time.Time flag with specified name, default value, and usage string.
+// The return value is the address of a time.Time variable that stores the value of the flag.
+func Time(name string, value time.Time, formats []string, usage string) *time.Time {
+ return CommandLine.TimeP(name, "", value, formats, usage)
+}
+
+// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash.
+func TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time {
+ return CommandLine.TimeP(name, shorthand, value, formats, usage)
+}
diff --git a/vendor/golang.org/x/mod/sumdb/dirhash/hash.go b/vendor/golang.org/x/mod/sumdb/dirhash/hash.go
index 51ec4db8..117985ac 100644
--- a/vendor/golang.org/x/mod/sumdb/dirhash/hash.go
+++ b/vendor/golang.org/x/mod/sumdb/dirhash/hash.go
@@ -16,7 +16,7 @@ import (
"io"
"os"
"path/filepath"
- "sort"
+ "slices"
"strings"
)
@@ -36,7 +36,7 @@ type Hash func(files []string, open func(string) (io.ReadCloser, error)) (string
// sha256sum $(find . -type f | sort) | sha256sum
//
// More precisely, the hashed summary contains a single line for each file in the list,
-// ordered by sort.Strings applied to the file names, where each line consists of
+// ordered by [slices.Sort] applied to the file names, where each line consists of
// the hexadecimal SHA-256 hash of the file content,
// two spaces (U+0020), the file name, and a newline (U+000A).
//
@@ -44,7 +44,7 @@ type Hash func(files []string, open func(string) (io.ReadCloser, error)) (string
func Hash1(files []string, open func(string) (io.ReadCloser, error)) (string, error) {
h := sha256.New()
files = append([]string(nil), files...)
- sort.Strings(files)
+ slices.Sort(files)
for _, file := range files {
if strings.Contains(file, "\n") {
return "", errors.New("dirhash: filenames with newlines are not supported")
diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go
index 948a3ee6..cfafed5b 100644
--- a/vendor/golang.org/x/sync/errgroup/errgroup.go
+++ b/vendor/golang.org/x/sync/errgroup/errgroup.go
@@ -12,13 +12,15 @@ package errgroup
import (
"context"
"fmt"
+ "runtime"
+ "runtime/debug"
"sync"
)
type token struct{}
// A Group is a collection of goroutines working on subtasks that are part of
-// the same overall task.
+// the same overall task. A Group should not be reused for different tasks.
//
// A zero Group is valid, has no limit on the number of active goroutines,
// and does not cancel on error.
@@ -31,6 +33,10 @@ type Group struct {
errOnce sync.Once
err error
+
+ mu sync.Mutex
+ panicValue any // = PanicError | PanicValue; non-nil if some Group.Go goroutine panicked.
+ abnormal bool // some Group.Go goroutine terminated abnormally (panic or goexit).
}
func (g *Group) done() {
@@ -46,36 +52,84 @@ func (g *Group) done() {
// returns a non-nil error or the first time Wait returns, whichever occurs
// first.
func WithContext(ctx context.Context) (*Group, context.Context) {
- ctx, cancel := withCancelCause(ctx)
+ ctx, cancel := context.WithCancelCause(ctx)
return &Group{cancel: cancel}, ctx
}
-// Wait blocks until all function calls from the Go method have returned, then
-// returns the first non-nil error (if any) from them.
+// Wait blocks until all function calls from the Go method have returned
+// normally, then returns the first non-nil error (if any) from them.
+//
+// If any of the calls panics, Wait panics with a [PanicValue];
+// and if any of them calls [runtime.Goexit], Wait calls runtime.Goexit.
func (g *Group) Wait() error {
g.wg.Wait()
if g.cancel != nil {
g.cancel(g.err)
}
+ if g.panicValue != nil {
+ panic(g.panicValue)
+ }
+ if g.abnormal {
+ runtime.Goexit()
+ }
return g.err
}
// Go calls the given function in a new goroutine.
+// The first call to Go must happen before a Wait.
// It blocks until the new goroutine can be added without the number of
// active goroutines in the group exceeding the configured limit.
//
-// The first call to return a non-nil error cancels the group's context, if the
-// group was created by calling WithContext. The error will be returned by Wait.
+// It blocks until the new goroutine can be added without the number of
+// goroutines in the group exceeding the configured limit.
+//
+// The first goroutine in the group that returns a non-nil error, panics, or
+// invokes [runtime.Goexit] will cancel the associated Context, if any.
func (g *Group) Go(f func() error) {
if g.sem != nil {
g.sem <- token{}
}
+ g.add(f)
+}
+
+func (g *Group) add(f func() error) {
g.wg.Add(1)
go func() {
defer g.done()
+ normalReturn := false
+ defer func() {
+ if normalReturn {
+ return
+ }
+ v := recover()
+ g.mu.Lock()
+ defer g.mu.Unlock()
+ if !g.abnormal {
+ if g.cancel != nil {
+ g.cancel(g.err)
+ }
+ g.abnormal = true
+ }
+ if v != nil && g.panicValue == nil {
+ switch v := v.(type) {
+ case error:
+ g.panicValue = PanicError{
+ Recovered: v,
+ Stack: debug.Stack(),
+ }
+ default:
+ g.panicValue = PanicValue{
+ Recovered: v,
+ Stack: debug.Stack(),
+ }
+ }
+ }
+ }()
- if err := f(); err != nil {
+ err := f()
+ normalReturn = true
+ if err != nil {
g.errOnce.Do(func() {
g.err = err
if g.cancel != nil {
@@ -100,24 +154,13 @@ func (g *Group) TryGo(f func() error) bool {
}
}
- g.wg.Add(1)
- go func() {
- defer g.done()
-
- if err := f(); err != nil {
- g.errOnce.Do(func() {
- g.err = err
- if g.cancel != nil {
- g.cancel(g.err)
- }
- })
- }
- }()
+ g.add(f)
return true
}
// SetLimit limits the number of active goroutines in this group to at most n.
// A negative value indicates no limit.
+// A limit of zero will prevent any new goroutines from being added.
//
// Any subsequent call to the Go method will block until it can add an active
// goroutine without exceeding the configured limit.
@@ -133,3 +176,33 @@ func (g *Group) SetLimit(n int) {
}
g.sem = make(chan token, n)
}
+
+// PanicError wraps an error recovered from an unhandled panic
+// when calling a function passed to Go or TryGo.
+type PanicError struct {
+ Recovered error
+ Stack []byte // result of call to [debug.Stack]
+}
+
+func (p PanicError) Error() string {
+ // A Go Error method conventionally does not include a stack dump, so omit it
+ // here. (Callers who care can extract it from the Stack field.)
+ return fmt.Sprintf("recovered from errgroup.Group: %v", p.Recovered)
+}
+
+func (p PanicError) Unwrap() error { return p.Recovered }
+
+// PanicValue wraps a value that does not implement the error interface,
+// recovered from an unhandled panic when calling a function passed to Go or
+// TryGo.
+type PanicValue struct {
+ Recovered any
+ Stack []byte // result of call to [debug.Stack]
+}
+
+func (p PanicValue) String() string {
+ if len(p.Stack) > 0 {
+ return fmt.Sprintf("recovered from errgroup.Group: %v\n%s", p.Recovered, p.Stack)
+ }
+ return fmt.Sprintf("recovered from errgroup.Group: %v", p.Recovered)
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 7473dff5..30c8b3d7 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -351,7 +351,7 @@ github.com/mxk/go-flowrate/flowrate
# github.com/opencontainers/go-digest v1.0.0
## explicit; go 1.13
github.com/opencontainers/go-digest
-# github.com/opencontainers/image-spec v1.1.0
+# github.com/opencontainers/image-spec v1.1.1
## explicit; go 1.18
github.com/opencontainers/image-spec/specs-go
github.com/opencontainers/image-spec/specs-go/v1
@@ -397,10 +397,10 @@ github.com/sirupsen/logrus
# github.com/spf13/cast v1.7.0
## explicit; go 1.19
github.com/spf13/cast
-# github.com/spf13/cobra v1.8.1
+# github.com/spf13/cobra v1.10.1
## explicit; go 1.15
github.com/spf13/cobra
-# github.com/spf13/pflag v1.0.5
+# github.com/spf13/pflag v1.0.9
## explicit; go 1.12
github.com/spf13/pflag
# github.com/src-d/gcfg v1.4.0
@@ -490,8 +490,8 @@ golang.org/x/crypto/ssh
golang.org/x/crypto/ssh/agent
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
golang.org/x/crypto/ssh/knownhosts
-# golang.org/x/mod v0.22.0
-## explicit; go 1.22.0
+# golang.org/x/mod v0.28.0
+## explicit; go 1.24.0
golang.org/x/mod/sumdb/dirhash
# golang.org/x/net v0.26.0
## explicit; go 1.18
@@ -509,8 +509,8 @@ golang.org/x/net/websocket
## explicit; go 1.18
golang.org/x/oauth2
golang.org/x/oauth2/internal
-# golang.org/x/sync v0.8.0
-## explicit; go 1.18
+# golang.org/x/sync v0.14.0
+## explicit; go 1.23.0
golang.org/x/sync/errgroup
golang.org/x/sync/semaphore
# golang.org/x/sys v0.25.0
@@ -1048,8 +1048,8 @@ oras.land/oras-go/pkg/registry/remote/auth
oras.land/oras-go/pkg/registry/remote/internal/errutil
oras.land/oras-go/pkg/registry/remote/internal/syncutil
oras.land/oras-go/pkg/target
-# oras.land/oras-go/v2 v2.5.0
-## explicit; go 1.21
+# oras.land/oras-go/v2 v2.6.0
+## explicit; go 1.23.0
oras.land/oras-go/v2
oras.land/oras-go/v2/content
oras.land/oras-go/v2/content/file
diff --git a/vendor/oras.land/oras-go/v2/MIGRATION_GUIDE.md b/vendor/oras.land/oras-go/v2/MIGRATION_GUIDE.md
index b9292f14..9a922f5a 100644
--- a/vendor/oras.land/oras-go/v2/MIGRATION_GUIDE.md
+++ b/vendor/oras.land/oras-go/v2/MIGRATION_GUIDE.md
@@ -7,19 +7,21 @@ In version `v2`, ORAS Go library has been completely refreshed with:
- Higher test coverage
- Better documentation
-**Besides, ORAS Go `v2` is now a registry client.**
+**Additionally, ORAS Go `v2` is now a registry client.**
## Major Changes in `v2`
-- Moves `content.FileStore` to [file.Store](https://pkg.go.dev/oras.land/oras-go/v2/content/file#Store)
-- Moves `content.OCIStore` to [oci.Store](https://pkg.go.dev/oras.land/oras-go/v2/content/oci#Store)
-- Moves `content.MemoryStore` to [memory.Store](https://pkg.go.dev/oras.land/oras-go/v2/content/memory#Store)
-- Provides [SDK](https://pkg.go.dev/oras.land/oras-go/v2/registry/remote) to interact with OCI-compliant and Docker-compliant registries
-- Supports [Copy](https://pkg.go.dev/oras.land/oras-go/v2#Copy) with more flexible options
-- Supports [Extended Copy](https://pkg.go.dev/oras.land/oras-go/v2#ExtendedCopy) with options *(experimental)*
-- No longer supports `docker.Login` and `docker.Logout` (removes the dependency on `docker`); instead, provides authentication through [auth.Client](https://pkg.go.dev/oras.land/oras-go/v2/registry/remote/auth#Client)
-
-Documentation and examples are available at [pkg.go.dev](https://pkg.go.dev/oras.land/oras-go/v2).
+- Content store
+ - [`content.File`](https://pkg.go.dev/oras.land/oras-go/pkg/content#File) is now [`file.Store`](https://pkg.go.dev/oras.land/oras-go/v2/content/file#Store)
+ - [`content.OCI`](https://pkg.go.dev/oras.land/oras-go/pkg/content#OCI) is now [`oci.Store`](https://pkg.go.dev/oras.land/oras-go/v2/content/oci#Store)
+ - [`content.Memory`](https://pkg.go.dev/oras.land/oras-go/pkg/content#Memory) is now [`memory.Store`](https://pkg.go.dev/oras.land/oras-go/v2/content/memory#Store)
+- Registry interaction
+ - Introduces an [SDK](https://pkg.go.dev/oras.land/oras-go/v2/registry/remote) to interact with OCI-compliant and Docker-compliant registries
+- Authentication
+ - Implements authentication through [`auth.Client`](https://pkg.go.dev/oras.land/oras-go/v2/registry/remote/auth#Client) and supports credential management via [`credentials`](https://pkg.go.dev/oras.land/oras-go/v2/registry/remote/credentials)
+- Copy operations
+ - Enhances artifact [copying](https://pkg.go.dev/oras.land/oras-go/v2#Copy) capabilities between various [`Target`](https://pkg.go.dev/oras.land/oras-go/v2#Target) with flexible options
+ - Enables [extended-copying](https://pkg.go.dev/oras.land/oras-go/v2#ExtendedCopy) of artifacts along with their predecessors (e.g., referrers)
## Migrating from `v1` to `v2`
@@ -43,3 +45,17 @@ Documentation and examples are available at [pkg.go.dev](https://pkg.go.dev/oras
Since breaking changes are introduced in `v2`, code refactoring is required for migrating from `v1` to `v2`.
The migration can be done in an iterative fashion, as `v1` and `v2` can be imported and used at the same time.
+
+For comprehensive documentation and examples, please refer to [pkg.go.dev](https://pkg.go.dev/oras.land/oras-go/v2).
+
+## FAQs
+
+### Is there a 1:1 mapping of APIs between `v1` and `v2`?
+
+No, `v2` does not have a direct 1:1 mapping of APIs with `v1`, as the structure of the APIs has been significantly redesigned. Instead of looking for a direct replacement, see this as a chance to upgrade your application with `v2`'s new features.
+
+You can explore the [end-to-end examples](https://pkg.go.dev/oras.land/oras-go/v2#pkg-overview) that demonstrate the usage of v2 in practical scenarios.
+
+## Community Support
+
+If you encounter challenges during migration, seek assistance from the community by [submitting GitHub issues](https://github.com/oras-project/oras-go/issues/new) or asking in the [#oras](https://cloud-native.slack.com/archives/CJ1KHJM5Z) Slack channel.
diff --git a/vendor/oras.land/oras-go/v2/README.md b/vendor/oras.land/oras-go/v2/README.md
index 7c3013c7..9224754f 100644
--- a/vendor/oras.land/oras-go/v2/README.md
+++ b/vendor/oras.land/oras-go/v2/README.md
@@ -1,58 +1,66 @@
# ORAS Go library
+[](https://github.com/oras-project/oras-go/actions/workflows/build.yml?query=workflow%3Abuild+event%3Apush+branch%3Amain)
+[](https://codecov.io/gh/oras-project/oras-go)
+[](https://goreportcard.com/report/oras.land/oras-go/v2)
+[](https://pkg.go.dev/oras.land/oras-go/v2)
+
-
+
-## Project status
+`oras-go` is a Go library for managing OCI artifacts, compliant with the [OCI Image Format Specification](https://github.com/opencontainers/image-spec) and the [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec). It provides unified APIs for pushing, pulling, and managing artifacts across OCI-compliant registries, local file systems, and in-memory stores.
-### Versioning
+> [!Note]
+> The `main` branch follows [Go's Security Policy](https://github.com/golang/go/security/policy) and supports the two latest versions of Go (currently `1.23` and `1.24`).
-The ORAS Go library follows [Semantic Versioning](https://semver.org/), where breaking changes are reserved for MAJOR releases, and MINOR and PATCH releases must be 100% backwards compatible.
+## Getting Started
-### v2: stable
+### Concepts
-[](https://github.com/oras-project/oras-go/actions/workflows/build.yml?query=workflow%3Abuild+event%3Apush+branch%3Amain)
-[](https://codecov.io/gh/oras-project/oras-go)
-[](https://goreportcard.com/report/oras.land/oras-go/v2)
-[](https://pkg.go.dev/oras.land/oras-go/v2)
+Gain insights into the fundamental concepts:
-The version `2` is actively developed in the [`main`](https://github.com/oras-project/oras-go/tree/main) branch with all new features.
+- [Modeling Artifacts](docs/Modeling-Artifacts.md)
+- [Targets and Content Stores](docs/Targets.md)
-> [!Note]
-> The `main` branch follows [Go's Security Policy](https://github.com/golang/go/security/policy) and supports the two latest versions of Go (currently `1.21` and `1.22`).
+### Quickstart
+
+Follow the step-by-step tutorial to use `oras-go` v2:
+
+- [Quickstart: Managing OCI Artifacts with `oras-go` v2](docs/tutorial/quickstart.md)
+
+### Examples
+
+Check out sample code for common use cases:
-Examples for common use cases can be found below:
+- [Artifact copying](https://pkg.go.dev/oras.land/oras-go/v2#pkg-examples)
+- [Registry operations](https://pkg.go.dev/oras.land/oras-go/v2/registry#pkg-examples)
+- [Repository operations](https://pkg.go.dev/oras.land/oras-go/v2/registry/remote#pkg-examples)
+- [Authentication](https://pkg.go.dev/oras.land/oras-go/v2/registry/remote/auth#pkg-examples)
+- [Credentials management](https://pkg.go.dev/oras.land/oras-go/v2/registry/remote/credentials#pkg-examples)
-- [Copy examples](https://pkg.go.dev/oras.land/oras-go/v2#pkg-examples)
-- [Registry interaction examples](https://pkg.go.dev/oras.land/oras-go/v2/registry#pkg-examples)
-- [Repository interaction examples](https://pkg.go.dev/oras.land/oras-go/v2/registry/remote#pkg-examples)
-- [Authentication examples](https://pkg.go.dev/oras.land/oras-go/v2/registry/remote/auth#pkg-examples)
+Find more API examples at [pkg.go.dev](https://pkg.go.dev/oras.land/oras-go/v2).
-If you are seeking latest changes, you should use the [`main`](https://github.com/oras-project/oras-go/tree/main) branch (or a specific commit hash) over a tagged version when including the ORAS Go library in your project's `go.mod`.
-The Go Reference for the `main` branch is available [here](https://pkg.go.dev/oras.land/oras-go/v2@main).
-To migrate from `v1` to `v2`, see [MIGRATION_GUIDE.md](./MIGRATION_GUIDE.md).
+## Versioning
-### v1: stable
+This project follows [Semantic Versioning](https://semver.org/) (`MAJOR`.`MINOR`.`PATCH`), with `MAJOR` for breaking changes, `MINOR` for backward-compatible features, and `PATCH` for backward-compatible fixes.
+
+## Previous Major Versions
+
+### v1 (maintenance)
[](https://github.com/oras-project/oras-go/actions/workflows/build.yml?query=workflow%3Abuild+event%3Apush+branch%3Av1)
[](https://goreportcard.com/report/oras.land/oras-go)
[](https://pkg.go.dev/oras.land/oras-go)
-As there are various stable projects depending on the ORAS Go library `v1`, the
-[`v1`](https://github.com/oras-project/oras-go/tree/v1) branch
-is maintained for API stability, dependency updates, and security patches.
-All `v1.*` releases are based upon this branch.
-
-Since `v1` is in a maintenance state, you are highly encouraged
-to use releases with major version `2` for new features.
-
-## Docs
+The [`v1`](https://github.com/oras-project/oras-go/tree/v1) branch is maintained for dependency updates and security fixes only. All feature development happens in the [`main`](https://github.com/oras-project/oras-go/tree/main) branch.
-- [oras.land/client_libraries/go](https://oras.land/docs/Client_Libraries/go): Documentation for the ORAS Go library
-- [Reviewing guide](https://github.com/oras-project/community/blob/main/REVIEWING.md): All reviewers must read the reviewing guide and agree to follow the project review guidelines.
+To migrate from `v1` to `v2`, see [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md).
-## Code of Conduct
+## Community
-This project has adopted the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for further details.
+- Code of Conduct: [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
+- Security Policy: [SECURITY.md](SECURITY.md)
+- Reviewing Guide: [Reviewing Guide](https://github.com/oras-project/community/blob/main/REVIEWING.md)
+- Slack: [`#oras`](https://cloud-native.slack.com/archives/CJ1KHJM5Z) channel on CNCF Slack
diff --git a/vendor/oras.land/oras-go/v2/content/file/file.go b/vendor/oras.land/oras-go/v2/content/file/file.go
index 3f1e8c08..5caaedd0 100644
--- a/vendor/oras.land/oras-go/v2/content/file/file.go
+++ b/vendor/oras.land/oras-go/v2/content/file/file.go
@@ -108,6 +108,9 @@ type Store struct {
// value overrides the [AnnotationUnpack].
// Default value: false.
SkipUnpack bool
+ // PreservePermissions controls whether to preserve file permissions when unpacking,
+ // disregarding the active umask, similar to tar's `--preserve-permissions`
+ PreservePermissions bool
workingDir string // the working directory of the file store
closed int32 // if the store is closed - 0: false, 1: true.
@@ -394,8 +397,9 @@ func (s *Store) Predecessors(ctx context.Context, node ocispec.Descriptor) ([]oc
return s.graph.Predecessors(ctx, node)
}
-// Add adds a file into the file store.
-func (s *Store) Add(_ context.Context, name, mediaType, path string) (ocispec.Descriptor, error) {
+// Add adds a file or a directory into the file store.
+// Hard links within the directory are treated as regular files.
+func (s *Store) Add(ctx context.Context, name, mediaType, path string) (ocispec.Descriptor, error) {
if s.isClosedSet() {
return ocispec.Descriptor{}, ErrStoreClosed
}
@@ -426,7 +430,7 @@ func (s *Store) Add(_ context.Context, name, mediaType, path string) (ocispec.De
// generate descriptor
var desc ocispec.Descriptor
if fi.IsDir() {
- desc, err = s.descriptorFromDir(name, mediaType, path)
+ desc, err = s.descriptorFromDir(ctx, name, mediaType, path)
} else {
desc, err = s.descriptorFromFile(fi, mediaType, path)
}
@@ -498,14 +502,14 @@ func (s *Store) pushDir(name, target string, expected ocispec.Descriptor, conten
checksum := expected.Annotations[AnnotationDigest]
buf := bufPool.Get().(*[]byte)
defer bufPool.Put(buf)
- if err := extractTarGzip(target, name, gzPath, checksum, *buf); err != nil {
+ if err := extractTarGzip(target, name, gzPath, checksum, *buf, s.PreservePermissions); err != nil {
return fmt.Errorf("failed to extract tar to %s: %w", target, err)
}
return nil
}
// descriptorFromDir generates descriptor from the given directory.
-func (s *Store) descriptorFromDir(name, mediaType, dir string) (desc ocispec.Descriptor, err error) {
+func (s *Store) descriptorFromDir(ctx context.Context, name, mediaType, dir string) (desc ocispec.Descriptor, err error) {
// make a temp file to store the gzip
gz, err := s.tempFile()
if err != nil {
@@ -532,7 +536,7 @@ func (s *Store) descriptorFromDir(name, mediaType, dir string) (desc ocispec.Des
tw := io.MultiWriter(gzw, tarDigester.Hash())
buf := bufPool.Get().(*[]byte)
defer bufPool.Put(buf)
- if err := tarDirectory(dir, name, tw, s.TarReproducible, *buf); err != nil {
+ if err := tarDirectory(ctx, dir, name, tw, s.TarReproducible, *buf); err != nil {
return ocispec.Descriptor{}, fmt.Errorf("failed to tar %s: %w", dir, err)
}
diff --git a/vendor/oras.land/oras-go/v2/content/file/utils.go b/vendor/oras.land/oras-go/v2/content/file/utils.go
index c42013d8..bd1f4af1 100644
--- a/vendor/oras.land/oras-go/v2/content/file/utils.go
+++ b/vendor/oras.land/oras-go/v2/content/file/utils.go
@@ -18,9 +18,11 @@ package file
import (
"archive/tar"
"compress/gzip"
+ "context"
"errors"
"fmt"
"io"
+ "io/fs"
"os"
"path/filepath"
"strings"
@@ -31,7 +33,7 @@ import (
// tarDirectory walks the directory specified by path, and tar those files with a new
// path prefix.
-func tarDirectory(root, prefix string, w io.Writer, removeTimes bool, buf []byte) (err error) {
+func tarDirectory(ctx context.Context, root, prefix string, w io.Writer, removeTimes bool, buf []byte) (err error) {
tw := tar.NewWriter(w)
defer func() {
closeErr := tw.Close()
@@ -45,6 +47,12 @@ func tarDirectory(root, prefix string, w io.Writer, removeTimes bool, buf []byte
return err
}
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ default:
+ }
+
// Rename path
name, err := filepath.Rel(root, path)
if err != nil {
@@ -54,6 +62,7 @@ func tarDirectory(root, prefix string, w io.Writer, removeTimes bool, buf []byte
name = filepath.ToSlash(name)
// Generate header
+ // NOTE: We don't support hard links and treat it as regular files
var link string
mode := info.Mode()
if mode&os.ModeSymlink != 0 {
@@ -104,8 +113,8 @@ func tarDirectory(root, prefix string, w io.Writer, removeTimes bool, buf []byte
// extractTarGzip decompresses the gzip
// and extracts tar file to a directory specified by the `dir` parameter.
-func extractTarGzip(dir, prefix, filename, checksum string, buf []byte) (err error) {
- fp, err := os.Open(filename)
+func extractTarGzip(dirPath, dirName, gzPath, checksum string, buf []byte, preservePermissions bool) (err error) {
+ fp, err := os.Open(gzPath)
if err != nil {
return err
}
@@ -135,7 +144,7 @@ func extractTarGzip(dir, prefix, filename, checksum string, buf []byte) (err err
r = io.TeeReader(r, verifier)
}
}
- if err := extractTarDirectory(dir, prefix, r, buf); err != nil {
+ if err := extractTarDirectory(dirPath, dirName, r, buf, preservePermissions); err != nil {
return err
}
if verifier != nil && !verifier.Verified() {
@@ -147,7 +156,7 @@ func extractTarGzip(dir, prefix, filename, checksum string, buf []byte) (err err
// extractTarDirectory extracts tar file to a directory specified by the `dir`
// parameter. The file name prefix is ensured to be the string specified by the
// `prefix` parameter and is trimmed.
-func extractTarDirectory(dir, prefix string, r io.Reader, buf []byte) error {
+func extractTarDirectory(dirPath, dirName string, r io.Reader, buf []byte, preservePermissions bool) error {
tr := tar.NewReader(r)
for {
header, err := tr.Next()
@@ -159,28 +168,43 @@ func extractTarDirectory(dir, prefix string, r io.Reader, buf []byte) error {
}
// Name check
- name := header.Name
- path, err := ensureBasePath(dir, prefix, name)
+ filename := header.Name
+ filePathRel, err := resolveRelToBase(dirPath, dirName, filename)
if err != nil {
return err
}
- path = filepath.Join(dir, path)
+ filePath := filepath.Join(dirPath, filePathRel)
// Create content
switch header.Typeflag {
case tar.TypeReg:
- err = writeFile(path, tr, header.FileInfo().Mode(), buf)
+ err = writeFile(filePath, tr, header.FileInfo().Mode(), buf)
case tar.TypeDir:
- err = os.MkdirAll(path, header.FileInfo().Mode())
+ err = os.MkdirAll(filePath, header.FileInfo().Mode())
case tar.TypeLink:
+ // NOTE: ORAS does not generate hard links when creating tarballs.
+ // If a hard link is found in the tarball, it will be extracted.
+ // If the target link already exists, os.Link will throw an error.
+ // This is a known limitation and will not be addressed.
var target string
- if target, err = ensureLinkPath(dir, prefix, path, header.Linkname); err == nil {
- err = os.Link(target, path)
+ if target, err = ensureLinkPath(dirPath, dirName, filePath, header.Linkname); err == nil {
+ err = os.Link(target, filePath)
}
case tar.TypeSymlink:
var target string
- if target, err = ensureLinkPath(dir, prefix, path, header.Linkname); err == nil {
- err = os.Symlink(target, path)
+ target, err = ensureLinkPath(dirPath, dirName, filePath, header.Linkname)
+ if err != nil {
+ return err
+ }
+ if err = os.Symlink(target, filePath); err != nil {
+ if !errors.Is(err, fs.ErrExist) {
+ return err
+ }
+ // link already exists, remove the old one and try again
+ if err := os.Remove(filePath); err != nil {
+ return err
+ }
+ err = os.Symlink(target, filePath)
}
default:
continue // Non-regular files are skipped
@@ -190,14 +214,21 @@ func extractTarDirectory(dir, prefix string, r io.Reader, buf []byte) error {
}
// Change access time and modification time if possible (error ignored)
- os.Chtimes(path, header.AccessTime, header.ModTime)
+ _ = os.Chtimes(filePath, header.AccessTime, header.ModTime)
+
+ // Restore full mode bits
+ if preservePermissions && (header.Typeflag == tar.TypeReg || header.Typeflag == tar.TypeDir) {
+ if err := os.Chmod(filePath, os.FileMode(header.Mode)); err != nil {
+ return err
+ }
+ }
}
}
-// ensureBasePath ensures the target path is in the base path,
+// resolveRelToBase ensures the target path is in the base path,
// returning its relative path to the base path.
// target can be either an absolute path or a relative path.
-func ensureBasePath(baseAbs, baseRel, target string) (string, error) {
+func resolveRelToBase(baseAbs, baseRel, target string) (string, error) {
base := baseRel
if filepath.IsAbs(target) {
// ensure base and target are consistent
@@ -237,7 +268,7 @@ func ensureLinkPath(baseAbs, baseRel, link, target string) (string, error) {
path = filepath.Join(filepath.Dir(link), target)
}
// ensure path is under baseAbs or baseRel
- if _, err := ensureBasePath(baseAbs, baseRel, path); err != nil {
+ if _, err := resolveRelToBase(baseAbs, baseRel, path); err != nil {
return "", err
}
return target, nil
diff --git a/vendor/oras.land/oras-go/v2/content/reader.go b/vendor/oras.land/oras-go/v2/content/reader.go
index e575378e..37bab5e1 100644
--- a/vendor/oras.land/oras-go/v2/content/reader.go
+++ b/vendor/oras.land/oras-go/v2/content/reader.go
@@ -99,6 +99,11 @@ func (vr *VerifyReader) Verify() error {
// NewVerifyReader wraps r for reading content with verification against desc.
func NewVerifyReader(r io.Reader, desc ocispec.Descriptor) *VerifyReader {
+ if err := desc.Digest.Validate(); err != nil {
+ return &VerifyReader{
+ err: fmt.Errorf("failed to validate %s: %w", desc.Digest, err),
+ }
+ }
verifier := desc.Digest.Verifier()
lr := &io.LimitedReader{
R: io.TeeReader(r, verifier),
diff --git a/vendor/oras.land/oras-go/v2/copy.go b/vendor/oras.land/oras-go/v2/copy.go
index 2f131a8c..2c614694 100644
--- a/vendor/oras.land/oras-go/v2/copy.go
+++ b/vendor/oras.land/oras-go/v2/copy.go
@@ -120,18 +120,21 @@ type CopyGraphOptions struct {
FindSuccessors func(ctx context.Context, fetcher content.Fetcher, desc ocispec.Descriptor) ([]ocispec.Descriptor, error)
}
-// Copy copies a rooted directed acyclic graph (DAG) with the tagged root node
-// in the source Target to the destination Target.
+// Copy copies a rooted directed acyclic graph (DAG), such as an artifact,
+// from the source Target to the destination Target.
+//
+// The root node (e.g. a tagged manifest of the artifact) is identified by the
+// source reference.
// The destination reference will be the same as the source reference if the
// destination reference is left blank.
//
// Returns the descriptor of the root node on successful copy.
func Copy(ctx context.Context, src ReadOnlyTarget, srcRef string, dst Target, dstRef string, opts CopyOptions) (ocispec.Descriptor, error) {
if src == nil {
- return ocispec.Descriptor{}, errors.New("nil source target")
+ return ocispec.Descriptor{}, newCopyError("Copy", CopyErrorOriginSource, errors.New("nil source target"))
}
if dst == nil {
- return ocispec.Descriptor{}, errors.New("nil destination target")
+ return ocispec.Descriptor{}, newCopyError("Copy", CopyErrorOriginDestination, errors.New("nil destination target"))
}
if dstRef == "" {
dstRef = srcRef
@@ -144,14 +147,14 @@ func Copy(ctx context.Context, src ReadOnlyTarget, srcRef string, dst Target, ds
proxy := cas.NewProxyWithLimit(src, cas.NewMemory(), opts.MaxMetadataBytes)
root, err := resolveRoot(ctx, src, srcRef, proxy)
if err != nil {
- return ocispec.Descriptor{}, fmt.Errorf("failed to resolve %s: %w", srcRef, err)
+ return ocispec.Descriptor{}, err
}
if opts.MapRoot != nil {
proxy.StopCaching = true
root, err = opts.MapRoot(ctx, proxy, root)
if err != nil {
- return ocispec.Descriptor{}, err
+ return ocispec.Descriptor{}, newCopyError("MapRoot", CopyErrorOriginSource, err)
}
proxy.StopCaching = false
}
@@ -167,9 +170,16 @@ func Copy(ctx context.Context, src ReadOnlyTarget, srcRef string, dst Target, ds
return root, nil
}
-// CopyGraph copies a rooted directed acyclic graph (DAG) from the source CAS to
-// the destination CAS.
+// CopyGraph copies a rooted directed acyclic graph (DAG), such as an artifact,
+// from the source CAS to the destination CAS.
+// The root node (e.g. a manifest of the artifact) is identified by a descriptor.
func CopyGraph(ctx context.Context, src content.ReadOnlyStorage, dst content.Storage, root ocispec.Descriptor, opts CopyGraphOptions) error {
+ if src == nil {
+ return newCopyError("CopyGraph", CopyErrorOriginSource, errors.New("nil source target"))
+ }
+ if dst == nil {
+ return newCopyError("CopyGraph", CopyErrorOriginDestination, errors.New("nil destination target"))
+ }
return copyGraph(ctx, src, dst, root, nil, nil, nil, opts)
}
@@ -218,7 +228,7 @@ func copyGraph(ctx context.Context, src content.ReadOnlyStorage, dst content.Sto
// skip if a rooted sub-DAG exists
exists, err := dst.Exists(ctx, desc)
if err != nil {
- return err
+ return newCopyError("Exists", CopyErrorOriginDestination, err)
}
if exists {
if opts.OnCopySkipped != nil {
@@ -232,7 +242,7 @@ func copyGraph(ctx context.Context, src content.ReadOnlyStorage, dst content.Sto
// find successors while non-leaf nodes will be fetched and cached
successors, err := opts.FindSuccessors(ctx, proxy, desc)
if err != nil {
- return err
+ return newCopyError("FindSuccessors", CopyErrorOriginSource, err)
}
successors = removeForeignLayers(successors)
@@ -260,7 +270,7 @@ func copyGraph(ctx context.Context, src content.ReadOnlyStorage, dst content.Sto
exists, err = proxy.Cache.Exists(ctx, desc)
if err != nil {
- return err
+ return fmt.Errorf("failed to check cache existence: %s: %w", desc.Digest, err)
}
if exists {
return copyNode(ctx, proxy.Cache, dst, desc, opts)
@@ -320,7 +330,7 @@ func mountOrCopyNode(ctx context.Context, src content.ReadOnlyStorage, dst conte
// Mount or copy
if err := mounter.Mount(ctx, desc, sourceRepository, getContent); err != nil && !errors.Is(err, skipSource) {
- return err
+ return newCopyError("Mount", CopyErrorOriginDestination, err)
}
if !mountFailed {
@@ -348,12 +358,12 @@ func mountOrCopyNode(ctx context.Context, src content.ReadOnlyStorage, dst conte
func doCopyNode(ctx context.Context, src content.ReadOnlyStorage, dst content.Storage, desc ocispec.Descriptor) error {
rc, err := src.Fetch(ctx, desc)
if err != nil {
- return err
+ return newCopyError("Fetch", CopyErrorOriginSource, err)
}
defer rc.Close()
err = dst.Push(ctx, desc, rc)
if err != nil && !errors.Is(err, errdef.ErrAlreadyExists) {
- return err
+ return newCopyError("Push", CopyErrorOriginDestination, err)
}
return nil
}
@@ -385,13 +395,13 @@ func copyNode(ctx context.Context, src content.ReadOnlyStorage, dst content.Stor
func copyCachedNodeWithReference(ctx context.Context, src *cas.Proxy, dst registry.ReferencePusher, desc ocispec.Descriptor, dstRef string) error {
rc, err := src.FetchCached(ctx, desc)
if err != nil {
- return err
+ return newCopyError("Fetch", CopyErrorOriginSource, err)
}
defer rc.Close()
err = dst.PushReference(ctx, desc, rc, dstRef)
if err != nil && !errors.Is(err, errdef.ErrAlreadyExists) {
- return err
+ return newCopyError("PushReference", CopyErrorOriginDestination, err)
}
return nil
}
@@ -400,7 +410,11 @@ func copyCachedNodeWithReference(ctx context.Context, src *cas.Proxy, dst regist
func resolveRoot(ctx context.Context, src ReadOnlyTarget, srcRef string, proxy *cas.Proxy) (ocispec.Descriptor, error) {
refFetcher, ok := src.(registry.ReferenceFetcher)
if !ok {
- return src.Resolve(ctx, srcRef)
+ desc, err := src.Resolve(ctx, srcRef)
+ if err != nil {
+ return ocispec.Descriptor{}, newCopyError("Resolve", CopyErrorOriginSource, err)
+ }
+ return desc, nil
}
// optimize performance for ReferenceFetcher targets
@@ -410,7 +424,7 @@ func resolveRoot(ctx context.Context, src ReadOnlyTarget, srcRef string, proxy *
}
root, rc, err := refProxy.FetchReference(ctx, srcRef)
if err != nil {
- return ocispec.Descriptor{}, err
+ return ocispec.Descriptor{}, newCopyError("FetchReference", CopyErrorOriginSource, err)
}
defer rc.Close()
// cache root if it is a non-leaf node
@@ -421,7 +435,7 @@ func resolveRoot(ctx context.Context, src ReadOnlyTarget, srcRef string, proxy *
return nil, errors.New("fetching only root node expected")
})
if _, err = content.Successors(ctx, fetcher, root); err != nil {
- return ocispec.Descriptor{}, err
+ return ocispec.Descriptor{}, newCopyError("Successors", CopyErrorOriginSource, err)
}
// TODO: optimize special case where root is a leaf node (i.e. a blob)
@@ -430,7 +444,7 @@ func resolveRoot(ctx context.Context, src ReadOnlyTarget, srcRef string, proxy *
}
// prepareCopy prepares the hooks for copy.
-func prepareCopy(ctx context.Context, dst Target, dstRef string, proxy *cas.Proxy, root ocispec.Descriptor, opts *CopyOptions) error {
+func prepareCopy(_ context.Context, dst Target, dstRef string, proxy *cas.Proxy, root ocispec.Descriptor, opts *CopyOptions) error {
if refPusher, ok := dst.(registry.ReferencePusher); ok {
// optimize performance for ReferencePusher targets
preCopy := opts.PreCopy
@@ -463,7 +477,7 @@ func prepareCopy(ctx context.Context, dst Target, dstRef string, proxy *cas.Prox
if content.Equal(desc, root) {
// for root node, tag it after copying it
if err := dst.Tag(ctx, root, dstRef); err != nil {
- return err
+ return newCopyError("Tag", CopyErrorOriginDestination, err)
}
}
if postCopy != nil {
@@ -495,7 +509,10 @@ func prepareCopy(ctx context.Context, dst Target, dstRef string, proxy *cas.Prox
return err
}
}
- return dst.Tag(ctx, root, dstRef)
+ if err := dst.Tag(ctx, root, dstRef); err != nil {
+ return newCopyError("Tag", CopyErrorOriginDestination, err)
+ }
+ return nil
}
return nil
diff --git a/vendor/oras.land/oras-go/v2/copyerror.go b/vendor/oras.land/oras-go/v2/copyerror.go
new file mode 100644
index 00000000..03ed8e24
--- /dev/null
+++ b/vendor/oras.land/oras-go/v2/copyerror.go
@@ -0,0 +1,78 @@
+/*
+Copyright The ORAS Authors.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package oras
+
+import "fmt"
+
+// CopyErrorOrigin defines the source of a copy error.
+type CopyErrorOrigin int
+
+const (
+ // CopyErrorOriginSource indicates the error occurred at the source side.
+ CopyErrorOriginSource CopyErrorOrigin = 1
+
+ // CopyErrorOriginDestination indicates the error occurred at the destination side.
+ CopyErrorOriginDestination CopyErrorOrigin = 2
+)
+
+// String returns the string representation of the CopyErrorOrigin.
+func (o CopyErrorOrigin) String() string {
+ switch o {
+ case CopyErrorOriginSource:
+ return "source"
+ case CopyErrorOriginDestination:
+ return "destination"
+ default:
+ return "unknown"
+ }
+}
+
+// CopyError represents an error encountered during a copy operation.
+type CopyError struct {
+ // Op is the operation that caused the error.
+ Op string
+ // Origin indicates the source of the error.
+ Origin CopyErrorOrigin
+ // Err is the underlying error.
+ Err error
+}
+
+// newCopyError creates a new CopyError.
+func newCopyError(op string, origin CopyErrorOrigin, err error) error {
+ if err == nil {
+ return nil
+ }
+ return &CopyError{
+ Op: op,
+ Origin: origin,
+ Err: err,
+ }
+}
+
+// Error implements the error interface for CopyError.
+func (e *CopyError) Error() string {
+ switch e.Origin {
+ case CopyErrorOriginSource, CopyErrorOriginDestination:
+ return fmt.Sprintf("failed to perform %q on %s: %v", e.Op, e.Origin, e.Err)
+ default:
+ return fmt.Sprintf("failed to perform %q: %v", e.Op, e.Err)
+ }
+}
+
+// Unwrap implements the errors.Unwrap interface for CopyError.
+func (e *CopyError) Unwrap() error {
+ return e.Err
+}
diff --git a/vendor/oras.land/oras-go/v2/extendedcopy.go b/vendor/oras.land/oras-go/v2/extendedcopy.go
index 49b6264e..40f57832 100644
--- a/vendor/oras.land/oras-go/v2/extendedcopy.go
+++ b/vendor/oras.land/oras-go/v2/extendedcopy.go
@@ -65,16 +65,21 @@ type ExtendedCopyGraphOptions struct {
// ExtendedCopy copies the directed acyclic graph (DAG) that are reachable from
// the given tagged node from the source GraphTarget to the destination Target.
+// In other words, it copies a tagged artifact along with its referrers or
+// other predecessor manifests referencing it.
+//
+// The tagged node (e.g. a tagged manifest of the artifact) is identified by the
+// source reference.
// The destination reference will be the same as the source reference if the
// destination reference is left blank.
//
// Returns the descriptor of the tagged node on successful copy.
func ExtendedCopy(ctx context.Context, src ReadOnlyGraphTarget, srcRef string, dst Target, dstRef string, opts ExtendedCopyOptions) (ocispec.Descriptor, error) {
if src == nil {
- return ocispec.Descriptor{}, errors.New("nil source graph target")
+ return ocispec.Descriptor{}, newCopyError("ExtendedCopy", CopyErrorOriginSource, errors.New("nil source target"))
}
if dst == nil {
- return ocispec.Descriptor{}, errors.New("nil destination target")
+ return ocispec.Descriptor{}, newCopyError("ExtendedCopy", CopyErrorOriginDestination, errors.New("nil destination target"))
}
if dstRef == "" {
dstRef = srcRef
@@ -82,7 +87,7 @@ func ExtendedCopy(ctx context.Context, src ReadOnlyGraphTarget, srcRef string, d
node, err := src.Resolve(ctx, srcRef)
if err != nil {
- return ocispec.Descriptor{}, err
+ return ocispec.Descriptor{}, newCopyError("Resolve", CopyErrorOriginSource, err)
}
if err := ExtendedCopyGraph(ctx, src, dst, node, opts.ExtendedCopyGraphOptions); err != nil {
@@ -90,7 +95,7 @@ func ExtendedCopy(ctx context.Context, src ReadOnlyGraphTarget, srcRef string, d
}
if err := dst.Tag(ctx, node, dstRef); err != nil {
- return ocispec.Descriptor{}, err
+ return ocispec.Descriptor{}, newCopyError("Tag", CopyErrorOriginDestination, err)
}
return node, nil
@@ -98,7 +103,17 @@ func ExtendedCopy(ctx context.Context, src ReadOnlyGraphTarget, srcRef string, d
// ExtendedCopyGraph copies the directed acyclic graph (DAG) that are reachable
// from the given node from the source GraphStorage to the destination Storage.
+// In other words, it copies an artifact along with its referrers or other
+// predecessor manifests referencing it.
+// The node (e.g. a manifest of the artifact) is identified by a descriptor.
func ExtendedCopyGraph(ctx context.Context, src content.ReadOnlyGraphStorage, dst content.Storage, node ocispec.Descriptor, opts ExtendedCopyGraphOptions) error {
+ if src == nil {
+ return newCopyError("ExtendedCopyGraph", CopyErrorOriginSource, errors.New("nil source target"))
+ }
+ if dst == nil {
+ return newCopyError("ExtendedCopyGraph", CopyErrorOriginDestination, errors.New("nil destination target"))
+ }
+
roots, err := findRoots(ctx, src, node, opts)
if err != nil {
return err
@@ -174,7 +189,7 @@ func findRoots(ctx context.Context, storage content.ReadOnlyGraphStorage, node o
predecessors, err := opts.FindPredecessors(ctx, storage, currentNode)
if err != nil {
- return nil, err
+ return nil, newCopyError("FindPredecessors", CopyErrorOriginSource, err)
}
// The current node has no predecessor node,
diff --git a/vendor/oras.land/oras-go/v2/internal/platform/platform.go b/vendor/oras.land/oras-go/v2/internal/platform/platform.go
index 3aea3a1b..60d000d1 100644
--- a/vendor/oras.land/oras-go/v2/internal/platform/platform.go
+++ b/vendor/oras.land/oras-go/v2/internal/platform/platform.go
@@ -127,7 +127,7 @@ func SelectManifest(ctx context.Context, src content.ReadOnlyStorage, root ocisp
// fields in config blob.
func getPlatformFromConfig(ctx context.Context, src content.ReadOnlyStorage, desc ocispec.Descriptor, targetConfigMediaType string) (*ocispec.Platform, error) {
if desc.MediaType != targetConfigMediaType {
- return nil, fmt.Errorf("fail to recognize platform from unknown config %s: expect %s", desc.MediaType, targetConfigMediaType)
+ return nil, fmt.Errorf("fail to recognize platform from unknown config %s: expect %s: %w", desc.MediaType, targetConfigMediaType, errdef.ErrUnsupported)
}
rc, err := src.Fetch(ctx, desc)
diff --git a/vendor/oras.land/oras-go/v2/internal/resolver/memory.go b/vendor/oras.land/oras-go/v2/internal/resolver/memory.go
index 092a29e9..df710e66 100644
--- a/vendor/oras.land/oras-go/v2/internal/resolver/memory.go
+++ b/vendor/oras.land/oras-go/v2/internal/resolver/memory.go
@@ -17,6 +17,7 @@ package resolver
import (
"context"
+ "fmt"
"maps"
"sync"
@@ -48,7 +49,7 @@ func (m *Memory) Resolve(_ context.Context, reference string) (ocispec.Descripto
desc, ok := m.index[reference]
if !ok {
- return ocispec.Descriptor{}, errdef.ErrNotFound
+ return ocispec.Descriptor{}, fmt.Errorf("%s: %w", reference, errdef.ErrNotFound)
}
return desc, nil
}
diff --git a/vendor/oras.land/oras-go/v2/internal/syncutil/limit.go b/vendor/oras.land/oras-go/v2/internal/syncutil/limit.go
index 2a05d4ea..e429f24f 100644
--- a/vendor/oras.land/oras-go/v2/internal/syncutil/limit.go
+++ b/vendor/oras.land/oras-go/v2/internal/syncutil/limit.go
@@ -67,18 +67,41 @@ type GoFunc[T any] func(ctx context.Context, region *LimitedRegion, t T) error
// Go concurrently invokes fn on items.
func Go[T any](ctx context.Context, limiter *semaphore.Weighted, fn GoFunc[T], items ...T) error {
+ ctx, cancel := context.WithCancelCause(ctx)
+ defer cancel(nil)
+
eg, egCtx := errgroup.WithContext(ctx)
for _, item := range items {
- region := LimitRegion(ctx, limiter)
+ region := LimitRegion(egCtx, limiter)
if err := region.Start(); err != nil {
- return err
+ cancel(err)
+ // break loop instead of returning to allow previously scheduled
+ // goroutines to finish their deferred region.End() calls
+ break
}
- eg.Go(func(t T) func() error {
+
+ eg.Go(func(t T, lr *LimitedRegion) func() error {
return func() error {
- defer region.End()
- return fn(egCtx, region, t)
+ defer lr.End()
+
+ select {
+ case <-egCtx.Done():
+ // skip the task if the context is already cancelled
+ return nil
+ default:
+ }
+
+ if err := fn(egCtx, lr, t); err != nil {
+ cancel(err)
+ return err
+ }
+ return nil
}
- }(item))
+ }(item, region))
+ }
+
+ if err := eg.Wait(); err != nil {
+ cancel(err)
}
- return eg.Wait()
+ return context.Cause(ctx)
}
diff --git a/vendor/oras.land/oras-go/v2/internal/syncutil/limitgroup.go b/vendor/oras.land/oras-go/v2/internal/syncutil/limitgroup.go
index 1071bedc..4ef087dc 100644
--- a/vendor/oras.land/oras-go/v2/internal/syncutil/limitgroup.go
+++ b/vendor/oras.land/oras-go/v2/internal/syncutil/limitgroup.go
@@ -21,7 +21,7 @@ import (
"golang.org/x/sync/errgroup"
)
-// A LimitedGroup is a collection of goroutines working on subtasks that are part of
+// LimitedGroup is a collection of goroutines working on subtasks that are part of
// the same overall task.
type LimitedGroup struct {
grp *errgroup.Group
diff --git a/vendor/oras.land/oras-go/v2/pack.go b/vendor/oras.land/oras-go/v2/pack.go
index 1b995612..6d1635c9 100644
--- a/vendor/oras.land/oras-go/v2/pack.go
+++ b/vendor/oras.land/oras-go/v2/pack.go
@@ -48,8 +48,8 @@ const (
var (
// ErrInvalidDateTimeFormat is returned by [Pack] and [PackManifest] when
- // AnnotationArtifactCreated or AnnotationCreated is provided, but its value
- // is not in RFC 3339 format.
+ // "org.opencontainers.artifact.created" or "org.opencontainers.image.created"
+ // is provided, but its value is not in RFC 3339 format.
// Reference: https://www.rfc-editor.org/rfc/rfc3339#section-5.6
ErrInvalidDateTimeFormat = errors.New("invalid date and time format")
@@ -78,8 +78,8 @@ const (
PackManifestVersion1_1_RC4 PackManifestVersion = PackManifestVersion1_1
// PackManifestVersion1_1 represents the OCI Image Manifest defined in
- // image-spec v1.1.0.
- // Reference: https://github.com/opencontainers/image-spec/blob/v1.1.0/manifest.md
+ // image-spec v1.1.1.
+ // Reference: https://github.com/opencontainers/image-spec/blob/v1.1.1/manifest.md
PackManifestVersion1_1 PackManifestVersion = 2
)
@@ -93,7 +93,10 @@ type PackManifestOptions struct {
// Layers is the layers of the manifest.
Layers []ocispec.Descriptor
- // ManifestAnnotations is the annotation map of the manifest.
+ // ManifestAnnotations is the annotation map of the manifest. In order to
+ // make [PackManifest] reproducible, set the key ocispec.AnnotationCreated
+ // (i.e. "org.opencontainers.image.created") to a fixed value. The value
+ // must conform to RFC 3339.
ManifestAnnotations map[string]string
// ConfigDescriptor is a pointer to the descriptor of the config blob.
@@ -107,9 +110,9 @@ type PackManifestOptions struct {
// mediaTypeRegexp checks the format of media types.
// References:
-// - https://github.com/opencontainers/image-spec/blob/v1.1.0/schema/defs-descriptor.json#L7
+// - https://github.com/opencontainers/image-spec/blob/v1.1.1/schema/defs-descriptor.json#L7
// - https://datatracker.ietf.org/doc/html/rfc6838#section-4.2
-var mediaTypeRegexp = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9!#$&-^_.+]{0,126}/[A-Za-z0-9][A-Za-z0-9!#$&-^_.+]{0,126}$`)
+var mediaTypeRegexp = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}/[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}$`)
// PackManifest generates an OCI Image Manifest based on the given parameters
// and pushes the packed manifest to a content storage using pusher. The version
@@ -126,6 +129,12 @@ var mediaTypeRegexp = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9!#$&-^_.+]{0,126
//
// artifactType and opts.ConfigDescriptor.MediaType MUST comply with RFC 6838.
//
+// Each time when PackManifest is called, if a time stamp is not specified, a new time
+// stamp is generated in the manifest annotations with the key ocispec.AnnotationCreated
+// (i.e. "org.opencontainers.image.created"). To make [PackManifest] reproducible,
+// set the key ocispec.AnnotationCreated to a fixed value in
+// opts.ManifestAnnotations. The value MUST conform to RFC 3339.
+//
// If succeeded, returns a descriptor of the packed manifest.
func PackManifest(ctx context.Context, pusher content.Pusher, packManifestVersion PackManifestVersion, artifactType string, opts PackManifestOptions) (ocispec.Descriptor, error) {
switch packManifestVersion {
@@ -292,8 +301,8 @@ func packManifestV1_1_RC2(ctx context.Context, pusher content.Pusher, configMedi
return pushManifest(ctx, pusher, manifest, manifest.MediaType, manifest.Config.MediaType, manifest.Annotations)
}
-// packManifestV1_1 packs an image manifest defined in image-spec v1.1.0.
-// Reference: https://github.com/opencontainers/image-spec/blob/v1.1.0/manifest.md#guidelines-for-artifact-usage
+// packManifestV1_1 packs an image manifest defined in image-spec v1.1.1.
+// Reference: https://github.com/opencontainers/image-spec/blob/v1.1.1/manifest.md#guidelines-for-artifact-usage
func packManifestV1_1(ctx context.Context, pusher content.Pusher, artifactType string, opts PackManifestOptions) (ocispec.Descriptor, error) {
if artifactType == "" && (opts.ConfigDescriptor == nil || opts.ConfigDescriptor.MediaType == ocispec.MediaTypeEmptyJSON) {
// artifactType MUST be set when config.mediaType is set to the empty value
diff --git a/vendor/oras.land/oras-go/v2/registry/reference.go b/vendor/oras.land/oras-go/v2/registry/reference.go
index fc3e95e5..54c72fd2 100644
--- a/vendor/oras.land/oras-go/v2/registry/reference.go
+++ b/vendor/oras.land/oras-go/v2/registry/reference.go
@@ -34,13 +34,13 @@ var (
//
// References:
// - https://github.com/distribution/distribution/blob/v2.7.1/reference/regexp.go#L53
- // - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#pulling-manifests
+ // - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#pulling-manifests
repositoryRegexp = regexp.MustCompile(`^[a-z0-9]+(?:(?:[._]|__|[-]*)[a-z0-9]+)*(?:/[a-z0-9]+(?:(?:[._]|__|[-]*)[a-z0-9]+)*)*$`)
// tagRegexp checks the tag name.
// The docker and OCI spec have the same regular expression.
//
- // Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#pulling-manifests
+ // Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#pulling-manifests
tagRegexp = regexp.MustCompile(`^[\w][\w.-]{0,127}$`)
)
diff --git a/vendor/oras.land/oras-go/v2/registry/registry.go b/vendor/oras.land/oras-go/v2/registry/registry.go
index e1da0ab9..4736efa8 100644
--- a/vendor/oras.land/oras-go/v2/registry/registry.go
+++ b/vendor/oras.land/oras-go/v2/registry/registry.go
@@ -31,7 +31,7 @@ type Registry interface {
// Note: When implemented by a remote registry, the catalog API is called.
// However, not all registries supports pagination or conforms the
// specification.
- // Reference: https://docs.docker.com/registry/spec/api/#catalog
+ // Reference: https://distribution.github.io/distribution/spec/api/#catalog
// See also `Repositories()` in this package.
Repositories(ctx context.Context, last string, fn func(repos []string) error) error
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/auth/challenge.go b/vendor/oras.land/oras-go/v2/registry/remote/auth/challenge.go
index 58bdefda..ffc52f8e 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/auth/challenge.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/auth/challenge.go
@@ -62,7 +62,7 @@ func (s Scheme) String() string {
// parseChallenge parses the "WWW-Authenticate" header returned by the remote
// registry, and extracts parameters if scheme is Bearer.
// References:
-// - https://docs.docker.com/registry/spec/auth/token/#how-to-authenticate
+// - https://distribution.github.io/distribution/spec/auth/token/#how-to-authenticate
// - https://tools.ietf.org/html/rfc7235#section-2.1
func parseChallenge(header string) (scheme Scheme, params map[string]string) {
// as defined in RFC 7235 section 2.1, we have
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/auth/client.go b/vendor/oras.land/oras-go/v2/registry/remote/auth/client.go
index 8d9685a2..5c5330e7 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/auth/client.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/auth/client.go
@@ -51,7 +51,7 @@ var DefaultClient = &Client{
// limit, which is usually 16 KiB. As specified by the distribution, the
// response may contain 2 identical tokens, that is, 16 x 2 = 32 KiB.
// Hence, 128 KiB should be sufficient.
-// References: https://docs.docker.com/registry/spec/auth/token/
+// References: https://distribution.github.io/distribution/spec/auth/token/
var maxResponseBytes int64 = 128 * 1024 // 128 KiB
// defaultClientID specifies the default client ID used in OAuth2.
@@ -110,15 +110,15 @@ type Client struct {
// ClientID used in fetching OAuth2 token as a required field.
// If empty, a default client ID is used.
- // Reference: https://docs.docker.com/registry/spec/auth/oauth/#getting-a-token
+ // Reference: https://distribution.github.io/distribution/spec/auth/oauth/#getting-a-token
ClientID string
// ForceAttemptOAuth2 controls whether to follow OAuth2 with password grant
// instead the distribution spec when authenticating using username and
// password.
// References:
- // - https://docs.docker.com/registry/spec/auth/jwt/
- // - https://docs.docker.com/registry/spec/auth/oauth/
+ // - https://distribution.github.io/distribution/spec/auth/jwt/
+ // - https://distribution.github.io/distribution/spec/auth/oauth/
ForceAttemptOAuth2 bool
}
@@ -312,8 +312,8 @@ func (c *Client) fetchBearerToken(ctx context.Context, registry, realm, service
// specification.
// It fetches anonymous tokens if no credential is provided.
// References:
-// - https://docs.docker.com/registry/spec/auth/jwt/
-// - https://docs.docker.com/registry/spec/auth/token/
+// - https://distribution.github.io/distribution/spec/auth/jwt/
+// - https://distribution.github.io/distribution/spec/auth/token/
func (c *Client) fetchDistributionToken(ctx context.Context, realm, service string, scopes []string, username, password string) (string, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, realm, nil)
if err != nil {
@@ -340,7 +340,7 @@ func (c *Client) fetchDistributionToken(ctx context.Context, realm, service stri
return "", errutil.ParseErrorResponse(resp)
}
- // As specified in https://docs.docker.com/registry/spec/auth/token/ section
+ // As specified in https://distribution.github.io/distribution/spec/auth/token/ section
// "Token Response Fields", the token is either in `token` or
// `access_token`. If both present, they are identical.
var result struct {
@@ -361,7 +361,7 @@ func (c *Client) fetchDistributionToken(ctx context.Context, realm, service stri
}
// fetchOAuth2Token fetches an OAuth2 access token.
-// Reference: https://docs.docker.com/registry/spec/auth/oauth/
+// Reference: https://distribution.github.io/distribution/spec/auth/oauth/
func (c *Client) fetchOAuth2Token(ctx context.Context, realm, service string, scopes []string, cred Credential) (string, error) {
form := url.Values{}
if cred.RefreshToken != "" {
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/auth/credential.go b/vendor/oras.land/oras-go/v2/registry/remote/auth/credential.go
index 013305f7..044bcaec 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/auth/credential.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/auth/credential.go
@@ -30,11 +30,11 @@ type Credential struct {
// RefreshToken is a bearer token to be sent to the authorization service
// for fetching access tokens.
// A refresh token is often referred as an identity token.
- // Reference: https://docs.docker.com/registry/spec/auth/oauth/
+ // Reference: https://distribution.github.io/distribution/spec/auth/oauth/
RefreshToken string
// AccessToken is a bearer token to be sent to the registry.
// An access token is often referred as a registry token.
- // Reference: https://docs.docker.com/registry/spec/auth/token/
+ // Reference: https://distribution.github.io/distribution/spec/auth/token/
AccessToken string
}
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/auth/scope.go b/vendor/oras.land/oras-go/v2/registry/remote/auth/scope.go
index d81cc0d4..bdd6e5c4 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/auth/scope.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/auth/scope.go
@@ -24,7 +24,7 @@ import (
)
// Actions used in scopes.
-// Reference: https://docs.docker.com/registry/spec/auth/scope/
+// Reference: https://distribution.github.io/distribution/spec/auth/scope/
const (
// ActionPull represents generic read access for resources of the repository
// type.
@@ -43,7 +43,7 @@ const (
const ScopeRegistryCatalog = "registry:catalog:*"
// ScopeRepository returns a repository scope with given actions.
-// Reference: https://docs.docker.com/registry/spec/auth/scope/
+// Reference: https://distribution.github.io/distribution/spec/auth/scope/
func ScopeRepository(repository string, actions ...string) string {
actions = cleanActions(actions)
if repository == "" || len(actions) == 0 {
@@ -98,7 +98,7 @@ type scopesContextKey struct{}
// Passing an empty list of scopes will virtually remove the scope hints in the
// context.
//
-// Reference: https://docs.docker.com/registry/spec/auth/scope/
+// Reference: https://distribution.github.io/distribution/spec/auth/scope/
func WithScopes(ctx context.Context, scopes ...string) context.Context {
scopes = CleanScopes(scopes)
return context.WithValue(ctx, scopesContextKey{}, scopes)
@@ -143,7 +143,7 @@ type scopesForHostContextKey string
// Passing an empty list of scopes will virtually remove the scope hints in the
// context for the given host.
//
-// Reference: https://docs.docker.com/registry/spec/auth/scope/
+// Reference: https://distribution.github.io/distribution/spec/auth/scope/
func WithScopesForHost(ctx context.Context, host string, scopes ...string) context.Context {
scopes = CleanScopes(scopes)
return context.WithValue(ctx, scopesForHostContextKey(host), scopes)
@@ -303,7 +303,7 @@ func cleanActions(actions []string) []string {
// slow path
slices.Sort(actions)
n := 0
- for i := 0; i < len(actions); i++ {
+ for i := range len(actions) {
if actions[i] == "*" {
return []string{"*"}
}
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/errcode/errors.go b/vendor/oras.land/oras-go/v2/registry/remote/errcode/errors.go
index 9f87d86d..a32f1e5e 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/errcode/errors.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/errcode/errors.go
@@ -24,8 +24,8 @@ import (
)
// References:
-// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#error-codes
-// - https://docs.docker.com/registry/spec/api/#errors-2
+// - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#error-codes
+// - https://distribution.github.io/distribution/spec/api/#errors-2
const (
ErrorCodeBlobUnknown = "BLOB_UNKNOWN"
ErrorCodeBlobUploadInvalid = "BLOB_UPLOAD_INVALID"
@@ -45,8 +45,8 @@ const (
// Error represents a response inner error returned by the remote
// registry.
// References:
-// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#error-codes
-// - https://docs.docker.com/registry/spec/api/#errors-2
+// - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#error-codes
+// - https://distribution.github.io/distribution/spec/api/#errors-2
type Error struct {
Code string `json:"code"`
Message string `json:"message"`
@@ -73,8 +73,8 @@ func (e Error) Error() string {
// Errors represents a list of response inner errors returned by the remote
// server.
// References:
-// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#error-codes
-// - https://docs.docker.com/registry/spec/api/#errors-2
+// - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#error-codes
+// - https://distribution.github.io/distribution/spec/api/#errors-2
type Errors []Error
// Error returns a error string describing the error.
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/referrers.go b/vendor/oras.land/oras-go/v2/registry/remote/referrers.go
index 74668089..720430d3 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/referrers.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/referrers.go
@@ -17,6 +17,7 @@ package remote
import (
"errors"
+ "fmt"
"strings"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -102,11 +103,14 @@ func (e *ReferrersError) IsReferrersIndexDelete() bool {
// buildReferrersTag builds the referrers tag for the given manifest descriptor.
// Format: -
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#unavailable-referrers-api
-func buildReferrersTag(desc ocispec.Descriptor) string {
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#unavailable-referrers-api
+func buildReferrersTag(desc ocispec.Descriptor) (string, error) {
+ if err := desc.Digest.Validate(); err != nil {
+ return "", fmt.Errorf("failed to build referrers tag for %s: %w", desc.Digest, err)
+ }
alg := desc.Digest.Algorithm().String()
encoded := desc.Digest.Encoded()
- return alg + "-" + encoded
+ return alg + "-" + encoded, nil
}
// isReferrersFilterApplied checks if requsted is in the applied filter list.
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/registry.go b/vendor/oras.land/oras-go/v2/registry/remote/registry.go
index 1099b585..bb707c7e 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/registry.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/registry.go
@@ -43,7 +43,7 @@ type Registry struct {
// RepositoryListPageSize specifies the page size when invoking the catalog
// API.
// If zero, the page size is determined by the remote registry.
- // Reference: https://docs.docker.com/registry/spec/api/#catalog
+ // Reference: https://distribution.github.io/distribution/spec/api/#catalog
RepositoryListPageSize int
}
@@ -93,8 +93,8 @@ func (r *Registry) do(req *http.Request) (*http.Response, error) {
// Ping can be used to check authentication when an auth client is configured.
//
// References:
-// - https://docs.docker.com/registry/spec/api/#base
-// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#api
+// - https://distribution.github.io/distribution/spec/api/#base
+// - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#api
func (r *Registry) Ping(ctx context.Context) error {
url := buildRegistryBaseURL(r.PlainHTTP, r.Reference)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
@@ -125,7 +125,7 @@ func (r *Registry) Ping(ctx context.Context) error {
// repo specified by `last`. Otherwise, the response starts from the top
// of the Repositories list.
//
-// Reference: https://docs.docker.com/registry/spec/api/#catalog
+// Reference: https://distribution.github.io/distribution/spec/api/#catalog
func (r *Registry) Repositories(ctx context.Context, last string, fn func(repos []string) error) error {
ctx = auth.AppendScopesForHost(ctx, r.Reference.Host(), auth.ScopeRegistryCatalog)
url := buildRegistryCatalogURL(r.PlainHTTP, r.Reference)
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/repository.go b/vendor/oras.land/oras-go/v2/registry/remote/repository.go
index 7c36dc1c..fed993df 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/repository.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/repository.go
@@ -52,8 +52,8 @@ const (
// uploaded blob.
//
// References:
- // - https://docs.docker.com/registry/spec/api/#digest-header
- // - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#pull
+ // - https://distribution.github.io/distribution/spec/api/#digest-header
+ // - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#pull
headerDockerContentDigest = "Docker-Content-Digest"
// headerOCIFiltersApplied is the "OCI-Filters-Applied" header.
@@ -61,7 +61,7 @@ const (
// applied filters.
//
// Reference:
- // - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#listing-referrers
+ // - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#listing-referrers
headerOCIFiltersApplied = "OCI-Filters-Applied"
// headerOCISubject is the "OCI-Subject" header.
@@ -74,7 +74,7 @@ const (
// referrers.
//
// References:
-// - Latest spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#listing-referrers
+// - Latest spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#listing-referrers
// - Compatible spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#listing-referrers
const filterTypeArtifactType = "artifactType"
@@ -112,13 +112,18 @@ type Repository struct {
// TagListPageSize specifies the page size when invoking the tag list API.
// If zero, the page size is determined by the remote registry.
- // Reference: https://docs.docker.com/registry/spec/api/#tags
+ // Reference: https://distribution.github.io/distribution/spec/api/#tags
TagListPageSize int
// ReferrerListPageSize specifies the page size when invoking the Referrers
// API.
// If zero, the page size is determined by the remote registry.
- // Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#listing-referrers
+ //
+ // NOTE: Pagination for the Referrers API is not defined in the distribution
+ // spec, so not all registries support it. ReferrerListPageSize may be
+ // ignored if pagination is unsupported by the remote registry.
+ //
+ // Reference: https://github.com/oras-project/oras-go/issues/841
ReferrerListPageSize int
// MaxMetadataBytes specifies a limit on how many response bytes are allowed
@@ -133,16 +138,16 @@ type Repository struct {
// is successfully uploaded.
// - If true, the old referrers index is kept.
// By default, it is disabled (set to false). See also:
- // - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#referrers-tag-schema
- // - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#pushing-manifests-with-subject
- // - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#deleting-manifests
+ // - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#referrers-tag-schema
+ // - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#pushing-manifests-with-subject
+ // - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#deleting-manifests
SkipReferrersGC bool
// HandleWarning handles the warning returned by the remote server.
// Callers SHOULD deduplicate warnings from multiple associated responses.
//
// References:
- // - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#warnings
+ // - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#warnings
// - https://www.rfc-editor.org/rfc/rfc7234#section-5.5
HandleWarning func(warning Warning)
@@ -212,9 +217,9 @@ func (r *Repository) clone() *Repository {
// SetReferrersCapability returns ErrReferrersCapabilityAlreadySet if the
// Referrers API capability has been already set.
// - When the capability is set to true, the Referrers() function will always
-// request the Referrers API. Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#listing-referrers
+// request the Referrers API. Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#listing-referrers
// - When the capability is set to false, the Referrers() function will always
-// request the Referrers Tag. Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#referrers-tag-schema
+// request the Referrers Tag. Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#referrers-tag-schema
// - When the capability is not set, the Referrers() function will automatically
// determine which API to use.
func (r *Repository) SetReferrersCapability(capable bool) error {
@@ -388,8 +393,8 @@ func (r *Repository) ParseReference(reference string) (registry.Reference, error
// of the Tags list.
//
// References:
-// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#content-discovery
-// - https://docs.docker.com/registry/spec/api/#tags
+// - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#content-discovery
+// - https://distribution.github.io/distribution/spec/api/#tags
func (r *Repository) Tags(ctx context.Context, last string, fn func(tags []string) error) error {
ctx = auth.AppendRepositoryScope(ctx, r.Reference, auth.ActionPull)
url := buildRepositoryTagListURL(r.PlainHTTP, r.Reference)
@@ -447,7 +452,7 @@ func (r *Repository) tags(ctx context.Context, last string, fn func(tags []strin
// Predecessors returns the descriptors of image or artifact manifests directly
// referencing the given manifest descriptor.
// Predecessors internally leverages Referrers.
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#listing-referrers
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#listing-referrers
func (r *Repository) Predecessors(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
var res []ocispec.Descriptor
if err := r.Referrers(ctx, desc, "", func(referrers []ocispec.Descriptor) error {
@@ -466,7 +471,7 @@ func (r *Repository) Predecessors(ctx context.Context, desc ocispec.Descriptor)
// If artifactType is not empty, only referrers of the same artifact type are
// fed to fn.
//
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#listing-referrers
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#listing-referrers
func (r *Repository) Referrers(ctx context.Context, desc ocispec.Descriptor, artifactType string, fn func(referrers []ocispec.Descriptor) error) error {
state := r.loadReferrersState()
if state == referrersStateUnsupported {
@@ -565,7 +570,7 @@ func (r *Repository) referrersPageByAPI(ctx context.Context, artifactType string
referrers := index.Manifests
if artifactType != "" {
// check both filters header and filters annotations for compatibility
- // latest spec for filters header: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#listing-referrers
+ // latest spec for filters header: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#listing-referrers
// older spec for filters annotations: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#listing-referrers
filtersHeader := resp.Header.Get(headerOCIFiltersApplied)
filtersAnnotation := index.Annotations[spec.AnnotationReferrersFiltersApplied]
@@ -587,9 +592,12 @@ func (r *Repository) referrersPageByAPI(ctx context.Context, artifactType string
// referencing the given manifest descriptor by requesting referrers tag.
// fn is called for the referrers result. If artifactType is not empty,
// only referrers of the same artifact type are fed to fn.
-// reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#backwards-compatibility
+// reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#backwards-compatibility
func (r *Repository) referrersByTagSchema(ctx context.Context, desc ocispec.Descriptor, artifactType string, fn func(referrers []ocispec.Descriptor) error) error {
- referrersTag := buildReferrersTag(desc)
+ referrersTag, err := buildReferrersTag(desc)
+ if err != nil {
+ return err
+ }
_, referrers, err := r.referrersFromIndex(ctx, referrersTag)
if err != nil {
if errors.Is(err, errdef.ErrNotFound) {
@@ -739,15 +747,18 @@ func (s *blobStore) Fetch(ctx context.Context, target ocispec.Descriptor) (rc io
}()
switch resp.StatusCode {
- case http.StatusOK: // server does not support seek as `Range` was ignored.
+ case http.StatusOK:
if size := resp.ContentLength; size != -1 && size != target.Size {
return nil, fmt.Errorf("%s %q: mismatch Content-Length", resp.Request.Method, resp.Request.URL)
}
+ if err := verifyContentDigest(resp, target.Digest); err != nil {
+ return nil, err
+ }
// check server range request capability.
// Docker spec allows range header form of "Range: bytes=-".
// However, the remote server may still not RFC 7233 compliant.
- // Reference: https://docs.docker.com/registry/spec/api/#blob
+ // Reference: https://distribution.github.io/distribution/spec/api/#blob
if rangeUnit := resp.Header.Get("Accept-Ranges"); rangeUnit == "bytes" {
return httputil.NewReadSeekCloser(s.repo.client(), req, resp.Body, target.Size), nil
}
@@ -801,7 +812,7 @@ func (s *blobStore) Mount(ctx context.Context, desc ocispec.Descriptor, fromRepo
// push it. If the caller has provided a getContent function, we
// can use that, otherwise pull the content from the source repository.
//
- // [spec]: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#mounting-a-blob-from-another-repository
+ // [spec]: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#mounting-a-blob-from-another-repository
var r io.ReadCloser
if getContent != nil {
@@ -834,9 +845,9 @@ func (s *blobStore) sibling(otherRepoName string) *blobStore {
// authentication errors.
//
// References:
-// - https://docs.docker.com/registry/spec/api/#pushing-an-image
-// - https://docs.docker.com/registry/spec/api/#initiate-blob-upload
-// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#pushing-a-blob-monolithically
+// - https://distribution.github.io/distribution/spec/api/#pushing-an-image
+// - https://distribution.github.io/distribution/spec/api/#initiate-blob-upload
+// - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#pushing-a-blob-monolithically
func (s *blobStore) Push(ctx context.Context, expected ocispec.Descriptor, content io.Reader) error {
// start an upload
// pushing usually requires both pull and push actions.
@@ -1008,7 +1019,7 @@ func (s *blobStore) FetchReference(ctx context.Context, reference string) (desc
// check server range request capability.
// Docker spec allows range header form of "Range: bytes=-".
// However, the remote server may still not RFC 7233 compliant.
- // Reference: https://docs.docker.com/registry/spec/api/#blob
+ // Reference: https://distribution.github.io/distribution/spec/api/#blob
if rangeUnit := resp.Header.Get("Accept-Ranges"); rangeUnit == "bytes" {
return desc, httputil.NewReadSeekCloser(s.repo.client(), req, resp.Body, desc.Size), nil
}
@@ -1146,7 +1157,7 @@ func (s *manifestStore) deleteWithIndexing(ctx context.Context, target ocispec.D
// on manifest delete.
//
// References:
-// - Latest spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#deleting-manifests
+// - Latest spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#deleting-manifests
// - Compatible spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#deleting-manifests
func (s *manifestStore) indexReferrersForDelete(ctx context.Context, desc ocispec.Descriptor, manifestJSON []byte) error {
var manifest struct {
@@ -1332,7 +1343,7 @@ func (s *manifestStore) push(ctx context.Context, expected ocispec.Descriptor, c
// checkOCISubjectHeader checks the "OCI-Subject" header in the response and
// sets referrers capability accordingly.
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#pushing-manifests-with-subject
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#pushing-manifests-with-subject
func (s *manifestStore) checkOCISubjectHeader(resp *http.Response) {
// If the "OCI-Subject" header is set, it indicates that the registry
// supports the Referrers API and has processed the subject of the manifest.
@@ -1383,7 +1394,7 @@ func (s *manifestStore) pushWithIndexing(ctx context.Context, expected ocispec.D
// on manifest push.
//
// References:
-// - Latest spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#pushing-manifests-with-subject
+// - Latest spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#pushing-manifests-with-subject
// - Compatible spec: https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#pushing-manifests-with-subject
func (s *manifestStore) indexReferrersForPush(ctx context.Context, desc ocispec.Descriptor, manifestJSON []byte) error {
var subject ocispec.Descriptor
@@ -1440,10 +1451,13 @@ func (s *manifestStore) indexReferrersForPush(ctx context.Context, desc ocispec.
// updateReferrersIndex updates the referrers index for desc referencing subject
// on manifest push and manifest delete.
// References:
-// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#pushing-manifests-with-subject
-// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#deleting-manifests
+// - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#pushing-manifests-with-subject
+// - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#deleting-manifests
func (s *manifestStore) updateReferrersIndex(ctx context.Context, subject ocispec.Descriptor, change referrerChange) (err error) {
- referrersTag := buildReferrersTag(subject)
+ referrersTag, err := buildReferrersTag(subject)
+ if err != nil {
+ return err
+ }
var oldIndexDesc *ocispec.Descriptor
var oldReferrers []ocispec.Descriptor
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/retry/policy.go b/vendor/oras.land/oras-go/v2/registry/remote/retry/policy.go
index fe7fadee..ebe8b373 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/retry/policy.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/retry/policy.go
@@ -18,7 +18,7 @@ package retry
import (
"hash/maphash"
"math"
- "math/rand"
+ "math/rand/v2"
"net"
"net/http"
"strconv"
@@ -88,7 +88,7 @@ type Backoff func(attempt int, resp *http.Response) time.Duration
// jitter. The backoff is calculated as:
//
// temp = backoff * factor ^ attempt
-// interval = temp * (1 - jitter) + rand.Int63n(2 * jitter * temp)
+// interval = temp * (1 - jitter) + rand.Int64N(2 * jitter * temp)
//
// The HTTP response is checked for a Retry-After header. If it is present, the
// value is used as the backoff duration.
@@ -96,7 +96,7 @@ func ExponentialBackoff(backoff time.Duration, factor, jitter float64) Backoff {
return func(attempt int, resp *http.Response) time.Duration {
var h maphash.Hash
h.SetSeed(maphash.MakeSeed())
- rand := rand.New(rand.NewSource(int64(h.Sum64())))
+ rand := rand.New(rand.NewPCG(0, h.Sum64()))
// check Retry-After
if resp != nil && resp.StatusCode == http.StatusTooManyRequests {
@@ -109,7 +109,7 @@ func ExponentialBackoff(backoff time.Duration, factor, jitter float64) Backoff {
// do exponential backoff with jitter
temp := float64(backoff) * math.Pow(factor, float64(attempt))
- return time.Duration(temp*(1-jitter)) + time.Duration(rand.Int63n(int64(2*jitter*temp)))
+ return time.Duration(temp*(1-jitter)) + time.Duration(rand.Int64N(int64(2*jitter*temp)))
}
}
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/url.go b/vendor/oras.land/oras-go/v2/registry/remote/url.go
index 2d4b422b..64f6670a 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/url.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/url.go
@@ -34,14 +34,14 @@ func buildScheme(plainHTTP bool) string {
// buildRegistryBaseURL builds the URL for accessing the base API.
// Format: :///v2/
-// Reference: https://docs.docker.com/registry/spec/api/#base
+// Reference: https://distribution.github.io/distribution/spec/api/#base
func buildRegistryBaseURL(plainHTTP bool, ref registry.Reference) string {
return fmt.Sprintf("%s://%s/v2/", buildScheme(plainHTTP), ref.Host())
}
// buildRegistryCatalogURL builds the URL for accessing the catalog API.
// Format: :///v2/_catalog
-// Reference: https://docs.docker.com/registry/spec/api/#catalog
+// Reference: https://distribution.github.io/distribution/spec/api/#catalog
func buildRegistryCatalogURL(plainHTTP bool, ref registry.Reference) string {
return fmt.Sprintf("%s://%s/v2/_catalog", buildScheme(plainHTTP), ref.Host())
}
@@ -54,14 +54,14 @@ func buildRepositoryBaseURL(plainHTTP bool, ref registry.Reference) string {
// buildRepositoryTagListURL builds the URL for accessing the tag list API.
// Format: :///v2//tags/list
-// Reference: https://docs.docker.com/registry/spec/api/#tags
+// Reference: https://distribution.github.io/distribution/spec/api/#tags
func buildRepositoryTagListURL(plainHTTP bool, ref registry.Reference) string {
return buildRepositoryBaseURL(plainHTTP, ref) + "/tags/list"
}
// buildRepositoryManifestURL builds the URL for accessing the manifest API.
// Format: :///v2//manifests/
-// Reference: https://docs.docker.com/registry/spec/api/#manifest
+// Reference: https://distribution.github.io/distribution/spec/api/#manifest
func buildRepositoryManifestURL(plainHTTP bool, ref registry.Reference) string {
return strings.Join([]string{
buildRepositoryBaseURL(plainHTTP, ref),
@@ -72,7 +72,7 @@ func buildRepositoryManifestURL(plainHTTP bool, ref registry.Reference) string {
// buildRepositoryBlobURL builds the URL for accessing the blob API.
// Format: :///v2//blobs/
-// Reference: https://docs.docker.com/registry/spec/api/#blob
+// Reference: https://distribution.github.io/distribution/spec/api/#blob
func buildRepositoryBlobURL(plainHTTP bool, ref registry.Reference) string {
return strings.Join([]string{
buildRepositoryBaseURL(plainHTTP, ref),
@@ -83,14 +83,14 @@ func buildRepositoryBlobURL(plainHTTP bool, ref registry.Reference) string {
// buildRepositoryBlobUploadURL builds the URL for blob uploading.
// Format: :///v2//blobs/uploads/
-// Reference: https://docs.docker.com/registry/spec/api/#initiate-blob-upload
+// Reference: https://distribution.github.io/distribution/spec/api/#initiate-blob-upload
func buildRepositoryBlobUploadURL(plainHTTP bool, ref registry.Reference) string {
return buildRepositoryBaseURL(plainHTTP, ref) + "/blobs/uploads/"
}
// buildRepositoryBlobMountURLbuilds the URL for cross-repository mounting.
// Format: :///v2//blobs/uploads/?mount=&from=
-// Reference: https://docs.docker.com/registry/spec/api/#blob
+// Reference: https://distribution.github.io/distribution/spec/api/#blob
func buildRepositoryBlobMountURL(plainHTTP bool, ref registry.Reference, d digest.Digest, fromRepo string) string {
return fmt.Sprintf("%s?mount=%s&from=%s",
buildRepositoryBlobUploadURL(plainHTTP, ref),
@@ -101,7 +101,7 @@ func buildRepositoryBlobMountURL(plainHTTP bool, ref registry.Reference, d diges
// buildReferrersURL builds the URL for querying the Referrers API.
// Format: :///v2//referrers/?artifactType=
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#listing-referrers
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#listing-referrers
func buildReferrersURL(plainHTTP bool, ref registry.Reference, artifactType string) string {
var query string
if artifactType != "" {
diff --git a/vendor/oras.land/oras-go/v2/registry/remote/warning.go b/vendor/oras.land/oras-go/v2/registry/remote/warning.go
index 20f5071f..02d758ea 100644
--- a/vendor/oras.land/oras-go/v2/registry/remote/warning.go
+++ b/vendor/oras.land/oras-go/v2/registry/remote/warning.go
@@ -43,7 +43,7 @@ var errUnexpectedWarningFormat = errors.New("unexpected warning format")
// WarningValue represents the value of the Warning header.
//
// References:
-// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#warnings
+// - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#warnings
// - https://www.rfc-editor.org/rfc/rfc7234#section-5.5
type WarningValue struct {
// Code is the warn-code.
@@ -58,7 +58,7 @@ type WarningValue struct {
// other information related to the warning.
//
// References:
-// - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#warnings
+// - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#warnings
// - https://www.rfc-editor.org/rfc/rfc7234#section-5.5
type Warning struct {
// WarningValue is the value of the warning header.
diff --git a/vendor/oras.land/oras-go/v2/registry/repository.go b/vendor/oras.land/oras-go/v2/registry/repository.go
index 84a50e2a..367f2d0f 100644
--- a/vendor/oras.land/oras-go/v2/registry/repository.go
+++ b/vendor/oras.land/oras-go/v2/registry/repository.go
@@ -30,7 +30,7 @@ import (
// Repository is an ORAS target and an union of the blob and the manifest CASs.
//
-// As specified by https://docs.docker.com/registry/spec/api/, it is natural to
+// As specified by https://distribution.github.io/distribution/spec/api/, it is natural to
// assume that content.Resolver interface only works for manifests. Tagging a
// blob may be resulted in an `ErrUnsupported` error. However, this interface
// does not restrict tagging blobs.
@@ -87,7 +87,7 @@ type ReferenceFetcher interface {
}
// ReferrerLister provides the Referrers API.
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#listing-referrers
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#listing-referrers
type ReferrerLister interface {
Referrers(ctx context.Context, desc ocispec.Descriptor, artifactType string, fn func(referrers []ocispec.Descriptor) error) error
}
@@ -109,8 +109,8 @@ type TagLister interface {
// specification.
//
// References:
- // - https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#content-discovery
- // - https://docs.docker.com/registry/spec/api/#tags
+ // - https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#content-discovery
+ // - https://distribution.github.io/distribution/spec/api/#tags
// See also `Tags()` in this package.
Tags(ctx context.Context, last string, fn func(tags []string) error) error
}
@@ -143,7 +143,7 @@ func Tags(ctx context.Context, repo TagLister) ([]string, error) {
// Referrers lists the descriptors of image or artifact manifests directly
// referencing the given manifest descriptor.
//
-// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#listing-referrers
+// Reference: https://github.com/opencontainers/distribution-spec/blob/v1.1.1/spec.md#listing-referrers
func Referrers(ctx context.Context, store content.ReadOnlyGraphStorage, desc ocispec.Descriptor, artifactType string) ([]ocispec.Descriptor, error) {
if !descriptor.IsManifest(desc) {
return nil, fmt.Errorf("the descriptor %v is not a manifest: %w", desc, errdef.ErrUnsupported)