github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-internal/modload/load.go (about)

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package modload
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	"go/build"
    12  	"io/ioutil"
    13  	"os"
    14  	"path"
    15  	pathpkg "path"
    16  	"path/filepath"
    17  	"sort"
    18  	"strings"
    19  	"sync"
    20  
    21  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/base"
    22  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/cfg"
    23  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/imports"
    24  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/modfetch"
    25  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/mvs"
    26  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/par"
    27  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/search"
    28  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/str"
    29  
    30  	"golang.org/x/mod/modfile"
    31  	"golang.org/x/mod/module"
    32  	"golang.org/x/mod/semver"
    33  )
    34  
    35  // buildList is the list of modules to use for building packages.
    36  // It is initialized by calling ImportPaths, ImportFromFiles,
    37  // LoadALL, or LoadBuildList, each of which uses loaded.load.
    38  //
    39  // Ideally, exactly ONE of those functions would be called,
    40  // and exactly once. Most of the time, that's true.
    41  // During "go get" it may not be. TODO(rsc): Figure out if
    42  // that restriction can be established, or else document why not.
    43  //
    44  var buildList []module.Version
    45  
    46  // loaded is the most recently-used package loader.
    47  // It holds details about individual packages.
    48  //
    49  // Note that loaded.buildList is only valid during a load operation;
    50  // afterward, it is copied back into the global buildList,
    51  // which should be used instead.
    52  var loaded *loader
    53  
    54  // ImportPaths returns the set of packages matching the args (patterns),
    55  // on the target platform. Modules may be added to the build list
    56  // to satisfy new imports.
    57  func ImportPaths(patterns []string) []*search.Match {
    58  	matches := ImportPathsQuiet(patterns, imports.Tags())
    59  	search.WarnUnmatched(matches)
    60  	return matches
    61  }
    62  
    63  // ImportPathsQuiet is like ImportPaths but does not warn about patterns with
    64  // no matches. It also lets the caller specify a set of build tags to match
    65  // packages. The build tags should typically be imports.Tags() or
    66  // imports.AnyTags(); a nil map has no special meaning.
    67  func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
    68  	var fsDirs [][]string
    69  	updateMatches := func(matches []*search.Match, iterating bool) {
    70  		for i, m := range matches {
    71  			switch {
    72  			case build.IsLocalImport(m.Pattern) || filepath.IsAbs(m.Pattern):
    73  				// Evaluate list of file system directories on first iteration.
    74  				if fsDirs == nil {
    75  					fsDirs = make([][]string, len(matches))
    76  				}
    77  				if fsDirs[i] == nil {
    78  					var dirs []string
    79  					if m.Literal {
    80  						dirs = []string{m.Pattern}
    81  					} else {
    82  						dirs = search.MatchPackagesInFS(m.Pattern).Pkgs
    83  					}
    84  					fsDirs[i] = dirs
    85  				}
    86  
    87  				// Make a copy of the directory list and translate to import paths.
    88  				// Note that whether a directory corresponds to an import path
    89  				// changes as the build list is updated, and a directory can change
    90  				// from not being in the build list to being in it and back as
    91  				// the exact version of a particular module increases during
    92  				// the loader iterations.
    93  				m.Pkgs = str.StringList(fsDirs[i])
    94  				pkgs := m.Pkgs
    95  				m.Pkgs = m.Pkgs[:0]
    96  				for _, pkg := range pkgs {
    97  					var dir string
    98  					if !filepath.IsAbs(pkg) {
    99  						dir = filepath.Join(base.Cwd, pkg)
   100  					} else {
   101  						dir = filepath.Clean(pkg)
   102  					}
   103  
   104  					// golang.org/issue/32917: We should resolve a relative path to a
   105  					// package path only if the relative path actually contains the code
   106  					// for that package.
   107  					if !dirContainsPackage(dir) {
   108  						// If we're outside of a module, ensure that the failure mode
   109  						// indicates that.
   110  						ModRoot()
   111  
   112  						// If the directory is local but does not exist, don't return it
   113  						// while loader is iterating, since this might trigger a fetch.
   114  						// After loader is done iterating, we still need to return the
   115  						// path, so that "go list -e" produces valid output.
   116  						if !iterating {
   117  							// We don't have a valid path to resolve to, so report the
   118  							// unresolved path.
   119  							m.Pkgs = append(m.Pkgs, pkg)
   120  						}
   121  						continue
   122  					}
   123  
   124  					// Note: The checks for @ here are just to avoid misinterpreting
   125  					// the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar).
   126  					// It's not strictly necessary but helpful to keep the checks.
   127  					if modRoot != "" && dir == modRoot {
   128  						pkg = targetPrefix
   129  					} else if modRoot != "" && strings.HasPrefix(dir, modRoot+string(filepath.Separator)) && !strings.Contains(dir[len(modRoot):], "@") {
   130  						suffix := filepath.ToSlash(dir[len(modRoot):])
   131  						if strings.HasPrefix(suffix, "/vendor/") {
   132  							// TODO getmode vendor check
   133  							pkg = strings.TrimPrefix(suffix, "/vendor/")
   134  						} else if targetInGorootSrc && Target.Path == "std" {
   135  							// Don't add the prefix "std/" to packages in the "std" module.
   136  							// It's the one module path that isn't a prefix of its packages.
   137  							pkg = strings.TrimPrefix(suffix, "/")
   138  							if pkg == "builtin" {
   139  								// "builtin" is a pseudo-package with a real source file.
   140  								// It's not included in "std", so it shouldn't be included in
   141  								// "./..." within module "std" either.
   142  								continue
   143  							}
   144  						} else {
   145  							modPkg := targetPrefix + suffix
   146  							if _, ok := dirInModule(modPkg, targetPrefix, modRoot, true); ok {
   147  								pkg = modPkg
   148  							} else if !iterating {
   149  								ModRoot()
   150  								base.Errorf("go: directory %s is outside main module", base.ShortPath(dir))
   151  							}
   152  						}
   153  					} else if sub := search.InDir(dir, cfg.GOROOTsrc); sub != "" && sub != "." && !strings.Contains(sub, "@") {
   154  						pkg = filepath.ToSlash(sub)
   155  					} else if path := pathInModuleCache(dir); path != "" {
   156  						pkg = path
   157  					} else {
   158  						pkg = ""
   159  						if !iterating {
   160  							ModRoot()
   161  							base.Errorf("go: directory %s outside available modules", base.ShortPath(dir))
   162  						}
   163  					}
   164  					m.Pkgs = append(m.Pkgs, pkg)
   165  				}
   166  
   167  			case strings.Contains(m.Pattern, "..."):
   168  				m.Pkgs = matchPackages(m.Pattern, loaded.tags, true, buildList)
   169  
   170  			case m.Pattern == "all":
   171  				loaded.testAll = true
   172  				if iterating {
   173  					// Enumerate the packages in the main module.
   174  					// We'll load the dependencies as we find them.
   175  					m.Pkgs = matchPackages("...", loaded.tags, false, []module.Version{Target})
   176  				} else {
   177  					// Starting with the packages in the main module,
   178  					// enumerate the full list of "all".
   179  					m.Pkgs = loaded.computePatternAll(m.Pkgs)
   180  				}
   181  
   182  			case search.IsMetaPackage(m.Pattern): // std, cmd
   183  				if len(m.Pkgs) == 0 {
   184  					m.Pkgs = search.MatchPackages(m.Pattern).Pkgs
   185  				}
   186  
   187  			default:
   188  				m.Pkgs = []string{m.Pattern}
   189  			}
   190  		}
   191  	}
   192  
   193  	InitMod()
   194  
   195  	var matches []*search.Match
   196  	for _, pattern := range search.CleanPatterns(patterns) {
   197  		matches = append(matches, &search.Match{
   198  			Pattern: pattern,
   199  			Literal: !strings.Contains(pattern, "...") && !search.IsMetaPackage(pattern),
   200  		})
   201  	}
   202  
   203  	loaded = newLoader(tags)
   204  	loaded.load(func() []string {
   205  		var roots []string
   206  		updateMatches(matches, true)
   207  		for _, m := range matches {
   208  			roots = append(roots, m.Pkgs...)
   209  		}
   210  		return roots
   211  	})
   212  
   213  	// One last pass to finalize wildcards.
   214  	updateMatches(matches, false)
   215  	checkMultiplePaths()
   216  	WriteGoMod()
   217  
   218  	return matches
   219  }
   220  
   221  // checkMultiplePaths verifies that a given module path is used as itself
   222  // or as a replacement for another module, but not both at the same time.
   223  //
   224  // (See https://golang.org/issue/26607 and https://golang.org/issue/34650.)
   225  func checkMultiplePaths() {
   226  	firstPath := make(map[module.Version]string, len(buildList))
   227  	for _, mod := range buildList {
   228  		src := mod
   229  		if rep := Replacement(mod); rep.Path != "" {
   230  			src = rep
   231  		}
   232  		if prev, ok := firstPath[src]; !ok {
   233  			firstPath[src] = mod.Path
   234  		} else if prev != mod.Path {
   235  			base.Errorf("go: %s@%s used for two different module paths (%s and %s)", src.Path, src.Version, prev, mod.Path)
   236  		}
   237  	}
   238  	base.ExitIfErrors()
   239  }
   240  
   241  // pathInModuleCache returns the import path of the directory dir,
   242  // if dir is in the module cache copy of a module in our build list.
   243  func pathInModuleCache(dir string) string {
   244  	for _, m := range buildList[1:] {
   245  		var root string
   246  		var err error
   247  		if repl := Replacement(m); repl.Path != "" && repl.Version == "" {
   248  			root = repl.Path
   249  			if !filepath.IsAbs(root) {
   250  				root = filepath.Join(ModRoot(), root)
   251  			}
   252  		} else if repl.Path != "" {
   253  			root, err = modfetch.DownloadDir(repl)
   254  		} else {
   255  			root, err = modfetch.DownloadDir(m)
   256  		}
   257  		if err != nil {
   258  			continue
   259  		}
   260  		if sub := search.InDir(dir, root); sub != "" {
   261  			sub = filepath.ToSlash(sub)
   262  			if !strings.Contains(sub, "/vendor/") && !strings.HasPrefix(sub, "vendor/") && !strings.Contains(sub, "@") {
   263  				return path.Join(m.Path, filepath.ToSlash(sub))
   264  			}
   265  		}
   266  	}
   267  	return ""
   268  }
   269  
   270  var dirContainsPackageCache sync.Map // absolute dir → bool
   271  
   272  func dirContainsPackage(dir string) bool {
   273  	isPkg, ok := dirContainsPackageCache.Load(dir)
   274  	if !ok {
   275  		_, err := cfg.BuildContext.ImportDir(dir, 0)
   276  		if err == nil {
   277  			isPkg = true
   278  		} else {
   279  			if fi, statErr := os.Stat(dir); statErr != nil || !fi.IsDir() {
   280  				// A non-directory or inaccessible directory is not a Go package.
   281  				isPkg = false
   282  			} else if _, noGo := err.(*build.NoGoError); noGo {
   283  				// A directory containing no Go source files is not a Go package.
   284  				isPkg = false
   285  			} else {
   286  				// An error other than *build.NoGoError indicates that the package exists
   287  				// but has some other problem (such as a syntax error).
   288  				isPkg = true
   289  			}
   290  		}
   291  		isPkg, _ = dirContainsPackageCache.LoadOrStore(dir, isPkg)
   292  	}
   293  	return isPkg.(bool)
   294  }
   295  
   296  // ImportFromFiles adds modules to the build list as needed
   297  // to satisfy the imports in the named Go source files.
   298  func ImportFromFiles(gofiles []string) {
   299  	InitMod()
   300  
   301  	tags := imports.Tags()
   302  	imports, testImports, err := imports.ScanFiles(gofiles, tags)
   303  	if err != nil {
   304  		base.Fatalf("go: %v", err)
   305  	}
   306  
   307  	loaded = newLoader(tags)
   308  	loaded.load(func() []string {
   309  		var roots []string
   310  		roots = append(roots, imports...)
   311  		roots = append(roots, testImports...)
   312  		return roots
   313  	})
   314  	WriteGoMod()
   315  }
   316  
   317  // DirImportPath returns the effective import path for dir,
   318  // provided it is within the main module, or else returns ".".
   319  func DirImportPath(dir string) string {
   320  	if modRoot == "" {
   321  		return "."
   322  	}
   323  
   324  	if !filepath.IsAbs(dir) {
   325  		dir = filepath.Join(base.Cwd, dir)
   326  	} else {
   327  		dir = filepath.Clean(dir)
   328  	}
   329  
   330  	if dir == modRoot {
   331  		return targetPrefix
   332  	}
   333  	if strings.HasPrefix(dir, modRoot+string(filepath.Separator)) {
   334  		suffix := filepath.ToSlash(dir[len(modRoot):])
   335  		if strings.HasPrefix(suffix, "/vendor/") {
   336  			return strings.TrimPrefix(suffix, "/vendor/")
   337  		}
   338  		return targetPrefix + suffix
   339  	}
   340  	return "."
   341  }
   342  
   343  // LoadBuildList loads and returns the build list from go.mod.
   344  // The loading of the build list happens automatically in ImportPaths:
   345  // LoadBuildList need only be called if ImportPaths is not
   346  // (typically in commands that care about the module but
   347  // no particular package).
   348  func LoadBuildList() []module.Version {
   349  	InitMod()
   350  	ReloadBuildList()
   351  	WriteGoMod()
   352  	return buildList
   353  }
   354  
   355  func ReloadBuildList() []module.Version {
   356  	loaded = newLoader(imports.Tags())
   357  	loaded.load(func() []string { return nil })
   358  	return buildList
   359  }
   360  
   361  // LoadALL returns the set of all packages in the current module
   362  // and their dependencies in any other modules, without filtering
   363  // due to build tags, except "+build ignore".
   364  // It adds modules to the build list as needed to satisfy new imports.
   365  // This set is useful for deciding whether a particular import is needed
   366  // anywhere in a module.
   367  func LoadALL() []string {
   368  	return loadAll(true)
   369  }
   370  
   371  // LoadVendor is like LoadALL but only follows test dependencies
   372  // for tests in the main module. Tests in dependency modules are
   373  // ignored completely.
   374  // This set is useful for identifying the which packages to include in a vendor directory.
   375  func LoadVendor() []string {
   376  	return loadAll(false)
   377  }
   378  
   379  func loadAll(testAll bool) []string {
   380  	InitMod()
   381  
   382  	loaded = newLoader(imports.AnyTags())
   383  	loaded.isALL = true
   384  	loaded.testAll = testAll
   385  	if !testAll {
   386  		loaded.testRoots = true
   387  	}
   388  	all := TargetPackages("...")
   389  	loaded.load(func() []string { return all })
   390  	checkMultiplePaths()
   391  	WriteGoMod()
   392  
   393  	var paths []string
   394  	for _, pkg := range loaded.pkgs {
   395  		if pkg.err != nil {
   396  			base.Errorf("%s: %v", pkg.stackText(), pkg.err)
   397  			continue
   398  		}
   399  		paths = append(paths, pkg.path)
   400  	}
   401  	base.ExitIfErrors()
   402  	return paths
   403  }
   404  
   405  // TargetPackages returns the list of packages in the target (top-level) module
   406  // matching pattern, which may be relative to the working directory, under all
   407  // build tag settings.
   408  func TargetPackages(pattern string) []string {
   409  	// TargetPackages is relative to the main module, so ensure that the main
   410  	// module is a thing that can contain packages.
   411  	ModRoot()
   412  
   413  	return matchPackages(pattern, imports.AnyTags(), false, []module.Version{Target})
   414  }
   415  
   416  // BuildList returns the module build list,
   417  // typically constructed by a previous call to
   418  // LoadBuildList or ImportPaths.
   419  // The caller must not modify the returned list.
   420  func BuildList() []module.Version {
   421  	return buildList
   422  }
   423  
   424  // SetBuildList sets the module build list.
   425  // The caller is responsible for ensuring that the list is valid.
   426  // SetBuildList does not retain a reference to the original list.
   427  func SetBuildList(list []module.Version) {
   428  	buildList = append([]module.Version{}, list...)
   429  }
   430  
   431  // TidyBuildList trims the build list to the minimal requirements needed to
   432  // retain the same versions of all packages from the preceding Load* or
   433  // ImportPaths* call.
   434  func TidyBuildList() {
   435  	used := map[module.Version]bool{Target: true}
   436  	for _, pkg := range loaded.pkgs {
   437  		used[pkg.mod] = true
   438  	}
   439  
   440  	keep := []module.Version{Target}
   441  	var direct []string
   442  	for _, m := range buildList[1:] {
   443  		if used[m] {
   444  			keep = append(keep, m)
   445  			if loaded.direct[m.Path] {
   446  				direct = append(direct, m.Path)
   447  			}
   448  		} else if cfg.BuildV {
   449  			if _, ok := index.require[m]; ok {
   450  				fmt.Fprintf(os.Stderr, "unused %s\n", m.Path)
   451  			}
   452  		}
   453  	}
   454  
   455  	min, err := mvs.Req(Target, direct, &mvsReqs{buildList: keep})
   456  	if err != nil {
   457  		base.Fatalf("go: %v", err)
   458  	}
   459  	buildList = append([]module.Version{Target}, min...)
   460  }
   461  
   462  // ImportMap returns the actual package import path
   463  // for an import path found in source code.
   464  // If the given import path does not appear in the source code
   465  // for the packages that have been loaded, ImportMap returns the empty string.
   466  func ImportMap(path string) string {
   467  	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
   468  	if !ok {
   469  		return ""
   470  	}
   471  	return pkg.path
   472  }
   473  
   474  // PackageDir returns the directory containing the source code
   475  // for the package named by the import path.
   476  func PackageDir(path string) string {
   477  	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
   478  	if !ok {
   479  		return ""
   480  	}
   481  	return pkg.dir
   482  }
   483  
   484  // PackageModule returns the module providing the package named by the import path.
   485  func PackageModule(path string) module.Version {
   486  	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
   487  	if !ok {
   488  		return module.Version{}
   489  	}
   490  	return pkg.mod
   491  }
   492  
   493  // PackageImports returns the imports for the package named by the import path.
   494  // Test imports will be returned as well if tests were loaded for the package
   495  // (i.e., if "all" was loaded or if LoadTests was set and the path was matched
   496  // by a command line argument). PackageImports will return nil for
   497  // unknown package paths.
   498  func PackageImports(path string) (imports, testImports []string) {
   499  	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
   500  	if !ok {
   501  		return nil, nil
   502  	}
   503  	imports = make([]string, len(pkg.imports))
   504  	for i, p := range pkg.imports {
   505  		imports[i] = p.path
   506  	}
   507  	if pkg.test != nil {
   508  		testImports = make([]string, len(pkg.test.imports))
   509  		for i, p := range pkg.test.imports {
   510  			testImports[i] = p.path
   511  		}
   512  	}
   513  	return imports, testImports
   514  }
   515  
   516  // ModuleUsedDirectly reports whether the main module directly imports
   517  // some package in the module with the given path.
   518  func ModuleUsedDirectly(path string) bool {
   519  	return loaded.direct[path]
   520  }
   521  
   522  // Lookup returns the source directory, import path, and any loading error for
   523  // the package at path as imported from the package in parentDir.
   524  // Lookup requires that one of the Load functions in this package has already
   525  // been called.
   526  func Lookup(parentPath string, parentIsStd bool, path string) (dir, realPath string, err error) {
   527  	if path == "" {
   528  		panic("Lookup called with empty package path")
   529  	}
   530  
   531  	if parentIsStd {
   532  		path = loaded.stdVendor(parentPath, path)
   533  	}
   534  	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
   535  	if !ok {
   536  		// The loader should have found all the relevant paths.
   537  		// There are a few exceptions, though:
   538  		//	- during go list without -test, the p.Resolve calls to process p.TestImports and p.XTestImports
   539  		//	  end up here to canonicalize the import paths.
   540  		//	- during any load, non-loaded packages like "unsafe" end up here.
   541  		//	- during any load, build-injected dependencies like "runtime/cgo" end up here.
   542  		//	- because we ignore appengine/* in the module loader,
   543  		//	  the dependencies of any actual appengine/* library end up here.
   544  		dir := findStandardImportPath(path)
   545  		if dir != "" {
   546  			return dir, path, nil
   547  		}
   548  		return "", "", errMissing
   549  	}
   550  	return pkg.dir, pkg.path, pkg.err
   551  }
   552  
   553  // A loader manages the process of loading information about
   554  // the required packages for a particular build,
   555  // checking that the packages are available in the module set,
   556  // and updating the module set if needed.
   557  // Loading is an iterative process: try to load all the needed packages,
   558  // but if imports are missing, try to resolve those imports, and repeat.
   559  //
   560  // Although most of the loading state is maintained in the loader struct,
   561  // one key piece - the build list - is a global, so that it can be modified
   562  // separate from the loading operation, such as during "go get"
   563  // upgrades/downgrades or in "go mod" operations.
   564  // TODO(rsc): It might be nice to make the loader take and return
   565  // a buildList rather than hard-coding use of the global.
   566  type loader struct {
   567  	tags           map[string]bool // tags for scanDir
   568  	testRoots      bool            // include tests for roots
   569  	isALL          bool            // created with LoadALL
   570  	testAll        bool            // include tests for all packages
   571  	forceStdVendor bool            // if true, load standard-library dependencies from the vendor subtree
   572  
   573  	// reset on each iteration
   574  	roots    []*loadPkg
   575  	pkgs     []*loadPkg
   576  	work     *par.Work  // current work queue
   577  	pkgCache *par.Cache // map from string to *loadPkg
   578  
   579  	// computed at end of iterations
   580  	direct    map[string]bool   // imported directly by main module
   581  	goVersion map[string]string // go version recorded in each module
   582  }
   583  
   584  // LoadTests controls whether the loaders load tests of the root packages.
   585  var LoadTests bool
   586  
   587  func newLoader(tags map[string]bool) *loader {
   588  	ld := new(loader)
   589  	ld.tags = tags
   590  	ld.testRoots = LoadTests
   591  
   592  	// Inside the "std" and "cmd" modules, we prefer to use the vendor directory
   593  	// unless the command explicitly changes the module graph.
   594  	if !targetInGorootSrc || (cfg.CmdName != "get" && !strings.HasPrefix(cfg.CmdName, "mod ")) {
   595  		ld.forceStdVendor = true
   596  	}
   597  
   598  	return ld
   599  }
   600  
   601  func (ld *loader) reset() {
   602  	ld.roots = nil
   603  	ld.pkgs = nil
   604  	ld.work = new(par.Work)
   605  	ld.pkgCache = new(par.Cache)
   606  }
   607  
   608  // A loadPkg records information about a single loaded package.
   609  type loadPkg struct {
   610  	path        string         // import path
   611  	mod         module.Version // module providing package
   612  	dir         string         // directory containing source code
   613  	imports     []*loadPkg     // packages imported by this one
   614  	err         error          // error loading package
   615  	stack       *loadPkg       // package importing this one in minimal import stack for this pkg
   616  	test        *loadPkg       // package with test imports, if we need test
   617  	testOf      *loadPkg
   618  	testImports []string // test-only imports, saved for use by pkg.test.
   619  }
   620  
   621  var errMissing = errors.New("cannot find package")
   622  
   623  // load attempts to load the build graph needed to process a set of root packages.
   624  // The set of root packages is defined by the addRoots function,
   625  // which must call add(path) with the import path of each root package.
   626  func (ld *loader) load(roots func() []string) {
   627  	var err error
   628  	reqs := Reqs()
   629  	buildList, err = mvs.BuildList(Target, reqs)
   630  	if err != nil {
   631  		base.Fatalf("go: %v", err)
   632  	}
   633  
   634  	added := make(map[string]bool)
   635  	for {
   636  		ld.reset()
   637  		if roots != nil {
   638  			// Note: the returned roots can change on each iteration,
   639  			// since the expansion of package patterns depends on the
   640  			// build list we're using.
   641  			for _, path := range roots() {
   642  				ld.work.Add(ld.pkg(path, true))
   643  			}
   644  		}
   645  		ld.work.Do(10, ld.doPkg)
   646  		ld.buildStacks()
   647  		numAdded := 0
   648  		haveMod := make(map[module.Version]bool)
   649  		for _, m := range buildList {
   650  			haveMod[m] = true
   651  		}
   652  		modAddedBy := make(map[module.Version]*loadPkg)
   653  		for _, pkg := range ld.pkgs {
   654  			if err, ok := pkg.err.(*ImportMissingError); ok && err.Module.Path != "" {
   655  				if err.newMissingVersion != "" {
   656  					base.Fatalf("go: %s: package provided by %s at latest version %s but not at required version %s", pkg.stackText(), err.Module.Path, err.Module.Version, err.newMissingVersion)
   657  				}
   658  				if added[pkg.path] {
   659  					base.Fatalf("go: %s: looping trying to add package", pkg.stackText())
   660  				}
   661  				added[pkg.path] = true
   662  				numAdded++
   663  				if !haveMod[err.Module] {
   664  					fmt.Fprintf(os.Stderr, "go: found %s in %s %s\n", pkg.path, err.Module.Path, err.Module.Version)
   665  					haveMod[err.Module] = true
   666  					modAddedBy[err.Module] = pkg
   667  					buildList = append(buildList, err.Module)
   668  				}
   669  				continue
   670  			}
   671  			// Leave other errors for Import or load.Packages to report.
   672  		}
   673  		base.ExitIfErrors()
   674  		if numAdded == 0 {
   675  			break
   676  		}
   677  
   678  		// Recompute buildList with all our additions.
   679  		reqs = Reqs()
   680  		buildList, err = mvs.BuildList(Target, reqs)
   681  		if err != nil {
   682  			// If an error was found in a newly added module, report the package
   683  			// import stack instead of the module requirement stack. Packages
   684  			// are more descriptive.
   685  			if err, ok := err.(*mvs.BuildListError); ok {
   686  				if pkg := modAddedBy[err.Module()]; pkg != nil {
   687  					base.Fatalf("go: %s: %v", pkg.stackText(), err.Err)
   688  				}
   689  			}
   690  			base.Fatalf("go: %v", err)
   691  		}
   692  	}
   693  	base.ExitIfErrors()
   694  
   695  	// Compute directly referenced dependency modules.
   696  	ld.direct = make(map[string]bool)
   697  	for _, pkg := range ld.pkgs {
   698  		if pkg.mod == Target {
   699  			for _, dep := range pkg.imports {
   700  				if dep.mod.Path != "" {
   701  					ld.direct[dep.mod.Path] = true
   702  				}
   703  			}
   704  		}
   705  	}
   706  
   707  	// Add Go versions, computed during walk.
   708  	ld.goVersion = make(map[string]string)
   709  	for _, m := range buildList {
   710  		v, _ := reqs.(*mvsReqs).versions.Load(m)
   711  		ld.goVersion[m.Path], _ = v.(string)
   712  	}
   713  
   714  	// Mix in direct markings (really, lack of indirect markings)
   715  	// from go.mod, unless we scanned the whole module
   716  	// and can therefore be sure we know better than go.mod.
   717  	if !ld.isALL && modFile != nil {
   718  		for _, r := range modFile.Require {
   719  			if !r.Indirect {
   720  				ld.direct[r.Mod.Path] = true
   721  			}
   722  		}
   723  	}
   724  }
   725  
   726  // pkg returns the *loadPkg for path, creating and queuing it if needed.
   727  // If the package should be tested, its test is created but not queued
   728  // (the test is queued after processing pkg).
   729  // If isRoot is true, the pkg is being queued as one of the roots of the work graph.
   730  func (ld *loader) pkg(path string, isRoot bool) *loadPkg {
   731  	return ld.pkgCache.Do(path, func() interface{} {
   732  		pkg := &loadPkg{
   733  			path: path,
   734  		}
   735  		if ld.testRoots && isRoot || ld.testAll {
   736  			test := &loadPkg{
   737  				path:   path,
   738  				testOf: pkg,
   739  			}
   740  			pkg.test = test
   741  		}
   742  		if isRoot {
   743  			ld.roots = append(ld.roots, pkg)
   744  		}
   745  		ld.work.Add(pkg)
   746  		return pkg
   747  	}).(*loadPkg)
   748  }
   749  
   750  // doPkg processes a package on the work queue.
   751  func (ld *loader) doPkg(item interface{}) {
   752  	// TODO: what about replacements?
   753  	pkg := item.(*loadPkg)
   754  	var imports []string
   755  	if pkg.testOf != nil {
   756  		pkg.dir = pkg.testOf.dir
   757  		pkg.mod = pkg.testOf.mod
   758  		imports = pkg.testOf.testImports
   759  	} else {
   760  		if strings.Contains(pkg.path, "@") {
   761  			// Leave for error during load.
   762  			return
   763  		}
   764  		if build.IsLocalImport(pkg.path) {
   765  			// Leave for error during load.
   766  			// (Module mode does not allow local imports.)
   767  			return
   768  		}
   769  
   770  		pkg.mod, pkg.dir, pkg.err = Import(pkg.path)
   771  		if pkg.dir == "" {
   772  			return
   773  		}
   774  		var testImports []string
   775  		var err error
   776  		imports, testImports, err = scanDir(pkg.dir, ld.tags)
   777  		if err != nil {
   778  			pkg.err = err
   779  			return
   780  		}
   781  		if pkg.test != nil {
   782  			pkg.testImports = testImports
   783  		}
   784  	}
   785  
   786  	inStd := (search.IsStandardImportPath(pkg.path) && search.InDir(pkg.dir, cfg.GOROOTsrc) != "")
   787  	for _, path := range imports {
   788  		if inStd {
   789  			path = ld.stdVendor(pkg.path, path)
   790  		}
   791  		pkg.imports = append(pkg.imports, ld.pkg(path, false))
   792  	}
   793  
   794  	// Now that pkg.dir, pkg.mod, pkg.testImports are set, we can queue pkg.test.
   795  	// TODO: All that's left is creating new imports. Why not just do it now?
   796  	if pkg.test != nil {
   797  		ld.work.Add(pkg.test)
   798  	}
   799  }
   800  
   801  // stdVendor returns the canonical import path for the package with the given
   802  // path when imported from the standard-library package at parentPath.
   803  func (ld *loader) stdVendor(parentPath, path string) string {
   804  	if search.IsStandardImportPath(path) {
   805  		return path
   806  	}
   807  
   808  	if str.HasPathPrefix(parentPath, "cmd") {
   809  		if ld.forceStdVendor || Target.Path != "cmd" {
   810  			vendorPath := pathpkg.Join("cmd", "vendor", path)
   811  			if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil {
   812  				return vendorPath
   813  			}
   814  		}
   815  	} else if ld.forceStdVendor || Target.Path != "std" {
   816  		vendorPath := pathpkg.Join("vendor", path)
   817  		if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil {
   818  			return vendorPath
   819  		}
   820  	}
   821  
   822  	// Not vendored: resolve from modules.
   823  	return path
   824  }
   825  
   826  // computePatternAll returns the list of packages matching pattern "all",
   827  // starting with a list of the import paths for the packages in the main module.
   828  func (ld *loader) computePatternAll(paths []string) []string {
   829  	seen := make(map[*loadPkg]bool)
   830  	var all []string
   831  	var walk func(*loadPkg)
   832  	walk = func(pkg *loadPkg) {
   833  		if seen[pkg] {
   834  			return
   835  		}
   836  		seen[pkg] = true
   837  		if pkg.testOf == nil {
   838  			all = append(all, pkg.path)
   839  		}
   840  		for _, p := range pkg.imports {
   841  			walk(p)
   842  		}
   843  		if p := pkg.test; p != nil {
   844  			walk(p)
   845  		}
   846  	}
   847  	for _, path := range paths {
   848  		walk(ld.pkg(path, false))
   849  	}
   850  	sort.Strings(all)
   851  
   852  	return all
   853  }
   854  
   855  // scanDir is like imports.ScanDir but elides known magic imports from the list,
   856  // so that we do not go looking for packages that don't really exist.
   857  //
   858  // The standard magic import is "C", for cgo.
   859  //
   860  // The only other known magic imports are appengine and appengine/*.
   861  // These are so old that they predate "go get" and did not use URL-like paths.
   862  // Most code today now uses google.golang.org/appengine instead,
   863  // but not all code has been so updated. When we mostly ignore build tags
   864  // during "go vendor", we look into "// +build appengine" files and
   865  // may see these legacy imports. We drop them so that the module
   866  // search does not look for modules to try to satisfy them.
   867  func scanDir(dir string, tags map[string]bool) (imports_, testImports []string, err error) {
   868  	imports_, testImports, err = imports.ScanDir(dir, tags)
   869  
   870  	filter := func(x []string) []string {
   871  		w := 0
   872  		for _, pkg := range x {
   873  			if pkg != "C" && pkg != "appengine" && !strings.HasPrefix(pkg, "appengine/") &&
   874  				pkg != "appengine_internal" && !strings.HasPrefix(pkg, "appengine_internal/") {
   875  				x[w] = pkg
   876  				w++
   877  			}
   878  		}
   879  		return x[:w]
   880  	}
   881  
   882  	return filter(imports_), filter(testImports), err
   883  }
   884  
   885  // buildStacks computes minimal import stacks for each package,
   886  // for use in error messages. When it completes, packages that
   887  // are part of the original root set have pkg.stack == nil,
   888  // and other packages have pkg.stack pointing at the next
   889  // package up the import stack in their minimal chain.
   890  // As a side effect, buildStacks also constructs ld.pkgs,
   891  // the list of all packages loaded.
   892  func (ld *loader) buildStacks() {
   893  	if len(ld.pkgs) > 0 {
   894  		panic("buildStacks")
   895  	}
   896  	for _, pkg := range ld.roots {
   897  		pkg.stack = pkg // sentinel to avoid processing in next loop
   898  		ld.pkgs = append(ld.pkgs, pkg)
   899  	}
   900  	for i := 0; i < len(ld.pkgs); i++ { // not range: appending to ld.pkgs in loop
   901  		pkg := ld.pkgs[i]
   902  		for _, next := range pkg.imports {
   903  			if next.stack == nil {
   904  				next.stack = pkg
   905  				ld.pkgs = append(ld.pkgs, next)
   906  			}
   907  		}
   908  		if next := pkg.test; next != nil && next.stack == nil {
   909  			next.stack = pkg
   910  			ld.pkgs = append(ld.pkgs, next)
   911  		}
   912  	}
   913  	for _, pkg := range ld.roots {
   914  		pkg.stack = nil
   915  	}
   916  }
   917  
   918  // stackText builds the import stack text to use when
   919  // reporting an error in pkg. It has the general form
   920  //
   921  //	root imports
   922  //		other imports
   923  //		other2 tested by
   924  //		other2.test imports
   925  //		pkg
   926  //
   927  func (pkg *loadPkg) stackText() string {
   928  	var stack []*loadPkg
   929  	for p := pkg; p != nil; p = p.stack {
   930  		stack = append(stack, p)
   931  	}
   932  
   933  	var buf bytes.Buffer
   934  	for i := len(stack) - 1; i >= 0; i-- {
   935  		p := stack[i]
   936  		fmt.Fprint(&buf, p.path)
   937  		if p.testOf != nil {
   938  			fmt.Fprint(&buf, ".test")
   939  		}
   940  		if i > 0 {
   941  			if stack[i-1].testOf == p {
   942  				fmt.Fprint(&buf, " tested by\n\t")
   943  			} else {
   944  				fmt.Fprint(&buf, " imports\n\t")
   945  			}
   946  		}
   947  	}
   948  	return buf.String()
   949  }
   950  
   951  // why returns the text to use in "go mod why" output about the given package.
   952  // It is less ornate than the stackText but contains the same information.
   953  func (pkg *loadPkg) why() string {
   954  	var buf strings.Builder
   955  	var stack []*loadPkg
   956  	for p := pkg; p != nil; p = p.stack {
   957  		stack = append(stack, p)
   958  	}
   959  
   960  	for i := len(stack) - 1; i >= 0; i-- {
   961  		p := stack[i]
   962  		if p.testOf != nil {
   963  			fmt.Fprintf(&buf, "%s.test\n", p.testOf.path)
   964  		} else {
   965  			fmt.Fprintf(&buf, "%s\n", p.path)
   966  		}
   967  	}
   968  	return buf.String()
   969  }
   970  
   971  // Why returns the "go mod why" output stanza for the given package,
   972  // without the leading # comment.
   973  // The package graph must have been loaded already, usually by LoadALL.
   974  // If there is no reason for the package to be in the current build,
   975  // Why returns an empty string.
   976  func Why(path string) string {
   977  	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
   978  	if !ok {
   979  		return ""
   980  	}
   981  	return pkg.why()
   982  }
   983  
   984  // WhyDepth returns the number of steps in the Why listing.
   985  // If there is no reason for the package to be in the current build,
   986  // WhyDepth returns 0.
   987  func WhyDepth(path string) int {
   988  	n := 0
   989  	pkg, _ := loaded.pkgCache.Get(path).(*loadPkg)
   990  	for p := pkg; p != nil; p = p.stack {
   991  		n++
   992  	}
   993  	return n
   994  }
   995  
   996  // Replacement returns the replacement for mod, if any, from go.mod.
   997  // If there is no replacement for mod, Replacement returns
   998  // a module.Version with Path == "".
   999  func Replacement(mod module.Version) module.Version {
  1000  	if index != nil {
  1001  		if r, ok := index.replace[mod]; ok {
  1002  			return r
  1003  		}
  1004  		if r, ok := index.replace[module.Version{Path: mod.Path}]; ok {
  1005  			return r
  1006  		}
  1007  	}
  1008  	return module.Version{}
  1009  }
  1010  
  1011  // mvsReqs implements mvs.Reqs for module semantic versions,
  1012  // with any exclusions or replacements applied internally.
  1013  type mvsReqs struct {
  1014  	buildList []module.Version
  1015  	cache     par.Cache
  1016  	versions  sync.Map
  1017  }
  1018  
  1019  // Reqs returns the current module requirement graph.
  1020  // Future calls to SetBuildList do not affect the operation
  1021  // of the returned Reqs.
  1022  func Reqs() mvs.Reqs {
  1023  	r := &mvsReqs{
  1024  		buildList: buildList,
  1025  	}
  1026  	return r
  1027  }
  1028  
  1029  func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) {
  1030  	type cached struct {
  1031  		list []module.Version
  1032  		err  error
  1033  	}
  1034  
  1035  	c := r.cache.Do(mod, func() interface{} {
  1036  		list, err := r.required(mod)
  1037  		if err != nil {
  1038  			return cached{nil, err}
  1039  		}
  1040  		for i, mv := range list {
  1041  			if index != nil {
  1042  				for index.exclude[mv] {
  1043  					mv1, err := r.next(mv)
  1044  					if err != nil {
  1045  						return cached{nil, err}
  1046  					}
  1047  					if mv1.Version == "none" {
  1048  						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)}
  1049  					}
  1050  					mv = mv1
  1051  				}
  1052  			}
  1053  			list[i] = mv
  1054  		}
  1055  
  1056  		return cached{list, nil}
  1057  	}).(cached)
  1058  
  1059  	return c.list, c.err
  1060  }
  1061  
  1062  var vendorOnce sync.Once
  1063  
  1064  type vendorMetadata struct {
  1065  	Explicit    bool
  1066  	Replacement module.Version
  1067  }
  1068  
  1069  var (
  1070  	vendorList      []module.Version          // modules that contribute packages to the build, in order of appearance
  1071  	vendorReplaced  []module.Version          // all replaced modules; may or may not also contribute packages
  1072  	vendorVersion   map[string]string         // module path → selected version (if known)
  1073  	vendorPkgModule map[string]module.Version // package → containing module
  1074  	vendorMeta      map[module.Version]vendorMetadata
  1075  )
  1076  
  1077  // readVendorList reads the list of vendored modules from vendor/modules.txt.
  1078  func readVendorList() {
  1079  	vendorOnce.Do(func() {
  1080  		vendorList = nil
  1081  		vendorPkgModule = make(map[string]module.Version)
  1082  		vendorVersion = make(map[string]string)
  1083  		vendorMeta = make(map[module.Version]vendorMetadata)
  1084  		data, err := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt"))
  1085  		if err != nil {
  1086  			if !errors.Is(err, os.ErrNotExist) {
  1087  				base.Fatalf("go: %s", err)
  1088  			}
  1089  			return
  1090  		}
  1091  
  1092  		var mod module.Version
  1093  		for _, line := range strings.Split(string(data), "\n") {
  1094  			if strings.HasPrefix(line, "# ") {
  1095  				f := strings.Fields(line)
  1096  
  1097  				if len(f) < 3 {
  1098  					continue
  1099  				}
  1100  				if semver.IsValid(f[2]) {
  1101  					// A module, but we don't yet know whether it is in the build list or
  1102  					// only included to indicate a replacement.
  1103  					mod = module.Version{Path: f[1], Version: f[2]}
  1104  					f = f[3:]
  1105  				} else if f[2] == "=>" {
  1106  					// A wildcard replacement found in the main module's go.mod file.
  1107  					mod = module.Version{Path: f[1]}
  1108  					f = f[2:]
  1109  				} else {
  1110  					// Not a version or a wildcard replacement.
  1111  					// We don't know how to interpret this module line, so ignore it.
  1112  					mod = module.Version{}
  1113  					continue
  1114  				}
  1115  
  1116  				if len(f) >= 2 && f[0] == "=>" {
  1117  					meta := vendorMeta[mod]
  1118  					if len(f) == 2 {
  1119  						// File replacement.
  1120  						meta.Replacement = module.Version{Path: f[1]}
  1121  						vendorReplaced = append(vendorReplaced, mod)
  1122  					} else if len(f) == 3 && semver.IsValid(f[2]) {
  1123  						// Path and version replacement.
  1124  						meta.Replacement = module.Version{Path: f[1], Version: f[2]}
  1125  						vendorReplaced = append(vendorReplaced, mod)
  1126  					} else {
  1127  						// We don't understand this replacement. Ignore it.
  1128  					}
  1129  					vendorMeta[mod] = meta
  1130  				}
  1131  				continue
  1132  			}
  1133  
  1134  			// Not a module line. Must be a package within a module or a metadata
  1135  			// directive, either of which requires a preceding module line.
  1136  			if mod.Path == "" {
  1137  				continue
  1138  			}
  1139  
  1140  			if strings.HasPrefix(line, "## ") {
  1141  				// Metadata. Take the union of annotations across multiple lines, if present.
  1142  				meta := vendorMeta[mod]
  1143  				for _, entry := range strings.Split(strings.TrimPrefix(line, "## "), ";") {
  1144  					entry = strings.TrimSpace(entry)
  1145  					if entry == "explicit" {
  1146  						meta.Explicit = true
  1147  					}
  1148  					// All other tokens are reserved for future use.
  1149  				}
  1150  				vendorMeta[mod] = meta
  1151  				continue
  1152  			}
  1153  
  1154  			if f := strings.Fields(line); len(f) == 1 && module.CheckImportPath(f[0]) == nil {
  1155  				// A package within the current module.
  1156  				vendorPkgModule[f[0]] = mod
  1157  
  1158  				// Since this module provides a package for the build, we know that it
  1159  				// is in the build list and is the selected version of its path.
  1160  				// If this information is new, record it.
  1161  				if v, ok := vendorVersion[mod.Path]; !ok || semver.Compare(v, mod.Version) < 0 {
  1162  					vendorList = append(vendorList, mod)
  1163  					vendorVersion[mod.Path] = mod.Version
  1164  				}
  1165  			}
  1166  		}
  1167  	})
  1168  }
  1169  
  1170  func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version {
  1171  	list := make([]module.Version, 0, len(f.Require))
  1172  	for _, r := range f.Require {
  1173  		list = append(list, r.Mod)
  1174  	}
  1175  	return list
  1176  }
  1177  
  1178  // required returns a unique copy of the requirements of mod.
  1179  func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
  1180  	if mod == Target {
  1181  		if modFile != nil && modFile.Go != nil {
  1182  			r.versions.LoadOrStore(mod, modFile.Go.Version)
  1183  		}
  1184  		return append([]module.Version(nil), r.buildList[1:]...), nil
  1185  	}
  1186  
  1187  	if cfg.BuildMod == "vendor" {
  1188  		// For every module other than the target,
  1189  		// return the full list of modules from modules.txt.
  1190  		readVendorList()
  1191  		return append([]module.Version(nil), vendorList...), nil
  1192  	}
  1193  
  1194  	origPath := mod.Path
  1195  	if repl := Replacement(mod); repl.Path != "" {
  1196  		if repl.Version == "" {
  1197  			// TODO: need to slip the new version into the tags list etc.
  1198  			dir := repl.Path
  1199  			if !filepath.IsAbs(dir) {
  1200  				dir = filepath.Join(ModRoot(), dir)
  1201  			}
  1202  			gomod := filepath.Join(dir, "go.mod")
  1203  			data, err := ioutil.ReadFile(gomod)
  1204  			if err != nil {
  1205  				return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err)
  1206  			}
  1207  			f, err := modfile.ParseLax(gomod, data, nil)
  1208  			if err != nil {
  1209  				return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err)
  1210  			}
  1211  			if f.Go != nil {
  1212  				r.versions.LoadOrStore(mod, f.Go.Version)
  1213  			}
  1214  			return r.modFileToList(f), nil
  1215  		}
  1216  		mod = repl
  1217  	}
  1218  
  1219  	if mod.Version == "none" {
  1220  		return nil, nil
  1221  	}
  1222  
  1223  	if !semver.IsValid(mod.Version) {
  1224  		// Disallow the broader queries supported by fetch.Lookup.
  1225  		base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", mod.Path, mod.Version)
  1226  	}
  1227  
  1228  	data, err := modfetch.GoMod(mod.Path, mod.Version)
  1229  	if err != nil {
  1230  		return nil, err
  1231  	}
  1232  	f, err := modfile.ParseLax("go.mod", data, nil)
  1233  	if err != nil {
  1234  		return nil, module.VersionError(mod, fmt.Errorf("parsing go.mod: %v", err))
  1235  	}
  1236  
  1237  	if f.Module == nil {
  1238  		return nil, module.VersionError(mod, errors.New("parsing go.mod: missing module line"))
  1239  	}
  1240  	if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path {
  1241  		return nil, module.VersionError(mod, fmt.Errorf(`parsing go.mod:
  1242  	module declares its path as: %s
  1243  	        but was required as: %s`, mpath, mod.Path))
  1244  	}
  1245  	if f.Go != nil {
  1246  		r.versions.LoadOrStore(mod, f.Go.Version)
  1247  	}
  1248  
  1249  	return r.modFileToList(f), nil
  1250  }
  1251  
  1252  func (*mvsReqs) Max(v1, v2 string) string {
  1253  	if v1 != "" && semver.Compare(v1, v2) == -1 {
  1254  		return v2
  1255  	}
  1256  	return v1
  1257  }
  1258  
  1259  // Upgrade is a no-op, here to implement mvs.Reqs.
  1260  // The upgrade logic for go get -u is in ../modget/get.go.
  1261  func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) {
  1262  	return m, nil
  1263  }
  1264  
  1265  func versions(path string) ([]string, error) {
  1266  	// Note: modfetch.Lookup and repo.Versions are cached,
  1267  	// so there's no need for us to add extra caching here.
  1268  	var versions []string
  1269  	err := modfetch.TryProxies(func(proxy string) error {
  1270  		repo, err := modfetch.Lookup(proxy, path)
  1271  		if err == nil {
  1272  			versions, err = repo.Versions("")
  1273  		}
  1274  		return err
  1275  	})
  1276  	return versions, err
  1277  }
  1278  
  1279  // Previous returns the tagged version of m.Path immediately prior to
  1280  // m.Version, or version "none" if no prior version is tagged.
  1281  func (*mvsReqs) Previous(m module.Version) (module.Version, error) {
  1282  	list, err := versions(m.Path)
  1283  	if err != nil {
  1284  		return module.Version{}, err
  1285  	}
  1286  	i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 })
  1287  	if i > 0 {
  1288  		return module.Version{Path: m.Path, Version: list[i-1]}, nil
  1289  	}
  1290  	return module.Version{Path: m.Path, Version: "none"}, nil
  1291  }
  1292  
  1293  // next returns the next version of m.Path after m.Version.
  1294  // It is only used by the exclusion processing in the Required method,
  1295  // not called directly by MVS.
  1296  func (*mvsReqs) next(m module.Version) (module.Version, error) {
  1297  	list, err := versions(m.Path)
  1298  	if err != nil {
  1299  		return module.Version{}, err
  1300  	}
  1301  	i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 })
  1302  	if i < len(list) {
  1303  		return module.Version{Path: m.Path, Version: list[i]}, nil
  1304  	}
  1305  	return module.Version{Path: m.Path, Version: "none"}, nil
  1306  }
  1307  
  1308  // fetch downloads the given module (or its replacement)
  1309  // and returns its location.
  1310  //
  1311  // The isLocal return value reports whether the replacement,
  1312  // if any, is local to the filesystem.
  1313  func fetch(mod module.Version) (dir string, isLocal bool, err error) {
  1314  	if mod == Target {
  1315  		return ModRoot(), true, nil
  1316  	}
  1317  	if r := Replacement(mod); r.Path != "" {
  1318  		if r.Version == "" {
  1319  			dir = r.Path
  1320  			if !filepath.IsAbs(dir) {
  1321  				dir = filepath.Join(ModRoot(), dir)
  1322  			}
  1323  			// Ensure that the replacement directory actually exists:
  1324  			// dirInModule does not report errors for missing modules,
  1325  			// so if we don't report the error now, later failures will be
  1326  			// very mysterious.
  1327  			if _, err := os.Stat(dir); err != nil {
  1328  				if os.IsNotExist(err) {
  1329  					// Semantically the module version itself “exists” — we just don't
  1330  					// have its source code. Remove the equivalence to os.ErrNotExist,
  1331  					// and make the message more concise while we're at it.
  1332  					err = fmt.Errorf("replacement directory %s does not exist", r.Path)
  1333  				} else {
  1334  					err = fmt.Errorf("replacement directory %s: %w", r.Path, err)
  1335  				}
  1336  				return dir, true, module.VersionError(mod, err)
  1337  			}
  1338  			return dir, true, nil
  1339  		}
  1340  		mod = r
  1341  	}
  1342  
  1343  	dir, err = modfetch.Download(mod)
  1344  	return dir, false, err
  1345  }