aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuco van Amstel <duco.vanamstel@gmail.com>2019-10-04 13:05:13 +0000
committerBryan C. Mills <bcmills@google.com>2019-10-07 16:43:16 +0000
commit2f73eedd42b509e3aa262fb2846105d3b5cee986 (patch)
treebd9cf5ad7e8fb67b7eedd9ab259c377fada23722
parentb7b6e8e294d620477bd0266f199e633fcd57662d (diff)
downloadgo-2f73eedd42b509e3aa262fb2846105d3b5cee986.tar.gz
go-2f73eedd42b509e3aa262fb2846105d3b5cee986.zip
[release-branch.go1.13] cmd/go: fix listing of ambiguous paths
Passing ambiguous patterns, ending in `.go`, to `go list` results in them being interpreted as Go files despite potentially being package references. This can then result in errors on other package references. The parsing logic is modified to check for a locally present file corresponding to any pattern ending in `.go`. If no such file is present the pattern is considered to be a package reference. We're also adding a variety of non-regression tests that fail with the original parsing code but passes after applying the fix. Updates #34653 Fixes #34694 Change-Id: I073871da0dfc5641a359643f95ac14608fdca09b GitHub-Last-Rev: 5abc200103ffc122df05422d79cf30c3ba0ee646 GitHub-Pull-Request: golang/go#34663 Reviewed-on: https://go-review.googlesource.com/c/go/+/198459 Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com> (cherry picked from commit 33683f1d64df0cef2c598a84b741abb5af8abe5e) Reviewed-on: https://go-review.googlesource.com/c/go/+/198957 Reviewed-by: Jay Conrod <jayconrod@google.com>
-rw-r--r--src/cmd/go/internal/load/pkg.go11
-rw-r--r--src/cmd/go/internal/modget/get.go9
-rw-r--r--src/cmd/go/testdata/script/list_ambiguous_path.txt37
-rw-r--r--src/cmd/go/testdata/script/mod_get_trailing_slash.txt14
4 files changed, 51 insertions, 20 deletions
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index 27efc7c04a..f0a899fdc8 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -1950,9 +1950,14 @@ func Packages(args []string) []*Package {
// cannot be loaded at all.
// The packages that fail to load will have p.Error != nil.
func PackagesAndErrors(patterns []string) []*Package {
- if len(patterns) > 0 {
- for _, p := range patterns {
- if strings.HasSuffix(p, ".go") {
+ for _, p := range patterns {
+ // Listing is only supported with all patterns referring to either:
+ // - Files that are part of the same directory.
+ // - Explicit package paths or patterns.
+ if strings.HasSuffix(p, ".go") {
+ // We need to test whether the path is an actual Go file and not a
+ // package path or pattern ending in '.go' (see golang.org/issue/34653).
+ if fi, err := os.Stat(p); err == nil && !fi.IsDir() {
return []*Package{GoFilesPackage(patterns)}
}
}
diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go
index 3fcd2d412a..1cae311c4c 100644
--- a/src/cmd/go/internal/modget/get.go
+++ b/src/cmd/go/internal/modget/get.go
@@ -678,15 +678,6 @@ func runGet(cmd *base.Command, args []string) {
if *getD || len(pkgPatterns) == 0 {
return
}
- // TODO(golang.org/issue/32483): handle paths ending with ".go" consistently
- // with 'go build'. When we load packages above, we interpret arguments as
- // package patterns, not source files. To preserve that interpretation here,
- // we add a trailing slash to any patterns ending with ".go".
- for i := range pkgPatterns {
- if strings.HasSuffix(pkgPatterns[i], ".go") {
- pkgPatterns[i] += "/"
- }
- }
work.BuildInit()
pkgs := load.PackagesForBuild(pkgPatterns)
work.InstallPackages(pkgPatterns, pkgs)
diff --git a/src/cmd/go/testdata/script/list_ambiguous_path.txt b/src/cmd/go/testdata/script/list_ambiguous_path.txt
new file mode 100644
index 0000000000..9f1aa37be8
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_ambiguous_path.txt
@@ -0,0 +1,37 @@
+# Ensures that we can correctly list package patterns ending in '.go'.
+# See golang.org/issue/34653.
+
+# A single pattern for a package ending in '.go'.
+go list ./foo.go
+stdout '^test/foo.go$'
+
+# Multiple patterns for packages including one ending in '.go'.
+go list ./bar ./foo.go
+stdout '^test/bar$'
+stdout '^test/foo.go$'
+
+# A single pattern for a Go file.
+go list ./a.go
+stdout '^command-line-arguments$'
+
+# 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 'package ./foo.go/b.go: cannot find package "."'
+
+# Multiple patterns for Go files with a typo. This should
+# treat the wrong pattern as if it were a non-existint file.
+! go list ./foo.go/a.go ./foo.go/b.go
+[windows] stderr './foo.go/b.go: The system cannot find the file specified'
+[!windows] stderr './foo.go/b.go: no such file or directory'
+
+-- a.go --
+package main
+-- bar/a.go --
+package bar
+-- foo.go/a.go --
+package foo.go
+-- go.mod --
+module "test"
+
+go 1.13
diff --git a/src/cmd/go/testdata/script/mod_get_trailing_slash.txt b/src/cmd/go/testdata/script/mod_get_trailing_slash.txt
index 8828738abb..7b5d90c50b 100644
--- a/src/cmd/go/testdata/script/mod_get_trailing_slash.txt
+++ b/src/cmd/go/testdata/script/mod_get_trailing_slash.txt
@@ -1,8 +1,9 @@
-# go list should fail to load a package ending with ".go" since that denotes
-# a source file. However, ".go/" should work.
-# TODO(golang.org/issue/32483): perhaps we should treat non-existent paths
-# with .go suffixes as package paths instead.
-! go list example.com/dotgo.go
+# go list should succeed to load a package ending with ".go" if the path does
+# not correspond to an existing local file. Listing a pattern ending with
+# ".go/" should try to list a package regardless of whether a file exists at the
+# path without the suffixed "/" or not.
+go list example.com/dotgo.go
+stdout ^example.com/dotgo.go$
go list example.com/dotgo.go/
stdout ^example.com/dotgo.go$
@@ -15,9 +16,6 @@ go get -d example.com/dotgo.go@v1.0.0
go get -d example.com/dotgo.go/@v1.0.0
# go get (without -d) should also succeed in either case.
-# TODO(golang.org/issue/32483): we should be consistent with 'go build',
-# 'go list', and other commands. 'go list example.com/dotgo.go' (above) and
-# 'go get example.com/dotgo.go' should both succeed or both fail.
[short] skip
go get example.com/dotgo.go
go get example.com/dotgo.go/