Skip to content

Commit

Permalink
cmd/go/internal/modload: finish Import implementation
Browse files Browse the repository at this point in the history
modload.Import now means "figure out what this import means in the main module",
including searching for a module to add to go.mod if the import is missing.
(Previously it only did the search.)

Fix Import to handle overlapping module file trees correctly:
the fact that x/y/z is in the build list does not mean it is the
module that must provide x/y/z/v2/w or even x/y/z/w.

The definition of "go get x@v" is now easy to explain: if x is a module path,
go get is talking about that module. Otherwise go get is talking about the
module that provides or would provide x if encountered as an import in the
main module.

Simplify the package load process by using the new Import to eliminate
the separate doMissing parallel pass, as suggested by Bryan in an
earlier code review.

Drop modload.SrcMod in favor of modfetch.SrcMod,
and guard against SrcMod unset (filepath.Join(x, y) treats x="" as like x="."),
which can happen in tests.

Fixes golang/go#24851.
Fixes golang/go#26048.
Fixes golang/go#26250.

Change-Id: I16abfa0c095492fc10ccd75f5857c1c087935867
Reviewed-on: https://go-review.googlesource.com/123095
Reviewed-by: Bryan C. Mills <bcmills@google.com>
  • Loading branch information
rsc committed Jul 12, 2018
1 parent a42a7e8 commit 94c68ad
Show file tree
Hide file tree
Showing 15 changed files with 469 additions and 267 deletions.
3 changes: 3 additions & 0 deletions vendor/cmd/go/internal/load/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,9 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo
} else if modErr != nil {
bp = new(build.Package)
err = fmt.Errorf("unknown import path %q: %v", importPath, modErr)
} else if cfg.ModulesEnabled && path != "unsafe" {
bp = new(build.Package)
err = fmt.Errorf("unknown import path %q: internal error: module loader did not resolve import", importPath)
} else {
buildMode := build.ImportComment
if mode&ResolveImport == 0 || path != origPath {
Expand Down
5 changes: 3 additions & 2 deletions vendor/cmd/go/internal/modcmd/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"cmd/go/internal/base"
"cmd/go/internal/dirhash"
"cmd/go/internal/modfetch"
"cmd/go/internal/modload"
"cmd/go/internal/module"
)
Expand All @@ -29,9 +30,9 @@ func runVerify() {

func verifyMod(mod module.Version) bool {
ok := true
zip := filepath.Join(modload.SrcMod, "cache/download", mod.Path, "/@v/", mod.Version+".zip")
zip := filepath.Join(modfetch.SrcMod, "cache/download", mod.Path, "/@v/", mod.Version+".zip")
_, zipErr := os.Stat(zip)
dir := filepath.Join(modload.SrcMod, mod.Path+"@"+mod.Version)
dir := filepath.Join(modfetch.SrcMod, mod.Path+"@"+mod.Version)
_, dirErr := os.Stat(dir)
data, err := ioutil.ReadFile(zip + "hash")
if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions vendor/cmd/go/internal/modfetch/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,11 @@ func readDiskStat(path, rev string) (file string, info *RevInfo, err error) {
// just to find out about a commit we already know about
// (and have cached under its pseudo-version).
func readDiskStatByHash(path, rev string) (file string, info *RevInfo, err error) {
if SrcMod == "" {
// Do not download to current directory.
return "", nil, errNotCached
}

if !codehost.AllHex(rev) || len(rev) < 12 {
return "", nil, errNotCached
}
Expand Down
15 changes: 15 additions & 0 deletions vendor/cmd/go/internal/modfetch/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ var downloadCache par.Cache
// local download cache and returns the name of the directory
// corresponding to the root of the module's file tree.
func Download(mod module.Version) (dir string, err error) {
if SrcMod == "" {
// Do not download to current directory.
return "", fmt.Errorf("missing modfetch.SrcMod")
}

// The par.Cache here avoids duplicate work but also
// avoids conflicts from simultaneous calls by multiple goroutines
// for the same version.
Expand Down Expand Up @@ -190,6 +195,11 @@ func readGoSum(file string, data []byte) {

// checkSum checks the given module's checksum.
func checkSum(mod module.Version) {
if SrcMod == "" {
// Do not use current directory.
return
}

// Do the file I/O before acquiring the go.sum lock.
data, err := ioutil.ReadFile(filepath.Join(SrcMod, "cache/download", mod.Path, "@v", mod.Version+".ziphash"))
if err != nil {
Expand Down Expand Up @@ -245,6 +255,11 @@ func checkOneSum(mod module.Version, h string) {
// Sum returns the checksum for the downloaded copy of the given module,
// if present in the download cache.
func Sum(mod module.Version) string {
if SrcMod == "" {
// Do not use current directory.
return ""
}

data, err := ioutil.ReadFile(filepath.Join(SrcMod, "cache/download", mod.Path, "@v", mod.Version+".ziphash"))
if err != nil {
return ""
Expand Down
26 changes: 12 additions & 14 deletions vendor/cmd/go/internal/modget/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -511,24 +511,22 @@ func getQuery(path, vers string, forceModulePath bool) (module.Version, error) {
return module.Version{}, err
}

// Otherwise fall back to resolving package path as of today
// and applying the version to the resulting module.
// We could do more subtle things when older versions are
// specified, but this seems good enough and more predictable.
// If this behavior is wrong, the user can always specify the
// desired module path instead of a package path,
// and then the code above will handle it.
repo, info, err := modload.Import(path, modload.Allowed)
// Otherwise, interpret the package path as an import
// and determine what module that import would address
// if found in the current source code.
// Then apply the version to that module.
m, _, err := modload.Import(path)
if err != nil {
return module.Version{}, err
}
if vers != "latest" {
// modload.Import returned "latest" version. Look up requested version.
if info, err = modload.Query(repo.ModulePath(), vers, modload.Allowed); err != nil {
return module.Version{}, err
}
if m.Path == "" {
return module.Version{}, fmt.Errorf("package %q is not in a module", path)
}
return module.Version{Path: repo.ModulePath(), Version: info.Version}, nil
info, err = modload.Query(m.Path, vers, modload.Allowed)
if err != nil {
return module.Version{}, err
}
return module.Version{Path: m.Path, Version: info.Version}, nil
}

// isModulePath reports whether path names an actual module,
Expand Down
5 changes: 3 additions & 2 deletions vendor/cmd/go/internal/modload/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func moduleInfo(m module.Version, fromBuildList bool) *modinfo.ModulePublic {
}

if semver.IsValid(m.Version) {
dir := filepath.Join(SrcMod, m.Path+"@"+m.Version)
dir := filepath.Join(modfetch.SrcMod, m.Path+"@"+m.Version)
if stat, err := os.Stat(dir); err == nil && stat.IsDir() {
m.Dir = dir
}
Expand Down Expand Up @@ -194,11 +194,12 @@ func PackageBuildInfo(path string, deps []string) string {
}

func findModule(target, path string) module.Version {
// TODO: This should use loaded.
if path == "." {
return buildList[0]
}
for _, mod := range buildList {
if importPathInModule(path, mod.Path) {
if maybeInModule(path, mod.Path) {
return mod
}
}
Expand Down
Loading

0 comments on commit 94c68ad

Please sign in to comment.