New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/go: 'go get <pkg>@<tag>' should not fall back to 'latest' if <tag> does not provide <pkg> #29121

Open
kidlj opened this Issue Dec 6, 2018 · 9 comments

Comments

Projects
None yet
2 participants
@kidlj

kidlj commented Dec 6, 2018

What version of Go are you using (go version)?

go version go1.11.2 windows/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\kdlij\AppData\Local\go-build
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=D:/testmod/
set GOPROXY=
set GORACE=
set GOROOT=C:\Go
set GOTMPDIR=
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=D:\testclient\go.mod
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\kdlij\AppData\Local\Temp\go-build439133958=/tmp/go-build -gno-record-gcc-switches

What did you do?

Outside $GOPATH,

kidlj@collie MINGW64 /d/testclient
$ go mod init github.com/kidlj/test
go: creating new go.mod: module github.com/kidlj/test

kidlj@collie MINGW64 /d/testclient
$ cat go.mod
module github.com/kidlj/test

kidlj@collie MINGW64 /d/testclient
$ go get k8s.io/client-go@kubernetes-1.12.3
go: finding k8s.io/client-go kubernetes-1.12.3

kidlj@collie MINGW64 /d/testclient
$ cat go.mod
module github.com/kidlj/test

require k8s.io/client-go v2.0.0-alpha.0.0.20181126152608-d082d5923d3c+incompatible // indirect

What did you expect to see?

In go.mod:

require k8s.io/client-go v0.0.0-alpha.0.0.20181126152608-d082d5923d3c+incompatible // indirect

What did you see instead?

n go.mod:

require k8s.io/client-go v2.0.0-alpha.0.0.20181126152608-d082d5923d3c+incompatible // indirect

The question is:

How is the requested version(@kubernetes-1.12.3), also 20181126152608-d082d5923d3c related with v2.0.0-alpha?

The kubernetes/client-go releases page is here: https://github.com/kubernetes/client-go/tags

@kidlj

This comment has been minimized.

kidlj commented Dec 6, 2018

And, may I ask, why does go get download another newer version same package, or the latest version when wanted version requested?

$ go get k8s.io/apimachinery@kubernetes-1.12.3
go: finding k8s.io/apimachinery kubernetes-1.12.3
go: downloading k8s.io/apimachinery v0.0.0-20181126123746-eddba98df674
go: finding k8s.io/apimachinery latest
go: downloading k8s.io/apimachinery v0.0.0-20181204150028-eb8c8024849b
@bcmills

This comment has been minimized.

Member

bcmills commented Dec 6, 2018

