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

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

View as plain text