diff options
author | Bryan C. Mills <bcmills@google.com> | 2019-06-21 15:13:10 -0400 |
---|---|---|
committer | Bryan C. Mills <bcmills@google.com> | 2019-06-25 13:27:20 +0000 |
commit | 19690053606dd14dedcf028bb37df79e3e33c003 (patch) | |
tree | 416509349d9c604e0f08bb15f5c9dd052323eac6 | |
parent | e28f0d92991e60ac3174b2ebf224f37be22c8fad (diff) | |
download | go-19690053606dd14dedcf028bb37df79e3e33c003.tar.gz go-19690053606dd14dedcf028bb37df79e3e33c003.zip |
cmd/go/internal/modfetch: filter pseudo-versions from proxy /list endpoints
The /list files in the module cache include pseudo-versions, but the
documentation for (*modfetch).Repo.Versions explicitly states that
they are not included in the output of that method.
Fixes #32715
Change-Id: Ieba1500b91f52b5fa689e70e16dbe3ad40de20f7
Reviewed-on: https://go-review.googlesource.com/c/go/+/183402
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
5 files changed, 123 insertions, 11 deletions
diff --git a/src/cmd/go/internal/modfetch/proxy.go b/src/cmd/go/internal/modfetch/proxy.go index 6235ad3d6e..6049ccfd30 100644 --- a/src/cmd/go/internal/modfetch/proxy.go +++ b/src/cmd/go/internal/modfetch/proxy.go @@ -251,7 +251,7 @@ func (p *proxyRepo) Versions(prefix string) ([]string, error) { var list []string for _, line := range strings.Split(string(data), "\n") { f := strings.Fields(line) - if len(f) >= 1 && semver.IsValid(f[0]) && strings.HasPrefix(f[0], prefix) { + if len(f) >= 1 && semver.IsValid(f[0]) && strings.HasPrefix(f[0], prefix) && !IsPseudoVersion(f[0]) { list = append(list, f[0]) } } @@ -264,14 +264,36 @@ func (p *proxyRepo) latest() (*RevInfo, error) { if err != nil { return nil, p.versionError("", err) } - var best time.Time - var bestVersion string + + var ( + bestTime time.Time + bestTimeIsFromPseudo bool + bestVersion string + ) + for _, line := range strings.Split(string(data), "\n") { f := strings.Fields(line) - if len(f) >= 2 && semver.IsValid(f[0]) { - ft, err := time.Parse(time.RFC3339, f[1]) - if err == nil && best.Before(ft) { - best = ft + if len(f) >= 1 && semver.IsValid(f[0]) { + // If the proxy includes timestamps, prefer the timestamp it reports. + // Otherwise, derive the timestamp from the pseudo-version. + var ( + ft time.Time + ftIsFromPseudo = false + ) + if len(f) >= 2 { + ft, _ = time.Parse(time.RFC3339, f[1]) + } else if IsPseudoVersion(f[0]) { + ft, _ = PseudoVersionTime(f[0]) + ftIsFromPseudo = true + } else { + // Repo.Latest promises that this method is only called where there are + // no tagged versions. Ignore any tagged versions that were added in the + // meantime. + continue + } + if bestTime.Before(ft) { + bestTime = ft + bestTimeIsFromPseudo = ftIsFromPseudo bestVersion = f[0] } } @@ -279,13 +301,23 @@ func (p *proxyRepo) latest() (*RevInfo, error) { if bestVersion == "" { return nil, p.versionError("", codehost.ErrNoCommits) } - info := &RevInfo{ + + if bestTimeIsFromPseudo { + // We parsed bestTime from the pseudo-version, but that's in UTC and we're + // supposed to report the timestamp as reported by the VCS. + // Stat the selected version to canonicalize the timestamp. + // + // TODO(bcmills): Should we also stat other versions to ensure that we + // report the correct Name and Short for the revision? + return p.Stat(bestVersion) + } + + return &RevInfo{ Version: bestVersion, Name: bestVersion, Short: bestVersion, - Time: best, - } - return info, nil + Time: bestTime, + }, nil } func (p *proxyRepo) Stat(rev string) (*RevInfo, error) { diff --git a/src/cmd/go/testdata/mod/github.com_dmitshur-test_modtest5_v0.0.0-20190619020302-197a620e0c9a.txt b/src/cmd/go/testdata/mod/github.com_dmitshur-test_modtest5_v0.0.0-20190619020302-197a620e0c9a.txt new file mode 100644 index 0000000000..c2709c161e --- /dev/null +++ b/src/cmd/go/testdata/mod/github.com_dmitshur-test_modtest5_v0.0.0-20190619020302-197a620e0c9a.txt @@ -0,0 +1,10 @@ +module github.com/dmitshur-test/modtest5@v0.0.0-20190619020302-197a620e0c9a + +-- .mod -- +module github.com/dmitshur-test/modtest5 +-- .info -- +{"Version":"v0.0.0-20190619020302-197a620e0c9a","Time":"2019-06-18T19:03:02-07:00"} +-- p.go -- +package p + +const v = 1 diff --git a/src/cmd/go/testdata/mod/github.com_dmitshur-test_modtest5_v0.5.0-alpha.0.20190619023908-3da23a9deb9e.txt b/src/cmd/go/testdata/mod/github.com_dmitshur-test_modtest5_v0.5.0-alpha.0.20190619023908-3da23a9deb9e.txt new file mode 100644 index 0000000000..22e47f378e --- /dev/null +++ b/src/cmd/go/testdata/mod/github.com_dmitshur-test_modtest5_v0.5.0-alpha.0.20190619023908-3da23a9deb9e.txt @@ -0,0 +1,10 @@ +module github.com/dmitshur-test/modtest5@v0.5.0-alpha.0.20190619023908-3da23a9deb9e + +-- .mod -- +module github.com/dmitshur-test/modtest5 +-- .info -- +{"Version":"v0.5.0-alpha.0.20190619023908-3da23a9deb9e","Time":"2019-06-18T19:39:08-07:00"} +-- p.go -- +package p + +const v = 3 diff --git a/src/cmd/go/testdata/mod/github.com_dmitshur-test_modtest5_v0.5.0-alpha.txt b/src/cmd/go/testdata/mod/github.com_dmitshur-test_modtest5_v0.5.0-alpha.txt new file mode 100644 index 0000000000..4f088ccd2c --- /dev/null +++ b/src/cmd/go/testdata/mod/github.com_dmitshur-test_modtest5_v0.5.0-alpha.txt @@ -0,0 +1,10 @@ +module github.com/dmitshur-test/modtest5@v0.5.0-alpha + +-- .mod -- +module github.com/dmitshur-test/modtest5 +-- .info -- +{"Version":"v0.5.0-alpha","Time":"2019-06-18T19:04:46-07:00"} +-- p.go -- +package p + +const v = 2 diff --git a/src/cmd/go/testdata/script/mod_list_pseudo.txt b/src/cmd/go/testdata/script/mod_list_pseudo.txt new file mode 100644 index 0000000000..3a10b3a040 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_list_pseudo.txt @@ -0,0 +1,50 @@ +env GO111MODULE=on + +# Regression test for golang.org/issue/32715. + +# When using $GOPATH/pkg/mod/cache/download as a proxy, +# 'latest' queries should prefer tagged versions over pseudo-versions. + +go mod download github.com/dmitshur-test/modtest5@v0.0.0-20190619020302-197a620e0c9a +go mod download github.com/dmitshur-test/modtest5@v0.5.0-alpha +go mod download github.com/dmitshur-test/modtest5@v0.5.0-alpha.0.20190619023908-3da23a9deb9e +cmp $GOPATH/pkg/mod/cache/download/github.com/dmitshur-test/modtest5/@v/list $WORK/modtest5.list + +env GOPROXY=file:///$GOPATH/pkg/mod/cache/download +env GOPATH=$WORK/gopath2 +mkdir $GOPATH + +go list -m -json github.com/dmitshur-test/modtest5@latest +cmp stdout $WORK/modtest5.json + +# If the module proxy contains only pseudo-versions, 'latest' should stat +# the version with the most recent timestamp — not the highest semantic +# version — and return its metadata. +env GOPROXY=file:///$WORK/tinyproxy +go list -m -json dmitri.shuralyov.com/test/modtest3@latest +cmp stdout $WORK/modtest3.json + +-- $WORK/modtest5.list -- +v0.0.0-20190619020302-197a620e0c9a +v0.5.0-alpha +v0.5.0-alpha.0.20190619023908-3da23a9deb9e +-- $WORK/modtest5.json -- +{ + "Path": "github.com/dmitshur-test/modtest5", + "Version": "v0.5.0-alpha", + "Time": "2019-06-18T19:04:46-07:00" +} +-- $WORK/tinyproxy/dmitri.shuralyov.com/test/modtest3/@v/list -- +v0.1.0-0.20161023043300-000000000000 +v0.0.0-20181023043359-a85b471d5412 +-- $WORK/tinyproxy/dmitri.shuralyov.com/test/modtest3/@v/v0.0.0-20181023043359-a85b471d5412.info -- +{ + "Version": "v0.0.0-20181023043359-a85b471d5412", + "Time": "2018-10-22T21:33:59-07:00" +} +-- $WORK/modtest3.json -- +{ + "Path": "dmitri.shuralyov.com/test/modtest3", + "Version": "v0.0.0-20181023043359-a85b471d5412", + "Time": "2018-10-22T21:33:59-07:00" +} |