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
5package modload
6
7import (
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//
42var 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.
50var 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.
54func 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.
202func 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.
221func 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.
230func 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 ".".
250func 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).
279func LoadBuildList() []module.Version {
280	InitMod()
281	ReloadBuildList()
282	WriteGoMod()
283	return buildList
284}
285
286func 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.
298func 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.
306func LoadVendor() []string {
307	return loadAll(false)
308}
309
310func 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.
336var 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.
340func 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.
348func 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.
355func 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.
363func 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.
373func 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.
382func 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.
392func 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.
400func 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.
436type 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.
454var LoadTests bool
455
456func newLoader() *loader {
457	ld := new(loader)
458	ld.tags = imports.Tags()
459	ld.testRoots = LoadTests
460	return ld
461}
462
463func (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.
471type 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
483var 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.
488func (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.
578func (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.
599func (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		if cfg.BuildContext.Compiler == "gccgo" && pkg.mod.Path == "" {
623			return
624		}
625
626		var testImports []string
627		var err error
628		imports, testImports, err = scanDir(pkg.dir, ld.tags)
629		if err != nil {
630			pkg.err = err
631			return
632		}
633		if pkg.test != nil {
634			pkg.testImports = testImports
635		}
636	}
637
638	for _, path := range imports {
639		pkg.imports = append(pkg.imports, ld.pkg(path, false))
640	}
641
642	// Now that pkg.dir, pkg.mod, pkg.testImports are set, we can queue pkg.test.
643	// TODO: All that's left is creating new imports. Why not just do it now?
644	if pkg.test != nil {
645		ld.work.Add(pkg.test)
646	}
647}
648
649// computePatternAll returns the list of packages matching pattern "all",
650// starting with a list of the import paths for the packages in the main module.
651func (ld *loader) computePatternAll(paths []string) []string {
652	seen := make(map[*loadPkg]bool)
653	var all []string
654	var walk func(*loadPkg)
655	walk = func(pkg *loadPkg) {
656		if seen[pkg] {
657			return
658		}
659		seen[pkg] = true
660		if pkg.testOf == nil {
661			all = append(all, pkg.path)
662		}
663		for _, p := range pkg.imports {
664			walk(p)
665		}
666		if p := pkg.test; p != nil {
667			walk(p)
668		}
669	}
670	for _, path := range paths {
671		walk(ld.pkg(path, false))
672	}
673	sort.Strings(all)
674
675	return all
676}
677
678// scanDir is like imports.ScanDir but elides known magic imports from the list,
679// so that we do not go looking for packages that don't really exist.
680//
681// The standard magic import is "C", for cgo.
682//
683// The only other known magic imports are appengine and appengine/*.
684// These are so old that they predate "go get" and did not use URL-like paths.
685// Most code today now uses google.golang.org/appengine instead,
686// but not all code has been so updated. When we mostly ignore build tags
687// during "go vendor", we look into "// +build appengine" files and
688// may see these legacy imports. We drop them so that the module
689// search does not look for modules to try to satisfy them.
690func scanDir(dir string, tags map[string]bool) (imports_, testImports []string, err error) {
691	imports_, testImports, err = imports.ScanDir(dir, tags)
692
693	filter := func(x []string) []string {
694		w := 0
695		for _, pkg := range x {
696			if pkg != "C" && pkg != "appengine" && !strings.HasPrefix(pkg, "appengine/") &&
697				pkg != "appengine_internal" && !strings.HasPrefix(pkg, "appengine_internal/") {
698				x[w] = pkg
699				w++
700			}
701		}
702		return x[:w]
703	}
704
705	return filter(imports_), filter(testImports), err
706}
707
708// buildStacks computes minimal import stacks for each package,
709// for use in error messages. When it completes, packages that
710// are part of the original root set have pkg.stack == nil,
711// and other packages have pkg.stack pointing at the next
712// package up the import stack in their minimal chain.
713// As a side effect, buildStacks also constructs ld.pkgs,
714// the list of all packages loaded.
715func (ld *loader) buildStacks() {
716	if len(ld.pkgs) > 0 {
717		panic("buildStacks")
718	}
719	for _, pkg := range ld.roots {
720		pkg.stack = pkg // sentinel to avoid processing in next loop
721		ld.pkgs = append(ld.pkgs, pkg)
722	}
723	for i := 0; i < len(ld.pkgs); i++ { // not range: appending to ld.pkgs in loop
724		pkg := ld.pkgs[i]
725		for _, next := range pkg.imports {
726			if next.stack == nil {
727				next.stack = pkg
728				ld.pkgs = append(ld.pkgs, next)
729			}
730		}
731		if next := pkg.test; next != nil && next.stack == nil {
732			next.stack = pkg
733			ld.pkgs = append(ld.pkgs, next)
734		}
735	}
736	for _, pkg := range ld.roots {
737		pkg.stack = nil
738	}
739}
740
741// stackText builds the import stack text to use when
742// reporting an error in pkg. It has the general form
743//
744//	import root ->
745//		import other ->
746//		import other2 ->
747//		import pkg
748//
749func (pkg *loadPkg) stackText() string {
750	var stack []*loadPkg
751	for p := pkg.stack; p != nil; p = p.stack {
752		stack = append(stack, p)
753	}
754
755	var buf bytes.Buffer
756	for i := len(stack) - 1; i >= 0; i-- {
757		p := stack[i]
758		if p.testOf != nil {
759			fmt.Fprintf(&buf, "test ->\n\t")
760		} else {
761			fmt.Fprintf(&buf, "import %q ->\n\t", p.path)
762		}
763	}
764	fmt.Fprintf(&buf, "import %q", pkg.path)
765	return buf.String()
766}
767
768// why returns the text to use in "go mod why" output about the given package.
769// It is less ornate than the stackText but contains the same information.
770func (pkg *loadPkg) why() string {
771	var buf strings.Builder
772	var stack []*loadPkg
773	for p := pkg; p != nil; p = p.stack {
774		stack = append(stack, p)
775	}
776
777	for i := len(stack) - 1; i >= 0; i-- {
778		p := stack[i]
779		if p.testOf != nil {
780			fmt.Fprintf(&buf, "%s.test\n", p.testOf.path)
781		} else {
782			fmt.Fprintf(&buf, "%s\n", p.path)
783		}
784	}
785	return buf.String()
786}
787
788// Why returns the "go mod why" output stanza for the given package,
789// without the leading # comment.
790// The package graph must have been loaded already, usually by LoadALL.
791// If there is no reason for the package to be in the current build,
792// Why returns an empty string.
793func Why(path string) string {
794	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
795	if !ok {
796		return ""
797	}
798	return pkg.why()
799}
800
801// WhyDepth returns the number of steps in the Why listing.
802// If there is no reason for the package to be in the current build,
803// WhyDepth returns 0.
804func WhyDepth(path string) int {
805	n := 0
806	pkg, _ := loaded.pkgCache.Get(path).(*loadPkg)
807	for p := pkg; p != nil; p = p.stack {
808		n++
809	}
810	return n
811}
812
813// Replacement returns the replacement for mod, if any, from go.mod.
814// If there is no replacement for mod, Replacement returns
815// a module.Version with Path == "".
816func Replacement(mod module.Version) module.Version {
817	if modFile == nil {
818		// Happens during testing and if invoking 'go get' or 'go list' outside a module.
819		return module.Version{}
820	}
821
822	var found *modfile.Replace
823	for _, r := range modFile.Replace {
824		if r.Old.Path == mod.Path && (r.Old.Version == "" || r.Old.Version == mod.Version) {
825			found = r // keep going
826		}
827	}
828	if found == nil {
829		return module.Version{}
830	}
831	return found.New
832}
833
834// mvsReqs implements mvs.Reqs for module semantic versions,
835// with any exclusions or replacements applied internally.
836type mvsReqs struct {
837	buildList []module.Version
838	cache     par.Cache
839	versions  sync.Map
840}
841
842// Reqs returns the current module requirement graph.
843// Future calls to SetBuildList do not affect the operation
844// of the returned Reqs.
845func Reqs() mvs.Reqs {
846	r := &mvsReqs{
847		buildList: buildList,
848	}
849	return r
850}
851
852func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) {
853	type cached struct {
854		list []module.Version
855		err  error
856	}
857
858	c := r.cache.Do(mod, func() interface{} {
859		list, err := r.required(mod)
860		if err != nil {
861			return cached{nil, err}
862		}
863		for i, mv := range list {
864			for excluded[mv] {
865				mv1, err := r.next(mv)
866				if err != nil {
867					return cached{nil, err}
868				}
869				if mv1.Version == "none" {
870					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)}
871				}
872				mv = mv1
873			}
874			list[i] = mv
875		}
876
877		return cached{list, nil}
878	}).(cached)
879
880	return c.list, c.err
881}
882
883var vendorOnce sync.Once
884
885var (
886	vendorList []module.Version
887	vendorMap  map[string]module.Version
888)
889
890// readVendorList reads the list of vendored modules from vendor/modules.txt.
891func readVendorList() {
892	vendorOnce.Do(func() {
893		vendorList = nil
894		vendorMap = make(map[string]module.Version)
895		data, _ := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt"))
896		var m module.Version
897		for _, line := range strings.Split(string(data), "\n") {
898			if strings.HasPrefix(line, "# ") {
899				f := strings.Fields(line)
900				m = module.Version{}
901				if len(f) == 3 && semver.IsValid(f[2]) {
902					m = module.Version{Path: f[1], Version: f[2]}
903					vendorList = append(vendorList, m)
904				}
905			} else if m.Path != "" {
906				f := strings.Fields(line)
907				if len(f) == 1 {
908					vendorMap[f[0]] = m
909				}
910			}
911		}
912	})
913}
914
915func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version {
916	var list []module.Version
917	for _, r := range f.Require {
918		list = append(list, r.Mod)
919	}
920	return list
921}
922
923func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
924	if mod == Target {
925		if modFile != nil && modFile.Go != nil {
926			r.versions.LoadOrStore(mod, modFile.Go.Version)
927		}
928		var list []module.Version
929		return append(list, r.buildList[1:]...), nil
930	}
931
932	if cfg.BuildMod == "vendor" {
933		// For every module other than the target,
934		// return the full list of modules from modules.txt.
935		readVendorList()
936		return vendorList, nil
937	}
938
939	origPath := mod.Path
940	if repl := Replacement(mod); repl.Path != "" {
941		if repl.Version == "" {
942			// TODO: need to slip the new version into the tags list etc.
943			dir := repl.Path
944			if !filepath.IsAbs(dir) {
945				dir = filepath.Join(ModRoot(), dir)
946			}
947			gomod := filepath.Join(dir, "go.mod")
948			data, err := ioutil.ReadFile(gomod)
949			if err != nil {
950				base.Errorf("go: parsing %s: %v", base.ShortPath(gomod), err)
951				return nil, ErrRequire
952			}
953			f, err := modfile.ParseLax(gomod, data, nil)
954			if err != nil {
955				base.Errorf("go: parsing %s: %v", base.ShortPath(gomod), err)
956				return nil, ErrRequire
957			}
958			if f.Go != nil {
959				r.versions.LoadOrStore(mod, f.Go.Version)
960			}
961			return r.modFileToList(f), nil
962		}
963		mod = repl
964	}
965
966	if mod.Version == "none" {
967		return nil, nil
968	}
969
970	if !semver.IsValid(mod.Version) {
971		// Disallow the broader queries supported by fetch.Lookup.
972		base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", mod.Path, mod.Version)
973	}
974
975	data, err := modfetch.GoMod(mod.Path, mod.Version)
976	if err != nil {
977		base.Errorf("go: %s@%s: %v\n", mod.Path, mod.Version, err)
978		return nil, ErrRequire
979	}
980	f, err := modfile.ParseLax("go.mod", data, nil)
981	if err != nil {
982		base.Errorf("go: %s@%s: parsing go.mod: %v", mod.Path, mod.Version, err)
983		return nil, ErrRequire
984	}
985
986	if f.Module == nil {
987		base.Errorf("go: %s@%s: parsing go.mod: missing module line", mod.Path, mod.Version)
988		return nil, ErrRequire
989	}
990	if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path {
991		base.Errorf("go: %s@%s: parsing go.mod: unexpected module path %q", mod.Path, mod.Version, mpath)
992		return nil, ErrRequire
993	}
994	if f.Go != nil {
995		r.versions.LoadOrStore(mod, f.Go.Version)
996	}
997
998	return r.modFileToList(f), nil
999}
1000
1001// ErrRequire is the sentinel error returned when Require encounters problems.
1002// It prints the problems directly to standard error, so that multiple errors
1003// can be displayed easily.
1004var ErrRequire = errors.New("error loading module requirements")
1005
1006func (*mvsReqs) Max(v1, v2 string) string {
1007	if v1 != "" && semver.Compare(v1, v2) == -1 {
1008		return v2
1009	}
1010	return v1
1011}
1012
1013// Upgrade is a no-op, here to implement mvs.Reqs.
1014// The upgrade logic for go get -u is in ../modget/get.go.
1015func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) {
1016	return m, nil
1017}
1018
1019func versions(path string) ([]string, error) {
1020	// Note: modfetch.Lookup and repo.Versions are cached,
1021	// so there's no need for us to add extra caching here.
1022	repo, err := modfetch.Lookup(path)
1023	if err != nil {
1024		return nil, err
1025	}
1026	return repo.Versions("")
1027}
1028
1029// Previous returns the tagged version of m.Path immediately prior to
1030// m.Version, or version "none" if no prior version is tagged.
1031func (*mvsReqs) Previous(m module.Version) (module.Version, error) {
1032	list, err := versions(m.Path)
1033	if err != nil {
1034		return module.Version{}, err
1035	}
1036	i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 })
1037	if i > 0 {
1038		return module.Version{Path: m.Path, Version: list[i-1]}, nil
1039	}
1040	return module.Version{Path: m.Path, Version: "none"}, nil
1041}
1042
1043// next returns the next version of m.Path after m.Version.
1044// It is only used by the exclusion processing in the Required method,
1045// not called directly by MVS.
1046func (*mvsReqs) next(m module.Version) (module.Version, error) {
1047	list, err := versions(m.Path)
1048	if err != nil {
1049		return module.Version{}, err
1050	}
1051	i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 })
1052	if i < len(list) {
1053		return module.Version{Path: m.Path, Version: list[i]}, nil
1054	}
1055	return module.Version{Path: m.Path, Version: "none"}, nil
1056}
1057
1058func fetch(mod module.Version) (dir string, isLocal bool, err error) {
1059	if mod == Target {
1060		return ModRoot(), true, nil
1061	}
1062	if r := Replacement(mod); r.Path != "" {
1063		if r.Version == "" {
1064			dir = r.Path
1065			if !filepath.IsAbs(dir) {
1066				dir = filepath.Join(ModRoot(), dir)
1067			}
1068			return dir, true, nil
1069		}
1070		mod = r
1071	}
1072
1073	dir, err = modfetch.Download(mod)
1074	return dir, false, err
1075}
1076