1
0
mirror of https://github.com/golang/go synced 2024-11-11 21:20:21 -07:00

cmd/go: in 'go list -m', ignore "not found" errors loading updates

"Not found" and "no matching version" errors usually indicate the user
is offline or the proxy doesn't have a version of go.mod that could
provide retractions. 'go list -m -u' should still succeed.

We should still report unclassified errors though. Previously, we
reported most errors loading retractions but did not report errors
loading updates. This change makes those operations more consistent.

Fixes #45305

Change-Id: I2f23a566c9481bc7ff229a177f39d78f6a8aae77
Reviewed-on: https://go-review.googlesource.com/c/go/+/306572
Trust: Jay Conrod <jayconrod@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
Jay Conrod 2021-04-01 11:01:19 -04:00
parent 0e09e4143e
commit 23e1d36a87
4 changed files with 103 additions and 14 deletions

View File

@ -11,6 +11,7 @@ import (
"errors"
"fmt"
"internal/goroot"
"io/fs"
"os"
"path/filepath"
"strings"
@ -108,7 +109,26 @@ func addUpdate(ctx context.Context, m *modinfo.ModulePublic) {
return
}
if info, err := Query(ctx, m.Path, "upgrade", m.Version, CheckAllowed); err == nil && semver.Compare(info.Version, m.Version) > 0 {
info, err := Query(ctx, m.Path, "upgrade", m.Version, CheckAllowed)
var noVersionErr *NoMatchingVersionError
if errors.Is(err, fs.ErrNotExist) || errors.As(err, &noVersionErr) {
// Ignore "not found" and "no matching version" errors. This usually means
// the user is offline or the proxy doesn't have a matching version.
//
// We should report other errors though. An attacker that controls the
// network shouldn't be able to hide versions by interfering with
// the HTTPS connection. An attacker that controls the proxy may still
// hide versions, since the "list" and "latest" endpoints are not
// authenticated.
return
} else if err != nil {
if m.Error == nil {
m.Error = &modinfo.ModuleError{Err: err.Error()}
}
return
}
if semver.Compare(info.Version, m.Version) > 0 {
m.Update = &modinfo.ModulePublic{
Path: m.Path,
Version: info.Version,
@ -140,14 +160,26 @@ func addRetraction(ctx context.Context, m *modinfo.ModulePublic) {
}
err := CheckRetractions(ctx, module.Version{Path: m.Path, Version: m.Version})
var rerr *ModuleRetractedError
if errors.As(err, &rerr) {
if len(rerr.Rationale) == 0 {
var noVersionErr *NoMatchingVersionError
var retractErr *ModuleRetractedError
if err == nil || errors.Is(err, fs.ErrNotExist) || errors.As(err, &noVersionErr) {
// Ignore "not found" and "no matching version" errors. This usually means
// the user is offline or the proxy doesn't have a go.mod file that could
// contain retractions.
//
// We should report other errors though. An attacker that controls the
// network shouldn't be able to hide versions by interfering with
// the HTTPS connection. An attacker that controls the proxy may still
// hide versions, since the "list" and "latest" endpoints are not
// authenticated.
return
} else if errors.As(err, &retractErr) {
if len(retractErr.Rationale) == 0 {
m.Retracted = []string{"retracted by module author"}
} else {
m.Retracted = rerr.Rationale
m.Retracted = retractErr.Rationale
}
} else if err != nil && m.Error == nil {
} else if m.Error == nil {
m.Error = &modinfo.ModuleError{Err: err.Error()}
}
}

View File

@ -29,12 +29,12 @@ go list -m -retracted -f '{{with .Retracted}}retracted{{end}}' example.com/retra
go list -m -f '{{with .Retracted}}retracted{{end}}' example.com/retract@v1.0.0-unused
! stdout .
# 'go list -m -retracted mod@version' shows an error if the go.mod that should
# contain the retractions is not available.
! go list -m -retracted example.com/retract/missingmod@v1.0.0
stderr '^go list -m: loading module retractions for example.com/retract/missingmod@v1.0.0: .*404 Not Found$'
go list -e -m -retracted -f '{{.Error.Err}}' example.com/retract/missingmod@v1.0.0
stdout '^loading module retractions for example.com/retract/missingmod@v1.0.0: .*404 Not Found$'
# 'go list -m -retracted mod@version' does not show an error if the module
# that would contain the retraction is unavailable. See #45305.
go list -m -retracted -f '{{.Path}} {{.Version}} {{.Error}}' example.com/retract/missingmod@v1.0.0
stdout '^example.com/retract/missingmod v1.0.0 <nil>$'
exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.info
! exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.mod
# 'go list -m -retracted mod@version' shows retractions.
go list -m -retracted example.com/retract@v1.0.0-unused

View File

@ -0,0 +1,55 @@
# Check that if a proxy does not have a version of a module that could be
# an upgrade, 'go list -m -u' still succeeds.
# We use a local file proxy, since our test proxy doesn't have the behavior
# we want to test, and we don't want it to be too clever.
# Verifies #45305, where proxy.golang.org serves an empty /@v/list (200)
# but has no /@latest (410) because the go.mod at the tip of the default
# branch has a different major version suffix.
env testproxy=$GOPROXY
env GOPROXY=file://$WORK/proxy
env GOSUMDB=off
# If the proxy does not return a list of versions (404/410)
# or a latest version (404/410), we should see no error.
go list -m example.com/noversion
stdout '^example.com/noversion v0.0.0$'
go list -m -u example.com/noversion
stdout '^example.com/noversion v0.0.0$'
# If the proxy returns an empty list of versions (200, not 404/410)
# but does not have a latest version (404/410), we should see no error.
go list -m example.com/nolatest
stdout '^example.com/nolatest v0.0.0$'
go list -m -u example.com/nolatest
stdout '^example.com/nolatest v0.0.0$'
# If proxy returns an invalid response, we should see an error.
env GOPROXY=$testproxy/invalid
! go list -m -u example.com/nolatest
stderr '^go list -m: loading module retractions for example.com/nolatest@v0.0.0: invalid response from proxy "[^"]*": invalid character ''i'' looking for beginning of value$'
-- go.mod --
module m
go 1.17
require (
example.com/nolatest v0.0.0
example.com/noversion v0.0.0
)
-- go.sum --
example.com/nolatest v0.0.0/go.mod h1:HnLrCt6SJga5tCtJ7IzG9dOOCniY3G5C0VT7jfMdS0M=
example.com/noversion v0.0.0/go.mod h1:2RUfWiCYsygSXPM2Igxx0FD3Kq33OnVdxm34eDDhXbQ=
-- $WORK/proxy/example.com/nolatest/@v/list --
-- $WORK/proxy/example.com/nolatest/@v/v0.0.0.info --
{"Version":"v0.0.0"}
-- $WORK/proxy/example.com/nolatest/@v/v0.0.0.mod --
module example.com/nolatest
go 1.17
-- $WORK/proxy/example.com/noversion/@v/v0.0.0.info --
{"Version":"v0.0.0"}
-- $WORK/proxy/example.com/noversion/@v/v0.0.0.mod --
module example.com/noversion
go 1.17

View File

@ -5,8 +5,10 @@
go get -d
# The latest version, v1.9.0, is not available on the proxy.
! go list -m -retracted example.com/retract/missingmod
stderr '^go list -m: loading module retractions for example.com/retract/missingmod@v1.0.0: .*404 Not Found$'
go list -m -retracted example.com/retract/missingmod
stdout '^example.com/retract/missingmod v1.0.0$'
exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.info
! exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.mod
# If we replace that version, we should see retractions.
go mod edit -replace=example.com/retract/missingmod@v1.9.0=./missingmod-v1.9.0