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 5package modload 6 7import ( 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// 42var 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. 50var 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. 54func 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. 202func 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. 221func 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. 230func 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 ".". 250func 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). 279func LoadBuildList() []module.Version { 280 InitMod() 281 ReloadBuildList() 282 WriteGoMod() 283 return buildList 284} 285 286func 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. 298func 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. 306func LoadVendor() []string { 307 return loadAll(false) 308} 309 310func 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. 336var 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. 340func 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. 348func 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. 355func 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. 363func 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. 373func 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. 382func 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. 392func 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. 400func 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. 436type 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. 454var LoadTests bool 455 456func newLoader() *loader { 457 ld := new(loader) 458 ld.tags = imports.Tags() 459 ld.testRoots = LoadTests 460 return ld 461} 462 463func (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. 471type 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 483var 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. 488func (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. 578func (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. 599func (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 if cfg.BuildContext.Compiler == "gccgo" && pkg.mod.Path == "" { 623 return 624 } 625 626 var testImports []string 627 var err error 628 imports, testImports, err = scanDir(pkg.dir, ld.tags) 629 if err != nil { 630 pkg.err = err 631 return 632 } 633 if pkg.test != nil { 634 pkg.testImports = testImports 635 } 636 } 637 638 for _, path := range imports { 639 pkg.imports = append(pkg.imports, ld.pkg(path, false)) 640 } 641 642 // Now that pkg.dir, pkg.mod, pkg.testImports are set, we can queue pkg.test. 643 // TODO: All that's left is creating new imports. Why not just do it now? 644 if pkg.test != nil { 645 ld.work.Add(pkg.test) 646 } 647} 648 649// computePatternAll returns the list of packages matching pattern "all", 650// starting with a list of the import paths for the packages in the main module. 651func (ld *loader) computePatternAll(paths []string) []string { 652 seen := make(map[*loadPkg]bool) 653 var all []string 654 var walk func(*loadPkg) 655 walk = func(pkg *loadPkg) { 656 if seen[pkg] { 657 return 658 } 659 seen[pkg] = true 660 if pkg.testOf == nil { 661 all = append(all, pkg.path) 662 } 663 for _, p := range pkg.imports { 664 walk(p) 665 } 666 if p := pkg.test; p != nil { 667 walk(p) 668 } 669 } 670 for _, path := range paths { 671 walk(ld.pkg(path, false)) 672 } 673 sort.Strings(all) 674 675 return all 676} 677 678// scanDir is like imports.ScanDir but elides known magic imports from the list, 679// so that we do not go looking for packages that don't really exist. 680// 681// The standard magic import is "C", for cgo. 682// 683// The only other known magic imports are appengine and appengine/*. 684// These are so old that they predate "go get" and did not use URL-like paths. 685// Most code today now uses google.golang.org/appengine instead, 686// but not all code has been so updated. When we mostly ignore build tags 687// during "go vendor", we look into "// +build appengine" files and 688// may see these legacy imports. We drop them so that the module 689// search does not look for modules to try to satisfy them. 690func scanDir(dir string, tags map[string]bool) (imports_, testImports []string, err error) { 691 imports_, testImports, err = imports.ScanDir(dir, tags) 692 693 filter := func(x []string) []string { 694 w := 0 695 for _, pkg := range x { 696 if pkg != "C" && pkg != "appengine" && !strings.HasPrefix(pkg, "appengine/") && 697 pkg != "appengine_internal" && !strings.HasPrefix(pkg, "appengine_internal/") { 698 x[w] = pkg 699 w++ 700 } 701 } 702 return x[:w] 703 } 704 705 return filter(imports_), filter(testImports), err 706} 707 708// buildStacks computes minimal import stacks for each package, 709// for use in error messages. When it completes, packages that 710// are part of the original root set have pkg.stack == nil, 711// and other packages have pkg.stack pointing at the next 712// package up the import stack in their minimal chain. 713// As a side effect, buildStacks also constructs ld.pkgs, 714// the list of all packages loaded. 715func (ld *loader) buildStacks() { 716 if len(ld.pkgs) > 0 { 717 panic("buildStacks") 718 } 719 for _, pkg := range ld.roots { 720 pkg.stack = pkg // sentinel to avoid processing in next loop 721 ld.pkgs = append(ld.pkgs, pkg) 722 } 723 for i := 0; i < len(ld.pkgs); i++ { // not range: appending to ld.pkgs in loop 724 pkg := ld.pkgs[i] 725 for _, next := range pkg.imports { 726 if next.stack == nil { 727 next.stack = pkg 728 ld.pkgs = append(ld.pkgs, next) 729 } 730 } 731 if next := pkg.test; next != nil && next.stack == nil { 732 next.stack = pkg 733 ld.pkgs = append(ld.pkgs, next) 734 } 735 } 736 for _, pkg := range ld.roots { 737 pkg.stack = nil 738 } 739} 740 741// stackText builds the import stack text to use when 742// reporting an error in pkg. It has the general form 743// 744// import root -> 745// import other -> 746// import other2 -> 747// import pkg 748// 749func (pkg *loadPkg) stackText() string { 750 var stack []*loadPkg 751 for p := pkg.stack; p != nil; p = p.stack { 752 stack = append(stack, p) 753 } 754 755 var buf bytes.Buffer 756 for i := len(stack) - 1; i >= 0; i-- { 757 p := stack[i] 758 if p.testOf != nil { 759 fmt.Fprintf(&buf, "test ->\n\t") 760 } else { 761 fmt.Fprintf(&buf, "import %q ->\n\t", p.path) 762 } 763 } 764 fmt.Fprintf(&buf, "import %q", pkg.path) 765 return buf.String() 766} 767 768// why returns the text to use in "go mod why" output about the given package. 769// It is less ornate than the stackText but contains the same information. 770func (pkg *loadPkg) why() string { 771 var buf strings.Builder 772 var stack []*loadPkg 773 for p := pkg; p != nil; p = p.stack { 774 stack = append(stack, p) 775 } 776 777 for i := len(stack) - 1; i >= 0; i-- { 778 p := stack[i] 779 if p.testOf != nil { 780 fmt.Fprintf(&buf, "%s.test\n", p.testOf.path) 781 } else { 782 fmt.Fprintf(&buf, "%s\n", p.path) 783 } 784 } 785 return buf.String() 786} 787 788// Why returns the "go mod why" output stanza for the given package, 789// without the leading # comment. 790// The package graph must have been loaded already, usually by LoadALL. 791// If there is no reason for the package to be in the current build, 792// Why returns an empty string. 793func Why(path string) string { 794 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 795 if !ok { 796 return "" 797 } 798 return pkg.why() 799} 800 801// WhyDepth returns the number of steps in the Why listing. 802// If there is no reason for the package to be in the current build, 803// WhyDepth returns 0. 804func WhyDepth(path string) int { 805 n := 0 806 pkg, _ := loaded.pkgCache.Get(path).(*loadPkg) 807 for p := pkg; p != nil; p = p.stack { 808 n++ 809 } 810 return n 811} 812 813// Replacement returns the replacement for mod, if any, from go.mod. 814// If there is no replacement for mod, Replacement returns 815// a module.Version with Path == "". 816func Replacement(mod module.Version) module.Version { 817 if modFile == nil { 818 // Happens during testing and if invoking 'go get' or 'go list' outside a module. 819 return module.Version{} 820 } 821 822 var found *modfile.Replace 823 for _, r := range modFile.Replace { 824 if r.Old.Path == mod.Path && (r.Old.Version == "" || r.Old.Version == mod.Version) { 825 found = r // keep going 826 } 827 } 828 if found == nil { 829 return module.Version{} 830 } 831 return found.New 832} 833 834// mvsReqs implements mvs.Reqs for module semantic versions, 835// with any exclusions or replacements applied internally. 836type mvsReqs struct { 837 buildList []module.Version 838 cache par.Cache 839 versions sync.Map 840} 841 842// Reqs returns the current module requirement graph. 843// Future calls to SetBuildList do not affect the operation 844// of the returned Reqs. 845func Reqs() mvs.Reqs { 846 r := &mvsReqs{ 847 buildList: buildList, 848 } 849 return r 850} 851 852func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { 853 type cached struct { 854 list []module.Version 855 err error 856 } 857 858 c := r.cache.Do(mod, func() interface{} { 859 list, err := r.required(mod) 860 if err != nil { 861 return cached{nil, err} 862 } 863 for i, mv := range list { 864 for excluded[mv] { 865 mv1, err := r.next(mv) 866 if err != nil { 867 return cached{nil, err} 868 } 869 if mv1.Version == "none" { 870 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)} 871 } 872 mv = mv1 873 } 874 list[i] = mv 875 } 876 877 return cached{list, nil} 878 }).(cached) 879 880 return c.list, c.err 881} 882 883var vendorOnce sync.Once 884 885var ( 886 vendorList []module.Version 887 vendorMap map[string]module.Version 888) 889 890// readVendorList reads the list of vendored modules from vendor/modules.txt. 891func readVendorList() { 892 vendorOnce.Do(func() { 893 vendorList = nil 894 vendorMap = make(map[string]module.Version) 895 data, _ := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt")) 896 var m module.Version 897 for _, line := range strings.Split(string(data), "\n") { 898 if strings.HasPrefix(line, "# ") { 899 f := strings.Fields(line) 900 m = module.Version{} 901 if len(f) == 3 && semver.IsValid(f[2]) { 902 m = module.Version{Path: f[1], Version: f[2]} 903 vendorList = append(vendorList, m) 904 } 905 } else if m.Path != "" { 906 f := strings.Fields(line) 907 if len(f) == 1 { 908 vendorMap[f[0]] = m 909 } 910 } 911 } 912 }) 913} 914 915func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version { 916 var list []module.Version 917 for _, r := range f.Require { 918 list = append(list, r.Mod) 919 } 920 return list 921} 922 923func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) { 924 if mod == Target { 925 if modFile != nil && modFile.Go != nil { 926 r.versions.LoadOrStore(mod, modFile.Go.Version) 927 } 928 var list []module.Version 929 return append(list, r.buildList[1:]...), nil 930 } 931 932 if cfg.BuildMod == "vendor" { 933 // For every module other than the target, 934 // return the full list of modules from modules.txt. 935 readVendorList() 936 return vendorList, nil 937 } 938 939 origPath := mod.Path 940 if repl := Replacement(mod); repl.Path != "" { 941 if repl.Version == "" { 942 // TODO: need to slip the new version into the tags list etc. 943 dir := repl.Path 944 if !filepath.IsAbs(dir) { 945 dir = filepath.Join(ModRoot(), dir) 946 } 947 gomod := filepath.Join(dir, "go.mod") 948 data, err := ioutil.ReadFile(gomod) 949 if err != nil { 950 base.Errorf("go: parsing %s: %v", base.ShortPath(gomod), err) 951 return nil, ErrRequire 952 } 953 f, err := modfile.ParseLax(gomod, data, nil) 954 if err != nil { 955 base.Errorf("go: parsing %s: %v", base.ShortPath(gomod), err) 956 return nil, ErrRequire 957 } 958 if f.Go != nil { 959 r.versions.LoadOrStore(mod, f.Go.Version) 960 } 961 return r.modFileToList(f), nil 962 } 963 mod = repl 964 } 965 966 if mod.Version == "none" { 967 return nil, nil 968 } 969 970 if !semver.IsValid(mod.Version) { 971 // Disallow the broader queries supported by fetch.Lookup. 972 base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", mod.Path, mod.Version) 973 } 974 975 data, err := modfetch.GoMod(mod.Path, mod.Version) 976 if err != nil { 977 base.Errorf("go: %s@%s: %v\n", mod.Path, mod.Version, err) 978 return nil, ErrRequire 979 } 980 f, err := modfile.ParseLax("go.mod", data, nil) 981 if err != nil { 982 base.Errorf("go: %s@%s: parsing go.mod: %v", mod.Path, mod.Version, err) 983 return nil, ErrRequire 984 } 985 986 if f.Module == nil { 987 base.Errorf("go: %s@%s: parsing go.mod: missing module line", mod.Path, mod.Version) 988 return nil, ErrRequire 989 } 990 if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path { 991 base.Errorf("go: %s@%s: parsing go.mod: unexpected module path %q", mod.Path, mod.Version, mpath) 992 return nil, ErrRequire 993 } 994 if f.Go != nil { 995 r.versions.LoadOrStore(mod, f.Go.Version) 996 } 997 998 return r.modFileToList(f), nil 999} 1000 1001// ErrRequire is the sentinel error returned when Require encounters problems. 1002// It prints the problems directly to standard error, so that multiple errors 1003// can be displayed easily. 1004var ErrRequire = errors.New("error loading module requirements") 1005 1006func (*mvsReqs) Max(v1, v2 string) string { 1007 if v1 != "" && semver.Compare(v1, v2) == -1 { 1008 return v2 1009 } 1010 return v1 1011} 1012 1013// Upgrade is a no-op, here to implement mvs.Reqs. 1014// The upgrade logic for go get -u is in ../modget/get.go. 1015func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) { 1016 return m, nil 1017} 1018 1019func versions(path string) ([]string, error) { 1020 // Note: modfetch.Lookup and repo.Versions are cached, 1021 // so there's no need for us to add extra caching here. 1022 repo, err := modfetch.Lookup(path) 1023 if err != nil { 1024 return nil, err 1025 } 1026 return repo.Versions("") 1027} 1028 1029// Previous returns the tagged version of m.Path immediately prior to 1030// m.Version, or version "none" if no prior version is tagged. 1031func (*mvsReqs) Previous(m module.Version) (module.Version, error) { 1032 list, err := versions(m.Path) 1033 if err != nil { 1034 return module.Version{}, err 1035 } 1036 i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 }) 1037 if i > 0 { 1038 return module.Version{Path: m.Path, Version: list[i-1]}, nil 1039 } 1040 return module.Version{Path: m.Path, Version: "none"}, nil 1041} 1042 1043// next returns the next version of m.Path after m.Version. 1044// It is only used by the exclusion processing in the Required method, 1045// not called directly by MVS. 1046func (*mvsReqs) next(m module.Version) (module.Version, error) { 1047 list, err := versions(m.Path) 1048 if err != nil { 1049 return module.Version{}, err 1050 } 1051 i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 }) 1052 if i < len(list) { 1053 return module.Version{Path: m.Path, Version: list[i]}, nil 1054 } 1055 return module.Version{Path: m.Path, Version: "none"}, nil 1056} 1057 1058func fetch(mod module.Version) (dir string, isLocal bool, err error) { 1059 if mod == Target { 1060 return ModRoot(), true, nil 1061 } 1062 if r := Replacement(mod); r.Path != "" { 1063 if r.Version == "" { 1064 dir = r.Path 1065 if !filepath.IsAbs(dir) { 1066 dir = filepath.Join(ModRoot(), dir) 1067 } 1068 return dir, true, nil 1069 } 1070 mod = r 1071 } 1072 1073 dir, err = modfetch.Download(mod) 1074 return dir, false, err 1075} 1076