Commit fc335068 authored by Bryan C. Mills's avatar Bryan C. Mills

cmd/go: re-enable 'go list -m' with -mod=vendor for limited patterns

I had prohibited 'go list -m' with -mod=vendor because the module
graph is incomplete, but I've realized that many queries do not
actually require the full graph — and may, in fact, be driven using
modules previously reported by 'go list' for specific, vendored
packages. Queries for those modules should succeed.

Updates #33848

Change-Id: I1000b4cf586a830bb78faf620ebf62d73a3cb300
Reviewed-on: https://go-review.googlesource.com/c/go/+/203138
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarJay Conrod <jayconrod@google.com>
parent b36f22bf
...@@ -381,17 +381,22 @@ func runList(cmd *base.Command, args []string) { ...@@ -381,17 +381,22 @@ func runList(cmd *base.Command, args []string) {
base.Fatalf("go list -test cannot be used with -m") base.Fatalf("go list -test cannot be used with -m")
} }
buildModIsDefault := (cfg.BuildMod == "")
if modload.Init(); !modload.Enabled() { if modload.Init(); !modload.Enabled() {
base.Fatalf("go list -m: not using modules") base.Fatalf("go list -m: not using modules")
} }
modload.InitMod() // Parses go.mod and sets cfg.BuildMod. modload.InitMod() // Parses go.mod and sets cfg.BuildMod.
if cfg.BuildMod == "vendor" { if cfg.BuildMod == "vendor" {
if buildModIsDefault { for _, arg := range args {
base.Fatalf("go list -m: can't list modules using the vendor directory\n\tUse -mod=mod or -mod=readonly to ignore it.") // In vendor mode, the module graph is incomplete: it contains only the
} else { // explicit module dependencies and the modules that supply packages in
base.Fatalf("go list -m: can't list modules with -mod=vendor\n\tUse -mod=mod or -mod=readonly to ignore the vendor directory.") // the import graph. Reject queries that imply more information than that.
if arg == "all" {
base.Fatalf("go list -m: can't compute 'all' using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")
}
if strings.Contains(arg, "...") {
base.Fatalf("go list -m: can't match module patterns using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")
}
} }
} }
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"strings" "strings"
"cmd/go/internal/base" "cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/modinfo" "cmd/go/internal/modinfo"
"cmd/go/internal/module" "cmd/go/internal/module"
"cmd/go/internal/par" "cmd/go/internal/par"
...@@ -124,10 +125,20 @@ func listModules(args []string, listVersions bool) []*modinfo.ModulePublic { ...@@ -124,10 +125,20 @@ func listModules(args []string, listVersions bool) []*modinfo.ModulePublic {
} }
continue continue
} }
mods = append(mods, &modinfo.ModulePublic{ if cfg.BuildMod == "vendor" {
Path: arg, // In vendor mode, we can't determine whether a missing module is “a
Error: modinfoError(arg, "", errors.New("not a known dependency")), // known dependency” because the module graph is incomplete.
}) // Give a more explicit error message.
mods = append(mods, &modinfo.ModulePublic{
Path: arg,
Error: modinfoError(arg, "", errors.New("can't resolve module using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")),
})
} else {
mods = append(mods, &modinfo.ModulePublic{
Path: arg,
Error: modinfoError(arg, "", errors.New("not a known dependency")),
})
}
} else { } else {
fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg) fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg)
} }
......
...@@ -10,7 +10,7 @@ stderr '\s*cd \.\. && go mod init' ...@@ -10,7 +10,7 @@ stderr '\s*cd \.\. && go mod init'
# The command we suggested should succeed. # The command we suggested should succeed.
cd .. cd ..
go mod init go mod init
go list -mod=mod -m all go list -m
stdout '^m$' stdout '^m$'
-- $WORK/test/vendor/vendor.json -- -- $WORK/test/vendor/vendor.json --
......
...@@ -10,7 +10,7 @@ stderr '\s*cd \.\. && go mod init' ...@@ -10,7 +10,7 @@ stderr '\s*cd \.\. && go mod init'
# The command we suggested should succeed. # The command we suggested should succeed.
cd .. cd ..
go mod init go mod init
go list -mod=mod -m all go list -m
stdout '^m$' stdout '^m$'
-- $WORK/test/vendor/manifest -- -- $WORK/test/vendor/manifest --
......
...@@ -11,10 +11,17 @@ stdout '^rsc.io/quote v1.5.1 .*vendor[\\/]rsc.io[\\/]quote$' ...@@ -11,10 +11,17 @@ stdout '^rsc.io/quote v1.5.1 .*vendor[\\/]rsc.io[\\/]quote$'
stdout '^golang.org/x/text v0.0.0.* .*vendor[\\/]golang.org[\\/]x[\\/]text[\\/]language$' stdout '^golang.org/x/text v0.0.0.* .*vendor[\\/]golang.org[\\/]x[\\/]text[\\/]language$'
! go list -mod=vendor -m rsc.io/quote@latest ! go list -mod=vendor -m rsc.io/quote@latest
stderr 'go list -m: can''t list modules with -mod=vendor\n\tUse -mod=mod or -mod=readonly to ignore the vendor directory.' stderr 'go list -m: rsc.io/quote@latest: module lookup disabled by -mod=vendor'
! go get -mod=vendor -u ! go get -mod=vendor -u
stderr 'flag provided but not defined: -mod' stderr 'flag provided but not defined: -mod'
# Since we don't have a complete module graph, 'go list -m' queries
# that require the complete graph should fail with a useful error.
! go list -mod=vendor -m all
stderr 'go list -m: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
! go list -mod=vendor -m ...
stderr 'go list -m: can''t match module patterns using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
-- go.mod -- -- go.mod --
module x module x
......
...@@ -32,19 +32,28 @@ stdout 'src[\\/]x' ...@@ -32,19 +32,28 @@ stdout 'src[\\/]x'
go list -mod=vendor -f {{.Dir}} x go list -mod=vendor -f {{.Dir}} x
stdout 'src[\\/]vendor[\\/]x' stdout 'src[\\/]vendor[\\/]x'
# 'go list -mod=vendor -m' does not have enough information to list modules # 'go list -mod=vendor -m' should successfully list vendored modules,
# accurately, and should fail. # but should not provide a module directory because no directory contains
! go list -mod=vendor -f {{.Dir}} -m x # the complete module.
stderr 'can''t list modules with -mod=vendor\n\tUse -mod=mod or -mod=readonly to ignore the vendor directory.' go list -mod=vendor -f '{{.Version}} {{.Dir}}' -m x
stdout '^v1.0.0 $'
# 'go list -mod=vendor -m' on a transitive dependency that does not
# provide vendored packages should give a helpful error rather than
# 'not a known dependency'.
! go list -mod=vendor -f '{{.Version}} {{.Dir}}' -m diamondright
stderr 'go list -m: module diamondright: can''t resolve module using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
# 'go list -mod=mod' should report packages outside the import graph, # 'go list -mod=mod' should report packages outside the import graph,
# but 'go list -mod=vendor' should error out for them. # but 'go list -mod=vendor' should error out for them.
go list -mod=mod -f {{.Dir}} w go list -mod=mod -f {{.Dir}} w
stdout 'src[\\/]w' stdout 'src[\\/]w'
! go list -mod=vendor -f {{.Dir}} w ! go list -mod=vendor -f {{.Dir}} w
stderr 'src[\\/]vendor[\\/]w' stderr 'src[\\/]vendor[\\/]w'
go list -mod=mod -f {{.Dir}} diamondright
stdout 'src[\\/]diamondright'
# Test dependencies should not be copied. # Test dependencies should not be copied.
! exists vendor/x/testdata ! exists vendor/x/testdata
! exists vendor/a/foo/bar/b/ignored.go ! exists vendor/a/foo/bar/b/ignored.go
...@@ -79,6 +88,8 @@ go fmt -mod=vendor ./... ...@@ -79,6 +88,8 @@ go fmt -mod=vendor ./...
-- go.mod -- -- go.mod --
module m module m
go 1.13
require ( require (
a v1.0.0 a v1.0.0
diamondroot v0.0.0 diamondroot v0.0.0
...@@ -264,10 +275,11 @@ require ( ...@@ -264,10 +275,11 @@ require (
-- diamondroot/x.go -- -- diamondroot/x.go --
package diamondroot package diamondroot
import ( import _ "diamondleft"
_ "diamondleft" -- diamondroot/unused/unused.go --
_ "diamondright" package unused
)
import _ "diamondright"
-- diamondleft/go.mod -- -- diamondleft/go.mod --
module diamondleft module diamondleft
......
...@@ -17,10 +17,10 @@ stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]printversion$' ...@@ -17,10 +17,10 @@ stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]printversion$'
stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$' stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$'
! go list -m all ! go list -m all
stderr 'can''t list modules with -mod=vendor\n\tUse -mod=mod or -mod=readonly to ignore the vendor directory.' stderr 'go list -m: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
! go list -m -f '{{.Dir}}' all ! go list -m -f '{{.Dir}}' all
stderr 'can''t list modules with -mod=vendor\n\tUse -mod=mod or -mod=readonly to ignore the vendor directory.' stderr 'go list -m: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
# An explicit -mod=mod should force the vendor directory to be ignored. # An explicit -mod=mod should force the vendor directory to be ignored.
env GOFLAGS=-mod=mod env GOFLAGS=-mod=mod
...@@ -106,10 +106,10 @@ stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$' ...@@ -106,10 +106,10 @@ stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$'
# ...but 'go list -m' should continue to fail, this time without # ...but 'go list -m' should continue to fail, this time without
# referring to a -mod default that the user didn't set. # referring to a -mod default that the user didn't set.
! go list -m all ! go list -m all
stderr 'can''t list modules using the vendor directory\n\tUse -mod=mod or -mod=readonly to ignore it.' stderr 'go list -m: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
! go list -m -f '{{.Dir}}' all ! go list -m -f '{{.Dir}}' all
stderr 'can''t list modules using the vendor directory\n\tUse -mod=mod or -mod=readonly to ignore it.' stderr 'go list -m: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'
# 'go mod init' should work if there is already a GOPATH-mode vendor directory # 'go mod init' should work if there is already a GOPATH-mode vendor directory
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment