mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/doc: provide working directory to build.Import calls
The current cmd/doc implementation uses go/build.Import in a few places to check whether a package is findable and importable. go/build has limited support for finding packages in modules, but to do so, build.Import requires knowing the source directory to use when performing the lookup (so it can find the go.mod file). Otherwise, it only looks inside the GOPATH workspace. Start passing the current working directory to build.Import calls, so that it can correctly look for packages in modules when in cmd/doc is executed in module mode. Before this change, cmd/doc in module mode could mistakenly find and use a package in the GOPATH workspace, instead of the current module. Since the result of os.Getwd is needed in even more places, assign it to a local variable in parseArgs now. Fixes #28992 Updates #26504 Change-Id: I7571618e18420d2d3b3890cc69ade2d97b1962bf Reviewed-on: https://go-review.googlesource.com/c/go/+/183991 Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
parent
67f181bfd8
commit
3b040b7e80
3 changed files with 40 additions and 19 deletions
|
|
@ -920,7 +920,10 @@ func TestDotSlashLookup(t *testing.T) {
|
||||||
t.Skip("scanning file system takes too long")
|
t.Skip("scanning file system takes too long")
|
||||||
}
|
}
|
||||||
maybeSkip(t)
|
maybeSkip(t)
|
||||||
where := pwd()
|
where, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := os.Chdir(where); err != nil {
|
if err := os.Chdir(where); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -931,7 +934,7 @@ func TestDotSlashLookup(t *testing.T) {
|
||||||
}
|
}
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
var flagSet flag.FlagSet
|
var flagSet flag.FlagSet
|
||||||
err := do(&b, &flagSet, []string{"./template"})
|
err = do(&b, &flagSet, []string{"./template"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error %q from ./template", err)
|
t.Errorf("unexpected error %q from ./template", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -187,16 +187,20 @@ func failMessage(paths []string, symbol, method string) error {
|
||||||
// is rand.Float64, we must scan both crypto/rand and math/rand
|
// is rand.Float64, we must scan both crypto/rand and math/rand
|
||||||
// to find the symbol, and the first call will return crypto/rand, true.
|
// to find the symbol, and the first call will return crypto/rand, true.
|
||||||
func parseArgs(args []string) (pkg *build.Package, path, symbol string, more bool) {
|
func parseArgs(args []string) (pkg *build.Package, path, symbol string, more bool) {
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
// Easy: current directory.
|
// Easy: current directory.
|
||||||
return importDir(pwd()), "", "", false
|
return importDir(wd), "", "", false
|
||||||
}
|
}
|
||||||
arg := args[0]
|
arg := args[0]
|
||||||
// We have an argument. If it is a directory name beginning with . or ..,
|
// We have an argument. If it is a directory name beginning with . or ..,
|
||||||
// use the absolute path name. This discriminates "./errors" from "errors"
|
// use the absolute path name. This discriminates "./errors" from "errors"
|
||||||
// if the current directory contains a non-standard errors package.
|
// if the current directory contains a non-standard errors package.
|
||||||
if isDotSlash(arg) {
|
if isDotSlash(arg) {
|
||||||
arg = filepath.Join(pwd(), arg)
|
arg = filepath.Join(wd, arg)
|
||||||
}
|
}
|
||||||
switch len(args) {
|
switch len(args) {
|
||||||
default:
|
default:
|
||||||
|
|
@ -205,7 +209,7 @@ func parseArgs(args []string) (pkg *build.Package, path, symbol string, more boo
|
||||||
// Done below.
|
// Done below.
|
||||||
case 2:
|
case 2:
|
||||||
// Package must be findable and importable.
|
// Package must be findable and importable.
|
||||||
pkg, err := build.Import(args[0], "", build.ImportComment)
|
pkg, err := build.Import(args[0], wd, build.ImportComment)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return pkg, args[0], args[1], false
|
return pkg, args[0], args[1], false
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +229,7 @@ func parseArgs(args []string) (pkg *build.Package, path, symbol string, more boo
|
||||||
// First, is it a complete package path as it is? If so, we are done.
|
// First, is it a complete package path as it is? If so, we are done.
|
||||||
// This avoids confusion over package paths that have other
|
// This avoids confusion over package paths that have other
|
||||||
// package paths as their prefix.
|
// package paths as their prefix.
|
||||||
pkg, err := build.Import(arg, "", build.ImportComment)
|
pkg, err = build.Import(arg, wd, build.ImportComment)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return pkg, arg, "", false
|
return pkg, arg, "", false
|
||||||
}
|
}
|
||||||
|
|
@ -260,7 +264,7 @@ func parseArgs(args []string) (pkg *build.Package, path, symbol string, more boo
|
||||||
symbol = arg[period+1:]
|
symbol = arg[period+1:]
|
||||||
}
|
}
|
||||||
// Have we identified a package already?
|
// Have we identified a package already?
|
||||||
pkg, err := build.Import(arg[0:period], "", build.ImportComment)
|
pkg, err := build.Import(arg[0:period], wd, build.ImportComment)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return pkg, arg[0:period], symbol, false
|
return pkg, arg[0:period], symbol, false
|
||||||
}
|
}
|
||||||
|
|
@ -283,7 +287,7 @@ func parseArgs(args []string) (pkg *build.Package, path, symbol string, more boo
|
||||||
log.Fatalf("no such package %s", arg[0:period])
|
log.Fatalf("no such package %s", arg[0:period])
|
||||||
}
|
}
|
||||||
// Guess it's a symbol in the current directory.
|
// Guess it's a symbol in the current directory.
|
||||||
return importDir(pwd()), "", arg, false
|
return importDir(wd), "", arg, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// dotPaths lists all the dotted paths legal on Unix-like and
|
// dotPaths lists all the dotted paths legal on Unix-like and
|
||||||
|
|
@ -385,12 +389,3 @@ var buildCtx = build.Default
|
||||||
func splitGopath() []string {
|
func splitGopath() []string {
|
||||||
return filepath.SplitList(buildCtx.GOPATH)
|
return filepath.SplitList(buildCtx.GOPATH)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pwd returns the current directory.
|
|
||||||
func pwd() string {
|
|
||||||
wd, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
return wd
|
|
||||||
}
|
|
||||||
|
|
|
||||||
27
src/cmd/go/testdata/script/mod_doc.txt
vendored
27
src/cmd/go/testdata/script/mod_doc.txt
vendored
|
|
@ -3,6 +3,7 @@
|
||||||
env GO111MODULE=on
|
env GO111MODULE=on
|
||||||
[short] skip
|
[short] skip
|
||||||
|
|
||||||
|
# Check when module x is inside GOPATH/src.
|
||||||
go doc y
|
go doc y
|
||||||
stdout 'Package y is.*alphabet'
|
stdout 'Package y is.*alphabet'
|
||||||
stdout 'import "x/y"'
|
stdout 'import "x/y"'
|
||||||
|
|
@ -16,13 +17,25 @@ stdout 'Hello returns a greeting'
|
||||||
go doc quote
|
go doc quote
|
||||||
stdout 'Package quote collects pithy sayings.'
|
stdout 'Package quote collects pithy sayings.'
|
||||||
|
|
||||||
# Double-check go doc y when y is not in GOPATH/src.
|
# Double-check when module x is outside GOPATH/src.
|
||||||
env GOPATH=$WORK/altgopath
|
env GOPATH=$WORK/emptygopath
|
||||||
go doc x/y
|
go doc x/y
|
||||||
stdout 'Package y is.*alphabet'
|
stdout 'Package y is.*alphabet'
|
||||||
go doc y
|
go doc y
|
||||||
stdout 'Package y is.*alphabet'
|
stdout 'Package y is.*alphabet'
|
||||||
|
|
||||||
|
# Triple-check when module x is outside GOPATH/src,
|
||||||
|
# but other packages with same import paths are in GOPATH/src.
|
||||||
|
# Since go doc is running in module mode here, packages in active module
|
||||||
|
# should be preferred over packages in GOPATH. See golang.org/issue/28992.
|
||||||
|
env GOPATH=$WORK/gopath2
|
||||||
|
go doc x/y
|
||||||
|
! stdout 'Package y is.*GOPATH'
|
||||||
|
stdout 'Package y is.*alphabet'
|
||||||
|
go doc rsc.io/quote
|
||||||
|
! stdout 'Package quote is located in a GOPATH workspace.'
|
||||||
|
stdout 'Package quote collects pithy sayings.'
|
||||||
|
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module x
|
module x
|
||||||
require rsc.io/quote v1.5.2
|
require rsc.io/quote v1.5.2
|
||||||
|
|
@ -33,3 +46,13 @@ package y
|
||||||
|
|
||||||
-- x.go --
|
-- x.go --
|
||||||
package x
|
package x
|
||||||
|
|
||||||
|
-- $WORK/gopath2/src/x/y/y.go --
|
||||||
|
// Package y is located in a GOPATH workspace.
|
||||||
|
package y
|
||||||
|
-- $WORK/gopath2/src/rsc.io/quote/quote.go --
|
||||||
|
// Package quote is located in a GOPATH workspace.
|
||||||
|
package quote
|
||||||
|
|
||||||
|
// Hello is located in a GOPATH workspace.
|
||||||
|
func Hello() string { return "" }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue