github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/cmd/go/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  	"cmd/go/internal/base"
    10  	"cmd/go/internal/cfg"
    11  	"cmd/go/internal/get"
    12  	"cmd/go/internal/load"
    13  	"cmd/go/internal/modfetch"
    14  	"cmd/go/internal/modload"
    15  	"cmd/go/internal/module"
    16  	"cmd/go/internal/mvs"
    17  	"cmd/go/internal/par"
    18  	"cmd/go/internal/search"
    19  	"cmd/go/internal/semver"
    20  	"cmd/go/internal/str"
    21  	"cmd/go/internal/work"
    22  	"fmt"
    23  	"os"
    24  	pathpkg "path"
    25  	"path/filepath"
    26  	"strings"
    27  )
    28  
    29  var CmdGet = &base.Command{
    30  	// Note: -d -m -u are listed explicitly because they are the most common get flags.
    31  	// Do not send CLs removing them because they're covered by [get flags].
    32  	UsageLine: "go get [-d] [-m] [-u] [-v] [-insecure] [build flags] [packages]",
    33  	Short:     "add dependencies to current module and install them",
    34  	Long: `
    35  Get resolves and adds dependencies to the current development module
    36  and then builds and installs them.
    37  
    38  The first step is to resolve which dependencies to add.
    39  
    40  For each named package or package pattern, get must decide which version of
    41  the corresponding module to use. By default, get chooses the latest tagged
    42  release version, such as v0.4.5 or v1.2.3. If there are no tagged release
    43  versions, get chooses the latest tagged prerelease version, such as
    44  v0.0.1-pre1. If there are no tagged versions at all, get chooses the latest
    45  known commit.
    46  
    47  This default version selection can be overridden by adding an @version
    48  suffix to the package argument, as in 'go get golang.org/x/text@v0.3.0'.
    49  For modules stored in source control repositories, the version suffix can
    50  also be a commit hash, branch identifier, or other syntax known to the
    51  source control system, as in 'go get golang.org/x/text@master'.
    52  The version suffix @latest explicitly requests the default behavior
    53  described above.
    54  
    55  If a module under consideration is already a dependency of the current
    56  development module, then get will update the required version.
    57  Specifying a version earlier than the current required version is valid and
    58  downgrades the dependency. The version suffix @none indicates that the
    59  dependency should be removed entirely, downgrading or removing modules
    60  depending on it as needed.
    61  
    62  Although get defaults to using the latest version of the module containing
    63  a named package, it does not use the latest version of that module's
    64  dependencies. Instead it prefers to use the specific dependency versions
    65  requested by that module. For example, if the latest A requires module
    66  B v1.2.3, while B v1.2.4 and v1.3.1 are also available, then 'go get A'
    67  will use the latest A but then use B v1.2.3, as requested by A. (If there
    68  are competing requirements for a particular module, then 'go get' resolves
    69  those requirements by taking the maximum requested version.)
    70  
    71  The -u flag instructs get to update dependencies to use newer minor or
    72  patch releases when available. Continuing the previous example,
    73  'go get -u A' will use the latest A with B v1.3.1 (not B v1.2.3).
    74  
    75  The -u=patch flag (not -u patch) instructs get to update dependencies
    76  to use newer patch releases when available. Continuing the previous example,
    77  'go get -u=patch A' will use the latest A with B v1.2.4 (not B v1.2.3).
    78  
    79  In general, adding a new dependency may require upgrading
    80  existing dependencies to keep a working build, and 'go get' does
    81  this automatically. Similarly, downgrading one dependency may
    82  require downgrading other dependencies, and 'go get' does
    83  this automatically as well.
    84  
    85  The -m flag instructs get to stop here, after resolving, upgrading,
    86  and downgrading modules and updating go.mod. When using -m,
    87  each specified package path must be a module path as well,
    88  not the import path of a package below the module root.
    89  
    90  The -insecure flag permits fetching from repositories and resolving
    91  custom domains using insecure schemes such as HTTP. Use with caution.
    92  
    93  The second step is to download (if needed), build, and install
    94  the named packages.
    95  
    96  If an argument names a module but not a package (because there is no
    97  Go source code in the module's root directory), then the install step
    98  is skipped for that argument, instead of causing a build failure.
    99  For example 'go get golang.org/x/perf' succeeds even though there
   100  is no code corresponding to that import path.
   101  
   102  Note that package patterns are allowed and are expanded after resolving
   103  the module versions. For example, 'go get golang.org/x/perf/cmd/...'
   104  adds the latest golang.org/x/perf and then installs the commands in that
   105  latest version.
   106  
   107  The -d flag instructs get to download the source code needed to build
   108  the named packages, including downloading necessary dependencies,
   109  but not to build and install them.
   110  
   111  With no package arguments, 'go get' applies to the main module,
   112  and to the Go package in the current directory, if any. In particular,
   113  'go get -u' and 'go get -u=patch' update all the dependencies of the
   114  main module. With no package arguments and also without -u,
   115  'go get' is not much more than 'go install', and 'go get -d' not much
   116  more than 'go list'.
   117  
   118  For more about modules, see 'go help modules'.
   119  
   120  For more about specifying packages, see 'go help packages'.
   121  
   122  This text describes the behavior of get using modules to manage source
   123  code and dependencies. If instead the go command is running in GOPATH
   124  mode, the details of get's flags and effects change, as does 'go help get'.
   125  See 'go help modules' and 'go help gopath-get'.
   126  
   127  See also: go build, go install, go clean, go mod.
   128  	`,
   129  }
   130  
   131  // Note that this help text is a stopgap to make the module-aware get help text
   132  // available even in non-module settings. It should be deleted when the old get
   133  // is deleted. It should NOT be considered to set a precedent of having hierarchical
   134  // help names with dashes.
   135  var HelpModuleGet = &base.Command{
   136  	UsageLine: "module-get",
   137  	Short:     "module-aware go get",
   138  	Long: `
   139  The 'go get' command changes behavior depending on whether the
   140  go command is running in module-aware mode or legacy GOPATH mode.
   141  This help text, accessible as 'go help module-get' even in legacy GOPATH mode,
   142  describes 'go get' as it operates in module-aware mode.
   143  
   144  Usage: ` + CmdGet.UsageLine + `
   145  ` + CmdGet.Long,
   146  }
   147  
   148  var (
   149  	getD   = CmdGet.Flag.Bool("d", false, "")
   150  	getF   = CmdGet.Flag.Bool("f", false, "")
   151  	getFix = CmdGet.Flag.Bool("fix", false, "")
   152  	getM   = CmdGet.Flag.Bool("m", false, "")
   153  	getT   = CmdGet.Flag.Bool("t", false, "")
   154  	getU   upgradeFlag
   155  	// -insecure is get.Insecure
   156  	// -v is cfg.BuildV
   157  )
   158  
   159  // upgradeFlag is a custom flag.Value for -u.
   160  type upgradeFlag string
   161  
   162  func (*upgradeFlag) IsBoolFlag() bool { return true } // allow -u
   163  
   164  func (v *upgradeFlag) Set(s string) error {
   165  	if s == "false" {
   166  		s = ""
   167  	}
   168  	*v = upgradeFlag(s)
   169  	return nil
   170  }
   171  
   172  func (v *upgradeFlag) String() string { return "" }
   173  
   174  func init() {
   175  	work.AddBuildFlags(CmdGet)
   176  	CmdGet.Run = runGet // break init loop
   177  	CmdGet.Flag.BoolVar(&get.Insecure, "insecure", get.Insecure, "")
   178  	CmdGet.Flag.Var(&getU, "u", "")
   179  }
   180  
   181  // A task holds the state for processing a single get argument (path@vers).
   182  type task struct {
   183  	arg             string // original argument
   184  	index           int
   185  	path            string           // package path part of arg
   186  	forceModulePath bool             // path must be interpreted as a module path
   187  	vers            string           // version part of arg
   188  	m               module.Version   // module version indicated by argument
   189  	req             []module.Version // m's requirement list (not upgraded)
   190  }
   191  
   192  func runGet(cmd *base.Command, args []string) {
   193  	// -mod=readonly has no effect on "go get".
   194  	if cfg.BuildMod == "readonly" {
   195  		cfg.BuildMod = ""
   196  	}
   197  
   198  	switch getU {
   199  	case "", "patch", "true":
   200  		// ok
   201  	default:
   202  		base.Fatalf("go get: unknown upgrade flag -u=%s", getU)
   203  	}
   204  	if *getF {
   205  		fmt.Fprintf(os.Stderr, "go get: -f flag is a no-op when using modules\n")
   206  	}
   207  	if *getFix {
   208  		fmt.Fprintf(os.Stderr, "go get: -fix flag is a no-op when using modules\n")
   209  	}
   210  	if *getT {
   211  		fmt.Fprintf(os.Stderr, "go get: -t flag is a no-op when using modules\n")
   212  	}
   213  
   214  	if cfg.BuildMod == "vendor" {
   215  		base.Fatalf("go get: disabled by -mod=%s", cfg.BuildMod)
   216  	}
   217  
   218  	modload.LoadBuildList()
   219  
   220  	// Do not allow any updating of go.mod until we've applied
   221  	// all the requested changes and checked that the result matches
   222  	// what was requested.
   223  	modload.DisallowWriteGoMod()
   224  
   225  	// Build task and install lists.
   226  	// The command-line arguments are of the form path@version
   227  	// or simply path, with implicit @latest. path@none is "downgrade away".
   228  	// At the end of the loop, we've resolved the list of arguments into
   229  	// a list of tasks (a path@vers that needs further processing)
   230  	// and a list of install targets (for the "go install" at the end).
   231  	var tasks []*task
   232  	var install []string
   233  	for _, arg := range search.CleanPatterns(args) {
   234  		// Argument is module query path@vers, or else path with implicit @latest.
   235  		path := arg
   236  		vers := ""
   237  		if i := strings.Index(arg, "@"); i >= 0 {
   238  			path, vers = arg[:i], arg[i+1:]
   239  		}
   240  		if strings.Contains(vers, "@") || arg != path && vers == "" {
   241  			base.Errorf("go get %s: invalid module version syntax", arg)
   242  			continue
   243  		}
   244  		if vers != "none" {
   245  			install = append(install, path)
   246  		}
   247  
   248  		// Deciding which module to upgrade/downgrade for a particular argument is difficult.
   249  		// Patterns only make it more difficult.
   250  		// We impose restrictions to avoid needing to interlace pattern expansion,
   251  		// like in modload.ImportPaths.
   252  		// Specifically, these patterns are supported:
   253  		//
   254  		//	- Relative paths like ../../foo or ../../foo... are restricted to matching directories
   255  		//	  in the current module and therefore map to the current module.
   256  		//	  It's possible that the pattern matches no packages, but we will still treat it
   257  		//	  as mapping to the current module.
   258  		//	  TODO: In followup, could just expand the full list and remove the discrepancy.
   259  		//	- The pattern "all" has its usual package meaning and maps to the list of modules
   260  		//	  from which the matched packages are drawn. This is potentially a subset of the
   261  		//	  module pattern "all". If module A requires B requires C but A does not import
   262  		//	  the parts of B that import C, the packages matched by "all" are only from A and B,
   263  		//	  so only A and B end up on the tasks list.
   264  		//	  TODO: Even in -m mode?
   265  		//	- The patterns "std" and "cmd" expand to packages in the standard library,
   266  		//	  which aren't upgradable, so we skip over those.
   267  		//	  In -m mode they expand to non-module-paths, so they are disallowed.
   268  		//	- Import path patterns like foo/bar... are matched against the module list,
   269  		//	  assuming any package match would imply a module pattern match.
   270  		//	  TODO: What about -m mode?
   271  		//	- Import paths without patterns are left as is, for resolution by getQuery (eventually modload.Import).
   272  		//
   273  		if search.IsRelativePath(path) {
   274  			// Check that this relative pattern only matches directories in the current module,
   275  			// and then record the current module as the target.
   276  			dir := path
   277  			if i := strings.Index(path, "..."); i >= 0 {
   278  				dir, _ = pathpkg.Split(path[:i])
   279  			}
   280  			abs, err := filepath.Abs(dir)
   281  			if err != nil {
   282  				base.Errorf("go get %s: %v", arg, err)
   283  				continue
   284  			}
   285  			if !str.HasFilePathPrefix(abs, modload.ModRoot()) {
   286  				base.Errorf("go get %s: directory %s is outside module root %s", arg, abs, modload.ModRoot())
   287  				continue
   288  			}
   289  			// TODO: Check if abs is inside a nested module.
   290  			tasks = append(tasks, &task{arg: arg, path: modload.Target.Path, vers: ""})
   291  			continue
   292  		}
   293  		if path == "all" {
   294  			// TODO: If *getM, should this be the module pattern "all"?
   295  
   296  			// This is the package pattern "all" not the module pattern "all":
   297  			// enumerate all the modules actually needed by builds of the packages
   298  			// in the main module, not incidental modules that happen to be
   299  			// in the package graph (and therefore build list).
   300  			// Note that LoadALL may add new modules to the build list to
   301  			// satisfy new imports, but vers == "latest" implicitly anyway,
   302  			// so we'll assume that's OK.
   303  			seen := make(map[module.Version]bool)
   304  			pkgs := modload.LoadALL()
   305  			for _, pkg := range pkgs {
   306  				m := modload.PackageModule(pkg)
   307  				if m.Path != "" && !seen[m] {
   308  					seen[m] = true
   309  					tasks = append(tasks, &task{arg: arg, path: m.Path, vers: "latest", forceModulePath: true})
   310  				}
   311  			}
   312  			continue
   313  		}
   314  		if search.IsMetaPackage(path) {
   315  			// Already handled "all", so this must be "std" or "cmd",
   316  			// which are entirely in the standard library.
   317  			if path != arg {
   318  				base.Errorf("go get %s: cannot use pattern %q with explicit version", arg, arg)
   319  			}
   320  			if *getM {
   321  				base.Errorf("go get %s: cannot use pattern %q with -m", arg, arg)
   322  				continue
   323  			}
   324  			continue
   325  		}
   326  		if strings.Contains(path, "...") {
   327  			// Apply to modules in build list matched by pattern (golang.org/x/...), if any.
   328  			match := search.MatchPattern(path)
   329  			matched := false
   330  			for _, m := range modload.BuildList() {
   331  				if match(m.Path) || str.HasPathPrefix(path, m.Path) {
   332  					tasks = append(tasks, &task{arg: arg, path: m.Path, vers: vers, forceModulePath: true})
   333  					matched = true
   334  				}
   335  			}
   336  			// If matched, we're done.
   337  			// Otherwise assume pattern is inside a single module
   338  			// (golang.org/x/text/unicode/...) and leave for usual lookup.
   339  			// Unless we're using -m.
   340  			if matched {
   341  				continue
   342  			}
   343  			if *getM {
   344  				base.Errorf("go get %s: pattern matches no modules in build list", arg)
   345  				continue
   346  			}
   347  		}
   348  		tasks = append(tasks, &task{arg: arg, path: path, vers: vers})
   349  	}
   350  	base.ExitIfErrors()
   351  
   352  	// Now we've reduced the upgrade/downgrade work to a list of path@vers pairs (tasks).
   353  	// Resolve each one in parallel.
   354  	reqs := modload.Reqs()
   355  	var lookup par.Work
   356  	for _, t := range tasks {
   357  		lookup.Add(t)
   358  	}
   359  	lookup.Do(10, func(item interface{}) {
   360  		t := item.(*task)
   361  		if t.vers == "none" {
   362  			// Wait for downgrade step.
   363  			t.m = module.Version{Path: t.path, Version: "none"}
   364  			return
   365  		}
   366  		m, err := getQuery(t.path, t.vers, t.forceModulePath)
   367  		if err != nil {
   368  			base.Errorf("go get %v: %v", t.arg, err)
   369  			return
   370  		}
   371  		t.m = m
   372  	})
   373  	base.ExitIfErrors()
   374  
   375  	// Now we know the specific version of each path@vers.
   376  	// The final build list will be the union of three build lists:
   377  	//	1. the original build list
   378  	//	2. the modules named on the command line (other than @none)
   379  	//	3. the upgraded requirements of those modules (if upgrading)
   380  	// Start building those lists.
   381  	// This loop collects (2).
   382  	// Also, because the list of paths might have named multiple packages in a single module
   383  	// (or even the same package multiple times), now that we know the module for each
   384  	// package, this loop deduplicates multiple references to a given module.
   385  	// (If a module is mentioned multiple times, the listed target version must be the same each time.)
   386  	var named []module.Version
   387  	byPath := make(map[string]*task)
   388  	for _, t := range tasks {
   389  		prev, ok := byPath[t.m.Path]
   390  		if prev != nil && prev.m != t.m {
   391  			base.Errorf("go get: conflicting versions for module %s: %s and %s", t.m.Path, prev.m.Version, t.m.Version)
   392  			byPath[t.m.Path] = nil // sentinel to stop errors
   393  			continue
   394  		}
   395  		if ok {
   396  			continue // already added
   397  		}
   398  		byPath[t.m.Path] = t
   399  		if t.m.Version != "none" {
   400  			named = append(named, t.m)
   401  		}
   402  	}
   403  	base.ExitIfErrors()
   404  
   405  	// If the modules named on the command line have any dependencies
   406  	// and we're supposed to upgrade dependencies,
   407  	// chase down the full list of upgraded dependencies.
   408  	// This turns required from a not-yet-upgraded (3) to the final (3).
   409  	// (See list above.)
   410  	var required []module.Version
   411  	if getU != "" {
   412  		upgraded, err := mvs.UpgradeAll(upgradeTarget, &upgrader{
   413  			Reqs:    modload.Reqs(),
   414  			targets: named,
   415  			patch:   getU == "patch",
   416  			tasks:   byPath,
   417  		})
   418  		if err != nil {
   419  			base.Fatalf("go get: %v", err)
   420  		}
   421  		required = upgraded[1:] // slice off upgradeTarget
   422  		base.ExitIfErrors()
   423  	}
   424  
   425  	// Put together the final build list as described above (1) (2) (3).
   426  	// If we're not using -u, then len(required) == 0 and ReloadBuildList
   427  	// chases down the dependencies of all the named module versions
   428  	// in one operation.
   429  	var list []module.Version
   430  	list = append(list, modload.BuildList()...)
   431  	list = append(list, named...)
   432  	list = append(list, required...)
   433  	modload.SetBuildList(list)
   434  	modload.ReloadBuildList() // note: does not update go.mod
   435  	base.ExitIfErrors()
   436  
   437  	// Scan for and apply any needed downgrades.
   438  	var down []module.Version
   439  	for _, m := range modload.BuildList() {
   440  		t := byPath[m.Path]
   441  		if t != nil && semver.Compare(m.Version, t.m.Version) > 0 {
   442  			down = append(down, module.Version{Path: m.Path, Version: t.m.Version})
   443  		}
   444  	}
   445  	if len(down) > 0 {
   446  		list, err := mvs.Downgrade(modload.Target, modload.Reqs(), down...)
   447  		if err != nil {
   448  			base.Fatalf("go get: %v", err)
   449  		}
   450  		modload.SetBuildList(list)
   451  		modload.ReloadBuildList() // note: does not update go.mod
   452  	}
   453  	base.ExitIfErrors()
   454  
   455  	// Scan for any upgrades lost by the downgrades.
   456  	lost := make(map[string]string)
   457  	for _, m := range modload.BuildList() {
   458  		t := byPath[m.Path]
   459  		if t != nil && semver.Compare(m.Version, t.m.Version) != 0 {
   460  			lost[m.Path] = m.Version
   461  		}
   462  	}
   463  	if len(lost) > 0 {
   464  		desc := func(m module.Version) string {
   465  			s := m.Path + "@" + m.Version
   466  			t := byPath[m.Path]
   467  			if t != nil && t.arg != s {
   468  				s += " from " + t.arg
   469  			}
   470  			return s
   471  		}
   472  		downByPath := make(map[string]module.Version)
   473  		for _, d := range down {
   474  			downByPath[d.Path] = d
   475  		}
   476  		var buf strings.Builder
   477  		fmt.Fprintf(&buf, "go get: inconsistent versions:")
   478  		for _, t := range tasks {
   479  			if lost[t.m.Path] == "" {
   480  				continue
   481  			}
   482  			// We lost t because its build list requires a newer version of something in down.
   483  			// Figure out exactly what.
   484  			// Repeatedly constructing the build list is inefficient
   485  			// if there are MANY command-line arguments,
   486  			// but at least all the necessary requirement lists are cached at this point.
   487  			list, err := mvs.BuildList(t.m, reqs)
   488  			if err != nil {
   489  				base.Fatalf("go get: %v", err)
   490  			}
   491  
   492  			fmt.Fprintf(&buf, "\n\t%s", desc(t.m))
   493  			sep := " requires"
   494  			for _, m := range list {
   495  				if down, ok := downByPath[m.Path]; ok && semver.Compare(down.Version, m.Version) < 0 {
   496  					fmt.Fprintf(&buf, "%s %s@%s (not %s)", sep, m.Path, m.Version, desc(down))
   497  					sep = ","
   498  				}
   499  			}
   500  			if sep != "," {
   501  				// We have no idea why this happened.
   502  				// At least report the problem.
   503  				fmt.Fprintf(&buf, " ended up at %v unexpectedly (please report at golang.org/issue/new)", lost[t.m.Path])
   504  			}
   505  		}
   506  		base.Fatalf("%v", buf.String())
   507  	}
   508  
   509  	// Everything succeeded. Update go.mod.
   510  	modload.AllowWriteGoMod()
   511  	modload.WriteGoMod()
   512  
   513  	// If -m was specified, we're done after the module work. No download, no build.
   514  	if *getM {
   515  		return
   516  	}
   517  
   518  	if len(install) > 0 {
   519  		// All requested versions were explicitly @none.
   520  		// Note that 'go get -u' without any arguments results in len(install) == 1:
   521  		// search.CleanImportPaths returns "." for empty args.
   522  		work.BuildInit()
   523  		pkgs := load.PackagesAndErrors(install)
   524  		var todo []*load.Package
   525  		for _, p := range pkgs {
   526  			// Ignore "no Go source files" errors for 'go get' operations on modules.
   527  			if p.Error != nil {
   528  				if len(args) == 0 && getU != "" && strings.HasPrefix(p.Error.Err, "no Go files") {
   529  					// Upgrading modules: skip the implicitly-requested package at the
   530  					// current directory, even if it is not tho module root.
   531  					continue
   532  				}
   533  				if strings.Contains(p.Error.Err, "cannot find module providing") && modload.ModuleInfo(p.ImportPath) != nil {
   534  					// Explicitly-requested module, but it doesn't contain a package at the
   535  					// module root.
   536  					continue
   537  				}
   538  				base.Errorf("%s", p.Error)
   539  			}
   540  			todo = append(todo, p)
   541  		}
   542  		base.ExitIfErrors()
   543  
   544  		// If -d was specified, we're done after the download: no build.
   545  		// (The load.PackagesAndErrors is what did the download
   546  		// of the named packages and their dependencies.)
   547  		if len(todo) > 0 && !*getD {
   548  			work.InstallPackages(install, todo)
   549  		}
   550  	}
   551  }
   552  
   553  // getQuery evaluates the given package path, version pair
   554  // to determine the underlying module version being requested.
   555  // If forceModulePath is set, getQuery must interpret path
   556  // as a module path.
   557  func getQuery(path, vers string, forceModulePath bool) (module.Version, error) {
   558  	if vers == "" {
   559  		vers = "latest"
   560  	}
   561  
   562  	// First choice is always to assume path is a module path.
   563  	// If that works out, we're done.
   564  	info, err := modload.Query(path, vers, modload.Allowed)
   565  	if err == nil {
   566  		return module.Version{Path: path, Version: info.Version}, nil
   567  	}
   568  
   569  	// Even if the query fails, if the path must be a real module, then report the query error.
   570  	if forceModulePath || *getM {
   571  		return module.Version{}, err
   572  	}
   573  
   574  	// Otherwise, try a package path.
   575  	m, _, err := modload.QueryPackage(path, vers, modload.Allowed)
   576  	return m, err
   577  }
   578  
   579  // An upgrader adapts an underlying mvs.Reqs to apply an
   580  // upgrade policy to a list of targets and their dependencies.
   581  // If patch=false, the upgrader implements "get -u".
   582  // If patch=true, the upgrader implements "get -u=patch".
   583  type upgrader struct {
   584  	mvs.Reqs
   585  	targets []module.Version
   586  	patch   bool
   587  	tasks   map[string]*task
   588  }
   589  
   590  // upgradeTarget is a fake "target" requiring all the modules to be upgraded.
   591  var upgradeTarget = module.Version{Path: "upgrade target", Version: ""}
   592  
   593  // Required returns the requirement list for m.
   594  // Other than the upgradeTarget, we defer to u.Reqs.
   595  func (u *upgrader) Required(m module.Version) ([]module.Version, error) {
   596  	if m == upgradeTarget {
   597  		return u.targets, nil
   598  	}
   599  	return u.Reqs.Required(m)
   600  }
   601  
   602  // Upgrade returns the desired upgrade for m.
   603  // If m is a tagged version, then Upgrade returns the latest tagged version.
   604  // If m is a pseudo-version, then Upgrade returns the latest tagged version
   605  // when that version has a time-stamp newer than m.
   606  // Otherwise Upgrade returns m (preserving the pseudo-version).
   607  // This special case prevents accidental downgrades
   608  // when already using a pseudo-version newer than the latest tagged version.
   609  func (u *upgrader) Upgrade(m module.Version) (module.Version, error) {
   610  	// Allow pkg@vers on the command line to override the upgrade choice v.
   611  	// If t's version is < v, then we're going to downgrade anyway,
   612  	// and it's cleaner to avoid moving back and forth and picking up
   613  	// extraneous other newer dependencies.
   614  	// If t's version is > v, then we're going to upgrade past v anyway,
   615  	// and again it's cleaner to avoid moving back and forth picking up
   616  	// extraneous other newer dependencies.
   617  	if t := u.tasks[m.Path]; t != nil {
   618  		return t.m, nil
   619  	}
   620  
   621  	// Note that query "latest" is not the same as
   622  	// using repo.Latest.
   623  	// The query only falls back to untagged versions
   624  	// if nothing is tagged. The Latest method
   625  	// only ever returns untagged versions,
   626  	// which is not what we want.
   627  	query := "latest"
   628  	if u.patch {
   629  		// For patch upgrade, query "v1.2".
   630  		query = semver.MajorMinor(m.Version)
   631  	}
   632  	info, err := modload.Query(m.Path, query, modload.Allowed)
   633  	if err != nil {
   634  		// Report error but return m, to let version selection continue.
   635  		// (Reporting the error will fail the command at the next base.ExitIfErrors.)
   636  		// Special case: if the error is "no matching versions" then don't
   637  		// even report the error. Because Query does not consider pseudo-versions,
   638  		// it may happen that we have a pseudo-version but during -u=patch
   639  		// the query v0.0 matches no versions (not even the one we're using).
   640  		if !strings.Contains(err.Error(), "no matching versions") {
   641  			base.Errorf("go get: upgrading %s@%s: %v", m.Path, m.Version, err)
   642  		}
   643  		return m, nil
   644  	}
   645  
   646  	// If we're on a later prerelease, keep using it,
   647  	// even though normally an Upgrade will ignore prereleases.
   648  	if semver.Compare(info.Version, m.Version) < 0 {
   649  		return m, nil
   650  	}
   651  
   652  	// If we're on a pseudo-version chronologically after the latest tagged version, keep using it.
   653  	// This avoids some accidental downgrades.
   654  	if mTime, err := modfetch.PseudoVersionTime(m.Version); err == nil && info.Time.Before(mTime) {
   655  		return m, nil
   656  	}
   657  
   658  	return module.Version{Path: m.Path, Version: info.Version}, nil
   659  }