zrpc.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. package cli
  2. import (
  3. "errors"
  4. "os"
  5. "path/filepath"
  6. "strings"
  7. "github.com/urfave/cli"
  8. "github.com/zeromicro/go-zero/tools/goctl/rpc/generator"
  9. "github.com/zeromicro/go-zero/tools/goctl/util"
  10. "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
  11. )
  12. var (
  13. errInvalidGrpcOutput = errors.New("ZRPC: missing --go-grpc_out")
  14. errInvalidGoOutput = errors.New("ZRPC: missing --go_out")
  15. errInvalidZrpcOutput = errors.New("ZRPC: missing zrpc output, please use --zrpc_out to specify the output")
  16. errInvalidInput = errors.New("ZRPC: missing source")
  17. errMultiInput = errors.New("ZRPC: only one source is expected")
  18. )
  19. // ZRPC generates grpc code directly by protoc and generates
  20. // zrpc code by goctl.
  21. func ZRPC(c *cli.Context) error {
  22. if c.NumFlags() == 0 {
  23. cli.ShowCommandHelpAndExit(c, "protoc", 1)
  24. }
  25. args := c.Parent().Args()
  26. protocArgs := removeGoctlFlag(args)
  27. pwd, err := os.Getwd()
  28. if err != nil {
  29. return err
  30. }
  31. source, err := getSourceProto(c.Args(), pwd)
  32. if err != nil {
  33. return err
  34. }
  35. grpcOutList := c.StringSlice("go-grpc_out")
  36. goOutList := c.StringSlice("go_out")
  37. zrpcOut := c.String("zrpc_out")
  38. style := c.String("style")
  39. home := c.String("home")
  40. remote := c.String("remote")
  41. branch := c.String("branch")
  42. verbose := c.Bool("verbose")
  43. if len(grpcOutList) == 0 {
  44. return errInvalidGrpcOutput
  45. }
  46. if len(goOutList) == 0 {
  47. return errInvalidGoOutput
  48. }
  49. goOut := goOutList[len(goOutList)-1]
  50. grpcOut := grpcOutList[len(grpcOutList)-1]
  51. if len(goOut) == 0 {
  52. return errInvalidGrpcOutput
  53. }
  54. if len(zrpcOut) == 0 {
  55. return errInvalidZrpcOutput
  56. }
  57. goOutAbs, err := filepath.Abs(goOut)
  58. if err != nil {
  59. return err
  60. }
  61. grpcOutAbs, err := filepath.Abs(grpcOut)
  62. if err != nil {
  63. return err
  64. }
  65. err = pathx.MkdirIfNotExist(goOutAbs)
  66. if err != nil {
  67. return err
  68. }
  69. err = pathx.MkdirIfNotExist(grpcOutAbs)
  70. if err != nil {
  71. return err
  72. }
  73. if len(remote) > 0 {
  74. repo, _ := util.CloneIntoGitHome(remote, branch)
  75. if len(repo) > 0 {
  76. home = repo
  77. }
  78. }
  79. if len(home) > 0 {
  80. pathx.RegisterGoctlHome(home)
  81. }
  82. if !filepath.IsAbs(zrpcOut) {
  83. zrpcOut = filepath.Join(pwd, zrpcOut)
  84. }
  85. isGooglePlugin := len(grpcOut) > 0
  86. goOut, err = filepath.Abs(goOut)
  87. if err != nil {
  88. return err
  89. }
  90. grpcOut, err = filepath.Abs(grpcOut)
  91. if err != nil {
  92. return err
  93. }
  94. zrpcOut, err = filepath.Abs(zrpcOut)
  95. if err != nil {
  96. return err
  97. }
  98. var ctx generator.ZRpcContext
  99. ctx.Src = source
  100. ctx.GoOutput = goOut
  101. ctx.GrpcOutput = grpcOut
  102. ctx.IsGooglePlugin = isGooglePlugin
  103. ctx.Output = zrpcOut
  104. ctx.ProtocCmd = strings.Join(protocArgs, " ")
  105. g := generator.NewGenerator(style, verbose)
  106. return g.Generate(&ctx)
  107. }
  108. func removeGoctlFlag(args []string) []string {
  109. var ret []string
  110. var step int
  111. for step < len(args) {
  112. arg := args[step]
  113. switch {
  114. case arg == "--style", arg == "--home",
  115. arg == "--zrpc_out", arg == "--verbose",
  116. arg == "-v", arg == "--remote",
  117. arg == "--branch":
  118. step += 2
  119. continue
  120. case strings.HasPrefix(arg, "--style="),
  121. strings.HasPrefix(arg, "--home="),
  122. strings.HasPrefix(arg, "--verbose="),
  123. strings.HasPrefix(arg, "-v="),
  124. strings.HasPrefix(arg, "--remote="),
  125. strings.HasPrefix(arg, "--branch="),
  126. strings.HasPrefix(arg, "--zrpc_out="):
  127. step += 1
  128. continue
  129. }
  130. step += 1
  131. ret = append(ret, arg)
  132. }
  133. return ret
  134. }
  135. func getSourceProto(args []string, pwd string) (string, error) {
  136. var source []string
  137. for _, p := range args {
  138. if strings.HasSuffix(p, ".proto") {
  139. source = append(source, p)
  140. }
  141. }
  142. switch len(source) {
  143. case 0:
  144. return "", errInvalidInput
  145. case 1:
  146. isAbs := filepath.IsAbs(source[0])
  147. if isAbs {
  148. return source[0], nil
  149. }
  150. abs := filepath.Join(pwd, source[0])
  151. return abs, nil
  152. default:
  153. return "", errMultiInput
  154. }
  155. }
  156. func removePluginFlag(goOut string) string {
  157. goOut = strings.ReplaceAll(goOut, "plugins=", "")
  158. index := strings.LastIndex(goOut, ":")
  159. if index < 0 {
  160. return goOut
  161. }
  162. return goOut[index+1:]
  163. }