From: Jay Conrod Date: Mon, 16 Nov 2020 21:27:19 +0000 (-0500) Subject: cmd/go: allow querying other versions of the main module X-Git-Tag: go1.16beta1~219 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=01df2febf5f00b1dcba1843093ef99b338b23546;p=gostls13.git cmd/go: allow querying other versions of the main module 'go mod download' and a few other commands can now query specific versions of the main module. 'go get' still reports an error when attempting to update the main module. Fixes #42524 Change-Id: Ia93ef8f5f34443e938667c48a0db432200108c63 Reviewed-on: https://go-review.googlesource.com/c/go/+/270520 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go index e2e8ba6825..ef1ad780c8 100644 --- a/src/cmd/go/internal/modcmd/download.go +++ b/src/cmd/go/internal/modcmd/download.go @@ -88,12 +88,11 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { args = []string{"all"} } else if modload.HasModRoot() { modload.LoadModFile(ctx) // to fill Target - targetAtLatest := modload.Target.Path + "@latest" targetAtUpgrade := modload.Target.Path + "@upgrade" targetAtPatch := modload.Target.Path + "@patch" for _, arg := range args { switch arg { - case modload.Target.Path, targetAtLatest, targetAtUpgrade, targetAtPatch: + case modload.Target.Path, targetAtUpgrade, targetAtPatch: os.Stderr.WriteString("go mod download: skipping argument " + arg + " that resolves to the main module\n") } } @@ -170,7 +169,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { for _, m := range mods { b, err := json.MarshalIndent(m, "", "\t") if err != nil { - base.Fatalf("%v", err) + base.Fatalf("go mod download: %v", err) } os.Stdout.Write(append(b, '\n')) if m.Error != "" { @@ -180,7 +179,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { } else { for _, m := range mods { if m.Error != "" { - base.Errorf("%s", m.Error) + base.Errorf("go mod download: %v", m.Error) } } base.ExitIfErrors() diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index d4a1e85041..e35e0fc16e 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -109,10 +109,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed allowed = func(context.Context, module.Version) error { return nil } } - if path == Target.Path { - if query != "upgrade" && query != "patch" { - return nil, &QueryMatchesMainModuleError{Pattern: path, Query: query} - } + if path == Target.Path && (query == "upgrade" || query == "patch") { if err := allowed(ctx, Target); err != nil { return nil, fmt.Errorf("internal error: main module version is not allowed: %w", err) } @@ -582,6 +579,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin } } + var queryMatchesMainModule bool if HasModRoot() { m := match(Target, modRoot, true) if len(m.Pkgs) > 0 { @@ -605,7 +603,11 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin return nil, nil, err } - if query != "upgrade" && query != "patch" && matchPattern(Target.Path) { + if matchPattern(Target.Path) { + queryMatchesMainModule = true + } + + if (query == "upgrade" || query == "patch") && queryMatchesMainModule { if err := allowed(ctx, Target); err == nil { modOnly = &QueryResult{ Mod: Target, @@ -620,14 +622,20 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin candidateModules = modulePrefixesExcludingTarget(base) ) if len(candidateModules) == 0 { - if modOnly == nil { + if modOnly != nil { + return nil, modOnly, nil + } else if queryMatchesMainModule { + return nil, nil, &QueryMatchesMainModuleError{ + Pattern: pattern, + Query: query, + } + } else { return nil, nil, &PackageNotInModuleError{ Mod: Target, Query: query, Pattern: pattern, } } - return nil, modOnly, nil } err = modfetch.TryProxies(func(proxy string) error { @@ -675,6 +683,12 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin return err }) + if queryMatchesMainModule && len(results) == 0 && modOnly == nil && errors.Is(err, fs.ErrNotExist) { + return nil, nil, &QueryMatchesMainModuleError{ + Pattern: pattern, + Query: query, + } + } return results[:len(results):len(results)], modOnly, err } diff --git a/src/cmd/go/testdata/script/mod_download.txt b/src/cmd/go/testdata/script/mod_download.txt index 2775fca44e..8a9faffe4e 100644 --- a/src/cmd/go/testdata/script/mod_download.txt +++ b/src/cmd/go/testdata/script/mod_download.txt @@ -93,11 +93,11 @@ exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.zip # download reports errors encountered when locating modules ! go mod download bad/path -stderr '^module bad/path: not a known dependency$' +stderr '^go mod download: module bad/path: not a known dependency$' ! go mod download bad/path@latest -stderr '^bad/path@latest: malformed module path "bad/path": missing dot in first path element$' +stderr '^go mod download: bad/path@latest: malformed module path "bad/path": missing dot in first path element$' ! go mod download rsc.io/quote@v1.999.999 -stderr '^rsc.io/quote@v1.999.999: reading .*/v1.999.999.info: 404 Not Found$' +stderr '^go mod download: rsc.io/quote@v1.999.999: reading .*/v1.999.999.info: 404 Not Found$' ! go mod download -json bad/path stdout '^\t"Error": "module bad/path: not a known dependency"' @@ -105,7 +105,7 @@ stdout '^\t"Error": "module bad/path: not a known dependency"' go mod download m stderr '^go mod download: skipping argument m that resolves to the main module\n' ! go mod download m@latest -stderr 'm@latest: can''t request version "latest" of the main module \(m\)' +stderr '^go mod download: m@latest: malformed module path "m": missing dot in first path element$' # download updates go.mod and populates go.sum cd update diff --git a/src/cmd/go/testdata/script/mod_get_main.txt b/src/cmd/go/testdata/script/mod_get_main.txt index eeaa92d8ca..50b2fee9ae 100644 --- a/src/cmd/go/testdata/script/mod_get_main.txt +++ b/src/cmd/go/testdata/script/mod_get_main.txt @@ -30,10 +30,14 @@ grep 'rsc.io/quote v1.5.1' go.mod # The main module cannot be updated to a specific version. +! go get -d rsc.io@v0.1.0 +stderr '^go get: can''t request version "v0.1.0" of the main module \(rsc.io\)$' + +# A package in the main module can't be upgraded either. ! go get -d rsc.io/x@v0.1.0 stderr '^go get: package rsc.io/x is in the main module, so can''t request version v0.1.0$' -# The main module cannot be updated to @latest, which is a specific version. +# Nor can a pattern matching packages in the main module. ! go get -d rsc.io/x/...@latest stderr '^go get: pattern rsc.io/x/... matches package rsc.io/x in the main module, so can''t request version latest$' diff --git a/src/cmd/go/testdata/script/mod_query_main.txt b/src/cmd/go/testdata/script/mod_query_main.txt new file mode 100644 index 0000000000..39e5841a9c --- /dev/null +++ b/src/cmd/go/testdata/script/mod_query_main.txt @@ -0,0 +1,43 @@ +# 'go mod download' can download specific versions of the main module. +go mod download rsc.io/quote@5d9f230b +go mod download rsc.io/quote@v1.5.2 +go mod download rsc.io/quote@latest + +# 'go mod download' will not download @upgrade or @patch, since they always +# resolve to the main module. +go mod download rsc.io/quote@upgrade +stderr '^go mod download: skipping argument rsc.io/quote@upgrade that resolves to the main module$' +go mod download rsc.io/quote@patch +stderr '^go mod download: skipping argument rsc.io/quote@patch that resolves to the main module$' + +# 'go list -m' can show a version of the main module. +go list -m rsc.io/quote@5d9f230b +stdout '^rsc.io/quote v0.0.0-20180710144737-5d9f230bcfba$' +go list -m rsc.io/quote@v1.5.2 +stdout '^rsc.io/quote v1.5.2$' +go list -m rsc.io/quote@latest +stdout '^rsc.io/quote v1.5.2$' + +# 'go list -m -versions' shows available versions. +go list -m -versions rsc.io/quote +stdout '^rsc.io/quote.*v1.5.2' + +# 'go list -m' resolves @upgrade and @patch to the main module. +go list -m rsc.io/quote@upgrade +stdout '^rsc.io/quote$' +go list -m rsc.io/quote@patch +stdout '^rsc.io/quote$' + +# 'go get' will not attempt to upgrade the main module to any specific version. +# See also: mod_get_main.txt. +! go get rsc.io/quote@5d9f230b +stderr '^go get: can''t request version "5d9f230b" of the main module \(rsc.io/quote\)$' +! go get rsc.io/quote@v1.5.2 +stderr '^go get: can''t request version "v1.5.2" of the main module \(rsc.io/quote\)$' +! go get rsc.io/quote@latest +stderr '^go get: can''t request version "latest" of the main module \(rsc.io/quote\)$' + +-- go.mod -- +module rsc.io/quote + +go 1.16