mirror of
https://github.com/beego/bee.git
synced 2025-06-12 04:50:40 +00:00
beego pro init
This commit is contained in:
20
internal/app/module/beegopro/config.go
Normal file
20
internal/app/module/beegopro/config.go
Normal file
@ -0,0 +1,20 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"github.com/beego/bee/internal/pkg/utils"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func (c *Container) GenConfig() {
|
||||
if utils.IsExist(c.BeegoProFile) {
|
||||
beeLogger.Log.Fatalf("beego pro toml exist")
|
||||
return
|
||||
}
|
||||
|
||||
err := ioutil.WriteFile("beegopro.toml", []byte(BeegoToml), 0644)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("write beego pro toml err: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
18
internal/app/module/beegopro/constx.go
Normal file
18
internal/app/module/beegopro/constx.go
Normal file
@ -0,0 +1,18 @@
|
||||
package beegopro
|
||||
|
||||
const BeegoToml = `
|
||||
dsn = "root:123456@tcp(127.0.0.1:3306)/beego"
|
||||
driver = "mysql"
|
||||
proType = "default"
|
||||
enableModule = []
|
||||
apiPrefix = "/"
|
||||
gitRemotePath = "https://github.com/beego-dev/beego-pro.git"
|
||||
format = true
|
||||
sourceGen = "text"
|
||||
gitPull = true
|
||||
[models.user]
|
||||
name = ["uid"]
|
||||
orm = ["auto"]
|
||||
comment = ["Uid"]
|
||||
|
||||
`
|
214
internal/app/module/beegopro/container.go
Normal file
214
internal/app/module/beegopro/container.go
Normal file
@ -0,0 +1,214 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/beego/bee/internal/pkg/git"
|
||||
"github.com/beego/bee/internal/pkg/system"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/pelletier/go-toml"
|
||||
"github.com/spf13/viper"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const MDateFormat = "20060102_150405"
|
||||
|
||||
var DefaultBeegoPro = &Container{
|
||||
BeegoProFile: system.CurrentDir + "/beegopro.toml",
|
||||
TimestampFile: system.CurrentDir + "/beegopro.timestamp",
|
||||
GoModFile: system.CurrentDir + "/go.mod",
|
||||
Option: Option{
|
||||
Debug: false,
|
||||
ContextDebug: false,
|
||||
Dsn: "",
|
||||
Driver: "mysql",
|
||||
ProType: "default",
|
||||
ApiPrefix: "/",
|
||||
EnableModule: nil,
|
||||
Models: make(map[string]ModelContent, 0),
|
||||
GitRemotePath: "https://github.com/beego-dev/beego-pro.git",
|
||||
Branch: "master",
|
||||
GitLocalPath: system.BeegoHome + "/beego-pro",
|
||||
EnableFormat: true,
|
||||
SourceGen: "text",
|
||||
EnableGitPull: true,
|
||||
RefreshGitTime: 24 * 3600,
|
||||
Path: map[string]string{
|
||||
"beego": ".",
|
||||
},
|
||||
EnableGomod: true,
|
||||
},
|
||||
GenerateTime: time.Now().Format(MDateFormat),
|
||||
GenerateTimeUnix: time.Now().Unix(),
|
||||
Tmpl: Tmpl{},
|
||||
CurPath: system.CurrentDir,
|
||||
EnableModules: make(map[string]interface{}, 0), // get the user configuration, get the enable module result
|
||||
FunctionOnce: make(map[string]sync.Once, 0), // get the tmpl configuration, get the function once result
|
||||
}
|
||||
|
||||
func (c *Container) Run() {
|
||||
// init git refresh cache time
|
||||
c.initTimestamp()
|
||||
c.initBeegoPro()
|
||||
c.initBeegoTmpl()
|
||||
c.initRender()
|
||||
c.flushTimestamp()
|
||||
}
|
||||
|
||||
func (c *Container) initBeegoPro() {
|
||||
if !utils.IsExist(c.BeegoProFile) {
|
||||
beeLogger.Log.Fatalf("beego pro config is not exist, beego json path: %s", c.BeegoProFile)
|
||||
return
|
||||
}
|
||||
viper.SetConfigFile(c.BeegoProFile)
|
||||
err := viper.ReadInConfig()
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("read beego pro config content, err: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = viper.Unmarshal(&c.Option)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego pro config unmarshal error, err: %s", err.Error())
|
||||
return
|
||||
}
|
||||
if c.Option.Debug {
|
||||
viper.Debug()
|
||||
}
|
||||
|
||||
if c.Option.EnableGomod {
|
||||
if !utils.IsExist(c.GoModFile) {
|
||||
beeLogger.Log.Fatalf("go mod not exist, please create go mod file")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, value := range c.Option.EnableModule {
|
||||
c.EnableModules[value] = struct{}{}
|
||||
}
|
||||
|
||||
if len(c.EnableModules) == 0 {
|
||||
c.EnableModules["*"] = struct{}{}
|
||||
}
|
||||
|
||||
if c.Option.Debug {
|
||||
fmt.Println("c.modules", c.EnableModules)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Container) initBeegoTmpl() {
|
||||
if c.Option.EnableGitPull && (c.GenerateTimeUnix-c.Timestamp.GitCacheLastRefresh > c.Option.RefreshGitTime) {
|
||||
err := git.CloneORPullRepo(c.Option.GitRemotePath, c.Option.GitLocalPath)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego pro git clone or pull repo error, err: %s", err)
|
||||
return
|
||||
}
|
||||
c.Timestamp.GitCacheLastRefresh = c.GenerateTimeUnix
|
||||
}
|
||||
|
||||
tree, err := toml.LoadFile(c.Option.GitLocalPath + "/" + c.Option.ProType + "/bee.toml")
|
||||
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego tmpl exec error, err: %s", err)
|
||||
return
|
||||
}
|
||||
err = tree.Unmarshal(&c.Tmpl)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego tmpl parse error, err: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if c.Option.Debug {
|
||||
spew.Dump("tmpl", c.Tmpl)
|
||||
}
|
||||
|
||||
for _, value := range c.Tmpl.Descriptor {
|
||||
if value.Once == true {
|
||||
c.FunctionOnce[value.SrcName] = sync.Once{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type modelInfo struct {
|
||||
Module string
|
||||
ModelName string
|
||||
Option Option
|
||||
Content ModelContent
|
||||
Descriptor Descriptor
|
||||
TmplPath string
|
||||
GenerateTime string
|
||||
}
|
||||
|
||||
func (c *Container) initRender() {
|
||||
for _, desc := range c.Tmpl.Descriptor {
|
||||
_, allFlag := c.EnableModules["*"]
|
||||
_, moduleFlag := c.EnableModules[desc.Module]
|
||||
if !allFlag && !moduleFlag {
|
||||
continue
|
||||
}
|
||||
|
||||
// model table name, model table schema
|
||||
for modelName, content := range c.Option.Models {
|
||||
m := modelInfo{
|
||||
Module: desc.Module,
|
||||
ModelName: modelName,
|
||||
Content: content,
|
||||
Option: c.Option,
|
||||
Descriptor: desc,
|
||||
TmplPath: c.Tmpl.RenderPath,
|
||||
GenerateTime: c.GenerateTime,
|
||||
}
|
||||
|
||||
// some render exec once
|
||||
syncOnce, flag := c.FunctionOnce[desc.SrcName]
|
||||
if flag {
|
||||
syncOnce.Do(func() {
|
||||
c.renderModel(m)
|
||||
})
|
||||
continue
|
||||
}
|
||||
c.renderModel(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Container) renderModel(m modelInfo) {
|
||||
render := NewRender(m)
|
||||
render.Exec(m.Descriptor.SrcName)
|
||||
if render.Descriptor.IsExistScript() {
|
||||
err := render.Descriptor.ExecScript(c.CurPath)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego exec shell error, err: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Container) initTimestamp() {
|
||||
if utils.IsExist(c.TimestampFile) {
|
||||
tree, err := toml.LoadFile(c.TimestampFile)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego timestamp tmpl exec error, err: %s", err)
|
||||
return
|
||||
}
|
||||
err = tree.Unmarshal(&c.Timestamp)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego timestamp tmpl parse error, err: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
c.Timestamp.Generate = c.GenerateTimeUnix
|
||||
}
|
||||
|
||||
func (c *Container) flushTimestamp() {
|
||||
tomlByte, err := toml.Marshal(c.Timestamp)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("marshal timestamp tmpl parse error, err: %s", err)
|
||||
}
|
||||
err = ioutil.WriteFile(c.TimestampFile, tomlByte, 0644)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("flush timestamp tmpl parse error, err: %s", err)
|
||||
}
|
||||
}
|
35
internal/app/module/beegopro/migration.go
Normal file
35
internal/app/module/beegopro/migration.go
Normal file
@ -0,0 +1,35 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var SQL utils.DocValue
|
||||
|
||||
func (c *Container) Migration(args []string) {
|
||||
c.initBeegoPro()
|
||||
db, err := sql.Open(c.Option.Driver, c.Option.Dsn)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not connect to '%s' database using '%s': %s", c.Option.Driver, c.Option.Dsn, err)
|
||||
return
|
||||
}
|
||||
|
||||
defer db.Close()
|
||||
|
||||
absFile, _ := filepath.Abs(SQL.String())
|
||||
content, err := ioutil.ReadFile(SQL.String())
|
||||
if err != nil {
|
||||
beeLogger.Log.Errorf("read file err %s, abs file %s", err, absFile)
|
||||
}
|
||||
|
||||
result, err := db.Exec(string(content))
|
||||
if err != nil {
|
||||
beeLogger.Log.Errorf("db exec err %s", err)
|
||||
}
|
||||
beeLogger.Log.Infof("db exec info %v", result)
|
||||
|
||||
}
|
58
internal/app/module/beegopro/pongo2.go
Normal file
58
internal/app/module/beegopro/pongo2.go
Normal file
@ -0,0 +1,58 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"github.com/beego/bee/utils"
|
||||
"github.com/flosch/pongo2"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
func init() {
|
||||
_ = pongo2.RegisterFilter("lowerFirst", pongo2LowerFirst)
|
||||
_ = pongo2.RegisterFilter("upperFirst", pongo2UpperFirst)
|
||||
_ = pongo2.RegisterFilter("snakeString", pongo2SnakeString)
|
||||
_ = pongo2.RegisterFilter("camelString", pongo2CamelString)
|
||||
}
|
||||
|
||||
func pongo2LowerFirst(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
|
||||
if in.Len() <= 0 {
|
||||
return pongo2.AsValue(""), nil
|
||||
}
|
||||
t := in.String()
|
||||
r, size := utf8.DecodeRuneInString(t)
|
||||
return pongo2.AsValue(strings.ToLower(string(r)) + t[size:]), nil
|
||||
}
|
||||
|
||||
func pongo2UpperFirst(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
|
||||
if in.Len() <= 0 {
|
||||
return pongo2.AsValue(""), nil
|
||||
}
|
||||
t := in.String()
|
||||
return pongo2.AsValue(strings.Replace(t, string(t[0]), strings.ToUpper(string(t[0])), 1)), nil
|
||||
}
|
||||
|
||||
// snake string, XxYy to xx_yy
|
||||
func pongo2SnakeString(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
|
||||
if in.Len() <= 0 {
|
||||
return pongo2.AsValue(""), nil
|
||||
}
|
||||
t := in.String()
|
||||
return pongo2.AsValue(utils.SnakeString(t)), nil
|
||||
}
|
||||
|
||||
// snake string, XxYy to xx_yy
|
||||
func pongo2CamelString(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
|
||||
if in.Len() <= 0 {
|
||||
return pongo2.AsValue(""), nil
|
||||
}
|
||||
t := in.String()
|
||||
return pongo2.AsValue(utils.CamelString(t)), nil
|
||||
}
|
||||
|
||||
func upperFirst(str string) string {
|
||||
return strings.Replace(str, string(str[0]), strings.ToUpper(string(str[0])), 1)
|
||||
}
|
||||
|
||||
func lowerFirst(str string) string {
|
||||
return strings.Replace(str, string(str[0]), strings.ToLower(string(str[0])), 1)
|
||||
}
|
123
internal/app/module/beegopro/render.go
Normal file
123
internal/app/module/beegopro/render.go
Normal file
@ -0,0 +1,123 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"github.com/beego/bee/internal/pkg/system"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/smartwalle/pongo2render"
|
||||
"path"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// render
|
||||
type RenderFile struct {
|
||||
*pongo2render.Render
|
||||
Context pongo2.Context
|
||||
GenerateTime string
|
||||
Option Option
|
||||
ModelName string
|
||||
PackageName string
|
||||
FlushFile string
|
||||
PkgPath string
|
||||
TmplPath string
|
||||
Descriptor Descriptor
|
||||
}
|
||||
|
||||
func NewRender(m modelInfo) *RenderFile {
|
||||
var (
|
||||
pathCtx pongo2.Context
|
||||
newDescriptor Descriptor
|
||||
)
|
||||
|
||||
// parse descriptor, get flush file path, beego path, etc...
|
||||
newDescriptor, pathCtx = m.Descriptor.Parse(m.ModelName, m.Option.Path)
|
||||
|
||||
obj := &RenderFile{
|
||||
Context: make(pongo2.Context, 0),
|
||||
Option: m.Option,
|
||||
ModelName: m.ModelName,
|
||||
GenerateTime: m.GenerateTime,
|
||||
Descriptor: newDescriptor,
|
||||
}
|
||||
|
||||
obj.FlushFile = newDescriptor.DstPath
|
||||
|
||||
// new render
|
||||
obj.Render = pongo2render.NewRender(path.Join(obj.Option.GitLocalPath, obj.Option.ProType, m.TmplPath))
|
||||
|
||||
filePath := path.Dir(obj.FlushFile)
|
||||
err := createPath(filePath)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not create the controllers directory: %s", err)
|
||||
}
|
||||
// get go package path
|
||||
obj.PkgPath = getPackagePath()
|
||||
|
||||
relativePath, err := filepath.Rel(system.CurrentDir, obj.FlushFile)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not get the relative path: %s", err)
|
||||
}
|
||||
|
||||
modelSchemas := m.Content.ToModelSchemas()
|
||||
camelPrimaryKey := modelSchemas.GetPrimaryKey()
|
||||
importMaps := make(map[string]struct{}, 0)
|
||||
if modelSchemas.IsExistTime() {
|
||||
importMaps["time"] = struct{}{}
|
||||
}
|
||||
obj.PackageName = filepath.Base(filepath.Dir(relativePath))
|
||||
beeLogger.Log.Infof("Using '%s' as name", obj.ModelName)
|
||||
|
||||
beeLogger.Log.Infof("Using '%s' as package name from %s", obj.ModelName, obj.PackageName)
|
||||
|
||||
// package
|
||||
obj.SetContext("packageName", obj.PackageName)
|
||||
obj.SetContext("packageImports", importMaps)
|
||||
|
||||
// todo optimize
|
||||
// todo Set the beego directory, should recalculate the package
|
||||
if pathCtx["pathRelBeego"] == "." {
|
||||
obj.SetContext("packagePath", obj.PkgPath)
|
||||
} else {
|
||||
obj.SetContext("packagePath", obj.PkgPath+"/"+pathCtx["pathRelBeego"].(string))
|
||||
}
|
||||
|
||||
obj.SetContext("packageMod", obj.PkgPath)
|
||||
|
||||
obj.SetContext("modelSchemas", modelSchemas)
|
||||
obj.SetContext("modelPrimaryKey", camelPrimaryKey)
|
||||
|
||||
for key, value := range pathCtx {
|
||||
obj.SetContext(key, value)
|
||||
}
|
||||
|
||||
obj.SetContext("apiPrefix", obj.Option.ApiPrefix)
|
||||
obj.SetContext("generateTime", obj.GenerateTime)
|
||||
|
||||
if obj.Option.ContextDebug {
|
||||
spew.Dump(obj.Context)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
func (r *RenderFile) SetContext(key string, value interface{}) {
|
||||
r.Context[key] = value
|
||||
}
|
||||
|
||||
func (r *RenderFile) Exec(name string) {
|
||||
var (
|
||||
buf string
|
||||
err error
|
||||
)
|
||||
buf, err = r.Render.Template(name).Execute(r.Context)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not create the %s render tmpl: %s", name, err)
|
||||
return
|
||||
}
|
||||
err = r.write(r.FlushFile, buf)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not create file: %s", err)
|
||||
return
|
||||
}
|
||||
beeLogger.Log.Infof("create file '%s' from %s", r.FlushFile, r.PackageName)
|
||||
}
|
151
internal/app/module/beegopro/schema.go
Normal file
151
internal/app/module/beegopro/schema.go
Normal file
@ -0,0 +1,151 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/beego/bee/internal/pkg/command"
|
||||
"github.com/beego/bee/internal/pkg/system"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/smartwalle/pongo2render"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// store all data
|
||||
type Container struct {
|
||||
BeegoProFile string // beego pro toml
|
||||
TimestampFile string // store ts file
|
||||
GoModFile string // go mod file
|
||||
Option Option // user option
|
||||
Tmpl Tmpl // remote tmpl
|
||||
CurPath string // user current path
|
||||
EnableModules map[string]interface{} // beego pro provider a collection of module
|
||||
FunctionOnce map[string]sync.Once // exec function once
|
||||
Timestamp Timestamp
|
||||
GenerateTime string
|
||||
GenerateTimeUnix int64
|
||||
}
|
||||
|
||||
// user option
|
||||
type Option struct {
|
||||
Debug bool `json:"debug"`
|
||||
ContextDebug bool `json:"contextDebug"`
|
||||
Dsn string `json:"dsn"`
|
||||
Driver string `json:"driver"`
|
||||
ProType string `json:"proType"`
|
||||
ApiPrefix string `json:"apiPrefix"`
|
||||
EnableModule []string `json:"enableModule"`
|
||||
Models map[string]ModelContent `json:"models"`
|
||||
GitRemotePath string `json:"gitRemotePath"`
|
||||
Branch string `json:"branch"`
|
||||
GitLocalPath string `json:"gitLocalPath"`
|
||||
EnableFormat bool `json:"enableFormat"`
|
||||
SourceGen string `json:"sourceGen"`
|
||||
EnableGitPull bool `json:"enbaleGitPull"`
|
||||
Path map[string]string `json:"path"`
|
||||
EnableGomod bool `json:"enableGomod"`
|
||||
RefreshGitTime int64 `json:"refreshGitTime"`
|
||||
Extend map[string]string `json:"extend"` // extend user data
|
||||
}
|
||||
|
||||
type BeegoPro struct {
|
||||
FilePath string
|
||||
CurPath string
|
||||
Option Option
|
||||
}
|
||||
|
||||
// tmpl option
|
||||
type Tmpl struct {
|
||||
RenderPath string `toml:"renderPath"`
|
||||
Descriptor []Descriptor
|
||||
}
|
||||
|
||||
type Descriptor struct {
|
||||
Module string `toml:"module"`
|
||||
SrcName string `toml:"srcName"`
|
||||
DstPath string `toml:"dstPath"`
|
||||
Once bool `toml:"once"`
|
||||
Script string `toml:"script"`
|
||||
}
|
||||
|
||||
func (descriptor Descriptor) Parse(modelName string, paths map[string]string) (newDescriptor Descriptor, ctx pongo2.Context) {
|
||||
var (
|
||||
err error
|
||||
relativeDstPath string
|
||||
absFile string
|
||||
relPath string
|
||||
)
|
||||
|
||||
newDescriptor = descriptor
|
||||
render := pongo2render.NewRender("")
|
||||
ctx = make(pongo2.Context, 0)
|
||||
for key, value := range paths {
|
||||
absFile, err = filepath.Abs(value)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("absolute path error %s from key %s and value %s", err, key, value)
|
||||
}
|
||||
relPath, err = filepath.Rel(system.CurrentDir, absFile)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not get the relative path: %s", err)
|
||||
}
|
||||
// user input path
|
||||
ctx["path"+utils.CamelCase(key)] = value
|
||||
// relativePath
|
||||
ctx["pathRel"+utils.CamelCase(key)] = relPath
|
||||
}
|
||||
ctx["modelName"] = lowerFirst(utils.CamelString(modelName))
|
||||
relativeDstPath, err = render.TemplateFromString(descriptor.DstPath).Execute(ctx)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego tmpl exec error, err: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
newDescriptor.DstPath, err = filepath.Abs(relativeDstPath)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("absolute path error %s from flush file %s", err, relativeDstPath)
|
||||
}
|
||||
|
||||
newDescriptor.Script, err = render.TemplateFromString(descriptor.Script).Execute(ctx)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("parse script %s, error %s", descriptor.Script, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (descriptor Descriptor) IsExistScript() bool {
|
||||
if descriptor.Script != "" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d Descriptor) ExecScript(path string) (err error) {
|
||||
arr := strings.Split(d.Script, " ")
|
||||
if len(arr) == 0 {
|
||||
return
|
||||
}
|
||||
fmt.Println("path------>", path)
|
||||
|
||||
stdout, stderr, err := command.ExecCmdDir(path, arr[0], arr[1:]...)
|
||||
if err != nil {
|
||||
return concatenateError(err, stderr)
|
||||
}
|
||||
|
||||
beeLogger.Log.Info(stdout)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Timestamp struct {
|
||||
GitCacheLastRefresh int64 `toml:"gitCacheLastRefresh"`
|
||||
Generate int64 `toml:"generate"`
|
||||
}
|
||||
|
||||
func concatenateError(err error, stderr string) error {
|
||||
if len(stderr) == 0 {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("%v: %s", err, stderr)
|
||||
}
|
141
internal/app/module/beegopro/schema_model.go
Normal file
141
internal/app/module/beegopro/schema_model.go
Normal file
@ -0,0 +1,141 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ModelContent struct {
|
||||
Names []string
|
||||
Orms []string
|
||||
Comments []string
|
||||
Extends []string
|
||||
}
|
||||
|
||||
type ModelInfo struct {
|
||||
Name string `json:"name"` // mysql name
|
||||
InputType string `json:"inputType"` // user input type
|
||||
MysqlType string `json:"mysqlType"` // mysql type
|
||||
GoType string `json:"goType"` // go type
|
||||
Orm string `json:"orm"` // orm tag
|
||||
Comment string `json:"comment"` // mysql comment
|
||||
Extend string `json:"extend"` // user extend info
|
||||
}
|
||||
|
||||
func (m ModelInfo) GetColumnKey() (columnKey string) {
|
||||
if m.InputType == "auto" || m.Orm == "pk" {
|
||||
columnKey = "PRI"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m ModelInfo) IsPrimaryKey() (flag bool) {
|
||||
if m.Orm == "auto" || m.Orm == "pk" || strings.ToLower(m.Name) == "id" {
|
||||
flag = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (content ModelContent) ToModelInfoArr() (output []ModelInfo) {
|
||||
namesLen := len(content.Names)
|
||||
ormsLen := len(content.Orms)
|
||||
commentsLen := len(content.Comments)
|
||||
if namesLen != ormsLen && namesLen != commentsLen {
|
||||
beeLogger.Log.Fatalf("length error, namesLen is %d, ormsLen is %d, commentsLen is %d", namesLen, ormsLen, commentsLen)
|
||||
}
|
||||
extendLen := len(content.Extends)
|
||||
if extendLen != 0 && extendLen != namesLen {
|
||||
beeLogger.Log.Fatalf("extend length error, namesLen is %d, extendsLen is %d", namesLen, extendLen)
|
||||
}
|
||||
|
||||
output = make([]ModelInfo, 0)
|
||||
for i, name := range content.Names {
|
||||
comment := content.Comments[i]
|
||||
if comment == "" {
|
||||
comment = name
|
||||
}
|
||||
inputType, goType, mysqlType, ormTag := getModelType(content.Orms[i])
|
||||
|
||||
m := ModelInfo{
|
||||
Name: name,
|
||||
InputType: inputType,
|
||||
GoType: goType,
|
||||
Orm: ormTag,
|
||||
Comment: comment,
|
||||
MysqlType: mysqlType,
|
||||
Extend: "",
|
||||
}
|
||||
// extend value
|
||||
if extendLen != 0 {
|
||||
m.Extend = content.Extends[i]
|
||||
}
|
||||
output = append(output, m)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (content ModelContent) ToModelSchemas() (output ModelSchemas) {
|
||||
modelInfoArr := content.ToModelInfoArr()
|
||||
|
||||
output = make(ModelSchemas, 0)
|
||||
for i, value := range modelInfoArr {
|
||||
if i == 0 && !value.IsPrimaryKey() {
|
||||
inputType, goType, mysqlType, ormTag := getModelType("auto")
|
||||
output = append(output, &ModelSchema{
|
||||
Name: "id",
|
||||
InputType: inputType,
|
||||
ColumnKey: "PRI",
|
||||
Comment: "ID",
|
||||
MysqlType: mysqlType,
|
||||
GoType: goType,
|
||||
OrmTag: ormTag,
|
||||
Extend: value.Extend,
|
||||
})
|
||||
}
|
||||
|
||||
modelSchema := &ModelSchema{
|
||||
Name: value.Name,
|
||||
InputType: value.InputType,
|
||||
ColumnKey: value.GetColumnKey(),
|
||||
MysqlType: value.MysqlType,
|
||||
Comment: value.Comment,
|
||||
GoType: value.GoType,
|
||||
OrmTag: value.Orm,
|
||||
}
|
||||
output = append(output, modelSchema)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ModelSchema struct {
|
||||
Name string // column name
|
||||
InputType string // user input type
|
||||
MysqlType string // mysql type
|
||||
ColumnKey string // PRI
|
||||
Comment string // comment
|
||||
GoType string // go type
|
||||
OrmTag string // orm tag
|
||||
Extend string
|
||||
}
|
||||
|
||||
type ModelSchemas []*ModelSchema
|
||||
|
||||
func (m ModelSchemas) IsExistTime() bool {
|
||||
for _, value := range m {
|
||||
if value.InputType == "datetime" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m ModelSchemas) GetPrimaryKey() string {
|
||||
camelPrimaryKey := ""
|
||||
for _, value := range m {
|
||||
if value.ColumnKey == "PRI" {
|
||||
camelPrimaryKey = utils.CamelString(value.Name)
|
||||
}
|
||||
}
|
||||
return camelPrimaryKey
|
||||
}
|
185
internal/app/module/beegopro/util.go
Normal file
185
internal/app/module/beegopro/util.go
Normal file
@ -0,0 +1,185 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/beego/bee/internal/pkg/utils"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"go/format"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// write to file
|
||||
func (c *RenderFile) write(filename string, buf string) (err error) {
|
||||
if utils.IsExist(filename) && !isNeedOverwrite(filename) {
|
||||
return
|
||||
}
|
||||
|
||||
filePath := path.Dir(filename)
|
||||
err = createPath(filePath)
|
||||
if err != nil {
|
||||
err = errors.New("write create path " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
filePathBak := filePath + "/bak"
|
||||
err = createPath(filePathBak)
|
||||
if err != nil {
|
||||
err = errors.New("write create path bak " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
name := path.Base(filename)
|
||||
|
||||
if utils.IsExist(filename) {
|
||||
bakName := fmt.Sprintf("%s/%s.%s.bak", filePathBak, name, time.Now().Format("2006.01.02.15.04.05"))
|
||||
beeLogger.Log.Infof("bak file '%s'", bakName)
|
||||
if err := os.Rename(filename, bakName); err != nil {
|
||||
err = errors.New("file is bak error, path is " + bakName)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
file, err := os.Create(filename)
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
err = errors.New("write create file " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
output := []byte(buf)
|
||||
|
||||
if c.Option.EnableFormat && filepath.Ext(filename) == ".go" {
|
||||
// format code
|
||||
var bts []byte
|
||||
bts, err = format.Source([]byte(buf))
|
||||
if err != nil {
|
||||
err = errors.New("format buf error " + err.Error())
|
||||
return
|
||||
}
|
||||
output = bts
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(filename, output, 0644)
|
||||
if err != nil {
|
||||
err = errors.New("write write file " + err.Error())
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func isNeedOverwrite(fileName string) (flag bool) {
|
||||
seg := "//"
|
||||
ext := filepath.Ext(fileName)
|
||||
if ext == "sql" {
|
||||
seg = "--"
|
||||
}
|
||||
|
||||
f, err := os.Open(fileName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
overwrite := ""
|
||||
var contentByte []byte
|
||||
contentByte, err = ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, s := range strings.Split(string(contentByte), "\n") {
|
||||
s = strings.TrimSpace(strings.TrimPrefix(s, seg))
|
||||
if strings.HasPrefix(s, "@BeeOverwrite") {
|
||||
overwrite = strings.TrimSpace(s[len("@BeeOverwrite"):])
|
||||
}
|
||||
}
|
||||
if strings.ToLower(overwrite) == "yes" {
|
||||
flag = true
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// createPath 调用os.MkdirAll递归创建文件夹
|
||||
func createPath(filePath string) error {
|
||||
if !utils.IsExist(filePath) {
|
||||
err := os.MkdirAll(filePath, os.ModePerm)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPackagePath() (packagePath string) {
|
||||
f, err := os.Open("go.mod")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
var contentByte []byte
|
||||
contentByte, err = ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, s := range strings.Split(string(contentByte), "\n") {
|
||||
packagePath = strings.TrimSpace(strings.TrimPrefix(s, "module"))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getModelType(orm string) (inputType, goType, mysqlType, tag string) {
|
||||
kv := strings.SplitN(orm, ",", 2)
|
||||
inputType = kv[0]
|
||||
switch inputType {
|
||||
case "string":
|
||||
goType = "string"
|
||||
tag = "size(255)"
|
||||
// todo use orm data
|
||||
mysqlType = "varchar(255) NOT NULL"
|
||||
case "text":
|
||||
goType = "string"
|
||||
tag = "type(longtext)"
|
||||
mysqlType = "longtext NOT NULL"
|
||||
case "auto":
|
||||
goType = "int"
|
||||
tag = "auto"
|
||||
mysqlType = "int(11) NOT NULL AUTO_INCREMENT"
|
||||
case "pk":
|
||||
goType = "int"
|
||||
tag = "pk"
|
||||
mysqlType = "int(11) NOT NULL"
|
||||
case "datetime":
|
||||
goType = "time.Time"
|
||||
tag = "type(datetime)"
|
||||
mysqlType = "datetime NOT NULL"
|
||||
case "int", "int8", "int16", "int32", "int64":
|
||||
fallthrough
|
||||
case "uint", "uint8", "uint16", "uint32", "uint64":
|
||||
goType = inputType
|
||||
tag = ""
|
||||
mysqlType = "int(11) DEFAULT NULL"
|
||||
case "bool":
|
||||
goType = inputType
|
||||
tag = ""
|
||||
mysqlType = "int(11) DEFAULT NULL"
|
||||
case "float32", "float64":
|
||||
goType = inputType
|
||||
tag = ""
|
||||
mysqlType = "float NOT NULL"
|
||||
case "float":
|
||||
goType = "float64"
|
||||
tag = ""
|
||||
mysqlType = "float NOT NULL"
|
||||
default:
|
||||
beeLogger.Log.Fatalf("not support type: %s", inputType)
|
||||
}
|
||||
// user set orm tag
|
||||
if len(kv) == 2 {
|
||||
tag = orm
|
||||
}
|
||||
return
|
||||
}
|
65
internal/pkg/command/cmd.go
Normal file
65
internal/pkg/command/cmd.go
Normal file
@ -0,0 +1,65 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ExecCmdDirBytes executes system command in given directory
|
||||
// and return stdout, stderr in bytes type, along with possible error.
|
||||
func ExecCmdDirBytes(dir, cmdName string, args ...string) ([]byte, []byte, error) {
|
||||
bufOut := new(bytes.Buffer)
|
||||
bufErr := new(bytes.Buffer)
|
||||
|
||||
cmd := exec.Command(cmdName, args...)
|
||||
cmd.Dir = dir
|
||||
cmd.Stdout = bufOut
|
||||
cmd.Stderr = bufErr
|
||||
|
||||
err := cmd.Run()
|
||||
return bufOut.Bytes(), bufErr.Bytes(), err
|
||||
}
|
||||
|
||||
// ExecCmdBytes executes system command
|
||||
// and return stdout, stderr in bytes type, along with possible error.
|
||||
func ExecCmdBytes(cmdName string, args ...string) ([]byte, []byte, error) {
|
||||
return ExecCmdDirBytes("", cmdName, args...)
|
||||
}
|
||||
|
||||
// ExecCmdDir executes system command in given directory
|
||||
// and return stdout, stderr in string type, along with possible error.
|
||||
func ExecCmdDir(dir, cmdName string, args ...string) (string, string, error) {
|
||||
bufOut, bufErr, err := ExecCmdDirBytes(dir, cmdName, args...)
|
||||
return string(bufOut), string(bufErr), err
|
||||
}
|
||||
|
||||
// ExecCmd executes system command
|
||||
// and return stdout, stderr in string type, along with possible error.
|
||||
func ExecCmd(cmdName string, args ...string) (string, string, error) {
|
||||
return ExecCmdDir("", cmdName, args...)
|
||||
}
|
||||
|
||||
// 版本对比 v1比v2大返回1,小于返回-1,等于返回0
|
||||
func VerCompare(ver1, ver2 string) int {
|
||||
ver1 = strings.TrimLeft(ver1, "ver") // 清除v,e,r
|
||||
ver2 = strings.TrimLeft(ver2, "ver") // 清除v,e,r
|
||||
p1 := strings.Split(ver1, ".")
|
||||
p2 := strings.Split(ver2, ".")
|
||||
|
||||
ver1 = ""
|
||||
for _, v := range p1 {
|
||||
iv, _ := strconv.Atoi(v)
|
||||
ver1 = fmt.Sprintf("%s%04d", ver1, iv)
|
||||
}
|
||||
|
||||
ver2 = ""
|
||||
for _, v := range p2 {
|
||||
iv, _ := strconv.Atoi(v)
|
||||
ver2 = fmt.Sprintf("%s%04d", ver2, iv)
|
||||
}
|
||||
|
||||
return strings.Compare(ver1, ver2)
|
||||
}
|
231
internal/pkg/git/repository.go
Normal file
231
internal/pkg/git/repository.go
Normal file
@ -0,0 +1,231 @@
|
||||
package git
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/beego/bee/internal/pkg/command"
|
||||
"github.com/beego/bee/internal/pkg/utils"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 获取某项目代码库的标签列表
|
||||
func GetTags(repoPath string, limit int) ([]string, error) {
|
||||
repo, err := OpenRepository(repoPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = repo.Pull()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list, err := repo.GetTags()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(list) > limit {
|
||||
list = list[0:limit]
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// clone repo
|
||||
func CloneRepo(url string, dst string) (err error) {
|
||||
if utils.IsExist(dst) {
|
||||
return errors.New("dst is not empty, dst is " + dst)
|
||||
}
|
||||
if !utils.Mkdir(dst) {
|
||||
err = errors.New("make dir error, dst is " + dst)
|
||||
return
|
||||
}
|
||||
|
||||
beeLogger.Log.Info("start git clone from " + url + ", to dst at " + dst)
|
||||
_, stderr, err := command.ExecCmd("git", "clone", url, dst)
|
||||
|
||||
if err != nil {
|
||||
beeLogger.Log.Error("error git clone from " + url + ", to dst at " + dst)
|
||||
return concatenateError(err, stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CloneORPullRepo
|
||||
func CloneORPullRepo(url string, dst string) error {
|
||||
if !utils.IsDir(dst) {
|
||||
return CloneRepo(url, dst)
|
||||
} else {
|
||||
//projectName, err := getGitProjectName(url)
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
|
||||
//fmt.Println("dst------>", dst)
|
||||
//projectDir := dst + "/" + projectName
|
||||
utils.Mkdir(dst)
|
||||
|
||||
repo, err := OpenRepository(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return repo.Pull()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
func CloneRepoBranch(branch string, url string, dst string) error {
|
||||
_, stderr, err := command.ExecCmd("git", "clone", "-b", branch, url, dst)
|
||||
if err != nil {
|
||||
return concatenateError(err, stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SortTag ...
|
||||
type SortTag struct {
|
||||
data []string
|
||||
}
|
||||
|
||||
// Len ...
|
||||
func (t *SortTag) Len() int {
|
||||
return len(t.data)
|
||||
}
|
||||
|
||||
// Swap ...
|
||||
func (t *SortTag) Swap(i, j int) {
|
||||
t.data[i], t.data[j] = t.data[j], t.data[i]
|
||||
}
|
||||
|
||||
// Less ...
|
||||
func (t *SortTag) Less(i, j int) bool {
|
||||
return command.VerCompare(t.data[i], t.data[j]) == 1
|
||||
}
|
||||
|
||||
// Sort ...
|
||||
func (t *SortTag) Sort() []string {
|
||||
sort.Sort(t)
|
||||
return t.data
|
||||
}
|
||||
|
||||
// Repository ...
|
||||
type Repository struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// OpenRepository ...
|
||||
func OpenRepository(repoPath string) (*Repository, error) {
|
||||
repoPath, err := filepath.Abs(repoPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !utils.IsDir(repoPath) {
|
||||
return nil, errors.New("no such file or directory")
|
||||
}
|
||||
|
||||
return &Repository{Path: repoPath}, nil
|
||||
}
|
||||
|
||||
// 拉取代码
|
||||
func (repo *Repository) Pull() error {
|
||||
beeLogger.Log.Info("git pull " + repo.Path)
|
||||
_, stderr, err := command.ExecCmdDir(repo.Path, "git", "pull")
|
||||
if err != nil {
|
||||
return concatenateError(err, stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取tag列表
|
||||
func (repo *Repository) GetTags() ([]string, error) {
|
||||
stdout, stderr, err := command.ExecCmdDir(repo.Path, "git", "tag", "-l")
|
||||
if err != nil {
|
||||
return nil, concatenateError(err, stderr)
|
||||
}
|
||||
tags := strings.Split(stdout, "\n")
|
||||
tags = tags[:len(tags)-1]
|
||||
|
||||
so := &SortTag{data: tags}
|
||||
return so.Sort(), nil
|
||||
}
|
||||
|
||||
// 获取两个版本之间的修改日志
|
||||
func (repo *Repository) GetChangeLogs(startVer, endVer string) ([]string, error) {
|
||||
// git log --pretty=format:"%cd %cn: %s" --date=iso v1.8.0...v1.9.0
|
||||
stdout, stderr, err := command.ExecCmdDir(repo.Path, "git", "log", "--pretty=format:%cd %cn: %s", "--date=iso", startVer+"..."+endVer)
|
||||
if err != nil {
|
||||
return nil, concatenateError(err, stderr)
|
||||
}
|
||||
|
||||
logs := strings.Split(stdout, "\n")
|
||||
return logs, nil
|
||||
}
|
||||
|
||||
// 获取两个版本之间的差异文件列表
|
||||
func (repo *Repository) GetChangeFiles(startVer, endVer string, onlyFile bool) ([]string, error) {
|
||||
// git diff --name-status -b v1.8.0 v1.9.0
|
||||
param := "--name-status"
|
||||
if onlyFile {
|
||||
param = "--name-only"
|
||||
}
|
||||
stdout, stderr, err := command.ExecCmdDir(repo.Path, "git", "diff", param, "-b", startVer, endVer)
|
||||
if err != nil {
|
||||
return nil, concatenateError(err, stderr)
|
||||
}
|
||||
lines := strings.Split(stdout, "\n")
|
||||
return lines[:len(lines)-1], nil
|
||||
}
|
||||
|
||||
// 获取两个版本间的新增或修改的文件数量
|
||||
func (repo *Repository) GetDiffFileCount(startVer, endVer string) (int, error) {
|
||||
cmd := "git diff --name-status -b " + startVer + " " + endVer + " |grep -v ^D |wc -l"
|
||||
stdout, stderr, err := command.ExecCmdDir(repo.Path, "/bin/bash", "-c", cmd)
|
||||
if err != nil {
|
||||
return 0, concatenateError(err, stderr)
|
||||
}
|
||||
count, _ := strconv.Atoi(strings.TrimSpace(stdout))
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// 导出版本到tar包
|
||||
func (repo *Repository) Export(startVer, endVer string, filename string) error {
|
||||
// git archive --format=tar.gz $endVer $(git diff --name-status -b $beginVer $endVer |grep -v ^D |grep -v Upgrade/ |awk '{print $2}') -o $tmpFile
|
||||
|
||||
cmd := ""
|
||||
if startVer == "" {
|
||||
cmd = "git archive --format=tar " + endVer + " | gzip > " + filename
|
||||
} else {
|
||||
cmd = "git archive --format=tar " + endVer + " $(dgit diff --name-status -b " + startVer + " " + endVer + "|grep -v ^D |awk '{print $2}') | gzip > " + filename
|
||||
}
|
||||
|
||||
_, stderr, err := command.ExecCmdDir(repo.Path, "/bin/bash", "-c", cmd)
|
||||
|
||||
if err != nil {
|
||||
return concatenateError(err, stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func concatenateError(err error, stderr string) error {
|
||||
if len(stderr) == 0 {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("%v: %s", err, stderr)
|
||||
}
|
||||
|
||||
// getGitProjectName 获取项目名称
|
||||
func getGitProjectName(url string) (name string, err error) {
|
||||
if !strings.Contains(url, ".git") {
|
||||
return "", errors.New("Project address does not contain .git")
|
||||
}
|
||||
fileSlice := strings.Split(url, "/")
|
||||
projectName := fileSlice[len(fileSlice)-1]
|
||||
if projectName == "" {
|
||||
return "", errors.New("Project name does not exist")
|
||||
}
|
||||
|
||||
nameSlice := strings.Split(projectName, ".git")
|
||||
|
||||
return nameSlice[0], nil
|
||||
}
|
22
internal/pkg/system/system.go
Normal file
22
internal/pkg/system/system.go
Normal file
@ -0,0 +1,22 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Bee System Params ...
|
||||
var (
|
||||
Usr, _ = user.Current()
|
||||
BeegoHome = filepath.Join(Usr.HomeDir, "/.beego")
|
||||
CurrentDir = getCurrentDirectory()
|
||||
GoPath = os.Getenv("GOPATH")
|
||||
)
|
||||
|
||||
func getCurrentDirectory() string {
|
||||
if dir, err := os.Getwd(); err == nil {
|
||||
return dir
|
||||
}
|
||||
return ""
|
||||
}
|
37
internal/pkg/utils/file.go
Normal file
37
internal/pkg/utils/file.go
Normal file
@ -0,0 +1,37 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Mkdir ...
|
||||
func Mkdir(dir string) bool {
|
||||
if dir == "" {
|
||||
beeLogger.Log.Fatalf("The directory is empty")
|
||||
return false
|
||||
}
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not create the directory: %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
beeLogger.Log.Infof("Create %s Success!", dir)
|
||||
return true
|
||||
}
|
||||
|
||||
// IsDir ...
|
||||
func IsDir(dir string) bool {
|
||||
f, e := os.Stat(dir)
|
||||
if e != nil {
|
||||
return false
|
||||
}
|
||||
return f.IsDir()
|
||||
}
|
||||
|
||||
// IsExist returns whether a file or directory exists.
|
||||
func IsExist(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
Reference in New Issue
Block a user