github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/cmd/go/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  	"path/filepath"
    16  	"sort"
    17  	"strings"
    18  	"sync"
    19  
    20  	"cmd/go/internal/base"
    21  	"cmd/go/internal/cfg"
    22  	"cmd/go/internal/imports"
    23  	"cmd/go/internal/modfetch"
    24  	"cmd/go/internal/modfile"
    25  	"cmd/go/internal/module"
    26  	"cmd/go/internal/mvs"
    27  	"cmd/go/internal/par"
    28  	"cmd/go/internal/search"
    29  	"cmd/go/internal/semver"
    30  	"cmd/go/internal/str"
    31  )
    32  
    33  // buildList is the list of modules to use for building packages.
    34  // It is initialized by calling ImportPaths, ImportFromFiles,
    35  // LoadALL, or LoadBuildList, each of which uses loaded.load.
    36  //
    37  // Ideally, exactly ONE of those functions would be called,
    38  // and exactly once. Most of the time, that's true.
    39  // During "go get" it may not be. TODO(rsc): Figure out if
    40  // that restriction can be established, or else document why not.
    41  //
    42  var buildList []module.Version
    43  
    44  // loaded is the most recently-used package loader.
    45  // It holds details about individual packages.
    46  //
    47  // Note that loaded.buildList is only valid during a load operation;
    48  // afterward, it is copied back into the global buildList,
    49  // which should be used instead.
    50  var loaded *loader
    51  
    52  // ImportPaths returns the set of packages matching the args (patterns),
    53  // adding modules to the build list as needed to satisfy new imports.
    54  func ImportPaths(patterns []string) []*search.Match {
    55  	InitMod()
    56  
    57  	var matches []*search.Match
    58  	for _, pattern := range search.CleanPatterns(patterns) {
    59  		m := &search.Match{
    60  			Pattern: pattern,
    61  			Literal: !strings.Contains(pattern, "...") && !search.IsMetaPackage(pattern),
    62  		}
    63  		if m.Literal {
    64  			m.Pkgs = []string{pattern}
    65  		}
    66  		matches = append(matches, m)
    67  	}
    68  
    69  	fsDirs := make([][]string, len(matches))
    70  	loaded = newLoader()
    71  	updateMatches := func(iterating bool) {
    72  		for i, m := range matches {
    73  			switch {
    74  			case build.IsLocalImport(m.Pattern) || filepath.IsAbs(m.Pattern):
    75  				// Evaluate list of file system directories on first iteration.
    76  				if fsDirs[i] == nil {
    77  					var dirs []string
    78  					if m.Literal {
    79  						dirs = []string{m.Pattern}
    80  					} else {
    81  						dirs = search.MatchPackagesInFS(m.Pattern).Pkgs
    82  					}
    83  					fsDirs[i] = dirs
    84  				}
    85  
    86  				// Make a copy of the directory list and translate to import paths.
    87  				// Note that whether a directory corresponds to an import path
    88  				// changes as the build list is updated, and a directory can change
    89  				// from not being in the build list to being in it and back as
    90  				// the exact version of a particular module increases during
    91  				// the loader iterations.
    92  				m.Pkgs = str.StringList(fsDirs[i])
    93  				for j, pkg := range m.Pkgs {
    94  					dir := pkg
    95  					if !filepath.IsAbs(dir) {
    96  						dir = filepath.Join(cwd, pkg)
    97  					} else {
    98  						dir = filepath.Clean(dir)
    99  					}
   100  
   101  					// Note: The checks for @ here are just to avoid misinterpreting
   102  					// the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar).
   103  					// It's not strictly necessary but helpful to keep the checks.
   104  					if modRoot != "" && dir == modRoot {
   105  						pkg = Target.Path
   106  					} else if modRoot != "" && strings.HasPrefix(dir, modRoot+string(filepath.Separator)) && !strings.Contains(dir[len(modRoot):], "@") {
   107  						suffix := filepath.ToSlash(dir[len(modRoot):])
   108  						if strings.HasPrefix(suffix, "/vendor/") {
   109  							// TODO getmode vendor check
   110  							pkg = strings.TrimPrefix(suffix, "/vendor/")
   111  						} else {
   112  							pkg = Target.Path + suffix
   113  						}
   114  					} else if sub := search.InDir(dir, cfg.GOROOTsrc); sub != "" && !strings.Contains(sub, "@") {
   115  						pkg = filepath.ToSlash(sub)
   116  					} else if path := pathInModuleCache(dir); path != "" {
   117  						pkg = path
   118  					} else {
   119  						pkg = ""
   120  						if !iterating {
   121  							ModRoot()
   122  							base.Errorf("go: directory %s outside available modules", base.ShortPath(dir))
   123  						}
   124  					}
   125  					info, err := os.Stat(dir)
   126  					if err != nil || !info.IsDir() {
   127  						// If the directory is local but does not exist, don't return it
   128  						// while loader is iterating, since this would trigger a fetch.
   129  						// After loader is done iterating, we still need to return the
   130  						// path, so that "go list -e" produces valid output.
   131  						if iterating {
   132  							pkg = ""
   133  						}
   134  					}
   135  					m.Pkgs[j] = pkg
   136  				}
   137  
   138  			case strings.Contains(m.Pattern, "..."):
   139  				m.Pkgs = matchPackages(m.Pattern, loaded.tags, true, buildList)
   140  
   141  			case m.Pattern == "all":
   142  				loaded.testAll = true
   143  				if iterating {
   144  					// Enumerate the packages in the main module.
   145  					// We'll load the dependencies as we find them.
   146  					m.Pkgs = matchPackages("...", loaded.tags, false, []module.Version{Target})
   147  				} else {
   148  					// Starting with the packages in the main module,
   149  					// enumerate the full list of "all".
   150  					m.Pkgs = loaded.computePatternAll(m.Pkgs)
   151  				}
   152  
   153  			case search.IsMetaPackage(m.Pattern): // std, cmd
   154  				if len(m.Pkgs) == 0 {
   155  					m.Pkgs = search.MatchPackages(m.Pattern).Pkgs
   156  				}
   157  			}
   158  		}
   159  	}
   160  
   161  	loaded.load(func() []string {
   162  		var roots []string
   163  		updateMatches(true)
   164  		for _, m := range matches {
   165  			for _, pkg := range m.Pkgs {
   166  				if pkg != "" {
   167  					roots = append(roots, pkg)
   168  				}
   169  			}
   170  		}
   171  		return roots
   172  	})
   173  
   174  	// One last pass to finalize wildcards.
   175  	updateMatches(false)
   176  
   177  	// A given module path may be used as itself or as a replacement for another
   178  	// module, but not both at the same time. Otherwise, the aliasing behavior is
   179  	// too subtle (see https://golang.org/issue/26607), and we don't want to
   180  	// commit to a specific behavior at this point.
   181  	firstPath := make(map[module.Version]string, len(buildList))
   182  	for _, mod := range buildList {
   183  		src := mod
   184  		if rep := Replacement(mod); rep.Path != "" {
   185  			src = rep
   186  		}
   187  		if prev, ok := firstPath[src]; !ok {
   188  			firstPath[src] = mod.Path
   189  		} else if prev != mod.Path {
   190  			base.Errorf("go: %s@%s used for two different module paths (%s and %s)", src.Path, src.Version, prev, mod.Path)
   191  		}
   192  	}
   193  	base.ExitIfErrors()
   194  	WriteGoMod()
   195  
   196  	search.WarnUnmatched(matches)
   197  	return matches
   198  }
   199  
   200  // pathInModuleCache returns the import path of the directory dir,
   201  // if dir is in the module cache copy of a module in our build list.
   202  func pathInModuleCache(dir string) string {
   203  	for _, m := range buildList[1:] {
   204  		root, err := modfetch.DownloadDir(m)
   205  		if err != nil {
   206  			continue
   207  		}
   208  		if sub := search.InDir(dir, root); sub != "" {
   209  			sub = filepath.ToSlash(sub)
   210  			if !strings.Contains(sub, "/vendor/") && !strings.HasPrefix(sub, "vendor/") && !strings.Contains(sub, "@") {
   211  				return path.Join(m.Path, filepath.ToSlash(sub))
   212  			}
   213  		}
   214  	}
   215  	return ""
   216  }
   217  
   218  // warnPattern returns list, the result of matching pattern,
   219  // but if list is empty then first it prints a warning about
   220  // the pattern not matching any packages.
   221  func warnPattern(pattern string, list []string) []string {
   222  	if len(list) == 0 {
   223  		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
   224  	}
   225  	return list
   226  }
   227  
   228  // ImportFromFiles adds modules to the build list as needed
   229  // to satisfy the imports in the named Go source files.
   230  func ImportFromFiles(gofiles []string) {
   231  	InitMod()
   232  
   233  	imports, testImports, err := imports.ScanFiles(gofiles, imports.Tags())
   234  	if err != nil {
   235  		base.Fatalf("go: %v", err)
   236  	}
   237  
   238  	loaded = newLoader()
   239  	loaded.load(func() []string {
   240  		var roots []string
   241  		roots = append(roots, imports...)
   242  		roots = append(roots, testImports...)
   243  		return roots
   244  	})
   245  	WriteGoMod()
   246  }
   247  
   248  // DirImportPath returns the effective import path for dir,
   249  // provided it is within the main module, or else returns ".".
   250  func DirImportPath(dir string) string {
   251  	if modRoot == "" {
   252  		return "."
   253  	}
   254  
   255  	if !filepath.IsAbs(dir) {
   256  		dir = filepath.Join(cwd, dir)
   257  	} else {
   258  		dir = filepath.Clean(dir)
   259  	}
   260  
   261  	if dir == modRoot {
   262  		return Target.Path
   263  	}
   264  	if strings.HasPrefix(dir, modRoot+string(filepath.Separator)) {
   265  		suffix := filepath.ToSlash(dir[len(modRoot):])
   266  		if strings.HasPrefix(suffix, "/vendor/") {
   267  			return strings.TrimPrefix(suffix, "/vendor/")
   268  		}
   269  		return Target.Path + suffix
   270  	}
   271  	return "."
   272  }
   273  
   274  // LoadBuildList loads and returns the build list from go.mod.
   275  // The loading of the build list happens automatically in ImportPaths:
   276  // LoadBuildList need only be called if ImportPaths is not
   277  // (typically in commands that care about the module but
   278  // no particular package).
   279  func LoadBuildList() []module.Version {
   280  	InitMod()
   281  	ReloadBuildList()
   282  	WriteGoMod()
   283  	return buildList
   284  }
   285  
   286  func ReloadBuildList() []module.Version {
   287  	loaded = newLoader()
   288  	loaded.load(func() []string { return nil })
   289  	return buildList
   290  }
   291  
   292  // LoadALL returns the set of all packages in the current module
   293  // and their dependencies in any other modules, without filtering
   294  // due to build tags, except "+build ignore".
   295  // It adds modules to the build list as needed to satisfy new imports.
   296  // This set is useful for deciding whether a particular import is needed
   297  // anywhere in a module.
   298  func LoadALL() []string {
   299  	return loadAll(true)
   300  }
   301  
   302  // LoadVendor is like LoadALL but only follows test dependencies
   303  // for tests in the main module. Tests in dependency modules are
   304  // ignored completely.
   305  // This set is useful for identifying the which packages to include in a vendor directory.
   306  func LoadVendor() []string {
   307  	return loadAll(false)
   308  }
   309  
   310  func loadAll(testAll bool) []string {
   311  	InitMod()
   312  
   313  	loaded = newLoader()
   314  	loaded.isALL = true
   315  	loaded.tags = anyTags
   316  	loaded.testAll = testAll
   317  	if !testAll {
   318  		loaded.testRoots = true
   319  	}
   320  	all := TargetPackages()
   321  	loaded.load(func() []string { return all })
   322  	WriteGoMod()
   323  
   324  	var paths []string
   325  	for _, pkg := range loaded.pkgs {
   326  		if e, ok := pkg.err.(*ImportMissingError); ok && e.Module.Path == "" {
   327  			continue // Package doesn't actually exist.
   328  		}
   329  		paths = append(paths, pkg.path)
   330  	}
   331  	return paths
   332  }
   333  
   334  // anyTags is a special tags map that satisfies nearly all build tag expressions.
   335  // Only "ignore" and malformed build tag requirements are considered false.
   336  var anyTags = map[string]bool{"*": true}
   337  
   338  // TargetPackages returns the list of packages in the target (top-level) module,
   339  // under all build tag settings.
   340  func TargetPackages() []string {
   341  	return matchPackages("...", anyTags, false, []module.Version{Target})
   342  }
   343  
   344  // BuildList returns the module build list,
   345  // typically constructed by a previous call to
   346  // LoadBuildList or ImportPaths.
   347  // The caller must not modify the returned list.
   348  func BuildList() []module.Version {
   349  	return buildList
   350  }
   351  
   352  // SetBuildList sets the module build list.
   353  // The caller is responsible for ensuring that the list is valid.
   354  // SetBuildList does not retain a reference to the original list.
   355  func SetBuildList(list []module.Version) {
   356  	buildList = append([]module.Version{}, list...)
   357  }
   358  
   359  // ImportMap returns the actual package import path
   360  // for an import path found in source code.
   361  // If the given import path does not appear in the source code
   362  // for the packages that have been loaded, ImportMap returns the empty string.
   363  func ImportMap(path string) string {
   364  	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
   365  	if !ok {
   366  		return ""
   367  	}
   368  	return pkg.path
   369  }
   370  
   371  // PackageDir returns the directory containing the source code
   372  // for the package named by the import path.
   373  func PackageDir(path string) string {
   374  	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
   375  	if !ok {
   376  		return ""
   377  	}
   378  	return pkg.dir
   379  }
   380  
   381  // PackageModule returns the module providing the package named by the import path.
   382  func PackageModule(path string) module.Version {
   383  	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
   384  	if !ok {
   385  		return module.Version{}
   386  	}
   387  	return pkg.mod
   388  }
   389  
   390  // ModuleUsedDirectly reports whether the main module directly imports
   391  // some package in the module with the given path.
   392  func ModuleUsedDirectly(path string) bool {
   393  	return loaded.direct[path]
   394  }
   395  
   396  // Lookup returns the source directory, import path, and any loading error for
   397  // the package at path.
   398  // Lookup requires that one of the Load functions in this package has already
   399  // been called.
   400  func Lookup(path string) (dir, realPath string, err error) {
   401  	if path == "" {
   402  		panic("Lookup called with empty package path")
   403  	}
   404  	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
   405  	if !ok {
   406  		// The loader should have found all the relevant paths.
   407  		// There are a few exceptions, though:
   408  		//	- during go list without -test, the p.Resolve calls to process p.TestImports and p.XTestImports
   409  		//	  end up here to canonicalize the import paths.
   410  		//	- during any load, non-loaded packages like "unsafe" end up here.
   411  		//	- during any load, build-injected dependencies like "runtime/cgo" end up here.
   412  		//	- because we ignore appengine/* in the module loader,
   413  		//	  the dependencies of any actual appengine/* library end up here.
   414  		dir := findStandardImportPath(path)
   415  		if dir != "" {
   416  			return dir, path, nil
   417  		}
   418  		return "", "", errMissing
   419  	}
   420  	return pkg.dir, pkg.path, pkg.err
   421  }
   422  
   423  // A loader manages the process of loading information about
   424  // the required packages for a particular build,
   425  // checking that the packages are available in the module set,
   426  // and updating the module set if needed.
   427  // Loading is an iterative process: try to load all the needed packages,
   428  // but if imports are missing, try to resolve those imports, and repeat.
   429  //
   430  // Although most of the loading state is maintained in the loader struct,
   431  // one key piece - the build list - is a global, so that it can be modified
   432  // separate from the loading operation, such as during "go get"
   433  // upgrades/downgrades or in "go mod" operations.
   434  // TODO(rsc): It might be nice to make the loader take and return
   435  // a buildList rather than hard-coding use of the global.
   436  type loader struct {
   437  	tags      map[string]bool // tags for scanDir
   438  	testRoots bool            // include tests for roots
   439  	isALL     bool            // created with LoadALL
   440  	testAll   bool            // include tests for all packages
   441  
   442  	// reset on each iteration
   443  	roots    []*loadPkg
   444  	pkgs     []*loadPkg
   445  	work     *par.Work  // current work queue
   446  	pkgCache *par.Cache // map from string to *loadPkg
   447  
   448  	// computed at end of iterations
   449  	direct    map[string]bool   // imported directly by main module
   450  	goVersion map[string]string // go version recorded in each module
   451  }
   452  
   453  // LoadTests controls whether the loaders load tests of the root packages.
   454  var LoadTests bool
   455  
   456  func newLoader() *loader {
   457  	ld := new(loader)
   458  	ld.tags = imports.Tags()
   459  	ld.testRoots = LoadTests
   460  	return ld
   461  }
   462  
   463  func (ld *loader) reset() {
   464  	ld.roots = nil
   465  	ld.pkgs = nil
   466  	ld.work = new(par.Work)
   467  	ld.pkgCache = new(par.Cache)
   468  }
   469  
   470  // A loadPkg records information about a single loaded package.
   471  type loadPkg struct {
   472  	path        string         // import path
   473  	mod         module.Version // module providing package
   474  	dir         string         // directory containing source code
   475  	imports     []*loadPkg     // packages imported by this one
   476  	err         error          // error loading package
   477  	stack       *loadPkg       // package importing this one in minimal import stack for this pkg
   478  	test        *loadPkg       // package with test imports, if we need test
   479  	testOf      *loadPkg
   480  	testImports []string // test-only imports, saved for use by pkg.test.
   481  }
   482  
   483  var errMissing = errors.New("cannot find package")
   484  
   485  // load attempts to load the build graph needed to process a set of root packages.
   486  // The set of root packages is defined by the addRoots function,
   487  // which must call add(path) with the import path of each root package.
   488  func (ld *loader) load(roots func() []string) {
   489  	var err error
   490  	reqs := Reqs()
   491  	buildList, err = mvs.BuildList(Target, reqs)
   492  	if err != nil {
   493  		base.Fatalf("go: %v", err)
   494  	}
   495  
   496  	added := make(map[string]bool)
   497  	for {
   498  		ld.reset()
   499  		if roots != nil {
   500  			// Note: the returned roots can change on each iteration,
   501  			// since the expansion of package patterns depends on the
   502  			// build list we're using.
   503  			for _, path := range roots() {
   504  				ld.work.Add(ld.pkg(path, true))
   505  			}
   506  		}
   507  		ld.work.Do(10, ld.doPkg)
   508  		ld.buildStacks()
   509  		numAdded := 0
   510  		haveMod := make(map[module.Version]bool)
   511  		for _, m := range buildList {
   512  			haveMod[m] = true
   513  		}
   514  		for _, pkg := range ld.pkgs {
   515  			if err, ok := pkg.err.(*ImportMissingError); ok && err.Module.Path != "" {
   516  				if added[pkg.path] {
   517  					base.Fatalf("go: %s: looping trying to add package", pkg.stackText())
   518  				}
   519  				added[pkg.path] = true
   520  				numAdded++
   521  				if !haveMod[err.Module] {
   522  					haveMod[err.Module] = true
   523  					buildList = append(buildList, err.Module)
   524  				}
   525  				continue
   526  			}
   527  			// Leave other errors for Import or load.Packages to report.
   528  		}
   529  		base.ExitIfErrors()
   530  		if numAdded == 0 {
   531  			break
   532  		}
   533  
   534  		// Recompute buildList with all our additions.
   535  		reqs = Reqs()
   536  		buildList, err = mvs.BuildList(Target, reqs)
   537  		if err != nil {
   538  			base.Fatalf("go: %v", err)
   539  		}
   540  	}
   541  	base.ExitIfErrors()
   542  
   543  	// Compute directly referenced dependency modules.
   544  	ld.direct = make(map[string]bool)
   545  	for _, pkg := range ld.pkgs {
   546  		if pkg.mod == Target {
   547  			for _, dep := range pkg.imports {
   548  				if dep.mod.Path != "" {
   549  					ld.direct[dep.mod.Path] = true
   550  				}
   551  			}
   552  		}
   553  	}
   554  
   555  	// Add Go versions, computed during walk.
   556  	ld.goVersion = make(map[string]string)
   557  	for _, m := range buildList {
   558  		v, _ := reqs.(*mvsReqs).versions.Load(m)
   559  		ld.goVersion[m.Path], _ = v.(string)
   560  	}
   561  
   562  	// Mix in direct markings (really, lack of indirect markings)
   563  	// from go.mod, unless we scanned the whole module
   564  	// and can therefore be sure we know better than go.mod.
   565  	if !ld.isALL && modFile != nil {
   566  		for _, r := range modFile.Require {
   567  			if !r.Indirect {
   568  				ld.direct[r.Mod.Path] = true
   569  			}
   570  		}
   571  	}
   572  }
   573  
   574  // pkg returns the *loadPkg for path, creating and queuing it if needed.
   575  // If the package should be tested, its test is created but not queued
   576  // (the test is queued after processing pkg).
   577  // If isRoot is true, the pkg is being queued as one of the roots of the work graph.
   578  func (ld *loader) pkg(path string, isRoot bool) *loadPkg {
   579  	return ld.pkgCache.Do(path, func() interface{} {
   580  		pkg := &loadPkg{
   581  			path: path,
   582  		}
   583  		if ld.testRoots && isRoot || ld.testAll {
   584  			test := &loadPkg{
   585  				path:   path,
   586  				testOf: pkg,
   587  			}
   588  			pkg.test = test
   589  		}
   590  		if isRoot {
   591  			ld.roots = append(ld.roots, pkg)
   592  		}
   593  		ld.work.Add(pkg)
   594  		return pkg
   595  	}).(*loadPkg)
   596  }
   597  
   598  // doPkg processes a package on the work queue.
   599  func (ld *loader) doPkg(item interface{}) {
   600  	// TODO: what about replacements?
   601  	pkg := item.(*loadPkg)
   602  	var imports []string
   603  	if pkg.testOf != nil {
   604  		pkg.dir = pkg.testOf.dir
   605  		pkg.mod = pkg.testOf.mod
   606  		imports = pkg.testOf.testImports
   607  	} else {
   608  		if strings.Contains(pkg.path, "@") {
   609  			// Leave for error during load.
   610  			return
   611  		}
   612  		if build.IsLocalImport(pkg.path) {
   613  			// Leave for error during load.
   614  			// (Module mode does not allow local imports.)
   615  			return
   616  		}
   617  
   618  		pkg.mod, pkg.dir, pkg.err = Import(pkg.path)
   619  		if pkg.dir == "" {
   620  			return
   621  		}
   622  		var testImports []string
   623  		var err error
   624  		imports, testImports, err = scanDir(pkg.dir, ld.tags)
   625  		if err != nil {
   626  			pkg.err = err
   627  			return
   628  		}
   629  		if pkg.test != nil {
   630  			pkg.testImports = testImports
   631  		}
   632  	}
   633  
   634  	for _, path := range imports {
   635  		pkg.imports = append(pkg.imports, ld.pkg(path, false))
   636  	}
   637  
   638  	// Now that pkg.dir, pkg.mod, pkg.testImports are set, we can queue pkg.test.
   639  	// TODO: All that's left is creating new imports. Why not just do it now?
   640  	if pkg.test != nil {
   641  		ld.work.Add(pkg.test)
   642  	}
   643  }
   644  
   645  // computePatternAll returns the list of packages matching pattern "all",
   646  // starting with a list of the import paths for the packages in the main module.
   647  func (ld *loader) computePatternAll(paths []string) []string {
   648  	seen := make(map[*loadPkg]bool)
   649  	var all []string
   650  	var walk func(*loadPkg)
   651  	walk = func(pkg *loadPkg) {
   652  		if seen[pkg] {
   653  			return
   654  		}
   655  		seen[pkg] = true
   656  		if pkg.testOf == nil {
   657  			all = append(all, pkg.path)
   658  		}
   659  		for _, p := range pkg.imports {
   660  			walk(p)
   661  		}
   662  		if p := pkg.test; p != nil {
   663  			walk(p)
   664  		}
   665  	}
   666  	for _, path := range paths {
   667  		walk(ld.pkg(path, false))
   668  	}
   669  	sort.Strings(all)
   670  
   671  	return all
   672  }
   673  
   674  // scanDir is like imports.ScanDir but elides known magic imports from the list,
   675  // so that we do not go looking for packages that don't really exist.
   676  //
   677  // The standard magic import is "C", for cgo.
   678  //
   679  // The only other known magic imports are appengine and appengine/*.
   680  // These are so old that they predate "go get" and did not use URL-like paths.
   681  // Most code today now uses google.golang.org/appengine instead,
   682  // but not all code has been so updated. When we mostly ignore build tags
   683  // during "go vendor", we look into "// +build appengine" files and
   684  // may see these legacy imports. We drop them so that the module
   685  // search does not look for modules to try to satisfy them.
   686  func scanDir(dir string, tags map[string]bool) (imports_, testImports []string, err error) {
   687  	imports_, testImports, err = imports.ScanDir(dir, tags)
   688  
   689  	filter := func(x []string) []string {
   690  		w := 0
   691  		for _, pkg := range x {
   692  			if pkg != "C" && pkg != "appengine" && !strings.HasPrefix(pkg, "appengine/") &&
   693  				pkg != "appengine_internal" && !strings.HasPrefix(pkg, "appengine_internal/") {
   694  				x[w] = pkg
   695  				w++
   696  			}
   697  		}
   698  		return x[:w]
   699  	}
   700  
   701  	return filter(imports_), filter(testImports), err
   702  }
   703  
   704  // buildStacks computes minimal import stacks for each package,
   705  // for use in error messages. When it completes, packages that
   706  // are part of the original root set have pkg.stack == nil,
   707  // and other packages have pkg.stack pointing at the next
   708  // package up the import stack in their minimal chain.
   709  // As a side effect, buildStacks also constructs ld.pkgs,
   710  // the list of all packages loaded.
   711  func (ld *loader) buildStacks() {
   712  	if len(ld.pkgs) > 0 {
   713  		panic("buildStacks")
   714  	}
   715  	for _, pkg := range ld.roots {
   716  		pkg.stack = pkg // sentinel to avoid processing in next loop
   717  		ld.pkgs = append(ld.pkgs, pkg)
   718  	}
   719  	for i := 0; i < len(ld.pkgs); i++ { // not range: appending to ld.pkgs in loop
   720  		pkg := ld.pkgs[i]
   721  		for _, next := range pkg.imports {
   722  			if next.stack == nil {
   723  				next.stack = pkg
   724  				ld.pkgs = append(ld.pkgs, next)
   725  			}
   726  		}
   727  		if next := pkg.test; next != nil && next.stack == nil {
   728  			next.stack = pkg
   729  			ld.pkgs = append(ld.pkgs, next)
   730  		}
   731  	}
   732  	for _, pkg := range ld.roots {
   733  		pkg.stack = nil
   734  	}
   735  }
   736  
   737  // stackText builds the import stack text to use when
   738  // reporting an error in pkg. It has the general form
   739  //
   740  //	import root ->
   741  //		import other ->
   742  //		import other2 ->
   743  //		import pkg
   744  //
   745  func (pkg *loadPkg) stackText() string {
   746  	var stack []*loadPkg
   747  	for p := pkg.stack; p != nil; p = p.stack {
   748  		stack = append(stack, p)
   749  	}
   750  
   751  	var buf bytes.Buffer
   752  	for i := len(stack) - 1; i >= 0; i-- {
   753  		p := stack[i]
   754  		if p.testOf != nil {
   755  			fmt.Fprintf(&buf, "test ->\n\t")
   756  		} else {
   757  			fmt.Fprintf(&buf, "import %q ->\n\t", p.path)
   758  		}
   759  	}
   760  	fmt.Fprintf(&buf, "import %q", pkg.path)
   761  	return buf.String()
   762  }
   763  
   764  // why returns the text to use in "go mod why" output about the given package.
   765  // It is less ornate than the stackText but contains the same information.
   766  func (pkg *loadPkg) why() string {
   767  	var buf strings.Builder
   768  	var stack []*loadPkg
   769  	for p := pkg; p != nil; p = p.stack {
   770  		stack = append(stack, p)
   771  	}
   772  
   773  	for i := len(stack) - 1; i >= 0; i-- {
   774  		p := stack[i]
   775  		if p.testOf != nil {
   776  			fmt.Fprintf(&buf, "%s.test\n", p.testOf.path)
   777  		} else {
   778  			fmt.Fprintf(&buf, "%s\n", p.path)
   779  		}
   780  	}
   781  	return buf.String()
   782  }
   783  
   784  // Why returns the "go mod why" output stanza for the given package,
   785  // without the leading # comment.
   786  // The package graph must have been loaded already, usually by LoadALL.
   787  // If there is no reason for the package to be in the current build,
   788  // Why returns an empty string.
   789  func Why(path string) string {
   790  	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
   791  	if !ok {
   792  		return ""
   793  	}
   794  	return pkg.why()
   795  }
   796  
   797  // WhyDepth returns the number of steps in the Why listing.
   798  // If there is no reason for the package to be in the current build,
   799  // WhyDepth returns 0.
   800  func WhyDepth(path string) int {
   801  	n := 0
   802  	pkg, _ := loaded.pkgCache.Get(path).(*loadPkg)
   803  	for p := pkg; p != nil; p = p.stack {
   804  		n++
   805  	}
   806  	return n
   807  }
   808  
   809  // Replacement returns the replacement for mod, if any, from go.mod.
   810  // If there is no replacement for mod, Replacement returns
   811  // a module.Version with Path == "".
   812  func Replacement(mod module.Version) module.Version {
   813  	if modFile == nil {
   814  		// Happens during testing and if invoking 'go get' or 'go list' outside a module.
   815  		return module.Version{}
   816  	}
   817  
   818  	var found *modfile.Replace
   819  	for _, r := range modFile.Replace {
   820  		if r.Old.Path == mod.Path && (r.Old.Version == "" || r.Old.Version == mod.Version) {
   821  			found = r // keep going
   822  		}
   823  	}
   824  	if found == nil {
   825  		return module.Version{}
   826  	}
   827  	return found.New
   828  }
   829  
   830  // mvsReqs implements mvs.Reqs for module semantic versions,
   831  // with any exclusions or replacements applied internally.
   832  type mvsReqs struct {
   833  	buildList []module.Version
   834  	cache     par.Cache
   835  	versions  sync.Map
   836  }
   837  
   838  // Reqs returns the current module requirement graph.
   839  // Future calls to SetBuildList do not affect the operation
   840  // of the returned Reqs.
   841  func Reqs() mvs.Reqs {
   842  	r := &mvsReqs{
   843  		buildList: buildList,
   844  	}
   845  	return r
   846  }
   847  
   848  func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) {
   849  	type cached struct {
   850  		list []module.Version
   851  		err  error
   852  	}
   853  
   854  	c := r.cache.Do(mod, func() interface{} {
   855  		list, err := r.required(mod)
   856  		if err != nil {
   857  			return cached{nil, err}
   858  		}
   859  		for i, mv := range list {
   860  			for excluded[mv] {
   861  				mv1, err := r.next(mv)
   862  				if err != nil {
   863  					return cached{nil, err}
   864  				}
   865  				if mv1.Version == "none" {
   866  					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)}
   867  				}
   868  				mv = mv1
   869  			}
   870  			list[i] = mv
   871  		}
   872  
   873  		return cached{list, nil}
   874  	}).(cached)
   875  
   876  	return c.list, c.err
   877  }
   878  
   879  var vendorOnce sync.Once
   880  
   881  var (
   882  	vendorList []module.Version
   883  	vendorMap  map[string]module.Version
   884  )
   885  
   886  // readVendorList reads the list of vendored modules from vendor/modules.txt.
   887  func readVendorList() {
   888  	vendorOnce.Do(func() {
   889  		vendorList = nil
   890  		vendorMap = make(map[string]module.Version)
   891  		data, _ := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt"))
   892  		var m module.Version
   893  		for _, line := range strings.Split(string(data), "\n") {
   894  			if strings.HasPrefix(line, "# ") {
   895  				f := strings.Fields(line)
   896  				m = module.Version{}
   897  				if len(f) == 3 && semver.IsValid(f[2]) {
   898  					m = module.Version{Path: f[1], Version: f[2]}
   899  					vendorList = append(vendorList, m)
   900  				}
   901  			} else if m.Path != "" {
   902  				f := strings.Fields(line)
   903  				if len(f) == 1 {
   904  					vendorMap[f[0]] = m
   905  				}
   906  			}
   907  		}
   908  	})
   909  }
   910  
   911  func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version {
   912  	var list []module.Version
   913  	for _, r := range f.Require {
   914  		list = append(list, r.Mod)
   915  	}
   916  	return list
   917  }
   918  
   919  func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
   920  	if mod == Target {
   921  		if modFile != nil && modFile.Go != nil {
   922  			r.versions.LoadOrStore(mod, modFile.Go.Version)
   923  		}
   924  		var list []module.Version
   925  		return append(list, r.buildList[1:]...), nil
   926  	}
   927  
   928  	if cfg.BuildMod == "vendor" {
   929  		// For every module other than the target,
   930  		// return the full list of modules from modules.txt.
   931  		readVendorList()
   932  		return vendorList, nil
   933  	}
   934  
   935  	origPath := mod.Path
   936  	if repl := Replacement(mod); repl.Path != "" {
   937  		if repl.Version == "" {
   938  			// TODO: need to slip the new version into the tags list etc.
   939  			dir := repl.Path
   940  			if !filepath.IsAbs(dir) {
   941  				dir = filepath.Join(ModRoot(), dir)
   942  			}
   943  			gomod := filepath.Join(dir, "go.mod")
   944  			data, err := ioutil.ReadFile(gomod)
   945  			if err != nil {
   946  				base.Errorf("go: parsing %s: %v", base.ShortPath(gomod), err)
   947  				return nil, ErrRequire
   948  			}
   949  			f, err := modfile.ParseLax(gomod, data, nil)
   950  			if err != nil {
   951  				base.Errorf("go: parsing %s: %v", base.ShortPath(gomod), err)
   952  				return nil, ErrRequire
   953  			}
   954  			if f.Go != nil {
   955  				r.versions.LoadOrStore(mod, f.Go.Version)
   956  			}
   957  			return r.modFileToList(f), nil
   958  		}
   959  		mod = repl
   960  	}
   961  
   962  	if mod.Version == "none" {
   963  		return nil, nil
   964  	}
   965  
   966  	if !semver.IsValid(mod.Version) {
   967  		// Disallow the broader queries supported by fetch.Lookup.
   968  		base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", mod.Path, mod.Version)
   969  	}
   970  
   971  	data, err := modfetch.GoMod(mod.Path, mod.Version)
   972  	if err != nil {
   973  		base.Errorf("go: %s@%s: %v\n", mod.Path, mod.Version, err)
   974  		return nil, ErrRequire
   975  	}
   976  	f, err := modfile.ParseLax("go.mod", data, nil)
   977  	if err != nil {
   978  		base.Errorf("go: %s@%s: parsing go.mod: %v", mod.Path, mod.Version, err)
   979  		return nil, ErrRequire
   980  	}
   981  
   982  	if f.Module == nil {
   983  		base.Errorf("go: %s@%s: parsing go.mod: missing module line", mod.Path, mod.Version)
   984  		return nil, ErrRequire
   985  	}
   986  	if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path {
   987  		base.Errorf("go: %s@%s: parsing go.mod: unexpected module path %q", mod.Path, mod.Version, mpath)
   988  		return nil, ErrRequire
   989  	}
   990  	if f.Go != nil {
   991  		r.versions.LoadOrStore(mod, f.Go.Version)
   992  	}
   993  
   994  	return r.modFileToList(f), nil
   995  }
   996  
   997  // ErrRequire is the sentinel error returned when Require encounters problems.
   998  // It prints the problems directly to standard error, so that multiple errors
   999  // can be displayed easily.
  1000  var ErrRequire = errors.New("error loading module requirements")
  1001  
  1002  func (*mvsReqs) Max(v1, v2 string) string {
  1003  	if v1 != "" && semver.Compare(v1, v2) == -1 {
  1004  		return v2
  1005  	}
  1006  	return v1
  1007  }
  1008  
  1009  // Upgrade is a no-op, here to implement mvs.Reqs.
  1010  // The upgrade logic for go get -u is in ../modget/get.go.
  1011  func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) {
  1012  	return m, nil
  1013  }
  1014  
  1015  func versions(path string) ([]string, error) {
  1016  	// Note: modfetch.Lookup and repo.Versions are cached,
  1017  	// so there's no need for us to add extra caching here.
  1018  	repo, err := modfetch.Lookup(path)
  1019  	if err != nil {
  1020  		return nil, err
  1021  	}
  1022  	return repo.Versions("")
  1023  }
  1024  
  1025  // Previous returns the tagged version of m.Path immediately prior to
  1026  // m.Version, or version "none" if no prior version is tagged.
  1027  func (*mvsReqs) Previous(m module.Version) (module.Version, error) {
  1028  	list, err := versions(m.Path)
  1029  	if err != nil {
  1030  		return module.Version{}, err
  1031  	}
  1032  	i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 })
  1033  	if i > 0 {
  1034  		return module.Version{Path: m.Path, Version: list[i-1]}, nil
  1035  	}
  1036  	return module.Version{Path: m.Path, Version: "none"}, nil
  1037  }
  1038  
  1039  // next returns the next version of m.Path after m.Version.
  1040  // It is only used by the exclusion processing in the Required method,
  1041  // not called directly by MVS.
  1042  func (*mvsReqs) next(m module.Version) (module.Version, error) {
  1043  	list, err := versions(m.Path)
  1044  	if err != nil {
  1045  		return module.Version{}, err
  1046  	}
  1047  	i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 })
  1048  	if i < len(list) {
  1049  		return module.Version{Path: m.Path, Version: list[i]}, nil
  1050  	}
  1051  	return module.Version{Path: m.Path, Version: "none"}, nil
  1052  }
  1053  
  1054  func fetch(mod module.Version) (dir string, isLocal bool, err error) {
  1055  	if mod == Target {
  1056  		return ModRoot(), true, nil
  1057  	}
  1058  	if r := Replacement(mod); r.Path != "" {
  1059  		if r.Version == "" {
  1060  			dir = r.Path
  1061  			if !filepath.IsAbs(dir) {
  1062  				dir = filepath.Join(ModRoot(), dir)
  1063  			}
  1064  			return dir, true, nil
  1065  		}
  1066  		mod = r
  1067  	}
  1068  
  1069  	dir, err = modfetch.Download(mod)
  1070  	return dir, false, err
  1071  }