Source file src/cmd/go/internal/modget/get.go

     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.
     6  package modget
     7  
     8  // The arguments to 'go get' are patterns with optional version queries, with
     9  // the version queries defaulting to "upgrade".
    10  //
    11  // The patterns are normally interpreted as package patterns. However, if a
    12  // pattern cannot match a package, it is instead interpreted as a *module*
    13  // pattern. For version queries such as "upgrade" and "patch" that depend on the
    14  // selected version of a module (or of the module containing a package),
    15  // whether a pattern denotes a package or module may change as updates are
    16  // applied (see the example in mod_get_patchmod.txt).
    17  //
    18  // There are a few other ambiguous cases to resolve, too. A package can exist in
    19  // two different modules at the same version: for example, the package
    20  // example.com/foo might be found in module example.com and also in module
    21  // example.com/foo, and those modules may have independent v0.1.0 tags — so the
    22  // input 'example.com/foo@v0.1.0' could syntactically refer to the variant of
    23  // the package loaded from either module! (See mod_get_ambiguous_pkg.txt.)
    24  // If the argument is ambiguous, the user can often disambiguate by specifying
    25  // explicit versions for *all* of the potential module paths involved.
    26  
    27  import (
    28  	"context"
    29  	"errors"
    30  	"fmt"
    31  	"os"
    32  	"path/filepath"
    33  	"runtime"
    34  	"sort"
    35  	"strings"
    36  	"sync"
    37  
    38  	"cmd/go/internal/base"
    39  	"cmd/go/internal/cfg"
    40  	"cmd/go/internal/gover"
    41  	"cmd/go/internal/imports"
    42  	"cmd/go/internal/modfetch"
    43  	"cmd/go/internal/modload"
    44  	"cmd/go/internal/par"
    45  	"cmd/go/internal/search"
    46  	"cmd/go/internal/toolchain"
    47  	"cmd/go/internal/work"
    48  
    49  	"golang.org/x/mod/modfile"
    50  	"golang.org/x/mod/module"
    51  )
    52  
    53  var CmdGet = &base.Command{
    54  	// Note: flags below are listed explicitly because they're the most common.
    55  	// Do not send CLs removing them because they're covered by [get flags].
    56  	UsageLine: "go get [-t] [-u] [-v] [build flags] [packages]",
    57  	Short:     "add dependencies to current module and install them",
    58  	Long: `
    59  Get resolves its command-line arguments to packages at specific module versions,
    60  updates go.mod to require those versions, and downloads source code into the
    61  module cache.
    62  
    63  To add a dependency for a package or upgrade it to its latest version:
    64  
    65  	go get example.com/pkg
    66  
    67  To upgrade or downgrade a package to a specific version:
    68  
    69  	go get example.com/pkg@v1.2.3
    70  
    71  To remove a dependency on a module and downgrade modules that require it:
    72  
    73  	go get example.com/mod@none
    74  
    75  To upgrade the minimum required Go version to the latest released Go version:
    76  
    77  	go get go@latest
    78  
    79  To upgrade the Go toolchain to the latest patch release of the current Go toolchain:
    80  
    81  	go get toolchain@patch
    82  
    83  See https://golang.org/ref/mod#go-get for details.
    84  
    85  In earlier versions of Go, 'go get' was used to build and install packages.
    86  Now, 'go get' is dedicated to adjusting dependencies in go.mod. 'go install'
    87  may be used to build and install commands instead. When a version is specified,
    88  'go install' runs in module-aware mode and ignores the go.mod file in the
    89  current directory. For example:
    90  
    91  	go install example.com/pkg@v1.2.3
    92  	go install example.com/pkg@latest
    93  
    94  See 'go help install' or https://golang.org/ref/mod#go-install for details.
    95  
    96  'go get' accepts the following flags.
    97  
    98  The -t flag instructs get to consider modules needed to build tests of
    99  packages specified on the command line.
   100  
   101  The -u flag instructs get to update modules providing dependencies
   102  of packages named on the command line to use newer minor or patch
   103  releases when available.
   104  
   105  The -u=patch flag (not -u patch) also instructs get to update dependencies,
   106  but changes the default to select patch releases.
   107  
   108  When the -t and -u flags are used together, get will update
   109  test dependencies as well.
   110  
   111  The -x flag prints commands as they are executed. This is useful for
   112  debugging version control commands when a module is downloaded directly
   113  from a repository.
   114  
   115  For more about modules, see https://golang.org/ref/mod.
   116  
   117  For more about using 'go get' to update the minimum Go version and
   118  suggested Go toolchain, see https://go.dev/doc/toolchain.
   119  
   120  For more about specifying packages, see 'go help packages'.
   121  
   122  This text describes the behavior of get using modules to manage source
   123  code and dependencies. If instead the go command is running in GOPATH
   124  mode, the details of get's flags and effects change, as does 'go help get'.
   125  See 'go help gopath-get'.
   126  
   127  See also: go build, go install, go clean, go mod.
   128  	`,
   129  }
   130  
   131  var HelpVCS = &base.Command{
   132  	UsageLine: "vcs",
   133  	Short:     "controlling version control with GOVCS",
   134  	Long: `
   135  The 'go get' command can run version control commands like git
   136  to download imported code. This functionality is critical to the decentralized
   137  Go package ecosystem, in which code can be imported from any server,
   138  but it is also a potential security problem, if a malicious server finds a
   139  way to cause the invoked version control command to run unintended code.
   140  
   141  To balance the functionality and security concerns, the 'go get' command
   142  by default will only use git and hg to download code from public servers.
   143  But it will use any known version control system (bzr, fossil, git, hg, svn)
   144  to download code from private servers, defined as those hosting packages
   145  matching the GOPRIVATE variable (see 'go help private'). The rationale behind
   146  allowing only Git and Mercurial is that these two systems have had the most
   147  attention to issues of being run as clients of untrusted servers. In contrast,
   148  Bazaar, Fossil, and Subversion have primarily been used in trusted,
   149  authenticated environments and are not as well scrutinized as attack surfaces.
   150  
   151  The version control command restrictions only apply when using direct version
   152  control access to download code. When downloading modules from a proxy,
   153  'go get' uses the proxy protocol instead, which is always permitted.
   154  By default, the 'go get' command uses the Go module mirror (proxy.golang.org)
   155  for public packages and only falls back to version control for private
   156  packages or when the mirror refuses to serve a public package (typically for
   157  legal reasons). Therefore, clients can still access public code served from
   158  Bazaar, Fossil, or Subversion repositories by default, because those downloads
   159  use the Go module mirror, which takes on the security risk of running the
   160  version control commands using a custom sandbox.
   161  
   162  The GOVCS variable can be used to change the allowed version control systems
   163  for specific packages (identified by a module or import path).
   164  The GOVCS variable applies when building package in both module-aware mode
   165  and GOPATH mode. When using modules, the patterns match against the module path.
   166  When using GOPATH, the patterns match against the import path corresponding to
   167  the root of the version control repository.
   168  
   169  The general form of the GOVCS setting is a comma-separated list of
   170  pattern:vcslist rules. The pattern is a glob pattern that must match
   171  one or more leading elements of the module or import path. The vcslist
   172  is a pipe-separated list of allowed version control commands, or "all"
   173  to allow use of any known command, or "off" to disallow all commands.
   174  Note that if a module matches a pattern with vcslist "off", it may still be
   175  downloaded if the origin server uses the "mod" scheme, which instructs the
   176  go command to download the module using the GOPROXY protocol.
   177  The earliest matching pattern in the list applies, even if later patterns
   178  might also match.
   179  
   180  For example, consider:
   181  
   182  	GOVCS=github.com:git,evil.com:off,*:git|hg
   183  
   184  With this setting, code with a module or import path beginning with
   185  github.com/ can only use git; paths on evil.com cannot use any version
   186  control command, and all other paths (* matches everything) can use
   187  only git or hg.
   188  
   189  The special patterns "public" and "private" match public and private
   190  module or import paths. A path is private if it matches the GOPRIVATE
   191  variable; otherwise it is public.
   192  
   193  If no rules in the GOVCS variable match a particular module or import path,
   194  the 'go get' command applies its default rule, which can now be summarized
   195  in GOVCS notation as 'public:git|hg,private:all'.
   196  
   197  To allow unfettered use of any version control system for any package, use:
   198  
   199  	GOVCS=*:all
   200  
   201  To disable all use of version control, use:
   202  
   203  	GOVCS=*:off
   204  
   205  The 'go env -w' command (see 'go help env') can be used to set the GOVCS
   206  variable for future go command invocations.
   207  `,
   208  }
   209  
   210  var (
   211  	getD        = CmdGet.Flag.Bool("d", true, "")
   212  	getF        = CmdGet.Flag.Bool("f", false, "")
   213  	getFix      = CmdGet.Flag.Bool("fix", false, "")
   214  	getM        = CmdGet.Flag.Bool("m", false, "")
   215  	getT        = CmdGet.Flag.Bool("t", false, "")
   216  	getU        upgradeFlag
   217  	getInsecure = CmdGet.Flag.Bool("insecure", false, "")
   218  	// -v is cfg.BuildV
   219  )
   220  
   221  // upgradeFlag is a custom flag.Value for -u.
   222  type upgradeFlag struct {
   223  	rawVersion string
   224  	version    string
   225  }
   226  
   227  func (*upgradeFlag) IsBoolFlag() bool { return true } // allow -u
   228  
   229  func (v *upgradeFlag) Set(s string) error {
   230  	if s == "false" {
   231  		v.version = ""
   232  		v.rawVersion = ""
   233  	} else if s == "true" {
   234  		v.version = "upgrade"
   235  		v.rawVersion = ""
   236  	} else {
   237  		v.version = s
   238  		v.rawVersion = s
   239  	}
   240  	return nil
   241  }
   242  
   243  func (v *upgradeFlag) String() string { return "" }
   244  
   245  func init() {
   246  	work.AddBuildFlags(CmdGet, work.OmitModFlag)
   247  	CmdGet.Run = runGet // break init loop
   248  	CmdGet.Flag.Var(&getU, "u", "")
   249  }
   250  
   251  func runGet(ctx context.Context, cmd *base.Command, args []string) {
   252  	switch getU.version {
   253  	case "", "upgrade", "patch":
   254  		// ok
   255  	default:
   256  		base.Fatalf("go: unknown upgrade flag -u=%s", getU.rawVersion)
   257  	}
   258  	// TODO(#43684): in the future (Go 1.20), warn that -d is a no-op.
   259  	if !*getD {
   260  		base.Fatalf("go: -d flag may not be disabled")
   261  	}
   262  	if *getF {
   263  		fmt.Fprintf(os.Stderr, "go: -f flag is a no-op when using modules\n")
   264  	}
   265  	if *getFix {
   266  		fmt.Fprintf(os.Stderr, "go: -fix flag is a no-op when using modules\n")
   267  	}
   268  	if *getM {
   269  		base.Fatalf("go: -m flag is no longer supported")
   270  	}
   271  	if *getInsecure {
   272  		base.Fatalf("go: -insecure flag is no longer supported; use GOINSECURE instead")
   273  	}
   274  
   275  	modload.ForceUseModules = true
   276  
   277  	// Do not allow any updating of go.mod until we've applied
   278  	// all the requested changes and checked that the result matches
   279  	// what was requested.
   280  	modload.ExplicitWriteGoMod = true
   281  
   282  	// Allow looking up modules for import paths when outside of a module.
   283  	// 'go get' is expected to do this, unlike other commands.
   284  	modload.AllowMissingModuleImports()
   285  
   286  	// 'go get' no longer builds or installs packages, so there's nothing to do
   287  	// if there's no go.mod file.
   288  	// TODO(#40775): make modload.Init return ErrNoModRoot instead of exiting.
   289  	// We could handle that here by printing a different message.
   290  	modload.Init()
   291  	if !modload.HasModRoot() {
   292  		base.Fatalf("go: go.mod file not found in current directory or any parent directory.\n" +
   293  			"\t'go get' is no longer supported outside a module.\n" +
   294  			"\tTo build and install a command, use 'go install' with a version,\n" +
   295  			"\tlike 'go install example.com/cmd@latest'\n" +
   296  			"\tFor more information, see https://golang.org/doc/go-get-install-deprecation\n" +
   297  			"\tor run 'go help get' or 'go help install'.")
   298  	}
   299  
   300  	dropToolchain, queries := parseArgs(ctx, args)
   301  	opts := modload.WriteOpts{
   302  		DropToolchain: dropToolchain,
   303  	}
   304  	for _, q := range queries {
   305  		if q.pattern == "toolchain" {
   306  			opts.ExplicitToolchain = true
   307  		}
   308  	}
   309  
   310  	r := newResolver(ctx, queries)
   311  	r.performLocalQueries(ctx)
   312  	r.performPathQueries(ctx)
   313  
   314  	for {
   315  		r.performWildcardQueries(ctx)
   316  		r.performPatternAllQueries(ctx)
   317  
   318  		if changed := r.resolveQueries(ctx, queries); changed {
   319  			// 'go get' arguments can be (and often are) package patterns rather than
   320  			// (just) modules. A package can be provided by any module with a prefix
   321  			// of its import path, and a wildcard can even match packages in modules
   322  			// with totally different paths. Because of these effects, and because any
   323  			// change to the selected version of a module can bring in entirely new
   324  			// module paths as dependencies, we need to reissue queries whenever we
   325  			// change the build list.
   326  			//
   327  			// The result of any version query for a given module — even "upgrade" or
   328  			// "patch" — is always relative to the build list at the start of
   329  			// the 'go get' command, not an intermediate state, and is therefore
   330  			// deterministic and therefore cacheable, and the constraints on the
   331  			// selected version of each module can only narrow as we iterate.
   332  			//
   333  			// "all" is functionally very similar to a wildcard pattern. The set of
   334  			// packages imported by the main module does not change, and the query
   335  			// result for the module containing each such package also does not change
   336  			// (it is always relative to the initial build list, before applying
   337  			// queries). So the only way that the result of an "all" query can change
   338  			// is if some matching package moves from one module in the build list
   339  			// to another, which should not happen very often.
   340  			continue
   341  		}
   342  
   343  		// When we load imports, we detect the following conditions:
   344  		//
   345  		// - missing transitive dependencies that need to be resolved from outside the
   346  		//   current build list (note that these may add new matches for existing
   347  		//   pattern queries!)
   348  		//
   349  		// - transitive dependencies that didn't match any other query,
   350  		//   but need to be upgraded due to the -u flag
   351  		//
   352  		// - ambiguous import errors.
   353  		//   TODO(#27899): Try to resolve ambiguous import errors automatically.
   354  		upgrades := r.findAndUpgradeImports(ctx, queries)
   355  		if changed := r.applyUpgrades(ctx, upgrades); changed {
   356  			continue
   357  		}
   358  
   359  		r.findMissingWildcards(ctx)
   360  		if changed := r.resolveQueries(ctx, r.wildcardQueries); changed {
   361  			continue
   362  		}
   363  
   364  		break
   365  	}
   366  
   367  	r.checkWildcardVersions(ctx)
   368  
   369  	var pkgPatterns []string
   370  	for _, q := range queries {
   371  		if q.matchesPackages {
   372  			pkgPatterns = append(pkgPatterns, q.pattern)
   373  		}
   374  	}
   375  	r.checkPackageProblems(ctx, pkgPatterns)
   376  
   377  	// Everything succeeded. Update go.mod.
   378  	oldReqs := reqsFromGoMod(modload.ModFile())
   379  
   380  	if err := modload.WriteGoMod(ctx, opts); err != nil {
   381  		// A TooNewError can happen for 'go get go@newversion'
   382  		// when all the required modules are old enough
   383  		// but the command line is not.
   384  		// TODO(bcmills): modload.EditBuildList should catch this instead,
   385  		// and then this can be changed to base.Fatal(err).
   386  		toolchain.SwitchOrFatal(ctx, err)
   387  	}
   388  
   389  	newReqs := reqsFromGoMod(modload.ModFile())
   390  	r.reportChanges(oldReqs, newReqs)
   391  
   392  	if gowork := modload.FindGoWork(base.Cwd()); gowork != "" {
   393  		wf, err := modload.ReadWorkFile(gowork)
   394  		if err == nil && modload.UpdateWorkGoVersion(wf, modload.MainModules.GoVersion()) {
   395  			modload.WriteWorkFile(gowork, wf)
   396  		}
   397  	}
   398  }
   399  
   400  // parseArgs parses command-line arguments and reports errors.
   401  //
   402  // The command-line arguments are of the form path@version or simply path, with
   403  // implicit @upgrade. path@none is "downgrade away".
   404  func parseArgs(ctx context.Context, rawArgs []string) (dropToolchain bool, queries []*query) {
   405  	defer base.ExitIfErrors()
   406  
   407  	for _, arg := range search.CleanPatterns(rawArgs) {
   408  		q, err := newQuery(arg)
   409  		if err != nil {
   410  			base.Error(err)
   411  			continue
   412  		}
   413  
   414  		if q.version == "none" {
   415  			switch q.pattern {
   416  			case "go":
   417  				base.Errorf("go: cannot use go@none")
   418  				continue
   419  			case "toolchain":
   420  				dropToolchain = true
   421  				continue
   422  			}
   423  		}
   424  
   425  		// If there were no arguments, CleanPatterns returns ".". Set the raw
   426  		// string back to "" for better errors.
   427  		if len(rawArgs) == 0 {
   428  			q.raw = ""
   429  		}
   430  
   431  		// Guard against 'go get x.go', a common mistake.
   432  		// Note that package and module paths may end with '.go', so only print an error
   433  		// if the argument has no version and either has no slash or refers to an existing file.
   434  		if strings.HasSuffix(q.raw, ".go") && q.rawVersion == "" {
   435  			if !strings.Contains(q.raw, "/") {
   436  				base.Errorf("go: %s: arguments must be package or module paths", q.raw)
   437  				continue
   438  			}
   439  			if fi, err := os.Stat(q.raw); err == nil && !fi.IsDir() {
   440  				base.Errorf("go: %s exists as a file, but 'go get' requires package arguments", q.raw)
   441  				continue
   442  			}
   443  		}
   444  
   445  		queries = append(queries, q)
   446  	}
   447  
   448  	return dropToolchain, queries
   449  }
   450  
   451  type resolver struct {
   452  	localQueries      []*query // queries for absolute or relative paths
   453  	pathQueries       []*query // package path literal queries in original order
   454  	wildcardQueries   []*query // path wildcard queries in original order
   455  	patternAllQueries []*query // queries with the pattern "all"
   456  
   457  	// Indexed "none" queries. These are also included in the slices above;
   458  	// they are indexed here to speed up noneForPath.
   459  	nonesByPath   map[string]*query // path-literal "@none" queries indexed by path
   460  	wildcardNones []*query          // wildcard "@none" queries
   461  
   462  	// resolvedVersion maps each module path to the version of that module that
   463  	// must be selected in the final build list, along with the first query
   464  	// that resolved the module to that version (the “reason”).
   465  	resolvedVersion map[string]versionReason
   466  
   467  	buildList        []module.Version
   468  	buildListVersion map[string]string // index of buildList (module path → version)
   469  
   470  	initialVersion map[string]string // index of the initial build list at the start of 'go get'
   471  
   472  	missing []pathSet // candidates for missing transitive dependencies
   473  
   474  	work *par.Queue
   475  
   476  	matchInModuleCache par.ErrCache[matchInModuleKey, []string]
   477  }
   478  
   479  type versionReason struct {
   480  	version string
   481  	reason  *query
   482  }
   483  
   484  type matchInModuleKey struct {
   485  	pattern string
   486  	m       module.Version
   487  }
   488  
   489  func newResolver(ctx context.Context, queries []*query) *resolver {
   490  	// LoadModGraph also sets modload.Target, which is needed by various resolver
   491  	// methods.
   492  	mg, err := modload.LoadModGraph(ctx, "")
   493  	if err != nil {
   494  		toolchain.SwitchOrFatal(ctx, err)
   495  	}
   496  
   497  	buildList := mg.BuildList()
   498  	initialVersion := make(map[string]string, len(buildList))
   499  	for _, m := range buildList {
   500  		initialVersion[m.Path] = m.Version
   501  	}
   502  
   503  	r := &resolver{
   504  		work:             par.NewQueue(runtime.GOMAXPROCS(0)),
   505  		resolvedVersion:  map[string]versionReason{},
   506  		buildList:        buildList,
   507  		buildListVersion: initialVersion,
   508  		initialVersion:   initialVersion,
   509  		nonesByPath:      map[string]*query{},
   510  	}
   511  
   512  	for _, q := range queries {
   513  		if q.pattern == "all" {
   514  			r.patternAllQueries = append(r.patternAllQueries, q)
   515  		} else if q.patternIsLocal {
   516  			r.localQueries = append(r.localQueries, q)
   517  		} else if q.isWildcard() {
   518  			r.wildcardQueries = append(r.wildcardQueries, q)
   519  		} else {
   520  			r.pathQueries = append(r.pathQueries, q)
   521  		}
   522  
   523  		if q.version == "none" {
   524  			// Index "none" queries to make noneForPath more efficient.
   525  			if q.isWildcard() {
   526  				r.wildcardNones = append(r.wildcardNones, q)
   527  			} else {
   528  				// All "<path>@none" queries for the same path are identical; we only
   529  				// need to index one copy.
   530  				r.nonesByPath[q.pattern] = q
   531  			}
   532  		}
   533  	}
   534  
   535  	return r
   536  }
   537  
   538  // initialSelected returns the version of the module with the given path that
   539  // was selected at the start of this 'go get' invocation.
   540  func (r *resolver) initialSelected(mPath string) (version string) {
   541  	v, ok := r.initialVersion[mPath]
   542  	if !ok {
   543  		return "none"
   544  	}
   545  	return v
   546  }
   547  
   548  // selected returns the version of the module with the given path that is
   549  // selected in the resolver's current build list.
   550  func (r *resolver) selected(mPath string) (version string) {
   551  	v, ok := r.buildListVersion[mPath]
   552  	if !ok {
   553  		return "none"
   554  	}
   555  	return v
   556  }
   557  
   558  // noneForPath returns a "none" query matching the given module path,
   559  // or found == false if no such query exists.
   560  func (r *resolver) noneForPath(mPath string) (nq *query, found bool) {
   561  	if nq = r.nonesByPath[mPath]; nq != nil {
   562  		return nq, true
   563  	}
   564  	for _, nq := range r.wildcardNones {
   565  		if nq.matchesPath(mPath) {
   566  			return nq, true
   567  		}
   568  	}
   569  	return nil, false
   570  }
   571  
   572  // queryModule wraps modload.Query, substituting r.checkAllowedOr to decide
   573  // allowed versions.
   574  func (r *resolver) queryModule(ctx context.Context, mPath, query string, selected func(string) string) (module.Version, error) {
   575  	current := r.initialSelected(mPath)
   576  	rev, err := modload.Query(ctx, mPath, query, current, r.checkAllowedOr(query, selected))
   577  	if err != nil {
   578  		return module.Version{}, err
   579  	}
   580  	return module.Version{Path: mPath, Version: rev.Version}, nil
   581  }
   582  
   583  // queryPackages wraps modload.QueryPackage, substituting r.checkAllowedOr to
   584  // decide allowed versions.
   585  func (r *resolver) queryPackages(ctx context.Context, pattern, query string, selected func(string) string) (pkgMods []module.Version, err error) {
   586  	results, err := modload.QueryPackages(ctx, pattern, query, selected, r.checkAllowedOr(query, selected))
   587  	if len(results) > 0 {
   588  		pkgMods = make([]module.Version, 0, len(results))
   589  		for _, qr := range results {
   590  			pkgMods = append(pkgMods, qr.Mod)
   591  		}
   592  	}
   593  	return pkgMods, err
   594  }
   595  
   596  // queryPattern wraps modload.QueryPattern, substituting r.checkAllowedOr to
   597  // decide allowed versions.
   598  func (r *resolver) queryPattern(ctx context.Context, pattern, query string, selected func(string) string) (pkgMods []module.Version, mod module.Version, err error) {
   599  	results, modOnly, err := modload.QueryPattern(ctx, pattern, query, selected, r.checkAllowedOr(query, selected))
   600  	if len(results) > 0 {
   601  		pkgMods = make([]module.Version, 0, len(results))
   602  		for _, qr := range results {
   603  			pkgMods = append(pkgMods, qr.Mod)
   604  		}
   605  	}
   606  	if modOnly != nil {
   607  		mod = modOnly.Mod
   608  	}
   609  	return pkgMods, mod, err
   610  }
   611  
   612  // checkAllowedOr is like modload.CheckAllowed, but it always allows the requested
   613  // and current versions (even if they are retracted or otherwise excluded).
   614  func (r *resolver) checkAllowedOr(requested string, selected func(string) string) modload.AllowedFunc {
   615  	return func(ctx context.Context, m module.Version) error {
   616  		if m.Version == requested {
   617  			return modload.CheckExclusions(ctx, m)
   618  		}
   619  		if (requested == "upgrade" || requested == "patch") && m.Version == selected(m.Path) {
   620  			return nil
   621  		}
   622  		return modload.CheckAllowed(ctx, m)
   623  	}
   624  }
   625  
   626  // matchInModule is a caching wrapper around modload.MatchInModule.
   627  func (r *resolver) matchInModule(ctx context.Context, pattern string, m module.Version) (packages []string, err error) {
   628  	return r.matchInModuleCache.Do(matchInModuleKey{pattern, m}, func() ([]string, error) {
   629  		match := modload.MatchInModule(ctx, pattern, m, imports.AnyTags())
   630  		if len(match.Errs) > 0 {
   631  			return match.Pkgs, match.Errs[0]
   632  		}
   633  		return match.Pkgs, nil
   634  	})
   635  }
   636  
   637  // queryNone adds a candidate set to q for each module matching q.pattern.
   638  // Each candidate set has only one possible module version: the matched
   639  // module at version "none".
   640  //
   641  // We interpret arguments to 'go get' as packages first, and fall back to
   642  // modules second. However, no module exists at version "none", and therefore no
   643  // package exists at that version either: we know that the argument cannot match
   644  // any packages, and thus it must match modules instead.
   645  func (r *resolver) queryNone(ctx context.Context, q *query) {
   646  	if search.IsMetaPackage(q.pattern) {
   647  		panic(fmt.Sprintf("internal error: queryNone called with pattern %q", q.pattern))
   648  	}
   649  
   650  	if !q.isWildcard() {
   651  		q.pathOnce(q.pattern, func() pathSet {
   652  			hasModRoot := modload.HasModRoot()
   653  			if hasModRoot && modload.MainModules.Contains(q.pattern) {
   654  				v := module.Version{Path: q.pattern}
   655  				// The user has explicitly requested to downgrade their own module to
   656  				// version "none". This is not an entirely unreasonable request: it
   657  				// could plausibly mean “downgrade away everything that depends on any
   658  				// explicit version of the main module”, or “downgrade away the
   659  				// package with the same path as the main module, found in a module
   660  				// with a prefix of the main module's path”.
   661  				//
   662  				// However, neither of those behaviors would be consistent with the
   663  				// plain meaning of the query. To try to reduce confusion, reject the
   664  				// query explicitly.
   665  				return errSet(&modload.QueryMatchesMainModulesError{MainModules: []module.Version{v}, Pattern: q.pattern, Query: q.version})
   666  			}
   667  
   668  			return pathSet{mod: module.Version{Path: q.pattern, Version: "none"}}
   669  		})
   670  	}
   671  
   672  	for _, curM := range r.buildList {
   673  		if !q.matchesPath(curM.Path) {
   674  			continue
   675  		}
   676  		q.pathOnce(curM.Path, func() pathSet {
   677  			if modload.HasModRoot() && curM.Version == "" && modload.MainModules.Contains(curM.Path) {
   678  				return errSet(&modload.QueryMatchesMainModulesError{MainModules: []module.Version{curM}, Pattern: q.pattern, Query: q.version})
   679  			}
   680  			return pathSet{mod: module.Version{Path: curM.Path, Version: "none"}}
   681  		})
   682  	}
   683  }
   684  
   685  func (r *resolver) performLocalQueries(ctx context.Context) {
   686  	for _, q := range r.localQueries {
   687  		q.pathOnce(q.pattern, func() pathSet {
   688  			absDetail := ""
   689  			if !filepath.IsAbs(q.pattern) {
   690  				if absPath, err := filepath.Abs(q.pattern); err == nil {
   691  					absDetail = fmt.Sprintf(" (%s)", absPath)
   692  				}
   693  			}
   694  
   695  			// Absolute paths like C:\foo and relative paths like ../foo... are
   696  			// restricted to matching packages in the main module.
   697  			pkgPattern, mainModule := modload.MainModules.DirImportPath(ctx, q.pattern)
   698  			if pkgPattern == "." {
   699  				modload.MustHaveModRoot()
   700  				var modRoots []string
   701  				for _, m := range modload.MainModules.Versions() {
   702  					modRoots = append(modRoots, modload.MainModules.ModRoot(m))
   703  				}
   704  				var plural string
   705  				if len(modRoots) != 1 {
   706  					plural = "s"
   707  				}
   708  				return errSet(fmt.Errorf("%s%s is not within module%s rooted at %s", q.pattern, absDetail, plural, strings.Join(modRoots, ", ")))
   709  			}
   710  
   711  			match := modload.MatchInModule(ctx, pkgPattern, mainModule, imports.AnyTags())
   712  			if len(match.Errs) > 0 {
   713  				return pathSet{err: match.Errs[0]}
   714  			}
   715  
   716  			if len(match.Pkgs) == 0 {
   717  				if q.raw == "" || q.raw == "." {
   718  					return errSet(fmt.Errorf("no package to get in current directory"))
   719  				}
   720  				if !q.isWildcard() {
   721  					modload.MustHaveModRoot()
   722  					return errSet(fmt.Errorf("%s%s is not a package in module rooted at %s", q.pattern, absDetail, modload.MainModules.ModRoot(mainModule)))
   723  				}
   724  				search.WarnUnmatched([]*search.Match{match})
   725  				return pathSet{}
   726  			}
   727  
   728  			return pathSet{pkgMods: []module.Version{mainModule}}
   729  		})
   730  	}
   731  }
   732  
   733  // performWildcardQueries populates the candidates for each query whose pattern
   734  // is a wildcard.
   735  //
   736  // The candidates for a given module path matching (or containing a package
   737  // matching) a wildcard query depend only on the initial build list, but the set
   738  // of modules may be expanded by other queries, so wildcard queries need to be
   739  // re-evaluated whenever a potentially-matching module path is added to the
   740  // build list.
   741  func (r *resolver) performWildcardQueries(ctx context.Context) {
   742  	for _, q := range r.wildcardQueries {
   743  		q := q
   744  		r.work.Add(func() {
   745  			if q.version == "none" {
   746  				r.queryNone(ctx, q)
   747  			} else {
   748  				r.queryWildcard(ctx, q)
   749  			}
   750  		})
   751  	}
   752  	<-r.work.Idle()
   753  }
   754  
   755  // queryWildcard adds a candidate set to q for each module for which:
   756  //   - some version of the module is already in the build list, and
   757  //   - that module exists at some version matching q.version, and
   758  //   - either the module path itself matches q.pattern, or some package within
   759  //     the module at q.version matches q.pattern.
   760  func (r *resolver) queryWildcard(ctx context.Context, q *query) {
   761  	// For wildcard patterns, modload.QueryPattern only identifies modules
   762  	// matching the prefix of the path before the wildcard. However, the build
   763  	// list may already contain other modules with matching packages, and we
   764  	// should consider those modules to satisfy the query too.
   765  	// We want to match any packages in existing dependencies, but we only want to
   766  	// resolve new dependencies if nothing else turns up.
   767  	for _, curM := range r.buildList {
   768  		if !q.canMatchInModule(curM.Path) {
   769  			continue
   770  		}
   771  		q.pathOnce(curM.Path, func() pathSet {
   772  			if _, hit := r.noneForPath(curM.Path); hit {
   773  				// This module is being removed, so it will no longer be in the build list
   774  				// (and thus will no longer match the pattern).
   775  				return pathSet{}
   776  			}
   777  
   778  			if modload.MainModules.Contains(curM.Path) && !versionOkForMainModule(q.version) {
   779  				if q.matchesPath(curM.Path) {
   780  					return errSet(&modload.QueryMatchesMainModulesError{
   781  						MainModules: []module.Version{curM},
   782  						Pattern:     q.pattern,
   783  						Query:       q.version,
   784  					})
   785  				}
   786  
   787  				packages, err := r.matchInModule(ctx, q.pattern, curM)
   788  				if err != nil {
   789  					return errSet(err)
   790  				}
   791  				if len(packages) > 0 {
   792  					return errSet(&modload.QueryMatchesPackagesInMainModuleError{
   793  						Pattern:  q.pattern,
   794  						Query:    q.version,
   795  						Packages: packages,
   796  					})
   797  				}
   798  
   799  				return r.tryWildcard(ctx, q, curM)
   800  			}
   801  
   802  			m, err := r.queryModule(ctx, curM.Path, q.version, r.initialSelected)
   803  			if err != nil {
   804  				if !isNoSuchModuleVersion(err) {
   805  					// We can't tell whether a matching version exists.
   806  					return errSet(err)
   807  				}
   808  				// There is no version of curM.Path matching the query.
   809  
   810  				// We haven't checked whether curM contains any matching packages at its
   811  				// currently-selected version, or whether curM.Path itself matches q. If
   812  				// either of those conditions holds, *and* no other query changes the
   813  				// selected version of curM, then we will fail in checkWildcardVersions.
   814  				// (This could be an error, but it's too soon to tell.)
   815  				//
   816  				// However, even then the transitive requirements of some other query
   817  				// may downgrade this module out of the build list entirely, in which
   818  				// case the pattern will no longer include it and it won't be an error.
   819  				//
   820  				// Either way, punt on the query rather than erroring out just yet.
   821  				return pathSet{}
   822  			}
   823  
   824  			return r.tryWildcard(ctx, q, m)
   825  		})
   826  	}
   827  
   828  	// Even if no modules matched, we shouldn't query for a new module to provide
   829  	// the pattern yet: some other query may yet induce a new requirement that
   830  	// will match the wildcard. Instead, we'll check in findMissingWildcards.
   831  }
   832  
   833  // tryWildcard returns a pathSet for module m matching query q.
   834  // If m does not actually match q, tryWildcard returns an empty pathSet.
   835  func (r *resolver) tryWildcard(ctx context.Context, q *query, m module.Version) pathSet {
   836  	mMatches := q.matchesPath(m.Path)
   837  	packages, err := r.matchInModule(ctx, q.pattern, m)
   838  	if err != nil {
   839  		return errSet(err)
   840  	}
   841  	if len(packages) > 0 {
   842  		return pathSet{pkgMods: []module.Version{m}}
   843  	}
   844  	if mMatches {
   845  		return pathSet{mod: m}
   846  	}
   847  	return pathSet{}
   848  }
   849  
   850  // findMissingWildcards adds a candidate set for each query in r.wildcardQueries
   851  // that has not yet resolved to any version containing packages.
   852  func (r *resolver) findMissingWildcards(ctx context.Context) {
   853  	for _, q := range r.wildcardQueries {
   854  		if q.version == "none" || q.matchesPackages {
   855  			continue // q is not “missing”
   856  		}
   857  		r.work.Add(func() {
   858  			q.pathOnce(q.pattern, func() pathSet {
   859  				pkgMods, mod, err := r.queryPattern(ctx, q.pattern, q.version, r.initialSelected)
   860  				if err != nil {
   861  					if isNoSuchPackageVersion(err) && len(q.resolved) > 0 {
   862  						// q already resolved one or more modules but matches no packages.
   863  						// That's ok: this pattern is just a module pattern, and we don't
   864  						// need to add any more modules to satisfy it.
   865  						return pathSet{}
   866  					}
   867  					return errSet(err)
   868  				}
   869  
   870  				return pathSet{pkgMods: pkgMods, mod: mod}
   871  			})
   872  		})
   873  	}
   874  	<-r.work.Idle()
   875  }
   876  
   877  // checkWildcardVersions reports an error if any module in the build list has a
   878  // path (or contains a package) matching a query with a wildcard pattern, but
   879  // has a selected version that does *not* match the query.
   880  func (r *resolver) checkWildcardVersions(ctx context.Context) {
   881  	defer base.ExitIfErrors()
   882  
   883  	for _, q := range r.wildcardQueries {
   884  		for _, curM := range r.buildList {
   885  			if !q.canMatchInModule(curM.Path) {
   886  				continue
   887  			}
   888  			if !q.matchesPath(curM.Path) {
   889  				packages, err := r.matchInModule(ctx, q.pattern, curM)
   890  				if len(packages) == 0 {
   891  					if err != nil {
   892  						reportError(q, err)
   893  					}
   894  					continue // curM is not relevant to q.
   895  				}
   896  			}
   897  
   898  			rev, err := r.queryModule(ctx, curM.Path, q.version, r.initialSelected)
   899  			if err != nil {
   900  				reportError(q, err)
   901  				continue
   902  			}
   903  			if rev.Version == curM.Version {
   904  				continue // curM already matches q.
   905  			}
   906  
   907  			if !q.matchesPath(curM.Path) {
   908  				m := module.Version{Path: curM.Path, Version: rev.Version}
   909  				packages, err := r.matchInModule(ctx, q.pattern, m)
   910  				if err != nil {
   911  					reportError(q, err)
   912  					continue
   913  				}
   914  				if len(packages) == 0 {
   915  					// curM at its original version contains a path matching q.pattern,
   916  					// but at rev.Version it does not, so (somewhat paradoxically) if
   917  					// we changed the version of curM it would no longer match the query.
   918  					var version any = m
   919  					if rev.Version != q.version {
   920  						version = fmt.Sprintf("%s@%s (%s)", m.Path, q.version, m.Version)
   921  					}
   922  					reportError(q, fmt.Errorf("%v matches packages in %v but not %v: specify a different version for module %s", q, curM, version, m.Path))
   923  					continue
   924  				}
   925  			}
   926  
   927  			// Since queryModule succeeded and either curM or one of the packages it
   928  			// contains matches q.pattern, we should have either selected the version
   929  			// of curM matching q, or reported a conflict error (and exited).
   930  			// If we're still here and the version doesn't match,
   931  			// something has gone very wrong.
   932  			reportError(q, fmt.Errorf("internal error: selected %v instead of %v", curM, rev.Version))
   933  		}
   934  	}
   935  }
   936  
   937  // performPathQueries populates the candidates for each query whose pattern is
   938  // a path literal.
   939  //
   940  // The candidate packages and modules for path literals depend only on the
   941  // initial build list, not the current build list, so we only need to query path
   942  // literals once.
   943  func (r *resolver) performPathQueries(ctx context.Context) {
   944  	for _, q := range r.pathQueries {
   945  		q := q
   946  		r.work.Add(func() {
   947  			if q.version == "none" {
   948  				r.queryNone(ctx, q)
   949  			} else {
   950  				r.queryPath(ctx, q)
   951  			}
   952  		})
   953  	}
   954  	<-r.work.Idle()
   955  }
   956  
   957  // queryPath adds a candidate set to q for the package with path q.pattern.
   958  // The candidate set consists of all modules that could provide q.pattern
   959  // and have a version matching q, plus (if it exists) the module whose path
   960  // is itself q.pattern (at a matching version).
   961  func (r *resolver) queryPath(ctx context.Context, q *query) {
   962  	q.pathOnce(q.pattern, func() pathSet {
   963  		if search.IsMetaPackage(q.pattern) || q.isWildcard() {
   964  			panic(fmt.Sprintf("internal error: queryPath called with pattern %q", q.pattern))
   965  		}
   966  		if q.version == "none" {
   967  			panic(`internal error: queryPath called with version "none"`)
   968  		}
   969  
   970  		if search.IsStandardImportPath(q.pattern) {
   971  			stdOnly := module.Version{}
   972  			packages, _ := r.matchInModule(ctx, q.pattern, stdOnly)
   973  			if len(packages) > 0 {
   974  				if q.rawVersion != "" {
   975  					return errSet(fmt.Errorf("can't request explicit version %q of standard library package %s", q.version, q.pattern))
   976  				}
   977  
   978  				q.matchesPackages = true
   979  				return pathSet{} // No module needed for standard library.
   980  			}
   981  		}
   982  
   983  		pkgMods, mod, err := r.queryPattern(ctx, q.pattern, q.version, r.initialSelected)
   984  		if err != nil {
   985  			return errSet(err)
   986  		}
   987  		return pathSet{pkgMods: pkgMods, mod: mod}
   988  	})
   989  }
   990  
   991  // performPatternAllQueries populates the candidates for each query whose
   992  // pattern is "all".
   993  //
   994  // The candidate modules for a given package in "all" depend only on the initial
   995  // build list, but we cannot follow the dependencies of a given package until we
   996  // know which candidate is selected — and that selection may depend on the
   997  // results of other queries. We need to re-evaluate the "all" queries whenever
   998  // the module for one or more packages in "all" are resolved.
   999  func (r *resolver) performPatternAllQueries(ctx context.Context) {
  1000  	if len(r.patternAllQueries) == 0 {
  1001  		return
  1002  	}
  1003  
  1004  	findPackage := func(ctx context.Context, path string, m module.Version) (versionOk bool) {
  1005  		versionOk = true
  1006  		for _, q := range r.patternAllQueries {
  1007  			q.pathOnce(path, func() pathSet {
  1008  				pkgMods, err := r.queryPackages(ctx, path, q.version, r.initialSelected)
  1009  				if len(pkgMods) != 1 || pkgMods[0] != m {
  1010  					// There are candidates other than m for the given path, so we can't
  1011  					// be certain that m will actually be the module selected to provide
  1012  					// the package. Don't load its dependencies just yet, because they
  1013  					// might no longer be dependencies after we resolve the correct
  1014  					// version.
  1015  					versionOk = false
  1016  				}
  1017  				return pathSet{pkgMods: pkgMods, err: err}
  1018  			})
  1019  		}
  1020  		return versionOk
  1021  	}
  1022  
  1023  	r.loadPackages(ctx, []string{"all"}, findPackage)
  1024  
  1025  	// Since we built up the candidate lists concurrently, they may be in a
  1026  	// nondeterministic order. We want 'go get' to be fully deterministic,
  1027  	// including in which errors it chooses to report, so sort the candidates
  1028  	// into a deterministic-but-arbitrary order.
  1029  	for _, q := range r.patternAllQueries {
  1030  		sort.Slice(q.candidates, func(i, j int) bool {
  1031  			return q.candidates[i].path < q.candidates[j].path
  1032  		})
  1033  	}
  1034  }
  1035  
  1036  // findAndUpgradeImports returns a pathSet for each package that is not yet
  1037  // in the build list but is transitively imported by the packages matching the
  1038  // given queries (which must already have been resolved).
  1039  //
  1040  // If the getU flag ("-u") is set, findAndUpgradeImports also returns a
  1041  // pathSet for each module that is not constrained by any other
  1042  // command-line argument and has an available matching upgrade.
  1043  func (r *resolver) findAndUpgradeImports(ctx context.Context, queries []*query) (upgrades []pathSet) {
  1044  	patterns := make([]string, 0, len(queries))
  1045  	for _, q := range queries {
  1046  		if q.matchesPackages {
  1047  			patterns = append(patterns, q.pattern)
  1048  		}
  1049  	}
  1050  	if len(patterns) == 0 {
  1051  		return nil
  1052  	}
  1053  
  1054  	// mu guards concurrent writes to upgrades, which will be sorted
  1055  	// (to restore determinism) after loading.
  1056  	var mu sync.Mutex
  1057  
  1058  	findPackage := func(ctx context.Context, path string, m module.Version) (versionOk bool) {
  1059  		version := "latest"
  1060  		if m.Path != "" {
  1061  			if getU.version == "" {
  1062  				// The user did not request that we upgrade transitive dependencies.
  1063  				return true
  1064  			}
  1065  			if _, ok := r.resolvedVersion[m.Path]; ok {
  1066  				// We cannot upgrade m implicitly because its version is determined by
  1067  				// an explicit pattern argument.
  1068  				return true
  1069  			}
  1070  			version = getU.version
  1071  		}
  1072  
  1073  		// Unlike other queries, the "-u" flag upgrades relative to the build list
  1074  		// after applying changes so far, not the initial build list.
  1075  		// This is for two reasons:
  1076  		//
  1077  		// 	- The "-u" flag intentionally applies to transitive dependencies,
  1078  		// 	  which may not be known or even resolved in advance of applying
  1079  		// 	  other version changes.
  1080  		//
  1081  		// 	- The "-u" flag, unlike other arguments, does not cause version
  1082  		// 	  conflicts with other queries. (The other query always wins.)
  1083  
  1084  		pkgMods, err := r.queryPackages(ctx, path, version, r.selected)
  1085  		for _, u := range pkgMods {
  1086  			if u == m {
  1087  				// The selected package version is already upgraded appropriately; there
  1088  				// is no need to change it.
  1089  				return true
  1090  			}
  1091  		}
  1092  
  1093  		if err != nil {
  1094  			if isNoSuchPackageVersion(err) || (m.Path == "" && module.CheckPath(path) != nil) {
  1095  				// We can't find the package because it doesn't — or can't — even exist
  1096  				// in any module at the latest version. (Note that invalid module paths
  1097  				// could in general exist due to replacements, so we at least need to
  1098  				// run the query to check those.)
  1099  				//
  1100  				// There is no version change we can make to fix the package, so leave
  1101  				// it unresolved. Either some other query (perhaps a wildcard matching a
  1102  				// newly-added dependency for some other missing package) will fill in
  1103  				// the gaps, or we will report an error (with a better import stack) in
  1104  				// the final LoadPackages call.
  1105  				return true
  1106  			}
  1107  		}
  1108  
  1109  		mu.Lock()
  1110  		upgrades = append(upgrades, pathSet{path: path, pkgMods: pkgMods, err: err})
  1111  		mu.Unlock()
  1112  		return false
  1113  	}
  1114  
  1115  	r.loadPackages(ctx, patterns, findPackage)
  1116  
  1117  	// Since we built up the candidate lists concurrently, they may be in a
  1118  	// nondeterministic order. We want 'go get' to be fully deterministic,
  1119  	// including in which errors it chooses to report, so sort the candidates
  1120  	// into a deterministic-but-arbitrary order.
  1121  	sort.Slice(upgrades, func(i, j int) bool {
  1122  		return upgrades[i].path < upgrades[j].path
  1123  	})
  1124  	return upgrades
  1125  }
  1126  
  1127  // loadPackages loads the packages matching the given patterns, invoking the
  1128  // findPackage function for each package that may require a change to the
  1129  // build list.
  1130  //
  1131  // loadPackages invokes the findPackage function for each package loaded from a
  1132  // module outside the main module. If the module or version that supplies that
  1133  // package needs to be changed due to a query, findPackage may return false
  1134  // and the imports of that package will not be loaded.
  1135  //
  1136  // loadPackages also invokes the findPackage function for each imported package
  1137  // that is neither present in the standard library nor in any module in the
  1138  // build list.
  1139  func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPackage func(ctx context.Context, path string, m module.Version) (versionOk bool)) {
  1140  	opts := modload.PackageOpts{
  1141  		Tags:                     imports.AnyTags(),
  1142  		VendorModulesInGOROOTSrc: true,
  1143  		LoadTests:                *getT,
  1144  		AssumeRootsImported:      true, // After 'go get foo', imports of foo should build.
  1145  		SilencePackageErrors:     true, // May be fixed by subsequent upgrades or downgrades.
  1146  		Switcher:                 new(toolchain.Switcher),
  1147  	}
  1148  
  1149  	opts.AllowPackage = func(ctx context.Context, path string, m module.Version) error {
  1150  		if m.Path == "" || m.Version == "" {
  1151  			// Packages in the standard library and main modules are already at their
  1152  			// latest (and only) available versions.
  1153  			return nil
  1154  		}
  1155  		if ok := findPackage(ctx, path, m); !ok {
  1156  			return errVersionChange
  1157  		}
  1158  		return nil
  1159  	}
  1160  
  1161  	_, pkgs := modload.LoadPackages(ctx, opts, patterns...)
  1162  	for _, path := range pkgs {
  1163  		const (
  1164  			parentPath  = ""
  1165  			parentIsStd = false
  1166  		)
  1167  		_, _, err := modload.Lookup(parentPath, parentIsStd, path)
  1168  		if err == nil {
  1169  			continue
  1170  		}
  1171  		if errors.Is(err, errVersionChange) {
  1172  			// We already added candidates during loading.
  1173  			continue
  1174  		}
  1175  
  1176  		var (
  1177  			importMissing *modload.ImportMissingError
  1178  			ambiguous     *modload.AmbiguousImportError
  1179  		)
  1180  		if !errors.As(err, &importMissing) && !errors.As(err, &ambiguous) {
  1181  			// The package, which is a dependency of something we care about, has some
  1182  			// problem that we can't resolve with a version change.
  1183  			// Leave the error for the final LoadPackages call.
  1184  			continue
  1185  		}
  1186  
  1187  		path := path
  1188  		r.work.Add(func() {
  1189  			findPackage(ctx, path, module.Version{})
  1190  		})
  1191  	}
  1192  	<-r.work.Idle()
  1193  }
  1194  
  1195  // errVersionChange is a sentinel error indicating that a module's version needs
  1196  // to be updated before its dependencies can be loaded.
  1197  var errVersionChange = errors.New("version change needed")
  1198  
  1199  // resolveQueries resolves candidate sets that are attached to the given
  1200  // queries and/or needed to provide the given missing-package dependencies.
  1201  //
  1202  // resolveQueries starts by resolving one module version from each
  1203  // unambiguous pathSet attached to the given queries.
  1204  //
  1205  // If no unambiguous query results in a change to the build list,
  1206  // resolveQueries revisits the ambiguous query candidates and resolves them
  1207  // arbitrarily in order to guarantee forward progress.
  1208  //
  1209  // If all pathSets are resolved without any changes to the build list,
  1210  // resolveQueries returns with changed=false.
  1211  func (r *resolver) resolveQueries(ctx context.Context, queries []*query) (changed bool) {
  1212  	defer base.ExitIfErrors()
  1213  
  1214  	// Note: this is O(N²) with the number of pathSets in the worst case.
  1215  	//
  1216  	// We could perhaps get it down to O(N) if we were to index the pathSets
  1217  	// by module path, so that we only revisit a given pathSet when the
  1218  	// version of some module in its containingPackage list has been determined.
  1219  	//
  1220  	// However, N tends to be small, and most candidate sets will include only one
  1221  	// candidate module (so they will be resolved in the first iteration), so for
  1222  	// now we'll stick to the simple O(N²) approach.
  1223  
  1224  	resolved := 0
  1225  	for {
  1226  		prevResolved := resolved
  1227  
  1228  		// If we found modules that were too new, find the max of the required versions
  1229  		// and then try to switch to a newer toolchain.
  1230  		var sw toolchain.Switcher
  1231  		for _, q := range queries {
  1232  			for _, cs := range q.candidates {
  1233  				sw.Error(cs.err)
  1234  			}
  1235  		}
  1236  		// Only switch if we need a newer toolchain.
  1237  		// Otherwise leave the cs.err for reporting later.
  1238  		if sw.NeedSwitch() {
  1239  			sw.Switch(ctx)
  1240  			// If NeedSwitch is true and Switch returns, Switch has failed to locate a newer toolchain.
  1241  			// It printed the errors along with one more about not finding a good toolchain.
  1242  			base.Exit()
  1243  		}
  1244  
  1245  		for _, q := range queries {
  1246  			unresolved := q.candidates[:0]
  1247  
  1248  			for _, cs := range q.candidates {
  1249  				if cs.err != nil {
  1250  					reportError(q, cs.err)
  1251  					resolved++
  1252  					continue
  1253  				}
  1254  
  1255  				filtered, isPackage, m, unique := r.disambiguate(cs)
  1256  				if !unique {
  1257  					unresolved = append(unresolved, filtered)
  1258  					continue
  1259  				}
  1260  
  1261  				if m.Path == "" {
  1262  					// The query is not viable. Choose an arbitrary candidate from
  1263  					// before filtering and “resolve” it to report a conflict.
  1264  					isPackage, m = r.chooseArbitrarily(cs)
  1265  				}
  1266  				if isPackage {
  1267  					q.matchesPackages = true
  1268  				}
  1269  				r.resolve(q, m)
  1270  				resolved++
  1271  			}
  1272  
  1273  			q.candidates = unresolved
  1274  		}
  1275  
  1276  		base.ExitIfErrors()
  1277  		if resolved == prevResolved {
  1278  			break // No unambiguous candidate remains.
  1279  		}
  1280  	}
  1281  
  1282  	if resolved > 0 {
  1283  		if changed = r.updateBuildList(ctx, nil); changed {
  1284  			// The build list has changed, so disregard any remaining ambiguous queries:
  1285  			// they might now be determined by requirements in the build list, which we
  1286  			// would prefer to use instead of arbitrary versions.
  1287  			return true
  1288  		}
  1289  	}
  1290  
  1291  	// The build list will be the same on the next iteration as it was on this
  1292  	// iteration, so any ambiguous queries will remain so. In order to make
  1293  	// progress, resolve them arbitrarily but deterministically.
  1294  	//
  1295  	// If that results in conflicting versions, the user can re-run 'go get'
  1296  	// with additional explicit versions for the conflicting packages or
  1297  	// modules.
  1298  	resolvedArbitrarily := 0
  1299  	for _, q := range queries {
  1300  		for _, cs := range q.candidates {
  1301  			isPackage, m := r.chooseArbitrarily(cs)
  1302  			if isPackage {
  1303  				q.matchesPackages = true
  1304  			}
  1305  			r.resolve(q, m)
  1306  			resolvedArbitrarily++
  1307  		}
  1308  	}
  1309  	if resolvedArbitrarily > 0 {
  1310  		changed = r.updateBuildList(ctx, nil)
  1311  	}
  1312  	return changed
  1313  }
  1314  
  1315  // applyUpgrades disambiguates candidate sets that are needed to upgrade (or
  1316  // provide) transitive dependencies imported by previously-resolved packages.
  1317  //
  1318  // applyUpgrades modifies the build list by adding one module version from each
  1319  // pathSet in upgrades, then downgrading (or further upgrading) those modules as
  1320  // needed to maintain any already-resolved versions of other modules.
  1321  // applyUpgrades does not mark the new versions as resolved, so they can still
  1322  // be further modified by other queries (such as wildcards).
  1323  //
  1324  // If all pathSets are resolved without any changes to the build list,
  1325  // applyUpgrades returns with changed=false.
  1326  func (r *resolver) applyUpgrades(ctx context.Context, upgrades []pathSet) (changed bool) {
  1327  	defer base.ExitIfErrors()
  1328  
  1329  	// Arbitrarily add a "latest" version that provides each missing package, but
  1330  	// do not mark the version as resolved: we still want to allow the explicit
  1331  	// queries to modify the resulting versions.
  1332  	var tentative []module.Version
  1333  	for _, cs := range upgrades {
  1334  		if cs.err != nil {
  1335  			base.Error(cs.err)
  1336  			continue
  1337  		}
  1338  
  1339  		filtered, _, m, unique := r.disambiguate(cs)
  1340  		if !unique {
  1341  			_, m = r.chooseArbitrarily(filtered)
  1342  		}
  1343  		if m.Path == "" {
  1344  			// There is no viable candidate for the missing package.
  1345  			// Leave it unresolved.
  1346  			continue
  1347  		}
  1348  		tentative = append(tentative, m)
  1349  	}
  1350  	base.ExitIfErrors()
  1351  
  1352  	changed = r.updateBuildList(ctx, tentative)
  1353  	return changed
  1354  }
  1355  
  1356  // disambiguate eliminates candidates from cs that conflict with other module
  1357  // versions that have already been resolved. If there is only one (unique)
  1358  // remaining candidate, disambiguate returns that candidate, along with
  1359  // an indication of whether that result interprets cs.path as a package
  1360  //
  1361  // Note: we're only doing very simple disambiguation here. The goal is to
  1362  // reproduce the user's intent, not to find a solution that a human couldn't.
  1363  // In the vast majority of cases, we expect only one module per pathSet,
  1364  // but we want to give some minimal additional tools so that users can add an
  1365  // extra argument or two on the command line to resolve simple ambiguities.
  1366  func (r *resolver) disambiguate(cs pathSet) (filtered pathSet, isPackage bool, m module.Version, unique bool) {
  1367  	if len(cs.pkgMods) == 0 && cs.mod.Path == "" {
  1368  		panic("internal error: resolveIfUnambiguous called with empty pathSet")
  1369  	}
  1370  
  1371  	for _, m := range cs.pkgMods {
  1372  		if _, ok := r.noneForPath(m.Path); ok {
  1373  			// A query with version "none" forces the candidate module to version
  1374  			// "none", so we cannot use any other version for that module.
  1375  			continue
  1376  		}
  1377  
  1378  		if modload.MainModules.Contains(m.Path) {
  1379  			if m.Version == "" {
  1380  				return pathSet{}, true, m, true
  1381  			}
  1382  			// A main module can only be set to its own version.
  1383  			continue
  1384  		}
  1385  
  1386  		vr, ok := r.resolvedVersion[m.Path]
  1387  		if !ok {
  1388  			// m is a viable answer to the query, but other answers may also
  1389  			// still be viable.
  1390  			filtered.pkgMods = append(filtered.pkgMods, m)
  1391  			continue
  1392  		}
  1393  
  1394  		if vr.version != m.Version {
  1395  			// Some query forces the candidate module to a version other than this
  1396  			// one.
  1397  			//
  1398  			// The command could be something like
  1399  			//
  1400  			// 	go get example.com/foo/bar@none example.com/foo/bar/baz@latest
  1401  			//
  1402  			// in which case we *cannot* resolve the package from
  1403  			// example.com/foo/bar (because it is constrained to version
  1404  			// "none") and must fall through to module example.com/foo@latest.
  1405  			continue
  1406  		}
  1407  
  1408  		// Some query forces the candidate module *to* the candidate version.
  1409  		// As a result, this candidate is the only viable choice to provide
  1410  		// its package(s): any other choice would result in an ambiguous import
  1411  		// for this path.
  1412  		//
  1413  		// For example, consider the command
  1414  		//
  1415  		// 	go get example.com/foo@latest example.com/foo/bar/baz@latest
  1416  		//
  1417  		// If modules example.com/foo and example.com/foo/bar both provide
  1418  		// package example.com/foo/bar/baz, then we *must* resolve the package
  1419  		// from example.com/foo: if we instead resolved it from
  1420  		// example.com/foo/bar, we would have two copies of the package.
  1421  		return pathSet{}, true, m, true
  1422  	}
  1423  
  1424  	if cs.mod.Path != "" {
  1425  		vr, ok := r.resolvedVersion[cs.mod.Path]
  1426  		if !ok || vr.version == cs.mod.Version {
  1427  			filtered.mod = cs.mod
  1428  		}
  1429  	}
  1430  
  1431  	if len(filtered.pkgMods) == 1 &&
  1432  		(filtered.mod.Path == "" || filtered.mod == filtered.pkgMods[0]) {
  1433  		// Exactly one viable module contains the package with the given path
  1434  		// (by far the common case), so we can resolve it unambiguously.
  1435  		return pathSet{}, true, filtered.pkgMods[0], true
  1436  	}
  1437  
  1438  	if len(filtered.pkgMods) == 0 {
  1439  		// All modules that could provide the path as a package conflict with other
  1440  		// resolved arguments. If it can refer to a module instead, return that;
  1441  		// otherwise, this pathSet cannot be resolved (and we will return the
  1442  		// zero module.Version).
  1443  		return pathSet{}, false, filtered.mod, true
  1444  	}
  1445  
  1446  	// The query remains ambiguous: there are at least two different modules
  1447  	// to which cs.path could refer.
  1448  	return filtered, false, module.Version{}, false
  1449  }
  1450  
  1451  // chooseArbitrarily returns an arbitrary (but deterministic) module version
  1452  // from among those in the given set.
  1453  //
  1454  // chooseArbitrarily prefers module paths that were already in the build list at
  1455  // the start of 'go get', prefers modules that provide packages over those that
  1456  // do not, and chooses the first module meeting those criteria (so biases toward
  1457  // longer paths).
  1458  func (r *resolver) chooseArbitrarily(cs pathSet) (isPackage bool, m module.Version) {
  1459  	// Prefer to upgrade some module that was already in the build list.
  1460  	for _, m := range cs.pkgMods {
  1461  		if r.initialSelected(m.Path) != "none" {
  1462  			return true, m
  1463  		}
  1464  	}
  1465  
  1466  	// Otherwise, arbitrarily choose the first module that provides the package.
  1467  	if len(cs.pkgMods) > 0 {
  1468  		return true, cs.pkgMods[0]
  1469  	}
  1470  
  1471  	return false, cs.mod
  1472  }
  1473  
  1474  // checkPackageProblems reloads packages for the given patterns and reports
  1475  // missing and ambiguous package errors. It also reports retractions and
  1476  // deprecations for resolved modules and modules needed to build named packages.
  1477  // It also adds a sum for each updated module in the build list if we had one
  1478  // before and didn't get one while loading packages.
  1479  //
  1480  // We skip missing-package errors earlier in the process, since we want to
  1481  // resolve pathSets ourselves, but at that point, we don't have enough context
  1482  // to log the package-import chains leading to each error.
  1483  func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []string) {
  1484  	defer base.ExitIfErrors()
  1485  
  1486  	// Gather information about modules we might want to load retractions and
  1487  	// deprecations for. Loading this metadata requires at least one version
  1488  	// lookup per module, and we don't want to load information that's neither
  1489  	// relevant nor actionable.
  1490  	type modFlags int
  1491  	const (
  1492  		resolved modFlags = 1 << iota // version resolved by 'go get'
  1493  		named                         // explicitly named on command line or provides a named package
  1494  		hasPkg                        // needed to build named packages
  1495  		direct                        // provides a direct dependency of the main module
  1496  	)
  1497  	relevantMods := make(map[module.Version]modFlags)
  1498  	for path, reason := range r.resolvedVersion {
  1499  		m := module.Version{Path: path, Version: reason.version}
  1500  		relevantMods[m] |= resolved
  1501  	}
  1502  
  1503  	// Reload packages, reporting errors for missing and ambiguous imports.
  1504  	if len(pkgPatterns) > 0 {
  1505  		// LoadPackages will print errors (since it has more context) but will not
  1506  		// exit, since we need to load retractions later.
  1507  		pkgOpts := modload.PackageOpts{
  1508  			VendorModulesInGOROOTSrc: true,
  1509  			LoadTests:                *getT,
  1510  			ResolveMissingImports:    false,
  1511  			AllowErrors:              true,
  1512  			SilenceNoGoErrors:        true,
  1513  		}
  1514  		matches, pkgs := modload.LoadPackages(ctx, pkgOpts, pkgPatterns...)
  1515  		for _, m := range matches {
  1516  			if len(m.Errs) > 0 {
  1517  				base.SetExitStatus(1)
  1518  				break
  1519  			}
  1520  		}
  1521  		for _, pkg := range pkgs {
  1522  			if dir, _, err := modload.Lookup("", false, pkg); err != nil {
  1523  				if dir != "" && errors.Is(err, imports.ErrNoGo) {
  1524  					// Since dir is non-empty, we must have located source files
  1525  					// associated with either the package or its test — ErrNoGo must
  1526  					// indicate that none of those source files happen to apply in this
  1527  					// configuration. If we are actually building the package (no -d
  1528  					// flag), we will report the problem then; otherwise, assume that the
  1529  					// user is going to build or test this package in some other
  1530  					// configuration and suppress the error.
  1531  					continue
  1532  				}
  1533  
  1534  				base.SetExitStatus(1)
  1535  				if ambiguousErr := (*modload.AmbiguousImportError)(nil); errors.As(err, &ambiguousErr) {
  1536  					for _, m := range ambiguousErr.Modules {
  1537  						relevantMods[m] |= hasPkg
  1538  					}
  1539  				}
  1540  			}
  1541  			if m := modload.PackageModule(pkg); m.Path != "" {
  1542  				relevantMods[m] |= hasPkg
  1543  			}
  1544  		}
  1545  		for _, match := range matches {
  1546  			for _, pkg := range match.Pkgs {
  1547  				m := modload.PackageModule(pkg)
  1548  				relevantMods[m] |= named
  1549  			}
  1550  		}
  1551  	}
  1552  
  1553  	reqs := modload.LoadModFile(ctx)
  1554  	for m := range relevantMods {
  1555  		if reqs.IsDirect(m.Path) {
  1556  			relevantMods[m] |= direct
  1557  		}
  1558  	}
  1559  
  1560  	// Load retractions for modules mentioned on the command line and modules
  1561  	// needed to build named packages. We care about retractions of indirect
  1562  	// dependencies, since we might be able to upgrade away from them.
  1563  	type modMessage struct {
  1564  		m       module.Version
  1565  		message string
  1566  	}
  1567  	retractions := make([]modMessage, 0, len(relevantMods))
  1568  	for m, flags := range relevantMods {
  1569  		if flags&(resolved|named|hasPkg) != 0 {
  1570  			retractions = append(retractions, modMessage{m: m})
  1571  		}
  1572  	}
  1573  	sort.Slice(retractions, func(i, j int) bool { return retractions[i].m.Path < retractions[j].m.Path })
  1574  	for i := range retractions {
  1575  		i := i
  1576  		r.work.Add(func() {
  1577  			err := modload.CheckRetractions(ctx, retractions[i].m)
  1578  			if retractErr := (*modload.ModuleRetractedError)(nil); errors.As(err, &retractErr) {
  1579  				retractions[i].message = err.Error()
  1580  			}
  1581  		})
  1582  	}
  1583  
  1584  	// Load deprecations for modules mentioned on the command line. Only load
  1585  	// deprecations for indirect dependencies if they're also direct dependencies
  1586  	// of the main module. Deprecations of purely indirect dependencies are
  1587  	// not actionable.
  1588  	deprecations := make([]modMessage, 0, len(relevantMods))
  1589  	for m, flags := range relevantMods {
  1590  		if flags&(resolved|named) != 0 || flags&(hasPkg|direct) == hasPkg|direct {
  1591  			deprecations = append(deprecations, modMessage{m: m})
  1592  		}
  1593  	}
  1594  	sort.Slice(deprecations, func(i, j int) bool { return deprecations[i].m.Path < deprecations[j].m.Path })
  1595  	for i := range deprecations {
  1596  		i := i
  1597  		r.work.Add(func() {
  1598  			deprecation, err := modload.CheckDeprecation(ctx, deprecations[i].m)
  1599  			if err != nil || deprecation == "" {
  1600  				return
  1601  			}
  1602  			deprecations[i].message = modload.ShortMessage(deprecation, "")
  1603  		})
  1604  	}
  1605  
  1606  	// Load sums for updated modules that had sums before. When we update a
  1607  	// module, we may update another module in the build list that provides a
  1608  	// package in 'all' that wasn't loaded as part of this 'go get' command.
  1609  	// If we don't add a sum for that module, builds may fail later.
  1610  	// Note that an incidentally updated package could still import packages
  1611  	// from unknown modules or from modules in the build list that we didn't
  1612  	// need previously. We can't handle that case without loading 'all'.
  1613  	sumErrs := make([]error, len(r.buildList))
  1614  	for i := range r.buildList {
  1615  		i := i
  1616  		m := r.buildList[i]
  1617  		mActual := m
  1618  		if mRepl := modload.Replacement(m); mRepl.Path != "" {
  1619  			mActual = mRepl
  1620  		}
  1621  		old := module.Version{Path: m.Path, Version: r.initialVersion[m.Path]}
  1622  		if old.Version == "" {
  1623  			continue
  1624  		}
  1625  		oldActual := old
  1626  		if oldRepl := modload.Replacement(old); oldRepl.Path != "" {
  1627  			oldActual = oldRepl
  1628  		}
  1629  		if mActual == oldActual || mActual.Version == "" || !modfetch.HaveSum(oldActual) {
  1630  			continue
  1631  		}
  1632  		r.work.Add(func() {
  1633  			if _, err := modfetch.DownloadZip(ctx, mActual); err != nil {
  1634  				verb := "upgraded"
  1635  				if gover.ModCompare(m.Path, m.Version, old.Version) < 0 {
  1636  					verb = "downgraded"
  1637  				}
  1638  				replaced := ""
  1639  				if mActual != m {
  1640  					replaced = fmt.Sprintf(" (replaced by %s)", mActual)
  1641  				}
  1642  				err = fmt.Errorf("%s %s %s => %s%s: error finding sum for %s: %v", verb, m.Path, old.Version, m.Version, replaced, mActual, err)
  1643  				sumErrs[i] = err
  1644  			}
  1645  		})
  1646  	}
  1647  
  1648  	<-r.work.Idle()
  1649  
  1650  	// Report deprecations, then retractions, then errors fetching sums.
  1651  	// Only errors fetching sums are hard errors.
  1652  	for _, mm := range deprecations {
  1653  		if mm.message != "" {
  1654  			fmt.Fprintf(os.Stderr, "go: module %s is deprecated: %s\n", mm.m.Path, mm.message)
  1655  		}
  1656  	}
  1657  	var retractPath string
  1658  	for _, mm := range retractions {
  1659  		if mm.message != "" {
  1660  			fmt.Fprintf(os.Stderr, "go: warning: %v\n", mm.message)
  1661  			if retractPath == "" {
  1662  				retractPath = mm.m.Path
  1663  			} else {
  1664  				retractPath = "<module>"
  1665  			}
  1666  		}
  1667  	}
  1668  	if retractPath != "" {
  1669  		fmt.Fprintf(os.Stderr, "go: to switch to the latest unretracted version, run:\n\tgo get %s@latest\n", retractPath)
  1670  	}
  1671  	for _, err := range sumErrs {
  1672  		if err != nil {
  1673  			base.Error(err)
  1674  		}
  1675  	}
  1676  	base.ExitIfErrors()
  1677  }
  1678  
  1679  // reportChanges logs version changes to os.Stderr.
  1680  //
  1681  // reportChanges only logs changes to modules named on the command line and to
  1682  // explicitly required modules in go.mod. Most changes to indirect requirements
  1683  // are not relevant to the user and are not logged.
  1684  //
  1685  // reportChanges should be called after WriteGoMod.
  1686  func (r *resolver) reportChanges(oldReqs, newReqs []module.Version) {
  1687  	type change struct {
  1688  		path, old, new string
  1689  	}
  1690  	changes := make(map[string]change)
  1691  
  1692  	// Collect changes in modules matched by command line arguments.
  1693  	for path, reason := range r.resolvedVersion {
  1694  		if gover.IsToolchain(path) {
  1695  			continue
  1696  		}
  1697  		old := r.initialVersion[path]
  1698  		new := reason.version
  1699  		if old != new && (old != "" || new != "none") {
  1700  			changes[path] = change{path, old, new}
  1701  		}
  1702  	}
  1703  
  1704  	// Collect changes to explicit requirements in go.mod.
  1705  	for _, req := range oldReqs {
  1706  		if gover.IsToolchain(req.Path) {
  1707  			continue
  1708  		}
  1709  		path := req.Path
  1710  		old := req.Version
  1711  		new := r.buildListVersion[path]
  1712  		if old != new {
  1713  			changes[path] = change{path, old, new}
  1714  		}
  1715  	}
  1716  	for _, req := range newReqs {
  1717  		if gover.IsToolchain(req.Path) {
  1718  			continue
  1719  		}
  1720  		path := req.Path
  1721  		old := r.initialVersion[path]
  1722  		new := req.Version
  1723  		if old != new {
  1724  			changes[path] = change{path, old, new}
  1725  		}
  1726  	}
  1727  
  1728  	// Toolchain diffs are easier than requirements: diff old and new directly.
  1729  	toolchainVersions := func(reqs []module.Version) (goV, toolchain string) {
  1730  		for _, req := range reqs {
  1731  			if req.Path == "go" {
  1732  				goV = req.Version
  1733  			}
  1734  			if req.Path == "toolchain" {
  1735  				toolchain = req.Version
  1736  			}
  1737  		}
  1738  		return
  1739  	}
  1740  	oldGo, oldToolchain := toolchainVersions(oldReqs)
  1741  	newGo, newToolchain := toolchainVersions(newReqs)
  1742  	if oldGo != newGo {
  1743  		changes["go"] = change{"go", oldGo, newGo}
  1744  	}
  1745  	if oldToolchain != newToolchain {
  1746  		changes["toolchain"] = change{"toolchain", oldToolchain, newToolchain}
  1747  	}
  1748  
  1749  	sortedChanges := make([]change, 0, len(changes))
  1750  	for _, c := range changes {
  1751  		sortedChanges = append(sortedChanges, c)
  1752  	}
  1753  	sort.Slice(sortedChanges, func(i, j int) bool {
  1754  		pi := sortedChanges[i].path
  1755  		pj := sortedChanges[j].path
  1756  		if pi == pj {
  1757  			return false
  1758  		}
  1759  		// go first; toolchain second
  1760  		switch {
  1761  		case pi == "go":
  1762  			return true
  1763  		case pj == "go":
  1764  			return false
  1765  		case pi == "toolchain":
  1766  			return true
  1767  		case pj == "toolchain":
  1768  			return false
  1769  		}
  1770  		return pi < pj
  1771  	})
  1772  
  1773  	for _, c := range sortedChanges {
  1774  		if c.old == "" {
  1775  			fmt.Fprintf(os.Stderr, "go: added %s %s\n", c.path, c.new)
  1776  		} else if c.new == "none" || c.new == "" {
  1777  			fmt.Fprintf(os.Stderr, "go: removed %s %s\n", c.path, c.old)
  1778  		} else if gover.ModCompare(c.path, c.new, c.old) > 0 {
  1779  			fmt.Fprintf(os.Stderr, "go: upgraded %s %s => %s\n", c.path, c.old, c.new)
  1780  			if c.path == "go" && gover.Compare(c.old, gover.ExplicitIndirectVersion) < 0 && gover.Compare(c.new, gover.ExplicitIndirectVersion) >= 0 {
  1781  				fmt.Fprintf(os.Stderr, "\tnote: expanded dependencies to upgrade to go %s or higher; run 'go mod tidy' to clean up\n", gover.ExplicitIndirectVersion)
  1782  			}
  1783  
  1784  		} else {
  1785  			fmt.Fprintf(os.Stderr, "go: downgraded %s %s => %s\n", c.path, c.old, c.new)
  1786  		}
  1787  	}
  1788  
  1789  	// TODO(golang.org/issue/33284): attribute changes to command line arguments.
  1790  	// For modules matched by command line arguments, this probably isn't
  1791  	// necessary, but it would be useful for unmatched direct dependencies of
  1792  	// the main module.
  1793  }
  1794  
  1795  // resolve records that module m must be at its indicated version (which may be
  1796  // "none") due to query q. If some other query forces module m to be at a
  1797  // different version, resolve reports a conflict error.
  1798  func (r *resolver) resolve(q *query, m module.Version) {
  1799  	if m.Path == "" {
  1800  		panic("internal error: resolving a module.Version with an empty path")
  1801  	}
  1802  
  1803  	if modload.MainModules.Contains(m.Path) && m.Version != "" {
  1804  		reportError(q, &modload.QueryMatchesMainModulesError{
  1805  			MainModules: []module.Version{{Path: m.Path}},
  1806  			Pattern:     q.pattern,
  1807  			Query:       q.version,
  1808  		})
  1809  		return
  1810  	}
  1811  
  1812  	vr, ok := r.resolvedVersion[m.Path]
  1813  	if ok && vr.version != m.Version {
  1814  		reportConflict(q, m, vr)
  1815  		return
  1816  	}
  1817  	r.resolvedVersion[m.Path] = versionReason{m.Version, q}
  1818  	q.resolved = append(q.resolved, m)
  1819  }
  1820  
  1821  // updateBuildList updates the module loader's global build list to be
  1822  // consistent with r.resolvedVersion, and to include additional modules
  1823  // provided that they do not conflict with the resolved versions.
  1824  //
  1825  // If the additional modules conflict with the resolved versions, they will be
  1826  // downgraded to a non-conflicting version (possibly "none").
  1827  //
  1828  // If the resulting build list is the same as the one resulting from the last
  1829  // call to updateBuildList, updateBuildList returns with changed=false.
  1830  func (r *resolver) updateBuildList(ctx context.Context, additions []module.Version) (changed bool) {
  1831  	defer base.ExitIfErrors()
  1832  
  1833  	resolved := make([]module.Version, 0, len(r.resolvedVersion))
  1834  	for mPath, rv := range r.resolvedVersion {
  1835  		if !modload.MainModules.Contains(mPath) {
  1836  			resolved = append(resolved, module.Version{Path: mPath, Version: rv.version})
  1837  		}
  1838  	}
  1839  
  1840  	changed, err := modload.EditBuildList(ctx, additions, resolved)
  1841  	if err != nil {
  1842  		if errors.Is(err, gover.ErrTooNew) {
  1843  			toolchain.SwitchOrFatal(ctx, err)
  1844  		}
  1845  
  1846  		var constraint *modload.ConstraintError
  1847  		if !errors.As(err, &constraint) {
  1848  			base.Fatal(err)
  1849  		}
  1850  
  1851  		if cfg.BuildV {
  1852  			// Log complete paths for the conflicts before we summarize them.
  1853  			for _, c := range constraint.Conflicts {
  1854  				fmt.Fprintf(os.Stderr, "go: %v\n", c.String())
  1855  			}
  1856  		}
  1857  
  1858  		// modload.EditBuildList reports constraint errors at
  1859  		// the module level, but 'go get' operates on packages.
  1860  		// Rewrite the errors to explain them in terms of packages.
  1861  		reason := func(m module.Version) string {
  1862  			rv, ok := r.resolvedVersion[m.Path]
  1863  			if !ok {
  1864  				return fmt.Sprintf("(INTERNAL ERROR: no reason found for %v)", m)
  1865  			}
  1866  			return rv.reason.ResolvedString(module.Version{Path: m.Path, Version: rv.version})
  1867  		}
  1868  		for _, c := range constraint.Conflicts {
  1869  			adverb := ""
  1870  			if len(c.Path) > 2 {
  1871  				adverb = "indirectly "
  1872  			}
  1873  			firstReason := reason(c.Path[0])
  1874  			last := c.Path[len(c.Path)-1]
  1875  			if c.Err != nil {
  1876  				base.Errorf("go: %v %srequires %v: %v", firstReason, adverb, last, c.UnwrapModuleError())
  1877  			} else {
  1878  				base.Errorf("go: %v %srequires %v, not %v", firstReason, adverb, last, reason(c.Constraint))
  1879  			}
  1880  		}
  1881  		return false
  1882  	}
  1883  	if !changed {
  1884  		return false
  1885  	}
  1886  
  1887  	mg, err := modload.LoadModGraph(ctx, "")
  1888  	if err != nil {
  1889  		toolchain.SwitchOrFatal(ctx, err)
  1890  	}
  1891  
  1892  	r.buildList = mg.BuildList()
  1893  	r.buildListVersion = make(map[string]string, len(r.buildList))
  1894  	for _, m := range r.buildList {
  1895  		r.buildListVersion[m.Path] = m.Version
  1896  	}
  1897  	return true
  1898  }
  1899  
  1900  func reqsFromGoMod(f *modfile.File) []module.Version {
  1901  	reqs := make([]module.Version, len(f.Require), 2+len(f.Require))
  1902  	for i, r := range f.Require {
  1903  		reqs[i] = r.Mod
  1904  	}
  1905  	if f.Go != nil {
  1906  		reqs = append(reqs, module.Version{Path: "go", Version: f.Go.Version})
  1907  	}
  1908  	if f.Toolchain != nil {
  1909  		reqs = append(reqs, module.Version{Path: "toolchain", Version: f.Toolchain.Name})
  1910  	}
  1911  	return reqs
  1912  }
  1913  
  1914  // isNoSuchModuleVersion reports whether err indicates that the requested module
  1915  // does not exist at the requested version, either because the module does not
  1916  // exist at all or because it does not include that specific version.
  1917  func isNoSuchModuleVersion(err error) bool {
  1918  	var noMatch *modload.NoMatchingVersionError
  1919  	return errors.Is(err, os.ErrNotExist) || errors.As(err, &noMatch)
  1920  }
  1921  
  1922  // isNoSuchPackageVersion reports whether err indicates that the requested
  1923  // package does not exist at the requested version, either because no module
  1924  // that could contain it exists at that version, or because every such module
  1925  // that does exist does not actually contain the package.
  1926  func isNoSuchPackageVersion(err error) bool {
  1927  	var noPackage *modload.PackageNotInModuleError
  1928  	return isNoSuchModuleVersion(err) || errors.As(err, &noPackage)
  1929  }
  1930  

View as plain text