project.go 2.6 KB

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