feat(gendao): 添加代码生成工具用于自动生成DAO层代码
- 实现了完整的gendao命令行工具功能 - 添加了模板文件用于生成DAO、DO、Entity等代码结构 - 集成了数据库表字段映射和类型转换功能 - 支持分片表模式匹配和自定义配置选项 - 实现了代码清理和格式化功能 - 提供了灵活的表名过滤和前缀处理机制
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package consts
|
||||
|
||||
const (
|
||||
// DoNotEditKey is used in generated files,
|
||||
// which marks the files will be overwritten by CLI tool.
|
||||
DoNotEditKey = `DO NOT EDIT`
|
||||
)
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package mlog
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/genv"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
headerPrintEnvName = "GF_CLI_MLOG_HEADER"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
logger = glog.New()
|
||||
)
|
||||
|
||||
func init() {
|
||||
if genv.Get(headerPrintEnvName).String() == "1" {
|
||||
logger.SetHeaderPrint(true)
|
||||
} else {
|
||||
logger.SetHeaderPrint(false)
|
||||
}
|
||||
|
||||
if gcmd.GetOpt("debug") != nil || gcmd.GetOpt("gf.debug") != nil {
|
||||
logger.SetHeaderPrint(true)
|
||||
logger.SetStackSkip(4)
|
||||
logger.SetFlags(logger.GetFlags() | glog.F_FILE_LONG)
|
||||
logger.SetDebug(true)
|
||||
} else {
|
||||
logger.SetStack(false)
|
||||
logger.SetDebug(false)
|
||||
}
|
||||
}
|
||||
|
||||
// SetHeaderPrint enables/disables header printing to stdout.
|
||||
func SetHeaderPrint(enabled bool) {
|
||||
logger.SetHeaderPrint(enabled)
|
||||
if enabled {
|
||||
_ = genv.Set(headerPrintEnvName, "1")
|
||||
} else {
|
||||
_ = genv.Set(headerPrintEnvName, "0")
|
||||
}
|
||||
}
|
||||
|
||||
func Print(v ...any) {
|
||||
logger.Print(ctx, v...)
|
||||
}
|
||||
|
||||
func Printf(format string, v ...any) {
|
||||
logger.Printf(ctx, format, v...)
|
||||
}
|
||||
|
||||
func Fatal(v ...any) {
|
||||
logger.Fatal(ctx, v...)
|
||||
}
|
||||
|
||||
func Fatalf(format string, v ...any) {
|
||||
logger.Fatalf(ctx, format, v...)
|
||||
}
|
||||
|
||||
func Debug(v ...any) {
|
||||
logger.Debug(ctx, v...)
|
||||
}
|
||||
|
||||
func Debugf(format string, v ...any) {
|
||||
logger.Debugf(ctx, format, v...)
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/tools/imports"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/consts"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// GoFmt formats the source file and adds or removes import statements as necessary.
|
||||
func GoFmt(path string) {
|
||||
replaceFunc := func(path, content string) string {
|
||||
res, err := imports.Process(path, []byte(content), nil)
|
||||
if err != nil {
|
||||
mlog.Printf(`error format "%s" go files: %v`, path, err)
|
||||
return content
|
||||
}
|
||||
return string(res)
|
||||
}
|
||||
|
||||
var err error
|
||||
if gfile.IsFile(path) {
|
||||
// File format.
|
||||
if gfile.ExtName(path) != "go" {
|
||||
return
|
||||
}
|
||||
err = gfile.ReplaceFileFunc(replaceFunc, path)
|
||||
} else {
|
||||
// Folder format.
|
||||
err = gfile.ReplaceDirFunc(replaceFunc, path, "*.go", true)
|
||||
}
|
||||
if err != nil {
|
||||
mlog.Printf(`error format "%s" go files: %v`, path, err)
|
||||
}
|
||||
}
|
||||
|
||||
// GoModTidy executes `go mod tidy` at specified directory `dirPath`.
|
||||
func GoModTidy(ctx context.Context, dirPath string) error {
|
||||
command := fmt.Sprintf(`cd %s && go mod tidy`, dirPath)
|
||||
err := gproc.ShellRun(ctx, command)
|
||||
return err
|
||||
}
|
||||
|
||||
// IsFileDoNotEdit checks and returns whether file contains `do not edit` key.
|
||||
func IsFileDoNotEdit(filePath string) bool {
|
||||
if !gfile.Exists(filePath) {
|
||||
return true
|
||||
}
|
||||
return gstr.Contains(gfile.GetContents(filePath), consts.DoNotEditKey)
|
||||
}
|
||||
|
||||
// ReplaceGeneratedContentGFV2 replaces generated go content from goframe v1 to v2.
|
||||
func ReplaceGeneratedContentGFV2(folderPath string) (err error) {
|
||||
return gfile.ReplaceDirFunc(func(path, content string) string {
|
||||
if gstr.Contains(content, `"github.com/gogf/gf`) && !gstr.Contains(content, `"github.com/gogf/gf/v2`) {
|
||||
content = gstr.Replace(content, `"github.com/gogf/gf"`, `"github.com/gogf/gf/v2"`)
|
||||
content = gstr.Replace(content, `"github.com/gogf/gf/`, `"github.com/gogf/gf/v2/`)
|
||||
content = gstr.Replace(content, `"github.com/gogf/gf/v2/contrib/`, `"github.com/gogf/gf/contrib/`)
|
||||
return content
|
||||
}
|
||||
return content
|
||||
}, folderPath, "*.go", true)
|
||||
}
|
||||
|
||||
// GetImportPath calculates and returns the golang import path for given `dirPath`.
|
||||
// Note that it needs a `go.mod` in current working directory or parent directories to detect the path.
|
||||
func GetImportPath(dirPath string) string {
|
||||
// If `filePath` does not exist, create it firstly to find the import path.
|
||||
var realPath = gfile.RealPath(dirPath)
|
||||
if realPath == "" {
|
||||
_ = gfile.Mkdir(dirPath)
|
||||
realPath = gfile.RealPath(dirPath)
|
||||
}
|
||||
|
||||
var (
|
||||
newDir = gfile.Dir(realPath)
|
||||
oldDir string
|
||||
suffix = gfile.Basename(dirPath)
|
||||
goModName = "go.mod"
|
||||
goModPath string
|
||||
importPath string
|
||||
)
|
||||
for {
|
||||
goModPath = gfile.Join(newDir, goModName)
|
||||
if gfile.Exists(goModPath) {
|
||||
match, _ := gregex.MatchString(`^module\s+(.+)\s*`, gfile.GetContents(goModPath))
|
||||
importPath = gstr.Trim(match[1]) + "/" + suffix
|
||||
importPath = gstr.Replace(importPath, `\`, `/`)
|
||||
importPath = gstr.TrimRight(importPath, `/`)
|
||||
return importPath
|
||||
}
|
||||
oldDir = newDir
|
||||
newDir = gfile.Dir(oldDir)
|
||||
if newDir == oldDir {
|
||||
return ""
|
||||
}
|
||||
suffix = gfile.Basename(oldDir) + "/" + suffix
|
||||
}
|
||||
}
|
||||
|
||||
// GetModPath retrieves and returns the file path of go.mod for current project.
|
||||
func GetModPath() string {
|
||||
var (
|
||||
oldDir = gfile.Pwd()
|
||||
newDir = oldDir
|
||||
goModName = "go.mod"
|
||||
goModPath string
|
||||
)
|
||||
for {
|
||||
goModPath = gfile.Join(newDir, goModName)
|
||||
if gfile.Exists(goModPath) {
|
||||
return goModPath
|
||||
}
|
||||
newDir = gfile.Dir(oldDir)
|
||||
if newDir == oldDir {
|
||||
break
|
||||
}
|
||||
oldDir = newDir
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/schollz/progressbar/v3"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// HTTPDownloadFileWithPercent downloads target url file to local path with percent process printing.
|
||||
func HTTPDownloadFileWithPercent(url string, localSaveFilePath string) error {
|
||||
start := time.Now()
|
||||
out, err := os.Create(localSaveFilePath)
|
||||
if err != nil {
|
||||
return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
headResp, err := http.Head(url)
|
||||
if err != nil {
|
||||
return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath)
|
||||
}
|
||||
defer headResp.Body.Close()
|
||||
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
bar := progressbar.NewOptions(int(resp.ContentLength), progressbar.OptionShowBytes(true), progressbar.OptionShowCount())
|
||||
writer := io.MultiWriter(out, bar)
|
||||
_, err = io.Copy(writer, resp.Body)
|
||||
|
||||
elapsed := time.Since(start)
|
||||
if elapsed > time.Minute {
|
||||
mlog.Printf(`download completed in %.0fm`, float64(elapsed)/float64(time.Minute))
|
||||
} else {
|
||||
mlog.Printf(`download completed in %.0fs`, elapsed.Seconds())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package utils_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/utils"
|
||||
)
|
||||
|
||||
func Test_GetModPath(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
goModPath := utils.GetModPath()
|
||||
fmt.Println(goModPath)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user