]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: re-enable 'go list -m' with -mod=vendor for limited patterns
authorBryan C. Mills <bcmills@google.com>
Thu, 24 Oct 2019 13:17:54 +0000 (09:17 -0400)
committerBryan C. Mills <bcmills@google.com>
Thu, 24 Oct 2019 16:18:09 +0000 (16:18 +0000)
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: Jay Conrod <jayconrod@google.com>
src/cmd/go/internal/list/list.go
src/cmd/go/internal/modload/list.go
src/cmd/go/testdata/script/mod_convert_vendor_json.txt
src/cmd/go/testdata/script/mod_convert_vendor_manifest.txt
src/cmd/go/testdata/script/mod_getmode_vendor.txt
src/cmd/go/testdata/script/mod_vendor.txt
src/cmd/go/testdata/script/mod_vendor_auto.txt

index 7965a84f99c79e07be4b469d7698e564e241b2e2..b393c67ddb25dfe90a777b454d8f8802c510ea79 100644 (file)
@@ -381,17 +381,22 @@ func runList(cmd *base.Command, args []string) {
                        base.Fatalf("go list -test cannot be used with -m")
                }
 
-               buildModIsDefault := (cfg.BuildMod == "")
                if modload.Init(); !modload.Enabled() {
                        base.Fatalf("go list -m: not using modules")
                }
 
                modload.InitMod() // Parses go.mod and sets cfg.BuildMod.
                if cfg.BuildMod == "vendor" {
-                       if buildModIsDefault {
-                               base.Fatalf("go list -m: can't list modules using the vendor directory\n\tUse -mod=mod or -mod=readonly to ignore it.")
-                       } else {
-                               base.Fatalf("go list -m: can't list modules with -mod=vendor\n\tUse -mod=mod or -mod=readonly to ignore the vendor directory.")
+                       for _, arg := range args {
+                               // In vendor mode, the module graph is incomplete: it contains only the
+                               // explicit module dependencies and the modules that supply packages in
+                               // 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.)")
+                               }
                        }
                }
 
index 6c0b3945cb8d50a38882713b4bf26e2e8eb8965e..cd162f88759b5f615a88bce75a5f6ea0834c239f 100644 (file)
@@ -11,6 +11,7 @@ import (
        "strings"
 
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
        "cmd/go/internal/modinfo"
        "cmd/go/internal/module"
        "cmd/go/internal/par"
@@ -124,10 +125,20 @@ func listModules(args []string, listVersions bool) []*modinfo.ModulePublic {
                                        }
                                        continue
                                }
-                               mods = append(mods, &modinfo.ModulePublic{
-                                       Path:  arg,
-                                       Error: modinfoError(arg, "", errors.New("not a known dependency")),
-                               })
+                               if cfg.BuildMod == "vendor" {
+                                       // In vendor mode, we can't determine whether a missing module is “a
+                                       // 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 {
                                fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg)
                        }
index 2f5ccec32c615b5eb323d0af636a9577af9d5b3c..df6db36574f31096ffc9e2c4000fd853e4562389 100644 (file)
@@ -10,7 +10,7 @@ stderr '\s*cd \.\. && go mod init'
 # The command we suggested should succeed.
 cd ..
 go mod init
-go list -mod=mod -m all
+go list -m
 stdout '^m$'
 
 -- $WORK/test/vendor/vendor.json --
index 6f3a145430ad959b423ff525be1920acc06cb235..8b6a1414be26b2b3e7f9623d724b8b62710a8d1f 100644 (file)
@@ -10,7 +10,7 @@ stderr '\s*cd \.\. && go mod init'
 # The command we suggested should succeed.
 cd ..
 go mod init
-go list -mod=mod -m all
+go list -m
 stdout '^m$'
 
 -- $WORK/test/vendor/manifest --
index baa79a083a9f9c5608bdbb0d863b095f2dbd2c9a..430bf1ef44434c29396beb418305aa34a548b000 100644 (file)
@@ -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$'
 
 ! 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
 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 --
 module x
 
index 17fb2f3c1609d36af955bcbb4f9098f6558c3926..bb3e634b3a35dc96c26d34249747205043727b1c 100644 (file)
@@ -32,19 +32,28 @@ stdout 'src[\\/]x'
 go list -mod=vendor -f {{.Dir}} x
 stdout 'src[\\/]vendor[\\/]x'
 
-# 'go list -mod=vendor -m' does not have enough information to list modules
-# accurately, and should fail.
-! go list -mod=vendor -f {{.Dir}} -m x
-stderr 'can''t list modules with -mod=vendor\n\tUse -mod=mod or -mod=readonly to ignore the vendor directory.'
+# 'go list -mod=vendor -m' should successfully list vendored modules,
+# but should not provide a module directory because no directory contains
+# the complete module.
+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,
 # but 'go list -mod=vendor' should error out for them.
 go list -mod=mod -f {{.Dir}} w
 stdout 'src[\\/]w'
-
 ! go list -mod=vendor -f {{.Dir}} w
 stderr 'src[\\/]vendor[\\/]w'
 
+go list -mod=mod -f {{.Dir}} diamondright
+stdout 'src[\\/]diamondright'
+
 # Test dependencies should not be copied.
 ! exists vendor/x/testdata
 ! exists vendor/a/foo/bar/b/ignored.go
@@ -79,6 +88,8 @@ go fmt -mod=vendor ./...
 -- go.mod --
 module m
 
+go 1.13
+
 require (
        a v1.0.0
        diamondroot v0.0.0
@@ -264,10 +275,11 @@ require (
 -- diamondroot/x.go --
 package diamondroot
 
-import (
-       _ "diamondleft"
-       _ "diamondright"
-)
+import _ "diamondleft"
+-- diamondroot/unused/unused.go --
+package unused
+
+import _ "diamondright"
 -- diamondleft/go.mod --
 module diamondleft
 
index 6e79f6b99438e31712f64dc1589643829cf3787b..873644b4383572465e9c9bb59c0527a9d6297688 100644 (file)
@@ -17,10 +17,10 @@ stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]printversion$'
 stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$'
 
 ! 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
-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.
 env GOFLAGS=-mod=mod
@@ -106,10 +106,10 @@ stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$'
 # ...but 'go list -m' should continue to fail, this time without
 # referring to a -mod default that the user didn't set.
 ! 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
-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