Skip to content

Commit 608b94b

Browse files
author
Jay Conrod
committed
cmd/go: fix error for empty packages referenced with relative paths
'go build' now reports a more useful error when a relative path on the command line points to a directory that doesn't exist or a directory without .go files. Errors are generated by go/build.Context.ImportDir instead of a vague call to base.Fatalf in modload. Fixes golang#35414 Change-Id: I2642230c5e409107b98bb6d6c3a484d8d25b4147 Reviewed-on: https://go-review.googlesource.com/c/go/+/206902 Run-TryBot: Jay Conrod <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]>
1 parent 718f553 commit 608b94b

4 files changed

Lines changed: 75 additions & 10 deletions

File tree

src/cmd/go/internal/load/pkg.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,11 @@ func loadPackageData(path, parentPath, parentDir, parentRoot string, parentIsStd
670670
// we create from the full directory to the package.
671671
// Otherwise it is the usual import path.
672672
// For vendored imports, it is the expanded form.
673+
//
674+
// Note that when modules are enabled, local import paths are normally
675+
// canonicalized by modload.ImportPaths before now. However, if there's an
676+
// error resolving a local path, it will be returned untransformed
677+
// so that 'go list -e' reports something useful.
673678
importKey := importSpec{
674679
path: path,
675680
parentPath: parentPath,

src/cmd/go/internal/modload/build.go

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,19 @@ func findStandardImportPath(path string) string {
4545
return ""
4646
}
4747

48+
// PackageModuleInfo returns information about the module that provides
49+
// a given package. If modules are not enabled or if the package is in the
50+
// standard library or if the package was not successfully loaded with
51+
// ImportPaths or a similar loading function, nil is returned.
4852
func PackageModuleInfo(pkgpath string) *modinfo.ModulePublic {
4953
if isStandardImportPath(pkgpath) || !Enabled() {
5054
return nil
5155
}
52-
return moduleInfo(findModule(pkgpath, pkgpath), true)
56+
m, ok := findModule(pkgpath)
57+
if !ok {
58+
return nil
59+
}
60+
return moduleInfo(m, true)
5361
}
5462

5563
func ModuleInfo(path string) *modinfo.ModulePublic {
@@ -199,12 +207,11 @@ func PackageBuildInfo(path string, deps []string) string {
199207
if isStandardImportPath(path) || !Enabled() {
200208
return ""
201209
}
202-
203-
target := findModule(path, path)
210+
target := mustFindModule(path, path)
204211
mdeps := make(map[module.Version]bool)
205212
for _, dep := range deps {
206213
if !isStandardImportPath(dep) {
207-
mdeps[findModule(path, dep)] = true
214+
mdeps[mustFindModule(path, dep)] = true
208215
}
209216
}
210217
var mods []module.Version
@@ -239,9 +246,12 @@ func PackageBuildInfo(path string, deps []string) string {
239246
return buf.String()
240247
}
241248

242-
// findModule returns the module containing the package at path,
243-
// needed to build the package at target.
244-
func findModule(target, path string) module.Version {
249+
// mustFindModule is like findModule, but it calls base.Fatalf if the
250+
// module can't be found.
251+
//
252+
// TODO(jayconrod): remove this. Callers should use findModule and return
253+
// errors instead of relying on base.Fatalf.
254+
func mustFindModule(target, path string) module.Version {
245255
pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
246256
if ok {
247257
if pkg.err != nil {
@@ -261,6 +271,20 @@ func findModule(target, path string) module.Version {
261271
panic("unreachable")
262272
}
263273

274+
// findModule searches for the module that contains the package at path.
275+
// If the package was loaded with ImportPaths or one of the other loading
276+
// functions, its containing module and true are returned. Otherwise,
277+
// module.Version{} and false are returend.
278+
func findModule(path string) (module.Version, bool) {
279+
if pkg, ok := loaded.pkgCache.Get(path).(*loadPkg); ok {
280+
return pkg.mod, pkg.mod != module.Version{}
281+
}
282+
if path == "command-line-arguments" {
283+
return Target, true
284+
}
285+
return module.Version{}, false
286+
}
287+
264288
func ModInfoProg(info string, isgccgo bool) []byte {
265289
// Inject a variable with the debug information as runtime.modinfo,
266290
// but compile it in package main so that it is specific to the binary.

src/cmd/go/internal/modload/load.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
9494
pkgs := m.Pkgs
9595
m.Pkgs = m.Pkgs[:0]
9696
for _, pkg := range pkgs {
97-
dir := pkg
98-
if !filepath.IsAbs(dir) {
97+
var dir string
98+
if !filepath.IsAbs(pkg) {
9999
dir = filepath.Join(base.Cwd, pkg)
100100
} else {
101-
dir = filepath.Clean(dir)
101+
dir = filepath.Clean(pkg)
102102
}
103103

104104
// golang.org/issue/32917: We should resolve a relative path to a
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# This test checks error messages for non-existant packages in module mode.
2+
# Veries golang.org/issue/35414
3+
env GO111MODULE=on
4+
cd $WORK
5+
6+
go list -e -f {{.Error}} .
7+
stdout 'package \.: no Go files in \$WORK'
8+
9+
go list -e -f {{.Error}} ./empty
10+
stdout 'package \./empty: no Go files in \$WORK[/\\]empty'
11+
12+
go list -e -f {{.Error}} ./exclude
13+
stdout 'package \./exclude: build constraints exclude all Go files in \$WORK[/\\]exclude'
14+
15+
go list -e -f {{.Error}} ./missing
16+
stdout 'package \./missing: cannot find package "." in:\s*\$WORK[/\\]missing'
17+
18+
# use 'go build -n' because 'go list' reports no error.
19+
! go build -n ./testonly
20+
stderr 'example.com/m/testonly: no non-test Go files in \$WORK[/\\]testonly'
21+
22+
-- $WORK/go.mod --
23+
module example.com/m
24+
25+
go 1.14
26+
27+
-- $WORK/empty/empty.txt --
28+
-- $WORK/exclude/exclude.go --
29+
// +build exclude
30+
31+
package exclude
32+
-- $WORK/testonly/testonly_test.go --
33+
package testonly_test
34+
-- $WORK/excluded-stdout --
35+
package ./excluded: cannot find package "." in:
36+
$WORK/excluded

0 commit comments

Comments
 (0)