github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-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 pathpkg "path" 16 "path/filepath" 17 "sort" 18 "strings" 19 "sync" 20 21 "github.com/gagliardetto/golang-go/cmd/go/not-internal/base" 22 "github.com/gagliardetto/golang-go/cmd/go/not-internal/cfg" 23 "github.com/gagliardetto/golang-go/cmd/go/not-internal/imports" 24 "github.com/gagliardetto/golang-go/cmd/go/not-internal/modfetch" 25 "github.com/gagliardetto/golang-go/cmd/go/not-internal/mvs" 26 "github.com/gagliardetto/golang-go/cmd/go/not-internal/par" 27 "github.com/gagliardetto/golang-go/cmd/go/not-internal/search" 28 "github.com/gagliardetto/golang-go/cmd/go/not-internal/str" 29 30 "golang.org/x/mod/modfile" 31 "golang.org/x/mod/module" 32 "golang.org/x/mod/semver" 33 ) 34 35 // buildList is the list of modules to use for building packages. 36 // It is initialized by calling ImportPaths, ImportFromFiles, 37 // LoadALL, or LoadBuildList, each of which uses loaded.load. 38 // 39 // Ideally, exactly ONE of those functions would be called, 40 // and exactly once. Most of the time, that's true. 41 // During "go get" it may not be. TODO(rsc): Figure out if 42 // that restriction can be established, or else document why not. 43 // 44 var buildList []module.Version 45 46 // loaded is the most recently-used package loader. 47 // It holds details about individual packages. 48 // 49 // Note that loaded.buildList is only valid during a load operation; 50 // afterward, it is copied back into the global buildList, 51 // which should be used instead. 52 var loaded *loader 53 54 // ImportPaths returns the set of packages matching the args (patterns), 55 // on the target platform. Modules may be added to the build list 56 // to satisfy new imports. 57 func ImportPaths(patterns []string) []*search.Match { 58 matches := ImportPathsQuiet(patterns, imports.Tags()) 59 search.WarnUnmatched(matches) 60 return matches 61 } 62 63 // ImportPathsQuiet is like ImportPaths but does not warn about patterns with 64 // no matches. It also lets the caller specify a set of build tags to match 65 // packages. The build tags should typically be imports.Tags() or 66 // imports.AnyTags(); a nil map has no special meaning. 67 func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match { 68 var fsDirs [][]string 69 updateMatches := func(matches []*search.Match, iterating bool) { 70 for i, m := range matches { 71 switch { 72 case build.IsLocalImport(m.Pattern) || filepath.IsAbs(m.Pattern): 73 // Evaluate list of file system directories on first iteration. 74 if fsDirs == nil { 75 fsDirs = make([][]string, len(matches)) 76 } 77 if fsDirs[i] == nil { 78 var dirs []string 79 if m.Literal { 80 dirs = []string{m.Pattern} 81 } else { 82 dirs = search.MatchPackagesInFS(m.Pattern).Pkgs 83 } 84 fsDirs[i] = dirs 85 } 86 87 // Make a copy of the directory list and translate to import paths. 88 // Note that whether a directory corresponds to an import path 89 // changes as the build list is updated, and a directory can change 90 // from not being in the build list to being in it and back as 91 // the exact version of a particular module increases during 92 // the loader iterations. 93 m.Pkgs = str.StringList(fsDirs[i]) 94 pkgs := m.Pkgs 95 m.Pkgs = m.Pkgs[:0] 96 for _, pkg := range pkgs { 97 var dir string 98 if !filepath.IsAbs(pkg) { 99 dir = filepath.Join(base.Cwd, pkg) 100 } else { 101 dir = filepath.Clean(pkg) 102 } 103 104 // golang.org/issue/32917: We should resolve a relative path to a 105 // package path only if the relative path actually contains the code 106 // for that package. 107 if !dirContainsPackage(dir) { 108 // If we're outside of a module, ensure that the failure mode 109 // indicates that. 110 ModRoot() 111 112 // If the directory is local but does not exist, don't return it 113 // while loader is iterating, since this might trigger a fetch. 114 // After loader is done iterating, we still need to return the 115 // path, so that "go list -e" produces valid output. 116 if !iterating { 117 // We don't have a valid path to resolve to, so report the 118 // unresolved path. 119 m.Pkgs = append(m.Pkgs, pkg) 120 } 121 continue 122 } 123 124 // Note: The checks for @ here are just to avoid misinterpreting 125 // the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar). 126 // It's not strictly necessary but helpful to keep the checks. 127 if modRoot != "" && dir == modRoot { 128 pkg = targetPrefix 129 } else if modRoot != "" && strings.HasPrefix(dir, modRoot+string(filepath.Separator)) && !strings.Contains(dir[len(modRoot):], "@") { 130 suffix := filepath.ToSlash(dir[len(modRoot):]) 131 if strings.HasPrefix(suffix, "/vendor/") { 132 // TODO getmode vendor check 133 pkg = strings.TrimPrefix(suffix, "/vendor/") 134 } else if targetInGorootSrc && Target.Path == "std" { 135 // Don't add the prefix "std/" to packages in the "std" module. 136 // It's the one module path that isn't a prefix of its packages. 137 pkg = strings.TrimPrefix(suffix, "/") 138 if pkg == "builtin" { 139 // "builtin" is a pseudo-package with a real source file. 140 // It's not included in "std", so it shouldn't be included in 141 // "./..." within module "std" either. 142 continue 143 } 144 } else { 145 modPkg := targetPrefix + suffix 146 if _, ok := dirInModule(modPkg, targetPrefix, modRoot, true); ok { 147 pkg = modPkg 148 } else if !iterating { 149 ModRoot() 150 base.Errorf("go: directory %s is outside main module", base.ShortPath(dir)) 151 } 152 } 153 } else if sub := search.InDir(dir, cfg.GOROOTsrc); sub != "" && sub != "." && !strings.Contains(sub, "@") { 154 pkg = filepath.ToSlash(sub) 155 } else if path := pathInModuleCache(dir); path != "" { 156 pkg = path 157 } else { 158 pkg = "" 159 if !iterating { 160 ModRoot() 161 base.Errorf("go: directory %s outside available modules", base.ShortPath(dir)) 162 } 163 } 164 m.Pkgs = append(m.Pkgs, pkg) 165 } 166 167 case strings.Contains(m.Pattern, "..."): 168 m.Pkgs = matchPackages(m.Pattern, loaded.tags, true, buildList) 169 170 case m.Pattern == "all": 171 loaded.testAll = true 172 if iterating { 173 // Enumerate the packages in the main module. 174 // We'll load the dependencies as we find them. 175 m.Pkgs = matchPackages("...", loaded.tags, false, []module.Version{Target}) 176 } else { 177 // Starting with the packages in the main module, 178 // enumerate the full list of "all". 179 m.Pkgs = loaded.computePatternAll(m.Pkgs) 180 } 181 182 case search.IsMetaPackage(m.Pattern): // std, cmd 183 if len(m.Pkgs) == 0 { 184 m.Pkgs = search.MatchPackages(m.Pattern).Pkgs 185 } 186 187 default: 188 m.Pkgs = []string{m.Pattern} 189 } 190 } 191 } 192 193 InitMod() 194 195 var matches []*search.Match 196 for _, pattern := range search.CleanPatterns(patterns) { 197 matches = append(matches, &search.Match{ 198 Pattern: pattern, 199 Literal: !strings.Contains(pattern, "...") && !search.IsMetaPackage(pattern), 200 }) 201 } 202 203 loaded = newLoader(tags) 204 loaded.load(func() []string { 205 var roots []string 206 updateMatches(matches, true) 207 for _, m := range matches { 208 roots = append(roots, m.Pkgs...) 209 } 210 return roots 211 }) 212 213 // One last pass to finalize wildcards. 214 updateMatches(matches, false) 215 checkMultiplePaths() 216 WriteGoMod() 217 218 return matches 219 } 220 221 // checkMultiplePaths verifies that a given module path is used as itself 222 // or as a replacement for another module, but not both at the same time. 223 // 224 // (See https://golang.org/issue/26607 and https://golang.org/issue/34650.) 225 func checkMultiplePaths() { 226 firstPath := make(map[module.Version]string, len(buildList)) 227 for _, mod := range buildList { 228 src := mod 229 if rep := Replacement(mod); rep.Path != "" { 230 src = rep 231 } 232 if prev, ok := firstPath[src]; !ok { 233 firstPath[src] = mod.Path 234 } else if prev != mod.Path { 235 base.Errorf("go: %s@%s used for two different module paths (%s and %s)", src.Path, src.Version, prev, mod.Path) 236 } 237 } 238 base.ExitIfErrors() 239 } 240 241 // pathInModuleCache returns the import path of the directory dir, 242 // if dir is in the module cache copy of a module in our build list. 243 func pathInModuleCache(dir string) string { 244 for _, m := range buildList[1:] { 245 var root string 246 var err error 247 if repl := Replacement(m); repl.Path != "" && repl.Version == "" { 248 root = repl.Path 249 if !filepath.IsAbs(root) { 250 root = filepath.Join(ModRoot(), root) 251 } 252 } else if repl.Path != "" { 253 root, err = modfetch.DownloadDir(repl) 254 } else { 255 root, err = modfetch.DownloadDir(m) 256 } 257 if err != nil { 258 continue 259 } 260 if sub := search.InDir(dir, root); sub != "" { 261 sub = filepath.ToSlash(sub) 262 if !strings.Contains(sub, "/vendor/") && !strings.HasPrefix(sub, "vendor/") && !strings.Contains(sub, "@") { 263 return path.Join(m.Path, filepath.ToSlash(sub)) 264 } 265 } 266 } 267 return "" 268 } 269 270 var dirContainsPackageCache sync.Map // absolute dir → bool 271 272 func dirContainsPackage(dir string) bool { 273 isPkg, ok := dirContainsPackageCache.Load(dir) 274 if !ok { 275 _, err := cfg.BuildContext.ImportDir(dir, 0) 276 if err == nil { 277 isPkg = true 278 } else { 279 if fi, statErr := os.Stat(dir); statErr != nil || !fi.IsDir() { 280 // A non-directory or inaccessible directory is not a Go package. 281 isPkg = false 282 } else if _, noGo := err.(*build.NoGoError); noGo { 283 // A directory containing no Go source files is not a Go package. 284 isPkg = false 285 } else { 286 // An error other than *build.NoGoError indicates that the package exists 287 // but has some other problem (such as a syntax error). 288 isPkg = true 289 } 290 } 291 isPkg, _ = dirContainsPackageCache.LoadOrStore(dir, isPkg) 292 } 293 return isPkg.(bool) 294 } 295 296 // ImportFromFiles adds modules to the build list as needed 297 // to satisfy the imports in the named Go source files. 298 func ImportFromFiles(gofiles []string) { 299 InitMod() 300 301 tags := imports.Tags() 302 imports, testImports, err := imports.ScanFiles(gofiles, tags) 303 if err != nil { 304 base.Fatalf("go: %v", err) 305 } 306 307 loaded = newLoader(tags) 308 loaded.load(func() []string { 309 var roots []string 310 roots = append(roots, imports...) 311 roots = append(roots, testImports...) 312 return roots 313 }) 314 WriteGoMod() 315 } 316 317 // DirImportPath returns the effective import path for dir, 318 // provided it is within the main module, or else returns ".". 319 func DirImportPath(dir string) string { 320 if modRoot == "" { 321 return "." 322 } 323 324 if !filepath.IsAbs(dir) { 325 dir = filepath.Join(base.Cwd, dir) 326 } else { 327 dir = filepath.Clean(dir) 328 } 329 330 if dir == modRoot { 331 return targetPrefix 332 } 333 if strings.HasPrefix(dir, modRoot+string(filepath.Separator)) { 334 suffix := filepath.ToSlash(dir[len(modRoot):]) 335 if strings.HasPrefix(suffix, "/vendor/") { 336 return strings.TrimPrefix(suffix, "/vendor/") 337 } 338 return targetPrefix + suffix 339 } 340 return "." 341 } 342 343 // LoadBuildList loads and returns the build list from go.mod. 344 // The loading of the build list happens automatically in ImportPaths: 345 // LoadBuildList need only be called if ImportPaths is not 346 // (typically in commands that care about the module but 347 // no particular package). 348 func LoadBuildList() []module.Version { 349 InitMod() 350 ReloadBuildList() 351 WriteGoMod() 352 return buildList 353 } 354 355 func ReloadBuildList() []module.Version { 356 loaded = newLoader(imports.Tags()) 357 loaded.load(func() []string { return nil }) 358 return buildList 359 } 360 361 // LoadALL returns the set of all packages in the current module 362 // and their dependencies in any other modules, without filtering 363 // due to build tags, except "+build ignore". 364 // It adds modules to the build list as needed to satisfy new imports. 365 // This set is useful for deciding whether a particular import is needed 366 // anywhere in a module. 367 func LoadALL() []string { 368 return loadAll(true) 369 } 370 371 // LoadVendor is like LoadALL but only follows test dependencies 372 // for tests in the main module. Tests in dependency modules are 373 // ignored completely. 374 // This set is useful for identifying the which packages to include in a vendor directory. 375 func LoadVendor() []string { 376 return loadAll(false) 377 } 378 379 func loadAll(testAll bool) []string { 380 InitMod() 381 382 loaded = newLoader(imports.AnyTags()) 383 loaded.isALL = true 384 loaded.testAll = testAll 385 if !testAll { 386 loaded.testRoots = true 387 } 388 all := TargetPackages("...") 389 loaded.load(func() []string { return all }) 390 checkMultiplePaths() 391 WriteGoMod() 392 393 var paths []string 394 for _, pkg := range loaded.pkgs { 395 if pkg.err != nil { 396 base.Errorf("%s: %v", pkg.stackText(), pkg.err) 397 continue 398 } 399 paths = append(paths, pkg.path) 400 } 401 base.ExitIfErrors() 402 return paths 403 } 404 405 // TargetPackages returns the list of packages in the target (top-level) module 406 // matching pattern, which may be relative to the working directory, under all 407 // build tag settings. 408 func TargetPackages(pattern string) []string { 409 // TargetPackages is relative to the main module, so ensure that the main 410 // module is a thing that can contain packages. 411 ModRoot() 412 413 return matchPackages(pattern, imports.AnyTags(), false, []module.Version{Target}) 414 } 415 416 // BuildList returns the module build list, 417 // typically constructed by a previous call to 418 // LoadBuildList or ImportPaths. 419 // The caller must not modify the returned list. 420 func BuildList() []module.Version { 421 return buildList 422 } 423 424 // SetBuildList sets the module build list. 425 // The caller is responsible for ensuring that the list is valid. 426 // SetBuildList does not retain a reference to the original list. 427 func SetBuildList(list []module.Version) { 428 buildList = append([]module.Version{}, list...) 429 } 430 431 // TidyBuildList trims the build list to the minimal requirements needed to 432 // retain the same versions of all packages from the preceding Load* or 433 // ImportPaths* call. 434 func TidyBuildList() { 435 used := map[module.Version]bool{Target: true} 436 for _, pkg := range loaded.pkgs { 437 used[pkg.mod] = true 438 } 439 440 keep := []module.Version{Target} 441 var direct []string 442 for _, m := range buildList[1:] { 443 if used[m] { 444 keep = append(keep, m) 445 if loaded.direct[m.Path] { 446 direct = append(direct, m.Path) 447 } 448 } else if cfg.BuildV { 449 if _, ok := index.require[m]; ok { 450 fmt.Fprintf(os.Stderr, "unused %s\n", m.Path) 451 } 452 } 453 } 454 455 min, err := mvs.Req(Target, direct, &mvsReqs{buildList: keep}) 456 if err != nil { 457 base.Fatalf("go: %v", err) 458 } 459 buildList = append([]module.Version{Target}, min...) 460 } 461 462 // ImportMap returns the actual package import path 463 // for an import path found in source code. 464 // If the given import path does not appear in the source code 465 // for the packages that have been loaded, ImportMap returns the empty string. 466 func ImportMap(path string) string { 467 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 468 if !ok { 469 return "" 470 } 471 return pkg.path 472 } 473 474 // PackageDir returns the directory containing the source code 475 // for the package named by the import path. 476 func PackageDir(path string) string { 477 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 478 if !ok { 479 return "" 480 } 481 return pkg.dir 482 } 483 484 // PackageModule returns the module providing the package named by the import path. 485 func PackageModule(path string) module.Version { 486 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 487 if !ok { 488 return module.Version{} 489 } 490 return pkg.mod 491 } 492 493 // PackageImports returns the imports for the package named by the import path. 494 // Test imports will be returned as well if tests were loaded for the package 495 // (i.e., if "all" was loaded or if LoadTests was set and the path was matched 496 // by a command line argument). PackageImports will return nil for 497 // unknown package paths. 498 func PackageImports(path string) (imports, testImports []string) { 499 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 500 if !ok { 501 return nil, nil 502 } 503 imports = make([]string, len(pkg.imports)) 504 for i, p := range pkg.imports { 505 imports[i] = p.path 506 } 507 if pkg.test != nil { 508 testImports = make([]string, len(pkg.test.imports)) 509 for i, p := range pkg.test.imports { 510 testImports[i] = p.path 511 } 512 } 513 return imports, testImports 514 } 515 516 // ModuleUsedDirectly reports whether the main module directly imports 517 // some package in the module with the given path. 518 func ModuleUsedDirectly(path string) bool { 519 return loaded.direct[path] 520 } 521 522 // Lookup returns the source directory, import path, and any loading error for 523 // the package at path as imported from the package in parentDir. 524 // Lookup requires that one of the Load functions in this package has already 525 // been called. 526 func Lookup(parentPath string, parentIsStd bool, path string) (dir, realPath string, err error) { 527 if path == "" { 528 panic("Lookup called with empty package path") 529 } 530 531 if parentIsStd { 532 path = loaded.stdVendor(parentPath, path) 533 } 534 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 535 if !ok { 536 // The loader should have found all the relevant paths. 537 // There are a few exceptions, though: 538 // - during go list without -test, the p.Resolve calls to process p.TestImports and p.XTestImports 539 // end up here to canonicalize the import paths. 540 // - during any load, non-loaded packages like "unsafe" end up here. 541 // - during any load, build-injected dependencies like "runtime/cgo" end up here. 542 // - because we ignore appengine/* in the module loader, 543 // the dependencies of any actual appengine/* library end up here. 544 dir := findStandardImportPath(path) 545 if dir != "" { 546 return dir, path, nil 547 } 548 return "", "", errMissing 549 } 550 return pkg.dir, pkg.path, pkg.err 551 } 552 553 // A loader manages the process of loading information about 554 // the required packages for a particular build, 555 // checking that the packages are available in the module set, 556 // and updating the module set if needed. 557 // Loading is an iterative process: try to load all the needed packages, 558 // but if imports are missing, try to resolve those imports, and repeat. 559 // 560 // Although most of the loading state is maintained in the loader struct, 561 // one key piece - the build list - is a global, so that it can be modified 562 // separate from the loading operation, such as during "go get" 563 // upgrades/downgrades or in "go mod" operations. 564 // TODO(rsc): It might be nice to make the loader take and return 565 // a buildList rather than hard-coding use of the global. 566 type loader struct { 567 tags map[string]bool // tags for scanDir 568 testRoots bool // include tests for roots 569 isALL bool // created with LoadALL 570 testAll bool // include tests for all packages 571 forceStdVendor bool // if true, load standard-library dependencies from the vendor subtree 572 573 // reset on each iteration 574 roots []*loadPkg 575 pkgs []*loadPkg 576 work *par.Work // current work queue 577 pkgCache *par.Cache // map from string to *loadPkg 578 579 // computed at end of iterations 580 direct map[string]bool // imported directly by main module 581 goVersion map[string]string // go version recorded in each module 582 } 583 584 // LoadTests controls whether the loaders load tests of the root packages. 585 var LoadTests bool 586 587 func newLoader(tags map[string]bool) *loader { 588 ld := new(loader) 589 ld.tags = tags 590 ld.testRoots = LoadTests 591 592 // Inside the "std" and "cmd" modules, we prefer to use the vendor directory 593 // unless the command explicitly changes the module graph. 594 if !targetInGorootSrc || (cfg.CmdName != "get" && !strings.HasPrefix(cfg.CmdName, "mod ")) { 595 ld.forceStdVendor = true 596 } 597 598 return ld 599 } 600 601 func (ld *loader) reset() { 602 ld.roots = nil 603 ld.pkgs = nil 604 ld.work = new(par.Work) 605 ld.pkgCache = new(par.Cache) 606 } 607 608 // A loadPkg records information about a single loaded package. 609 type loadPkg struct { 610 path string // import path 611 mod module.Version // module providing package 612 dir string // directory containing source code 613 imports []*loadPkg // packages imported by this one 614 err error // error loading package 615 stack *loadPkg // package importing this one in minimal import stack for this pkg 616 test *loadPkg // package with test imports, if we need test 617 testOf *loadPkg 618 testImports []string // test-only imports, saved for use by pkg.test. 619 } 620 621 var errMissing = errors.New("cannot find package") 622 623 // load attempts to load the build graph needed to process a set of root packages. 624 // The set of root packages is defined by the addRoots function, 625 // which must call add(path) with the import path of each root package. 626 func (ld *loader) load(roots func() []string) { 627 var err error 628 reqs := Reqs() 629 buildList, err = mvs.BuildList(Target, reqs) 630 if err != nil { 631 base.Fatalf("go: %v", err) 632 } 633 634 added := make(map[string]bool) 635 for { 636 ld.reset() 637 if roots != nil { 638 // Note: the returned roots can change on each iteration, 639 // since the expansion of package patterns depends on the 640 // build list we're using. 641 for _, path := range roots() { 642 ld.work.Add(ld.pkg(path, true)) 643 } 644 } 645 ld.work.Do(10, ld.doPkg) 646 ld.buildStacks() 647 numAdded := 0 648 haveMod := make(map[module.Version]bool) 649 for _, m := range buildList { 650 haveMod[m] = true 651 } 652 modAddedBy := make(map[module.Version]*loadPkg) 653 for _, pkg := range ld.pkgs { 654 if err, ok := pkg.err.(*ImportMissingError); ok && err.Module.Path != "" { 655 if err.newMissingVersion != "" { 656 base.Fatalf("go: %s: package provided by %s at latest version %s but not at required version %s", pkg.stackText(), err.Module.Path, err.Module.Version, err.newMissingVersion) 657 } 658 if added[pkg.path] { 659 base.Fatalf("go: %s: looping trying to add package", pkg.stackText()) 660 } 661 added[pkg.path] = true 662 numAdded++ 663 if !haveMod[err.Module] { 664 fmt.Fprintf(os.Stderr, "go: found %s in %s %s\n", pkg.path, err.Module.Path, err.Module.Version) 665 haveMod[err.Module] = true 666 modAddedBy[err.Module] = pkg 667 buildList = append(buildList, err.Module) 668 } 669 continue 670 } 671 // Leave other errors for Import or load.Packages to report. 672 } 673 base.ExitIfErrors() 674 if numAdded == 0 { 675 break 676 } 677 678 // Recompute buildList with all our additions. 679 reqs = Reqs() 680 buildList, err = mvs.BuildList(Target, reqs) 681 if err != nil { 682 // If an error was found in a newly added module, report the package 683 // import stack instead of the module requirement stack. Packages 684 // are more descriptive. 685 if err, ok := err.(*mvs.BuildListError); ok { 686 if pkg := modAddedBy[err.Module()]; pkg != nil { 687 base.Fatalf("go: %s: %v", pkg.stackText(), err.Err) 688 } 689 } 690 base.Fatalf("go: %v", err) 691 } 692 } 693 base.ExitIfErrors() 694 695 // Compute directly referenced dependency modules. 696 ld.direct = make(map[string]bool) 697 for _, pkg := range ld.pkgs { 698 if pkg.mod == Target { 699 for _, dep := range pkg.imports { 700 if dep.mod.Path != "" { 701 ld.direct[dep.mod.Path] = true 702 } 703 } 704 } 705 } 706 707 // Add Go versions, computed during walk. 708 ld.goVersion = make(map[string]string) 709 for _, m := range buildList { 710 v, _ := reqs.(*mvsReqs).versions.Load(m) 711 ld.goVersion[m.Path], _ = v.(string) 712 } 713 714 // Mix in direct markings (really, lack of indirect markings) 715 // from go.mod, unless we scanned the whole module 716 // and can therefore be sure we know better than go.mod. 717 if !ld.isALL && modFile != nil { 718 for _, r := range modFile.Require { 719 if !r.Indirect { 720 ld.direct[r.Mod.Path] = true 721 } 722 } 723 } 724 } 725 726 // pkg returns the *loadPkg for path, creating and queuing it if needed. 727 // If the package should be tested, its test is created but not queued 728 // (the test is queued after processing pkg). 729 // If isRoot is true, the pkg is being queued as one of the roots of the work graph. 730 func (ld *loader) pkg(path string, isRoot bool) *loadPkg { 731 return ld.pkgCache.Do(path, func() interface{} { 732 pkg := &loadPkg{ 733 path: path, 734 } 735 if ld.testRoots && isRoot || ld.testAll { 736 test := &loadPkg{ 737 path: path, 738 testOf: pkg, 739 } 740 pkg.test = test 741 } 742 if isRoot { 743 ld.roots = append(ld.roots, pkg) 744 } 745 ld.work.Add(pkg) 746 return pkg 747 }).(*loadPkg) 748 } 749 750 // doPkg processes a package on the work queue. 751 func (ld *loader) doPkg(item interface{}) { 752 // TODO: what about replacements? 753 pkg := item.(*loadPkg) 754 var imports []string 755 if pkg.testOf != nil { 756 pkg.dir = pkg.testOf.dir 757 pkg.mod = pkg.testOf.mod 758 imports = pkg.testOf.testImports 759 } else { 760 if strings.Contains(pkg.path, "@") { 761 // Leave for error during load. 762 return 763 } 764 if build.IsLocalImport(pkg.path) { 765 // Leave for error during load. 766 // (Module mode does not allow local imports.) 767 return 768 } 769 770 pkg.mod, pkg.dir, pkg.err = Import(pkg.path) 771 if pkg.dir == "" { 772 return 773 } 774 var testImports []string 775 var err error 776 imports, testImports, err = scanDir(pkg.dir, ld.tags) 777 if err != nil { 778 pkg.err = err 779 return 780 } 781 if pkg.test != nil { 782 pkg.testImports = testImports 783 } 784 } 785 786 inStd := (search.IsStandardImportPath(pkg.path) && search.InDir(pkg.dir, cfg.GOROOTsrc) != "") 787 for _, path := range imports { 788 if inStd { 789 path = ld.stdVendor(pkg.path, path) 790 } 791 pkg.imports = append(pkg.imports, ld.pkg(path, false)) 792 } 793 794 // Now that pkg.dir, pkg.mod, pkg.testImports are set, we can queue pkg.test. 795 // TODO: All that's left is creating new imports. Why not just do it now? 796 if pkg.test != nil { 797 ld.work.Add(pkg.test) 798 } 799 } 800 801 // stdVendor returns the canonical import path for the package with the given 802 // path when imported from the standard-library package at parentPath. 803 func (ld *loader) stdVendor(parentPath, path string) string { 804 if search.IsStandardImportPath(path) { 805 return path 806 } 807 808 if str.HasPathPrefix(parentPath, "cmd") { 809 if ld.forceStdVendor || Target.Path != "cmd" { 810 vendorPath := pathpkg.Join("cmd", "vendor", path) 811 if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil { 812 return vendorPath 813 } 814 } 815 } else if ld.forceStdVendor || Target.Path != "std" { 816 vendorPath := pathpkg.Join("vendor", path) 817 if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil { 818 return vendorPath 819 } 820 } 821 822 // Not vendored: resolve from modules. 823 return path 824 } 825 826 // computePatternAll returns the list of packages matching pattern "all", 827 // starting with a list of the import paths for the packages in the main module. 828 func (ld *loader) computePatternAll(paths []string) []string { 829 seen := make(map[*loadPkg]bool) 830 var all []string 831 var walk func(*loadPkg) 832 walk = func(pkg *loadPkg) { 833 if seen[pkg] { 834 return 835 } 836 seen[pkg] = true 837 if pkg.testOf == nil { 838 all = append(all, pkg.path) 839 } 840 for _, p := range pkg.imports { 841 walk(p) 842 } 843 if p := pkg.test; p != nil { 844 walk(p) 845 } 846 } 847 for _, path := range paths { 848 walk(ld.pkg(path, false)) 849 } 850 sort.Strings(all) 851 852 return all 853 } 854 855 // scanDir is like imports.ScanDir but elides known magic imports from the list, 856 // so that we do not go looking for packages that don't really exist. 857 // 858 // The standard magic import is "C", for cgo. 859 // 860 // The only other known magic imports are appengine and appengine/*. 861 // These are so old that they predate "go get" and did not use URL-like paths. 862 // Most code today now uses google.golang.org/appengine instead, 863 // but not all code has been so updated. When we mostly ignore build tags 864 // during "go vendor", we look into "// +build appengine" files and 865 // may see these legacy imports. We drop them so that the module 866 // search does not look for modules to try to satisfy them. 867 func scanDir(dir string, tags map[string]bool) (imports_, testImports []string, err error) { 868 imports_, testImports, err = imports.ScanDir(dir, tags) 869 870 filter := func(x []string) []string { 871 w := 0 872 for _, pkg := range x { 873 if pkg != "C" && pkg != "appengine" && !strings.HasPrefix(pkg, "appengine/") && 874 pkg != "appengine_internal" && !strings.HasPrefix(pkg, "appengine_internal/") { 875 x[w] = pkg 876 w++ 877 } 878 } 879 return x[:w] 880 } 881 882 return filter(imports_), filter(testImports), err 883 } 884 885 // buildStacks computes minimal import stacks for each package, 886 // for use in error messages. When it completes, packages that 887 // are part of the original root set have pkg.stack == nil, 888 // and other packages have pkg.stack pointing at the next 889 // package up the import stack in their minimal chain. 890 // As a side effect, buildStacks also constructs ld.pkgs, 891 // the list of all packages loaded. 892 func (ld *loader) buildStacks() { 893 if len(ld.pkgs) > 0 { 894 panic("buildStacks") 895 } 896 for _, pkg := range ld.roots { 897 pkg.stack = pkg // sentinel to avoid processing in next loop 898 ld.pkgs = append(ld.pkgs, pkg) 899 } 900 for i := 0; i < len(ld.pkgs); i++ { // not range: appending to ld.pkgs in loop 901 pkg := ld.pkgs[i] 902 for _, next := range pkg.imports { 903 if next.stack == nil { 904 next.stack = pkg 905 ld.pkgs = append(ld.pkgs, next) 906 } 907 } 908 if next := pkg.test; next != nil && next.stack == nil { 909 next.stack = pkg 910 ld.pkgs = append(ld.pkgs, next) 911 } 912 } 913 for _, pkg := range ld.roots { 914 pkg.stack = nil 915 } 916 } 917 918 // stackText builds the import stack text to use when 919 // reporting an error in pkg. It has the general form 920 // 921 // root imports 922 // other imports 923 // other2 tested by 924 // other2.test imports 925 // pkg 926 // 927 func (pkg *loadPkg) stackText() string { 928 var stack []*loadPkg 929 for p := pkg; p != nil; p = p.stack { 930 stack = append(stack, p) 931 } 932 933 var buf bytes.Buffer 934 for i := len(stack) - 1; i >= 0; i-- { 935 p := stack[i] 936 fmt.Fprint(&buf, p.path) 937 if p.testOf != nil { 938 fmt.Fprint(&buf, ".test") 939 } 940 if i > 0 { 941 if stack[i-1].testOf == p { 942 fmt.Fprint(&buf, " tested by\n\t") 943 } else { 944 fmt.Fprint(&buf, " imports\n\t") 945 } 946 } 947 } 948 return buf.String() 949 } 950 951 // why returns the text to use in "go mod why" output about the given package. 952 // It is less ornate than the stackText but contains the same information. 953 func (pkg *loadPkg) why() string { 954 var buf strings.Builder 955 var stack []*loadPkg 956 for p := pkg; p != nil; p = p.stack { 957 stack = append(stack, p) 958 } 959 960 for i := len(stack) - 1; i >= 0; i-- { 961 p := stack[i] 962 if p.testOf != nil { 963 fmt.Fprintf(&buf, "%s.test\n", p.testOf.path) 964 } else { 965 fmt.Fprintf(&buf, "%s\n", p.path) 966 } 967 } 968 return buf.String() 969 } 970 971 // Why returns the "go mod why" output stanza for the given package, 972 // without the leading # comment. 973 // The package graph must have been loaded already, usually by LoadALL. 974 // If there is no reason for the package to be in the current build, 975 // Why returns an empty string. 976 func Why(path string) string { 977 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 978 if !ok { 979 return "" 980 } 981 return pkg.why() 982 } 983 984 // WhyDepth returns the number of steps in the Why listing. 985 // If there is no reason for the package to be in the current build, 986 // WhyDepth returns 0. 987 func WhyDepth(path string) int { 988 n := 0 989 pkg, _ := loaded.pkgCache.Get(path).(*loadPkg) 990 for p := pkg; p != nil; p = p.stack { 991 n++ 992 } 993 return n 994 } 995 996 // Replacement returns the replacement for mod, if any, from go.mod. 997 // If there is no replacement for mod, Replacement returns 998 // a module.Version with Path == "". 999 func Replacement(mod module.Version) module.Version { 1000 if index != nil { 1001 if r, ok := index.replace[mod]; ok { 1002 return r 1003 } 1004 if r, ok := index.replace[module.Version{Path: mod.Path}]; ok { 1005 return r 1006 } 1007 } 1008 return module.Version{} 1009 } 1010 1011 // mvsReqs implements mvs.Reqs for module semantic versions, 1012 // with any exclusions or replacements applied internally. 1013 type mvsReqs struct { 1014 buildList []module.Version 1015 cache par.Cache 1016 versions sync.Map 1017 } 1018 1019 // Reqs returns the current module requirement graph. 1020 // Future calls to SetBuildList do not affect the operation 1021 // of the returned Reqs. 1022 func Reqs() mvs.Reqs { 1023 r := &mvsReqs{ 1024 buildList: buildList, 1025 } 1026 return r 1027 } 1028 1029 func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { 1030 type cached struct { 1031 list []module.Version 1032 err error 1033 } 1034 1035 c := r.cache.Do(mod, func() interface{} { 1036 list, err := r.required(mod) 1037 if err != nil { 1038 return cached{nil, err} 1039 } 1040 for i, mv := range list { 1041 if index != nil { 1042 for index.exclude[mv] { 1043 mv1, err := r.next(mv) 1044 if err != nil { 1045 return cached{nil, err} 1046 } 1047 if mv1.Version == "none" { 1048 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)} 1049 } 1050 mv = mv1 1051 } 1052 } 1053 list[i] = mv 1054 } 1055 1056 return cached{list, nil} 1057 }).(cached) 1058 1059 return c.list, c.err 1060 } 1061 1062 var vendorOnce sync.Once 1063 1064 type vendorMetadata struct { 1065 Explicit bool 1066 Replacement module.Version 1067 } 1068 1069 var ( 1070 vendorList []module.Version // modules that contribute packages to the build, in order of appearance 1071 vendorReplaced []module.Version // all replaced modules; may or may not also contribute packages 1072 vendorVersion map[string]string // module path → selected version (if known) 1073 vendorPkgModule map[string]module.Version // package → containing module 1074 vendorMeta map[module.Version]vendorMetadata 1075 ) 1076 1077 // readVendorList reads the list of vendored modules from vendor/modules.txt. 1078 func readVendorList() { 1079 vendorOnce.Do(func() { 1080 vendorList = nil 1081 vendorPkgModule = make(map[string]module.Version) 1082 vendorVersion = make(map[string]string) 1083 vendorMeta = make(map[module.Version]vendorMetadata) 1084 data, err := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt")) 1085 if err != nil { 1086 if !errors.Is(err, os.ErrNotExist) { 1087 base.Fatalf("go: %s", err) 1088 } 1089 return 1090 } 1091 1092 var mod module.Version 1093 for _, line := range strings.Split(string(data), "\n") { 1094 if strings.HasPrefix(line, "# ") { 1095 f := strings.Fields(line) 1096 1097 if len(f) < 3 { 1098 continue 1099 } 1100 if semver.IsValid(f[2]) { 1101 // A module, but we don't yet know whether it is in the build list or 1102 // only included to indicate a replacement. 1103 mod = module.Version{Path: f[1], Version: f[2]} 1104 f = f[3:] 1105 } else if f[2] == "=>" { 1106 // A wildcard replacement found in the main module's go.mod file. 1107 mod = module.Version{Path: f[1]} 1108 f = f[2:] 1109 } else { 1110 // Not a version or a wildcard replacement. 1111 // We don't know how to interpret this module line, so ignore it. 1112 mod = module.Version{} 1113 continue 1114 } 1115 1116 if len(f) >= 2 && f[0] == "=>" { 1117 meta := vendorMeta[mod] 1118 if len(f) == 2 { 1119 // File replacement. 1120 meta.Replacement = module.Version{Path: f[1]} 1121 vendorReplaced = append(vendorReplaced, mod) 1122 } else if len(f) == 3 && semver.IsValid(f[2]) { 1123 // Path and version replacement. 1124 meta.Replacement = module.Version{Path: f[1], Version: f[2]} 1125 vendorReplaced = append(vendorReplaced, mod) 1126 } else { 1127 // We don't understand this replacement. Ignore it. 1128 } 1129 vendorMeta[mod] = meta 1130 } 1131 continue 1132 } 1133 1134 // Not a module line. Must be a package within a module or a metadata 1135 // directive, either of which requires a preceding module line. 1136 if mod.Path == "" { 1137 continue 1138 } 1139 1140 if strings.HasPrefix(line, "## ") { 1141 // Metadata. Take the union of annotations across multiple lines, if present. 1142 meta := vendorMeta[mod] 1143 for _, entry := range strings.Split(strings.TrimPrefix(line, "## "), ";") { 1144 entry = strings.TrimSpace(entry) 1145 if entry == "explicit" { 1146 meta.Explicit = true 1147 } 1148 // All other tokens are reserved for future use. 1149 } 1150 vendorMeta[mod] = meta 1151 continue 1152 } 1153 1154 if f := strings.Fields(line); len(f) == 1 && module.CheckImportPath(f[0]) == nil { 1155 // A package within the current module. 1156 vendorPkgModule[f[0]] = mod 1157 1158 // Since this module provides a package for the build, we know that it 1159 // is in the build list and is the selected version of its path. 1160 // If this information is new, record it. 1161 if v, ok := vendorVersion[mod.Path]; !ok || semver.Compare(v, mod.Version) < 0 { 1162 vendorList = append(vendorList, mod) 1163 vendorVersion[mod.Path] = mod.Version 1164 } 1165 } 1166 } 1167 }) 1168 } 1169 1170 func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version { 1171 list := make([]module.Version, 0, len(f.Require)) 1172 for _, r := range f.Require { 1173 list = append(list, r.Mod) 1174 } 1175 return list 1176 } 1177 1178 // required returns a unique copy of the requirements of mod. 1179 func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) { 1180 if mod == Target { 1181 if modFile != nil && modFile.Go != nil { 1182 r.versions.LoadOrStore(mod, modFile.Go.Version) 1183 } 1184 return append([]module.Version(nil), r.buildList[1:]...), nil 1185 } 1186 1187 if cfg.BuildMod == "vendor" { 1188 // For every module other than the target, 1189 // return the full list of modules from modules.txt. 1190 readVendorList() 1191 return append([]module.Version(nil), vendorList...), nil 1192 } 1193 1194 origPath := mod.Path 1195 if repl := Replacement(mod); repl.Path != "" { 1196 if repl.Version == "" { 1197 // TODO: need to slip the new version into the tags list etc. 1198 dir := repl.Path 1199 if !filepath.IsAbs(dir) { 1200 dir = filepath.Join(ModRoot(), dir) 1201 } 1202 gomod := filepath.Join(dir, "go.mod") 1203 data, err := ioutil.ReadFile(gomod) 1204 if err != nil { 1205 return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err) 1206 } 1207 f, err := modfile.ParseLax(gomod, data, nil) 1208 if err != nil { 1209 return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err) 1210 } 1211 if f.Go != nil { 1212 r.versions.LoadOrStore(mod, f.Go.Version) 1213 } 1214 return r.modFileToList(f), nil 1215 } 1216 mod = repl 1217 } 1218 1219 if mod.Version == "none" { 1220 return nil, nil 1221 } 1222 1223 if !semver.IsValid(mod.Version) { 1224 // Disallow the broader queries supported by fetch.Lookup. 1225 base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", mod.Path, mod.Version) 1226 } 1227 1228 data, err := modfetch.GoMod(mod.Path, mod.Version) 1229 if err != nil { 1230 return nil, err 1231 } 1232 f, err := modfile.ParseLax("go.mod", data, nil) 1233 if err != nil { 1234 return nil, module.VersionError(mod, fmt.Errorf("parsing go.mod: %v", err)) 1235 } 1236 1237 if f.Module == nil { 1238 return nil, module.VersionError(mod, errors.New("parsing go.mod: missing module line")) 1239 } 1240 if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path { 1241 return nil, module.VersionError(mod, fmt.Errorf(`parsing go.mod: 1242 module declares its path as: %s 1243 but was required as: %s`, mpath, mod.Path)) 1244 } 1245 if f.Go != nil { 1246 r.versions.LoadOrStore(mod, f.Go.Version) 1247 } 1248 1249 return r.modFileToList(f), nil 1250 } 1251 1252 func (*mvsReqs) Max(v1, v2 string) string { 1253 if v1 != "" && semver.Compare(v1, v2) == -1 { 1254 return v2 1255 } 1256 return v1 1257 } 1258 1259 // Upgrade is a no-op, here to implement mvs.Reqs. 1260 // The upgrade logic for go get -u is in ../modget/get.go. 1261 func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) { 1262 return m, nil 1263 } 1264 1265 func versions(path string) ([]string, error) { 1266 // Note: modfetch.Lookup and repo.Versions are cached, 1267 // so there's no need for us to add extra caching here. 1268 var versions []string 1269 err := modfetch.TryProxies(func(proxy string) error { 1270 repo, err := modfetch.Lookup(proxy, path) 1271 if err == nil { 1272 versions, err = repo.Versions("") 1273 } 1274 return err 1275 }) 1276 return versions, err 1277 } 1278 1279 // Previous returns the tagged version of m.Path immediately prior to 1280 // m.Version, or version "none" if no prior version is tagged. 1281 func (*mvsReqs) Previous(m module.Version) (module.Version, error) { 1282 list, err := versions(m.Path) 1283 if err != nil { 1284 return module.Version{}, err 1285 } 1286 i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 }) 1287 if i > 0 { 1288 return module.Version{Path: m.Path, Version: list[i-1]}, nil 1289 } 1290 return module.Version{Path: m.Path, Version: "none"}, nil 1291 } 1292 1293 // next returns the next version of m.Path after m.Version. 1294 // It is only used by the exclusion processing in the Required method, 1295 // not called directly by MVS. 1296 func (*mvsReqs) next(m module.Version) (module.Version, error) { 1297 list, err := versions(m.Path) 1298 if err != nil { 1299 return module.Version{}, err 1300 } 1301 i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 }) 1302 if i < len(list) { 1303 return module.Version{Path: m.Path, Version: list[i]}, nil 1304 } 1305 return module.Version{Path: m.Path, Version: "none"}, nil 1306 } 1307 1308 // fetch downloads the given module (or its replacement) 1309 // and returns its location. 1310 // 1311 // The isLocal return value reports whether the replacement, 1312 // if any, is local to the filesystem. 1313 func fetch(mod module.Version) (dir string, isLocal bool, err error) { 1314 if mod == Target { 1315 return ModRoot(), true, nil 1316 } 1317 if r := Replacement(mod); r.Path != "" { 1318 if r.Version == "" { 1319 dir = r.Path 1320 if !filepath.IsAbs(dir) { 1321 dir = filepath.Join(ModRoot(), dir) 1322 } 1323 // Ensure that the replacement directory actually exists: 1324 // dirInModule does not report errors for missing modules, 1325 // so if we don't report the error now, later failures will be 1326 // very mysterious. 1327 if _, err := os.Stat(dir); err != nil { 1328 if os.IsNotExist(err) { 1329 // Semantically the module version itself “exists” — we just don't 1330 // have its source code. Remove the equivalence to os.ErrNotExist, 1331 // and make the message more concise while we're at it. 1332 err = fmt.Errorf("replacement directory %s does not exist", r.Path) 1333 } else { 1334 err = fmt.Errorf("replacement directory %s: %w", r.Path, err) 1335 } 1336 return dir, true, module.VersionError(mod, err) 1337 } 1338 return dir, true, nil 1339 } 1340 mod = r 1341 } 1342 1343 dir, err = modfetch.Download(mod) 1344 return dir, false, err 1345 }