]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: import vendored packages only listed in modules.txt
authorSam Thanawalla <samthanawalla@google.com>
Mon, 18 Mar 2024 19:33:36 +0000 (19:33 +0000)
committerSam Thanawalla <samthanawalla@google.com>
Tue, 7 May 2024 15:21:14 +0000 (15:21 +0000)
Fixes: #60922
Change-Id: I4a18267596441b97c6a701a2befd75ee10644d7d
Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest,gotip-windows-amd64-longtest
Reviewed-on: https://go-review.googlesource.com/c/go/+/572200
Reviewed-by: Michael Matloob <matloob@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/go/internal/gover/version.go
src/cmd/go/internal/modload/import.go
src/cmd/go/testdata/script/mod_import_vendor.txt [new file with mode: 0644]
src/cmd/go/testdata/script/mod_vendor_auto.txt

index 2681013fef7f281546943500f0bfba29c0c3dc0b..15c712a4392825648faf13d6225c94a64ec2bec0 100644 (file)
@@ -53,6 +53,10 @@ const (
        // or later, every module must have a go version line ≥ all its dependencies.
        // It is also the version after which "too new" a version is considered a fatal error.
        GoStrictVersion = "1.21"
+
+       // ExplicitModulesTxtImportVersion is the Go version at which vendored packages need to be present
+       // in modules.txt to be imported.
+       ExplicitModulesTxtImportVersion = "1.23"
 )
 
 // FromGoMod returns the go version from the go.mod file.
index 7cd5fcf36a67ace4635a88dd2a88454b3030b840..a3105b6b6daf85526116267f7baf3229d60129be 100644 (file)
@@ -338,16 +338,24 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
 
                if HasModRoot() {
                        vendorDir := VendorDir()
-                       dir, vendorOK, _ := dirInModule(path, "", vendorDir, false)
-                       if vendorOK {
+                       dir, inVendorDir, _ := dirInModule(path, "", vendorDir, false)
+                       if inVendorDir {
                                readVendorList(vendorDir)
-                               // TODO(#60922): It's possible for a package to manually have been added to the
-                               // vendor directory, causing the dirInModule to succeed, but no vendorPkgModule
-                               // to exist, causing an empty module path to be reported. Do better checking
-                               // here.
-                               mods = append(mods, vendorPkgModule[path])
-                               dirs = append(dirs, dir)
-                               roots = append(roots, vendorDir)
+                               // If vendorPkgModule does not contain an entry for path then it's probably either because
+                               // vendor/modules.txt does not exist or the user manually added directories to the vendor directory.
+                               // Go 1.23 and later require vendored packages to be present in modules.txt to be imported.
+                               _, ok := vendorPkgModule[path]
+                               if ok || (gover.Compare(MainModules.GoVersion(), gover.ExplicitModulesTxtImportVersion) < 0) {
+                                       mods = append(mods, vendorPkgModule[path])
+                                       dirs = append(dirs, dir)
+                                       roots = append(roots, vendorDir)
+                               } else {
+                                       subCommand := "mod"
+                                       if inWorkspaceMode() {
+                                               subCommand = "work"
+                                       }
+                                       fmt.Fprintf(os.Stderr, "go: ignoring package %s which exists in the vendor directory but is missing from vendor/modules.txt. To sync the vendor directory run go %s vendor.\n", path, subCommand)
+                               }
                        }
                }
 
@@ -359,7 +367,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
                        return module.Version{}, "", "", nil, mainErr
                }
 
-               if len(dirs) == 0 {
+               if len(mods) == 0 {
                        return module.Version{}, "", "", nil, &ImportMissingError{Path: path}
                }
 
diff --git a/src/cmd/go/testdata/script/mod_import_vendor.txt b/src/cmd/go/testdata/script/mod_import_vendor.txt
new file mode 100644 (file)
index 0000000..391ea86
--- /dev/null
@@ -0,0 +1,50 @@
+# For 1.23+, vendored packages that are missing in modules.txt should result in an error.
+cp incorrect_modules.txt vendor/modules.txt
+# incorrect_modules is missing foo.com/internal/bar/b so the build should fail.
+! go build ./vendor/foo.com/internal/bar/a
+stderr 'cannot find module providing package foo.com/internal/bar/b: import lookup disabled by -mod=vendor'
+stderr 'go: ignoring package foo.com/internal/bar/b which exists in the vendor directory but is missing from vendor/modules.txt. To sync the vendor directory run go mod vendor.'
+
+cp correct_modules.txt vendor/modules.txt
+go build ./vendor/foo.com/internal/bar/a
+
+# For go versions < 1.23, vendored packages that are missing in modules.txt should not result in an error.
+cp 122go.mod go.mod
+
+cp incorrect_modules.txt vendor/modules.txt
+
+# go version < 1.23 and incorrect_modules is missing foo.com/internal/bar/b so the build should not fail
+go build ./vendor/foo.com/internal/bar/a
+
+cp correct_modules.txt vendor/modules.txt
+go build ./vendor/foo.com/internal/bar/a
+
+-- 122go.mod --
+module example.com/x
+go 1.22
+
+require "foo.com/internal/bar" v1.0.0
+
+-- go.mod --
+module example.com/x
+go 1.23
+
+require "foo.com/internal/bar" v1.0.0
+
+-- incorrect_modules.txt --
+# foo.com/internal/bar v1.0.0
+## explicit
+foo.com/internal/bar/a
+
+-- correct_modules.txt --
+# foo.com/internal/bar v1.0.0
+## explicit
+foo.com/internal/bar/a
+foo.com/internal/bar/b
+
+-- vendor/foo.com/internal/bar/a/a.go --
+package a
+import _ "foo.com/internal/bar/b"
+
+-- vendor/foo.com/internal/bar/b/b.go --
+package b
\ No newline at end of file
index 2cafcdab6aea84f28b53195bb0858d5d0e3cbc98..3c385c5b44c66f415f46d809cb8c46413f2bce96 100644 (file)
@@ -118,11 +118,14 @@ stderr 'go: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod
 # present. If there are no module dependencies, -mod=vendor should be used by
 # default and should not fail the consistency check even though no module
 # information is present.
+# Note: This behavior only applies pre-1.23. Go 1.23 and later require vendored
+# packages to be present in modules.txt to be imported.
 
 rm go.mod
 rm vendor/modules.txt
 
 go mod init example.com/auto
+go mod edit -go=1.22
 go list -f {{.Dir}} -tags tools -e all
 stdout '^'$WORK'[/\\]auto$'
 stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]printversion$'