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 modget implements the module-aware ``go get'' command.
6package modget
7
8import (
9	"errors"
10	"fmt"
11	"os"
12	"path/filepath"
13	"sort"
14	"strings"
15	"sync"
16
17	"cmd/go/internal/base"
18	"cmd/go/internal/get"
19	"cmd/go/internal/imports"
20	"cmd/go/internal/load"
21	"cmd/go/internal/modload"
22	"cmd/go/internal/mvs"
23	"cmd/go/internal/par"
24	"cmd/go/internal/search"
25	"cmd/go/internal/work"
26
27	"golang.org/x/mod/module"
28	"golang.org/x/mod/semver"
29)
30
31var CmdGet = &base.Command{
32	// Note: -d -u are listed explicitly because they are the most common get flags.
33	// Do not send CLs removing them because they're covered by [get flags].
34	UsageLine: "go get [-d] [-t] [-u] [-v] [-insecure] [build flags] [packages]",
35	Short:     "add dependencies to current module and install them",
36	Long: `
37Get resolves and adds dependencies to the current development module
38and then builds and installs them.
39
40The first step is to resolve which dependencies to add.
41
42For each named package or package pattern, get must decide which version of
43the corresponding module to use. By default, get looks up the latest tagged
44release version, such as v0.4.5 or v1.2.3. If there are no tagged release
45versions, get looks up the latest tagged pre-release version, such as
46v0.0.1-pre1. If there are no tagged versions at all, get looks up the latest
47known commit. If the module is not already required at a later version
48(for example, a pre-release newer than the latest release), get will use
49the version it looked up. Otherwise, get will use the currently
50required version.
51
52This default version selection can be overridden by adding an @version
53suffix to the package argument, as in 'go get golang.org/x/text@v0.3.0'.
54The version may be a prefix: @v1 denotes the latest available version starting
55with v1. See 'go help modules' under the heading 'Module queries' for the
56full query syntax.
57
58For modules stored in source control repositories, the version suffix can
59also be a commit hash, branch identifier, or other syntax known to the
60source control system, as in 'go get golang.org/x/text@master'. Note that
61branches with names that overlap with other module query syntax cannot be
62selected explicitly. For example, the suffix @v2 means the latest version
63starting with v2, not the branch named v2.
64
65If a module under consideration is already a dependency of the current
66development module, then get will update the required version.
67Specifying a version earlier than the current required version is valid and
68downgrades the dependency. The version suffix @none indicates that the
69dependency should be removed entirely, downgrading or removing modules
70depending on it as needed.
71
72The version suffix @latest explicitly requests the latest minor release of the
73module named by the given path. The suffix @upgrade is like @latest but
74will not downgrade a module if it is already required at a revision or
75pre-release version newer than the latest released version. The suffix
76@patch requests the latest patch release: the latest released version
77with the same major and minor version numbers as the currently required
78version. Like @upgrade, @patch will not downgrade a module already required
79at a newer version. If the path is not already required, @upgrade and @patch
80are equivalent to @latest.
81
82Although get defaults to using the latest version of the module containing
83a named package, it does not use the latest version of that module's
84dependencies. Instead it prefers to use the specific dependency versions
85requested by that module. For example, if the latest A requires module
86B v1.2.3, while B v1.2.4 and v1.3.1 are also available, then 'go get A'
87will use the latest A but then use B v1.2.3, as requested by A. (If there
88are competing requirements for a particular module, then 'go get' resolves
89those requirements by taking the maximum requested version.)
90
91The -t flag instructs get to consider modules needed to build tests of
92packages specified on the command line.
93
94The -u flag instructs get to update modules providing dependencies
95of packages named on the command line to use newer minor or patch
96releases when available. Continuing the previous example, 'go get -u A'
97will use the latest A with B v1.3.1 (not B v1.2.3). If B requires module C,
98but C does not provide any packages needed to build packages in A
99(not including tests), then C will not be updated.
100
101The -u=patch flag (not -u patch) also instructs get to update dependencies,
102but changes the default to select patch releases.
103Continuing the previous example,
104'go get -u=patch A@latest' will use the latest A with B v1.2.4 (not B v1.2.3),
105while 'go get -u=patch A' will use a patch release of A instead.
106
107When the -t and -u flags are used together, get will update
108test dependencies as well.
109
110In general, adding a new dependency may require upgrading
111existing dependencies to keep a working build, and 'go get' does
112this automatically. Similarly, downgrading one dependency may
113require downgrading other dependencies, and 'go get' does
114this automatically as well.
115
116The -insecure flag permits fetching from repositories and resolving
117custom domains using insecure schemes such as HTTP. Use with caution.
118
119The second step is to download (if needed), build, and install
120the named packages.
121
122If an argument names a module but not a package (because there is no
123Go source code in the module's root directory), then the install step
124is skipped for that argument, instead of causing a build failure.
125For example 'go get golang.org/x/perf' succeeds even though there
126is no code corresponding to that import path.
127
128Note that package patterns are allowed and are expanded after resolving
129the module versions. For example, 'go get golang.org/x/perf/cmd/...'
130adds the latest golang.org/x/perf and then installs the commands in that
131latest version.
132
133The -d flag instructs get to download the source code needed to build
134the named packages, including downloading necessary dependencies,
135but not to build and install them.
136
137With no package arguments, 'go get' applies to Go package in the
138current directory, if any. In particular, 'go get -u' and
139'go get -u=patch' update all the dependencies of that package.
140With no package arguments and also without -u, 'go get' is not much more
141than 'go install', and 'go get -d' not much more than 'go list'.
142
143For more about modules, see 'go help modules'.
144
145For more about specifying packages, see 'go help packages'.
146
147This text describes the behavior of get using modules to manage source
148code and dependencies. If instead the go command is running in GOPATH
149mode, the details of get's flags and effects change, as does 'go help get'.
150See 'go help modules' and 'go help gopath-get'.
151
152See also: go build, go install, go clean, go mod.
153	`,
154}
155
156// Note that this help text is a stopgap to make the module-aware get help text
157// available even in non-module settings. It should be deleted when the old get
158// is deleted. It should NOT be considered to set a precedent of having hierarchical
159// help names with dashes.
160var HelpModuleGet = &base.Command{
161	UsageLine: "module-get",
162	Short:     "module-aware go get",
163	Long: `
164The 'go get' command changes behavior depending on whether the
165go command is running in module-aware mode or legacy GOPATH mode.
166This help text, accessible as 'go help module-get' even in legacy GOPATH mode,
167describes 'go get' as it operates in module-aware mode.
168
169Usage: ` + CmdGet.UsageLine + `
170` + CmdGet.Long,
171}
172
173var (
174	getD   = CmdGet.Flag.Bool("d", false, "")
175	getF   = CmdGet.Flag.Bool("f", false, "")
176	getFix = CmdGet.Flag.Bool("fix", false, "")
177	getM   = CmdGet.Flag.Bool("m", false, "")
178	getT   = CmdGet.Flag.Bool("t", false, "")
179	getU   upgradeFlag
180	// -insecure is get.Insecure
181	// -v is cfg.BuildV
182)
183
184// upgradeFlag is a custom flag.Value for -u.
185type upgradeFlag string
186
187func (*upgradeFlag) IsBoolFlag() bool { return true } // allow -u
188
189func (v *upgradeFlag) Set(s string) error {
190	if s == "false" {
191		s = ""
192	}
193	if s == "true" {
194		s = "upgrade"
195	}
196	*v = upgradeFlag(s)
197	return nil
198}
199
200func (v *upgradeFlag) String() string { return "" }
201
202func init() {
203	work.AddBuildFlags(CmdGet, work.OmitModFlag)
204	CmdGet.Run = runGet // break init loop
205	CmdGet.Flag.BoolVar(&get.Insecure, "insecure", get.Insecure, "")
206	CmdGet.Flag.Var(&getU, "u", "")
207}
208
209// A getArg holds a parsed positional argument for go get (path@vers).
210type getArg struct {
211	// raw is the original argument, to be printed in error messages.
212	raw string
213
214	// path is the part of the argument before "@" (or the whole argument
215	// if there is no "@"). path specifies the modules or packages to get.
216	path string
217
218	// vers is the part of the argument after "@" or an implied
219	// "upgrade" or "patch" if there is no "@". vers specifies the
220	// module version to get.
221	vers string
222}
223
224// querySpec describes a query for a specific module. path may be a
225// module path, package path, or package pattern. vers is a version
226// query string from a command line argument.
227type querySpec struct {
228	// path is a module path, package path, or package pattern that
229	// specifies which module to query.
230	path string
231
232	// vers specifies what version of the module to get.
233	vers string
234
235	// forceModulePath is true if path should be interpreted as a module path.
236	// If forceModulePath is true, prevM must be set.
237	forceModulePath bool
238
239	// prevM is the previous version of the module. prevM is needed
240	// to determine the minor version number if vers is "patch". It's also
241	// used to avoid downgrades from prerelease versions newer than
242	// "latest" and "patch". If prevM is set, forceModulePath must be true.
243	prevM module.Version
244}
245
246// query holds the state for a query made for a specific module.
247// After a query is performed, we know the actual module path and
248// version and whether any packages were matched by the query path.
249type query struct {
250	querySpec
251
252	// arg is the command line argument that matched the specified module.
253	arg string
254
255	// m is the module path and version found by the query.
256	m module.Version
257}
258
259func runGet(cmd *base.Command, args []string) {
260	switch getU {
261	case "", "upgrade", "patch":
262		// ok
263	default:
264		base.Fatalf("go get: unknown upgrade flag -u=%s", getU)
265	}
266	if *getF {
267		fmt.Fprintf(os.Stderr, "go get: -f flag is a no-op when using modules\n")
268	}
269	if *getFix {
270		fmt.Fprintf(os.Stderr, "go get: -fix flag is a no-op when using modules\n")
271	}
272	if *getM {
273		base.Fatalf("go get: -m flag is no longer supported; consider -d to skip building packages")
274	}
275	modload.LoadTests = *getT
276
277	buildList := modload.LoadBuildList()
278	buildList = buildList[:len(buildList):len(buildList)] // copy on append
279	versionByPath := make(map[string]string)
280	for _, m := range buildList {
281		versionByPath[m.Path] = m.Version
282	}
283
284	// Do not allow any updating of go.mod until we've applied
285	// all the requested changes and checked that the result matches
286	// what was requested.
287	modload.DisallowWriteGoMod()
288
289	// Allow looking up modules for import paths outside of a module.
290	// 'go get' is expected to do this, unlike other commands.
291	modload.AllowMissingModuleImports()
292
293	// Parse command-line arguments and report errors. The command-line
294	// arguments are of the form path@version or simply path, with implicit
295	// @upgrade. path@none is "downgrade away".
296	var gets []getArg
297	var queries []*query
298	for _, arg := range search.CleanPatterns(args) {
299		// Argument is path or path@vers.
300		path := arg
301		vers := ""
302		if i := strings.Index(arg, "@"); i >= 0 {
303			path, vers = arg[:i], arg[i+1:]
304		}
305		if strings.Contains(vers, "@") || arg != path && vers == "" {
306			base.Errorf("go get %s: invalid module version syntax", arg)
307			continue
308		}
309
310		// If no version suffix is specified, assume @upgrade.
311		// If -u=patch was specified, assume @patch instead.
312		if vers == "" {
313			if getU != "" {
314				vers = string(getU)
315			} else {
316				vers = "upgrade"
317			}
318		}
319
320		gets = append(gets, getArg{raw: arg, path: path, vers: vers})
321
322		// Determine the modules that path refers to, and create queries
323		// to lookup modules at target versions before loading packages.
324		// This is an imprecise process, but it helps reduce unnecessary
325		// queries and package loading. It's also necessary for handling
326		// patterns like golang.org/x/tools/..., which can't be expanded
327		// during package loading until they're in the build list.
328		switch {
329		case search.IsRelativePath(path):
330			// Relative paths like ../../foo or ../../foo... are restricted to
331			// matching packages in the main module. If the path is explicit and
332			// contains no wildcards (...), check that it is a package in
333			// the main module. If the path contains wildcards but matches no
334			// packages, we'll warn after package loading.
335			if !strings.Contains(path, "...") {
336				pkgPath := modload.DirImportPath(filepath.FromSlash(path))
337				if pkgs := modload.TargetPackages(pkgPath); len(pkgs) == 0 {
338					abs, err := filepath.Abs(path)
339					if err != nil {
340						abs = path
341					}
342					base.Errorf("go get %s: path %s is not a package in module rooted at %s", arg, abs, modload.ModRoot())
343					continue
344				}
345			}
346
347			if path != arg {
348				base.Errorf("go get %s: can't request explicit version of path in main module", arg)
349				continue
350			}
351
352		case strings.Contains(path, "..."):
353			// Wait until we load packages to look up modules.
354			// We don't know yet whether any modules in the build list provide
355			// packages matching the pattern. For example, suppose
356			// golang.org/x/tools and golang.org/x/tools/playground are separate
357			// modules, and only golang.org/x/tools is in the build list. If the
358			// user runs 'go get golang.org/x/tools/playground/...', we should
359			// add a requirement for golang.org/x/tools/playground. We should not
360			// upgrade golang.org/x/tools.
361
362		case path == "all":
363			// If there is no main module, "all" is not meaningful.
364			if !modload.HasModRoot() {
365				base.Errorf(`go get %s: cannot match "all": working directory is not part of a module`, arg)
366			}
367			// Don't query modules until we load packages. We'll automatically
368			// look up any missing modules.
369
370		case search.IsMetaPackage(path):
371			base.Errorf("go get %s: explicit requirement on standard-library module %s not allowed", path, path)
372			continue
373
374		default:
375			// The argument is a package or module path.
376			if modload.HasModRoot() {
377				if pkgs := modload.TargetPackages(path); len(pkgs) != 0 {
378					// The path is in the main module. Nothing to query.
379					if vers != "upgrade" && vers != "patch" {
380						base.Errorf("go get %s: can't request explicit version of path in main module", arg)
381					}
382					continue
383				}
384			}
385
386			first := path
387			if i := strings.IndexByte(first, '/'); i >= 0 {
388				first = path
389			}
390			if !strings.Contains(first, ".") {
391				// The path doesn't have a dot in the first component and cannot be
392				// queried as a module. It may be a package in the standard library,
393				// which is fine, so don't report an error unless we encounter
394				// a problem loading packages below.
395				continue
396			}
397
398			// If we're querying "upgrade" or "patch", we need to know the current
399			// version of the module. For "upgrade", we want to avoid accidentally
400			// downgrading from a newer prerelease. For "patch", we need to query
401			// the correct minor version.
402			// Here, we check if "path" is the name of a module in the build list
403			// (other than the main module) and set prevM if so. If "path" isn't
404			// a module in the build list, the current version doesn't matter
405			// since it's either an unknown module or a package within a module
406			// that we'll discover later.
407			q := &query{querySpec: querySpec{path: path, vers: vers}, arg: arg}
408			if v, ok := versionByPath[path]; ok && path != modload.Target.Path {
409				q.prevM = module.Version{Path: path, Version: v}
410				q.forceModulePath = true
411			}
412			queries = append(queries, q)
413		}
414	}
415	base.ExitIfErrors()
416
417	// Query modules referenced by command line arguments at requested versions.
418	// We need to do this before loading packages since patterns that refer to
419	// packages in unknown modules can't be expanded. This also avoids looking
420	// up new modules while loading packages, only to downgrade later.
421	queryCache := make(map[querySpec]*query)
422	byPath := runQueries(queryCache, queries, nil)
423
424	// Add missing modules to the build list.
425	// We call SetBuildList here and elsewhere, since newUpgrader,
426	// ImportPathsQuiet, and other functions read the global build list.
427	for _, q := range queries {
428		if _, ok := versionByPath[q.m.Path]; !ok && q.m.Version != "none" {
429			buildList = append(buildList, q.m)
430		}
431	}
432	versionByPath = nil // out of date now; rebuilt later when needed
433	modload.SetBuildList(buildList)
434
435	// Upgrade modules specifically named on the command line. This is our only
436	// chance to upgrade modules without root packages (modOnly below).
437	// This also skips loading packages at an old version, only to upgrade
438	// and reload at a new version.
439	upgrade := make(map[string]*query)
440	for path, q := range byPath {
441		if q.path == q.m.Path && q.m.Version != "none" {
442			upgrade[path] = q
443		}
444	}
445	buildList, err := mvs.UpgradeAll(modload.Target, newUpgrader(upgrade, nil))
446	if err != nil {
447		base.Fatalf("go get: %v", err)
448	}
449	modload.SetBuildList(buildList)
450	base.ExitIfErrors()
451	prevBuildList := buildList
452
453	// Build a set of module paths that we don't plan to load packages from.
454	// This includes explicitly requested modules that don't have a root package
455	// and modules with a target version of "none".
456	var wg sync.WaitGroup
457	var modOnlyMu sync.Mutex
458	modOnly := make(map[string]*query)
459	for _, q := range queries {
460		if q.m.Version == "none" {
461			modOnlyMu.Lock()
462			modOnly[q.m.Path] = q
463			modOnlyMu.Unlock()
464			continue
465		}
466		if q.path == q.m.Path {
467			wg.Add(1)
468			go func(q *query) {
469				if hasPkg, err := modload.ModuleHasRootPackage(q.m); err != nil {
470					base.Errorf("go get: %v", err)
471				} else if !hasPkg {
472					modOnlyMu.Lock()
473					modOnly[q.m.Path] = q
474					modOnlyMu.Unlock()
475				}
476				wg.Done()
477			}(q)
478		}
479	}
480	wg.Wait()
481	base.ExitIfErrors()
482
483	// Build a list of arguments that may refer to packages.
484	var pkgPatterns []string
485	var pkgGets []getArg
486	for _, arg := range gets {
487		if modOnly[arg.path] == nil && arg.vers != "none" {
488			pkgPatterns = append(pkgPatterns, arg.path)
489			pkgGets = append(pkgGets, arg)
490		}
491	}
492
493	// Load packages and upgrade the modules that provide them. We do this until
494	// we reach a fixed point, since modules providing packages may change as we
495	// change versions. This must terminate because the module graph is finite,
496	// and the load and upgrade operations may only add and upgrade modules
497	// in the build list.
498	var matches []*search.Match
499	for {
500		var seenPkgs map[string]bool
501		seenQuery := make(map[querySpec]bool)
502		var queries []*query
503		addQuery := func(q *query) {
504			if !seenQuery[q.querySpec] {
505				seenQuery[q.querySpec] = true
506				queries = append(queries, q)
507			}
508		}
509
510		if len(pkgPatterns) > 0 {
511			// Don't load packages if pkgPatterns is empty. Both
512			// modload.ImportPathsQuiet and ModulePackages convert an empty list
513			// of patterns to []string{"."}, which is not what we want.
514			matches = modload.ImportPathsQuiet(pkgPatterns, imports.AnyTags())
515			seenPkgs = make(map[string]bool)
516			for i, match := range matches {
517				arg := pkgGets[i]
518
519				if len(match.Pkgs) == 0 {
520					// If the pattern did not match any packages, look up a new module.
521					// If the pattern doesn't match anything on the last iteration,
522					// we'll print a warning after the outer loop.
523					if !search.IsRelativePath(arg.path) && !match.Literal && arg.path != "all" {
524						addQuery(&query{querySpec: querySpec{path: arg.path, vers: arg.vers}, arg: arg.raw})
525					}
526					continue
527				}
528
529				allStd := true
530				for _, pkg := range match.Pkgs {
531					if !seenPkgs[pkg] {
532						seenPkgs[pkg] = true
533						if _, _, err := modload.Lookup("", false, pkg); err != nil {
534							allStd = false
535							base.Errorf("go get %s: %v", arg.raw, err)
536							continue
537						}
538					}
539					m := modload.PackageModule(pkg)
540					if m.Path == "" {
541						// pkg is in the standard library.
542						continue
543					}
544					allStd = false
545					if m.Path == modload.Target.Path {
546						// pkg is in the main module.
547						continue
548					}
549					addQuery(&query{querySpec: querySpec{path: m.Path, vers: arg.vers, forceModulePath: true, prevM: m}, arg: arg.raw})
550				}
551				if allStd && arg.path != arg.raw {
552					base.Errorf("go get %s: cannot use pattern %q with explicit version", arg.raw, arg.raw)
553				}
554			}
555		}
556		base.ExitIfErrors()
557
558		// Query target versions for modules providing packages matched by
559		// command line arguments.
560		byPath = runQueries(queryCache, queries, modOnly)
561
562		// Handle upgrades. This is needed for arguments that didn't match
563		// modules or matched different modules from a previous iteration. It
564		// also upgrades modules providing package dependencies if -u is set.
565		buildList, err := mvs.UpgradeAll(modload.Target, newUpgrader(byPath, seenPkgs))
566		if err != nil {
567			base.Fatalf("go get: %v", err)
568		}
569		modload.SetBuildList(buildList)
570		base.ExitIfErrors()
571
572		// Stop if no changes have been made to the build list.
573		buildList = modload.BuildList()
574		eq := len(buildList) == len(prevBuildList)
575		for i := 0; eq && i < len(buildList); i++ {
576			eq = buildList[i] == prevBuildList[i]
577		}
578		if eq {
579			break
580		}
581		prevBuildList = buildList
582	}
583	if !*getD {
584		// Only print warnings after the last iteration,
585		// and only if we aren't going to build.
586		search.WarnUnmatched(matches)
587	}
588
589	// Handle downgrades.
590	var down []module.Version
591	for _, m := range modload.BuildList() {
592		q := byPath[m.Path]
593		if q != nil && semver.Compare(m.Version, q.m.Version) > 0 {
594			down = append(down, module.Version{Path: m.Path, Version: q.m.Version})
595		}
596	}
597	if len(down) > 0 {
598		buildList, err := mvs.Downgrade(modload.Target, modload.Reqs(), down...)
599		if err != nil {
600			base.Fatalf("go: %v", err)
601		}
602		modload.SetBuildList(buildList)
603		modload.ReloadBuildList() // note: does not update go.mod
604		base.ExitIfErrors()
605	}
606
607	// Scan for any upgrades lost by the downgrades.
608	var lostUpgrades []*query
609	if len(down) > 0 {
610		versionByPath = make(map[string]string)
611		for _, m := range modload.BuildList() {
612			versionByPath[m.Path] = m.Version
613		}
614		for _, q := range byPath {
615			if v, ok := versionByPath[q.m.Path]; q.m.Version != "none" && (!ok || semver.Compare(v, q.m.Version) != 0) {
616				lostUpgrades = append(lostUpgrades, q)
617			}
618		}
619		sort.Slice(lostUpgrades, func(i, j int) bool {
620			return lostUpgrades[i].m.Path < lostUpgrades[j].m.Path
621		})
622	}
623	if len(lostUpgrades) > 0 {
624		desc := func(m module.Version) string {
625			s := m.Path + "@" + m.Version
626			t := byPath[m.Path]
627			if t != nil && t.arg != s {
628				s += " from " + t.arg
629			}
630			return s
631		}
632		downByPath := make(map[string]module.Version)
633		for _, d := range down {
634			downByPath[d.Path] = d
635		}
636
637		var buf strings.Builder
638		fmt.Fprintf(&buf, "go get: inconsistent versions:")
639		reqs := modload.Reqs()
640		for _, q := range lostUpgrades {
641			// We lost q because its build list requires a newer version of something in down.
642			// Figure out exactly what.
643			// Repeatedly constructing the build list is inefficient
644			// if there are MANY command-line arguments,
645			// but at least all the necessary requirement lists are cached at this point.
646			list, err := buildListForLostUpgrade(q.m, reqs)
647			if err != nil {
648				base.Fatalf("go: %v", err)
649			}
650
651			fmt.Fprintf(&buf, "\n\t%s", desc(q.m))
652			sep := " requires"
653			for _, m := range list {
654				if down, ok := downByPath[m.Path]; ok && semver.Compare(down.Version, m.Version) < 0 {
655					fmt.Fprintf(&buf, "%s %s@%s (not %s)", sep, m.Path, m.Version, desc(down))
656					sep = ","
657				}
658			}
659			if sep != "," {
660				// We have no idea why this happened.
661				// At least report the problem.
662				if v := versionByPath[q.m.Path]; v == "" {
663					fmt.Fprintf(&buf, " removed unexpectedly")
664				} else {
665					fmt.Fprintf(&buf, " ended up at %s unexpectedly", v)
666				}
667				fmt.Fprintf(&buf, " (please report at golang.org/issue/new)")
668			}
669		}
670		base.Fatalf("%v", buf.String())
671	}
672
673	// Everything succeeded. Update go.mod.
674	modload.AllowWriteGoMod()
675	modload.WriteGoMod()
676
677	// If -d was specified, we're done after the module work.
678	// We've already downloaded modules by loading packages above.
679	// Otherwise, we need to build and install the packages matched by
680	// command line arguments. This may be a different set of packages,
681	// since we only build packages for the target platform.
682	// Note that 'go get -u' without arguments is equivalent to
683	// 'go get -u .', so we'll typically build the package in the current
684	// directory.
685	if *getD || len(pkgPatterns) == 0 {
686		return
687	}
688	work.BuildInit()
689	pkgs := load.PackagesForBuild(pkgPatterns)
690	work.InstallPackages(pkgPatterns, pkgs)
691}
692
693// runQueries looks up modules at target versions in parallel. Results will be
694// cached. If the same module is referenced by multiple queries at different
695// versions (including earlier queries in the modOnly map), an error will be
696// reported. A map from module paths to queries is returned, which includes
697// queries and modOnly.
698func runQueries(cache map[querySpec]*query, queries []*query, modOnly map[string]*query) map[string]*query {
699	var lookup par.Work
700	for _, q := range queries {
701		if cached := cache[q.querySpec]; cached != nil {
702			*q = *cached
703		} else {
704			cache[q.querySpec] = q
705			lookup.Add(q)
706		}
707	}
708
709	lookup.Do(10, func(item interface{}) {
710		q := item.(*query)
711		if q.vers == "none" {
712			// Wait for downgrade step.
713			q.m = module.Version{Path: q.path, Version: "none"}
714			return
715		}
716		m, err := getQuery(q.path, q.vers, q.prevM, q.forceModulePath)
717		if err != nil {
718			base.Errorf("go get %s: %v", q.arg, err)
719		}
720		q.m = m
721	})
722	base.ExitIfErrors()
723
724	byPath := make(map[string]*query)
725	check := func(q *query) {
726		if prev, ok := byPath[q.m.Path]; prev != nil && prev.m != q.m {
727			base.Errorf("go get: conflicting versions for module %s: %s and %s", q.m.Path, prev.m.Version, q.m.Version)
728			byPath[q.m.Path] = nil // sentinel to stop errors
729			return
730		} else if !ok {
731			byPath[q.m.Path] = q
732		}
733	}
734	for _, q := range queries {
735		check(q)
736	}
737	for _, q := range modOnly {
738		check(q)
739	}
740	base.ExitIfErrors()
741
742	return byPath
743}
744
745// getQuery evaluates the given (package or module) path and version
746// to determine the underlying module version being requested.
747// If forceModulePath is set, getQuery must interpret path
748// as a module path.
749func getQuery(path, vers string, prevM module.Version, forceModulePath bool) (module.Version, error) {
750	if (prevM.Version != "") != forceModulePath {
751		// We resolve package patterns by calling QueryPattern, which does not
752		// accept a previous version and therefore cannot take it into account for
753		// the "latest" or "patch" queries.
754		// If we are resolving a package path or pattern, the caller has already
755		// resolved any existing packages to their containing module(s), and
756		// will set both prevM.Version and forceModulePath for those modules.
757		// The only remaining package patterns are those that are not already
758		// provided by the build list, which are indicated by
759		// an empty prevM.Version.
760		base.Fatalf("go get: internal error: prevM may be set if and only if forceModulePath is set")
761	}
762
763	// If the query must be a module path, try only that module path.
764	if forceModulePath {
765		if path == modload.Target.Path {
766			if vers != "latest" {
767				return module.Version{}, fmt.Errorf("can't get a specific version of the main module")
768			}
769		}
770
771		info, err := modload.Query(path, vers, prevM.Version, modload.Allowed)
772		if err == nil {
773			if info.Version != vers && info.Version != prevM.Version {
774				logOncef("go: %s %s => %s", path, vers, info.Version)
775			}
776			return module.Version{Path: path, Version: info.Version}, nil
777		}
778
779		// If the query was "upgrade" or "patch" and the current version has been
780		// replaced, check to see whether the error was for that same version:
781		// if so, the version was probably replaced because it is invalid,
782		// and we should keep that replacement without complaining.
783		if vers == "upgrade" || vers == "patch" {
784			var vErr *module.InvalidVersionError
785			if errors.As(err, &vErr) && vErr.Version == prevM.Version && modload.Replacement(prevM).Path != "" {
786				return prevM, nil
787			}
788		}
789
790		return module.Version{}, err
791	}
792
793	// If the query may be either a package or a module, try it as a package path.
794	// If it turns out to only exist as a module, we can detect the resulting
795	// PackageNotInModuleError and avoid a second round-trip through (potentially)
796	// all of the configured proxies.
797	results, err := modload.QueryPattern(path, vers, modload.Allowed)
798	if err != nil {
799		// If the path doesn't contain a wildcard, check whether it was actually a
800		// module path instead. If so, return that.
801		if !strings.Contains(path, "...") {
802			var modErr *modload.PackageNotInModuleError
803			if errors.As(err, &modErr) && modErr.Mod.Path == path {
804				if modErr.Mod.Version != vers {
805					logOncef("go: %s %s => %s", path, vers, modErr.Mod.Version)
806				}
807				return modErr.Mod, nil
808			}
809		}
810
811		return module.Version{}, err
812	}
813
814	m := results[0].Mod
815	if m.Path != path {
816		logOncef("go: found %s in %s %s", path, m.Path, m.Version)
817	} else if m.Version != vers {
818		logOncef("go: %s %s => %s", path, vers, m.Version)
819	}
820	return m, nil
821}
822
823// An upgrader adapts an underlying mvs.Reqs to apply an
824// upgrade policy to a list of targets and their dependencies.
825type upgrader struct {
826	mvs.Reqs
827
828	// cmdline maps a module path to a query made for that module at a
829	// specific target version. Each query corresponds to a module
830	// matched by a command line argument.
831	cmdline map[string]*query
832
833	// upgrade is a set of modules providing dependencies of packages
834	// matched by command line arguments. If -u or -u=patch is set,
835	// these modules are upgraded accordingly.
836	upgrade map[string]bool
837}
838
839// newUpgrader creates an upgrader. cmdline contains queries made at
840// specific versions for modules matched by command line arguments. pkgs
841// is the set of packages matched by command line arguments. If -u or -u=patch
842// is set, modules providing dependencies of pkgs are upgraded accordingly.
843func newUpgrader(cmdline map[string]*query, pkgs map[string]bool) *upgrader {
844	u := &upgrader{
845		Reqs:    modload.Reqs(),
846		cmdline: cmdline,
847	}
848	if getU != "" {
849		u.upgrade = make(map[string]bool)
850
851		// Traverse package import graph.
852		// Initialize work queue with root packages.
853		seen := make(map[string]bool)
854		var work []string
855		add := func(path string) {
856			if !seen[path] {
857				seen[path] = true
858				work = append(work, path)
859			}
860		}
861		for pkg := range pkgs {
862			add(pkg)
863		}
864		for len(work) > 0 {
865			pkg := work[0]
866			work = work[1:]
867			m := modload.PackageModule(pkg)
868			u.upgrade[m.Path] = true
869
870			// testImports is empty unless test imports were actually loaded,
871			// i.e., -t was set or "all" was one of the arguments.
872			imports, testImports := modload.PackageImports(pkg)
873			for _, imp := range imports {
874				add(imp)
875			}
876			for _, imp := range testImports {
877				add(imp)
878			}
879		}
880	}
881	return u
882}
883
884// Required returns the requirement list for m.
885// For the main module, we override requirements with the modules named
886// one the command line, and we include new requirements. Otherwise,
887// we defer to u.Reqs.
888func (u *upgrader) Required(m module.Version) ([]module.Version, error) {
889	rs, err := u.Reqs.Required(m)
890	if err != nil {
891		return nil, err
892	}
893	if m != modload.Target {
894		return rs, nil
895	}
896
897	overridden := make(map[string]bool)
898	for i, m := range rs {
899		if q := u.cmdline[m.Path]; q != nil && q.m.Version != "none" {
900			rs[i] = q.m
901			overridden[q.m.Path] = true
902		}
903	}
904	for _, q := range u.cmdline {
905		if !overridden[q.m.Path] && q.m.Path != modload.Target.Path && q.m.Version != "none" {
906			rs = append(rs, q.m)
907		}
908	}
909	return rs, nil
910}
911
912// Upgrade returns the desired upgrade for m.
913//
914// If m was requested at a specific version on the command line, then
915// Upgrade returns that version.
916//
917// If -u is set and m provides a dependency of a package matched by
918// command line arguments, then Upgrade may provider a newer tagged version.
919// If m is a tagged version, then Upgrade will return the latest tagged
920// version (with the same minor version number if -u=patch).
921// If m is a pseudo-version, then Upgrade returns the latest tagged version
922// only if that version has a time-stamp newer than m. This special case
923// prevents accidental downgrades when already using a pseudo-version
924// newer than the latest tagged version.
925//
926// If none of the above cases apply, then Upgrade returns m.
927func (u *upgrader) Upgrade(m module.Version) (module.Version, error) {
928	// Allow pkg@vers on the command line to override the upgrade choice v.
929	// If q's version is < m.Version, then we're going to downgrade anyway,
930	// and it's cleaner to avoid moving back and forth and picking up
931	// extraneous other newer dependencies.
932	// If q's version is > m.Version, then we're going to upgrade past
933	// m.Version anyway, and again it's cleaner to avoid moving back and forth
934	// picking up extraneous other newer dependencies.
935	if q := u.cmdline[m.Path]; q != nil {
936		return q.m, nil
937	}
938
939	if !u.upgrade[m.Path] {
940		// Not involved in upgrade. Leave alone.
941		return m, nil
942	}
943
944	// Run query required by upgrade semantics.
945	// Note that Query "latest" is not the same as using repo.Latest,
946	// which may return a pseudoversion for the latest commit.
947	// Query "latest" returns the newest tagged version or the newest
948	// prerelease version if there are no non-prereleases, or repo.Latest
949	// if there aren't any tagged versions.
950	// If we're querying "upgrade" or "patch", Query will compare the current
951	// version against the chosen version and will return the current version
952	// if it is newer.
953	info, err := modload.Query(m.Path, string(getU), m.Version, modload.Allowed)
954	if err != nil {
955		// Report error but return m, to let version selection continue.
956		// (Reporting the error will fail the command at the next base.ExitIfErrors.)
957
958		// Special case: if the error is for m.Version itself and m.Version has a
959		// replacement, then keep it and don't report the error: the fact that the
960		// version is invalid is likely the reason it was replaced to begin with.
961		var vErr *module.InvalidVersionError
962		if errors.As(err, &vErr) && vErr.Version == m.Version && modload.Replacement(m).Path != "" {
963			return m, nil
964		}
965
966		// Special case: if the error is "no matching versions" then don't
967		// even report the error. Because Query does not consider pseudo-versions,
968		// it may happen that we have a pseudo-version but during -u=patch
969		// the query v0.0 matches no versions (not even the one we're using).
970		var noMatch *modload.NoMatchingVersionError
971		if !errors.As(err, &noMatch) {
972			base.Errorf("go get: upgrading %s@%s: %v", m.Path, m.Version, err)
973		}
974		return m, nil
975	}
976
977	if info.Version != m.Version {
978		logOncef("go: %s %s => %s", m.Path, getU, info.Version)
979	}
980	return module.Version{Path: m.Path, Version: info.Version}, nil
981}
982
983// buildListForLostUpgrade returns the build list for the module graph
984// rooted at lost. Unlike mvs.BuildList, the target module (lost) is not
985// treated specially. The returned build list may contain a newer version
986// of lost.
987//
988// buildListForLostUpgrade is used after a downgrade has removed a module
989// requested at a specific version. This helps us understand the requirements
990// implied by each downgrade.
991func buildListForLostUpgrade(lost module.Version, reqs mvs.Reqs) ([]module.Version, error) {
992	return mvs.BuildList(lostUpgradeRoot, &lostUpgradeReqs{Reqs: reqs, lost: lost})
993}
994
995var lostUpgradeRoot = module.Version{Path: "lost-upgrade-root", Version: ""}
996
997type lostUpgradeReqs struct {
998	mvs.Reqs
999	lost module.Version
1000}
1001
1002func (r *lostUpgradeReqs) Required(mod module.Version) ([]module.Version, error) {
1003	if mod == lostUpgradeRoot {
1004		return []module.Version{r.lost}, nil
1005	}
1006	return r.Reqs.Required(mod)
1007}
1008
1009var loggedLines sync.Map
1010
1011func logOncef(format string, args ...interface{}) {
1012	msg := fmt.Sprintf(format, args...)
1013	if _, dup := loggedLines.LoadOrStore(msg, true); !dup {
1014		fmt.Fprintln(os.Stderr, msg)
1015	}
1016}
1017