Commit 8c74bfb4 authored by Duco van Amstel's avatar Duco van Amstel Committed by Bryan C. Mills

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.

Fixes #32483
Fixes #34653

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: default avatarBryan C. Mills <bcmills@google.com>
parent a7042249
...@@ -1950,9 +1950,14 @@ func Packages(args []string) []*Package { ...@@ -1950,9 +1950,14 @@ func Packages(args []string) []*Package {
// cannot be loaded at all. // cannot be loaded at all.
// The packages that fail to load will have p.Error != nil. // The packages that fail to load will have p.Error != nil.
func PackagesAndErrors(patterns []string) []*Package { func PackagesAndErrors(patterns []string) []*Package {
if len(patterns) > 0 {
for _, p := range patterns { 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") { 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)} return []*Package{GoFilesPackage(patterns)}
} }
} }
......
...@@ -678,15 +678,6 @@ func runGet(cmd *base.Command, args []string) { ...@@ -678,15 +678,6 @@ func runGet(cmd *base.Command, args []string) {
if *getD || len(pkgPatterns) == 0 { if *getD || len(pkgPatterns) == 0 {
return 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() work.BuildInit()
pkgs := load.PackagesForBuild(pkgPatterns) pkgs := load.PackagesForBuild(pkgPatterns)
work.InstallPackages(pkgPatterns, pkgs) work.InstallPackages(pkgPatterns, pkgs)
......
# 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
# go list should fail to load a package ending with ".go" since that denotes # go list should succeed to load a package ending with ".go" if the path does
# a source file. However, ".go/" should work. # not correspond to an existing local file. Listing a pattern ending with
# TODO(golang.org/issue/32483): perhaps we should treat non-existent paths # ".go/" should try to list a package regardless of whether a file exists at the
# with .go suffixes as package paths instead. # path without the suffixed "/" or not.
! go list example.com/dotgo.go go list example.com/dotgo.go
stdout ^example.com/dotgo.go$
go list example.com/dotgo.go/ go list example.com/dotgo.go/
stdout ^example.com/dotgo.go$ stdout ^example.com/dotgo.go$
...@@ -15,9 +16,6 @@ go get -d example.com/dotgo.go@v1.0.0 ...@@ -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 -d example.com/dotgo.go/@v1.0.0
# go get (without -d) should also succeed in either case. # 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 [short] skip
go get example.com/dotgo.go go get example.com/dotgo.go
go get example.com/dotgo.go/ go get example.com/dotgo.go/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment