reactor rpc (#179)

* reactor rpc generation

* update flag

* update command

* update command

* update unit test

* delete test file

* optimize code

* update doc

* update gen pb

* rename target dir

* update mysql data type convert rule

* add done flag

* optimize req/reply parameter

* optimize req/reply parameter

* remove waste code

* remove duplicate parameter

* format code

* format code

* optimize naming

* reactor rpcv2 to rpc

* remove new line

* format code

* rename underline to snake

* reactor getParentPackage

* remove debug log

* reactor background
This commit is contained in:
Keson
2020-11-05 14:12:47 +08:00
committed by GitHub
parent c9ec22d5f4
commit e76f44a35b
95 changed files with 2708 additions and 3301 deletions

View File

@@ -0,0 +1,53 @@
package ctx
import (
"errors"
"path/filepath"
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
)
var moduleCheckErr = errors.New("the work directory must be found in the go mod or the $GOPATH")
type (
ProjectContext struct {
WorkDir string
// Name is the root name of the project
// eg: go-zero、greet
Name string
// Path identifies which module a project belongs to, which is module value if it's a go mod project,
// or else it is the root name of the project, eg: github.com/tal-tech/go-zero、greet
Path string
// Dir is the path of the project, eg: /Users/keson/goland/go/go-zero、/Users/keson/go/src/greet
Dir string
}
)
// Prepare checks the project which module belongs to,and returns the path and module.
// workDir parameter is the directory of the source of generating code,
// where can be found the project path and the project module,
func Prepare(workDir string) (*ProjectContext, error) {
ctx, err := background(workDir)
if err == nil {
return ctx, nil
}
name := filepath.Base(workDir)
_, err = execx.Run("go mod init "+name, workDir)
if err != nil {
return nil, err
}
return background(workDir)
}
func background(workDir string) (*ProjectContext, error) {
isGoMod, err := IsGoMod(workDir)
if err != nil {
return nil, err
}
if isGoMod {
return projectFromGoMod(workDir)
}
return projectFromGoPath(workDir)
}

View File

@@ -0,0 +1,22 @@
package ctx
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestBackground(t *testing.T) {
workDir := "."
ctx, err := Prepare(workDir)
assert.Nil(t, err)
assert.True(t, true, func() bool {
return len(ctx.Dir) != 0 && len(ctx.Path) != 0
}())
}
func TestBackgroundNilWorkDir(t *testing.T) {
workDir := ""
_, err := Prepare(workDir)
assert.NotNil(t, err)
}

View File

@@ -0,0 +1,47 @@
package ctx
import (
"errors"
"os"
"path/filepath"
"github.com/tal-tech/go-zero/core/jsonx"
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
)
type Module struct {
Path string
Main bool
Dir string
GoMod string
GoVersion string
}
// projectFromGoMod is used to find the go module and project file path
// the workDir flag specifies which folder we need to detect based on
// only valid for go mod project
func projectFromGoMod(workDir string) (*ProjectContext, error) {
if len(workDir) == 0 {
return nil, errors.New("the work directory is not found")
}
if _, err := os.Stat(workDir); err != nil {
return nil, err
}
data, err := execx.Run("go list -json -m", workDir)
if err != nil {
return nil, err
}
var m Module
err = jsonx.Unmarshal([]byte(data), &m)
if err != nil {
return nil, err
}
var ret ProjectContext
ret.WorkDir = workDir
ret.Name = filepath.Base(m.Dir)
ret.Dir = m.Dir
ret.Path = m.Path
return &ret, nil
}

View File

@@ -0,0 +1,38 @@
package ctx
import (
"go/build"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
"github.com/tal-tech/go-zero/tools/goctl/util"
)
func TestProjectFromGoMod(t *testing.T) {
dft := build.Default
gp := dft.GOPATH
if len(gp) == 0 {
return
}
projectName := stringx.Rand()
dir := filepath.Join(gp, "src", projectName)
err := util.MkdirIfNotExist(dir)
if err != nil {
return
}
_, err = execx.Run("go mod init "+projectName, dir)
assert.Nil(t, err)
defer func() {
_ = os.RemoveAll(dir)
}()
ctx, err := projectFromGoMod(dir)
assert.Nil(t, err)
assert.Equal(t, projectName, ctx.Path)
assert.Equal(t, dir, ctx.Dir)
}

View File

@@ -0,0 +1,47 @@
package ctx
import (
"errors"
"go/build"
"os"
"path/filepath"
"strings"
"github.com/tal-tech/go-zero/tools/goctl/util"
)
// projectFromGoPath is used to find the main module and project file path
// the workDir flag specifies which folder we need to detect based on
// only valid for go mod project
func projectFromGoPath(workDir string) (*ProjectContext, error) {
if len(workDir) == 0 {
return nil, errors.New("the work directory is not found")
}
if _, err := os.Stat(workDir); err != nil {
return nil, err
}
buildContext := build.Default
goPath := buildContext.GOPATH
goSrc := filepath.Join(goPath, "src")
if !util.FileExists(goSrc) {
return nil, moduleCheckErr
}
wd, err := filepath.Abs(workDir)
if err != nil {
return nil, err
}
if !strings.HasPrefix(wd, goSrc) {
return nil, moduleCheckErr
}
projectName := strings.TrimPrefix(wd, goSrc+string(filepath.Separator))
return &ProjectContext{
WorkDir: workDir,
Name: projectName,
Path: projectName,
Dir: filepath.Join(goSrc, projectName),
}, nil
}

View File

@@ -0,0 +1,54 @@
package ctx
import (
"go/build"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/tal-tech/go-zero/tools/goctl/util"
)
func TestProjectFromGoPath(t *testing.T) {
dft := build.Default
gp := dft.GOPATH
if len(gp) == 0 {
return
}
projectName := stringx.Rand()
dir := filepath.Join(gp, "src", projectName)
err := util.MkdirIfNotExist(dir)
if err != nil {
return
}
defer func() {
_ = os.RemoveAll(dir)
}()
ctx, err := projectFromGoPath(dir)
assert.Nil(t, err)
assert.Equal(t, dir, ctx.Dir)
assert.Equal(t, projectName, ctx.Path)
}
func TestProjectFromGoPathNotInGoSrc(t *testing.T) {
dft := build.Default
gp := dft.GOPATH
if len(gp) == 0 {
return
}
projectName := stringx.Rand()
dir := filepath.Join(gp, "src", projectName)
err := util.MkdirIfNotExist(dir)
if err != nil {
return
}
defer func() {
_ = os.RemoveAll(dir)
}()
_, err = projectFromGoPath("testPath")
assert.NotNil(t, err)
}

View File

@@ -0,0 +1,32 @@
package ctx
import (
"errors"
"os"
"github.com/tal-tech/go-zero/core/jsonx"
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
)
// IsGoMod is used to determine whether workDir is a go module project through command `go list -json -m`
func IsGoMod(workDir string) (bool, error) {
if len(workDir) == 0 {
return false, errors.New("the work directory is not found")
}
if _, err := os.Stat(workDir); err != nil {
return false, err
}
data, err := execx.Run("go list -json -m", workDir)
if err != nil {
return false, nil
}
var m Module
err = jsonx.Unmarshal([]byte(data), &m)
if err != nil {
return false, err
}
return len(m.GoMod) > 0, nil
}

View File

@@ -0,0 +1,67 @@
package ctx
import (
"go/build"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
"github.com/tal-tech/go-zero/tools/goctl/util"
)
func TestIsGoMod(t *testing.T) {
// create mod project
dft := build.Default
gp := dft.GOPATH
if len(gp) == 0 {
return
}
projectName := stringx.Rand()
dir := filepath.Join(gp, "src", projectName)
err := util.MkdirIfNotExist(dir)
if err != nil {
return
}
_, err = execx.Run("go mod init "+projectName, dir)
assert.Nil(t, err)
defer func() {
_ = os.RemoveAll(dir)
}()
isGoMod, err := IsGoMod(dir)
assert.Nil(t, err)
assert.Equal(t, true, isGoMod)
}
func TestIsGoModNot(t *testing.T) {
dft := build.Default
gp := dft.GOPATH
if len(gp) == 0 {
return
}
projectName := stringx.Rand()
dir := filepath.Join(gp, "src", projectName)
err := util.MkdirIfNotExist(dir)
if err != nil {
return
}
defer func() {
_ = os.RemoveAll(dir)
}()
isGoMod, err := IsGoMod(dir)
assert.Nil(t, err)
assert.Equal(t, false, isGoMod)
}
func TestIsGoModWorkDirIsNil(t *testing.T) {
_, err := IsGoMod("")
assert.Equal(t, err.Error(), func() string {
return "the work directory is not found"
}())
}

View File

@@ -1,141 +0,0 @@
package project
import (
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
)
const (
constGo = "go"
constProtoC = "protoc"
constGoMod = "go env GOMOD"
constGoPath = "go env GOPATH"
constProtoCGenGo = "protoc-gen-go"
)
type (
Project struct {
Path string // Project path name
Name string // Project name
Package string // The service related package
// true-> project in go path or project init with go mod,or else->false
IsInGoEnv bool
GoMod GoMod
}
GoMod struct {
Module string // The gomod module name
Path string // The gomod related path
}
)
func Prepare(projectDir string, checkGrpcEnv bool) (*Project, error) {
_, err := exec.LookPath(constGo)
if err != nil {
return nil, fmt.Errorf("please install go first,reference documents:「https://golang.org/doc/install」")
}
if checkGrpcEnv {
_, err = exec.LookPath(constProtoC)
if err != nil {
return nil, fmt.Errorf("please install protoc first,reference documents:「https://github.com/golang/protobuf」")
}
_, err = exec.LookPath(constProtoCGenGo)
if err != nil {
return nil, fmt.Errorf("please install plugin protoc-gen-go first,reference documents:「https://github.com/golang/protobuf」")
}
}
var (
goMod, module string
goPath string
name, path string
pkg string
)
ret, err := execx.Run(constGoMod, projectDir)
if err != nil {
return nil, err
}
goMod = strings.TrimSpace(ret)
if goMod == os.DevNull {
goMod = ""
}
ret, err = execx.Run(constGoPath, "")
if err != nil {
return nil, err
}
goPath = strings.TrimSpace(ret)
src := filepath.Join(goPath, "src")
var isInGoEnv = true
if len(goMod) > 0 {
path = filepath.Dir(goMod)
name = filepath.Base(path)
data, err := ioutil.ReadFile(goMod)
if err != nil {
return nil, err
}
module, err = matchModule(data)
if err != nil {
return nil, err
}
} else {
pwd, err := filepath.Abs(projectDir)
if err != nil {
return nil, err
}
if !strings.HasPrefix(pwd, src) {
name = filepath.Clean(filepath.Base(pwd))
path = projectDir
pkg = name
isInGoEnv = false
} else {
r := strings.TrimPrefix(pwd, src+string(filepath.Separator))
name = filepath.Dir(r)
if name == "." {
name = r
}
path = filepath.Join(src, name)
pkg = r
}
module = name
}
return &Project{
Name: name,
Path: path,
Package: strings.ReplaceAll(pkg, `\`, "/"),
IsInGoEnv: isInGoEnv,
GoMod: GoMod{
Module: module,
Path: goMod,
},
}, nil
}
func matchModule(data []byte) (string, error) {
text := string(data)
re := regexp.MustCompile(`(?m)^\s*module\s+[a-z0-9_/\-.]+$`)
matches := re.FindAllString(text, -1)
if len(matches) == 1 {
target := matches[0]
index := strings.Index(target, "module")
return strings.TrimSpace(target[index+6:]), nil
}
return "", errors.New("module not matched")
}