internal/goroot: in IsStandardPackage check for go source files

Be more strict in IsStandardPackage: before this change we'd just
check for the existence of the directory, but now we check to see that
there's at least one .go file in the directory.

Also update some comments in the modindex package to reflect the fact
that an IndexPackage might represent a directory that does not contain
any source files.

Fixes #65406
Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest,gotip-windows-amd64-longtest

Change-Id: I82f0c0e7bfcd5bb4df0195c4c8c7fc7c67fae53e
Reviewed-on: https://go-review.googlesource.com/c/go/+/561338
Reviewed-by: Bryan Mills <bcmills@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Michael Matloob 2024-02-05 12:20:45 -05:00
parent 151362cf7c
commit 4e91c5697a
5 changed files with 40 additions and 14 deletions

View File

@ -124,7 +124,7 @@ var (
errNotFromModuleCache = fmt.Errorf("%w: not from module cache", ErrNotIndexed)
)
// GetPackage returns the IndexPackage for the package at the given path.
// GetPackage returns the IndexPackage for the directory at the given path.
// It will return ErrNotIndexed if the directory should be read without
// using the index, for instance because the index is disabled, or the package
// is not in a module.
@ -669,11 +669,9 @@ func IsStandardPackage(goroot_, compiler, path string) bool {
reldir = str.TrimFilePathPrefix(reldir, "cmd")
modroot = filepath.Join(modroot, "cmd")
}
if _, err := GetPackage(modroot, filepath.Join(modroot, reldir)); err == nil {
// Note that goroot.IsStandardPackage doesn't check that the directory
// actually contains any go files-- merely that it exists. GetPackage
// returning a nil error is enough for us to know the directory exists.
return true
if pkg, err := GetPackage(modroot, filepath.Join(modroot, reldir)); err == nil {
hasGo, err := pkg.IsDirWithGoFiles()
return err == nil && hasGo
} else if errors.Is(err, ErrNotIndexed) {
// Fall back because package isn't indexable. (Probably because
// a file was modified recently)
@ -786,8 +784,8 @@ func shouldBuild(sf *sourceFile, tags map[string]bool) bool {
return true
}
// IndexPackage holds the information needed to access information in the
// index needed to load a package in a specific directory.
// IndexPackage holds the information in the index
// needed to load a package in a specific directory.
type IndexPackage struct {
error error
dir string // directory of the package relative to the modroot

View File

@ -0,0 +1,11 @@
# Issue 65406. The testdata directory in GOROOT/src
# shouldn't be treated as a standard package.
go list -f '{{.ImportPath}} {{.Dir}}' testdata
! stderr 'found package testdata in multiple modules'
stdout 'testdata '$WORK${/}'gopath'${/}'src'
-- go.mod --
module testdata
-- p.go --
package p

View File

@ -44,9 +44,9 @@ stderr '^go: module rsc.io/quote/buggy: not a known dependency'
# Module loader does not interfere with list -e (golang.org/issue/24149).
go list -e -f '{{.Error.Err}}' database
stdout 'no Go files in '
stdout 'package database is not in std'
! go list database
stderr 'no Go files in '
stderr 'package database is not in std'
-- go.mod --
module x

View File

@ -20,8 +20,16 @@ func IsStandardPackage(goroot, compiler, path string) bool {
switch compiler {
case "gc":
dir := filepath.Join(goroot, "src", path)
info, err := os.Stat(dir)
return err == nil && info.IsDir()
dirents, err := os.ReadDir(dir)
if err != nil {
return false
}
for _, dirent := range dirents {
if strings.HasSuffix(dirent.Name(), ".go") {
return true
}
}
return false
case "gccgo":
return gccgoSearch.isStandard(path)
default:

View File

@ -9,6 +9,7 @@ package goroot
import (
"os"
"path/filepath"
"strings"
)
// IsStandardPackage reports whether path is a standard package,
@ -17,8 +18,16 @@ func IsStandardPackage(goroot, compiler, path string) bool {
switch compiler {
case "gc":
dir := filepath.Join(goroot, "src", path)
_, err := os.Stat(dir)
return err == nil
dirents, err := os.ReadDir(dir)
if err != nil {
return false
}
for _, dirent := range dirents {
if strings.HasSuffix(dirent.Name(), ".go") {
return true
}
}
return false
case "gccgo":
return stdpkg[path]
default: