github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-internal/modget/get.go (about)

     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  import (
     9  	"errors"
    10  	"fmt"
    11  	"os"
    12  	"path/filepath"
    13  	"sort"
    14  	"strings"
    15  	"sync"
    16  
    17  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/base"
    18  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/get"
    19  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/imports"
    20  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/load"
    21  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/modload"
    22  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/mvs"
    23  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/par"
    24  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/search"
    25  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/work"
    26  
    27  	"golang.org/x/mod/module"
    28  	"golang.org/x/mod/semver"
    29  )
    30  
    31  var CmdGet = &base.Command{
    32  	// Note: -d -u are listed explicitly because they are the most common get flags.
    33  	// Do not send CLs removing them because they're covered by [get flags].
    34  	UsageLine: "go get [-d] [-t] [-u] [-v] [-insecure] [build flags] [packages]",
    35  	Short:     "add dependencies to current module and install them",
    36  	Long: `
    37  Get resolves and adds dependencies to the current development module
    38  and then builds and installs them.
    39  
    40  The first step is to resolve which dependencies to add.
    41  
    42  For each named package or package pattern, get must decide which version of
    43  the corresponding module to use. By default, get looks up the latest tagged
    44  release version, such as v0.4.5 or v1.2.3. If there are no tagged release
    45  versions, get looks up the latest tagged pre-release version, such as
    46  v0.0.1-pre1. If there are no tagged versions at all, get looks up the latest
    47  known commit. If the module is not already required at a later version
    48  (for example, a pre-release newer than the latest release), get will use
    49  the version it looked up. Otherwise, get will use the currently
    50  required version.
    51  
    52  This default version selection can be overridden by adding an @version
    53  suffix to the package argument, as in 'go get golang.org/x/text@v0.3.0'.
    54  The version may be a prefix: @v1 denotes the latest available version starting
    55  with v1. See 'go help modules' under the heading 'Module queries' for the
    56  full query syntax.
    57  
    58  For modules stored in source control repositories, the version suffix can
    59  also be a commit hash, branch identifier, or other syntax known to the
    60  source control system, as in 'go get golang.org/x/text@master'. Note that
    61  branches with names that overlap with other module query syntax cannot be
    62  selected explicitly. For example, the suffix @v2 means the latest version
    63  starting with v2, not the branch named v2.
    64  
    65  If a module under consideration is already a dependency of the current
    66  development module, then get will update the required version.
    67  Specifying a version earlier than the current required version is valid and
    68  downgrades the dependency. The version suffix @none indicates that the
    69  dependency should be removed entirely, downgrading or removing modules
    70  depending on it as needed.
    71  
    72  The version suffix @latest explicitly requests the latest minor release of the
    73  module named by the given path. The suffix @upgrade is like @latest but
    74  will not downgrade a module if it is already required at a revision or
    75  pre-release version newer than the latest released version. The suffix
    76  @patch requests the latest patch release: the latest released version
    77  with the same major and minor version numbers as the currently required
    78  version. Like @upgrade, @patch will not downgrade a module already required
    79  at a newer version. If the path is not already required, @upgrade and @patch
    80  are equivalent to @latest.
    81  
    82  Although get defaults to using the latest version of the module containing
    83  a named package, it does not use the latest version of that module's
    84  dependencies. Instead it prefers to use the specific dependency versions
    85  requested by that module. For example, if the latest A requires module
    86  B v1.2.3, while B v1.2.4 and v1.3.1 are also available, then 'go get A'
    87  will use the latest A but then use B v1.2.3, as requested by A. (If there
    88  are competing requirements for a particular module, then 'go get' resolves
    89  those requirements by taking the maximum requested version.)
    90  
    91  The -t flag instructs get to consider modules needed to build tests of
    92  packages specified on the command line.
    93  
    94  The -u flag instructs get to update modules providing dependencies
    95  of packages named on the command line to use newer minor or patch
    96  releases when available. Continuing the previous example, 'go get -u A'
    97  will use the latest A with B v1.3.1 (not B v1.2.3). If B requires module C,
    98  but C does not provide any packages needed to build packages in A
    99  (not including tests), then C will not be updated.
   100  
   101  The -u=patch flag (not -u patch) also instructs get to update dependencies,
   102  but changes the default to select patch releases.
   103  Continuing the previous example,
   104  'go get -u=patch A@latest' will use the latest A with B v1.2.4 (not B v1.2.3),
   105  while 'go get -u=patch A' will use a patch release of A instead.
   106  
   107  When the -t and -u flags are used together, get will update
   108  test dependencies as well.
   109  
   110  In general, adding a new dependency may require upgrading
   111  existing dependencies to keep a working build, and 'go get' does
   112  this automatically. Similarly, downgrading one dependency may
   113  require downgrading other dependencies, and 'go get' does
   114  this automatically as well.
   115  
   116  The -insecure flag permits fetching from repositories and resolving
   117  custom domains using insecure schemes such as HTTP. Use with caution.
   118  
   119  The second step is to download (if needed), build, and install
   120  the named packages.
   121  
   122  If an argument names a module but not a package (because there is no
   123  Go source code in the module's root directory), then the install step
   124  is skipped for that argument, instead of causing a build failure.
   125  For example 'go get golang.org/x/perf' succeeds even though there
   126  is no code corresponding to that import path.
   127  
   128  Note that package patterns are allowed and are expanded after resolving
   129  the module versions. For example, 'go get golang.org/x/perf/cmd/...'
   130  adds the latest golang.org/x/perf and then installs the commands in that
   131  latest version.
   132  
   133  The -d flag instructs get to download the source code needed to build
   134  the named packages, including downloading necessary dependencies,
   135  but not to build and install them.
   136  
   137  With no package arguments, 'go get' applies to Go package in the
   138  current directory, if any. In particular, 'go get -u' and
   139  'go get -u=patch' update all the dependencies of that package.
   140  With no package arguments and also without -u, 'go get' is not much more
   141  than 'go install', and 'go get -d' not much more than 'go list'.
   142  
   143  For more about modules, see 'go help modules'.
   144  
   145  For more about specifying packages, see 'go help packages'.
   146  
   147  This text describes the behavior of get using modules to manage source
   148  code and dependencies. If instead the go command is running in GOPATH
   149  mode, the details of get's flags and effects change, as does 'go help get'.
   150  See 'go help modules' and 'go help gopath-get'.
   151  
   152  See also: go build, go install, go clean, go mod.
   153  	`,
   154  }
   155  
   156  // Note that this help text is a stopgap to make the module-aware get help text
   157  // available even in non-module settings. It should be deleted when the old get
   158  // is deleted. It should NOT be considered to set a precedent of having hierarchical
   159  // help names with dashes.
   160  var HelpModuleGet = &base.Command{
   161  	UsageLine: "module-get",
   162  	Short:     "module-aware go get",
   163  	Long: `
   164  The 'go get' command changes behavior depending on whether the
   165  go command is running in module-aware mode or legacy GOPATH mode.
   166  This help text, accessible as 'go help module-get' even in legacy GOPATH mode,
   167  describes 'go get' as it operates in module-aware mode.
   168  
   169  Usage: ` + CmdGet.UsageLine + `
   170  ` + CmdGet.Long,
   171  }
   172  
   173  var (
   174  	getD   = CmdGet.Flag.Bool("d", false, "")
   175  	getF   = CmdGet.Flag.Bool("f", false, "")
   176  	getFix = CmdGet.Flag.Bool("fix", false, "")
   177  	getM   = CmdGet.Flag.Bool("m", false, "")
   178  	getT   = CmdGet.Flag.Bool("t", false, "")
   179  	getU   upgradeFlag
   180  	// -insecure is get.Insecure
   181  	// -v is cfg.BuildV
   182  )
   183  
   184  // upgradeFlag is a custom flag.Value for -u.
   185  type upgradeFlag string
   186  
   187  func (*upgradeFlag) IsBoolFlag() bool { return true } // allow -u
   188  
   189  func (v *upgradeFlag) Set(s string) error {
   190  	if s == "false" {
   191  		s = ""
   192  	}
   193  	if s == "true" {
   194  		s = "upgrade"
   195  	}
   196  	*v = upgradeFlag(s)
   197  	return nil
   198  }
   199  
   200  func (v *upgradeFlag) String() string { return "" }
   201  
   202  func init() {
   203  	work.AddBuildFlags(CmdGet, work.OmitModFlag)
   204  	CmdGet.Run = runGet // break init loop
   205  	CmdGet.Flag.BoolVar(&get.Insecure, "insecure", get.Insecure, "")
   206  	CmdGet.Flag.Var(&getU, "u", "")
   207  }
   208  
   209  // A getArg holds a parsed positional argument for go get (path@vers).
   210  type getArg struct {
   211  	// raw is the original argument, to be printed in error messages.
   212  	raw string
   213  
   214  	// path is the part of the argument before "@" (or the whole argument
   215  	// if there is no "@"). path specifies the modules or packages to get.
   216  	path string
   217  
   218  	// vers is the part of the argument after "@" or an implied
   219  	// "upgrade" or "patch" if there is no "@". vers specifies the
   220  	// module version to get.
   221  	vers string
   222  }
   223  
   224  // querySpec describes a query for a specific module. path may be a
   225  // module path, package path, or package pattern. vers is a version
   226  // query string from a command line argument.
   227  type querySpec struct {
   228  	// path is a module path, package path, or package pattern that
   229  	// specifies which module to query.
   230  	path string
   231  
   232  	// vers specifies what version of the module to get.
   233  	vers string
   234  
   235  	// forceModulePath is true if path should be interpreted as a module path.
   236  	// If forceModulePath is true, prevM must be set.
   237  	forceModulePath bool
   238  
   239  	// prevM is the previous version of the module. prevM is needed
   240  	// to determine the minor version number if vers is "patch". It's also
   241  	// used to avoid downgrades from prerelease versions newer than
   242  	// "latest" and "patch". If prevM is set, forceModulePath must be true.
   243  	prevM module.Version
   244  }
   245  
   246  // query holds the state for a query made for a specific module.
   247  // After a query is performed, we know the actual module path and
   248  // version and whether any packages were matched by the query path.
   249  type query struct {
   250  	querySpec
   251  
   252  	// arg is the command line argument that matched the specified module.
   253  	arg string
   254  
   255  	// m is the module path and version found by the query.
   256  	m module.Version
   257  }
   258  
   259  func runGet(cmd *base.Command, args []string) {
   260  	switch getU {
   261  	case "", "upgrade", "patch":
   262  		// ok
   263  	default:
   264  		base.Fatalf("go get: unknown upgrade flag -u=%s", getU)
   265  	}
   266  	if *getF {
   267  		fmt.Fprintf(os.Stderr, "go get: -f flag is a no-op when using modules\n")
   268  	}
   269  	if *getFix {
   270  		fmt.Fprintf(os.Stderr, "go get: -fix flag is a no-op when using modules\n")
   271  	}
   272  	if *getM {
   273  		base.Fatalf("go get: -m flag is no longer supported; consider -d to skip building packages")
   274  	}
   275  	modload.LoadTests = *getT
   276  
   277  	buildList := modload.LoadBuildList()
   278  	buildList = buildList[:len(buildList):len(buildList)] // copy on append
   279  	versionByPath := make(map[string]string)
   280  	for _, m := range buildList {
   281  		versionByPath[m.Path] = m.Version
   282  	}
   283  
   284  	// Do not allow any updating of go.mod until we've applied
   285  	// all the requested changes and checked that the result matches
   286  	// what was requested.
   287  	modload.DisallowWriteGoMod()
   288  
   289  	// Allow looking up modules for import paths outside of a module.
   290  	// 'go get' is expected to do this, unlike other commands.
   291  	modload.AllowMissingModuleImports()
   292  
   293  	// Parse command-line arguments and report errors. The command-line
   294  	// arguments are of the form path@version or simply path, with implicit
   295  	// @upgrade. path@none is "downgrade away".
   296  	var gets []getArg
   297  	var queries []*query
   298  	for _, arg := range search.CleanPatterns(args) {
   299  		// Argument is path or path@vers.
   300  		path := arg
   301  		vers := ""
   302  		if i := strings.Index(arg, "@"); i >= 0 {
   303  			path, vers = arg[:i], arg[i+1:]
   304  		}
   305  		if strings.Contains(vers, "@") || arg != path && vers == "" {
   306  			base.Errorf("go get %s: invalid module version syntax", arg)
   307  			continue
   308  		}
   309  
   310  		// If no version suffix is specified, assume @upgrade.
   311  		// If -u=patch was specified, assume @patch instead.
   312  		if vers == "" {
   313  			if getU != "" {
   314  				vers = string(getU)
   315  			} else {
   316  				vers = "upgrade"
   317  			}
   318  		}
   319  
   320  		gets = append(gets, getArg{raw: arg, path: path, vers: vers})
   321  
   322  		// Determine the modules that path refers to, and create queries
   323  		// to lookup modules at target versions before loading packages.
   324  		// This is an imprecise process, but it helps reduce unnecessary
   325  		// queries and package loading. It's also necessary for handling
   326  		// patterns like golang.org/x/tools/..., which can't be expanded
   327  		// during package loading until they're in the build list.
   328  		switch {
   329  		case search.IsRelativePath(path):
   330  			// Relative paths like ../../foo or ../../foo... are restricted to
   331  			// matching packages in the main module. If the path is explicit and
   332  			// contains no wildcards (...), check that it is a package in
   333  			// the main module. If the path contains wildcards but matches no
   334  			// packages, we'll warn after package loading.
   335  			if !strings.Contains(path, "...") {
   336  				pkgPath := modload.DirImportPath(filepath.FromSlash(path))
   337  				if pkgs := modload.TargetPackages(pkgPath); len(pkgs) == 0 {
   338  					abs, err := filepath.Abs(path)
   339  					if err != nil {
   340  						abs = path
   341  					}
   342  					base.Errorf("go get %s: path %s is not a package in module rooted at %s", arg, abs, modload.ModRoot())
   343  					continue
   344  				}
   345  			}
   346  
   347  			if path != arg {
   348  				base.Errorf("go get %s: can't request explicit version of path in main module", arg)
   349  				continue
   350  			}
   351  
   352  		case strings.Contains(path, "..."):
   353  			// Wait until we load packages to look up modules.
   354  			// We don't know yet whether any modules in the build list provide
   355  			// packages matching the pattern. For example, suppose
   356  			// golang.org/x/tools and golang.org/x/tools/playground are separate
   357  			// modules, and only golang.org/x/tools is in the build list. If the
   358  			// user runs 'go get golang.org/x/tools/playground/...', we should
   359  			// add a requirement for golang.org/x/tools/playground. We should not
   360  			// upgrade golang.org/x/tools.
   361  
   362  		case path == "all":
   363  			// If there is no main module, "all" is not meaningful.
   364  			if !modload.HasModRoot() {
   365  				base.Errorf(`go get %s: cannot match "all": working directory is not part of a module`, arg)
   366  			}
   367  			// Don't query modules until we load packages. We'll automatically
   368  			// look up any missing modules.
   369  
   370  		case search.IsMetaPackage(path):
   371  			base.Errorf("go get %s: explicit requirement on standard-library module %s not allowed", path, path)
   372  			continue
   373  
   374  		default:
   375  			// The argument is a package or module path.
   376  			if modload.HasModRoot() {
   377  				if pkgs := modload.TargetPackages(path); len(pkgs) != 0 {
   378  					// The path is in the main module. Nothing to query.
   379  					if vers != "upgrade" && vers != "patch" {
   380  						base.Errorf("go get %s: can't request explicit version of path in main module", arg)
   381  					}
   382  					continue
   383  				}
   384  			}
   385  
   386  			first := path
   387  			if i := strings.IndexByte(first, '/'); i >= 0 {
   388  				first = path
   389  			}
   390  			if !strings.Contains(first, ".") {
   391  				// The path doesn't have a dot in the first component and cannot be
   392  				// queried as a module. It may be a package in the standard library,
   393  				// which is fine, so don't report an error unless we encounter
   394  				// a problem loading packages below.
   395  				continue
   396  			}
   397  
   398  			// If we're querying "upgrade" or "patch", we need to know the current
   399  			// version of the module. For "upgrade", we want to avoid accidentally
   400  			// downgrading from a newer prerelease. For "patch", we need to query
   401  			// the correct minor version.
   402  			// Here, we check if "path" is the name of a module in the build list
   403  			// (other than the main module) and set prevM if so. If "path" isn't
   404  			// a module in the build list, the current version doesn't matter
   405  			// since it's either an unknown module or a package within a module
   406  			// that we'll discover later.
   407  			q := &query{querySpec: querySpec{path: path, vers: vers}, arg: arg}
   408  			if v, ok := versionByPath[path]; ok && path != modload.Target.Path {
   409  				q.prevM = module.Version{Path: path, Version: v}
   410  				q.forceModulePath = true
   411  			}
   412  			queries = append(queries, q)
   413  		}
   414  	}
   415  	base.ExitIfErrors()
   416  
   417  	// Query modules referenced by command line arguments at requested versions.
   418  	// We need to do this before loading packages since patterns that refer to
   419  	// packages in unknown modules can't be expanded. This also avoids looking
   420  	// up new modules while loading packages, only to downgrade later.
   421  	queryCache := make(map[querySpec]*query)
   422  	byPath := runQueries(queryCache, queries, nil)
   423  
   424  	// Add missing modules to the build list.
   425  	// We call SetBuildList here and elsewhere, since newUpgrader,
   426  	// ImportPathsQuiet, and other functions read the global build list.
   427  	for _, q := range queries {
   428  		if _, ok := versionByPath[q.m.Path]; !ok && q.m.Version != "none" {
   429  			buildList = append(buildList, q.m)
   430  		}
   431  	}
   432  	versionByPath = nil // out of date now; rebuilt later when needed
   433  	modload.SetBuildList(buildList)
   434  
   435  	// Upgrade modules specifically named on the command line. This is our only
   436  	// chance to upgrade modules without root packages (modOnly below).
   437  	// This also skips loading packages at an old version, only to upgrade
   438  	// and reload at a new version.
   439  	upgrade := make(map[string]*query)
   440  	for path, q := range byPath {
   441  		if q.path == q.m.Path && q.m.Version != "none" {
   442  			upgrade[path] = q
   443  		}
   444  	}
   445  	buildList, err := mvs.UpgradeAll(modload.Target, newUpgrader(upgrade, nil))
   446  	if err != nil {
   447  		base.Fatalf("go get: %v", err)
   448  	}
   449  	modload.SetBuildList(buildList)
   450  	base.ExitIfErrors()
   451  	prevBuildList := buildList
   452  
   453  	// Build a set of module paths that we don't plan to load packages from.
   454  	// This includes explicitly requested modules that don't have a root package
   455  	// and modules with a target version of "none".
   456  	var wg sync.WaitGroup
   457  	var modOnlyMu sync.Mutex
   458  	modOnly := make(map[string]*query)
   459  	for _, q := range queries {
   460  		if q.m.Version == "none" {
   461  			modOnlyMu.Lock()
   462  			modOnly[q.m.Path] = q
   463  			modOnlyMu.Unlock()
   464  			continue
   465  		}
   466  		if q.path == q.m.Path {
   467  			wg.Add(1)
   468  			go func(q *query) {
   469  				if hasPkg, err := modload.ModuleHasRootPackage(q.m); err != nil {
   470  					base.Errorf("go get: %v", err)
   471  				} else if !hasPkg {
   472  					modOnlyMu.Lock()
   473  					modOnly[q.m.Path] = q
   474  					modOnlyMu.Unlock()
   475  				}
   476  				wg.Done()
   477  			}(q)
   478  		}
   479  	}
   480  	wg.Wait()
   481  	base.ExitIfErrors()
   482  
   483  	// Build a list of arguments that may refer to packages.
   484  	var pkgPatterns []string
   485  	var pkgGets []getArg
   486  	for _, arg := range gets {
   487  		if modOnly[arg.path] == nil && arg.vers != "none" {
   488  			pkgPatterns = append(pkgPatterns, arg.path)
   489  			pkgGets = append(pkgGets, arg)
   490  		}
   491  	}
   492  
   493  	// Load packages and upgrade the modules that provide them. We do this until
   494  	// we reach a fixed point, since modules providing packages may change as we
   495  	// change versions. This must terminate because the module graph is finite,
   496  	// and the load and upgrade operations may only add and upgrade modules
   497  	// in the build list.
   498  	var matches []*search.Match
   499  	for {
   500  		var seenPkgs map[string]bool
   501  		seenQuery := make(map[querySpec]bool)
   502  		var queries []*query
   503  		addQuery := func(q *query) {
   504  			if !seenQuery[q.querySpec] {
   505  				seenQuery[q.querySpec] = true
   506  				queries = append(queries, q)
   507  			}
   508  		}
   509  
   510  		if len(pkgPatterns) > 0 {
   511  			// Don't load packages if pkgPatterns is empty. Both
   512  			// modload.ImportPathsQuiet and ModulePackages convert an empty list
   513  			// of patterns to []string{"."}, which is not what we want.
   514  			matches = modload.ImportPathsQuiet(pkgPatterns, imports.AnyTags())
   515  			seenPkgs = make(map[string]bool)
   516  			for i, match := range matches {
   517  				arg := pkgGets[i]
   518  
   519  				if len(match.Pkgs) == 0 {
   520  					// If the pattern did not match any packages, look up a new module.
   521  					// If the pattern doesn't match anything on the last iteration,
   522  					// we'll print a warning after the outer loop.
   523  					if !search.IsRelativePath(arg.path) && !match.Literal && arg.path != "all" {
   524  						addQuery(&query{querySpec: querySpec{path: arg.path, vers: arg.vers}, arg: arg.raw})
   525  					}
   526  					continue
   527  				}
   528  
   529  				allStd := true
   530  				for _, pkg := range match.Pkgs {
   531  					if !seenPkgs[pkg] {
   532  						seenPkgs[pkg] = true
   533  						if _, _, err := modload.Lookup("", false, pkg); err != nil {
   534  							allStd = false
   535  							base.Errorf("go get %s: %v", arg.raw, err)
   536  							continue
   537  						}
   538  					}
   539  					m := modload.PackageModule(pkg)
   540  					if m.Path == "" {
   541  						// pkg is in the standard library.
   542  						continue
   543  					}
   544  					allStd = false
   545  					if m.Path == modload.Target.Path {
   546  						// pkg is in the main module.
   547  						continue
   548  					}
   549  					addQuery(&query{querySpec: querySpec{path: m.Path, vers: arg.vers, forceModulePath: true, prevM: m}, arg: arg.raw})
   550  				}
   551  				if allStd && arg.path != arg.raw {
   552  					base.Errorf("go get %s: cannot use pattern %q with explicit version", arg.raw, arg.raw)
   553  				}
   554  			}
   555  		}
   556  		base.ExitIfErrors()
   557  
   558  		// Query target versions for modules providing packages matched by
   559  		// command line arguments.
   560  		byPath = runQueries(queryCache, queries, modOnly)
   561  
   562  		// Handle upgrades. This is needed for arguments that didn't match
   563  		// modules or matched different modules from a previous iteration. It
   564  		// also upgrades modules providing package dependencies if -u is set.
   565  		buildList, err := mvs.UpgradeAll(modload.Target, newUpgrader(byPath, seenPkgs))
   566  		if err != nil {
   567  			base.Fatalf("go get: %v", err)
   568  		}
   569  		modload.SetBuildList(buildList)
   570  		base.ExitIfErrors()
   571  
   572  		// Stop if no changes have been made to the build list.
   573  		buildList = modload.BuildList()
   574  		eq := len(buildList) == len(prevBuildList)
   575  		for i := 0; eq && i < len(buildList); i++ {
   576  			eq = buildList[i] == prevBuildList[i]
   577  		}
   578  		if eq {
   579  			break
   580  		}
   581  		prevBuildList = buildList
   582  	}
   583  	if !*getD {
   584  		// Only print warnings after the last iteration,
   585  		// and only if we aren't going to build.
   586  		search.WarnUnmatched(matches)
   587  	}
   588  
   589  	// Handle downgrades.
   590  	var down []module.Version
   591  	for _, m := range modload.BuildList() {
   592  		q := byPath[m.Path]
   593  		if q != nil && semver.Compare(m.Version, q.m.Version) > 0 {
   594  			down = append(down, module.Version{Path: m.Path, Version: q.m.Version})
   595  		}
   596  	}
   597  	if len(down) > 0 {
   598  		buildList, err := mvs.Downgrade(modload.Target, modload.Reqs(), down...)
   599  		if err != nil {
   600  			base.Fatalf("go: %v", err)
   601  		}
   602  		modload.SetBuildList(buildList)
   603  		modload.ReloadBuildList() // note: does not update go.mod
   604  		base.ExitIfErrors()
   605  	}
   606  
   607  	// Scan for any upgrades lost by the downgrades.
   608  	var lostUpgrades []*query
   609  	if len(down) > 0 {
   610  		versionByPath = make(map[string]string)
   611  		for _, m := range modload.BuildList() {
   612  			versionByPath[m.Path] = m.Version
   613  		}
   614  		for _, q := range byPath {
   615  			if v, ok := versionByPath[q.m.Path]; q.m.Version != "none" && (!ok || semver.Compare(v, q.m.Version) != 0) {
   616  				lostUpgrades = append(lostUpgrades, q)
   617  			}
   618  		}
   619  		sort.Slice(lostUpgrades, func(i, j int) bool {
   620  			return lostUpgrades[i].m.Path < lostUpgrades[j].m.Path
   621  		})
   622  	}
   623  	if len(lostUpgrades) > 0 {
   624  		desc := func(m module.Version) string {
   625  			s := m.Path + "@" + m.Version
   626  			t := byPath[m.Path]
   627  			if t != nil && t.arg != s {
   628  				s += " from " + t.arg
   629  			}
   630  			return s
   631  		}
   632  		downByPath := make(map[string]module.Version)
   633  		for _, d := range down {
   634  			downByPath[d.Path] = d
   635  		}
   636  
   637  		var buf strings.Builder
   638  		fmt.Fprintf(&buf, "go get: inconsistent versions:")
   639  		reqs := modload.Reqs()
   640  		for _, q := range lostUpgrades {
   641  			// We lost q because its build list requires a newer version of something in down.
   642  			// Figure out exactly what.
   643  			// Repeatedly constructing the build list is inefficient
   644  			// if there are MANY command-line arguments,
   645  			// but at least all the necessary requirement lists are cached at this point.
   646  			list, err := buildListForLostUpgrade(q.m, reqs)
   647  			if err != nil {
   648  				base.Fatalf("go: %v", err)
   649  			}
   650  
   651  			fmt.Fprintf(&buf, "\n\t%s", desc(q.m))
   652  			sep := " requires"
   653  			for _, m := range list {
   654  				if down, ok := downByPath[m.Path]; ok && semver.Compare(down.Version, m.Version) < 0 {
   655  					fmt.Fprintf(&buf, "%s %s@%s (not %s)", sep, m.Path, m.Version, desc(down))
   656  					sep = ","
   657  				}
   658  			}
   659  			if sep != "," {
   660  				// We have no idea why this happened.
   661  				// At least report the problem.
   662  				if v := versionByPath[q.m.Path]; v == "" {
   663  					fmt.Fprintf(&buf, " removed unexpectedly")
   664  				} else {
   665  					fmt.Fprintf(&buf, " ended up at %s unexpectedly", v)
   666  				}
   667  				fmt.Fprintf(&buf, " (please report at golang.org/issue/new)")
   668  			}
   669  		}
   670  		base.Fatalf("%v", buf.String())
   671  	}
   672  
   673  	// Everything succeeded. Update go.mod.
   674  	modload.AllowWriteGoMod()
   675  	modload.WriteGoMod()
   676  
   677  	// If -d was specified, we're done after the module work.
   678  	// We've already downloaded modules by loading packages above.
   679  	// Otherwise, we need to build and install the packages matched by
   680  	// command line arguments. This may be a different set of packages,
   681  	// since we only build packages for the target platform.
   682  	// Note that 'go get -u' without arguments is equivalent to
   683  	// 'go get -u .', so we'll typically build the package in the current
   684  	// directory.
   685  	if *getD || len(pkgPatterns) == 0 {
   686  		return
   687  	}
   688  	work.BuildInit()
   689  	pkgs := load.PackagesForBuild(pkgPatterns)
   690  	work.InstallPackages(pkgPatterns, pkgs)
   691  }
   692  
   693  // runQueries looks up modules at target versions in parallel. Results will be
   694  // cached. If the same module is referenced by multiple queries at different
   695  // versions (including earlier queries in the modOnly map), an error will be
   696  // reported. A map from module paths to queries is returned, which includes
   697  // queries and modOnly.
   698  func runQueries(cache map[querySpec]*query, queries []*query, modOnly map[string]*query) map[string]*query {
   699  	var lookup par.Work
   700  	for _, q := range queries {
   701  		if cached := cache[q.querySpec]; cached != nil {
   702  			*q = *cached
   703  		} else {
   704  			cache[q.querySpec] = q
   705  			lookup.Add(q)
   706  		}
   707  	}
   708  
   709  	lookup.Do(10, func(item interface{}) {
   710  		q := item.(*query)
   711  		if q.vers == "none" {
   712  			// Wait for downgrade step.
   713  			q.m = module.Version{Path: q.path, Version: "none"}
   714  			return
   715  		}
   716  		m, err := getQuery(q.path, q.vers, q.prevM, q.forceModulePath)
   717  		if err != nil {
   718  			base.Errorf("go get %s: %v", q.arg, err)
   719  		}
   720  		q.m = m
   721  	})
   722  	base.ExitIfErrors()
   723  
   724  	byPath := make(map[string]*query)
   725  	check := func(q *query) {
   726  		if prev, ok := byPath[q.m.Path]; prev != nil && prev.m != q.m {
   727  			base.Errorf("go get: conflicting versions for module %s: %s and %s", q.m.Path, prev.m.Version, q.m.Version)
   728  			byPath[q.m.Path] = nil // sentinel to stop errors
   729  			return
   730  		} else if !ok {
   731  			byPath[q.m.Path] = q
   732  		}
   733  	}
   734  	for _, q := range queries {
   735  		check(q)
   736  	}
   737  	for _, q := range modOnly {
   738  		check(q)
   739  	}
   740  	base.ExitIfErrors()
   741  
   742  	return byPath
   743  }
   744  
   745  // getQuery evaluates the given (package or module) path and version
   746  // to determine the underlying module version being requested.
   747  // If forceModulePath is set, getQuery must interpret path
   748  // as a module path.
   749  func getQuery(path, vers string, prevM module.Version, forceModulePath bool) (module.Version, error) {
   750  	if (prevM.Version != "") != forceModulePath {
   751  		// We resolve package patterns by calling QueryPattern, which does not
   752  		// accept a previous version and therefore cannot take it into account for
   753  		// the "latest" or "patch" queries.
   754  		// If we are resolving a package path or pattern, the caller has already
   755  		// resolved any existing packages to their containing module(s), and
   756  		// will set both prevM.Version and forceModulePath for those modules.
   757  		// The only remaining package patterns are those that are not already
   758  		// provided by the build list, which are indicated by
   759  		// an empty prevM.Version.
   760  		base.Fatalf("go get: internal error: prevM may be set if and only if forceModulePath is set")
   761  	}
   762  
   763  	// If the query must be a module path, try only that module path.
   764  	if forceModulePath {
   765  		if path == modload.Target.Path {
   766  			if vers != "latest" {
   767  				return module.Version{}, fmt.Errorf("can't get a specific version of the main module")
   768  			}
   769  		}
   770  
   771  		info, err := modload.Query(path, vers, prevM.Version, modload.Allowed)
   772  		if err == nil {
   773  			if info.Version != vers && info.Version != prevM.Version {
   774  				logOncef("go: %s %s => %s", path, vers, info.Version)
   775  			}
   776  			return module.Version{Path: path, Version: info.Version}, nil
   777  		}
   778  
   779  		// If the query was "upgrade" or "patch" and the current version has been
   780  		// replaced, check to see whether the error was for that same version:
   781  		// if so, the version was probably replaced because it is invalid,
   782  		// and we should keep that replacement without complaining.
   783  		if vers == "upgrade" || vers == "patch" {
   784  			var vErr *module.InvalidVersionError
   785  			if errors.As(err, &vErr) && vErr.Version == prevM.Version && modload.Replacement(prevM).Path != "" {
   786  				return prevM, nil
   787  			}
   788  		}
   789  
   790  		return module.Version{}, err
   791  	}
   792  
   793  	// If the query may be either a package or a module, try it as a package path.
   794  	// If it turns out to only exist as a module, we can detect the resulting
   795  	// PackageNotInModuleError and avoid a second round-trip through (potentially)
   796  	// all of the configured proxies.
   797  	results, err := modload.QueryPattern(path, vers, modload.Allowed)
   798  	if err != nil {
   799  		// If the path doesn't contain a wildcard, check whether it was actually a
   800  		// module path instead. If so, return that.
   801  		if !strings.Contains(path, "...") {
   802  			var modErr *modload.PackageNotInModuleError
   803  			if errors.As(err, &modErr) && modErr.Mod.Path == path {
   804  				if modErr.Mod.Version != vers {
   805  					logOncef("go: %s %s => %s", path, vers, modErr.Mod.Version)
   806  				}
   807  				return modErr.Mod, nil
   808  			}
   809  		}
   810  
   811  		return module.Version{}, err
   812  	}
   813  
   814  	m := results[0].Mod
   815  	if m.Path != path {
   816  		logOncef("go: found %s in %s %s", path, m.Path, m.Version)
   817  	} else if m.Version != vers {
   818  		logOncef("go: %s %s => %s", path, vers, m.Version)
   819  	}
   820  	return m, nil
   821  }
   822  
   823  // An upgrader adapts an underlying mvs.Reqs to apply an
   824  // upgrade policy to a list of targets and their dependencies.
   825  type upgrader struct {
   826  	mvs.Reqs
   827  
   828  	// cmdline maps a module path to a query made for that module at a
   829  	// specific target version. Each query corresponds to a module
   830  	// matched by a command line argument.
   831  	cmdline map[string]*query
   832  
   833  	// upgrade is a set of modules providing dependencies of packages
   834  	// matched by command line arguments. If -u or -u=patch is set,
   835  	// these modules are upgraded accordingly.
   836  	upgrade map[string]bool
   837  }
   838  
   839  // newUpgrader creates an upgrader. cmdline contains queries made at
   840  // specific versions for modules matched by command line arguments. pkgs
   841  // is the set of packages matched by command line arguments. If -u or -u=patch
   842  // is set, modules providing dependencies of pkgs are upgraded accordingly.
   843  func newUpgrader(cmdline map[string]*query, pkgs map[string]bool) *upgrader {
   844  	u := &upgrader{
   845  		Reqs:    modload.Reqs(),
   846  		cmdline: cmdline,
   847  	}
   848  	if getU != "" {
   849  		u.upgrade = make(map[string]bool)
   850  
   851  		// Traverse package import graph.
   852  		// Initialize work queue with root packages.
   853  		seen := make(map[string]bool)
   854  		var work []string
   855  		add := func(path string) {
   856  			if !seen[path] {
   857  				seen[path] = true
   858  				work = append(work, path)
   859  			}
   860  		}
   861  		for pkg := range pkgs {
   862  			add(pkg)
   863  		}
   864  		for len(work) > 0 {
   865  			pkg := work[0]
   866  			work = work[1:]
   867  			m := modload.PackageModule(pkg)
   868  			u.upgrade[m.Path] = true
   869  
   870  			// testImports is empty unless test imports were actually loaded,
   871  			// i.e., -t was set or "all" was one of the arguments.
   872  			imports, testImports := modload.PackageImports(pkg)
   873  			for _, imp := range imports {
   874  				add(imp)
   875  			}
   876  			for _, imp := range testImports {
   877  				add(imp)
   878  			}
   879  		}
   880  	}
   881  	return u
   882  }
   883  
   884  // Required returns the requirement list for m.
   885  // For the main module, we override requirements with the modules named
   886  // one the command line, and we include new requirements. Otherwise,
   887  // we defer to u.Reqs.
   888  func (u *upgrader) Required(m module.Version) ([]module.Version, error) {
   889  	rs, err := u.Reqs.Required(m)
   890  	if err != nil {
   891  		return nil, err
   892  	}
   893  	if m != modload.Target {
   894  		return rs, nil
   895  	}
   896  
   897  	overridden := make(map[string]bool)
   898  	for i, m := range rs {
   899  		if q := u.cmdline[m.Path]; q != nil && q.m.Version != "none" {
   900  			rs[i] = q.m
   901  			overridden[q.m.Path] = true
   902  		}
   903  	}
   904  	for _, q := range u.cmdline {
   905  		if !overridden[q.m.Path] && q.m.Path != modload.Target.Path && q.m.Version != "none" {
   906  			rs = append(rs, q.m)
   907  		}
   908  	}
   909  	return rs, nil
   910  }
   911  
   912  // Upgrade returns the desired upgrade for m.
   913  //
   914  // If m was requested at a specific version on the command line, then
   915  // Upgrade returns that version.
   916  //
   917  // If -u is set and m provides a dependency of a package matched by
   918  // command line arguments, then Upgrade may provider a newer tagged version.
   919  // If m is a tagged version, then Upgrade will return the latest tagged
   920  // version (with the same minor version number if -u=patch).
   921  // If m is a pseudo-version, then Upgrade returns the latest tagged version
   922  // only if that version has a time-stamp newer than m. This special case
   923  // prevents accidental downgrades when already using a pseudo-version
   924  // newer than the latest tagged version.
   925  //
   926  // If none of the above cases apply, then Upgrade returns m.
   927  func (u *upgrader) Upgrade(m module.Version) (module.Version, error) {
   928  	// Allow pkg@vers on the command line to override the upgrade choice v.
   929  	// If q's version is < m.Version, then we're going to downgrade anyway,
   930  	// and it's cleaner to avoid moving back and forth and picking up
   931  	// extraneous other newer dependencies.
   932  	// If q's version is > m.Version, then we're going to upgrade past
   933  	// m.Version anyway, and again it's cleaner to avoid moving back and forth
   934  	// picking up extraneous other newer dependencies.
   935  	if q := u.cmdline[m.Path]; q != nil {
   936  		return q.m, nil
   937  	}
   938  
   939  	if !u.upgrade[m.Path] {
   940  		// Not involved in upgrade. Leave alone.
   941  		return m, nil
   942  	}
   943  
   944  	// Run query required by upgrade semantics.
   945  	// Note that Query "latest" is not the same as using repo.Latest,
   946  	// which may return a pseudoversion for the latest commit.
   947  	// Query "latest" returns the newest tagged version or the newest
   948  	// prerelease version if there are no non-prereleases, or repo.Latest
   949  	// if there aren't any tagged versions.
   950  	// If we're querying "upgrade" or "patch", Query will compare the current
   951  	// version against the chosen version and will return the current version
   952  	// if it is newer.
   953  	info, err := modload.Query(m.Path, string(getU), m.Version, modload.Allowed)
   954  	if err != nil {
   955  		// Report error but return m, to let version selection continue.
   956  		// (Reporting the error will fail the command at the next base.ExitIfErrors.)
   957  
   958  		// Special case: if the error is for m.Version itself and m.Version has a
   959  		// replacement, then keep it and don't report the error: the fact that the
   960  		// version is invalid is likely the reason it was replaced to begin with.
   961  		var vErr *module.InvalidVersionError
   962  		if errors.As(err, &vErr) && vErr.Version == m.Version && modload.Replacement(m).Path != "" {
   963  			return m, nil
   964  		}
   965  
   966  		// Special case: if the error is "no matching versions" then don't
   967  		// even report the error. Because Query does not consider pseudo-versions,
   968  		// it may happen that we have a pseudo-version but during -u=patch
   969  		// the query v0.0 matches no versions (not even the one we're using).
   970  		var noMatch *modload.NoMatchingVersionError
   971  		if !errors.As(err, &noMatch) {
   972  			base.Errorf("go get: upgrading %s@%s: %v", m.Path, m.Version, err)
   973  		}
   974  		return m, nil
   975  	}
   976  
   977  	if info.Version != m.Version {
   978  		logOncef("go: %s %s => %s", m.Path, getU, info.Version)
   979  	}
   980  	return module.Version{Path: m.Path, Version: info.Version}, nil
   981  }
   982  
   983  // buildListForLostUpgrade returns the build list for the module graph
   984  // rooted at lost. Unlike mvs.BuildList, the target module (lost) is not
   985  // treated specially. The returned build list may contain a newer version
   986  // of lost.
   987  //
   988  // buildListForLostUpgrade is used after a downgrade has removed a module
   989  // requested at a specific version. This helps us understand the requirements
   990  // implied by each downgrade.
   991  func buildListForLostUpgrade(lost module.Version, reqs mvs.Reqs) ([]module.Version, error) {
   992  	return mvs.BuildList(lostUpgradeRoot, &lostUpgradeReqs{Reqs: reqs, lost: lost})
   993  }
   994  
   995  var lostUpgradeRoot = module.Version{Path: "lost-upgrade-root", Version: ""}
   996  
   997  type lostUpgradeReqs struct {
   998  	mvs.Reqs
   999  	lost module.Version
  1000  }
  1001  
  1002  func (r *lostUpgradeReqs) Required(mod module.Version) ([]module.Version, error) {
  1003  	if mod == lostUpgradeRoot {
  1004  		return []module.Version{r.lost}, nil
  1005  	}
  1006  	return r.Reqs.Required(mod)
  1007  }
  1008  
  1009  var loggedLines sync.Map
  1010  
  1011  func logOncef(format string, args ...interface{}) {
  1012  	msg := fmt.Sprintf(format, args...)
  1013  	if _, dup := loggedLines.LoadOrStore(msg, true); !dup {
  1014  		fmt.Fprintln(os.Stderr, msg)
  1015  	}
  1016  }