first commit
This commit is contained in:
parent
dcd6422c3b
commit
136f31f093
|
@ -17,6 +17,7 @@ func AddKernelCommands(root *cobra.Command) {
|
|||
root.AddCommand(initProviderCommand())
|
||||
root.AddCommand(initCmdCommand())
|
||||
root.AddCommand(initMiddlewareCommand())
|
||||
root.AddCommand(initNewCommand())
|
||||
}
|
||||
|
||||
// 封装通用的命令执行器
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/google/go-github/v39/github"
|
||||
"github.com/spf13/cast"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Superdanda/hade/framework/cobra"
|
||||
"github.com/Superdanda/hade/framework/util"
|
||||
)
|
||||
|
||||
// new相关的名称
|
||||
func initNewCommand() *cobra.Command {
|
||||
return newCommand
|
||||
}
|
||||
|
||||
// 创建一个新应用
|
||||
var newCommand = &cobra.Command{
|
||||
Use: "new",
|
||||
Aliases: []string{"create", "init"},
|
||||
Short: "创建一个新的应用",
|
||||
RunE: func(c *cobra.Command, args []string) error {
|
||||
currentPath := util.GetExecDirectory()
|
||||
|
||||
var name string
|
||||
var folder string
|
||||
var mod string
|
||||
var version string
|
||||
var release *github.RepositoryRelease
|
||||
{
|
||||
prompt := &survey.Input{
|
||||
Message: "请输入目录名称:",
|
||||
}
|
||||
err := survey.AskOne(prompt, &name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
folder = filepath.Join(currentPath, name)
|
||||
if util.Exists(folder) {
|
||||
isForce := false
|
||||
prompt2 := &survey.Confirm{
|
||||
Message: "目录" + folder + "已经存在,是否删除重新创建?(确认后立刻执行删除操作!)",
|
||||
Default: false,
|
||||
}
|
||||
err := survey.AskOne(prompt2, &isForce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isForce {
|
||||
if err := os.RemoveAll(folder); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
fmt.Println("目录已存在,创建应用失败")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
prompt := &survey.Input{
|
||||
Message: "请输入模块名称(go.mod中的module, 默认为文件夹名称):",
|
||||
}
|
||||
err := survey.AskOne(prompt, &mod)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if mod == "" {
|
||||
mod = name
|
||||
}
|
||||
}
|
||||
{
|
||||
// 获取hade的版本
|
||||
client := github.NewClient(nil)
|
||||
prompt := &survey.Input{
|
||||
Message: "请输入版本名称(参考 https://github.com/Superdanda/hade/releases,默认为最新版本):",
|
||||
}
|
||||
err := survey.AskOne(prompt, &version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if version != "" {
|
||||
// 确认版本是否正确
|
||||
release, _, err = client.Repositories.GetReleaseByTag(context.Background(), "Superdanda", "hade", version)
|
||||
if err != nil || release == nil {
|
||||
fmt.Println("版本不存在,创建应用失败,请参考 https://github.com/Superdanda/hade/releases")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if version == "" {
|
||||
release, _, err = client.Repositories.GetLatestRelease(context.Background(), "gohade", "hade")
|
||||
version = release.GetTagName()
|
||||
}
|
||||
}
|
||||
fmt.Println("====================================================")
|
||||
fmt.Println("开始进行创建应用操作")
|
||||
fmt.Println("创建目录:", folder)
|
||||
fmt.Println("应用名称:", mod)
|
||||
fmt.Println("hade框架版本:", release.GetTagName())
|
||||
|
||||
templateFolder := filepath.Join(currentPath, "template-hade-"+version+"-"+cast.ToString(time.Now().Unix()))
|
||||
os.Mkdir(templateFolder, os.ModePerm)
|
||||
fmt.Println("创建临时目录", templateFolder)
|
||||
|
||||
// 拷贝template项目
|
||||
url := release.GetZipballURL()
|
||||
err := util.DownloadFile(filepath.Join(templateFolder, "template.zip"), url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("下载zip包到template.zip")
|
||||
|
||||
_, err = util.Unzip(filepath.Join(templateFolder, "template.zip"), templateFolder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 获取folder下的gohade-hade-xxx相关解压目录
|
||||
fInfos, err := ioutil.ReadDir(templateFolder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, fInfo := range fInfos {
|
||||
// 找到解压后的文件夹
|
||||
if fInfo.IsDir() && strings.Contains(fInfo.Name(), "gohade-hade-") {
|
||||
if err := os.Rename(filepath.Join(templateFolder, fInfo.Name()), folder); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("解压zip包")
|
||||
|
||||
if err := os.RemoveAll(templateFolder); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("删除临时文件夹", templateFolder)
|
||||
|
||||
os.RemoveAll(path.Join(folder, ".git"))
|
||||
fmt.Println("删除.git目录")
|
||||
|
||||
// 删除framework 目录
|
||||
os.RemoveAll(path.Join(folder, "framework"))
|
||||
fmt.Println("删除framework目录")
|
||||
|
||||
filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
c, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if path == filepath.Join(folder, "go.mod") {
|
||||
fmt.Println("更新文件:" + path)
|
||||
c = bytes.ReplaceAll(c, []byte("module github.com/Superdanda/hade"), []byte("module "+mod))
|
||||
c = bytes.ReplaceAll(c, []byte("require ("), []byte("require (\n\tgithub.com/Superdanda/hade "+version))
|
||||
err = ioutil.WriteFile(path, c, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
isContain := bytes.Contains(c, []byte("github.com/Superdanda/hade/app"))
|
||||
if isContain {
|
||||
fmt.Println("更新文件:" + path)
|
||||
c = bytes.ReplaceAll(c, []byte("github.com/Superdanda/hade/app"), []byte(mod+"/app"))
|
||||
err = ioutil.WriteFile(path, c, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
fmt.Println("创建应用结束")
|
||||
fmt.Println("目录:", folder)
|
||||
fmt.Println("====================================================")
|
||||
return nil
|
||||
},
|
||||
}
|
|
@ -1 +1,68 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Unzip will decompress a zip archive, moving all files and folders
|
||||
// within the zip file (parameter 1) to an output directory (parameter 2).
|
||||
func Unzip(src string, dest string) ([]string, error) {
|
||||
|
||||
var filenames []string
|
||||
|
||||
r, err := zip.OpenReader(src)
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
for _, f := range r.File {
|
||||
|
||||
// Store filename/path for returning and using later on
|
||||
fpath := filepath.Join(dest, f.Name)
|
||||
|
||||
// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
|
||||
if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
|
||||
return filenames, fmt.Errorf("%s: illegal file path", fpath)
|
||||
}
|
||||
|
||||
filenames = append(filenames, fpath)
|
||||
|
||||
if f.FileInfo().IsDir() {
|
||||
// Make Folder
|
||||
os.MkdirAll(fpath, os.ModePerm)
|
||||
continue
|
||||
}
|
||||
|
||||
// Make File
|
||||
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
|
||||
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
|
||||
_, err = io.Copy(outFile, rc)
|
||||
|
||||
// Close the file without defer to close before next iteration of loop
|
||||
outFile.Close()
|
||||
rc.Close()
|
||||
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
}
|
||||
return filenames, nil
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -27,6 +27,8 @@ require (
|
|||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.12.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/google/go-github/v39 v39.2.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jonboulle/clockwork v0.4.0 // indirect
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||
|
|
14
go.sum
14
go.sum
|
@ -60,9 +60,17 @@ github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
|
|||
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-github/v39 v39.2.0 h1:rNNM311XtPOz5rDdsJXAp2o8F67X9FnROXTvto3aSnQ=
|
||||
github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
|
@ -169,6 +177,7 @@ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUu
|
|||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
|
@ -179,6 +188,7 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
|
|||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
|
@ -188,6 +198,7 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -215,6 +226,7 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
|||
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
|
@ -230,6 +242,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|||
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/Superdanda/hade/app/provider/demo"
|
||||
"github.com/Superdanda/hade/framework/gin"
|
||||
)
|
||||
|
||||
func SubjectDelController(c *gin.Context) {
|
||||
c.ISetOkStatus().IJson("ok SubjectDelController")
|
||||
}
|
||||
|
||||
func SubjectUpdateController(c *gin.Context) {
|
||||
c.ISetOkStatus().IJson("ok SubjectUpdateController")
|
||||
}
|
||||
|
||||
func SubjectGetController(c *gin.Context) {
|
||||
c.ISetOkStatus().IJson("ok SubjectGetController")
|
||||
}
|
||||
|
||||
func SubjectListController(c *gin.Context) {
|
||||
demoService := c.MustMake(demo.Key).(demo.Service)
|
||||
foo := demoService.GetFoo()
|
||||
c.ISetOkStatus().IJson(foo)
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/Superdanda/hade/framework/gin"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func FooControllerHandler(ctx *gin.Context) error {
|
||||
finish := make(chan struct{}, 1)
|
||||
panicChan := make(chan interface{}, 1)
|
||||
|
||||
durationCtx, cancel := context.WithTimeout(ctx.BaseContext(), 2*time.Second) // 这里记得当所有事情处理结束后调用 cancel,告知 durationCtx 的后续 Context 结束
|
||||
defer cancel()
|
||||
|
||||
go func() {
|
||||
time.Sleep(1 * time.Second)
|
||||
ctx.ISetOkStatus().IJson(map[string]interface{}{"code": 0})
|
||||
finish <- struct{}{}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-finish:
|
||||
fmt.Println("调用结束了")
|
||||
case <-durationCtx.Done():
|
||||
ctx.ISetStatus(http.StatusInternalServerError).IJson("time out")
|
||||
case <-panicChan:
|
||||
ctx.ISetStatus(http.StatusInternalServerError).IJson("panic")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UserLoginController(c *gin.Context) {
|
||||
foo, _ := c.DefaultQueryString("foo", "def")
|
||||
// 等待10s才结束执行
|
||||
time.Sleep(10 * time.Second)
|
||||
// 输出结果
|
||||
c.ISetOkStatus().IJson("ok, UserLoginController: " + foo)
|
||||
}
|
Loading…
Reference in New Issue