Bryan Mills has uploaded this change for review.
cmd/go: improve error handling for nonexistent files
Also ensure that 'go list -e' reports nonexistent files as package
errors (rather than writing directly to stderr).
Fixes #48559
Updates #29280
Change-Id: I5c76b0c4e5fdc77a947ca4006a3fd0d111284c14
---
M src/cmd/go/internal/load/pkg.go
A src/cmd/go/testdata/script/build_issue48559.txt
M src/cmd/go/testdata/script/list_ambiguous_path.txt
3 files changed, 94 insertions(+), 34 deletions(-)
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index d68f43a..2f1c261 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -20,6 +20,7 @@
"path"
pathpkg "path"
"path/filepath"
+ "reflect"
"runtime"
"runtime/debug"
"sort"
@@ -2662,6 +2663,7 @@
ctx, span := trace.StartSpan(ctx, "load.PackagesAndErrors")
defer span.Done()
+ maybeAllGoFiles := len(patterns) > 0 // len(patterns) == 0 implies ".", which is not a file.
for _, p := range patterns {
// Listing is only supported with all patterns referring to either:
// - Files that are part of the same directory.
@@ -2672,6 +2674,8 @@
if fi, err := fsys.Stat(p); err == nil && !fi.IsDir() {
return []*Package{GoFilesPackage(ctx, opts, patterns)}
}
+ } else {
+ maybeAllGoFiles = false
}
}
@@ -2698,6 +2702,7 @@
defer pre.flush()
pre.preloadMatches(ctx, opts, matches)
+ allImportMissing := true
for _, m := range matches {
for _, pkg := range m.Pkgs {
if pkg == "" {
@@ -2715,6 +2720,9 @@
if seenPkg[p] {
continue
}
+ if p.Error == nil || !errors.As(p.Error.Err, new(*modload.ImportMissingError)) {
+ allImportMissing = false
+ }
seenPkg[p] = true
pkgs = append(pkgs, p)
}
@@ -2739,6 +2747,13 @@
}
}
+ if allImportMissing && maybeAllGoFiles {
+ // https://go.dev/issue/48559: if all of the arguments could be *either* Go
+ // source files or packages, and neither the files nor the packages actually
+ // exist, treat them as files.
+ return []*Package{GoFilesPackage(ctx, opts, patterns)}
+ }
+
if opts.MainOnly {
pkgs = mainPackagesOnly(pkgs, matches)
}
@@ -2880,20 +2895,19 @@
func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Package {
modload.Init()
+ pkg := new(Package)
+ pkg.Internal.Local = true
+ pkg.Internal.CmdlineFiles = true
+ pkg.ImportPath = "command-line-arguments"
+ pkg.Match = gofiles
+
for _, f := range gofiles {
if !strings.HasSuffix(f, ".go") {
- pkg := new(Package)
- pkg.Internal.Local = true
- pkg.Internal.CmdlineFiles = true
- pkg.Name = f
- pkg.Error = &PackageError{
- Err: fmt.Errorf("named files must be .go files: %s", pkg.Name),
- }
+ pkg.Error = &PackageError{Err: fmt.Errorf("named files must be .go files: %s", f)}
return pkg
}
}
- var stk ImportStack
ctxt := cfg.BuildContext
ctxt.UseAllFiles = true
@@ -2902,49 +2916,61 @@
// command directory. So that local imports resolve
// consistently, the files must all be in the same directory.
var dirent []fs.FileInfo
- var dir string
for _, file := range gofiles {
fi, err := fsys.Stat(file)
if err != nil {
- base.Fatalf("%s", err)
+ pkg.Error = &PackageError{Err: err}
+ return pkg
}
if fi.IsDir() {
- base.Fatalf("%s is a directory, should be a Go file", file)
+ pkg.Error = &PackageError{Err: fmt.Errorf("%s is a directory, should be a Go file", file)}
+ return pkg
}
dir1 := filepath.Dir(file)
- if dir == "" {
- dir = dir1
- } else if dir != dir1 {
- base.Fatalf("named files must all be in one directory; have %s and %s", dir, dir1)
+ if pkg.Dir == "" {
+ pkg.Dir = dir1
+ } else if pkg.Dir != dir1 {
+ pkg.Error = &PackageError{Err: fmt.Errorf("named files must all be in one directory; have %s and %s", pkg.Dir, dir1)}
+ return pkg
}
dirent = append(dirent, fi)
}
ctxt.ReadDir = func(string) ([]fs.FileInfo, error) { return dirent, nil }
+ var err error
+ if pkg.Dir == "" {
+ pkg.Dir = base.Cwd()
+ }
+ if !filepath.IsAbs(pkg.Dir) {
+ pkg.Dir = filepath.Join(base.Cwd(), pkg.Dir)
+ }
+
+ if pkg.Error == nil && !cfg.ModulesEnabled {
+ pkg.Internal.LocalPrefix = dirToImportPath(pkg.Dir)
+ }
+
if cfg.ModulesEnabled {
modload.ImportFromFiles(ctx, gofiles)
}
- var err error
- if dir == "" {
- dir = base.Cwd()
- }
- dir, err = filepath.Abs(dir)
- if err != nil {
- base.Fatalf("%s", err)
- }
-
- bp, err := ctxt.ImportDir(dir, 0)
- pkg := new(Package)
- pkg.Internal.Local = true
- pkg.Internal.CmdlineFiles = true
+ bp, err := ctxt.ImportDir(pkg.Dir, 0)
+ // ctxt.ImportDir sets ImportPath to ".", and pkg.load copies it over unconditionally.
+ // Set it to the path we actually intend.
+ bp.ImportPath = pkg.ImportPath
+ var stk ImportStack
pkg.load(ctx, opts, "command-line-arguments", &stk, nil, bp, err)
- if !cfg.ModulesEnabled {
- pkg.Internal.LocalPrefix = dirToImportPath(dir)
+ if !pkg.Internal.Local {
+ panic("local removed")
}
- pkg.ImportPath = "command-line-arguments"
- pkg.Target = ""
- pkg.Match = gofiles
+ if !pkg.Internal.CmdlineFiles {
+ panic("cmdlinefiles removed")
+ }
+ if pkg.ImportPath != "command-line-arguments" {
+ panic("importpath removed")
+ }
+ if !reflect.DeepEqual(pkg.Match, gofiles) {
+ panic("gofiles changed")
+ }
if pkg.Name == "main" {
exe := pkg.DefaultExecName() + cfg.ExeSuffix
diff --git a/src/cmd/go/testdata/script/build_issue48559.txt b/src/cmd/go/testdata/script/build_issue48559.txt
new file mode 100644
index 0000000..fa8ad77
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_issue48559.txt
@@ -0,0 +1,19 @@
+# https://go.dev/issue/48559: 'go build nonexist.go' should report a
+# 'no such file' error.
+
+cd $WORK
+go list -f '{{.ImportPath}}: {{.Error}}' -e notexist1.go notexist2.go
+stdout -count=1 '.+\n'
+stdout '^command-line-arguments: stat notexist1.go: no such file or directory$'
+
+go list -f '{{.ImportPath}}: {{.Error}}' -e notexist1.go notexist2.go main.go
+stdout -count=1 '.+\n'
+stdout '^command-line-arguments: stat notexist1.go: no such file or directory$'
+
+-- $WORK/go.mod --
+module test
+go 1.18
+-- $WORK/main.go --
+package main
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/list_ambiguous_path.txt b/src/cmd/go/testdata/script/list_ambiguous_path.txt
index 82dde45..be0c41c 100644
--- a/src/cmd/go/testdata/script/list_ambiguous_path.txt
+++ b/src/cmd/go/testdata/script/list_ambiguous_path.txt
@@ -17,7 +17,7 @@
# A single typo-ed pattern for a Go file. This should
# treat the wrong pattern as if it were a package.
! go list ./foo.go/b.go
-stderr '^stat .*[/\\]foo\.go[/\\]b\.go: directory not found$'
+stderr '^stat .*[/\\]foo\.go[/\\]b\.go: no such file or directory$'
# Multiple patterns for Go files with a typo. This should
# treat the wrong pattern as if it were a nonexistent file.
To view, visit change 386496. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Michael Matloob.
Patch set 1:Run-TryBot +1
1 comment:
Patchset:
TRY=longtest,windows-amd64-longtest
To view, visit change 386496. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Bryan Mills, Michael Matloob.
1 comment:
Patchset:
What's the status of this CL? Thanks.
To view, visit change 386496. To unsubscribe, or for help writing mail filters, visit settings.
Patchset:
What is the status of this CL? Do we want this for 1.19? Thanks.
To view, visit change 386496. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Ian Lance Taylor, Michael Matloob.
1 comment:
Patchset:
What is the status of this CL? Do we want this for 1.19? Thanks.
This didn't make RC1, and doesn't seem important enough to merge post-RC1 during the freeze. I'll see if I can have it ready again when the 1.20 window opens.
To view, visit change 386496. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Ian Lance Taylor, Michael Matloob.
Patch set 2:Run-TryBot +1
Attention is currently required from: Bryan Mills, Michael Matloob.
1 comment:
Patchset:
Ping @bcm...@google.com Do we want this for 1.20? Thanks.
To view, visit change 386496. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Ian Lance Taylor, Michael Matloob.
1 comment:
Patchset:
Ping @bcm...@google.com Do we want this for 1.20? Thanks.
It would be nice to have, but isn't as important as a couple of other fixes I need to work on this week.
To view, visit change 386496. To unsubscribe, or for help writing mail filters, visit settings.