for _, p := range pkgs {
if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") {
- errorf("go install: no install location for directory %s outside GOPATH", p.Dir)
+ if p.ConflictDir != "" {
+ errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir)
+ } else {
+ errorf("go install: no install location for directory %s outside GOPATH", p.Dir)
+ }
}
}
exitIfErrors()
// Note: These fields are part of the go command's public API.
// See list.go. It is okay to add fields, but not to change or
// remove existing ones. Keep in sync with list.go
- Dir string `json:",omitempty"` // directory containing package sources
- ImportPath string `json:",omitempty"` // import path of package in dir
- Name string `json:",omitempty"` // package name
- Doc string `json:",omitempty"` // package documentation string
- Target string `json:",omitempty"` // install path
- Goroot bool `json:",omitempty"` // is this package found in the Go root?
- Standard bool `json:",omitempty"` // is this package part of the standard Go library?
- Stale bool `json:",omitempty"` // would 'go install' do anything for this package?
- Root string `json:",omitempty"` // Go root or Go path dir containing this package
+ Dir string `json:",omitempty"` // directory containing package sources
+ ImportPath string `json:",omitempty"` // import path of package in dir
+ Name string `json:",omitempty"` // package name
+ Doc string `json:",omitempty"` // package documentation string
+ Target string `json:",omitempty"` // install path
+ Goroot bool `json:",omitempty"` // is this package found in the Go root?
+ Standard bool `json:",omitempty"` // is this package part of the standard Go library?
+ Stale bool `json:",omitempty"` // would 'go install' do anything for this package?
+ Root string `json:",omitempty"` // Go root or Go path dir containing this package
+ ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
// Source files
GoFiles []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
p.Name = pp.Name
p.Doc = pp.Doc
p.Root = pp.Root
+ p.ConflictDir = pp.ConflictDir
// TODO? Target
p.Goroot = pp.Goroot
p.Standard = p.Goroot && p.ImportPath != "" && !strings.Contains(p.ImportPath, ".")
unset GOPATH
rm -rf $d
+TEST shadowing logic
+export GOPATH=$(pwd)/testdata/shadow/root1:$(pwd)/testdata/shadow/root2
+
+# The math in root1 is not "math" because the standard math is.
+cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root1/src/math)
+if [ "$cdir" != "(_$(pwd)/testdata/shadow/root1/src/math) ($GOROOT/src/pkg/math)" ]; then
+ echo shadowed math is not shadowed: "$cdir"
+ ok=false
+fi
+
+# The foo in root1 is "foo".
+cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root1/src/foo)
+if [ "$cdir" != "(foo) ()" ]; then
+ echo unshadowed foo is shadowed: "$cdir"
+ ok=false
+fi
+
+# The foo in root2 is not "foo" because the foo in root1 got there first.
+cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root2/src/foo)
+if [ "$cdir" != "(_$(pwd)/testdata/shadow/root2/src/foo) ($(pwd)/testdata/shadow/root1/src/foo)" ]; then
+ echo shadowed foo is not shadowed: "$cdir"
+ ok=false
+fi
+
+# The error for go install should mention the conflicting directory.
+err=$(! ./testgo install ./testdata/shadow/root2/src/foo 2>&1)
+if [ "$err" != "go install: no install location for directory $(pwd)/testdata/shadow/root2/src/foo hidden by $(pwd)/testdata/shadow/root1/src/foo" ]; then
+ echo wrong shadowed install error: "$err"
+ ok=false
+fi
+
# Only succeeds if source order is preserved.
TEST source file name order preserved
./testgo test testdata/example[12]_test.go || ok=false
--- /dev/null
+package foo
--- /dev/null
+package math
--- /dev/null
+package foo
// A Package describes the Go package found in a directory.
type Package struct {
- Dir string // directory containing package sources
- Name string // package name
- Doc string // documentation synopsis
- ImportPath string // import path of package ("" if unknown)
- Root string // root of Go tree where this package lives
- SrcRoot string // package source root directory ("" if unknown)
- PkgRoot string // package install root directory ("" if unknown)
- BinDir string // command install directory ("" if unknown)
- Goroot bool // package found in Go root
- PkgObj string // installed .a file
- AllTags []string // tags that can influence file selection in this directory
+ Dir string // directory containing package sources
+ Name string // package name
+ Doc string // documentation synopsis
+ ImportPath string // import path of package ("" if unknown)
+ Root string // root of Go tree where this package lives
+ SrcRoot string // package source root directory ("" if unknown)
+ PkgRoot string // package install root directory ("" if unknown)
+ BinDir string // command install directory ("" if unknown)
+ Goroot bool // package found in Go root
+ PkgObj string // installed .a file
+ AllTags []string // tags that can influence file selection in this directory
+ ConflictDir string // this directory shadows Dir in $GOPATH
// Source files
GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
// else first.
if ctxt.GOROOT != "" {
if dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", sub); ctxt.isDir(dir) {
+ p.ConflictDir = dir
goto Found
}
}
for _, earlyRoot := range all[:i] {
if dir := ctxt.joinPath(earlyRoot, "src", sub); ctxt.isDir(dir) {
+ p.ConflictDir = dir
goto Found
}
}