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

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

View as plain text