project.go 2.9 KB

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