github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-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 "encoding/json" 10 "errors" 11 "fmt" 12 "go/build" 13 "github.com/gagliardetto/golang-go/not-internal/lazyregexp" 14 "io/ioutil" 15 "os" 16 "path" 17 "path/filepath" 18 "runtime/debug" 19 "strconv" 20 "strings" 21 22 "github.com/gagliardetto/golang-go/cmd/go/not-internal/base" 23 "github.com/gagliardetto/golang-go/cmd/go/not-internal/cache" 24 "github.com/gagliardetto/golang-go/cmd/go/not-internal/cfg" 25 "github.com/gagliardetto/golang-go/cmd/go/not-internal/load" 26 "github.com/gagliardetto/golang-go/cmd/go/not-internal/lockedfile" 27 "github.com/gagliardetto/golang-go/cmd/go/not-internal/modconv" 28 "github.com/gagliardetto/golang-go/cmd/go/not-internal/modfetch" 29 "github.com/gagliardetto/golang-go/cmd/go/not-internal/modfetch/codehost" 30 "github.com/gagliardetto/golang-go/cmd/go/not-internal/mvs" 31 "github.com/gagliardetto/golang-go/cmd/go/not-internal/search" 32 33 "golang.org/x/mod/modfile" 34 "golang.org/x/mod/module" 35 "golang.org/x/mod/semver" 36 ) 37 38 var ( 39 mustUseModules = false 40 initialized bool 41 42 modRoot string 43 Target module.Version 44 45 // targetPrefix is the path prefix for packages in Target, without a trailing 46 // slash. For most modules, targetPrefix is just Target.Path, but the 47 // standard-library module "std" has an empty prefix. 48 targetPrefix string 49 50 // targetInGorootSrc caches whether modRoot is within GOROOT/src. 51 // The "std" module is special within GOROOT/src, but not otherwise. 52 targetInGorootSrc bool 53 54 gopath string 55 56 CmdModInit bool // running 'go mod init' 57 CmdModModule string // module argument for 'go mod init' 58 59 allowMissingModuleImports bool 60 ) 61 62 var modFile *modfile.File 63 64 // A modFileIndex is an index of data corresponding to a modFile 65 // at a specific point in time. 66 type modFileIndex struct { 67 data []byte 68 dataNeedsFix bool // true if fixVersion applied a change while parsing data 69 module module.Version 70 goVersion string 71 require map[module.Version]requireMeta 72 replace map[module.Version]module.Version 73 exclude map[module.Version]bool 74 } 75 76 // index is the index of the go.mod file as of when it was last read or written. 77 var index *modFileIndex 78 79 type requireMeta struct { 80 indirect bool 81 } 82 83 // ModFile returns the parsed go.mod file. 84 // 85 // Note that after calling ImportPaths or LoadBuildList, 86 // the require statements in the modfile.File are no longer 87 // the source of truth and will be ignored: edits made directly 88 // will be lost at the next call to WriteGoMod. 89 // To make permanent changes to the require statements 90 // in go.mod, edit it before calling ImportPaths or LoadBuildList. 91 func ModFile() *modfile.File { 92 Init() 93 if modFile == nil { 94 die() 95 } 96 return modFile 97 } 98 99 func BinDir() string { 100 Init() 101 return filepath.Join(gopath, "bin") 102 } 103 104 // Init determines whether module mode is enabled, locates the root of the 105 // current module (if any), sets environment variables for Git subprocesses, and 106 // configures the cfg, codehost, load, modfetch, and search packages for use 107 // with modules. 108 func Init() { 109 if initialized { 110 return 111 } 112 initialized = true 113 114 // Keep in sync with WillBeEnabled. We perform extra validation here, and 115 // there are lots of diagnostics and side effects, so we can't use 116 // WillBeEnabled directly. 117 env := cfg.Getenv("GO111MODULE") 118 switch env { 119 default: 120 base.Fatalf("go: unknown environment setting GO111MODULE=%s", env) 121 case "auto", "": 122 mustUseModules = false 123 case "on": 124 mustUseModules = true 125 case "off": 126 mustUseModules = false 127 return 128 } 129 130 // Disable any prompting for passwords by Git. 131 // Only has an effect for 2.3.0 or later, but avoiding 132 // the prompt in earlier versions is just too hard. 133 // If user has explicitly set GIT_TERMINAL_PROMPT=1, keep 134 // prompting. 135 // See golang.org/issue/9341 and golang.org/issue/12706. 136 if os.Getenv("GIT_TERMINAL_PROMPT") == "" { 137 os.Setenv("GIT_TERMINAL_PROMPT", "0") 138 } 139 140 // Disable any ssh connection pooling by Git. 141 // If a Git subprocess forks a child into the background to cache a new connection, 142 // that child keeps stdout/stderr open. After the Git subprocess exits, 143 // os /exec expects to be able to read from the stdout/stderr pipe 144 // until EOF to get all the data that the Git subprocess wrote before exiting. 145 // The EOF doesn't come until the child exits too, because the child 146 // is holding the write end of the pipe. 147 // This is unfortunate, but it has come up at least twice 148 // (see golang.org/issue/13453 and golang.org/issue/16104) 149 // and confuses users when it does. 150 // If the user has explicitly set GIT_SSH or GIT_SSH_COMMAND, 151 // assume they know what they are doing and don't step on it. 152 // But default to turning off ControlMaster. 153 if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" { 154 os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no") 155 } 156 157 if CmdModInit { 158 // Running 'go mod init': go.mod will be created in current directory. 159 modRoot = base.Cwd 160 } else { 161 modRoot = findModuleRoot(base.Cwd) 162 if modRoot == "" { 163 if cfg.ModFile != "" { 164 base.Fatalf("go: cannot find main module, but -modfile was set.\n\t-modfile cannot be used to set the module root directory.") 165 } 166 if !mustUseModules { 167 // GO111MODULE is 'auto', and we can't find a module root. 168 // Stay in GOPATH mode. 169 return 170 } 171 } else if search.InDir(modRoot, os.TempDir()) == "." { 172 // If you create /tmp/go.mod for experimenting, 173 // then any tests that create work directories under /tmp 174 // will find it and get modules when they're not expecting them. 175 // It's a bit of a peculiar thing to disallow but quite mysterious 176 // when it happens. See golang.org/issue/26708. 177 modRoot = "" 178 fmt.Fprintf(os.Stderr, "go: warning: ignoring go.mod in system temp root %v\n", os.TempDir()) 179 } 180 } 181 if cfg.ModFile != "" && !strings.HasSuffix(cfg.ModFile, ".mod") { 182 base.Fatalf("go: -modfile=%s: file does not have .mod extension", cfg.ModFile) 183 } 184 185 // We're in module mode. Install the hooks to make it work. 186 187 if c := cache.Default(); c == nil { 188 // With modules, there are no install locations for packages 189 // other than the build cache. 190 base.Fatalf("go: cannot use modules with build cache disabled") 191 } 192 193 list := filepath.SplitList(cfg.BuildContext.GOPATH) 194 if len(list) == 0 || list[0] == "" { 195 base.Fatalf("missing $GOPATH") 196 } 197 gopath = list[0] 198 if _, err := os.Stat(filepath.Join(gopath, "go.mod")); err == nil { 199 base.Fatalf("$GOPATH/go.mod exists but should not") 200 } 201 202 oldSrcMod := filepath.Join(list[0], "src/mod") 203 pkgMod := filepath.Join(list[0], "pkg/mod") 204 infoOld, errOld := os.Stat(oldSrcMod) 205 _, errMod := os.Stat(pkgMod) 206 if errOld == nil && infoOld.IsDir() && errMod != nil && os.IsNotExist(errMod) { 207 os.Rename(oldSrcMod, pkgMod) 208 } 209 210 modfetch.PkgMod = pkgMod 211 codehost.WorkRoot = filepath.Join(pkgMod, "cache/vcs") 212 213 cfg.ModulesEnabled = true 214 load.ModBinDir = BinDir 215 load.ModLookup = Lookup 216 load.ModPackageModuleInfo = PackageModuleInfo 217 load.ModImportPaths = ImportPaths 218 load.ModPackageBuildInfo = PackageBuildInfo 219 load.ModInfoProg = ModInfoProg 220 load.ModImportFromFiles = ImportFromFiles 221 load.ModDirImportPath = DirImportPath 222 223 if modRoot == "" { 224 // We're in module mode, but not inside a module. 225 // 226 // Commands like 'go build', 'go run', 'go list' have no go.mod file to 227 // read or write. They would need to find and download the latest versions 228 // of a potentially large number of modules with no way to save version 229 // information. We can succeed slowly (but not reproducibly), but that's 230 // not usually a good experience. 231 // 232 // Instead, we forbid resolving import paths to modules other than std and 233 // cmd. Users may still build packages specified with .go files on the 234 // command line, but they'll see an error if those files import anything 235 // outside std. 236 // 237 // This can be overridden by calling AllowMissingModuleImports. 238 // For example, 'go get' does this, since it is expected to resolve paths. 239 // 240 // See golang.org/issue/32027. 241 } else { 242 modfetch.GoSumFile = strings.TrimSuffix(ModFilePath(), ".mod") + ".sum" 243 search.SetModRoot(modRoot) 244 } 245 } 246 247 func init() { 248 load.ModInit = Init 249 250 // Set modfetch.PkgMod and codehost.WorkRoot unconditionally, 251 // so that go clean -modcache and go mod download can run even without modules enabled. 252 if list := filepath.SplitList(cfg.BuildContext.GOPATH); len(list) > 0 && list[0] != "" { 253 modfetch.PkgMod = filepath.Join(list[0], "pkg/mod") 254 codehost.WorkRoot = filepath.Join(list[0], "pkg/mod/cache/vcs") 255 } 256 } 257 258 // WillBeEnabled checks whether modules should be enabled but does not 259 // initialize modules by installing hooks. If Init has already been called, 260 // WillBeEnabled returns the same result as Enabled. 261 // 262 // This function is needed to break a cycle. The main package needs to know 263 // whether modules are enabled in order to install the module or GOPATH version 264 // of 'go get', but Init reads the -modfile flag in 'go get', so it shouldn't 265 // be called until the command is installed and flags are parsed. Instead of 266 // calling Init and Enabled, the main package can call this function. 267 func WillBeEnabled() bool { 268 if modRoot != "" || mustUseModules { 269 return true 270 } 271 if initialized { 272 return false 273 } 274 275 // Keep in sync with Init. Init does extra validation and prints warnings or 276 // exits, so it can't call this function directly. 277 env := cfg.Getenv("GO111MODULE") 278 switch env { 279 case "on": 280 return true 281 case "auto", "": 282 break 283 default: 284 return false 285 } 286 287 if CmdModInit { 288 // Running 'go mod init': go.mod will be created in current directory. 289 return true 290 } 291 if modRoot := findModuleRoot(base.Cwd); modRoot == "" { 292 // GO111MODULE is 'auto', and we can't find a module root. 293 // Stay in GOPATH mode. 294 return false 295 } else if search.InDir(modRoot, os.TempDir()) == "." { 296 // If you create /tmp/go.mod for experimenting, 297 // then any tests that create work directories under /tmp 298 // will find it and get modules when they're not expecting them. 299 // It's a bit of a peculiar thing to disallow but quite mysterious 300 // when it happens. See golang.org/issue/26708. 301 return false 302 } 303 return true 304 } 305 306 // Enabled reports whether modules are (or must be) enabled. 307 // If modules are enabled but there is no main module, Enabled returns true 308 // and then the first use of module information will call die 309 // (usually through MustModRoot). 310 func Enabled() bool { 311 Init() 312 return modRoot != "" || mustUseModules 313 } 314 315 // ModRoot returns the root of the main module. 316 // It calls base.Fatalf if there is no main module. 317 func ModRoot() string { 318 if !HasModRoot() { 319 die() 320 } 321 return modRoot 322 } 323 324 // HasModRoot reports whether a main module is present. 325 // HasModRoot may return false even if Enabled returns true: for example, 'get' 326 // does not require a main module. 327 func HasModRoot() bool { 328 Init() 329 return modRoot != "" 330 } 331 332 // ModFilePath returns the effective path of the go.mod file. Normally, this 333 // "go.mod" in the directory returned by ModRoot, but the -modfile flag may 334 // change its location. ModFilePath calls base.Fatalf if there is no main 335 // module, even if -modfile is set. 336 func ModFilePath() string { 337 if !HasModRoot() { 338 die() 339 } 340 if cfg.ModFile != "" { 341 return cfg.ModFile 342 } 343 return filepath.Join(modRoot, "go.mod") 344 } 345 346 // printStackInDie causes die to print a stack trace. 347 // 348 // It is enabled by the testgo tag, and helps to diagnose paths that 349 // unexpectedly require a main module. 350 var printStackInDie = false 351 352 func die() { 353 if printStackInDie { 354 debug.PrintStack() 355 } 356 if cfg.Getenv("GO111MODULE") == "off" { 357 base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'") 358 } 359 if dir, name := findAltConfig(base.Cwd); dir != "" { 360 rel, err := filepath.Rel(base.Cwd, dir) 361 if err != nil { 362 rel = dir 363 } 364 cdCmd := "" 365 if rel != "." { 366 cdCmd = fmt.Sprintf("cd %s && ", rel) 367 } 368 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) 369 } 370 base.Fatalf("go: cannot find main module; see 'go help modules'") 371 } 372 373 // InitMod sets Target and, if there is a main module, parses the initial build 374 // list from its go.mod file, creating and populating that file if needed. 375 // 376 // As a side-effect, InitMod sets a default for cfg.BuildMod if it does not 377 // already have an explicit value. 378 func InitMod() { 379 if len(buildList) > 0 { 380 return 381 } 382 383 Init() 384 if modRoot == "" { 385 Target = module.Version{Path: "command-line-arguments"} 386 targetPrefix = "command-line-arguments" 387 buildList = []module.Version{Target} 388 return 389 } 390 391 if CmdModInit { 392 // Running go mod init: do legacy module conversion 393 legacyModInit() 394 modFileToBuildList() 395 WriteGoMod() 396 return 397 } 398 399 gomod := ModFilePath() 400 data, err := lockedfile.Read(gomod) 401 if err != nil { 402 base.Fatalf("go: %v", err) 403 } 404 405 var fixed bool 406 f, err := modfile.Parse(gomod, data, fixVersion(&fixed)) 407 if err != nil { 408 // Errors returned by modfile.Parse begin with file:line. 409 base.Fatalf("go: errors parsing go.mod:\n%s\n", err) 410 } 411 modFile = f 412 index = indexModFile(data, f, fixed) 413 414 if len(f.Syntax.Stmt) == 0 || f.Module == nil { 415 // Empty mod file. Must add module path. 416 path, err := findModulePath(modRoot) 417 if err != nil { 418 base.Fatalf("go: %v", err) 419 } 420 f.AddModuleStmt(path) 421 } 422 423 if len(f.Syntax.Stmt) == 1 && f.Module != nil { 424 // Entire file is just a module statement. 425 // Populate require if possible. 426 legacyModInit() 427 } 428 429 modFileToBuildList() 430 setDefaultBuildMod() 431 if cfg.BuildMod == "vendor" { 432 readVendorList() 433 checkVendorConsistency() 434 } else { 435 // TODO(golang.org/issue/33326): if cfg.BuildMod != "readonly"? 436 WriteGoMod() 437 } 438 } 439 440 // fixVersion returns a modfile.VersionFixer implemented using the Query function. 441 // 442 // It resolves commit hashes and branch names to versions, 443 // canonicalizes versions that appeared in early vgo drafts, 444 // and does nothing for versions that already appear to be canonical. 445 // 446 // The VersionFixer sets 'fixed' if it ever returns a non-canonical version. 447 func fixVersion(fixed *bool) modfile.VersionFixer { 448 return func(path, vers string) (resolved string, err error) { 449 defer func() { 450 if err == nil && resolved != vers { 451 *fixed = true 452 } 453 }() 454 455 // Special case: remove the old -gopkgin- hack. 456 if strings.HasPrefix(path, "gopkg.in/") && strings.Contains(vers, "-gopkgin-") { 457 vers = vers[strings.Index(vers, "-gopkgin-")+len("-gopkgin-"):] 458 } 459 460 // fixVersion is called speculatively on every 461 // module, version pair from every go.mod file. 462 // Avoid the query if it looks OK. 463 _, pathMajor, ok := module.SplitPathVersion(path) 464 if !ok { 465 return "", &module.ModuleError{ 466 Path: path, 467 Err: &module.InvalidVersionError{ 468 Version: vers, 469 Err: fmt.Errorf("malformed module path %q", path), 470 }, 471 } 472 } 473 if vers != "" && module.CanonicalVersion(vers) == vers { 474 if err := module.CheckPathMajor(vers, pathMajor); err == nil { 475 return vers, nil 476 } 477 } 478 479 info, err := Query(path, vers, "", nil) 480 if err != nil { 481 return "", err 482 } 483 return info.Version, nil 484 } 485 } 486 487 // AllowMissingModuleImports allows import paths to be resolved to modules 488 // when there is no module root. Normally, this is forbidden because it's slow 489 // and there's no way to make the result reproducible, but some commands 490 // like 'go get' are expected to do this. 491 func AllowMissingModuleImports() { 492 allowMissingModuleImports = true 493 } 494 495 // modFileToBuildList initializes buildList from the modFile. 496 func modFileToBuildList() { 497 Target = modFile.Module.Mod 498 targetPrefix = Target.Path 499 if rel := search.InDir(base.Cwd, cfg.GOROOTsrc); rel != "" { 500 targetInGorootSrc = true 501 if Target.Path == "std" { 502 targetPrefix = "" 503 } 504 } 505 506 list := []module.Version{Target} 507 for _, r := range modFile.Require { 508 list = append(list, r.Mod) 509 } 510 buildList = list 511 } 512 513 // setDefaultBuildMod sets a default value for cfg.BuildMod 514 // if it is currently empty. 515 func setDefaultBuildMod() { 516 if cfg.BuildMod != "" { 517 // Don't override an explicit '-mod=' argument. 518 return 519 } 520 cfg.BuildMod = "mod" 521 if cfg.CmdName == "get" || strings.HasPrefix(cfg.CmdName, "mod ") { 522 // Don't set -mod implicitly for commands whose purpose is to 523 // manipulate the build list. 524 return 525 } 526 if modRoot == "" { 527 return 528 } 529 530 if fi, err := os.Stat(filepath.Join(modRoot, "vendor")); err == nil && fi.IsDir() { 531 modGo := "unspecified" 532 if index.goVersion != "" { 533 if semver.Compare("v"+index.goVersion, "v1.14") >= 0 { 534 // The Go version is at least 1.14, and a vendor directory exists. 535 // Set -mod=vendor by default. 536 cfg.BuildMod = "vendor" 537 cfg.BuildModReason = "Go version in go.mod is at least 1.14 and vendor directory exists." 538 return 539 } else { 540 modGo = index.goVersion 541 } 542 } 543 544 // Since a vendor directory exists, we have a non-trivial reason for 545 // choosing -mod=mod, although it probably won't be used for anything. 546 // Record the reason anyway for consistency. 547 // It may be overridden if we switch to mod=readonly below. 548 cfg.BuildModReason = fmt.Sprintf("Go version in go.mod is %s.", modGo) 549 } 550 551 p := ModFilePath() 552 if fi, err := os.Stat(p); err == nil && !hasWritePerm(p, fi) { 553 cfg.BuildMod = "readonly" 554 cfg.BuildModReason = "go.mod file is read-only." 555 } 556 } 557 558 // checkVendorConsistency verifies that the vendor/modules.txt file matches (if 559 // go 1.14) or at least does not contradict (go 1.13 or earlier) the 560 // requirements and replacements listed in the main module's go.mod file. 561 func checkVendorConsistency() { 562 readVendorList() 563 564 pre114 := false 565 if modFile.Go == nil || semver.Compare("v"+modFile.Go.Version, "v1.14") < 0 { 566 // Go versions before 1.14 did not include enough information in 567 // vendor/modules.txt to check for consistency. 568 // If we know that we're on an earlier version, relax the consistency check. 569 pre114 = true 570 } 571 572 vendErrors := new(strings.Builder) 573 vendErrorf := func(mod module.Version, format string, args ...interface{}) { 574 detail := fmt.Sprintf(format, args...) 575 if mod.Version == "" { 576 fmt.Fprintf(vendErrors, "\n\t%s: %s", mod.Path, detail) 577 } else { 578 fmt.Fprintf(vendErrors, "\n\t%s@%s: %s", mod.Path, mod.Version, detail) 579 } 580 } 581 582 for _, r := range modFile.Require { 583 if !vendorMeta[r.Mod].Explicit { 584 if pre114 { 585 // Before 1.14, modules.txt did not indicate whether modules were listed 586 // explicitly in the main module's go.mod file. 587 // However, we can at least detect a version mismatch if packages were 588 // vendored from a non-matching version. 589 if vv, ok := vendorVersion[r.Mod.Path]; ok && vv != r.Mod.Version { 590 vendErrorf(r.Mod, fmt.Sprintf("is explicitly required in go.mod, but vendor/modules.txt indicates %s@%s", r.Mod.Path, vv)) 591 } 592 } else { 593 vendErrorf(r.Mod, "is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt") 594 } 595 } 596 } 597 598 describe := func(m module.Version) string { 599 if m.Version == "" { 600 return m.Path 601 } 602 return m.Path + "@" + m.Version 603 } 604 605 // We need to verify *all* replacements that occur in modfile: even if they 606 // don't directly apply to any module in the vendor list, the replacement 607 // go.mod file can affect the selected versions of other (transitive) 608 // dependencies 609 for _, r := range modFile.Replace { 610 vr := vendorMeta[r.Old].Replacement 611 if vr == (module.Version{}) { 612 if pre114 && (r.Old.Version == "" || vendorVersion[r.Old.Path] != r.Old.Version) { 613 // Before 1.14, modules.txt omitted wildcard replacements and 614 // replacements for modules that did not have any packages to vendor. 615 } else { 616 vendErrorf(r.Old, "is replaced in go.mod, but not marked as replaced in vendor/modules.txt") 617 } 618 } else if vr != r.New { 619 vendErrorf(r.Old, "is replaced by %s in go.mod, but marked as replaced by %s in vendor/modules.txt", describe(r.New), describe(vr)) 620 } 621 } 622 623 for _, mod := range vendorList { 624 meta := vendorMeta[mod] 625 if meta.Explicit { 626 if _, inGoMod := index.require[mod]; !inGoMod { 627 vendErrorf(mod, "is marked as explicit in vendor/modules.txt, but not explicitly required in go.mod") 628 } 629 } 630 } 631 632 for _, mod := range vendorReplaced { 633 r := Replacement(mod) 634 if r == (module.Version{}) { 635 vendErrorf(mod, "is marked as replaced in vendor/modules.txt, but not replaced in go.mod") 636 continue 637 } 638 if meta := vendorMeta[mod]; r != meta.Replacement { 639 vendErrorf(mod, "is marked as replaced by %s in vendor/modules.txt, but replaced by %s in go.mod", describe(meta.Replacement), describe(r)) 640 } 641 } 642 643 if vendErrors.Len() > 0 { 644 base.Fatalf("go: inconsistent vendoring in %s:%s\n\nrun 'go mod vendor' to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory", modRoot, vendErrors) 645 } 646 } 647 648 // Allowed reports whether module m is allowed (not excluded) by the main module's go.mod. 649 func Allowed(m module.Version) bool { 650 return index == nil || !index.exclude[m] 651 } 652 653 func legacyModInit() { 654 if modFile == nil { 655 path, err := findModulePath(modRoot) 656 if err != nil { 657 base.Fatalf("go: %v", err) 658 } 659 fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", path) 660 modFile = new(modfile.File) 661 modFile.AddModuleStmt(path) 662 addGoStmt() // Add the go directive before converted module requirements. 663 } 664 665 for _, name := range altConfigs { 666 cfg := filepath.Join(modRoot, name) 667 data, err := ioutil.ReadFile(cfg) 668 if err == nil { 669 convert := modconv.Converters[name] 670 if convert == nil { 671 return 672 } 673 fmt.Fprintf(os.Stderr, "go: copying requirements from %s\n", base.ShortPath(cfg)) 674 cfg = filepath.ToSlash(cfg) 675 if err := modconv.ConvertLegacyConfig(modFile, cfg, data); err != nil { 676 base.Fatalf("go: %v", err) 677 } 678 if len(modFile.Syntax.Stmt) == 1 { 679 // Add comment to avoid re-converting every time it runs. 680 modFile.AddComment("// go: no requirements found in " + name) 681 } 682 return 683 } 684 } 685 } 686 687 // addGoStmt adds a go directive to the go.mod file if it does not already include one. 688 // The 'go' version added, if any, is the latest version supported by this toolchain. 689 func addGoStmt() { 690 if modFile.Go != nil && modFile.Go.Version != "" { 691 return 692 } 693 tags := build.Default.ReleaseTags 694 version := tags[len(tags)-1] 695 if !strings.HasPrefix(version, "go") || !modfile.GoVersionRE.MatchString(version[2:]) { 696 base.Fatalf("go: unrecognized default version %q", version) 697 } 698 if err := modFile.AddGoStmt(version[2:]); err != nil { 699 base.Fatalf("go: internal error: %v", err) 700 } 701 } 702 703 var altConfigs = []string{ 704 "Gopkg.lock", 705 706 "GLOCKFILE", 707 "Godeps/Godeps.json", 708 "dependencies.tsv", 709 "glide.lock", 710 "vendor.conf", 711 "vendor.yml", 712 "vendor/manifest", 713 "vendor/vendor.json", 714 715 ".git/config", 716 } 717 718 func findModuleRoot(dir string) (root string) { 719 if dir == "" { 720 panic("dir not set") 721 } 722 dir = filepath.Clean(dir) 723 724 // Look for enclosing go.mod. 725 for { 726 if fi, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil && !fi.IsDir() { 727 return dir 728 } 729 d := filepath.Dir(dir) 730 if d == dir { 731 break 732 } 733 dir = d 734 } 735 return "" 736 } 737 738 func findAltConfig(dir string) (root, name string) { 739 if dir == "" { 740 panic("dir not set") 741 } 742 dir = filepath.Clean(dir) 743 for { 744 for _, name := range altConfigs { 745 if fi, err := os.Stat(filepath.Join(dir, name)); err == nil && !fi.IsDir() { 746 if rel := search.InDir(dir, cfg.BuildContext.GOROOT); rel == "." { 747 // Don't suggest creating a module from $GOROOT/.git/config. 748 return "", "" 749 } 750 return dir, name 751 } 752 } 753 d := filepath.Dir(dir) 754 if d == dir { 755 break 756 } 757 dir = d 758 } 759 return "", "" 760 } 761 762 func findModulePath(dir string) (string, error) { 763 if CmdModModule != "" { 764 // Running go mod init x/y/z; return x/y/z. 765 if err := module.CheckImportPath(CmdModModule); err != nil { 766 return "", err 767 } 768 return CmdModModule, nil 769 } 770 771 // TODO(bcmills): once we have located a plausible module path, we should 772 // query version control (if available) to verify that it matches the major 773 // version of the most recent tag. 774 // See https://golang.org/issue/29433, https://golang.org/issue/27009, and 775 // https://golang.org/issue/31549. 776 777 // Cast about for import comments, 778 // first in top-level directory, then in subdirectories. 779 list, _ := ioutil.ReadDir(dir) 780 for _, info := range list { 781 if info.Mode().IsRegular() && strings.HasSuffix(info.Name(), ".go") { 782 if com := findImportComment(filepath.Join(dir, info.Name())); com != "" { 783 return com, nil 784 } 785 } 786 } 787 for _, info1 := range list { 788 if info1.IsDir() { 789 files, _ := ioutil.ReadDir(filepath.Join(dir, info1.Name())) 790 for _, info2 := range files { 791 if info2.Mode().IsRegular() && strings.HasSuffix(info2.Name(), ".go") { 792 if com := findImportComment(filepath.Join(dir, info1.Name(), info2.Name())); com != "" { 793 return path.Dir(com), nil 794 } 795 } 796 } 797 } 798 } 799 800 // Look for Godeps.json declaring import path. 801 data, _ := ioutil.ReadFile(filepath.Join(dir, "Godeps/Godeps.json")) 802 var cfg1 struct{ ImportPath string } 803 json.Unmarshal(data, &cfg1) 804 if cfg1.ImportPath != "" { 805 return cfg1.ImportPath, nil 806 } 807 808 // Look for vendor.json declaring import path. 809 data, _ = ioutil.ReadFile(filepath.Join(dir, "vendor/vendor.json")) 810 var cfg2 struct{ RootPath string } 811 json.Unmarshal(data, &cfg2) 812 if cfg2.RootPath != "" { 813 return cfg2.RootPath, nil 814 } 815 816 // Look for path in GOPATH. 817 for _, gpdir := range filepath.SplitList(cfg.BuildContext.GOPATH) { 818 if gpdir == "" { 819 continue 820 } 821 if rel := search.InDir(dir, filepath.Join(gpdir, "src")); rel != "" && rel != "." { 822 return filepath.ToSlash(rel), nil 823 } 824 } 825 826 msg := `cannot determine module path for source directory %s (outside GOPATH, module path must be specified) 827 828 Example usage: 829 'go mod init example.com/m' to initialize a v0 or v1 module 830 'go mod init example.com/m/v2' to initialize a v2 module 831 832 Run 'go help mod init' for more information. 833 ` 834 return "", fmt.Errorf(msg, dir) 835 } 836 837 var ( 838 importCommentRE = lazyregexp.New(`(?m)^package[ \t]+[^ \t\r\n/]+[ \t]+//[ \t]+import[ \t]+(\"[^"]+\")[ \t]*\r?\n`) 839 ) 840 841 func findImportComment(file string) string { 842 data, err := ioutil.ReadFile(file) 843 if err != nil { 844 return "" 845 } 846 m := importCommentRE.FindSubmatch(data) 847 if m == nil { 848 return "" 849 } 850 path, err := strconv.Unquote(string(m[1])) 851 if err != nil { 852 return "" 853 } 854 return path 855 } 856 857 var allowWriteGoMod = true 858 859 // DisallowWriteGoMod causes future calls to WriteGoMod to do nothing at all. 860 func DisallowWriteGoMod() { 861 allowWriteGoMod = false 862 } 863 864 // AllowWriteGoMod undoes the effect of DisallowWriteGoMod: 865 // future calls to WriteGoMod will update go.mod if needed. 866 // Note that any past calls have been discarded, so typically 867 // a call to AlowWriteGoMod should be followed by a call to WriteGoMod. 868 func AllowWriteGoMod() { 869 allowWriteGoMod = true 870 } 871 872 // MinReqs returns a Reqs with minimal additional dependencies of Target, 873 // as will be written to go.mod. 874 func MinReqs() mvs.Reqs { 875 var retain []string 876 for _, m := range buildList[1:] { 877 _, explicit := index.require[m] 878 if explicit || loaded.direct[m.Path] { 879 retain = append(retain, m.Path) 880 } 881 } 882 min, err := mvs.Req(Target, retain, Reqs()) 883 if err != nil { 884 base.Fatalf("go: %v", err) 885 } 886 return &mvsReqs{buildList: append([]module.Version{Target}, min...)} 887 } 888 889 // WriteGoMod writes the current build list back to go.mod. 890 func WriteGoMod() { 891 // If we're using -mod=vendor we basically ignored 892 // go.mod, so definitely don't try to write back our 893 // incomplete view of the world. 894 if !allowWriteGoMod || cfg.BuildMod == "vendor" { 895 return 896 } 897 898 // If we aren't in a module, we don't have anywhere to write a go.mod file. 899 if modRoot == "" { 900 return 901 } 902 903 if cfg.BuildMod != "readonly" { 904 addGoStmt() 905 } 906 907 if loaded != nil { 908 reqs := MinReqs() 909 min, err := reqs.Required(Target) 910 if err != nil { 911 base.Fatalf("go: %v", err) 912 } 913 var list []*modfile.Require 914 for _, m := range min { 915 list = append(list, &modfile.Require{ 916 Mod: m, 917 Indirect: !loaded.direct[m.Path], 918 }) 919 } 920 modFile.SetRequire(list) 921 } 922 modFile.Cleanup() 923 924 dirty := index.modFileIsDirty(modFile) 925 if dirty && cfg.BuildMod == "readonly" { 926 // If we're about to fail due to -mod=readonly, 927 // prefer to report a dirty go.mod over a dirty go.sum 928 if cfg.BuildModReason != "" { 929 base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly\n\t(%s)", cfg.BuildModReason) 930 } else { 931 base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly") 932 } 933 } 934 // Always update go.sum, even if we didn't change go.mod: we may have 935 // downloaded modules that we didn't have before. 936 modfetch.WriteGoSum() 937 938 if !dirty && cfg.CmdName != "mod tidy" { 939 // The go.mod file has the same semantic content that it had before 940 // (but not necessarily the same exact bytes). 941 // Ignore any intervening edits. 942 return 943 } 944 945 new, err := modFile.Format() 946 if err != nil { 947 base.Fatalf("go: %v", err) 948 } 949 defer func() { 950 // At this point we have determined to make the go.mod file on disk equal to new. 951 index = indexModFile(new, modFile, false) 952 }() 953 954 // Make a best-effort attempt to acquire the side lock, only to exclude 955 // previous versions of the 'go' command from making simultaneous edits. 956 if unlock, err := modfetch.SideLock(); err == nil { 957 defer unlock() 958 } 959 960 errNoChange := errors.New("no update needed") 961 962 err = lockedfile.Transform(ModFilePath(), func(old []byte) ([]byte, error) { 963 if bytes.Equal(old, new) { 964 // The go.mod file is already equal to new, possibly as the result of some 965 // other process. 966 return nil, errNoChange 967 } 968 969 if index != nil && !bytes.Equal(old, index.data) { 970 // The contents of the go.mod file have changed. In theory we could add all 971 // of the new modules to the build list, recompute, and check whether any 972 // module in *our* build list got bumped to a different version, but that's 973 // a lot of work for marginal benefit. Instead, fail the command: if users 974 // want to run concurrent commands, they need to start with a complete, 975 // consistent module definition. 976 return nil, fmt.Errorf("existing contents have changed since last read") 977 } 978 979 return new, nil 980 }) 981 982 if err != nil && err != errNoChange { 983 base.Fatalf("go: updating go.mod: %v", err) 984 } 985 } 986 987 // indexModFile rebuilds the index of modFile. 988 // If modFile has been changed since it was first read, 989 // modFile.Cleanup must be called before indexModFile. 990 func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileIndex { 991 i := new(modFileIndex) 992 i.data = data 993 i.dataNeedsFix = needsFix 994 995 i.module = module.Version{} 996 if modFile.Module != nil { 997 i.module = modFile.Module.Mod 998 } 999 1000 i.goVersion = "" 1001 if modFile.Go != nil { 1002 i.goVersion = modFile.Go.Version 1003 } 1004 1005 i.require = make(map[module.Version]requireMeta, len(modFile.Require)) 1006 for _, r := range modFile.Require { 1007 i.require[r.Mod] = requireMeta{indirect: r.Indirect} 1008 } 1009 1010 i.replace = make(map[module.Version]module.Version, len(modFile.Replace)) 1011 for _, r := range modFile.Replace { 1012 if prev, dup := i.replace[r.Old]; dup && prev != r.New { 1013 base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v", r.Old, prev, r.New) 1014 } 1015 i.replace[r.Old] = r.New 1016 } 1017 1018 i.exclude = make(map[module.Version]bool, len(modFile.Exclude)) 1019 for _, x := range modFile.Exclude { 1020 i.exclude[x.Mod] = true 1021 } 1022 1023 return i 1024 } 1025 1026 // modFileIsDirty reports whether the go.mod file differs meaningfully 1027 // from what was indexed. 1028 // If modFile has been changed (even cosmetically) since it was first read, 1029 // modFile.Cleanup must be called before modFileIsDirty. 1030 func (i *modFileIndex) modFileIsDirty(modFile *modfile.File) bool { 1031 if i == nil { 1032 return modFile != nil 1033 } 1034 1035 if i.dataNeedsFix { 1036 return true 1037 } 1038 1039 if modFile.Module == nil { 1040 if i.module != (module.Version{}) { 1041 return true 1042 } 1043 } else if modFile.Module.Mod != i.module { 1044 return true 1045 } 1046 1047 if modFile.Go == nil { 1048 if i.goVersion != "" { 1049 return true 1050 } 1051 } else if modFile.Go.Version != i.goVersion { 1052 if i.goVersion == "" && cfg.BuildMod == "readonly" { 1053 // go.mod files did not always require a 'go' version, so do not error out 1054 // if one is missing — we may be inside an older module in the module 1055 // cache, and should bias toward providing useful behavior. 1056 } else { 1057 return true 1058 } 1059 } 1060 1061 if len(modFile.Require) != len(i.require) || 1062 len(modFile.Replace) != len(i.replace) || 1063 len(modFile.Exclude) != len(i.exclude) { 1064 return true 1065 } 1066 1067 for _, r := range modFile.Require { 1068 if meta, ok := i.require[r.Mod]; !ok { 1069 return true 1070 } else if r.Indirect != meta.indirect { 1071 if cfg.BuildMod == "readonly" { 1072 // The module's requirements are consistent; only the "// indirect" 1073 // comments that are wrong. But those are only guaranteed to be accurate 1074 // after a "go mod tidy" — it's a good idea to run those before 1075 // committing a change, but it's certainly not mandatory. 1076 } else { 1077 return true 1078 } 1079 } 1080 } 1081 1082 for _, r := range modFile.Replace { 1083 if r.New != i.replace[r.Old] { 1084 return true 1085 } 1086 } 1087 1088 for _, x := range modFile.Exclude { 1089 if !i.exclude[x.Mod] { 1090 return true 1091 } 1092 } 1093 1094 return false 1095 }