// 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.
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)
+ }
}
}
return module.Version{}, "", "", nil, mainErr
}
- if len(dirs) == 0 {
+ if len(mods) == 0 {
return module.Version{}, "", "", nil, &ImportMissingError{Path: path}
}
--- /dev/null
+# 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
# 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$'