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

View as plain text