diff options
author | Bryan C. Mills <bcmills@google.com> | 2020-03-06 17:18:16 -0500 |
---|---|---|
committer | Bryan C. Mills <bcmills@google.com> | 2020-03-09 19:17:27 +0000 |
commit | 2818a11b1824ca52803a3a335354970fbccfcf2e (patch) | |
tree | b75a94adfd714040e5e0ab3e109bb21f58a9706d /src/cmd/go/internal/modload/load.go | |
parent | b559a173f9f187e1185f8de00a9cc1f5b05aceef (diff) | |
download | go-2818a11b1824ca52803a3a335354970fbccfcf2e.tar.gz go-2818a11b1824ca52803a3a335354970fbccfcf2e.zip |
cmd/go/internal/modload: factor smaller files out of load.go and init.go
No semantic changes intended: just structural cleanup.
Updates #36460
Change-Id: I405bc2572d3ff00f595dae645e673a11e01621ca
Reviewed-on: https://go-review.googlesource.com/c/go/+/222340
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
Diffstat (limited to 'src/cmd/go/internal/modload/load.go')
-rw-r--r-- | src/cmd/go/internal/modload/load.go | 355 |
1 files changed, 0 insertions, 355 deletions
diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 6ea7d8c69b..21601cb13e 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -9,14 +9,12 @@ import ( "errors" "fmt" "go/build" - "io/ioutil" "os" "path" pathpkg "path" "path/filepath" "sort" "strings" - "sync" "cmd/go/internal/base" "cmd/go/internal/cfg" @@ -27,9 +25,7 @@ import ( "cmd/go/internal/search" "cmd/go/internal/str" - "golang.org/x/mod/modfile" "golang.org/x/mod/module" - "golang.org/x/mod/semver" ) // buildList is the list of modules to use for building packages. @@ -1033,354 +1029,3 @@ func WhyDepth(path string) int { } return n } - -// Replacement returns the replacement for mod, if any, from go.mod. -// If there is no replacement for mod, Replacement returns -// a module.Version with Path == "". -func Replacement(mod module.Version) module.Version { - if index != nil { - if r, ok := index.replace[mod]; ok { - return r - } - if r, ok := index.replace[module.Version{Path: mod.Path}]; ok { - return r - } - } - return module.Version{} -} - -// mvsReqs implements mvs.Reqs for module semantic versions, -// with any exclusions or replacements applied internally. -type mvsReqs struct { - buildList []module.Version - cache par.Cache - versions sync.Map -} - -// Reqs returns the current module requirement graph. -// Future calls to SetBuildList do not affect the operation -// of the returned Reqs. -func Reqs() mvs.Reqs { - r := &mvsReqs{ - buildList: buildList, - } - return r -} - -func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { - type cached struct { - list []module.Version - err error - } - - c := r.cache.Do(mod, func() interface{} { - list, err := r.required(mod) - if err != nil { - return cached{nil, err} - } - for i, mv := range list { - if index != nil { - for index.exclude[mv] { - mv1, err := r.next(mv) - if err != nil { - return cached{nil, err} - } - if mv1.Version == "none" { - return cached{nil, fmt.Errorf("%s(%s) depends on excluded %s(%s) with no newer version available", mod.Path, mod.Version, mv.Path, mv.Version)} - } - mv = mv1 - } - } - list[i] = mv - } - - return cached{list, nil} - }).(cached) - - return c.list, c.err -} - -var vendorOnce sync.Once - -type vendorMetadata struct { - Explicit bool - Replacement module.Version -} - -var ( - vendorList []module.Version // modules that contribute packages to the build, in order of appearance - vendorReplaced []module.Version // all replaced modules; may or may not also contribute packages - vendorVersion map[string]string // module path → selected version (if known) - vendorPkgModule map[string]module.Version // package → containing module - vendorMeta map[module.Version]vendorMetadata -) - -// readVendorList reads the list of vendored modules from vendor/modules.txt. -func readVendorList() { - vendorOnce.Do(func() { - vendorList = nil - vendorPkgModule = make(map[string]module.Version) - vendorVersion = make(map[string]string) - vendorMeta = make(map[module.Version]vendorMetadata) - data, err := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt")) - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - base.Fatalf("go: %s", err) - } - return - } - - var mod module.Version - for _, line := range strings.Split(string(data), "\n") { - if strings.HasPrefix(line, "# ") { - f := strings.Fields(line) - - if len(f) < 3 { - continue - } - if semver.IsValid(f[2]) { - // A module, but we don't yet know whether it is in the build list or - // only included to indicate a replacement. - mod = module.Version{Path: f[1], Version: f[2]} - f = f[3:] - } else if f[2] == "=>" { - // A wildcard replacement found in the main module's go.mod file. - mod = module.Version{Path: f[1]} - f = f[2:] - } else { - // Not a version or a wildcard replacement. - // We don't know how to interpret this module line, so ignore it. - mod = module.Version{} - continue - } - - if len(f) >= 2 && f[0] == "=>" { - meta := vendorMeta[mod] - if len(f) == 2 { - // File replacement. - meta.Replacement = module.Version{Path: f[1]} - vendorReplaced = append(vendorReplaced, mod) - } else if len(f) == 3 && semver.IsValid(f[2]) { - // Path and version replacement. - meta.Replacement = module.Version{Path: f[1], Version: f[2]} - vendorReplaced = append(vendorReplaced, mod) - } else { - // We don't understand this replacement. Ignore it. - } - vendorMeta[mod] = meta - } - continue - } - - // Not a module line. Must be a package within a module or a metadata - // directive, either of which requires a preceding module line. - if mod.Path == "" { - continue - } - - if strings.HasPrefix(line, "## ") { - // Metadata. Take the union of annotations across multiple lines, if present. - meta := vendorMeta[mod] - for _, entry := range strings.Split(strings.TrimPrefix(line, "## "), ";") { - entry = strings.TrimSpace(entry) - if entry == "explicit" { - meta.Explicit = true - } - // All other tokens are reserved for future use. - } - vendorMeta[mod] = meta - continue - } - - if f := strings.Fields(line); len(f) == 1 && module.CheckImportPath(f[0]) == nil { - // A package within the current module. - vendorPkgModule[f[0]] = mod - - // Since this module provides a package for the build, we know that it - // is in the build list and is the selected version of its path. - // If this information is new, record it. - if v, ok := vendorVersion[mod.Path]; !ok || semver.Compare(v, mod.Version) < 0 { - vendorList = append(vendorList, mod) - vendorVersion[mod.Path] = mod.Version - } - } - } - }) -} - -func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version { - list := make([]module.Version, 0, len(f.Require)) - for _, r := range f.Require { - list = append(list, r.Mod) - } - return list -} - -// required returns a unique copy of the requirements of mod. -func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) { - if mod == Target { - if modFile != nil && modFile.Go != nil { - r.versions.LoadOrStore(mod, modFile.Go.Version) - } - return append([]module.Version(nil), r.buildList[1:]...), nil - } - - if cfg.BuildMod == "vendor" { - // For every module other than the target, - // return the full list of modules from modules.txt. - readVendorList() - return append([]module.Version(nil), vendorList...), nil - } - - origPath := mod.Path - if repl := Replacement(mod); repl.Path != "" { - if repl.Version == "" { - // TODO: need to slip the new version into the tags list etc. - dir := repl.Path - if !filepath.IsAbs(dir) { - dir = filepath.Join(ModRoot(), dir) - } - gomod := filepath.Join(dir, "go.mod") - data, err := ioutil.ReadFile(gomod) - if err != nil { - return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err) - } - f, err := modfile.ParseLax(gomod, data, nil) - if err != nil { - return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err) - } - if f.Go != nil { - r.versions.LoadOrStore(mod, f.Go.Version) - } - return r.modFileToList(f), nil - } - mod = repl - } - - if mod.Version == "none" { - return nil, nil - } - - if !semver.IsValid(mod.Version) { - // Disallow the broader queries supported by fetch.Lookup. - base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", mod.Path, mod.Version) - } - - data, err := modfetch.GoMod(mod.Path, mod.Version) - if err != nil { - return nil, err - } - f, err := modfile.ParseLax("go.mod", data, nil) - if err != nil { - return nil, module.VersionError(mod, fmt.Errorf("parsing go.mod: %v", err)) - } - - if f.Module == nil { - return nil, module.VersionError(mod, errors.New("parsing go.mod: missing module line")) - } - if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path { - return nil, module.VersionError(mod, fmt.Errorf(`parsing go.mod: - module declares its path as: %s - but was required as: %s`, mpath, mod.Path)) - } - if f.Go != nil { - r.versions.LoadOrStore(mod, f.Go.Version) - } - - return r.modFileToList(f), nil -} - -func (*mvsReqs) Max(v1, v2 string) string { - if v1 != "" && semver.Compare(v1, v2) == -1 { - return v2 - } - return v1 -} - -// Upgrade is a no-op, here to implement mvs.Reqs. -// The upgrade logic for go get -u is in ../modget/get.go. -func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) { - return m, nil -} - -func versions(path string) ([]string, error) { - // Note: modfetch.Lookup and repo.Versions are cached, - // so there's no need for us to add extra caching here. - var versions []string - err := modfetch.TryProxies(func(proxy string) error { - repo, err := modfetch.Lookup(proxy, path) - if err == nil { - versions, err = repo.Versions("") - } - return err - }) - return versions, err -} - -// Previous returns the tagged version of m.Path immediately prior to -// m.Version, or version "none" if no prior version is tagged. -func (*mvsReqs) Previous(m module.Version) (module.Version, error) { - list, err := versions(m.Path) - if err != nil { - return module.Version{}, err - } - i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 }) - if i > 0 { - return module.Version{Path: m.Path, Version: list[i-1]}, nil - } - return module.Version{Path: m.Path, Version: "none"}, nil -} - -// next returns the next version of m.Path after m.Version. -// It is only used by the exclusion processing in the Required method, -// not called directly by MVS. -func (*mvsReqs) next(m module.Version) (module.Version, error) { - list, err := versions(m.Path) - if err != nil { - return module.Version{}, err - } - i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 }) - if i < len(list) { - return module.Version{Path: m.Path, Version: list[i]}, nil - } - return module.Version{Path: m.Path, Version: "none"}, nil -} - -// fetch downloads the given module (or its replacement) -// and returns its location. -// -// The isLocal return value reports whether the replacement, -// if any, is local to the filesystem. -func fetch(mod module.Version) (dir string, isLocal bool, err error) { - if mod == Target { - return ModRoot(), true, nil - } - if r := Replacement(mod); r.Path != "" { - if r.Version == "" { - dir = r.Path - if !filepath.IsAbs(dir) { - dir = filepath.Join(ModRoot(), dir) - } - // Ensure that the replacement directory actually exists: - // dirInModule does not report errors for missing modules, - // so if we don't report the error now, later failures will be - // very mysterious. - if _, err := os.Stat(dir); err != nil { - if os.IsNotExist(err) { - // Semantically the module version itself “exists” — we just don't - // have its source code. Remove the equivalence to os.ErrNotExist, - // and make the message more concise while we're at it. - err = fmt.Errorf("replacement directory %s does not exist", r.Path) - } else { - err = fmt.Errorf("replacement directory %s: %w", r.Path, err) - } - return dir, true, module.VersionError(mod, err) - } - return dir, true, nil - } - mod = r - } - - dir, err = modfetch.Download(mod) - return dir, false, err -} |