mirror of
https://github.com/ko-build/ko.git
synced 2024-12-12 08:54:09 +02:00
Update go-containerregistry (#140)
Pick up https://github.com/google/go-containerregistry/pull/690
This commit is contained in:
parent
acf34edd61
commit
ed28755e6b
8
go.mod
8
go.mod
@ -3,19 +3,21 @@ module github.com/google/ko
|
|||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/docker/cli v0.0.0-20200303162255-7d407207c304 // indirect
|
||||||
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7
|
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7
|
||||||
github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960
|
github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960
|
||||||
github.com/fsnotify/fsnotify v1.4.7
|
github.com/fsnotify/fsnotify v1.4.7
|
||||||
github.com/google/go-cmp v0.3.0
|
github.com/google/go-cmp v0.3.0
|
||||||
github.com/google/go-containerregistry v0.0.0-20200212224832-c629a66d7231
|
github.com/google/go-containerregistry v0.0.0-20200310013544-4fe717a9b4cb
|
||||||
github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc // indirect
|
github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc // indirect
|
||||||
github.com/mattmoor/dep-notify v0.0.0-20190205035814-a45dec370a17
|
github.com/mattmoor/dep-notify v0.0.0-20190205035814-a45dec370a17
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/spf13/cobra v0.0.5
|
github.com/spf13/cobra v0.0.5
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/spf13/viper v1.3.2
|
github.com/spf13/viper v1.3.2
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
|
||||||
golang.org/x/tools v0.0.0-20200115192306-3ded1b734dda
|
golang.org/x/tools v0.0.0-20200210192313-1ace956b0e17
|
||||||
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d
|
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d
|
||||||
k8s.io/apimachinery v0.17.1
|
k8s.io/apimachinery v0.17.1
|
||||||
k8s.io/cli-runtime v0.17.0
|
k8s.io/cli-runtime v0.17.0
|
||||||
|
15
go.sum
15
go.sum
@ -65,6 +65,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
|||||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||||
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017 h1:2HQmlpI3yI9deH18Q6xiSOIjXD4sLI55Y/gfpa8/558=
|
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017 h1:2HQmlpI3yI9deH18Q6xiSOIjXD4sLI55Y/gfpa8/558=
|
||||||
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
|
github.com/docker/cli v0.0.0-20200303162255-7d407207c304 h1:A7SYzidcyuQ/yS4wezWGYeUioUFJQk8HYWY9aMYTF4I=
|
||||||
|
github.com/docker/cli v0.0.0-20200303162255-7d407207c304/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
@ -138,6 +140,10 @@ github.com/google/go-containerregistry v0.0.0-20200115190719-e8e9aa676278 h1:jzL
|
|||||||
github.com/google/go-containerregistry v0.0.0-20200115190719-e8e9aa676278/go.mod h1:Wtl/v6YdQxv397EREtzwgd9+Ud7Q5D8XMbi3Zazgkrs=
|
github.com/google/go-containerregistry v0.0.0-20200115190719-e8e9aa676278/go.mod h1:Wtl/v6YdQxv397EREtzwgd9+Ud7Q5D8XMbi3Zazgkrs=
|
||||||
github.com/google/go-containerregistry v0.0.0-20200212224832-c629a66d7231 h1:zoj6E1dzY9aeZw1CGJv1hffxgyunrLpjI0SZWK7ynzg=
|
github.com/google/go-containerregistry v0.0.0-20200212224832-c629a66d7231 h1:zoj6E1dzY9aeZw1CGJv1hffxgyunrLpjI0SZWK7ynzg=
|
||||||
github.com/google/go-containerregistry v0.0.0-20200212224832-c629a66d7231/go.mod h1:Wtl/v6YdQxv397EREtzwgd9+Ud7Q5D8XMbi3Zazgkrs=
|
github.com/google/go-containerregistry v0.0.0-20200212224832-c629a66d7231/go.mod h1:Wtl/v6YdQxv397EREtzwgd9+Ud7Q5D8XMbi3Zazgkrs=
|
||||||
|
github.com/google/go-containerregistry v0.0.0-20200304201134-fcc8ea80e26f h1:tc00QCOHwGF/IyStWQnJN7zmrPP9LBJTKyulXzApCfw=
|
||||||
|
github.com/google/go-containerregistry v0.0.0-20200304201134-fcc8ea80e26f/go.mod h1:m8YvHwSOuBCq25yrj1DaX/fIMrv6ec3CNg8jY8+5PEA=
|
||||||
|
github.com/google/go-containerregistry v0.0.0-20200310013544-4fe717a9b4cb h1:YZuYn5esRDuCPmdzqWupP4mM/CnOy/ZkSHEP0eXpiLA=
|
||||||
|
github.com/google/go-containerregistry v0.0.0-20200310013544-4fe717a9b4cb/go.mod h1:m8YvHwSOuBCq25yrj1DaX/fIMrv6ec3CNg8jY8+5PEA=
|
||||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
@ -250,6 +256,8 @@ github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR
|
|||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
@ -336,6 +344,7 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk
|
|||||||
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=
|
||||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
@ -368,6 +377,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -419,6 +430,9 @@ golang.org/x/tools v0.0.0-20200115165105-de0b1760071a h1:bEJ3JL2YUH3tt9KX9dsy0WU
|
|||||||
golang.org/x/tools v0.0.0-20200115165105-de0b1760071a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200115165105-de0b1760071a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200115192306-3ded1b734dda h1:auEDF/YdrZGhWDfRdeHl7UpNtm5FtLF0X3NLqo4feXM=
|
golang.org/x/tools v0.0.0-20200115192306-3ded1b734dda h1:auEDF/YdrZGhWDfRdeHl7UpNtm5FtLF0X3NLqo4feXM=
|
||||||
golang.org/x/tools v0.0.0-20200115192306-3ded1b734dda/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200115192306-3ded1b734dda/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200210192313-1ace956b0e17 h1:a/Fd23DJvg1CaeDH0dYHahE+hCI0v9rFgxSNIThoUcM=
|
||||||
|
golang.org/x/tools v0.0.0-20200210192313-1ace956b0e17/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
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=
|
||||||
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
|
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
|
||||||
@ -490,6 +504,7 @@ k8s.io/client-go v0.17.1/go.mod h1:HZtHJSC/VuSHcETN9QA5QDZky1tXiYrkF/7t7vRpO1A=
|
|||||||
k8s.io/cloud-provider v0.17.0/go.mod h1:Ze4c3w2C0bRsjkBUoHpFi+qWe3ob1wI2/7cUn+YQIDE=
|
k8s.io/cloud-provider v0.17.0/go.mod h1:Ze4c3w2C0bRsjkBUoHpFi+qWe3ob1wI2/7cUn+YQIDE=
|
||||||
k8s.io/code-generator v0.17.1 h1:e3B1UqRzRUWygp7WD+QTRT3ZUahPIaRKF0OFa7duQwI=
|
k8s.io/code-generator v0.17.1 h1:e3B1UqRzRUWygp7WD+QTRT3ZUahPIaRKF0OFa7duQwI=
|
||||||
k8s.io/code-generator v0.17.1/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
|
k8s.io/code-generator v0.17.1/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
|
||||||
|
k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
|
||||||
k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc=
|
k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc=
|
||||||
k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQksuCrHKWls=
|
k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQksuCrHKWls=
|
||||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
|
2
vendor/github.com/docker/cli/cli/config/config.go
generated
vendored
2
vendor/github.com/docker/cli/cli/config/config.go
generated
vendored
@ -112,7 +112,7 @@ func Load(configDir string) (*configfile.ConfigFile, error) {
|
|||||||
}
|
}
|
||||||
confFile := filepath.Join(homedir, oldConfigfile)
|
confFile := filepath.Join(homedir, oldConfigfile)
|
||||||
if _, err := os.Stat(confFile); err != nil {
|
if _, err := os.Stat(confFile); err != nil {
|
||||||
return configFile, nil //missing file is not an error
|
return configFile, nil // missing file is not an error
|
||||||
}
|
}
|
||||||
file, err := os.Open(confFile)
|
file, err := os.Open(confFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
3
vendor/github.com/docker/cli/cli/config/configfile/file.go
generated
vendored
3
vendor/github.com/docker/cli/cli/config/configfile/file.go
generated
vendored
@ -196,6 +196,9 @@ func (configFile *ConfigFile) Save() error {
|
|||||||
os.Remove(temp.Name())
|
os.Remove(temp.Name())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// Try copying the current config file (if any) ownership and permissions
|
||||||
|
copyFilePermissions(configFile.Filename, temp.Name())
|
||||||
|
|
||||||
return os.Rename(temp.Name(), configFile.Filename)
|
return os.Rename(temp.Name(), configFile.Filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
vendor/github.com/docker/cli/cli/config/configfile/file_unix.go
generated
vendored
Normal file
35
vendor/github.com/docker/cli/cli/config/configfile/file_unix.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package configfile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// copyFilePermissions copies file ownership and permissions from "src" to "dst",
|
||||||
|
// ignoring any error during the process.
|
||||||
|
func copyFilePermissions(src, dst string) {
|
||||||
|
var (
|
||||||
|
mode os.FileMode = 0600
|
||||||
|
uid, gid int
|
||||||
|
)
|
||||||
|
|
||||||
|
fi, err := os.Stat(src)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if fi.Mode().IsRegular() {
|
||||||
|
mode = fi.Mode()
|
||||||
|
}
|
||||||
|
if err := os.Chmod(dst, mode); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
uid = int(fi.Sys().(*syscall.Stat_t).Uid)
|
||||||
|
gid = int(fi.Sys().(*syscall.Stat_t).Gid)
|
||||||
|
|
||||||
|
if uid > 0 && gid > 0 {
|
||||||
|
_ = os.Chown(dst, uid, gid)
|
||||||
|
}
|
||||||
|
}
|
5
vendor/github.com/docker/cli/cli/config/configfile/file_windows.go
generated
vendored
Normal file
5
vendor/github.com/docker/cli/cli/config/configfile/file_windows.go
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package configfile
|
||||||
|
|
||||||
|
func copyFilePermissions(src, dst string) {
|
||||||
|
// TODO implement for Windows
|
||||||
|
}
|
2
vendor/github.com/google/go-containerregistry/pkg/authn/README.md
generated
vendored
2
vendor/github.com/google/go-containerregistry/pkg/authn/README.md
generated
vendored
@ -1,5 +1,7 @@
|
|||||||
# `authn`
|
# `authn`
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/google/go-containerregistry/pkg/authn?status.svg)](https://godoc.org/github.com/google/go-containerregistry/pkg/authn)
|
||||||
|
|
||||||
This README outlines how we acquire and use credentials when interacting with a registry.
|
This README outlines how we acquire and use credentials when interacting with a registry.
|
||||||
|
|
||||||
As much as possible, we attempt to emulate docker's authentication behavior and configuration so that this library "just works" if you've already configured credentials that work with docker; however, when things don't work, a basic understanding of what's going on can help with debugging.
|
As much as possible, we attempt to emulate docker's authentication behavior and configuration so that this library "just works" if you've already configured credentials that work with docker; however, when things don't work, a basic understanding of what's going on can help with debugging.
|
||||||
|
6
vendor/github.com/google/go-containerregistry/pkg/authn/keychain.go
generated
vendored
6
vendor/github.com/google/go-containerregistry/pkg/authn/keychain.go
generated
vendored
@ -52,7 +52,9 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultAuthKey = "https://" + name.DefaultRegistry + "/v1/"
|
// DefaultAuthKey is the key used for dockerhub in config files, which
|
||||||
|
// is hardcoded for historical reasons.
|
||||||
|
DefaultAuthKey = "https://" + name.DefaultRegistry + "/v1/"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Resolve implements Keychain.
|
// Resolve implements Keychain.
|
||||||
@ -67,7 +69,7 @@ func (dk *defaultKeychain) Resolve(target Resource) (Authenticator, error) {
|
|||||||
// https://github.com/moby/moby/blob/fc01c2b481097a6057bec3cd1ab2d7b4488c50c4/registry/config.go#L397-L404
|
// https://github.com/moby/moby/blob/fc01c2b481097a6057bec3cd1ab2d7b4488c50c4/registry/config.go#L397-L404
|
||||||
key := target.RegistryStr()
|
key := target.RegistryStr()
|
||||||
if key == name.DefaultRegistry {
|
if key == name.DefaultRegistry {
|
||||||
key = defaultAuthKey
|
key = DefaultAuthKey
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := cf.GetAuthConfig(key)
|
cfg, err := cf.GetAuthConfig(key)
|
||||||
|
3
vendor/github.com/google/go-containerregistry/pkg/name/README.md
generated
vendored
Normal file
3
vendor/github.com/google/go-containerregistry/pkg/name/README.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# `name`
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/google/go-containerregistry/pkg/name?status.svg)](https://godoc.org/github.com/google/go-containerregistry/pkg/name)
|
5
vendor/github.com/google/go-containerregistry/pkg/v1/config.go
generated
vendored
5
vendor/github.com/google/go-containerregistry/pkg/v1/config.go
generated
vendored
@ -23,6 +23,9 @@ import (
|
|||||||
// ConfigFile is the configuration file that holds the metadata describing
|
// ConfigFile is the configuration file that holds the metadata describing
|
||||||
// how to launch a container. See:
|
// how to launch a container. See:
|
||||||
// https://github.com/opencontainers/image-spec/blob/master/config.md
|
// https://github.com/opencontainers/image-spec/blob/master/config.md
|
||||||
|
//
|
||||||
|
// docker_version and os.version are not part of the spec but included
|
||||||
|
// for backwards compatibility.
|
||||||
type ConfigFile struct {
|
type ConfigFile struct {
|
||||||
Architecture string `json:"architecture"`
|
Architecture string `json:"architecture"`
|
||||||
Author string `json:"author,omitempty"`
|
Author string `json:"author,omitempty"`
|
||||||
@ -33,7 +36,7 @@ type ConfigFile struct {
|
|||||||
OS string `json:"os"`
|
OS string `json:"os"`
|
||||||
RootFS RootFS `json:"rootfs"`
|
RootFS RootFS `json:"rootfs"`
|
||||||
Config Config `json:"config"`
|
Config Config `json:"config"`
|
||||||
OSVersion string `json:"osversion,omitempty"`
|
OSVersion string `json:"os.version,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// History is one entry of a list recording how this container image was built.
|
// History is one entry of a list recording how this container image was built.
|
||||||
|
11
vendor/github.com/google/go-containerregistry/pkg/v1/daemon/README.md
generated
vendored
Normal file
11
vendor/github.com/google/go-containerregistry/pkg/v1/daemon/README.md
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# `daemon`
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/daemon?status.svg)](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/daemon)
|
||||||
|
|
||||||
|
The `daemon` package enables reading/writing images from/to the docker daemon.
|
||||||
|
|
||||||
|
It is not fully fleshed out, but is useful for interoperability, see various issues:
|
||||||
|
|
||||||
|
* https://github.com/google/go-containerregistry/issues/205
|
||||||
|
* https://github.com/google/go-containerregistry/issues/552
|
||||||
|
* https://github.com/google/go-containerregistry/issues/627
|
48
vendor/github.com/google/go-containerregistry/pkg/v1/daemon/image.go
generated
vendored
48
vendor/github.com/google/go-containerregistry/pkg/v1/daemon/image.go
generated
vendored
@ -36,6 +36,7 @@ var _ v1.Image = (*image)(nil)
|
|||||||
type imageOpener struct {
|
type imageOpener struct {
|
||||||
ref name.Reference
|
ref name.Reference
|
||||||
buffered bool
|
buffered bool
|
||||||
|
client Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImageOption is a functional option for Image.
|
// ImageOption is a functional option for Image.
|
||||||
@ -45,14 +46,16 @@ func (i *imageOpener) Open() (v1.Image, error) {
|
|||||||
var opener tarball.Opener
|
var opener tarball.Opener
|
||||||
var err error
|
var err error
|
||||||
if i.buffered {
|
if i.buffered {
|
||||||
opener, err = bufferedOpener(i.ref)
|
opener, err = i.bufferedOpener(i.ref)
|
||||||
} else {
|
} else {
|
||||||
opener, err = unbufferedOpener(i.ref)
|
opener, err = i.unbufferedOpener(i.ref)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i.client.NegotiateAPIVersion(context.Background())
|
||||||
|
|
||||||
tb, err := tarball.Image(opener, nil)
|
tb, err := tarball.Image(opener, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -63,33 +66,13 @@ func (i *imageOpener) Open() (v1.Image, error) {
|
|||||||
return img, nil
|
return img, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImageSaver is an interface for testing.
|
func (i *imageOpener) saveImage(ref name.Reference) (io.ReadCloser, error) {
|
||||||
type ImageSaver interface {
|
return i.client.ImageSave(context.Background(), []string{ref.Name()})
|
||||||
ImageSave(context.Context, []string) (io.ReadCloser, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a variable so we can override in tests.
|
func (i *imageOpener) bufferedOpener(ref name.Reference) (tarball.Opener, error) {
|
||||||
var getImageSaver = func() (ImageSaver, error) {
|
|
||||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
cli.NegotiateAPIVersion(context.Background())
|
|
||||||
return cli, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func saveImage(ref name.Reference) (io.ReadCloser, error) {
|
|
||||||
cli, err := getImageSaver()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return cli.ImageSave(context.Background(), []string{ref.Name()})
|
|
||||||
}
|
|
||||||
|
|
||||||
func bufferedOpener(ref name.Reference) (tarball.Opener, error) {
|
|
||||||
// Store the tarball in memory and return a new reader into the bytes each time we need to access something.
|
// Store the tarball in memory and return a new reader into the bytes each time we need to access something.
|
||||||
rc, err := saveImage(ref)
|
rc, err := i.saveImage(ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -106,10 +89,10 @@ func bufferedOpener(ref name.Reference) (tarball.Opener, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unbufferedOpener(ref name.Reference) (tarball.Opener, error) {
|
func (i *imageOpener) unbufferedOpener(ref name.Reference) (tarball.Opener, error) {
|
||||||
// To avoid storing the tarball in memory, do a save every time we need to access something.
|
// To avoid storing the tarball in memory, do a save every time we need to access something.
|
||||||
return func() (io.ReadCloser, error) {
|
return func() (io.ReadCloser, error) {
|
||||||
return saveImage(ref)
|
return i.saveImage(ref)
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,5 +109,14 @@ func Image(ref name.Reference, options ...ImageOption) (v1.Image, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if i.client == nil {
|
||||||
|
var err error
|
||||||
|
i.client, err = client.NewClientWithOpts(client.FromEnv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return i.Open()
|
return i.Open()
|
||||||
}
|
}
|
||||||
|
26
vendor/github.com/google/go-containerregistry/pkg/v1/daemon/options.go
generated
vendored
26
vendor/github.com/google/go-containerregistry/pkg/v1/daemon/options.go
generated
vendored
@ -14,6 +14,13 @@
|
|||||||
|
|
||||||
package daemon
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
)
|
||||||
|
|
||||||
// WithBufferedOpener buffers the image.
|
// WithBufferedOpener buffers the image.
|
||||||
func WithBufferedOpener() ImageOption {
|
func WithBufferedOpener() ImageOption {
|
||||||
return func(i *imageOpener) error {
|
return func(i *imageOpener) error {
|
||||||
@ -32,3 +39,22 @@ func (i *imageOpener) setBuffered(buffer bool) error {
|
|||||||
i.buffered = buffer
|
i.buffered = buffer
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithClient is a functional option to allow injecting a docker client.
|
||||||
|
//
|
||||||
|
// By default, github.com/docker/docker/client.FromEnv is used.
|
||||||
|
func WithClient(client Client) ImageOption {
|
||||||
|
return func(i *imageOpener) error {
|
||||||
|
i.client = client
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client represents the subset of a docker client that the daemon
|
||||||
|
// package uses.
|
||||||
|
type Client interface {
|
||||||
|
NegotiateAPIVersion(ctx context.Context)
|
||||||
|
ImageSave(context.Context, []string) (io.ReadCloser, error)
|
||||||
|
ImageLoad(context.Context, io.Reader, bool) (types.ImageLoadResponse, error)
|
||||||
|
ImageTag(context.Context, string, string) error
|
||||||
|
}
|
||||||
|
8
vendor/github.com/google/go-containerregistry/pkg/v1/empty/README.md
generated
vendored
Normal file
8
vendor/github.com/google/go-containerregistry/pkg/v1/empty/README.md
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# `empty`
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/empty?status.svg)](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/empty)
|
||||||
|
|
||||||
|
The empty packages provides an empty base for constructing a `v1.Image` or `v1.ImageIndex`.
|
||||||
|
This is especially useful when paired with the [`mutate`](/pkg/v1/mutate) package,
|
||||||
|
see [`mutate.Append`](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/mutate#Append)
|
||||||
|
and [`mutate.AppendManifests`](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/mutate#AppendManifests).
|
5
vendor/github.com/google/go-containerregistry/pkg/v1/image.go
generated
vendored
5
vendor/github.com/google/go-containerregistry/pkg/v1/image.go
generated
vendored
@ -31,13 +31,14 @@ type Image interface {
|
|||||||
// Size returns the size of the manifest.
|
// Size returns the size of the manifest.
|
||||||
Size() (int64, error)
|
Size() (int64, error)
|
||||||
|
|
||||||
// ConfigName returns the hash of the image's config file.
|
// ConfigName returns the hash of the image's config file, also known as
|
||||||
|
// the Image ID.
|
||||||
ConfigName() (Hash, error)
|
ConfigName() (Hash, error)
|
||||||
|
|
||||||
// ConfigFile returns this image's config file.
|
// ConfigFile returns this image's config file.
|
||||||
ConfigFile() (*ConfigFile, error)
|
ConfigFile() (*ConfigFile, error)
|
||||||
|
|
||||||
// RawConfigFile returns the serialized bytes of ConfigFile()
|
// RawConfigFile returns the serialized bytes of ConfigFile().
|
||||||
RawConfigFile() ([]byte, error)
|
RawConfigFile() ([]byte, error)
|
||||||
|
|
||||||
// Digest returns the sha256 of this image's manifest.
|
// Digest returns the sha256 of this image's manifest.
|
||||||
|
5
vendor/github.com/google/go-containerregistry/pkg/v1/layout/README.md
generated
vendored
Normal file
5
vendor/github.com/google/go-containerregistry/pkg/v1/layout/README.md
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# `layout`
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/layout?status.svg)](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/layout)
|
||||||
|
|
||||||
|
The `layout` package implements support for interacting with an [OCI Image Layout](https://github.com/opencontainers/image-spec/blob/master/image-layout.md).
|
16
vendor/github.com/google/go-containerregistry/pkg/v1/layout/write.go
generated
vendored
16
vendor/github.com/google/go-containerregistry/pkg/v1/layout/write.go
generated
vendored
@ -124,15 +124,19 @@ func (l Path) AppendDescriptor(desc v1.Descriptor) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return l.writeFile("index.json", rawIndex)
|
return l.WriteFile("index.json", rawIndex, os.ModePerm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l Path) writeFile(name string, data []byte) error {
|
// WriteFile write a file with arbitrary data at an arbitrary location in a v1
|
||||||
|
// layout. Used mostly internally to write files like "oci-layout" and
|
||||||
|
// "index.json", also can be used to write other arbitrary files. Do *not* use
|
||||||
|
// this to write blobs. Use only WriteBlob() for that.
|
||||||
|
func (l Path) WriteFile(name string, data []byte, perm os.FileMode) error {
|
||||||
if err := os.MkdirAll(l.path(), os.ModePerm); err != nil && !os.IsExist(err) {
|
if err := os.MkdirAll(l.path(), os.ModePerm); err != nil && !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ioutil.WriteFile(l.path(name), data, os.ModePerm)
|
return ioutil.WriteFile(l.path(name), data, perm)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,12 +263,12 @@ func (l Path) writeIndexToFile(indexFile string, ii v1.ImageIndex) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return l.writeFile(indexFile, rawIndex)
|
return l.WriteFile(indexFile, rawIndex, os.ModePerm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l Path) writeIndex(ii v1.ImageIndex) error {
|
func (l Path) writeIndex(ii v1.ImageIndex) error {
|
||||||
// Always just write oci-layout file, since it's small.
|
// Always just write oci-layout file, since it's small.
|
||||||
if err := l.writeFile("oci-layout", []byte(layoutFile)); err != nil {
|
if err := l.WriteFile("oci-layout", []byte(layoutFile), os.ModePerm); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +295,7 @@ func (l Path) writeIndex(ii v1.ImageIndex) error {
|
|||||||
func Write(path string, ii v1.ImageIndex) (Path, error) {
|
func Write(path string, ii v1.ImageIndex) (Path, error) {
|
||||||
lp := Path(path)
|
lp := Path(path)
|
||||||
// Always just write oci-layout file, since it's small.
|
// Always just write oci-layout file, since it's small.
|
||||||
if err := lp.writeFile("oci-layout", []byte(layoutFile)); err != nil {
|
if err := lp.WriteFile("oci-layout", []byte(layoutFile), os.ModePerm); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
56
vendor/github.com/google/go-containerregistry/pkg/v1/mutate/README.md
generated
vendored
Normal file
56
vendor/github.com/google/go-containerregistry/pkg/v1/mutate/README.md
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# `mutate`
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/mutate?status.svg)](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/mutate)
|
||||||
|
|
||||||
|
The `v1.Image`, `v1.ImageIndex`, and `v1.Layer` interfaces provide only
|
||||||
|
accessor methods, so they are essentially immutable. If you want to change
|
||||||
|
something about them, you need to produce a new instance of that interface.
|
||||||
|
|
||||||
|
A common use case for this library is to read an image from somewhere (a source),
|
||||||
|
change something about it, and write the image somewhere else (a sink).
|
||||||
|
|
||||||
|
Graphically, this looks something like:
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="/images/mutate.dot.svg" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## Mutations
|
||||||
|
|
||||||
|
This is obviously not a comprehensive set of useful transformations (PRs welcome!),
|
||||||
|
but a rough summary of what the `mutate` package currently does:
|
||||||
|
|
||||||
|
### `Config` and `ConfigFile`
|
||||||
|
|
||||||
|
These allow you to change the [image configuration](https://github.com/opencontainers/image-spec/blob/master/config.md#properties),
|
||||||
|
e.g. to change the entrypoint, environment, author, etc.
|
||||||
|
|
||||||
|
### `Time`, `Canonical`, and `CreatedAt`
|
||||||
|
|
||||||
|
These are useful in the context of [reproducible builds](https://reproducible-builds.org/),
|
||||||
|
where you may want to strip timestamps and other non-reproducible information.
|
||||||
|
|
||||||
|
### `Append`, `AppendLayers`, and `AppendManifests`
|
||||||
|
|
||||||
|
These functions allow the extension of a `v1.Image` or `v1.ImageIndex` with
|
||||||
|
new layers or manifests.
|
||||||
|
|
||||||
|
For constructing an image `FROM scratch`, see the [`empty`](/pkg/v1/empty) package.
|
||||||
|
|
||||||
|
### `MediaType` and `IndexMediaType`
|
||||||
|
|
||||||
|
Sometimes, it is necessary to change the media type of an image or index,
|
||||||
|
e.g. to appease a registry with strict validation of images (_looking at you, GCR_).
|
||||||
|
|
||||||
|
### `Rebase`
|
||||||
|
|
||||||
|
Rebase has [its own README](/cmd/crane/rebase.md).
|
||||||
|
|
||||||
|
This is the underlying implementation of [`crane rebase`](https://github.com/google/go-containerregistry/blob/master/cmd/crane/doc/crane_rebase.md).
|
||||||
|
|
||||||
|
### `Extract`
|
||||||
|
|
||||||
|
Extract will flatten an image filesystem into a single tar stream,
|
||||||
|
respecting whiteout files.
|
||||||
|
|
||||||
|
This is the underlying implementation of [`crane export`](https://github.com/google/go-containerregistry/blob/master/cmd/crane/doc/crane_export.md).
|
3
vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go
generated
vendored
3
vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go
generated
vendored
@ -140,8 +140,6 @@ func CreatedAt(base v1.Image, created v1.Time) (v1.Image, error) {
|
|||||||
//
|
//
|
||||||
// If a caller doesn't read the full contents, they should Close it to free up
|
// If a caller doesn't read the full contents, they should Close it to free up
|
||||||
// resources used during extraction.
|
// resources used during extraction.
|
||||||
//
|
|
||||||
// Adapted from https://github.com/google/containerregistry/blob/master/client/v2_2/docker_image_.py#L731
|
|
||||||
func Extract(img v1.Image) io.ReadCloser {
|
func Extract(img v1.Image) io.ReadCloser {
|
||||||
pr, pw := io.Pipe()
|
pr, pw := io.Pipe()
|
||||||
|
|
||||||
@ -156,6 +154,7 @@ func Extract(img v1.Image) io.ReadCloser {
|
|||||||
return pr
|
return pr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adapted from https://github.com/google/containerregistry/blob/da03b395ccdc4e149e34fbb540483efce962dc64/client/v2_2/docker_image_.py#L816
|
||||||
func extract(img v1.Image, w io.Writer) error {
|
func extract(img v1.Image, w io.Writer) error {
|
||||||
tarWriter := tar.NewWriter(w)
|
tarWriter := tar.NewWriter(w)
|
||||||
defer tarWriter.Close()
|
defer tarWriter.Close()
|
||||||
|
66
vendor/github.com/google/go-containerregistry/pkg/v1/partial/README.md
generated
vendored
Normal file
66
vendor/github.com/google/go-containerregistry/pkg/v1/partial/README.md
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# `partial`
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/partial?status.svg)](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/partial)
|
||||||
|
|
||||||
|
## Partial Implementations
|
||||||
|
|
||||||
|
There are roughly two kinds of image representations: compressed and uncompressed.
|
||||||
|
|
||||||
|
The implementations for these kinds of images are almost identical, with the only
|
||||||
|
major difference being how blobs (config and layers) are fetched. This common
|
||||||
|
code lives in this package, where you provide a _partial_ implementation of a
|
||||||
|
compressed or uncompressed image, and you get back a full `v1.Image` implementation.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
In a registry, blobs are compressed, so it's easiest to implement a `v1.Image` in terms
|
||||||
|
of compressed layers. `remote.remoteImage` does this by implementing `CompressedImageCore`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type CompressedImageCore interface {
|
||||||
|
RawConfigFile() ([]byte, error)
|
||||||
|
MediaType() (types.MediaType, error)
|
||||||
|
RawManifest() ([]byte, error)
|
||||||
|
LayerByDigest(v1.Hash) (CompressedLayer, error)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In a tarball, blobs are (often) uncompressed, so it's easiest to implement a `v1.Image` in terms
|
||||||
|
of uncompressed layers. `tarball.uncompressedImage` does this by implementing `UncompressedImageCore`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type CompressedImageCore interface {
|
||||||
|
RawConfigFile() ([]byte, error)
|
||||||
|
MediaType() (types.MediaType, error)
|
||||||
|
LayerByDiffID(v1.Hash) (UncompressedLayer, error)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Optional Methods
|
||||||
|
|
||||||
|
Where possible, we access some information via optional methods as an optimization.
|
||||||
|
|
||||||
|
### [`partial.Descriptor`](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/partial#Descriptor)
|
||||||
|
|
||||||
|
There are some properties of a [`Descriptor`](https://github.com/opencontainers/image-spec/blob/master/descriptor.md#properties) that aren't derivable from just image data:
|
||||||
|
|
||||||
|
* `MediaType`
|
||||||
|
* `Platform`
|
||||||
|
* `URLs`
|
||||||
|
* `Annotations`
|
||||||
|
|
||||||
|
For example, in a `tarball.Image`, there is a `LayerSources` field that contains
|
||||||
|
an entire layer descriptor with `URLs` information for foreign layers. This
|
||||||
|
information can be passed through to callers by implementing this optional
|
||||||
|
`Descriptor` method.
|
||||||
|
|
||||||
|
See [`#654`](https://github.com/google/go-containerregistry/pull/654).
|
||||||
|
|
||||||
|
### [`partial.UncompressedSize`](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/partial#UncompressedSize)
|
||||||
|
|
||||||
|
Usually, you don't need to know the uncompressed size of a layer, since that
|
||||||
|
information isn't stored in a config file (just he sha256 is needed); however,
|
||||||
|
there are cases where it is very helpful to know the layer size, e.g. when
|
||||||
|
writing the uncompressed layer into a tarball.
|
||||||
|
|
||||||
|
See [`#655`](https://github.com/google/go-containerregistry/pull/655).
|
2
vendor/github.com/google/go-containerregistry/pkg/v1/partial/compressed.go
generated
vendored
2
vendor/github.com/google/go-containerregistry/pkg/v1/partial/compressed.go
generated
vendored
@ -76,7 +76,7 @@ func CompressedToLayer(ul CompressedLayer) (v1.Layer, error) {
|
|||||||
// CompressedImageCore represents the base minimum interface a natively
|
// CompressedImageCore represents the base minimum interface a natively
|
||||||
// compressed image must implement for us to produce a v1.Image.
|
// compressed image must implement for us to produce a v1.Image.
|
||||||
type CompressedImageCore interface {
|
type CompressedImageCore interface {
|
||||||
imageCore
|
ImageCore
|
||||||
|
|
||||||
// RawManifest returns the serialized bytes of the manifest.
|
// RawManifest returns the serialized bytes of the manifest.
|
||||||
RawManifest() ([]byte, error)
|
RawManifest() ([]byte, error)
|
||||||
|
4
vendor/github.com/google/go-containerregistry/pkg/v1/partial/image.go
generated
vendored
4
vendor/github.com/google/go-containerregistry/pkg/v1/partial/image.go
generated
vendored
@ -18,8 +18,8 @@ import (
|
|||||||
"github.com/google/go-containerregistry/pkg/v1/types"
|
"github.com/google/go-containerregistry/pkg/v1/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// imageCore is the core set of properties without which we cannot build a v1.Image
|
// ImageCore is the core set of properties without which we cannot build a v1.Image
|
||||||
type imageCore interface {
|
type ImageCore interface {
|
||||||
// RawConfigFile returns the serialized bytes of this image's config file.
|
// RawConfigFile returns the serialized bytes of this image's config file.
|
||||||
RawConfigFile() ([]byte, error)
|
RawConfigFile() ([]byte, error)
|
||||||
|
|
||||||
|
2
vendor/github.com/google/go-containerregistry/pkg/v1/partial/uncompressed.go
generated
vendored
2
vendor/github.com/google/go-containerregistry/pkg/v1/partial/uncompressed.go
generated
vendored
@ -89,7 +89,7 @@ func UncompressedToLayer(ul UncompressedLayer) (v1.Layer, error) {
|
|||||||
// UncompressedImageCore represents the bare minimum interface a natively
|
// UncompressedImageCore represents the bare minimum interface a natively
|
||||||
// uncompressed image must implement for us to produce a v1.Image
|
// uncompressed image must implement for us to produce a v1.Image
|
||||||
type UncompressedImageCore interface {
|
type UncompressedImageCore interface {
|
||||||
imageCore
|
ImageCore
|
||||||
|
|
||||||
// LayerByDiffID is a variation on the v1.Image method, which returns
|
// LayerByDiffID is a variation on the v1.Image method, which returns
|
||||||
// an UncompressedLayer instead.
|
// an UncompressedLayer instead.
|
||||||
|
10
vendor/github.com/google/go-containerregistry/pkg/v1/partial/with.go
generated
vendored
10
vendor/github.com/google/go-containerregistry/pkg/v1/partial/with.go
generated
vendored
@ -201,22 +201,22 @@ func BlobSize(i WithManifest, h v1.Hash) (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BlobDescriptor is a helper for implementing v1.Image
|
// BlobDescriptor is a helper for implementing v1.Image
|
||||||
func BlobDescriptor(i WithManifest, h v1.Hash) (v1.Descriptor, error) {
|
func BlobDescriptor(i WithManifest, h v1.Hash) (*v1.Descriptor, error) {
|
||||||
m, err := i.Manifest()
|
m, err := i.Manifest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return v1.Descriptor{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.Config.Digest == h {
|
if m.Config.Digest == h {
|
||||||
return m.Config, nil
|
return &m.Config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, l := range m.Layers {
|
for _, l := range m.Layers {
|
||||||
if l.Digest == h {
|
if l.Digest == h {
|
||||||
return l, nil
|
return &l, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return v1.Descriptor{}, fmt.Errorf("blob %v not found", h)
|
return nil, fmt.Errorf("blob %v not found", h)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithManifestAndConfigFile defines the subset of v1.Image used by these helper methods
|
// WithManifestAndConfigFile defines the subset of v1.Image used by these helper methods
|
||||||
|
117
vendor/github.com/google/go-containerregistry/pkg/v1/remote/README.md
generated
vendored
Normal file
117
vendor/github.com/google/go-containerregistry/pkg/v1/remote/README.md
generated
vendored
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
# `remote`
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/remote?status.svg)](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/remote)
|
||||||
|
|
||||||
|
The `remote` package implements a client for accessing a registry,
|
||||||
|
per the [OCI distribution spec](https://github.com/opencontainers/distribution-spec/blob/master/spec.md).
|
||||||
|
|
||||||
|
It leans heavily on the lower level [`transport`](/pkg/v1/remote/transport) package, which handles the
|
||||||
|
authentication handshake and structured errors.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/go-containerregistry/pkg/authn"
|
||||||
|
"github.com/google/go-containerregistry/pkg/name"
|
||||||
|
"github.com/google/go-containerregistry/pkg/v1/remote"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ref, err := name.ParseReference("gcr.io/google-containers/pause")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
img, err := remote.Image(ref, remote.WithAuthFromKeychain(authn.DefaultKeychain))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// do stuff with img
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="/images/remote.dot.svg" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
There are a lot of confusingly similar terms that come up when talking about images in registries.
|
||||||
|
|
||||||
|
### Anatomy of an image
|
||||||
|
|
||||||
|
In general...
|
||||||
|
|
||||||
|
* A tag refers to an image manifest.
|
||||||
|
* An image manifest references a config file and an orderered list of _compressed_ layers by sha256 digest.
|
||||||
|
* A config file references an ordered list of _uncompressed_ layers by sha256 digest and contains runtime configuration.
|
||||||
|
* The sha256 digest of the config file is the [image id](https://github.com/opencontainers/image-spec/blob/master/config.md#imageid) for the image.
|
||||||
|
|
||||||
|
For example, an image with two layers would look something like this:
|
||||||
|
|
||||||
|
![image anatomy](/images/image-anatomy.dot.svg)
|
||||||
|
|
||||||
|
### Anatomy of an index
|
||||||
|
|
||||||
|
In the normal case, an [index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) is used to represent a multi-platform image.
|
||||||
|
This was the original use case for a [manifest
|
||||||
|
list](https://docs.docker.com/registry/spec/manifest-v2-2/#manifest-list).
|
||||||
|
|
||||||
|
![image index anatomy](/images/index-anatomy.dot.svg)
|
||||||
|
|
||||||
|
It is possible for an index to reference another index, per the OCI
|
||||||
|
[image-spec](https://github.com/opencontainers/image-spec/blob/master/media-types.md#compatibility-matrix).
|
||||||
|
In theory, both an image and image index can reference arbitrary things via
|
||||||
|
[descriptors](https://github.com/opencontainers/image-spec/blob/master/descriptor.md),
|
||||||
|
e.g. see the [image layout
|
||||||
|
example](https://github.com/opencontainers/image-spec/blob/master/image-layout.md#index-example),
|
||||||
|
which references an application/xml file from an image index.
|
||||||
|
|
||||||
|
That could look something like this:
|
||||||
|
|
||||||
|
![exotic image index anatomy](/images/index-anatomy-exotic.dot.svg)
|
||||||
|
|
||||||
|
Using a recursive index like this might not be possible with all registries,
|
||||||
|
but this flexibility allows for some interesting applications, e.g. the
|
||||||
|
[OCI Artifacts](https://github.com/opencontainers/artifacts) effort.
|
||||||
|
|
||||||
|
### Anatomy of an image upload
|
||||||
|
|
||||||
|
The structure of an image requires a delicate ordering when uploading an image to a registry.
|
||||||
|
Below is a (slightly simplified) figure that describes how an image is prepared for upload
|
||||||
|
to a registry and how the data flows between various artifacts:
|
||||||
|
|
||||||
|
![upload](/images/upload.dot.svg)
|
||||||
|
|
||||||
|
Note that:
|
||||||
|
|
||||||
|
* A config file references the uncompressed layer contents by sha256.
|
||||||
|
* A manifest references the compressed layer contents by sha256 and the size of the layer.
|
||||||
|
* A manifest references the config file contents by sha256 and the size of the file.
|
||||||
|
|
||||||
|
It follows that during an upload, we need to upload layers before the config file,
|
||||||
|
and we need to upload the config file before the manifest.
|
||||||
|
|
||||||
|
Sometimes, we know all of this information ahead of time, (e.g. when copying from remote.Image),
|
||||||
|
so the ordering is less important.
|
||||||
|
|
||||||
|
In other cases, e.g. when using a [`stream.Layer`](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/stream#Layer),
|
||||||
|
we can't compute anything until we have already uploaded the layer, so we need to be careful about ordering.
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
### schema 1
|
||||||
|
|
||||||
|
This package does not support schema 1 images, see [`#377`](https://github.com/google/go-containerregistry/issues/377),
|
||||||
|
however, it's possible to do _something_ useful with them via [`remote.Get`](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/remote#Get),
|
||||||
|
which doesn't try to interpret what is returned by the registry.
|
||||||
|
|
||||||
|
[`crane.Copy`](https://godoc.org/github.com/google/go-containerregistry/pkg/crane#Copy) takes advantage of this to implement support for copying schema 1 images,
|
||||||
|
see [here](https://github.com/google/go-containerregistry/blob/master/pkg/internal/legacy/copy.go).
|
16
vendor/github.com/google/go-containerregistry/pkg/v1/remote/descriptor.go
generated
vendored
16
vendor/github.com/google/go-containerregistry/pkg/v1/remote/descriptor.go
generated
vendored
@ -77,14 +77,12 @@ func (d *Descriptor) RawManifest() ([]byte, error) {
|
|||||||
// querying what kind of artifact a reference represents.
|
// querying what kind of artifact a reference represents.
|
||||||
func Get(ref name.Reference, options ...Option) (*Descriptor, error) {
|
func Get(ref name.Reference, options ...Option) (*Descriptor, error) {
|
||||||
acceptable := []types.MediaType{
|
acceptable := []types.MediaType{
|
||||||
types.DockerManifestSchema2,
|
|
||||||
types.OCIManifestSchema1,
|
|
||||||
types.DockerManifestList,
|
|
||||||
types.OCIImageIndex,
|
|
||||||
// Just to look at them.
|
// Just to look at them.
|
||||||
types.DockerManifestSchema1,
|
types.DockerManifestSchema1,
|
||||||
types.DockerManifestSchema1Signed,
|
types.DockerManifestSchema1Signed,
|
||||||
}
|
}
|
||||||
|
acceptable = append(acceptable, acceptableImageMediaTypes...)
|
||||||
|
acceptable = append(acceptable, acceptableIndexMediaTypes...)
|
||||||
return get(ref, acceptable, options...)
|
return get(ref, acceptable, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,8 +172,9 @@ func (d *Descriptor) remoteImage() *remoteImage {
|
|||||||
Ref: d.Ref,
|
Ref: d.Ref,
|
||||||
Client: d.Client,
|
Client: d.Client,
|
||||||
},
|
},
|
||||||
manifest: d.Manifest,
|
manifest: d.Manifest,
|
||||||
mediaType: d.MediaType,
|
mediaType: d.MediaType,
|
||||||
|
descriptor: &d.Descriptor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,8 +184,9 @@ func (d *Descriptor) remoteIndex() *remoteIndex {
|
|||||||
Ref: d.Ref,
|
Ref: d.Ref,
|
||||||
Client: d.Client,
|
Client: d.Client,
|
||||||
},
|
},
|
||||||
manifest: d.Manifest,
|
manifest: d.Manifest,
|
||||||
mediaType: d.MediaType,
|
mediaType: d.MediaType,
|
||||||
|
descriptor: &d.Descriptor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
vendor/github.com/google/go-containerregistry/pkg/v1/remote/image.go
generated
vendored
30
vendor/github.com/google/go-containerregistry/pkg/v1/remote/image.go
generated
vendored
@ -29,6 +29,11 @@ import (
|
|||||||
"github.com/google/go-containerregistry/pkg/v1/v1util"
|
"github.com/google/go-containerregistry/pkg/v1/v1util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var acceptableImageMediaTypes = []types.MediaType{
|
||||||
|
types.DockerManifestSchema2,
|
||||||
|
types.OCIManifestSchema1,
|
||||||
|
}
|
||||||
|
|
||||||
// remoteImage accesses an image from a remote registry
|
// remoteImage accesses an image from a remote registry
|
||||||
type remoteImage struct {
|
type remoteImage struct {
|
||||||
fetcher
|
fetcher
|
||||||
@ -37,6 +42,7 @@ type remoteImage struct {
|
|||||||
configLock sync.Mutex // Protects config
|
configLock sync.Mutex // Protects config
|
||||||
config []byte
|
config []byte
|
||||||
mediaType types.MediaType
|
mediaType types.MediaType
|
||||||
|
descriptor *v1.Descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ partial.CompressedImageCore = (*remoteImage)(nil)
|
var _ partial.CompressedImageCore = (*remoteImage)(nil)
|
||||||
@ -68,15 +74,14 @@ func (r *remoteImage) RawManifest() ([]byte, error) {
|
|||||||
// NOTE(jonjohnsonjr): We should never get here because the public entrypoints
|
// NOTE(jonjohnsonjr): We should never get here because the public entrypoints
|
||||||
// do type-checking via remote.Descriptor. I've left this here for tests that
|
// do type-checking via remote.Descriptor. I've left this here for tests that
|
||||||
// directly instantiate a remoteImage.
|
// directly instantiate a remoteImage.
|
||||||
acceptable := []types.MediaType{
|
manifest, desc, err := r.fetchManifest(r.Ref, acceptableImageMediaTypes)
|
||||||
types.DockerManifestSchema2,
|
|
||||||
types.OCIManifestSchema1,
|
|
||||||
}
|
|
||||||
manifest, desc, err := r.fetchManifest(r.Ref, acceptable)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r.descriptor == nil {
|
||||||
|
r.descriptor = desc
|
||||||
|
}
|
||||||
r.mediaType = desc.MediaType
|
r.mediaType = desc.MediaType
|
||||||
r.manifest = manifest
|
r.manifest = manifest
|
||||||
return r.manifest, nil
|
return r.manifest, nil
|
||||||
@ -107,6 +112,15 @@ func (r *remoteImage) RawConfigFile() ([]byte, error) {
|
|||||||
return r.config, nil
|
return r.config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Descriptor retains the original descriptor from an index manifest.
|
||||||
|
// See partial.Descriptor.
|
||||||
|
func (r *remoteImage) Descriptor() (*v1.Descriptor, error) {
|
||||||
|
// kind of a hack, but RawManifest does appropriate locking/memoization
|
||||||
|
// and makes sure r.descriptor is populated.
|
||||||
|
_, err := r.RawManifest()
|
||||||
|
return r.descriptor, err
|
||||||
|
}
|
||||||
|
|
||||||
// remoteImageLayer implements partial.CompressedLayer
|
// remoteImageLayer implements partial.CompressedLayer
|
||||||
type remoteImageLayer struct {
|
type remoteImageLayer struct {
|
||||||
ri *remoteImage
|
ri *remoteImage
|
||||||
@ -192,6 +206,12 @@ func (rl *remoteImageLayer) DiffID() (v1.Hash, error) {
|
|||||||
return partial.BlobToDiffID(rl, rl.digest)
|
return partial.BlobToDiffID(rl, rl.digest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Descriptor retains the original descriptor from an image manifest.
|
||||||
|
// See partial.Descriptor.
|
||||||
|
func (rl *remoteImageLayer) Descriptor() (*v1.Descriptor, error) {
|
||||||
|
return partial.BlobDescriptor(rl, rl.digest)
|
||||||
|
}
|
||||||
|
|
||||||
// LayerByDigest implements partial.CompressedLayer
|
// LayerByDigest implements partial.CompressedLayer
|
||||||
func (r *remoteImage) LayerByDigest(h v1.Hash) (partial.CompressedLayer, error) {
|
func (r *remoteImage) LayerByDigest(h v1.Hash) (partial.CompressedLayer, error) {
|
||||||
return &remoteImageLayer{
|
return &remoteImageLayer{
|
||||||
|
35
vendor/github.com/google/go-containerregistry/pkg/v1/remote/index.go
generated
vendored
35
vendor/github.com/google/go-containerregistry/pkg/v1/remote/index.go
generated
vendored
@ -25,22 +25,23 @@ import (
|
|||||||
"github.com/google/go-containerregistry/pkg/v1/types"
|
"github.com/google/go-containerregistry/pkg/v1/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var acceptableIndexMediaTypes = []types.MediaType{
|
||||||
|
types.DockerManifestList,
|
||||||
|
types.OCIImageIndex,
|
||||||
|
}
|
||||||
|
|
||||||
// remoteIndex accesses an index from a remote registry
|
// remoteIndex accesses an index from a remote registry
|
||||||
type remoteIndex struct {
|
type remoteIndex struct {
|
||||||
fetcher
|
fetcher
|
||||||
manifestLock sync.Mutex // Protects manifest
|
manifestLock sync.Mutex // Protects manifest
|
||||||
manifest []byte
|
manifest []byte
|
||||||
mediaType types.MediaType
|
mediaType types.MediaType
|
||||||
|
descriptor *v1.Descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
// Index provides access to a remote index reference.
|
// Index provides access to a remote index reference.
|
||||||
func Index(ref name.Reference, options ...Option) (v1.ImageIndex, error) {
|
func Index(ref name.Reference, options ...Option) (v1.ImageIndex, error) {
|
||||||
acceptable := []types.MediaType{
|
desc, err := get(ref, acceptableIndexMediaTypes, options...)
|
||||||
types.DockerManifestList,
|
|
||||||
types.OCIImageIndex,
|
|
||||||
}
|
|
||||||
|
|
||||||
desc, err := get(ref, acceptable, options...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -73,15 +74,14 @@ func (r *remoteIndex) RawManifest() ([]byte, error) {
|
|||||||
// NOTE(jonjohnsonjr): We should never get here because the public entrypoints
|
// NOTE(jonjohnsonjr): We should never get here because the public entrypoints
|
||||||
// do type-checking via remote.Descriptor. I've left this here for tests that
|
// do type-checking via remote.Descriptor. I've left this here for tests that
|
||||||
// directly instantiate a remoteIndex.
|
// directly instantiate a remoteIndex.
|
||||||
acceptable := []types.MediaType{
|
manifest, desc, err := r.fetchManifest(r.Ref, acceptableIndexMediaTypes)
|
||||||
types.DockerManifestList,
|
|
||||||
types.OCIImageIndex,
|
|
||||||
}
|
|
||||||
manifest, desc, err := r.fetchManifest(r.Ref, acceptable)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r.descriptor == nil {
|
||||||
|
r.descriptor = desc
|
||||||
|
}
|
||||||
r.mediaType = desc.MediaType
|
r.mediaType = desc.MediaType
|
||||||
r.manifest = manifest
|
r.manifest = manifest
|
||||||
return r.manifest, nil
|
return r.manifest, nil
|
||||||
@ -105,6 +105,15 @@ func (r *remoteIndex) Image(h v1.Hash) (v1.Image, error) {
|
|||||||
return desc.Image()
|
return desc.Image()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Descriptor retains the original descriptor from an index manifest.
|
||||||
|
// See partial.Descriptor.
|
||||||
|
func (r *remoteIndex) Descriptor() (*v1.Descriptor, error) {
|
||||||
|
// kind of a hack, but RawManifest does appropriate locking/memoization
|
||||||
|
// and makes sure r.descriptor is populated.
|
||||||
|
_, err := r.RawManifest()
|
||||||
|
return r.descriptor, err
|
||||||
|
}
|
||||||
|
|
||||||
func (r *remoteIndex) ImageIndex(h v1.Hash) (v1.ImageIndex, error) {
|
func (r *remoteIndex) ImageIndex(h v1.Hash) (v1.ImageIndex, error) {
|
||||||
desc, err := r.childByHash(h)
|
desc, err := r.childByHash(h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -165,7 +174,7 @@ func (r *remoteIndex) childByHash(h v1.Hash) (*Descriptor, error) {
|
|||||||
// Convert one of this index's child's v1.Descriptor into a remote.Descriptor, with the given platform option.
|
// Convert one of this index's child's v1.Descriptor into a remote.Descriptor, with the given platform option.
|
||||||
func (r *remoteIndex) childDescriptor(child v1.Descriptor, platform v1.Platform) (*Descriptor, error) {
|
func (r *remoteIndex) childDescriptor(child v1.Descriptor, platform v1.Platform) (*Descriptor, error) {
|
||||||
ref := r.Ref.Context().Digest(child.Digest.String())
|
ref := r.Ref.Context().Digest(child.Digest.String())
|
||||||
manifest, desc, err := r.fetchManifest(ref, []types.MediaType{child.MediaType})
|
manifest, _, err := r.fetchManifest(ref, []types.MediaType{child.MediaType})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -175,7 +184,7 @@ func (r *remoteIndex) childDescriptor(child v1.Descriptor, platform v1.Platform)
|
|||||||
Client: r.Client,
|
Client: r.Client,
|
||||||
},
|
},
|
||||||
Manifest: manifest,
|
Manifest: manifest,
|
||||||
Descriptor: *desc,
|
Descriptor: child,
|
||||||
platform: platform,
|
platform: platform,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
10
vendor/github.com/google/go-containerregistry/pkg/v1/remote/list.go
generated
vendored
10
vendor/github.com/google/go-containerregistry/pkg/v1/remote/list.go
generated
vendored
@ -50,10 +50,12 @@ func ListWithContext(ctx context.Context, repo name.Repository, options ...Optio
|
|||||||
}
|
}
|
||||||
|
|
||||||
uri := &url.URL{
|
uri := &url.URL{
|
||||||
Scheme: repo.Registry.Scheme(),
|
Scheme: repo.Registry.Scheme(),
|
||||||
Host: repo.Registry.RegistryStr(),
|
Host: repo.Registry.RegistryStr(),
|
||||||
Path: fmt.Sprintf("/v2/%s/tags/list", repo.RepositoryStr()),
|
Path: fmt.Sprintf("/v2/%s/tags/list", repo.RepositoryStr()),
|
||||||
RawQuery: "n=10000",
|
// ECR returns an error if n > 1000:
|
||||||
|
// https://github.com/google/go-containerregistry/issues/681
|
||||||
|
RawQuery: "n=1000",
|
||||||
}
|
}
|
||||||
|
|
||||||
client := http.Client{Transport: tr}
|
client := http.Client{Transport: tr}
|
||||||
|
13
vendor/github.com/google/go-containerregistry/pkg/v1/remote/mount.go
generated
vendored
13
vendor/github.com/google/go-containerregistry/pkg/v1/remote/mount.go
generated
vendored
@ -17,6 +17,7 @@ package remote
|
|||||||
import (
|
import (
|
||||||
"github.com/google/go-containerregistry/pkg/name"
|
"github.com/google/go-containerregistry/pkg/name"
|
||||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||||
|
"github.com/google/go-containerregistry/pkg/v1/partial"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MountableLayer wraps a v1.Layer in a shim that enables the layer to be
|
// MountableLayer wraps a v1.Layer in a shim that enables the layer to be
|
||||||
@ -27,6 +28,12 @@ type MountableLayer struct {
|
|||||||
Reference name.Reference
|
Reference name.Reference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Descriptor retains the original descriptor from an image manifest.
|
||||||
|
// See partial.Descriptor.
|
||||||
|
func (ml *MountableLayer) Descriptor() (*v1.Descriptor, error) {
|
||||||
|
return partial.Descriptor(ml.Layer)
|
||||||
|
}
|
||||||
|
|
||||||
// mountableImage wraps the v1.Layer references returned by the embedded v1.Image
|
// mountableImage wraps the v1.Layer references returned by the embedded v1.Image
|
||||||
// in MountableLayer's so that remote.Write might attempt to mount them from their
|
// in MountableLayer's so that remote.Write might attempt to mount them from their
|
||||||
// source repository.
|
// source repository.
|
||||||
@ -75,3 +82,9 @@ func (mi *mountableImage) LayerByDiffID(d v1.Hash) (v1.Layer, error) {
|
|||||||
Reference: mi.Reference,
|
Reference: mi.Reference,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Descriptor retains the original descriptor from an index manifest.
|
||||||
|
// See partial.Descriptor.
|
||||||
|
func (mi *mountableImage) Descriptor() (*v1.Descriptor, error) {
|
||||||
|
return partial.Descriptor(mi.Image)
|
||||||
|
}
|
||||||
|
2
vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/README.md
generated
vendored
2
vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/README.md
generated
vendored
@ -1,5 +1,7 @@
|
|||||||
# `transport`
|
# `transport`
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/transport?status.svg)](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/transport)
|
||||||
|
|
||||||
The [distribution protocol](https://github.com/opencontainers/distribution-spec) is fairly simple, but correctly [implementing authentication](../../../authn/README.md) is **hard**.
|
The [distribution protocol](https://github.com/opencontainers/distribution-spec) is fairly simple, but correctly [implementing authentication](../../../authn/README.md) is **hard**.
|
||||||
|
|
||||||
This package [implements](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/remote/transport#New) an [`http.RoundTripper`](https://godoc.org/net/http#RoundTripper)
|
This package [implements](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/remote/transport#New) an [`http.RoundTripper`](https://godoc.org/net/http#RoundTripper)
|
||||||
|
2
vendor/github.com/google/go-containerregistry/pkg/v1/remote/write.go
generated
vendored
2
vendor/github.com/google/go-containerregistry/pkg/v1/remote/write.go
generated
vendored
@ -449,7 +449,7 @@ func scopesForUploadingImage(repo name.Repository, layers []v1.Layer) []string {
|
|||||||
if ml, ok := l.(*MountableLayer); ok {
|
if ml, ok := l.(*MountableLayer); ok {
|
||||||
// we will add push scope for ref.Context() after the loop.
|
// we will add push scope for ref.Context() after the loop.
|
||||||
// for now we ask pull scope for references of the same registry
|
// for now we ask pull scope for references of the same registry
|
||||||
if ml.Reference.Context() != repo && ml.Reference.Context().Registry == repo.Registry {
|
if ml.Reference.Context().String() != repo.String() && ml.Reference.Context().Registry.String() == repo.Registry.String() {
|
||||||
scopeSet[ml.Reference.Scope(transport.PullScope)] = struct{}{}
|
scopeSet[ml.Reference.Scope(transport.PullScope)] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
68
vendor/github.com/google/go-containerregistry/pkg/v1/stream/README.md
generated
vendored
Normal file
68
vendor/github.com/google/go-containerregistry/pkg/v1/stream/README.md
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
# `stream`
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/stream?status.svg)](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/stream)
|
||||||
|
|
||||||
|
The `stream` package contains an implementation of
|
||||||
|
[`v1.Layer`](https://godoc.org/github.com/google/go-containerregistry/pkg/v1#Layer)
|
||||||
|
that supports _streaming_ access, i.e. the layer contents are read once and not
|
||||||
|
buffered.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/google/go-containerregistry/pkg/name"
|
||||||
|
"github.com/google/go-containerregistry/pkg/v1/remote"
|
||||||
|
"github.com/google/go-containerregistry/pkg/v1/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
// upload the contents of stdin as a layer to a local registry
|
||||||
|
func main() {
|
||||||
|
repo, err := name.NewRepository("localhost:5000/stream")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
layer := stream.NewLayer(os.Stdin)
|
||||||
|
|
||||||
|
if err := remote.WriteLayer(repo, layer); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
This implements the layer portion of an [image
|
||||||
|
upload](/pkg/v1/remote#anatomy-of-an-image-upload). We launch a goroutine that
|
||||||
|
is responsible for hashing the uncompressed contents to compute the `DiffID`,
|
||||||
|
gzipping them to produce the `Compressed` contents, and hashing/counting the
|
||||||
|
bytes to produce the `Digest`/`Size`. This goroutine writes to an
|
||||||
|
`io.PipeWriter`, which blocks until `Compressed` reads the gzipped contents from
|
||||||
|
the corresponding `io.PipeReader`.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="/images/stream.dot.svg" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
This assumes that you have an uncompressed layer (i.e. a tarball) and would like
|
||||||
|
to compress it. Calling `Uncompressed` is always an error. Likewise, other
|
||||||
|
methods are invalid until the contents of `Compressed` have been completely
|
||||||
|
consumed and `Close`d.
|
||||||
|
|
||||||
|
Using a `stream.Layer` will likely not work without careful consideration. For
|
||||||
|
example, in the `mutate` package, we defer computing the manifest and config
|
||||||
|
file until they are actually called. This allows you to `mutate.Append` a
|
||||||
|
streaming layer to an image without accidentally consuming it. Similarly, in
|
||||||
|
`remote.Write`, if calling `Digest` on a layer fails, we attempt to upload the
|
||||||
|
layer anyway, understanding that we may be dealing with a `stream.Layer` whose
|
||||||
|
contents need to be uploaded before we can upload the config file.
|
||||||
|
|
||||||
|
Given the [structure](#structure) of how this is implemented, forgetting to
|
||||||
|
`Close` a `stream.Layer` will leak a goroutine.
|
280
vendor/github.com/google/go-containerregistry/pkg/v1/tarball/README.md
generated
vendored
Normal file
280
vendor/github.com/google/go-containerregistry/pkg/v1/tarball/README.md
generated
vendored
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
# `tarball`
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/tarball?status.svg)](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/tarball)
|
||||||
|
|
||||||
|
This package produces tarballs that can consumed via `docker load`. Note
|
||||||
|
that this is a _different_ format from the [`legacy`](/pkg/legacy/tarball)
|
||||||
|
tarballs that are produced by `docker save`, but this package is still able to
|
||||||
|
read the legacy tarballs produced by `docker save`.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/google/go-containerregistry/pkg/name"
|
||||||
|
"github.com/google/go-containerregistry/pkg/v1/tarball"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Read a tarball from os.Args[1] that contains ubuntu.
|
||||||
|
tag, err := name.NewTag("ubuntu")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
img, err := tarball.ImageFromPath(os.Args[1], &tag)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write that tarball to os.Args[2] with a different tag.
|
||||||
|
newTag, err := name.NewTag("ubuntu:newest")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
f, err := os.Create(os.Args[2])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
if err := tarball.Write(newTag, img, f); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="/images/tarball.dot.svg" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
Let's look at what happens when we write out a tarball:
|
||||||
|
|
||||||
|
|
||||||
|
### `ubuntu:latest`
|
||||||
|
|
||||||
|
```
|
||||||
|
$ crane pull ubuntu ubuntu.tar && mkdir ubuntu && tar xf ubuntu.tar -C ubuntu && rm ubuntu.tar
|
||||||
|
$ tree ubuntu/
|
||||||
|
ubuntu/
|
||||||
|
├── 423ae2b273f4c17ceee9e8482fa8d071d90c7d052ae208e1fe4963fceb3d6954.tar.gz
|
||||||
|
├── b6b53be908de2c0c78070fff0a9f04835211b3156c4e73785747af365e71a0d7.tar.gz
|
||||||
|
├── de83a2304fa1f7c4a13708a0d15b9704f5945c2be5cbb2b3ed9b2ccb718d0b3d.tar.gz
|
||||||
|
├── f9a83bce3af0648efaa60b9bb28225b09136d2d35d0bed25ac764297076dec1b.tar.gz
|
||||||
|
├── manifest.json
|
||||||
|
└── sha256:72300a873c2ca11c70d0c8642177ce76ff69ae04d61a5813ef58d40ff66e3e7c
|
||||||
|
|
||||||
|
0 directories, 6 files
|
||||||
|
```
|
||||||
|
|
||||||
|
There are a couple interesting files here.
|
||||||
|
|
||||||
|
`manifest.json` is the entrypoint: a list of [`tarball.Descriptor`s](https://godoc.org/github.com/google/go-containerregistry/pkg/v1/tarball#Descriptor)
|
||||||
|
that describe the images containd in this tarball.
|
||||||
|
|
||||||
|
For each image, this has the `RepoTags` (how it was pulled), a `Config` file
|
||||||
|
that points to the image's config file, a list of `Layers`, and (optionally)
|
||||||
|
`LayerSources`.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ jq < ubuntu/manifest.json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"Config": "sha256:72300a873c2ca11c70d0c8642177ce76ff69ae04d61a5813ef58d40ff66e3e7c",
|
||||||
|
"RepoTags": [
|
||||||
|
"ubuntu"
|
||||||
|
],
|
||||||
|
"Layers": [
|
||||||
|
"423ae2b273f4c17ceee9e8482fa8d071d90c7d052ae208e1fe4963fceb3d6954.tar.gz",
|
||||||
|
"de83a2304fa1f7c4a13708a0d15b9704f5945c2be5cbb2b3ed9b2ccb718d0b3d.tar.gz",
|
||||||
|
"f9a83bce3af0648efaa60b9bb28225b09136d2d35d0bed25ac764297076dec1b.tar.gz",
|
||||||
|
"b6b53be908de2c0c78070fff0a9f04835211b3156c4e73785747af365e71a0d7.tar.gz"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
The config file and layers are exactly what you would expect, and match the
|
||||||
|
registry representations of the same artifacts. You'll notice that the
|
||||||
|
`manifest.json` contains similar information as the registry manifest, but isn't
|
||||||
|
quite the same:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ crane manifest ubuntu@sha256:0925d086715714114c1988f7c947db94064fd385e171a63c07730f1fa014e6f9
|
||||||
|
{
|
||||||
|
"schemaVersion": 2,
|
||||||
|
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||||
|
"config": {
|
||||||
|
"mediaType": "application/vnd.docker.container.image.v1+json",
|
||||||
|
"size": 3408,
|
||||||
|
"digest": "sha256:72300a873c2ca11c70d0c8642177ce76ff69ae04d61a5813ef58d40ff66e3e7c"
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
|
"size": 26692096,
|
||||||
|
"digest": "sha256:423ae2b273f4c17ceee9e8482fa8d071d90c7d052ae208e1fe4963fceb3d6954"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
|
"size": 35365,
|
||||||
|
"digest": "sha256:de83a2304fa1f7c4a13708a0d15b9704f5945c2be5cbb2b3ed9b2ccb718d0b3d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
|
"size": 852,
|
||||||
|
"digest": "sha256:f9a83bce3af0648efaa60b9bb28225b09136d2d35d0bed25ac764297076dec1b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
|
"size": 163,
|
||||||
|
"digest": "sha256:b6b53be908de2c0c78070fff0a9f04835211b3156c4e73785747af365e71a0d7"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This makes it difficult to maintain image digests when roundtripping images
|
||||||
|
through the tarball format, so it's not a great format if you care about
|
||||||
|
provenance.
|
||||||
|
|
||||||
|
The ubuntu example didn't have any `LayerSources` -- let's look at another image
|
||||||
|
that does.
|
||||||
|
|
||||||
|
### `hello-world:nanoserver`
|
||||||
|
|
||||||
|
```
|
||||||
|
$ crane pull hello-world:nanoserver@sha256:63c287625c2b0b72900e562de73c0e381472a83b1b39217aef3856cd398eca0b nanoserver.tar
|
||||||
|
$ mkdir nanoserver && tar xf nanoserver.tar -C nanoserver && rm nanoserver.tar
|
||||||
|
$ tree nanoserver/
|
||||||
|
nanoserver/
|
||||||
|
├── 10d1439be4eb8819987ec2e9c140d44d74d6b42a823d57fe1953bd99948e1bc0.tar.gz
|
||||||
|
├── a35da61c356213336e646756218539950461ff2bf096badf307a23add6e70053.tar.gz
|
||||||
|
├── be21f08f670160cbae227e3053205b91d6bfa3de750b90c7e00bd2c511ccb63a.tar.gz
|
||||||
|
├── manifest.json
|
||||||
|
└── sha256:bc5d255ea81f83c8c38a982a6d29a6f2198427d258aea5f166e49856896b2da6
|
||||||
|
|
||||||
|
0 directories, 5 files
|
||||||
|
|
||||||
|
$ jq < nanoserver/manifest.json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"Config": "sha256:bc5d255ea81f83c8c38a982a6d29a6f2198427d258aea5f166e49856896b2da6",
|
||||||
|
"RepoTags": [
|
||||||
|
"index.docker.io/library/hello-world:i-was-a-digest"
|
||||||
|
],
|
||||||
|
"Layers": [
|
||||||
|
"a35da61c356213336e646756218539950461ff2bf096badf307a23add6e70053.tar.gz",
|
||||||
|
"be21f08f670160cbae227e3053205b91d6bfa3de750b90c7e00bd2c511ccb63a.tar.gz",
|
||||||
|
"10d1439be4eb8819987ec2e9c140d44d74d6b42a823d57fe1953bd99948e1bc0.tar.gz"
|
||||||
|
],
|
||||||
|
"LayerSources": {
|
||||||
|
"sha256:26fd2d9d4c64a4f965bbc77939a454a31b607470f430b5d69fc21ded301fa55e": {
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.foreign.diff.tar.gzip",
|
||||||
|
"size": 101145811,
|
||||||
|
"digest": "sha256:a35da61c356213336e646756218539950461ff2bf096badf307a23add6e70053",
|
||||||
|
"urls": [
|
||||||
|
"https://mcr.microsoft.com/v2/windows/nanoserver/blobs/sha256:a35da61c356213336e646756218539950461ff2bf096badf307a23add6e70053"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
A couple things to note about this `manifest.json` versus the other:
|
||||||
|
* The `RepoTags` field is a bit weird here. `hello-world` is a multi-platform
|
||||||
|
image, so We had to pull this image by digest, since we're (I'm) on
|
||||||
|
amd64/linux and wanted to grab a windows image. Since the tarball format
|
||||||
|
expects a tag under `RepoTags`, and we didn't pull by tag, we replace the
|
||||||
|
digest with a sentinel `i-was-a-digest` "tag" to appease docker.
|
||||||
|
* The `LayerSources` has enough information to reconstruct the foreign layers
|
||||||
|
pointer when pushing/pulling from the registry. For legal reasons, microsoft
|
||||||
|
doesn't want anyone but them to serve windows base images, so the mediaType
|
||||||
|
here indicates a "foreign" or "non-distributable" layer with an URL for where
|
||||||
|
you can download it from microsoft (see the [OCI
|
||||||
|
image-spec](https://github.com/opencontainers/image-spec/blob/master/layer.md#non-distributable-layers)).
|
||||||
|
|
||||||
|
We can look at what's in the registry to explain both of these things:
|
||||||
|
```
|
||||||
|
$ crane manifest hello-world:nanoserver | jq .
|
||||||
|
{
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"digest": "sha256:63c287625c2b0b72900e562de73c0e381472a83b1b39217aef3856cd398eca0b",
|
||||||
|
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||||
|
"platform": {
|
||||||
|
"architecture": "amd64",
|
||||||
|
"os": "windows",
|
||||||
|
"os.version": "10.0.17763.1040"
|
||||||
|
},
|
||||||
|
"size": 1124
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
|
||||||
|
"schemaVersion": 2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Note the media type and "urls" field.
|
||||||
|
$ crane manifest hello-world:nanoserver@sha256:63c287625c2b0b72900e562de73c0e381472a83b1b39217aef3856cd398eca0b | jq .
|
||||||
|
{
|
||||||
|
"schemaVersion": 2,
|
||||||
|
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||||
|
"config": {
|
||||||
|
"mediaType": "application/vnd.docker.container.image.v1+json",
|
||||||
|
"size": 1721,
|
||||||
|
"digest": "sha256:bc5d255ea81f83c8c38a982a6d29a6f2198427d258aea5f166e49856896b2da6"
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.foreign.diff.tar.gzip",
|
||||||
|
"size": 101145811,
|
||||||
|
"digest": "sha256:a35da61c356213336e646756218539950461ff2bf096badf307a23add6e70053",
|
||||||
|
"urls": [
|
||||||
|
"https://mcr.microsoft.com/v2/windows/nanoserver/blobs/sha256:a35da61c356213336e646756218539950461ff2bf096badf307a23add6e70053"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
|
"size": 1669,
|
||||||
|
"digest": "sha256:be21f08f670160cbae227e3053205b91d6bfa3de750b90c7e00bd2c511ccb63a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
|
"size": 949,
|
||||||
|
"digest": "sha256:10d1439be4eb8819987ec2e9c140d44d74d6b42a823d57fe1953bd99948e1bc0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `LayerSources` map is keyed by the diffid. Note that `sha256:26fd2d9d4c64a4f965bbc77939a454a31b607470f430b5d69fc21ded301fa55e` matches the first layer in the config file:
|
||||||
|
```
|
||||||
|
$ jq '.[0].LayerSources' < nanoserver/manifest.json
|
||||||
|
{
|
||||||
|
"sha256:26fd2d9d4c64a4f965bbc77939a454a31b607470f430b5d69fc21ded301fa55e": {
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.foreign.diff.tar.gzip",
|
||||||
|
"size": 101145811,
|
||||||
|
"digest": "sha256:a35da61c356213336e646756218539950461ff2bf096badf307a23add6e70053",
|
||||||
|
"urls": [
|
||||||
|
"https://mcr.microsoft.com/v2/windows/nanoserver/blobs/sha256:a35da61c356213336e646756218539950461ff2bf096badf307a23add6e70053"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ jq < nanoserver/sha256\:bc5d255ea81f83c8c38a982a6d29a6f2198427d258aea5f166e49856896b2da6 | jq .rootfs
|
||||||
|
{
|
||||||
|
"type": "layers",
|
||||||
|
"diff_ids": [
|
||||||
|
"sha256:26fd2d9d4c64a4f965bbc77939a454a31b607470f430b5d69fc21ded301fa55e",
|
||||||
|
"sha256:601cf7d78c62e4b4d32a7bbf96a17606a9cea5bd9d22ffa6f34aa431d056b0e8",
|
||||||
|
"sha256:a1e1a3bf6529adcce4d91dce2cad86c2604a66b507ccbc4d2239f3da0ec5aab9"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
2
vendor/github.com/google/go-containerregistry/pkg/v1/tarball/write.go
generated
vendored
2
vendor/github.com/google/go-containerregistry/pkg/v1/tarball/write.go
generated
vendored
@ -146,7 +146,7 @@ func MultiRefWrite(refToImage map[name.Reference]v1.Image, w io.Writer) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
layerSources[diffid] = desc
|
layerSources[diffid] = *desc
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := l.Compressed()
|
r, err := l.Compressed()
|
||||||
|
11
vendor/github.com/pkg/errors/.travis.yml
generated
vendored
11
vendor/github.com/pkg/errors/.travis.yml
generated
vendored
@ -1,15 +1,10 @@
|
|||||||
language: go
|
language: go
|
||||||
go_import_path: github.com/pkg/errors
|
go_import_path: github.com/pkg/errors
|
||||||
go:
|
go:
|
||||||
- 1.4.x
|
|
||||||
- 1.5.x
|
|
||||||
- 1.6.x
|
|
||||||
- 1.7.x
|
|
||||||
- 1.8.x
|
|
||||||
- 1.9.x
|
|
||||||
- 1.10.x
|
|
||||||
- 1.11.x
|
- 1.11.x
|
||||||
|
- 1.12.x
|
||||||
|
- 1.13.x
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- go test -v ./...
|
- make check
|
||||||
|
44
vendor/github.com/pkg/errors/Makefile
generated
vendored
Normal file
44
vendor/github.com/pkg/errors/Makefile
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
PKGS := github.com/pkg/errors
|
||||||
|
SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS))
|
||||||
|
GO := go
|
||||||
|
|
||||||
|
check: test vet gofmt misspell unconvert staticcheck ineffassign unparam
|
||||||
|
|
||||||
|
test:
|
||||||
|
$(GO) test $(PKGS)
|
||||||
|
|
||||||
|
vet: | test
|
||||||
|
$(GO) vet $(PKGS)
|
||||||
|
|
||||||
|
staticcheck:
|
||||||
|
$(GO) get honnef.co/go/tools/cmd/staticcheck
|
||||||
|
staticcheck -checks all $(PKGS)
|
||||||
|
|
||||||
|
misspell:
|
||||||
|
$(GO) get github.com/client9/misspell/cmd/misspell
|
||||||
|
misspell \
|
||||||
|
-locale GB \
|
||||||
|
-error \
|
||||||
|
*.md *.go
|
||||||
|
|
||||||
|
unconvert:
|
||||||
|
$(GO) get github.com/mdempsky/unconvert
|
||||||
|
unconvert -v $(PKGS)
|
||||||
|
|
||||||
|
ineffassign:
|
||||||
|
$(GO) get github.com/gordonklaus/ineffassign
|
||||||
|
find $(SRCDIRS) -name '*.go' | xargs ineffassign
|
||||||
|
|
||||||
|
pedantic: check errcheck
|
||||||
|
|
||||||
|
unparam:
|
||||||
|
$(GO) get mvdan.cc/unparam
|
||||||
|
unparam ./...
|
||||||
|
|
||||||
|
errcheck:
|
||||||
|
$(GO) get github.com/kisielk/errcheck
|
||||||
|
errcheck $(PKGS)
|
||||||
|
|
||||||
|
gofmt:
|
||||||
|
@echo Checking code is gofmted
|
||||||
|
@test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)"
|
11
vendor/github.com/pkg/errors/README.md
generated
vendored
11
vendor/github.com/pkg/errors/README.md
generated
vendored
@ -41,11 +41,18 @@ default:
|
|||||||
|
|
||||||
[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).
|
[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows:
|
||||||
|
|
||||||
|
- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible)
|
||||||
|
- 1.0. Final release.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high.
|
Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports.
|
||||||
|
|
||||||
Before proposing a change, please discuss your change by raising an issue.
|
Before sending a PR, please discuss your change by raising an issue.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
8
vendor/github.com/pkg/errors/errors.go
generated
vendored
8
vendor/github.com/pkg/errors/errors.go
generated
vendored
@ -82,7 +82,7 @@
|
|||||||
//
|
//
|
||||||
// if err, ok := err.(stackTracer); ok {
|
// if err, ok := err.(stackTracer); ok {
|
||||||
// for _, f := range err.StackTrace() {
|
// for _, f := range err.StackTrace() {
|
||||||
// fmt.Printf("%+s:%d", f)
|
// fmt.Printf("%+s:%d\n", f, f)
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
@ -159,6 +159,9 @@ type withStack struct {
|
|||||||
|
|
||||||
func (w *withStack) Cause() error { return w.error }
|
func (w *withStack) Cause() error { return w.error }
|
||||||
|
|
||||||
|
// Unwrap provides compatibility for Go 1.13 error chains.
|
||||||
|
func (w *withStack) Unwrap() error { return w.error }
|
||||||
|
|
||||||
func (w *withStack) Format(s fmt.State, verb rune) {
|
func (w *withStack) Format(s fmt.State, verb rune) {
|
||||||
switch verb {
|
switch verb {
|
||||||
case 'v':
|
case 'v':
|
||||||
@ -241,6 +244,9 @@ type withMessage struct {
|
|||||||
func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
|
func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
|
||||||
func (w *withMessage) Cause() error { return w.cause }
|
func (w *withMessage) Cause() error { return w.cause }
|
||||||
|
|
||||||
|
// Unwrap provides compatibility for Go 1.13 error chains.
|
||||||
|
func (w *withMessage) Unwrap() error { return w.cause }
|
||||||
|
|
||||||
func (w *withMessage) Format(s fmt.State, verb rune) {
|
func (w *withMessage) Format(s fmt.State, verb rune) {
|
||||||
switch verb {
|
switch verb {
|
||||||
case 'v':
|
case 'v':
|
||||||
|
38
vendor/github.com/pkg/errors/go113.go
generated
vendored
Normal file
38
vendor/github.com/pkg/errors/go113.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// +build go1.13
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
stderrors "errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Is reports whether any error in err's chain matches target.
|
||||||
|
//
|
||||||
|
// The chain consists of err itself followed by the sequence of errors obtained by
|
||||||
|
// repeatedly calling Unwrap.
|
||||||
|
//
|
||||||
|
// An error is considered to match a target if it is equal to that target or if
|
||||||
|
// it implements a method Is(error) bool such that Is(target) returns true.
|
||||||
|
func Is(err, target error) bool { return stderrors.Is(err, target) }
|
||||||
|
|
||||||
|
// As finds the first error in err's chain that matches target, and if so, sets
|
||||||
|
// target to that error value and returns true.
|
||||||
|
//
|
||||||
|
// The chain consists of err itself followed by the sequence of errors obtained by
|
||||||
|
// repeatedly calling Unwrap.
|
||||||
|
//
|
||||||
|
// An error matches target if the error's concrete value is assignable to the value
|
||||||
|
// pointed to by target, or if the error has a method As(interface{}) bool such that
|
||||||
|
// As(target) returns true. In the latter case, the As method is responsible for
|
||||||
|
// setting target.
|
||||||
|
//
|
||||||
|
// As will panic if target is not a non-nil pointer to either a type that implements
|
||||||
|
// error, or to any interface type. As returns false if err is nil.
|
||||||
|
func As(err error, target interface{}) bool { return stderrors.As(err, target) }
|
||||||
|
|
||||||
|
// Unwrap returns the result of calling the Unwrap method on err, if err's
|
||||||
|
// type contains an Unwrap method returning error.
|
||||||
|
// Otherwise, Unwrap returns nil.
|
||||||
|
func Unwrap(err error) error {
|
||||||
|
return stderrors.Unwrap(err)
|
||||||
|
}
|
58
vendor/github.com/pkg/errors/stack.go
generated
vendored
58
vendor/github.com/pkg/errors/stack.go
generated
vendored
@ -5,10 +5,13 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Frame represents a program counter inside a stack frame.
|
// Frame represents a program counter inside a stack frame.
|
||||||
|
// For historical reasons if Frame is interpreted as a uintptr
|
||||||
|
// its value represents the program counter + 1.
|
||||||
type Frame uintptr
|
type Frame uintptr
|
||||||
|
|
||||||
// pc returns the program counter for this frame;
|
// pc returns the program counter for this frame;
|
||||||
@ -37,6 +40,15 @@ func (f Frame) line() int {
|
|||||||
return line
|
return line
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// name returns the name of this function, if known.
|
||||||
|
func (f Frame) name() string {
|
||||||
|
fn := runtime.FuncForPC(f.pc())
|
||||||
|
if fn == nil {
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
return fn.Name()
|
||||||
|
}
|
||||||
|
|
||||||
// Format formats the frame according to the fmt.Formatter interface.
|
// Format formats the frame according to the fmt.Formatter interface.
|
||||||
//
|
//
|
||||||
// %s source file
|
// %s source file
|
||||||
@ -54,22 +66,16 @@ func (f Frame) Format(s fmt.State, verb rune) {
|
|||||||
case 's':
|
case 's':
|
||||||
switch {
|
switch {
|
||||||
case s.Flag('+'):
|
case s.Flag('+'):
|
||||||
pc := f.pc()
|
io.WriteString(s, f.name())
|
||||||
fn := runtime.FuncForPC(pc)
|
io.WriteString(s, "\n\t")
|
||||||
if fn == nil {
|
io.WriteString(s, f.file())
|
||||||
io.WriteString(s, "unknown")
|
|
||||||
} else {
|
|
||||||
file, _ := fn.FileLine(pc)
|
|
||||||
fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
io.WriteString(s, path.Base(f.file()))
|
io.WriteString(s, path.Base(f.file()))
|
||||||
}
|
}
|
||||||
case 'd':
|
case 'd':
|
||||||
fmt.Fprintf(s, "%d", f.line())
|
io.WriteString(s, strconv.Itoa(f.line()))
|
||||||
case 'n':
|
case 'n':
|
||||||
name := runtime.FuncForPC(f.pc()).Name()
|
io.WriteString(s, funcname(f.name()))
|
||||||
io.WriteString(s, funcname(name))
|
|
||||||
case 'v':
|
case 'v':
|
||||||
f.Format(s, 's')
|
f.Format(s, 's')
|
||||||
io.WriteString(s, ":")
|
io.WriteString(s, ":")
|
||||||
@ -77,6 +83,16 @@ func (f Frame) Format(s fmt.State, verb rune) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalText formats a stacktrace Frame as a text string. The output is the
|
||||||
|
// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs.
|
||||||
|
func (f Frame) MarshalText() ([]byte, error) {
|
||||||
|
name := f.name()
|
||||||
|
if name == "unknown" {
|
||||||
|
return []byte(name), nil
|
||||||
|
}
|
||||||
|
return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil
|
||||||
|
}
|
||||||
|
|
||||||
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
|
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
|
||||||
type StackTrace []Frame
|
type StackTrace []Frame
|
||||||
|
|
||||||
@ -94,18 +110,32 @@ func (st StackTrace) Format(s fmt.State, verb rune) {
|
|||||||
switch {
|
switch {
|
||||||
case s.Flag('+'):
|
case s.Flag('+'):
|
||||||
for _, f := range st {
|
for _, f := range st {
|
||||||
fmt.Fprintf(s, "\n%+v", f)
|
io.WriteString(s, "\n")
|
||||||
|
f.Format(s, verb)
|
||||||
}
|
}
|
||||||
case s.Flag('#'):
|
case s.Flag('#'):
|
||||||
fmt.Fprintf(s, "%#v", []Frame(st))
|
fmt.Fprintf(s, "%#v", []Frame(st))
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(s, "%v", []Frame(st))
|
st.formatSlice(s, verb)
|
||||||
}
|
}
|
||||||
case 's':
|
case 's':
|
||||||
fmt.Fprintf(s, "%s", []Frame(st))
|
st.formatSlice(s, verb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// formatSlice will format this StackTrace into the given buffer as a slice of
|
||||||
|
// Frame, only valid when called with '%s' or '%v'.
|
||||||
|
func (st StackTrace) formatSlice(s fmt.State, verb rune) {
|
||||||
|
io.WriteString(s, "[")
|
||||||
|
for i, f := range st {
|
||||||
|
if i > 0 {
|
||||||
|
io.WriteString(s, " ")
|
||||||
|
}
|
||||||
|
f.Format(s, verb)
|
||||||
|
}
|
||||||
|
io.WriteString(s, "]")
|
||||||
|
}
|
||||||
|
|
||||||
// stack represents a stack of program counters.
|
// stack represents a stack of program counters.
|
||||||
type stack []uintptr
|
type stack []uintptr
|
||||||
|
|
||||||
|
8
vendor/golang.org/x/tools/go/internal/gcimporter/gcimporter.go
generated
vendored
8
vendor/golang.org/x/tools/go/internal/gcimporter/gcimporter.go
generated
vendored
@ -344,7 +344,7 @@ func (p *parser) expectKeyword(keyword string) {
|
|||||||
|
|
||||||
// PackageId = string_lit .
|
// PackageId = string_lit .
|
||||||
//
|
//
|
||||||
func (p *parser) parsePackageId() string {
|
func (p *parser) parsePackageID() string {
|
||||||
id, err := strconv.Unquote(p.expect(scanner.String))
|
id, err := strconv.Unquote(p.expect(scanner.String))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.error(err)
|
p.error(err)
|
||||||
@ -384,7 +384,7 @@ func (p *parser) parseDotIdent() string {
|
|||||||
//
|
//
|
||||||
func (p *parser) parseQualifiedName() (id, name string) {
|
func (p *parser) parseQualifiedName() (id, name string) {
|
||||||
p.expect('@')
|
p.expect('@')
|
||||||
id = p.parsePackageId()
|
id = p.parsePackageID()
|
||||||
p.expect('.')
|
p.expect('.')
|
||||||
// Per rev f280b8a485fd (10/2/2013), qualified names may be used for anonymous fields.
|
// Per rev f280b8a485fd (10/2/2013), qualified names may be used for anonymous fields.
|
||||||
if p.tok == '?' {
|
if p.tok == '?' {
|
||||||
@ -696,7 +696,7 @@ func (p *parser) parseInterfaceType(parent *types.Package) types.Type {
|
|||||||
|
|
||||||
// Complete requires the type's embedded interfaces to be fully defined,
|
// Complete requires the type's embedded interfaces to be fully defined,
|
||||||
// but we do not define any
|
// but we do not define any
|
||||||
return types.NewInterface(methods, nil).Complete()
|
return newInterface(methods, nil).Complete()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
|
// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
|
||||||
@ -785,7 +785,7 @@ func (p *parser) parseType(parent *types.Package) types.Type {
|
|||||||
func (p *parser) parseImportDecl() {
|
func (p *parser) parseImportDecl() {
|
||||||
p.expectKeyword("import")
|
p.expectKeyword("import")
|
||||||
name := p.parsePackageName()
|
name := p.parsePackageName()
|
||||||
p.getPkg(p.parsePackageId(), name)
|
p.getPkg(p.parsePackageID(), name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// int_lit = [ "+" | "-" ] { "0" ... "9" } .
|
// int_lit = [ "+" | "-" ] { "0" ... "9" } .
|
||||||
|
645
vendor/golang.org/x/tools/go/packages/golist.go
generated
vendored
645
vendor/golang.org/x/tools/go/packages/golist.go
generated
vendored
@ -6,17 +6,17 @@ package packages
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/types"
|
"go/types"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -24,8 +24,6 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"golang.org/x/tools/go/internal/packagesdriver"
|
"golang.org/x/tools/go/internal/packagesdriver"
|
||||||
"golang.org/x/tools/internal/gopathwalk"
|
|
||||||
"golang.org/x/tools/internal/semver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// debug controls verbose logging.
|
// debug controls verbose logging.
|
||||||
@ -44,16 +42,21 @@ type responseDeduper struct {
|
|||||||
dr *driverResponse
|
dr *driverResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// init fills in r with a driverResponse.
|
func newDeduper() *responseDeduper {
|
||||||
func (r *responseDeduper) init(dr *driverResponse) {
|
return &responseDeduper{
|
||||||
r.dr = dr
|
dr: &driverResponse{},
|
||||||
r.seenRoots = map[string]bool{}
|
seenRoots: map[string]bool{},
|
||||||
r.seenPackages = map[string]*Package{}
|
seenPackages: map[string]*Package{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// addAll fills in r with a driverResponse.
|
||||||
|
func (r *responseDeduper) addAll(dr *driverResponse) {
|
||||||
for _, pkg := range dr.Packages {
|
for _, pkg := range dr.Packages {
|
||||||
r.seenPackages[pkg.ID] = pkg
|
r.addPackage(pkg)
|
||||||
}
|
}
|
||||||
for _, root := range dr.Roots {
|
for _, root := range dr.Roots {
|
||||||
r.seenRoots[root] = true
|
r.addRoot(root)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,25 +76,47 @@ func (r *responseDeduper) addRoot(id string) {
|
|||||||
r.dr.Roots = append(r.dr.Roots, id)
|
r.dr.Roots = append(r.dr.Roots, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// goInfo contains global information from the go tool.
|
type golistState struct {
|
||||||
type goInfo struct {
|
cfg *Config
|
||||||
rootDirs map[string]string
|
ctx context.Context
|
||||||
env goEnv
|
|
||||||
|
envOnce sync.Once
|
||||||
|
goEnvError error
|
||||||
|
goEnv map[string]string
|
||||||
|
|
||||||
|
rootsOnce sync.Once
|
||||||
|
rootDirsError error
|
||||||
|
rootDirs map[string]string
|
||||||
|
|
||||||
|
// vendorDirs caches the (non)existence of vendor directories.
|
||||||
|
vendorDirs map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type goEnv struct {
|
// getEnv returns Go environment variables. Only specific variables are
|
||||||
modulesOn bool
|
// populated -- computing all of them is slow.
|
||||||
|
func (state *golistState) getEnv() (map[string]string, error) {
|
||||||
|
state.envOnce.Do(func() {
|
||||||
|
var b *bytes.Buffer
|
||||||
|
b, state.goEnvError = state.invokeGo("env", "-json", "GOMOD", "GOPATH")
|
||||||
|
if state.goEnvError != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
state.goEnv = make(map[string]string)
|
||||||
|
decoder := json.NewDecoder(b)
|
||||||
|
if state.goEnvError = decoder.Decode(&state.goEnv); state.goEnvError != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return state.goEnv, state.goEnvError
|
||||||
}
|
}
|
||||||
|
|
||||||
func determineEnv(cfg *Config) goEnv {
|
// mustGetEnv is a convenience function that can be used if getEnv has already succeeded.
|
||||||
buf, err := invokeGo(cfg, "env", "GOMOD")
|
func (state *golistState) mustGetEnv() map[string]string {
|
||||||
|
env, err := state.getEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return goEnv{}
|
panic(fmt.Sprintf("mustGetEnv: %v", err))
|
||||||
}
|
}
|
||||||
gomod := bytes.TrimSpace(buf.Bytes())
|
|
||||||
|
|
||||||
env := goEnv{}
|
|
||||||
env.modulesOn = len(gomod) > 0
|
|
||||||
return env
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,47 +124,38 @@ func determineEnv(cfg *Config) goEnv {
|
|||||||
// 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, error) {
|
||||||
var sizes types.Sizes
|
// Make sure that any asynchronous go commands are killed when we return.
|
||||||
|
parentCtx := cfg.Context
|
||||||
|
if parentCtx == nil {
|
||||||
|
parentCtx = context.Background()
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithCancel(parentCtx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
response := newDeduper()
|
||||||
|
|
||||||
|
// Fill in response.Sizes asynchronously if necessary.
|
||||||
var sizeserr error
|
var sizeserr error
|
||||||
var sizeswg sync.WaitGroup
|
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)
|
sizeswg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
sizes, sizeserr = getSizes(cfg)
|
var sizes types.Sizes
|
||||||
|
sizes, sizeserr = packagesdriver.GetSizesGolist(ctx, cfg.BuildFlags, cfg.Env, cfg.Dir, usesExportData(cfg))
|
||||||
|
// types.SizesFor always returns nil or a *types.StdSizes.
|
||||||
|
response.dr.Sizes, _ = sizes.(*types.StdSizes)
|
||||||
sizeswg.Done()
|
sizeswg.Done()
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
defer sizeswg.Wait()
|
|
||||||
|
|
||||||
// start fetching rootDirs
|
state := &golistState{
|
||||||
var info goInfo
|
cfg: cfg,
|
||||||
var rootDirsReady, envReady = make(chan struct{}), make(chan struct{})
|
ctx: ctx,
|
||||||
go func() {
|
vendorDirs: map[string]bool{},
|
||||||
info.rootDirs = determineRootDirs(cfg)
|
|
||||||
close(rootDirsReady)
|
|
||||||
}()
|
|
||||||
go func() {
|
|
||||||
info.env = determineEnv(cfg)
|
|
||||||
close(envReady)
|
|
||||||
}()
|
|
||||||
getGoInfo := func() *goInfo {
|
|
||||||
<-rootDirsReady
|
|
||||||
<-envReady
|
|
||||||
return &info
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that we don't leak goroutines: Load is synchronous, so callers will
|
|
||||||
// not expect it to access the fields of cfg after the call returns.
|
|
||||||
defer getGoInfo()
|
|
||||||
|
|
||||||
// always pass getGoInfo to golistDriver
|
|
||||||
golistDriver := func(cfg *Config, patterns ...string) (*driverResponse, error) {
|
|
||||||
return golistDriver(cfg, getGoInfo, patterns...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine files requested in contains patterns
|
// Determine files requested in contains patterns
|
||||||
var containFiles []string
|
var containFiles []string
|
||||||
var packagesNamed []string
|
|
||||||
restPatterns := make([]string, 0, len(patterns))
|
restPatterns := make([]string, 0, len(patterns))
|
||||||
// Extract file= and other [querytype]= patterns. Report an error if querytype
|
// Extract file= and other [querytype]= patterns. Report an error if querytype
|
||||||
// doesn't exist.
|
// doesn't exist.
|
||||||
@ -155,8 +171,6 @@ extractQueries:
|
|||||||
containFiles = append(containFiles, value)
|
containFiles = append(containFiles, value)
|
||||||
case "pattern":
|
case "pattern":
|
||||||
restPatterns = append(restPatterns, value)
|
restPatterns = append(restPatterns, value)
|
||||||
case "iamashamedtousethedisabledqueryname":
|
|
||||||
packagesNamed = append(packagesNamed, value)
|
|
||||||
case "": // not a reserved query
|
case "": // not a reserved query
|
||||||
restPatterns = append(restPatterns, pattern)
|
restPatterns = append(restPatterns, pattern)
|
||||||
default:
|
default:
|
||||||
@ -172,52 +186,34 @@ extractQueries:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response := &responseDeduper{}
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// See if we have any patterns to pass through to go list. Zero initial
|
// See if we have any patterns to pass through to go list. Zero initial
|
||||||
// patterns also requires a go list call, since it's the equivalent of
|
// patterns also requires a go list call, since it's the equivalent of
|
||||||
// ".".
|
// ".".
|
||||||
if len(restPatterns) > 0 || len(patterns) == 0 {
|
if len(restPatterns) > 0 || len(patterns) == 0 {
|
||||||
dr, err := golistDriver(cfg, restPatterns...)
|
dr, err := state.createDriverResponse(restPatterns...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
response.init(dr)
|
response.addAll(dr)
|
||||||
} else {
|
|
||||||
response.init(&driverResponse{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sizeswg.Wait()
|
|
||||||
if sizeserr != nil {
|
|
||||||
return nil, sizeserr
|
|
||||||
}
|
|
||||||
// types.SizesFor always returns nil or a *types.StdSizes
|
|
||||||
response.dr.Sizes, _ = sizes.(*types.StdSizes)
|
|
||||||
|
|
||||||
var containsCandidates []string
|
|
||||||
|
|
||||||
if len(containFiles) != 0 {
|
if len(containFiles) != 0 {
|
||||||
if err := runContainsQueries(cfg, golistDriver, response, containFiles, getGoInfo); err != nil {
|
if err := state.runContainsQueries(response, containFiles); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(packagesNamed) != 0 {
|
modifiedPkgs, needPkgs, err := state.processGolistOverlay(response)
|
||||||
if err := runNamedQueries(cfg, golistDriver, response, packagesNamed); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
modifiedPkgs, needPkgs, err := processGolistOverlay(cfg, response, getGoInfo)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var containsCandidates []string
|
||||||
if len(containFiles) > 0 {
|
if len(containFiles) > 0 {
|
||||||
containsCandidates = append(containsCandidates, modifiedPkgs...)
|
containsCandidates = append(containsCandidates, modifiedPkgs...)
|
||||||
containsCandidates = append(containsCandidates, needPkgs...)
|
containsCandidates = append(containsCandidates, needPkgs...)
|
||||||
}
|
}
|
||||||
if err := addNeededOverlayPackages(cfg, golistDriver, response, needPkgs, getGoInfo); err != nil {
|
if err := state.addNeededOverlayPackages(response, needPkgs); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Check candidate packages for containFiles.
|
// Check candidate packages for containFiles.
|
||||||
@ -246,28 +242,32 @@ extractQueries:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sizeswg.Wait()
|
||||||
|
if sizeserr != nil {
|
||||||
|
return nil, sizeserr
|
||||||
|
}
|
||||||
return response.dr, nil
|
return response.dr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addNeededOverlayPackages(cfg *Config, driver driver, response *responseDeduper, pkgs []string, getGoInfo func() *goInfo) error {
|
func (state *golistState) addNeededOverlayPackages(response *responseDeduper, pkgs []string) error {
|
||||||
if len(pkgs) == 0 {
|
if len(pkgs) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
dr, err := driver(cfg, pkgs...)
|
dr, err := state.createDriverResponse(pkgs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, pkg := range dr.Packages {
|
for _, pkg := range dr.Packages {
|
||||||
response.addPackage(pkg)
|
response.addPackage(pkg)
|
||||||
}
|
}
|
||||||
_, needPkgs, err := processGolistOverlay(cfg, response, getGoInfo)
|
_, needPkgs, err := state.processGolistOverlay(response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return addNeededOverlayPackages(cfg, driver, response, needPkgs, getGoInfo)
|
return state.addNeededOverlayPackages(response, needPkgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runContainsQueries(cfg *Config, driver driver, response *responseDeduper, queries []string, goInfo func() *goInfo) error {
|
func (state *golistState) runContainsQueries(response *responseDeduper, queries []string) error {
|
||||||
for _, query := range queries {
|
for _, query := range queries {
|
||||||
// TODO(matloob): Do only one query per directory.
|
// TODO(matloob): Do only one query per directory.
|
||||||
fdir := filepath.Dir(query)
|
fdir := filepath.Dir(query)
|
||||||
@ -277,44 +277,17 @@ func runContainsQueries(cfg *Config, driver driver, response *responseDeduper, q
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not determine absolute path of file= query path %q: %v", query, err)
|
return fmt.Errorf("could not determine absolute path of file= query path %q: %v", query, err)
|
||||||
}
|
}
|
||||||
dirResponse, err := driver(cfg, pattern)
|
dirResponse, err := state.createDriverResponse(pattern)
|
||||||
if err != nil || (len(dirResponse.Packages) == 1 && len(dirResponse.Packages[0].Errors) == 1) {
|
|
||||||
// There was an error loading the package. Try to load the file as an ad-hoc package.
|
// If there was an error loading the package, or the package is returned
|
||||||
// Usually the error will appear in a returned package, but may not if we're in modules mode
|
// with errors, try to load the file as an ad-hoc package.
|
||||||
// and the ad-hoc is located outside a module.
|
// Usually the error will appear in a returned package, but may not if we're
|
||||||
|
// in module mode and the ad-hoc is located outside a module.
|
||||||
|
if err != nil || len(dirResponse.Packages) == 1 && len(dirResponse.Packages[0].GoFiles) == 0 &&
|
||||||
|
len(dirResponse.Packages[0].Errors) == 1 {
|
||||||
var queryErr error
|
var queryErr error
|
||||||
dirResponse, queryErr = driver(cfg, query)
|
if dirResponse, queryErr = state.adhocPackage(pattern, query); queryErr != nil {
|
||||||
if queryErr != nil {
|
return err // return the original error
|
||||||
// Return the original error if the attempt to fall back failed.
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// If we get nothing back from `go list`, try to make this file into its own ad-hoc package.
|
|
||||||
if len(dirResponse.Packages) == 0 && queryErr == nil {
|
|
||||||
dirResponse.Packages = append(dirResponse.Packages, &Package{
|
|
||||||
ID: "command-line-arguments",
|
|
||||||
PkgPath: query,
|
|
||||||
GoFiles: []string{query},
|
|
||||||
CompiledGoFiles: []string{query},
|
|
||||||
Imports: make(map[string]*Package),
|
|
||||||
})
|
|
||||||
dirResponse.Roots = append(dirResponse.Roots, "command-line-arguments")
|
|
||||||
}
|
|
||||||
// Special case to handle issue #33482:
|
|
||||||
// If this is a file= query for ad-hoc packages where the file only exists on an overlay,
|
|
||||||
// and exists outside of a module, add the file in for the package.
|
|
||||||
if len(dirResponse.Packages) == 1 && (dirResponse.Packages[0].ID == "command-line-arguments" ||
|
|
||||||
filepath.ToSlash(dirResponse.Packages[0].PkgPath) == filepath.ToSlash(query)) {
|
|
||||||
if len(dirResponse.Packages[0].GoFiles) == 0 {
|
|
||||||
filename := filepath.Join(pattern, filepath.Base(query)) // avoid recomputing abspath
|
|
||||||
// TODO(matloob): check if the file is outside of a root dir?
|
|
||||||
for path := range cfg.Overlay {
|
|
||||||
if path == filename {
|
|
||||||
dirResponse.Packages[0].Errors = nil
|
|
||||||
dirResponse.Packages[0].GoFiles = []string{path}
|
|
||||||
dirResponse.Packages[0].CompiledGoFiles = []string{path}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isRoot := make(map[string]bool, len(dirResponse.Roots))
|
isRoot := make(map[string]bool, len(dirResponse.Roots))
|
||||||
@ -342,276 +315,47 @@ func runContainsQueries(cfg *Config, driver driver, response *responseDeduper, q
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// modCacheRegexp splits a path in a module cache into module, module version, and package.
|
// adhocPackage attempts to load or construct an ad-hoc package for a given
|
||||||
var modCacheRegexp = regexp.MustCompile(`(.*)@([^/\\]*)(.*)`)
|
// query, if the original call to the driver produced inadequate results.
|
||||||
|
func (state *golistState) adhocPackage(pattern, query string) (*driverResponse, error) {
|
||||||
func runNamedQueries(cfg *Config, driver driver, response *responseDeduper, queries []string) error {
|
response, err := state.createDriverResponse(query)
|
||||||
// calling `go env` isn't free; bail out if there's nothing to do.
|
|
||||||
if len(queries) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Determine which directories are relevant to scan.
|
|
||||||
roots, modRoot, err := roots(cfg)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// If we get nothing back from `go list`,
|
||||||
// Scan the selected directories. Simple matches, from GOPATH/GOROOT
|
// try to make this file into its own ad-hoc package.
|
||||||
// or the local module, can simply be "go list"ed. Matches from the
|
// TODO(rstambler): Should this check against the original response?
|
||||||
// module cache need special treatment.
|
if len(response.Packages) == 0 {
|
||||||
var matchesMu sync.Mutex
|
response.Packages = append(response.Packages, &Package{
|
||||||
var simpleMatches, modCacheMatches []string
|
ID: "command-line-arguments",
|
||||||
add := func(root gopathwalk.Root, dir string) {
|
PkgPath: query,
|
||||||
// Walk calls this concurrently; protect the result slices.
|
GoFiles: []string{query},
|
||||||
matchesMu.Lock()
|
CompiledGoFiles: []string{query},
|
||||||
defer matchesMu.Unlock()
|
Imports: make(map[string]*Package),
|
||||||
|
|
||||||
path := dir
|
|
||||||
if dir != root.Path {
|
|
||||||
path = dir[len(root.Path)+1:]
|
|
||||||
}
|
|
||||||
if pathMatchesQueries(path, queries) {
|
|
||||||
switch root.Type {
|
|
||||||
case gopathwalk.RootModuleCache:
|
|
||||||
modCacheMatches = append(modCacheMatches, path)
|
|
||||||
case gopathwalk.RootCurrentModule:
|
|
||||||
// We'd need to read go.mod to find the full
|
|
||||||
// import path. Relative's easier.
|
|
||||||
rel, err := filepath.Rel(cfg.Dir, dir)
|
|
||||||
if err != nil {
|
|
||||||
// This ought to be impossible, since
|
|
||||||
// we found dir in the current module.
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
simpleMatches = append(simpleMatches, "./"+rel)
|
|
||||||
case gopathwalk.RootGOPATH, gopathwalk.RootGOROOT:
|
|
||||||
simpleMatches = append(simpleMatches, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
startWalk := time.Now()
|
|
||||||
gopathwalk.Walk(roots, add, gopathwalk.Options{ModulesEnabled: modRoot != "", Debug: debug})
|
|
||||||
cfg.Logf("%v for walk", time.Since(startWalk))
|
|
||||||
|
|
||||||
// Weird special case: the top-level package in a module will be in
|
|
||||||
// whatever directory the user checked the repository out into. It's
|
|
||||||
// more reasonable for that to not match the package name. So, if there
|
|
||||||
// are any Go files in the mod root, query it just to be safe.
|
|
||||||
if modRoot != "" {
|
|
||||||
rel, err := filepath.Rel(cfg.Dir, modRoot)
|
|
||||||
if err != nil {
|
|
||||||
panic(err) // See above.
|
|
||||||
}
|
|
||||||
|
|
||||||
files, err := ioutil.ReadDir(modRoot)
|
|
||||||
if err != nil {
|
|
||||||
panic(err) // See above.
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, f := range files {
|
|
||||||
if strings.HasSuffix(f.Name(), ".go") {
|
|
||||||
simpleMatches = append(simpleMatches, rel)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addResponse := func(r *driverResponse) {
|
|
||||||
for _, pkg := range r.Packages {
|
|
||||||
response.addPackage(pkg)
|
|
||||||
for _, name := range queries {
|
|
||||||
if pkg.Name == name {
|
|
||||||
response.addRoot(pkg.ID)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(simpleMatches) != 0 {
|
|
||||||
resp, err := driver(cfg, simpleMatches...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
addResponse(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Module cache matches are tricky. We want to avoid downloading new
|
|
||||||
// versions of things, so we need to use the ones present in the cache.
|
|
||||||
// go list doesn't accept version specifiers, so we have to write out a
|
|
||||||
// temporary module, and do the list in that module.
|
|
||||||
if len(modCacheMatches) != 0 {
|
|
||||||
// Collect all the matches, deduplicating by major version
|
|
||||||
// and preferring the newest.
|
|
||||||
type modInfo struct {
|
|
||||||
mod string
|
|
||||||
major string
|
|
||||||
}
|
|
||||||
mods := make(map[modInfo]string)
|
|
||||||
var imports []string
|
|
||||||
for _, modPath := range modCacheMatches {
|
|
||||||
matches := modCacheRegexp.FindStringSubmatch(modPath)
|
|
||||||
mod, ver := filepath.ToSlash(matches[1]), matches[2]
|
|
||||||
importPath := filepath.ToSlash(filepath.Join(matches[1], matches[3]))
|
|
||||||
|
|
||||||
major := semver.Major(ver)
|
|
||||||
if prevVer, ok := mods[modInfo{mod, major}]; !ok || semver.Compare(ver, prevVer) > 0 {
|
|
||||||
mods[modInfo{mod, major}] = ver
|
|
||||||
}
|
|
||||||
|
|
||||||
imports = append(imports, importPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the temporary module.
|
|
||||||
var gomod bytes.Buffer
|
|
||||||
gomod.WriteString("module modquery\nrequire (\n")
|
|
||||||
for mod, version := range mods {
|
|
||||||
gomod.WriteString("\t" + mod.mod + " " + version + "\n")
|
|
||||||
}
|
|
||||||
gomod.WriteString(")\n")
|
|
||||||
|
|
||||||
tmpCfg := *cfg
|
|
||||||
|
|
||||||
// We're only trying to look at stuff in the module cache, so
|
|
||||||
// disable the network. This should speed things up, and has
|
|
||||||
// prevented errors in at least one case, #28518.
|
|
||||||
tmpCfg.Env = append([]string{"GOPROXY=off"}, cfg.Env...)
|
|
||||||
|
|
||||||
var err error
|
|
||||||
tmpCfg.Dir, err = ioutil.TempDir("", "gopackages-modquery")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(tmpCfg.Dir)
|
|
||||||
|
|
||||||
if err := ioutil.WriteFile(filepath.Join(tmpCfg.Dir, "go.mod"), gomod.Bytes(), 0777); err != nil {
|
|
||||||
return fmt.Errorf("writing go.mod for module cache query: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the query, using the import paths calculated from the matches above.
|
|
||||||
resp, err := driver(&tmpCfg, imports...)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("querying module cache matches: %v", err)
|
|
||||||
}
|
|
||||||
addResponse(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSizes(cfg *Config) (types.Sizes, error) {
|
|
||||||
return packagesdriver.GetSizesGolist(cfg.Context, cfg.BuildFlags, cfg.Env, cfg.Dir, usesExportData(cfg))
|
|
||||||
}
|
|
||||||
|
|
||||||
// roots selects the appropriate paths to walk based on the passed-in configuration,
|
|
||||||
// particularly the environment and the presence of a go.mod in cfg.Dir's parents.
|
|
||||||
func roots(cfg *Config) ([]gopathwalk.Root, string, error) {
|
|
||||||
stdout, err := invokeGo(cfg, "env", "GOROOT", "GOPATH", "GOMOD")
|
|
||||||
if err != nil {
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
fields := strings.Split(stdout.String(), "\n")
|
|
||||||
if len(fields) != 4 || len(fields[3]) != 0 {
|
|
||||||
return nil, "", fmt.Errorf("go env returned unexpected output: %q", stdout.String())
|
|
||||||
}
|
|
||||||
goroot, gopath, gomod := fields[0], filepath.SplitList(fields[1]), fields[2]
|
|
||||||
var modDir string
|
|
||||||
if gomod != "" {
|
|
||||||
modDir = filepath.Dir(gomod)
|
|
||||||
}
|
|
||||||
|
|
||||||
var roots []gopathwalk.Root
|
|
||||||
// Always add GOROOT.
|
|
||||||
roots = append(roots, gopathwalk.Root{
|
|
||||||
Path: filepath.Join(goroot, "/src"),
|
|
||||||
Type: gopathwalk.RootGOROOT,
|
|
||||||
})
|
|
||||||
// If modules are enabled, scan the module dir.
|
|
||||||
if modDir != "" {
|
|
||||||
roots = append(roots, gopathwalk.Root{
|
|
||||||
Path: modDir,
|
|
||||||
Type: gopathwalk.RootCurrentModule,
|
|
||||||
})
|
})
|
||||||
|
response.Roots = append(response.Roots, "command-line-arguments")
|
||||||
}
|
}
|
||||||
// Add either GOPATH/src or GOPATH/pkg/mod, depending on module mode.
|
// Handle special cases.
|
||||||
for _, p := range gopath {
|
if len(response.Packages) == 1 {
|
||||||
if modDir != "" {
|
// golang/go#33482: If this is a file= query for ad-hoc packages where
|
||||||
roots = append(roots, gopathwalk.Root{
|
// the file only exists on an overlay, and exists outside of a module,
|
||||||
Path: filepath.Join(p, "/pkg/mod"),
|
// add the file to the package and remove the errors.
|
||||||
Type: gopathwalk.RootModuleCache,
|
if response.Packages[0].ID == "command-line-arguments" ||
|
||||||
})
|
filepath.ToSlash(response.Packages[0].PkgPath) == filepath.ToSlash(query) {
|
||||||
} else {
|
if len(response.Packages[0].GoFiles) == 0 {
|
||||||
roots = append(roots, gopathwalk.Root{
|
filename := filepath.Join(pattern, filepath.Base(query)) // avoid recomputing abspath
|
||||||
Path: filepath.Join(p, "/src"),
|
// TODO(matloob): check if the file is outside of a root dir?
|
||||||
Type: gopathwalk.RootGOPATH,
|
for path := range state.cfg.Overlay {
|
||||||
})
|
if path == filename {
|
||||||
}
|
response.Packages[0].Errors = nil
|
||||||
}
|
response.Packages[0].GoFiles = []string{path}
|
||||||
|
response.Packages[0].CompiledGoFiles = []string{path}
|
||||||
return roots, modDir, nil
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// These functions were copied from goimports. See further documentation there.
|
|
||||||
|
|
||||||
// pathMatchesQueries is adapted from pkgIsCandidate.
|
|
||||||
// TODO: is it reasonable to do Contains here, rather than an exact match on a path component?
|
|
||||||
func pathMatchesQueries(path string, queries []string) bool {
|
|
||||||
lastTwo := lastTwoComponents(path)
|
|
||||||
for _, query := range queries {
|
|
||||||
if strings.Contains(lastTwo, query) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if hasHyphenOrUpperASCII(lastTwo) && !hasHyphenOrUpperASCII(query) {
|
|
||||||
lastTwo = lowerASCIIAndRemoveHyphen(lastTwo)
|
|
||||||
if strings.Contains(lastTwo, query) {
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return response, nil
|
||||||
}
|
|
||||||
|
|
||||||
// lastTwoComponents returns at most the last two path components
|
|
||||||
// of v, using either / or \ as the path separator.
|
|
||||||
func lastTwoComponents(v string) string {
|
|
||||||
nslash := 0
|
|
||||||
for i := len(v) - 1; i >= 0; i-- {
|
|
||||||
if v[i] == '/' || v[i] == '\\' {
|
|
||||||
nslash++
|
|
||||||
if nslash == 2 {
|
|
||||||
return v[i:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasHyphenOrUpperASCII(s string) bool {
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
b := s[i]
|
|
||||||
if b == '-' || ('A' <= b && b <= 'Z') {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func lowerASCIIAndRemoveHyphen(s string) (ret string) {
|
|
||||||
buf := make([]byte, 0, len(s))
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
b := s[i]
|
|
||||||
switch {
|
|
||||||
case b == '-':
|
|
||||||
continue
|
|
||||||
case 'A' <= b && b <= 'Z':
|
|
||||||
buf = append(buf, b+('a'-'A'))
|
|
||||||
default:
|
|
||||||
buf = append(buf, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return string(buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fields must match go list;
|
// Fields must match go list;
|
||||||
@ -656,10 +400,9 @@ func otherFiles(p *jsonPackage) [][]string {
|
|||||||
return [][]string{p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.FFiles, p.SFiles, p.SwigFiles, p.SwigCXXFiles, p.SysoFiles}
|
return [][]string{p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.FFiles, p.SFiles, p.SwigFiles, p.SwigCXXFiles, p.SysoFiles}
|
||||||
}
|
}
|
||||||
|
|
||||||
// golistDriver uses the "go list" command to expand the pattern
|
// createDriverResponse uses the "go list" command to expand the pattern
|
||||||
// words and return metadata for the specified packages. dir may be
|
// words and return a response for the specified packages.
|
||||||
// "" and env may be nil, as per os/exec.Command.
|
func (state *golistState) createDriverResponse(words ...string) (*driverResponse, error) {
|
||||||
func golistDriver(cfg *Config, rootsDirs func() *goInfo, 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)
|
||||||
@ -673,11 +416,13 @@ func golistDriver(cfg *Config, rootsDirs func() *goInfo, words ...string) (*driv
|
|||||||
|
|
||||||
// Run "go list" for complete
|
// Run "go list" for complete
|
||||||
// information on the specified packages.
|
// information on the specified packages.
|
||||||
buf, err := invokeGo(cfg, "list", golistargs(cfg, words)...)
|
buf, err := state.invokeGo("list", golistargs(state.cfg, words)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
seen := make(map[string]*jsonPackage)
|
seen := make(map[string]*jsonPackage)
|
||||||
|
pkgs := make(map[string]*Package)
|
||||||
|
additionalErrors := make(map[string][]Error)
|
||||||
// Decode the JSON and convert it to Package form.
|
// Decode the JSON and convert it to Package form.
|
||||||
var response driverResponse
|
var response driverResponse
|
||||||
for dec := json.NewDecoder(buf); dec.More(); {
|
for dec := json.NewDecoder(buf); dec.More(); {
|
||||||
@ -708,18 +453,72 @@ func golistDriver(cfg *Config, rootsDirs func() *goInfo, words ...string) (*driv
|
|||||||
// contained in a known module or GOPATH entry. This will allow the package to be
|
// contained in a known module or GOPATH entry. This will allow the package to be
|
||||||
// properly "reclaimed" when overlays are processed.
|
// properly "reclaimed" when overlays are processed.
|
||||||
if filepath.IsAbs(p.ImportPath) && p.Error != nil {
|
if filepath.IsAbs(p.ImportPath) && p.Error != nil {
|
||||||
pkgPath, ok := getPkgPath(cfg, p.ImportPath, rootsDirs)
|
pkgPath, ok, err := state.getPkgPath(p.ImportPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if ok {
|
if ok {
|
||||||
p.ImportPath = pkgPath
|
p.ImportPath = pkgPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if old, found := seen[p.ImportPath]; found {
|
if old, found := seen[p.ImportPath]; found {
|
||||||
if !reflect.DeepEqual(p, old) {
|
// If one version of the package has an error, and the other doesn't, assume
|
||||||
return nil, fmt.Errorf("internal error: go list gives conflicting information for package %v", p.ImportPath)
|
// that this is a case where go list is reporting a fake dependency variant
|
||||||
|
// of the imported package: When a package tries to invalidly import another
|
||||||
|
// package, go list emits a variant of the imported package (with the same
|
||||||
|
// import path, but with an error on it, and the package will have a
|
||||||
|
// DepError set on it). An example of when this can happen is for imports of
|
||||||
|
// main packages: main packages can not be imported, but they may be
|
||||||
|
// separately matched and listed by another pattern.
|
||||||
|
// See golang.org/issue/36188 for more details.
|
||||||
|
|
||||||
|
// The plan is that eventually, hopefully in Go 1.15, the error will be
|
||||||
|
// reported on the importing package rather than the duplicate "fake"
|
||||||
|
// version of the imported package. Once all supported versions of Go
|
||||||
|
// have the new behavior this logic can be deleted.
|
||||||
|
// TODO(matloob): delete the workaround logic once all supported versions of
|
||||||
|
// Go return the errors on the proper package.
|
||||||
|
|
||||||
|
// There should be exactly one version of a package that doesn't have an
|
||||||
|
// error.
|
||||||
|
if old.Error == nil && p.Error == nil {
|
||||||
|
if !reflect.DeepEqual(p, old) {
|
||||||
|
return nil, fmt.Errorf("internal error: go list gives conflicting information for package %v", p.ImportPath)
|
||||||
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
// skip the duplicate
|
|
||||||
continue
|
// Determine if this package's error needs to be bubbled up.
|
||||||
|
// This is a hack, and we expect for go list to eventually set the error
|
||||||
|
// on the package.
|
||||||
|
if old.Error != nil {
|
||||||
|
var errkind string
|
||||||
|
if strings.Contains(old.Error.Err, "not an importable package") {
|
||||||
|
errkind = "not an importable package"
|
||||||
|
} else if strings.Contains(old.Error.Err, "use of internal package") && strings.Contains(old.Error.Err, "not allowed") {
|
||||||
|
errkind = "use of internal package not allowed"
|
||||||
|
}
|
||||||
|
if errkind != "" {
|
||||||
|
if len(old.Error.ImportStack) < 2 {
|
||||||
|
return nil, fmt.Errorf(`internal error: go list gave a %q error with an import stack with fewer than two elements`, errkind)
|
||||||
|
}
|
||||||
|
importingPkg := old.Error.ImportStack[len(old.Error.ImportStack)-2]
|
||||||
|
additionalErrors[importingPkg] = append(additionalErrors[importingPkg], Error{
|
||||||
|
Pos: old.Error.Pos,
|
||||||
|
Msg: old.Error.Err,
|
||||||
|
Kind: ListError,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that if there's a version of the package without an error,
|
||||||
|
// that's the one reported to the user.
|
||||||
|
if old.Error == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// This package will replace the old one at the end of the loop.
|
||||||
}
|
}
|
||||||
seen[p.ImportPath] = p
|
seen[p.ImportPath] = p
|
||||||
|
|
||||||
@ -729,6 +528,7 @@ func golistDriver(cfg *Config, rootsDirs func() *goInfo, words ...string) (*driv
|
|||||||
GoFiles: absJoin(p.Dir, p.GoFiles, p.CgoFiles),
|
GoFiles: absJoin(p.Dir, p.GoFiles, p.CgoFiles),
|
||||||
CompiledGoFiles: absJoin(p.Dir, p.CompiledGoFiles),
|
CompiledGoFiles: absJoin(p.Dir, p.CompiledGoFiles),
|
||||||
OtherFiles: absJoin(p.Dir, otherFiles(p)...),
|
OtherFiles: absJoin(p.Dir, otherFiles(p)...),
|
||||||
|
forTest: p.ForTest,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Work around https://golang.org/issue/28749:
|
// Work around https://golang.org/issue/28749:
|
||||||
@ -817,29 +617,37 @@ func golistDriver(cfg *Config, rootsDirs func() *goInfo, words ...string) (*driv
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pkgs[pkg.ID] = pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
for id, errs := range additionalErrors {
|
||||||
|
if p, ok := pkgs[id]; ok {
|
||||||
|
p.Errors = append(p.Errors, errs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, pkg := range pkgs {
|
||||||
response.Packages = append(response.Packages, pkg)
|
response.Packages = append(response.Packages, pkg)
|
||||||
}
|
}
|
||||||
|
sort.Slice(response.Packages, func(i, j int) bool { return response.Packages[i].ID < response.Packages[j].ID })
|
||||||
|
|
||||||
return &response, nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getPkgPath finds the package path of a directory if it's relative to a root directory.
|
// getPkgPath finds the package path of a directory if it's relative to a root directory.
|
||||||
func getPkgPath(cfg *Config, dir string, goInfo func() *goInfo) (string, bool) {
|
func (state *golistState) getPkgPath(dir string) (string, bool, error) {
|
||||||
absDir, err := filepath.Abs(dir)
|
absDir, err := filepath.Abs(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cfg.Logf("error getting absolute path of %s: %v", dir, err)
|
return "", false, err
|
||||||
return "", false
|
|
||||||
}
|
}
|
||||||
for rdir, rpath := range goInfo().rootDirs {
|
roots, err := state.determineRootDirs()
|
||||||
absRdir, err := filepath.Abs(rdir)
|
if err != nil {
|
||||||
if err != nil {
|
return "", false, err
|
||||||
cfg.Logf("error getting absolute path of %s: %v", rdir, err)
|
}
|
||||||
continue
|
|
||||||
}
|
for rdir, rpath := range roots {
|
||||||
// Make sure that the directory is in the module,
|
// Make sure that the directory is in the module,
|
||||||
// to avoid creating a path relative to another module.
|
// to avoid creating a path relative to another module.
|
||||||
if !strings.HasPrefix(absDir, absRdir) {
|
if !strings.HasPrefix(absDir, rdir) {
|
||||||
cfg.Logf("%s does not have prefix %s", absDir, absRdir)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// TODO(matloob): This doesn't properly handle symlinks.
|
// TODO(matloob): This doesn't properly handle symlinks.
|
||||||
@ -854,11 +662,11 @@ func getPkgPath(cfg *Config, dir string, goInfo func() *goInfo) (string, bool) {
|
|||||||
// Once the file is saved, gopls, or the next invocation of the tool will get the correct
|
// Once the file is saved, gopls, or the next invocation of the tool will get the correct
|
||||||
// result straight from golist.
|
// result straight from golist.
|
||||||
// TODO(matloob): Implement module tiebreaking?
|
// TODO(matloob): Implement module tiebreaking?
|
||||||
return path.Join(rpath, filepath.ToSlash(r)), true
|
return path.Join(rpath, filepath.ToSlash(r)), true, nil
|
||||||
}
|
}
|
||||||
return filepath.ToSlash(r), true
|
return filepath.ToSlash(r), true, nil
|
||||||
}
|
}
|
||||||
return "", false
|
return "", false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// absJoin absolutizes and flattens the lists of files.
|
// absJoin absolutizes and flattens the lists of files.
|
||||||
@ -878,7 +686,7 @@ func golistargs(cfg *Config, words []string) []string {
|
|||||||
const findFlags = NeedImports | NeedTypes | NeedSyntax | NeedTypesInfo
|
const findFlags = NeedImports | NeedTypes | NeedSyntax | NeedTypesInfo
|
||||||
fullargs := []string{
|
fullargs := []string{
|
||||||
"-e", "-json",
|
"-e", "-json",
|
||||||
fmt.Sprintf("-compiled=%t", cfg.Mode&(NeedCompiledGoFiles|NeedSyntax|NeedTypesInfo|NeedTypesSizes) != 0),
|
fmt.Sprintf("-compiled=%t", cfg.Mode&(NeedCompiledGoFiles|NeedSyntax|NeedTypes|NeedTypesInfo|NeedTypesSizes) != 0),
|
||||||
fmt.Sprintf("-test=%t", cfg.Tests),
|
fmt.Sprintf("-test=%t", cfg.Tests),
|
||||||
fmt.Sprintf("-export=%t", usesExportData(cfg)),
|
fmt.Sprintf("-export=%t", usesExportData(cfg)),
|
||||||
fmt.Sprintf("-deps=%t", cfg.Mode&NeedImports != 0),
|
fmt.Sprintf("-deps=%t", cfg.Mode&NeedImports != 0),
|
||||||
@ -893,13 +701,17 @@ func golistargs(cfg *Config, words []string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// invokeGo returns the stdout of a go command invocation.
|
// invokeGo returns the stdout of a go command invocation.
|
||||||
func invokeGo(cfg *Config, verb string, args ...string) (*bytes.Buffer, error) {
|
func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, error) {
|
||||||
|
cfg := state.cfg
|
||||||
|
|
||||||
stdout := new(bytes.Buffer)
|
stdout := new(bytes.Buffer)
|
||||||
stderr := new(bytes.Buffer)
|
stderr := new(bytes.Buffer)
|
||||||
goArgs := []string{verb}
|
goArgs := []string{verb}
|
||||||
goArgs = append(goArgs, cfg.BuildFlags...)
|
if verb != "env" {
|
||||||
|
goArgs = append(goArgs, cfg.BuildFlags...)
|
||||||
|
}
|
||||||
goArgs = append(goArgs, args...)
|
goArgs = append(goArgs, args...)
|
||||||
cmd := exec.CommandContext(cfg.Context, "go", goArgs...)
|
cmd := exec.CommandContext(state.ctx, "go", goArgs...)
|
||||||
// On darwin the cwd gets resolved to the real path, which breaks anything that
|
// On darwin the cwd gets resolved to the real path, which breaks anything that
|
||||||
// expects the working directory to keep the original path, including the
|
// expects the working directory to keep the original path, including the
|
||||||
// go command when dealing with modules.
|
// go command when dealing with modules.
|
||||||
@ -911,7 +723,7 @@ func invokeGo(cfg *Config, verb string, args ...string) (*bytes.Buffer, error) {
|
|||||||
cmd.Stdout = stdout
|
cmd.Stdout = stdout
|
||||||
cmd.Stderr = stderr
|
cmd.Stderr = stderr
|
||||||
defer func(start time.Time) {
|
defer func(start time.Time) {
|
||||||
cfg.Logf("%s for %v, stderr: <<%s>> stdout: <<%s>>\n", time.Since(start), cmdDebugStr(cmd, args...), stderr, stdout)
|
cfg.Logf("%s for %v, stderr: <<%s>> stdout: <<%s>>\n", time.Since(start), cmdDebugStr(cmd, goArgs...), stderr, stdout)
|
||||||
}(time.Now())
|
}(time.Now())
|
||||||
|
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
@ -951,7 +763,12 @@ func invokeGo(cfg *Config, verb string, args ...string) (*bytes.Buffer, error) {
|
|||||||
!strings.ContainsRune("!\"#$%&'()*,:;<=>?[\\]^`{|}\uFFFD", r)
|
!strings.ContainsRune("!\"#$%&'()*,:;<=>?[\\]^`{|}\uFFFD", r)
|
||||||
}
|
}
|
||||||
if len(stderr.String()) > 0 && strings.HasPrefix(stderr.String(), "# ") {
|
if len(stderr.String()) > 0 && strings.HasPrefix(stderr.String(), "# ") {
|
||||||
if strings.HasPrefix(strings.TrimLeftFunc(stderr.String()[len("# "):], isPkgPathRune), "\n") {
|
msg := stderr.String()[len("# "):]
|
||||||
|
if strings.HasPrefix(strings.TrimLeftFunc(msg, isPkgPathRune), "\n") {
|
||||||
|
return stdout, nil
|
||||||
|
}
|
||||||
|
// Treat pkg-config errors as a special case (golang.org/issue/36770).
|
||||||
|
if strings.HasPrefix(msg, "pkg-config") {
|
||||||
return stdout, nil
|
return stdout, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
201
vendor/golang.org/x/tools/go/packages/golist_overlay.go
generated
vendored
201
vendor/golang.org/x/tools/go/packages/golist_overlay.go
generated
vendored
@ -1,12 +1,13 @@
|
|||||||
package packages
|
package packages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -16,7 +17,7 @@ import (
|
|||||||
// sometimes incorrect.
|
// sometimes incorrect.
|
||||||
// TODO(matloob): Handle unsupported cases, including the following:
|
// TODO(matloob): Handle unsupported cases, including the following:
|
||||||
// - determining the correct package to add given a new import path
|
// - determining the correct package to add given a new import path
|
||||||
func processGolistOverlay(cfg *Config, response *responseDeduper, rootDirs func() *goInfo) (modifiedPkgs, needPkgs []string, err error) {
|
func (state *golistState) processGolistOverlay(response *responseDeduper) (modifiedPkgs, needPkgs []string, err error) {
|
||||||
havePkgs := make(map[string]string) // importPath -> non-test package ID
|
havePkgs := make(map[string]string) // importPath -> non-test package ID
|
||||||
needPkgsSet := make(map[string]bool)
|
needPkgsSet := make(map[string]bool)
|
||||||
modifiedPkgsSet := make(map[string]bool)
|
modifiedPkgsSet := make(map[string]bool)
|
||||||
@ -34,7 +35,23 @@ func processGolistOverlay(cfg *Config, response *responseDeduper, rootDirs func(
|
|||||||
// potentially modifying the transitive set of dependencies).
|
// potentially modifying the transitive set of dependencies).
|
||||||
var overlayAddsImports bool
|
var overlayAddsImports bool
|
||||||
|
|
||||||
for opath, contents := range cfg.Overlay {
|
// If both a package and its test package are created by the overlay, we
|
||||||
|
// need the real package first. Process all non-test files before test
|
||||||
|
// files, and make the whole process deterministic while we're at it.
|
||||||
|
var overlayFiles []string
|
||||||
|
for opath := range state.cfg.Overlay {
|
||||||
|
overlayFiles = append(overlayFiles, opath)
|
||||||
|
}
|
||||||
|
sort.Slice(overlayFiles, func(i, j int) bool {
|
||||||
|
iTest := strings.HasSuffix(overlayFiles[i], "_test.go")
|
||||||
|
jTest := strings.HasSuffix(overlayFiles[j], "_test.go")
|
||||||
|
if iTest != jTest {
|
||||||
|
return !iTest // non-tests are before tests.
|
||||||
|
}
|
||||||
|
return overlayFiles[i] < overlayFiles[j]
|
||||||
|
})
|
||||||
|
for _, opath := range overlayFiles {
|
||||||
|
contents := state.cfg.Overlay[opath]
|
||||||
base := filepath.Base(opath)
|
base := filepath.Base(opath)
|
||||||
dir := filepath.Dir(opath)
|
dir := filepath.Dir(opath)
|
||||||
var pkg *Package // if opath belongs to both a package and its test variant, this will be the test variant
|
var pkg *Package // if opath belongs to both a package and its test variant, this will be the test variant
|
||||||
@ -64,14 +81,8 @@ func processGolistOverlay(cfg *Config, response *responseDeduper, rootDirs func(
|
|||||||
testVariantOf = p
|
testVariantOf = p
|
||||||
continue nextPackage
|
continue nextPackage
|
||||||
}
|
}
|
||||||
|
// We must have already seen the package of which this is a test variant.
|
||||||
if pkg != nil && p != pkg && pkg.PkgPath == p.PkgPath {
|
if pkg != nil && p != pkg && pkg.PkgPath == p.PkgPath {
|
||||||
// If we've already seen the test variant,
|
|
||||||
// make sure to label which package it is a test variant of.
|
|
||||||
if hasTestFiles(pkg) {
|
|
||||||
testVariantOf = p
|
|
||||||
continue nextPackage
|
|
||||||
}
|
|
||||||
// If we have already seen the package of which this is a test variant.
|
|
||||||
if hasTestFiles(p) {
|
if hasTestFiles(p) {
|
||||||
testVariantOf = pkg
|
testVariantOf = pkg
|
||||||
}
|
}
|
||||||
@ -86,7 +97,10 @@ func processGolistOverlay(cfg *Config, response *responseDeduper, rootDirs func(
|
|||||||
if pkg == nil {
|
if pkg == nil {
|
||||||
// Try to find the module or gopath dir the file is contained in.
|
// Try to find the module or gopath dir the file is contained in.
|
||||||
// Then for modules, add the module opath to the beginning.
|
// Then for modules, add the module opath to the beginning.
|
||||||
pkgPath, ok := getPkgPath(cfg, dir, rootDirs)
|
pkgPath, ok, err := state.getPkgPath(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -114,6 +128,11 @@ func processGolistOverlay(cfg *Config, response *responseDeduper, rootDirs func(
|
|||||||
if isTestFile && !isXTest && testVariantOf != nil {
|
if isTestFile && !isXTest && testVariantOf != nil {
|
||||||
pkg.GoFiles = append(pkg.GoFiles, testVariantOf.GoFiles...)
|
pkg.GoFiles = append(pkg.GoFiles, testVariantOf.GoFiles...)
|
||||||
pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, testVariantOf.CompiledGoFiles...)
|
pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, testVariantOf.CompiledGoFiles...)
|
||||||
|
// Add the package under test and its imports to the test variant.
|
||||||
|
pkg.forTest = testVariantOf.PkgPath
|
||||||
|
for k, v := range testVariantOf.Imports {
|
||||||
|
pkg.Imports[k] = &Package{ID: v.ID}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,42 +149,45 @@ func processGolistOverlay(cfg *Config, response *responseDeduper, rootDirs func(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, imp := range imports {
|
for _, imp := range imports {
|
||||||
_, found := pkg.Imports[imp]
|
if _, found := pkg.Imports[imp]; found {
|
||||||
if !found {
|
continue
|
||||||
overlayAddsImports = true
|
}
|
||||||
// TODO(matloob): Handle cases when the following block isn't correct.
|
overlayAddsImports = true
|
||||||
// These include imports of vendored packages, etc.
|
id, ok := havePkgs[imp]
|
||||||
id, ok := havePkgs[imp]
|
if !ok {
|
||||||
if !ok {
|
var err error
|
||||||
id = imp
|
id, err = state.resolveImport(dir, imp)
|
||||||
}
|
if err != nil {
|
||||||
pkg.Imports[imp] = &Package{ID: id}
|
return nil, nil, err
|
||||||
// Add dependencies to the non-test variant version of this package as wel.
|
|
||||||
if testVariantOf != nil {
|
|
||||||
testVariantOf.Imports[imp] = &Package{ID: id}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pkg.Imports[imp] = &Package{ID: id}
|
||||||
|
// Add dependencies to the non-test variant version of this package as well.
|
||||||
|
if testVariantOf != nil {
|
||||||
|
testVariantOf.Imports[imp] = &Package{ID: id}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// toPkgPath tries to guess the package path given the id.
|
// toPkgPath guesses the package path given the id.
|
||||||
// This isn't always correct -- it's certainly wrong for
|
toPkgPath := func(sourceDir, id string) (string, error) {
|
||||||
// vendored packages' paths.
|
if i := strings.IndexByte(id, ' '); i >= 0 {
|
||||||
toPkgPath := func(id string) string {
|
return state.resolveImport(sourceDir, id[:i])
|
||||||
// TODO(matloob): Handle vendor paths.
|
|
||||||
i := strings.IndexByte(id, ' ')
|
|
||||||
if i >= 0 {
|
|
||||||
return id[:i]
|
|
||||||
}
|
}
|
||||||
return id
|
return state.resolveImport(sourceDir, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do another pass now that new packages have been created to determine the
|
// Now that new packages have been created, do another pass to determine
|
||||||
// set of missing packages.
|
// the new set of missing packages.
|
||||||
for _, pkg := range response.dr.Packages {
|
for _, pkg := range response.dr.Packages {
|
||||||
for _, imp := range pkg.Imports {
|
for _, imp := range pkg.Imports {
|
||||||
pkgPath := toPkgPath(imp.ID)
|
if len(pkg.GoFiles) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("cannot resolve imports for package %q with no Go files", pkg.PkgPath)
|
||||||
|
}
|
||||||
|
pkgPath, err := toPkgPath(filepath.Dir(pkg.GoFiles[0]), imp.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
if _, ok := havePkgs[pkgPath]; !ok {
|
if _, ok := havePkgs[pkgPath]; !ok {
|
||||||
needPkgsSet[pkgPath] = true
|
needPkgsSet[pkgPath] = true
|
||||||
}
|
}
|
||||||
@ -185,6 +207,52 @@ func processGolistOverlay(cfg *Config, response *responseDeduper, rootDirs func(
|
|||||||
return modifiedPkgs, needPkgs, err
|
return modifiedPkgs, needPkgs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolveImport finds the the ID of a package given its import path.
|
||||||
|
// In particular, it will find the right vendored copy when in GOPATH mode.
|
||||||
|
func (state *golistState) resolveImport(sourceDir, importPath string) (string, error) {
|
||||||
|
env, err := state.getEnv()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if env["GOMOD"] != "" {
|
||||||
|
return importPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
searchDir := sourceDir
|
||||||
|
for {
|
||||||
|
vendorDir := filepath.Join(searchDir, "vendor")
|
||||||
|
exists, ok := state.vendorDirs[vendorDir]
|
||||||
|
if !ok {
|
||||||
|
info, err := os.Stat(vendorDir)
|
||||||
|
exists = err == nil && info.IsDir()
|
||||||
|
state.vendorDirs[vendorDir] = exists
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
vendoredPath := filepath.Join(vendorDir, importPath)
|
||||||
|
if info, err := os.Stat(vendoredPath); err == nil && info.IsDir() {
|
||||||
|
// We should probably check for .go files here, but shame on anyone who fools us.
|
||||||
|
path, ok, err := state.getPkgPath(vendoredPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know we've hit the top of the filesystem when we Dir / and get /,
|
||||||
|
// or C:\ and get C:\, etc.
|
||||||
|
next := filepath.Dir(searchDir)
|
||||||
|
if next == searchDir {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
searchDir = next
|
||||||
|
}
|
||||||
|
return importPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
func hasTestFiles(p *Package) bool {
|
func hasTestFiles(p *Package) bool {
|
||||||
for _, f := range p.GoFiles {
|
for _, f := range p.GoFiles {
|
||||||
if strings.HasSuffix(f, "_test.go") {
|
if strings.HasSuffix(f, "_test.go") {
|
||||||
@ -194,44 +262,59 @@ func hasTestFiles(p *Package) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// determineRootDirs returns a mapping from directories code can be contained in to the
|
// determineRootDirs returns a mapping from absolute directories that could
|
||||||
// corresponding import path prefixes of those directories.
|
// contain code to their corresponding import path prefixes.
|
||||||
// Its result is used to try to determine the import path for a package containing
|
func (state *golistState) determineRootDirs() (map[string]string, error) {
|
||||||
// an overlay file.
|
env, err := state.getEnv()
|
||||||
func determineRootDirs(cfg *Config) map[string]string {
|
|
||||||
// Assume modules first:
|
|
||||||
out, err := invokeGo(cfg, "list", "-m", "-json", "all")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return determineRootDirsGOPATH(cfg)
|
return nil, err
|
||||||
|
}
|
||||||
|
if env["GOMOD"] != "" {
|
||||||
|
state.rootsOnce.Do(func() {
|
||||||
|
state.rootDirs, state.rootDirsError = state.determineRootDirsModules()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
state.rootsOnce.Do(func() {
|
||||||
|
state.rootDirs, state.rootDirsError = state.determineRootDirsGOPATH()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return state.rootDirs, state.rootDirsError
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *golistState) determineRootDirsModules() (map[string]string, error) {
|
||||||
|
out, err := state.invokeGo("list", "-m", "-json", "all")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
m := map[string]string{}
|
m := map[string]string{}
|
||||||
type jsonMod struct{ Path, Dir string }
|
type jsonMod struct{ Path, Dir string }
|
||||||
for dec := json.NewDecoder(out); dec.More(); {
|
for dec := json.NewDecoder(out); dec.More(); {
|
||||||
mod := new(jsonMod)
|
mod := new(jsonMod)
|
||||||
if err := dec.Decode(mod); err != nil {
|
if err := dec.Decode(mod); err != nil {
|
||||||
return m // Give up and return an empty map. Package won't be found for overlay.
|
return nil, err
|
||||||
}
|
}
|
||||||
if mod.Dir != "" && mod.Path != "" {
|
if mod.Dir != "" && mod.Path != "" {
|
||||||
// This is a valid module; add it to the map.
|
// This is a valid module; add it to the map.
|
||||||
m[mod.Dir] = mod.Path
|
absDir, err := filepath.Abs(mod.Dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
m[absDir] = mod.Path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func determineRootDirsGOPATH(cfg *Config) map[string]string {
|
func (state *golistState) determineRootDirsGOPATH() (map[string]string, error) {
|
||||||
m := map[string]string{}
|
m := map[string]string{}
|
||||||
out, err := invokeGo(cfg, "env", "GOPATH")
|
for _, dir := range filepath.SplitList(state.mustGetEnv()["GOPATH"]) {
|
||||||
if err != nil {
|
absDir, err := filepath.Abs(dir)
|
||||||
// Could not determine root dir mapping. Everything is best-effort, so just return an empty map.
|
if err != nil {
|
||||||
// When we try to find the import path for a directory, there will be no root-dir match and
|
return nil, err
|
||||||
// we'll give up.
|
}
|
||||||
return m
|
m[filepath.Join(absDir, "src")] = ""
|
||||||
}
|
}
|
||||||
for _, p := range filepath.SplitList(string(bytes.TrimSpace(out.Bytes()))) {
|
return m, nil
|
||||||
m[filepath.Join(p, "src")] = ""
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractImports(filename string, contents []byte) ([]string, error) {
|
func extractImports(filename string, contents []byte) ([]string, error) {
|
||||||
|
34
vendor/golang.org/x/tools/go/packages/packages.go
generated
vendored
34
vendor/golang.org/x/tools/go/packages/packages.go
generated
vendored
@ -23,6 +23,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"golang.org/x/tools/go/gcexportdata"
|
"golang.org/x/tools/go/gcexportdata"
|
||||||
|
"golang.org/x/tools/internal/packagesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A LoadMode controls the amount of detail to return when loading.
|
// A LoadMode controls the amount of detail to return when loading.
|
||||||
@ -34,6 +35,9 @@ import (
|
|||||||
// Load may return more information than requested.
|
// Load may return more information than requested.
|
||||||
type LoadMode int
|
type LoadMode int
|
||||||
|
|
||||||
|
// TODO(matloob): When a V2 of go/packages is released, rename NeedExportsFile to
|
||||||
|
// NeedExportFile to make it consistent with the Package field it's adding.
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// NeedName adds Name and PkgPath.
|
// NeedName adds Name and PkgPath.
|
||||||
NeedName LoadMode = 1 << iota
|
NeedName LoadMode = 1 << iota
|
||||||
@ -51,7 +55,7 @@ const (
|
|||||||
// NeedDeps adds the fields requested by the LoadMode in the packages in Imports.
|
// NeedDeps adds the fields requested by the LoadMode in the packages in Imports.
|
||||||
NeedDeps
|
NeedDeps
|
||||||
|
|
||||||
// NeedExportsFile adds ExportsFile.
|
// NeedExportsFile adds ExportFile.
|
||||||
NeedExportsFile
|
NeedExportsFile
|
||||||
|
|
||||||
// NeedTypes adds Types, Fset, and IllTyped.
|
// NeedTypes adds Types, Fset, and IllTyped.
|
||||||
@ -292,6 +296,15 @@ type Package struct {
|
|||||||
|
|
||||||
// TypesSizes provides the effective size function for types in TypesInfo.
|
// TypesSizes provides the effective size function for types in TypesInfo.
|
||||||
TypesSizes types.Sizes
|
TypesSizes types.Sizes
|
||||||
|
|
||||||
|
// forTest is the package under test, if any.
|
||||||
|
forTest string
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
packagesinternal.GetForTest = func(p interface{}) string {
|
||||||
|
return p.(*Package).forTest
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// An Error describes a problem with a package's metadata, syntax, or types.
|
// An Error describes a problem with a package's metadata, syntax, or types.
|
||||||
@ -500,12 +513,23 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
|
|||||||
if i, found := rootMap[pkg.ID]; found {
|
if i, found := rootMap[pkg.ID]; found {
|
||||||
rootIndex = i
|
rootIndex = i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Overlays can invalidate export data.
|
||||||
|
// TODO(matloob): make this check fine-grained based on dependencies on overlaid files
|
||||||
|
exportDataInvalid := len(ld.Overlay) > 0 || pkg.ExportFile == "" && pkg.PkgPath != "unsafe"
|
||||||
|
// This package needs type information if the caller requested types and the package is
|
||||||
|
// either a root, or it's a non-root and the user requested dependencies ...
|
||||||
|
needtypes := (ld.Mode&NeedTypes|NeedTypesInfo != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0))
|
||||||
|
// This package needs source if the call requested source (or types info, which implies source)
|
||||||
|
// and the package is either a root, or itas a non- root and the user requested dependencies...
|
||||||
|
needsrc := ((ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) ||
|
||||||
|
// ... or if we need types and the exportData is invalid. We fall back to (incompletely)
|
||||||
|
// typechecking packages from source if they fail to compile.
|
||||||
|
(ld.Mode&NeedTypes|NeedTypesInfo != 0 && exportDataInvalid)) && pkg.PkgPath != "unsafe"
|
||||||
lpkg := &loaderPackage{
|
lpkg := &loaderPackage{
|
||||||
Package: pkg,
|
Package: pkg,
|
||||||
needtypes: (ld.Mode&(NeedTypes|NeedTypesInfo) != 0 && ld.Mode&NeedDeps != 0 && rootIndex < 0) || rootIndex >= 0,
|
needtypes: needtypes,
|
||||||
needsrc: (ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && ld.Mode&NeedDeps != 0 && rootIndex < 0) || rootIndex >= 0 ||
|
needsrc: needsrc,
|
||||||
len(ld.Overlay) > 0 || // Overlays can invalidate export data. TODO(matloob): make this check fine-grained based on dependencies on overlaid files
|
|
||||||
pkg.ExportFile == "" && pkg.PkgPath != "unsafe",
|
|
||||||
}
|
}
|
||||||
ld.pkgs[lpkg.ID] = lpkg
|
ld.pkgs[lpkg.ID] = lpkg
|
||||||
if rootIndex >= 0 {
|
if rootIndex >= 0 {
|
||||||
|
196
vendor/golang.org/x/tools/internal/fastwalk/fastwalk.go
generated
vendored
196
vendor/golang.org/x/tools/internal/fastwalk/fastwalk.go
generated
vendored
@ -1,196 +0,0 @@
|
|||||||
// Copyright 2016 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 fastwalk provides a faster version of filepath.Walk for file system
|
|
||||||
// scanning tools.
|
|
||||||
package fastwalk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TraverseLink is used as a return value from WalkFuncs to indicate that the
|
|
||||||
// symlink named in the call may be traversed.
|
|
||||||
var TraverseLink = errors.New("fastwalk: traverse symlink, assuming target is a directory")
|
|
||||||
|
|
||||||
// SkipFiles is a used as a return value from WalkFuncs to indicate that the
|
|
||||||
// callback should not be called for any other files in the current directory.
|
|
||||||
// Child directories will still be traversed.
|
|
||||||
var SkipFiles = errors.New("fastwalk: skip remaining files in directory")
|
|
||||||
|
|
||||||
// Walk is a faster implementation of filepath.Walk.
|
|
||||||
//
|
|
||||||
// filepath.Walk's design necessarily calls os.Lstat on each file,
|
|
||||||
// even if the caller needs less info.
|
|
||||||
// Many tools need only the type of each file.
|
|
||||||
// On some platforms, this information is provided directly by the readdir
|
|
||||||
// system call, avoiding the need to stat each file individually.
|
|
||||||
// fastwalk_unix.go contains a fork of the syscall routines.
|
|
||||||
//
|
|
||||||
// See golang.org/issue/16399
|
|
||||||
//
|
|
||||||
// Walk walks the file tree rooted at root, calling walkFn for
|
|
||||||
// each file or directory in the tree, including root.
|
|
||||||
//
|
|
||||||
// If fastWalk returns filepath.SkipDir, the directory is skipped.
|
|
||||||
//
|
|
||||||
// Unlike filepath.Walk:
|
|
||||||
// * file stat calls must be done by the user.
|
|
||||||
// The only provided metadata is the file type, which does not include
|
|
||||||
// any permission bits.
|
|
||||||
// * multiple goroutines stat the filesystem concurrently. The provided
|
|
||||||
// walkFn must be safe for concurrent use.
|
|
||||||
// * fastWalk can follow symlinks if walkFn returns the TraverseLink
|
|
||||||
// sentinel error. It is the walkFn's responsibility to prevent
|
|
||||||
// fastWalk from going into symlink cycles.
|
|
||||||
func Walk(root string, walkFn func(path string, typ os.FileMode) error) error {
|
|
||||||
// TODO(bradfitz): make numWorkers configurable? We used a
|
|
||||||
// minimum of 4 to give the kernel more info about multiple
|
|
||||||
// things we want, in hopes its I/O scheduling can take
|
|
||||||
// advantage of that. Hopefully most are in cache. Maybe 4 is
|
|
||||||
// even too low of a minimum. Profile more.
|
|
||||||
numWorkers := 4
|
|
||||||
if n := runtime.NumCPU(); n > numWorkers {
|
|
||||||
numWorkers = n
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure to wait for all workers to finish, otherwise
|
|
||||||
// walkFn could still be called after returning. This Wait call
|
|
||||||
// runs after close(e.donec) below.
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
defer wg.Wait()
|
|
||||||
|
|
||||||
w := &walker{
|
|
||||||
fn: walkFn,
|
|
||||||
enqueuec: make(chan walkItem, numWorkers), // buffered for performance
|
|
||||||
workc: make(chan walkItem, numWorkers), // buffered for performance
|
|
||||||
donec: make(chan struct{}),
|
|
||||||
|
|
||||||
// buffered for correctness & not leaking goroutines:
|
|
||||||
resc: make(chan error, numWorkers),
|
|
||||||
}
|
|
||||||
defer close(w.donec)
|
|
||||||
|
|
||||||
for i := 0; i < numWorkers; i++ {
|
|
||||||
wg.Add(1)
|
|
||||||
go w.doWork(&wg)
|
|
||||||
}
|
|
||||||
todo := []walkItem{{dir: root}}
|
|
||||||
out := 0
|
|
||||||
for {
|
|
||||||
workc := w.workc
|
|
||||||
var workItem walkItem
|
|
||||||
if len(todo) == 0 {
|
|
||||||
workc = nil
|
|
||||||
} else {
|
|
||||||
workItem = todo[len(todo)-1]
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case workc <- workItem:
|
|
||||||
todo = todo[:len(todo)-1]
|
|
||||||
out++
|
|
||||||
case it := <-w.enqueuec:
|
|
||||||
todo = append(todo, it)
|
|
||||||
case err := <-w.resc:
|
|
||||||
out--
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if out == 0 && len(todo) == 0 {
|
|
||||||
// It's safe to quit here, as long as the buffered
|
|
||||||
// enqueue channel isn't also readable, which might
|
|
||||||
// happen if the worker sends both another unit of
|
|
||||||
// work and its result before the other select was
|
|
||||||
// scheduled and both w.resc and w.enqueuec were
|
|
||||||
// readable.
|
|
||||||
select {
|
|
||||||
case it := <-w.enqueuec:
|
|
||||||
todo = append(todo, it)
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// doWork reads directories as instructed (via workc) and runs the
|
|
||||||
// user's callback function.
|
|
||||||
func (w *walker) doWork(wg *sync.WaitGroup) {
|
|
||||||
defer wg.Done()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-w.donec:
|
|
||||||
return
|
|
||||||
case it := <-w.workc:
|
|
||||||
select {
|
|
||||||
case <-w.donec:
|
|
||||||
return
|
|
||||||
case w.resc <- w.walk(it.dir, !it.callbackDone):
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type walker struct {
|
|
||||||
fn func(path string, typ os.FileMode) error
|
|
||||||
|
|
||||||
donec chan struct{} // closed on fastWalk's return
|
|
||||||
workc chan walkItem // to workers
|
|
||||||
enqueuec chan walkItem // from workers
|
|
||||||
resc chan error // from workers
|
|
||||||
}
|
|
||||||
|
|
||||||
type walkItem struct {
|
|
||||||
dir string
|
|
||||||
callbackDone bool // callback already called; don't do it again
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) enqueue(it walkItem) {
|
|
||||||
select {
|
|
||||||
case w.enqueuec <- it:
|
|
||||||
case <-w.donec:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) onDirEnt(dirName, baseName string, typ os.FileMode) error {
|
|
||||||
joined := dirName + string(os.PathSeparator) + baseName
|
|
||||||
if typ == os.ModeDir {
|
|
||||||
w.enqueue(walkItem{dir: joined})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := w.fn(joined, typ)
|
|
||||||
if typ == os.ModeSymlink {
|
|
||||||
if err == TraverseLink {
|
|
||||||
// Set callbackDone so we don't call it twice for both the
|
|
||||||
// symlink-as-symlink and the symlink-as-directory later:
|
|
||||||
w.enqueue(walkItem{dir: joined, callbackDone: true})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err == filepath.SkipDir {
|
|
||||||
// Permit SkipDir on symlinks too.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) walk(root string, runUserCallback bool) error {
|
|
||||||
if runUserCallback {
|
|
||||||
err := w.fn(root, os.ModeDir)
|
|
||||||
if err == filepath.SkipDir {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return readDir(root, w.onDirEnt)
|
|
||||||
}
|
|
13
vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_fileno.go
generated
vendored
13
vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_fileno.go
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
// Copyright 2016 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.
|
|
||||||
|
|
||||||
// +build freebsd openbsd netbsd
|
|
||||||
|
|
||||||
package fastwalk
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
func direntInode(dirent *syscall.Dirent) uint64 {
|
|
||||||
return uint64(dirent.Fileno)
|
|
||||||
}
|
|
14
vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_ino.go
generated
vendored
14
vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_ino.go
generated
vendored
@ -1,14 +0,0 @@
|
|||||||
// Copyright 2016 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.
|
|
||||||
|
|
||||||
// +build linux darwin
|
|
||||||
// +build !appengine
|
|
||||||
|
|
||||||
package fastwalk
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
func direntInode(dirent *syscall.Dirent) uint64 {
|
|
||||||
return uint64(dirent.Ino)
|
|
||||||
}
|
|
13
vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_namlen_bsd.go
generated
vendored
13
vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_namlen_bsd.go
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
// Copyright 2018 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.
|
|
||||||
|
|
||||||
// +build darwin freebsd openbsd netbsd
|
|
||||||
|
|
||||||
package fastwalk
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
func direntNamlen(dirent *syscall.Dirent) uint64 {
|
|
||||||
return uint64(dirent.Namlen)
|
|
||||||
}
|
|
29
vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_namlen_linux.go
generated
vendored
29
vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_namlen_linux.go
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
// Copyright 2018 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.
|
|
||||||
|
|
||||||
// +build linux
|
|
||||||
// +build !appengine
|
|
||||||
|
|
||||||
package fastwalk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func direntNamlen(dirent *syscall.Dirent) uint64 {
|
|
||||||
const fixedHdr = uint16(unsafe.Offsetof(syscall.Dirent{}.Name))
|
|
||||||
nameBuf := (*[unsafe.Sizeof(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
|
|
||||||
const nameBufLen = uint16(len(nameBuf))
|
|
||||||
limit := dirent.Reclen - fixedHdr
|
|
||||||
if limit > nameBufLen {
|
|
||||||
limit = nameBufLen
|
|
||||||
}
|
|
||||||
nameLen := bytes.IndexByte(nameBuf[:limit], 0)
|
|
||||||
if nameLen < 0 {
|
|
||||||
panic("failed to find terminating 0 byte in dirent")
|
|
||||||
}
|
|
||||||
return uint64(nameLen)
|
|
||||||
}
|
|
37
vendor/golang.org/x/tools/internal/fastwalk/fastwalk_portable.go
generated
vendored
37
vendor/golang.org/x/tools/internal/fastwalk/fastwalk_portable.go
generated
vendored
@ -1,37 +0,0 @@
|
|||||||
// Copyright 2016 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.
|
|
||||||
|
|
||||||
// +build appengine !linux,!darwin,!freebsd,!openbsd,!netbsd
|
|
||||||
|
|
||||||
package fastwalk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// readDir calls fn for each directory entry in dirName.
|
|
||||||
// It does not descend into directories or follow symlinks.
|
|
||||||
// If fn returns a non-nil error, readDir returns with that error
|
|
||||||
// immediately.
|
|
||||||
func readDir(dirName string, fn func(dirName, entName string, typ os.FileMode) error) error {
|
|
||||||
fis, err := ioutil.ReadDir(dirName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
skipFiles := false
|
|
||||||
for _, fi := range fis {
|
|
||||||
if fi.Mode().IsRegular() && skipFiles {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := fn(dirName, fi.Name(), fi.Mode()&os.ModeType); err != nil {
|
|
||||||
if err == SkipFiles {
|
|
||||||
skipFiles = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
127
vendor/golang.org/x/tools/internal/fastwalk/fastwalk_unix.go
generated
vendored
127
vendor/golang.org/x/tools/internal/fastwalk/fastwalk_unix.go
generated
vendored
@ -1,127 +0,0 @@
|
|||||||
// Copyright 2016 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.
|
|
||||||
|
|
||||||
// +build linux darwin freebsd openbsd netbsd
|
|
||||||
// +build !appengine
|
|
||||||
|
|
||||||
package fastwalk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
const blockSize = 8 << 10
|
|
||||||
|
|
||||||
// unknownFileMode is a sentinel (and bogus) os.FileMode
|
|
||||||
// value used to represent a syscall.DT_UNKNOWN Dirent.Type.
|
|
||||||
const unknownFileMode os.FileMode = os.ModeNamedPipe | os.ModeSocket | os.ModeDevice
|
|
||||||
|
|
||||||
func readDir(dirName string, fn func(dirName, entName string, typ os.FileMode) error) error {
|
|
||||||
fd, err := syscall.Open(dirName, 0, 0)
|
|
||||||
if err != nil {
|
|
||||||
return &os.PathError{Op: "open", Path: dirName, Err: err}
|
|
||||||
}
|
|
||||||
defer syscall.Close(fd)
|
|
||||||
|
|
||||||
// The buffer must be at least a block long.
|
|
||||||
buf := make([]byte, blockSize) // stack-allocated; doesn't escape
|
|
||||||
bufp := 0 // starting read position in buf
|
|
||||||
nbuf := 0 // end valid data in buf
|
|
||||||
skipFiles := false
|
|
||||||
for {
|
|
||||||
if bufp >= nbuf {
|
|
||||||
bufp = 0
|
|
||||||
nbuf, err = syscall.ReadDirent(fd, buf)
|
|
||||||
if err != nil {
|
|
||||||
return os.NewSyscallError("readdirent", err)
|
|
||||||
}
|
|
||||||
if nbuf <= 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
consumed, name, typ := parseDirEnt(buf[bufp:nbuf])
|
|
||||||
bufp += consumed
|
|
||||||
if name == "" || name == "." || name == ".." {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Fallback for filesystems (like old XFS) that don't
|
|
||||||
// support Dirent.Type and have DT_UNKNOWN (0) there
|
|
||||||
// instead.
|
|
||||||
if typ == unknownFileMode {
|
|
||||||
fi, err := os.Lstat(dirName + "/" + name)
|
|
||||||
if err != nil {
|
|
||||||
// It got deleted in the meantime.
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
typ = fi.Mode() & os.ModeType
|
|
||||||
}
|
|
||||||
if skipFiles && typ.IsRegular() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := fn(dirName, name, typ); err != nil {
|
|
||||||
if err == SkipFiles {
|
|
||||||
skipFiles = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseDirEnt(buf []byte) (consumed int, name string, typ os.FileMode) {
|
|
||||||
// golang.org/issue/15653
|
|
||||||
dirent := (*syscall.Dirent)(unsafe.Pointer(&buf[0]))
|
|
||||||
if v := unsafe.Offsetof(dirent.Reclen) + unsafe.Sizeof(dirent.Reclen); uintptr(len(buf)) < v {
|
|
||||||
panic(fmt.Sprintf("buf size of %d smaller than dirent header size %d", len(buf), v))
|
|
||||||
}
|
|
||||||
if len(buf) < int(dirent.Reclen) {
|
|
||||||
panic(fmt.Sprintf("buf size %d < record length %d", len(buf), dirent.Reclen))
|
|
||||||
}
|
|
||||||
consumed = int(dirent.Reclen)
|
|
||||||
if direntInode(dirent) == 0 { // File absent in directory.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch dirent.Type {
|
|
||||||
case syscall.DT_REG:
|
|
||||||
typ = 0
|
|
||||||
case syscall.DT_DIR:
|
|
||||||
typ = os.ModeDir
|
|
||||||
case syscall.DT_LNK:
|
|
||||||
typ = os.ModeSymlink
|
|
||||||
case syscall.DT_BLK:
|
|
||||||
typ = os.ModeDevice
|
|
||||||
case syscall.DT_FIFO:
|
|
||||||
typ = os.ModeNamedPipe
|
|
||||||
case syscall.DT_SOCK:
|
|
||||||
typ = os.ModeSocket
|
|
||||||
case syscall.DT_UNKNOWN:
|
|
||||||
typ = unknownFileMode
|
|
||||||
default:
|
|
||||||
// Skip weird things.
|
|
||||||
// It's probably a DT_WHT (http://lwn.net/Articles/325369/)
|
|
||||||
// or something. Revisit if/when this package is moved outside
|
|
||||||
// of goimports. goimports only cares about regular files,
|
|
||||||
// symlinks, and directories.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
nameBuf := (*[unsafe.Sizeof(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
|
|
||||||
nameLen := direntNamlen(dirent)
|
|
||||||
|
|
||||||
// Special cases for common things:
|
|
||||||
if nameLen == 1 && nameBuf[0] == '.' {
|
|
||||||
name = "."
|
|
||||||
} else if nameLen == 2 && nameBuf[0] == '.' && nameBuf[1] == '.' {
|
|
||||||
name = ".."
|
|
||||||
} else {
|
|
||||||
name = string(nameBuf[:nameLen])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
273
vendor/golang.org/x/tools/internal/gopathwalk/walk.go
generated
vendored
273
vendor/golang.org/x/tools/internal/gopathwalk/walk.go
generated
vendored
@ -1,273 +0,0 @@
|
|||||||
// Copyright 2018 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 gopathwalk is like filepath.Walk but specialized for finding Go
|
|
||||||
// packages, particularly in $GOPATH and $GOROOT.
|
|
||||||
package gopathwalk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/build"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/tools/internal/fastwalk"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Options controls the behavior of a Walk call.
|
|
||||||
type Options struct {
|
|
||||||
Debug bool // Enable debug logging
|
|
||||||
ModulesEnabled bool // Search module caches. Also disables legacy goimports ignore rules.
|
|
||||||
}
|
|
||||||
|
|
||||||
// RootType indicates the type of a Root.
|
|
||||||
type RootType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
RootUnknown RootType = iota
|
|
||||||
RootGOROOT
|
|
||||||
RootGOPATH
|
|
||||||
RootCurrentModule
|
|
||||||
RootModuleCache
|
|
||||||
RootOther
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Root is a starting point for a Walk.
|
|
||||||
type Root struct {
|
|
||||||
Path string
|
|
||||||
Type RootType
|
|
||||||
}
|
|
||||||
|
|
||||||
// SrcDirsRoots returns the roots from build.Default.SrcDirs(). Not modules-compatible.
|
|
||||||
func SrcDirsRoots(ctx *build.Context) []Root {
|
|
||||||
var roots []Root
|
|
||||||
roots = append(roots, Root{filepath.Join(ctx.GOROOT, "src"), RootGOROOT})
|
|
||||||
for _, p := range filepath.SplitList(ctx.GOPATH) {
|
|
||||||
roots = append(roots, Root{filepath.Join(p, "src"), RootGOPATH})
|
|
||||||
}
|
|
||||||
return roots
|
|
||||||
}
|
|
||||||
|
|
||||||
// Walk walks Go source directories ($GOROOT, $GOPATH, etc) to find packages.
|
|
||||||
// For each package found, add will be called (concurrently) with the absolute
|
|
||||||
// paths of the containing source directory and the package directory.
|
|
||||||
// add will be called concurrently.
|
|
||||||
func Walk(roots []Root, add func(root Root, dir string), opts Options) {
|
|
||||||
WalkSkip(roots, add, func(Root, string) bool { return false }, opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WalkSkip walks Go source directories ($GOROOT, $GOPATH, etc) to find packages.
|
|
||||||
// For each package found, add will be called (concurrently) with the absolute
|
|
||||||
// paths of the containing source directory and the package directory.
|
|
||||||
// For each directory that will be scanned, skip will be called (concurrently)
|
|
||||||
// with the absolute paths of the containing source directory and the directory.
|
|
||||||
// If skip returns false on a directory it will be processed.
|
|
||||||
// add will be called concurrently.
|
|
||||||
// skip will be called concurrently.
|
|
||||||
func WalkSkip(roots []Root, add func(root Root, dir string), skip func(root Root, dir string) bool, opts Options) {
|
|
||||||
for _, root := range roots {
|
|
||||||
walkDir(root, add, skip, opts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// walkDir creates a walker and starts fastwalk with this walker.
|
|
||||||
func walkDir(root Root, add func(Root, string), skip func(root Root, dir string) bool, opts Options) {
|
|
||||||
if _, err := os.Stat(root.Path); os.IsNotExist(err) {
|
|
||||||
if opts.Debug {
|
|
||||||
log.Printf("skipping nonexistent directory: %v", root.Path)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
start := time.Now()
|
|
||||||
if opts.Debug {
|
|
||||||
log.Printf("gopathwalk: scanning %s", root.Path)
|
|
||||||
}
|
|
||||||
w := &walker{
|
|
||||||
root: root,
|
|
||||||
add: add,
|
|
||||||
skip: skip,
|
|
||||||
opts: opts,
|
|
||||||
}
|
|
||||||
w.init()
|
|
||||||
if err := fastwalk.Walk(root.Path, w.walk); err != nil {
|
|
||||||
log.Printf("gopathwalk: scanning directory %v: %v", root.Path, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.Debug {
|
|
||||||
log.Printf("gopathwalk: scanned %s in %v", root.Path, time.Since(start))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// walker is the callback for fastwalk.Walk.
|
|
||||||
type walker struct {
|
|
||||||
root Root // The source directory to scan.
|
|
||||||
add func(Root, string) // The callback that will be invoked for every possible Go package dir.
|
|
||||||
skip func(Root, string) bool // The callback that will be invoked for every dir. dir is skipped if it returns true.
|
|
||||||
opts Options // Options passed to Walk by the user.
|
|
||||||
|
|
||||||
ignoredDirs []os.FileInfo // The ignored directories, loaded from .goimportsignore files.
|
|
||||||
}
|
|
||||||
|
|
||||||
// init initializes the walker based on its Options
|
|
||||||
func (w *walker) init() {
|
|
||||||
var ignoredPaths []string
|
|
||||||
if w.root.Type == RootModuleCache {
|
|
||||||
ignoredPaths = []string{"cache"}
|
|
||||||
}
|
|
||||||
if !w.opts.ModulesEnabled && w.root.Type == RootGOPATH {
|
|
||||||
ignoredPaths = w.getIgnoredDirs(w.root.Path)
|
|
||||||
ignoredPaths = append(ignoredPaths, "v", "mod")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, p := range ignoredPaths {
|
|
||||||
full := filepath.Join(w.root.Path, p)
|
|
||||||
if fi, err := os.Stat(full); err == nil {
|
|
||||||
w.ignoredDirs = append(w.ignoredDirs, fi)
|
|
||||||
if w.opts.Debug {
|
|
||||||
log.Printf("Directory added to ignore list: %s", full)
|
|
||||||
}
|
|
||||||
} else if w.opts.Debug {
|
|
||||||
log.Printf("Error statting ignored directory: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getIgnoredDirs reads an optional config file at <path>/.goimportsignore
|
|
||||||
// of relative directories to ignore when scanning for go files.
|
|
||||||
// The provided path is one of the $GOPATH entries with "src" appended.
|
|
||||||
func (w *walker) getIgnoredDirs(path string) []string {
|
|
||||||
file := filepath.Join(path, ".goimportsignore")
|
|
||||||
slurp, err := ioutil.ReadFile(file)
|
|
||||||
if w.opts.Debug {
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
} else {
|
|
||||||
log.Printf("Read %s", file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var ignoredDirs []string
|
|
||||||
bs := bufio.NewScanner(bytes.NewReader(slurp))
|
|
||||||
for bs.Scan() {
|
|
||||||
line := strings.TrimSpace(bs.Text())
|
|
||||||
if line == "" || strings.HasPrefix(line, "#") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ignoredDirs = append(ignoredDirs, line)
|
|
||||||
}
|
|
||||||
return ignoredDirs
|
|
||||||
}
|
|
||||||
|
|
||||||
// shouldSkipDir reports whether the file should be skipped or not.
|
|
||||||
func (w *walker) shouldSkipDir(fi os.FileInfo, dir string) bool {
|
|
||||||
for _, ignoredDir := range w.ignoredDirs {
|
|
||||||
if os.SameFile(fi, ignoredDir) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if w.skip != nil {
|
|
||||||
// Check with the user specified callback.
|
|
||||||
return w.skip(w.root, dir)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// walk walks through the given path.
|
|
||||||
func (w *walker) walk(path string, typ os.FileMode) error {
|
|
||||||
dir := filepath.Dir(path)
|
|
||||||
if typ.IsRegular() {
|
|
||||||
if dir == w.root.Path && (w.root.Type == RootGOROOT || w.root.Type == RootGOPATH) {
|
|
||||||
// Doesn't make sense to have regular files
|
|
||||||
// directly in your $GOPATH/src or $GOROOT/src.
|
|
||||||
return fastwalk.SkipFiles
|
|
||||||
}
|
|
||||||
if !strings.HasSuffix(path, ".go") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
w.add(w.root, dir)
|
|
||||||
return fastwalk.SkipFiles
|
|
||||||
}
|
|
||||||
if typ == os.ModeDir {
|
|
||||||
base := filepath.Base(path)
|
|
||||||
if base == "" || base[0] == '.' || base[0] == '_' ||
|
|
||||||
base == "testdata" ||
|
|
||||||
(w.root.Type == RootGOROOT && w.opts.ModulesEnabled && base == "vendor") ||
|
|
||||||
(!w.opts.ModulesEnabled && base == "node_modules") {
|
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
fi, err := os.Lstat(path)
|
|
||||||
if err == nil && w.shouldSkipDir(fi, path) {
|
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if typ == os.ModeSymlink {
|
|
||||||
base := filepath.Base(path)
|
|
||||||
if strings.HasPrefix(base, ".#") {
|
|
||||||
// Emacs noise.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
fi, err := os.Lstat(path)
|
|
||||||
if err != nil {
|
|
||||||
// Just ignore it.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if w.shouldTraverse(dir, fi) {
|
|
||||||
return fastwalk.TraverseLink
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// shouldTraverse reports whether the symlink fi, found in dir,
|
|
||||||
// should be followed. It makes sure symlinks were never visited
|
|
||||||
// before to avoid symlink loops.
|
|
||||||
func (w *walker) shouldTraverse(dir string, fi os.FileInfo) bool {
|
|
||||||
path := filepath.Join(dir, fi.Name())
|
|
||||||
target, err := filepath.EvalSymlinks(path)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
ts, err := os.Stat(target)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if !ts.IsDir() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if w.shouldSkipDir(ts, dir) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Check for symlink loops by statting each directory component
|
|
||||||
// and seeing if any are the same file as ts.
|
|
||||||
for {
|
|
||||||
parent := filepath.Dir(path)
|
|
||||||
if parent == path {
|
|
||||||
// Made it to the root without seeing a cycle.
|
|
||||||
// Use this symlink.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
parentInfo, err := os.Stat(parent)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if os.SameFile(ts, parentInfo) {
|
|
||||||
// Cycle. Don't traverse.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
path = parent
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
4
vendor/golang.org/x/tools/internal/packagesinternal/packages.go
generated
vendored
Normal file
4
vendor/golang.org/x/tools/internal/packagesinternal/packages.go
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// Package packagesinternal exposes internal-only fields from go/packages.
|
||||||
|
package packagesinternal
|
||||||
|
|
||||||
|
var GetForTest = func(p interface{}) string { return "" }
|
388
vendor/golang.org/x/tools/internal/semver/semver.go
generated
vendored
388
vendor/golang.org/x/tools/internal/semver/semver.go
generated
vendored
@ -1,388 +0,0 @@
|
|||||||
// Copyright 2018 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 semver implements comparison of semantic version strings.
|
|
||||||
// In this package, semantic version strings must begin with a leading "v",
|
|
||||||
// as in "v1.0.0".
|
|
||||||
//
|
|
||||||
// The general form of a semantic version string accepted by this package is
|
|
||||||
//
|
|
||||||
// vMAJOR[.MINOR[.PATCH[-PRERELEASE][+BUILD]]]
|
|
||||||
//
|
|
||||||
// where square brackets indicate optional parts of the syntax;
|
|
||||||
// MAJOR, MINOR, and PATCH are decimal integers without extra leading zeros;
|
|
||||||
// PRERELEASE and BUILD are each a series of non-empty dot-separated identifiers
|
|
||||||
// using only alphanumeric characters and hyphens; and
|
|
||||||
// all-numeric PRERELEASE identifiers must not have leading zeros.
|
|
||||||
//
|
|
||||||
// This package follows Semantic Versioning 2.0.0 (see semver.org)
|
|
||||||
// with two exceptions. First, it requires the "v" prefix. Second, it recognizes
|
|
||||||
// vMAJOR and vMAJOR.MINOR (with no prerelease or build suffixes)
|
|
||||||
// as shorthands for vMAJOR.0.0 and vMAJOR.MINOR.0.
|
|
||||||
package semver
|
|
||||||
|
|
||||||
// parsed returns the parsed form of a semantic version string.
|
|
||||||
type parsed struct {
|
|
||||||
major string
|
|
||||||
minor string
|
|
||||||
patch string
|
|
||||||
short string
|
|
||||||
prerelease string
|
|
||||||
build string
|
|
||||||
err string
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValid reports whether v is a valid semantic version string.
|
|
||||||
func IsValid(v string) bool {
|
|
||||||
_, ok := parse(v)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Canonical returns the canonical formatting of the semantic version v.
|
|
||||||
// It fills in any missing .MINOR or .PATCH and discards build metadata.
|
|
||||||
// Two semantic versions compare equal only if their canonical formattings
|
|
||||||
// are identical strings.
|
|
||||||
// The canonical invalid semantic version is the empty string.
|
|
||||||
func Canonical(v string) string {
|
|
||||||
p, ok := parse(v)
|
|
||||||
if !ok {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if p.build != "" {
|
|
||||||
return v[:len(v)-len(p.build)]
|
|
||||||
}
|
|
||||||
if p.short != "" {
|
|
||||||
return v + p.short
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Major returns the major version prefix of the semantic version v.
|
|
||||||
// For example, Major("v2.1.0") == "v2".
|
|
||||||
// If v is an invalid semantic version string, Major returns the empty string.
|
|
||||||
func Major(v string) string {
|
|
||||||
pv, ok := parse(v)
|
|
||||||
if !ok {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return v[:1+len(pv.major)]
|
|
||||||
}
|
|
||||||
|
|
||||||
// MajorMinor returns the major.minor version prefix of the semantic version v.
|
|
||||||
// For example, MajorMinor("v2.1.0") == "v2.1".
|
|
||||||
// If v is an invalid semantic version string, MajorMinor returns the empty string.
|
|
||||||
func MajorMinor(v string) string {
|
|
||||||
pv, ok := parse(v)
|
|
||||||
if !ok {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
i := 1 + len(pv.major)
|
|
||||||
if j := i + 1 + len(pv.minor); j <= len(v) && v[i] == '.' && v[i+1:j] == pv.minor {
|
|
||||||
return v[:j]
|
|
||||||
}
|
|
||||||
return v[:i] + "." + pv.minor
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prerelease returns the prerelease suffix of the semantic version v.
|
|
||||||
// For example, Prerelease("v2.1.0-pre+meta") == "-pre".
|
|
||||||
// If v is an invalid semantic version string, Prerelease returns the empty string.
|
|
||||||
func Prerelease(v string) string {
|
|
||||||
pv, ok := parse(v)
|
|
||||||
if !ok {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return pv.prerelease
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build returns the build suffix of the semantic version v.
|
|
||||||
// For example, Build("v2.1.0+meta") == "+meta".
|
|
||||||
// If v is an invalid semantic version string, Build returns the empty string.
|
|
||||||
func Build(v string) string {
|
|
||||||
pv, ok := parse(v)
|
|
||||||
if !ok {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return pv.build
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare returns an integer comparing two versions according to
|
|
||||||
// according to semantic version precedence.
|
|
||||||
// The result will be 0 if v == w, -1 if v < w, or +1 if v > w.
|
|
||||||
//
|
|
||||||
// An invalid semantic version string is considered less than a valid one.
|
|
||||||
// All invalid semantic version strings compare equal to each other.
|
|
||||||
func Compare(v, w string) int {
|
|
||||||
pv, ok1 := parse(v)
|
|
||||||
pw, ok2 := parse(w)
|
|
||||||
if !ok1 && !ok2 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if !ok1 {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if !ok2 {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
if c := compareInt(pv.major, pw.major); c != 0 {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
if c := compareInt(pv.minor, pw.minor); c != 0 {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
if c := compareInt(pv.patch, pw.patch); c != 0 {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
return comparePrerelease(pv.prerelease, pw.prerelease)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max canonicalizes its arguments and then returns the version string
|
|
||||||
// that compares greater.
|
|
||||||
func Max(v, w string) string {
|
|
||||||
v = Canonical(v)
|
|
||||||
w = Canonical(w)
|
|
||||||
if Compare(v, w) > 0 {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
return w
|
|
||||||
}
|
|
||||||
|
|
||||||
func parse(v string) (p parsed, ok bool) {
|
|
||||||
if v == "" || v[0] != 'v' {
|
|
||||||
p.err = "missing v prefix"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.major, v, ok = parseInt(v[1:])
|
|
||||||
if !ok {
|
|
||||||
p.err = "bad major version"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v == "" {
|
|
||||||
p.minor = "0"
|
|
||||||
p.patch = "0"
|
|
||||||
p.short = ".0.0"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v[0] != '.' {
|
|
||||||
p.err = "bad minor prefix"
|
|
||||||
ok = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.minor, v, ok = parseInt(v[1:])
|
|
||||||
if !ok {
|
|
||||||
p.err = "bad minor version"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v == "" {
|
|
||||||
p.patch = "0"
|
|
||||||
p.short = ".0"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v[0] != '.' {
|
|
||||||
p.err = "bad patch prefix"
|
|
||||||
ok = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.patch, v, ok = parseInt(v[1:])
|
|
||||||
if !ok {
|
|
||||||
p.err = "bad patch version"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(v) > 0 && v[0] == '-' {
|
|
||||||
p.prerelease, v, ok = parsePrerelease(v)
|
|
||||||
if !ok {
|
|
||||||
p.err = "bad prerelease"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(v) > 0 && v[0] == '+' {
|
|
||||||
p.build, v, ok = parseBuild(v)
|
|
||||||
if !ok {
|
|
||||||
p.err = "bad build"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v != "" {
|
|
||||||
p.err = "junk on end"
|
|
||||||
ok = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ok = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseInt(v string) (t, rest string, ok bool) {
|
|
||||||
if v == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v[0] < '0' || '9' < v[0] {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
i := 1
|
|
||||||
for i < len(v) && '0' <= v[i] && v[i] <= '9' {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if v[0] == '0' && i != 1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return v[:i], v[i:], true
|
|
||||||
}
|
|
||||||
|
|
||||||
func parsePrerelease(v string) (t, rest string, ok bool) {
|
|
||||||
// "A pre-release version MAY be denoted by appending a hyphen and
|
|
||||||
// a series of dot separated identifiers immediately following the patch version.
|
|
||||||
// Identifiers MUST comprise only ASCII alphanumerics and hyphen [0-9A-Za-z-].
|
|
||||||
// Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes."
|
|
||||||
if v == "" || v[0] != '-' {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
i := 1
|
|
||||||
start := 1
|
|
||||||
for i < len(v) && v[i] != '+' {
|
|
||||||
if !isIdentChar(v[i]) && v[i] != '.' {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v[i] == '.' {
|
|
||||||
if start == i || isBadNum(v[start:i]) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
start = i + 1
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if start == i || isBadNum(v[start:i]) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return v[:i], v[i:], true
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseBuild(v string) (t, rest string, ok bool) {
|
|
||||||
if v == "" || v[0] != '+' {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
i := 1
|
|
||||||
start := 1
|
|
||||||
for i < len(v) {
|
|
||||||
if !isIdentChar(v[i]) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v[i] == '.' {
|
|
||||||
if start == i {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
start = i + 1
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if start == i {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return v[:i], v[i:], true
|
|
||||||
}
|
|
||||||
|
|
||||||
func isIdentChar(c byte) bool {
|
|
||||||
return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '-'
|
|
||||||
}
|
|
||||||
|
|
||||||
func isBadNum(v string) bool {
|
|
||||||
i := 0
|
|
||||||
for i < len(v) && '0' <= v[i] && v[i] <= '9' {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return i == len(v) && i > 1 && v[0] == '0'
|
|
||||||
}
|
|
||||||
|
|
||||||
func isNum(v string) bool {
|
|
||||||
i := 0
|
|
||||||
for i < len(v) && '0' <= v[i] && v[i] <= '9' {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return i == len(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func compareInt(x, y string) int {
|
|
||||||
if x == y {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if len(x) < len(y) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if len(x) > len(y) {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
if x < y {
|
|
||||||
return -1
|
|
||||||
} else {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func comparePrerelease(x, y string) int {
|
|
||||||
// "When major, minor, and patch are equal, a pre-release version has
|
|
||||||
// lower precedence than a normal version.
|
|
||||||
// Example: 1.0.0-alpha < 1.0.0.
|
|
||||||
// Precedence for two pre-release versions with the same major, minor,
|
|
||||||
// and patch version MUST be determined by comparing each dot separated
|
|
||||||
// identifier from left to right until a difference is found as follows:
|
|
||||||
// identifiers consisting of only digits are compared numerically and
|
|
||||||
// identifiers with letters or hyphens are compared lexically in ASCII
|
|
||||||
// sort order. Numeric identifiers always have lower precedence than
|
|
||||||
// non-numeric identifiers. A larger set of pre-release fields has a
|
|
||||||
// higher precedence than a smaller set, if all of the preceding
|
|
||||||
// identifiers are equal.
|
|
||||||
// Example: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta <
|
|
||||||
// 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0."
|
|
||||||
if x == y {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if x == "" {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
if y == "" {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
for x != "" && y != "" {
|
|
||||||
x = x[1:] // skip - or .
|
|
||||||
y = y[1:] // skip - or .
|
|
||||||
var dx, dy string
|
|
||||||
dx, x = nextIdent(x)
|
|
||||||
dy, y = nextIdent(y)
|
|
||||||
if dx != dy {
|
|
||||||
ix := isNum(dx)
|
|
||||||
iy := isNum(dy)
|
|
||||||
if ix != iy {
|
|
||||||
if ix {
|
|
||||||
return -1
|
|
||||||
} else {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ix {
|
|
||||||
if len(dx) < len(dy) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if len(dx) > len(dy) {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if dx < dy {
|
|
||||||
return -1
|
|
||||||
} else {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if x == "" {
|
|
||||||
return -1
|
|
||||||
} else {
|
|
||||||
return +1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func nextIdent(x string) (dx, rest string) {
|
|
||||||
i := 0
|
|
||||||
for i < len(x) && x[i] != '.' {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return x[:i], x[i:]
|
|
||||||
}
|
|
14
vendor/modules.txt
vendored
14
vendor/modules.txt
vendored
@ -9,7 +9,7 @@ github.com/PuerkitoBio/urlesc
|
|||||||
github.com/containerd/containerd/errdefs
|
github.com/containerd/containerd/errdefs
|
||||||
# github.com/davecgh/go-spew v1.1.1
|
# github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/davecgh/go-spew/spew
|
github.com/davecgh/go-spew/spew
|
||||||
# github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017
|
# github.com/docker/cli v0.0.0-20200303162255-7d407207c304
|
||||||
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
|
||||||
github.com/docker/cli/cli/config/credentials
|
github.com/docker/cli/cli/config/credentials
|
||||||
@ -84,7 +84,7 @@ github.com/google/go-cmp/cmp/internal/diff
|
|||||||
github.com/google/go-cmp/cmp/internal/flags
|
github.com/google/go-cmp/cmp/internal/flags
|
||||||
github.com/google/go-cmp/cmp/internal/function
|
github.com/google/go-cmp/cmp/internal/function
|
||||||
github.com/google/go-cmp/cmp/internal/value
|
github.com/google/go-cmp/cmp/internal/value
|
||||||
# github.com/google/go-containerregistry v0.0.0-20200212224832-c629a66d7231
|
# github.com/google/go-containerregistry v0.0.0-20200310013544-4fe717a9b4cb
|
||||||
github.com/google/go-containerregistry/pkg/authn
|
github.com/google/go-containerregistry/pkg/authn
|
||||||
github.com/google/go-containerregistry/pkg/internal/retry
|
github.com/google/go-containerregistry/pkg/internal/retry
|
||||||
github.com/google/go-containerregistry/pkg/internal/retry/wait
|
github.com/google/go-containerregistry/pkg/internal/retry/wait
|
||||||
@ -156,7 +156,7 @@ github.com/opencontainers/image-spec/specs-go/v1
|
|||||||
github.com/pelletier/go-toml
|
github.com/pelletier/go-toml
|
||||||
# github.com/peterbourgon/diskv v2.0.1+incompatible
|
# github.com/peterbourgon/diskv v2.0.1+incompatible
|
||||||
github.com/peterbourgon/diskv
|
github.com/peterbourgon/diskv
|
||||||
# github.com/pkg/errors v0.8.1
|
# github.com/pkg/errors v0.9.1
|
||||||
github.com/pkg/errors
|
github.com/pkg/errors
|
||||||
# github.com/sirupsen/logrus v1.4.2
|
# github.com/sirupsen/logrus v1.4.2
|
||||||
github.com/sirupsen/logrus
|
github.com/sirupsen/logrus
|
||||||
@ -187,7 +187,7 @@ golang.org/x/net/proxy
|
|||||||
# golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
# golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||||
golang.org/x/oauth2
|
golang.org/x/oauth2
|
||||||
golang.org/x/oauth2/internal
|
golang.org/x/oauth2/internal
|
||||||
# golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
# golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
|
||||||
golang.org/x/sync/errgroup
|
golang.org/x/sync/errgroup
|
||||||
golang.org/x/sync/semaphore
|
golang.org/x/sync/semaphore
|
||||||
# golang.org/x/sys v0.0.0-20191010194322-b09406accb47
|
# golang.org/x/sys v0.0.0-20191010194322-b09406accb47
|
||||||
@ -207,14 +207,12 @@ golang.org/x/text/unicode/norm
|
|||||||
golang.org/x/text/width
|
golang.org/x/text/width
|
||||||
# golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
|
# golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
|
||||||
golang.org/x/time/rate
|
golang.org/x/time/rate
|
||||||
# golang.org/x/tools v0.0.0-20200115192306-3ded1b734dda
|
# golang.org/x/tools v0.0.0-20200210192313-1ace956b0e17
|
||||||
golang.org/x/tools/go/gcexportdata
|
golang.org/x/tools/go/gcexportdata
|
||||||
golang.org/x/tools/go/internal/gcimporter
|
golang.org/x/tools/go/internal/gcimporter
|
||||||
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/internal/fastwalk
|
golang.org/x/tools/internal/packagesinternal
|
||||||
golang.org/x/tools/internal/gopathwalk
|
|
||||||
golang.org/x/tools/internal/semver
|
|
||||||
# google.golang.org/appengine v1.5.0
|
# google.golang.org/appengine v1.5.0
|
||||||
google.golang.org/appengine/internal
|
google.golang.org/appengine/internal
|
||||||
google.golang.org/appengine/internal/base
|
google.golang.org/appengine/internal/base
|
||||||
|
Loading…
Reference in New Issue
Block a user