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

View as plain text