...

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

Documentation: cmd/go/internal/modget

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

View as plain text