From bc7df9274c12140835ca8dd9daab3371981015b9 Mon Sep 17 00:00:00 2001 From: GrantZheng Date: Sun, 7 Jul 2019 14:29:23 +0800 Subject: [PATCH] Support mod feature --- README.md | 11 ++++ cmd/g_service.go | 34 ++++++++++++ cmd/root.go | 3 + cmd/service.go | 55 ++++++++++++++++++ go.mod | 1 + go.sum | 8 +++ main.go | 31 +---------- utils/utils.go | 142 +++++++++++++++-------------------------------- 8 files changed, 160 insertions(+), 125 deletions(-) diff --git a/README.md b/README.md index 7d5698f..6ab5064 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,17 @@ kit g m hi -s hello kit g m hi -s hello -e # if you want to add endpoint middleware ``` The only thing left to do is add your middleware logic and wire the middleware with your service/endpoint. +# Mod support +If you want to create project outside the gopath, you should use --mod_module flag when you create a new service, generate the service, the client library and the new middleware. The --mod_module value should be as same as your mod module path and is under your work directory. + +For example, under your work directory /XXX/github.com/groupname, running commands as follows: + +```bash +kit n s hello --mod_mudole github.com/groupname/hello +kit g s hello --mod_mudole github.com/groupname/hello --dmw +kit g c hello --mod_mudole github.com/groupname/hello +cd hello && go mod init github.com/groupname/hello +``` # Enable docker integration ```bash diff --git a/cmd/g_service.go b/cmd/g_service.go index c5db132..e160ada 100644 --- a/cmd/g_service.go +++ b/cmd/g_service.go @@ -5,6 +5,11 @@ import ( "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" + "os" + "path/filepath" + "strings" + "github.com/kujtimiihoxha/kit/utils" + "github.com/spf13/afero" ) var methods []string @@ -13,6 +18,35 @@ var initserviceCmd = &cobra.Command{ Short: "Initiate a service", Aliases: []string{"s"}, Run: func(cmd *cobra.Command, args []string) { + gosrc := strings.TrimSuffix(utils.GetGOPATH(), afero.FilePathSeparator ) + afero.FilePathSeparator + "src" + afero.FilePathSeparator + pwd, err := os.Getwd() + if err != nil { + logrus.Error(err) + return + } + gosrc, err = filepath.EvalSymlinks(gosrc) + if err != nil { + logrus.Error(err) + return + } + pwd, err = filepath.EvalSymlinks(pwd) + if err != nil { + logrus.Error(err) + return + } + + var modPath string + modPath = viper.GetString("g_s_mod_module") + if modPath != "" && strings.HasPrefix(pwd, gosrc) { + logrus.Error("The project in the $GOPATH/src folder for the generator to work do not need to set --mod_module.") + return + } + + if modPath == "" && !strings.HasPrefix(pwd, gosrc) { + logrus.Error("The project must be in the $GOPATH/src folder for the generator to work.") + return + } + if len(args) == 0 { logrus.Error("You must provide a name for the service") return diff --git a/cmd/root.go b/cmd/root.go index 70d2306..533a27d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -31,9 +31,12 @@ func init() { RootCmd.PersistentFlags().BoolP("debug", "d", false, "If you want to se the debug logs.") RootCmd.PersistentFlags().BoolP("force", "f", false, "Force overide existing files without asking.") RootCmd.PersistentFlags().StringP("folder", "b", "", "If you want to specify the base folder of the project.") + RootCmd.PersistentFlags().String("mod_module", "", "The mod module path you plan to set in the project") + viper.BindPFlag("gk_folder", RootCmd.PersistentFlags().Lookup("folder")) viper.BindPFlag("gk_force", RootCmd.PersistentFlags().Lookup("force")) viper.BindPFlag("gk_debug", RootCmd.PersistentFlags().Lookup("debug")) + viper.BindPFlag("g_s_mod_module", RootCmd.PersistentFlags().Lookup("mod_module")) } func checkProtoc() bool { diff --git a/cmd/service.go b/cmd/service.go index 47baf00..23c18f0 100644 --- a/cmd/service.go +++ b/cmd/service.go @@ -4,6 +4,12 @@ import ( "github.com/kujtimiihoxha/kit/generator" "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/spf13/viper" + "os" + "path/filepath" + "strings" + "github.com/kujtimiihoxha/kit/utils" + "github.com/spf13/afero" ) var serviceCmd = &cobra.Command{ @@ -11,6 +17,55 @@ var serviceCmd = &cobra.Command{ Short: "Generate new service", Aliases: []string{"s"}, Run: func(cmd *cobra.Command, args []string) { + gosrc := strings.TrimSuffix(utils.GetGOPATH(), afero.FilePathSeparator ) + afero.FilePathSeparator + "src" + afero.FilePathSeparator + pwd, err := os.Getwd() + if err != nil { + logrus.Error(err) + return + } + gosrc, err = filepath.EvalSymlinks(gosrc) + if err != nil { + logrus.Error(err) + return + } + pwd, err = filepath.EvalSymlinks(pwd) + if err != nil { + logrus.Error(err) + return + } + + var modPath string + modPath = viper.GetString("g_s_mod_module") + if modPath != "" && strings.HasPrefix(pwd, gosrc) { + logrus.Error("The project in the $GOPATH/src folder for the generator to work do not need to set --mod_module.") + return + } + + if modPath != "" && !strings.HasPrefix(pwd, gosrc) { //modPath is complete project path, such as github.com/groupame/projectname; modPath is a projectname directory + modPath = strings.Replace(modPath, "\\", "/", -1) + modPathArr := strings.Split(modPath, "/") + pwdArr := strings.Split(pwd, "/") + if len(pwdArr) < len(modPathArr) { + logrus.Error("The mod_module path invalid, and your mod_module path must be under the " + pwd) + return + } + j := len(pwdArr) + if len(modPathArr) > 1 { //only consider complete project path + for i := len(modPathArr) - 2 ; i >=0 && j > 0 ; i-- { + if modPathArr[i] != pwdArr[j - 1] { + logrus.Error("The mod_module path invalid, and your mod_module path must be under the " + pwd) + return + } + j -- + } + } + } + + if modPath == "" && !strings.HasPrefix(pwd, gosrc) { + logrus.Error("The project must be in the $GOPATH/src folder for the generator to work, or generate project with —mod_module flag") + return + } + if len(args) == 0 { logrus.Error("You must provide a name for the service") return diff --git a/go.mod b/go.mod index de82df1..dae48ea 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/emicklei/proto-contrib v0.0.0-20190206213850-73879796f936 github.com/mattn/go-isatty v0.0.7 // indirect github.com/sirupsen/logrus v1.4.0 + github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a github.com/spf13/afero v1.2.2 github.com/spf13/cobra v0.0.3 github.com/spf13/viper v1.3.2 diff --git a/go.sum b/go.sum index 8fd48ff..78f835e 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,11 @@ github.com/emicklei/proto-contrib v0.0.0-20190206213850-73879796f936 h1:sXk80AaZ github.com/emicklei/proto-contrib v0.0.0-20190206213850-73879796f936/go.mod h1:WhnsyUacG9u39ADSgKY555WFJ4cVjZmEzN6vpvjfoQs= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -30,6 +33,10 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.4.0 h1:yKenngtzGh+cUSSh6GWbxW2abRqhYUSR/t/6+2QqNvE= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -60,6 +67,7 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpbl golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190401163957-4fc9f0bfa59a h1:8uDq1cly8U9Rv4OKK7v3+67Eci6dUaa/tGZbJ/2KzpM= golang.org/x/tools v0.0.0-20190401163957-4fc9f0bfa59a/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/main.go b/main.go index e273478..a9eccd6 100644 --- a/main.go +++ b/main.go @@ -1,42 +1,15 @@ package main import ( - "os" - "path" - "path/filepath" - "runtime" - "strings" - "github.com/kujtimiihoxha/kit/cmd" - "github.com/kujtimiihoxha/kit/utils" - "github.com/sirupsen/logrus" - "github.com/spf13/afero" "github.com/spf13/viper" + "path" + "runtime" ) func main() { setDefaults() viper.AutomaticEnv() - gosrc := strings.TrimSuffix(utils.GetGOPATH(), afero.FilePathSeparator ) + afero.FilePathSeparator + "src" + afero.FilePathSeparator - pwd, err := os.Getwd() - if err != nil { - logrus.Error(err) - return - } - gosrc, err = filepath.EvalSymlinks(gosrc) - if err != nil { - logrus.Error(err) - return - } - pwd, err = filepath.EvalSymlinks(pwd) - if err != nil { - logrus.Error(err) - return - } - if !strings.HasPrefix(pwd, gosrc) { - logrus.Error("The project must be in the $GOPATH/src folder for the generator to work.") - return - } cmd.Execute() } diff --git a/utils/utils.go b/utils/utils.go index dee0f9d..1998f86 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -55,122 +55,32 @@ func GoImportsSource(path string, s string) (string, error) { // GetServiceImportPath returns the import path of the service interface. func GetServiceImportPath(name string) (string, error) { - gosrc := GetGOPATH() + "/src/" - gosrc = strings.Replace(gosrc, "\\", "/", -1) - pwd, err := os.Getwd() - if err != nil { - return "", err - } - if viper.GetString("gk_folder") != "" { - pwd += "/" + viper.GetString("gk_folder") - } - pwd = strings.Replace(pwd, "\\", "/", -1) - projectPath := strings.Replace(pwd, gosrc, "", 1) - svcPath := fmt.Sprintf(viper.GetString("gk_service_path_format"), ToLowerSnakeCase(name)) - - svcPath = strings.Replace(svcPath, "\\", "/", -1) - serviceImport := projectPath + "/" + svcPath - return serviceImport, nil + return getImportPath(name, "gk_service_path_format") } // GetCmdServiceImportPath returns the import path of the cmd service (used by cmd/main.go). func GetCmdServiceImportPath(name string) (string, error) { - gosrc := GetGOPATH() + "/src/" - gosrc = strings.Replace(gosrc, "\\", "/", -1) - pwd, err := os.Getwd() - if err != nil { - return "", err - } - if viper.GetString("gk_folder") != "" { - pwd += "/" + viper.GetString("gk_folder") - } - pwd = strings.Replace(pwd, "\\", "/", -1) - projectPath := strings.Replace(pwd, gosrc, "", 1) - svcPath := fmt.Sprintf(viper.GetString("gk_cmd_service_path_format"), ToLowerSnakeCase(name)) - - svcPath = strings.Replace(svcPath, "\\", "/", -1) - serviceImport := projectPath + "/" + svcPath - return serviceImport, nil + return getImportPath(name, "gk_cmd_service_path_format") } // GetEndpointImportPath returns the import path of the service endpoints. func GetEndpointImportPath(name string) (string, error) { - gosrc := GetGOPATH() + "/src/" - gosrc = strings.Replace(gosrc, "\\", "/", -1) - pwd, err := os.Getwd() - if err != nil { - return "", err - } - if viper.GetString("gk_folder") != "" { - pwd += "/" + viper.GetString("gk_folder") - } - pwd = strings.Replace(pwd, "\\", "/", -1) - projectPath := strings.Replace(pwd, gosrc, "", 1) - epPath := fmt.Sprintf(viper.GetString("gk_endpoint_path_format"), ToLowerSnakeCase(name)) - - epPath = strings.Replace(epPath, "\\", "/", -1) - endpointImport := projectPath + "/" + epPath - return endpointImport, nil + return getImportPath(name, "gk_endpoint_path_format") } // GetGRPCTransportImportPath returns the import path of the service grpc transport. func GetGRPCTransportImportPath(name string) (string, error) { - gosrc := GetGOPATH() + "/src/" - gosrc = strings.Replace(gosrc, "\\", "/", -1) - pwd, err := os.Getwd() - if err != nil { - return "", err - } - if viper.GetString("gk_folder") != "" { - pwd += "/" + viper.GetString("gk_folder") - } - pwd = strings.Replace(pwd, "\\", "/", -1) - projectPath := strings.Replace(pwd, gosrc, "", 1) - epPath := fmt.Sprintf(viper.GetString("gk_grpc_path_format"), ToLowerSnakeCase(name)) - - epPath = strings.Replace(epPath, "\\", "/", -1) - endpointImport := projectPath + "/" + epPath - return endpointImport, nil + return getImportPath(name, "gk_grpc_path_format") } // GetPbImportPath returns the import path of the generated service grpc pb. func GetPbImportPath(name string) (string, error) { - gosrc := GetGOPATH() + "/src/" - gosrc = strings.Replace(gosrc, "\\", "/", -1) - pwd, err := os.Getwd() - if err != nil { - return "", err - } - if viper.GetString("gk_folder") != "" { - pwd += "/" + viper.GetString("gk_folder") - } - pwd = strings.Replace(pwd, "\\", "/", -1) - projectPath := strings.Replace(pwd, gosrc, "", 1) - epPath := fmt.Sprintf(viper.GetString("gk_grpc_pb_path_format"), ToLowerSnakeCase(name)) - - epPath = strings.Replace(epPath, "\\", "/", -1) - endpointImport := projectPath + "/" + epPath - return endpointImport, nil + return getImportPath(name, "gk_grpc_pb_path_format") } // GetHTTPTransportImportPath returns the import path of the service http transport. func GetHTTPTransportImportPath(name string) (string, error) { - gosrc := GetGOPATH() + "/src/" - gosrc = strings.Replace(gosrc, "\\", "/", -1) - pwd, err := os.Getwd() - if err != nil { - return "", err - } - if viper.GetString("gk_folder") != "" { - pwd += "/" + viper.GetString("gk_folder") - } - pwd = strings.Replace(pwd, "\\", "/", -1) - projectPath := strings.Replace(pwd, gosrc, "", 1) - epPath := fmt.Sprintf(viper.GetString("gk_http_path_format"), ToLowerSnakeCase(name)) - - epPath = strings.Replace(epPath, "\\", "/", -1) - httpImports := projectPath + "/" + epPath - return httpImports, nil + return getImportPath(name, "gk_http_path_format") } // GetDockerFileProjectPath returns the path of the project. @@ -184,8 +94,10 @@ func GetDockerFileProjectPath() (string, error) { if viper.GetString("gk_folder") != "" { pwd += "/" + viper.GetString("gk_folder") } + pwd = strings.Replace(pwd, "\\", "/", -1) projectPath := strings.Replace(pwd, gosrc, "", 1) + return projectPath, nil } @@ -215,3 +127,41 @@ func defaultGOPATH() string { } return "" } + +func getImportPath(name string, key string) (string, error) { + gosrc := GetGOPATH() + "/src/" + gosrc = strings.Replace(gosrc, "\\", "/", -1) + pwd, err := os.Getwd() + if err != nil { + return "", err + } + if viper.GetString("gk_folder") != "" { + pwd += "/" + viper.GetString("gk_folder") + } + + pwd = strings.Replace(pwd, "\\", "/", -1) + projectPath := strings.Replace(pwd, gosrc, "", 1) + + svcPath := fmt.Sprintf(viper.GetString(key), ToLowerSnakeCase(name)) + + path := strings.Replace(svcPath, "\\", "/", -1) + if viper.GetString("g_s_mod_module") != "" { + projectPath = viper.GetString("g_s_mod_module") + projectPath = strings.Replace(projectPath, "\\", "/", -1) + + projectPathArr := strings.Split(projectPath, "/") + pathArr := strings.Split(path, "/") + if len(projectPathArr) != 0 && len(pathArr) != 0 && projectPathArr[len(projectPathArr) - 1] == pathArr[0] { + projectPathArr = projectPathArr[0:len(projectPathArr) - 1] + projectPath = strings.Join(projectPathArr, "/") + } + } + var importPath string + if projectPath == "" { + importPath = path + } else { + importPath = projectPath + "/" + path + } + return importPath, nil +} +