mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
improve command docker/gen service
This commit is contained in:
@ -38,40 +38,43 @@ It runs "gf build" firstly to compile the project to binary file.
|
||||
It then runs "docker build" command automatically to generate the docker image.
|
||||
You should have docker installed, and there must be a Dockerfile in the root of the project.
|
||||
`
|
||||
cDockerMainBrief = `main file path for "gf build", it's "main.go" in default. empty string for no binary build`
|
||||
cDockerBuildBrief = `binary build options before docker image build, it's "-a amd64 -s linux" in default`
|
||||
cDockerFileBrief = `file path of the Dockerfile. it's "manifest/docker/Dockerfile" in default`
|
||||
cDockerShellBrief = `path of the shell file which is executed before docker build`
|
||||
cDockerPushBrief = `auto push the docker image to docker registry if "-t" option passed`
|
||||
cDockerTagsBrief = `tag names for this docker, which are usually used for docker push, multiple tags joined with char ","`
|
||||
cDockerExtraBrief = `extra build options passed to "docker image"`
|
||||
cDockerMainBrief = `main file path for "gf build", it's "main.go" in default. empty string for no binary build`
|
||||
cDockerBuildBrief = `binary build options before docker image build, it's "-a amd64 -s linux" in default`
|
||||
cDockerFileBrief = `file path of the Dockerfile. it's "manifest/docker/Dockerfile" in default`
|
||||
cDockerShellBrief = `path of the shell file which is executed before docker build`
|
||||
cDockerPushBrief = `auto push the docker image to docker registry if "-t" option passed`
|
||||
cDockerTagNameBrief = `tag name for this docker, pattern like "image:tag". this option is required with TagPrefixes`
|
||||
cDockerTagPrefixesBrief = `tag prefixes for this docker, which are used for docker push. this option is required with TagName`
|
||||
cDockerExtraBrief = `extra build options passed to "docker image"`
|
||||
)
|
||||
|
||||
func init() {
|
||||
gtag.Sets(g.MapStrStr{
|
||||
`cDockerUsage`: cDockerUsage,
|
||||
`cDockerBrief`: cDockerBrief,
|
||||
`cDockerEg`: cDockerEg,
|
||||
`cDockerDc`: cDockerDc,
|
||||
`cDockerMainBrief`: cDockerMainBrief,
|
||||
`cDockerFileBrief`: cDockerFileBrief,
|
||||
`cDockerShellBrief`: cDockerShellBrief,
|
||||
`cDockerBuildBrief`: cDockerBuildBrief,
|
||||
`cDockerPushBrief`: cDockerPushBrief,
|
||||
`cDockerTagsBrief`: cDockerTagsBrief,
|
||||
`cDockerExtraBrief`: cDockerExtraBrief,
|
||||
`cDockerUsage`: cDockerUsage,
|
||||
`cDockerBrief`: cDockerBrief,
|
||||
`cDockerEg`: cDockerEg,
|
||||
`cDockerDc`: cDockerDc,
|
||||
`cDockerMainBrief`: cDockerMainBrief,
|
||||
`cDockerFileBrief`: cDockerFileBrief,
|
||||
`cDockerShellBrief`: cDockerShellBrief,
|
||||
`cDockerBuildBrief`: cDockerBuildBrief,
|
||||
`cDockerPushBrief`: cDockerPushBrief,
|
||||
`cDockerTagNameBrief`: cDockerTagNameBrief,
|
||||
`cDockerTagPrefixesBrief`: cDockerTagPrefixesBrief,
|
||||
`cDockerExtraBrief`: cDockerExtraBrief,
|
||||
})
|
||||
}
|
||||
|
||||
type cDockerInput struct {
|
||||
g.Meta `name:"docker" config:"gfcli.docker"`
|
||||
Main string `name:"MAIN" arg:"true" brief:"{cDockerMainBrief}" d:"main.go"`
|
||||
File string `name:"file" short:"f" brief:"{cDockerFileBrief}" d:"manifest/docker/Dockerfile"`
|
||||
Shell string `name:"shell" short:"s" brief:"{cDockerShellBrief}" d:"manifest/docker/docker.sh"`
|
||||
Build string `name:"build" short:"b" brief:"{cDockerBuildBrief}" d:"-a amd64 -s linux"`
|
||||
Tags string `name:"tags" short:"t" brief:"{cDockerTagsBrief}"`
|
||||
Push bool `name:"push" short:"p" brief:"{cDockerPushBrief}" orphan:"true"`
|
||||
Extra string `name:"extra" short:"e" brief:"{cDockerExtraBrief}"`
|
||||
g.Meta `name:"docker" config:"gfcli.docker"`
|
||||
Main string `name:"MAIN" arg:"true" brief:"{cDockerMainBrief}" d:"main.go"`
|
||||
File string `name:"file" short:"f" brief:"{cDockerFileBrief}" d:"manifest/docker/Dockerfile"`
|
||||
Shell string `name:"shell" short:"s" brief:"{cDockerShellBrief}" d:"manifest/docker/docker.sh"`
|
||||
Build string `name:"build" short:"b" brief:"{cDockerBuildBrief}" d:"-a amd64 -s linux"`
|
||||
TagName string `name:"tagName" short:"tn" brief:"{cDockerTagNameBrief}" v:"required-with:TagPrefixes"`
|
||||
TagPrefixes []string `name:"tagPrefixes" short:"tp" brief:"{cDockerTagPrefixesBrief}" v:"required-with:TagName"`
|
||||
Push bool `name:"push" short:"p" brief:"{cDockerPushBrief}" orphan:"true"`
|
||||
Extra string `name:"extra" short:"e" brief:"{cDockerExtraBrief}"`
|
||||
}
|
||||
type cDockerOutput struct{}
|
||||
|
||||
@ -98,8 +101,14 @@ func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput
|
||||
// Docker build.
|
||||
var (
|
||||
dockerBuildOptions string
|
||||
dockerTags = gstr.SplitAndTrim(in.Tags, ",")
|
||||
dockerTags []string
|
||||
)
|
||||
if len(in.TagPrefixes) > 0 {
|
||||
for _, tagPrefix := range in.TagPrefixes {
|
||||
tagPrefix = gstr.TrimRight(tagPrefix, "/")
|
||||
dockerTags = append(dockerTags, fmt.Sprintf(`%s/%s`, tagPrefix, in.TagName))
|
||||
}
|
||||
}
|
||||
if len(dockerTags) == 0 {
|
||||
dockerTags = []string{""}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
@ -15,39 +16,58 @@ import (
|
||||
|
||||
type (
|
||||
cGenServiceInput struct {
|
||||
g.Meta `name:"service" brief:"parse logic struct and associated functions to generate service go file"`
|
||||
Logic string `short:"l" name:"logic" brief:"logic folder path to be parsed" d:"internal/logic"`
|
||||
Path string `short:"p" name:"path" brief:"folder path storing automatically generated go files" d:"internal/service"`
|
||||
Pattern string `short:"a" name:"pattern" brief:"regular expression matching struct name for generating service" d:"s(\\w+)"`
|
||||
WatchFile string `short:"w" name:"watchFile" brief:"used in file watcher, it generates service go files only if given file is under Logic folder"`
|
||||
g.Meta `name:"service" brief:"parse struct and associated functions from packages to generate service go file"`
|
||||
SrcFolder string `short:"s" name:"srcFolder" brief:"source folder path to be parsed" d:"internal/logic"`
|
||||
DstFolder string `short:"d" name:"dstFolder" brief:"destination folder path storing automatically generated go files" d:"internal/service"`
|
||||
StPattern string `short:"a" name:"stPattern" brief:"regular expression matching struct name for generating service" d:"s(\\w+)"`
|
||||
ImportPrefix string `short:"p" name:"importPrefix" brief:"custom import prefix to calculate import path for generated go files"`
|
||||
WatchFile string `short:"w" name:"watchFile" brief:"used in file watcher, it generates service go files only if given file is under Logic folder"`
|
||||
OverWrite bool `short:"o" name:"overwrite" brief:"overwrite files that already exist in generating folder" d:"true" orphan:"true"`
|
||||
}
|
||||
cGenServiceOutput struct{}
|
||||
)
|
||||
|
||||
func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServiceOutput, err error) {
|
||||
in.Logic = gstr.Trim(in.Logic, `\/`)
|
||||
in.SrcFolder = gstr.Trim(in.SrcFolder, `\/`)
|
||||
in.WatchFile = gstr.Trim(in.WatchFile, `\/`)
|
||||
if !gfile.Exists(in.Logic) {
|
||||
mlog.Fatalf(`logic folder path "%s" does not exist`, in.Logic)
|
||||
if !gfile.Exists(in.SrcFolder) {
|
||||
mlog.Fatalf(`logic folder path "%s" does not exist`, in.SrcFolder)
|
||||
}
|
||||
if in.WatchFile != "" {
|
||||
// It works only if given WatchFile is in Logic folder.
|
||||
if !gstr.Contains(gstr.Replace(in.WatchFile, "\\", "/"), gstr.Replace(in.Logic, "\\", "/")) {
|
||||
mlog.Printf(`ignore watch file "%s", not in logic path "%s"`, in.WatchFile, in.Logic)
|
||||
if !gstr.Contains(gstr.Replace(in.WatchFile, "\\", "/"), gstr.Replace(in.SrcFolder, "\\", "/")) {
|
||||
mlog.Printf(`ignore watch file "%s", not in source path "%s"`, in.WatchFile, in.SrcFolder)
|
||||
return
|
||||
}
|
||||
}
|
||||
if in.ImportPrefix == "" {
|
||||
if !gfile.Exists("go.mod") {
|
||||
mlog.Fatal("go.mod does not exist in current working directory")
|
||||
}
|
||||
var (
|
||||
goModContent = gfile.GetContents("go.mod")
|
||||
match, _ = gregex.MatchString(`^module\s+(.+)\s*`, goModContent)
|
||||
)
|
||||
if len(match) > 1 {
|
||||
in.ImportPrefix = fmt.Sprintf(`%s/%s`, gstr.Trim(match[1]), gstr.Replace(in.SrcFolder, `\`, `/`))
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
files []string
|
||||
fileContent string
|
||||
matches [][]string
|
||||
packageName = gstr.ToLower(gfile.Basename(in.Path))
|
||||
files []string
|
||||
fileContent string
|
||||
matches [][]string
|
||||
srcPackages []string
|
||||
dstPackageName = gstr.ToLower(gfile.Basename(in.DstFolder))
|
||||
)
|
||||
logicFolders, err := gfile.ScanDir(in.Logic, "*", false)
|
||||
logicFolders, err := gfile.ScanDir(in.SrcFolder, "*", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, logicFolder := range logicFolders {
|
||||
if !gfile.IsDir(logicFolder) {
|
||||
continue
|
||||
}
|
||||
if files, err = gfile.ScanDir(logicFolder, "*.go", false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -75,7 +95,7 @@ func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServic
|
||||
if !gstr.IsLetterUpper(funcTitle[0]) {
|
||||
continue
|
||||
}
|
||||
structMatch, err = gregex.MatchString(in.Pattern, structName)
|
||||
structMatch, err = gregex.MatchString(in.StPattern, structName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -90,24 +110,52 @@ func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServic
|
||||
interfaceFuncArray.Append(funcTitle)
|
||||
}
|
||||
}
|
||||
srcPackages = append(srcPackages, fmt.Sprintf(`%s/%s`, in.ImportPrefix, gfile.Basename(logicFolder)))
|
||||
// Generating go files for service.
|
||||
for structName, funcArray := range interfaceMap {
|
||||
var (
|
||||
filePath = gfile.Join(in.Path, gstr.ToLower(structName)+".go")
|
||||
filePath = gfile.Join(in.DstFolder, gstr.ToLower(structName)+".go")
|
||||
generatedContent = gstr.ReplaceByMap(consts.TemplateGenServiceContent, g.MapStrStr{
|
||||
"{StructName}": structName,
|
||||
"{PackageName}": packageName,
|
||||
"{PackageName}": dstPackageName,
|
||||
"{FuncDefinition}": funcArray.Join("\n\t"),
|
||||
})
|
||||
)
|
||||
if !in.OverWrite && gfile.Exists(filePath) {
|
||||
mlog.Printf(`ignore generating service go file: %s`, filePath)
|
||||
continue
|
||||
}
|
||||
mlog.Printf(`generating service go file: %s`, filePath)
|
||||
if err = gfile.PutContents(filePath, generatedContent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
mlog.Printf(`goimports go files in "%s", it may take seconds...`, in.Path)
|
||||
utils.GoImports(in.Path)
|
||||
// Generate initialization go file.
|
||||
if len(srcPackages) > 0 {
|
||||
var (
|
||||
srcPackageName = gstr.ToLower(gfile.Basename(in.SrcFolder))
|
||||
srcFilePath = gfile.Join(in.SrcFolder, srcPackageName+".go")
|
||||
srcImports string
|
||||
generatedContent string
|
||||
)
|
||||
for _, srcPackage := range srcPackages {
|
||||
srcImports += fmt.Sprintf(`%s_ "%s"%s`, "\t", srcPackage, "\n")
|
||||
}
|
||||
generatedContent = gstr.ReplaceByMap(consts.TemplateGenServiceLogicContent, g.MapStrStr{
|
||||
"{PackageName}": srcPackageName,
|
||||
"{Imports}": srcImports,
|
||||
})
|
||||
mlog.Printf(`generating init go file: %s`, srcFilePath)
|
||||
if err = gfile.PutContents(srcFilePath, generatedContent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
utils.GoFmt(srcFilePath)
|
||||
}
|
||||
|
||||
// Go imports updating.
|
||||
mlog.Printf(`goimports go files in "%s", it may take seconds...`, in.DstFolder)
|
||||
utils.GoImports(in.DstFolder)
|
||||
|
||||
// Replica v1 to v2 for GoFrame.
|
||||
err = gfile.ReplaceDirFunc(func(path, content string) string {
|
||||
@ -117,12 +165,12 @@ func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServic
|
||||
return content
|
||||
}
|
||||
return content
|
||||
}, in.Path, "*.go", false)
|
||||
}, in.DstFolder, "*.go", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mlog.Printf(`gofmt go files in "%s"`, in.Path)
|
||||
utils.GoFmt(in.Path)
|
||||
mlog.Printf(`gofmt go files in "%s"`, in.DstFolder)
|
||||
utils.GoFmt(in.DstFolder)
|
||||
mlog.Print(`done!`)
|
||||
return
|
||||
}
|
||||
|
||||
@ -14,6 +14,9 @@ type I{StructName} interface {
|
||||
var local{StructName} I{StructName}
|
||||
|
||||
func {StructName}() I{StructName} {
|
||||
if local{StructName} == nil {
|
||||
panic("implement not found for interface I{StructName}, forgot register?")
|
||||
}
|
||||
return local{StructName}
|
||||
}
|
||||
|
||||
|
||||
13
cmd/gf/internal/consts/consts_gen_service_template_logic.go
Normal file
13
cmd/gf/internal/consts/consts_gen_service_template_logic.go
Normal file
@ -0,0 +1,13 @@
|
||||
package consts
|
||||
|
||||
const TemplateGenServiceLogicContent = `
|
||||
// ==========================================================================
|
||||
// Code generated by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
package {PackageName}
|
||||
|
||||
import(
|
||||
{Imports}
|
||||
)
|
||||
`
|
||||
@ -17,10 +17,10 @@ func GoFmt(path string) {
|
||||
if gofmtPath == "" {
|
||||
mlog.Fatal(`command "gofmt" not found`)
|
||||
}
|
||||
var command = fmt.Sprintf(`%s -w -s %s`, gofmtPath, path)
|
||||
var command = fmt.Sprintf(`%s -w %s`, gofmtPath, path)
|
||||
result, err := gproc.ShellExec(command)
|
||||
if err != nil {
|
||||
mlog.Fatal(`error executing command "%s": %s`, command, result)
|
||||
mlog.Fatalf(`error executing command "%s": %s`, command, result)
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,9 +29,9 @@ func GoImports(path string) {
|
||||
if goimportsPath == "" {
|
||||
mlog.Fatal(`command "goimports" not found`)
|
||||
}
|
||||
var command = fmt.Sprintf(`%s -w -s %s`, goimportsPath, path)
|
||||
var command = fmt.Sprintf(`%s -w %s`, goimportsPath, path)
|
||||
result, err := gproc.ShellExec(command)
|
||||
if err != nil {
|
||||
mlog.Fatal(`error executing command "%s": %s`, command, result)
|
||||
mlog.Fatalf(`error executing command "%s": %s`, command, result)
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -48,7 +49,7 @@ var (
|
||||
|
||||
func init() {
|
||||
// Initialize internal package variable: tempDir.
|
||||
if Separator != "/" || !Exists(tempDir) {
|
||||
if runtime.GOOS == "windows" || Separator != "/" || !Exists(tempDir) {
|
||||
tempDir = os.TempDir()
|
||||
}
|
||||
// Initialize internal package variable: selfPath.
|
||||
|
||||
Reference in New Issue
Block a user