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