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