kubernetes-1.12.3 is not a valid semantic version (per https://semver.org), so the go command treats it as just another tag, and uses the usual algorithm to try to find a valid semantically-versioned name for it.

That tag corresponds to commit d082d5923d3cc0bfbb066ee5fbdea3d0ca79acf8, which happens to
have v2.0.0-alpha.0-1296-gd082d592 as a (transitive) parent:

~/src/k8s.io/client-go$ git describe --tags d082d5923d3cc0bfbb066ee5fbdea3d0ca79acf8 --match 'v*'
v2.0.0-alpha.0-1296-gd082d592

So the go command synthesizes a pseudo-version for an arbitrary commit after v2.0.0-alpha.0. That is working as designed.

@bcmills

This comment has been minimized.

Member

bcmills commented Dec 6, 2018

In the case of apimachinery, there are no valid semantically-versioned tags in the history, so go picks a pseudo-version appropriate to a repository without any semantically-versioned tags — that is, v0.0.0.

~/src/k8s.io/apimachinery$ git rev-list -n 1 kubernetes-1.12.3
eddba98df674a16931d2d4ba75edc3a389bf633a

~/src/k8s.io/apimachinery$ git describe --match 'v*' --tags eddba98df674a16931d2d4ba75edc3a389bf633a
fatal: No names found, cannot describe anything.

When you run go get k8s.io/apimachinery@kubernetes-1.12.3, you are asking go get to resolve the package k8s.io/apimachinery, which does not exist at that revision. It appears to be trying latest instead, but that is a bug.

$ go mod init golang.org/issue/scratch
go: creating new go.mod: module golang.org/issue/scratch

$ go get -m k8s.io/apimachinery@kubernetes-1.12.3
go: finding k8s.io/apimachinery kubernetes-1.12.3

$ go list -m all
golang.org/issue/scratch
k8s.io/apimachinery v0.0.0-20181126123746-eddba98df674

$ go get k8s.io/apimachinery@kubernetes-1.12.3
go: finding k8s.io/apimachinery kubernetes-1.12.3
go: downloading k8s.io/apimachinery v0.0.0-20181126123746-eddba98df674
go: extracting k8s.io/apimachinery v0.0.0-20181126123746-eddba98df674
go: finding k8s.io/apimachinery latest
go: downloading k8s.io/apimachinery v0.0.0-20181204150028-eb8c8024849b
go: extracting k8s.io/apimachinery v0.0.0-20181204150028-eb8c8024849b

@bcmills bcmills changed the title from cmd/go: `go get <pkg>@<tag>` generates wrong version string in go.mod to cmd/go: 'go get <pkg>@<tag>' should not fall back to 'latest' if <tag> does not provide <pkg> Dec 6, 2018

@bcmills bcmills added this to the Go1.12 milestone Dec 6, 2018

@kidlj

This comment has been minimized.

kidlj commented Dec 7, 2018

kubernetes-1.12.3 is not a valid semantic version (per https://semver.org), so the go command treats it as just another tag, and uses the usual algorithm to try to find a valid semantically-versioned name for it.

That tag corresponds to commit d082d5923d3cc0bfbb066ee5fbdea3d0ca79acf8, which happens to
have v2.0.0-alpha.0-1296-gd082d592 as a (transitive) parent:

~/src/k8s.io/client-go$ git describe --tags d082d5923d3cc0bfbb066ee5fbdea3d0ca79acf8 --match 'v*'
v2.0.0-alpha.0-1296-gd082d592

So the go command synthesizes a pseudo-version for an arbitrary commit after v2.0.0-alpha.0. That is working as designed.

Thanks. And I found the official doc explaining this: https://golang.org/cmd/go/#hdr-Pseudo_versions

@bcmills

This comment has been minimized.

Member

bcmills commented Dec 12, 2018

See also #27102.

@bcmills bcmills self-assigned this Dec 12, 2018

@kidlj

This comment has been minimized.

kidlj commented Dec 13, 2018

When you run go get k8s.io/apimachinery@kubernetes-1.12.3, you are asking go get to resolve the package k8s.io/apimachinery, which does not exist at that revision. It appears to be trying latest instead, but that is a bug.

Hi, @bcmills , I still have a question:

Since go packages are not version-aware, I'm requesting k8s.io/apimachinery with a version mark(which is @kubernetes-1.12.3), so I guess I'm asking go get to resolve a module. Is this correct? Thanks.

@bcmills

This comment has been minimized.

Member

bcmills commented Dec 13, 2018

Since go packages are not version-aware, […] I guess I'm asking go get to resolve a module. Is this correct?

That's a really great question, because it is a bit funny to mix packages and module-versions like that. 🙂

As implemented, what it means today is “get me some module with tag kubernetes-1.12.3 that contains the package k8s.io/apimachinery”. We don't know exactly which module that is ahead of time, but in most cases it ends up being unambiguous: overlapping modules are rare, and overlapping versions of overlapping modules are even more rare.

@kidlj

This comment has been minimized.

kidlj commented Dec 13, 2018

@bcmills , through go help module-get doc and your explanation, I just found that whether in module-aware mode or not, go get should always get a package.

Usage: go get [-d] [-m] [-u] [-v] [-insecure] [build flags] [packages]

Earlier I thought that in module-aware mode or when a module version is specified get get should get a module.

The implementation is go get always gets a package, and by the way resolves a module to add to go.mod. Is this right?

So continuing the k8s.io/apimachinery example, If I want to add specific version k8s/apimachinery module to go.mod manually in advance and hope to import all packages under the the module to use this version, I should run get get with -m option, like go get -m k8s.io/apimachinery@kubernetes-1.12.3, right? Or there is another canonical way to achieve this?

@bcmills

This comment has been minimized.

Member

bcmills commented Dec 13, 2018

The implementation is go get always gets a package, and by the way resolves a module to add to go.mod. Is this right?

Close. The -m flag tells it to fetch a module rather than a package. (Without -m the paths are interpreted as package paths, and with -m they are interpreted as module paths.)

If I want to add specific version k8s/apimachinery module to go.mod manually in advance and hope to import all packages under the the module to use this version, I should run get get with -m option, like go get -m k8s.io/apimachinery@kubernetes-1.12.3, right?

Correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment