project.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package project
  2. import (
  3. "errors"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "os/exec"
  8. "path/filepath"
  9. "regexp"
  10. "strings"
  11. "github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
  12. )
  13. const (
  14. constGo = "go"
  15. constProtoC = "protoc"
  16. constGoMod = "go env GOMOD"
  17. constGoPath = "go env GOPATH"
  18. constProtoCGenGo = "protoc-gen-go"
  19. )
  20. type (
  21. Project struct {
  22. Path string // Project path name
  23. Name string // Project name
  24. Package string // The service related package
  25. // true-> project in go path or project init with go mod,or else->false
  26. IsInGoEnv bool
  27. GoMod GoMod
  28. }
  29. GoMod struct {
  30. Module string // The gomod module name
  31. Path string // The gomod related path
  32. }
  33. )
  34. func Prepare(projectDir string, checkGrpcEnv bool) (*Project, error) {
  35. _, err := exec.LookPath(constGo)
  36. if err != nil {
  37. return nil, fmt.Errorf("please install go first,reference documents:「https://golang.org/doc/install」")
  38. }
  39. if checkGrpcEnv {
  40. _, err = exec.LookPath(constProtoC)
  41. if err != nil {
  42. return nil, fmt.Errorf("please install protoc first,reference documents:「https://github.com/golang/protobuf」")
  43. }
  44. _, err = exec.LookPath(constProtoCGenGo)
  45. if err != nil {
  46. return nil, fmt.Errorf("please install plugin protoc-gen-go first,reference documents:「https://github.com/golang/protobuf」")
  47. }
  48. }
  49. var (
  50. goMod, module string
  51. goPath string
  52. name, path string
  53. pkg string
  54. )
  55. ret, err := execx.Run(constGoMod, projectDir)
  56. if err != nil {
  57. return nil, err
  58. }
  59. goMod = strings.TrimSpace(ret)
  60. if goMod == os.DevNull {
  61. goMod = ""
  62. }
  63. ret, err = execx.Run(constGoPath, "")
  64. if err != nil {
  65. return nil, err
  66. }
  67. goPath = strings.TrimSpace(ret)
  68. src := filepath.Join(goPath, "src")
  69. var isInGoEnv = true
  70. if len(goMod) > 0 {
  71. path = filepath.Dir(goMod)
  72. name = filepath.Base(path)
  73. data, err := ioutil.ReadFile(goMod)
  74. if err != nil {
  75. return nil, err
  76. }
  77. module, err = matchModule(data)
  78. if err != nil {
  79. return nil, err
  80. }
  81. } else {
  82. pwd, err := filepath.Abs(projectDir)
  83. if err != nil {
  84. return nil, err
  85. }
  86. if !strings.HasPrefix(pwd, src) {
  87. name = filepath.Clean(filepath.Base(pwd))
  88. path = projectDir
  89. pkg = name
  90. isInGoEnv = false
  91. } else {
  92. r := strings.TrimPrefix(pwd, src+string(filepath.Separator))
  93. name = filepath.Dir(r)
  94. if name == "." {
  95. name = r
  96. }
  97. path = filepath.Join(src, name)
  98. pkg = r
  99. }
  100. module = name
  101. }
  102. return &Project{
  103. Name: name,
  104. Path: path,
  105. Package: strings.ReplaceAll(pkg, `\`, "/"),
  106. IsInGoEnv: isInGoEnv,
  107. GoMod: GoMod{
  108. Module: module,
  109. Path: goMod,
  110. },
  111. }, nil
  112. }
  113. func matchModule(data []byte) (string, error) {
  114. text := string(data)
  115. re := regexp.MustCompile(`(?m)^\s*module\s+[a-z0-9_/\-.]+$`)
  116. matches := re.FindAllString(text, -1)
  117. if len(matches) == 1 {
  118. target := matches[0]
  119. index := strings.Index(target, "module")
  120. return strings.TrimSpace(target[index+6:]), nil
  121. }
  122. return "", errors.New("module not matched")
  123. }