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