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 }