Black Lives Matter. Support the Equal Justice Initiative.

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

View as plain text