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

View as plain text