chore: update cred helper go libraries (#3087)

This commit is contained in:
Aaron Prindle 2024-03-26 11:34:57 -07:00 committed by GitHub
parent 02860eff08
commit b47d323f2e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 782 additions and 394 deletions

18
go.mod
View File

@ -41,13 +41,13 @@ require (
require ( require (
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
golang.org/x/mod v0.14.0 // indirect golang.org/x/mod v0.16.0 // indirect
golang.org/x/tools v0.17.0 // indirect golang.org/x/tools v0.19.0 // indirect
) )
require ( require (
cloud.google.com/go v0.112.1 // indirect cloud.google.com/go v0.112.1 // indirect
cloud.google.com/go/compute v1.24.0 // indirect cloud.google.com/go/compute v1.25.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.6 // indirect cloud.google.com/go/iam v1.1.6 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
@ -85,9 +85,9 @@ require (
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/docker/cli v25.0.3+incompatible // indirect github.com/docker/cli v26.0.0+incompatible // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.0 // indirect github.com/docker/docker-credential-helpers v0.8.1 // indirect
github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-metrics v0.0.1 // indirect
@ -99,7 +99,7 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/gax-go/v2 v2.12.3 // indirect github.com/googleapis/gax-go/v2 v2.12.3 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
@ -154,9 +154,11 @@ require (
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible // indirect
github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect
github.com/aws/aws-sdk-go-v2/service/ecr v1.24.5 // indirect github.com/aws/aws-sdk-go-v2/service/ecr v1.24.5 // indirect
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.21.5 // indirect github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.21.5 // indirect
github.com/awslabs/amazon-ecr-credential-helper v0.7.1 // indirect
github.com/cloudflare/circl v1.3.7 // indirect github.com/cloudflare/circl v1.3.7 // indirect
github.com/containerd/cgroups/v3 v3.0.2 // indirect github.com/containerd/cgroups/v3 v3.0.2 // indirect
github.com/containerd/log v0.1.0 // indirect github.com/containerd/log v0.1.0 // indirect
@ -177,7 +179,7 @@ require (
github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/swarmkit/v2 v2.0.0-20230315203717-e28e8ba9bc83 // indirect github.com/moby/swarmkit/v2 v2.0.0-20230315203717-e28e8ba9bc83 // indirect
github.com/moby/sys/user v0.1.0 // indirect github.com/moby/sys/user v0.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect github.com/pelletier/go-toml/v2 v2.2.0 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect
@ -193,7 +195,7 @@ require (
go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20231219160207-73b9e39aefca // indirect golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect

23
go.sum
View File

@ -3,6 +3,8 @@ cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM=
cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4=
cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg=
cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40=
cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU=
cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc=
@ -55,6 +57,8 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible h1:juIaKLLVhqzP55d8x4cSVgwyQv76Z55/fRv/UBr2KkQ=
github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs=
github.com/GoogleCloudPlatform/docker-credential-gcr/v2 v2.1.22 h1:HevuUpLsTedep2D6wnIp6AAJbVgP0BiVxaMt3HXeOyA= github.com/GoogleCloudPlatform/docker-credential-gcr/v2 v2.1.22 h1:HevuUpLsTedep2D6wnIp6AAJbVgP0BiVxaMt3HXeOyA=
github.com/GoogleCloudPlatform/docker-credential-gcr/v2 v2.1.22/go.mod h1:nzCpg7DFIIkQIZB3mdUPXVvqQ5f/GahA6xgWXTjnK7w= github.com/GoogleCloudPlatform/docker-credential-gcr/v2 v2.1.22/go.mod h1:nzCpg7DFIIkQIZB3mdUPXVvqQ5f/GahA6xgWXTjnK7w=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
@ -114,6 +118,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.28.4 h1:Ppup1nVNAOWbBOrcoOxaxPeEnSFB
github.com/aws/aws-sdk-go-v2/service/sts v1.28.4/go.mod h1:+K1rNPVyGxkRuv9NNiaZ4YhBFuyw2MMA9SlIJ1Zlpz8= github.com/aws/aws-sdk-go-v2/service/sts v1.28.4/go.mod h1:+K1rNPVyGxkRuv9NNiaZ4YhBFuyw2MMA9SlIJ1Zlpz8=
github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw= github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/awslabs/amazon-ecr-credential-helper v0.7.1 h1:MpOEF1ZCctVadCOnNiALwjmz5K4OZ6O7U7F47wKFn6Q=
github.com/awslabs/amazon-ecr-credential-helper v0.7.1/go.mod h1:qdmDatFsfbKXDJD8lc16C4gvMM6Jom09bdHQBPisMJg=
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231213181459-b0fcec718dc6 h1:PlJRmqKlSlEUlwem1c3zdPaEMtJc/ktnV7naD5Qvsx4= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231213181459-b0fcec718dc6 h1:PlJRmqKlSlEUlwem1c3zdPaEMtJc/ktnV7naD5Qvsx4=
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231213181459-b0fcec718dc6/go.mod h1:08sPJIlDHu4HwQ1xScPgsBWezvM6U10ghGKBJu0mowA= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231213181459-b0fcec718dc6/go.mod h1:08sPJIlDHu4HwQ1xScPgsBWezvM6U10ghGKBJu0mowA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@ -178,12 +184,16 @@ github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/docker/cli v25.0.3+incompatible h1:KLeNs7zws74oFuVhgZQ5ONGZiXUUdgsdy6/EsX/6284= github.com/docker/cli v25.0.3+incompatible h1:KLeNs7zws74oFuVhgZQ5ONGZiXUUdgsdy6/EsX/6284=
github.com/docker/cli v25.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v25.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I=
github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU= github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU=
github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8=
github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40=
github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo=
github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
@ -262,6 +272,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@ -396,8 +408,11 @@ github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
@ -459,6 +474,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@ -469,6 +485,7 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
@ -527,6 +544,8 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20231219160207-73b9e39aefca h1:+xQfFu/HO/82Wwg4zuJ5xiLp0yaOLJjBGnuafXp85YQ= golang.org/x/exp v0.0.0-20231219160207-73b9e39aefca h1:+xQfFu/HO/82Wwg4zuJ5xiLp0yaOLJjBGnuafXp85YQ=
golang.org/x/exp v0.0.0-20231219160207-73b9e39aefca/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/exp v0.0.0-20231219160207-73b9e39aefca/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@ -537,6 +556,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -633,6 +654,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -15,4 +15,4 @@
package internal package internal
// Version is the current tagged release of the library. // Version is the current tagged release of the library.
const Version = "1.24.0" const Version = "1.25.1"

View File

@ -16,11 +16,9 @@ func isValidCredsMessage(msg string) error {
if credentials.IsCredentialsMissingServerURLMessage(msg) { if credentials.IsCredentialsMissingServerURLMessage(msg) {
return credentials.NewErrCredentialsMissingServerURL() return credentials.NewErrCredentialsMissingServerURL()
} }
if credentials.IsCredentialsMissingUsernameMessage(msg) { if credentials.IsCredentialsMissingUsernameMessage(msg) {
return credentials.NewErrCredentialsMissingUsername() return credentials.NewErrCredentialsMissingUsername()
} }
return nil return nil
} }
@ -36,13 +34,10 @@ func Store(program ProgramFunc, creds *credentials.Credentials) error {
out, err := cmd.Output() out, err := cmd.Output()
if err != nil { if err != nil {
t := strings.TrimSpace(string(out)) if isValidErr := isValidCredsMessage(string(out)); isValidErr != nil {
if isValidErr := isValidCredsMessage(t); isValidErr != nil {
err = isValidErr err = isValidErr
} }
return fmt.Errorf("error storing credentials - err: %v, out: `%s`", err, strings.TrimSpace(string(out)))
return fmt.Errorf("error storing credentials - err: %v, out: `%s`", err, t)
} }
return nil return nil
@ -55,17 +50,15 @@ func Get(program ProgramFunc, serverURL string) (*credentials.Credentials, error
out, err := cmd.Output() out, err := cmd.Output()
if err != nil { if err != nil {
t := strings.TrimSpace(string(out)) if credentials.IsErrCredentialsNotFoundMessage(string(out)) {
if credentials.IsErrCredentialsNotFoundMessage(t) {
return nil, credentials.NewErrCredentialsNotFound() return nil, credentials.NewErrCredentialsNotFound()
} }
if isValidErr := isValidCredsMessage(t); isValidErr != nil { if isValidErr := isValidCredsMessage(string(out)); isValidErr != nil {
err = isValidErr err = isValidErr
} }
return nil, fmt.Errorf("error getting credentials - err: %v, out: `%s`", err, t) return nil, fmt.Errorf("error getting credentials - err: %v, out: `%s`", err, strings.TrimSpace(string(out)))
} }
resp := &credentials.Credentials{ resp := &credentials.Credentials{

View File

@ -1,6 +1,9 @@
package credentials package credentials
import "errors" import (
"errors"
"strings"
)
const ( const (
// ErrCredentialsNotFound standardizes the not found error, so every helper returns // ErrCredentialsNotFound standardizes the not found error, so every helper returns
@ -47,7 +50,7 @@ func IsErrCredentialsNotFound(err error) bool {
// This function helps to check messages returned by an // This function helps to check messages returned by an
// external program via its standard output. // external program via its standard output.
func IsErrCredentialsNotFoundMessage(err string) bool { func IsErrCredentialsNotFoundMessage(err string) bool {
return err == errCredentialsNotFoundMessage return strings.TrimSpace(err) == errCredentialsNotFoundMessage
} }
// errCredentialsMissingServerURL represents an error raised // errCredentialsMissingServerURL represents an error raised
@ -104,7 +107,7 @@ func IsCredentialsMissingServerURL(err error) bool {
// IsCredentialsMissingServerURLMessage checks for an // IsCredentialsMissingServerURLMessage checks for an
// errCredentialsMissingServerURL in the error message. // errCredentialsMissingServerURL in the error message.
func IsCredentialsMissingServerURLMessage(err string) bool { func IsCredentialsMissingServerURLMessage(err string) bool {
return err == errCredentialsMissingServerURLMessage return strings.TrimSpace(err) == errCredentialsMissingServerURLMessage
} }
// IsCredentialsMissingUsername returns true if the error // IsCredentialsMissingUsername returns true if the error
@ -117,5 +120,5 @@ func IsCredentialsMissingUsername(err error) bool {
// IsCredentialsMissingUsernameMessage checks for an // IsCredentialsMissingUsernameMessage checks for an
// errCredentialsMissingUsername in the error message. // errCredentialsMissingUsername in the error message.
func IsCredentialsMissingUsernameMessage(err string) bool { func IsCredentialsMissingUsernameMessage(err string) bool {
return err == errCredentialsMissingUsernameMessage return strings.TrimSpace(err) == errCredentialsMissingUsernameMessage
} }

View File

@ -165,25 +165,22 @@ Checklist:
### New release ### New release
1. Decide on the next version number. Use semver. 1. Decide on the next version number. Use semver. Review commits since last
2. Generate release notes using [`gh`][gh]. Example: version to assess.
2. Tag release. For example:
``` ```
$ gh api -X POST \ git checkout v2
-F tag_name='v2.0.0-beta.5' \ git pull
-F target_commitish='v2' \ git tag v2.2.0
-F previous_tag_name='v2.0.0-beta.4' \ git push --tags
--jq '.body' \
repos/pelletier/go-toml/releases/generate-notes
``` ```
3. Look for "Other changes". That would indicate a pull request not labeled 3. CI automatically builds a draft Github release. Review it and edit as
properly. Tweak labels and pull request titles until changelog looks good for necessary. Look for "Other changes". That would indicate a pull request not
users. labeled properly. Tweak labels and pull request titles until changelog looks
4. [Draft new release][new-release]. good for users.
5. Fill tag and target with the same value used to generate the changelog. 4. Check "create discussion" box, in the "Releases" category.
6. Set title to the new tag value. 5. If new version is an alpha or beta only, check pre-release box.
7. Paste the generated changelog.
8. Check "create discussion", in the "Releases" category.
9. Check pre-release if new version is an alpha or beta.
[issues-tracker]: https://github.com/pelletier/go-toml/issues [issues-tracker]: https://github.com/pelletier/go-toml/issues
[bug-report]: https://github.com/pelletier/go-toml/issues/new?template=bug_report.md [bug-report]: https://github.com/pelletier/go-toml/issues/new?template=bug_report.md

View File

@ -98,9 +98,9 @@ Given the following struct, let's see how to read it and write it as TOML:
```go ```go
type MyConfig struct { type MyConfig struct {
Version int Version int
Name string Name string
Tags []string Tags []string
} }
``` ```
@ -119,7 +119,7 @@ tags = ["go", "toml"]
var cfg MyConfig var cfg MyConfig
err := toml.Unmarshal([]byte(doc), &cfg) err := toml.Unmarshal([]byte(doc), &cfg)
if err != nil { if err != nil {
panic(err) panic(err)
} }
fmt.Println("version:", cfg.Version) fmt.Println("version:", cfg.Version)
fmt.Println("name:", cfg.Name) fmt.Println("name:", cfg.Name)
@ -140,14 +140,14 @@ as a TOML document:
```go ```go
cfg := MyConfig{ cfg := MyConfig{
Version: 2, Version: 2,
Name: "go-toml", Name: "go-toml",
Tags: []string{"go", "toml"}, Tags: []string{"go", "toml"},
} }
b, err := toml.Marshal(cfg) b, err := toml.Marshal(cfg)
if err != nil { if err != nil {
panic(err) panic(err)
} }
fmt.Println(string(b)) fmt.Println(string(b))
@ -175,17 +175,17 @@ the AST level. See https://pkg.go.dev/github.com/pelletier/go-toml/v2/unstable.
Execution time speedup compared to other Go TOML libraries: Execution time speedup compared to other Go TOML libraries:
<table> <table>
<thead> <thead>
<tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr> <tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
</thead> </thead>
<tbody> <tbody>
<tr><td>Marshal/HugoFrontMatter-2</td><td>1.9x</td><td>2.2x</td></tr> <tr><td>Marshal/HugoFrontMatter-2</td><td>1.9x</td><td>2.2x</td></tr>
<tr><td>Marshal/ReferenceFile/map-2</td><td>1.7x</td><td>2.1x</td></tr> <tr><td>Marshal/ReferenceFile/map-2</td><td>1.7x</td><td>2.1x</td></tr>
<tr><td>Marshal/ReferenceFile/struct-2</td><td>2.2x</td><td>3.0x</td></tr> <tr><td>Marshal/ReferenceFile/struct-2</td><td>2.2x</td><td>3.0x</td></tr>
<tr><td>Unmarshal/HugoFrontMatter-2</td><td>2.9x</td><td>2.7x</td></tr> <tr><td>Unmarshal/HugoFrontMatter-2</td><td>2.9x</td><td>2.7x</td></tr>
<tr><td>Unmarshal/ReferenceFile/map-2</td><td>2.6x</td><td>2.7x</td></tr> <tr><td>Unmarshal/ReferenceFile/map-2</td><td>2.6x</td><td>2.7x</td></tr>
<tr><td>Unmarshal/ReferenceFile/struct-2</td><td>4.6x</td><td>5.1x</td></tr> <tr><td>Unmarshal/ReferenceFile/struct-2</td><td>4.6x</td><td>5.1x</td></tr>
</tbody> </tbody>
</table> </table>
<details><summary>See more</summary> <details><summary>See more</summary>
<p>The table above has the results of the most common use-cases. The table below <p>The table above has the results of the most common use-cases. The table below
@ -193,22 +193,22 @@ contains the results of all benchmarks, including unrealistic ones. It is
provided for completeness.</p> provided for completeness.</p>
<table> <table>
<thead> <thead>
<tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr> <tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
</thead> </thead>
<tbody> <tbody>
<tr><td>Marshal/SimpleDocument/map-2</td><td>1.8x</td><td>2.7x</td></tr> <tr><td>Marshal/SimpleDocument/map-2</td><td>1.8x</td><td>2.7x</td></tr>
<tr><td>Marshal/SimpleDocument/struct-2</td><td>2.7x</td><td>3.8x</td></tr> <tr><td>Marshal/SimpleDocument/struct-2</td><td>2.7x</td><td>3.8x</td></tr>
<tr><td>Unmarshal/SimpleDocument/map-2</td><td>3.8x</td><td>3.0x</td></tr> <tr><td>Unmarshal/SimpleDocument/map-2</td><td>3.8x</td><td>3.0x</td></tr>
<tr><td>Unmarshal/SimpleDocument/struct-2</td><td>5.6x</td><td>4.1x</td></tr> <tr><td>Unmarshal/SimpleDocument/struct-2</td><td>5.6x</td><td>4.1x</td></tr>
<tr><td>UnmarshalDataset/example-2</td><td>3.0x</td><td>3.2x</td></tr> <tr><td>UnmarshalDataset/example-2</td><td>3.0x</td><td>3.2x</td></tr>
<tr><td>UnmarshalDataset/code-2</td><td>2.3x</td><td>2.9x</td></tr> <tr><td>UnmarshalDataset/code-2</td><td>2.3x</td><td>2.9x</td></tr>
<tr><td>UnmarshalDataset/twitter-2</td><td>2.6x</td><td>2.7x</td></tr> <tr><td>UnmarshalDataset/twitter-2</td><td>2.6x</td><td>2.7x</td></tr>
<tr><td>UnmarshalDataset/citm_catalog-2</td><td>2.2x</td><td>2.3x</td></tr> <tr><td>UnmarshalDataset/citm_catalog-2</td><td>2.2x</td><td>2.3x</td></tr>
<tr><td>UnmarshalDataset/canada-2</td><td>1.8x</td><td>1.5x</td></tr> <tr><td>UnmarshalDataset/canada-2</td><td>1.8x</td><td>1.5x</td></tr>
<tr><td>UnmarshalDataset/config-2</td><td>4.1x</td><td>2.9x</td></tr> <tr><td>UnmarshalDataset/config-2</td><td>4.1x</td><td>2.9x</td></tr>
<tr><td>geomean</td><td>2.7x</td><td>2.8x</td></tr> <tr><td>geomean</td><td>2.7x</td><td>2.8x</td></tr>
</tbody> </tbody>
</table> </table>
<p>This table can be generated with <code>./ci.sh benchmark -a -html</code>.</p> <p>This table can be generated with <code>./ci.sh benchmark -a -html</code>.</p>
</details> </details>
@ -233,24 +233,24 @@ Go-toml provides three handy command line tools:
* `tomljson`: Reads a TOML file and outputs its JSON representation. * `tomljson`: Reads a TOML file and outputs its JSON representation.
``` ```
$ go install github.com/pelletier/go-toml/v2/cmd/tomljson@latest $ go install github.com/pelletier/go-toml/v2/cmd/tomljson@latest
$ tomljson --help $ tomljson --help
``` ```
* `jsontoml`: Reads a JSON file and outputs a TOML representation. * `jsontoml`: Reads a JSON file and outputs a TOML representation.
``` ```
$ go install github.com/pelletier/go-toml/v2/cmd/jsontoml@latest $ go install github.com/pelletier/go-toml/v2/cmd/jsontoml@latest
$ jsontoml --help $ jsontoml --help
``` ```
* `tomll`: Lints and reformats a TOML file. * `tomll`: Lints and reformats a TOML file.
``` ```
$ go install github.com/pelletier/go-toml/v2/cmd/tomll@latest $ go install github.com/pelletier/go-toml/v2/cmd/tomll@latest
$ tomll --help $ tomll --help
``` ```
### Docker image ### Docker image
@ -261,7 +261,7 @@ Those tools are also available as a [Docker image][docker]. For example, to use
docker run -i ghcr.io/pelletier/go-toml:v2 tomljson < example.toml docker run -i ghcr.io/pelletier/go-toml:v2 tomljson < example.toml
``` ```
Multiple versions are availble on [ghcr.io][docker]. Multiple versions are available on [ghcr.io][docker].
[docker]: https://github.com/pelletier/go-toml/pkgs/container/go-toml [docker]: https://github.com/pelletier/go-toml/pkgs/container/go-toml
@ -293,16 +293,16 @@ element in the interface to decode the object. For example:
```go ```go
type inner struct { type inner struct {
B interface{} B interface{}
} }
type doc struct { type doc struct {
A interface{} A interface{}
} }
d := doc{ d := doc{
A: inner{ A: inner{
B: "Before", B: "Before",
}, },
} }
data := ` data := `
@ -341,7 +341,7 @@ contained in the doc is superior to the capacity of the array. For example:
```go ```go
type doc struct { type doc struct {
A [2]string A [2]string
} }
d := doc{} d := doc{}
err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d) err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d)
@ -565,10 +565,11 @@ complete solutions exist out there.
## Versioning ## Versioning
Go-toml follows [Semantic Versioning](https://semver.org). The supported version Expect for parts explicitely marked otherwise, go-toml follows [Semantic
of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of Versioning](https://semver.org). The supported version of
this document. The last two major versions of Go are supported [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of this
(see [Go Release Policy](https://golang.org/doc/devel/release.html#policy)). document. The last two major versions of Go are supported (see [Go Release
Policy](https://golang.org/doc/devel/release.html#policy)).
## License ## License

View File

@ -149,8 +149,9 @@ func (s *SeenTracker) setExplicitFlag(parentIdx int) {
// CheckExpression takes a top-level node and checks that it does not contain // CheckExpression takes a top-level node and checks that it does not contain
// keys that have been seen in previous calls, and validates that types are // keys that have been seen in previous calls, and validates that types are
// consistent. // consistent. It returns true if it is the first time this node's key is seen.
func (s *SeenTracker) CheckExpression(node *unstable.Node) error { // Useful to clear array tables on first use.
func (s *SeenTracker) CheckExpression(node *unstable.Node) (bool, error) {
if s.entries == nil { if s.entries == nil {
s.reset() s.reset()
} }
@ -166,7 +167,7 @@ func (s *SeenTracker) CheckExpression(node *unstable.Node) error {
} }
} }
func (s *SeenTracker) checkTable(node *unstable.Node) error { func (s *SeenTracker) checkTable(node *unstable.Node) (bool, error) {
if s.currentIdx >= 0 { if s.currentIdx >= 0 {
s.setExplicitFlag(s.currentIdx) s.setExplicitFlag(s.currentIdx)
} }
@ -192,7 +193,7 @@ func (s *SeenTracker) checkTable(node *unstable.Node) error {
} else { } else {
entry := s.entries[idx] entry := s.entries[idx]
if entry.kind == valueKind { if entry.kind == valueKind {
return fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind) return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
} }
} }
parentIdx = idx parentIdx = idx
@ -201,25 +202,27 @@ func (s *SeenTracker) checkTable(node *unstable.Node) error {
k := it.Node().Data k := it.Node().Data
idx := s.find(parentIdx, k) idx := s.find(parentIdx, k)
first := false
if idx >= 0 { if idx >= 0 {
kind := s.entries[idx].kind kind := s.entries[idx].kind
if kind != tableKind { if kind != tableKind {
return fmt.Errorf("toml: key %s should be a table, not a %s", string(k), kind) return false, fmt.Errorf("toml: key %s should be a table, not a %s", string(k), kind)
} }
if s.entries[idx].explicit { if s.entries[idx].explicit {
return fmt.Errorf("toml: table %s already exists", string(k)) return false, fmt.Errorf("toml: table %s already exists", string(k))
} }
s.entries[idx].explicit = true s.entries[idx].explicit = true
} else { } else {
idx = s.create(parentIdx, k, tableKind, true, false) idx = s.create(parentIdx, k, tableKind, true, false)
first = true
} }
s.currentIdx = idx s.currentIdx = idx
return nil return first, nil
} }
func (s *SeenTracker) checkArrayTable(node *unstable.Node) error { func (s *SeenTracker) checkArrayTable(node *unstable.Node) (bool, error) {
if s.currentIdx >= 0 { if s.currentIdx >= 0 {
s.setExplicitFlag(s.currentIdx) s.setExplicitFlag(s.currentIdx)
} }
@ -242,7 +245,7 @@ func (s *SeenTracker) checkArrayTable(node *unstable.Node) error {
} else { } else {
entry := s.entries[idx] entry := s.entries[idx]
if entry.kind == valueKind { if entry.kind == valueKind {
return fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind) return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
} }
} }
@ -252,22 +255,23 @@ func (s *SeenTracker) checkArrayTable(node *unstable.Node) error {
k := it.Node().Data k := it.Node().Data
idx := s.find(parentIdx, k) idx := s.find(parentIdx, k)
if idx >= 0 { firstTime := idx < 0
if firstTime {
idx = s.create(parentIdx, k, arrayTableKind, true, false)
} else {
kind := s.entries[idx].kind kind := s.entries[idx].kind
if kind != arrayTableKind { if kind != arrayTableKind {
return fmt.Errorf("toml: key %s already exists as a %s, but should be an array table", kind, string(k)) return false, fmt.Errorf("toml: key %s already exists as a %s, but should be an array table", kind, string(k))
} }
s.clear(idx) s.clear(idx)
} else {
idx = s.create(parentIdx, k, arrayTableKind, true, false)
} }
s.currentIdx = idx s.currentIdx = idx
return nil return firstTime, nil
} }
func (s *SeenTracker) checkKeyValue(node *unstable.Node) error { func (s *SeenTracker) checkKeyValue(node *unstable.Node) (bool, error) {
parentIdx := s.currentIdx parentIdx := s.currentIdx
it := node.Key() it := node.Key()
@ -281,11 +285,11 @@ func (s *SeenTracker) checkKeyValue(node *unstable.Node) error {
} else { } else {
entry := s.entries[idx] entry := s.entries[idx]
if it.IsLast() { if it.IsLast() {
return fmt.Errorf("toml: key %s is already defined", string(k)) return false, fmt.Errorf("toml: key %s is already defined", string(k))
} else if entry.kind != tableKind { } else if entry.kind != tableKind {
return fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind) return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
} else if entry.explicit { } else if entry.explicit {
return fmt.Errorf("toml: cannot redefine table %s that has already been explicitly defined", string(k)) return false, fmt.Errorf("toml: cannot redefine table %s that has already been explicitly defined", string(k))
} }
} }
@ -303,30 +307,30 @@ func (s *SeenTracker) checkKeyValue(node *unstable.Node) error {
return s.checkArray(value) return s.checkArray(value)
} }
return nil return false, nil
} }
func (s *SeenTracker) checkArray(node *unstable.Node) error { func (s *SeenTracker) checkArray(node *unstable.Node) (first bool, err error) {
it := node.Children() it := node.Children()
for it.Next() { for it.Next() {
n := it.Node() n := it.Node()
switch n.Kind { switch n.Kind {
case unstable.InlineTable: case unstable.InlineTable:
err := s.checkInlineTable(n) first, err = s.checkInlineTable(n)
if err != nil { if err != nil {
return err return false, err
} }
case unstable.Array: case unstable.Array:
err := s.checkArray(n) first, err = s.checkArray(n)
if err != nil { if err != nil {
return err return false, err
} }
} }
} }
return nil return first, nil
} }
func (s *SeenTracker) checkInlineTable(node *unstable.Node) error { func (s *SeenTracker) checkInlineTable(node *unstable.Node) (first bool, err error) {
if pool.New == nil { if pool.New == nil {
pool.New = func() interface{} { pool.New = func() interface{} {
return &SeenTracker{} return &SeenTracker{}
@ -339,9 +343,9 @@ func (s *SeenTracker) checkInlineTable(node *unstable.Node) error {
it := node.Children() it := node.Children()
for it.Next() { for it.Next() {
n := it.Node() n := it.Node()
err := s.checkKeyValue(n) first, err = s.checkKeyValue(n)
if err != nil { if err != nil {
return err return false, err
} }
} }
@ -352,5 +356,5 @@ func (s *SeenTracker) checkInlineTable(node *unstable.Node) error {
// redefinition of its keys: check* functions cannot walk into // redefinition of its keys: check* functions cannot walk into
// a value. // a value.
pool.Put(s) pool.Put(s)
return nil return first, nil
} }

View File

@ -3,6 +3,7 @@ package toml
import ( import (
"bytes" "bytes"
"encoding" "encoding"
"encoding/json"
"fmt" "fmt"
"io" "io"
"math" "math"
@ -37,10 +38,11 @@ type Encoder struct {
w io.Writer w io.Writer
// global settings // global settings
tablesInline bool tablesInline bool
arraysMultiline bool arraysMultiline bool
indentSymbol string indentSymbol string
indentTables bool indentTables bool
marshalJsonNumbers bool
} }
// NewEncoder returns a new Encoder that writes to w. // NewEncoder returns a new Encoder that writes to w.
@ -87,6 +89,17 @@ func (enc *Encoder) SetIndentTables(indent bool) *Encoder {
return enc return enc
} }
// SetMarshalJsonNumbers forces the encoder to serialize `json.Number` as a
// float or integer instead of relying on TextMarshaler to emit a string.
//
// *Unstable:* This method does not follow the compatibility guarantees of
// semver. It can be changed or removed without a new major version being
// issued.
func (enc *Encoder) SetMarshalJsonNumbers(indent bool) *Encoder {
enc.marshalJsonNumbers = indent
return enc
}
// Encode writes a TOML representation of v to the stream. // Encode writes a TOML representation of v to the stream.
// //
// If v cannot be represented to TOML it returns an error. // If v cannot be represented to TOML it returns an error.
@ -252,6 +265,18 @@ func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, e
return append(b, x.String()...), nil return append(b, x.String()...), nil
case LocalDateTime: case LocalDateTime:
return append(b, x.String()...), nil return append(b, x.String()...), nil
case json.Number:
if enc.marshalJsonNumbers {
if x == "" { /// Useful zero value.
return append(b, "0"...), nil
} else if v, err := x.Int64(); err == nil {
return enc.encode(b, ctx, reflect.ValueOf(v))
} else if f, err := x.Float64(); err == nil {
return enc.encode(b, ctx, reflect.ValueOf(f))
} else {
return nil, fmt.Errorf("toml: unable to convert %q to int64 or float64", x)
}
}
} }
hasTextMarshaler := v.Type().Implements(textMarshalerType) hasTextMarshaler := v.Type().Implements(textMarshalerType)
@ -707,6 +732,8 @@ func walkStruct(ctx encoderCtx, t *table, v reflect.Value) {
if fieldType.Anonymous { if fieldType.Anonymous {
if fieldType.Type.Kind() == reflect.Struct { if fieldType.Type.Kind() == reflect.Struct {
walkStruct(ctx, t, f) walkStruct(ctx, t, f)
} else if fieldType.Type.Kind() == reflect.Pointer && !f.IsNil() && f.Elem().Kind() == reflect.Struct {
walkStruct(ctx, t, f.Elem())
} }
continue continue
} else { } else {

View File

@ -35,6 +35,9 @@ type Decoder struct {
// global settings // global settings
strict bool strict bool
// toggles unmarshaler interface
unmarshalerInterface bool
} }
// NewDecoder creates a new Decoder that will read from r. // NewDecoder creates a new Decoder that will read from r.
@ -54,6 +57,24 @@ func (d *Decoder) DisallowUnknownFields() *Decoder {
return d return d
} }
// EnableUnmarshalerInterface allows to enable unmarshaler interface.
//
// With this feature enabled, types implementing the unstable/Unmarshaler
// interface can be decoded from any structure of the document. It allows types
// that don't have a straightfoward TOML representation to provide their own
// decoding logic.
//
// Currently, types can only decode from a single value. Tables and array tables
// are not supported.
//
// *Unstable:* This method does not follow the compatibility guarantees of
// semver. It can be changed or removed without a new major version being
// issued.
func (d *Decoder) EnableUnmarshalerInterface() *Decoder {
d.unmarshalerInterface = true
return d
}
// Decode the whole content of r into v. // Decode the whole content of r into v.
// //
// By default, values in the document that don't exist in the target Go value // By default, values in the document that don't exist in the target Go value
@ -108,6 +129,7 @@ func (d *Decoder) Decode(v interface{}) error {
strict: strict{ strict: strict{
Enabled: d.strict, Enabled: d.strict,
}, },
unmarshalerInterface: d.unmarshalerInterface,
} }
return dec.FromParser(v) return dec.FromParser(v)
@ -127,6 +149,10 @@ type decoder struct {
// need to be skipped. // need to be skipped.
skipUntilTable bool skipUntilTable bool
// Flag indicating that the current array/slice table should be cleared because
// it is the first encounter of an array table.
clearArrayTable bool
// Tracks position in Go arrays. // Tracks position in Go arrays.
// This is used when decoding [[array tables]] into Go arrays. Given array // This is used when decoding [[array tables]] into Go arrays. Given array
// tables are separate TOML expression, we need to keep track of where we // tables are separate TOML expression, we need to keep track of where we
@ -139,6 +165,9 @@ type decoder struct {
// Strict mode // Strict mode
strict strict strict strict
// Flag that enables/disables unmarshaler interface.
unmarshalerInterface bool
// Current context for the error. // Current context for the error.
errorContext *errorContext errorContext *errorContext
} }
@ -246,9 +275,10 @@ Rules for the unmarshal code:
func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) error { func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) error {
var x reflect.Value var x reflect.Value
var err error var err error
var first bool // used for to clear array tables on first use
if !(d.skipUntilTable && expr.Kind == unstable.KeyValue) { if !(d.skipUntilTable && expr.Kind == unstable.KeyValue) {
err = d.seen.CheckExpression(expr) first, err = d.seen.CheckExpression(expr)
if err != nil { if err != nil {
return err return err
} }
@ -267,6 +297,7 @@ func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) err
case unstable.ArrayTable: case unstable.ArrayTable:
d.skipUntilTable = false d.skipUntilTable = false
d.strict.EnterArrayTable(expr) d.strict.EnterArrayTable(expr)
d.clearArrayTable = first
x, err = d.handleArrayTable(expr.Key(), v) x, err = d.handleArrayTable(expr.Key(), v)
default: default:
panic(fmt.Errorf("parser should not permit expression of kind %s at document root", expr.Kind)) panic(fmt.Errorf("parser should not permit expression of kind %s at document root", expr.Kind))
@ -307,6 +338,10 @@ func (d *decoder) handleArrayTableCollectionLast(key unstable.Iterator, v reflec
reflect.Copy(nelem, elem) reflect.Copy(nelem, elem)
elem = nelem elem = nelem
} }
if d.clearArrayTable && elem.Len() > 0 {
elem.SetLen(0)
d.clearArrayTable = false
}
} }
return d.handleArrayTableCollectionLast(key, elem) return d.handleArrayTableCollectionLast(key, elem)
case reflect.Ptr: case reflect.Ptr:
@ -325,6 +360,10 @@ func (d *decoder) handleArrayTableCollectionLast(key unstable.Iterator, v reflec
return v, nil return v, nil
case reflect.Slice: case reflect.Slice:
if d.clearArrayTable && v.Len() > 0 {
v.SetLen(0)
d.clearArrayTable = false
}
elemType := v.Type().Elem() elemType := v.Type().Elem()
var elem reflect.Value var elem reflect.Value
if elemType.Kind() == reflect.Interface { if elemType.Kind() == reflect.Interface {
@ -576,7 +615,7 @@ func (d *decoder) handleKeyValues(v reflect.Value) (reflect.Value, error) {
break break
} }
err := d.seen.CheckExpression(expr) _, err := d.seen.CheckExpression(expr)
if err != nil { if err != nil {
return reflect.Value{}, err return reflect.Value{}, err
} }
@ -634,6 +673,14 @@ func (d *decoder) handleValue(value *unstable.Node, v reflect.Value) error {
v = initAndDereferencePointer(v) v = initAndDereferencePointer(v)
} }
if d.unmarshalerInterface {
if v.CanAddr() && v.Addr().CanInterface() {
if outi, ok := v.Addr().Interface().(unstable.Unmarshaler); ok {
return outi.UnmarshalTOML(value)
}
}
}
ok, err := d.tryTextUnmarshaler(value, v) ok, err := d.tryTextUnmarshaler(value, v)
if ok || err != nil { if ok || err != nil {
return err return err

View File

@ -0,0 +1,7 @@
package unstable
// The Unmarshaler interface may be implemented by types to customize their
// behavior when being unmarshaled from a TOML document.
type Unmarshaler interface {
UnmarshalTOML(value *Node) error
}

View File

@ -209,25 +209,37 @@ func Insert[S ~[]E, E any](s S, i int, v ...E) S {
return s return s
} }
// Delete removes the elements s[i:j] from s, returning the modified slice. // clearSlice sets all elements up to the length of s to the zero value of E.
// Delete panics if s[i:j] is not a valid slice of s. // We may use the builtin clear func instead, and remove clearSlice, when upgrading
// Delete is O(len(s)-j), so if many items must be deleted, it is better to // to Go 1.21+.
// make a single call deleting them all together than to delete one at a time. func clearSlice[S ~[]E, E any](s S) {
// Delete might not modify the elements s[len(s)-(j-i):len(s)]. If those var zero E
// elements contain pointers you might consider zeroing those elements so that for i := range s {
// objects they reference can be garbage collected. s[i] = zero
func Delete[S ~[]E, E any](s S, i, j int) S { }
_ = s[i:j] // bounds check }
return append(s[:i], s[j:]...) // Delete removes the elements s[i:j] from s, returning the modified slice.
// Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
// Delete is O(len(s)-i), so if many items must be deleted, it is better to
// make a single call deleting them all together than to delete one at a time.
// Delete zeroes the elements s[len(s)-(j-i):len(s)].
func Delete[S ~[]E, E any](s S, i, j int) S {
_ = s[i:j:len(s)] // bounds check
if i == j {
return s
}
oldlen := len(s)
s = append(s[:i], s[j:]...)
clearSlice(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC
return s
} }
// DeleteFunc removes any elements from s for which del returns true, // DeleteFunc removes any elements from s for which del returns true,
// returning the modified slice. // returning the modified slice.
// When DeleteFunc removes m elements, it might not modify the elements // DeleteFunc zeroes the elements between the new length and the original length.
// s[len(s)-m:len(s)]. If those elements contain pointers you might consider
// zeroing those elements so that objects they reference can be garbage
// collected.
func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S { func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
i := IndexFunc(s, del) i := IndexFunc(s, del)
if i == -1 { if i == -1 {
@ -240,11 +252,13 @@ func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
i++ i++
} }
} }
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
return s[:i] return s[:i]
} }
// Replace replaces the elements s[i:j] by the given v, and returns the // Replace replaces the elements s[i:j] by the given v, and returns the
// modified slice. Replace panics if s[i:j] is not a valid slice of s. // modified slice. Replace panics if s[i:j] is not a valid slice of s.
// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length.
func Replace[S ~[]E, E any](s S, i, j int, v ...E) S { func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
_ = s[i:j] // verify that i:j is a valid subslice _ = s[i:j] // verify that i:j is a valid subslice
@ -272,6 +286,7 @@ func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
if i+len(v) != j { if i+len(v) != j {
copy(r[i+len(v):], s[j:]) copy(r[i+len(v):], s[j:])
} }
clearSlice(s[tot:]) // zero/nil out the obsolete elements, for GC
return r return r
} }
@ -345,9 +360,7 @@ func Clone[S ~[]E, E any](s S) S {
// This is like the uniq command found on Unix. // This is like the uniq command found on Unix.
// Compact modifies the contents of the slice s and returns the modified slice, // Compact modifies the contents of the slice s and returns the modified slice,
// which may have a smaller length. // which may have a smaller length.
// When Compact discards m elements in total, it might not modify the elements // Compact zeroes the elements between the new length and the original length.
// s[len(s)-m:len(s)]. If those elements contain pointers you might consider
// zeroing those elements so that objects they reference can be garbage collected.
func Compact[S ~[]E, E comparable](s S) S { func Compact[S ~[]E, E comparable](s S) S {
if len(s) < 2 { if len(s) < 2 {
return s return s
@ -361,11 +374,13 @@ func Compact[S ~[]E, E comparable](s S) S {
i++ i++
} }
} }
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
return s[:i] return s[:i]
} }
// CompactFunc is like [Compact] but uses an equality function to compare elements. // CompactFunc is like [Compact] but uses an equality function to compare elements.
// For runs of elements that compare equal, CompactFunc keeps the first one. // For runs of elements that compare equal, CompactFunc keeps the first one.
// CompactFunc zeroes the elements between the new length and the original length.
func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S { func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
if len(s) < 2 { if len(s) < 2 {
return s return s
@ -379,6 +394,7 @@ func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
i++ i++
} }
} }
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
return s[:i] return s[:i]
} }

View File

@ -47,7 +47,7 @@ import (
func Find(importPath, srcDir string) (filename, path string) { func Find(importPath, srcDir string) (filename, path string) {
cmd := exec.Command("go", "list", "-json", "-export", "--", importPath) cmd := exec.Command("go", "list", "-json", "-export", "--", importPath)
cmd.Dir = srcDir cmd.Dir = srcDir
out, err := cmd.CombinedOutput() out, err := cmd.Output()
if err != nil { if err != nil {
return "", "" return "", ""
} }

View File

@ -15,22 +15,10 @@ Load passes most patterns directly to the underlying build tool.
The default build tool is the go command. The default build tool is the go command.
Its supported patterns are described at Its supported patterns are described at
https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns. https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns.
Other build systems may be supported by providing a "driver";
see [The driver protocol].
Load may be used in Go projects that use alternative build systems, by All patterns with the prefix "query=", where query is a
installing an appropriate "driver" program for the build system and
specifying its location in the GOPACKAGESDRIVER environment variable.
For example,
https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration
explains how to use the driver for Bazel.
The driver program is responsible for interpreting patterns in its
preferred notation and reporting information about the packages that
they identify.
(See driverRequest and driverResponse types for the JSON
schema used by the protocol.
Though the protocol is supported, these types are currently unexported;
see #64608 for a proposal to publish them.)
Regardless of driver, all patterns with the prefix "query=", where query is a
non-empty string of letters from [a-z], are reserved and may be non-empty string of letters from [a-z], are reserved and may be
interpreted as query operators. interpreted as query operators.
@ -86,7 +74,29 @@ for details.
Most tools should pass their command-line arguments (after any flags) Most tools should pass their command-line arguments (after any flags)
uninterpreted to [Load], so that it can interpret them uninterpreted to [Load], so that it can interpret them
according to the conventions of the underlying build system. according to the conventions of the underlying build system.
See the Example function for typical usage. See the Example function for typical usage.
# The driver protocol
[Load] may be used to load Go packages even in Go projects that use
alternative build systems, by installing an appropriate "driver"
program for the build system and specifying its location in the
GOPACKAGESDRIVER environment variable.
For example,
https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration
explains how to use the driver for Bazel.
The driver program is responsible for interpreting patterns in its
preferred notation and reporting information about the packages that
those patterns identify. Drivers must also support the special "file="
and "pattern=" patterns described above.
The patterns are provided as positional command-line arguments. A
JSON-encoded [DriverRequest] message providing additional information
is written to the driver's standard input. The driver must write a
JSON-encoded [DriverResponse] message to its standard output. (This
message differs from the JSON schema produced by 'go list'.)
*/ */
package packages // import "golang.org/x/tools/go/packages" package packages // import "golang.org/x/tools/go/packages"

View File

@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// This file enables an external tool to intercept package requests.
// If the tool is present then its results are used in preference to
// the go list command.
package packages package packages
// This file defines the protocol that enables an external "driver"
// tool to supply package metadata in place of 'go list'.
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
@ -17,31 +16,71 @@ import (
"strings" "strings"
) )
// The Driver Protocol // DriverRequest defines the schema of a request for package metadata
// from an external driver program. The JSON-encoded DriverRequest
// message is provided to the driver program's standard input. The
// query patterns are provided as command-line arguments.
// //
// The driver, given the inputs to a call to Load, returns metadata about the packages specified. // See the package documentation for an overview.
// This allows for different build systems to support go/packages by telling go/packages how the type DriverRequest struct {
// packages' source is organized.
// The driver is a binary, either specified by the GOPACKAGESDRIVER environment variable or in
// the path as gopackagesdriver. It's given the inputs to load in its argv. See the package
// documentation in doc.go for the full description of the patterns that need to be supported.
// A driver receives as a JSON-serialized driverRequest struct in standard input and will
// produce a JSON-serialized driverResponse (see definition in packages.go) in its standard output.
// driverRequest is used to provide the portion of Load's Config that is needed by a driver.
type driverRequest struct {
Mode LoadMode `json:"mode"` Mode LoadMode `json:"mode"`
// Env specifies the environment the underlying build system should be run in. // Env specifies the environment the underlying build system should be run in.
Env []string `json:"env"` Env []string `json:"env"`
// BuildFlags are flags that should be passed to the underlying build system. // BuildFlags are flags that should be passed to the underlying build system.
BuildFlags []string `json:"build_flags"` BuildFlags []string `json:"build_flags"`
// Tests specifies whether the patterns should also return test packages. // Tests specifies whether the patterns should also return test packages.
Tests bool `json:"tests"` Tests bool `json:"tests"`
// Overlay maps file paths (relative to the driver's working directory) to the byte contents // Overlay maps file paths (relative to the driver's working directory) to the byte contents
// of overlay files. // of overlay files.
Overlay map[string][]byte `json:"overlay"` Overlay map[string][]byte `json:"overlay"`
} }
// DriverResponse defines the schema of a response from an external
// driver program, providing the results of a query for package
// metadata. The driver program must write a JSON-encoded
// DriverResponse message to its standard output.
//
// See the package documentation for an overview.
type DriverResponse struct {
// NotHandled is returned if the request can't be handled by the current
// driver. If an external driver returns a response with NotHandled, the
// rest of the DriverResponse is ignored, and go/packages will fallback
// to the next driver. If go/packages is extended in the future to support
// lists of multiple drivers, go/packages will fall back to the next driver.
NotHandled bool
// Compiler and Arch are the arguments pass of types.SizesFor
// to get a types.Sizes to use when type checking.
Compiler string
Arch string
// Roots is the set of package IDs that make up the root packages.
// We have to encode this separately because when we encode a single package
// we cannot know if it is one of the roots as that requires knowledge of the
// graph it is part of.
Roots []string `json:",omitempty"`
// Packages is the full set of packages in the graph.
// The packages are not connected into a graph.
// The Imports if populated will be stubs that only have their ID set.
// Imports will be connected and then type and syntax information added in a
// later pass (see refine).
Packages []*Package
// GoVersion is the minor version number used by the driver
// (e.g. the go command on the PATH) when selecting .go files.
// Zero means unknown.
GoVersion int
}
// driver is the type for functions that query the build system for the
// packages named by the patterns.
type driver func(cfg *Config, patterns ...string) (*DriverResponse, error)
// findExternalDriver returns the file path of a tool that supplies // findExternalDriver returns the file path of a tool that supplies
// the build system package structure, or "" if not found." // the build system package structure, or "" if not found."
// If GOPACKAGESDRIVER is set in the environment findExternalTool returns its // If GOPACKAGESDRIVER is set in the environment findExternalTool returns its
@ -64,8 +103,8 @@ func findExternalDriver(cfg *Config) driver {
return nil return nil
} }
} }
return func(cfg *Config, words ...string) (*driverResponse, error) { return func(cfg *Config, words ...string) (*DriverResponse, error) {
req, err := json.Marshal(driverRequest{ req, err := json.Marshal(DriverRequest{
Mode: cfg.Mode, Mode: cfg.Mode,
Env: cfg.Env, Env: cfg.Env,
BuildFlags: cfg.BuildFlags, BuildFlags: cfg.BuildFlags,
@ -92,7 +131,7 @@ func findExternalDriver(cfg *Config) driver {
fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr) fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr)
} }
var response driverResponse var response DriverResponse
if err := json.Unmarshal(buf.Bytes(), &response); err != nil { if err := json.Unmarshal(buf.Bytes(), &response); err != nil {
return nil, err return nil, err
} }

View File

@ -35,23 +35,23 @@ type goTooOldError struct {
error error
} }
// responseDeduper wraps a driverResponse, deduplicating its contents. // responseDeduper wraps a DriverResponse, deduplicating its contents.
type responseDeduper struct { type responseDeduper struct {
seenRoots map[string]bool seenRoots map[string]bool
seenPackages map[string]*Package seenPackages map[string]*Package
dr *driverResponse dr *DriverResponse
} }
func newDeduper() *responseDeduper { func newDeduper() *responseDeduper {
return &responseDeduper{ return &responseDeduper{
dr: &driverResponse{}, dr: &DriverResponse{},
seenRoots: map[string]bool{}, seenRoots: map[string]bool{},
seenPackages: map[string]*Package{}, seenPackages: map[string]*Package{},
} }
} }
// addAll fills in r with a driverResponse. // addAll fills in r with a DriverResponse.
func (r *responseDeduper) addAll(dr *driverResponse) { func (r *responseDeduper) addAll(dr *DriverResponse) {
for _, pkg := range dr.Packages { for _, pkg := range dr.Packages {
r.addPackage(pkg) r.addPackage(pkg)
} }
@ -128,7 +128,7 @@ func (state *golistState) mustGetEnv() map[string]string {
// goListDriver uses the go list command to interpret the patterns and produce // goListDriver uses the go list command to interpret the patterns and produce
// the build system package structure. // the build system package structure.
// See driver for more details. // See driver for more details.
func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) { func goListDriver(cfg *Config, patterns ...string) (_ *DriverResponse, err error) {
// Make sure that any asynchronous go commands are killed when we return. // Make sure that any asynchronous go commands are killed when we return.
parentCtx := cfg.Context parentCtx := cfg.Context
if parentCtx == nil { if parentCtx == nil {
@ -146,16 +146,18 @@ func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
} }
// Fill in response.Sizes asynchronously if necessary. // Fill in response.Sizes asynchronously if necessary.
var sizeserr error
var sizeswg sync.WaitGroup
if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 { if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 {
sizeswg.Add(1) errCh := make(chan error)
go func() { go func() {
compiler, arch, err := packagesdriver.GetSizesForArgsGolist(ctx, state.cfgInvocation(), cfg.gocmdRunner) compiler, arch, err := packagesdriver.GetSizesForArgsGolist(ctx, state.cfgInvocation(), cfg.gocmdRunner)
sizeserr = err
response.dr.Compiler = compiler response.dr.Compiler = compiler
response.dr.Arch = arch response.dr.Arch = arch
sizeswg.Done() errCh <- err
}()
defer func() {
if sizesErr := <-errCh; sizesErr != nil {
err = sizesErr
}
}() }()
} }
@ -208,10 +210,7 @@ extractQueries:
} }
} }
sizeswg.Wait() // (We may yet return an error due to defer.)
if sizeserr != nil {
return nil, sizeserr
}
return response.dr, nil return response.dr, nil
} }
@ -266,7 +265,7 @@ func (state *golistState) runContainsQueries(response *responseDeduper, queries
// adhocPackage attempts to load or construct an ad-hoc package for a given // adhocPackage attempts to load or construct an ad-hoc package for a given
// query, if the original call to the driver produced inadequate results. // query, if the original call to the driver produced inadequate results.
func (state *golistState) adhocPackage(pattern, query string) (*driverResponse, error) { func (state *golistState) adhocPackage(pattern, query string) (*DriverResponse, error) {
response, err := state.createDriverResponse(query) response, err := state.createDriverResponse(query)
if err != nil { if err != nil {
return nil, err return nil, err
@ -357,7 +356,7 @@ func otherFiles(p *jsonPackage) [][]string {
// createDriverResponse uses the "go list" command to expand the pattern // createDriverResponse uses the "go list" command to expand the pattern
// words and return a response for the specified packages. // words and return a response for the specified packages.
func (state *golistState) createDriverResponse(words ...string) (*driverResponse, error) { func (state *golistState) createDriverResponse(words ...string) (*DriverResponse, error) {
// go list uses the following identifiers in ImportPath and Imports: // go list uses the following identifiers in ImportPath and Imports:
// //
// "p" -- importable package or main (command) // "p" -- importable package or main (command)
@ -384,7 +383,7 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse
pkgs := make(map[string]*Package) pkgs := make(map[string]*Package)
additionalErrors := make(map[string][]Error) additionalErrors := make(map[string][]Error)
// Decode the JSON and convert it to Package form. // Decode the JSON and convert it to Package form.
response := &driverResponse{ response := &DriverResponse{
GoVersion: goVersion, GoVersion: goVersion,
} }
for dec := json.NewDecoder(buf); dec.More(); { for dec := json.NewDecoder(buf); dec.More(); {

View File

@ -206,43 +206,6 @@ type Config struct {
Overlay map[string][]byte Overlay map[string][]byte
} }
// driver is the type for functions that query the build system for the
// packages named by the patterns.
type driver func(cfg *Config, patterns ...string) (*driverResponse, error)
// driverResponse contains the results for a driver query.
type driverResponse struct {
// NotHandled is returned if the request can't be handled by the current
// driver. If an external driver returns a response with NotHandled, the
// rest of the driverResponse is ignored, and go/packages will fallback
// to the next driver. If go/packages is extended in the future to support
// lists of multiple drivers, go/packages will fall back to the next driver.
NotHandled bool
// Compiler and Arch are the arguments pass of types.SizesFor
// to get a types.Sizes to use when type checking.
Compiler string
Arch string
// Roots is the set of package IDs that make up the root packages.
// We have to encode this separately because when we encode a single package
// we cannot know if it is one of the roots as that requires knowledge of the
// graph it is part of.
Roots []string `json:",omitempty"`
// Packages is the full set of packages in the graph.
// The packages are not connected into a graph.
// The Imports if populated will be stubs that only have their ID set.
// Imports will be connected and then type and syntax information added in a
// later pass (see refine).
Packages []*Package
// GoVersion is the minor version number used by the driver
// (e.g. the go command on the PATH) when selecting .go files.
// Zero means unknown.
GoVersion int
}
// Load loads and returns the Go packages named by the given patterns. // Load loads and returns the Go packages named by the given patterns.
// //
// Config specifies loading options; // Config specifies loading options;
@ -291,7 +254,7 @@ func Load(cfg *Config, patterns ...string) ([]*Package, error) {
// no external driver, or the driver returns a response with NotHandled set, // no external driver, or the driver returns a response with NotHandled set,
// defaultDriver will fall back to the go list driver. // defaultDriver will fall back to the go list driver.
// The boolean result indicates that an external driver handled the request. // The boolean result indicates that an external driver handled the request.
func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, bool, error) { func defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, error) {
if driver := findExternalDriver(cfg); driver != nil { if driver := findExternalDriver(cfg); driver != nil {
response, err := driver(cfg, patterns...) response, err := driver(cfg, patterns...)
if err != nil { if err != nil {
@ -303,7 +266,10 @@ func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, bool, erro
} }
response, err := goListDriver(cfg, patterns...) response, err := goListDriver(cfg, patterns...)
return response, false, err if err != nil {
return nil, false, err
}
return response, false, nil
} }
// A Package describes a loaded Go package. // A Package describes a loaded Go package.
@ -648,7 +614,7 @@ func newLoader(cfg *Config) *loader {
// refine connects the supplied packages into a graph and then adds type // refine connects the supplied packages into a graph and then adds type
// and syntax information as requested by the LoadMode. // and syntax information as requested by the LoadMode.
func (ld *loader) refine(response *driverResponse) ([]*Package, error) { func (ld *loader) refine(response *DriverResponse) ([]*Package, error) {
roots := response.Roots roots := response.Roots
rootMap := make(map[string]int, len(roots)) rootMap := make(map[string]int, len(roots))
for i, root := range roots { for i, root := range roots {

View File

@ -29,9 +29,13 @@ import (
"strconv" "strconv"
"strings" "strings"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/typeparams" "golang.org/x/tools/internal/typeparams"
"golang.org/x/tools/internal/typesinternal"
) )
// TODO(adonovan): think about generic aliases.
// A Path is an opaque name that identifies a types.Object // A Path is an opaque name that identifies a types.Object
// relative to its package. Conceptually, the name consists of a // relative to its package. Conceptually, the name consists of a
// sequence of destructuring operations applied to the package scope // sequence of destructuring operations applied to the package scope
@ -223,7 +227,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
// Reject obviously non-viable cases. // Reject obviously non-viable cases.
switch obj := obj.(type) { switch obj := obj.(type) {
case *types.TypeName: case *types.TypeName:
if _, ok := obj.Type().(*types.TypeParam); !ok { if _, ok := aliases.Unalias(obj.Type()).(*types.TypeParam); !ok {
// With the exception of type parameters, only package-level type names // With the exception of type parameters, only package-level type names
// have a path. // have a path.
return "", fmt.Errorf("no path for %v", obj) return "", fmt.Errorf("no path for %v", obj)
@ -310,7 +314,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
} }
// Inspect declared methods of defined types. // Inspect declared methods of defined types.
if T, ok := o.Type().(*types.Named); ok { if T, ok := aliases.Unalias(o.Type()).(*types.Named); ok {
path = append(path, opType) path = append(path, opType)
// The method index here is always with respect // The method index here is always with respect
// to the underlying go/types data structures, // to the underlying go/types data structures,
@ -395,13 +399,8 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
return "", false return "", false
} }
recvT := meth.Type().(*types.Signature).Recv().Type() _, named := typesinternal.ReceiverNamed(meth.Type().(*types.Signature).Recv())
if ptr, ok := recvT.(*types.Pointer); ok { if named == nil {
recvT = ptr.Elem()
}
named, ok := recvT.(*types.Named)
if !ok {
return "", false return "", false
} }
@ -444,6 +443,8 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
// nil, it will be allocated as necessary. // nil, it will be allocated as necessary.
func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte { func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte {
switch T := T.(type) { switch T := T.(type) {
case *aliases.Alias:
return find(obj, aliases.Unalias(T), path, seen)
case *types.Basic, *types.Named: case *types.Basic, *types.Named:
// Named types belonging to pkg were handled already, // Named types belonging to pkg were handled already,
// so T must belong to another package. No path. // so T must belong to another package. No path.
@ -616,6 +617,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
// Inv: t != nil, obj == nil // Inv: t != nil, obj == nil
t = aliases.Unalias(t)
switch code { switch code {
case opElem: case opElem:
hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map

28
vendor/golang.org/x/tools/internal/aliases/aliases.go generated vendored Normal file
View File

@ -0,0 +1,28 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package aliases
import (
"go/token"
"go/types"
)
// Package aliases defines backward compatible shims
// for the types.Alias type representation added in 1.22.
// This defines placeholders for x/tools until 1.26.
// NewAlias creates a new TypeName in Package pkg that
// is an alias for the type rhs.
//
// When GoVersion>=1.22 and GODEBUG=gotypesalias=1,
// the Type() of the return value is a *types.Alias.
func NewAlias(pos token.Pos, pkg *types.Package, name string, rhs types.Type) *types.TypeName {
if enabled() {
tname := types.NewTypeName(pos, pkg, name, nil)
newAlias(tname, rhs)
return tname
}
return types.NewTypeName(pos, pkg, name, rhs)
}

View File

@ -0,0 +1,30 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !go1.22
// +build !go1.22
package aliases
import (
"go/types"
)
// Alias is a placeholder for a go/types.Alias for <=1.21.
// It will never be created by go/types.
type Alias struct{}
func (*Alias) String() string { panic("unreachable") }
func (*Alias) Underlying() types.Type { panic("unreachable") }
func (*Alias) Obj() *types.TypeName { panic("unreachable") }
// Unalias returns the type t for go <=1.21.
func Unalias(t types.Type) types.Type { return t }
// Always false for go <=1.21. Ignores GODEBUG.
func enabled() bool { return false }
func newAlias(name *types.TypeName, rhs types.Type) *Alias { panic("unreachable") }

View File

@ -0,0 +1,72 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.22
// +build go1.22
package aliases
import (
"go/ast"
"go/parser"
"go/token"
"go/types"
"os"
"strings"
"sync"
)
// Alias is an alias of types.Alias.
type Alias = types.Alias
// Unalias is a wrapper of types.Unalias.
func Unalias(t types.Type) types.Type { return types.Unalias(t) }
// newAlias is an internal alias around types.NewAlias.
// Direct usage is discouraged as the moment.
// Try to use NewAlias instead.
func newAlias(tname *types.TypeName, rhs types.Type) *Alias {
a := types.NewAlias(tname, rhs)
// TODO(go.dev/issue/65455): Remove kludgy workaround to set a.actual as a side-effect.
Unalias(a)
return a
}
// enabled returns true when types.Aliases are enabled.
func enabled() bool {
// Use the gotypesalias value in GODEBUG if set.
godebug := os.Getenv("GODEBUG")
value := -1 // last set value.
for _, f := range strings.Split(godebug, ",") {
switch f {
case "gotypesalias=1":
value = 1
case "gotypesalias=0":
value = 0
}
}
switch value {
case 0:
return false
case 1:
return true
default:
return aliasesDefault()
}
}
// aliasesDefault reports if aliases are enabled by default.
func aliasesDefault() bool {
// Dynamically check if Aliases will be produced from go/types.
aliasesDefaultOnce.Do(func() {
fset := token.NewFileSet()
f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", 0)
pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil)
_, gotypesaliasDefault = pkg.Scope().Lookup("A").Type().(*types.Alias)
})
return gotypesaliasDefault
}
var gotypesaliasDefault bool
var aliasesDefaultOnce sync.Once

View File

@ -259,13 +259,6 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
return return
} }
func deref(typ types.Type) types.Type {
if p, _ := typ.(*types.Pointer); p != nil {
return p.Elem()
}
return typ
}
type byPath []*types.Package type byPath []*types.Package
func (a byPath) Len() int { return len(a) } func (a byPath) Len() int { return len(a) }

View File

@ -23,6 +23,7 @@ import (
"strings" "strings"
"golang.org/x/tools/go/types/objectpath" "golang.org/x/tools/go/types/objectpath"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/tokeninternal" "golang.org/x/tools/internal/tokeninternal"
) )
@ -506,13 +507,13 @@ func (p *iexporter) doDecl(obj types.Object) {
case *types.TypeName: case *types.TypeName:
t := obj.Type() t := obj.Type()
if tparam, ok := t.(*types.TypeParam); ok { if tparam, ok := aliases.Unalias(t).(*types.TypeParam); ok {
w.tag('P') w.tag('P')
w.pos(obj.Pos()) w.pos(obj.Pos())
constraint := tparam.Constraint() constraint := tparam.Constraint()
if p.version >= iexportVersionGo1_18 { if p.version >= iexportVersionGo1_18 {
implicit := false implicit := false
if iface, _ := constraint.(*types.Interface); iface != nil { if iface, _ := aliases.Unalias(constraint).(*types.Interface); iface != nil {
implicit = iface.IsImplicit() implicit = iface.IsImplicit()
} }
w.bool(implicit) w.bool(implicit)
@ -738,6 +739,8 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
}() }()
} }
switch t := t.(type) { switch t := t.(type) {
// TODO(adonovan): support types.Alias.
case *types.Named: case *types.Named:
if targs := t.TypeArgs(); targs.Len() > 0 { if targs := t.TypeArgs(); targs.Len() > 0 {
w.startType(instanceType) w.startType(instanceType)
@ -843,7 +846,7 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
ft := t.EmbeddedType(i) ft := t.EmbeddedType(i)
tPkg := pkg tPkg := pkg
if named, _ := ft.(*types.Named); named != nil { if named, _ := aliases.Unalias(ft).(*types.Named); named != nil {
w.pos(named.Obj().Pos()) w.pos(named.Obj().Pos())
} else { } else {
w.pos(token.NoPos) w.pos(token.NoPos)

View File

@ -22,6 +22,8 @@ import (
"strings" "strings"
"golang.org/x/tools/go/types/objectpath" "golang.org/x/tools/go/types/objectpath"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/typesinternal"
) )
type intReader struct { type intReader struct {
@ -224,6 +226,7 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte
// Gather the relevant packages from the manifest. // Gather the relevant packages from the manifest.
items := make([]GetPackagesItem, r.uint64()) items := make([]GetPackagesItem, r.uint64())
uniquePkgPaths := make(map[string]bool)
for i := range items { for i := range items {
pkgPathOff := r.uint64() pkgPathOff := r.uint64()
pkgPath := p.stringAt(pkgPathOff) pkgPath := p.stringAt(pkgPathOff)
@ -248,6 +251,12 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte
} }
items[i].nameIndex = nameIndex items[i].nameIndex = nameIndex
uniquePkgPaths[pkgPath] = true
}
// Debugging #63822; hypothesis: there are duplicate PkgPaths.
if len(uniquePkgPaths) != len(items) {
reportf("found duplicate PkgPaths while reading export data manifest: %v", items)
} }
// Request packages all at once from the client, // Request packages all at once from the client,
@ -515,7 +524,7 @@ func canReuse(def *types.Named, rhs types.Type) bool {
if def == nil { if def == nil {
return true return true
} }
iface, _ := rhs.(*types.Interface) iface, _ := aliases.Unalias(rhs).(*types.Interface)
if iface == nil { if iface == nil {
return true return true
} }
@ -580,14 +589,13 @@ func (r *importReader) obj(name string) {
// If the receiver has any targs, set those as the // If the receiver has any targs, set those as the
// rparams of the method (since those are the // rparams of the method (since those are the
// typeparams being used in the method sig/body). // typeparams being used in the method sig/body).
base := baseType(recv.Type()) _, recvNamed := typesinternal.ReceiverNamed(recv)
assert(base != nil) targs := recvNamed.TypeArgs()
targs := base.TypeArgs()
var rparams []*types.TypeParam var rparams []*types.TypeParam
if targs.Len() > 0 { if targs.Len() > 0 {
rparams = make([]*types.TypeParam, targs.Len()) rparams = make([]*types.TypeParam, targs.Len())
for i := range rparams { for i := range rparams {
rparams[i] = targs.At(i).(*types.TypeParam) rparams[i] = aliases.Unalias(targs.At(i)).(*types.TypeParam)
} }
} }
msig := r.signature(recv, rparams, nil) msig := r.signature(recv, rparams, nil)
@ -617,7 +625,7 @@ func (r *importReader) obj(name string) {
} }
constraint := r.typ() constraint := r.typ()
if implicit { if implicit {
iface, _ := constraint.(*types.Interface) iface, _ := aliases.Unalias(constraint).(*types.Interface)
if iface == nil { if iface == nil {
errorf("non-interface constraint marked implicit") errorf("non-interface constraint marked implicit")
} }
@ -824,7 +832,7 @@ func (r *importReader) typ() types.Type {
} }
func isInterface(t types.Type) bool { func isInterface(t types.Type) bool {
_, ok := t.(*types.Interface) _, ok := aliases.Unalias(t).(*types.Interface)
return ok return ok
} }
@ -1023,7 +1031,7 @@ func (r *importReader) tparamList() []*types.TypeParam {
for i := range xs { for i := range xs {
// Note: the standard library importer is tolerant of nil types here, // Note: the standard library importer is tolerant of nil types here,
// though would panic in SetTypeParams. // though would panic in SetTypeParams.
xs[i] = r.typ().(*types.TypeParam) xs[i] = aliases.Unalias(r.typ()).(*types.TypeParam)
} }
return xs return xs
} }
@ -1070,13 +1078,3 @@ func (r *importReader) byte() byte {
} }
return x return x
} }
func baseType(typ types.Type) *types.Named {
// pointer receivers are never types.Named types
if p, _ := typ.(*types.Pointer); p != nil {
typ = p.Elem()
}
// receiver base types are always (possibly generic) types.Named types
n, _ := typ.(*types.Named)
return n
}

View File

@ -1,16 +0,0 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !go1.18
// +build !go1.18
package gcimporter
import "go/types"
const iexportVersion = iexportVersionGo1_11
func additionalPredeclared() []types.Type {
return nil
}

View File

@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build go1.18
// +build go1.18
package gcimporter package gcimporter
import "go/types" import "go/types"

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !(go1.18 && goexperiment.unified) //go:build !goexperiment.unified
// +build !go1.18 !goexperiment.unified // +build !goexperiment.unified
package gcimporter package gcimporter

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build go1.18 && goexperiment.unified //go:build goexperiment.unified
// +build go1.18,goexperiment.unified // +build goexperiment.unified
package gcimporter package gcimporter

View File

@ -1,19 +0,0 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !go1.18
// +build !go1.18
package gcimporter
import (
"fmt"
"go/token"
"go/types"
)
func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
err = fmt.Errorf("go/tools compiled with a Go version earlier than 1.18 cannot read unified IR export data")
return
}

View File

@ -4,9 +4,6 @@
// Derived from go/internal/gcimporter/ureader.go // Derived from go/internal/gcimporter/ureader.go
//go:build go1.18
// +build go1.18
package gcimporter package gcimporter
import ( import (
@ -16,6 +13,7 @@ import (
"sort" "sort"
"strings" "strings"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/pkgbits" "golang.org/x/tools/internal/pkgbits"
) )
@ -553,7 +551,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
// If the underlying type is an interface, we need to // If the underlying type is an interface, we need to
// duplicate its methods so we can replace the receiver // duplicate its methods so we can replace the receiver
// parameter's type (#49906). // parameter's type (#49906).
if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 { if iface, ok := aliases.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 {
methods := make([]*types.Func, iface.NumExplicitMethods()) methods := make([]*types.Func, iface.NumExplicitMethods())
for i := range methods { for i := range methods {
fn := iface.ExplicitMethod(i) fn := iface.ExplicitMethod(i)

View File

@ -34,30 +34,16 @@ func GetLines(file *token.File) []int {
lines []int lines []int
_ []struct{} _ []struct{}
} }
type tokenFile118 struct {
_ *token.FileSet // deleted in go1.19
tokenFile119
}
type uP = unsafe.Pointer if unsafe.Sizeof(*file) != unsafe.Sizeof(tokenFile119{}) {
switch unsafe.Sizeof(*file) {
case unsafe.Sizeof(tokenFile118{}):
var ptr *tokenFile118
*(*uP)(uP(&ptr)) = uP(file)
ptr.mu.Lock()
defer ptr.mu.Unlock()
return ptr.lines
case unsafe.Sizeof(tokenFile119{}):
var ptr *tokenFile119
*(*uP)(uP(&ptr)) = uP(file)
ptr.mu.Lock()
defer ptr.mu.Unlock()
return ptr.lines
default:
panic("unexpected token.File size") panic("unexpected token.File size")
} }
var ptr *tokenFile119
type uP = unsafe.Pointer
*(*uP)(uP(&ptr)) = uP(file)
ptr.mu.Lock()
defer ptr.mu.Unlock()
return ptr.lines
} }
// AddExistingFiles adds the specified files to the FileSet if they // AddExistingFiles adds the specified files to the FileSet if they

View File

@ -2,20 +2,10 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package typeparams contains common utilities for writing tools that interact // Package typeparams contains common utilities for writing tools that
// with generic Go code, as introduced with Go 1.18. // interact with generic Go code, as introduced with Go 1.18. It
// // supplements the standard library APIs. Notably, the StructuralTerms
// Many of the types and functions in this package are proxies for the new APIs // API computes a minimal representation of the structural
// introduced in the standard library with Go 1.18. For example, the
// typeparams.Union type is an alias for go/types.Union, and the ForTypeSpec
// function returns the value of the go/ast.TypeSpec.TypeParams field. At Go
// versions older than 1.18 these helpers are implemented as stubs, allowing
// users of this package to write code that handles generic constructs inline,
// even if the Go version being used to compile does not support generics.
//
// Additionally, this package contains common utilities for working with the
// new generic constructs, to supplement the standard library APIs. Notably,
// the StructuralTerms API computes a minimal representation of the structural
// restrictions on a type parameter. // restrictions on a type parameter.
// //
// An external version of these APIs is available in the // An external version of these APIs is available in the
@ -27,6 +17,9 @@ import (
"go/ast" "go/ast"
"go/token" "go/token"
"go/types" "go/types"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/typesinternal"
) )
// UnpackIndexExpr extracts data from AST nodes that represent index // UnpackIndexExpr extracts data from AST nodes that represent index
@ -72,9 +65,9 @@ func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack toke
} }
} }
// IsTypeParam reports whether t is a type parameter. // IsTypeParam reports whether t is a type parameter (or an alias of one).
func IsTypeParam(t types.Type) bool { func IsTypeParam(t types.Type) bool {
_, ok := t.(*types.TypeParam) _, ok := aliases.Unalias(t).(*types.TypeParam)
return ok return ok
} }
@ -90,13 +83,8 @@ func OriginMethod(fn *types.Func) *types.Func {
if recv == nil { if recv == nil {
return fn return fn
} }
base := recv.Type() _, named := typesinternal.ReceiverNamed(recv)
p, isPtr := base.(*types.Pointer) if named == nil {
if isPtr {
base = p.Elem()
}
named, isNamed := base.(*types.Named)
if !isNamed {
// Receiver is a *types.Interface. // Receiver is a *types.Interface.
return fn return fn
} }
@ -158,6 +146,9 @@ func OriginMethod(fn *types.Func) *types.Func {
// In this case, GenericAssignableTo reports that instantiations of Container // In this case, GenericAssignableTo reports that instantiations of Container
// are assignable to the corresponding instantiation of Interface. // are assignable to the corresponding instantiation of Interface.
func GenericAssignableTo(ctxt *types.Context, V, T types.Type) bool { func GenericAssignableTo(ctxt *types.Context, V, T types.Type) bool {
V = aliases.Unalias(V)
T = aliases.Unalias(T)
// If V and T are not both named, or do not have matching non-empty type // If V and T are not both named, or do not have matching non-empty type
// parameter lists, fall back on types.AssignableTo. // parameter lists, fall back on types.AssignableTo.

View File

@ -5,7 +5,10 @@
package typeparams package typeparams
import ( import (
"fmt"
"go/types" "go/types"
"golang.org/x/tools/internal/aliases"
) )
// CoreType returns the core type of T or nil if T does not have a core type. // CoreType returns the core type of T or nil if T does not have a core type.
@ -109,7 +112,7 @@ func CoreType(T types.Type) types.Type {
// _NormalTerms makes no guarantees about the order of terms, except that it // _NormalTerms makes no guarantees about the order of terms, except that it
// is deterministic. // is deterministic.
func _NormalTerms(typ types.Type) ([]*types.Term, error) { func _NormalTerms(typ types.Type) ([]*types.Term, error) {
switch typ := typ.(type) { switch typ := aliases.Unalias(typ).(type) {
case *types.TypeParam: case *types.TypeParam:
return StructuralTerms(typ) return StructuralTerms(typ)
case *types.Union: case *types.Union:
@ -120,3 +123,15 @@ func _NormalTerms(typ types.Type) ([]*types.Term, error) {
return []*types.Term{types.NewTerm(false, typ)}, nil return []*types.Term{types.NewTerm(false, typ)}, nil
} }
} }
// MustDeref returns the type of the variable pointed to by t.
// It panics if t's core type is not a pointer.
//
// TODO(adonovan): ideally this would live in typesinternal, but that
// creates an import cycle. Move there when we melt this package down.
func MustDeref(t types.Type) types.Type {
if ptr, ok := CoreType(t).(*types.Pointer); ok {
return ptr.Elem()
}
panic(fmt.Sprintf("%v is not a pointer", t))
}

View File

@ -0,0 +1,43 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package typesinternal
import (
"go/types"
"golang.org/x/tools/internal/aliases"
)
// ReceiverNamed returns the named type (if any) associated with the
// type of recv, which may be of the form N or *N, or aliases thereof.
// It also reports whether a Pointer was present.
func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) {
t := recv.Type()
if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok {
isPtr = true
t = ptr.Elem()
}
named, _ = aliases.Unalias(t).(*types.Named)
return
}
// Unpointer returns T given *T or an alias thereof.
// For all other types it is the identity function.
// It does not look at underlying types.
// The result may be an alias.
//
// Use this function to strip off the optional pointer on a receiver
// in a field or method selection, without losing the named type
// (which is needed to compute the method set).
//
// See also [typeparams.MustDeref], which removes one level of
// indirection from the type, regardless of named types (analogous to
// a LOAD instruction).
func Unpointer(t types.Type) types.Type {
if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok {
return ptr.Elem()
}
return t
}

View File

@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build go1.18
// +build go1.18
package typesinternal package typesinternal
import ( import (

View File

@ -0,0 +1,43 @@
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package versions
// This file contains predicates for working with file versions to
// decide when a tool should consider a language feature enabled.
// GoVersions that features in x/tools can be gated to.
const (
Go1_18 = "go1.18"
Go1_19 = "go1.19"
Go1_20 = "go1.20"
Go1_21 = "go1.21"
Go1_22 = "go1.22"
)
// Future is an invalid unknown Go version sometime in the future.
// Do not use directly with Compare.
const Future = ""
// AtLeast reports whether the file version v comes after a Go release.
//
// Use this predicate to enable a behavior once a certain Go release
// has happened (and stays enabled in the future).
func AtLeast(v, release string) bool {
if v == Future {
return true // an unknown future version is always after y.
}
return Compare(Lang(v), Lang(release)) >= 0
}
// Before reports whether the file version v is strictly before a Go release.
//
// Use this predicate to disable a behavior once a certain Go release
// has happened (and stays enabled in the future).
func Before(v, release string) bool {
if v == Future {
return false // an unknown future version happens after y.
}
return Compare(Lang(v), Lang(release)) < 0
}

View File

@ -0,0 +1,14 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package versions
// toolchain is maximum version (<1.22) that the go toolchain used
// to build the current tool is known to support.
//
// When a tool is built with >=1.22, the value of toolchain is unused.
//
// x/tools does not support building with go <1.18. So we take this
// as the minimum possible maximum.
var toolchain string = Go1_18

View File

@ -0,0 +1,14 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.19
// +build go1.19
package versions
func init() {
if Compare(toolchain, Go1_19) < 0 {
toolchain = Go1_19
}
}

View File

@ -0,0 +1,14 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.20
// +build go1.20
package versions
func init() {
if Compare(toolchain, Go1_20) < 0 {
toolchain = Go1_20
}
}

View File

@ -0,0 +1,14 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.21
// +build go1.21
package versions
func init() {
if Compare(toolchain, Go1_21) < 0 {
toolchain = Go1_21
}
}

View File

@ -12,9 +12,19 @@ import (
"go/types" "go/types"
) )
// FileVersions always reports the a file's Go version as the // FileVersion returns a language version (<=1.21) derived from runtime.Version()
// zero version at this Go version. // or an unknown future version.
func FileVersions(info *types.Info, file *ast.File) string { return "" } func FileVersion(info *types.Info, file *ast.File) string {
// In x/tools built with Go <= 1.21, we do not have Info.FileVersions
// available. We use a go version derived from the toolchain used to
// compile the tool by default.
// This will be <= go1.21. We take this as the maximum version that
// this tool can support.
//
// There are no features currently in x/tools that need to tell fine grained
// differences for versions <1.22.
return toolchain
}
// InitFileVersions is a noop at this Go version. // InitFileVersions is a noop when compiled with this Go version.
func InitFileVersions(*types.Info) {} func InitFileVersions(*types.Info) {}

View File

@ -12,10 +12,27 @@ import (
"go/types" "go/types"
) )
// FileVersions maps a file to the file's semantic Go version. // FileVersions returns a file's Go version.
// The reported version is the zero version if a version cannot be determined. // The reported version is an unknown Future version if a
func FileVersions(info *types.Info, file *ast.File) string { // version cannot be determined.
return info.FileVersions[file] func FileVersion(info *types.Info, file *ast.File) string {
// In tools built with Go >= 1.22, the Go version of a file
// follow a cascades of sources:
// 1) types.Info.FileVersion, which follows the cascade:
// 1.a) file version (ast.File.GoVersion),
// 1.b) the package version (types.Config.GoVersion), or
// 2) is some unknown Future version.
//
// File versions require a valid package version to be provided to types
// in Config.GoVersion. Config.GoVersion is either from the package's module
// or the toolchain (go run). This value should be provided by go/packages
// or unitchecker.Config.GoVersion.
if v := info.FileVersions[file]; IsValid(v) {
return v
}
// Note: we could instead return runtime.Version() [if valid].
// This would act as a max version on what a tool can support.
return Future
} }
// InitFileVersions initializes info to record Go versions for Go files. // InitFileVersions initializes info to record Go versions for Go files.

View File

@ -4,6 +4,10 @@
package versions package versions
import (
"strings"
)
// Note: If we use build tags to use go/versions when go >=1.22, // Note: If we use build tags to use go/versions when go >=1.22,
// we run into go.dev/issue/53737. Under some operations users would see an // we run into go.dev/issue/53737. Under some operations users would see an
// import of "go/versions" even if they would not compile the file. // import of "go/versions" even if they would not compile the file.
@ -45,6 +49,7 @@ func IsValid(x string) bool { return isValid(stripGo(x)) }
// stripGo converts from a "go1.21" version to a "1.21" version. // stripGo converts from a "go1.21" version to a "1.21" version.
// If v does not start with "go", stripGo returns the empty string (a known invalid version). // If v does not start with "go", stripGo returns the empty string (a known invalid version).
func stripGo(v string) string { func stripGo(v string) string {
v, _, _ = strings.Cut(v, "-") // strip -bigcorp suffix.
if len(v) < 2 || v[:2] != "go" { if len(v) < 2 || v[:2] != "go" {
return "" return ""
} }

25
vendor/modules.txt vendored
View File

@ -4,7 +4,7 @@ cloud.google.com/go/internal
cloud.google.com/go/internal/optional cloud.google.com/go/internal/optional
cloud.google.com/go/internal/trace cloud.google.com/go/internal/trace
cloud.google.com/go/internal/version cloud.google.com/go/internal/version
# cloud.google.com/go/compute v1.24.0 # cloud.google.com/go/compute v1.25.1
## explicit; go 1.19 ## explicit; go 1.19
cloud.google.com/go/compute/internal cloud.google.com/go/compute/internal
# cloud.google.com/go/compute/metadata v0.2.3 # cloud.google.com/go/compute/metadata v0.2.3
@ -105,6 +105,8 @@ github.com/Azure/go-autorest/logger
# github.com/Azure/go-autorest/tracing v0.6.0 # github.com/Azure/go-autorest/tracing v0.6.0
## explicit; go 1.12 ## explicit; go 1.12
github.com/Azure/go-autorest/tracing github.com/Azure/go-autorest/tracing
# github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible
## explicit
# github.com/GoogleCloudPlatform/docker-credential-gcr/v2 v2.1.22 # github.com/GoogleCloudPlatform/docker-credential-gcr/v2 v2.1.22
## explicit; go 1.21 ## explicit; go 1.21
github.com/GoogleCloudPlatform/docker-credential-gcr/v2 github.com/GoogleCloudPlatform/docker-credential-gcr/v2
@ -315,6 +317,8 @@ github.com/aws/smithy-go/time
github.com/aws/smithy-go/transport/http github.com/aws/smithy-go/transport/http
github.com/aws/smithy-go/transport/http/internal/io github.com/aws/smithy-go/transport/http/internal/io
github.com/aws/smithy-go/waiter github.com/aws/smithy-go/waiter
# github.com/awslabs/amazon-ecr-credential-helper v0.7.1
## explicit
# github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231213181459-b0fcec718dc6 # github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231213181459-b0fcec718dc6
## explicit; go 1.19 ## explicit; go 1.19
github.com/awslabs/amazon-ecr-credential-helper/ecr-login github.com/awslabs/amazon-ecr-credential-helper/ecr-login
@ -488,7 +492,7 @@ github.com/dimchansky/utfbom
# github.com/distribution/reference v0.5.0 # github.com/distribution/reference v0.5.0
## explicit; go 1.20 ## explicit; go 1.20
github.com/distribution/reference github.com/distribution/reference
# github.com/docker/cli v25.0.3+incompatible # github.com/docker/cli v26.0.0+incompatible
## explicit ## explicit
github.com/docker/cli/cli/config github.com/docker/cli/cli/config
github.com/docker/cli/cli/config/configfile github.com/docker/cli/cli/config/configfile
@ -587,7 +591,7 @@ github.com/docker/docker/runconfig
github.com/docker/docker/runconfig/opts github.com/docker/docker/runconfig/opts
github.com/docker/docker/volume github.com/docker/docker/volume
github.com/docker/docker/volume/mounts github.com/docker/docker/volume/mounts
# github.com/docker/docker-credential-helpers v0.8.0 # github.com/docker/docker-credential-helpers v0.8.1
## explicit; go 1.19 ## explicit; go 1.19
github.com/docker/docker-credential-helpers/client github.com/docker/docker-credential-helpers/client
github.com/docker/docker-credential-helpers/credentials github.com/docker/docker-credential-helpers/credentials
@ -710,8 +714,8 @@ github.com/golang/groupcache/lru
# github.com/golang/mock v1.6.0 # github.com/golang/mock v1.6.0
## explicit; go 1.11 ## explicit; go 1.11
github.com/golang/mock/gomock github.com/golang/mock/gomock
# github.com/golang/protobuf v1.5.3 # github.com/golang/protobuf v1.5.4
## explicit; go 1.9 ## explicit; go 1.17
github.com/golang/protobuf/proto github.com/golang/protobuf/proto
# github.com/google/go-cmp v0.6.0 # github.com/google/go-cmp v0.6.0
## explicit; go 1.13 ## explicit; go 1.13
@ -933,7 +937,7 @@ github.com/opencontainers/selinux/pkg/pwalkdir
# github.com/otiai10/copy v1.14.0 # github.com/otiai10/copy v1.14.0
## explicit; go 1.18 ## explicit; go 1.18
github.com/otiai10/copy github.com/otiai10/copy
# github.com/pelletier/go-toml/v2 v2.1.1 # github.com/pelletier/go-toml/v2 v2.2.0
## explicit; go 1.16 ## explicit; go 1.16
github.com/pelletier/go-toml/v2 github.com/pelletier/go-toml/v2
github.com/pelletier/go-toml/v2/internal/characters github.com/pelletier/go-toml/v2/internal/characters
@ -1107,14 +1111,14 @@ golang.org/x/crypto/ssh
golang.org/x/crypto/ssh/agent golang.org/x/crypto/ssh/agent
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
golang.org/x/crypto/ssh/knownhosts golang.org/x/crypto/ssh/knownhosts
# golang.org/x/exp v0.0.0-20231219160207-73b9e39aefca # golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8
## explicit; go 1.20 ## explicit; go 1.20
golang.org/x/exp/constraints golang.org/x/exp/constraints
golang.org/x/exp/slices golang.org/x/exp/slices
golang.org/x/exp/slog golang.org/x/exp/slog
golang.org/x/exp/slog/internal golang.org/x/exp/slog/internal
golang.org/x/exp/slog/internal/buffer golang.org/x/exp/slog/internal/buffer
# golang.org/x/mod v0.14.0 # golang.org/x/mod v0.16.0
## explicit; go 1.18 ## explicit; go 1.18
golang.org/x/mod/semver golang.org/x/mod/semver
# golang.org/x/net v0.22.0 # golang.org/x/net v0.22.0
@ -1167,13 +1171,14 @@ golang.org/x/text/unicode/norm
# golang.org/x/time v0.5.0 # golang.org/x/time v0.5.0
## explicit; go 1.18 ## explicit; go 1.18
golang.org/x/time/rate golang.org/x/time/rate
# golang.org/x/tools v0.17.0 # golang.org/x/tools v0.19.0
## explicit; go 1.18 ## explicit; go 1.19
golang.org/x/tools/cmd/stringer golang.org/x/tools/cmd/stringer
golang.org/x/tools/go/gcexportdata golang.org/x/tools/go/gcexportdata
golang.org/x/tools/go/internal/packagesdriver golang.org/x/tools/go/internal/packagesdriver
golang.org/x/tools/go/packages golang.org/x/tools/go/packages
golang.org/x/tools/go/types/objectpath golang.org/x/tools/go/types/objectpath
golang.org/x/tools/internal/aliases
golang.org/x/tools/internal/event golang.org/x/tools/internal/event
golang.org/x/tools/internal/event/core golang.org/x/tools/internal/event/core
golang.org/x/tools/internal/event/keys golang.org/x/tools/internal/event/keys