Merge remote-tracking branch 'upstream/master'

This commit is contained in:
ZhengYang 2014-08-19 11:52:32 +08:00
commit daaccf8972
18 changed files with 177 additions and 53 deletions

View File

@ -542,7 +542,7 @@ func init() {
cmdApiapp.Flag.Var(&conn, "conn", "connection string used by the driver to connect to a database instance") cmdApiapp.Flag.Var(&conn, "conn", "connection string used by the driver to connect to a database instance")
} }
func createapi(cmd *Command, args []string) { func createapi(cmd *Command, args []string) int {
curpath, _ := os.Getwd() curpath, _ := os.Getwd()
if len(args) > 1 { if len(args) > 1 {
cmd.Flag.Parse(args[1:]) cmd.Flag.Parse(args[1:])
@ -621,6 +621,7 @@ func createapi(cmd *Command, args []string) {
writetofile(path.Join(apppath, "main.go"), writetofile(path.Join(apppath, "main.go"),
strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1)) strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1))
} }
return 0
} }
func checkEnv(appname string) (apppath, packpath string, err error) { func checkEnv(appname string) (apppath, packpath string, err error) {

View File

@ -44,8 +44,9 @@ func init() {
cmdRouter.Run = autoRouter cmdRouter.Run = autoRouter
} }
func autoRouter(cmd *Command, args []string) { func autoRouter(cmd *Command, args []string) int {
fmt.Println("[INFO] Starting auto-generating routers...") fmt.Println("[INFO] Starting auto-generating routers...")
return 0
} }
// getControllerInfo returns controllers that embeded "beego.controller" // getControllerInfo returns controllers that embeded "beego.controller"

View File

@ -43,7 +43,7 @@ func init() {
cmdBale.Run = runBale cmdBale.Run = runBale
} }
func runBale(cmd *Command, args []string) { func runBale(cmd *Command, args []string) int {
err := loadConfig() err := loadConfig()
if err != nil { if err != nil {
ColorLog("[ERRO] Fail to parse bee.json[ %s ]\n", err) ColorLog("[ERRO] Fail to parse bee.json[ %s ]\n", err)
@ -82,6 +82,7 @@ func runBale(cmd *Command, args []string) {
} }
ColorLog("[SUCC] Baled resources successfully!\n") ColorLog("[SUCC] Baled resources successfully!\n")
return 0
} }
const ( const (

13
bee.go
View File

@ -25,12 +25,12 @@ import (
"strings" "strings"
) )
const version = "1.2.0" const version = "1.2.1"
type Command struct { type Command struct {
// Run runs the command. // Run runs the command.
// The args are the arguments after the command name. // The args are the arguments after the command name.
Run func(cmd *Command, args []string) Run func(cmd *Command, args []string) int
// UsageLine is the one-line usage message. // UsageLine is the one-line usage message.
// The first word in the line is taken to be the command name. // The first word in the line is taken to be the command name.
@ -77,12 +77,12 @@ var commands = []*Command{
cmdRun, cmdRun,
cmdPack, cmdPack,
cmdApiapp, cmdApiapp,
cmdRouter, //cmdRouter,
cmdTest, //cmdTest,
cmdBale, cmdBale,
cmdVersion, cmdVersion,
cmdGenerate, cmdGenerate,
cmdRundocs, //cmdRundocs,
cmdMigrate, cmdMigrate,
} }
@ -110,8 +110,7 @@ func main() {
cmd.Flag.Parse(args[1:]) cmd.Flag.Parse(args[1:])
args = cmd.Flag.Args() args = cmd.Flag.Args()
} }
cmd.Run(cmd, args) os.Exit(cmd.Run(cmd, args))
os.Exit(2)
return return
} }
} }

27
g.go
View File

