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