libgo: update to Go 1.11
[official-gcc.git] / libgo / go / cmd / go / internal / modload / init.go
blobf995bad13b5433a71246672d1f548c3522000da3
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.
5 package modload
7 import (
8 "bytes"
9 "cmd/go/internal/base"
10 "cmd/go/internal/cache"
11 "cmd/go/internal/cfg"
12 "cmd/go/internal/load"
13 "cmd/go/internal/modconv"
14 "cmd/go/internal/modfetch"
15 "cmd/go/internal/modfetch/codehost"
16 "cmd/go/internal/modfile"
17 "cmd/go/internal/module"
18 "cmd/go/internal/mvs"
19 "cmd/go/internal/search"
20 "encoding/json"
21 "fmt"
22 "io/ioutil"
23 "os"
24 "path"
25 "path/filepath"
26 "regexp"
27 "strconv"
28 "strings"
31 var (
32 cwd string
33 MustUseModules = mustUseModules()
34 initialized bool
36 ModRoot string
37 modFile *modfile.File
38 excluded map[module.Version]bool
39 Target module.Version
41 gopath string
43 CmdModInit bool // running 'go mod init'
44 CmdModModule string // module argument for 'go mod init'
47 // ModFile returns the parsed go.mod file.
49 // Note that after calling ImportPaths or LoadBuildList,
50 // the require statements in the modfile.File are no longer
51 // the source of truth and will be ignored: edits made directly
52 // will be lost at the next call to WriteGoMod.
53 // To make permanent changes to the require statements
54 // in go.mod, edit it before calling ImportPaths or LoadBuildList.
55 func ModFile() *modfile.File {
56 return modFile
59 func BinDir() string {
60 MustInit()
61 return filepath.Join(gopath, "bin")
64 // mustUseModules reports whether we are invoked as vgo
65 // (as opposed to go).
66 // If so, we only support builds with go.mod files.
67 func mustUseModules() bool {
68 name := os.Args[0]
69 name = name[strings.LastIndex(name, "/")+1:]
70 name = name[strings.LastIndex(name, `\`)+1:]
71 return strings.HasPrefix(name, "vgo")
74 var inGOPATH bool // running in GOPATH/src
76 func Init() {
77 if initialized {
78 return
80 initialized = true
82 env := os.Getenv("GO111MODULE")
83 switch env {
84 default:
85 base.Fatalf("go: unknown environment setting GO111MODULE=%s", env)
86 case "", "auto":
87 // leave MustUseModules alone
88 case "on":
89 MustUseModules = true
90 case "off":
91 if !MustUseModules {
92 return
96 // Disable any prompting for passwords by Git.
97 // Only has an effect for 2.3.0 or later, but avoiding
98 // the prompt in earlier versions is just too hard.
99 // If user has explicitly set GIT_TERMINAL_PROMPT=1, keep
100 // prompting.
101 // See golang.org/issue/9341 and golang.org/issue/12706.
102 if os.Getenv("GIT_TERMINAL_PROMPT") == "" {
103 os.Setenv("GIT_TERMINAL_PROMPT", "0")
106 // Disable any ssh connection pooling by Git.
107 // If a Git subprocess forks a child into the background to cache a new connection,
108 // that child keeps stdout/stderr open. After the Git subprocess exits,
109 // os /exec expects to be able to read from the stdout/stderr pipe
110 // until EOF to get all the data that the Git subprocess wrote before exiting.
111 // The EOF doesn't come until the child exits too, because the child
112 // is holding the write end of the pipe.
113 // This is unfortunate, but it has come up at least twice
114 // (see golang.org/issue/13453 and golang.org/issue/16104)
115 // and confuses users when it does.
116 // If the user has explicitly set GIT_SSH or GIT_SSH_COMMAND,
117 // assume they know what they are doing and don't step on it.
118 // But default to turning off ControlMaster.
119 if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" {
120 os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no")
123 var err error
124 cwd, err = os.Getwd()
125 if err != nil {
126 base.Fatalf("go: %v", err)
129 inGOPATH = false
130 for _, gopath := range filepath.SplitList(cfg.BuildContext.GOPATH) {
131 if gopath == "" {
132 continue
134 if search.InDir(cwd, filepath.Join(gopath, "src")) != "" {
135 inGOPATH = true
136 break
140 if inGOPATH && !MustUseModules {
141 // No automatic enabling in GOPATH.
142 if root, _ := FindModuleRoot(cwd, "", false); root != "" {
143 cfg.GoModInGOPATH = filepath.Join(root, "go.mod")
145 return
148 if CmdModInit {
149 // Running 'go mod init': go.mod will be created in current directory.
150 ModRoot = cwd
151 } else {
152 ModRoot, _ = FindModuleRoot(cwd, "", MustUseModules)
153 if !MustUseModules {
154 if ModRoot == "" {
155 return
157 if search.InDir(ModRoot, os.TempDir()) == "." {
158 // If you create /tmp/go.mod for experimenting,
159 // then any tests that create work directories under /tmp
160 // will find it and get modules when they're not expecting them.
161 // It's a bit of a peculiar thing to disallow but quite mysterious
162 // when it happens. See golang.org/issue/26708.
163 ModRoot = ""
164 fmt.Fprintf(os.Stderr, "go: warning: ignoring go.mod in system temp root %v\n", os.TempDir())
165 return
170 cfg.ModulesEnabled = true
171 load.ModBinDir = BinDir
172 load.ModLookup = Lookup
173 load.ModPackageModuleInfo = PackageModuleInfo
174 load.ModImportPaths = ImportPaths
175 load.ModPackageBuildInfo = PackageBuildInfo
176 load.ModInfoProg = ModInfoProg
177 load.ModImportFromFiles = ImportFromFiles
178 load.ModDirImportPath = DirImportPath
180 search.SetModRoot(ModRoot)
183 func init() {
184 load.ModInit = Init
186 // Set modfetch.PkgMod unconditionally, so that go clean -modcache can run even without modules enabled.
187 if list := filepath.SplitList(cfg.BuildContext.GOPATH); len(list) > 0 && list[0] != "" {
188 modfetch.PkgMod = filepath.Join(list[0], "pkg/mod")
192 // Enabled reports whether modules are (or must be) enabled.
193 // If modules must be enabled but are not, Enabled returns true
194 // and then the first use of module information will call die
195 // (usually through InitMod and MustInit).
196 func Enabled() bool {
197 if !initialized {
198 panic("go: Enabled called before Init")
200 return ModRoot != "" || MustUseModules
203 // MustInit calls Init if needed and checks that
204 // modules are enabled and the main module has been found.
205 // If not, MustInit calls base.Fatalf with an appropriate message.
206 func MustInit() {
207 if Init(); ModRoot == "" {
208 die()
210 if c := cache.Default(); c == nil {
211 // With modules, there are no install locations for packages
212 // other than the build cache.
213 base.Fatalf("go: cannot use modules with build cache disabled")
217 // Failed reports whether module loading failed.
218 // If Failed returns true, then any use of module information will call die.
219 func Failed() bool {
220 Init()
221 return cfg.ModulesEnabled && ModRoot == ""
224 func die() {
225 if os.Getenv("GO111MODULE") == "off" {
226 base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'")
228 if inGOPATH && !MustUseModules {
229 base.Fatalf("go: modules disabled inside GOPATH/src by GO111MODULE=auto; see 'go help modules'")
231 base.Fatalf("go: cannot find main module; see 'go help modules'")
234 func InitMod() {
235 MustInit()
236 if modFile != nil {
237 return
240 list := filepath.SplitList(cfg.BuildContext.GOPATH)
241 if len(list) == 0 || list[0] == "" {
242 base.Fatalf("missing $GOPATH")
244 gopath = list[0]
245 if _, err := os.Stat(filepath.Join(gopath, "go.mod")); err == nil {
246 base.Fatalf("$GOPATH/go.mod exists but should not")
249 oldSrcMod := filepath.Join(list[0], "src/mod")
250 pkgMod := filepath.Join(list[0], "pkg/mod")
251 infoOld, errOld := os.Stat(oldSrcMod)
252 _, errMod := os.Stat(pkgMod)
253 if errOld == nil && infoOld.IsDir() && errMod != nil && os.IsNotExist(errMod) {
254 os.Rename(oldSrcMod, pkgMod)
257 modfetch.PkgMod = pkgMod
258 modfetch.GoSumFile = filepath.Join(ModRoot, "go.sum")
259 codehost.WorkRoot = filepath.Join(pkgMod, "cache/vcs")
261 if CmdModInit {
262 // Running go mod init: do legacy module conversion
263 legacyModInit()
264 modFileToBuildList()
265 WriteGoMod()
266 return
269 gomod := filepath.Join(ModRoot, "go.mod")
270 data, err := ioutil.ReadFile(gomod)
271 if err != nil {
272 if os.IsNotExist(err) {
273 legacyModInit()
274 modFileToBuildList()
275 WriteGoMod()
276 return
278 base.Fatalf("go: %v", err)
281 f, err := modfile.Parse(gomod, data, fixVersion)
282 if err != nil {
283 // Errors returned by modfile.Parse begin with file:line.
284 base.Fatalf("go: errors parsing go.mod:\n%s\n", err)
286 modFile = f
288 if len(f.Syntax.Stmt) == 0 || f.Module == nil {
289 // Empty mod file. Must add module path.
290 path, err := FindModulePath(ModRoot)
291 if err != nil {
292 base.Fatalf("go: %v", err)
294 f.AddModuleStmt(path)
297 if len(f.Syntax.Stmt) == 1 && f.Module != nil {
298 // Entire file is just a module statement.
299 // Populate require if possible.
300 legacyModInit()
303 excluded = make(map[module.Version]bool)
304 for _, x := range f.Exclude {
305 excluded[x.Mod] = true
307 modFileToBuildList()
308 WriteGoMod()
311 // modFileToBuildList initializes buildList from the modFile.
312 func modFileToBuildList() {
313 Target = modFile.Module.Mod
314 list := []module.Version{Target}
315 for _, r := range modFile.Require {
316 list = append(list, r.Mod)
318 buildList = list
321 // Allowed reports whether module m is allowed (not excluded) by the main module's go.mod.
322 func Allowed(m module.Version) bool {
323 return !excluded[m]
326 func legacyModInit() {
327 if modFile == nil {
328 path, err := FindModulePath(ModRoot)
329 if err != nil {
330 base.Fatalf("go: %v", err)
332 fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", path)
333 modFile = new(modfile.File)
334 modFile.AddModuleStmt(path)
337 for _, name := range altConfigs {
338 cfg := filepath.Join(ModRoot, name)
339 data, err := ioutil.ReadFile(cfg)
340 if err == nil {
341 convert := modconv.Converters[name]
342 if convert == nil {
343 return
345 fmt.Fprintf(os.Stderr, "go: copying requirements from %s\n", base.ShortPath(cfg))
346 cfg = filepath.ToSlash(cfg)
347 if err := modconv.ConvertLegacyConfig(modFile, cfg, data); err != nil {
348 base.Fatalf("go: %v", err)
350 if len(modFile.Syntax.Stmt) == 1 {
351 // Add comment to avoid re-converting every time it runs.
352 modFile.AddComment("// go: no requirements found in " + name)
354 return
359 var altConfigs = []string{
360 "Gopkg.lock",
362 "GLOCKFILE",
363 "Godeps/Godeps.json",
364 "dependencies.tsv",
365 "glide.lock",
366 "vendor.conf",
367 "vendor.yml",
368 "vendor/manifest",
369 "vendor/vendor.json",
371 ".git/config",
374 // Exported only for testing.
375 func FindModuleRoot(dir, limit string, legacyConfigOK bool) (root, file string) {
376 dir = filepath.Clean(dir)
377 dir1 := dir
378 limit = filepath.Clean(limit)
380 // Look for enclosing go.mod.
381 for {
382 if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
383 return dir, "go.mod"
385 if dir == limit {
386 break
388 d := filepath.Dir(dir)
389 if d == dir {
390 break
392 dir = d
395 // Failing that, look for enclosing alternate version config.
396 if legacyConfigOK {
397 dir = dir1
398 for {
399 for _, name := range altConfigs {
400 if _, err := os.Stat(filepath.Join(dir, name)); err == nil {
401 return dir, name
404 if dir == limit {
405 break
407 d := filepath.Dir(dir)
408 if d == dir {
409 break
411 dir = d
415 return "", ""
418 // Exported only for testing.
419 func FindModulePath(dir string) (string, error) {
420 if CmdModModule != "" {
421 // Running go mod init x/y/z; return x/y/z.
422 return CmdModModule, nil
425 // Cast about for import comments,
426 // first in top-level directory, then in subdirectories.
427 list, _ := ioutil.ReadDir(dir)
428 for _, info := range list {
429 if info.Mode().IsRegular() && strings.HasSuffix(info.Name(), ".go") {
430 if com := findImportComment(filepath.Join(dir, info.Name())); com != "" {
431 return com, nil
435 for _, info1 := range list {
436 if info1.IsDir() {
437 files, _ := ioutil.ReadDir(filepath.Join(dir, info1.Name()))
438 for _, info2 := range files {
439 if info2.Mode().IsRegular() && strings.HasSuffix(info2.Name(), ".go") {
440 if com := findImportComment(filepath.Join(dir, info1.Name(), info2.Name())); com != "" {
441 return path.Dir(com), nil
448 // Look for Godeps.json declaring import path.
449 data, _ := ioutil.ReadFile(filepath.Join(dir, "Godeps/Godeps.json"))
450 var cfg1 struct{ ImportPath string }
451 json.Unmarshal(data, &cfg1)
452 if cfg1.ImportPath != "" {
453 return cfg1.ImportPath, nil
456 // Look for vendor.json declaring import path.
457 data, _ = ioutil.ReadFile(filepath.Join(dir, "vendor/vendor.json"))
458 var cfg2 struct{ RootPath string }
459 json.Unmarshal(data, &cfg2)
460 if cfg2.RootPath != "" {
461 return cfg2.RootPath, nil
464 // Look for path in GOPATH.
465 for _, gpdir := range filepath.SplitList(cfg.BuildContext.GOPATH) {
466 if gpdir == "" {
467 continue
469 if rel := search.InDir(dir, filepath.Join(gpdir, "src")); rel != "" && rel != "." {
470 return filepath.ToSlash(rel), nil
474 // Look for .git/config with github origin as last resort.
475 data, _ = ioutil.ReadFile(filepath.Join(dir, ".git/config"))
476 if m := gitOriginRE.FindSubmatch(data); m != nil {
477 return "github.com/" + string(m[1]), nil
480 return "", fmt.Errorf("cannot determine module path for source directory %s (outside GOPATH, no import comments)", dir)
483 var (
484 gitOriginRE = regexp.MustCompile(`(?m)^\[remote "origin"\]\r?\n\turl = (?:https://github.com/|git@github.com:|gh:)([^/]+/[^/]+?)(\.git)?\r?\n`)
485 importCommentRE = regexp.MustCompile(`(?m)^package[ \t]+[^ \t\r\n/]+[ \t]+//[ \t]+import[ \t]+(\"[^"]+\")[ \t]*\r?\n`)
488 func findImportComment(file string) string {
489 data, err := ioutil.ReadFile(file)
490 if err != nil {
491 return ""
493 m := importCommentRE.FindSubmatch(data)
494 if m == nil {
495 return ""
497 path, err := strconv.Unquote(string(m[1]))
498 if err != nil {
499 return ""
501 return path
504 var allowWriteGoMod = true
506 // DisallowWriteGoMod causes future calls to WriteGoMod to do nothing at all.
507 func DisallowWriteGoMod() {
508 allowWriteGoMod = false
511 // AllowWriteGoMod undoes the effect of DisallowWriteGoMod:
512 // future calls to WriteGoMod will update go.mod if needed.
513 // Note that any past calls have been discarded, so typically
514 // a call to AlowWriteGoMod should be followed by a call to WriteGoMod.
515 func AllowWriteGoMod() {
516 allowWriteGoMod = true
519 // MinReqs returns a Reqs with minimal dependencies of Target,
520 // as will be written to go.mod.
521 func MinReqs() mvs.Reqs {
522 var direct []string
523 for _, m := range buildList[1:] {
524 if loaded.direct[m.Path] {
525 direct = append(direct, m.Path)
528 min, err := mvs.Req(Target, buildList, direct, Reqs())
529 if err != nil {
530 base.Fatalf("go: %v", err)
532 return &mvsReqs{buildList: append([]module.Version{Target}, min...)}
535 // WriteGoMod writes the current build list back to go.mod.
536 func WriteGoMod() {
537 // If we're using -mod=vendor we basically ignored
538 // go.mod, so definitely don't try to write back our
539 // incomplete view of the world.
540 if !allowWriteGoMod || cfg.BuildMod == "vendor" {
541 return
544 if loaded != nil {
545 reqs := MinReqs()
546 min, err := reqs.Required(Target)
547 if err != nil {
548 base.Fatalf("go: %v", err)
550 var list []*modfile.Require
551 for _, m := range min {
552 list = append(list, &modfile.Require{
553 Mod: m,
554 Indirect: !loaded.direct[m.Path],
557 modFile.SetRequire(list)
560 file := filepath.Join(ModRoot, "go.mod")
561 old, _ := ioutil.ReadFile(file)
562 modFile.Cleanup() // clean file after edits
563 new, err := modFile.Format()
564 if err != nil {
565 base.Fatalf("go: %v", err)
567 if !bytes.Equal(old, new) {
568 if cfg.BuildMod == "readonly" {
569 base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly")
571 if err := ioutil.WriteFile(file, new, 0666); err != nil {
572 base.Fatalf("go: %v", err)
575 modfetch.WriteGoSum()
578 func fixVersion(path, vers string) (string, error) {
579 // Special case: remove the old -gopkgin- hack.
580 if strings.HasPrefix(path, "gopkg.in/") && strings.Contains(vers, "-gopkgin-") {
581 vers = vers[strings.Index(vers, "-gopkgin-")+len("-gopkgin-"):]
584 // fixVersion is called speculatively on every
585 // module, version pair from every go.mod file.
586 // Avoid the query if it looks OK.
587 _, pathMajor, ok := module.SplitPathVersion(path)
588 if !ok {
589 return "", fmt.Errorf("malformed module path: %s", path)
591 if vers != "" && module.CanonicalVersion(vers) == vers && module.MatchPathMajor(vers, pathMajor) {
592 return vers, nil
595 info, err := Query(path, vers, nil)
596 if err != nil {
597 return "", err
599 return info.Version, nil