@ -22,13 +22,14 @@ var cmdGenerate = &Command{
Long: ` Long: `
bee generate scaffold [scaffoldname] [-fields=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] bee generate scaffold [scaffoldname] [-fields=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"]
The generate scaffold command will do a number of things for you. The generate scaffold command will do a number of things for you.
-fields: a list of database fields. -fields: a list of table fields.
-driver: [mysql | postgresql | sqlite], the default is mysql -driver: [mysql | postgresql | sqlite], the default is mysql
-conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test -conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test
example: bee generate scaffold post -fields="title:string,body:text" example: bee generate scaffold post -fields="title:string,body:text"
bee generate model [modelname] [-fields=""] bee generate model [modelname] [-fields=""]
generate RESTFul model based on fields generate RESTFul model based on fields
-fields: a list of table fields.
bee generate controller [controllerfile] bee generate controller [controllerfile]
generate RESTFul controllers generate RESTFul controllers
@ -36,8 +37,9 @@ bee generate controller [controllerfile]
bee generate view [viewpath] bee generate view [viewpath]
generate CRUD view in viewpath generate CRUD view in viewpath
bee generate migration [migrationfile] bee generate migration [migrationfile] [-fields=""]
generate migration file for making database schema update generate migration file for making database schema update
-fields: a list of table fields.
bee generate docs bee generate docs
generate swagger doc file generate swagger doc file
@ -69,7 +71,7 @@ func init() {
cmdGenerate.Flag.Var(&fields, "fields", "specify the fields want to generate.") cmdGenerate.Flag.Var(&fields, "fields", "specify the fields want to generate.")
} }
func generateCode(cmd *Command, args []string) { func generateCode(cmd *Command, args []string) int {
curpath, _ := os.Getwd() curpath, _ := os.Getwd()
if len(args) < 1 { if len(args) < 1 {
ColorLog("[ERRO] command is missing\n") ColorLog("[ERRO] command is missing\n")
@ -147,15 +149,21 @@ func generateCode(cmd *Command, args []string) {
ColorLog("[INFO] Using '%s' as 'level'\n", level) ColorLog("[INFO] Using '%s' as 'level'\n", level)
generateAppcode(driver.String(), conn.String(), level.String(), tables.String(), curpath) generateAppcode(driver.String(), conn.String(), level.String(), tables.String(), curpath)
case "migration": case "migration":
if len(args) == 2 { if len(args) < 2 {
mname := args[1]
ColorLog("[INFO] Using '%s' as migration name\n", mname)
generateMigration(mname, curpath)
} else {
ColorLog("[ERRO] Wrong number of arguments\n") ColorLog("[ERRO] Wrong number of arguments\n")
ColorLog("[HINT] Usage: bee generate migration [migrationname]\n") ColorLog("[HINT] Usage: bee generate migration [migrationname] [-fields=\"\"]\n")
os.Exit(2) os.Exit(2)
} }
cmd.Flag.Parse(args[2:])
mname := args[1]
ColorLog("[INFO] Using '%s' as migration name\n", mname)
upsql := ""
downsql := ""
if fields != "" {
upsql = `m.Sql("CREATE TABLE ` + mname + "(" + generateSQLFromFields(fields.String()) + `)");`
downsql = `m.Sql("DROP TABLE ` + "`" + mname + "`" + `")`
}
generateMigration(mname, upsql, downsql, curpath)
case "controller": case "controller":
if len(args) == 2 { if len(args) == 2 {
cname := args[1] cname := args[1]
@ -193,4 +201,5 @@ func generateCode(cmd *Command, args []string) {
ColorLog("[ERRO] command is missing\n") ColorLog("[ERRO] command is missing\n")
} }
ColorLog("[SUCC] generate successfully created!\n") ColorLog("[SUCC] generate successfully created!\n")
return 0
} }

View File

@ -807,6 +807,14 @@ type {{ctrlName}}Controller struct {
beego.Controller beego.Controller
} }
func (this *{{ctrlName}}Controller) URLMapping() {
this.Mapping("Post", this.Post)
this.Mapping("GetOne", this.GetOne)
this.Mapping("GetAll", this.GetAll)
this.Mapping("Put", this.Put)
this.Mapping("Delete", this.Delete)
}
// @Title Post // @Title Post
// @Description create {{ctrlName}} // @Description create {{ctrlName}}
// @Param body body models.{{ctrlName}} true "body for {{ctrlName}} content" // @Param body body models.{{ctrlName}} true "body for {{ctrlName}} content"

View File

@ -68,6 +68,14 @@ type {{controllerName}}Controller struct {
beego.Controller beego.Controller
} }
func (this *{{controllerName}}Controller) URLMapping() {
this.Mapping("Post", this.Post)
this.Mapping("GetOne", this.GetOne)
this.Mapping("GetAll", this.GetAll)
this.Mapping("Put", this.Put)
this.Mapping("Delete", this.Delete)
}
// @Title Post // @Title Post
// @Description create {{controllerName}} // @Description create {{controllerName}}
// @Param body body models.{{controllerName}} true "body for {{controllerName}} content" // @Param body body models.{{controllerName}} true "body for {{controllerName}} content"

View File

@ -31,7 +31,7 @@ const (
// generateMigration generates migration file template for database schema update. // generateMigration generates migration file template for database schema update.
// The generated file template consists of an up() method for updating schema and // The generated file template consists of an up() method for updating schema and
// a down() method for reverting the update. // a down() method for reverting the update.
func generateMigration(mname string, curpath string) { func generateMigration(mname, upsql, downsql, curpath string) {
migrationFilePath := path.Join(curpath, "database", M_PATH) migrationFilePath := path.Join(curpath, "database", M_PATH)
if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) { if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) {
// create migrations directory // create migrations directory
@ -47,6 +47,8 @@ func generateMigration(mname string, curpath string) {
defer f.Close() defer f.Close()
content := strings.Replace(MIGRATION_TPL, "{{StructName}}", camelCase(mname)+"_"+today, -1) content := strings.Replace(MIGRATION_TPL, "{{StructName}}", camelCase(mname)+"_"+today, -1)
content = strings.Replace(content, "{{CurrTime}}", today, -1) content = strings.Replace(content, "{{CurrTime}}", today, -1)
content = strings.Replace(content, "{{UpSQL}}", upsql, -1)
content = strings.Replace(content, "{{DownSQL}}", downsql, -1)
f.WriteString(content) f.WriteString(content)
// gofmt generated source code // gofmt generated source code
formatSourceCode(fpath) formatSourceCode(fpath)
@ -85,10 +87,12 @@ func init() {
// Run the migrations // Run the migrations
func (m *{{StructName}}) Up() { func (m *{{StructName}}) Up() {
// use m.Sql("CREATE TABLE ...") to make schema update // use m.Sql("CREATE TABLE ...") to make schema update
{{UpSQL}}
} }
// Reverse the migrations // Reverse the migrations
func (m *{{StructName}}) Down() { func (m *{{StructName}}) Down() {
// use m.Sql("DROP TABLE ...") to reverse schema update // use m.Sql("DROP TABLE ...") to reverse schema update
{{DownSQL}}
} }
` `

View File

@ -71,30 +71,6 @@ func getStruct(structname, fields string) (string, error) {
return structStr, nil return structStr, nil
} }
func camelString(s string) string {
data := make([]byte, 0, len(s))
j := false
k := false
num := len(s) - 1
for i := 0; i <= num; i++ {
d := s[i]
if k == false && d >= 'A' && d <= 'Z' {
k = true
}
if d >= 'a' && d <= 'z' && (j || k == false) {
d = d - 32
j = false
k = true
}
if k && d == '_' && num > i && s[i+1] >= 'a' && s[i+1] <= 'z' {
j = true
continue
}
data = append(data, d)
}
return string(data[:len(data)])
}
// fields support type // fields support type
// http://beego.me/docs/mvc/model/models.md#mysql // http://beego.me/docs/mvc/model/models.md#mysql
func getType(ktype string) (kt, tag string) { func getType(ktype string) (kt, tag string) {

View File

@ -1,6 +1,9 @@
package main package main
import "strings" import (
"fmt"
"strings"
)
func generateScaffold(sname, fields, crupath, driver, conn string) { func generateScaffold(sname, fields, crupath, driver, conn string) {
// generate model // generate model
@ -22,7 +25,13 @@ func generateScaffold(sname, fields, crupath, driver, conn string) {
// generate migration // generate migration
ColorLog("[INFO] Do you want me to create a %v migration and schema for this resource? [yes|no]] ", sname) ColorLog("[INFO] Do you want me to create a %v migration and schema for this resource? [yes|no]] ", sname)
if askForConfirmation() { if askForConfirmation() {
generateMigration(sname, crupath) upsql := ""
downsql := ""
if fields != "" {
upsql = `m.Sql("CREATE TABLE ` + sname + "(" + generateSQLFromFields(fields) + `)");`
downsql = `m.Sql("DROP TABLE ` + "`" + sname + "`" + `")`
}
generateMigration(sname, upsql, downsql, crupath)
} }
// run migration // run migration
ColorLog("[INFO] Do you want to go ahead and migrate the database? [yes|no]] ") ColorLog("[INFO] Do you want to go ahead and migrate the database? [yes|no]] ")
@ -31,3 +40,62 @@ func generateScaffold(sname, fields, crupath, driver, conn string) {
} }
ColorLog("[INFO] All done! Don't forget to add beego.Router(\"/%v\" ,&controllers.%vController{}) to routers/route.go\n", sname, strings.Title(sname)) ColorLog("[INFO] All done! Don't forget to add beego.Router(\"/%v\" ,&controllers.%vController{}) to routers/route.go\n", sname, strings.Title(sname))
} }
func generateSQLFromFields(fields string) string {
sql := ""
tags := ""
fds := strings.Split(fields, ",")
for i, v := range fds {
kv := strings.SplitN(v, ":", 2)
if len(kv) != 2 {
ColorLog("[ERRO] the filds format is wrong. should key:type,key:type " + v)
return ""
}
typ, tag := getSqlType(kv[1])
if typ == "" {
ColorLog("[ERRO] the filds format is wrong. should key:type,key:type " + v)
return ""
}
if i == 0 && strings.ToLower(kv[0]) != "id" {
sql = sql + "`id` int(11) NOT NULL AUTO_INCREMENT,"
tags = tags + "PRIMARY KEY (`id`),"
}
sql = sql + "`" + snakeString(kv[0]) + "` " + typ + ","
if tag != "" {
tags = tags + fmt.Sprintf(tag, "`"+snakeString(kv[0])+"`") + ","
}
}
sql = strings.TrimRight(sql+tags, ",")
return sql
}
func getSqlType(ktype string) (tp, tag string) {
kv := strings.SplitN(ktype, ":", 2)
switch kv[0] {
case "string":
if len(kv) == 2 {
return "varchar(" + kv[1] + ") NOT NULL", ""
} else {
return "varchar(128) NOT NULL", ""
}
case "text":
return "longtext NOT NULL", ""
case "auto":
return "int(11) NOT NULL AUTO_INCREMENT", ""
case "pk":
return "int(11) NOT NULL", "PRIMARY KEY (%s)"
case "datetime":
return "datetime NOT NULL", ""
case "int", "int8", "int16", "int32", "int64":
fallthrough
case "uint", "uint8", "uint16", "uint32", "uint64":
return "int(11) DEFAULT NULL", ""
case "bool":
return "tinyint(1) NOT NULL", ""
case "float32", "float64":
return "float NOT NULL", ""
case "float":
return "float NOT NULL", ""
}
return "", ""
}

View File

@ -61,7 +61,7 @@ func init() {
} }
// runMigration is the entry point for starting a migration // runMigration is the entry point for starting a migration
func runMigration(cmd *Command, args []string) { func runMigration(cmd *Command, args []string) int {
crupath, _ := os.Getwd() crupath, _ := os.Getwd()
gopath := os.Getenv("GOPATH") gopath := os.Getenv("GOPATH")
@ -117,6 +117,7 @@ func runMigration(cmd *Command, args []string) {
} }
} }
ColorLog("[SUCC] Migration successful!\n") ColorLog("[SUCC] Migration successful!\n")
return 0
} }
// migrateUpdate does the schema update // migrateUpdate does the schema update

3
new.go
View File

@ -55,7 +55,7 @@ func init() {
cmdNew.Run = createApp cmdNew.Run = createApp
} }
func createApp(cmd *Command, args []string) { func createApp(cmd *Command, args []string) int {
curpath, _ := os.Getwd() curpath, _ := os.Getwd()
if len(args) != 1 { if len(args) != 1 {
ColorLog("[ERRO] Argument [appname] is missing\n") ColorLog("[ERRO] Argument [appname] is missing\n")
@ -139,6 +139,7 @@ func createApp(cmd *Command, args []string) {
writetofile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", strings.Join(strings.Split(apppath[len(appsrcpath)+1:], string(path.Separator)), "/"), -1)) writetofile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", strings.Join(strings.Split(apppath[len(appsrcpath)+1:], string(path.Separator)), "/"), -1))
ColorLog("[SUCC] New application successfully created!\n") ColorLog("[SUCC] New application successfully created!\n")
return 0
} }
var appconf = `appname = {{.Appname}} var appconf = `appname = {{.Appname}}

View File

@ -469,7 +469,7 @@ func isBeegoProject(thePath string) bool {
return false return false
} }
func packApp(cmd *Command, args []string) { func packApp(cmd *Command, args []string) int {
curPath, _ := os.Getwd() curPath, _ := os.Getwd()
thePath := "" thePath := ""
@ -624,4 +624,5 @@ func packApp(cmd *Command, args []string) {
} }
fmt.Printf("file write to `%s`\n", outputP) fmt.Printf("file write to `%s`\n", outputP)
return 0
} }

3
run.go
View File

@ -58,7 +58,7 @@ func init() {
var appname string var appname string
func runApp(cmd *Command, args []string) { func runApp(cmd *Command, args []string) int {
exit := make(chan bool) exit := make(chan bool)
crupath, _ := os.Getwd() crupath, _ := os.Getwd()
@ -119,6 +119,7 @@ func runApp(cmd *Command, args []string) {
runtime.Goexit() runtime.Goexit()
} }
} }
return 0
} }
func readAppDirectories(directory string, paths *[]string) { func readAppDirectories(directory string, paths *[]string) {

View File

@ -57,7 +57,7 @@ func init() {
cmdRundocs.Flag.Var(&docport, "docport", "doc server port") cmdRundocs.Flag.Var(&docport, "docport", "doc server port")
} }
func runDocs(cmd *Command, args []string) { func runDocs(cmd *Command, args []string) int {
if isDownload == "true" { if isDownload == "true" {
downloadFromUrl(swaggerlink, "swagger.zip") downloadFromUrl(swaggerlink, "swagger.zip")
err := unzipAndDelete("swagger.zip", "swagger") err := unzipAndDelete("swagger.zip", "swagger")
@ -74,6 +74,7 @@ func runDocs(cmd *Command, args []string) {
} }
fmt.Println("start the docs server on: http://127.0.0.1:" + docport) fmt.Println("start the docs server on: http://127.0.0.1:" + docport)
log.Fatal(http.ListenAndServe(":"+string(docport), http.FileServer(http.Dir("swagger")))) log.Fatal(http.ListenAndServe(":"+string(docport), http.FileServer(http.Dir("swagger"))))
return 0
} }
func downloadFromUrl(url, fileName string) { func downloadFromUrl(url, fileName string) {

View File

@ -49,7 +49,7 @@ func pathExists(path string) bool {
var started = make(chan bool) var started = make(chan bool)
func testApp(cmd *Command, args []string) { func testApp(cmd *Command, args []string) int {
if len(args) != 1 { if len(args) != 1 {
ColorLog("[ERRO] Cannot start running[ %s ]\n", ColorLog("[ERRO] Cannot start running[ %s ]\n",
"argument 'appname' is missing") "argument 'appname' is missing")
@ -73,6 +73,7 @@ func testApp(cmd *Command, args []string) {
runTest() runTest()
} }
} }
return 0
} }
func runTest() { func runTest() {

42
util.go
View File

@ -206,3 +206,45 @@ func containsString(slice []string, element string) bool {
} }
return false return false
} }
// snake string, XxYy to xx_yy
func snakeString(s string) string {
data := make([]byte, 0, len(s)*2)
j := false
num := len(s)
for i := 0; i < num; i++ {
d := s[i]
if i > 0 && d >= 'A' && d <= 'Z' && j {
data = append(data, '_')
}
if d != '_' {
j = true
}
data = append(data, d)
}
return strings.ToLower(string(data[:len(data)]))
}
func camelString(s string) string {
data := make([]byte, 0, len(s))
j := false
k := false
num := len(s) - 1
for i := 0; i <= num; i++ {
d := s[i]
if k == false && d >= 'A' && d <= 'Z' {
k = true
}
if d >= 'a' && d <= 'z' && (j || k == false) {
d = d - 32
j = false
k = true
}
if k && d == '_' && num > i && s[i+1] >= 'a' && s[i+1] <= 'z' {
j = true
continue
}
data = append(data, d)
}
return string(data[:len(data)])
}

View File

@ -27,7 +27,7 @@ func init() {
cmdVersion.Run = versionCmd cmdVersion.Run = versionCmd
} }
func versionCmd(cmd *Command, args []string) { func versionCmd(cmd *Command, args []string) int {
fmt.Println("bee :" + version) fmt.Println("bee :" + version)
fmt.Println("beego :" + getbeegoVersion()) fmt.Println("beego :" + getbeegoVersion())
//fmt.Println("Go :" + runtime.Version()) //fmt.Println("Go :" + runtime.Version())
@ -36,6 +36,7 @@ func versionCmd(cmd *Command, args []string) {
log.Fatal(err) log.Fatal(err)
} }
fmt.Println("Go :" + string(goversion)) fmt.Println("Go :" + string(goversion))
return 0
} }
func getbeegoVersion() string { func getbeegoVersion() string {