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