aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2018-07-30 12:59:42 -0400
committerRuss Cox <rsc@golang.org>2018-08-01 00:35:23 +0000
commitcdac6c22c30cbe75031563ff2859d0314aa8477b (patch)
treeb1d4f091bdbf325a6945251900db21322dd963c8
parent30a84b389daf8f6c358f92da056ac19280e3640d (diff)
downloadgo-cdac6c22c30cbe75031563ff2859d0314aa8477b.tar.gz
go-cdac6c22c30cbe75031563ff2859d0314aa8477b.zip
cmd/go: allow list of absolute directory path
Relative directory paths have always worked. This CL makes absolute directory paths be handled the same way. (It was an oversight that they were excluded.) It also fixes the case of naming the directory holding source code for a package in a module dependency. Fixes #14177. Fixes #26550. Change-Id: I29a0ca2795d35eca773121ee91a97628b56947ce Reviewed-on: https://go-review.googlesource.com/126715 Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Michael Matloob <matloob@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
-rw-r--r--src/cmd/go/internal/load/pkg.go8
-rw-r--r--src/cmd/go/internal/modload/load.go40
-rw-r--r--src/cmd/go/testdata/script/mod_list_dir.txt27
3 files changed, 69 insertions, 6 deletions
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index 2559e9fb54..691e8a537b 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -1755,8 +1755,12 @@ func LoadPackage(arg string, stk *ImportStack) *Package {
// This lets you run go test ./ioutil in package io and be
// referring to io/ioutil rather than a hypothetical import of
// "./ioutil".
- if build.IsLocalImport(arg) {
- bp, _ := cfg.BuildContext.ImportDir(filepath.Join(base.Cwd, arg), build.FindOnly)
+ if build.IsLocalImport(arg) || filepath.IsAbs(arg) {
+ dir := arg
+ if !filepath.IsAbs(arg) {
+ dir = filepath.Join(base.Cwd, arg)
+ }
+ bp, _ := cfg.BuildContext.ImportDir(dir, build.FindOnly)
if bp.ImportPath != "" && bp.ImportPath != "." {
arg = bp.ImportPath
}
diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go
index b7dbc39b05..9c550445ee 100644
--- a/src/cmd/go/internal/modload/load.go
+++ b/src/cmd/go/internal/modload/load.go
@@ -11,6 +11,7 @@ import (
"go/build"
"io/ioutil"
"os"
+ "path"
"path/filepath"
"sort"
"strings"
@@ -60,17 +61,26 @@ func ImportPaths(args []string) []string {
paths = nil
for _, pkg := range cleaned {
switch {
- case build.IsLocalImport(pkg):
+ case build.IsLocalImport(pkg) || filepath.IsAbs(pkg):
list := []string{pkg}
if strings.Contains(pkg, "...") {
// TODO: Where is the go.mod cutoff?
list = warnPattern(pkg, search.AllPackagesInFS(pkg))
}
for _, pkg := range list {
- dir := filepath.Join(cwd, pkg)
+ dir := pkg
+ if !filepath.IsAbs(dir) {
+ dir = filepath.Join(cwd, pkg)
+ } else {
+ dir = filepath.Clean(dir)
+ }
+
+ // Note: The checks for @ here are just to avoid misinterpreting
+ // the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar).
+ // It's not strictly necessary but helpful to keep the checks.
if dir == ModRoot {
pkg = Target.Path
- } else if strings.HasPrefix(dir, ModRoot+string(filepath.Separator)) {
+ } else if strings.HasPrefix(dir, ModRoot+string(filepath.Separator)) && !strings.Contains(dir[len(ModRoot):], "@") {
suffix := filepath.ToSlash(dir[len(ModRoot):])
if strings.HasPrefix(suffix, "/vendor/") {
// TODO getmode vendor check
@@ -78,8 +88,12 @@ func ImportPaths(args []string) []string {
} else {
pkg = Target.Path + suffix
}
+ } else if sub := search.InDir(dir, cfg.GOROOTsrc); sub != "" && !strings.Contains(sub, "@") {
+ pkg = filepath.ToSlash(sub)
+ } else if path := pathInModuleCache(dir); path != "" {
+ pkg = path
} else {
- base.Errorf("go: package %s outside module root", pkg)
+ base.Errorf("go: directory %s outside available modules", base.ShortPath(dir))
continue
}
roots = append(roots, pkg)
@@ -156,6 +170,24 @@ func ImportPaths(args []string) []string {
return final
}
+// pathInModuleCache returns the import path of the directory dir,
+// if dir is in the module cache copy of a module in our build list.
+func pathInModuleCache(dir string) string {
+ for _, m := range buildList[1:] {
+ root, err := modfetch.DownloadDir(m)
+ if err != nil {
+ continue
+ }
+ if sub := search.InDir(dir, root); sub != "" {
+ sub = filepath.ToSlash(sub)
+ if !strings.Contains(sub, "/vendor/") && !strings.HasPrefix(sub, "vendor/") && !strings.Contains(sub, "@") {
+ return path.Join(m.Path, filepath.ToSlash(sub))
+ }
+ }
+ }
+ return ""
+}
+
// warnPattern returns list, the result of matching pattern,
// but if list is empty then first it prints a warning about
// the pattern not matching any packages.
diff --git a/src/cmd/go/testdata/script/mod_list_dir.txt b/src/cmd/go/testdata/script/mod_list_dir.txt
new file mode 100644
index 0000000000..9b3ee14d1b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_list_dir.txt
@@ -0,0 +1,27 @@
+# go list with path to directory should work
+
+env GO111MODULE=off
+go list -f '{{.ImportPath}}' $GOROOT/src/math
+stdout ^math$
+
+env GO111MODULE=on
+go list -f '{{.ImportPath}}' $GOROOT/src/math
+stdout ^math$
+go list -f '{{.ImportPath}}' .
+stdout ^x$
+go list -f '{{.ImportPath}}' $GOPATH/src/mod/rsc.io/quote@v1.5.2
+stdout '^rsc.io/quote$'
+go list -f '{{.ImportPath}}' $GOPATH/src/mod/rsc.io/sampler@v1.3.0
+stdout '^rsc.io/sampler$'
+go get rsc.io/sampler@v1.3.1
+go list -f '{{.ImportPath}}' $GOPATH/src/mod/rsc.io/sampler@v1.3.1
+stdout '^rsc.io/sampler$'
+! go list -f '{{.ImportPath}}' $GOPATH/src/mod/rsc.io/sampler@v1.3.0
+stderr 'outside available modules'
+
+-- go.mod --
+module x
+require rsc.io/quote v1.5.2
+
+-- x.go --
+package x