github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/cmd/go/internal/modload/load.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 modload 6 7 import ( 8 "bytes" 9 "errors" 10 "fmt" 11 "go/build" 12 "io/ioutil" 13 "os" 14 "path" 15 "path/filepath" 16 "sort" 17 "strings" 18 "sync" 19 20 "cmd/go/internal/base" 21 "cmd/go/internal/cfg" 22 "cmd/go/internal/imports" 23 "cmd/go/internal/modfetch" 24 "cmd/go/internal/modfile" 25 "cmd/go/internal/module" 26 "cmd/go/internal/mvs" 27 "cmd/go/internal/par" 28 "cmd/go/internal/search" 29 "cmd/go/internal/semver" 30 "cmd/go/internal/str" 31 ) 32 33 // buildList is the list of modules to use for building packages. 34 // It is initialized by calling ImportPaths, ImportFromFiles, 35 // LoadALL, or LoadBuildList, each of which uses loaded.load. 36 // 37 // Ideally, exactly ONE of those functions would be called, 38 // and exactly once. Most of the time, that's true. 39 // During "go get" it may not be. TODO(rsc): Figure out if 40 // that restriction can be established, or else document why not. 41 // 42 var buildList []module.Version 43 44 // loaded is the most recently-used package loader. 45 // It holds details about individual packages. 46 // 47 // Note that loaded.buildList is only valid during a load operation; 48 // afterward, it is copied back into the global buildList, 49 // which should be used instead. 50 var loaded *loader 51 52 // ImportPaths returns the set of packages matching the args (patterns), 53 // adding modules to the build list as needed to satisfy new imports. 54 func ImportPaths(patterns []string) []*search.Match { 55 InitMod() 56 57 var matches []*search.Match 58 for _, pattern := range search.CleanPatterns(patterns) { 59 m := &search.Match{ 60 Pattern: pattern, 61 Literal: !strings.Contains(pattern, "...") && !search.IsMetaPackage(pattern), 62 } 63 if m.Literal { 64 m.Pkgs = []string{pattern} 65 } 66 matches = append(matches, m) 67 } 68 69 fsDirs := make([][]string, len(matches)) 70 loaded = newLoader() 71 updateMatches := func(iterating bool) { 72 for i, m := range matches { 73 switch { 74 case build.IsLocalImport(m.Pattern) || filepath.IsAbs(m.Pattern): 75 // Evaluate list of file system directories on first iteration. 76 if fsDirs[i] == nil { 77 var dirs []string 78 if m.Literal { 79 dirs = []string{m.Pattern} 80 } else { 81 dirs = search.MatchPackagesInFS(m.Pattern).Pkgs 82 } 83 fsDirs[i] = dirs 84 } 85 86 // Make a copy of the directory list and translate to import paths. 87 // Note that whether a directory corresponds to an import path 88 // changes as the build list is updated, and a directory can change 89 // from not being in the build list to being in it and back as 90 // the exact version of a particular module increases during 91 // the loader iterations. 92 m.Pkgs = str.StringList(fsDirs[i]) 93 for j, pkg := range m.Pkgs { 94 dir := pkg 95 if !filepath.IsAbs(dir) { 96 dir = filepath.Join(cwd, pkg) 97 } else { 98 dir = filepath.Clean(dir) 99 } 100 101 // Note: The checks for @ here are just to avoid misinterpreting 102 // the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar). 103 // It's not strictly necessary but helpful to keep the checks. 104 if modRoot != "" && dir == modRoot { 105 pkg = Target.Path 106 } else if modRoot != "" && strings.HasPrefix(dir, modRoot+string(filepath.Separator)) && !strings.Contains(dir[len(modRoot):], "@") { 107 suffix := filepath.ToSlash(dir[len(modRoot):]) 108 if strings.HasPrefix(suffix, "/vendor/") { 109 // TODO getmode vendor check 110 pkg = strings.TrimPrefix(suffix, "/vendor/") 111 } else { 112 pkg = Target.Path + suffix 113 } 114 } else if sub := search.InDir(dir, cfg.GOROOTsrc); sub != "" && !strings.Contains(sub, "@") { 115 pkg = filepath.ToSlash(sub) 116 } else if path := pathInModuleCache(dir); path != "" { 117 pkg = path 118 } else { 119 pkg = "" 120 if !iterating { 121 ModRoot() 122 base.Errorf("go: directory %s outside available modules", base.ShortPath(dir)) 123 } 124 } 125 info, err := os.Stat(dir) 126 if err != nil || !info.IsDir() { 127 // If the directory is local but does not exist, don't return it 128 // while loader is iterating, since this would trigger a fetch. 129 // After loader is done iterating, we still need to return the 130 // path, so that "go list -e" produces valid output. 131 if iterating { 132 pkg = "" 133 } 134 } 135 m.Pkgs[j] = pkg 136 } 137 138 case strings.Contains(m.Pattern, "..."): 139 m.Pkgs = matchPackages(m.Pattern, loaded.tags, true, buildList) 140 141 case m.Pattern == "all": 142 loaded.testAll = true 143 if iterating { 144 // Enumerate the packages in the main module. 145 // We'll load the dependencies as we find them. 146 m.Pkgs = matchPackages("...", loaded.tags, false, []module.Version{Target}) 147 } else { 148 // Starting with the packages in the main module, 149 // enumerate the full list of "all". 150 m.Pkgs = loaded.computePatternAll(m.Pkgs) 151 } 152 153 case search.IsMetaPackage(m.Pattern): // std, cmd 154 if len(m.Pkgs) == 0 { 155 m.Pkgs = search.MatchPackages(m.Pattern).Pkgs 156 } 157 } 158 } 159 } 160 161 loaded.load(func() []string { 162 var roots []string 163 updateMatches(true) 164 for _, m := range matches { 165 for _, pkg := range m.Pkgs { 166 if pkg != "" { 167 roots = append(roots, pkg) 168 } 169 } 170 } 171 return roots 172 }) 173 174 // One last pass to finalize wildcards. 175 updateMatches(false) 176 177 // A given module path may be used as itself or as a replacement for another 178 // module, but not both at the same time. Otherwise, the aliasing behavior is 179 // too subtle (see https://golang.org/issue/26607), and we don't want to 180 // commit to a specific behavior at this point. 181 firstPath := make(map[module.Version]string, len(buildList)) 182 for _, mod := range buildList { 183 src := mod 184 if rep := Replacement(mod); rep.Path != "" { 185 src = rep 186 } 187 if prev, ok := firstPath[src]; !ok { 188 firstPath[src] = mod.Path 189 } else if prev != mod.Path { 190 base.Errorf("go: %s@%s used for two different module paths (%s and %s)", src.Path, src.Version, prev, mod.Path) 191 } 192 } 193 base.ExitIfErrors() 194 WriteGoMod() 195 196 search.WarnUnmatched(matches) 197 return matches 198 } 199 200 // pathInModuleCache returns the import path of the directory dir, 201 // if dir is in the module cache copy of a module in our build list. 202 func pathInModuleCache(dir string) string { 203 for _, m := range buildList[1:] { 204 root, err := modfetch.DownloadDir(m) 205 if err != nil { 206 continue 207 } 208 if sub := search.InDir(dir, root); sub != "" { 209 sub = filepath.ToSlash(sub) 210 if !strings.Contains(sub, "/vendor/") && !strings.HasPrefix(sub, "vendor/") && !strings.Contains(sub, "@") { 211 return path.Join(m.Path, filepath.ToSlash(sub)) 212 } 213 } 214 } 215 return "" 216 } 217 218 // warnPattern returns list, the result of matching pattern, 219 // but if list is empty then first it prints a warning about 220 // the pattern not matching any packages. 221 func warnPattern(pattern string, list []string) []string { 222 if len(list) == 0 { 223 fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) 224 } 225 return list 226 } 227 228 // ImportFromFiles adds modules to the build list as needed 229 // to satisfy the imports in the named Go source files. 230 func ImportFromFiles(gofiles []string) { 231 InitMod() 232 233 imports, testImports, err := imports.ScanFiles(gofiles, imports.Tags()) 234 if err != nil { 235 base.Fatalf("go: %v", err) 236 } 237 238 loaded = newLoader() 239 loaded.load(func() []string { 240 var roots []string 241 roots = append(roots, imports...) 242 roots = append(roots, testImports...) 243 return roots 244 }) 245 WriteGoMod() 246 } 247 248 // DirImportPath returns the effective import path for dir, 249 // provided it is within the main module, or else returns ".". 250 func DirImportPath(dir string) string { 251 if modRoot == "" { 252 return "." 253 } 254 255 if !filepath.IsAbs(dir) { 256 dir = filepath.Join(cwd, dir) 257 } else { 258 dir = filepath.Clean(dir) 259 } 260 261 if dir == modRoot { 262 return Target.Path 263 } 264 if strings.HasPrefix(dir, modRoot+string(filepath.Separator)) { 265 suffix := filepath.ToSlash(dir[len(modRoot):]) 266 if strings.HasPrefix(suffix, "/vendor/") { 267 return strings.TrimPrefix(suffix, "/vendor/") 268 } 269 return Target.Path + suffix 270 } 271 return "." 272 } 273 274 // LoadBuildList loads and returns the build list from go.mod. 275 // The loading of the build list happens automatically in ImportPaths: 276 // LoadBuildList need only be called if ImportPaths is not 277 // (typically in commands that care about the module but 278 // no particular package). 279 func LoadBuildList() []module.Version { 280 InitMod() 281 ReloadBuildList() 282 WriteGoMod() 283 return buildList 284 } 285 286 func ReloadBuildList() []module.Version { 287 loaded = newLoader() 288 loaded.load(func() []string { return nil }) 289 return buildList 290 } 291 292 // LoadALL returns the set of all packages in the current module 293 // and their dependencies in any other modules, without filtering 294 // due to build tags, except "+build ignore". 295 // It adds modules to the build list as needed to satisfy new imports. 296 // This set is useful for deciding whether a particular import is needed 297 // anywhere in a module. 298 func LoadALL() []string { 299 return loadAll(true) 300 } 301 302 // LoadVendor is like LoadALL but only follows test dependencies 303 // for tests in the main module. Tests in dependency modules are 304 // ignored completely. 305 // This set is useful for identifying the which packages to include in a vendor directory. 306 func LoadVendor() []string { 307 return loadAll(false) 308 } 309 310 func loadAll(testAll bool) []string { 311 InitMod() 312 313 loaded = newLoader() 314 loaded.isALL = true 315 loaded.tags = anyTags 316 loaded.testAll = testAll 317 if !testAll { 318 loaded.testRoots = true 319 } 320 all := TargetPackages() 321 loaded.load(func() []string { return all }) 322 WriteGoMod() 323 324 var paths []string 325 for _, pkg := range loaded.pkgs { 326 if e, ok := pkg.err.(*ImportMissingError); ok && e.Module.Path == "" { 327 continue // Package doesn't actually exist. 328 } 329 paths = append(paths, pkg.path) 330 } 331 return paths 332 } 333 334 // anyTags is a special tags map that satisfies nearly all build tag expressions. 335 // Only "ignore" and malformed build tag requirements are considered false. 336 var anyTags = map[string]bool{"*": true} 337 338 // TargetPackages returns the list of packages in the target (top-level) module, 339 // under all build tag settings. 340 func TargetPackages() []string { 341 return matchPackages("...", anyTags, false, []module.Version{Target}) 342 } 343 344 // BuildList returns the module build list, 345 // typically constructed by a previous call to 346 // LoadBuildList or ImportPaths. 347 // The caller must not modify the returned list. 348 func BuildList() []module.Version { 349 return buildList 350 } 351 352 // SetBuildList sets the module build list. 353 // The caller is responsible for ensuring that the list is valid. 354 // SetBuildList does not retain a reference to the original list. 355 func SetBuildList(list []module.Version) { 356 buildList = append([]module.Version{}, list...) 357 } 358 359 // ImportMap returns the actual package import path 360 // for an import path found in source code. 361 // If the given import path does not appear in the source code 362 // for the packages that have been loaded, ImportMap returns the empty string. 363 func ImportMap(path string) string { 364 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 365 if !ok { 366 return "" 367 } 368 return pkg.path 369 } 370 371 // PackageDir returns the directory containing the source code 372 // for the package named by the import path. 373 func PackageDir(path string) string { 374 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 375 if !ok { 376 return "" 377 } 378 return pkg.dir 379 } 380 381 // PackageModule returns the module providing the package named by the import path. 382 func PackageModule(path string) module.Version { 383 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 384 if !ok { 385 return module.Version{} 386 } 387 return pkg.mod 388 } 389 390 // ModuleUsedDirectly reports whether the main module directly imports 391 // some package in the module with the given path. 392 func ModuleUsedDirectly(path string) bool { 393 return loaded.direct[path] 394 } 395 396 // Lookup returns the source directory, import path, and any loading error for 397 // the package at path. 398 // Lookup requires that one of the Load functions in this package has already 399 // been called. 400 func Lookup(path string) (dir, realPath string, err error) { 401 if path == "" { 402 panic("Lookup called with empty package path") 403 } 404 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 405 if !ok { 406 // The loader should have found all the relevant paths. 407 // There are a few exceptions, though: 408 // - during go list without -test, the p.Resolve calls to process p.TestImports and p.XTestImports 409 // end up here to canonicalize the import paths. 410 // - during any load, non-loaded packages like "unsafe" end up here. 411 // - during any load, build-injected dependencies like "runtime/cgo" end up here. 412 // - because we ignore appengine/* in the module loader, 413 // the dependencies of any actual appengine/* library end up here. 414 dir := findStandardImportPath(path) 415 if dir != "" { 416 return dir, path, nil 417 } 418 return "", "", errMissing 419 } 420 return pkg.dir, pkg.path, pkg.err 421 } 422 423 // A loader manages the process of loading information about 424 // the required packages for a particular build, 425 // checking that the packages are available in the module set, 426 // and updating the module set if needed. 427 // Loading is an iterative process: try to load all the needed packages, 428 // but if imports are missing, try to resolve those imports, and repeat. 429 // 430 // Although most of the loading state is maintained in the loader struct, 431 // one key piece - the build list - is a global, so that it can be modified 432 // separate from the loading operation, such as during "go get" 433 // upgrades/downgrades or in "go mod" operations. 434 // TODO(rsc): It might be nice to make the loader take and return 435 // a buildList rather than hard-coding use of the global. 436 type loader struct { 437 tags map[string]bool // tags for scanDir 438 testRoots bool // include tests for roots 439 isALL bool // created with LoadALL 440 testAll bool // include tests for all packages 441 442 // reset on each iteration 443 roots []*loadPkg 444 pkgs []*loadPkg 445 work *par.Work // current work queue 446 pkgCache *par.Cache // map from string to *loadPkg 447 448 // computed at end of iterations 449 direct map[string]bool // imported directly by main module 450 goVersion map[string]string // go version recorded in each module 451 } 452 453 // LoadTests controls whether the loaders load tests of the root packages. 454 var LoadTests bool 455 456 func newLoader() *loader { 457 ld := new(loader) 458 ld.tags = imports.Tags() 459 ld.testRoots = LoadTests 460 return ld 461 } 462 463 func (ld *loader) reset() { 464 ld.roots = nil 465 ld.pkgs = nil 466 ld.work = new(par.Work) 467 ld.pkgCache = new(par.Cache) 468 } 469 470 // A loadPkg records information about a single loaded package. 471 type loadPkg struct { 472 path string // import path 473 mod module.Version // module providing package 474 dir string // directory containing source code 475 imports []*loadPkg // packages imported by this one 476 err error // error loading package 477 stack *loadPkg // package importing this one in minimal import stack for this pkg 478 test *loadPkg // package with test imports, if we need test 479 testOf *loadPkg 480 testImports []string // test-only imports, saved for use by pkg.test. 481 } 482 483 var errMissing = errors.New("cannot find package") 484 485 // load attempts to load the build graph needed to process a set of root packages. 486 // The set of root packages is defined by the addRoots function, 487 // which must call add(path) with the import path of each root package. 488 func (ld *loader) load(roots func() []string) { 489 var err error 490 reqs := Reqs() 491 buildList, err = mvs.BuildList(Target, reqs) 492 if err != nil { 493 base.Fatalf("go: %v", err) 494 } 495 496 added := make(map[string]bool) 497 for { 498 ld.reset() 499 if roots != nil { 500 // Note: the returned roots can change on each iteration, 501 // since the expansion of package patterns depends on the 502 // build list we're using. 503 for _, path := range roots() { 504 ld.work.Add(ld.pkg(path, true)) 505 } 506 } 507 ld.work.Do(10, ld.doPkg) 508 ld.buildStacks() 509 numAdded := 0 510 haveMod := make(map[module.Version]bool) 511 for _, m := range buildList { 512 haveMod[m] = true 513 } 514 for _, pkg := range ld.pkgs { 515 if err, ok := pkg.err.(*ImportMissingError); ok && err.Module.Path != "" { 516 if added[pkg.path] { 517 base.Fatalf("go: %s: looping trying to add package", pkg.stackText()) 518 } 519 added[pkg.path] = true 520 numAdded++ 521 if !haveMod[err.Module] { 522 haveMod[err.Module] = true 523 buildList = append(buildList, err.Module) 524 } 525 continue 526 } 527 // Leave other errors for Import or load.Packages to report. 528 } 529 base.ExitIfErrors() 530 if numAdded == 0 { 531 break 532 } 533 534 // Recompute buildList with all our additions. 535 reqs = Reqs() 536 buildList, err = mvs.BuildList(Target, reqs) 537 if err != nil { 538 base.Fatalf("go: %v", err) 539 } 540 } 541 base.ExitIfErrors() 542 543 // Compute directly referenced dependency modules. 544 ld.direct = make(map[string]bool) 545 for _, pkg := range ld.pkgs { 546 if pkg.mod == Target { 547 for _, dep := range pkg.imports { 548 if dep.mod.Path != "" { 549 ld.direct[dep.mod.Path] = true 550 } 551 } 552 } 553 } 554 555 // Add Go versions, computed during walk. 556 ld.goVersion = make(map[string]string) 557 for _, m := range buildList { 558 v, _ := reqs.(*mvsReqs).versions.Load(m) 559 ld.goVersion[m.Path], _ = v.(string) 560 } 561 562 // Mix in direct markings (really, lack of indirect markings) 563 // from go.mod, unless we scanned the whole module 564 // and can therefore be sure we know better than go.mod. 565 if !ld.isALL && modFile != nil { 566 for _, r := range modFile.Require { 567 if !r.Indirect { 568 ld.direct[r.Mod.Path] = true 569 } 570 } 571 } 572 } 573 574 // pkg returns the *loadPkg for path, creating and queuing it if needed. 575 // If the package should be tested, its test is created but not queued 576 // (the test is queued after processing pkg). 577 // If isRoot is true, the pkg is being queued as one of the roots of the work graph. 578 func (ld *loader) pkg(path string, isRoot bool) *loadPkg { 579 return ld.pkgCache.Do(path, func() interface{} { 580 pkg := &loadPkg{ 581 path: path, 582 } 583 if ld.testRoots && isRoot || ld.testAll { 584 test := &loadPkg{ 585 path: path, 586 testOf: pkg, 587 } 588 pkg.test = test 589 } 590 if isRoot { 591 ld.roots = append(ld.roots, pkg) 592 } 593 ld.work.Add(pkg) 594 return pkg 595 }).(*loadPkg) 596 } 597 598 // doPkg processes a package on the work queue. 599 func (ld *loader) doPkg(item interface{}) { 600 // TODO: what about replacements? 601 pkg := item.(*loadPkg) 602 var imports []string 603 if pkg.testOf != nil { 604 pkg.dir = pkg.testOf.dir 605 pkg.mod = pkg.testOf.mod 606 imports = pkg.testOf.testImports 607 } else { 608 if strings.Contains(pkg.path, "@") { 609 // Leave for error during load. 610 return 611 } 612 if build.IsLocalImport(pkg.path) { 613 // Leave for error during load. 614 // (Module mode does not allow local imports.) 615 return 616 } 617 618 pkg.mod, pkg.dir, pkg.err = Import(pkg.path) 619 if pkg.dir == "" { 620 return 621 } 622 var testImports []string 623 var err error 624 imports, testImports, err = scanDir(pkg.dir, ld.tags) 625 if err != nil { 626 pkg.err = err 627 return 628 } 629 if pkg.test != nil { 630 pkg.testImports = testImports 631 } 632 } 633 634 for _, path := range imports { 635 pkg.imports = append(pkg.imports, ld.pkg(path, false)) 636 } 637 638 // Now that pkg.dir, pkg.mod, pkg.testImports are set, we can queue pkg.test. 639 // TODO: All that's left is creating new imports. Why not just do it now? 640 if pkg.test != nil { 641 ld.work.Add(pkg.test) 642 } 643 } 644 645 // computePatternAll returns the list of packages matching pattern "all", 646 // starting with a list of the import paths for the packages in the main module. 647 func (ld *loader) computePatternAll(paths []string) []string { 648 seen := make(map[*loadPkg]bool) 649 var all []string 650 var walk func(*loadPkg) 651 walk = func(pkg *loadPkg) { 652 if seen[pkg] { 653 return 654 } 655 seen[pkg] = true 656 if pkg.testOf == nil { 657 all = append(all, pkg.path) 658 } 659 for _, p := range pkg.imports { 660 walk(p) 661 } 662 if p := pkg.test; p != nil { 663 walk(p) 664 } 665 } 666 for _, path := range paths { 667 walk(ld.pkg(path, false)) 668 } 669 sort.Strings(all) 670 671 return all 672 } 673 674 // scanDir is like imports.ScanDir but elides known magic imports from the list, 675 // so that we do not go looking for packages that don't really exist. 676 // 677 // The standard magic import is "C", for cgo. 678 // 679 // The only other known magic imports are appengine and appengine/*. 680 // These are so old that they predate "go get" and did not use URL-like paths. 681 // Most code today now uses google.golang.org/appengine instead, 682 // but not all code has been so updated. When we mostly ignore build tags 683 // during "go vendor", we look into "// +build appengine" files and 684 // may see these legacy imports. We drop them so that the module 685 // search does not look for modules to try to satisfy them. 686 func scanDir(dir string, tags map[string]bool) (imports_, testImports []string, err error) { 687 imports_, testImports, err = imports.ScanDir(dir, tags) 688 689 filter := func(x []string) []string { 690 w := 0 691 for _, pkg := range x { 692 if pkg != "C" && pkg != "appengine" && !strings.HasPrefix(pkg, "appengine/") && 693 pkg != "appengine_internal" && !strings.HasPrefix(pkg, "appengine_internal/") { 694 x[w] = pkg 695 w++ 696 } 697 } 698 return x[:w] 699 } 700 701 return filter(imports_), filter(testImports), err 702 } 703 704 // buildStacks computes minimal import stacks for each package, 705 // for use in error messages. When it completes, packages that 706 // are part of the original root set have pkg.stack == nil, 707 // and other packages have pkg.stack pointing at the next 708 // package up the import stack in their minimal chain. 709 // As a side effect, buildStacks also constructs ld.pkgs, 710 // the list of all packages loaded. 711 func (ld *loader) buildStacks() { 712 if len(ld.pkgs) > 0 { 713 panic("buildStacks") 714 } 715 for _, pkg := range ld.roots { 716 pkg.stack = pkg // sentinel to avoid processing in next loop 717 ld.pkgs = append(ld.pkgs, pkg) 718 } 719 for i := 0; i < len(ld.pkgs); i++ { // not range: appending to ld.pkgs in loop 720 pkg := ld.pkgs[i] 721 for _, next := range pkg.imports { 722 if next.stack == nil { 723 next.stack = pkg 724 ld.pkgs = append(ld.pkgs, next) 725 } 726 } 727 if next := pkg.test; next != nil && next.stack == nil { 728 next.stack = pkg 729 ld.pkgs = append(ld.pkgs, next) 730 } 731 } 732 for _, pkg := range ld.roots { 733 pkg.stack = nil 734 } 735 } 736 737 // stackText builds the import stack text to use when 738 // reporting an error in pkg. It has the general form 739 // 740 // import root -> 741 // import other -> 742 // import other2 -> 743 // import pkg 744 // 745 func (pkg *loadPkg) stackText() string { 746 var stack []*loadPkg 747 for p := pkg.stack; p != nil; p = p.stack { 748 stack = append(stack, p) 749 } 750 751 var buf bytes.Buffer 752 for i := len(stack) - 1; i >= 0; i-- { 753 p := stack[i] 754 if p.testOf != nil { 755 fmt.Fprintf(&buf, "test ->\n\t") 756 } else { 757 fmt.Fprintf(&buf, "import %q ->\n\t", p.path) 758 } 759 } 760 fmt.Fprintf(&buf, "import %q", pkg.path) 761 return buf.String() 762 } 763 764 // why returns the text to use in "go mod why" output about the given package. 765 // It is less ornate than the stackText but contains the same information. 766 func (pkg *loadPkg) why() string { 767 var buf strings.Builder 768 var stack []*loadPkg 769 for p := pkg; p != nil; p = p.stack { 770 stack = append(stack, p) 771 } 772 773 for i := len(stack) - 1; i >= 0; i-- { 774 p := stack[i] 775 if p.testOf != nil { 776 fmt.Fprintf(&buf, "%s.test\n", p.testOf.path) 777 } else { 778 fmt.Fprintf(&buf, "%s\n", p.path) 779 } 780 } 781 return buf.String() 782 } 783 784 // Why returns the "go mod why" output stanza for the given package, 785 // without the leading # comment. 786 // The package graph must have been loaded already, usually by LoadALL. 787 // If there is no reason for the package to be in the current build, 788 // Why returns an empty string. 789 func Why(path string) string { 790 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 791 if !ok { 792 return "" 793 } 794 return pkg.why() 795 } 796 797 // WhyDepth returns the number of steps in the Why listing. 798 // If there is no reason for the package to be in the current build, 799 // WhyDepth returns 0. 800 func WhyDepth(path string) int { 801 n := 0 802 pkg, _ := loaded.pkgCache.Get(path).(*loadPkg) 803 for p := pkg; p != nil; p = p.stack { 804 n++ 805 } 806 return n 807 } 808 809 // Replacement returns the replacement for mod, if any, from go.mod. 810 // If there is no replacement for mod, Replacement returns 811 // a module.Version with Path == "". 812 func Replacement(mod module.Version) module.Version { 813 if modFile == nil { 814 // Happens during testing and if invoking 'go get' or 'go list' outside a module. 815 return module.Version{} 816 } 817 818 var found *modfile.Replace 819 for _, r := range modFile.Replace { 820 if r.Old.Path == mod.Path && (r.Old.Version == "" || r.Old.Version == mod.Version) { 821 found = r // keep going 822 } 823 } 824 if found == nil { 825 return module.Version{} 826 } 827 return found.New 828 } 829 830 // mvsReqs implements mvs.Reqs for module semantic versions, 831 // with any exclusions or replacements applied internally. 832 type mvsReqs struct { 833 buildList []module.Version 834 cache par.Cache 835 versions sync.Map 836 } 837 838 // Reqs returns the current module requirement graph. 839 // Future calls to SetBuildList do not affect the operation 840 // of the returned Reqs. 841 func Reqs() mvs.Reqs { 842 r := &mvsReqs{ 843 buildList: buildList, 844 } 845 return r 846 } 847 848 func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { 849 type cached struct { 850 list []module.Version 851 err error 852 } 853 854 c := r.cache.Do(mod, func() interface{} { 855 list, err := r.required(mod) 856 if err != nil { 857 return cached{nil, err} 858 } 859 for i, mv := range list { 860 for excluded[mv] { 861 mv1, err := r.next(mv) 862 if err != nil { 863 return cached{nil, err} 864 } 865 if mv1.Version == "none" { 866 return cached{nil, fmt.Errorf("%s(%s) depends on excluded %s(%s) with no newer version available", mod.Path, mod.Version, mv.Path, mv.Version)} 867 } 868 mv = mv1 869 } 870 list[i] = mv 871 } 872 873 return cached{list, nil} 874 }).(cached) 875 876 return c.list, c.err 877 } 878 879 var vendorOnce sync.Once 880 881 var ( 882 vendorList []module.Version 883 vendorMap map[string]module.Version 884 ) 885 886 // readVendorList reads the list of vendored modules from vendor/modules.txt. 887 func readVendorList() { 888 vendorOnce.Do(func() { 889 vendorList = nil 890 vendorMap = make(map[string]module.Version) 891 data, _ := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt")) 892 var m module.Version 893 for _, line := range strings.Split(string(data), "\n") { 894 if strings.HasPrefix(line, "# ") { 895 f := strings.Fields(line) 896 m = module.Version{} 897 if len(f) == 3 && semver.IsValid(f[2]) { 898 m = module.Version{Path: f[1], Version: f[2]} 899 vendorList = append(vendorList, m) 900 } 901 } else if m.Path != "" { 902 f := strings.Fields(line) 903 if len(f) == 1 { 904 vendorMap[f[0]] = m 905 } 906 } 907 } 908 }) 909 } 910 911 func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version { 912 var list []module.Version 913 for _, r := range f.Require { 914 list = append(list, r.Mod) 915 } 916 return list 917 } 918 919 func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) { 920 if mod == Target { 921 if modFile != nil && modFile.Go != nil { 922 r.versions.LoadOrStore(mod, modFile.Go.Version) 923 } 924 var list []module.Version 925 return append(list, r.buildList[1:]...), nil 926 } 927 928 if cfg.BuildMod == "vendor" { 929 // For every module other than the target, 930 // return the full list of modules from modules.txt. 931 readVendorList() 932 return vendorList, nil 933 } 934 935 origPath := mod.Path 936 if repl := Replacement(mod); repl.Path != "" { 937 if repl.Version == "" { 938 // TODO: need to slip the new version into the tags list etc. 939 dir := repl.Path 940 if !filepath.IsAbs(dir) { 941 dir = filepath.Join(ModRoot(), dir) 942 } 943 gomod := filepath.Join(dir, "go.mod") 944 data, err := ioutil.ReadFile(gomod) 945 if err != nil { 946 base.Errorf("go: parsing %s: %v", base.ShortPath(gomod), err) 947 return nil, ErrRequire 948 } 949 f, err := modfile.ParseLax(gomod, data, nil) 950 if err != nil { 951 base.Errorf("go: parsing %s: %v", base.ShortPath(gomod), err) 952 return nil, ErrRequire 953 } 954 if f.Go != nil { 955 r.versions.LoadOrStore(mod, f.Go.Version) 956 } 957 return r.modFileToList(f), nil 958 } 959 mod = repl 960 } 961 962 if mod.Version == "none" { 963 return nil, nil 964 } 965 966 if !semver.IsValid(mod.Version) { 967 // Disallow the broader queries supported by fetch.Lookup. 968 base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", mod.Path, mod.Version) 969 } 970 971 data, err := modfetch.GoMod(mod.Path, mod.Version) 972 if err != nil { 973 base.Errorf("go: %s@%s: %v\n", mod.Path, mod.Version, err) 974 return nil, ErrRequire 975 } 976 f, err := modfile.ParseLax("go.mod", data, nil) 977 if err != nil { 978 base.Errorf("go: %s@%s: parsing go.mod: %v", mod.Path, mod.Version, err) 979 return nil, ErrRequire 980 } 981 982 if f.Module == nil { 983 base.Errorf("go: %s@%s: parsing go.mod: missing module line", mod.Path, mod.Version) 984 return nil, ErrRequire 985 } 986 if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path { 987 base.Errorf("go: %s@%s: parsing go.mod: unexpected module path %q", mod.Path, mod.Version, mpath) 988 return nil, ErrRequire 989 } 990 if f.Go != nil { 991 r.versions.LoadOrStore(mod, f.Go.Version) 992 } 993 994 return r.modFileToList(f), nil 995 } 996 997 // ErrRequire is the sentinel error returned when Require encounters problems. 998 // It prints the problems directly to standard error, so that multiple errors 999 // can be displayed easily. 1000 var ErrRequire = errors.New("error loading module requirements") 1001 1002 func (*mvsReqs) Max(v1, v2 string) string { 1003 if v1 != "" && semver.Compare(v1, v2) == -1 { 1004 return v2 1005 } 1006 return v1 1007 } 1008 1009 // Upgrade is a no-op, here to implement mvs.Reqs. 1010 // The upgrade logic for go get -u is in ../modget/get.go. 1011 func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) { 1012 return m, nil 1013 } 1014 1015 func versions(path string) ([]string, error) { 1016 // Note: modfetch.Lookup and repo.Versions are cached, 1017 // so there's no need for us to add extra caching here. 1018 repo, err := modfetch.Lookup(path) 1019 if err != nil { 1020 return nil, err 1021 } 1022 return repo.Versions("") 1023 } 1024 1025 // Previous returns the tagged version of m.Path immediately prior to 1026 // m.Version, or version "none" if no prior version is tagged. 1027 func (*mvsReqs) Previous(m module.Version) (module.Version, error) { 1028 list, err := versions(m.Path) 1029 if err != nil { 1030 return module.Version{}, err 1031 } 1032 i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 }) 1033 if i > 0 { 1034 return module.Version{Path: m.Path, Version: list[i-1]}, nil 1035 } 1036 return module.Version{Path: m.Path, Version: "none"}, nil 1037 } 1038 1039 // next returns the next version of m.Path after m.Version. 1040 // It is only used by the exclusion processing in the Required method, 1041 // not called directly by MVS. 1042 func (*mvsReqs) next(m module.Version) (module.Version, error) { 1043 list, err := versions(m.Path) 1044 if err != nil { 1045 return module.Version{}, err 1046 } 1047 i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 }) 1048 if i < len(list) { 1049 return module.Version{Path: m.Path, Version: list[i]}, nil 1050 } 1051 return module.Version{Path: m.Path, Version: "none"}, nil 1052 } 1053 1054 func fetch(mod module.Version) (dir string, isLocal bool, err error) { 1055 if mod == Target { 1056 return ModRoot(), true, nil 1057 } 1058 if r := Replacement(mod); r.Path != "" { 1059 if r.Version == "" { 1060 dir = r.Path 1061 if !filepath.IsAbs(dir) { 1062 dir = filepath.Join(ModRoot(), dir) 1063 } 1064 return dir, true, nil 1065 } 1066 mod = r 1067 } 1068 1069 dir, err = modfetch.Download(mod) 1070 return dir, false, err 1071 }