Skip to content

Commit d651660

Browse files
committed
cmd/go: set Root and target fields for packages in GOPATH
This change replicates the behavior filed in issue #37015 for packages imported from the module index. That behavior is that packages that happen to exist in a GOPATH src directory have p.Root and p.Target set even when the packages are loaded from modules. This is likely unintentional behavior because in module mode, packages shouldn't behave differently depending on whether their directories exist in GOPATH. But for uniformity, (and because two of our tests depend on this behavior), this CL will implement this behavior. We can remove it from the module index when we remove it from the go/build logic. Change-Id: I3f501c92fbb76eaf86b6b9275539f2129b67f884 Reviewed-on: https://go-review.googlesource.com/c/go/+/410822 Reviewed-by: Michael Matloob <[email protected]> Run-TryBot: Michael Matloob <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Russ Cox <[email protected]>
1 parent 4afb0b9 commit d651660

File tree

2 files changed

+61
-14
lines changed

2 files changed

+61
-14
lines changed

src/cmd/go/internal/modindex/build.go

+31
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,37 @@ func hasSubdir(root, dir string) (rel string, ok bool) {
177177
return filepath.ToSlash(dir[len(root):]), true
178178
}
179179

180+
// gopath returns the list of Go path directories.
181+
func (ctxt *Context) gopath() []string {
182+
var all []string
183+
for _, p := range ctxt.splitPathList(ctxt.GOPATH) {
184+
if p == "" || p == ctxt.GOROOT {
185+
// Empty paths are uninteresting.
186+
// If the path is the GOROOT, ignore it.
187+
// People sometimes set GOPATH=$GOROOT.
188+
// Do not get confused by this common mistake.
189+
continue
190+
}
191+
if strings.HasPrefix(p, "~") {
192+
// Path segments starting with ~ on Unix are almost always
193+
// users who have incorrectly quoted ~ while setting GOPATH,
194+
// preventing it from expanding to $HOME.
195+
// The situation is made more confusing by the fact that
196+
// bash allows quoted ~ in $PATH (most shells do not).
197+
// Do not get confused by this, and do not try to use the path.
198+
// It does not exist, and printing errors about it confuses
199+
// those users even more, because they think "sure ~ exists!".
200+
// The go command diagnoses this situation and prints a
201+
// useful error.
202+
// On Windows, ~ is used in short names, such as c:\progra~1
203+
// for c:\program files.
204+
continue
205+
}
206+
all = append(all, p)
207+
}
208+
return all
209+
}
210+
180211
var defaultToolTags, defaultReleaseTags []string
181212

182213
// A Package describes the Go package found in a directory.

src/cmd/go/internal/modindex/read.go

+30-14
Original file line numberDiff line numberDiff line change
@@ -242,31 +242,47 @@ func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.Im
242242
return p, fmt.Errorf("import %q: import of unknown directory", p.Dir)
243243
}
244244

245-
// goroot
245+
// goroot and gopath
246246
inTestdata := func(sub string) bool {
247247
return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || str.HasPathPrefix(sub, "testdata")
248248
}
249-
if ctxt.GOROOT != "" && str.HasFilePathPrefix(mi.modroot, cfg.GOROOTsrc) && !inTestdata(relpath) {
250-
modprefix := str.TrimFilePathPrefix(mi.modroot, cfg.GOROOTsrc)
251-
p.Goroot = true
252-
p.ImportPath = relpath
253-
if modprefix != "" {
254-
p.ImportPath = filepath.Join(modprefix, p.ImportPath)
255-
}
249+
if !inTestdata(relpath) {
256250
// In build.go, p.Root should only be set in the non-local-import case, or in
257251
// GOROOT or GOPATH. Since module mode only calls Import with path set to "."
258252
// and the module index doesn't apply outside modules, the GOROOT case is
259253
// the only case where GOROOT needs to be set.
260-
// TODO(#37015): p.Root actually might be set in the local-import case outside
261-
// GOROOT, if the directory is contained in GOPATH/src, even in module
262-
// mode, but that's a bug.
263-
p.Root = ctxt.GOROOT
254+
// But: p.Root is actually set in the local-import case outside GOROOT, if
255+
// the directory is contained in GOPATH/src
256+
// TODO(#37015): fix that behavior in go/build and remove the gopath case
257+
// below.
258+
if ctxt.GOROOT != "" && str.HasFilePathPrefix(p.Dir, cfg.GOROOTsrc) && p.Dir != cfg.GOROOTsrc {
259+
p.Root = ctxt.GOROOT
260+
p.Goroot = true
261+
modprefix := str.TrimFilePathPrefix(mi.modroot, cfg.GOROOTsrc)
262+
p.ImportPath = relpath
263+
if modprefix != "" {
264+
p.ImportPath = filepath.Join(modprefix, p.ImportPath)
265+
}
266+
}
267+
for _, root := range ctxt.gopath() {
268+
// TODO(matloob): do we need to reimplement the conflictdir logic?
264269

265-
// Set GOROOT-specific fields
270+
// TODO(matloob): ctxt.hasSubdir evaluates symlinks, so it
271+
// can be slower than we'd like. Find out if we can drop this
272+
// logic before the release.
273+
if sub, ok := ctxt.hasSubdir(filepath.Join(root, "src"), p.Dir); ok {
274+
p.ImportPath = sub
275+
p.Root = root
276+
}
277+
}
278+
}
279+
if p.Root != "" {
280+
// Set GOROOT-specific fields (sometimes for modules in a GOPATH directory).
266281
// The fields set below (SrcRoot, PkgRoot, BinDir, PkgTargetRoot, and PkgObj)
267282
// are only set in build.Import if p.Root != "". As noted in the comment
268283
// on setting p.Root above, p.Root should only be set in the GOROOT case for the
269-
// set of packages we care about.
284+
// set of packages we care about, but is also set for modules in a GOPATH src
285+
// directory.
270286
var pkgtargetroot string
271287
var pkga string
272288
suffix := ""

0 commit comments

Comments
 (0)