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

View as plain text