-
Notifications
You must be signed in to change notification settings - Fork 17.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cmd/go: check for source files in relative paths before attempting to…
… determine the package path This is a more minimial fix for the immediate symptom of 32917 and 30590, but does not improve 'list -e' behavior or error messages resulting from other package loading issues. Fixes #32917 Fixes #30590 Change-Id: I6088d14d864410159ebf228d9392d186322fd2a5 Reviewed-on: https://go-review.googlesource.com/c/go/+/185417 Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
- Loading branch information
Bryan C. Mills
committed
Jul 15, 2019
1 parent
4b36588
commit b9edee3
Showing
5 changed files
with
96 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -100,11 +100,31 @@ func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match { | |
dir = filepath.Clean(dir) | ||
} | ||
|
||
// golang.org/issue/32917: We should resolve a relative path to a | ||
// package path only if the relative path actually contains the code | ||
// for that package. | ||
if !dirContainsPackage(dir) { | ||
// If we're outside of a module, ensure that the failure mode | ||
// indicates that. | ||
ModRoot() | ||
|
||
// If the directory is local but does not exist, don't return it | ||
// while loader is iterating, since this might trigger a fetch. | ||
// After loader is done iterating, we still need to return the | ||
// path, so that "go list -e" produces valid output. | ||
if !iterating { | ||
// We don't have a valid path to resolve to, so report the | ||
// unresolved path. | ||
m.Pkgs = append(m.Pkgs, pkg) | ||
} | ||
continue | ||
} | ||
|
||
// Note: The checks for @ here are just to avoid misinterpreting | ||
// the module cache directories (formerly GOPATH/src/mod/[email protected]/bar). | ||
// It's not strictly necessary but helpful to keep the checks. | ||
if modRoot != "" && dir == modRoot { | ||
pkg = Target.Path | ||
pkg = targetPrefix | ||
} else if modRoot != "" && strings.HasPrefix(dir, modRoot+string(filepath.Separator)) && !strings.Contains(dir[len(modRoot):], "@") { | ||
suffix := filepath.ToSlash(dir[len(modRoot):]) | ||
if strings.HasPrefix(suffix, "/vendor/") { | ||
|
@@ -121,7 +141,13 @@ func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match { | |
continue | ||
} | ||
} else { | ||
pkg = Target.Path + suffix | ||
modPkg := targetPrefix + suffix | ||
if _, ok := dirInModule(modPkg, targetPrefix, modRoot, true); ok { | ||
pkg = modPkg | ||
} else if !iterating { | ||
ModRoot() | ||
base.Errorf("go: directory %s is outside main module", base.ShortPath(dir)) | ||
} | ||
} | ||
} else if sub := search.InDir(dir, cfg.GOROOTsrc); sub != "" && sub != "." && !strings.Contains(sub, "@") { | ||
pkg = filepath.ToSlash(sub) | ||
|
@@ -134,16 +160,6 @@ func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match { | |
base.Errorf("go: directory %s outside available modules", base.ShortPath(dir)) | ||
} | ||
} | ||
info, err := os.Stat(dir) | ||
if err != nil || !info.IsDir() { | ||
// If the directory is local but does not exist, don't return it | ||
// while loader is iterating, since this would trigger a fetch. | ||
// After loader is done iterating, we still need to return the | ||
// path, so that "go list -e" produces valid output. | ||
if iterating { | ||
continue | ||
} | ||
} | ||
m.Pkgs = append(m.Pkgs, pkg) | ||
} | ||
|
||
|
@@ -247,6 +263,32 @@ func pathInModuleCache(dir string) string { | |
return "" | ||
} | ||
|
||
var dirContainsPackageCache sync.Map // absolute dir → bool | ||
|
||
func dirContainsPackage(dir string) bool { | ||
isPkg, ok := dirContainsPackageCache.Load(dir) | ||
if !ok { | ||
_, err := cfg.BuildContext.ImportDir(dir, 0) | ||
if err == nil { | ||
isPkg = true | ||
} else { | ||
if fi, statErr := os.Stat(dir); statErr != nil || !fi.IsDir() { | ||
// A non-directory or inaccessible directory is not a Go package. | ||
isPkg = false | ||
} else if _, noGo := err.(*build.NoGoError); noGo { | ||
// A directory containing no Go source files is not a Go package. | ||
isPkg = false | ||
} else { | ||
// An error other than *build.NoGoError indicates that the package exists | ||
// but has some other problem (such as a syntax error). | ||
isPkg = true | ||
} | ||
} | ||
isPkg, _ = dirContainsPackageCache.LoadOrStore(dir, isPkg) | ||
} | ||
return isPkg.(bool) | ||
} | ||
|
||
// ImportFromFiles adds modules to the build list as needed | ||
// to satisfy the imports in the named Go source files. | ||
func ImportFromFiles(gofiles []string) { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
env GO111MODULE=on | ||
|
||
# golang.org/issue/32917 and golang.org/issue/28459: 'go build' and 'go test' | ||
# in an empty directory should refer to the path '.' and should not attempt | ||
# to resolve an external module. | ||
cd dir | ||
! go get . | ||
stderr 'go get \.: path .* is not a package in module rooted at .*[/\\]dir$' | ||
! go list | ||
! stderr 'cannot find module providing package' | ||
stderr '^can.t load package: package \.: no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir$' | ||
|
||
cd subdir | ||
! go list | ||
! stderr 'cannot find module providing package' | ||
stderr '^can.t load package: package \.: no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]subdir$' | ||
cd .. | ||
|
||
# golang.org/issue/30590: if a package is found in the filesystem | ||
# but is not in the main module, the error message should not say | ||
# "cannot find module providing package", and we shouldn't try | ||
# to find a module providing the package. | ||
! go list ./othermodule | ||
! stderr 'cannot find module providing package' | ||
stderr 'go: directory othermodule is outside main module' | ||
|
||
-- dir/go.mod -- | ||
module example.com | ||
go 1.13 | ||
-- dir/subdir/README -- | ||
There are no Go source files in this directory. | ||
-- dir/othermodule/go.mod -- | ||
module example.com/othermodule | ||
go 1.13 | ||
-- dir/othermodule/om.go -- | ||
package othermodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,9 +12,10 @@ stdout ^math$ | |
go list -f '{{.ImportPath}}' . | ||
stdout ^x$ | ||
! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/[email protected] | ||
stderr 'unknown import path "rsc.io/quote": cannot find package' | ||
stderr '^can.t load package: package '$WORK'[/\\]gopath/pkg/mod/rsc.io/[email protected]: can only use path@version syntax with .go get.' | ||
|
||
go list -e -f '{{with .Error}}{{.}}{{end}}' $GOPATH/pkg/mod/rsc.io/[email protected] | ||
stdout 'unknown import path "rsc.io/quote": cannot find package' | ||
stdout '^package '$WORK'[/\\]gopath/pkg/mod/rsc.io/quote@v1.5.2: can only use path@version syntax with .go get.' | ||
go mod download rsc.io/[email protected] | ||
go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/[email protected] | ||
stdout '^rsc.io/quote$' | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ env GO111MODULE=on | |
go mod download | ||
|
||
! go list $GOPATH/pkg/mod/rsc.io/[email protected] | ||
stderr 'outside available modules' | ||
stderr 'can only use path@version syntax with .go get.' | ||
|
||
go list $GOPATH/pkg/mod/rsc.io/[email protected] | ||
stdout 'rsc.io/quote' | ||
|