From 70886d4cfda073a409b319c79b3fb52ac036e720 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 15 Aug 2014 09:37:55 +0800 Subject: [PATCH 1/5] update the version from 1.2.0 to 1.2.1 --- bee.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bee.go b/bee.go index 2e8770c..3118ac3 100644 --- a/bee.go +++ b/bee.go @@ -25,7 +25,7 @@ import ( "strings" ) -const version = "1.2.0" +const version = "1.2.1" type Command struct { // Run runs the command. From 55741df579ef39e431a6f0e6d468658f6d3b72af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=9B=E7=90=A6?= Date: Fri, 15 Aug 2014 17:38:51 +0800 Subject: [PATCH 2/5] return actual value from subcommand --- apiapp.go | 3 ++- autorouter.go | 3 ++- bale.go | 3 ++- bee.go | 5 ++--- g.go | 3 ++- migrate.go | 3 ++- new.go | 3 ++- pack.go | 3 ++- run.go | 3 ++- rundocs.go | 3 ++- test.go | 3 ++- version.go | 3 ++- 12 files changed, 24 insertions(+), 14 deletions(-) diff --git a/apiapp.go b/apiapp.go index 65bb906..8ee8c85 100644 --- a/apiapp.go +++ b/apiapp.go @@ -542,7 +542,7 @@ func init() { 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() if len(args) > 1 { cmd.Flag.Parse(args[1:]) @@ -621,6 +621,7 @@ func createapi(cmd *Command, args []string) { writetofile(path.Join(apppath, "main.go"), strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1)) } + return 0 } func checkEnv(appname string) (apppath, packpath string, err error) { diff --git a/autorouter.go b/autorouter.go index 99dee37..1273551 100644 --- a/autorouter.go +++ b/autorouter.go @@ -44,8 +44,9 @@ func init() { cmdRouter.Run = autoRouter } -func autoRouter(cmd *Command, args []string) { +func autoRouter(cmd *Command, args []string) int { fmt.Println("[INFO] Starting auto-generating routers...") + return 0 } // getControllerInfo returns controllers that embeded "beego.controller" diff --git a/bale.go b/bale.go index 64c275d..27ee6d1 100644 --- a/bale.go +++ b/bale.go @@ -43,7 +43,7 @@ func init() { cmdBale.Run = runBale } -func runBale(cmd *Command, args []string) { +func runBale(cmd *Command, args []string) int { err := loadConfig() if err != nil { 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") + return 0 } const ( diff --git a/bee.go b/bee.go index 3118ac3..30905cd 100644 --- a/bee.go +++ b/bee.go @@ -30,7 +30,7 @@ const version = "1.2.1" type Command struct { // Run runs the command. // 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. // The first word in the line is taken to be the command name. @@ -110,8 +110,7 @@ func main() { cmd.Flag.Parse(args[1:]) args = cmd.Flag.Args() } - cmd.Run(cmd, args) - os.Exit(2) + os.Exit(cmd.Run(cmd, args)) return } } diff --git a/g.go b/g.go index 2523e08..1f08fd0 100644 --- a/g.go +++ b/g.go @@ -69,7 +69,7 @@ func init() { 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() if len(args) < 1 { ColorLog("[ERRO] command is missing\n") @@ -193,4 +193,5 @@ func generateCode(cmd *Command, args []string) { ColorLog("[ERRO] command is missing\n") } ColorLog("[SUCC] generate successfully created!\n") + return 0 } diff --git a/migrate.go b/migrate.go index ebc04fa..9db0ce3 100644 --- a/migrate.go +++ b/migrate.go @@ -61,7 +61,7 @@ func init() { } // 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() gopath := os.Getenv("GOPATH") @@ -117,6 +117,7 @@ func runMigration(cmd *Command, args []string) { } } ColorLog("[SUCC] Migration successful!\n") + return 0 } // migrateUpdate does the schema update diff --git a/new.go b/new.go index 8d87b71..50c8f1d 100644 --- a/new.go +++ b/new.go @@ -55,7 +55,7 @@ func init() { cmdNew.Run = createApp } -func createApp(cmd *Command, args []string) { +func createApp(cmd *Command, args []string) int { curpath, _ := os.Getwd() if len(args) != 1 { 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)) ColorLog("[SUCC] New application successfully created!\n") + return 0 } var appconf = `appname = {{.Appname}} diff --git a/pack.go b/pack.go index 9f1d041..6a605d2 100644 --- a/pack.go +++ b/pack.go @@ -469,7 +469,7 @@ func isBeegoProject(thePath string) bool { return false } -func packApp(cmd *Command, args []string) { +func packApp(cmd *Command, args []string) int { curPath, _ := os.Getwd() thePath := "" @@ -624,4 +624,5 @@ func packApp(cmd *Command, args []string) { } fmt.Printf("file write to `%s`\n", outputP) + return 0 } diff --git a/run.go b/run.go index 9976fe9..2d74f87 100644 --- a/run.go +++ b/run.go @@ -58,7 +58,7 @@ func init() { var appname string -func runApp(cmd *Command, args []string) { +func runApp(cmd *Command, args []string) int { exit := make(chan bool) crupath, _ := os.Getwd() @@ -119,6 +119,7 @@ func runApp(cmd *Command, args []string) { runtime.Goexit() } } + return 0 } func readAppDirectories(directory string, paths *[]string) { diff --git a/rundocs.go b/rundocs.go index ae1442d..13b0a9a 100644 --- a/rundocs.go +++ b/rundocs.go @@ -57,7 +57,7 @@ func init() { cmdRundocs.Flag.Var(&docport, "docport", "doc server port") } -func runDocs(cmd *Command, args []string) { +func runDocs(cmd *Command, args []string) int { if isDownload == "true" { downloadFromUrl(swaggerlink, "swagger.zip") 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) log.Fatal(http.ListenAndServe(":"+string(docport), http.FileServer(http.Dir("swagger")))) + return 0 } func downloadFromUrl(url, fileName string) { diff --git a/test.go b/test.go index 0cef690..6790c42 100644 --- a/test.go +++ b/test.go @@ -49,7 +49,7 @@ func pathExists(path string) bool { var started = make(chan bool) -func testApp(cmd *Command, args []string) { +func testApp(cmd *Command, args []string) int { if len(args) != 1 { ColorLog("[ERRO] Cannot start running[ %s ]\n", "argument 'appname' is missing") @@ -73,6 +73,7 @@ func testApp(cmd *Command, args []string) { runTest() } } + return 0 } func runTest() { diff --git a/version.go b/version.go index e3d917c..15da074 100644 --- a/version.go +++ b/version.go @@ -27,7 +27,7 @@ func init() { cmdVersion.Run = versionCmd } -func versionCmd(cmd *Command, args []string) { +func versionCmd(cmd *Command, args []string) int { fmt.Println("bee :" + version) fmt.Println("beego :" + getbeegoVersion()) //fmt.Println("Go :" + runtime.Version()) @@ -36,6 +36,7 @@ func versionCmd(cmd *Command, args []string) { log.Fatal(err) } fmt.Println("Go :" + string(goversion)) + return 0 } func getbeegoVersion() string { From 67c1c05a456bcb6208401c0f6db1521673b0fc30 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 18 Aug 2014 11:51:57 +0800 Subject: [PATCH 3/5] support migrate generate sql --- g.go | 22 ++++++++++------ g_migration.go | 6 ++++- g_model.go | 24 ----------------- g_scaffold.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++++-- util.go | 42 ++++++++++++++++++++++++++++++ 5 files changed, 129 insertions(+), 35 deletions(-) diff --git a/g.go b/g.go index 2523e08..6204321 100644 --- a/g.go +++ b/g.go @@ -22,13 +22,14 @@ var cmdGenerate = &Command{ Long: ` 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. - -fields: a list of database fields. + -fields: a list of table fields. -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 example: bee generate scaffold post -fields="title:string,body:text" bee generate model [modelname] [-fields=""] generate RESTFul model based on fields + -fields: a list of table fields. bee generate controller [controllerfile] generate RESTFul controllers @@ -36,8 +37,9 @@ bee generate controller [controllerfile] bee generate view [viewpath] generate CRUD view in viewpath -bee generate migration [migrationfile] +bee generate migration [migrationfile] [-fields=""] generate migration file for making database schema update + -fields: a list of table fields. bee generate docs generate swagger doc file @@ -147,15 +149,19 @@ func generateCode(cmd *Command, args []string) { ColorLog("[INFO] Using '%s' as 'level'\n", level) generateAppcode(driver.String(), conn.String(), level.String(), tables.String(), curpath) case "migration": - if len(args) == 2 { - mname := args[1] - ColorLog("[INFO] Using '%s' as migration name\n", mname) - generateMigration(mname, curpath) - } else { + if len(args) < 2 { 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) } + cmd.Flag.Parse(args[2:]) + mname := args[1] + ColorLog("[INFO] Using '%s' as migration name\n", mname) + upsql := "" + if fields != "" { + upsql = `m.Sql("CREATE TABLE ` + mname + "(" + generateSQLFromFields(fields.String()) + `)");` + } + generateMigration(mname, upsql, "", curpath) case "controller": if len(args) == 2 { cname := args[1] diff --git a/g_migration.go b/g_migration.go index 26c4f19..5dd58a4 100644 --- a/g_migration.go +++ b/g_migration.go @@ -31,7 +31,7 @@ const ( // generateMigration generates migration file template for database schema update. // The generated file template consists of an up() method for updating schema and // 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) if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) { // create migrations directory @@ -47,6 +47,8 @@ func generateMigration(mname string, curpath string) { defer f.Close() content := strings.Replace(MIGRATION_TPL, "{{StructName}}", camelCase(mname)+"_"+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) // gofmt generated source code formatSourceCode(fpath) @@ -85,10 +87,12 @@ func init() { // Run the migrations func (m *{{StructName}}) Up() { // use m.Sql("CREATE TABLE ...") to make schema update + {{UpSQL}} } // Reverse the migrations func (m *{{StructName}}) Down() { // use m.Sql("DROP TABLE ...") to reverse schema update + {{DownSQL}} } ` diff --git a/g_model.go b/g_model.go index 1d080d5..4226ab2 100644 --- a/g_model.go +++ b/g_model.go @@ -71,30 +71,6 @@ func getStruct(structname, fields string) (string, error) { 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 // http://beego.me/docs/mvc/model/models.md#mysql func getType(ktype string) (kt, tag string) { diff --git a/g_scaffold.go b/g_scaffold.go index 66ef8a3..44406bf 100644 --- a/g_scaffold.go +++ b/g_scaffold.go @@ -1,6 +1,9 @@ package main -import "strings" +import ( + "fmt" + "strings" +) func generateScaffold(sname, fields, crupath, driver, conn string) { // generate model @@ -22,7 +25,11 @@ func generateScaffold(sname, fields, crupath, driver, conn string) { // generate migration ColorLog("[INFO] Do you want me to create a %v migration and schema for this resource? [yes|no]] ", sname) if askForConfirmation() { - generateMigration(sname, crupath) + upsql := "" + if fields != "" { + upsql = `m.Sql("CREATE TABLE ` + sname + "(" + generateSQLFromFields(fields) + `)");` + } + generateMigration(sname, upsql, "", crupath) } // run migration ColorLog("[INFO] Do you want to go ahead and migrate the database? [yes|no]] ") @@ -31,3 +38,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)) } + +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 "", "" +} diff --git a/util.go b/util.go index 0e24d08..e953861 100644 --- a/util.go +++ b/util.go @@ -206,3 +206,45 @@ func containsString(slice []string, element string) bool { } 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)]) +} From 9faf04fea045d75d25ae9173f39208e3af360ff0 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 18 Aug 2014 12:21:21 +0800 Subject: [PATCH 4/5] add downsql & controller add mapping --- g.go | 4 +++- g_appcode.go | 8 ++++++++ g_controllers.go | 8 ++++++++ g_scaffold.go | 4 +++- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/g.go b/g.go index 187e4d6..750580c 100644 --- a/g.go +++ b/g.go @@ -158,10 +158,12 @@ func generateCode(cmd *Command, args []string) int { 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, "", curpath) + generateMigration(mname, upsql, downsql, curpath) case "controller": if len(args) == 2 { cname := args[1] diff --git a/g_appcode.go b/g_appcode.go index 6a5ba3a..d6124d9 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -807,6 +807,14 @@ type {{ctrlName}}Controller struct { 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 // @Description create {{ctrlName}} // @Param body body models.{{ctrlName}} true "body for {{ctrlName}} content" diff --git a/g_controllers.go b/g_controllers.go index e176d86..22c3c9c 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -68,6 +68,14 @@ type {{controllerName}}Controller struct { 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 // @Description create {{controllerName}} // @Param body body models.{{controllerName}} true "body for {{controllerName}} content" diff --git a/g_scaffold.go b/g_scaffold.go index 44406bf..1d0c239 100644 --- a/g_scaffold.go +++ b/g_scaffold.go @@ -26,10 +26,12 @@ func generateScaffold(sname, fields, crupath, driver, conn string) { ColorLog("[INFO] Do you want me to create a %v migration and schema for this resource? [yes|no]] ", sname) if askForConfirmation() { upsql := "" + downsql := "" if fields != "" { upsql = `m.Sql("CREATE TABLE ` + sname + "(" + generateSQLFromFields(fields) + `)");` + downsql = `m.Sql("DROP TABLE ` + "`" + sname + "`" + `")` } - generateMigration(sname, upsql, "", crupath) + generateMigration(sname, upsql, downsql, crupath) } // run migration ColorLog("[INFO] Do you want to go ahead and migrate the database? [yes|no]] ") From 5efe6ebd5546f458672701604978cda37bdff5d2 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 18 Aug 2014 23:12:27 +0800 Subject: [PATCH 5/5] comments router test rundocs --- bee.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bee.go b/bee.go index 30905cd..c5cdc99 100644 --- a/bee.go +++ b/bee.go @@ -77,12 +77,12 @@ var commands = []*Command{ cmdRun, cmdPack, cmdApiapp, - cmdRouter, - cmdTest, + //cmdRouter, + //cmdTest, cmdBale, cmdVersion, cmdGenerate, - cmdRundocs, + //cmdRundocs, cmdMigrate, }