vendor.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Copyright 2020 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. package gocommand
  5. import (
  6. "bytes"
  7. "context"
  8. "fmt"
  9. "os"
  10. "path/filepath"
  11. "regexp"
  12. "strings"
  13. "time"
  14. "golang.org/x/mod/semver"
  15. )
  16. // ModuleJSON holds information about a module.
  17. type ModuleJSON struct {
  18. Path string // module path
  19. Version string // module version
  20. Versions []string // available module versions (with -versions)
  21. Replace *ModuleJSON // replaced by this module
  22. Time *time.Time // time version was created
  23. Update *ModuleJSON // available update, if any (with -u)
  24. Main bool // is this the main module?
  25. Indirect bool // is this module only an indirect dependency of main module?
  26. Dir string // directory holding files for this module, if any
  27. GoMod string // path to go.mod file used when loading this module, if any
  28. GoVersion string // go version used in module
  29. }
  30. var modFlagRegexp = regexp.MustCompile(`-mod[ =](\w+)`)
  31. // VendorEnabled reports whether vendoring is enabled. It takes a *Runner to execute Go commands
  32. // with the supplied context.Context and Invocation. The Invocation can contain pre-defined fields,
  33. // of which only Verb and Args are modified to run the appropriate Go command.
  34. // Inspired by setDefaultBuildMod in modload/init.go
  35. func VendorEnabled(ctx context.Context, inv Invocation, r *Runner) (bool, *ModuleJSON, error) {
  36. mainMod, go114, err := getMainModuleAnd114(ctx, inv, r)
  37. if err != nil {
  38. return false, nil, err
  39. }
  40. // We check the GOFLAGS to see if there is anything overridden or not.
  41. inv.Verb = "env"
  42. inv.Args = []string{"GOFLAGS"}
  43. stdout, err := r.Run(ctx, inv)
  44. if err != nil {
  45. return false, nil, err
  46. }
  47. goflags := string(bytes.TrimSpace(stdout.Bytes()))
  48. matches := modFlagRegexp.FindStringSubmatch(goflags)
  49. var modFlag string
  50. if len(matches) != 0 {
  51. modFlag = matches[1]
  52. }
  53. // Don't override an explicit '-mod=' argument.
  54. if modFlag == "vendor" {
  55. return true, mainMod, nil
  56. } else if modFlag != "" {
  57. return false, nil, nil
  58. }
  59. if mainMod == nil || !go114 {
  60. return false, nil, nil
  61. }
  62. // Check 1.14's automatic vendor mode.
  63. if fi, err := os.Stat(filepath.Join(mainMod.Dir, "vendor")); err == nil && fi.IsDir() {
  64. if mainMod.GoVersion != "" && semver.Compare("v"+mainMod.GoVersion, "v1.14") >= 0 {
  65. // The Go version is at least 1.14, and a vendor directory exists.
  66. // Set -mod=vendor by default.
  67. return true, mainMod, nil
  68. }
  69. }
  70. return false, nil, nil
  71. }
  72. // getMainModuleAnd114 gets one of the main modules' information and whether the
  73. // go command in use is 1.14+. This is the information needed to figure out
  74. // if vendoring should be enabled.
  75. func getMainModuleAnd114(ctx context.Context, inv Invocation, r *Runner) (*ModuleJSON, bool, error) {
  76. const format = `{{.Path}}
  77. {{.Dir}}
  78. {{.GoMod}}
  79. {{.GoVersion}}
  80. {{range context.ReleaseTags}}{{if eq . "go1.14"}}{{.}}{{end}}{{end}}
  81. `
  82. inv.Verb = "list"
  83. inv.Args = []string{"-m", "-f", format}
  84. stdout, err := r.Run(ctx, inv)
  85. if err != nil {
  86. return nil, false, err
  87. }
  88. lines := strings.Split(stdout.String(), "\n")
  89. if len(lines) < 5 {
  90. return nil, false, fmt.Errorf("unexpected stdout: %q", stdout.String())
  91. }
  92. mod := &ModuleJSON{
  93. Path: lines[0],
  94. Dir: lines[1],
  95. GoMod: lines[2],
  96. GoVersion: lines[3],
  97. Main: true,
  98. }
  99. return mod, lines[4] == "go1.14", nil
  100. }