github.com/bir3/gocompiler@v0.3.205/src/cmd/gocmd/internal/modload/init.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 "context" 10 "encoding/json" 11 "errors" 12 "fmt" 13 "github.com/bir3/gocompiler/src/go/build" 14 "github.com/bir3/gocompiler/src/internal/lazyregexp" 15 "os" 16 "path" 17 "path/filepath" 18 "strconv" 19 "strings" 20 "sync" 21 22 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/base" 23 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/cfg" 24 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/fsys" 25 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/lockedfile" 26 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/modconv" 27 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/modfetch" 28 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/search" 29 30 "github.com/bir3/gocompiler/src/xvendor/golang.org/x/mod/modfile" 31 "github.com/bir3/gocompiler/src/xvendor/golang.org/x/mod/module" 32 "github.com/bir3/gocompiler/src/xvendor/golang.org/x/mod/semver" 33 ) 34 35 // Variables set by other packages. 36 // 37 // TODO(#40775): See if these can be plumbed as explicit parameters. 38 var ( 39 // RootMode determines whether a module root is needed. 40 RootMode Root 41 42 // ForceUseModules may be set to force modules to be enabled when 43 // GO111MODULE=auto or to report an error when GO111MODULE=off. 44 ForceUseModules bool 45 46 allowMissingModuleImports bool 47 48 // ExplicitWriteGoMod prevents LoadPackages, ListModules, and other functions 49 // from updating go.mod and go.sum or reporting errors when updates are 50 // needed. A package should set this if it would cause go.mod to be written 51 // multiple times (for example, 'go get' calls LoadPackages multiple times) or 52 // if it needs some other operation to be successful before go.mod and go.sum 53 // can be written (for example, 'go mod download' must download modules before 54 // adding sums to go.sum). Packages that set this are responsible for calling 55 // WriteGoMod explicitly. 56 ExplicitWriteGoMod bool 57 ) 58 59 // Variables set in Init. 60 var ( 61 initialized bool 62 63 // These are primarily used to initialize the MainModules, and should be 64 // eventually superceded by them but are still used in cases where the module 65 // roots are required but MainModules hasn't been initialized yet. Set to 66 // the modRoots of the main modules. 67 // modRoots != nil implies len(modRoots) > 0 68 modRoots []string 69 gopath string 70 ) 71 72 // EnterModule resets MainModules and requirements to refer to just this one module. 73 func EnterModule(ctx context.Context, enterModroot string) { 74 MainModules = nil // reset MainModules 75 requirements = nil 76 workFilePath = "" // Force module mode 77 modfetch.Reset() 78 79 modRoots = []string{enterModroot} 80 LoadModFile(ctx) 81 } 82 83 // Variable set in InitWorkfile 84 var ( 85 // Set to the path to the go.work file, or "" if workspace mode is disabled. 86 workFilePath string 87 ) 88 89 type MainModuleSet struct { 90 // versions are the module.Version values of each of the main modules. 91 // For each of them, the Path fields are ordinary module paths and the Version 92 // fields are empty strings. 93 versions []module.Version 94 95 // modRoot maps each module in versions to its absolute filesystem path. 96 modRoot map[module.Version]string 97 98 // pathPrefix is the path prefix for packages in the module, without a trailing 99 // slash. For most modules, pathPrefix is just version.Path, but the 100 // standard-library module "std" has an empty prefix. 101 pathPrefix map[module.Version]string 102 103 // inGorootSrc caches whether modRoot is within GOROOT/src. 104 // The "std" module is special within GOROOT/src, but not otherwise. 105 inGorootSrc map[module.Version]bool 106 107 modFiles map[module.Version]*modfile.File 108 109 modContainingCWD module.Version 110 111 workFileGoVersion string 112 113 workFileReplaceMap map[module.Version]module.Version 114 // highest replaced version of each module path; empty string for wildcard-only replacements 115 highestReplaced map[string]string 116 117 indexMu sync.Mutex 118 indices map[module.Version]*modFileIndex 119 } 120 121 func (mms *MainModuleSet) PathPrefix(m module.Version) string { 122 return mms.pathPrefix[m] 123 } 124 125 // Versions returns the module.Version values of each of the main modules. 126 // For each of them, the Path fields are ordinary module paths and the Version 127 // fields are empty strings. 128 // Callers should not modify the returned slice. 129 func (mms *MainModuleSet) Versions() []module.Version { 130 if mms == nil { 131 return nil 132 } 133 return mms.versions 134 } 135 136 func (mms *MainModuleSet) Contains(path string) bool { 137 if mms == nil { 138 return false 139 } 140 for _, v := range mms.versions { 141 if v.Path == path { 142 return true 143 } 144 } 145 return false 146 } 147 148 func (mms *MainModuleSet) ModRoot(m module.Version) string { 149 if mms == nil { 150 return "" 151 } 152 return mms.modRoot[m] 153 } 154 155 func (mms *MainModuleSet) InGorootSrc(m module.Version) bool { 156 if mms == nil { 157 return false 158 } 159 return mms.inGorootSrc[m] 160 } 161 162 func (mms *MainModuleSet) mustGetSingleMainModule() module.Version { 163 if mms == nil || len(mms.versions) == 0 { 164 panic("internal error: mustGetSingleMainModule called in context with no main modules") 165 } 166 if len(mms.versions) != 1 { 167 if inWorkspaceMode() { 168 panic("internal error: mustGetSingleMainModule called in workspace mode") 169 } else { 170 panic("internal error: multiple main modules present outside of workspace mode") 171 } 172 } 173 return mms.versions[0] 174 } 175 176 func (mms *MainModuleSet) GetSingleIndexOrNil() *modFileIndex { 177 if mms == nil { 178 return nil 179 } 180 if len(mms.versions) == 0 { 181 return nil 182 } 183 return mms.indices[mms.mustGetSingleMainModule()] 184 } 185 186 func (mms *MainModuleSet) Index(m module.Version) *modFileIndex { 187 mms.indexMu.Lock() 188 defer mms.indexMu.Unlock() 189 return mms.indices[m] 190 } 191 192 func (mms *MainModuleSet) SetIndex(m module.Version, index *modFileIndex) { 193 mms.indexMu.Lock() 194 defer mms.indexMu.Unlock() 195 mms.indices[m] = index 196 } 197 198 func (mms *MainModuleSet) ModFile(m module.Version) *modfile.File { 199 return mms.modFiles[m] 200 } 201 202 func (mms *MainModuleSet) Len() int { 203 if mms == nil { 204 return 0 205 } 206 return len(mms.versions) 207 } 208 209 // ModContainingCWD returns the main module containing the working directory, 210 // or module.Version{} if none of the main modules contain the working 211 // directory. 212 func (mms *MainModuleSet) ModContainingCWD() module.Version { 213 return mms.modContainingCWD 214 } 215 216 func (mms *MainModuleSet) HighestReplaced() map[string]string { 217 return mms.highestReplaced 218 } 219 220 // GoVersion returns the go version set on the single module, in module mode, 221 // or the go.work file in workspace mode. 222 func (mms *MainModuleSet) GoVersion() string { 223 if !inWorkspaceMode() { 224 return modFileGoVersion(mms.ModFile(mms.mustGetSingleMainModule())) 225 } 226 v := mms.workFileGoVersion 227 if v == "" { 228 // Fall back to 1.18 for go.work files. 229 v = "1.18" 230 } 231 return v 232 } 233 234 func (mms *MainModuleSet) WorkFileReplaceMap() map[module.Version]module.Version { 235 return mms.workFileReplaceMap 236 } 237 238 var MainModules *MainModuleSet 239 240 type Root int 241 242 const ( 243 // AutoRoot is the default for most commands. modload.Init will look for 244 // a go.mod file in the current directory or any parent. If none is found, 245 // modules may be disabled (GO111MODULE=auto) or commands may run in a 246 // limited module mode. 247 AutoRoot Root = iota 248 249 // NoRoot is used for commands that run in module mode and ignore any go.mod 250 // file the current directory or in parent directories. 251 NoRoot 252 253 // NeedRoot is used for commands that must run in module mode and don't 254 // make sense without a main module. 255 NeedRoot 256 ) 257 258 // ModFile returns the parsed go.mod file. 259 // 260 // Note that after calling LoadPackages or LoadModGraph, 261 // the require statements in the modfile.File are no longer 262 // the source of truth and will be ignored: edits made directly 263 // will be lost at the next call to WriteGoMod. 264 // To make permanent changes to the require statements 265 // in go.mod, edit it before loading. 266 func ModFile() *modfile.File { 267 Init() 268 modFile := MainModules.ModFile(MainModules.mustGetSingleMainModule()) 269 if modFile == nil { 270 die() 271 } 272 return modFile 273 } 274 275 func BinDir() string { 276 Init() 277 if cfg.GOBIN != "" { 278 return cfg.GOBIN 279 } 280 if gopath == "" { 281 return "" 282 } 283 return filepath.Join(gopath, "bin") 284 } 285 286 // InitWorkfile initializes the workFilePath variable for commands that 287 // operate in workspace mode. It should not be called by other commands, 288 // for example 'go mod tidy', that don't operate in workspace mode. 289 func InitWorkfile() { 290 if RootMode == NoRoot { 291 workFilePath = "" 292 return 293 } 294 295 switch gowork := cfg.Getenv("GOWORK"); gowork { 296 case "off": 297 workFilePath = "" 298 case "", "auto": 299 workFilePath = findWorkspaceFile(base.Cwd()) 300 default: 301 if !filepath.IsAbs(gowork) { 302 base.Fatalf("the path provided to GOWORK must be an absolute path") 303 } 304 workFilePath = gowork 305 } 306 } 307 308 // WorkFilePath returns the absolute path of the go.work file, or "" if not in 309 // workspace mode. WorkFilePath must be called after InitWorkfile. 310 func WorkFilePath() string { 311 return workFilePath 312 } 313 314 // Init determines whether module mode is enabled, locates the root of the 315 // current module (if any), sets environment variables for Git subprocesses, and 316 // configures the cfg, codehost, load, modfetch, and search packages for use 317 // with modules. 318 func Init() { 319 if initialized { 320 return 321 } 322 initialized = true 323 324 // Keep in sync with WillBeEnabled. We perform extra validation here, and 325 // there are lots of diagnostics and side effects, so we can't use 326 // WillBeEnabled directly. 327 var mustUseModules bool 328 env := cfg.Getenv("GO111MODULE") 329 switch env { 330 default: 331 base.Fatalf("go: unknown environment setting GO111MODULE=%s", env) 332 case "auto": 333 mustUseModules = ForceUseModules 334 case "on", "": 335 mustUseModules = true 336 case "off": 337 if ForceUseModules { 338 base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'") 339 } 340 mustUseModules = false 341 return 342 } 343 344 if err := fsys.Init(base.Cwd()); err != nil { 345 base.Fatalf("go: %v", err) 346 } 347 348 // Disable any prompting for passwords by Git. 349 // Only has an effect for 2.3.0 or later, but avoiding 350 // the prompt in earlier versions is just too hard. 351 // If user has explicitly set GIT_TERMINAL_PROMPT=1, keep 352 // prompting. 353 // See golang.org/issue/9341 and golang.org/issue/12706. 354 if os.Getenv("GIT_TERMINAL_PROMPT") == "" { 355 os.Setenv("GIT_TERMINAL_PROMPT", "0") 356 } 357 358 // Disable any ssh connection pooling by Git. 359 // If a Git subprocess forks a child into the background to cache a new connection, 360 // that child keeps stdout/stderr open. After the Git subprocess exits, 361 // os /exec expects to be able to read from the stdout/stderr pipe 362 // until EOF to get all the data that the Git subprocess wrote before exiting. 363 // The EOF doesn't come until the child exits too, because the child 364 // is holding the write end of the pipe. 365 // This is unfortunate, but it has come up at least twice 366 // (see golang.org/issue/13453 and golang.org/issue/16104) 367 // and confuses users when it does. 368 // If the user has explicitly set GIT_SSH or GIT_SSH_COMMAND, 369 // assume they know what they are doing and don't step on it. 370 // But default to turning off ControlMaster. 371 if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" { 372 os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no -o BatchMode=yes") 373 } 374 375 if os.Getenv("GCM_INTERACTIVE") == "" { 376 os.Setenv("GCM_INTERACTIVE", "never") 377 } 378 if modRoots != nil { 379 // modRoot set before Init was called ("go mod init" does this). 380 // No need to search for go.mod. 381 } else if RootMode == NoRoot { 382 if cfg.ModFile != "" && !base.InGOFLAGS("-modfile") { 383 base.Fatalf("go: -modfile cannot be used with commands that ignore the current module") 384 } 385 modRoots = nil 386 } else if inWorkspaceMode() { 387 // We're in workspace mode. 388 } else { 389 if modRoot := findModuleRoot(base.Cwd()); modRoot == "" { 390 if cfg.ModFile != "" { 391 base.Fatalf("go: cannot find main module, but -modfile was set.\n\t-modfile cannot be used to set the module root directory.") 392 } 393 if RootMode == NeedRoot { 394 base.Fatalf("go: %v", ErrNoModRoot) 395 } 396 if !mustUseModules { 397 // GO111MODULE is 'auto', and we can't find a module root. 398 // Stay in GOPATH mode. 399 return 400 } 401 } else if search.InDir(modRoot, os.TempDir()) == "." { 402 // If you create /tmp/go.mod for experimenting, 403 // then any tests that create work directories under /tmp 404 // will find it and get modules when they're not expecting them. 405 // It's a bit of a peculiar thing to disallow but quite mysterious 406 // when it happens. See golang.org/issue/26708. 407 fmt.Fprintf(os.Stderr, "go: warning: ignoring go.mod in system temp root %v\n", os.TempDir()) 408 if !mustUseModules { 409 return 410 } 411 } else { 412 modRoots = []string{modRoot} 413 } 414 } 415 if cfg.ModFile != "" && !strings.HasSuffix(cfg.ModFile, ".mod") { 416 base.Fatalf("go: -modfile=%s: file does not have .mod extension", cfg.ModFile) 417 } 418 419 // We're in module mode. Set any global variables that need to be set. 420 cfg.ModulesEnabled = true 421 setDefaultBuildMod() 422 list := filepath.SplitList(cfg.BuildContext.GOPATH) 423 if len(list) > 0 && list[0] != "" { 424 gopath = list[0] 425 if _, err := fsys.Stat(filepath.Join(gopath, "go.mod")); err == nil { 426 base.Fatalf("$GOPATH/go.mod exists but should not") 427 } 428 } 429 } 430 431 // WillBeEnabled checks whether modules should be enabled but does not 432 // initialize modules by installing hooks. If Init has already been called, 433 // WillBeEnabled returns the same result as Enabled. 434 // 435 // This function is needed to break a cycle. The main package needs to know 436 // whether modules are enabled in order to install the module or GOPATH version 437 // of 'go get', but Init reads the -modfile flag in 'go get', so it shouldn't 438 // be called until the command is installed and flags are parsed. Instead of 439 // calling Init and Enabled, the main package can call this function. 440 func WillBeEnabled() bool { 441 if modRoots != nil || cfg.ModulesEnabled { 442 // Already enabled. 443 return true 444 } 445 if initialized { 446 // Initialized, not enabled. 447 return false 448 } 449 450 // Keep in sync with Init. Init does extra validation and prints warnings or 451 // exits, so it can't call this function directly. 452 env := cfg.Getenv("GO111MODULE") 453 switch env { 454 case "on", "": 455 return true 456 case "auto": 457 break 458 default: 459 return false 460 } 461 462 if modRoot := findModuleRoot(base.Cwd()); modRoot == "" { 463 // GO111MODULE is 'auto', and we can't find a module root. 464 // Stay in GOPATH mode. 465 return false 466 } else if search.InDir(modRoot, os.TempDir()) == "." { 467 // If you create /tmp/go.mod for experimenting, 468 // then any tests that create work directories under /tmp 469 // will find it and get modules when they're not expecting them. 470 // It's a bit of a peculiar thing to disallow but quite mysterious 471 // when it happens. See golang.org/issue/26708. 472 return false 473 } 474 return true 475 } 476 477 // Enabled reports whether modules are (or must be) enabled. 478 // If modules are enabled but there is no main module, Enabled returns true 479 // and then the first use of module information will call die 480 // (usually through MustModRoot). 481 func Enabled() bool { 482 Init() 483 return modRoots != nil || cfg.ModulesEnabled 484 } 485 486 func VendorDir() string { 487 return filepath.Join(MainModules.ModRoot(MainModules.mustGetSingleMainModule()), "vendor") 488 } 489 490 func inWorkspaceMode() bool { 491 if !initialized { 492 panic("inWorkspaceMode called before modload.Init called") 493 } 494 return workFilePath != "" 495 } 496 497 // HasModRoot reports whether a main module is present. 498 // HasModRoot may return false even if Enabled returns true: for example, 'get' 499 // does not require a main module. 500 func HasModRoot() bool { 501 Init() 502 return modRoots != nil 503 } 504 505 // MustHaveModRoot checks that a main module or main modules are present, 506 // and calls base.Fatalf if there are no main modules. 507 func MustHaveModRoot() { 508 Init() 509 if !HasModRoot() { 510 die() 511 } 512 } 513 514 // ModFilePath returns the path that would be used for the go.mod 515 // file, if in module mode. ModFilePath calls base.Fatalf if there is no main 516 // module, even if -modfile is set. 517 func ModFilePath() string { 518 MustHaveModRoot() 519 return modFilePath(findModuleRoot(base.Cwd())) 520 } 521 522 func modFilePath(modRoot string) string { 523 if cfg.ModFile != "" { 524 return cfg.ModFile 525 } 526 return filepath.Join(modRoot, "go.mod") 527 } 528 529 func die() { 530 if cfg.Getenv("GO111MODULE") == "off" { 531 base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'") 532 } 533 if inWorkspaceMode() { 534 base.Fatalf("go: no modules were found in the current workspace; see 'go help work'") 535 } 536 if dir, name := findAltConfig(base.Cwd()); dir != "" { 537 rel, err := filepath.Rel(base.Cwd(), dir) 538 if err != nil { 539 rel = dir 540 } 541 cdCmd := "" 542 if rel != "." { 543 cdCmd = fmt.Sprintf("cd %s && ", rel) 544 } 545 base.Fatalf("go: cannot find main module, but found %s in %s\n\tto create a module there, run:\n\t%sgo mod init", name, dir, cdCmd) 546 } 547 base.Fatalf("go: %v", ErrNoModRoot) 548 } 549 550 var ErrNoModRoot = errors.New("go.mod file not found in current directory or any parent directory; see 'go help modules'") 551 552 type goModDirtyError struct{} 553 554 func (goModDirtyError) Error() string { 555 if cfg.BuildModExplicit { 556 return fmt.Sprintf("updates to go.mod needed, disabled by -mod=%v; to update it:\n\tgo mod tidy", cfg.BuildMod) 557 } 558 if cfg.BuildModReason != "" { 559 return fmt.Sprintf("updates to go.mod needed, disabled by -mod=%s\n\t(%s)\n\tto update it:\n\tgo mod tidy", cfg.BuildMod, cfg.BuildModReason) 560 } 561 return "updates to go.mod needed; to update it:\n\tgo mod tidy" 562 } 563 564 var errGoModDirty error = goModDirtyError{} 565 566 func loadWorkFile(path string) (goVersion string, modRoots []string, replaces []*modfile.Replace, err error) { 567 workDir := filepath.Dir(path) 568 wf, err := ReadWorkFile(path) 569 if err != nil { 570 return "", nil, nil, err 571 } 572 if wf.Go != nil { 573 goVersion = wf.Go.Version 574 } 575 seen := map[string]bool{} 576 for _, d := range wf.Use { 577 modRoot := d.Path 578 if !filepath.IsAbs(modRoot) { 579 modRoot = filepath.Join(workDir, modRoot) 580 } 581 582 if seen[modRoot] { 583 return "", nil, nil, fmt.Errorf("path %s appears multiple times in workspace", modRoot) 584 } 585 seen[modRoot] = true 586 modRoots = append(modRoots, modRoot) 587 } 588 589 return goVersion, modRoots, wf.Replace, nil 590 } 591 592 // ReadWorkFile reads and parses the go.work file at the given path. 593 func ReadWorkFile(path string) (*modfile.WorkFile, error) { 594 workData, err := os.ReadFile(path) 595 if err != nil { 596 return nil, err 597 } 598 599 return modfile.ParseWork(path, workData, nil) 600 } 601 602 // WriteWorkFile cleans and writes out the go.work file to the given path. 603 func WriteWorkFile(path string, wf *modfile.WorkFile) error { 604 wf.SortBlocks() 605 wf.Cleanup() 606 out := modfile.Format(wf.Syntax) 607 608 return os.WriteFile(path, out, 0666) 609 } 610 611 // UpdateWorkFile updates comments on directory directives in the go.work 612 // file to include the associated module path. 613 func UpdateWorkFile(wf *modfile.WorkFile) { 614 missingModulePaths := map[string]string{} // module directory listed in file -> abspath modroot 615 616 for _, d := range wf.Use { 617 if d.Path == "" { 618 continue // d is marked for deletion. 619 } 620 modRoot := d.Path 621 if d.ModulePath == "" { 622 missingModulePaths[d.Path] = modRoot 623 } 624 } 625 626 // Clean up and annotate directories. 627 // TODO(matloob): update x/mod to actually add module paths. 628 for moddir, absmodroot := range missingModulePaths { 629 _, f, err := ReadModFile(filepath.Join(absmodroot, "go.mod"), nil) 630 if err != nil { 631 continue // Error will be reported if modules are loaded. 632 } 633 wf.AddUse(moddir, f.Module.Mod.Path) 634 } 635 } 636 637 // LoadModFile sets Target and, if there is a main module, parses the initial 638 // build list from its go.mod file. 639 // 640 // LoadModFile may make changes in memory, like adding a go directive and 641 // ensuring requirements are consistent. The caller is responsible for ensuring 642 // those changes are written to disk by calling LoadPackages or ListModules 643 // (unless ExplicitWriteGoMod is set) or by calling WriteGoMod directly. 644 // 645 // As a side-effect, LoadModFile may change cfg.BuildMod to "vendor" if 646 // -mod wasn't set explicitly and automatic vendoring should be enabled. 647 // 648 // If LoadModFile or CreateModFile has already been called, LoadModFile returns 649 // the existing in-memory requirements (rather than re-reading them from disk). 650 // 651 // LoadModFile checks the roots of the module graph for consistency with each 652 // other, but unlike LoadModGraph does not load the full module graph or check 653 // it for global consistency. Most callers outside of the modload package should 654 // use LoadModGraph instead. 655 func LoadModFile(ctx context.Context) *Requirements { 656 if requirements != nil { 657 return requirements 658 } 659 660 Init() 661 var ( 662 workFileGoVersion string 663 workFileReplaces []*modfile.Replace 664 ) 665 if inWorkspaceMode() { 666 var err error 667 workFileGoVersion, modRoots, workFileReplaces, err = loadWorkFile(workFilePath) 668 if err != nil { 669 base.Fatalf("reading go.work: %v", err) 670 } 671 for _, modRoot := range modRoots { 672 sumFile := strings.TrimSuffix(modFilePath(modRoot), ".mod") + ".sum" 673 modfetch.WorkspaceGoSumFiles = append(modfetch.WorkspaceGoSumFiles, sumFile) 674 } 675 modfetch.GoSumFile = workFilePath + ".sum" 676 } else if len(modRoots) == 0 { 677 // We're in module mode, but not inside a module. 678 // 679 // Commands like 'go build', 'go run', 'go list' have no go.mod file to 680 // read or write. They would need to find and download the latest versions 681 // of a potentially large number of modules with no way to save version 682 // information. We can succeed slowly (but not reproducibly), but that's 683 // not usually a good experience. 684 // 685 // Instead, we forbid resolving import paths to modules other than std and 686 // cmd. Users may still build packages specified with .go files on the 687 // command line, but they'll see an error if those files import anything 688 // outside std. 689 // 690 // This can be overridden by calling AllowMissingModuleImports. 691 // For example, 'go get' does this, since it is expected to resolve paths. 692 // 693 // See golang.org/issue/32027. 694 } else { 695 modfetch.GoSumFile = strings.TrimSuffix(modFilePath(modRoots[0]), ".mod") + ".sum" 696 } 697 if len(modRoots) == 0 { 698 // TODO(#49228): Instead of creating a fake module with an empty modroot, 699 // make MainModules.Len() == 0 mean that we're in module mode but not inside 700 // any module. 701 mainModule := module.Version{Path: "command-line-arguments"} 702 MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, "", nil) 703 goVersion := LatestGoVersion() 704 rawGoVersion.Store(mainModule, goVersion) 705 pruning := pruningForGoVersion(goVersion) 706 if inWorkspaceMode() { 707 pruning = workspace 708 } 709 requirements = newRequirements(pruning, nil, nil) 710 if cfg.BuildMod == "vendor" { 711 // For issue 56536: Some users may have GOFLAGS=-mod=vendor set. 712 // Make sure it behaves as though the fake module is vendored 713 // with no dependencies. 714 requirements.initVendor(nil) 715 } 716 return requirements 717 } 718 719 var modFiles []*modfile.File 720 var mainModules []module.Version 721 var indices []*modFileIndex 722 for _, modroot := range modRoots { 723 gomod := modFilePath(modroot) 724 var fixed bool 725 data, f, err := ReadModFile(gomod, fixVersion(ctx, &fixed)) 726 if err != nil { 727 if inWorkspaceMode() { 728 base.Fatalf("go: cannot load module listed in go.work file: %v", err) 729 } else { 730 base.Fatalf("go: %v", err) 731 } 732 } 733 734 modFiles = append(modFiles, f) 735 mainModule := f.Module.Mod 736 mainModules = append(mainModules, mainModule) 737 indices = append(indices, indexModFile(data, f, mainModule, fixed)) 738 739 if err := module.CheckImportPath(f.Module.Mod.Path); err != nil { 740 if pathErr, ok := err.(*module.InvalidPathError); ok { 741 pathErr.Kind = "module" 742 } 743 base.Fatalf("go: %v", err) 744 } 745 } 746 747 MainModules = makeMainModules(mainModules, modRoots, modFiles, indices, workFileGoVersion, workFileReplaces) 748 setDefaultBuildMod() // possibly enable automatic vendoring 749 rs := requirementsFromModFiles(ctx, modFiles) 750 751 if inWorkspaceMode() { 752 // We don't need to do anything for vendor or update the mod file so 753 // return early. 754 requirements = rs 755 return rs 756 } 757 758 mainModule := MainModules.mustGetSingleMainModule() 759 760 if cfg.BuildMod == "vendor" { 761 readVendorList(mainModule) 762 index := MainModules.Index(mainModule) 763 modFile := MainModules.ModFile(mainModule) 764 checkVendorConsistency(index, modFile) 765 rs.initVendor(vendorList) 766 } 767 768 if rs.hasRedundantRoot() { 769 // If any module path appears more than once in the roots, we know that the 770 // go.mod file needs to be updated even though we have not yet loaded any 771 // transitive dependencies. 772 var err error 773 rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false) 774 if err != nil { 775 base.Fatalf("go: %v", err) 776 } 777 } 778 779 if MainModules.Index(mainModule).goVersionV == "" && rs.pruning != workspace { 780 // TODO(#45551): Do something more principled instead of checking 781 // cfg.CmdName directly here. 782 if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" { 783 addGoStmt(MainModules.ModFile(mainModule), mainModule, LatestGoVersion()) 784 785 // We need to add a 'go' version to the go.mod file, but we must assume 786 // that its existing contents match something between Go 1.11 and 1.16. 787 // Go 1.11 through 1.16 do not support graph pruning, but the latest Go 788 // version uses a pruned module graph — so we need to convert the 789 // requirements to support pruning. 790 var err error 791 rs, err = convertPruning(ctx, rs, pruned) 792 if err != nil { 793 base.Fatalf("go: %v", err) 794 } 795 } else { 796 rawGoVersion.Store(mainModule, modFileGoVersion(MainModules.ModFile(mainModule))) 797 } 798 } 799 800 requirements = rs 801 return requirements 802 } 803 804 // CreateModFile initializes a new module by creating a go.mod file. 805 // 806 // If modPath is empty, CreateModFile will attempt to infer the path from the 807 // directory location within GOPATH. 808 // 809 // If a vendoring configuration file is present, CreateModFile will attempt to 810 // translate it to go.mod directives. The resulting build list may not be 811 // exactly the same as in the legacy configuration (for example, we can't get 812 // packages at multiple versions from the same module). 813 func CreateModFile(ctx context.Context, modPath string) { 814 modRoot := base.Cwd() 815 modRoots = []string{modRoot} 816 Init() 817 modFilePath := modFilePath(modRoot) 818 if _, err := fsys.Stat(modFilePath); err == nil { 819 base.Fatalf("go: %s already exists", modFilePath) 820 } 821 822 if modPath == "" { 823 var err error 824 modPath, err = findModulePath(modRoot) 825 if err != nil { 826 base.Fatalf("go: %v", err) 827 } 828 } else if err := module.CheckImportPath(modPath); err != nil { 829 if pathErr, ok := err.(*module.InvalidPathError); ok { 830 pathErr.Kind = "module" 831 // Same as build.IsLocalPath() 832 if pathErr.Path == "." || pathErr.Path == ".." || 833 strings.HasPrefix(pathErr.Path, "./") || strings.HasPrefix(pathErr.Path, "../") { 834 pathErr.Err = errors.New("is a local import path") 835 } 836 } 837 base.Fatalf("go: %v", err) 838 } else if _, _, ok := module.SplitPathVersion(modPath); !ok { 839 if strings.HasPrefix(modPath, "gopkg.in/") { 840 invalidMajorVersionMsg := fmt.Errorf("module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN:\n\tgo mod init %s", suggestGopkgIn(modPath)) 841 base.Fatalf(`go: invalid module path "%v": %v`, modPath, invalidMajorVersionMsg) 842 } 843 invalidMajorVersionMsg := fmt.Errorf("major version suffixes must be in the form of /vN and are only allowed for v2 or later:\n\tgo mod init %s", suggestModulePath(modPath)) 844 base.Fatalf(`go: invalid module path "%v": %v`, modPath, invalidMajorVersionMsg) 845 } 846 847 fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath) 848 modFile := new(modfile.File) 849 modFile.AddModuleStmt(modPath) 850 MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot}, []*modfile.File{modFile}, []*modFileIndex{nil}, "", nil) 851 addGoStmt(modFile, modFile.Module.Mod, LatestGoVersion()) // Add the go directive before converted module requirements. 852 853 convertedFrom, err := convertLegacyConfig(modFile, modRoot) 854 if convertedFrom != "" { 855 fmt.Fprintf(os.Stderr, "go: copying requirements from %s\n", base.ShortPath(convertedFrom)) 856 } 857 if err != nil { 858 base.Fatalf("go: %v", err) 859 } 860 861 rs := requirementsFromModFiles(ctx, []*modfile.File{modFile}) 862 rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false) 863 if err != nil { 864 base.Fatalf("go: %v", err) 865 } 866 requirements = rs 867 if err := commitRequirements(ctx); err != nil { 868 base.Fatalf("go: %v", err) 869 } 870 871 // Suggest running 'go mod tidy' unless the project is empty. Even if we 872 // imported all the correct requirements above, we're probably missing 873 // some sums, so the next build command in -mod=readonly will likely fail. 874 // 875 // We look for non-hidden .go files or subdirectories to determine whether 876 // this is an existing project. Walking the tree for packages would be more 877 // accurate, but could take much longer. 878 empty := true 879 files, _ := os.ReadDir(modRoot) 880 for _, f := range files { 881 name := f.Name() 882 if strings.HasPrefix(name, ".") || strings.HasPrefix(name, "_") { 883 continue 884 } 885 if strings.HasSuffix(name, ".go") || f.IsDir() { 886 empty = false 887 break 888 } 889 } 890 if !empty { 891 fmt.Fprintf(os.Stderr, "go: to add module requirements and sums:\n\tgo mod tidy\n") 892 } 893 } 894 895 // CreateWorkFile initializes a new workspace by creating a go.work file. 896 func CreateWorkFile(ctx context.Context, workFile string, modDirs []string) { 897 if _, err := fsys.Stat(workFile); err == nil { 898 base.Fatalf("go: %s already exists", workFile) 899 } 900 901 goV := LatestGoVersion() // Use current Go version by default 902 workF := new(modfile.WorkFile) 903 workF.Syntax = new(modfile.FileSyntax) 904 workF.AddGoStmt(goV) 905 906 for _, dir := range modDirs { 907 _, f, err := ReadModFile(filepath.Join(dir, "go.mod"), nil) 908 if err != nil { 909 if os.IsNotExist(err) { 910 base.Fatalf("go: creating workspace file: no go.mod file exists in directory %v", dir) 911 } 912 base.Fatalf("go: error parsing go.mod in directory %s: %v", dir, err) 913 } 914 workF.AddUse(ToDirectoryPath(dir), f.Module.Mod.Path) 915 } 916 917 UpdateWorkFile(workF) 918 WriteWorkFile(workFile, workF) 919 } 920 921 // fixVersion returns a modfile.VersionFixer implemented using the Query function. 922 // 923 // It resolves commit hashes and branch names to versions, 924 // canonicalizes versions that appeared in early vgo drafts, 925 // and does nothing for versions that already appear to be canonical. 926 // 927 // The VersionFixer sets 'fixed' if it ever returns a non-canonical version. 928 func fixVersion(ctx context.Context, fixed *bool) modfile.VersionFixer { 929 return func(path, vers string) (resolved string, err error) { 930 defer func() { 931 if err == nil && resolved != vers { 932 *fixed = true 933 } 934 }() 935 936 // Special case: remove the old -gopkgin- hack. 937 if strings.HasPrefix(path, "gopkg.in/") && strings.Contains(vers, "-gopkgin-") { 938 vers = vers[strings.Index(vers, "-gopkgin-")+len("-gopkgin-"):] 939 } 940 941 // fixVersion is called speculatively on every 942 // module, version pair from every go.mod file. 943 // Avoid the query if it looks OK. 944 _, pathMajor, ok := module.SplitPathVersion(path) 945 if !ok { 946 return "", &module.ModuleError{ 947 Path: path, 948 Err: &module.InvalidVersionError{ 949 Version: vers, 950 Err: fmt.Errorf("malformed module path %q", path), 951 }, 952 } 953 } 954 if vers != "" && module.CanonicalVersion(vers) == vers { 955 if err := module.CheckPathMajor(vers, pathMajor); err != nil { 956 return "", module.VersionError(module.Version{Path: path, Version: vers}, err) 957 } 958 return vers, nil 959 } 960 961 info, err := Query(ctx, path, vers, "", nil) 962 if err != nil { 963 return "", err 964 } 965 return info.Version, nil 966 } 967 } 968 969 // AllowMissingModuleImports allows import paths to be resolved to modules 970 // when there is no module root. Normally, this is forbidden because it's slow 971 // and there's no way to make the result reproducible, but some commands 972 // like 'go get' are expected to do this. 973 // 974 // This function affects the default cfg.BuildMod when outside of a module, 975 // so it can only be called prior to Init. 976 func AllowMissingModuleImports() { 977 if initialized { 978 panic("AllowMissingModuleImports after Init") 979 } 980 allowMissingModuleImports = true 981 } 982 983 // makeMainModules creates a MainModuleSet and associated variables according to 984 // the given main modules. 985 func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile.File, indices []*modFileIndex, workFileGoVersion string, workFileReplaces []*modfile.Replace) *MainModuleSet { 986 for _, m := range ms { 987 if m.Version != "" { 988 panic("mainModulesCalled with module.Version with non empty Version field: " + fmt.Sprintf("%#v", m)) 989 } 990 } 991 modRootContainingCWD := findModuleRoot(base.Cwd()) 992 mainModules := &MainModuleSet{ 993 versions: ms[:len(ms):len(ms)], 994 inGorootSrc: map[module.Version]bool{}, 995 pathPrefix: map[module.Version]string{}, 996 modRoot: map[module.Version]string{}, 997 modFiles: map[module.Version]*modfile.File{}, 998 indices: map[module.Version]*modFileIndex{}, 999 workFileGoVersion: workFileGoVersion, 1000 workFileReplaceMap: toReplaceMap(workFileReplaces), 1001 highestReplaced: map[string]string{}, 1002 } 1003 mainModulePaths := make(map[string]bool) 1004 for _, m := range ms { 1005 if mainModulePaths[m.Path] { 1006 base.Errorf("go: module %s appears multiple times in workspace", m.Path) 1007 } 1008 mainModulePaths[m.Path] = true 1009 } 1010 replacedByWorkFile := make(map[string]bool) 1011 replacements := make(map[module.Version]module.Version) 1012 for _, r := range workFileReplaces { 1013 if mainModulePaths[r.Old.Path] && r.Old.Version == "" { 1014 base.Errorf("go: workspace module %v is replaced at all versions in the go.work file. To fix, remove the replacement from the go.work file or specify the version at which to replace the module.", r.Old.Path) 1015 } 1016 replacedByWorkFile[r.Old.Path] = true 1017 v, ok := mainModules.highestReplaced[r.Old.Path] 1018 if !ok || semver.Compare(r.Old.Version, v) > 0 { 1019 mainModules.highestReplaced[r.Old.Path] = r.Old.Version 1020 } 1021 replacements[r.Old] = r.New 1022 } 1023 for i, m := range ms { 1024 mainModules.pathPrefix[m] = m.Path 1025 mainModules.modRoot[m] = rootDirs[i] 1026 mainModules.modFiles[m] = modFiles[i] 1027 mainModules.indices[m] = indices[i] 1028 1029 if mainModules.modRoot[m] == modRootContainingCWD { 1030 mainModules.modContainingCWD = m 1031 } 1032 1033 if rel := search.InDir(rootDirs[i], cfg.GOROOTsrc); rel != "" { 1034 mainModules.inGorootSrc[m] = true 1035 if m.Path == "std" { 1036 // The "std" module in GOROOT/src is the Go standard library. Unlike other 1037 // modules, the packages in the "std" module have no import-path prefix. 1038 // 1039 // Modules named "std" outside of GOROOT/src do not receive this special 1040 // treatment, so it is possible to run 'go test .' in other GOROOTs to 1041 // test individual packages using a combination of the modified package 1042 // and the ordinary standard library. 1043 // (See https://golang.org/issue/30756.) 1044 mainModules.pathPrefix[m] = "" 1045 } 1046 } 1047 1048 if modFiles[i] != nil { 1049 curModuleReplaces := make(map[module.Version]bool) 1050 for _, r := range modFiles[i].Replace { 1051 if replacedByWorkFile[r.Old.Path] { 1052 continue 1053 } 1054 var newV module.Version = r.New 1055 if WorkFilePath() != "" && newV.Version == "" && !filepath.IsAbs(newV.Path) { 1056 // Since we are in a workspace, we may be loading replacements from 1057 // multiple go.mod files. Relative paths in those replacement are 1058 // relative to the go.mod file, not the workspace, so the same string 1059 // may refer to two different paths and different strings may refer to 1060 // the same path. Convert them all to be absolute instead. 1061 // 1062 // (We could do this outside of a workspace too, but it would mean that 1063 // replacement paths in error strings needlessly differ from what's in 1064 // the go.mod file.) 1065 newV.Path = filepath.Join(rootDirs[i], newV.Path) 1066 } 1067 if prev, ok := replacements[r.Old]; ok && !curModuleReplaces[r.Old] && prev != newV { 1068 base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v\nuse \"go work edit -replace %v=[override]\" to resolve", r.Old, prev, newV, r.Old) 1069 } 1070 curModuleReplaces[r.Old] = true 1071 replacements[r.Old] = newV 1072 1073 v, ok := mainModules.highestReplaced[r.Old.Path] 1074 if !ok || semver.Compare(r.Old.Version, v) > 0 { 1075 mainModules.highestReplaced[r.Old.Path] = r.Old.Version 1076 } 1077 } 1078 } 1079 } 1080 return mainModules 1081 } 1082 1083 // requirementsFromModFiles returns the set of non-excluded requirements from 1084 // the global modFile. 1085 func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Requirements { 1086 var roots []module.Version 1087 direct := map[string]bool{} 1088 var pruning modPruning 1089 if inWorkspaceMode() { 1090 pruning = workspace 1091 roots = make([]module.Version, len(MainModules.Versions())) 1092 copy(roots, MainModules.Versions()) 1093 } else { 1094 pruning = pruningForGoVersion(MainModules.GoVersion()) 1095 if len(modFiles) != 1 { 1096 panic(fmt.Errorf("requirementsFromModFiles called with %v modfiles outside workspace mode", len(modFiles))) 1097 } 1098 modFile := modFiles[0] 1099 roots = make([]module.Version, 0, len(modFile.Require)) 1100 mm := MainModules.mustGetSingleMainModule() 1101 for _, r := range modFile.Require { 1102 if index := MainModules.Index(mm); index != nil && index.exclude[r.Mod] { 1103 if cfg.BuildMod == "mod" { 1104 fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) 1105 } else { 1106 fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) 1107 } 1108 continue 1109 } 1110 1111 roots = append(roots, r.Mod) 1112 if !r.Indirect { 1113 direct[r.Mod.Path] = true 1114 } 1115 } 1116 } 1117 module.Sort(roots) 1118 rs := newRequirements(pruning, roots, direct) 1119 return rs 1120 } 1121 1122 // setDefaultBuildMod sets a default value for cfg.BuildMod if the -mod flag 1123 // wasn't provided. setDefaultBuildMod may be called multiple times. 1124 func setDefaultBuildMod() { 1125 if cfg.BuildModExplicit { 1126 if inWorkspaceMode() && cfg.BuildMod != "readonly" { 1127 base.Fatalf("go: -mod may only be set to readonly when in workspace mode, but it is set to %q"+ 1128 "\n\tRemove the -mod flag to use the default readonly value,"+ 1129 "\n\tor set GOWORK=off to disable workspace mode.", cfg.BuildMod) 1130 } 1131 // Don't override an explicit '-mod=' argument. 1132 return 1133 } 1134 1135 // TODO(#40775): commands should pass in the module mode as an option 1136 // to modload functions instead of relying on an implicit setting 1137 // based on command name. 1138 switch cfg.CmdName { 1139 case "get", "mod download", "mod init", "mod tidy", "work sync": 1140 // These commands are intended to update go.mod and go.sum. 1141 cfg.BuildMod = "mod" 1142 return 1143 case "mod graph", "mod verify", "mod why": 1144 // These commands should not update go.mod or go.sum, but they should be 1145 // able to fetch modules not in go.sum and should not report errors if 1146 // go.mod is inconsistent. They're useful for debugging, and they need 1147 // to work in buggy situations. 1148 cfg.BuildMod = "mod" 1149 return 1150 case "mod vendor": 1151 cfg.BuildMod = "readonly" 1152 return 1153 } 1154 if modRoots == nil { 1155 if allowMissingModuleImports { 1156 cfg.BuildMod = "mod" 1157 } else { 1158 cfg.BuildMod = "readonly" 1159 } 1160 return 1161 } 1162 1163 if len(modRoots) == 1 && !inWorkspaceMode() { 1164 index := MainModules.GetSingleIndexOrNil() 1165 if fi, err := fsys.Stat(filepath.Join(modRoots[0], "vendor")); err == nil && fi.IsDir() { 1166 modGo := "unspecified" 1167 if index != nil && index.goVersionV != "" { 1168 if semver.Compare(index.goVersionV, "v1.14") >= 0 { 1169 // The Go version is at least 1.14, and a vendor directory exists. 1170 // Set -mod=vendor by default. 1171 cfg.BuildMod = "vendor" 1172 cfg.BuildModReason = "Go version in go.mod is at least 1.14 and vendor directory exists." 1173 return 1174 } else { 1175 modGo = index.goVersionV[1:] 1176 } 1177 } 1178 1179 // Since a vendor directory exists, we should record why we didn't use it. 1180 // This message won't normally be shown, but it may appear with import errors. 1181 cfg.BuildModReason = fmt.Sprintf("Go version in go.mod is %s, so vendor directory was not used.", modGo) 1182 } 1183 } 1184 1185 cfg.BuildMod = "readonly" 1186 } 1187 1188 func mustHaveCompleteRequirements() bool { 1189 return cfg.BuildMod != "mod" && !inWorkspaceMode() 1190 } 1191 1192 // convertLegacyConfig imports module requirements from a legacy vendoring 1193 // configuration file, if one is present. 1194 func convertLegacyConfig(modFile *modfile.File, modRoot string) (from string, err error) { 1195 noneSelected := func(path string) (version string) { return "none" } 1196 queryPackage := func(path, rev string) (module.Version, error) { 1197 pkgMods, modOnly, err := QueryPattern(context.Background(), path, rev, noneSelected, nil) 1198 if err != nil { 1199 return module.Version{}, err 1200 } 1201 if len(pkgMods) > 0 { 1202 return pkgMods[0].Mod, nil 1203 } 1204 return modOnly.Mod, nil 1205 } 1206 for _, name := range altConfigs { 1207 cfg := filepath.Join(modRoot, name) 1208 data, err := os.ReadFile(cfg) 1209 if err == nil { 1210 convert := modconv.Converters[name] 1211 if convert == nil { 1212 return "", nil 1213 } 1214 cfg = filepath.ToSlash(cfg) 1215 err := modconv.ConvertLegacyConfig(modFile, cfg, data, queryPackage) 1216 return name, err 1217 } 1218 } 1219 return "", nil 1220 } 1221 1222 // addGoStmt adds a go directive to the go.mod file if it does not already 1223 // include one. The 'go' version added, if any, is the latest version supported 1224 // by this toolchain. 1225 func addGoStmt(modFile *modfile.File, mod module.Version, v string) { 1226 if modFile.Go != nil && modFile.Go.Version != "" { 1227 return 1228 } 1229 if err := modFile.AddGoStmt(v); err != nil { 1230 base.Fatalf("go: internal error: %v", err) 1231 } 1232 rawGoVersion.Store(mod, v) 1233 } 1234 1235 // LatestGoVersion returns the latest version of the Go language supported by 1236 // this toolchain, like "1.17". 1237 func LatestGoVersion() string { 1238 tags := build.Default.ReleaseTags 1239 version := tags[len(tags)-1] 1240 if !strings.HasPrefix(version, "go") || !modfile.GoVersionRE.MatchString(version[2:]) { 1241 base.Fatalf("go: internal error: unrecognized default version %q", version) 1242 } 1243 return version[2:] 1244 } 1245 1246 // priorGoVersion returns the Go major release immediately preceding v, 1247 // or v itself if v is the first Go major release (1.0) or not a supported 1248 // Go version. 1249 func priorGoVersion(v string) string { 1250 vTag := "go" + v 1251 tags := build.Default.ReleaseTags 1252 for i, tag := range tags { 1253 if tag == vTag { 1254 if i == 0 { 1255 return v 1256 } 1257 1258 version := tags[i-1] 1259 if !strings.HasPrefix(version, "go") || !modfile.GoVersionRE.MatchString(version[2:]) { 1260 base.Fatalf("go: internal error: unrecognized version %q", version) 1261 } 1262 return version[2:] 1263 } 1264 } 1265 return v 1266 } 1267 1268 var altConfigs = []string{ 1269 "Gopkg.lock", 1270 1271 "GLOCKFILE", 1272 "Godeps/Godeps.json", 1273 "dependencies.tsv", 1274 "glide.lock", 1275 "vendor.conf", 1276 "vendor.yml", 1277 "vendor/manifest", 1278 "vendor/vendor.json", 1279 1280 ".git/config", 1281 } 1282 1283 func findModuleRoot(dir string) (roots string) { 1284 if dir == "" { 1285 panic("dir not set") 1286 } 1287 dir = filepath.Clean(dir) 1288 1289 // Look for enclosing go.mod. 1290 for { 1291 if fi, err := fsys.Stat(filepath.Join(dir, "go.mod")); err == nil && !fi.IsDir() { 1292 return dir 1293 } 1294 d := filepath.Dir(dir) 1295 if d == dir { 1296 break 1297 } 1298 dir = d 1299 } 1300 return "" 1301 } 1302 1303 func findWorkspaceFile(dir string) (root string) { 1304 if dir == "" { 1305 panic("dir not set") 1306 } 1307 dir = filepath.Clean(dir) 1308 1309 // Look for enclosing go.mod. 1310 for { 1311 f := filepath.Join(dir, "go.work") 1312 if fi, err := fsys.Stat(f); err == nil && !fi.IsDir() { 1313 return f 1314 } 1315 d := filepath.Dir(dir) 1316 if d == dir { 1317 break 1318 } 1319 if d == cfg.GOROOT { 1320 // As a special case, don't cross GOROOT to find a go.work file. 1321 // The standard library and commands built in go always use the vendored 1322 // dependencies, so avoid using a most likely irrelevant go.work file. 1323 return "" 1324 } 1325 dir = d 1326 } 1327 return "" 1328 } 1329 1330 func findAltConfig(dir string) (root, name string) { 1331 if dir == "" { 1332 panic("dir not set") 1333 } 1334 dir = filepath.Clean(dir) 1335 if rel := search.InDir(dir, cfg.BuildContext.GOROOT); rel != "" { 1336 // Don't suggest creating a module from $GOROOT/.git/config 1337 // or a config file found in any parent of $GOROOT (see #34191). 1338 return "", "" 1339 } 1340 for { 1341 for _, name := range altConfigs { 1342 if fi, err := fsys.Stat(filepath.Join(dir, name)); err == nil && !fi.IsDir() { 1343 return dir, name 1344 } 1345 } 1346 d := filepath.Dir(dir) 1347 if d == dir { 1348 break 1349 } 1350 dir = d 1351 } 1352 return "", "" 1353 } 1354 1355 func findModulePath(dir string) (string, error) { 1356 // TODO(bcmills): once we have located a plausible module path, we should 1357 // query version control (if available) to verify that it matches the major 1358 // version of the most recent tag. 1359 // See https://golang.org/issue/29433, https://golang.org/issue/27009, and 1360 // https://golang.org/issue/31549. 1361 1362 // Cast about for import comments, 1363 // first in top-level directory, then in subdirectories. 1364 list, _ := os.ReadDir(dir) 1365 for _, info := range list { 1366 if info.Type().IsRegular() && strings.HasSuffix(info.Name(), ".go") { 1367 if com := findImportComment(filepath.Join(dir, info.Name())); com != "" { 1368 return com, nil 1369 } 1370 } 1371 } 1372 for _, info1 := range list { 1373 if info1.IsDir() { 1374 files, _ := os.ReadDir(filepath.Join(dir, info1.Name())) 1375 for _, info2 := range files { 1376 if info2.Type().IsRegular() && strings.HasSuffix(info2.Name(), ".go") { 1377 if com := findImportComment(filepath.Join(dir, info1.Name(), info2.Name())); com != "" { 1378 return path.Dir(com), nil 1379 } 1380 } 1381 } 1382 } 1383 } 1384 1385 // Look for Godeps.json declaring import path. 1386 data, _ := os.ReadFile(filepath.Join(dir, "Godeps/Godeps.json")) 1387 var cfg1 struct{ ImportPath string } 1388 json.Unmarshal(data, &cfg1) 1389 if cfg1.ImportPath != "" { 1390 return cfg1.ImportPath, nil 1391 } 1392 1393 // Look for vendor.json declaring import path. 1394 data, _ = os.ReadFile(filepath.Join(dir, "vendor/vendor.json")) 1395 var cfg2 struct{ RootPath string } 1396 json.Unmarshal(data, &cfg2) 1397 if cfg2.RootPath != "" { 1398 return cfg2.RootPath, nil 1399 } 1400 1401 // Look for path in GOPATH. 1402 var badPathErr error 1403 for _, gpdir := range filepath.SplitList(cfg.BuildContext.GOPATH) { 1404 if gpdir == "" { 1405 continue 1406 } 1407 if rel := search.InDir(dir, filepath.Join(gpdir, "src")); rel != "" && rel != "." { 1408 path := filepath.ToSlash(rel) 1409 // gorelease will alert users publishing their modules to fix their paths. 1410 if err := module.CheckImportPath(path); err != nil { 1411 badPathErr = err 1412 break 1413 } 1414 return path, nil 1415 } 1416 } 1417 1418 reason := "outside GOPATH, module path must be specified" 1419 if badPathErr != nil { 1420 // return a different error message if the module was in GOPATH, but 1421 // the module path determined above would be an invalid path. 1422 reason = fmt.Sprintf("bad module path inferred from directory in GOPATH: %v", badPathErr) 1423 } 1424 msg := `cannot determine module path for source directory %s (%s) 1425 1426 Example usage: 1427 'go mod init example.com/m' to initialize a v0 or v1 module 1428 'go mod init example.com/m/v2' to initialize a v2 module 1429 1430 Run 'go help mod init' for more information. 1431 ` 1432 return "", fmt.Errorf(msg, dir, reason) 1433 } 1434 1435 var ( 1436 importCommentRE = lazyregexp.New(`(?m)^package[ \t]+[^ \t\r\n/]+[ \t]+//[ \t]+import[ \t]+(\"[^"]+\")[ \t]*\r?\n`) 1437 ) 1438 1439 func findImportComment(file string) string { 1440 data, err := os.ReadFile(file) 1441 if err != nil { 1442 return "" 1443 } 1444 m := importCommentRE.FindSubmatch(data) 1445 if m == nil { 1446 return "" 1447 } 1448 path, err := strconv.Unquote(string(m[1])) 1449 if err != nil { 1450 return "" 1451 } 1452 return path 1453 } 1454 1455 // WriteGoMod writes the current build list back to go.mod. 1456 func WriteGoMod(ctx context.Context) error { 1457 requirements = LoadModFile(ctx) 1458 return commitRequirements(ctx) 1459 } 1460 1461 // commitRequirements ensures go.mod and go.sum are up to date with the current 1462 // requirements. 1463 // 1464 // In "mod" mode, commitRequirements writes changes to go.mod and go.sum. 1465 // 1466 // In "readonly" and "vendor" modes, commitRequirements returns an error if 1467 // go.mod or go.sum are out of date in a semantically significant way. 1468 // 1469 // In workspace mode, commitRequirements only writes changes to go.work.sum. 1470 func commitRequirements(ctx context.Context) (err error) { 1471 if inWorkspaceMode() { 1472 // go.mod files aren't updated in workspace mode, but we still want to 1473 // update the go.work.sum file. 1474 return modfetch.WriteGoSum(keepSums(ctx, loaded, requirements, addBuildListZipSums), mustHaveCompleteRequirements()) 1475 } 1476 if MainModules.Len() != 1 || MainModules.ModRoot(MainModules.Versions()[0]) == "" { 1477 // We aren't in a module, so we don't have anywhere to write a go.mod file. 1478 return nil 1479 } 1480 mainModule := MainModules.mustGetSingleMainModule() 1481 modFile := MainModules.ModFile(mainModule) 1482 if modFile == nil { 1483 // command-line-arguments has no .mod file to write. 1484 return nil 1485 } 1486 modFilePath := modFilePath(MainModules.ModRoot(mainModule)) 1487 1488 var list []*modfile.Require 1489 for _, m := range requirements.rootModules { 1490 list = append(list, &modfile.Require{ 1491 Mod: m, 1492 Indirect: !requirements.direct[m.Path], 1493 }) 1494 } 1495 if modFile.Go == nil || modFile.Go.Version == "" { 1496 modFile.AddGoStmt(modFileGoVersion(modFile)) 1497 } 1498 if semver.Compare("v"+modFileGoVersion(modFile), separateIndirectVersionV) < 0 { 1499 modFile.SetRequire(list) 1500 } else { 1501 modFile.SetRequireSeparateIndirect(list) 1502 } 1503 modFile.Cleanup() 1504 1505 index := MainModules.GetSingleIndexOrNil() 1506 dirty := index.modFileIsDirty(modFile) 1507 if dirty && cfg.BuildMod != "mod" { 1508 // If we're about to fail due to -mod=readonly, 1509 // prefer to report a dirty go.mod over a dirty go.sum 1510 return errGoModDirty 1511 } 1512 1513 if !dirty && cfg.CmdName != "mod tidy" { 1514 // The go.mod file has the same semantic content that it had before 1515 // (but not necessarily the same exact bytes). 1516 // Don't write go.mod, but write go.sum in case we added or trimmed sums. 1517 // 'go mod init' shouldn't write go.sum, since it will be incomplete. 1518 if cfg.CmdName != "mod init" { 1519 if err := modfetch.WriteGoSum(keepSums(ctx, loaded, requirements, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil { 1520 return err 1521 } 1522 } 1523 return nil 1524 } 1525 if _, ok := fsys.OverlayPath(modFilePath); ok { 1526 if dirty { 1527 return errors.New("updates to go.mod needed, but go.mod is part of the overlay specified with -overlay") 1528 } 1529 return nil 1530 } 1531 1532 new, err := modFile.Format() 1533 if err != nil { 1534 return err 1535 } 1536 defer func() { 1537 // At this point we have determined to make the go.mod file on disk equal to new. 1538 MainModules.SetIndex(mainModule, indexModFile(new, modFile, mainModule, false)) 1539 1540 // Update go.sum after releasing the side lock and refreshing the index. 1541 // 'go mod init' shouldn't write go.sum, since it will be incomplete. 1542 if cfg.CmdName != "mod init" { 1543 if err == nil { 1544 err = modfetch.WriteGoSum(keepSums(ctx, loaded, requirements, addBuildListZipSums), mustHaveCompleteRequirements()) 1545 } 1546 } 1547 }() 1548 1549 // Make a best-effort attempt to acquire the side lock, only to exclude 1550 // previous versions of the 'go' command from making simultaneous edits. 1551 if unlock, err := modfetch.SideLock(); err == nil { 1552 defer unlock() 1553 } 1554 1555 errNoChange := errors.New("no update needed") 1556 1557 err = lockedfile.Transform(modFilePath, func(old []byte) ([]byte, error) { 1558 if bytes.Equal(old, new) { 1559 // The go.mod file is already equal to new, possibly as the result of some 1560 // other process. 1561 return nil, errNoChange 1562 } 1563 1564 if index != nil && !bytes.Equal(old, index.data) { 1565 // The contents of the go.mod file have changed. In theory we could add all 1566 // of the new modules to the build list, recompute, and check whether any 1567 // module in *our* build list got bumped to a different version, but that's 1568 // a lot of work for marginal benefit. Instead, fail the command: if users 1569 // want to run concurrent commands, they need to start with a complete, 1570 // consistent module definition. 1571 return nil, fmt.Errorf("existing contents have changed since last read") 1572 } 1573 1574 return new, nil 1575 }) 1576 1577 if err != nil && err != errNoChange { 1578 return fmt.Errorf("updating go.mod: %w", err) 1579 } 1580 return nil 1581 } 1582 1583 // keepSums returns the set of modules (and go.mod file entries) for which 1584 // checksums would be needed in order to reload the same set of packages 1585 // loaded by the most recent call to LoadPackages or ImportFromFiles, 1586 // including any go.mod files needed to reconstruct the MVS result 1587 // or identify go versions, 1588 // in addition to the checksums for every module in keepMods. 1589 func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums) map[module.Version]bool { 1590 // Every module in the full module graph contributes its requirements, 1591 // so in order to ensure that the build list itself is reproducible, 1592 // we need sums for every go.mod in the graph (regardless of whether 1593 // that version is selected). 1594 keep := make(map[module.Version]bool) 1595 1596 // Add entries for modules in the build list with paths that are prefixes of 1597 // paths of loaded packages. We need to retain sums for all of these modules — 1598 // not just the modules containing the actual packages — in order to rule out 1599 // ambiguous import errors the next time we load the package. 1600 if ld != nil { 1601 for _, pkg := range ld.pkgs { 1602 // We check pkg.mod.Path here instead of pkg.inStd because the 1603 // pseudo-package "C" is not in std, but not provided by any module (and 1604 // shouldn't force loading the whole module graph). 1605 if pkg.testOf != nil || (pkg.mod.Path == "" && pkg.err == nil) || module.CheckImportPath(pkg.path) != nil { 1606 continue 1607 } 1608 1609 // We need the checksum for the go.mod file for pkg.mod 1610 // so that we know what Go version to use to compile pkg. 1611 // However, we didn't do so before Go 1.21, and the bug is relatively 1612 // minor, so we maintain the previous (buggy) behavior in 'go mod tidy' to 1613 // avoid introducing unnecessary churn. 1614 if !ld.Tidy || semver.Compare("v"+ld.GoVersion, tidyGoModSumVersionV) >= 0 { 1615 r := resolveReplacement(pkg.mod) 1616 keep[modkey(r)] = true 1617 } 1618 1619 if rs.pruning == pruned && pkg.mod.Path != "" { 1620 if v, ok := rs.rootSelected(pkg.mod.Path); ok && v == pkg.mod.Version { 1621 // pkg was loaded from a root module, and because the main module has 1622 // a pruned module graph we do not check non-root modules for 1623 // conflicts for packages that can be found in roots. So we only need 1624 // the checksums for the root modules that may contain pkg, not all 1625 // possible modules. 1626 for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { 1627 if v, ok := rs.rootSelected(prefix); ok && v != "none" { 1628 m := module.Version{Path: prefix, Version: v} 1629 r := resolveReplacement(m) 1630 keep[r] = true 1631 } 1632 } 1633 continue 1634 } 1635 } 1636 1637 mg, _ := rs.Graph(ctx) 1638 for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { 1639 if v := mg.Selected(prefix); v != "none" { 1640 m := module.Version{Path: prefix, Version: v} 1641 r := resolveReplacement(m) 1642 keep[r] = true 1643 } 1644 } 1645 } 1646 } 1647 1648 if rs.graph.Load() == nil { 1649 // We haven't needed to load the module graph so far. 1650 // Save sums for the root modules (or their replacements), but don't 1651 // incur the cost of loading the graph just to find and retain the sums. 1652 for _, m := range rs.rootModules { 1653 r := resolveReplacement(m) 1654 keep[modkey(r)] = true 1655 if which == addBuildListZipSums { 1656 keep[r] = true 1657 } 1658 } 1659 } else { 1660 mg, _ := rs.Graph(ctx) 1661 mg.WalkBreadthFirst(func(m module.Version) { 1662 if _, ok := mg.RequiredBy(m); ok { 1663 // The requirements from m's go.mod file are present in the module graph, 1664 // so they are relevant to the MVS result regardless of whether m was 1665 // actually selected. 1666 r := resolveReplacement(m) 1667 keep[modkey(r)] = true 1668 } 1669 }) 1670 1671 if which == addBuildListZipSums { 1672 for _, m := range mg.BuildList() { 1673 r := resolveReplacement(m) 1674 keep[modkey(r)] = true // we need the go version from the go.mod file to do anything useful with the zipfile 1675 keep[r] = true 1676 } 1677 } 1678 } 1679 1680 return keep 1681 } 1682 1683 type whichSums int8 1684 1685 const ( 1686 loadedZipSumsOnly = whichSums(iota) 1687 addBuildListZipSums 1688 ) 1689 1690 // modkey returns the module.Version under which the checksum for m's go.mod 1691 // file is stored in the go.sum file. 1692 func modkey(m module.Version) module.Version { 1693 return module.Version{Path: m.Path, Version: m.Version + "/go.mod"} 1694 } 1695 1696 func suggestModulePath(path string) string { 1697 var m string 1698 1699 i := len(path) 1700 for i > 0 && ('0' <= path[i-1] && path[i-1] <= '9' || path[i-1] == '.') { 1701 i-- 1702 } 1703 url := path[:i] 1704 url = strings.TrimSuffix(url, "/v") 1705 url = strings.TrimSuffix(url, "/") 1706 1707 f := func(c rune) bool { 1708 return c > '9' || c < '0' 1709 } 1710 s := strings.FieldsFunc(path[i:], f) 1711 if len(s) > 0 { 1712 m = s[0] 1713 } 1714 m = strings.TrimLeft(m, "0") 1715 if m == "" || m == "1" { 1716 return url + "/v2" 1717 } 1718 1719 return url + "/v" + m 1720 } 1721 1722 func suggestGopkgIn(path string) string { 1723 var m string 1724 i := len(path) 1725 for i > 0 && (('0' <= path[i-1] && path[i-1] <= '9') || (path[i-1] == '.')) { 1726 i-- 1727 } 1728 url := path[:i] 1729 url = strings.TrimSuffix(url, ".v") 1730 url = strings.TrimSuffix(url, "/v") 1731 url = strings.TrimSuffix(url, "/") 1732 1733 f := func(c rune) bool { 1734 return c > '9' || c < '0' 1735 } 1736 s := strings.FieldsFunc(path, f) 1737 if len(s) > 0 { 1738 m = s[0] 1739 } 1740 1741 m = strings.TrimLeft(m, "0") 1742 1743 if m == "" { 1744 return url + ".v1" 1745 } 1746 return url + ".v" + m 1747 }