From 47e8ce32d982a3d4fbe926b1db21f8206c2afb1e Mon Sep 17 00:00:00 2001 From: Sacheendra Talluri Date: Tue, 9 Jun 2015 14:29:43 -0500 Subject: [PATCH 001/123] add jsonb and timestamp with time zone to postgres data types --- g_appcode.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/g_appcode.go b/g_appcode.go index c3c295c..5607e77 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -118,6 +118,7 @@ var typeMappingPostgres = map[string]string{ "time": "time.Time", "timestamp": "time.Time", "timestamp without time zone": "time.Time", + "timestamp with time zone": "time.Time", "interval": "string", // time interval, string for now "real": "float32", // float & decimal "double precision": "float64", @@ -130,6 +131,7 @@ var typeMappingPostgres = map[string]string{ "USER-DEFINED": "string", // user defined "uuid": "string", // uuid "json": "string", // json + "jsonb": "string", } // Table represent a table in a database From 60e4f1b872255d3b78fa6ac08af419a85177c9b1 Mon Sep 17 00:00:00 2001 From: Lei Cao Date: Wed, 17 Jun 2015 14:59:59 +0800 Subject: [PATCH 002/123] Issue-119: flags for excluding Godeps. --- run.go | 22 +++++++++++++++++++++- util.go | 12 ++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/run.go b/run.go index 6563824..8d2f9a2 100644 --- a/run.go +++ b/run.go @@ -23,7 +23,7 @@ import ( ) var cmdRun = &Command{ - UsageLine: "run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true]", + UsageLine: "run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] [-e=Godeps -e=folderToExclude]", Short: "run the app and start a Web server for development", Long: ` Run command will supervise the file system of the beego project using inotify, @@ -37,11 +37,15 @@ var mainFiles ListOpts var downdoc docValue var gendoc docValue +// The flags list of the paths excluded from watching +var excludedPaths strFlags + func init() { cmdRun.Run = runApp cmdRun.Flag.Var(&mainFiles, "main", "specify main go files") cmdRun.Flag.Var(&gendoc, "gendoc", "auto generate the docs") cmdRun.Flag.Var(&downdoc, "downdoc", "auto download swagger file when not exist") + cmdRun.Flag.Var(&excludedPaths, "e", "Excluded paths[].") } var appname string @@ -129,6 +133,11 @@ func readAppDirectories(directory string, paths *[]string) { if strings.HasSuffix(fileInfo.Name(), "docs") { continue } + + if isExcluded(fileInfo) { + continue + } + if fileInfo.IsDir() == true && fileInfo.Name()[0] != '.' { readAppDirectories(directory+"/"+fileInfo.Name(), paths) continue @@ -146,3 +155,14 @@ func readAppDirectories(directory string, paths *[]string) { return } + +// If a file is excluded +func isExcluded(fileInfo os.FileInfo) bool { + for _, p := range excludedPaths { + if strings.HasSuffix(fileInfo.Name(), p) { + ColorLog("[INFO] Excluding from watching [ %s ]\n", fileInfo.Name()) + return true + } + } + return false +} diff --git a/util.go b/util.go index 02b2300..1b8685d 100644 --- a/util.go +++ b/util.go @@ -247,3 +247,15 @@ func camelString(s string) string { } return string(data[:len(data)]) } + +// The string flag list, implemented flag.Value interface +type strFlags []string + +func (s *strFlags) String() string { + return fmt.Sprintf("%d", *s) +} + +func (s *strFlags) Set(value string) error { + *s = append(*s, value) + return nil +} From f50dce1d52fc1c76c0e6ca84970349a380657195 Mon Sep 17 00:00:00 2001 From: simsun Date: Wed, 1 Jul 2015 23:55:13 +0800 Subject: [PATCH 003/123] make docs works when EnableDocs = false --- g_docs.go | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/g_docs.go b/g_docs.go index 3fbb20f..ea2ef00 100644 --- a/g_docs.go +++ b/g_docs.go @@ -55,22 +55,24 @@ var rootapi swagger.ResourceListing var apilist map[string]*swagger.ApiDeclaration func init() { - err := json.Unmarshal([]byte(Rootinfo), &rootapi) - if err != nil { - beego.Error(err) - } - err = json.Unmarshal([]byte(Subapi), &apilist) - if err != nil { - beego.Error(err) - } - beego.GlobalDocApi["Root"] = rootapi - for k, v := range apilist { - for i, a := range v.Apis { - a.Path = urlReplace(k + a.Path) - v.Apis[i] = a + if beego.EnableDocs { + err := json.Unmarshal([]byte(Rootinfo), &rootapi) + if err != nil { + beego.Error(err) + } + err = json.Unmarshal([]byte(Subapi), &apilist) + if err != nil { + beego.Error(err) + } + beego.GlobalDocApi["Root"] = rootapi + for k, v := range apilist { + for i, a := range v.Apis { + a.Path = urlReplace(k + a.Path) + v.Apis[i] = a + } + v.BasePath = BasePath + beego.GlobalDocApi[strings.Trim(k, "/")] = v } - v.BasePath = BasePath - beego.GlobalDocApi[strings.Trim(k, "/")] = v } } From f385056264297534612761793de0d072e41f357b Mon Sep 17 00:00:00 2001 From: Pelle Johnsen Date: Thu, 16 Jul 2015 19:36:02 +0200 Subject: [PATCH 004/123] Generate fixes for model and controller - use int64 for all places handling model id - use controller code from appcode if a matching model is found --- g_controllers.go | 171 ++++++++++++++++++++++++++++++++++++++++++++++- g_model.go | 4 +- 2 files changed, 172 insertions(+), 3 deletions(-) diff --git a/g_controllers.go b/g_controllers.go index d782bdf..30bc86c 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -44,7 +44,16 @@ func generateController(cname, crupath string) { fpath := path.Join(fp, strings.ToLower(controllerName)+".go") if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { defer f.Close() - content := strings.Replace(controllerTpl, "{{packageName}}", packageName, -1) + modelPath := path.Join(crupath, "models", strings.ToLower(controllerName)+".go") + var content string + if _, err := os.Stat(modelPath); err == nil { + ColorLog("[INFO] Using matching model '%s'\n", controllerName) + content = strings.Replace(controllerModelTpl, "{{packageName}}", packageName, -1) + pkgPath := getPackagePath(crupath) + content = strings.Replace(content, "{{pkgPath}}", pkgPath, -1) + } else { + content = strings.Replace(controllerTpl, "{{packageName}}", packageName, -1) + } content = strings.Replace(content, "{{controllerName}}", controllerName, -1) f.WriteString(content) // gofmt generated source code @@ -132,3 +141,163 @@ func (c *{{controllerName}}Controller) Delete() { } ` + +var controllerModelTpl = `package {{packageName}} + +import ( + "{{pkgPath}}/models" + "encoding/json" + "errors" + "strconv" + "strings" + + "github.com/astaxie/beego" +) + +// oprations for {{controllerName}} +type {{controllerName}}Controller struct { + beego.Controller +} + +func (c *{{controllerName}}Controller) URLMapping() { + c.Mapping("Post", c.Post) + c.Mapping("GetOne", c.GetOne) + c.Mapping("GetAll", c.GetAll) + c.Mapping("Put", c.Put) + c.Mapping("Delete", c.Delete) +} + +// @Title Post +// @Description create {{controllerName}} +// @Param body body models.{{controllerName}} true "body for {{controllerName}} content" +// @Success 200 {int} models.{{controllerName}}.Id +// @Failure 403 body is empty +// @router / [post] +func (c *{{controllerName}}Controller) Post() { + var v models.{{controllerName}} + json.Unmarshal(c.Ctx.Input.RequestBody, &v) + if id, err := models.Add{{controllerName}}(&v); err == nil { + c.Data["json"] = map[string]int64{"id": id} + } else { + c.Data["json"] = err.Error() + } + c.ServeJson() +} + +// @Title Get +// @Description get {{controllerName}} by id +// @Param id path string true "The key for staticblock" +// @Success 200 {object} models.{{controllerName}} +// @Failure 403 :id is empty +// @router /:id [get] +func (c *{{controllerName}}Controller) GetOne() { + idStr := c.Ctx.Input.Params[":id"] + id, _ := strconv.ParseInt(idStr, 0, 64) + v, err := models.Get{{controllerName}}ById(id) + if err != nil { + c.Data["json"] = err.Error() + } else { + c.Data["json"] = v + } + c.ServeJson() +} + +// @Title Get All +// @Description get {{controllerName}} +// @Param query query string false "Filter. e.g. col1:v1,col2:v2 ..." +// @Param fields query string false "Fields returned. e.g. col1,col2 ..." +// @Param sortby query string false "Sorted-by fields. e.g. col1,col2 ..." +// @Param order query string false "Order corresponding to each sortby field, if single value, apply to all sortby fields. e.g. desc,asc ..." +// @Param limit query string false "Limit the size of result set. Must be an integer" +// @Param offset query string false "Start position of result set. Must be an integer" +// @Success 200 {object} models.{{controllerName}} +// @Failure 403 +// @router / [get] +func (c *{{controllerName}}Controller) GetAll() { + var fields []string + var sortby []string + var order []string + var query map[string]string = make(map[string]string) + var limit int64 = 10 + var offset int64 = 0 + + // fields: col1,col2,entity.col3 + if v := c.GetString("fields"); v != "" { + fields = strings.Split(v, ",") + } + // limit: 10 (default is 10) + if v, err := c.GetInt64("limit"); err == nil { + limit = v + } + // offset: 0 (default is 0) + if v, err := c.GetInt64("offset"); err == nil { + offset = v + } + // sortby: col1,col2 + if v := c.GetString("sortby"); v != "" { + sortby = strings.Split(v, ",") + } + // order: desc,asc + if v := c.GetString("order"); v != "" { + order = strings.Split(v, ",") + } + // query: k:v,k:v + if v := c.GetString("query"); v != "" { + for _, cond := range strings.Split(v, ",") { + kv := strings.Split(cond, ":") + if len(kv) != 2 { + c.Data["json"] = errors.New("Error: invalid query key/value pair") + c.ServeJson() + return + } + k, v := kv[0], kv[1] + query[k] = v + } + } + + l, err := models.GetAll{{controllerName}}(query, fields, sortby, order, offset, limit) + if err != nil { + c.Data["json"] = err.Error() + } else { + c.Data["json"] = l + } + c.ServeJson() +} + +// @Title Update +// @Description update the {{controllerName}} +// @Param id path string true "The id you want to update" +// @Param body body models.{{controllerName}} true "body for {{controllerName}} content" +// @Success 200 {object} models.{{controllerName}} +// @Failure 403 :id is not int +// @router /:id [put] +func (c *{{controllerName}}Controller) Put() { + idStr := c.Ctx.Input.Params[":id"] + id, _ := strconv.ParseInt(idStr, 0, 64) + v := models.{{controllerName}}{Id: id} + json.Unmarshal(c.Ctx.Input.RequestBody, &v) + if err := models.Update{{controllerName}}ById(&v); err == nil { + c.Data["json"] = "OK" + } else { + c.Data["json"] = err.Error() + } + c.ServeJson() +} + +// @Title Delete +// @Description delete the {{controllerName}} +// @Param id path string true "The id you want to delete" +// @Success 200 {string} delete success! +// @Failure 403 id is empty +// @router /:id [delete] +func (c *{{controllerName}}Controller) Delete() { + idStr := c.Ctx.Input.Params[":id"] + id, _ := strconv.ParseInt(idStr, 0, 64) + if err := models.Delete{{controllerName}}(id); err == nil { + c.Data["json"] = "OK" + } else { + c.Data["json"] = err.Error() + } + c.ServeJson() +} +` diff --git a/g_model.go b/g_model.go index 403c208..859164f 100644 --- a/g_model.go +++ b/g_model.go @@ -140,7 +140,7 @@ func Add{{modelName}}(m *{{modelName}}) (id int64, err error) { // Get{{modelName}}ById retrieves {{modelName}} by Id. Returns error if // Id doesn't exist -func Get{{modelName}}ById(id int) (v *{{modelName}}, err error) { +func Get{{modelName}}ById(id int64) (v *{{modelName}}, err error) { o := orm.NewOrm() v = &{{modelName}}{Id: id} if err = o.Read(v); err == nil { @@ -240,7 +240,7 @@ func Update{{modelName}}ById(m *{{modelName}}) (err error) { // Delete{{modelName}} deletes {{modelName}} by Id and returns error if // the record to be deleted doesn't exist -func Delete{{modelName}}(id int) (err error) { +func Delete{{modelName}}(id int64) (err error) { o := orm.NewOrm() v := {{modelName}}{Id: id} // ascertain id exists in the database From d7b23aa54f26b6625989a60a2f16e72b02ba89a8 Mon Sep 17 00:00:00 2001 From: itcbx Date: Sat, 29 Aug 2015 15:14:21 +0800 Subject: [PATCH 005/123] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=97=B6=EF=BC=8C@Sucess=20=E7=AC=AC?= =?UTF-8?q?=E4=B8=89=E4=B8=AA=E5=8F=82=E6=95=B0=E8=A7=A3=E6=9E=90=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原来的代码,当第三个参数有多个空格时,比如 // @Success 200 {string} delete success! 第三个参数会解析成success!,即会忽略第一个空格前的单词,修改后,可以正常解析。 --- g_docs.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/g_docs.go b/g_docs.go index ea2ef00..3db26a8 100644 --- a/g_docs.go +++ b/g_docs.go @@ -395,10 +395,13 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat tmp = make([]rune, 0) j += 1 start = false - continue - } else { - st[j] = strings.TrimSpace(ss[i+1:]) - break + if j == 1 { + continue + } else { + st[j] = strings.TrimSpace(ss[i+1:]) + break + + } } } else { start = true From faaa3320bc5c90f4f7970c74fbfc9c4dd319dfbd Mon Sep 17 00:00:00 2001 From: Pelle Johnsen Date: Tue, 22 Sep 2015 14:53:43 +0200 Subject: [PATCH 006/123] Update to match changes in beego develop branch Mainly changes casing: Api > API and Url > URL --- g_docs.go | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/g_docs.go b/g_docs.go index ea2ef00..6da36ce 100644 --- a/g_docs.go +++ b/g_docs.go @@ -52,7 +52,7 @@ const ( ) var rootapi swagger.ResourceListing -var apilist map[string]*swagger.ApiDeclaration +var apilist map[string]*swagger.APIDeclaration func init() { if beego.EnableDocs { @@ -64,14 +64,14 @@ func init() { if err != nil { beego.Error(err) } - beego.GlobalDocApi["Root"] = rootapi + beego.GlobalDocAPI["Root"] = rootapi for k, v := range apilist { - for i, a := range v.Apis { + for i, a := range v.APIs { a.Path = urlReplace(k + a.Path) - v.Apis[i] = a + v.APIs[i] = a } v.BasePath = BasePath - beego.GlobalDocApi[strings.Trim(k, "/")] = v + beego.GlobalDocAPI[strings.Trim(k, "/")] = v } } } @@ -102,8 +102,8 @@ const ( var pkgCache map[string]bool //pkg:controller:function:comments comments: key:value var controllerComments map[string]string var importlist map[string]string -var apilist map[string]*swagger.ApiDeclaration -var controllerList map[string][]swagger.Api +var apilist map[string]*swagger.APIDeclaration +var controllerList map[string][]swagger.API var modelsList map[string]map[string]swagger.Model var rootapi swagger.ResourceListing @@ -111,8 +111,8 @@ func init() { pkgCache = make(map[string]bool) controllerComments = make(map[string]string) importlist = make(map[string]string) - apilist = make(map[string]*swagger.ApiDeclaration) - controllerList = make(map[string][]swagger.Api) + apilist = make(map[string]*swagger.APIDeclaration) + controllerList = make(map[string][]swagger.API) modelsList = make(map[string]map[string]swagger.Model) } @@ -133,19 +133,19 @@ func generateDocs(curpath string) { for _, c := range f.Comments { for _, s := range strings.Split(c.Text(), "\n") { if strings.HasPrefix(s, "@APIVersion") { - rootapi.ApiVersion = strings.TrimSpace(s[len("@APIVersion"):]) + rootapi.APIVersion = strings.TrimSpace(s[len("@APIVersion"):]) } else if strings.HasPrefix(s, "@Title") { rootapi.Infos.Title = strings.TrimSpace(s[len("@Title"):]) } else if strings.HasPrefix(s, "@Description") { rootapi.Infos.Description = strings.TrimSpace(s[len("@Description"):]) } else if strings.HasPrefix(s, "@TermsOfServiceUrl") { - rootapi.Infos.TermsOfServiceUrl = strings.TrimSpace(s[len("@TermsOfServiceUrl"):]) + rootapi.Infos.TermsOfServiceURL = strings.TrimSpace(s[len("@TermsOfServiceUrl"):]) } else if strings.HasPrefix(s, "@Contact") { rootapi.Infos.Contact = strings.TrimSpace(s[len("@Contact"):]) } else if strings.HasPrefix(s, "@License") { rootapi.Infos.License = strings.TrimSpace(s[len("@License"):]) } else if strings.HasPrefix(s, "@LicenseUrl") { - rootapi.Infos.LicenseUrl = strings.TrimSpace(s[len("@LicenseUrl"):]) + rootapi.Infos.LicenseURL = strings.TrimSpace(s[len("@LicenseUrl"):]) } } } @@ -172,7 +172,7 @@ func generateDocs(curpath string) { case *ast.CallExpr: if selname := pp.Fun.(*ast.SelectorExpr).Sel.String(); selname == "NSNamespace" { s, params := analisysNewNamespace(pp) - subapi := swagger.ApiRef{Path: s} + subapi := swagger.APIRef{Path: s} controllerName := "" for _, sp := range params { switch pp := sp.(type) { @@ -185,7 +185,7 @@ func generateDocs(curpath string) { if v, ok := controllerComments[controllerName]; ok { subapi.Description = v } - rootapi.Apis = append(rootapi.Apis, subapi) + rootapi.APIs = append(rootapi.APIs, subapi) } else if selname == "NSInclude" { analisysNSInclude(f, pp) } @@ -233,12 +233,12 @@ func analisysNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) { func analisysNSInclude(baseurl string, ce *ast.CallExpr) string { cname := "" - a := &swagger.ApiDeclaration{} - a.ApiVersion = rootapi.ApiVersion + a := &swagger.APIDeclaration{} + a.APIVersion = rootapi.APIVersion a.SwaggerVersion = swagger.SwaggerVersion a.ResourcePath = baseurl a.Produces = []string{"application/json", "application/xml", "text/plain", "text/html"} - a.Apis = make([]swagger.Api, 0) + a.APIs = make([]swagger.API, 0) a.Models = make(map[string]swagger.Model) for _, p := range ce.Args { x := p.(*ast.UnaryExpr).X.(*ast.CompositeLit).Type.(*ast.SelectorExpr) @@ -246,15 +246,15 @@ func analisysNSInclude(baseurl string, ce *ast.CallExpr) string { cname = v + x.Sel.Name } if apis, ok := controllerList[cname]; ok { - if len(a.Apis) > 0 { - a.Apis = append(a.Apis, apis...) + if len(a.APIs) > 0 { + a.APIs = append(a.APIs, apis...) } else { - a.Apis = apis + a.APIs = apis } } if models, ok := modelsList[cname]; ok { for _, m := range models { - a.Models[m.Id] = m + a.Models[m.ID] = m } } } @@ -355,7 +355,7 @@ func isSystemPackage(pkgpath string) bool { // parse the func comments func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpath string) error { - innerapi := swagger.Api{} + innerapi := swagger.API{} opts := swagger.Operation{} if comments != nil && comments.List != nil { for _, c := range comments.List { @@ -369,9 +369,9 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat innerapi.Path = e1[0] if len(e1) == 2 && e1[1] != "" { e1 = strings.SplitN(e1[1], " ", 2) - opts.HttpMethod = strings.ToUpper(strings.Trim(e1[0], "[]")) + opts.HTTPMethod = strings.ToUpper(strings.Trim(e1[0], "[]")) } else { - opts.HttpMethod = "GET" + opts.HTTPMethod = "GET" } } else if strings.HasPrefix(t, "@Title") { opts.Nickname = strings.TrimSpace(t[len("@Title"):]) @@ -490,7 +490,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat if _, ok := controllerList[pkgpath+controllerName]; ok { controllerList[pkgpath+controllerName] = append(controllerList[pkgpath+controllerName], innerapi) } else { - controllerList[pkgpath+controllerName] = make([]swagger.Api, 1) + controllerList[pkgpath+controllerName] = make([]swagger.API, 1) controllerList[pkgpath+controllerName][0] = innerapi } } @@ -561,7 +561,7 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Model, realType if !ok { continue } - m.Id = k + m.ID = k if st.Fields.List != nil { m.Properties = make(map[string]swagger.ModelProperty) for _, field := range st.Fields.List { @@ -635,7 +635,7 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Model, realType } } } - if m.Id == "" { + if m.ID == "" { ColorLog("can't find the object: %v", str) os.Exit(1) } From 5c6eeae33ab4182718c5abe46007590efe790dca Mon Sep 17 00:00:00 2001 From: Haibin Liu Date: Mon, 28 Sep 2015 07:42:11 +0800 Subject: [PATCH 007/123] Fix no error message issue --- apiapp.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apiapp.go b/apiapp.go index f5a921b..8983cdf 100644 --- a/apiapp.go +++ b/apiapp.go @@ -323,7 +323,7 @@ func (o *ObjectController) Get() { if objectId != "" { ob, err := models.GetOne(objectId) if err != nil { - o.Data["json"] = err + o.Data["json"] = err.Error() } else { o.Data["json"] = ob } @@ -356,7 +356,7 @@ func (o *ObjectController) Put() { err := models.Update(objectId, ob.Score) if err != nil { - o.Data["json"] = err + o.Data["json"] = err.Error() } else { o.Data["json"] = "update success!" } @@ -426,7 +426,7 @@ func (u *UserController) Get() { if uid != "" { user, err := models.GetUser(uid) if err != nil { - u.Data["json"] = err + u.Data["json"] = err.Error() } else { u.Data["json"] = user } @@ -448,7 +448,7 @@ func (u *UserController) Put() { json.Unmarshal(u.Ctx.Input.RequestBody, &user) uu, err := models.UpdateUser(uid, &user) if err != nil { - u.Data["json"] = err + u.Data["json"] = err.Error() } else { u.Data["json"] = uu } From e2ee2a8a79ae22f23758d8fc19449a7ae95d3a4b Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 16 Oct 2015 23:44:11 +0800 Subject: [PATCH 008/123] update the status cide --- g_appcode.go | 27 ++++++++++++++------------- g_controllers.go | 15 ++++++++------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/g_appcode.go b/g_appcode.go index 5607e77..dffbb69 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -362,12 +362,12 @@ func getTableObjects(tableNames []string, db *sql.DB, dbTransformer DbTransforme // and fill in Table struct func (*MysqlDB) GetConstraints(db *sql.DB, table *Table, blackList map[string]bool) { rows, err := db.Query( - `SELECT + `SELECT c.constraint_type, u.column_name, u.referenced_table_schema, u.referenced_table_name, referenced_column_name, u.ordinal_position FROM - information_schema.table_constraints c + information_schema.table_constraints c INNER JOIN - information_schema.key_column_usage u ON c.constraint_name = u.constraint_name + information_schema.key_column_usage u ON c.constraint_name = u.constraint_name WHERE c.table_schema = database() AND c.table_name = ? AND u.table_schema = database() AND u.table_name = ?`, table.Name, table.Name) // u.position_in_unique_constraint, @@ -412,9 +412,9 @@ func (mysqlDB *MysqlDB) GetColumns(db *sql.DB, table *Table, blackList map[strin // retrieve columns colDefRows, _ := db.Query( `SELECT - column_name, data_type, column_type, is_nullable, column_default, extra + column_name, data_type, column_type, is_nullable, column_default, extra FROM - information_schema.columns + information_schema.columns WHERE table_schema = database() AND table_name = ?`, table.Name) @@ -537,7 +537,7 @@ func (*PostgresDB) GetTableNames(db *sql.DB) (tables []string) { // GetConstraints for PostgreSQL func (*PostgresDB) GetConstraints(db *sql.DB, table *Table, blackList map[string]bool) { rows, err := db.Query( - `SELECT + `SELECT c.constraint_type, u.column_name, cu.table_catalog AS referenced_table_catalog, @@ -545,13 +545,13 @@ func (*PostgresDB) GetConstraints(db *sql.DB, table *Table, blackList map[string cu.column_name AS referenced_column_name, u.ordinal_position FROM - information_schema.table_constraints c + information_schema.table_constraints c INNER JOIN information_schema.key_column_usage u ON c.constraint_name = u.constraint_name INNER JOIN information_schema.constraint_column_usage cu ON cu.constraint_name = c.constraint_name WHERE - c.table_catalog = current_database() AND c.table_schema = 'public' AND c.table_name = $1 + c.table_catalog = current_database() AND c.table_schema = 'public' AND c.table_name = $1 AND u.table_catalog = current_database() AND u.table_schema = 'public' AND u.table_name = $2`, table.Name, table.Name) // u.position_in_unique_constraint, if err != nil { @@ -606,7 +606,7 @@ func (postgresDB *PostgresDB) GetColumns(db *sql.DB, table *Table, blackList map column_default, '' AS extra FROM - information_schema.columns + information_schema.columns WHERE table_catalog = current_database() AND table_schema = 'public' AND table_name = $1`, table.Name) @@ -1167,14 +1167,15 @@ func (c *{{ctrlName}}Controller) URLMapping() { // @Title Post // @Description create {{ctrlName}} // @Param body body models.{{ctrlName}} true "body for {{ctrlName}} content" -// @Success 200 {int} models.{{ctrlName}}.Id +// @Success 201 {int} models.{{ctrlName}} // @Failure 403 body is empty // @router / [post] func (c *{{ctrlName}}Controller) Post() { var v models.{{ctrlName}} json.Unmarshal(c.Ctx.Input.RequestBody, &v) - if id, err := models.Add{{ctrlName}}(&v); err == nil { - c.Data["json"] = map[string]int64{"id": id} + if _, err := models.Add{{ctrlName}}(&v); err == nil { + c.Ctx.Output.SetStatus(201) + c.Data["json"] = v } else { c.Data["json"] = err.Error() } @@ -1208,7 +1209,7 @@ func (c *{{ctrlName}}Controller) GetOne() { // @Param limit query string false "Limit the size of result set. Must be an integer" // @Param offset query string false "Start position of result set. Must be an integer" // @Success 200 {object} models.{{ctrlName}} -// @Failure 403 +// @Failure 403 // @router / [get] func (c *{{ctrlName}}Controller) GetAll() { var fields []string diff --git a/g_controllers.go b/g_controllers.go index 30bc86c..a832679 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -88,7 +88,7 @@ func (c *{{controllerName}}Controller) URLMapping() { // @Title Post // @Description create {{controllerName}} // @Param body body models.{{controllerName}} true "body for {{controllerName}} content" -// @Success 200 {int} models.{{controllerName}}.Id +// @Success 201 {object} models.{{controllerName}} // @Failure 403 body is empty // @router / [post] func (c *{{controllerName}}Controller) Post() { @@ -128,7 +128,7 @@ func (c *{{controllerName}}Controller) GetAll() { // @Failure 403 :id is not int // @router /:id [put] func (c *{{controllerName}}Controller) Put() { - + } // @Title Delete @@ -138,7 +138,7 @@ func (c *{{controllerName}}Controller) Put() { // @Failure 403 id is empty // @router /:id [delete] func (c *{{controllerName}}Controller) Delete() { - + } ` @@ -170,14 +170,15 @@ func (c *{{controllerName}}Controller) URLMapping() { // @Title Post // @Description create {{controllerName}} // @Param body body models.{{controllerName}} true "body for {{controllerName}} content" -// @Success 200 {int} models.{{controllerName}}.Id +// @Success 201 {int} models.{{controllerName}} // @Failure 403 body is empty // @router / [post] func (c *{{controllerName}}Controller) Post() { var v models.{{controllerName}} json.Unmarshal(c.Ctx.Input.RequestBody, &v) - if id, err := models.Add{{controllerName}}(&v); err == nil { - c.Data["json"] = map[string]int64{"id": id} + if _, err := models.Add{{controllerName}}(&v); err == nil { + c.Ctx.Output.SetStatus(201) + c.Data["json"] = v } else { c.Data["json"] = err.Error() } @@ -211,7 +212,7 @@ func (c *{{controllerName}}Controller) GetOne() { // @Param limit query string false "Limit the size of result set. Must be an integer" // @Param offset query string false "Start position of result set. Must be an integer" // @Success 200 {object} models.{{controllerName}} -// @Failure 403 +// @Failure 403 // @router / [get] func (c *{{controllerName}}Controller) GetAll() { var fields []string From dec41734bd1c39c6622c07e5f4a34aafddb46b50 Mon Sep 17 00:00:00 2001 From: fugr Date: Thu, 22 Oct 2015 11:32:21 +0800 Subject: [PATCH 009/123] ServeJson-->ServeJSON,update to match beego develop --- apiapp.go | 24 ++++++++++++------------ g_appcode.go | 12 ++++++------ g_controllers.go | 12 ++++++------ 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/apiapp.go b/apiapp.go index 8983cdf..ec6bb95 100644 --- a/apiapp.go +++ b/apiapp.go @@ -309,7 +309,7 @@ func (o *ObjectController) Post() { json.Unmarshal(o.Ctx.Input.RequestBody, &ob) objectid := models.AddOne(ob) o.Data["json"] = map[string]string{"ObjectId": objectid} - o.ServeJson() + o.ServeJSON() } // @Title Get @@ -328,7 +328,7 @@ func (o *ObjectController) Get() { o.Data["json"] = ob } } - o.ServeJson() + o.ServeJSON() } // @Title GetAll @@ -339,7 +339,7 @@ func (o *ObjectController) Get() { func (o *ObjectController) GetAll() { obs := models.GetAll() o.Data["json"] = obs - o.ServeJson() + o.ServeJSON() } // @Title update @@ -360,7 +360,7 @@ func (o *ObjectController) Put() { } else { o.Data["json"] = "update success!" } - o.ServeJson() + o.ServeJSON() } // @Title delete @@ -373,7 +373,7 @@ func (o *ObjectController) Delete() { objectId := o.Ctx.Input.Params[":objectId"] models.Delete(objectId) o.Data["json"] = "delete success!" - o.ServeJson() + o.ServeJSON() } ` @@ -402,7 +402,7 @@ func (u *UserController) Post() { json.Unmarshal(u.Ctx.Input.RequestBody, &user) uid := models.AddUser(user) u.Data["json"] = map[string]string{"uid": uid} - u.ServeJson() + u.ServeJSON() } // @Title Get @@ -412,7 +412,7 @@ func (u *UserController) Post() { func (u *UserController) GetAll() { users := models.GetAllUsers() u.Data["json"] = users - u.ServeJson() + u.ServeJSON() } // @Title Get @@ -431,7 +431,7 @@ func (u *UserController) Get() { u.Data["json"] = user } } - u.ServeJson() + u.ServeJSON() } // @Title update @@ -453,7 +453,7 @@ func (u *UserController) Put() { u.Data["json"] = uu } } - u.ServeJson() + u.ServeJSON() } // @Title delete @@ -466,7 +466,7 @@ func (u *UserController) Delete() { uid := u.GetString(":uid") models.DeleteUser(uid) u.Data["json"] = "delete success!" - u.ServeJson() + u.ServeJSON() } // @Title login @@ -484,7 +484,7 @@ func (u *UserController) Login() { } else { u.Data["json"] = "user not exist" } - u.ServeJson() + u.ServeJSON() } // @Title logout @@ -493,7 +493,7 @@ func (u *UserController) Login() { // @router /logout [get] func (u *UserController) Logout() { u.Data["json"] = "logout success" - u.ServeJson() + u.ServeJSON() } ` diff --git a/g_appcode.go b/g_appcode.go index 5607e77..0869359 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -1178,7 +1178,7 @@ func (c *{{ctrlName}}Controller) Post() { } else { c.Data["json"] = err.Error() } - c.ServeJson() + c.ServeJSON() } // @Title Get @@ -1196,7 +1196,7 @@ func (c *{{ctrlName}}Controller) GetOne() { } else { c.Data["json"] = v } - c.ServeJson() + c.ServeJSON() } // @Title Get All @@ -1244,7 +1244,7 @@ func (c *{{ctrlName}}Controller) GetAll() { kv := strings.Split(cond, ":") if len(kv) != 2 { c.Data["json"] = errors.New("Error: invalid query key/value pair") - c.ServeJson() + c.ServeJSON() return } k, v := kv[0], kv[1] @@ -1258,7 +1258,7 @@ func (c *{{ctrlName}}Controller) GetAll() { } else { c.Data["json"] = l } - c.ServeJson() + c.ServeJSON() } // @Title Update @@ -1278,7 +1278,7 @@ func (c *{{ctrlName}}Controller) Put() { } else { c.Data["json"] = err.Error() } - c.ServeJson() + c.ServeJSON() } // @Title Delete @@ -1295,7 +1295,7 @@ func (c *{{ctrlName}}Controller) Delete() { } else { c.Data["json"] = err.Error() } - c.ServeJson() + c.ServeJSON() } ` ROUTER_TPL = `// @APIVersion 1.0.0 diff --git a/g_controllers.go b/g_controllers.go index 30bc86c..92be420 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -181,7 +181,7 @@ func (c *{{controllerName}}Controller) Post() { } else { c.Data["json"] = err.Error() } - c.ServeJson() + c.ServeJSON() } // @Title Get @@ -199,7 +199,7 @@ func (c *{{controllerName}}Controller) GetOne() { } else { c.Data["json"] = v } - c.ServeJson() + c.ServeJSON() } // @Title Get All @@ -247,7 +247,7 @@ func (c *{{controllerName}}Controller) GetAll() { kv := strings.Split(cond, ":") if len(kv) != 2 { c.Data["json"] = errors.New("Error: invalid query key/value pair") - c.ServeJson() + c.ServeJSON() return } k, v := kv[0], kv[1] @@ -261,7 +261,7 @@ func (c *{{controllerName}}Controller) GetAll() { } else { c.Data["json"] = l } - c.ServeJson() + c.ServeJSON() } // @Title Update @@ -281,7 +281,7 @@ func (c *{{controllerName}}Controller) Put() { } else { c.Data["json"] = err.Error() } - c.ServeJson() + c.ServeJSON() } // @Title Delete @@ -298,6 +298,6 @@ func (c *{{controllerName}}Controller) Delete() { } else { c.Data["json"] = err.Error() } - c.ServeJson() + c.ServeJSON() } ` From f664b678d94e12c139d11298526326be667199b7 Mon Sep 17 00:00:00 2001 From: Steeve Chailloux Date: Mon, 9 Nov 2015 19:48:53 -0600 Subject: [PATCH 010/123] fix typo and missing end-of-line --- g_scaffold.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/g_scaffold.go b/g_scaffold.go index 1d0c239..fb79a1f 100644 --- a/g_scaffold.go +++ b/g_scaffold.go @@ -48,12 +48,12 @@ func generateSQLFromFields(fields string) string { 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) + ColorLog("[ERRO] the fields format is wrong. should key:type,key:type " + v + "\n") return "" } typ, tag := getSqlType(kv[1]) if typ == "" { - ColorLog("[ERRO] the filds format is wrong. should key:type,key:type " + v) + ColorLog("[ERRO] the fields format is wrong. should key:type,key:type " + v + "\n") return "" } if i == 0 && strings.ToLower(kv[0]) != "id" { From d3153578ca7cf18460e699fb07cb4714fdd1b50e Mon Sep 17 00:00:00 2001 From: Steeve Chailloux Date: Mon, 9 Nov 2015 20:09:26 -0600 Subject: [PATCH 011/123] update migration.Sql to migration.SQL to match beego develop --- g.go | 4 ++-- g_migration.go | 4 ++-- g_scaffold.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/g.go b/g.go index 2d7e80e..e0eb265 100644 --- a/g.go +++ b/g.go @@ -166,8 +166,8 @@ func generateCode(cmd *Command, args []string) int { upsql := "" downsql := "" if fields != "" { - upsql = `m.Sql("CREATE TABLE ` + mname + "(" + generateSQLFromFields(fields.String()) + `)");` - downsql = `m.Sql("DROP TABLE ` + "`" + mname + "`" + `")` + upsql = `m.SQL("CREATE TABLE ` + mname + "(" + generateSQLFromFields(fields.String()) + `)");` + downsql = `m.SQL("DROP TABLE ` + "`" + mname + "`" + `")` } generateMigration(mname, upsql, downsql, curpath) case "controller": diff --git a/g_migration.go b/g_migration.go index 7e3fefe..d0d296d 100644 --- a/g_migration.go +++ b/g_migration.go @@ -79,13 +79,13 @@ func init() { // Run the migrations 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 func (m *{{StructName}}) Down() { - // use m.Sql("DROP TABLE ...") to reverse schema update + // use m.SQL("DROP TABLE ...") to reverse schema update {{DownSQL}} } ` diff --git a/g_scaffold.go b/g_scaffold.go index 1d0c239..e5617ba 100644 --- a/g_scaffold.go +++ b/g_scaffold.go @@ -28,8 +28,8 @@ func generateScaffold(sname, fields, crupath, driver, conn string) { upsql := "" downsql := "" if fields != "" { - upsql = `m.Sql("CREATE TABLE ` + sname + "(" + generateSQLFromFields(fields) + `)");` - downsql = `m.Sql("DROP TABLE ` + "`" + sname + "`" + `")` + upsql = `m.SQL("CREATE TABLE ` + sname + "(" + generateSQLFromFields(fields) + `)");` + downsql = `m.SQL("DROP TABLE ` + "`" + sname + "`" + `")` } generateMigration(sname, upsql, downsql, crupath) } From f2bbe62bce3676a519a07737622edb4b45817cd6 Mon Sep 17 00:00:00 2001 From: FarYoung Date: Wed, 25 Nov 2015 22:24:10 +0800 Subject: [PATCH 012/123] add post and put json invalid fomart filter --- g_appcode.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/g_appcode.go b/g_appcode.go index dffbb69..52d2a62 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -1172,10 +1172,13 @@ func (c *{{ctrlName}}Controller) URLMapping() { // @router / [post] func (c *{{ctrlName}}Controller) Post() { var v models.{{ctrlName}} - json.Unmarshal(c.Ctx.Input.RequestBody, &v) - if _, err := models.Add{{ctrlName}}(&v); err == nil { - c.Ctx.Output.SetStatus(201) - c.Data["json"] = v + if err := json.Unmarshal(c.Ctx.Input.RequestBody, &v); err == nil { + if _, err := models.Add{{ctrlName}}(&v); err == nil { + c.Ctx.Output.SetStatus(201) + c.Data["json"] = v + } else { + c.Data["json"] = err.Error() + } } else { c.Data["json"] = err.Error() } @@ -1273,9 +1276,12 @@ func (c *{{ctrlName}}Controller) Put() { idStr := c.Ctx.Input.Params[":id"] id, _ := strconv.Atoi(idStr) v := models.{{ctrlName}}{Id: id} - json.Unmarshal(c.Ctx.Input.RequestBody, &v) - if err := models.Update{{ctrlName}}ById(&v); err == nil { - c.Data["json"] = "OK" + if err := json.Unmarshal(c.Ctx.Input.RequestBody, &v); err == nil { + if err := models.Update{{ctrlName}}ById(&v); err == nil { + c.Data["json"] = "OK" + } else { + c.Data["json"] = err.Error() + } } else { c.Data["json"] = err.Error() } From 69c2bb9058a7bb47900b6caa0749d5df31eb96b8 Mon Sep 17 00:00:00 2001 From: Yanyi Wu Date: Fri, 27 Nov 2015 11:42:14 +0800 Subject: [PATCH 013/123] Fix bug about issue #143 --- pack.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pack.go b/pack.go index 7ce6b73..20f18f0 100644 --- a/pack.go +++ b/pack.go @@ -455,7 +455,7 @@ func packDirectory(excludePrefix []string, excludeSuffix []string, func isBeegoProject(thePath string) bool { fh, _ := os.Open(thePath) fis, _ := fh.Readdir(-1) - regex := regexp.MustCompile(`(?s)package main.*?import.*?\(.*?"github.com/astaxie/beego".*?\).*func main()`) + regex := regexp.MustCompile(`(?s)package main.*?import.*?\(.*?github.com/astaxie/beego".*?\).*func main()`) for _, fi := range fis { if fi.IsDir() == false && strings.HasSuffix(fi.Name(), ".go") { data, err := ioutil.ReadFile(path.Join(thePath, fi.Name())) From 807c3de8a7dcb2d84d4b25795aabdaddfb1909a0 Mon Sep 17 00:00:00 2001 From: astaxie Date: Wed, 6 Jan 2016 11:55:56 +0800 Subject: [PATCH 014/123] fix issue with new version --- apiapp.go | 18 +++++++++--------- bee.go | 1 + fix.go | 19 +++++++++++++++++++ g_appcode.go | 6 +++--- g_controllers.go | 6 +++--- g_docs.go | 2 +- 6 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 fix.go diff --git a/apiapp.go b/apiapp.go index ec6bb95..8ae376e 100644 --- a/apiapp.go +++ b/apiapp.go @@ -76,9 +76,9 @@ import ( ) func main() { - if beego.RunMode == "dev" { - beego.DirectoryIndex = true - beego.StaticDir["/swagger"] = "swagger" + if beego.BConfig.RunMode == "dev" { + beego.BConfig.WebConfig.DirectoryIndex = true + beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger" } beego.Run() } @@ -100,9 +100,9 @@ func init() { } func main() { - if beego.RunMode == "dev" { - beego.DirectoryIndex = true - beego.StaticDir["/swagger"] = "swagger" + if beego.BConfig.RunMode == "dev" { + beego.BConfig.WebConfig.DirectoryIndex = true + beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger" } beego.Run() } @@ -319,7 +319,7 @@ func (o *ObjectController) Post() { // @Failure 403 :objectId is empty // @router /:objectId [get] func (o *ObjectController) Get() { - objectId := o.Ctx.Input.Params[":objectId"] + objectId := o.Ctx.Input.Param(":objectId") if objectId != "" { ob, err := models.GetOne(objectId) if err != nil { @@ -350,7 +350,7 @@ func (o *ObjectController) GetAll() { // @Failure 403 :objectId is empty // @router /:objectId [put] func (o *ObjectController) Put() { - objectId := o.Ctx.Input.Params[":objectId"] + objectId := o.Ctx.Input.Param(":objectId") var ob models.Object json.Unmarshal(o.Ctx.Input.RequestBody, &ob) @@ -370,7 +370,7 @@ func (o *ObjectController) Put() { // @Failure 403 objectId is empty // @router /:objectId [delete] func (o *ObjectController) Delete() { - objectId := o.Ctx.Input.Params[":objectId"] + objectId := o.Ctx.Input.Param(":objectId") models.Delete(objectId) o.Data["json"] = "delete success!" o.ServeJSON() diff --git a/bee.go b/bee.go index 6f4b4f6..dcc9d14 100644 --- a/bee.go +++ b/bee.go @@ -85,6 +85,7 @@ var commands = []*Command{ cmdGenerate, //cmdRundocs, cmdMigrate, + cmdFix, } func main() { diff --git a/fix.go b/fix.go new file mode 100644 index 0000000..e572b7c --- /dev/null +++ b/fix.go @@ -0,0 +1,19 @@ +package main + +var cmdFix = &Command{ + UsageLine: "fix", + Short: "fix the beego application to compatibel with beego 1.6", + Long: ` +As from beego1.6, there's some incompatible code with the old version. + +bee fix help to upgrade the application to beego 1.6 +`, +} + +func init() { + cmdFix.Run = runFix +} + +func runFix(cmd *Command, args []string) int { + return 0 +} diff --git a/g_appcode.go b/g_appcode.go index 81d6213..228b9c2 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -1192,7 +1192,7 @@ func (c *{{ctrlName}}Controller) Post() { // @Failure 403 :id is empty // @router /:id [get] func (c *{{ctrlName}}Controller) GetOne() { - idStr := c.Ctx.Input.Params[":id"] + idStr := c.Ctx.Input.Param(":id") id, _ := strconv.Atoi(idStr) v, err := models.Get{{ctrlName}}ById(id) if err != nil { @@ -1273,7 +1273,7 @@ func (c *{{ctrlName}}Controller) GetAll() { // @Failure 403 :id is not int // @router /:id [put] func (c *{{ctrlName}}Controller) Put() { - idStr := c.Ctx.Input.Params[":id"] + idStr := c.Ctx.Input.Param(":id") id, _ := strconv.Atoi(idStr) v := models.{{ctrlName}}{Id: id} if err := json.Unmarshal(c.Ctx.Input.RequestBody, &v); err == nil { @@ -1295,7 +1295,7 @@ func (c *{{ctrlName}}Controller) Put() { // @Failure 403 id is empty // @router /:id [delete] func (c *{{ctrlName}}Controller) Delete() { - idStr := c.Ctx.Input.Params[":id"] + idStr := c.Ctx.Input.Param(":id") id, _ := strconv.Atoi(idStr) if err := models.Delete{{ctrlName}}(id); err == nil { c.Data["json"] = "OK" diff --git a/g_controllers.go b/g_controllers.go index 57f2e02..49b5fd9 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -192,7 +192,7 @@ func (c *{{controllerName}}Controller) Post() { // @Failure 403 :id is empty // @router /:id [get] func (c *{{controllerName}}Controller) GetOne() { - idStr := c.Ctx.Input.Params[":id"] + idStr := c.Ctx.Input.Param(":id") id, _ := strconv.ParseInt(idStr, 0, 64) v, err := models.Get{{controllerName}}ById(id) if err != nil { @@ -273,7 +273,7 @@ func (c *{{controllerName}}Controller) GetAll() { // @Failure 403 :id is not int // @router /:id [put] func (c *{{controllerName}}Controller) Put() { - idStr := c.Ctx.Input.Params[":id"] + idStr := c.Ctx.Input.Param(":id") id, _ := strconv.ParseInt(idStr, 0, 64) v := models.{{controllerName}}{Id: id} json.Unmarshal(c.Ctx.Input.RequestBody, &v) @@ -292,7 +292,7 @@ func (c *{{controllerName}}Controller) Put() { // @Failure 403 id is empty // @router /:id [delete] func (c *{{controllerName}}Controller) Delete() { - idStr := c.Ctx.Input.Params[":id"] + idStr := c.Ctx.Input.Param(":id") id, _ := strconv.ParseInt(idStr, 0, 64) if err := models.Delete{{controllerName}}(id); err == nil { c.Data["json"] = "OK" diff --git a/g_docs.go b/g_docs.go index 6da36ce..fb11bcd 100644 --- a/g_docs.go +++ b/g_docs.go @@ -55,7 +55,7 @@ var rootapi swagger.ResourceListing var apilist map[string]*swagger.APIDeclaration func init() { - if beego.EnableDocs { + if beego.Bconfig.WebConifg.EnableDocs { err := json.Unmarshal([]byte(Rootinfo), &rootapi) if err != nil { beego.Error(err) From 0ee483de971f3454ca0a17d99ebf7e282711cfa6 Mon Sep 17 00:00:00 2001 From: astaxie Date: Wed, 6 Jan 2016 13:59:49 +0800 Subject: [PATCH 015/123] fix the typo --- g_docs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/g_docs.go b/g_docs.go index fb11bcd..1d4d18b 100644 --- a/g_docs.go +++ b/g_docs.go @@ -55,7 +55,7 @@ var rootapi swagger.ResourceListing var apilist map[string]*swagger.APIDeclaration func init() { - if beego.Bconfig.WebConifg.EnableDocs { + if beego.BConfig.WebConfig.EnableDocs { err := json.Unmarshal([]byte(Rootinfo), &rootapi) if err != nil { beego.Error(err) From 2b4a3d19d2abd16aa4986d414ba736996e2775d0 Mon Sep 17 00:00:00 2001 From: tianqi Date: Wed, 6 Jan 2016 21:44:12 +0800 Subject: [PATCH 016/123] fix: https://github.com/beego/bee/issues/154 --- pack.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pack.go b/pack.go index 20f18f0..283c730 100644 --- a/pack.go +++ b/pack.go @@ -199,6 +199,7 @@ func (wft *walkFileTree) virPath(fpath string) string { return "" } name = name[1:] + name = strings.Replace(name, "\\", "/", -1) return name } From d9e7af689f98e4852a4beee7f58b0efb4d861910 Mon Sep 17 00:00:00 2001 From: tianqi Date: Wed, 6 Jan 2016 22:09:12 +0800 Subject: [PATCH 017/123] change replace windows seperator to filepath.Slash --- pack.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pack.go b/pack.go index 283c730..2ba42f8 100644 --- a/pack.go +++ b/pack.go @@ -199,7 +199,7 @@ func (wft *walkFileTree) virPath(fpath string) string { return "" } name = name[1:] - name = strings.Replace(name, "\\", "/", -1) + name = path.ToSlash(name) return name } From 04f8b3436e7c1bffa569649c35c79276fb37d320 Mon Sep 17 00:00:00 2001 From: astaxie Date: Thu, 7 Jan 2016 10:17:34 +0800 Subject: [PATCH 018/123] add goxc --- .gitignore | 1 + .goxc.json | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 .goxc.json diff --git a/.gitignore b/.gitignore index e5f9547..ffab5d0 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ _testmain.go .DS_Store bee *.exe~ +.goxc.local.json diff --git a/.goxc.json b/.goxc.json new file mode 100644 index 0000000..932660d --- /dev/null +++ b/.goxc.json @@ -0,0 +1,14 @@ +{ + "Tasks": [ + "default", + "publish-github" + ], + "PackageVersion": "0.0.1", + "TaskSettings": { + "publish-github": { + "owner": "beego", + "repository": "bee" + } + }, + "ConfigVersion": "0.9" +} \ No newline at end of file From 76fa75b8fcc2002254cddb9e71db610e89df7bc1 Mon Sep 17 00:00:00 2001 From: kyle Date: Thu, 7 Jan 2016 11:51:31 +0800 Subject: [PATCH 019/123] Fix bug that execute the cmd not in application catalog 2015/12/31 10:02:34 [INFO] Using matching model 'Post' panic: runtime error: slice bounds out of range goroutine 1 [running]: main.getPackagePath(0xc082005b60, 0xf, 0x0, 0x0) E:/ossbuild/src/bee/g_appcode.go:988 +0x5f7 main.generateController(0xc0820022b0, 0x4, 0xc082005b60, 0xf) E:/ossbuild/src/bee/g_controllers.go:52 +0xadc main.generateScaffold(0xc0820022b0, 0x4, 0xc0821150c0, 0x16, 0xc082005b60, 0xf, 0xc082118040, 0x5, 0xc0821150e0, 0x1e) E:/ossbuild/src/bee/g_scaffold.go:18 +0x2d7 main.generateCode(0xc0de40, 0xc08200c1b0, 0x3, 0x3, 0x0) E:/ossbuild/src/bee/g.go:123 +0x16c9 main.main() E:/ossbuild/src/bee/bee.go:114 +0x37d --- g_appcode.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/g_appcode.go b/g_appcode.go index 228b9c2..f5f6b0d 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -985,6 +985,12 @@ func getPackagePath(curpath string) (packpath string) { ColorLog("[ERRO] Can't generate application code outside of GOPATH '%s'\n", gopath) os.Exit(2) } + + if curpath == appsrcpath { + ColorLog("[ERRO] Can't generate application code outside of application PATH \n") + os.Exit(2) + } + packpath = strings.Join(strings.Split(curpath[len(appsrcpath)+1:], string(filepath.Separator)), "/") return } From 1f9de3a6e0962a972d56d84b7908418f2a27ee6d Mon Sep 17 00:00:00 2001 From: astaxie Date: Thu, 7 Jan 2016 18:38:43 +0800 Subject: [PATCH 020/123] change the name from TplNames to TplName --- new.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/new.go b/new.go index 36c02af..bba644d 100644 --- a/new.go +++ b/new.go @@ -237,7 +237,7 @@ type MainController struct { func (c *MainController) Get() { c.Data["Website"] = "beego.me" c.Data["Email"] = "astaxie@gmail.com" - c.TplNames = "index.tpl" + c.TplName = "index.tpl" } ` From c7c811358cbc2545829051c5637e07b3ba180003 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 8 Jan 2016 01:20:12 +0800 Subject: [PATCH 021/123] add fix command --- fix.go | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/fix.go b/fix.go index e572b7c..b220334 100644 --- a/fix.go +++ b/fix.go @@ -1,5 +1,13 @@ package main +import ( + "io/ioutil" + "os" + "path/filepath" + "regexp" + "strings" +) + var cmdFix = &Command{ UsageLine: "fix", Short: "fix the beego application to compatibel with beego 1.6", @@ -15,5 +23,105 @@ func init() { } func runFix(cmd *Command, args []string) int { + dir, err := os.Getwd() + if err != nil { + ColorLog("GetCurrent Path:%s\n", err) + } + filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if info.IsDir() { + return nil + } + ColorLog("%s\n", path) + err = fixFile(path) + if err != nil { + ColorLog("fixFile:%s\n", err) + } + return err + }) return 0 } + +var rules = []string{ + "beego.AppName", "beego.BConfig.AppName", + "beego.RunMode", "beego.BConfig.RunMode", + "beego.RecoverPanic", "beego.BConfig.RecoverPanic", + "beego.RouterCaseSensitive", "beego.BConfig.RouterCaseSensitive", + "beego.BeegoServerName", "beego.BConfig.ServerName", + "beego.EnableGzip", "beego.BConfig.EnableGzip", + "beego.ErrorsShow", "beego.BConfig.EnableErrorsShow", + "beego.CopyRequestBody", "beego.BConfig.CopyRequestBody", + "beego.MaxMemory", "beego.BConfig.MaxMemory", + "beego.Graceful", "beego.BConfig.Listen.Graceful", + "beego.HttpAddr", "beego.BConfig.Listen.HTTPAddr", + "beego.HttpPort", "beego.BConfig.Listen.HTTPPort", + "beego.ListenTCP4", "beego.BConfig.Listen.ListenTCP4", + "beego.EnableHttpListen", "beego.BConfig.Listen.HTTPEnable", + "beego.EnableHttpTLS", "beego.BConfig.Listen.HTTPSEnable", + "beego.HttpsAddr", "beego.BConfig.Listen.HTTPSAddr", + "beego.HttpsPort", "beego.BConfig.Listen.HTTPSPort", + "beego.HttpCertFile", "beego.BConfig.Listen.HTTPSCertFile", + "beego.HttpKeyFile", "beego.BConfig.Listen.HTTPSKeyFile", + "beego.EnableAdmin", "beego.BConfig.Listen.AdminEnable", + "beego.AdminHttpAddr", "beego.BConfig.Listen.AdminAddr", + "beego.AdminHttpPort", "beego.BConfig.Listen.AdminPort", + "beego.UseFcgi", "beego.BConfig.Listen.EnableFcgi", + "beego.HttpServerTimeOut", "beego.BConfig.Listen.ServerTimeOut", + "beego.AutoRender", "beego.BConfig.WebConfig.AutoRender", + "beego.ViewsPath", "beego.BConfig.WebConfig.ViewsPath", + "beego.DirectoryIndex", "beego.BConfig.WebConfig.DirectoryIndex", + "beego.FlashName", "beego.BConfig.WebConfig.FlashName", + "beego.FlashSeperator", "beego.BConfig.WebConfig.FlashSeperator", + "beego.EnableDocs", "beego.BConfig.WebConfig.EnableDocs", + "beego.XSRFKEY", "beego.BConfig.WebConfig.XSRFKEY", + "beego.EnableXSRF", "beego.BConfig.WebConfig.EnableXSRF", + "beego.XSRFExpire", "beego.BConfig.WebConfig.XSRFExpire", + "beego.TemplateLeft", "beego.BConfig.WebConfig.TemplateLeft", + "beego.TemplateRight", "beego.BConfig.WebConfig.TemplateRight", + "beego.SessionOn", "beego.BConfig.WebConfig.Session.SessionOn", + "beego.SessionProvider", "beego.BConfig.WebConfig.Session.SessionProvider", + "beego.SessionName", "beego.BConfig.WebConfig.Session.SessionName", + "beego.SessionGCMaxLifetime", "beego.BConfig.WebConfig.Session.SessionGCMaxLifetime", + "beego.SessionSavePath", "beego.BConfig.WebConfig.Session.SessionProviderConfig", + "beego.SessionCookieLifeTime", "beego.BConfig.WebConfig.Session.SessionCookieLifeTime", + "beego.SessionAutoSetCookie", "beego.BConfig.WebConfig.Session.SessionAutoSetCookie", + "beego.SessionDomain", "beego.BConfig.WebConfig.Session.SessionDomain", + ".UrlFor(", ".URLFor(", + ".ServeJson(", ".ServeJSON(", + ".ServeXml(", ".ServeXML(", + ".XsrfToken(", ".XSRFToken(", + ".CheckXsrfCookie(", ".CheckXSRFCookie(", + ".XsrfFormHtml(", ".XSRFFormHTML(", + "beego.UrlFor(", "beego.URLFor(", + "beego.GlobalDocApi", "beego.GlobalDocAPI", + "beego.Errorhandler", "beego.ErrorHandler", + "Output.Jsonp(", "Output.JSONP", + "Output.Json(", "Output.JSON", + "Output.Xml(", "Output.XML", + "Input.Uri()", "Input.URI()", + "Input.Url()", "Input.URL()", + "Input.AcceptsHtml()", "Input.AcceptsHTML()", + "Input.AcceptsXml()", "Input.AcceptsXML()", + "Input.AcceptsJson()", "Input.AcceptsJSON()", + "Ctx.XsrfToken()", "Ctx.XSRFToken()", + "Ctx.CheckXsrfCookie()", "Ctx.CheckXSRFCookie()", + "session.SessionStore", "session.Store", + ".TplNames", ".TplName", +} + +func fixFile(file string) error { + rp := strings.NewReplacer(rules...) + content, err := ioutil.ReadFile(file) + if err != nil { + return err + } + fixed := rp.Replace(string(content)) + pareg := regexp.MustCompile(`(Ctx.Input.Params\[")(.*)("])`) + fixed = pareg.ReplaceAllString(fixed, "Ctx.Input.Param(\"$2\")") + pareg = regexp.MustCompile(`Ctx.Input.Params\)`) + fixed = pareg.ReplaceAllString(fixed, "Ctx.Input.Params())") + err = os.Truncate(file, 0) + if err != nil { + return err + } + return ioutil.WriteFile(file, []byte(fixed), 0666) +} From 7342e701e5dc74f21ad533a51c9053e748604f2a Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 8 Jan 2016 10:50:52 +0800 Subject: [PATCH 022/123] add more rules for upgrade --- fix.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fix.go b/fix.go index b220334..a301042 100644 --- a/fix.go +++ b/fix.go @@ -85,6 +85,7 @@ var rules = []string{ "beego.SessionCookieLifeTime", "beego.BConfig.WebConfig.Session.SessionCookieLifeTime", "beego.SessionAutoSetCookie", "beego.BConfig.WebConfig.Session.SessionAutoSetCookie", "beego.SessionDomain", "beego.BConfig.WebConfig.Session.SessionDomain", + "Ctx.Input.CopyBody(", "Ctx.Input.CopyBody(beego.BConfig.MaxMemory", ".UrlFor(", ".URLFor(", ".ServeJson(", ".ServeJSON(", ".ServeXml(", ".ServeXML(", @@ -106,6 +107,11 @@ var rules = []string{ "Ctx.CheckXsrfCookie()", "Ctx.CheckXSRFCookie()", "session.SessionStore", "session.Store", ".TplNames", ".TplName", + "swagger.ApiRef", "swagger.APIRef", + "swagger.ApiDeclaration", "swagger.APIDeclaration", + "swagger.Api", "swagger.API", + "swagger.ApiRef", "swagger.APIRef", + "toolbox.UrlMap", "toolbox.URLMap", } func fixFile(file string) error { From f0da7795a4f593aa170cebf6be4e11ef880a9511 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 8 Jan 2016 11:04:05 +0800 Subject: [PATCH 023/123] skip start with . dir --- fix.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fix.go b/fix.go index a301042..43c2443 100644 --- a/fix.go +++ b/fix.go @@ -29,8 +29,14 @@ func runFix(cmd *Command, args []string) int { } filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if info.IsDir() { + if strings.HasPrefix(info.Name(), ".") { + return filepath.SkipDir + } return nil } + if err != nil { + return err + } ColorLog("%s\n", path) err = fixFile(path) if err != nil { From ed219d7158c5cefd664c9caa3ceb975f13feb566 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 8 Jan 2016 11:10:18 +0800 Subject: [PATCH 024/123] fix the params rules --- fix.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fix.go b/fix.go index 43c2443..0028cb9 100644 --- a/fix.go +++ b/fix.go @@ -127,10 +127,10 @@ func fixFile(file string) error { return err } fixed := rp.Replace(string(content)) - pareg := regexp.MustCompile(`(Ctx.Input.Params\[")(.*)("])`) - fixed = pareg.ReplaceAllString(fixed, "Ctx.Input.Param(\"$2\")") - pareg = regexp.MustCompile(`Ctx.Input.Params\)`) - fixed = pareg.ReplaceAllString(fixed, "Ctx.Input.Params())") + pareg := regexp.MustCompile(`(Input.Params\[")(.*)("])`) + fixed = pareg.ReplaceAllString(fixed, "Input.Param(\"$2\")") + pareg = regexp.MustCompile(`Input.Params\)`) + fixed = pareg.ReplaceAllString(fixed, "Input.Params())") err = os.Truncate(file, 0) if err != nil { return err From 284c7fd7a926f96b3864ad316c584b1a2e47cd35 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 8 Jan 2016 11:35:23 +0800 Subject: [PATCH 025/123] fix the log.LoggerInterface & v.Apis --- fix.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fix.go b/fix.go index 0028cb9..8e103d7 100644 --- a/fix.go +++ b/fix.go @@ -118,6 +118,7 @@ var rules = []string{ "swagger.Api", "swagger.API", "swagger.ApiRef", "swagger.APIRef", "toolbox.UrlMap", "toolbox.URLMap", + "log.LoggerInterface", "log.Logger", } func fixFile(file string) error { @@ -131,6 +132,10 @@ func fixFile(file string) error { fixed = pareg.ReplaceAllString(fixed, "Input.Param(\"$2\")") pareg = regexp.MustCompile(`Input.Params\)`) fixed = pareg.ReplaceAllString(fixed, "Input.Params())") + // replace the v.Apis in docs.go + if strings.Contains("docs.go") { + strings.Replace(fixed, "v.Apis", "v.APIs", -1) + } err = os.Truncate(file, 0) if err != nil { return err From b305152fe7afb22768868bcf5f3ffa682c0a3dfb Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 8 Jan 2016 11:37:46 +0800 Subject: [PATCH 026/123] fix the StaticDir & StaticExtensionsToGzip --- fix.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fix.go b/fix.go index 8e103d7..9d3b3ca 100644 --- a/fix.go +++ b/fix.go @@ -74,6 +74,8 @@ var rules = []string{ "beego.HttpServerTimeOut", "beego.BConfig.Listen.ServerTimeOut", "beego.AutoRender", "beego.BConfig.WebConfig.AutoRender", "beego.ViewsPath", "beego.BConfig.WebConfig.ViewsPath", + "beego.StaticDir", "beego.BConfig.WebConfig.StaticDir", + "beego.StaticExtensionsToGzip", "beego.BConfig.WebConfig.StaticExtensionsToGzip", "beego.DirectoryIndex", "beego.BConfig.WebConfig.DirectoryIndex", "beego.FlashName", "beego.BConfig.WebConfig.FlashName", "beego.FlashSeperator", "beego.BConfig.WebConfig.FlashSeperator", From 07aa189b6f547c69bd3785ee8065de57e9a2be69 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 8 Jan 2016 11:40:49 +0800 Subject: [PATCH 027/123] fix the miss arguments --- fix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fix.go b/fix.go index 9d3b3ca..a2111f2 100644 --- a/fix.go +++ b/fix.go @@ -135,7 +135,7 @@ func fixFile(file string) error { pareg = regexp.MustCompile(`Input.Params\)`) fixed = pareg.ReplaceAllString(fixed, "Input.Params())") // replace the v.Apis in docs.go - if strings.Contains("docs.go") { + if strings.Contains(file, "docs.go") { strings.Replace(fixed, "v.Apis", "v.APIs", -1) } err = os.Truncate(file, 0) From 4401bfccdaca26ff1737473f1770baeb2b421e36 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 8 Jan 2016 11:44:38 +0800 Subject: [PATCH 028/123] assignment the result --- fix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fix.go b/fix.go index a2111f2..52583b2 100644 --- a/fix.go +++ b/fix.go @@ -136,7 +136,7 @@ func fixFile(file string) error { fixed = pareg.ReplaceAllString(fixed, "Input.Params())") // replace the v.Apis in docs.go if strings.Contains(file, "docs.go") { - strings.Replace(fixed, "v.Apis", "v.APIs", -1) + fixed = strings.Replace(fixed, "v.Apis", "v.APIs", -1) } err = os.Truncate(file, 0) if err != nil { From 0e3370baa808292a4caee604b3a8169f49a85291 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 8 Jan 2016 11:47:16 +0800 Subject: [PATCH 029/123] fix the log prackage name --- fix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fix.go b/fix.go index 52583b2..9a88d09 100644 --- a/fix.go +++ b/fix.go @@ -120,7 +120,7 @@ var rules = []string{ "swagger.Api", "swagger.API", "swagger.ApiRef", "swagger.APIRef", "toolbox.UrlMap", "toolbox.URLMap", - "log.LoggerInterface", "log.Logger", + "logs.LoggerInterface", "logs.Logger", } func fixFile(file string) error { From f997f5b6252b3f53e795af9a5627e0bb298b8bb4 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 8 Jan 2016 23:16:17 +0800 Subject: [PATCH 030/123] add fix data & params --- fix.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fix.go b/fix.go index 9a88d09..20fa7a1 100644 --- a/fix.go +++ b/fix.go @@ -121,6 +121,8 @@ var rules = []string{ "swagger.ApiRef", "swagger.APIRef", "toolbox.UrlMap", "toolbox.URLMap", "logs.LoggerInterface", "logs.Logger", + "Input.Request", "Input.Context.Request", + "Input.Params)", "Input.Params())", } func fixFile(file string) error { @@ -130,14 +132,21 @@ func fixFile(file string) error { return err } fixed := rp.Replace(string(content)) + + // forword the RequestBody from the replace + // "Input.Request", "Input.Context.Request", + fixed = strings.Replace(fixed, "Input.Context.RequestBody", "Input.RequestBody", -1) + + // regexp replace pareg := regexp.MustCompile(`(Input.Params\[")(.*)("])`) fixed = pareg.ReplaceAllString(fixed, "Input.Param(\"$2\")") - pareg = regexp.MustCompile(`Input.Params\)`) - fixed = pareg.ReplaceAllString(fixed, "Input.Params())") + pareg = regexp.MustCompile(`(Input.Data\[\")(.*)(\"\])(\s)(=)(\s)(.*)`) + fixed = pareg.ReplaceAllString(fixed, "Input.SetData(\"$2\", $7)") // replace the v.Apis in docs.go if strings.Contains(file, "docs.go") { fixed = strings.Replace(fixed, "v.Apis", "v.APIs", -1) } + err = os.Truncate(file, 0) if err != nil { return err From 685da50d936139e28e28319c5fafa06ff44f5a39 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Mon, 11 Jan 2016 12:22:38 +0800 Subject: [PATCH 031/123] fix #1552 in beego, see: https://github.com/astaxie/beego/issues/1552 --- run.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/run.go b/run.go index 8d2f9a2..f1f97bb 100644 --- a/run.go +++ b/run.go @@ -134,7 +134,7 @@ func readAppDirectories(directory string, paths *[]string) { continue } - if isExcluded(fileInfo) { + if isExcluded(path.Join(directory, fileInfo.Name())) { continue } @@ -157,10 +157,20 @@ func readAppDirectories(directory string, paths *[]string) { } // If a file is excluded -func isExcluded(fileInfo os.FileInfo) bool { +func isExcluded(filePath string) bool { for _, p := range excludedPaths { - if strings.HasSuffix(fileInfo.Name(), p) { - ColorLog("[INFO] Excluding from watching [ %s ]\n", fileInfo.Name()) + absP, err := path.Abs(p) + if err != nil { + ColorLog("[ERROR] Can not get absolute path of [ %s ]\n", p) + continue + } + absFilePath, err := path.Abs(filePath) + if err != nil { + ColorLog("[ERROR] Can not get absolute path of [ %s ]\n", filePath) + break + } + if strings.HasPrefix(absFilePath, absP) { + ColorLog("[INFO] Excluding from watching [ %s ]\n", filePath) return true } } From d34e14d013e4a6f38cea4206099383a5cf8a0c1f Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 11 Jan 2016 14:30:42 +0800 Subject: [PATCH 032/123] update orm and httplib fix --- fix.go | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/fix.go b/fix.go index 20fa7a1..6d024ca 100644 --- a/fix.go +++ b/fix.go @@ -103,9 +103,9 @@ var rules = []string{ "beego.UrlFor(", "beego.URLFor(", "beego.GlobalDocApi", "beego.GlobalDocAPI", "beego.Errorhandler", "beego.ErrorHandler", - "Output.Jsonp(", "Output.JSONP", - "Output.Json(", "Output.JSON", - "Output.Xml(", "Output.XML", + "Output.Jsonp(", "Output.JSONP(", + "Output.Json(", "Output.JSON(", + "Output.Xml(", "Output.XML(", "Input.Uri()", "Input.URI()", "Input.Url()", "Input.URL()", "Input.AcceptsHtml()", "Input.AcceptsHTML()", @@ -123,6 +123,26 @@ var rules = []string{ "logs.LoggerInterface", "logs.Logger", "Input.Request", "Input.Context.Request", "Input.Params)", "Input.Params())", + "httplib.BeegoHttpSettings", "httplib.BeegoHTTPSettings", + "httplib.BeegoHttpRequest", "httplib.BeegoHTTPRequest", + ".TlsClientConfig", ".TLSClientConfig", + ".JsonBody", ".JSONBody", + ".ToJson", ".ToJSON", + ".ToXml", ".ToXML", + "beego.Html2str", "beego.HTML2str", + "beego.AssetsCss", "beego.AssetsCSS", + "orm.DR_Sqlite", "orm.DRSqlite", + "orm.DR_Postgres", "orm.DRPostgres", + "orm.DR_MySQL", "orm.DRMySQL", + "orm.DR_Oracle", "orm.DROracle", + "orm.Col_Add", "orm.ColAdd", + "orm.Col_Minus", "orm.ColMinus", + "orm.Col_Multiply", "orm.ColMultiply", + "orm.Col_Except", "orm.ColExcept", + "GenerateOperatorSql", "GenerateOperatorSQL", + "OperatorSql", "OperatorSQL", + "orm.Debug_Queries", "orm.DebugQueries", + "orm.COMMA_SPACE", "orm.CommaSpace", } func fixFile(file string) error { From c2bca2b11487ff2c25363298ab1b82a8ae56e59b Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 11 Jan 2016 15:21:54 +0800 Subject: [PATCH 033/123] fix data --- fix.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fix.go b/fix.go index 6d024ca..897cabb 100644 --- a/fix.go +++ b/fix.go @@ -162,6 +162,8 @@ func fixFile(file string) error { fixed = pareg.ReplaceAllString(fixed, "Input.Param(\"$2\")") pareg = regexp.MustCompile(`(Input.Data\[\")(.*)(\"\])(\s)(=)(\s)(.*)`) fixed = pareg.ReplaceAllString(fixed, "Input.SetData(\"$2\", $7)") + pareg = regexp.MustCompile(`(Input.Data\[\")(.*)(\"\])`) + fixed = pareg.ReplaceAllString(fixed, "Input.Data(\"$2\")") // replace the v.Apis in docs.go if strings.Contains(file, "docs.go") { fixed = strings.Replace(fixed, "v.Apis", "v.APIs", -1) From 36eb03e05c6bc4e895efbe9940d3b6e96bea5474 Mon Sep 17 00:00:00 2001 From: astaxie Date: Tue, 12 Jan 2016 21:57:52 +0800 Subject: [PATCH 034/123] update the fix for config --- fix.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fix.go b/fix.go index 897cabb..a52c9d9 100644 --- a/fix.go +++ b/fix.go @@ -168,6 +168,18 @@ func fixFile(file string) error { if strings.Contains(file, "docs.go") { fixed = strings.Replace(fixed, "v.Apis", "v.APIs", -1) } + // replace the config file + if strings.HasSuffix(file, ".conf") { + fixed = strings.Replace(fixed, "HttpCertFile", "HTTPSCertFile", -1) + fixed = strings.Replace(fixed, "HttpKeyFile", "HTTPSKeyFile", -1) + fixed = strings.Replace(fixed, "EnableHttpListen", "HTTPEnable", -1) + fixed = strings.Replace(fixed, "EnableHttpTLS", "EnableHTTPS", -1) + fixed = strings.Replace(fixed, "EnableHttpTLS", "EnableHTTPS", -1) + fixed = strings.Replace(fixed, "BeegoServerName", "ServerName", -1) + fixed = strings.Replace(fixed, "AdminHttpAddr", "AdminAddr", -1) + fixed = strings.Replace(fixed, "AdminHttpPort", "AdminPort", -1) + fixed = strings.Replace(fixed, "HttpServerTimeOut", "ServerTimeOut", -1) + } err = os.Truncate(file, 0) if err != nil { From 7ac766053e5ab59384339ad7e9cf52aede24e00f Mon Sep 17 00:00:00 2001 From: tianqi Date: Wed, 13 Jan 2016 13:14:51 +0800 Subject: [PATCH 035/123] add user : as separator for exp's and exs's flag tip --- pack.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pack.go b/pack.go index 2ba42f8..9d66088 100644 --- a/pack.go +++ b/pack.go @@ -48,8 +48,8 @@ This eases the deployment by extracting the zip file to a server. -be=[] additional ENV Variables of go build. eg: GOARCH=arm -o compressed file output dir. default use current path -f="" format: tar.gz, zip (default: tar.gz) --exp="" relpath exclude prefix (default: .). --exs="" relpath exclude suffix (default: .go:.DS_Store:.tmp). +-exp="" relpath exclude prefix (default: .). use : as separator +-exs="" relpath exclude suffix (default: .go:.DS_Store:.tmp). use : as separator all path use : as separator -exr=[] file/directory name exclude by Regexp (default: ^). -fs=false follow symlink (default: false). From 32eb301861b987b9a5594a901eb730e9f3a36fe3 Mon Sep 17 00:00:00 2001 From: astaxie Date: Wed, 13 Jan 2016 16:39:56 +0800 Subject: [PATCH 036/123] add fix for cache update --- fix.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/fix.go b/fix.go index a52c9d9..71167ff 100644 --- a/fix.go +++ b/fix.go @@ -1,6 +1,8 @@ package main import ( + "go/parser" + "go/token" "io/ioutil" "os" "path/filepath" @@ -164,6 +166,27 @@ func fixFile(file string) error { fixed = pareg.ReplaceAllString(fixed, "Input.SetData(\"$2\", $7)") pareg = regexp.MustCompile(`(Input.Data\[\")(.*)(\"\])`) fixed = pareg.ReplaceAllString(fixed, "Input.Data(\"$2\")") + // fix the cache object Put method + pareg = regexp.MustCompile(`(\.Put\(\")(.*)(\",)(\s)(.*)(,\s*)([^\*.]*)(\))`) + if pareg.MatchString(fixed) && strings.HasSuffix(file, ".go") { + fixed = pareg.ReplaceAllString(fixed, ".Put(\"$2\", $5, $7*time.Second)") + fset := token.NewFileSet() // positions are relative to fset + f, err := parser.ParseFile(fset, file, nil, parser.ImportsOnly) + if err != nil { + panic(err) + } + // Print the imports from the file's AST. + hasTimepkg := false + for _, s := range f.Imports { + if s.Path.Value == `"time"` { + hasTimepkg = true + break + } + } + if !hasTimepkg { + fixed = strings.Replace(fixed, "import (", "import (\n\t\"time\"", 1) + } + } // replace the v.Apis in docs.go if strings.Contains(file, "docs.go") { fixed = strings.Replace(fixed, "v.Apis", "v.APIs", -1) @@ -180,7 +203,6 @@ func fixFile(file string) error { fixed = strings.Replace(fixed, "AdminHttpPort", "AdminPort", -1) fixed = strings.Replace(fixed, "HttpServerTimeOut", "ServerTimeOut", -1) } - err = os.Truncate(file, 0) if err != nil { return err From 19c9f8923f229894b7403ca8c269154d1c98b9a4 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 15 Jan 2016 14:30:17 +0800 Subject: [PATCH 037/123] typo fixed https://github.com/JessonChan/beego/commit/52083de720bdb828e71ff94b278fd1f7bc5f830a https://github.com/astaxie/beego/pull/1567 --- fix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fix.go b/fix.go index 71167ff..5d1585c 100644 --- a/fix.go +++ b/fix.go @@ -80,7 +80,7 @@ var rules = []string{ "beego.StaticExtensionsToGzip", "beego.BConfig.WebConfig.StaticExtensionsToGzip", "beego.DirectoryIndex", "beego.BConfig.WebConfig.DirectoryIndex", "beego.FlashName", "beego.BConfig.WebConfig.FlashName", - "beego.FlashSeperator", "beego.BConfig.WebConfig.FlashSeperator", + "beego.FlashSeperator", "beego.BConfig.WebConfig.FlashSeparator", "beego.EnableDocs", "beego.BConfig.WebConfig.EnableDocs", "beego.XSRFKEY", "beego.BConfig.WebConfig.XSRFKEY", "beego.EnableXSRF", "beego.BConfig.WebConfig.EnableXSRF", From 0acdf2e816e31c3394d1a8f7099caa5cf37c8a89 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 15 Jan 2016 14:45:56 +0800 Subject: [PATCH 038/123] fix the rename in beego --- fix.go | 3 ++- g_docs.go | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/fix.go b/fix.go index 5d1585c..5500563 100644 --- a/fix.go +++ b/fix.go @@ -82,7 +82,7 @@ var rules = []string{ "beego.FlashName", "beego.BConfig.WebConfig.FlashName", "beego.FlashSeperator", "beego.BConfig.WebConfig.FlashSeparator", "beego.EnableDocs", "beego.BConfig.WebConfig.EnableDocs", - "beego.XSRFKEY", "beego.BConfig.WebConfig.XSRFKEY", + "beego.XSRFKEY", "beego.BConfig.WebConfig.XSRFKey", "beego.EnableXSRF", "beego.BConfig.WebConfig.EnableXSRF", "beego.XSRFExpire", "beego.BConfig.WebConfig.XSRFExpire", "beego.TemplateLeft", "beego.BConfig.WebConfig.TemplateLeft", @@ -121,6 +121,7 @@ var rules = []string{ "swagger.ApiDeclaration", "swagger.APIDeclaration", "swagger.Api", "swagger.API", "swagger.ApiRef", "swagger.APIRef", + "swagger.Infomation", "swagger.Information", "toolbox.UrlMap", "toolbox.URLMap", "logs.LoggerInterface", "logs.Logger", "Input.Request", "Input.Context.Request", diff --git a/g_docs.go b/g_docs.go index 1d4d18b..b067add 100644 --- a/g_docs.go +++ b/g_docs.go @@ -126,7 +126,7 @@ func generateDocs(curpath string) { os.Exit(2) } - rootapi.Infos = swagger.Infomation{} + rootapi.Info = swagger.Information{} rootapi.SwaggerVersion = swagger.SwaggerVersion //analysis API comments if f.Comments != nil { @@ -135,17 +135,17 @@ func generateDocs(curpath string) { if strings.HasPrefix(s, "@APIVersion") { rootapi.APIVersion = strings.TrimSpace(s[len("@APIVersion"):]) } else if strings.HasPrefix(s, "@Title") { - rootapi.Infos.Title = strings.TrimSpace(s[len("@Title"):]) + rootapi.Info.Title = strings.TrimSpace(s[len("@Title"):]) } else if strings.HasPrefix(s, "@Description") { - rootapi.Infos.Description = strings.TrimSpace(s[len("@Description"):]) + rootapi.Info.Description = strings.TrimSpace(s[len("@Description"):]) } else if strings.HasPrefix(s, "@TermsOfServiceUrl") { - rootapi.Infos.TermsOfServiceURL = strings.TrimSpace(s[len("@TermsOfServiceUrl"):]) + rootapi.Info.TermsOfServiceURL = strings.TrimSpace(s[len("@TermsOfServiceUrl"):]) } else if strings.HasPrefix(s, "@Contact") { - rootapi.Infos.Contact = strings.TrimSpace(s[len("@Contact"):]) + rootapi.Info.Contact = strings.TrimSpace(s[len("@Contact"):]) } else if strings.HasPrefix(s, "@License") { - rootapi.Infos.License = strings.TrimSpace(s[len("@License"):]) + rootapi.Info.License = strings.TrimSpace(s[len("@License"):]) } else if strings.HasPrefix(s, "@LicenseUrl") { - rootapi.Infos.LicenseURL = strings.TrimSpace(s[len("@LicenseUrl"):]) + rootapi.Info.LicenseURL = strings.TrimSpace(s[len("@LicenseUrl"):]) } } } From 4bc70441d21fce11140861fa396093d83b019c91 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 15 Jan 2016 23:43:37 +0800 Subject: [PATCH 039/123] change version from 1.3 to 1.4 --- bee.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bee.go b/bee.go index dcc9d14..17efccf 100644 --- a/bee.go +++ b/bee.go @@ -25,7 +25,7 @@ import ( "strings" ) -const version = "1.3.0" +const version = "1.4.0" type Command struct { // Run runs the command. From 08ff1c91efdb650373e43dbea477c163b3818d32 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 18 Jan 2016 10:27:17 +0800 Subject: [PATCH 040/123] fix the beego version --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 19c8159..23c461f 100644 --- a/version.go +++ b/version.go @@ -43,7 +43,7 @@ func versionCmd(cmd *Command, args []string) int { func getbeegoVersion() string { gopath := os.Getenv("GOPATH") - re, err := regexp.Compile(`const VERSION = "([0-9.]+)"`) + re, err := regexp.Compile(`VERSION = "([0-9.]+)"`) if err != nil { return "" } From 46a9c4a39051d1e574171e9bee9889922f8e0d8b Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 18 Jan 2016 11:33:52 +0800 Subject: [PATCH 041/123] update fix --- bee.go | 2 +- fix.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/bee.go b/bee.go index 17efccf..11f2352 100644 --- a/bee.go +++ b/bee.go @@ -25,7 +25,7 @@ import ( "strings" ) -const version = "1.4.0" +const version = "1.4.1" type Command struct { // Run runs the command. diff --git a/fix.go b/fix.go index 5500563..e5d2344 100644 --- a/fix.go +++ b/fix.go @@ -39,6 +39,9 @@ func runFix(cmd *Command, args []string) int { if err != nil { return err } + if strings.HasSuffix(info.Name(), ".exe") { + return nil + } ColorLog("%s\n", path) err = fixFile(path) if err != nil { @@ -146,6 +149,7 @@ var rules = []string{ "OperatorSql", "OperatorSQL", "orm.Debug_Queries", "orm.DebugQueries", "orm.COMMA_SPACE", "orm.CommaSpace", + ".SendOut()", ".DoRequest()", } func fixFile(file string) error { From 460aa32b7e026f0cedbbf6453857f9c24c622509 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 25 Jan 2016 21:05:08 +0800 Subject: [PATCH 042/123] fix #164 #165 --- fix.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fix.go b/fix.go index e5d2344..69d6584 100644 --- a/fix.go +++ b/fix.go @@ -102,6 +102,7 @@ var rules = []string{ ".UrlFor(", ".URLFor(", ".ServeJson(", ".ServeJSON(", ".ServeXml(", ".ServeXML(", + ".ServeJsonp(", ".ServeJSONP(", ".XsrfToken(", ".XSRFToken(", ".CheckXsrfCookie(", ".CheckXSRFCookie(", ".XsrfFormHtml(", ".XSRFFormHTML(", @@ -150,6 +151,7 @@ var rules = []string{ "orm.Debug_Queries", "orm.DebugQueries", "orm.COMMA_SPACE", "orm.CommaSpace", ".SendOut()", ".DoRequest()", + "validation.ValidationError", "validation.Error", } func fixFile(file string) error { From 0dbe35a943df043e0f0f373000675924ec67daf5 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 25 Jan 2016 21:43:29 +0800 Subject: [PATCH 043/123] go vet happy --- code.go | 1 - run.go | 1 - test.go | 1 - util.go | 3 +-- 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/code.go b/code.go index 5e4c3e2..c341a74 100644 --- a/code.go +++ b/code.go @@ -251,7 +251,6 @@ func commentAnnotations(src string) []Annotation { annotations = append(annotations, Annotation{Kind: CommentAnnotation, Pos: int16(p), End: int16(e)}) } } - return nil } type sliceWriter struct{ p *[]byte } diff --git a/run.go b/run.go index f1f97bb..8ef769c 100644 --- a/run.go +++ b/run.go @@ -119,7 +119,6 @@ func runApp(cmd *Command, args []string) int { runtime.Goexit() } } - return 0 } func readAppDirectories(directory string, paths *[]string) { diff --git a/test.go b/test.go index 6790c42..de5116d 100644 --- a/test.go +++ b/test.go @@ -73,7 +73,6 @@ func testApp(cmd *Command, args []string) int { runTest() } } - return 0 } func runTest() { diff --git a/util.go b/util.go index 1b8685d..0f314df 100644 --- a/util.go +++ b/util.go @@ -152,7 +152,6 @@ func getColorLevel(level string) string { default: return level } - return level } // IsExist returns whether a file or directory exists. @@ -252,7 +251,7 @@ func camelString(s string) string { type strFlags []string func (s *strFlags) String() string { - return fmt.Sprintf("%d", *s) + return fmt.Sprintf("%s", *s) } func (s *strFlags) Set(value string) error { From 1566ca7da16102eab17a81346a1bc223642bc183 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 25 Jan 2016 21:49:49 +0800 Subject: [PATCH 044/123] add beego version and bee version and travis --- .travis.yml | 6 ++++++ run.go | 13 ++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..933c032 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: go + +go: + - 1.5.3 + - 1.4.3 + - 1.3.3 diff --git a/run.go b/run.go index 8ef769c..ec136b6 100644 --- a/run.go +++ b/run.go @@ -15,8 +15,11 @@ package main import ( + "fmt" "io/ioutil" + "log" "os" + "os/exec" path "path/filepath" "runtime" "strings" @@ -51,6 +54,14 @@ func init() { var appname string func runApp(cmd *Command, args []string) int { + fmt.Println("bee :" + version) + fmt.Println("beego :" + getbeegoVersion()) + goversion, err := exec.Command("go", "version").Output() + if err != nil { + log.Fatal(err) + } + fmt.Println("Go :" + string(goversion)) + exit := make(chan bool) crupath, _ := os.Getwd() @@ -70,7 +81,7 @@ func runApp(cmd *Command, args []string) int { } Debugf("current path:%s\n", crupath) - err := loadConfig() + err = loadConfig() if err != nil { ColorLog("[ERRO] Fail to parse bee.json[ %s ]\n", err) } From 060b452ac058683c9462e36bcc0617f380cc4762 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Fri, 5 Feb 2016 08:32:45 +0800 Subject: [PATCH 045/123] fix #1663 --- fix.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fix.go b/fix.go index 69d6584..790d979 100644 --- a/fix.go +++ b/fix.go @@ -66,8 +66,8 @@ var rules = []string{ "beego.HttpAddr", "beego.BConfig.Listen.HTTPAddr", "beego.HttpPort", "beego.BConfig.Listen.HTTPPort", "beego.ListenTCP4", "beego.BConfig.Listen.ListenTCP4", - "beego.EnableHttpListen", "beego.BConfig.Listen.HTTPEnable", - "beego.EnableHttpTLS", "beego.BConfig.Listen.HTTPSEnable", + "beego.EnableHttpListen", "beego.BConfig.Listen.EnableHTTP", + "beego.EnableHttpTLS", "beego.BConfig.Listen.EnableHTTPS", "beego.HttpsAddr", "beego.BConfig.Listen.HTTPSAddr", "beego.HttpsPort", "beego.BConfig.Listen.HTTPSPort", "beego.HttpCertFile", "beego.BConfig.Listen.HTTPSCertFile", From 19b8add1c518b670e0a35f3130097433edd05039 Mon Sep 17 00:00:00 2001 From: Mark Mindenhall Date: Wed, 10 Feb 2016 12:39:02 -0700 Subject: [PATCH 046/123] Support go build tags (issue #149) --- run.go | 6 +++++- watch.go | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/run.go b/run.go index ec136b6..3d4da70 100644 --- a/run.go +++ b/run.go @@ -26,7 +26,7 @@ import ( ) var cmdRun = &Command{ - UsageLine: "run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] [-e=Godeps -e=folderToExclude]", + UsageLine: "run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] [-e=Godeps -e=folderToExclude] [-tags=goBuildTags]", Short: "run the app and start a Web server for development", Long: ` Run command will supervise the file system of the beego project using inotify, @@ -43,12 +43,16 @@ var gendoc docValue // The flags list of the paths excluded from watching var excludedPaths strFlags +// Pass through to -tags arg of "go build" +var buildTags string + func init() { cmdRun.Run = runApp cmdRun.Flag.Var(&mainFiles, "main", "specify main go files") cmdRun.Flag.Var(&gendoc, "gendoc", "auto generate the docs") cmdRun.Flag.Var(&downdoc, "downdoc", "auto download swagger file when not exist") cmdRun.Flag.Var(&excludedPaths, "e", "Excluded paths[].") + cmdRun.Flag.StringVar(&buildTags, "tags", "", "Build tags (https://golang.org/pkg/go/build/)") } var appname string diff --git a/watch.go b/watch.go index f18dd3c..371598e 100644 --- a/watch.go +++ b/watch.go @@ -170,6 +170,9 @@ func Autobuild(files []string, isgenerate bool) { args := []string{"build"} args = append(args, "-o", appName) + if buildTags != "" { + args = append(args, "-tags", buildTags) + } args = append(args, files...) bcmd := exec.Command(cmdName, args...) From 1767458b66e1760dc4c8e01405ee087cd0fb2458 Mon Sep 17 00:00:00 2001 From: Scott Le Date: Tue, 1 Mar 2016 10:08:04 +0700 Subject: [PATCH 047/123] fix cannot migrate with Postgres --- migrate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrate.go b/migrate.go index 2e3d8b2..173c5b0 100644 --- a/migrate.go +++ b/migrate.go @@ -244,7 +244,7 @@ func selectMigrationsTableSql(driver string) string { case "mysql": return "DESC migrations" case "postgres": - return "SELECT * FROM migrations ORDER BY id_migration;" + return "SELECT * FROM migrations WHERE false ORDER BY id_migration;" default: return "DESC migrations" } From 6481a96ca4506c769f1c6b1794d32f6c91237aa0 Mon Sep 17 00:00:00 2001 From: Liut Date: Fri, 11 Mar 2016 23:39:17 +0800 Subject: [PATCH 048/123] =?UTF-8?q?allow=20any=20schema=20in=20PostgresDB;?= =?UTF-8?q?=20=E5=A6=82=E6=9E=9C=E9=80=89=E6=8B=A9=20PostgreSQL=EF=BC=8C?= =?UTF-8?q?=E5=85=81=E8=AE=B8=E5=AE=9A=E5=88=B6=E7=9A=84=20schema;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g_appcode.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/g_appcode.go b/g_appcode.go index f5f6b0d..7860912 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -516,7 +516,9 @@ func (*MysqlDB) GetGoDataType(sqlType string) (goType string) { func (*PostgresDB) GetTableNames(db *sql.DB) (tables []string) { rows, err := db.Query(` SELECT table_name FROM information_schema.tables - WHERE table_catalog = current_database() and table_schema = 'public'`) + WHERE table_catalog = current_database() AND + table_type = 'BASE TABLE' AND + table_schema NOT IN ('pg_catalog', 'information_schema')`) if err != nil { ColorLog("[ERRO] Could not show tables: %s\n", err) ColorLog("[HINT] Check your connection string\n") @@ -551,8 +553,10 @@ func (*PostgresDB) GetConstraints(db *sql.DB, table *Table, blackList map[string INNER JOIN information_schema.constraint_column_usage cu ON cu.constraint_name = c.constraint_name WHERE - c.table_catalog = current_database() AND c.table_schema = 'public' AND c.table_name = $1 - AND u.table_catalog = current_database() AND u.table_schema = 'public' AND u.table_name = $2`, + c.table_catalog = current_database() AND c.table_schema NOT IN ('pg_catalog', 'information_schema') + AND c.table_name = $1 + AND u.table_catalog = current_database() AND u.table_schema NOT IN ('pg_catalog', 'information_schema') + AND u.table_name = $2`, table.Name, table.Name) // u.position_in_unique_constraint, if err != nil { ColorLog("[ERRO] Could not query INFORMATION_SCHEMA for PK/UK/FK information: %s\n", err) @@ -608,7 +612,8 @@ func (postgresDB *PostgresDB) GetColumns(db *sql.DB, table *Table, blackList map FROM information_schema.columns WHERE - table_catalog = current_database() AND table_schema = 'public' AND table_name = $1`, + table_catalog = current_database() AND table_schema NOT IN ('pg_catalog', 'information_schema') + AND table_name = $1`, table.Name) defer colDefRows.Close() for colDefRows.Next() { @@ -985,12 +990,12 @@ func getPackagePath(curpath string) (packpath string) { ColorLog("[ERRO] Can't generate application code outside of GOPATH '%s'\n", gopath) os.Exit(2) } - + if curpath == appsrcpath { ColorLog("[ERRO] Can't generate application code outside of application PATH \n") os.Exit(2) } - + packpath = strings.Join(strings.Split(curpath[len(appsrcpath)+1:], string(filepath.Separator)), "/") return } From 7210ac621d012af8282f6685cfb5baed48bd80da Mon Sep 17 00:00:00 2001 From: Sergey Lanzman Date: Sat, 12 Mar 2016 14:05:15 +0200 Subject: [PATCH 049/123] optimisation disable GC for go build , go list, go install +20% speed on large projects --- watch.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/watch.go b/watch.go index 371598e..7d966bd 100644 --- a/watch.go +++ b/watch.go @@ -136,6 +136,7 @@ func Autobuild(files []string, isgenerate bool) { icmd := exec.Command("go", "list", "./...") buf := bytes.NewBuffer([]byte("")) icmd.Stdout = buf + icmd.Env = append(os.Environ(), "GOGC=off") err = icmd.Run() if err == nil { list := strings.Split(buf.String(), "\n")[1:] @@ -146,6 +147,7 @@ func Autobuild(files []string, isgenerate bool) { icmd = exec.Command(cmdName, "install", pkg) icmd.Stdout = os.Stdout icmd.Stderr = os.Stderr + icmd.Env = append(os.Environ(), "GOGC=off") err = icmd.Run() if err != nil { break @@ -156,6 +158,7 @@ func Autobuild(files []string, isgenerate bool) { if isgenerate { icmd := exec.Command("bee", "generate", "docs") + icmd.Env = append(os.Environ(), "GOGC=off") icmd.Stdout = os.Stdout icmd.Stderr = os.Stderr icmd.Run() @@ -176,6 +179,7 @@ func Autobuild(files []string, isgenerate bool) { args = append(args, files...) bcmd := exec.Command(cmdName, args...) + bcmd.Env = append(os.Environ(), "GOGC=off") bcmd.Stdout = os.Stdout bcmd.Stderr = os.Stderr err = bcmd.Run() From e523bf5da4e717c6670522a86fcf1dbb7b821c4b Mon Sep 17 00:00:00 2001 From: Dmitri Logvinenko Date: Sun, 27 Mar 2016 16:42:26 +0300 Subject: [PATCH 050/123] Fix misspelling and improve command description --- fix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fix.go b/fix.go index 69d6584..3e1d3d6 100644 --- a/fix.go +++ b/fix.go @@ -12,7 +12,7 @@ import ( var cmdFix = &Command{ UsageLine: "fix", - Short: "fix the beego application to compatibel with beego 1.6", + Short: "fix the beego application to make it compatible with beego 1.6", Long: ` As from beego1.6, there's some incompatible code with the old version. From d312a60e4f4c8456c411d3cbb47914136dbd6158 Mon Sep 17 00:00:00 2001 From: Dmitry Burakov Date: Sat, 2 Apr 2016 21:37:58 +0300 Subject: [PATCH 051/123] changed required go version [issue 172] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b597b54..5bad9ee 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Bee is a command line tool facilitating development with beego framework. ## Requirements -- Go version >= 1.1. +- Go version >= 1.3. ## Installation From 7abba4be163a8197a0ed6fbf2f61cefb4cb2f246 Mon Sep 17 00:00:00 2001 From: Jonathan Penny Date: Wed, 13 Apr 2016 09:25:26 -0500 Subject: [PATCH 052/123] Fixed readme. $PATH was incorrect --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5bad9ee..cdb5e9d 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ go get github.com/beego/bee Then you can add `bee` binary to PATH environment variable in your `~/.bashrc` or `~/.bash_profile` file: ```bash -export PATH=$PATH:/bin/bee +export PATH=$PATH:/bin ``` > If you already have `bee` installed, updating `bee` is simple: From 6b9bc5debfbdc11606ca30fb36ce73bdd18b3229 Mon Sep 17 00:00:00 2001 From: Jacob Bin Wang Date: Fri, 20 May 2016 09:58:12 +0800 Subject: [PATCH 053/123] Fix EnableAdmin error in fix rules 1. "EnableAdmin" should be replaced by "BConfig.Listen.EnableAdmin", instead of "BConfig.Listen.AdminEnable" --- fix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fix.go b/fix.go index 855fc0a..b4dbd39 100644 --- a/fix.go +++ b/fix.go @@ -72,7 +72,7 @@ var rules = []string{ "beego.HttpsPort", "beego.BConfig.Listen.HTTPSPort", "beego.HttpCertFile", "beego.BConfig.Listen.HTTPSCertFile", "beego.HttpKeyFile", "beego.BConfig.Listen.HTTPSKeyFile", - "beego.EnableAdmin", "beego.BConfig.Listen.AdminEnable", + "beego.EnableAdmin", "beego.BConfig.Listen.EnableAdmin", "beego.AdminHttpAddr", "beego.BConfig.Listen.AdminAddr", "beego.AdminHttpPort", "beego.BConfig.Listen.AdminPort", "beego.UseFcgi", "beego.BConfig.Listen.EnableFcgi", From 01e7ff37749d3c060bb9bfcfcdbbc2294c6e86a6 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Thu, 26 May 2016 18:17:24 +0200 Subject: [PATCH 054/123] This fixes #201 --- apiapp.go | 64 +++++++++++++++------------------------------------- g_appcode.go | 10 ++++---- hproseapp.go | 10 ++++---- new.go | 51 +++++++++-------------------------------- 4 files changed, 39 insertions(+), 96 deletions(-) diff --git a/apiapp.go b/apiapp.go index 8ae376e..15ff035 100644 --- a/apiapp.go +++ b/apiapp.go @@ -546,14 +546,15 @@ func init() { } func createapi(cmd *Command, args []string) int { - curpath, _ := os.Getwd() if len(args) < 1 { ColorLog("[ERRO] Argument [appname] is missing\n") os.Exit(2) } + if len(args) > 1 { cmd.Flag.Parse(args[1:]) } + apppath, packpath, err := checkEnv(args[0]) if err != nil { fmt.Println(err) @@ -576,8 +577,8 @@ func createapi(cmd *Command, args []string) int { fmt.Println("create tests:", path.Join(apppath, "tests")) fmt.Println("create conf app.conf:", path.Join(apppath, "conf", "app.conf")) - writetofile(path.Join(apppath, "conf", "app.conf"), - strings.Replace(apiconf, "{{.Appname}}", args[0], -1)) + WriteToFile(path.Join(apppath, "conf", "app.conf"), + strings.Replace(apiconf, "{{.Appname}}", path.Base(args[0]), -1)) if conn != "" { fmt.Println("create main.go:", path.Join(apppath, "main.go")) @@ -588,7 +589,7 @@ func createapi(cmd *Command, args []string) int { } else if driver == "postgres" { maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/lib/pq"`, -1) } - writetofile(path.Join(apppath, "main.go"), + WriteToFile(path.Join(apppath, "main.go"), strings.Replace( maingoContent, "{{.conn}}", @@ -599,7 +600,7 @@ func createapi(cmd *Command, args []string) int { ColorLog("[INFO] Using '%s' as 'driver'\n", driver) ColorLog("[INFO] Using '%s' as 'conn'\n", conn) ColorLog("[INFO] Using '%s' as 'tables'\n", tables) - generateAppcode(string(driver), string(conn), "3", string(tables), path.Join(curpath, args[0])) + generateAppcode(string(driver), string(conn), "3", string(tables), path.Join(apppath, args[0])) } else { os.Mkdir(path.Join(apppath, "models"), 0755) fmt.Println("create models:", path.Join(apppath, "models")) @@ -607,43 +608,38 @@ func createapi(cmd *Command, args []string) int { fmt.Println(path.Join(apppath, "routers") + string(path.Separator)) fmt.Println("create controllers object.go:", path.Join(apppath, "controllers", "object.go")) - writetofile(path.Join(apppath, "controllers", "object.go"), + WriteToFile(path.Join(apppath, "controllers", "object.go"), strings.Replace(apiControllers, "{{.Appname}}", packpath, -1)) fmt.Println("create controllers user.go:", path.Join(apppath, "controllers", "user.go")) - writetofile(path.Join(apppath, "controllers", "user.go"), + WriteToFile(path.Join(apppath, "controllers", "user.go"), strings.Replace(apiControllers2, "{{.Appname}}", packpath, -1)) fmt.Println("create tests default.go:", path.Join(apppath, "tests", "default_test.go")) - writetofile(path.Join(apppath, "tests", "default_test.go"), + WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(apiTests, "{{.Appname}}", packpath, -1)) fmt.Println("create routers router.go:", path.Join(apppath, "routers", "router.go")) - writetofile(path.Join(apppath, "routers", "router.go"), + WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(apirouter, "{{.Appname}}", packpath, -1)) fmt.Println("create models object.go:", path.Join(apppath, "models", "object.go")) - writetofile(path.Join(apppath, "models", "object.go"), apiModels) + WriteToFile(path.Join(apppath, "models", "object.go"), apiModels) fmt.Println("create models user.go:", path.Join(apppath, "models", "user.go")) - writetofile(path.Join(apppath, "models", "user.go"), apiModels2) + WriteToFile(path.Join(apppath, "models", "user.go"), apiModels2) fmt.Println("create docs doc.go:", path.Join(apppath, "docs", "doc.go")) - writetofile(path.Join(apppath, "docs", "doc.go"), "package docs") + WriteToFile(path.Join(apppath, "docs", "doc.go"), "package docs") fmt.Println("create main.go:", path.Join(apppath, "main.go")) - writetofile(path.Join(apppath, "main.go"), + WriteToFile(path.Join(apppath, "main.go"), strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1)) } return 0 } func checkEnv(appname string) (apppath, packpath string, err error) { - curpath, err := os.Getwd() - if err != nil { - return - } - gopath := os.Getenv("GOPATH") Debugf("gopath:%s", gopath) if gopath == "" { @@ -651,38 +647,14 @@ func checkEnv(appname string) (apppath, packpath string, err error) { return } - appsrcpath := "" - haspath := false - wgopath := path.SplitList(gopath) - for _, wg := range wgopath { - wg = path.Join(wg, "src") - - if strings.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) { - haspath = true - appsrcpath = wg - break - } - - wg, _ = path.EvalSymlinks(wg) - - if strings.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) { - haspath = true - appsrcpath = wg - break - } - } - - if !haspath { - err = fmt.Errorf("can't create application outside of GOPATH `%s`\n"+ - "you first should `cd $GOPATH%ssrc` then use create\n", gopath, string(path.Separator)) - return - } - apppath = path.Join(curpath, appname) + gosrcpath := path.Join(gopath, "src") + apppath = path.Join(gosrcpath, appname) if _, e := os.Stat(apppath); os.IsNotExist(e) == false { err = fmt.Errorf("path `%s` exists, can not create app without remove it\n", apppath) return } - packpath = strings.Join(strings.Split(apppath[len(appsrcpath)+1:], string(path.Separator)), "/") + packpath = strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/") + return } diff --git a/g_appcode.go b/g_appcode.go index 7860912..fabec16 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -292,7 +292,7 @@ func generateAppcode(driver, connStr, level, tables, currpath string) { // Generate takes table, column and foreign key information from database connection // and generate corresponding golang source files -func gen(dbms, connStr string, mode byte, selectedTableNames map[string]bool, currpath string) { +func gen(dbms, connStr string, mode byte, selectedTableNames map[string]bool, apppath string) { db, err := sql.Open(dbms, connStr) if err != nil { ColorLog("[ERRO] Could not connect to %s database: %s, %s\n", dbms, connStr, err) @@ -304,11 +304,11 @@ func gen(dbms, connStr string, mode byte, selectedTableNames map[string]bool, cu tableNames := trans.GetTableNames(db) tables := getTableObjects(tableNames, db, trans) mvcPath := new(MvcPath) - mvcPath.ModelPath = path.Join(currpath, "models") - mvcPath.ControllerPath = path.Join(currpath, "controllers") - mvcPath.RouterPath = path.Join(currpath, "routers") + mvcPath.ModelPath = path.Join(apppath, "models") + mvcPath.ControllerPath = path.Join(apppath, "controllers") + mvcPath.RouterPath = path.Join(apppath, "routers") createPaths(mode, mvcPath) - pkgPath := getPackagePath(currpath) + pkgPath := getPackagePath(apppath) writeSourceFiles(pkgPath, tables, mode, mvcPath, selectedTableNames) } else { ColorLog("[ERRO] Generating app code from %s database is not supported yet.\n", dbms) diff --git a/hproseapp.go b/hproseapp.go index 5167c31..40abc47 100644 --- a/hproseapp.go +++ b/hproseapp.go @@ -274,7 +274,7 @@ func createhprose(cmd *Command, args []string) int { os.Mkdir(path.Join(apppath, "conf"), 0755) fmt.Println("create conf:", path.Join(apppath, "conf")) fmt.Println("create conf app.conf:", path.Join(apppath, "conf", "app.conf")) - writetofile(path.Join(apppath, "conf", "app.conf"), + WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(hproseconf, "{{.Appname}}", args[0], -1)) if conn != "" { @@ -291,7 +291,7 @@ func createhprose(cmd *Command, args []string) int { } else if driver == "postgres" { maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/lib/pq"`, -1) } - writetofile(path.Join(apppath, "main.go"), + WriteToFile(path.Join(apppath, "main.go"), strings.Replace( maingoContent, "{{.conn}}", @@ -304,13 +304,13 @@ func createhprose(cmd *Command, args []string) int { fmt.Println("create models:", path.Join(apppath, "models")) fmt.Println("create models object.go:", path.Join(apppath, "models", "object.go")) - writetofile(path.Join(apppath, "models", "object.go"), apiModels) + WriteToFile(path.Join(apppath, "models", "object.go"), apiModels) fmt.Println("create models user.go:", path.Join(apppath, "models", "user.go")) - writetofile(path.Join(apppath, "models", "user.go"), apiModels2) + WriteToFile(path.Join(apppath, "models", "user.go"), apiModels2) fmt.Println("create main.go:", path.Join(apppath, "main.go")) - writetofile(path.Join(apppath, "main.go"), + WriteToFile(path.Join(apppath, "main.go"), strings.Replace(hproseMaingo, "{{.Appname}}", packpath, -1)) } return 0 diff --git a/new.go b/new.go index bba644d..3c6fff9 100644 --- a/new.go +++ b/new.go @@ -55,7 +55,6 @@ func init() { } func createApp(cmd *Command, args []string) int { - curpath, _ := os.Getwd() if len(args) != 1 { ColorLog("[ERRO] Argument [appname] is missing\n") os.Exit(2) @@ -65,40 +64,12 @@ func createApp(cmd *Command, args []string) int { Debugf("gopath:%s", gopath) if gopath == "" { ColorLog("[ERRO] $GOPATH not found\n") - ColorLog("[HINT] Set $GOPATH in your environment vairables\n") - os.Exit(2) - } - haspath := false - appsrcpath := "" - - wgopath := path.SplitList(gopath) - for _, wg := range wgopath { - - wg = path.Join(wg, "src") - - if strings.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) { - haspath = true - appsrcpath = wg - break - } - - wg, _ = path.EvalSymlinks(wg) - - if strings.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) { - haspath = true - appsrcpath = wg - break - } - - } - - if !haspath { - ColorLog("[ERRO] Unable to create an application outside of $GOPATH%ssrc(%s%ssrc)\n", string(path.Separator), gopath, string(path.Separator)) - ColorLog("[HINT] Change your work directory by `cd ($GOPATH%ssrc)`\n", string(path.Separator)) + ColorLog("[HINT] Set $GOPATH in your environment variables\n") os.Exit(2) } - apppath := path.Join(curpath, args[0]) + gosrcpath := path.Join(gopath, "src") // User's workspace + apppath := path.Join(gosrcpath, args[0]) if isExist(apppath) { ColorLog("[ERRO] Path (%s) already exists\n", apppath) @@ -133,22 +104,22 @@ func createApp(cmd *Command, args []string) int { fmt.Println(path.Join(apppath, "views") + string(path.Separator)) os.Mkdir(path.Join(apppath, "views"), 0755) fmt.Println(path.Join(apppath, "conf", "app.conf")) - writetofile(path.Join(apppath, "conf", "app.conf"), strings.Replace(appconf, "{{.Appname}}", args[0], -1)) + WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(appconf, "{{.Appname}}", path.Base(args[0]), -1)) fmt.Println(path.Join(apppath, "controllers", "default.go")) - writetofile(path.Join(apppath, "controllers", "default.go"), controllers) + WriteToFile(path.Join(apppath, "controllers", "default.go"), controllers) fmt.Println(path.Join(apppath, "views", "index.tpl")) - writetofile(path.Join(apppath, "views", "index.tpl"), indextpl) + WriteToFile(path.Join(apppath, "views", "index.tpl"), indextpl) fmt.Println(path.Join(apppath, "routers", "router.go")) - writetofile(path.Join(apppath, "routers", "router.go"), strings.Replace(router, "{{.Appname}}", strings.Join(strings.Split(apppath[len(appsrcpath)+1:], string(path.Separator)), "/"), -1)) + WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(router, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1)) fmt.Println(path.Join(apppath, "tests", "default_test.go")) - writetofile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(test, "{{.Appname}}", strings.Join(strings.Split(apppath[len(appsrcpath)+1:], string(path.Separator)), "/"), -1)) + WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(test, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1)) fmt.Println(path.Join(apppath, "main.go")) - 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(gosrcpath)+1:], string(path.Separator)), "/"), -1)) ColorLog("[SUCC] New application successfully created!\n") return 0 @@ -336,11 +307,11 @@ var indextpl = ` ` -func writetofile(filename, content string) { +func WriteToFile(filename, content string) { f, err := os.Create(filename) + defer f.Close() if err != nil { panic(err) } - defer f.Close() f.WriteString(content) } From ebb0272bc86b12475e222d62fcb8fa2b10714fc0 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Tue, 31 May 2016 21:47:00 +0200 Subject: [PATCH 055/123] Ignore tmp/backup files while using watcher This fixes #212 and Adds the logic to skip tmp and backup files generated by Emacs, Vim or SublimeText. More RegExps can be added to 'ignoredFilesRegExps' slice in watch.go file. --- watch.go | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/watch.go b/watch.go index 7d966bd..868e892 100644 --- a/watch.go +++ b/watch.go @@ -17,14 +17,14 @@ package main import ( "bytes" "fmt" + "github.com/howeyc/fsnotify" "os" "os/exec" + "regexp" "runtime" "strings" "sync" "time" - - "github.com/howeyc/fsnotify" ) var ( @@ -47,8 +47,8 @@ func NewWatcher(paths []string, files []string, isgenerate bool) { case e := <-watcher.Event: isbuild := true - // Skip TMP files for Sublime Text. - if checkTMPFile(e.Name) { + // Skip ignored files + if shouldIgnoreFile(e.Name) { continue } if !checkIfWatchExt(e.Name) { @@ -230,15 +230,30 @@ func Start(appname string) { started <- true } -// checkTMPFile returns true if the event was for TMP files. -func checkTMPFile(name string) bool { - if strings.HasSuffix(strings.ToLower(name), ".tmp") { - return true +// Should ignore filenames generated by +// Emacs, Vim or SublimeText +func shouldIgnoreFile(filename string) bool { + for _, regex := range ignoredFilesRegExps { + r, err := regexp.Compile(regex) + if err != nil { + panic("Could not compile the regex: " + regex) + } + if r.MatchString(filename) { + return true + } else { + continue + } } return false } var watchExts = []string{".go"} +var ignoredFilesRegExps = []string{ + `.#(\w+).go`, + `.(\w+).go.swp`, + `(\w+).go~`, + `(\w+).tmp`, +} // checkIfWatchExt returns true if the name HasSuffix . func checkIfWatchExt(name string) bool { From b8250ebb726fc7ff797476a1b8d56dfc09f0f0ad Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Wed, 1 Jun 2016 14:30:29 +0200 Subject: [PATCH 056/123] New Bee banner Added a new Bee banner using ASCII art. When bee is invoked, the banner is displayed with the version number (short banner). A More verbose Banner is added to 'bee version' which shows more information about the host and Go runtime. --- apiapp.go | 53 ++++++++++++++++++++----------------- bale.go | 4 ++- banner.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ fix.go | 11 +++++--- g.go | 11 +++++--- g_controllers.go | 3 ++- g_migration.go | 2 +- g_model.go | 3 ++- g_scaffold.go | 14 +++++----- g_views.go | 10 ++++--- hproseapp.go | 22 +++++++++------ migrate.go | 2 ++ new.go | 38 +++++++++++++------------- pack.go | 29 ++++++++++---------- run.go | 13 ++------- version.go | 58 +++++++++++++++++++++++++++++----------- 16 files changed, 230 insertions(+), 112 deletions(-) create mode 100644 banner.go diff --git a/apiapp.go b/apiapp.go index 15ff035..ee1f1d0 100644 --- a/apiapp.go +++ b/apiapp.go @@ -546,6 +546,8 @@ func init() { } func createapi(cmd *Command, args []string) int { + ShowShortVersionBanner() + if len(args) < 1 { ColorLog("[ERRO] Argument [appname] is missing\n") os.Exit(2) @@ -565,23 +567,25 @@ func createapi(cmd *Command, args []string) int { } if conn == "" { } - os.MkdirAll(apppath, 0755) - fmt.Println("create app folder:", apppath) - os.Mkdir(path.Join(apppath, "conf"), 0755) - fmt.Println("create conf:", path.Join(apppath, "conf")) - os.Mkdir(path.Join(apppath, "controllers"), 0755) - fmt.Println("create controllers:", path.Join(apppath, "controllers")) - os.Mkdir(path.Join(apppath, "docs"), 0755) - fmt.Println("create docs:", path.Join(apppath, "docs")) - os.Mkdir(path.Join(apppath, "tests"), 0755) - fmt.Println("create tests:", path.Join(apppath, "tests")) - fmt.Println("create conf app.conf:", path.Join(apppath, "conf", "app.conf")) + ColorLog("[INFO] Creating API...\n") + + os.MkdirAll(apppath, 0755) + fmt.Println("\tcreate\t", apppath) + os.Mkdir(path.Join(apppath, "conf"), 0755) + fmt.Println("\tcreate\t", path.Join(apppath, "conf")) + os.Mkdir(path.Join(apppath, "controllers"), 0755) + fmt.Println("\tcreate\t", path.Join(apppath, "controllers")) + os.Mkdir(path.Join(apppath, "docs"), 0755) + fmt.Println("\tcreate\t", path.Join(apppath, "docs")) + os.Mkdir(path.Join(apppath, "tests"), 0755) + fmt.Println("\tcreate\t", path.Join(apppath, "tests")) + fmt.Println("\tcreate\t", path.Join(apppath, "conf", "app.conf")) WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(apiconf, "{{.Appname}}", path.Base(args[0]), -1)) if conn != "" { - fmt.Println("create main.go:", path.Join(apppath, "main.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "main.go")) maingoContent := strings.Replace(apiMainconngo, "{{.Appname}}", packpath, -1) maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(driver), -1) if driver == "mysql" { @@ -603,39 +607,40 @@ func createapi(cmd *Command, args []string) int { generateAppcode(string(driver), string(conn), "3", string(tables), path.Join(apppath, args[0])) } else { os.Mkdir(path.Join(apppath, "models"), 0755) - fmt.Println("create models:", path.Join(apppath, "models")) + fmt.Println("\tcreate\t", path.Join(apppath, "models")) os.Mkdir(path.Join(apppath, "routers"), 0755) - fmt.Println(path.Join(apppath, "routers") + string(path.Separator)) + fmt.Println("\tcreate\t", path.Join(apppath, "routers") + string(path.Separator)) - fmt.Println("create controllers object.go:", path.Join(apppath, "controllers", "object.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "controllers", "object.go")) WriteToFile(path.Join(apppath, "controllers", "object.go"), strings.Replace(apiControllers, "{{.Appname}}", packpath, -1)) - fmt.Println("create controllers user.go:", path.Join(apppath, "controllers", "user.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "controllers", "user.go")) WriteToFile(path.Join(apppath, "controllers", "user.go"), strings.Replace(apiControllers2, "{{.Appname}}", packpath, -1)) - fmt.Println("create tests default.go:", path.Join(apppath, "tests", "default_test.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "tests", "default_test.go")) WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(apiTests, "{{.Appname}}", packpath, -1)) - fmt.Println("create routers router.go:", path.Join(apppath, "routers", "router.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "routers", "router.go")) WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(apirouter, "{{.Appname}}", packpath, -1)) - fmt.Println("create models object.go:", path.Join(apppath, "models", "object.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "models", "object.go")) WriteToFile(path.Join(apppath, "models", "object.go"), apiModels) - fmt.Println("create models user.go:", path.Join(apppath, "models", "user.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "models", "user.go")) WriteToFile(path.Join(apppath, "models", "user.go"), apiModels2) - fmt.Println("create docs doc.go:", path.Join(apppath, "docs", "doc.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "docs", "doc.go")) WriteToFile(path.Join(apppath, "docs", "doc.go"), "package docs") - fmt.Println("create main.go:", path.Join(apppath, "main.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "main.go")) WriteToFile(path.Join(apppath, "main.go"), strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1)) } + ColorLog("[SUCC] New API successfully created!\n") return 0 } @@ -651,10 +656,10 @@ func checkEnv(appname string) (apppath, packpath string, err error) { apppath = path.Join(gosrcpath, appname) if _, e := os.Stat(apppath); os.IsNotExist(e) == false { - err = fmt.Errorf("path `%s` exists, can not create app without remove it\n", apppath) + err = fmt.Errorf("Cannot create application without removing `%s` first.", apppath) + ColorLog("[ERRO] Path `%s` already exists\n", apppath) return } packpath = strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/") - return } diff --git a/bale.go b/bale.go index 336d813..5f1f803 100644 --- a/bale.go +++ b/bale.go @@ -46,6 +46,8 @@ func init() { } func runBale(cmd *Command, args []string) int { + ShowShortVersionBanner() + err := loadConfig() if err != nil { ColorLog("[ERRO] Fail to parse bee.json[ %s ]\n", err) @@ -60,7 +62,7 @@ func runBale(cmd *Command, args []string) int { ColorLog("[WARN] Skipped directory( %s )\n", p) continue } - ColorLog("[INFO] Packing directory( %s )\n", p) + ColorLog("[INFO] Packaging directory( %s )\n", p) filepath.Walk(p, walkFn) } diff --git a/banner.go b/banner.go new file mode 100644 index 0000000..d04293b --- /dev/null +++ b/banner.go @@ -0,0 +1,69 @@ +package main + +import ( + "io" + "io/ioutil" + "os" + "runtime" + "text/template" + "time" +) + +type vars struct { + GoVersion string + GOOS string + GOARCH string + NumCPU int + GOPATH string + GOROOT string + Compiler string + BeeVersion string + BeegoVersion string +} + +func Now(layout string) string { + return time.Now().Format(layout) +} + +// Init load the banner and prints it to output +// All errors are ignored, the application will not +// print the banner in case of error. +func InitBanner(out io.Writer, in io.Reader) { + if in == nil { + ColorLog("[ERRO] The input is nil\n") + os.Exit(2) + } + + banner, err := ioutil.ReadAll(in) + if err != nil { + ColorLog("[ERRO] Error trying to read the banner\n") + ColorLog("[HINT] %v\n", err) + os.Exit(2) + } + + show(out, string(banner)) +} + +func show(out io.Writer, content string) { + t, err := template.New("banner"). + Funcs(template.FuncMap{"Now": Now}). + Parse(content) + + if err != nil { + ColorLog("[ERRO] Cannot parse the banner template\n") + ColorLog("[HINT] %v\n", err) + os.Exit(2) + } + + t.Execute(out, vars{ + runtime.Version(), + runtime.GOOS, + runtime.GOARCH, + runtime.NumCPU(), + os.Getenv("GOPATH"), + runtime.GOROOT(), + runtime.Compiler, + version, + getBeegoVersion(), + }) +} diff --git a/fix.go b/fix.go index 855fc0a..5e7487e 100644 --- a/fix.go +++ b/fix.go @@ -8,6 +8,7 @@ import ( "path/filepath" "regexp" "strings" + "fmt" ) var cmdFix = &Command{ @@ -25,9 +26,12 @@ func init() { } func runFix(cmd *Command, args []string) int { + ShowShortVersionBanner() + + ColorLog("[INFO] Upgrading the application...\n") dir, err := os.Getwd() if err != nil { - ColorLog("GetCurrent Path:%s\n", err) + ColorLog("[ERRO] GetCurrent Path:%s\n", err) } filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if info.IsDir() { @@ -42,13 +46,14 @@ func runFix(cmd *Command, args []string) int { if strings.HasSuffix(info.Name(), ".exe") { return nil } - ColorLog("%s\n", path) err = fixFile(path) + fmt.Println("\tfix\t", path) if err != nil { - ColorLog("fixFile:%s\n", err) + ColorLog("[ERRO] Could not fix file: %s\n", err) } return err }) + ColorLog("[INFO] Upgrade done!\n") return 0 } diff --git a/g.go b/g.go index e0eb265..567e247 100644 --- a/g.go +++ b/g.go @@ -14,7 +14,10 @@ package main -import "os" +import ( + "os" + "strings" +) var cmdGenerate = &Command{ UsageLine: "generate [Command]", @@ -74,6 +77,8 @@ func init() { } func generateCode(cmd *Command, args []string) int { + ShowShortVersionBanner() + curpath, _ := os.Getwd() if len(args) < 1 { ColorLog("[ERRO] command is missing\n") @@ -119,7 +124,6 @@ func generateCode(cmd *Command, args []string) int { os.Exit(2) } sname := args[1] - ColorLog("[INFO] Using '%s' as scaffold name\n", sname) generateScaffold(sname, fields.String(), curpath, driver.String(), conn.String()) case "docs": generateDocs(curpath) @@ -192,7 +196,6 @@ func generateCode(cmd *Command, args []string) int { os.Exit(2) } sname := args[1] - ColorLog("[INFO] Using '%s' as model name\n", sname) generateModel(sname, fields.String(), curpath) case "view": if len(args) == 2 { @@ -206,6 +209,6 @@ func generateCode(cmd *Command, args []string) int { default: ColorLog("[ERRO] command is missing\n") } - ColorLog("[SUCC] generate successfully created!\n") + ColorLog("[SUCC] %s successfully generated!\n", strings.Title(gcmd)) return 0 } diff --git a/g_controllers.go b/g_controllers.go index 49b5fd9..a4815c0 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -18,6 +18,7 @@ import ( "os" "path" "strings" + "fmt" ) // article @@ -58,7 +59,7 @@ func generateController(cname, crupath string) { f.WriteString(content) // gofmt generated source code formatSourceCode(fpath) - ColorLog("[INFO] controller file generated: %s\n", fpath) + fmt.Println("\tcreate\t", fpath) } else { // error creating file ColorLog("[ERRO] Could not create controller file: %s\n", err) diff --git a/g_migration.go b/g_migration.go index d0d296d..ee98aa2 100644 --- a/g_migration.go +++ b/g_migration.go @@ -51,7 +51,7 @@ func generateMigration(mname, upsql, downsql, curpath string) { f.WriteString(content) // gofmt generated source code formatSourceCode(fpath) - ColorLog("[INFO] Migration file generated: %s\n", fpath) + fmt.Println("\tcreate\t", fpath) } else { // error creating file ColorLog("[ERRO] Could not create migration file: %s\n", err) diff --git a/g_model.go b/g_model.go index 859164f..3a45ea1 100644 --- a/g_model.go +++ b/g_model.go @@ -5,6 +5,7 @@ import ( "os" "path" "strings" + "fmt" ) func generateModel(mname, fields, crupath string) { @@ -44,7 +45,7 @@ func generateModel(mname, fields, crupath string) { f.WriteString(content) // gofmt generated source code formatSourceCode(fpath) - ColorLog("[INFO] model file generated: %s\n", fpath) + fmt.Println("\tcreate\t", fpath) } else { // error creating file ColorLog("[ERRO] Could not create model file: %s\n", err) diff --git a/g_scaffold.go b/g_scaffold.go index a9df9d8..f1e7f24 100644 --- a/g_scaffold.go +++ b/g_scaffold.go @@ -7,23 +7,23 @@ import ( func generateScaffold(sname, fields, crupath, driver, conn string) { // generate model - ColorLog("[INFO] Do you want me to create a %v model? [yes|no]] ", sname) + ColorLog("[INFO] Do you want to create a %v model? [yes|no]] ", sname) if askForConfirmation() { generateModel(sname, fields, crupath) } // generate controller - ColorLog("[INFO] Do you want me to create a %v controller? [yes|no]] ", sname) + ColorLog("[INFO] Do you want to create a %v controller? [yes|no]] ", sname) if askForConfirmation() { generateController(sname, crupath) } // generate view - ColorLog("[INFO] Do you want me to create views for this %v resource? [yes|no]] ", sname) + ColorLog("[INFO] Do you want to create views for this %v resource? [yes|no]] ", sname) if askForConfirmation() { generateView(sname, crupath) } // 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 to create a %v migration and schema for this resource? [yes|no]] ", sname) if askForConfirmation() { upsql := "" downsql := "" @@ -34,7 +34,7 @@ func generateScaffold(sname, fields, crupath, driver, conn string) { generateMigration(sname, upsql, downsql, crupath) } // run migration - ColorLog("[INFO] Do you want to go ahead and migrate the database? [yes|no]] ") + ColorLog("[INFO] Do you want to migrate the database? [yes|no]] ") if askForConfirmation() { migrateUpdate(crupath, driver, conn) } @@ -48,12 +48,12 @@ func generateSQLFromFields(fields string) string { for i, v := range fds { kv := strings.SplitN(v, ":", 2) if len(kv) != 2 { - ColorLog("[ERRO] the fields format is wrong. should key:type,key:type " + v + "\n") + ColorLog("[ERRO] Fields format is wrong. Should be: key:type,key:type " + v + "\n") return "" } typ, tag := getSqlType(kv[1]) if typ == "" { - ColorLog("[ERRO] the fields format is wrong. should key:type,key:type " + v + "\n") + ColorLog("[ERRO] Fields format is wrong. Should be: key:type,key:type " + v + "\n") return "" } if i == 0 && strings.ToLower(kv[0]) != "id" { diff --git a/g_views.go b/g_views.go index 413c86f..47c252c 100644 --- a/g_views.go +++ b/g_views.go @@ -3,18 +3,20 @@ package main import ( "os" "path" + "fmt" ) // recipe // admin/recipe func generateView(vpath, crupath string) { + ColorLog("[INFO] Generating view...\n") absvpath := path.Join(crupath, "views", vpath) os.MkdirAll(absvpath, os.ModePerm) cfile := path.Join(absvpath, "index.tpl") if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { defer f.Close() f.WriteString(cfile) - ColorLog("[INFO] Created: %v\n", cfile) + fmt.Println("\tcreate\t", cfile) } else { ColorLog("[ERRO] Could not create view file: %s\n", err) os.Exit(2) @@ -23,7 +25,7 @@ func generateView(vpath, crupath string) { if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { defer f.Close() f.WriteString(cfile) - ColorLog("[INFO] Created: %v\n", cfile) + fmt.Println("\tcreate\t", cfile) } else { ColorLog("[ERRO] Could not create view file: %s\n", err) os.Exit(2) @@ -32,7 +34,7 @@ func generateView(vpath, crupath string) { if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { defer f.Close() f.WriteString(cfile) - ColorLog("[INFO] Created: %v\n", cfile) + fmt.Println("\tcreate\t", cfile) } else { ColorLog("[ERRO] Could not create view file: %s\n", err) os.Exit(2) @@ -41,7 +43,7 @@ func generateView(vpath, crupath string) { if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { defer f.Close() f.WriteString(cfile) - ColorLog("[INFO] Created: %v\n", cfile) + fmt.Println("\tcreate\t", cfile) } else { ColorLog("[ERRO] Could not create view file: %s\n", err) os.Exit(2) diff --git a/hproseapp.go b/hproseapp.go index 40abc47..8200de6 100644 --- a/hproseapp.go +++ b/hproseapp.go @@ -255,6 +255,8 @@ func init() { } func createhprose(cmd *Command, args []string) int { + ShowShortVersionBanner() + curpath, _ := os.Getwd() if len(args) > 1 { cmd.Flag.Parse(args[1:]) @@ -269,11 +271,14 @@ func createhprose(cmd *Command, args []string) int { } if conn == "" { } + + ColorLog("[INFO] Creating Hprose application...\n") + os.MkdirAll(apppath, 0755) - fmt.Println("create app folder:", apppath) + fmt.Println("\tcreate\t", apppath) os.Mkdir(path.Join(apppath, "conf"), 0755) - fmt.Println("create conf:", path.Join(apppath, "conf")) - fmt.Println("create conf app.conf:", path.Join(apppath, "conf", "app.conf")) + fmt.Println("\tcreate\t", path.Join(apppath, "conf")) + fmt.Println("\tcreate\t", path.Join(apppath, "conf", "app.conf")) WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(hproseconf, "{{.Appname}}", args[0], -1)) @@ -282,7 +287,7 @@ func createhprose(cmd *Command, args []string) int { ColorLog("[INFO] Using '%s' as 'conn'\n", conn) ColorLog("[INFO] Using '%s' as 'tables'\n", tables) generateHproseAppcode(string(driver), string(conn), "1", string(tables), path.Join(curpath, args[0])) - fmt.Println("create main.go:", path.Join(apppath, "main.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "main.go")) maingoContent := strings.Replace(hproseMainconngo, "{{.Appname}}", packpath, -1) maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(driver), -1) maingoContent = strings.Replace(maingoContent, "{{HproseFunctionList}}", strings.Join(hproseAddFunctions, ""), -1) @@ -301,17 +306,18 @@ func createhprose(cmd *Command, args []string) int { ) } else { os.Mkdir(path.Join(apppath, "models"), 0755) - fmt.Println("create models:", path.Join(apppath, "models")) + fmt.Println("\tcreate\t", path.Join(apppath, "models")) - fmt.Println("create models object.go:", path.Join(apppath, "models", "object.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "models", "object.go")) WriteToFile(path.Join(apppath, "models", "object.go"), apiModels) - fmt.Println("create models user.go:", path.Join(apppath, "models", "user.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "models", "user.go")) WriteToFile(path.Join(apppath, "models", "user.go"), apiModels2) - fmt.Println("create main.go:", path.Join(apppath, "main.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "main.go")) WriteToFile(path.Join(apppath, "main.go"), strings.Replace(hproseMaingo, "{{.Appname}}", packpath, -1)) } + ColorLog("[SUCC] New Hprose application successfully created!\n") return 0 } diff --git a/migrate.go b/migrate.go index 2e3d8b2..3dcc69b 100644 --- a/migrate.go +++ b/migrate.go @@ -62,6 +62,8 @@ func init() { // runMigration is the entry point for starting a migration func runMigration(cmd *Command, args []string) int { + ShowShortVersionBanner() + crupath, _ := os.Getwd() gopath := os.Getenv("GOPATH") diff --git a/new.go b/new.go index 3c6fff9..3a7e87c 100644 --- a/new.go +++ b/new.go @@ -55,6 +55,8 @@ func init() { } func createApp(cmd *Command, args []string) int { + ShowShortVersionBanner() + if len(args) != 1 { ColorLog("[ERRO] Argument [appname] is missing\n") os.Exit(2) @@ -79,46 +81,46 @@ func createApp(cmd *Command, args []string) int { } } - fmt.Println("[INFO] Creating application...") + ColorLog("[INFO] Creating application...\n") os.MkdirAll(apppath, 0755) - fmt.Println(apppath + string(path.Separator)) + fmt.Println("\tcreate\t", apppath + string(path.Separator)) os.Mkdir(path.Join(apppath, "conf"), 0755) - fmt.Println(path.Join(apppath, "conf") + string(path.Separator)) + fmt.Println("\tcreate\t", path.Join(apppath, "conf") + string(path.Separator)) os.Mkdir(path.Join(apppath, "controllers"), 0755) - fmt.Println(path.Join(apppath, "controllers") + string(path.Separator)) + fmt.Println("\tcreate\t", path.Join(apppath, "controllers") + string(path.Separator)) os.Mkdir(path.Join(apppath, "models"), 0755) - fmt.Println(path.Join(apppath, "models") + string(path.Separator)) + fmt.Println("\tcreate\t", path.Join(apppath, "models") + string(path.Separator)) os.Mkdir(path.Join(apppath, "routers"), 0755) - fmt.Println(path.Join(apppath, "routers") + string(path.Separator)) + fmt.Println("\tcreate\t", path.Join(apppath, "routers") + string(path.Separator)) os.Mkdir(path.Join(apppath, "tests"), 0755) - fmt.Println(path.Join(apppath, "tests") + string(path.Separator)) + fmt.Println("\tcreate\t", path.Join(apppath, "tests") + string(path.Separator)) os.Mkdir(path.Join(apppath, "static"), 0755) - fmt.Println(path.Join(apppath, "static") + string(path.Separator)) + fmt.Println("\tcreate\t", path.Join(apppath, "static") + string(path.Separator)) os.Mkdir(path.Join(apppath, "static", "js"), 0755) - fmt.Println(path.Join(apppath, "static", "js") + string(path.Separator)) + fmt.Println("\tcreate\t", path.Join(apppath, "static", "js") + string(path.Separator)) os.Mkdir(path.Join(apppath, "static", "css"), 0755) - fmt.Println(path.Join(apppath, "static", "css") + string(path.Separator)) + fmt.Println("\tcreate\t", path.Join(apppath, "static", "css") + string(path.Separator)) os.Mkdir(path.Join(apppath, "static", "img"), 0755) - fmt.Println(path.Join(apppath, "static", "img") + string(path.Separator)) - fmt.Println(path.Join(apppath, "views") + string(path.Separator)) + fmt.Println("\tcreate\t", path.Join(apppath, "static", "img") + string(path.Separator)) + fmt.Println("\tcreate\t", path.Join(apppath, "views") + string(path.Separator)) os.Mkdir(path.Join(apppath, "views"), 0755) - fmt.Println(path.Join(apppath, "conf", "app.conf")) + fmt.Println("\tcreate\t", path.Join(apppath, "conf", "app.conf")) WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(appconf, "{{.Appname}}", path.Base(args[0]), -1)) - fmt.Println(path.Join(apppath, "controllers", "default.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "controllers", "default.go")) WriteToFile(path.Join(apppath, "controllers", "default.go"), controllers) - fmt.Println(path.Join(apppath, "views", "index.tpl")) + fmt.Println("\tcreate\t", path.Join(apppath, "views", "index.tpl")) WriteToFile(path.Join(apppath, "views", "index.tpl"), indextpl) - fmt.Println(path.Join(apppath, "routers", "router.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "routers", "router.go")) WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(router, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1)) - fmt.Println(path.Join(apppath, "tests", "default_test.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "tests", "default_test.go")) WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(test, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1)) - fmt.Println(path.Join(apppath, "main.go")) + fmt.Println("\tcreate\t", path.Join(apppath, "main.go")) WriteToFile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1)) ColorLog("[SUCC] New application successfully created!\n") diff --git a/pack.go b/pack.go index 9d66088..c08bded 100644 --- a/pack.go +++ b/pack.go @@ -242,7 +242,7 @@ func (wft *walkFileTree) walkLeaf(fpath string, fi os.FileInfo, err error) error if added, err := wft.wak.compress(name, fpath, fi); added { if verbose { - fmt.Printf("Compressed: %s\n", name) + fmt.Printf("\t+ Compressed: %s\n", name) } wft.allfiles[name] = true return err @@ -397,10 +397,10 @@ func (wft *zipWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) { func packDirectory(excludePrefix []string, excludeSuffix []string, excludeRegexp []*regexp.Regexp, includePath ...string) (err error) { - fmt.Printf("exclude relpath prefix: %s\n", strings.Join(excludePrefix, ":")) - fmt.Printf("exclude relpath suffix: %s\n", strings.Join(excludeSuffix, ":")) + ColorLog("Excluding relpath prefix: %s\n", strings.Join(excludePrefix, ":")) + ColorLog("Excluding relpath suffix: %s\n", strings.Join(excludeSuffix, ":")) if len(excludeRegexp) > 0 { - fmt.Printf("exclude filename regex: `%s`\n", strings.Join(excludeR, "`, `")) + ColorLog("Excluding filename regex: `%s`\n", strings.Join(excludeR, "`, `")) } w, err := os.OpenFile(outputP, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) @@ -472,6 +472,8 @@ func isBeegoProject(thePath string) bool { } func packApp(cmd *Command, args []string) int { + ShowShortVersionBanner() + curPath, _ := os.Getwd() thePath := "" @@ -493,17 +495,17 @@ func packApp(cmd *Command, args []string) int { thePath, err := path.Abs(appPath) if err != nil { - exitPrint(fmt.Sprintf("wrong app path: %s", thePath)) + exitPrint(fmt.Sprintf("Wrong app path: %s", thePath)) } if stat, err := os.Stat(thePath); os.IsNotExist(err) || stat.IsDir() == false { - exitPrint(fmt.Sprintf("not exist app path: %s", thePath)) + exitPrint(fmt.Sprintf("App path does not exist: %s", thePath)) } if isBeegoProject(thePath) == false { - exitPrint(fmt.Sprintf("not support non beego project")) + exitPrint(fmt.Sprintf("Bee does not support non Beego project")) } - fmt.Printf("app path: %s\n", thePath) + ColorLog("Packaging application: %s\n", thePath) appName := path.Base(thePath) @@ -523,8 +525,7 @@ func packApp(cmd *Command, args []string) int { os.Mkdir(tmpdir, 0700) if build { - fmt.Println("build", appName) - + ColorLog("Building application...\n") var envs []string for _, env := range buildEnvs { parts := strings.SplitN(env, "=", 2) @@ -546,7 +547,7 @@ func packApp(cmd *Command, args []string) int { os.Setenv("GOOS", goos) os.Setenv("GOARCH", goarch) - fmt.Println("GOOS", goos, "GOARCH", goarch) + ColorLog("Env: GOOS=%s GOARCH=%s\n", goos, goarch) binPath := path.Join(tmpdir, appName) if goos == "windows" { @@ -559,7 +560,7 @@ func packApp(cmd *Command, args []string) int { } if verbose { - fmt.Println("go ", strings.Join(args, " ")) + fmt.Println("\t+ go", strings.Join(args, " ")) } execmd := exec.Command("go", args...) @@ -572,7 +573,7 @@ func packApp(cmd *Command, args []string) int { exitPrint(err.Error()) } - fmt.Println("build success") + ColorLog("Build successful\n") } switch format { @@ -624,6 +625,6 @@ func packApp(cmd *Command, args []string) int { exitPrint(err.Error()) } - fmt.Printf("file write to `%s`\n", outputP) + ColorLog("Writing to output: `%s`\n", outputP) return 0 } diff --git a/run.go b/run.go index 3d4da70..1200e4c 100644 --- a/run.go +++ b/run.go @@ -15,11 +15,8 @@ package main import ( - "fmt" "io/ioutil" - "log" "os" - "os/exec" path "path/filepath" "runtime" "strings" @@ -58,13 +55,7 @@ func init() { var appname string func runApp(cmd *Command, args []string) int { - fmt.Println("bee :" + version) - fmt.Println("beego :" + getbeegoVersion()) - goversion, err := exec.Command("go", "version").Output() - if err != nil { - log.Fatal(err) - } - fmt.Println("Go :" + string(goversion)) + ShowShortVersionBanner() exit := make(chan bool) crupath, _ := os.Getwd() @@ -85,7 +76,7 @@ func runApp(cmd *Command, args []string) int { } Debugf("current path:%s\n", crupath) - err = loadConfig() + err := loadConfig() if err != nil { ColorLog("[ERRO] Fail to parse bee.json[ %s ]\n", err) } diff --git a/version.go b/version.go index 23c461f..43931e1 100644 --- a/version.go +++ b/version.go @@ -4,11 +4,10 @@ import ( "bufio" "fmt" "io" - "log" "os" - "os/exec" path "path/filepath" "regexp" + "bytes" ) var cmdVersion = &Command{ @@ -25,30 +24,59 @@ bee version `, } +const verboseVersionBanner = +`______ +| ___ \ +| |_/ / ___ ___ +| ___ \ / _ \ / _ \ +| |_/ /| __/| __/ +\____/ \___| \___| v{{ .BeeVersion }} + +Beego : {{ .BeegoVersion }} +GoVersion : {{ .GoVersion }} +GOOS : {{ .GOOS }} +GOARCH : {{ .GOARCH }} +NumCPU : {{ .NumCPU }} +GOPATH : {{ .GOPATH }} +GOROOT : {{ .GOROOT }} +Compiler : {{ .Compiler }} +Date : {{ Now "Monday, 2 Jan 2006" }} +` + +const shortVersionBanner = +`______ +| ___ \ +| |_/ / ___ ___ +| ___ \ / _ \ / _ \ +| |_/ /| __/| __/ +\____/ \___| \___| v{{ .BeeVersion }} +` + func init() { cmdVersion.Run = versionCmd } func versionCmd(cmd *Command, args []string) int { - fmt.Println("bee :" + version) - fmt.Println("beego :" + getbeegoVersion()) - //fmt.Println("Go :" + runtime.Version()) - goversion, err := exec.Command("go", "version").Output() - if err != nil { - log.Fatal(err) - } - fmt.Println("Go :" + string(goversion)) + ShowVerboseVersionBanner() return 0 } -func getbeegoVersion() string { +func ShowVerboseVersionBanner() { + InitBanner(os.Stdout, bytes.NewBufferString(verboseVersionBanner)) +} + +func ShowShortVersionBanner() { + InitBanner(os.Stdout, bytes.NewBufferString(shortVersionBanner)) +} + +func getBeegoVersion() string { gopath := os.Getenv("GOPATH") re, err := regexp.Compile(`VERSION = "([0-9.]+)"`) if err != nil { return "" } if gopath == "" { - err = fmt.Errorf("you should set GOPATH in the env") + err = fmt.Errorf("You should set GOPATH env variable") return "" } wgopath := path.SplitList(gopath) @@ -60,11 +88,11 @@ func getbeegoVersion() string { if os.IsNotExist(err) { continue } - ColorLog("[ERRO] get beego.go has error\n") + ColorLog("[ERRO] Get `beego.go` has error\n") } fd, err := os.Open(filename) if err != nil { - ColorLog("[ERRO] open beego.go has error\n") + ColorLog("[ERRO] Open `beego.go` has error\n") continue } reader := bufio.NewReader(fd) @@ -84,5 +112,5 @@ func getbeegoVersion() string { } } - return "you don't install beego,install first: github.com/astaxie/beego" + return "Beego not installed. Please install it first: https://github.com/astaxie/beego" } From 5c12764c5fdde32dfcbf615cbd3d0960dca9b7b7 Mon Sep 17 00:00:00 2001 From: Sergey Lanzman Date: Thu, 7 Jul 2016 15:21:47 +0300 Subject: [PATCH 057/123] add Postgresql support generate(migrate,Scaffold..) --- g_scaffold.go | 56 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/g_scaffold.go b/g_scaffold.go index a9df9d8..db57767 100644 --- a/g_scaffold.go +++ b/g_scaffold.go @@ -51,25 +51,46 @@ func generateSQLFromFields(fields string) string { ColorLog("[ERRO] the fields format is wrong. should key:type,key:type " + v + "\n") return "" } - typ, tag := getSqlType(kv[1]) + typ, tag := "", "" + switch driver { + case "mysql": + typ, tag = getSqlTypeMysql(kv[1]) + case "postgres": + typ, tag = getSqlTypePostgresql(kv[1]) + default: + typ, tag = getSqlTypeMysql(kv[1]) + } if typ == "" { ColorLog("[ERRO] the fields format is wrong. should key:type,key:type " + v + "\n") return "" } if i == 0 && strings.ToLower(kv[0]) != "id" { - sql = sql + "`id` int(11) NOT NULL AUTO_INCREMENT," - tags = tags + "PRIMARY KEY (`id`)," + switch driver { + case "mysql": + sql = sql + "`id` int(11) NOT NULL AUTO_INCREMENT," + tags = tags + "PRIMARY KEY (`id`)," + case "postgres": + sql = sql + "id interger serial primary key," + default: + 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])+"`") + "," } } + if driver == "postgres" { + sql = strings.Replace(sql, "`", "", -1) + tags = strings.Replace(tags, "`", "", -1) + } sql = strings.TrimRight(sql+tags, ",") return sql } -func getSqlType(ktype string) (tp, tag string) { +func getSqlTypeMysql(ktype string) (tp, tag string) { kv := strings.SplitN(ktype, ":", 2) switch kv[0] { case "string": @@ -99,3 +120,30 @@ func getSqlType(ktype string) (tp, tag string) { } return "", "" } + +func getSqlTypePostgresql(ktype string) (tp, tag string) { + kv := strings.SplitN(ktype, ":", 2) + switch kv[0] { + case "string": + if len(kv) == 2 { + return "char(" + kv[1] + ") NOT NULL", "" + } else { + return "TEXT NOT NULL", "" + } + case "text": + return "TEXT NOT NULL", "" + case "auto", "pk": + return "serial primary key", "" + case "datetime": + return "TIMESTAMP WITHOUT TIME ZONE NOT NULL", "" + case "int", "int8", "int16", "int32", "int64": + fallthrough + case "uint", "uint8", "uint16", "uint32", "uint64": + return "integer DEFAULT NULL", "" + case "bool": + return "boolean NOT NULL", "" + case "float32", "float64", "float": + return "numeric NOT NULL", "" + } + return "", "" +} From 76b6a98c5536b0059737edf59b18c6ddf6212744 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Fri, 8 Jul 2016 15:17:33 +0300 Subject: [PATCH 058/123] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cdb5e9d..fecb3e9 100644 --- a/README.md +++ b/README.md @@ -199,17 +199,17 @@ usage: bee migrate [Command] bee migrate [-driver="mysql"] [-conn="root:@tcp(127.0.0.1:3306)/test"] run all outstanding migrations - -driver: [mysql | postgresql | sqlite], the default is mysql + -driver: [mysql | postgres | sqlite], the default is mysql -conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test bee migrate rollback [-driver="mysql"] [-conn="root:@tcp(127.0.0.1:3306)/test"] rollback the last migration operation - -driver: [mysql | postgresql | sqlite], the default is mysql + -driver: [mysql | postgres | sqlite], the default is mysql -conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test bee migrate reset [-driver="mysql"] [-conn="root:@tcp(127.0.0.1:3306)/test"] rollback all migrations - -driver: [mysql | postgresql | sqlite], the default is mysql + -driver: [mysql | postgres| sqlite], the default is mysql -conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test bee migrate refresh [-driver="mysql"] [-conn="root:@tcp(127.0.0.1:3306)/test"] From acf35e9151144a19d7380997aa7964e49506e8fb Mon Sep 17 00:00:00 2001 From: chenzhiming Date: Wed, 20 Jul 2016 20:49:09 +0800 Subject: [PATCH 059/123] fix bug of newer error --- g_appcode.go | 2 +- g_hproseappcode.go | 2 +- g_model.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/g_appcode.go b/g_appcode.go index 7860912..47b518d 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -1099,7 +1099,7 @@ func GetAll{{modelName}}(query map[string]string, fields []string, sortby []stri var l []{{modelName}} qs = qs.OrderBy(sortFields...) - if _, err := qs.Limit(limit, offset).All(&l, fields...); err == nil { + if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil { if len(fields) == 0 { for _, v := range l { ml = append(ml, v) diff --git a/g_hproseappcode.go b/g_hproseappcode.go index 86e3d02..b2a5a8f 100644 --- a/g_hproseappcode.go +++ b/g_hproseappcode.go @@ -260,7 +260,7 @@ func GetAll{{modelName}}(query map[string]string, fields []string, sortby []stri var l []{{modelName}} qs = qs.OrderBy(sortFields...) - if _, err := qs.Limit(limit, offset).All(&l, fields...); err == nil { + if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil { if len(fields) == 0 { for _, v := range l { ml = append(ml, v) diff --git a/g_model.go b/g_model.go index 859164f..6b0979e 100644 --- a/g_model.go +++ b/g_model.go @@ -202,7 +202,7 @@ func GetAll{{modelName}}(query map[string]string, fields []string, sortby []stri var l []{{modelName}} qs = qs.OrderBy(sortFields...) - if _, err := qs.Limit(limit, offset).All(&l, fields...); err == nil { + if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil { if len(fields) == 0 { for _, v := range l { ml = append(ml, v) From 4be4a20df4998e3120f8e16b29211ce667be4b97 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Fri, 22 Jul 2016 17:33:05 +0200 Subject: [PATCH 060/123] Added ability to run an application either from the appname directory or anywhere in the $GOPATH/src folder. (Fixes #219) --- run.go | 56 ++++++++++++++++++++++++++++++++++---------------------- watch.go | 4 ++-- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/run.go b/run.go index 1200e4c..c2263bf 100644 --- a/run.go +++ b/run.go @@ -20,11 +20,12 @@ import ( path "path/filepath" "runtime" "strings" + "fmt" ) var cmdRun = &Command{ UsageLine: "run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] [-e=Godeps -e=folderToExclude] [-tags=goBuildTags]", - Short: "run the app and start a Web server for development", + Short: "Run the app and start a Web server for development", Long: ` Run command will supervise the file system of the beego project using inotify, it will recompile and restart the app after any modifications. @@ -45,36 +46,55 @@ var buildTags string func init() { cmdRun.Run = runApp - cmdRun.Flag.Var(&mainFiles, "main", "specify main go files") - cmdRun.Flag.Var(&gendoc, "gendoc", "auto generate the docs") - cmdRun.Flag.Var(&downdoc, "downdoc", "auto download swagger file when not exist") + cmdRun.Flag.Var(&mainFiles, "main", "Specify main go files") + cmdRun.Flag.Var(&gendoc, "gendoc", "Auto generate the docs") + cmdRun.Flag.Var(&downdoc, "downdoc", "Auto download Swagger file when does not exist") cmdRun.Flag.Var(&excludedPaths, "e", "Excluded paths[].") cmdRun.Flag.StringVar(&buildTags, "tags", "", "Build tags (https://golang.org/pkg/go/build/)") } -var appname string +var ( + currpath = "" + appname = "" + exit = make(chan bool) +) func runApp(cmd *Command, args []string) int { ShowShortVersionBanner() - exit := make(chan bool) - crupath, _ := os.Getwd() + gps := GetGOPATHs() + if len(gps) == 0 { + ColorLog("[ERRO] Fail to start[ %s ]\n", "$GOPATH is not set or empty") + os.Exit(2) + } + gopath := gps[0] if len(args) == 0 || args[0] == "watchall" { - appname = path.Base(crupath) + currpath, _ = os.Getwd() + appname = path.Base(currpath) ColorLog("[INFO] Uses '%s' as 'appname'\n", appname) } else { - appname = args[0] + gopathsrc := path.Join(gopath, "src") + currpath = path.Join(gopathsrc, args[0]) + appname = path.Base(currpath) + + // Check if passed Bee application path/name exists + // in $GOPATH/src workspace + if !isExist(currpath) { + panic(fmt.Sprintf("No Beego application '%s' found in GOPATH: %s", args[0], gopathsrc)) + } + ColorLog("[INFO] Uses '%s' as 'appname'\n", appname) - if strings.HasSuffix(appname, ".go") && isExist(path.Join(crupath, appname)) { - ColorLog("[WARN] The appname has conflic with crupath's file, do you want to build appname as %s\n", appname) + if strings.HasSuffix(appname, ".go") && isExist(currpath) { + ColorLog("[WARN] The appname is in conflict with currpath's file, do you want to build appname as %s\n", appname) ColorLog("[INFO] Do you want to overwrite it? [yes|no]] ") if !askForConfirmation() { return 0 } } } - Debugf("current path:%s\n", crupath) + + Debugf("current path:%s\n", currpath) err := loadConfig() if err != nil { @@ -82,17 +102,10 @@ func runApp(cmd *Command, args []string) int { } var paths []string - - readAppDirectories(crupath, &paths) + readAppDirectories(currpath, &paths) // Because monitor files has some issues, we watch current directory // and ignore non-go files. - gps := GetGOPATHs() - if len(gps) == 0 { - ColorLog("[ERRO] Fail to start[ %s ]\n", "$GOPATH is not set or empty") - os.Exit(2) - } - gopath := gps[0] for _, p := range conf.DirStruct.Others { paths = append(paths, strings.Replace(p, "$GOPATH", gopath, -1)) } @@ -112,7 +125,7 @@ func runApp(cmd *Command, args []string) int { Autobuild(files, false) } if downdoc == "true" { - if _, err := os.Stat(path.Join(crupath, "swagger")); err != nil { + if _, err := os.Stat(path.Join(currpath, "swagger")); err != nil { if os.IsNotExist(err) { downloadFromUrl(swaggerlink, "swagger.zip") unzipAndDelete("swagger.zip", "swagger") @@ -157,7 +170,6 @@ func readAppDirectories(directory string, paths *[]string) { useDirectory = true } } - return } diff --git a/watch.go b/watch.go index 7d966bd..1b4af32 100644 --- a/watch.go +++ b/watch.go @@ -121,8 +121,8 @@ func Autobuild(files []string, isgenerate bool) { defer state.Unlock() ColorLog("[INFO] Start building...\n") - path, _ := os.Getwd() - os.Chdir(path) + + os.Chdir(currpath) cmdName := "go" if conf.Gopm.Enable { From 6192b395d9b30c0f4b7549778eb919ce7b39556c Mon Sep 17 00:00:00 2001 From: Sergey Lanzman Date: Sat, 23 Jul 2016 01:24:44 +0300 Subject: [PATCH 061/123] add vendor watch settings --- run.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/run.go b/run.go index 1200e4c..edd1e5b 100644 --- a/run.go +++ b/run.go @@ -23,7 +23,7 @@ import ( ) var cmdRun = &Command{ - UsageLine: "run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] [-e=Godeps -e=folderToExclude] [-tags=goBuildTags]", + UsageLine: "run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] [-vendor=true] [-e=folderToExclude] [-tags=goBuildTags]", Short: "run the app and start a Web server for development", Long: ` Run command will supervise the file system of the beego project using inotify, @@ -43,12 +43,15 @@ var excludedPaths strFlags // Pass through to -tags arg of "go build" var buildTags string +var vendorWatch bool + func init() { cmdRun.Run = runApp cmdRun.Flag.Var(&mainFiles, "main", "specify main go files") cmdRun.Flag.Var(&gendoc, "gendoc", "auto generate the docs") cmdRun.Flag.Var(&downdoc, "downdoc", "auto download swagger file when not exist") cmdRun.Flag.Var(&excludedPaths, "e", "Excluded paths[].") + cmdRun.Flag.BoolVar(&vendorWatch, "vendor", false, "Watch vendor folder") cmdRun.Flag.StringVar(&buildTags, "tags", "", "Build tags (https://golang.org/pkg/go/build/)") } @@ -139,6 +142,10 @@ func readAppDirectories(directory string, paths *[]string) { continue } + if !vendorWatch && strings.HasSuffix(fileInfo.Name(), "vendor") { + continue + } + if isExcluded(path.Join(directory, fileInfo.Name())) { continue } From bc963e0070230a80647956408a7cfabefe691d59 Mon Sep 17 00:00:00 2001 From: Sergey Lanzman Date: Sat, 23 Jul 2016 02:05:01 +0300 Subject: [PATCH 062/123] go lint --- bale.go | 12 +++++------ conf.go | 4 ++-- g_appcode.go | 54 ++++++++++++++++++++++------------------------ g_docs.go | 18 +++++++--------- g_hproseappcode.go | 20 ++++++++--------- g_migration.go | 12 +++++------ g_model.go | 17 +++++++-------- g_scaffold.go | 16 ++++++-------- migrate.go | 32 +++++++++++++-------------- pack.go | 3 +-- run.go | 2 +- rundocs.go | 4 ++-- 12 files changed, 93 insertions(+), 101 deletions(-) diff --git a/bale.go b/bale.go index 5f1f803..2bf14f9 100644 --- a/bale.go +++ b/bale.go @@ -68,7 +68,7 @@ func runBale(cmd *Command, args []string) int { // Generate auto-uncompress function. buf := new(bytes.Buffer) - buf.WriteString(fmt.Sprintf(_BALE_HEADER, conf.Bale.Import, + buf.WriteString(fmt.Sprintf(BaleHeader, conf.Bale.Import, strings.Join(resFiles, "\",\n\t\t\""), strings.Join(resFiles, ",\n\t\tbale.R"))) @@ -90,7 +90,7 @@ func runBale(cmd *Command, args []string) int { } const ( - _BALE_HEADER = `package main + BaleHeader = `package main import( "os" @@ -178,7 +178,7 @@ func walkFn(resPath string, info os.FileInfo, err error) error { defer fw.Close() // Write header. - fmt.Fprintf(fw, _HEADER, resPath) + fmt.Fprintf(fw, Header, resPath) // Copy and compress data. gz := gzip.NewWriter(&ByteWriter{Writer: fw}) @@ -186,7 +186,7 @@ func walkFn(resPath string, info os.FileInfo, err error) error { gz.Close() // Write footer. - fmt.Fprint(fw, _FOOTER) + fmt.Fprint(fw, Footer) resFiles = append(resFiles, resPath) return nil @@ -202,7 +202,7 @@ func filterSuffix(name string) bool { } const ( - _HEADER = `package bale + Header = `package bale import( "bytes" @@ -212,7 +212,7 @@ import( func R%s() []byte { gz, err := gzip.NewReader(bytes.NewBuffer([]byte{` - _FOOTER = ` + Footer = ` })) if err != nil { diff --git a/conf.go b/conf.go index 9d610d1..e6d3633 100644 --- a/conf.go +++ b/conf.go @@ -19,7 +19,7 @@ import ( "os" ) -const CONF_VER = 0 +const ConfVer = 0 var defaultConf = `{ "version": 0, @@ -91,7 +91,7 @@ func loadConfig() error { } // Check format version. - if conf.Version != CONF_VER { + if conf.Version != ConfVer { ColorLog("[WARN] Your bee.json is out-of-date, please update!\n") ColorLog("[HINT] Compare bee.json under bee source code path and yours\n") } diff --git a/g_appcode.go b/g_appcode.go index fabec16..9fea762 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -29,9 +29,9 @@ import ( ) const ( - O_MODEL byte = 1 << iota - O_CONTROLLER - O_ROUTER + OModel byte = 1 << iota + OController + ORouter ) // DbTransformer has method to reverse engineer a database schema to restful api code @@ -259,11 +259,11 @@ func generateAppcode(driver, connStr, level, tables, currpath string) { var mode byte switch level { case "1": - mode = O_MODEL + mode = OModel case "2": - mode = O_MODEL | O_CONTROLLER + mode = OModel | OController case "3": - mode = O_MODEL | O_CONTROLLER | O_ROUTER + mode = OModel | OController | ORouter default: ColorLog("[ERRO] Invalid 'level' option: %s\n", level) ColorLog("[HINT] Level must be either 1, 2 or 3\n") @@ -505,10 +505,9 @@ func (*MysqlDB) GetGoDataType(sqlType string) (goType string) { typeMapping = typeMappingMysql if v, ok := typeMapping[sqlType]; ok { return v - } else { - ColorLog("[ERRO] data type (%s) not found!\n", sqlType) - os.Exit(2) } + ColorLog("[ERRO] data type (%s) not found!\n", sqlType) + os.Exit(2) return goType } @@ -692,22 +691,21 @@ func (postgresDB *PostgresDB) GetColumns(db *sql.DB, table *Table, blackList map func (*PostgresDB) GetGoDataType(sqlType string) (goType string) { if v, ok := typeMappingPostgres[sqlType]; ok { return v - } else { - ColorLog("[ERRO] data type (%s) not found!\n", sqlType) - os.Exit(2) } + ColorLog("[ERRO] data type (%s) not found!\n", sqlType) + os.Exit(2) return goType } // deleteAndRecreatePaths removes several directories completely func createPaths(mode byte, paths *MvcPath) { - if (mode & O_MODEL) == O_MODEL { + if (mode & OModel) == OModel { os.Mkdir(paths.ModelPath, 0777) } - if (mode & O_CONTROLLER) == O_CONTROLLER { + if (mode & OController) == OController { os.Mkdir(paths.ControllerPath, 0777) } - if (mode & O_ROUTER) == O_ROUTER { + if (mode & ORouter) == ORouter { os.Mkdir(paths.RouterPath, 0777) } } @@ -716,15 +714,15 @@ func createPaths(mode byte, paths *MvcPath) { // It will wipe the following directories and recreate them:./models, ./controllers, ./routers // Newly geneated files will be inside these folders. func writeSourceFiles(pkgPath string, tables []*Table, mode byte, paths *MvcPath, selectedTables map[string]bool) { - if (O_MODEL & mode) == O_MODEL { + if (OModel & mode) == OModel { ColorLog("[INFO] Creating model files...\n") writeModelFiles(tables, paths.ModelPath, selectedTables) } - if (O_CONTROLLER & mode) == O_CONTROLLER { + if (OController & mode) == OController { ColorLog("[INFO] Creating controller files...\n") writeControllerFiles(tables, paths.ControllerPath, selectedTables, pkgPath) } - if (O_ROUTER & mode) == O_ROUTER { + if (ORouter & mode) == ORouter { ColorLog("[INFO] Creating router files...\n") writeRouterFile(tables, paths.RouterPath, selectedTables, pkgPath) } @@ -764,9 +762,9 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo } template := "" if tb.Pk == "" { - template = STRUCT_MODEL_TPL + template = StructModelTPL } else { - template = MODEL_TPL + template = ModelTPL } fileStr := strings.Replace(template, "{{modelStruct}}", tb.String(), 1) fileStr = strings.Replace(fileStr, "{{modelName}}", camelCase(tb.Name), -1) @@ -825,7 +823,7 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri continue } } - fileStr := strings.Replace(CTRL_TPL, "{{ctrlName}}", camelCase(tb.Name), -1) + fileStr := strings.Replace(CtrlTPL, "{{ctrlName}}", camelCase(tb.Name), -1) fileStr = strings.Replace(fileStr, "{{pkgPath}}", pkgPath, -1) if _, err := f.WriteString(fileStr); err != nil { ColorLog("[ERRO] Could not write controller file to %s\n", fpath) @@ -851,13 +849,13 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo continue } // add name spaces - nameSpace := strings.Replace(NAMESPACE_TPL, "{{nameSpace}}", tb.Name, -1) + nameSpace := strings.Replace(NamespaceTPL, "{{nameSpace}}", tb.Name, -1) nameSpace = strings.Replace(nameSpace, "{{ctrlName}}", camelCase(tb.Name), -1) nameSpaces = append(nameSpaces, nameSpace) } // add export controller fpath := path.Join(rPath, "router.go") - routerStr := strings.Replace(ROUTER_TPL, "{{nameSpaces}}", strings.Join(nameSpaces, ""), 1) + routerStr := strings.Replace(RouterTPL, "{{nameSpaces}}", strings.Join(nameSpaces, ""), 1) routerStr = strings.Replace(routerStr, "{{pkgPath}}", pkgPath, 1) var f *os.File var err error @@ -1001,12 +999,12 @@ func getPackagePath(curpath string) (packpath string) { } const ( - STRUCT_MODEL_TPL = `package models + StructModelTPL = `package models {{importTimePkg}} {{modelStruct}} ` - MODEL_TPL = `package models + ModelTPL = `package models import ( "errors" @@ -1150,7 +1148,7 @@ func Delete{{modelName}}(id int) (err error) { return } ` - CTRL_TPL = `package controllers + CtrlTPL = `package controllers import ( "{{pkgPath}}/models" @@ -1316,7 +1314,7 @@ func (c *{{ctrlName}}Controller) Delete() { c.ServeJSON() } ` - ROUTER_TPL = `// @APIVersion 1.0.0 + RouterTPL = `// @APIVersion 1.0.0 // @Title beego Test API // @Description beego has a very cool tools to autogenerate documents for your API // @Contact astaxie@gmail.com @@ -1338,7 +1336,7 @@ func init() { beego.AddNamespace(ns) } ` - NAMESPACE_TPL = ` + NamespaceTPL = ` beego.NSNamespace("/{{nameSpace}}", beego.NSInclude( &controllers.{{ctrlName}}Controller{}, diff --git a/g_docs.go b/g_docs.go index 229540a..2648ea8 100644 --- a/g_docs.go +++ b/g_docs.go @@ -393,7 +393,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat if j == 0 || j == 1 { st[j] = string(tmp) tmp = make([]rune, 0) - j += 1 + j++ start = false if j == 1 { continue @@ -655,16 +655,14 @@ func typeAnalyser(f *ast.Field) (isSlice bool, realType string) { } if star, ok := arr.Elt.(*ast.StarExpr); ok { return true, fmt.Sprint(star.X) - } else { - return true, fmt.Sprint(arr.Elt) } - } else { - switch t := f.Type.(type) { - case *ast.StarExpr: - return false, fmt.Sprint(t.X) - } - return false, fmt.Sprint(f.Type) + return true, fmt.Sprint(arr.Elt) } + switch t := f.Type.(type) { + case *ast.StarExpr: + return false, fmt.Sprint(t.X) + } + return false, fmt.Sprint(f.Type) } func isBasicType(Type string) bool { @@ -688,7 +686,7 @@ var basicTypes = []string{ } // regexp get json tag -func grepJsonTag(tag string) string { +func grepJSONTag(tag string) string { r, _ := regexp.Compile(`json:"([^"]*)"`) matches := r.FindAllStringSubmatch(tag, -1) if len(matches) > 0 { diff --git a/g_hproseappcode.go b/g_hproseappcode.go index 86e3d02..7dda6ce 100644 --- a/g_hproseappcode.go +++ b/g_hproseappcode.go @@ -31,11 +31,11 @@ func generateHproseAppcode(driver, connStr, level, tables, currpath string) { var mode byte switch level { case "1": - mode = O_MODEL + mode = OModel case "2": - mode = O_MODEL | O_CONTROLLER + mode = OModel | OController case "3": - mode = O_MODEL | O_CONTROLLER | O_ROUTER + mode = OModel | OController | ORouter default: ColorLog("[ERRO] Invalid 'level' option: %s\n", level) ColorLog("[HINT] Level must be either 1, 2 or 3\n") @@ -90,7 +90,7 @@ func genHprose(dbms, connStr string, mode byte, selectedTableNames map[string]bo // It will wipe the following directories and recreate them:./models, ./controllers, ./routers // Newly geneated files will be inside these folders. func writeHproseSourceFiles(pkgPath string, tables []*Table, mode byte, paths *MvcPath, selectedTables map[string]bool) { - if (O_MODEL & mode) == O_MODEL { + if (OModel & mode) == OModel { ColorLog("[INFO] Creating model files...\n") writeHproseModelFiles(tables, paths.ModelPath, selectedTables) } @@ -130,10 +130,10 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str } template := "" if tb.Pk == "" { - template = HPROSE_STRUCT_MODEL_TPL + template = HproseStructModelTPL } else { - template = HPROSE_MODEL_TPL - hproseAddFunctions = append(hproseAddFunctions, strings.Replace(HPROSE_ADDFUNCTION, "{{modelName}}", camelCase(tb.Name), -1)) + template = HproseModelTPL + hproseAddFunctions = append(hproseAddFunctions, strings.Replace(HproseAddFunction, "{{modelName}}", camelCase(tb.Name), -1)) } fileStr := strings.Replace(template, "{{modelStruct}}", tb.String(), 1) fileStr = strings.Replace(fileStr, "{{modelName}}", camelCase(tb.Name), -1) @@ -157,7 +157,7 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str } const ( - HPROSE_ADDFUNCTION = ` + HproseAddFunction = ` // publish about {{modelName}} function service.AddFunction("Add{{modelName}}", models.Add{{modelName}}) service.AddFunction("Get{{modelName}}ById", models.Get{{modelName}}ById) @@ -166,12 +166,12 @@ const ( service.AddFunction("Delete{{modelName}}", models.Delete{{modelName}}) ` - HPROSE_STRUCT_MODEL_TPL = `package models + HproseStructModelTPL = `package models {{importTimePkg}} {{modelStruct}} ` - HPROSE_MODEL_TPL = `package models + HproseModelTPL = `package models import ( "errors" diff --git a/g_migration.go b/g_migration.go index ee98aa2..d26211c 100644 --- a/g_migration.go +++ b/g_migration.go @@ -23,15 +23,15 @@ import ( ) const ( - M_PATH = "migrations" - M_DATE_FORMAT = "20060102_150405" + MPath = "migrations" + MDateFormat = "20060102_150405" ) // 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, upsql, downsql, curpath string) { - migrationFilePath := path.Join(curpath, "database", M_PATH) + migrationFilePath := path.Join(curpath, "database", MPath) if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) { // create migrations directory if err := os.MkdirAll(migrationFilePath, 0777); err != nil { @@ -40,11 +40,11 @@ func generateMigration(mname, upsql, downsql, curpath string) { } } // create file - today := time.Now().Format(M_DATE_FORMAT) + today := time.Now().Format(MDateFormat) fpath := path.Join(migrationFilePath, fmt.Sprintf("%s_%s.go", today, mname)) if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { defer f.Close() - content := strings.Replace(MIGRATION_TPL, "{{StructName}}", camelCase(mname)+"_"+today, -1) + content := strings.Replace(MigrationTPL, "{{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) @@ -59,7 +59,7 @@ func generateMigration(mname, upsql, downsql, curpath string) { } } -const MIGRATION_TPL = `package main +const MigrationTPL = `package main import ( "github.com/astaxie/beego/migration" diff --git a/g_model.go b/g_model.go index 3a45ea1..5c5ce37 100644 --- a/g_model.go +++ b/g_model.go @@ -2,10 +2,10 @@ package main import ( "errors" + "fmt" "os" "path" "strings" - "fmt" ) func generateModel(mname, fields, crupath string) { @@ -16,7 +16,7 @@ func generateModel(mname, fields, crupath string) { i := strings.LastIndex(p[:len(p)-1], "/") packageName = p[i+1 : len(p)-1] } - modelStruct, err, hastime := getStruct(modelName, fields) + modelStruct, hastime, err := getStruct(modelName, fields) if err != nil { ColorLog("[ERRO] Could not genrate models struct: %s\n", err) os.Exit(2) @@ -53,9 +53,9 @@ func generateModel(mname, fields, crupath string) { } } -func getStruct(structname, fields string) (string, error, bool) { +func getStruct(structname, fields string) (string, bool, error) { if fields == "" { - return "", errors.New("fields can't empty"), false + return "", false, errors.New("fields can't empty") } hastime := false structStr := "type " + structname + " struct{\n" @@ -63,11 +63,11 @@ func getStruct(structname, fields string) (string, error, bool) { for i, v := range fds { kv := strings.SplitN(v, ":", 2) if len(kv) != 2 { - return "", errors.New("the filds format is wrong. should key:type,key:type " + v), false + return "", false, errors.New("the filds format is wrong. should key:type,key:type " + v) } typ, tag, hastimeinner := getType(kv[1]) if typ == "" { - return "", errors.New("the filds format is wrong. should key:type,key:type " + v), false + return "", false, errors.New("the filds format is wrong. should key:type,key:type " + v) } if i == 0 && strings.ToLower(kv[0]) != "id" { structStr = structStr + "Id int64 `orm:\"auto\"`\n" @@ -78,7 +78,7 @@ func getStruct(structname, fields string) (string, error, bool) { structStr = structStr + camelString(kv[0]) + " " + typ + " " + tag + "\n" } structStr += "}\n" - return structStr, nil, hastime + return structStr, hastime, nil } // fields support type @@ -89,9 +89,8 @@ func getType(ktype string) (kt, tag string, hasTime bool) { case "string": if len(kv) == 2 { return "string", "`orm:\"size(" + kv[1] + ")\"`", false - } else { - return "string", "`orm:\"size(128)\"`", false } + return "string", "`orm:\"size(128)\"`", false case "text": return "string", "`orm:\"type(longtext)\"`", false case "auto": diff --git a/g_scaffold.go b/g_scaffold.go index 9e232c5..d02d622 100644 --- a/g_scaffold.go +++ b/g_scaffold.go @@ -54,11 +54,11 @@ func generateSQLFromFields(fields string) string { typ, tag := "", "" switch driver { case "mysql": - typ, tag = getSqlTypeMysql(kv[1]) + typ, tag = getSQLTypeMysql(kv[1]) case "postgres": - typ, tag = getSqlTypePostgresql(kv[1]) + typ, tag = getSQLTypePostgresql(kv[1]) default: - typ, tag = getSqlTypeMysql(kv[1]) + typ, tag = getSQLTypeMysql(kv[1]) } if typ == "" { ColorLog("[ERRO] Fields format is wrong. Should be: key:type,key:type " + v + "\n") @@ -90,15 +90,14 @@ func generateSQLFromFields(fields string) string { return sql } -func getSqlTypeMysql(ktype string) (tp, tag string) { +func getSQLTypeMysql(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", "" } + return "varchar(128) NOT NULL", "" case "text": return "longtext NOT NULL", "" case "auto": @@ -121,15 +120,14 @@ func getSqlTypeMysql(ktype string) (tp, tag string) { return "", "" } -func getSqlTypePostgresql(ktype string) (tp, tag string) { +func getSQLTypePostgresql(ktype string) (tp, tag string) { kv := strings.SplitN(ktype, ":", 2) switch kv[0] { case "string": if len(kv) == 2 { return "char(" + kv[1] + ") NOT NULL", "" - } else { - return "TEXT NOT NULL", "" } + return "TEXT NOT NULL", "" case "text": return "TEXT NOT NULL", "" case "auto", "pk": diff --git a/migrate.go b/migrate.go index 7bb27f7..0661ae1 100644 --- a/migrate.go +++ b/migrate.go @@ -167,23 +167,23 @@ func migrate(goal, crupath, driver, connStr string) { // checkForSchemaUpdateTable checks the existence of migrations table. // It checks for the proper table structures and creates the table using MYSQL_MIGRATION_DDL if it does not exist. func checkForSchemaUpdateTable(db *sql.DB, driver string) { - showTableSql := showMigrationsTableSql(driver) - if rows, err := db.Query(showTableSql); err != nil { + showTableSQL := showMigrationsTableSQL(driver) + if rows, err := db.Query(showTableSQL); err != nil { ColorLog("[ERRO] Could not show migrations table: %s\n", err) os.Exit(2) } else if !rows.Next() { // no migrations table, create anew - createTableSql := createMigrationsTableSql(driver) + createTableSQL := createMigrationsTableSQL(driver) ColorLog("[INFO] Creating 'migrations' table...\n") - if _, err := db.Query(createTableSql); err != nil { + if _, err := db.Query(createTableSQL); err != nil { ColorLog("[ERRO] Could not create migrations table: %s\n", err) os.Exit(2) } } // checking that migrations table schema are expected - selectTableSql := selectMigrationsTableSql(driver) - if rows, err := db.Query(selectTableSql); err != nil { + selectTableSQL := selectMigrationsTableSQL(driver) + if rows, err := db.Query(selectTableSQL); err != nil { ColorLog("[ERRO] Could not show columns of migrations table: %s\n", err) os.Exit(2) } else { @@ -219,7 +219,7 @@ func checkForSchemaUpdateTable(db *sql.DB, driver string) { } } -func showMigrationsTableSql(driver string) string { +func showMigrationsTableSQL(driver string) string { switch driver { case "mysql": return "SHOW TABLES LIKE 'migrations'" @@ -230,18 +230,18 @@ func showMigrationsTableSql(driver string) string { } } -func createMigrationsTableSql(driver string) string { +func createMigrationsTableSQL(driver string) string { switch driver { case "mysql": - return MYSQL_MIGRATION_DDL + return MYSQLMigrationDDL case "postgres": - return POSTGRES_MIGRATION_DDL + return POSTGRESMigrationDDL default: - return MYSQL_MIGRATION_DDL + return MYSQLMigrationDDL } } -func selectMigrationsTableSql(driver string) string { +func selectMigrationsTableSQL(driver string) string { switch driver { case "mysql": return "DESC migrations" @@ -290,7 +290,7 @@ func writeMigrationSourceFile(dir, source, driver, connStr string, latestTime in ColorLog("[ERRO] Could not create file: %s\n", err) os.Exit(2) } else { - content := strings.Replace(MIGRATION_MAIN_TPL, "{{DBDriver}}", driver, -1) + content := strings.Replace(MigrationMainTPL, "{{DBDriver}}", driver, -1) content = strings.Replace(content, "{{ConnStr}}", connStr, -1) content = strings.Replace(content, "{{LatestTime}}", strconv.FormatInt(latestTime, 10), -1) content = strings.Replace(content, "{{LatestName}}", latestName, -1) @@ -369,7 +369,7 @@ func formatShellOutput(o string) { } const ( - MIGRATION_MAIN_TPL = `package main + MigrationMainTPL = `package main import( "os" @@ -408,7 +408,7 @@ func main(){ } ` - MYSQL_MIGRATION_DDL = ` + MYSQLMigrationDDL = ` CREATE TABLE migrations ( id_migration int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'surrogate key', name varchar(255) DEFAULT NULL COMMENT 'migration name, unique', @@ -420,7 +420,7 @@ CREATE TABLE migrations ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ` - POSTGRES_MIGRATION_DDL = ` + POSTGRESMigrationDDL = ` CREATE TYPE migrations_status AS ENUM('update', 'rollback'); CREATE TABLE migrations ( diff --git a/pack.go b/pack.go index c08bded..db2978c 100644 --- a/pack.go +++ b/pack.go @@ -246,9 +246,8 @@ func (wft *walkFileTree) walkLeaf(fpath string, fi os.FileInfo, err error) error } wft.allfiles[name] = true return err - } else { - return err } + return err } func (wft *walkFileTree) iterDirectory(fpath string, fi os.FileInfo) error { diff --git a/run.go b/run.go index 1200e4c..17df1ee 100644 --- a/run.go +++ b/run.go @@ -114,7 +114,7 @@ func runApp(cmd *Command, args []string) int { if downdoc == "true" { if _, err := os.Stat(path.Join(crupath, "swagger")); err != nil { if os.IsNotExist(err) { - downloadFromUrl(swaggerlink, "swagger.zip") + downloadFromURL(swaggerlink, "swagger.zip") unzipAndDelete("swagger.zip", "swagger") } } diff --git a/rundocs.go b/rundocs.go index 13b0a9a..70a1657 100644 --- a/rundocs.go +++ b/rundocs.go @@ -59,7 +59,7 @@ func init() { func runDocs(cmd *Command, args []string) int { if isDownload == "true" { - downloadFromUrl(swaggerlink, "swagger.zip") + downloadFromURL(swaggerlink, "swagger.zip") err := unzipAndDelete("swagger.zip", "swagger") if err != nil { fmt.Println("has err exet unzipAndDelete", err) @@ -77,7 +77,7 @@ func runDocs(cmd *Command, args []string) int { return 0 } -func downloadFromUrl(url, fileName string) { +func downloadFromURL(url, fileName string) { fmt.Println("Downloading", url, "to", fileName) output, err := os.Create(fileName) From 1308ebd9409306a1c7cf1d8de2f02eafa81f629e Mon Sep 17 00:00:00 2001 From: Sergey Lanzman Date: Sat, 23 Jul 2016 02:14:33 +0300 Subject: [PATCH 063/123] fix generate migration for postgressql --- g.go | 3 +++ g_scaffold.go | 3 +++ 2 files changed, 6 insertions(+) diff --git a/g.go b/g.go index 567e247..3f36c07 100644 --- a/g.go +++ b/g.go @@ -172,6 +172,9 @@ func generateCode(cmd *Command, args []string) int { if fields != "" { upsql = `m.SQL("CREATE TABLE ` + mname + "(" + generateSQLFromFields(fields.String()) + `)");` downsql = `m.SQL("DROP TABLE ` + "`" + mname + "`" + `")` + if driver == "postgres" { + downsql = strings.Replace(downsql, "`", "", -1) + } } generateMigration(mname, upsql, downsql, curpath) case "controller": diff --git a/g_scaffold.go b/g_scaffold.go index 9e232c5..c87292c 100644 --- a/g_scaffold.go +++ b/g_scaffold.go @@ -30,6 +30,9 @@ func generateScaffold(sname, fields, crupath, driver, conn string) { if fields != "" { upsql = `m.SQL("CREATE TABLE ` + sname + "(" + generateSQLFromFields(fields) + `)");` downsql = `m.SQL("DROP TABLE ` + "`" + sname + "`" + `")` + if driver == "" { + downsql = strings.Replace(downsql, "`", "", -1) + } } generateMigration(sname, upsql, downsql, crupath) } From 834f346bff400abff60ccc7402122c3e9449e65c Mon Sep 17 00:00:00 2001 From: Sergey Lanzman Date: Sat, 23 Jul 2016 02:37:20 +0300 Subject: [PATCH 064/123] add Beefily yml --- Beefile | 15 +++++++++++++++ conf.go | 42 ++++++++++++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 Beefile diff --git a/Beefile b/Beefile new file mode 100644 index 0000000..7d682df --- /dev/null +++ b/Beefile @@ -0,0 +1,15 @@ +version: 0 +gopm: + enable: false + install: false +go_install: false +watch_ext: [] +dir_structure: + watch_all: false + controllers: "" + models: "" + others: [] +cmd_args: [] +envs: [] +database: + driver: "mysql" diff --git a/conf.go b/conf.go index 9d610d1..3139d22 100644 --- a/conf.go +++ b/conf.go @@ -16,7 +16,10 @@ package main import ( "encoding/json" + "io/ioutil" "os" + + "gopkg.in/yaml.v2" ) const CONF_VER = 0 @@ -50,20 +53,20 @@ var conf struct { Install bool } // Indicates whether execute "go install" before "go build". - GoInstall bool `json:"go_install"` - WatchExt []string `json:"watch_ext"` + GoInstall bool `json:"go_install" yaml:"go_install"` + WatchExt []string `json:"watch_ext" yaml:"watch_ext"` DirStruct struct { - WatchAll bool `json:"watch_all"` + WatchAll bool `json:"watch_all" yaml:"watch_all"` Controllers string Models string Others []string // Other directories. - } `json:"dir_structure"` - CmdArgs []string `json:"cmd_args"` + } `json:"dir_structure" yaml:"dir_structure"` + CmdArgs []string `json:"cmd_args" yaml:"cmd_args"` Envs []string Bale struct { Import string Dirs []string - IngExt []string `json:"ignore_ext"` + IngExt []string `json:"ignore_ext" yaml:"ignore_ext"` } Database struct { Driver string @@ -73,14 +76,9 @@ var conf struct { // loadConfig loads customized configuration. func loadConfig() error { + foundConf := false f, err := os.Open("bee.json") - if err != nil { - // Use default. - err = json.Unmarshal([]byte(defaultConf), &conf) - if err != nil { - return err - } - } else { + if err == nil { defer f.Close() ColorLog("[INFO] Detected bee.json\n") d := json.NewDecoder(f) @@ -88,8 +86,24 @@ func loadConfig() error { if err != nil { return err } + foundConf = true + } + byml, erryml := ioutil.ReadFile("Beefile") + if erryml == nil { + ColorLog("[INFO] Detected Beefile\n") + err = yaml.Unmarshal(byml, &conf) + if err != nil { + return err + } + foundConf = true + } + if !foundConf { + // Use default. + err = json.Unmarshal([]byte(defaultConf), &conf) + if err != nil { + return err + } } - // Check format version. if conf.Version != CONF_VER { ColorLog("[WARN] Your bee.json is out-of-date, please update!\n") From 4f3ed96523c780ff32f6f7b8497969350ef90ac2 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Mon, 25 Jul 2016 21:10:12 +0200 Subject: [PATCH 065/123] grouped variable declarations --- run.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/run.go b/run.go index c2263bf..be06849 100644 --- a/run.go +++ b/run.go @@ -15,12 +15,12 @@ package main import ( + "fmt" "io/ioutil" "os" path "path/filepath" "runtime" "strings" - "fmt" ) var cmdRun = &Command{ @@ -33,16 +33,21 @@ it will recompile and restart the app after any modifications. `, } -var mainFiles ListOpts - -var downdoc docValue -var gendoc docValue - -// The flags list of the paths excluded from watching -var excludedPaths strFlags - -// Pass through to -tags arg of "go build" -var buildTags string +var ( + mainFiles ListOpts + downdoc docValue + gendoc docValue + // The flags list of the paths excluded from watching + excludedPaths strFlags + // Pass through to -tags arg of "go build" + buildTags string + // Application path + currpath string + // Application name + appname string + // Channel to signal an Exit + exit chan bool +) func init() { cmdRun.Run = runApp @@ -51,14 +56,9 @@ func init() { cmdRun.Flag.Var(&downdoc, "downdoc", "Auto download Swagger file when does not exist") cmdRun.Flag.Var(&excludedPaths, "e", "Excluded paths[].") cmdRun.Flag.StringVar(&buildTags, "tags", "", "Build tags (https://golang.org/pkg/go/build/)") + exit = make(chan bool) } -var ( - currpath = "" - appname = "" - exit = make(chan bool) -) - func runApp(cmd *Command, args []string) int { ShowShortVersionBanner() From 7254acdb7fb5d6ae6ded9cb149f9673486dc1155 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Mon, 25 Jul 2016 21:11:07 +0200 Subject: [PATCH 066/123] added Makefile --- Makefile | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7259aa6 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +.PHONY: all test clean build install + +GOFLAGS ?= $(GOFLAGS:) + +all: install test + +build: + go build $(GOFLAGS) ./... + +install: + go get $(GOFLAGS) ./... + +test: install + go test $(GOFLAGS) ./... + +bench: install + go test -run=NONE -bench=. $(GOFLAGS) ./... + +clean: + go clean $(GOFLAGS) -i ./... From 23f03c61b128b65b5f579ef3d4fdb3a0837c2189 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Tue, 26 Jul 2016 21:07:17 +0200 Subject: [PATCH 067/123] Revert "grouped variable declarations" This reverts commit 4f3ed96523c780ff32f6f7b8497969350ef90ac2. --- run.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/run.go b/run.go index be06849..c2263bf 100644 --- a/run.go +++ b/run.go @@ -15,12 +15,12 @@ package main import ( - "fmt" "io/ioutil" "os" path "path/filepath" "runtime" "strings" + "fmt" ) var cmdRun = &Command{ @@ -33,21 +33,16 @@ it will recompile and restart the app after any modifications. `, } -var ( - mainFiles ListOpts - downdoc docValue - gendoc docValue - // The flags list of the paths excluded from watching - excludedPaths strFlags - // Pass through to -tags arg of "go build" - buildTags string - // Application path - currpath string - // Application name - appname string - // Channel to signal an Exit - exit chan bool -) +var mainFiles ListOpts + +var downdoc docValue +var gendoc docValue + +// The flags list of the paths excluded from watching +var excludedPaths strFlags + +// Pass through to -tags arg of "go build" +var buildTags string func init() { cmdRun.Run = runApp @@ -56,9 +51,14 @@ func init() { cmdRun.Flag.Var(&downdoc, "downdoc", "Auto download Swagger file when does not exist") cmdRun.Flag.Var(&excludedPaths, "e", "Excluded paths[].") cmdRun.Flag.StringVar(&buildTags, "tags", "", "Build tags (https://golang.org/pkg/go/build/)") - exit = make(chan bool) } +var ( + currpath = "" + appname = "" + exit = make(chan bool) +) + func runApp(cmd *Command, args []string) int { ShowShortVersionBanner() From 24955fb0441a4f6e50a4cc034ff156a149c25068 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Thu, 28 Jul 2016 14:19:42 +0200 Subject: [PATCH 068/123] Fixed merge conflict --- .gitignore | 1 + run.go | 37 +++++++++++++++++++------------------ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index ffab5d0..a4c4e18 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ # Folders _obj _test +.idea # Architecture specific extensions/prefixes *.[568vq] diff --git a/run.go b/run.go index b9d40ed..db1ceed 100644 --- a/run.go +++ b/run.go @@ -20,6 +20,7 @@ import ( path "path/filepath" "runtime" "strings" + "fmt" ) var cmdRun = &Command{ @@ -32,18 +33,23 @@ it will recompile and restart the app after any modifications. `, } -var mainFiles ListOpts - -var downdoc docValue -var gendoc docValue - -// The flags list of the paths excluded from watching -var excludedPaths strFlags - -// Pass through to -tags arg of "go build" -var buildTags string - -var vendorWatch bool +var ( + mainFiles ListOpts + downdoc docValue + gendoc docValue + // The flags list of the paths excluded from watching + excludedPaths strFlags + // Pass through to -tags arg of "go build" + buildTags string + // Application path + currpath string + // Application name + appname string + // Channel to signal an Exit + exit chan bool + // Flag to watch the vendor folder + vendorWatch bool +) func init() { cmdRun.Run = runApp @@ -53,14 +59,9 @@ func init() { cmdRun.Flag.Var(&excludedPaths, "e", "Excluded paths[].") cmdRun.Flag.BoolVar(&vendorWatch, "vendor", false, "Watch vendor folder") cmdRun.Flag.StringVar(&buildTags, "tags", "", "Build tags (https://golang.org/pkg/go/build/)") + exit = make(chan bool) } -var ( - currpath = "" - appname = "" - exit = make(chan bool) -) - func runApp(cmd *Command, args []string) int { ShowShortVersionBanner() From 5bc1c82a2b0d9aa16172663fd07e63cecb52e094 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Fri, 29 Jul 2016 17:45:15 +0200 Subject: [PATCH 069/123] Added check for multiple paths in GOPATH (instead of the first path in the list) --- run.go | 32 ++++++++++++++++---------------- util.go | 31 ++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/run.go b/run.go index db1ceed..a3af6c3 100644 --- a/run.go +++ b/run.go @@ -49,6 +49,8 @@ var ( exit chan bool // Flag to watch the vendor folder vendorWatch bool + // Current user workspace + currentGoPath string ) func init() { @@ -65,26 +67,24 @@ func init() { func runApp(cmd *Command, args []string) int { ShowShortVersionBanner() - gps := GetGOPATHs() - if len(gps) == 0 { - ColorLog("[ERRO] Fail to start[ %s ]\n", "$GOPATH is not set or empty") - os.Exit(2) - } - gopath := gps[0] - if len(args) == 0 || args[0] == "watchall" { currpath, _ = os.Getwd() + + if !isBeegoProject(currpath) { + exitPrint(fmt.Sprintf("Bee does not support non Beego project: %s", currpath)) + } + + _, currentGoPath, _ = SearchGOPATHs(currpath) appname = path.Base(currpath) ColorLog("[INFO] Uses '%s' as 'appname'\n", appname) } else { - gopathsrc := path.Join(gopath, "src") - currpath = path.Join(gopathsrc, args[0]) - appname = path.Base(currpath) - - // Check if passed Bee application path/name exists - // in $GOPATH/src workspace - if !isExist(currpath) { - panic(fmt.Sprintf("No Beego application '%s' found in GOPATH: %s", args[0], gopathsrc)) + // Check if passed Bee application path/name exists in the GOPATH(s) + if ok, _gopath, _path := SearchGOPATHs(args[0]); ok { + currpath = _path + currentGoPath = _gopath + appname = path.Base(currpath) + } else { + panic(fmt.Sprintf("No Beego application '%s' found in your GOPATH", args[0])) } ColorLog("[INFO] Uses '%s' as 'appname'\n", appname) @@ -110,7 +110,7 @@ func runApp(cmd *Command, args []string) int { // Because monitor files has some issues, we watch current directory // and ignore non-go files. for _, p := range conf.DirStruct.Others { - paths = append(paths, strings.Replace(p, "$GOPATH", gopath, -1)) + paths = append(paths, strings.Replace(p, "$GOPATH", currentGoPath, -1)) } files := []string{} diff --git a/util.go b/util.go index 0f314df..2cd76d3 100644 --- a/util.go +++ b/util.go @@ -15,13 +15,14 @@ package main import ( - "fmt" "log" "os" "path/filepath" "runtime" "strings" "time" + "path" + "fmt" ) // Go is a basic promise implementation: it wraps calls a function in a goroutine @@ -173,6 +174,34 @@ func GetGOPATHs() []string { return paths } +func SearchGOPATHs(app string) (bool, string, string) { + gps := GetGOPATHs() + if len(gps) == 0 { + ColorLog("[ERRO] Fail to start [ %s ]\n", "GOPATH environment variable is not set or empty") + os.Exit(2) + } + + // Lookup the application inside the user workspace(s) + for _, gopath := range gps { + var currentPath string + + if !strings.Contains(app, "src") { + gopathsrc := path.Join(gopath, "src") + currentPath = path.Join(gopathsrc, app) + } else { + currentPath = app + } + + if isExist(currentPath) { + if !isBeegoProject(currentPath) { + continue + } + return true, gopath, currentPath + } + } + return false, "", "" +} + // askForConfirmation uses Scanln to parse user input. A user must type in "yes" or "no" and // then press enter. It has fuzzy matching, so "y", "Y", "yes", "YES", and "Yes" all count as // confirmations. If the input is not recognized, it will ask again. The function does not return From 828b8d8b532b6d42ece7af091fc7c0cc2e69caa2 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Sat, 30 Jul 2016 13:42:38 +0200 Subject: [PATCH 070/123] Removed redundant beego project check --- run.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/run.go b/run.go index a3af6c3..d4bc44a 100644 --- a/run.go +++ b/run.go @@ -15,12 +15,12 @@ package main import ( + "fmt" "io/ioutil" "os" path "path/filepath" "runtime" "strings" - "fmt" ) var cmdRun = &Command{ @@ -35,8 +35,8 @@ it will recompile and restart the app after any modifications. var ( mainFiles ListOpts - downdoc docValue - gendoc docValue + downdoc docValue + gendoc docValue // The flags list of the paths excluded from watching excludedPaths strFlags // Pass through to -tags arg of "go build" @@ -70,16 +70,16 @@ func runApp(cmd *Command, args []string) int { if len(args) == 0 || args[0] == "watchall" { currpath, _ = os.Getwd() - if !isBeegoProject(currpath) { + if found, _gopath, _ := SearchGOPATHs(currpath); found { + appname = path.Base(currpath) + currentGoPath = _gopath + } else { exitPrint(fmt.Sprintf("Bee does not support non Beego project: %s", currpath)) } - - _, currentGoPath, _ = SearchGOPATHs(currpath) - appname = path.Base(currpath) - ColorLog("[INFO] Uses '%s' as 'appname'\n", appname) + ColorLog("[INFO] Using '%s' as 'appname'\n", appname) } else { // Check if passed Bee application path/name exists in the GOPATH(s) - if ok, _gopath, _path := SearchGOPATHs(args[0]); ok { + if found, _gopath, _path := SearchGOPATHs(args[0]); found { currpath = _path currentGoPath = _gopath appname = path.Base(currpath) @@ -87,7 +87,8 @@ func runApp(cmd *Command, args []string) int { panic(fmt.Sprintf("No Beego application '%s' found in your GOPATH", args[0])) } - ColorLog("[INFO] Uses '%s' as 'appname'\n", appname) + ColorLog("[INFO] Using '%s' as 'appname'\n", appname) + if strings.HasSuffix(appname, ".go") && isExist(currpath) { ColorLog("[WARN] The appname is in conflict with currpath's file, do you want to build appname as %s\n", appname) ColorLog("[INFO] Do you want to overwrite it? [yes|no]] ") From ea2376e90dbed46cf794770bf8e74ad232119a44 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Sun, 31 Jul 2016 23:21:20 +0200 Subject: [PATCH 071/123] Added ANSI color writer --- color.go | 51 +++++ colorwriter.go | 28 +++ colorwriter_windows.go | 427 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 506 insertions(+) create mode 100644 color.go create mode 100644 colorwriter.go create mode 100644 colorwriter_windows.go diff --git a/color.go b/color.go new file mode 100644 index 0000000..583d6c6 --- /dev/null +++ b/color.go @@ -0,0 +1,51 @@ +// Copyright 2013 bee authors +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +package main + +import "io" + +type outputMode int + +// DiscardNonColorEscSeq supports the divided color escape sequence. +// But non-color escape sequence is not output. +// Please use the OutputNonColorEscSeq If you want to output a non-color +// escape sequences such as ncurses. However, it does not support the divided +// color escape sequence. +const ( + _ outputMode = iota + DiscardNonColorEscSeq + OutputNonColorEscSeq +) + +// NewColorWriter creates and initializes a new ansiColorWriter +// using io.Writer w as its initial contents. +// In the console of Windows, which change the foreground and background +// colors of the text by the escape sequence. +// In the console of other systems, which writes to w all text. +func NewColorWriter(w io.Writer) io.Writer { + return NewModeColorWriter(w, DiscardNonColorEscSeq) +} + +// NewModeColorWriter create and initializes a new ansiColorWriter +// by specifying the outputMode. +func NewModeColorWriter(w io.Writer, mode outputMode) io.Writer { + if _, ok := w.(*colorWriter); !ok { + return &colorWriter{ + w: w, + mode: mode, + } + } + return w +} diff --git a/colorwriter.go b/colorwriter.go new file mode 100644 index 0000000..86201e8 --- /dev/null +++ b/colorwriter.go @@ -0,0 +1,28 @@ +// Copyright 2013 bee authors +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +// +build !windows + +package main + +import "io" + +type colorWriter struct { + w io.Writer + mode outputMode +} + +func (cw *colorWriter) Write(p []byte) (int, error) { + return cw.w.Write(p) +} diff --git a/colorwriter_windows.go b/colorwriter_windows.go new file mode 100644 index 0000000..d257f54 --- /dev/null +++ b/colorwriter_windows.go @@ -0,0 +1,427 @@ +// Copyright 2013 bee authors +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +// +build windows + +package main + +import ( + "bytes" + "io" + "strings" + "syscall" + "unsafe" +) + +type csiState int + +const ( + outsideCsiCode csiState = iota + firstCsiCode + secondCsiCode +) + +type parseResult int + +const ( + noConsole parseResult = iota + changedColor + unknown +) + +type colorWriter struct { + w io.Writer + mode outputMode + state csiState + paramStartBuf bytes.Buffer + paramBuf bytes.Buffer +} + +const ( + firstCsiChar byte = '\x1b' + secondeCsiChar byte = '[' + separatorChar byte = ';' + sgrCode byte = 'm' +) + +const ( + foregroundBlue = uint16(0x0001) + foregroundGreen = uint16(0x0002) + foregroundRed = uint16(0x0004) + foregroundIntensity = uint16(0x0008) + backgroundBlue = uint16(0x0010) + backgroundGreen = uint16(0x0020) + backgroundRed = uint16(0x0040) + backgroundIntensity = uint16(0x0080) + underscore = uint16(0x8000) + + foregroundMask = foregroundBlue | foregroundGreen | foregroundRed | foregroundIntensity + backgroundMask = backgroundBlue | backgroundGreen | backgroundRed | backgroundIntensity +) + +const ( + ansiReset = "0" + ansiIntensityOn = "1" + ansiIntensityOff = "21" + ansiUnderlineOn = "4" + ansiUnderlineOff = "24" + ansiBlinkOn = "5" + ansiBlinkOff = "25" + + ansiForegroundBlack = "30" + ansiForegroundRed = "31" + ansiForegroundGreen = "32" + ansiForegroundYellow = "33" + ansiForegroundBlue = "34" + ansiForegroundMagenta = "35" + ansiForegroundCyan = "36" + ansiForegroundWhite = "37" + ansiForegroundDefault = "39" + + ansiBackgroundBlack = "40" + ansiBackgroundRed = "41" + ansiBackgroundGreen = "42" + ansiBackgroundYellow = "43" + ansiBackgroundBlue = "44" + ansiBackgroundMagenta = "45" + ansiBackgroundCyan = "46" + ansiBackgroundWhite = "47" + ansiBackgroundDefault = "49" + + ansiLightForegroundGray = "90" + ansiLightForegroundRed = "91" + ansiLightForegroundGreen = "92" + ansiLightForegroundYellow = "93" + ansiLightForegroundBlue = "94" + ansiLightForegroundMagenta = "95" + ansiLightForegroundCyan = "96" + ansiLightForegroundWhite = "97" + + ansiLightBackgroundGray = "100" + ansiLightBackgroundRed = "101" + ansiLightBackgroundGreen = "102" + ansiLightBackgroundYellow = "103" + ansiLightBackgroundBlue = "104" + ansiLightBackgroundMagenta = "105" + ansiLightBackgroundCyan = "106" + ansiLightBackgroundWhite = "107" +) + +type drawType int + +const ( + foreground drawType = iota + background +) + +type winColor struct { + code uint16 + drawType drawType +} + +var colorMap = map[string]winColor{ + ansiForegroundBlack: {0, foreground}, + ansiForegroundRed: {foregroundRed, foreground}, + ansiForegroundGreen: {foregroundGreen, foreground}, + ansiForegroundYellow: {foregroundRed | foregroundGreen, foreground}, + ansiForegroundBlue: {foregroundBlue, foreground}, + ansiForegroundMagenta: {foregroundRed | foregroundBlue, foreground}, + ansiForegroundCyan: {foregroundGreen | foregroundBlue, foreground}, + ansiForegroundWhite: {foregroundRed | foregroundGreen | foregroundBlue, foreground}, + ansiForegroundDefault: {foregroundRed | foregroundGreen | foregroundBlue, foreground}, + + ansiBackgroundBlack: {0, background}, + ansiBackgroundRed: {backgroundRed, background}, + ansiBackgroundGreen: {backgroundGreen, background}, + ansiBackgroundYellow: {backgroundRed | backgroundGreen, background}, + ansiBackgroundBlue: {backgroundBlue, background}, + ansiBackgroundMagenta: {backgroundRed | backgroundBlue, background}, + ansiBackgroundCyan: {backgroundGreen | backgroundBlue, background}, + ansiBackgroundWhite: {backgroundRed | backgroundGreen | backgroundBlue, background}, + ansiBackgroundDefault: {0, background}, + + ansiLightForegroundGray: {foregroundIntensity, foreground}, + ansiLightForegroundRed: {foregroundIntensity | foregroundRed, foreground}, + ansiLightForegroundGreen: {foregroundIntensity | foregroundGreen, foreground}, + ansiLightForegroundYellow: {foregroundIntensity | foregroundRed | foregroundGreen, foreground}, + ansiLightForegroundBlue: {foregroundIntensity | foregroundBlue, foreground}, + ansiLightForegroundMagenta: {foregroundIntensity | foregroundRed | foregroundBlue, foreground}, + ansiLightForegroundCyan: {foregroundIntensity | foregroundGreen | foregroundBlue, foreground}, + ansiLightForegroundWhite: {foregroundIntensity | foregroundRed | foregroundGreen | foregroundBlue, foreground}, + + ansiLightBackgroundGray: {backgroundIntensity, background}, + ansiLightBackgroundRed: {backgroundIntensity | backgroundRed, background}, + ansiLightBackgroundGreen: {backgroundIntensity | backgroundGreen, background}, + ansiLightBackgroundYellow: {backgroundIntensity | backgroundRed | backgroundGreen, background}, + ansiLightBackgroundBlue: {backgroundIntensity | backgroundBlue, background}, + ansiLightBackgroundMagenta: {backgroundIntensity | backgroundRed | backgroundBlue, background}, + ansiLightBackgroundCyan: {backgroundIntensity | backgroundGreen | backgroundBlue, background}, + ansiLightBackgroundWhite: {backgroundIntensity | backgroundRed | backgroundGreen | backgroundBlue, background}, +} + +var ( + kernel32 = syscall.NewLazyDLL("kernel32.dll") + procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute") + procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") + defaultAttr *textAttributes +) + +func init() { + screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout)) + if screenInfo != nil { + colorMap[ansiForegroundDefault] = winColor{ + screenInfo.WAttributes & (foregroundRed | foregroundGreen | foregroundBlue), + foreground, + } + colorMap[ansiBackgroundDefault] = winColor{ + screenInfo.WAttributes & (backgroundRed | backgroundGreen | backgroundBlue), + background, + } + defaultAttr = convertTextAttr(screenInfo.WAttributes) + } +} + +type coord struct { + X, Y int16 +} + +type smallRect struct { + Left, Top, Right, Bottom int16 +} + +type consoleScreenBufferInfo struct { + DwSize coord + DwCursorPosition coord + WAttributes uint16 + SrWindow smallRect + DwMaximumWindowSize coord +} + +func getConsoleScreenBufferInfo(hConsoleOutput uintptr) *consoleScreenBufferInfo { + var csbi consoleScreenBufferInfo + ret, _, _ := procGetConsoleScreenBufferInfo.Call( + hConsoleOutput, + uintptr(unsafe.Pointer(&csbi))) + if ret == 0 { + return nil + } + return &csbi +} + +func setConsoleTextAttribute(hConsoleOutput uintptr, wAttributes uint16) bool { + ret, _, _ := procSetConsoleTextAttribute.Call( + hConsoleOutput, + uintptr(wAttributes)) + return ret != 0 +} + +type textAttributes struct { + foregroundColor uint16 + backgroundColor uint16 + foregroundIntensity uint16 + backgroundIntensity uint16 + underscore uint16 + otherAttributes uint16 +} + +func convertTextAttr(winAttr uint16) *textAttributes { + fgColor := winAttr & (foregroundRed | foregroundGreen | foregroundBlue) + bgColor := winAttr & (backgroundRed | backgroundGreen | backgroundBlue) + fgIntensity := winAttr & foregroundIntensity + bgIntensity := winAttr & backgroundIntensity + underline := winAttr & underscore + otherAttributes := winAttr &^ (foregroundMask | backgroundMask | underscore) + return &textAttributes{fgColor, bgColor, fgIntensity, bgIntensity, underline, otherAttributes} +} + +func convertWinAttr(textAttr *textAttributes) uint16 { + var winAttr uint16 + winAttr |= textAttr.foregroundColor + winAttr |= textAttr.backgroundColor + winAttr |= textAttr.foregroundIntensity + winAttr |= textAttr.backgroundIntensity + winAttr |= textAttr.underscore + winAttr |= textAttr.otherAttributes + return winAttr +} + +func changeColor(param []byte) parseResult { + screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout)) + if screenInfo == nil { + return noConsole + } + + winAttr := convertTextAttr(screenInfo.WAttributes) + strParam := string(param) + if len(strParam) <= 0 { + strParam = "0" + } + csiParam := strings.Split(strParam, string(separatorChar)) + for _, p := range csiParam { + c, ok := colorMap[p] + switch { + case !ok: + switch p { + case ansiReset: + winAttr.foregroundColor = defaultAttr.foregroundColor + winAttr.backgroundColor = defaultAttr.backgroundColor + winAttr.foregroundIntensity = defaultAttr.foregroundIntensity + winAttr.backgroundIntensity = defaultAttr.backgroundIntensity + winAttr.underscore = 0 + winAttr.otherAttributes = 0 + case ansiIntensityOn: + winAttr.foregroundIntensity = foregroundIntensity + case ansiIntensityOff: + winAttr.foregroundIntensity = 0 + case ansiUnderlineOn: + winAttr.underscore = underscore + case ansiUnderlineOff: + winAttr.underscore = 0 + case ansiBlinkOn: + winAttr.backgroundIntensity = backgroundIntensity + case ansiBlinkOff: + winAttr.backgroundIntensity = 0 + default: + // unknown code + } + case c.drawType == foreground: + winAttr.foregroundColor = c.code + case c.drawType == background: + winAttr.backgroundColor = c.code + } + } + winTextAttribute := convertWinAttr(winAttr) + setConsoleTextAttribute(uintptr(syscall.Stdout), winTextAttribute) + + return changedColor +} + +func parseEscapeSequence(command byte, param []byte) parseResult { + if defaultAttr == nil { + return noConsole + } + + switch command { + case sgrCode: + return changeColor(param) + default: + return unknown + } +} + +func (cw *ansiColorWriter) flushBuffer() (int, error) { + return cw.flushTo(cw.w) +} + +func (cw *ansiColorWriter) resetBuffer() (int, error) { + return cw.flushTo(nil) +} + +func (cw *ansiColorWriter) flushTo(w io.Writer) (int, error) { + var n1, n2 int + var err error + + startBytes := cw.paramStartBuf.Bytes() + cw.paramStartBuf.Reset() + if w != nil { + n1, err = cw.w.Write(startBytes) + if err != nil { + return n1, err + } + } else { + n1 = len(startBytes) + } + paramBytes := cw.paramBuf.Bytes() + cw.paramBuf.Reset() + if w != nil { + n2, err = cw.w.Write(paramBytes) + if err != nil { + return n1 + n2, err + } + } else { + n2 = len(paramBytes) + } + return n1 + n2, nil +} + +func isParameterChar(b byte) bool { + return ('0' <= b && b <= '9') || b == separatorChar +} + +func (cw *ansiColorWriter) Write(p []byte) (int, error) { + r, nw, first, last := 0, 0, 0, 0 + if cw.mode != DiscardNonColorEscSeq { + cw.state = outsideCsiCode + cw.resetBuffer() + } + + var err error + for i, ch := range p { + switch cw.state { + case outsideCsiCode: + if ch == firstCsiChar { + cw.paramStartBuf.WriteByte(ch) + cw.state = firstCsiCode + } + case firstCsiCode: + switch ch { + case firstCsiChar: + cw.paramStartBuf.WriteByte(ch) + break + case secondeCsiChar: + cw.paramStartBuf.WriteByte(ch) + cw.state = secondCsiCode + last = i - 1 + default: + cw.resetBuffer() + cw.state = outsideCsiCode + } + case secondCsiCode: + if isParameterChar(ch) { + cw.paramBuf.WriteByte(ch) + } else { + nw, err = cw.w.Write(p[first:last]) + r += nw + if err != nil { + return r, err + } + first = i + 1 + result := parseEscapeSequence(ch, cw.paramBuf.Bytes()) + if result == noConsole || (cw.mode == OutputNonColorEscSeq && result == unknown) { + cw.paramBuf.WriteByte(ch) + nw, err := cw.flushBuffer() + if err != nil { + return r, err + } + r += nw + } else { + n, _ := cw.resetBuffer() + // Add one more to the size of the buffer for the last ch + r += n + 1 + } + + cw.state = outsideCsiCode + } + default: + cw.state = outsideCsiCode + } + } + + if cw.mode != DiscardNonColorEscSeq || cw.state == outsideCsiCode { + nw, err = cw.w.Write(p[first:len(p)]) + r += nw + } + + return r, err +} From 7662cfe5d9be231c3a463bba66fa8d38178917b8 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Sun, 31 Jul 2016 23:23:07 +0200 Subject: [PATCH 072/123] Tweaked the Bee banner --- banner.go | 8 ++++++-- version.go | 52 ++++++++++++++++++++++++++-------------------------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/banner.go b/banner.go index d04293b..af33ef3 100644 --- a/banner.go +++ b/banner.go @@ -21,11 +21,12 @@ type vars struct { BeegoVersion string } +// Now returns the current local time in the specified layout func Now(layout string) string { return time.Now().Format(layout) } -// Init load the banner and prints it to output +// InitBanner loads the banner and prints it to output // All errors are ignored, the application will not // print the banner in case of error. func InitBanner(out io.Writer, in io.Reader) { @@ -55,7 +56,7 @@ func show(out io.Writer, content string) { os.Exit(2) } - t.Execute(out, vars{ + err = t.Execute(out, vars{ runtime.Version(), runtime.GOOS, runtime.GOARCH, @@ -66,4 +67,7 @@ func show(out io.Writer, content string) { version, getBeegoVersion(), }) + if err != nil { + panic(err) + } } diff --git a/version.go b/version.go index 43931e1..d9442aa 100644 --- a/version.go +++ b/version.go @@ -2,54 +2,47 @@ package main import ( "bufio" + "bytes" "fmt" "io" "os" path "path/filepath" "regexp" - "bytes" ) var cmdVersion = &Command{ UsageLine: "version", - Short: "show the Bee, Beego and Go version", + Short: "prints the current Bee version", Long: ` -show the Bee, Beego and Go version - -bee version - bee :1.2.3 - beego :1.4.2 - Go :go version go1.3.3 linux/amd64 +Prints the current Bee, Beego and Go version alongside the platform information `, } -const verboseVersionBanner = -`______ +const verboseVersionBanner string = `%s%s______ | ___ \ | |_/ / ___ ___ | ___ \ / _ \ / _ \ | |_/ /| __/| __/ -\____/ \___| \___| v{{ .BeeVersion }} - -Beego : {{ .BeegoVersion }} -GoVersion : {{ .GoVersion }} -GOOS : {{ .GOOS }} -GOARCH : {{ .GOARCH }} -NumCPU : {{ .NumCPU }} -GOPATH : {{ .GOPATH }} -GOROOT : {{ .GOROOT }} -Compiler : {{ .Compiler }} -Date : {{ Now "Monday, 2 Jan 2006" }} +\____/ \___| \___| v{{ .BeeVersion }}%s +%s%s +├── Beego : {{ .BeegoVersion }} +├── GoVersion : {{ .GoVersion }} +├── GOOS : {{ .GOOS }} +├── GOARCH : {{ .GOARCH }} +├── NumCPU : {{ .NumCPU }} +├── GOPATH : {{ .GOPATH }} +├── GOROOT : {{ .GOROOT }} +├── Compiler : {{ .Compiler }} +└── Date : {{ Now "Monday, 2 Jan 2006" }}%s ` -const shortVersionBanner = -`______ +const shortVersionBanner = `%s%s______ | ___ \ | |_/ / ___ ___ | ___ \ / _ \ / _ \ | |_/ /| __/| __/ -\____/ \___| \___| v{{ .BeeVersion }} +\____/ \___| \___| v{{ .BeeVersion }}%s ` func init() { @@ -61,12 +54,19 @@ func versionCmd(cmd *Command, args []string) int { return 0 } +// ShowVerboseVersionBanner prints the verbose version banner func ShowVerboseVersionBanner() { - InitBanner(os.Stdout, bytes.NewBufferString(verboseVersionBanner)) + w := NewColorWriter(os.Stdout) + coloredBanner := fmt.Sprintf(verboseVersionBanner, "\x1b[35m", "\x1b[1m", "\x1b[0m", + "\x1b[32m", "\x1b[1m", "\x1b[0m") + InitBanner(w, bytes.NewBufferString(coloredBanner)) } +// ShowShortVersionBanner prints the short version banner func ShowShortVersionBanner() { - InitBanner(os.Stdout, bytes.NewBufferString(shortVersionBanner)) + w := NewColorWriter(os.Stdout) + coloredBanner := fmt.Sprintf(shortVersionBanner, "\x1b[35m", "\x1b[1m", "\x1b[0m") + InitBanner(w, bytes.NewBufferString(coloredBanner)) } func getBeegoVersion() string { From 338dfc65ed71a92923ef64183c4e444aeb532435 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Sun, 31 Jul 2016 23:30:35 +0200 Subject: [PATCH 073/123] New tweaks Added enhanced logging while using bee to scaffold code Fixed some typos and errors Added more error handling Added more docs --- apiapp.go | 36 +++++++++++++++-------------- g.go | 4 ++-- g_appcode.go | 45 ++++++++++++++++++++---------------- g_controllers.go | 29 +++++++++++++++-------- g_hproseappcode.go | 18 ++++++++------- g_migration.go | 11 +++++---- g_model.go | 47 ++++++++++++++++++++++++++++---------- g_scaffold.go | 36 ++++++++++++++++------------- g_views.go | 57 +++++++++++++++++++++++++++++++++------------- hproseapp.go | 22 ++++++++++-------- migrate.go | 2 +- new.go | 41 +++++++++++++++++---------------- pack.go | 10 ++++---- util.go | 8 +++++++ 14 files changed, 227 insertions(+), 139 deletions(-) diff --git a/apiapp.go b/apiapp.go index ee1f1d0..a30c739 100644 --- a/apiapp.go +++ b/apiapp.go @@ -548,6 +548,8 @@ func init() { func createapi(cmd *Command, args []string) int { ShowShortVersionBanner() + w := NewColorWriter(os.Stdout) + if len(args) < 1 { ColorLog("[ERRO] Argument [appname] is missing\n") os.Exit(2) @@ -571,21 +573,21 @@ func createapi(cmd *Command, args []string) int { ColorLog("[INFO] Creating API...\n") os.MkdirAll(apppath, 0755) - fmt.Println("\tcreate\t", apppath) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m") os.Mkdir(path.Join(apppath, "conf"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "conf")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf"), "\x1b[0m") os.Mkdir(path.Join(apppath, "controllers"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "controllers")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers"), "\x1b[0m") os.Mkdir(path.Join(apppath, "docs"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "docs")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "docs"), "\x1b[0m") os.Mkdir(path.Join(apppath, "tests"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "tests")) - fmt.Println("\tcreate\t", path.Join(apppath, "conf", "app.conf")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests"), "\x1b[0m") + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m") WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(apiconf, "{{.Appname}}", path.Base(args[0]), -1)) if conn != "" { - fmt.Println("\tcreate\t", path.Join(apppath, "main.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m") maingoContent := strings.Replace(apiMainconngo, "{{.Appname}}", packpath, -1) maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(driver), -1) if driver == "mysql" { @@ -607,36 +609,36 @@ func createapi(cmd *Command, args []string) int { generateAppcode(string(driver), string(conn), "3", string(tables), path.Join(apppath, args[0])) } else { os.Mkdir(path.Join(apppath, "models"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "models")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models"), "\x1b[0m") os.Mkdir(path.Join(apppath, "routers"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "routers") + string(path.Separator)) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers")+string(path.Separator), "\x1b[0m") - fmt.Println("\tcreate\t", path.Join(apppath, "controllers", "object.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "object.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "controllers", "object.go"), strings.Replace(apiControllers, "{{.Appname}}", packpath, -1)) - fmt.Println("\tcreate\t", path.Join(apppath, "controllers", "user.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "user.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "controllers", "user.go"), strings.Replace(apiControllers2, "{{.Appname}}", packpath, -1)) - fmt.Println("\tcreate\t", path.Join(apppath, "tests", "default_test.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests", "default_test.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(apiTests, "{{.Appname}}", packpath, -1)) - fmt.Println("\tcreate\t", path.Join(apppath, "routers", "router.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(apirouter, "{{.Appname}}", packpath, -1)) - fmt.Println("\tcreate\t", path.Join(apppath, "models", "object.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "object.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "models", "object.go"), apiModels) - fmt.Println("\tcreate\t", path.Join(apppath, "models", "user.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "user.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "models", "user.go"), apiModels2) - fmt.Println("\tcreate\t", path.Join(apppath, "docs", "doc.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "docs", "doc.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "docs", "doc.go"), "package docs") - fmt.Println("\tcreate\t", path.Join(apppath, "main.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "main.go"), strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1)) } diff --git a/g.go b/g.go index 3f36c07..61716f8 100644 --- a/g.go +++ b/g.go @@ -35,7 +35,7 @@ bee generate model [modelname] [-fields=""] -fields: a list of table fields. Format: field:type, ... bee generate controller [controllerfile] - generate RESTFul controllers + generate RESTful controllers bee generate view [viewpath] generate CRUD view in viewpath @@ -43,7 +43,7 @@ bee generate view [viewpath] bee generate migration [migrationfile] [-fields=""] generate migration file for making database schema update -fields: a list of table fields. Format: field:type, ... - + bee generate docs generate swagger doc file diff --git a/g_appcode.go b/g_appcode.go index 9fea762..522af6a 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -17,15 +17,14 @@ package main import ( "database/sql" "fmt" + _ "github.com/go-sql-driver/mysql" + _ "github.com/lib/pq" "os" "os/exec" "path" "path/filepath" "regexp" "strings" - - _ "github.com/go-sql-driver/mysql" - _ "github.com/lib/pq" ) const ( @@ -499,7 +498,7 @@ func (mysqlDB *MysqlDB) GetColumns(db *sql.DB, table *Table, blackList map[strin } } -// getGoDataType maps an SQL data type to Golang data type +// GetGoDataType maps an SQL data type to Golang data type func (*MysqlDB) GetGoDataType(sqlType string) (goType string) { var typeMapping = map[string]string{} typeMapping = typeMappingMysql @@ -688,6 +687,8 @@ func (postgresDB *PostgresDB) GetColumns(db *sql.DB, table *Table, blackList map table.Columns = append(table.Columns, col) } } + +// GetGoDataType returns the Go type from the mapped Postgres type func (*PostgresDB) GetGoDataType(sqlType string) (goType string) { if v, ok := typeMappingPostgres[sqlType]; ok { return v @@ -730,6 +731,8 @@ func writeSourceFiles(pkgPath string, tables []*Table, mode byte, paths *MvcPath // writeModelFiles generates model files func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bool) { + w := NewColorWriter(os.Stdout) + for _, tb := range tables { // if selectedTables map is not nil and this table is not selected, ignore it if selectedTables != nil { @@ -742,7 +745,7 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo var f *os.File var err error if isExist(fpath) { - ColorLog("[WARN] %v is exist, do you want to overwrite it? Yes or No?\n", fpath) + ColorLog("[WARN] '%v' already exists. Do you want to overwrite it? [Yes|No] ", fpath) if askForConfirmation() { f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666) if err != nil { @@ -750,7 +753,7 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo continue } } else { - ColorLog("[WARN] skip create file\n") + ColorLog("[WARN] Skipped create file '%s'\n", fpath) continue } } else { @@ -782,14 +785,16 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo ColorLog("[ERRO] Could not write model file to %s\n", fpath) os.Exit(2) } - f.Close() - ColorLog("[INFO] model => %s\n", fpath) + CloseFile(f) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") formatSourceCode(fpath) } } // writeControllerFiles generates controller files func writeControllerFiles(tables []*Table, cPath string, selectedTables map[string]bool, pkgPath string) { + w := NewColorWriter(os.Stdout) + for _, tb := range tables { // if selectedTables map is not nil and this table is not selected, ignore it if selectedTables != nil { @@ -805,7 +810,7 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri var f *os.File var err error if isExist(fpath) { - ColorLog("[WARN] %v is exist, do you want to overwrite it? Yes or No?\n", fpath) + ColorLog("[WARN] '%v' already exists. Do you want to overwrite it? [Yes|No] ", fpath) if askForConfirmation() { f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666) if err != nil { @@ -813,7 +818,7 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri continue } } else { - ColorLog("[WARN] skip create file\n") + ColorLog("[WARN] Skipped create file '%s'\n", fpath) continue } } else { @@ -829,14 +834,16 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri ColorLog("[ERRO] Could not write controller file to %s\n", fpath) os.Exit(2) } - f.Close() - ColorLog("[INFO] controller => %s\n", fpath) + CloseFile(f) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") formatSourceCode(fpath) } } // writeRouterFile generates router file func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bool, pkgPath string) { + w := NewColorWriter(os.Stdout) + var nameSpaces []string for _, tb := range tables { // if selectedTables map is not nil and this table is not selected, ignore it @@ -848,7 +855,7 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo if tb.Pk == "" { continue } - // add name spaces + // add namespaces nameSpace := strings.Replace(NamespaceTPL, "{{nameSpace}}", tb.Name, -1) nameSpace = strings.Replace(nameSpace, "{{ctrlName}}", camelCase(tb.Name), -1) nameSpaces = append(nameSpaces, nameSpace) @@ -860,7 +867,7 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo var f *os.File var err error if isExist(fpath) { - ColorLog("[WARN] %v is exist, do you want to overwrite it? Yes or No?\n", fpath) + ColorLog("[WARN] '%v' already exists. Do you want to overwrite it? [Yes|No] ", fpath) if askForConfirmation() { f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666) if err != nil { @@ -868,7 +875,7 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo return } } else { - ColorLog("[WARN] skip create file\n") + ColorLog("[WARN] Skipped create file '%s'\n", fpath) return } } else { @@ -879,11 +886,11 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo } } if _, err := f.WriteString(routerStr); err != nil { - ColorLog("[ERRO] Could not write router file to %s\n", fpath) + ColorLog("[ERRO] Could not write router file to '%s'\n", fpath) os.Exit(2) } - f.Close() - ColorLog("[INFO] router => %s\n", fpath) + CloseFile(f) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") formatSourceCode(fpath) } @@ -966,7 +973,7 @@ func getPackagePath(curpath string) (packpath string) { gopath := os.Getenv("GOPATH") Debugf("gopath:%s", gopath) if gopath == "" { - ColorLog("[ERRO] you should set GOPATH in the env") + ColorLog("[ERRO] You should set GOPATH in the env") os.Exit(2) } diff --git a/g_controllers.go b/g_controllers.go index a4815c0..0345247 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -15,53 +15,62 @@ package main import ( + "fmt" "os" "path" "strings" - "fmt" ) // article // cms/article // -func generateController(cname, crupath string) { +func generateController(cname, currpath string) { + w := NewColorWriter(os.Stdout) + p, f := path.Split(cname) controllerName := strings.Title(f) packageName := "controllers" + if p != "" { i := strings.LastIndex(p[:len(p)-1], "/") packageName = p[i+1 : len(p)-1] } + ColorLog("[INFO] Using '%s' as controller name\n", controllerName) ColorLog("[INFO] Using '%s' as package name\n", packageName) - fp := path.Join(crupath, "controllers", p) + + fp := path.Join(currpath, "controllers", p) if _, err := os.Stat(fp); os.IsNotExist(err) { - // create controller directory + // Create the controller's directory if err := os.MkdirAll(fp, 0777); err != nil { ColorLog("[ERRO] Could not create controllers directory: %s\n", err) os.Exit(2) } } + fpath := path.Join(fp, strings.ToLower(controllerName)+".go") if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { - defer f.Close() - modelPath := path.Join(crupath, "models", strings.ToLower(controllerName)+".go") + defer CloseFile(f) + + modelPath := path.Join(currpath, "models", strings.ToLower(controllerName)+".go") + var content string if _, err := os.Stat(modelPath); err == nil { ColorLog("[INFO] Using matching model '%s'\n", controllerName) content = strings.Replace(controllerModelTpl, "{{packageName}}", packageName, -1) - pkgPath := getPackagePath(crupath) + pkgPath := getPackagePath(currpath) content = strings.Replace(content, "{{pkgPath}}", pkgPath, -1) } else { content = strings.Replace(controllerTpl, "{{packageName}}", packageName, -1) } + content = strings.Replace(content, "{{controllerName}}", controllerName, -1) f.WriteString(content) - // gofmt generated source code + + // Run 'gofmt' on the generated source code formatSourceCode(fpath) - fmt.Println("\tcreate\t", fpath) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") } else { - // error creating file ColorLog("[ERRO] Could not create controller file: %s\n", err) os.Exit(2) } diff --git a/g_hproseappcode.go b/g_hproseappcode.go index 7dda6ce..89ae1b2 100644 --- a/g_hproseappcode.go +++ b/g_hproseappcode.go @@ -19,12 +19,12 @@ package main import ( "database/sql" + "fmt" + _ "github.com/go-sql-driver/mysql" + _ "github.com/lib/pq" "os" "path" "strings" - - _ "github.com/go-sql-driver/mysql" - _ "github.com/lib/pq" ) func generateHproseAppcode(driver, connStr, level, tables, currpath string) { @@ -98,6 +98,8 @@ func writeHproseSourceFiles(pkgPath string, tables []*Table, mode byte, paths *M // writeHproseModelFiles generates model files func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[string]bool) { + w := NewColorWriter(os.Stdout) + for _, tb := range tables { // if selectedTables map is not nil and this table is not selected, ignore it if selectedTables != nil { @@ -110,7 +112,7 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str var f *os.File var err error if isExist(fpath) { - ColorLog("[WARN] %v is exist, do you want to overwrite it? Yes or No?\n", fpath) + ColorLog("[WARN] '%v' already exists. Do you want to overwrite it? [Yes|No] ", fpath) if askForConfirmation() { f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666) if err != nil { @@ -118,7 +120,7 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str continue } } else { - ColorLog("[WARN] skip create file\n") + ColorLog("[WARN] Skipped create file '%s'\n", fpath) continue } } else { @@ -147,11 +149,11 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str fileStr = strings.Replace(fileStr, "{{timePkg}}", timePkg, -1) fileStr = strings.Replace(fileStr, "{{importTimePkg}}", importTimePkg, -1) if _, err := f.WriteString(fileStr); err != nil { - ColorLog("[ERRO] Could not write model file to %s\n", fpath) + ColorLog("[ERRO] Could not write model file to '%s'\n", fpath) os.Exit(2) } - f.Close() - ColorLog("[INFO] model => %s\n", fpath) + CloseFile(f) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") formatSourceCode(fpath) } } diff --git a/g_migration.go b/g_migration.go index d26211c..4135ebe 100644 --- a/g_migration.go +++ b/g_migration.go @@ -23,7 +23,7 @@ import ( ) const ( - MPath = "migrations" + MPath = "migrations" MDateFormat = "20060102_150405" ) @@ -31,6 +31,8 @@ const ( // The generated file template consists of an up() method for updating schema and // a down() method for reverting the update. func generateMigration(mname, upsql, downsql, curpath string) { + w := NewColorWriter(os.Stdout) + migrationFilePath := path.Join(curpath, "database", MPath) if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) { // create migrations directory @@ -43,17 +45,16 @@ func generateMigration(mname, upsql, downsql, curpath string) { today := time.Now().Format(MDateFormat) fpath := path.Join(migrationFilePath, fmt.Sprintf("%s_%s.go", today, mname)) if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { - defer f.Close() + defer CloseFile(f) content := strings.Replace(MigrationTPL, "{{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 + // Run 'gofmt' on the generated source code formatSourceCode(fpath) - fmt.Println("\tcreate\t", fpath) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") } else { - // error creating file ColorLog("[ERRO] Could not create migration file: %s\n", err) os.Exit(2) } diff --git a/g_model.go b/g_model.go index 5c5ce37..9987d47 100644 --- a/g_model.go +++ b/g_model.go @@ -1,3 +1,17 @@ +// Copyright 2013 bee authors +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + package main import ( @@ -8,7 +22,9 @@ import ( "strings" ) -func generateModel(mname, fields, crupath string) { +func generateModel(mname, fields, currpath string) { + w := NewColorWriter(os.Stdout) + p, f := path.Split(mname) modelName := strings.Title(f) packageName := "models" @@ -16,24 +32,28 @@ func generateModel(mname, fields, crupath string) { i := strings.LastIndex(p[:len(p)-1], "/") packageName = p[i+1 : len(p)-1] } + modelStruct, hastime, err := getStruct(modelName, fields) if err != nil { - ColorLog("[ERRO] Could not genrate models struct: %s\n", err) + ColorLog("[ERRO] Could not generate the model struct: %s\n", err) os.Exit(2) } + ColorLog("[INFO] Using '%s' as model name\n", modelName) ColorLog("[INFO] Using '%s' as package name\n", packageName) - fp := path.Join(crupath, "models", p) + + fp := path.Join(currpath, "models", p) if _, err := os.Stat(fp); os.IsNotExist(err) { - // create controller directory + // Create the model's directory if err := os.MkdirAll(fp, 0777); err != nil { - ColorLog("[ERRO] Could not create models directory: %s\n", err) + ColorLog("[ERRO] Could not create the model directory: %s\n", err) os.Exit(2) } } + fpath := path.Join(fp, strings.ToLower(modelName)+".go") if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { - defer f.Close() + defer CloseFile(f) content := strings.Replace(modelTpl, "{{packageName}}", packageName, -1) content = strings.Replace(content, "{{modelName}}", modelName, -1) content = strings.Replace(content, "{{modelStruct}}", modelStruct, -1) @@ -43,11 +63,10 @@ func generateModel(mname, fields, crupath string) { content = strings.Replace(content, "{{timePkg}}", "", -1) } f.WriteString(content) - // gofmt generated source code + // Run 'gofmt' on the generated source code formatSourceCode(fpath) - fmt.Println("\tcreate\t", fpath) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") } else { - // error creating file ColorLog("[ERRO] Could not create model file: %s\n", err) os.Exit(2) } @@ -55,23 +74,27 @@ func generateModel(mname, fields, crupath string) { func getStruct(structname, fields string) (string, bool, error) { if fields == "" { - return "", false, errors.New("fields can't empty") + return "", false, errors.New("fields cannot be empty") } + hastime := false structStr := "type " + structname + " struct{\n" fds := strings.Split(fields, ",") for i, v := range fds { kv := strings.SplitN(v, ":", 2) if len(kv) != 2 { - return "", false, errors.New("the filds format is wrong. should key:type,key:type " + v) + return "", false, errors.New("the fields format is wrong. Should be key:type,key:type " + v) } + typ, tag, hastimeinner := getType(kv[1]) if typ == "" { - return "", false, errors.New("the filds format is wrong. should key:type,key:type " + v) + return "", false, errors.New("the fields format is wrong. Should be key:type,key:type " + v) } + if i == 0 && strings.ToLower(kv[0]) != "id" { structStr = structStr + "Id int64 `orm:\"auto\"`\n" } + if hastimeinner { hastime = true } diff --git a/g_scaffold.go b/g_scaffold.go index ef9b13e..8222b57 100644 --- a/g_scaffold.go +++ b/g_scaffold.go @@ -5,25 +5,28 @@ import ( "strings" ) -func generateScaffold(sname, fields, crupath, driver, conn string) { - // generate model - ColorLog("[INFO] Do you want to create a %v model? [yes|no]] ", sname) +func generateScaffold(sname, fields, currpath, driver, conn string) { + ColorLog("[INFO] Do you want to create a '%v' model? [Yes|No] ", sname) + + // Generate the model if askForConfirmation() { - generateModel(sname, fields, crupath) + generateModel(sname, fields, currpath) } - // generate controller - ColorLog("[INFO] Do you want to create a %v controller? [yes|no]] ", sname) + // Generate the controller + ColorLog("[INFO] Do you want to create a '%v' controller? [Yes|No] ", sname) if askForConfirmation() { - generateController(sname, crupath) + generateController(sname, currpath) } - // generate view - ColorLog("[INFO] Do you want to create views for this %v resource? [yes|no]] ", sname) + + // Generate the views + ColorLog("[INFO] Do you want to create views for this '%v' resource? [Yes|No] ", sname) if askForConfirmation() { - generateView(sname, crupath) + generateView(sname, currpath) } - // generate migration - ColorLog("[INFO] Do you want to create a %v migration and schema for this resource? [yes|no]] ", sname) + + // Generate a migration + ColorLog("[INFO] Do you want to create a '%v' migration and schema for this resource? [Yes|No] ", sname) if askForConfirmation() { upsql := "" downsql := "" @@ -34,12 +37,13 @@ func generateScaffold(sname, fields, crupath, driver, conn string) { downsql = strings.Replace(downsql, "`", "", -1) } } - generateMigration(sname, upsql, downsql, crupath) + generateMigration(sname, upsql, downsql, currpath) } - // run migration - ColorLog("[INFO] Do you want to migrate the database? [yes|no]] ") + + // Run the migration + ColorLog("[INFO] Do you want to migrate the database? [Yes|No] ") if askForConfirmation() { - migrateUpdate(crupath, driver, conn) + migrateUpdate(currpath, driver, conn) } ColorLog("[INFO] All done! Don't forget to add beego.Router(\"/%v\" ,&controllers.%vController{}) to routers/route.go\n", sname, strings.Title(sname)) } diff --git a/g_views.go b/g_views.go index 47c252c..c078223 100644 --- a/g_views.go +++ b/g_views.go @@ -1,49 +1,74 @@ +// Copyright 2013 bee authors +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + package main import ( + "fmt" "os" "path" - "fmt" ) // recipe // admin/recipe -func generateView(vpath, crupath string) { +func generateView(viewpath, currpath string) { + w := NewColorWriter(os.Stdout) + ColorLog("[INFO] Generating view...\n") - absvpath := path.Join(crupath, "views", vpath) - os.MkdirAll(absvpath, os.ModePerm) - cfile := path.Join(absvpath, "index.tpl") + + absViewPath := path.Join(currpath, "views", viewpath) + err := os.MkdirAll(absViewPath, os.ModePerm) + if err != nil { + ColorLog("[ERRO] Could not create '%s' view: %s\n", viewpath, err) + os.Exit(2) + } + + cfile := path.Join(absViewPath, "index.tpl") if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { - defer f.Close() + defer CloseFile(f) f.WriteString(cfile) - fmt.Println("\tcreate\t", cfile) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m") } else { ColorLog("[ERRO] Could not create view file: %s\n", err) os.Exit(2) } - cfile = path.Join(absvpath, "show.tpl") + + cfile = path.Join(absViewPath, "show.tpl") if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { - defer f.Close() + defer CloseFile(f) f.WriteString(cfile) - fmt.Println("\tcreate\t", cfile) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m") } else { ColorLog("[ERRO] Could not create view file: %s\n", err) os.Exit(2) } - cfile = path.Join(absvpath, "create.tpl") + + cfile = path.Join(absViewPath, "create.tpl") if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { - defer f.Close() + defer CloseFile(f) f.WriteString(cfile) - fmt.Println("\tcreate\t", cfile) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m") } else { ColorLog("[ERRO] Could not create view file: %s\n", err) os.Exit(2) } - cfile = path.Join(absvpath, "edit.tpl") + + cfile = path.Join(absViewPath, "edit.tpl") if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { - defer f.Close() + defer CloseFile(f) f.WriteString(cfile) - fmt.Println("\tcreate\t", cfile) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m") } else { ColorLog("[ERRO] Could not create view file: %s\n", err) os.Exit(2) diff --git a/hproseapp.go b/hproseapp.go index 8200de6..e6f7e1c 100644 --- a/hproseapp.go +++ b/hproseapp.go @@ -28,7 +28,7 @@ var cmdHproseapp = &Command{ // CustomFlags: true, UsageLine: "hprose [appname]", Short: "create an rpc application use hprose base on beego framework", - Long: ` + Long: ` create an rpc application use hprose base on beego framework bee hprose [appname] [-tables=""] [-driver=mysql] [-conn=root:@tcp(127.0.0.1:3306)/test] @@ -37,7 +37,7 @@ bee hprose [appname] [-tables=""] [-driver=mysql] [-conn=root:@tcp(127.0.0.1:330 -conn: the connection string used by the driver, the default is '' e.g. for mysql: root:@tcp(127.0.0.1:3306)/test e.g. for postgres: postgres://postgres:postgres@127.0.0.1:5432/postgres - + if conn is empty will create a example rpc application. otherwise generate rpc application use hprose based on an existing database. In the current path, will create a folder named [appname] @@ -257,6 +257,8 @@ func init() { func createhprose(cmd *Command, args []string) int { ShowShortVersionBanner() + w := NewColorWriter(os.Stdout) + curpath, _ := os.Getwd() if len(args) > 1 { cmd.Flag.Parse(args[1:]) @@ -275,10 +277,10 @@ func createhprose(cmd *Command, args []string) int { ColorLog("[INFO] Creating Hprose application...\n") os.MkdirAll(apppath, 0755) - fmt.Println("\tcreate\t", apppath) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m") os.Mkdir(path.Join(apppath, "conf"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "conf")) - fmt.Println("\tcreate\t", path.Join(apppath, "conf", "app.conf")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf"), "\x1b[0m") + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m") WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(hproseconf, "{{.Appname}}", args[0], -1)) @@ -287,7 +289,7 @@ func createhprose(cmd *Command, args []string) int { ColorLog("[INFO] Using '%s' as 'conn'\n", conn) ColorLog("[INFO] Using '%s' as 'tables'\n", tables) generateHproseAppcode(string(driver), string(conn), "1", string(tables), path.Join(curpath, args[0])) - fmt.Println("\tcreate\t", path.Join(apppath, "main.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m") maingoContent := strings.Replace(hproseMainconngo, "{{.Appname}}", packpath, -1) maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(driver), -1) maingoContent = strings.Replace(maingoContent, "{{HproseFunctionList}}", strings.Join(hproseAddFunctions, ""), -1) @@ -306,15 +308,15 @@ func createhprose(cmd *Command, args []string) int { ) } else { os.Mkdir(path.Join(apppath, "models"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "models")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models"), "\x1b[0m") - fmt.Println("\tcreate\t", path.Join(apppath, "models", "object.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "object.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "models", "object.go"), apiModels) - fmt.Println("\tcreate\t", path.Join(apppath, "models", "user.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "user.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "models", "user.go"), apiModels2) - fmt.Println("\tcreate\t", path.Join(apppath, "main.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "main.go"), strings.Replace(hproseMaingo, "{{.Appname}}", packpath, -1)) } diff --git a/migrate.go b/migrate.go index 0661ae1..67f00ac 100644 --- a/migrate.go +++ b/migrate.go @@ -299,7 +299,7 @@ func writeMigrationSourceFile(dir, source, driver, connStr string, latestTime in ColorLog("[ERRO] Could not write to file: %s\n", err) os.Exit(2) } - f.Close() + CloseFile(f) } } diff --git a/new.go b/new.go index 3a7e87c..c395f69 100644 --- a/new.go +++ b/new.go @@ -57,6 +57,8 @@ func init() { func createApp(cmd *Command, args []string) int { ShowShortVersionBanner() + w := NewColorWriter(os.Stdout) + if len(args) != 1 { ColorLog("[ERRO] Argument [appname] is missing\n") os.Exit(2) @@ -75,7 +77,7 @@ func createApp(cmd *Command, args []string) int { if isExist(apppath) { ColorLog("[ERRO] Path (%s) already exists\n", apppath) - ColorLog("[WARN] Do you want to overwrite it? [yes|no]]") + ColorLog("[WARN] Do you want to overwrite it? [Yes|No] ") if !askForConfirmation() { os.Exit(2) } @@ -84,43 +86,43 @@ func createApp(cmd *Command, args []string) int { ColorLog("[INFO] Creating application...\n") os.MkdirAll(apppath, 0755) - fmt.Println("\tcreate\t", apppath + string(path.Separator)) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath+string(path.Separator), "\x1b[0m") os.Mkdir(path.Join(apppath, "conf"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "conf") + string(path.Separator)) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf")+string(path.Separator), "\x1b[0m") os.Mkdir(path.Join(apppath, "controllers"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "controllers") + string(path.Separator)) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers")+string(path.Separator), "\x1b[0m") os.Mkdir(path.Join(apppath, "models"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "models") + string(path.Separator)) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models")+string(path.Separator), "\x1b[0m") os.Mkdir(path.Join(apppath, "routers"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "routers") + string(path.Separator)) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers")+string(path.Separator), "\x1b[0m") os.Mkdir(path.Join(apppath, "tests"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "tests") + string(path.Separator)) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests")+string(path.Separator), "\x1b[0m") os.Mkdir(path.Join(apppath, "static"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "static") + string(path.Separator)) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static")+string(path.Separator), "\x1b[0m") os.Mkdir(path.Join(apppath, "static", "js"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "static", "js") + string(path.Separator)) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "js")+string(path.Separator), "\x1b[0m") os.Mkdir(path.Join(apppath, "static", "css"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "static", "css") + string(path.Separator)) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "css")+string(path.Separator), "\x1b[0m") os.Mkdir(path.Join(apppath, "static", "img"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "static", "img") + string(path.Separator)) - fmt.Println("\tcreate\t", path.Join(apppath, "views") + string(path.Separator)) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "img")+string(path.Separator), "\x1b[0m") + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views")+string(path.Separator), "\x1b[0m") os.Mkdir(path.Join(apppath, "views"), 0755) - fmt.Println("\tcreate\t", path.Join(apppath, "conf", "app.conf")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m") WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(appconf, "{{.Appname}}", path.Base(args[0]), -1)) - fmt.Println("\tcreate\t", path.Join(apppath, "controllers", "default.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "default.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "controllers", "default.go"), controllers) - fmt.Println("\tcreate\t", path.Join(apppath, "views", "index.tpl")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views", "index.tpl"), "\x1b[0m") WriteToFile(path.Join(apppath, "views", "index.tpl"), indextpl) - fmt.Println("\tcreate\t", path.Join(apppath, "routers", "router.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(router, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1)) - fmt.Println("\tcreate\t", path.Join(apppath, "tests", "default_test.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests", "default_test.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(test, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1)) - fmt.Println("\tcreate\t", path.Join(apppath, "main.go")) + fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1)) ColorLog("[SUCC] New application successfully created!\n") @@ -309,9 +311,10 @@ var indextpl = ` ` +// WriteToFile creates a file and writes content to it func WriteToFile(filename, content string) { f, err := os.Create(filename) - defer f.Close() + defer CloseFile(f) if err != nil { panic(err) } diff --git a/pack.go b/pack.go index db2978c..bdf3581 100644 --- a/pack.go +++ b/pack.go @@ -72,6 +72,7 @@ var ( buildEnvs ListOpts verbose bool format string + w io.Writer ) type ListOpts []string @@ -101,6 +102,7 @@ func init() { fs.BoolVar(&verbose, "v", false, "verbose") cmdPack.Flag = *fs cmdPack.Run = packApp + w = NewColorWriter(os.Stdout) } func exitPrint(con string) { @@ -242,7 +244,7 @@ func (wft *walkFileTree) walkLeaf(fpath string, fi os.FileInfo, err error) error if added, err := wft.wak.compress(name, fpath, fi); added { if verbose { - fmt.Printf("\t+ Compressed: %s\n", name) + fmt.Fprintf(w, "\t%s%scompressed%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", name, "\x1b[0m") } wft.allfiles[name] = true return err @@ -338,7 +340,7 @@ func (wft *tarWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) { if err != nil { return false, err } - defer fr.Close() + defer CloseFile(fr) _, err = io.Copy(tw, fr) if err != nil { return false, err @@ -374,7 +376,7 @@ func (wft *zipWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) { if err != nil { return false, err } - defer fr.Close() + defer CloseFile(fr) _, err = io.Copy(w, fr) if err != nil { return false, err @@ -559,7 +561,7 @@ func packApp(cmd *Command, args []string) int { } if verbose { - fmt.Println("\t+ go", strings.Join(args, " ")) + fmt.Fprintf(w, "\t%s%s+ go %s%s%s\n", "\x1b[32m", "\x1b[1m", strings.Join(args, " "), "\x1b[21m", "\x1b[0m") } execmd := exec.Command("go", args...) diff --git a/util.go b/util.go index 0f314df..43a29c5 100644 --- a/util.go +++ b/util.go @@ -258,3 +258,11 @@ func (s *strFlags) Set(value string) error { *s = append(*s, value) return nil } + +// CloseFile attempts to close the passed file +// or panics with the actual error +func CloseFile(f *os.File) { + if err := f.Close(); err != nil { + panic(err) + } +} From 083fa9fd4b0947fb223da7c93c9c137df03c1ea6 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 1 Aug 2016 14:40:43 +0800 Subject: [PATCH 074/123] swagger 2 --- fix.go | 2 +- g_docs.go | 125 ++++++++++++++---------------------------------------- 2 files changed, 33 insertions(+), 94 deletions(-) diff --git a/fix.go b/fix.go index 855fc0a..b4dbd39 100644 --- a/fix.go +++ b/fix.go @@ -72,7 +72,7 @@ var rules = []string{ "beego.HttpsPort", "beego.BConfig.Listen.HTTPSPort", "beego.HttpCertFile", "beego.BConfig.Listen.HTTPSCertFile", "beego.HttpKeyFile", "beego.BConfig.Listen.HTTPSKeyFile", - "beego.EnableAdmin", "beego.BConfig.Listen.AdminEnable", + "beego.EnableAdmin", "beego.BConfig.Listen.EnableAdmin", "beego.AdminHttpAddr", "beego.BConfig.Listen.AdminAddr", "beego.AdminHttpPort", "beego.BConfig.Listen.AdminPort", "beego.UseFcgi", "beego.BConfig.Listen.EnableFcgi", diff --git a/g_docs.go b/g_docs.go index 229540a..388cc2f 100644 --- a/g_docs.go +++ b/g_docs.go @@ -35,63 +35,6 @@ import ( "github.com/astaxie/beego/utils" ) -var globalDocsTemplate = `package docs - -import ( - "encoding/json" - "strings" - - "github.com/astaxie/beego" - "github.com/astaxie/beego/swagger" -) - -const ( - Rootinfo string = {{.rootinfo}} - Subapi string = {{.subapi}} - BasePath string= "{{.version}}" -) - -var rootapi swagger.ResourceListing -var apilist map[string]*swagger.APIDeclaration - -func init() { - if beego.BConfig.WebConfig.EnableDocs { - err := json.Unmarshal([]byte(Rootinfo), &rootapi) - if err != nil { - beego.Error(err) - } - err = json.Unmarshal([]byte(Subapi), &apilist) - if err != nil { - beego.Error(err) - } - beego.GlobalDocAPI["Root"] = rootapi - for k, v := range apilist { - for i, a := range v.APIs { - a.Path = urlReplace(k + a.Path) - v.APIs[i] = a - } - v.BasePath = BasePath - beego.GlobalDocAPI[strings.Trim(k, "/")] = v - } - } -} - - -func urlReplace(src string) string { - pt := strings.Split(src, "/") - for i, p := range pt { - if len(p) > 0 { - if p[0] == ':' { - pt[i] = "{" + p[1:] + "}" - } else if p[0] == '?' && p[1] == ':' { - pt[i] = "{" + p[2:] + "}" - } - } - } - return strings.Join(pt, "/") -} -` - const ( ajson = "application/json" axml = "application/xml" @@ -99,21 +42,19 @@ const ( ahtml = "text/html" ) -var pkgCache map[string]bool //pkg:controller:function:comments comments: key:value +var pkgCache map[string]struct{} //pkg:controller:function:comments comments: key:value var controllerComments map[string]string var importlist map[string]string -var apilist map[string]*swagger.APIDeclaration -var controllerList map[string][]swagger.API -var modelsList map[string]map[string]swagger.Model -var rootapi swagger.ResourceListing +var controllerList map[string]map[string]swagger.Item //controllername Paths items +var modelsList map[string]map[string]swagger.Schema +var rootapi swagger.Swagger func init() { - pkgCache = make(map[string]bool) + pkgCache = make(map[string]struct{}) controllerComments = make(map[string]string) importlist = make(map[string]string) - apilist = make(map[string]*swagger.APIDeclaration) - controllerList = make(map[string][]swagger.API) - modelsList = make(map[string]map[string]swagger.Model) + controllerList = make(map[string]map[string]swagger.Item) + modelsList = make(map[string]map[string]swagger.Schema) } func generateDocs(curpath string) { @@ -126,26 +67,26 @@ func generateDocs(curpath string) { os.Exit(2) } - rootapi.Info = swagger.Information{} - rootapi.SwaggerVersion = swagger.SwaggerVersion + rootapi.Infos = swagger.Information{} + rootapi.SwaggerVersion = "2.0" //analysis API comments if f.Comments != nil { for _, c := range f.Comments { for _, s := range strings.Split(c.Text(), "\n") { if strings.HasPrefix(s, "@APIVersion") { - rootapi.APIVersion = strings.TrimSpace(s[len("@APIVersion"):]) + rootapi.Infos.Version = strings.TrimSpace(s[len("@APIVersion"):]) } else if strings.HasPrefix(s, "@Title") { - rootapi.Info.Title = strings.TrimSpace(s[len("@Title"):]) + rootapi.Infos.Title = strings.TrimSpace(s[len("@Title"):]) } else if strings.HasPrefix(s, "@Description") { - rootapi.Info.Description = strings.TrimSpace(s[len("@Description"):]) + rootapi.Infos.Description = strings.TrimSpace(s[len("@Description"):]) } else if strings.HasPrefix(s, "@TermsOfServiceUrl") { - rootapi.Info.TermsOfServiceURL = strings.TrimSpace(s[len("@TermsOfServiceUrl"):]) + rootapi.Infos.TermsOfServiceURL = strings.TrimSpace(s[len("@TermsOfServiceUrl"):]) } else if strings.HasPrefix(s, "@Contact") { - rootapi.Info.Contact = strings.TrimSpace(s[len("@Contact"):]) + rootapi.Infos.Contact.EMail = strings.TrimSpace(s[len("@Contact"):]) } else if strings.HasPrefix(s, "@License") { - rootapi.Info.License = strings.TrimSpace(s[len("@License"):]) + rootapi.Infos.License.Name = strings.TrimSpace(s[len("@License"):]) } else if strings.HasPrefix(s, "@LicenseUrl") { - rootapi.Info.LicenseURL = strings.TrimSpace(s[len("@LicenseUrl"):]) + rootapi.Infos.License.URL = strings.TrimSpace(s[len("@LicenseUrl"):]) } } } @@ -198,23 +139,17 @@ func generateDocs(curpath string) { } } } - apiinfo, err := json.Marshal(rootapi) - if err != nil { - panic(err) - } - subapi, err := json.Marshal(apilist) - if err != nil { - panic(err) - } - os.Mkdir(path.Join(curpath, "docs"), 0755) - fd, err := os.Create(path.Join(curpath, "docs", "docs.go")) + os.Mkdir(path.Join(curpath, "swagger"), 0755) + fd, err := os.Create(path.Join(curpath, "swagger", "swagger.json")) if err != nil { panic(err) } defer fd.Close() - a := strings.Replace(globalDocsTemplate, "{{.rootinfo}}", "`"+string(apiinfo)+"`", -1) - a = strings.Replace(a, "{{.subapi}}", "`"+string(subapi)+"`", -1) - fd.WriteString(a) + encode := json.NewEncoder(fd) + err = encode.Encode(rootapi) + if err != nil { + panic(err) + } } func analisysNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) { @@ -267,15 +202,15 @@ func analisyscontrollerPkg(localName, pkgpath string) { if isSystemPackage(pkgpath) { return } + if pkgpath == "github.com/astaxie/beego" { + return + } if localName != "" { importlist[localName] = pkgpath } else { pps := strings.Split(pkgpath, "/") importlist[pps[len(pps)-1]] = pkgpath } - if pkgpath == "github.com/astaxie/beego" { - return - } gopath := os.Getenv("GOPATH") if gopath == "" { panic("please set gopath") @@ -293,6 +228,8 @@ func analisyscontrollerPkg(localName, pkgpath string) { if pkgRealpath != "" { if _, ok := pkgCache[pkgpath]; ok { return + } else { + pkgCache[pkgpath] = struct{}{} } } else { ColorLog("[ERRO] the %s pkg not exist in gopath\n", pkgpath) @@ -315,15 +252,17 @@ func analisyscontrollerPkg(localName, pkgpath string) { case *ast.FuncDecl: if specDecl.Recv != nil && len(specDecl.Recv.List) > 0 { if t, ok := specDecl.Recv.List[0].Type.(*ast.StarExpr); ok { + // parse controller method parserComments(specDecl.Doc, specDecl.Name.String(), fmt.Sprint(t.X), pkgpath) } } case *ast.GenDecl: - if specDecl.Tok.String() == "type" { + if specDecl.Tok == token.TYPE { for _, s := range specDecl.Specs { switch tp := s.(*ast.TypeSpec).Type.(type) { case *ast.StructType: _ = tp.Struct + //parse controller definition comments controllerComments[pkgpath+s.(*ast.TypeSpec).Name.String()] = specDecl.Doc.Text() } } @@ -355,7 +294,7 @@ func isSystemPackage(pkgpath string) bool { // parse the func comments func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpath string) error { - innerapi := swagger.API{} + innerapi := swagger.Item{} opts := swagger.Operation{} if comments != nil && comments.List != nil { for _, c := range comments.List { From 6bf3ea614087c52ead8ca75259c5fd1226b361e2 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Mon, 1 Aug 2016 11:41:25 +0200 Subject: [PATCH 075/123] Fixed bug in color writer for Windows --- colorwriter_windows.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/colorwriter_windows.go b/colorwriter_windows.go index d257f54..0a8e88f 100644 --- a/colorwriter_windows.go +++ b/colorwriter_windows.go @@ -320,15 +320,15 @@ func parseEscapeSequence(command byte, param []byte) parseResult { } } -func (cw *ansiColorWriter) flushBuffer() (int, error) { +func (cw *colorWriter) flushBuffer() (int, error) { return cw.flushTo(cw.w) } -func (cw *ansiColorWriter) resetBuffer() (int, error) { +func (cw *colorWriter) resetBuffer() (int, error) { return cw.flushTo(nil) } -func (cw *ansiColorWriter) flushTo(w io.Writer) (int, error) { +func (cw *colorWriter) flushTo(w io.Writer) (int, error) { var n1, n2 int var err error @@ -359,7 +359,7 @@ func isParameterChar(b byte) bool { return ('0' <= b && b <= '9') || b == separatorChar } -func (cw *ansiColorWriter) Write(p []byte) (int, error) { +func (cw *colorWriter) Write(p []byte) (int, error) { r, nw, first, last := 0, 0, 0, 0 if cw.mode != DiscardNonColorEscSeq { cw.state = outsideCsiCode From 00e358fc03afcc049473230cf98f8f344e9793de Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Mon, 1 Aug 2016 11:42:16 +0200 Subject: [PATCH 076/123] Added support for multiple paths GOPATH --- apiapp.go | 17 ++++++++++------- g.go | 28 ++++++++++++++-------------- migrate.go | 41 +++++++++++++++++++++-------------------- new.go | 12 +++++++----- 4 files changed, 52 insertions(+), 46 deletions(-) diff --git a/apiapp.go b/apiapp.go index a30c739..3070aa4 100644 --- a/apiapp.go +++ b/apiapp.go @@ -647,19 +647,22 @@ func createapi(cmd *Command, args []string) int { } func checkEnv(appname string) (apppath, packpath string, err error) { - gopath := os.Getenv("GOPATH") - Debugf("gopath:%s", gopath) - if gopath == "" { - err = fmt.Errorf("you should set GOPATH in the env") - return + gps := GetGOPATHs() + if len(gps) == 0 { + ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty") + os.Exit(2) } + // In case of multiple paths in the GOPATH, by default + // we use the first path + gopath := gps[0] + Debugf("GOPATH: %s", gopath) gosrcpath := path.Join(gopath, "src") apppath = path.Join(gosrcpath, appname) if _, e := os.Stat(apppath); os.IsNotExist(e) == false { - err = fmt.Errorf("Cannot create application without removing `%s` first.", apppath) - ColorLog("[ERRO] Path `%s` already exists\n", apppath) + err = fmt.Errorf("Cannot create application without removing '%s' first.", apppath) + ColorLog("[ERRO] Path '%s' already exists\n", apppath) return } packpath = strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/") diff --git a/g.go b/g.go index 61716f8..3cccfbf 100644 --- a/g.go +++ b/g.go @@ -79,19 +79,19 @@ func init() { func generateCode(cmd *Command, args []string) int { ShowShortVersionBanner() - curpath, _ := os.Getwd() + currpath, _ := os.Getwd() if len(args) < 1 { ColorLog("[ERRO] command is missing\n") os.Exit(2) } - gopath := os.Getenv("GOPATH") - Debugf("gopath:%s", gopath) - if gopath == "" { - ColorLog("[ERRO] $GOPATH not found\n") - ColorLog("[HINT] Set $GOPATH in your environment vairables\n") + gps := GetGOPATHs() + if len(gps) == 0 { + ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty") os.Exit(2) } + gopath := gps[0] + Debugf("GOPATH: %s", gopath) gcmd := args[0] switch gcmd { @@ -124,9 +124,9 @@ func generateCode(cmd *Command, args []string) int { os.Exit(2) } sname := args[1] - generateScaffold(sname, fields.String(), curpath, driver.String(), conn.String()) + generateScaffold(sname, fields.String(), currpath, driver.String(), conn.String()) case "docs": - generateDocs(curpath) + generateDocs(currpath) case "appcode": // load config err := loadConfig() @@ -157,7 +157,7 @@ func generateCode(cmd *Command, args []string) int { ColorLog("[INFO] Using '%s' as 'conn'\n", conn) ColorLog("[INFO] Using '%s' as 'tables'\n", tables) 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(), currpath) case "migration": if len(args) < 2 { ColorLog("[ERRO] Wrong number of arguments\n") @@ -176,11 +176,11 @@ func generateCode(cmd *Command, args []string) int { downsql = strings.Replace(downsql, "`", "", -1) } } - generateMigration(mname, upsql, downsql, curpath) + generateMigration(mname, upsql, downsql, currpath) case "controller": if len(args) == 2 { cname := args[1] - generateController(cname, curpath) + generateController(cname, currpath) } else { ColorLog("[ERRO] Wrong number of arguments\n") ColorLog("[HINT] Usage: bee generate controller [controllername]\n") @@ -199,18 +199,18 @@ func generateCode(cmd *Command, args []string) int { os.Exit(2) } sname := args[1] - generateModel(sname, fields.String(), curpath) + generateModel(sname, fields.String(), currpath) case "view": if len(args) == 2 { cname := args[1] - generateView(cname, curpath) + generateView(cname, currpath) } else { ColorLog("[ERRO] Wrong number of arguments\n") ColorLog("[HINT] Usage: bee generate view [viewpath]\n") os.Exit(2) } default: - ColorLog("[ERRO] command is missing\n") + ColorLog("[ERRO] Command is missing\n") } ColorLog("[SUCC] %s successfully generated!\n", strings.Title(gcmd)) return 0 diff --git a/migrate.go b/migrate.go index 67f00ac..a32cc8e 100644 --- a/migrate.go +++ b/migrate.go @@ -64,15 +64,16 @@ func init() { func runMigration(cmd *Command, args []string) int { ShowShortVersionBanner() - crupath, _ := os.Getwd() + currpath, _ := os.Getwd() - gopath := os.Getenv("GOPATH") - Debugf("gopath:%s", gopath) - if gopath == "" { - ColorLog("[ERRO] $GOPATH not found\n") - ColorLog("[HINT] Set $GOPATH in your environment vairables\n") + gps := GetGOPATHs() + if len(gps) == 0 { + ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty") os.Exit(2) } + gopath := gps[0] + Debugf("GOPATH: %s", gopath) + // load config err := loadConfig() if err != nil { @@ -100,19 +101,19 @@ func runMigration(cmd *Command, args []string) int { if len(args) == 0 { // run all outstanding migrations ColorLog("[INFO] Running all outstanding migrations\n") - migrateUpdate(crupath, driverStr, connStr) + migrateUpdate(currpath, driverStr, connStr) } else { mcmd := args[0] switch mcmd { case "rollback": ColorLog("[INFO] Rolling back the last migration operation\n") - migrateRollback(crupath, driverStr, connStr) + migrateRollback(currpath, driverStr, connStr) case "reset": ColorLog("[INFO] Reseting all migrations\n") - migrateReset(crupath, driverStr, connStr) + migrateReset(currpath, driverStr, connStr) case "refresh": ColorLog("[INFO] Refreshing all migrations\n") - migrateRefresh(crupath, driverStr, connStr) + migrateRefresh(currpath, driverStr, connStr) default: ColorLog("[ERRO] Command is missing\n") os.Exit(2) @@ -123,28 +124,28 @@ func runMigration(cmd *Command, args []string) int { } // migrateUpdate does the schema update -func migrateUpdate(crupath, driver, connStr string) { - migrate("upgrade", crupath, driver, connStr) +func migrateUpdate(currpath, driver, connStr string) { + migrate("upgrade", currpath, driver, connStr) } // migrateRollback rolls back the latest migration -func migrateRollback(crupath, driver, connStr string) { - migrate("rollback", crupath, driver, connStr) +func migrateRollback(currpath, driver, connStr string) { + migrate("rollback", currpath, driver, connStr) } // migrateReset rolls back all migrations -func migrateReset(crupath, driver, connStr string) { - migrate("reset", crupath, driver, connStr) +func migrateReset(currpath, driver, connStr string) { + migrate("reset", currpath, driver, connStr) } // migrationRefresh rolls back all migrations and start over again -func migrateRefresh(crupath, driver, connStr string) { - migrate("refresh", crupath, driver, connStr) +func migrateRefresh(currpath, driver, connStr string) { + migrate("refresh", currpath, driver, connStr) } // migrate generates source code, build it, and invoke the binary who does the actual migration -func migrate(goal, crupath, driver, connStr string) { - dir := path.Join(crupath, "database", "migrations") +func migrate(goal, currpath, driver, connStr string) { + dir := path.Join(currpath, "database", "migrations") binary := "m" source := binary + ".go" // connect to database diff --git a/new.go b/new.go index c395f69..ccdc4f9 100644 --- a/new.go +++ b/new.go @@ -64,13 +64,15 @@ func createApp(cmd *Command, args []string) int { os.Exit(2) } - gopath := os.Getenv("GOPATH") - Debugf("gopath:%s", gopath) - if gopath == "" { - ColorLog("[ERRO] $GOPATH not found\n") - ColorLog("[HINT] Set $GOPATH in your environment variables\n") + gps := GetGOPATHs() + if len(gps) == 0 { + ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty") os.Exit(2) } + // In case of multiple paths in the GOPATH, by default + // we use the first path + gopath := gps[0] + Debugf("GOPATH: %s", gopath) gosrcpath := path.Join(gopath, "src") // User's workspace apppath := path.Join(gosrcpath, args[0]) From f1787c5beb473ac7296843f873bc3c693d34abea Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Mon, 1 Aug 2016 17:50:02 +0200 Subject: [PATCH 077/123] Reorganized imports --- g_appcode.go | 5 +++-- g_hproseappcode.go | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/g_appcode.go b/g_appcode.go index 522af6a..2c002b7 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -17,14 +17,15 @@ package main import ( "database/sql" "fmt" - _ "github.com/go-sql-driver/mysql" - _ "github.com/lib/pq" "os" "os/exec" "path" "path/filepath" "regexp" "strings" + + _ "github.com/go-sql-driver/mysql" + _ "github.com/lib/pq" ) const ( diff --git a/g_hproseappcode.go b/g_hproseappcode.go index 89ae1b2..171aab6 100644 --- a/g_hproseappcode.go +++ b/g_hproseappcode.go @@ -20,11 +20,12 @@ package main import ( "database/sql" "fmt" - _ "github.com/go-sql-driver/mysql" - _ "github.com/lib/pq" "os" "path" "strings" + + _ "github.com/go-sql-driver/mysql" + _ "github.com/lib/pq" ) func generateHproseAppcode(driver, connStr, level, tables, currpath string) { From d9f182c84f726bf70c05c1068230f1ba3735f64d Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 8 Aug 2016 16:44:49 +0800 Subject: [PATCH 078/123] bee support swagger2.0 --- g_docs.go | 185 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 117 insertions(+), 68 deletions(-) diff --git a/g_docs.go b/g_docs.go index befcb2e..1c48e04 100644 --- a/g_docs.go +++ b/g_docs.go @@ -45,7 +45,7 @@ const ( var pkgCache map[string]struct{} //pkg:controller:function:comments comments: key:value var controllerComments map[string]string var importlist map[string]string -var controllerList map[string]map[string]swagger.Item //controllername Paths items +var controllerList map[string]map[string]*swagger.Item //controllername Paths items var modelsList map[string]map[string]swagger.Schema var rootapi swagger.Swagger @@ -53,7 +53,7 @@ func init() { pkgCache = make(map[string]struct{}) controllerComments = make(map[string]string) importlist = make(map[string]string) - controllerList = make(map[string]map[string]swagger.Item) + controllerList = make(map[string]map[string]*swagger.Item) modelsList = make(map[string]map[string]swagger.Schema) } @@ -91,6 +91,7 @@ func generateDocs(curpath string) { } } } + // analisys controller package for _, im := range f.Imports { localName := "" if im.Name != nil { @@ -102,33 +103,41 @@ func generateDocs(curpath string) { switch specDecl := d.(type) { case *ast.FuncDecl: for _, l := range specDecl.Body.List { - switch smtp := l.(type) { + switch stmt := l.(type) { case *ast.AssignStmt: - for _, l := range smtp.Rhs { + for _, l := range stmt.Rhs { if v, ok := l.(*ast.CallExpr); ok { - f, params := analisysNewNamespace(v) - globalDocsTemplate = strings.Replace(globalDocsTemplate, "{{.version}}", f, -1) + // analisys NewNamespace, it will return version and the subfunction + version, params := analisysNewNamespace(v) + rootapi.BasePath = version for _, p := range params { switch pp := p.(type) { case *ast.CallExpr: + controllerName := "" if selname := pp.Fun.(*ast.SelectorExpr).Sel.String(); selname == "NSNamespace" { s, params := analisysNewNamespace(pp) - subapi := swagger.APIRef{Path: s} - controllerName := "" for _, sp := range params { switch pp := sp.(type) { case *ast.CallExpr: if pp.Fun.(*ast.SelectorExpr).Sel.String() == "NSInclude" { controllerName = analisysNSInclude(s, pp) + if v, ok := controllerComments[controllerName]; ok { + rootapi.Tags = append(rootapi.Tags, swagger.Tag{ + Name: s, + Description: v, + }) + } } } } - if v, ok := controllerComments[controllerName]; ok { - subapi.Description = v - } - rootapi.APIs = append(rootapi.APIs, subapi) } else if selname == "NSInclude" { - analisysNSInclude(f, pp) + controllerName = analisysNSInclude("", pp) + if v, ok := controllerComments[controllerName]; ok { + rootapi.Tags = append(rootapi.Tags, swagger.Tag{ + Name: controllerName, // if the NSInclude has no prefix, we use the controllername as the tag + Description: v, + }) + } } } } @@ -152,6 +161,7 @@ func generateDocs(curpath string) { } } +// return version and the others params func analisysNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) { for i, p := range ce.Args { if i == 0 { @@ -168,32 +178,45 @@ func analisysNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) { func analisysNSInclude(baseurl string, ce *ast.CallExpr) string { cname := "" - a := &swagger.APIDeclaration{} - a.APIVersion = rootapi.APIVersion - a.SwaggerVersion = swagger.SwaggerVersion - a.ResourcePath = baseurl - a.Produces = []string{"application/json", "application/xml", "text/plain", "text/html"} - a.APIs = make([]swagger.API, 0) - a.Models = make(map[string]swagger.Model) for _, p := range ce.Args { x := p.(*ast.UnaryExpr).X.(*ast.CompositeLit).Type.(*ast.SelectorExpr) if v, ok := importlist[fmt.Sprint(x.X)]; ok { cname = v + x.Sel.Name } if apis, ok := controllerList[cname]; ok { - if len(a.APIs) > 0 { - a.APIs = append(a.APIs, apis...) - } else { - a.APIs = apis - } - } - if models, ok := modelsList[cname]; ok { - for _, m := range models { - a.Models[m.ID] = m + for rt, item := range apis { + tag := "" + if baseurl != "" { + rt = "/" + baseurl + rt + tag = baseurl + } else { + tag = cname + } + if item.Get != nil { + item.Get.Tags = []string{tag} + } + if item.Post != nil { + item.Post.Tags = []string{tag} + } + if item.Put != nil { + item.Put.Tags = []string{tag} + } + if item.Patch != nil { + item.Patch.Tags = []string{tag} + } + if item.Head != nil { + item.Head.Tags = []string{tag} + } + if item.Delete != nil { + item.Delete.Tags = []string{tag} + } + if item.Options != nil { + item.Options.Tags = []string{tag} + } + rootapi.Paths[rt] = item } } } - apilist[baseurl] = a return cname } @@ -228,9 +251,8 @@ func analisyscontrollerPkg(localName, pkgpath string) { if pkgRealpath != "" { if _, ok := pkgCache[pkgpath]; ok { return - } else { - pkgCache[pkgpath] = struct{}{} } + pkgCache[pkgpath] = struct{}{} } else { ColorLog("[ERRO] the %s pkg not exist in gopath\n", pkgpath) os.Exit(1) @@ -263,7 +285,9 @@ func analisyscontrollerPkg(localName, pkgpath string) { case *ast.StructType: _ = tp.Struct //parse controller definition comments - controllerComments[pkgpath+s.(*ast.TypeSpec).Name.String()] = specDecl.Doc.Text() + if strings.TrimSpace(specDecl.Doc.Text()) != "" { + controllerComments[pkgpath+s.(*ast.TypeSpec).Name.String()] = specDecl.Doc.Text() + } } } } @@ -294,7 +318,8 @@ func isSystemPackage(pkgpath string) bool { // parse the func comments func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpath string) error { - innerapi := swagger.Item{} + var routerPath string + var HTTPMethod string opts := swagger.Operation{} if comments != nil && comments.List != nil { for _, c := range comments.List { @@ -305,20 +330,20 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat if len(e1) < 1 { return errors.New("you should has router infomation") } - innerapi.Path = e1[0] + routerPath = e1[0] if len(e1) == 2 && e1[1] != "" { e1 = strings.SplitN(e1[1], " ", 2) - opts.HTTPMethod = strings.ToUpper(strings.Trim(e1[0], "[]")) + HTTPMethod = strings.ToUpper(strings.Trim(e1[0], "[]")) } else { - opts.HTTPMethod = "GET" + HTTPMethod = "GET" } } else if strings.HasPrefix(t, "@Title") { - opts.Nickname = strings.TrimSpace(t[len("@Title"):]) + opts.OperationID = controllerName + "." + strings.TrimSpace(t[len("@Title"):]) } else if strings.HasPrefix(t, "@Description") { opts.Summary = strings.TrimSpace(t[len("@Description"):]) } else if strings.HasPrefix(t, "@Success") { ss := strings.TrimSpace(t[len("@Success"):]) - rs := swagger.ResponseMessage{} + rs := swagger.Response{} st := make([]string, 3) j := 0 var tmp []rune @@ -350,7 +375,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat if len(tmp) > 0 && st[2] == "" { st[2] = strings.TrimSpace(string(tmp)) } - rs.Message = st[2] + rs.Description = st[2] if st[1] == "{object}" { if st[2] == "" { panic(controllerName + " " + funcName + " has no object") @@ -358,16 +383,14 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat cmpath, m, mod, realTypes := getModel(st[2]) //ll := strings.Split(st[2], ".") //opts.Type = ll[len(ll)-1] - rs.ResponseModel = m + rs.Ref = "#/definitions/" + m if _, ok := modelsList[pkgpath+controllerName]; !ok { - modelsList[pkgpath+controllerName] = make(map[string]swagger.Model, 0) + modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema, 0) } modelsList[pkgpath+controllerName][st[2]] = mod appendModels(cmpath, pkgpath, controllerName, realTypes) } - - rs.Code, _ = strconv.Atoi(st[0]) - opts.ResponseMessages = append(opts.ResponseMessages, rs) + opts.Responses[st[0]] = rs } else if strings.HasPrefix(t, "@Param") { para := swagger.Parameter{} p := getparams(strings.TrimSpace(t[len("@Param "):])) @@ -375,9 +398,10 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat panic(controllerName + "_" + funcName + "'s comments @Param at least should has 4 params") } para.Name = p[0] - para.ParamType = p[1] + para.In = p[1] pp := strings.Split(p[2], ".") - para.DataType = pp[len(pp)-1] + //@TODO models.Objects need to ref + para.Type = pp[len(pp)-1] if len(p) > 4 { para.Required, _ = strconv.ParseBool(p[3]) para.Description = p[4] @@ -386,14 +410,14 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat } opts.Parameters = append(opts.Parameters, para) } else if strings.HasPrefix(t, "@Failure") { - rs := swagger.ResponseMessage{} + rs := swagger.Response{} st := strings.TrimSpace(t[len("@Failure"):]) var cd []rune var start bool for i, s := range st { if unicode.IsSpace(s) { if start { - rs.Message = strings.TrimSpace(st[i+1:]) + rs.Description = strings.TrimSpace(st[i+1:]) break } else { continue @@ -402,10 +426,9 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat start = true cd = append(cd, s) } - rs.Code, _ = strconv.Atoi(string(cd)) - opts.ResponseMessages = append(opts.ResponseMessages, rs) - } else if strings.HasPrefix(t, "@Type") { - opts.Type = strings.TrimSpace(t[len("@Type"):]) + opts.Responses[string(cd)] = rs + } else if strings.HasPrefix(t, "@Deprecated") { + opts.Deprecated, _ = strconv.ParseBool(strings.TrimSpace(t[len("@Deprecated"):])) } else if strings.HasPrefix(t, "@Accept") { accepts := strings.Split(strings.TrimSpace(strings.TrimSpace(t[len("@Accept"):])), ",") for _, a := range accepts { @@ -427,14 +450,35 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat } } } - innerapi.Operations = append(innerapi.Operations, opts) - if innerapi.Path != "" { - if _, ok := controllerList[pkgpath+controllerName]; ok { - controllerList[pkgpath+controllerName] = append(controllerList[pkgpath+controllerName], innerapi) + if routerPath != "" { + var item *swagger.Item + if itemList, ok := controllerList[pkgpath+controllerName]; ok { + if it, ok := itemList[routerPath]; !ok { + item = &swagger.Item{} + } else { + item = it + } } else { - controllerList[pkgpath+controllerName] = make([]swagger.API, 1) - controllerList[pkgpath+controllerName][0] = innerapi + controllerList[pkgpath+controllerName] = make(map[string]*swagger.Item) + item = &swagger.Item{} } + switch HTTPMethod { + case "GET": + item.Get = &opts + case "POST": + item.Post = &opts + case "PUT": + item.Put = &opts + case "PATCH": + item.Patch = &opts + case "DELETE": + item.Delete = &opts + case "Head": + item.Head = &opts + case "OPTIONS": + item.Options = &opts + } + controllerList[pkgpath+controllerName][routerPath] = item } return nil } @@ -470,7 +514,7 @@ func getparams(str string) []string { return r } -func getModel(str string) (pkgpath, objectname string, m swagger.Model, realTypes []string) { +func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTypes []string) { strs := strings.Split(str, ".") objectname = strs[len(strs)-1] pkgpath = strings.Join(strs[:len(strs)-1], "/") @@ -503,21 +547,25 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Model, realType if !ok { continue } - m.ID = k + m.Title = k if st.Fields.List != nil { - m.Properties = make(map[string]swagger.ModelProperty) + m.Properties = make(map[string]swagger.Propertie) for _, field := range st.Fields.List { isSlice, realType := typeAnalyser(field) realTypes = append(realTypes, realType) - mp := swagger.ModelProperty{} + mp := swagger.Propertie{} // add type slice if isSlice { + mp.Type = "array" + mp.Properties = make(map[string]swagger.Propertie) if isBasicType(realType) { - mp.Type = "[]" + realType + mp.Properties["items"] = swagger.Propertie{ + Type: realType, + } } else { - mp.Type = "array" - mp.Items = make(map[string]string) - mp.Items["$ref"] = realType + mp.Properties["items"] = swagger.Propertie{ + Ref: "#/definitions/" + realType, + } } } else { mp.Type = realType @@ -577,10 +625,11 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Model, realType } } } - if m.ID == "" { + if m.Title == "" { ColorLog("can't find the object: %v", str) os.Exit(1) } + rootapi.Definitions[objectname] = m return } From 743348ae1e88dd687935be71a3a62e5c9d7d82ac Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 8 Aug 2016 20:48:51 +0800 Subject: [PATCH 079/123] init the maps --- g_docs.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/g_docs.go b/g_docs.go index 1c48e04..a7488dd 100644 --- a/g_docs.go +++ b/g_docs.go @@ -213,6 +213,9 @@ func analisysNSInclude(baseurl string, ce *ast.CallExpr) string { if item.Options != nil { item.Options.Tags = []string{tag} } + if len(rootapi.Paths) == 0 { + rootapi.Paths = make(map[string]*swagger.Item) + } rootapi.Paths[rt] = item } } @@ -320,7 +323,9 @@ func isSystemPackage(pkgpath string) bool { func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpath string) error { var routerPath string var HTTPMethod string - opts := swagger.Operation{} + opts := swagger.Operation{ + Responses: make(map[string]swagger.Response), + } if comments != nil && comments.List != nil { for _, c := range comments.List { t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) From 0e240214addf6f611d555789adf5ebc084fabfbf Mon Sep 17 00:00:00 2001 From: astaxie Date: Sat, 13 Aug 2016 14:45:12 +0800 Subject: [PATCH 080/123] generator models --- g_docs.go | 57 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/g_docs.go b/g_docs.go index a7488dd..4ca27ae 100644 --- a/g_docs.go +++ b/g_docs.go @@ -80,7 +80,7 @@ func generateDocs(curpath string) { } else if strings.HasPrefix(s, "@Description") { rootapi.Infos.Description = strings.TrimSpace(s[len("@Description"):]) } else if strings.HasPrefix(s, "@TermsOfServiceUrl") { - rootapi.Infos.TermsOfServiceURL = strings.TrimSpace(s[len("@TermsOfServiceUrl"):]) + rootapi.Infos.TermsOfService = strings.TrimSpace(s[len("@TermsOfServiceUrl"):]) } else if strings.HasPrefix(s, "@Contact") { rootapi.Infos.Contact.EMail = strings.TrimSpace(s[len("@Contact"):]) } else if strings.HasPrefix(s, "@License") { @@ -154,8 +154,11 @@ func generateDocs(curpath string) { panic(err) } defer fd.Close() - encode := json.NewEncoder(fd) - err = encode.Encode(rootapi) + dt, err := json.MarshalIndent(rootapi, "", " ") + if err != nil { + panic(err) + } + _, err = fd.Write(dt) if err != nil { panic(err) } @@ -187,7 +190,7 @@ func analisysNSInclude(baseurl string, ce *ast.CallExpr) string { for rt, item := range apis { tag := "" if baseurl != "" { - rt = "/" + baseurl + rt + rt = baseurl + rt tag = baseurl } else { tag = cname @@ -388,7 +391,9 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat cmpath, m, mod, realTypes := getModel(st[2]) //ll := strings.Split(st[2], ".") //opts.Type = ll[len(ll)-1] - rs.Ref = "#/definitions/" + m + rs.Schema = &swagger.Schema{ + Ref: "#/definitions/" + m, + } if _, ok := modelsList[pkgpath+controllerName]; !ok { modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema, 0) } @@ -405,13 +410,22 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat para.Name = p[0] para.In = p[1] pp := strings.Split(p[2], ".") - //@TODO models.Objects need to ref - para.Type = pp[len(pp)-1] + typ := pp[len(pp)-1] + if len(pp) >= 2 { + para.Schema = &swagger.Schema{ + Ref: "#/definitions/" + typ, + } + } else { + if typ == "string" || typ == "number" || typ == "integer" || typ == "boolean" || + typ == "array" || typ == "file" { + para.Type = typ + } + } if len(p) > 4 { para.Required, _ = strconv.ParseBool(p[3]) - para.Description = p[4] + para.Description = strings.Trim(p[4], `" `) } else { - para.Description = p[3] + para.Description = strings.Trim(p[3], `" `) } opts.Parameters = append(opts.Parameters, para) } else if strings.HasPrefix(t, "@Failure") { @@ -478,7 +492,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat item.Patch = &opts case "DELETE": item.Delete = &opts - case "Head": + case "HEAD": item.Head = &opts case "OPTIONS": item.Options = &opts @@ -535,7 +549,7 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp ColorLog("[ERRO] the model %s parser.ParseDir error\n", str) os.Exit(1) } - + m.Type = "object" for _, pkg := range astPkgs { for _, fl := range pkg.Files { for k, d := range fl.Scope.Objects { @@ -625,7 +639,6 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp } } } - return } } } @@ -634,6 +647,9 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp ColorLog("can't find the object: %v", str) os.Exit(1) } + if len(rootapi.Definitions) == 0 { + rootapi.Definitions = make(map[string]swagger.Schema) + } rootapi.Definitions[objectname] = m return } @@ -668,14 +684,15 @@ func isBasicType(Type string) bool { } // refer to builtin.go -var basicTypes = []string{ - "bool", - "uint", "uint8", "uint16", "uint32", "uint64", - "int", "int8", "int16", "int32", "int64", - "float32", "float64", - "string", - "complex64", "complex128", - "byte", "rune", "uintptr", +var basicTypes = map[string]string{ + "bool": "boolean:", + "uint": "integer:int32", "uint8": "integer:int32", "uint16": "integer:int32", "uint32": "integer:int32", "uint64": "integer:int64", + "int": "integer:int64", "int8": "integer:int32", "int16:int32": "integer:int32", "int32": "integer:int32", "int64": "integer:int64", + "uintptr": "integer:int64", + "float32": "number:float", "float64": "number:double", + "string": "string:", + "complex64": "number:float", "complex128": "number:double", + "byte": "string:byte", "rune": "string:byte", } // regexp get json tag From 525d2b090179f36a8d2d59abd8b5b97cd49029e4 Mon Sep 17 00:00:00 2001 From: astaxie Date: Tue, 16 Aug 2016 23:32:13 +0800 Subject: [PATCH 081/123] support object ref model --- apiapp.go | 16 ++++++------- g_controllers.go | 6 ++--- g_docs.go | 61 ++++++++++++++++++++++++++++++++++-------------- 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/apiapp.go b/apiapp.go index 3070aa4..dda3a22 100644 --- a/apiapp.go +++ b/apiapp.go @@ -298,7 +298,7 @@ type ObjectController struct { beego.Controller } -// @Title create +// @Title Create // @Description create object // @Param body body models.Object true "The object content" // @Success 200 {string} models.Object.Id @@ -342,7 +342,7 @@ func (o *ObjectController) GetAll() { o.ServeJSON() } -// @Title update +// @Title Update // @Description update the object // @Param objectId path string true "The objectid you want to update" // @Param body body models.Object true "The body" @@ -363,7 +363,7 @@ func (o *ObjectController) Put() { o.ServeJSON() } -// @Title delete +// @Title Delete // @Description delete the object // @Param objectId path string true "The objectId you want to delete" // @Success 200 {string} delete success! @@ -391,7 +391,7 @@ type UserController struct { beego.Controller } -// @Title createUser +// @Title CreateUser // @Description create users // @Param body body models.User true "body for user content" // @Success 200 {int} models.User.Id @@ -405,7 +405,7 @@ func (u *UserController) Post() { u.ServeJSON() } -// @Title Get +// @Title GetAll // @Description get all Users // @Success 200 {object} models.User // @router / [get] @@ -434,7 +434,7 @@ func (u *UserController) Get() { u.ServeJSON() } -// @Title update +// @Title Update // @Description update the user // @Param uid path string true "The uid you want to update" // @Param body body models.User true "body for user content" @@ -456,7 +456,7 @@ func (u *UserController) Put() { u.ServeJSON() } -// @Title delete +// @Title Delete // @Description delete the user // @Param uid path string true "The uid you want to delete" // @Success 200 {string} delete success! @@ -469,7 +469,7 @@ func (u *UserController) Delete() { u.ServeJSON() } -// @Title login +// @Title Login // @Description Logs user into the system // @Param username query string true "The username for login" // @Param password query string true "The password for login" diff --git a/g_controllers.go b/g_controllers.go index 0345247..412abd9 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -95,7 +95,7 @@ func (c *{{controllerName}}Controller) URLMapping() { c.Mapping("Delete", c.Delete) } -// @Title Post +// @Title Create // @Description create {{controllerName}} // @Param body body models.{{controllerName}} true "body for {{controllerName}} content" // @Success 201 {object} models.{{controllerName}} @@ -105,7 +105,7 @@ func (c *{{controllerName}}Controller) Post() { } -// @Title Get +// @Title GetOne // @Description get {{controllerName}} by id // @Param id path string true "The key for staticblock" // @Success 200 {object} models.{{controllerName}} @@ -115,7 +115,7 @@ func (c *{{controllerName}}Controller) GetOne() { } -// @Title Get All +// @Title GetAll // @Description get {{controllerName}} // @Param query query string false "Filter. e.g. col1:v1,col2:v2 ..." // @Param fields query string false "Fields returned. e.g. col1,col2 ..." diff --git a/g_docs.go b/g_docs.go index 4ca27ae..71be086 100644 --- a/g_docs.go +++ b/g_docs.go @@ -123,7 +123,7 @@ func generateDocs(curpath string) { controllerName = analisysNSInclude(s, pp) if v, ok := controllerComments[controllerName]; ok { rootapi.Tags = append(rootapi.Tags, swagger.Tag{ - Name: s, + Name: strings.Trim(s, "/"), Description: v, }) } @@ -191,7 +191,7 @@ func analisysNSInclude(baseurl string, ce *ast.CallExpr) string { tag := "" if baseurl != "" { rt = baseurl + rt - tag = baseurl + tag = strings.Trim(baseurl, "/") } else { tag = cname } @@ -338,7 +338,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat if len(e1) < 1 { return errors.New("you should has router infomation") } - routerPath = e1[0] + routerPath = urlReplace(e1[0]) if len(e1) == 2 && e1[1] != "" { e1 = strings.SplitN(e1[1], " ", 2) HTTPMethod = strings.ToUpper(strings.Trim(e1[0], "[]")) @@ -570,7 +570,7 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp if st.Fields.List != nil { m.Properties = make(map[string]swagger.Propertie) for _, field := range st.Fields.List { - isSlice, realType := typeAnalyser(field) + isSlice, realType, sType := typeAnalyser(field) realTypes = append(realTypes, realType) mp := swagger.Propertie{} // add type slice @@ -578,8 +578,10 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp mp.Type = "array" mp.Properties = make(map[string]swagger.Propertie) if isBasicType(realType) { + typeFormat := strings.Split(sType, ":") mp.Properties["items"] = swagger.Propertie{ - Type: realType, + Type: typeFormat[0], + Format: typeFormat[1], } } else { mp.Properties["items"] = swagger.Propertie{ @@ -587,7 +589,13 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp } } } else { - mp.Type = realType + if isBasicType(realType) { + typeFormat := strings.Split(sType, ":") + mp.Type = typeFormat[0] + mp.Format = typeFormat[1] + } else if sType == "object" { + mp.Ref = "#/definitions/" + realType + } } // dont add property if anonymous field @@ -644,7 +652,7 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp } } if m.Title == "" { - ColorLog("can't find the object: %v", str) + ColorLog("can't find the object: %s", str) os.Exit(1) } if len(rootapi.Definitions) == 0 { @@ -654,31 +662,34 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp return } -func typeAnalyser(f *ast.Field) (isSlice bool, realType string) { +func typeAnalyser(f *ast.Field) (isSlice bool, realType, swaggerType string) { if arr, ok := f.Type.(*ast.ArrayType); ok { if isBasicType(fmt.Sprint(arr.Elt)) { - return false, fmt.Sprintf("[]%v", arr.Elt) + return false, fmt.Sprintf("[]%v", arr.Elt), basicTypes[fmt.Sprint(arr.Elt)] } if mp, ok := arr.Elt.(*ast.MapType); ok { - return false, fmt.Sprintf("map[%v][%v]", mp.Key, mp.Value) + return false, fmt.Sprintf("map[%v][%v]", mp.Key, mp.Value), "object" } if star, ok := arr.Elt.(*ast.StarExpr); ok { - return true, fmt.Sprint(star.X) + return true, fmt.Sprint(star.X), "object" } - return true, fmt.Sprint(arr.Elt) + return true, fmt.Sprint(arr.Elt), "object" } switch t := f.Type.(type) { case *ast.StarExpr: - return false, fmt.Sprint(t.X) + return false, fmt.Sprint(t.X), "object" + case *ast.MapType: + return false, fmt.Sprint(t.Value), "object" } - return false, fmt.Sprint(f.Type) + if k, ok := basicTypes[fmt.Sprint(f.Type)]; ok { + return false, fmt.Sprint(f.Type), k + } + return false, fmt.Sprint(f.Type), "object" } func isBasicType(Type string) bool { - for _, v := range basicTypes { - if v == Type { - return true - } + if _, ok := basicTypes[Type]; ok { + return true } return false } @@ -726,3 +737,17 @@ func appendModels(cmpath, pkgpath, controllerName string, realTypes []string) { } } } + +func urlReplace(src string) string { + pt := strings.Split(src, "/") + for i, p := range pt { + if len(p) > 0 { + if p[0] == ':' { + pt[i] = "{" + p[1:] + "}" + } else if p[0] == '?' && p[1] == ':' { + pt[i] = "{" + p[2:] + "}" + } + } + } + return strings.Join(pt, "/") +} From 20da95be6e6f1b324462623e750b1728830770b2 Mon Sep 17 00:00:00 2001 From: astaxie Date: Wed, 17 Aug 2016 00:52:57 +0800 Subject: [PATCH 082/123] update swagger links --- bee.go | 2 +- run.go | 21 +++++++++------- rundocs.go | 74 ++++++++++++++++++++++++++++++------------------------ 3 files changed, 54 insertions(+), 43 deletions(-) diff --git a/bee.go b/bee.go index 11f2352..28ae437 100644 --- a/bee.go +++ b/bee.go @@ -25,7 +25,7 @@ import ( "strings" ) -const version = "1.4.1" +const version = "1.5.0" type Command struct { // Run runs the command. diff --git a/run.go b/run.go index d4bc44a..b2f94da 100644 --- a/run.go +++ b/run.go @@ -120,7 +120,14 @@ func runApp(cmd *Command, args []string) int { files = append(files, arg) } } - + if downdoc == "true" { + if _, err := os.Stat(path.Join(currpath, "swagger", "index.html")); err != nil { + if os.IsNotExist(err) { + downloadFromURL(swaggerlink, "swagger.zip") + unzipAndDelete("swagger.zip") + } + } + } if gendoc == "true" { NewWatcher(paths, files, true) Autobuild(files, true) @@ -128,14 +135,7 @@ func runApp(cmd *Command, args []string) int { NewWatcher(paths, files, false) Autobuild(files, false) } - if downdoc == "true" { - if _, err := os.Stat(path.Join(currpath, "swagger")); err != nil { - if os.IsNotExist(err) { - downloadFromURL(swaggerlink, "swagger.zip") - unzipAndDelete("swagger.zip", "swagger") - } - } - } + for { select { case <-exit: @@ -155,6 +155,9 @@ func readAppDirectories(directory string, paths *[]string) { if strings.HasSuffix(fileInfo.Name(), "docs") { continue } + if strings.HasSuffix(fileInfo.Name(), "swagger") { + continue + } if !vendorWatch && strings.HasSuffix(fileInfo.Name(), "vendor") { continue diff --git a/rundocs.go b/rundocs.go index 70a1657..8c840af 100644 --- a/rundocs.go +++ b/rundocs.go @@ -20,7 +20,6 @@ import ( "log" "net/http" "os" - "path/filepath" ) var cmdRundocs = &Command{ @@ -33,8 +32,9 @@ var cmdRundocs = &Command{ `, } -const ( - swaggerlink = "https://github.com/beego/swagger/archive/v1.zip" +var ( + swaggerVersion = "2" + swaggerlink = "https://github.com/beego/swagger/archive/v" + swaggerVersion + ".zip" ) type docValue string @@ -60,7 +60,7 @@ func init() { func runDocs(cmd *Command, args []string) int { if isDownload == "true" { downloadFromURL(swaggerlink, "swagger.zip") - err := unzipAndDelete("swagger.zip", "swagger") + err := unzipAndDelete("swagger.zip") if err != nil { fmt.Println("has err exet unzipAndDelete", err) } @@ -78,33 +78,42 @@ func runDocs(cmd *Command, args []string) int { } func downloadFromURL(url, fileName string) { - fmt.Println("Downloading", url, "to", fileName) - - output, err := os.Create(fileName) - if err != nil { - fmt.Println("Error while creating", fileName, "-", err) + var down bool + if fd, err := os.Stat(fileName); err != nil && os.IsNotExist(err) { + down = true + } else if fd.Size() == int64(0) { + down = true + } else { + ColorLog("[%s] Filename %s already exist\n", INFO, fileName) return } - defer output.Close() + if down { + ColorLog("[%s]Downloading %s to %s\n", SUCC, url, fileName) + output, err := os.Create(fileName) + if err != nil { + ColorLog("[%s]Error while creating %s: %s\n", ERRO, fileName, err) + return + } + defer output.Close() - response, err := http.Get(url) - if err != nil { - fmt.Println("Error while downloading", url, "-", err) - return + response, err := http.Get(url) + if err != nil { + ColorLog("[%s]Error while downloading %s:%s\n", ERRO, url, err) + return + } + defer response.Body.Close() + + n, err := io.Copy(output, response.Body) + if err != nil { + ColorLog("[%s]Error while downloading %s:%s\n", ERRO, url, err) + return + } + ColorLog("[%s] %d bytes downloaded.\n", SUCC, n) } - defer response.Body.Close() - - n, err := io.Copy(output, response.Body) - if err != nil { - fmt.Println("Error while downloading", url, "-", err) - return - } - - fmt.Println(n, "bytes downloaded.") } -func unzipAndDelete(src, dest string) error { - fmt.Println("start to unzip file from " + src + " to " + dest) +func unzipAndDelete(src string) error { + ColorLog("[%s]start to unzip file from %s\n", INFO, src) r, err := zip.OpenReader(src) if err != nil { return err @@ -118,12 +127,11 @@ func unzipAndDelete(src, dest string) error { } defer rc.Close() - path := filepath.Join(dest, f.Name) if f.FileInfo().IsDir() { - os.MkdirAll(path, f.Mode()) + os.MkdirAll(f.Name, f.Mode()) } else { f, err := os.OpenFile( - path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) + f.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) if err != nil { return err } @@ -135,11 +143,11 @@ func unzipAndDelete(src, dest string) error { } } } - - fmt.Println("Start delete src file " + src) - err = os.RemoveAll(src) + os.RemoveAll("swagger") + err = os.Rename("swagger-"+swaggerVersion, "swagger") if err != nil { - return err + ColorLog("[%s]Rename swagger-%s to swagger:%s\n", ERRO, swaggerVersion, err) } - return nil + ColorLog("[%s]Start delete src file %s\n", INFO, src) + return os.RemoveAll(src) } From fd7742863d1bcd788d179a2cea1aa4bab559f139 Mon Sep 17 00:00:00 2001 From: astaxie Date: Wed, 17 Aug 2016 08:02:21 +0800 Subject: [PATCH 083/123] urlReplace all the paths --- g_docs.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/g_docs.go b/g_docs.go index 71be086..b8c06da 100644 --- a/g_docs.go +++ b/g_docs.go @@ -219,6 +219,7 @@ func analisysNSInclude(baseurl string, ce *ast.CallExpr) string { if len(rootapi.Paths) == 0 { rootapi.Paths = make(map[string]*swagger.Item) } + rt = urlReplace(rt) rootapi.Paths[rt] = item } } @@ -338,7 +339,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat if len(e1) < 1 { return errors.New("you should has router infomation") } - routerPath = urlReplace(e1[0]) + routerPath = e1[0] if len(e1) == 2 && e1[1] != "" { e1 = strings.SplitN(e1[1], " ", 2) HTTPMethod = strings.ToUpper(strings.Trim(e1[0], "[]")) From 11571b4af2add6c7b995fa87d7efe2f3e1e0fbe1 Mon Sep 17 00:00:00 2001 From: astaxie Date: Wed, 17 Aug 2016 23:48:38 +0800 Subject: [PATCH 084/123] fix beego#2016 --- g_docs.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/g_docs.go b/g_docs.go index b8c06da..005204d 100644 --- a/g_docs.go +++ b/g_docs.go @@ -413,9 +413,15 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat pp := strings.Split(p[2], ".") typ := pp[len(pp)-1] if len(pp) >= 2 { + cmpath, m, mod, realTypes := getModel(typ) para.Schema = &swagger.Schema{ - Ref: "#/definitions/" + typ, + Ref: "#/definitions/" + m, } + if _, ok := modelsList[pkgpath+controllerName]; !ok { + modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema, 0) + } + modelsList[pkgpath+controllerName][typ] = mod + appendModels(cmpath, pkgpath, controllerName, realTypes) } else { if typ == "string" || typ == "number" || typ == "integer" || typ == "boolean" || typ == "array" || typ == "file" { From ac1bf161fcbb3bd2b1fc6636111f6a0a16562aba Mon Sep 17 00:00:00 2001 From: tnextday Date: Thu, 18 Aug 2016 17:38:26 +0800 Subject: [PATCH 085/123] generate gocs support go buildin type in comment param --- g_docs.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/g_docs.go b/g_docs.go index 005204d..a2b5ce5 100644 --- a/g_docs.go +++ b/g_docs.go @@ -426,6 +426,12 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat if typ == "string" || typ == "number" || typ == "integer" || typ == "boolean" || typ == "array" || typ == "file" { para.Type = typ + } else if sType, ok := basicTypes[typ]; ok { + typeFormat := strings.Split(sType, ":") + para.Type = typeFormat[0] + para.Format = typeFormat[1] + }else { + fmt.Fprintf(os.Stderr, "[%s.%s] Unknow param type: %s\n", controllerName, funcName, typ) } } if len(p) > 4 { From 985c18a314b42bce903cced3811d9afdc0ba3cd0 Mon Sep 17 00:00:00 2001 From: tnextday Date: Thu, 18 Aug 2016 17:40:59 +0800 Subject: [PATCH 086/123] go format --- g_docs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/g_docs.go b/g_docs.go index a2b5ce5..b6d01c3 100644 --- a/g_docs.go +++ b/g_docs.go @@ -430,7 +430,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat typeFormat := strings.Split(sType, ":") para.Type = typeFormat[0] para.Format = typeFormat[1] - }else { + } else { fmt.Fprintf(os.Stderr, "[%s.%s] Unknow param type: %s\n", controllerName, funcName, typ) } } From c08afc129e0cb00d7bcd04b15ec5a9ca2e3a5c39 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Thu, 18 Aug 2016 12:58:36 +0300 Subject: [PATCH 087/123] Update g_docs.go Only you pass the model name, but do not pass the location. Although getModel() function again trying to split ( strs := strings.Split(str, ".") ) the parameter to the location and name. --- g_docs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/g_docs.go b/g_docs.go index 005204d..af93814 100644 --- a/g_docs.go +++ b/g_docs.go @@ -413,7 +413,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat pp := strings.Split(p[2], ".") typ := pp[len(pp)-1] if len(pp) >= 2 { - cmpath, m, mod, realTypes := getModel(typ) + cmpath, m, mod, realTypes := getModel(p[2]) para.Schema = &swagger.Schema{ Ref: "#/definitions/" + m, } From 07df26c7b6a68ccecf3d94c76b3d76a76a40b410 Mon Sep 17 00:00:00 2001 From: tnextday Date: Thu, 18 Aug 2016 18:21:23 +0800 Subject: [PATCH 088/123] add param location checker in generate gocs --- g_docs.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/g_docs.go b/g_docs.go index b6d01c3..0233650 100644 --- a/g_docs.go +++ b/g_docs.go @@ -409,7 +409,21 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat panic(controllerName + "_" + funcName + "'s comments @Param at least should has 4 params") } para.Name = p[0] - para.In = p[1] + switch p[1] { + case "query": + fallthrough + case "header": + fallthrough + case "path": + fallthrough + case "formData": + fallthrough + case "body": + para.In = p[1] + default: + fmt.Fprintf(os.Stderr, "[%s.%s] Unknow param location: %s, Possible values are `query`, `header`, `path`, `formData` or `body`.\n", controllerName, funcName, p[1]) + } + pp := strings.Split(p[2], ".") typ := pp[len(pp)-1] if len(pp) >= 2 { From 2f85185bcc1d5d6eeb86224a42138d5734fc4b37 Mon Sep 17 00:00:00 2001 From: tnextday Date: Thu, 18 Aug 2016 21:03:27 +0800 Subject: [PATCH 089/123] Print warnning only if param location is wrong --- g_docs.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/g_docs.go b/g_docs.go index 0233650..dc7be88 100644 --- a/g_docs.go +++ b/g_docs.go @@ -419,11 +419,11 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat case "formData": fallthrough case "body": - para.In = p[1] + break default: fmt.Fprintf(os.Stderr, "[%s.%s] Unknow param location: %s, Possible values are `query`, `header`, `path`, `formData` or `body`.\n", controllerName, funcName, p[1]) } - + para.In = p[1] pp := strings.Split(p[2], ".") typ := pp[len(pp)-1] if len(pp) >= 2 { From 3ccffe087e7dbca0d7bf46801f7e29696fd4f069 Mon Sep 17 00:00:00 2001 From: tnextday Date: Thu, 18 Aug 2016 21:30:57 +0800 Subject: [PATCH 090/123] update swagger array items define --- g_docs.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/g_docs.go b/g_docs.go index dc7be88..3199e13 100644 --- a/g_docs.go +++ b/g_docs.go @@ -603,17 +603,17 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp // add type slice if isSlice { mp.Type = "array" - mp.Properties = make(map[string]swagger.Propertie) if isBasicType(realType) { typeFormat := strings.Split(sType, ":") - mp.Properties["items"] = swagger.Propertie{ + mp.Items = []swagger.Propertie{{ Type: typeFormat[0], Format: typeFormat[1], - } + }} + } else { - mp.Properties["items"] = swagger.Propertie{ + mp.Items = []swagger.Propertie{{ Ref: "#/definitions/" + realType, - } + }} } } else { if isBasicType(realType) { From 4edf273341b17d85d3643a67cf9a81c801931a8a Mon Sep 17 00:00:00 2001 From: sunqida Date: Thu, 18 Aug 2016 22:27:59 +0800 Subject: [PATCH 091/123] =?UTF-8?q?=E5=85=BC=E5=AE=B9query=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E6=97=A5=E6=9C=9F=E3=80=81=E6=97=B6=E9=97=B4=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E3=80=82=E5=A6=82=EF=BC=9Aquery=3DxxTime.lt:2016-01-0?= =?UTF-8?q?1T23:22:21+08:00?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g_controllers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/g_controllers.go b/g_controllers.go index 412abd9..79ed554 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -255,7 +255,7 @@ func (c *{{controllerName}}Controller) GetAll() { // query: k:v,k:v if v := c.GetString("query"); v != "" { for _, cond := range strings.Split(v, ",") { - kv := strings.Split(cond, ":") + kv := strings.SplitN(cond, ":", 2) if len(kv) != 2 { c.Data["json"] = errors.New("Error: invalid query key/value pair") c.ServeJSON() From 1e247452fff6c25948882e4f4ce9c62c4460b62c Mon Sep 17 00:00:00 2001 From: tnextday Date: Thu, 18 Aug 2016 22:29:38 +0800 Subject: [PATCH 092/123] update swagger --- g_docs.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/g_docs.go b/g_docs.go index 3199e13..5a0a047 100644 --- a/g_docs.go +++ b/g_docs.go @@ -605,15 +605,15 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp mp.Type = "array" if isBasicType(realType) { typeFormat := strings.Split(sType, ":") - mp.Items = []swagger.Propertie{{ + mp.Items = &swagger.Propertie{ Type: typeFormat[0], Format: typeFormat[1], - }} + } } else { - mp.Items = []swagger.Propertie{{ + mp.Items = &swagger.Propertie{ Ref: "#/definitions/" + realType, - }} + } } } else { if isBasicType(realType) { From 424976201a4bd4a14825e5c943a34451f547d3fc Mon Sep 17 00:00:00 2001 From: sunqida Date: Thu, 18 Aug 2016 22:46:11 +0800 Subject: [PATCH 093/123] =?UTF-8?q?=E5=85=BC=E5=AE=B9query=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E6=97=A5=E6=9C=9F=E3=80=81=E6=97=B6=E9=97=B4=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E3=80=82=E5=A6=82=EF=BC=9Aquery=3DxxTime.lt:2016-01-0?= =?UTF-8?q?1T23:22:21+08:00?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g_controllers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/g_controllers.go b/g_controllers.go index 412abd9..79ed554 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -255,7 +255,7 @@ func (c *{{controllerName}}Controller) GetAll() { // query: k:v,k:v if v := c.GetString("query"); v != "" { for _, cond := range strings.Split(v, ",") { - kv := strings.Split(cond, ":") + kv := strings.SplitN(cond, ":", 2) if len(kv) != 2 { c.Data["json"] = errors.New("Error: invalid query key/value pair") c.ServeJSON() From cb064f68b78ed3ea931871cfdb5123ce5e50dec5 Mon Sep 17 00:00:00 2001 From: sunqida Date: Thu, 18 Aug 2016 23:25:18 +0800 Subject: [PATCH 094/123] =?UTF-8?q?=E5=85=BC=E5=AE=B9query=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E6=97=A5=E6=9C=9F=E3=80=81=E6=97=B6=E9=97=B4=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E3=80=82=E5=A6=82=EF=BC=9Aquery=3DxxTime.lt:2016-01-0?= =?UTF-8?q?1T23:22:21+08:00?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g_appcode.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/g_appcode.go b/g_appcode.go index 2c002b7..ac3718d 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -1262,7 +1262,7 @@ func (c *{{ctrlName}}Controller) GetAll() { // query: k:v,k:v if v := c.GetString("query"); v != "" { for _, cond := range strings.Split(v, ",") { - kv := strings.Split(cond, ":") + kv := strings.SplitN(cond, ":", 2) if len(kv) != 2 { c.Data["json"] = errors.New("Error: invalid query key/value pair") c.ServeJSON() From b160eb35b50b5bbfd7018bcb245c79628dffb2ed Mon Sep 17 00:00:00 2001 From: tnextday Date: Thu, 18 Aug 2016 23:31:09 +0800 Subject: [PATCH 095/123] Use first NewNamespace prefix as swagger `BasePath` --- g_docs.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/g_docs.go b/g_docs.go index 5a0a047..45ad67a 100644 --- a/g_docs.go +++ b/g_docs.go @@ -108,8 +108,13 @@ func generateDocs(curpath string) { for _, l := range stmt.Rhs { if v, ok := l.(*ast.CallExpr); ok { // analisys NewNamespace, it will return version and the subfunction + if selName := v.Fun.(*ast.SelectorExpr).Sel.String(); selName != "NewNamespace" { + continue + } version, params := analisysNewNamespace(v) - rootapi.BasePath = version + if rootapi.BasePath == "" && version != "" { + rootapi.BasePath = version + } for _, p := range params { switch pp := p.(type) { case *ast.CallExpr: From 3627eb2ddcb9f9f58d6c58d12bd5947f618051c0 Mon Sep 17 00:00:00 2001 From: Sergey Lanzman Date: Sat, 23 Jul 2016 21:05:44 +0300 Subject: [PATCH 096/123] refactor generate migration --- g.go | 8 +-- g_migration.go | 157 ++++++++++++++++++++++++++++++++++++++++++++++++- g_scaffold.go | 122 +++----------------------------------- 3 files changed, 166 insertions(+), 121 deletions(-) diff --git a/g.go b/g.go index 3cccfbf..bc4b123 100644 --- a/g.go +++ b/g.go @@ -170,11 +170,9 @@ func generateCode(cmd *Command, args []string) int { upsql := "" downsql := "" if fields != "" { - upsql = `m.SQL("CREATE TABLE ` + mname + "(" + generateSQLFromFields(fields.String()) + `)");` - downsql = `m.SQL("DROP TABLE ` + "`" + mname + "`" + `")` - if driver == "postgres" { - downsql = strings.Replace(downsql, "`", "", -1) - } + dbMigrator := newDBDriver() + upsql = dbMigrator.generateCreateUp(mname) + downsql = dbMigrator.generateCreateDown(mname) } generateMigration(mname, upsql, downsql, currpath) case "controller": diff --git a/g_migration.go b/g_migration.go index 4135ebe..c0485ef 100644 --- a/g_migration.go +++ b/g_migration.go @@ -25,15 +25,168 @@ import ( const ( MPath = "migrations" MDateFormat = "20060102_150405" + DBPath = "database" ) +type DBDriver interface { + generateCreateUp(tableName string) string + generateCreateDown(tableName string) string +} + +type mysqlDriver struct{} + +func (m mysqlDriver) generateCreateUp(tableName string) string { + upsql := `m.SQL("CREATE TABLE ` + tableName + "(" + m.generateSQLFromFields(fields.String()) + `)");` + return upsql +} + +func (m mysqlDriver) generateCreateDown(tableName string) string { + downsql := `m.SQL("DROP TABLE ` + "`" + tableName + "`" + `")` + return downsql +} + +func (m mysqlDriver) 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] Fields format is wrong. Should be: key:type,key:type " + v + "\n") + return "" + } + typ, tag := m.getSQLType(kv[1]) + if typ == "" { + ColorLog("[ERRO] Fields format is wrong. Should be: key:type,key:type " + v + "\n") + return "" + } + if i == 0 && strings.ToLower(kv[0]) != "id" { + sql += "`id` int(11) NOT NULL AUTO_INCREMENT," + tags = tags + "PRIMARY KEY (`id`)," + } + sql += "`" + snakeString(kv[0]) + "` " + typ + "," + if tag != "" { + tags = tags + fmt.Sprintf(tag, "`"+snakeString(kv[0])+"`") + "," + } + } + sql = strings.TrimRight(sql+tags, ",") + return sql +} + +func (m mysqlDriver) 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", "" + } + 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 "", "" +} + +type postgresqlDriver struct{} + +func (m postgresqlDriver) generateCreateUp(tableName string) string { + upsql := `m.SQL("CREATE TABLE ` + tableName + "(" + m.generateSQLFromFields(fields.String()) + `)");` + return upsql +} + +func (m postgresqlDriver) generateCreateDown(tableName string) string { + downsql := `m.SQL("DROP TABLE ` + tableName + `")` + return downsql +} + +func (m postgresqlDriver) 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] Fields format is wrong. Should be: key:type,key:type " + v + "\n") + return "" + } + typ, tag := m.getSQLType(kv[1]) + if typ == "" { + ColorLog("[ERRO] Fields format is wrong. Should be: key:type,key:type " + v + "\n") + return "" + } + if i == 0 && strings.ToLower(kv[0]) != "id" { + sql += "id interger serial primary key," + } + sql += snakeString(kv[0]) + " " + typ + "," + if tag != "" { + tags = tags + fmt.Sprintf(tag, snakeString(kv[0])) + "," + } + } + if tags != "" { + sql = strings.TrimRight(sql+" "+tags, ",") + } else { + sql = strings.TrimRight(sql, ",") + } + return sql +} + +func (m postgresqlDriver) getSQLType(ktype string) (tp, tag string) { + kv := strings.SplitN(ktype, ":", 2) + switch kv[0] { + case "string": + if len(kv) == 2 { + return "char(" + kv[1] + ") NOT NULL", "" + } + return "TEXT NOT NULL", "" + case "text": + return "TEXT NOT NULL", "" + case "auto", "pk": + return "serial primary key", "" + case "datetime": + return "TIMESTAMP WITHOUT TIME ZONE NOT NULL", "" + case "int", "int8", "int16", "int32", "int64": + fallthrough + case "uint", "uint8", "uint16", "uint32", "uint64": + return "integer DEFAULT NULL", "" + case "bool": + return "boolean NOT NULL", "" + case "float32", "float64", "float": + return "numeric NOT NULL", "" + } + return "", "" +} + +func newDBDriver() DBDriver { + switch driver { + case "mysql": + return mysqlDriver{} + case "postgres": + return postgresqlDriver{} + default: + panic("driver not supported") + } +} + // 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, upsql, downsql, curpath string) { w := NewColorWriter(os.Stdout) - - migrationFilePath := path.Join(curpath, "database", MPath) + migrationFilePath := path.Join(curpath, DBPath, MPath) if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) { // create migrations directory if err := os.MkdirAll(migrationFilePath, 0777); err != nil { diff --git a/g_scaffold.go b/g_scaffold.go index 8222b57..cccda16 100644 --- a/g_scaffold.go +++ b/g_scaffold.go @@ -1,9 +1,6 @@ package main -import ( - "fmt" - "strings" -) +import "strings" func generateScaffold(sname, fields, currpath, driver, conn string) { ColorLog("[INFO] Do you want to create a '%v' model? [Yes|No] ", sname) @@ -31,11 +28,13 @@ func generateScaffold(sname, fields, currpath, driver, conn string) { upsql := "" downsql := "" if fields != "" { - upsql = `m.SQL("CREATE TABLE ` + sname + "(" + generateSQLFromFields(fields) + `)");` - downsql = `m.SQL("DROP TABLE ` + "`" + sname + "`" + `")` - if driver == "" { - downsql = strings.Replace(downsql, "`", "", -1) - } + dbMigrator := newDBDriver() + upsql = dbMigrator.generateCreateUp(sname) + downsql = dbMigrator.generateCreateDown(sname) + //todo remove + //if driver == "" { + // downsql = strings.Replace(downsql, "`", "", -1) + //} } generateMigration(sname, upsql, downsql, currpath) } @@ -47,108 +46,3 @@ func generateScaffold(sname, fields, currpath, 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] Fields format is wrong. Should be: key:type,key:type " + v + "\n") - return "" - } - typ, tag := "", "" - switch driver { - case "mysql": - typ, tag = getSQLTypeMysql(kv[1]) - case "postgres": - typ, tag = getSQLTypePostgresql(kv[1]) - default: - typ, tag = getSQLTypeMysql(kv[1]) - } - if typ == "" { - ColorLog("[ERRO] Fields format is wrong. Should be: key:type,key:type " + v + "\n") - return "" - } - if i == 0 && strings.ToLower(kv[0]) != "id" { - switch driver { - case "mysql": - sql = sql + "`id` int(11) NOT NULL AUTO_INCREMENT," - tags = tags + "PRIMARY KEY (`id`)," - case "postgres": - sql = sql + "id interger serial primary key," - default: - 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])+"`") + "," - } - } - if driver == "postgres" { - sql = strings.Replace(sql, "`", "", -1) - tags = strings.Replace(tags, "`", "", -1) - } - sql = strings.TrimRight(sql+tags, ",") - return sql -} - -func getSQLTypeMysql(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", "" - } - 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 "", "" -} - -func getSQLTypePostgresql(ktype string) (tp, tag string) { - kv := strings.SplitN(ktype, ":", 2) - switch kv[0] { - case "string": - if len(kv) == 2 { - return "char(" + kv[1] + ") NOT NULL", "" - } - return "TEXT NOT NULL", "" - case "text": - return "TEXT NOT NULL", "" - case "auto", "pk": - return "serial primary key", "" - case "datetime": - return "TIMESTAMP WITHOUT TIME ZONE NOT NULL", "" - case "int", "int8", "int16", "int32", "int64": - fallthrough - case "uint", "uint8", "uint16", "uint32", "uint64": - return "integer DEFAULT NULL", "" - case "bool": - return "boolean NOT NULL", "" - case "float32", "float64", "float": - return "numeric NOT NULL", "" - } - return "", "" -} From cad9b71bbf09924b5ff821b98443c57ac92ffeda Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 19 Aug 2016 22:48:21 +0800 Subject: [PATCH 097/123] hotfix: fix the generate from conn. --- apiapp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apiapp.go b/apiapp.go index dda3a22..5a07120 100644 --- a/apiapp.go +++ b/apiapp.go @@ -606,7 +606,7 @@ func createapi(cmd *Command, args []string) int { ColorLog("[INFO] Using '%s' as 'driver'\n", driver) ColorLog("[INFO] Using '%s' as 'conn'\n", conn) ColorLog("[INFO] Using '%s' as 'tables'\n", tables) - generateAppcode(string(driver), string(conn), "3", string(tables), path.Join(apppath, args[0])) + generateAppcode(string(driver), string(conn), "3", string(tables), apppath) } else { os.Mkdir(path.Join(apppath, "models"), 0755) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models"), "\x1b[0m") From 340859ea10c1f7e8de1f1aa57e13533ca11b2a4a Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 19 Aug 2016 23:00:08 +0800 Subject: [PATCH 098/123] remove docs package --- apiapp.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apiapp.go b/apiapp.go index 5a07120..d76bf34 100644 --- a/apiapp.go +++ b/apiapp.go @@ -69,7 +69,6 @@ EnableDocs = true var apiMaingo = `package main import ( - _ "{{.Appname}}/docs" _ "{{.Appname}}/routers" "github.com/astaxie/beego" @@ -87,7 +86,6 @@ func main() { var apiMainconngo = `package main import ( - _ "{{.Appname}}/docs" _ "{{.Appname}}/routers" "github.com/astaxie/beego" @@ -578,8 +576,6 @@ func createapi(cmd *Command, args []string) int { fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf"), "\x1b[0m") os.Mkdir(path.Join(apppath, "controllers"), 0755) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers"), "\x1b[0m") - os.Mkdir(path.Join(apppath, "docs"), 0755) - fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "docs"), "\x1b[0m") os.Mkdir(path.Join(apppath, "tests"), 0755) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests"), "\x1b[0m") fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m") From 6ccd0e7d9f6d3b5d029d7f0c9975286f623896b6 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 19 Aug 2016 23:31:25 +0800 Subject: [PATCH 099/123] remove bee api default docs --- apiapp.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/apiapp.go b/apiapp.go index d76bf34..d05e0ad 100644 --- a/apiapp.go +++ b/apiapp.go @@ -631,9 +631,6 @@ func createapi(cmd *Command, args []string) int { fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "user.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "models", "user.go"), apiModels2) - fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "docs", "doc.go"), "\x1b[0m") - WriteToFile(path.Join(apppath, "docs", "doc.go"), "package docs") - fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "main.go"), strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1)) From 31eaaa14e79638079f5d8fee808aa1bbd4546a7d Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 19 Aug 2016 23:31:52 +0800 Subject: [PATCH 100/123] fix: if current path is in GOPATH, create api in current path --- apiapp.go | 10 ++++++++++ new.go | 22 ++++++---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/apiapp.go b/apiapp.go index d05e0ad..f79a7f8 100644 --- a/apiapp.go +++ b/apiapp.go @@ -645,9 +645,19 @@ func checkEnv(appname string) (apppath, packpath string, err error) { ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty") os.Exit(2) } + currpath, _ := os.Getwd() + currpath = path.Join(currpath, appname) + for _, gpath := range gps { + gsrcpath := path.Join(gpath, "src") + if strings.HasPrefix(currpath, gsrcpath) { + return currpath, currpath[len(gsrcpath):], nil + } + } + // In case of multiple paths in the GOPATH, by default // we use the first path gopath := gps[0] + ColorLog("[%s]You current workdir is not a $GOPATH/src, bee will create the application in GOPATH: %s\n", WARN, gopath) Debugf("GOPATH: %s", gopath) gosrcpath := path.Join(gopath, "src") diff --git a/new.go b/new.go index ccdc4f9..e0ba92f 100644 --- a/new.go +++ b/new.go @@ -56,26 +56,16 @@ func init() { func createApp(cmd *Command, args []string) int { ShowShortVersionBanner() - w := NewColorWriter(os.Stdout) - if len(args) != 1 { ColorLog("[ERRO] Argument [appname] is missing\n") os.Exit(2) } - - gps := GetGOPATHs() - if len(gps) == 0 { - ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty") + apppath, packpath, err := checkEnv(args[0]) + if err != nil { + fmt.Println(err) os.Exit(2) } - // In case of multiple paths in the GOPATH, by default - // we use the first path - gopath := gps[0] - Debugf("GOPATH: %s", gopath) - - gosrcpath := path.Join(gopath, "src") // User's workspace - apppath := path.Join(gosrcpath, args[0]) if isExist(apppath) { ColorLog("[ERRO] Path (%s) already exists\n", apppath) @@ -119,13 +109,13 @@ func createApp(cmd *Command, args []string) int { WriteToFile(path.Join(apppath, "views", "index.tpl"), indextpl) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m") - WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(router, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1)) + WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(router, "{{.Appname}}", packpath, -1)) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests", "default_test.go"), "\x1b[0m") - WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(test, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1)) + WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(test, "{{.Appname}}", packpath, -1)) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m") - WriteToFile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1)) + WriteToFile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", packpath, -1)) ColorLog("[SUCC] New application successfully created!\n") return 0 From b5bf9d07c3d0b345ee0c73f2cb65469368bf9bd4 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 19 Aug 2016 23:45:18 +0800 Subject: [PATCH 101/123] unzip to swagger while not swagger-2 --- apiapp.go | 2 +- rundocs.go | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/apiapp.go b/apiapp.go index f79a7f8..4d4e58a 100644 --- a/apiapp.go +++ b/apiapp.go @@ -650,7 +650,7 @@ func checkEnv(appname string) (apppath, packpath string, err error) { for _, gpath := range gps { gsrcpath := path.Join(gpath, "src") if strings.HasPrefix(currpath, gsrcpath) { - return currpath, currpath[len(gsrcpath):], nil + return currpath, currpath[len(gsrcpath)+1:], nil } } diff --git a/rundocs.go b/rundocs.go index 8c840af..35eef7e 100644 --- a/rundocs.go +++ b/rundocs.go @@ -20,6 +20,7 @@ import ( "log" "net/http" "os" + "strings" ) var cmdRundocs = &Command{ @@ -120,6 +121,7 @@ func unzipAndDelete(src string) error { } defer r.Close() + rp := strings.NewReplacer("swagger-"+swaggerVersion, "swagger") for _, f := range r.File { rc, err := f.Open() if err != nil { @@ -127,11 +129,12 @@ func unzipAndDelete(src string) error { } defer rc.Close() + fname := rp.Replace(f.Name) if f.FileInfo().IsDir() { - os.MkdirAll(f.Name, f.Mode()) + os.MkdirAll(fname, f.Mode()) } else { f, err := os.OpenFile( - f.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) + fname, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) if err != nil { return err } @@ -143,11 +146,6 @@ func unzipAndDelete(src string) error { } } } - os.RemoveAll("swagger") - err = os.Rename("swagger-"+swaggerVersion, "swagger") - if err != nil { - ColorLog("[%s]Rename swagger-%s to swagger:%s\n", ERRO, swaggerVersion, err) - } ColorLog("[%s]Start delete src file %s\n", INFO, src) return os.RemoveAll(src) } From 5309c72ef751bd4edb45d1702996eb279033b281 Mon Sep 17 00:00:00 2001 From: astaxie Date: Sat, 20 Aug 2016 00:14:39 +0800 Subject: [PATCH 102/123] support success response array objects --- g_docs.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/g_docs.go b/g_docs.go index 3a9b98d..76d11f7 100644 --- a/g_docs.go +++ b/g_docs.go @@ -405,6 +405,23 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat } modelsList[pkgpath+controllerName][st[2]] = mod appendModels(cmpath, pkgpath, controllerName, realTypes) + } else if st[1] == "{array}" { + rs.Schema.Type = "array" + if sType, ok := basicTypes[st[2]]; ok { + typeFormat := strings.Split(sType, ":") + rs.Schema.Type = typeFormat[0] + rs.Schema.Format = typeFormat[1] + } else { + cmpath, m, mod, realTypes := getModel(st[2]) + rs.Schema.Items = &swagger.Propertie{ + Ref: "#/definitions/" + m, + } + if _, ok := modelsList[pkgpath+controllerName]; !ok { + modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema, 0) + } + modelsList[pkgpath+controllerName][st[2]] = mod + appendModels(cmpath, pkgpath, controllerName, realTypes) + } } opts.Responses[st[0]] = rs } else if strings.HasPrefix(t, "@Param") { From ca2f60c72d8d7cb3a3ebcea51612b0cfc77c8ca7 Mon Sep 17 00:00:00 2001 From: tnextday Date: Sat, 20 Aug 2016 11:17:30 +0800 Subject: [PATCH 103/123] add array type support in comment param --- g_docs.go | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/g_docs.go b/g_docs.go index 3a9b98d..aa82fef 100644 --- a/g_docs.go +++ b/g_docs.go @@ -442,16 +442,33 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat modelsList[pkgpath+controllerName][typ] = mod appendModels(cmpath, pkgpath, controllerName, realTypes) } else { + isArray := false + paraType := "" + paraFormat := "" + if strings.HasPrefix(typ, "[]") { + typ = typ[2:] + isArray = true + } if typ == "string" || typ == "number" || typ == "integer" || typ == "boolean" || typ == "array" || typ == "file" { - para.Type = typ + paraType = typ } else if sType, ok := basicTypes[typ]; ok { typeFormat := strings.Split(sType, ":") - para.Type = typeFormat[0] - para.Format = typeFormat[1] + paraType = typeFormat[0] + paraFormat = typeFormat[1] } else { fmt.Fprintf(os.Stderr, "[%s.%s] Unknow param type: %s\n", controllerName, funcName, typ) } + if isArray { + para.Type = "array" + para.Items = &swagger.ParameterItems{ + Type: paraType, + Format: paraFormat, + } + } else { + para.Type = paraType + para.Format = paraFormat + } } if len(p) > 4 { para.Required, _ = strconv.ParseBool(p[3]) @@ -614,7 +631,6 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp Type: typeFormat[0], Format: typeFormat[1], } - } else { mp.Items = &swagger.Propertie{ Ref: "#/definitions/" + realType, From c3ff72ae77166485b35aeb8d875356360967906d Mon Sep 17 00:00:00 2001 From: tnextday Date: Sat, 20 Aug 2016 15:12:15 +0800 Subject: [PATCH 104/123] Add support for query param array format. exmple: // @Param app query []string true support multipil app params Update support for responses object format. exmple: // @Success 200 success // @Success 200 {object} int64 success count // @Success 200 {object} []int64 success ids // @Success 200 {array} int64 success ids --- g_docs.go | 109 ++++++++++++++++++++++++------------------------------ 1 file changed, 48 insertions(+), 61 deletions(-) diff --git a/g_docs.go b/g_docs.go index c977d9c..1be9fba 100644 --- a/g_docs.go +++ b/g_docs.go @@ -328,6 +328,17 @@ func isSystemPackage(pkgpath string) bool { return false } +func peekNextSplitString(ss string) (s string, spacePos int) { + spacePos = strings.IndexFunc(ss, unicode.IsSpace) + if spacePos < 0 { + s = ss + spacePos = len(ss) + } else { + s = strings.TrimSpace(ss[:spacePos]) + } + return +} + // parse the func comments func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpath string) error { var routerPath string @@ -358,72 +369,48 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat } else if strings.HasPrefix(t, "@Success") { ss := strings.TrimSpace(t[len("@Success"):]) rs := swagger.Response{} - st := make([]string, 3) - j := 0 - var tmp []rune - start := false - - for i, c := range ss { - if unicode.IsSpace(c) { - if !start && j < 2 { - continue - } - if j == 0 || j == 1 { - st[j] = string(tmp) - tmp = make([]rune, 0) - j++ - start = false - if j == 1 { - continue - } else { - st[j] = strings.TrimSpace(ss[i+1:]) - break - - } - } - } else { - start = true - tmp = append(tmp, c) + respCode, pos := peekNextSplitString(ss) + ss = strings.TrimSpace(ss[pos:]) + respType, pos := peekNextSplitString(ss) + if respType == "{object}" || respType == "{array}" { + isArray := respType == "{array}" + ss = strings.TrimSpace(ss[pos:]) + schemaName, pos := peekNextSplitString(ss) + if schemaName == "" { + ColorLog("[ERRO][%s.%s] Schema must follow {object} or {array}\n", controllerName, funcName) + os.Exit(-1) } - } - if len(tmp) > 0 && st[2] == "" { - st[2] = strings.TrimSpace(string(tmp)) - } - rs.Description = st[2] - if st[1] == "{object}" { - if st[2] == "" { - panic(controllerName + " " + funcName + " has no object") + if strings.HasPrefix(schemaName, "[]") { + schemaName = schemaName[2:] + isArray = true } - cmpath, m, mod, realTypes := getModel(st[2]) - //ll := strings.Split(st[2], ".") - //opts.Type = ll[len(ll)-1] - rs.Schema = &swagger.Schema{ - Ref: "#/definitions/" + m, - } - if _, ok := modelsList[pkgpath+controllerName]; !ok { - modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema, 0) - } - modelsList[pkgpath+controllerName][st[2]] = mod - appendModels(cmpath, pkgpath, controllerName, realTypes) - } else if st[1] == "{array}" { - rs.Schema.Type = "array" - if sType, ok := basicTypes[st[2]]; ok { + schema := swagger.Schema{} + if sType, ok := basicTypes[schemaName]; ok { typeFormat := strings.Split(sType, ":") - rs.Schema.Type = typeFormat[0] - rs.Schema.Format = typeFormat[1] + schema.Type = typeFormat[0] + schema.Format = typeFormat[1] } else { - cmpath, m, mod, realTypes := getModel(st[2]) - rs.Schema.Items = &swagger.Propertie{ - Ref: "#/definitions/" + m, - } + cmpath, m, mod, realTypes := getModel(schemaName) + schema.Ref = "#/definitions/" + m if _, ok := modelsList[pkgpath+controllerName]; !ok { modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema, 0) } - modelsList[pkgpath+controllerName][st[2]] = mod + modelsList[pkgpath+controllerName][schemaName] = mod appendModels(cmpath, pkgpath, controllerName, realTypes) } + if isArray { + rs.Schema = &swagger.Schema{ + Type: "array", + Items: &schema, + } + }else { + rs.Schema = &schema + } + rs.Description = strings.TrimSpace(ss[pos:]) + } else { + rs.Description = strings.TrimSpace(ss) } - opts.Responses[st[0]] = rs + opts.Responses[respCode] = rs } else if strings.HasPrefix(t, "@Param") { para := swagger.Parameter{} p := getparams(strings.TrimSpace(t[len("@Param "):])) @@ -443,7 +430,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat case "body": break default: - fmt.Fprintf(os.Stderr, "[%s.%s] Unknow param location: %s, Possible values are `query`, `header`, `path`, `formData` or `body`.\n", controllerName, funcName, p[1]) + ColorLog("[WARN][%s.%s] Unknow param location: %s, Possible values are `query`, `header`, `path`, `formData` or `body`.\n", controllerName, funcName, p[1]) } para.In = p[1] pp := strings.Split(p[2], ".") @@ -474,7 +461,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat paraType = typeFormat[0] paraFormat = typeFormat[1] } else { - fmt.Fprintf(os.Stderr, "[%s.%s] Unknow param type: %s\n", controllerName, funcName, typ) + ColorLog("[WARN][%s.%s] Unknow param type: %s\n", controllerName, funcName, typ) } if isArray { para.Type = "array" @@ -625,7 +612,7 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp } ts, ok := d.Decl.(*ast.TypeSpec) if !ok { - ColorLog("Unknown type without TypeSec: %v", d) + ColorLog("Unknown type without TypeSec: %v\n", d) os.Exit(1) } st, ok := ts.Type.(*ast.StructType) @@ -717,8 +704,8 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp } } if m.Title == "" { - ColorLog("can't find the object: %s", str) - os.Exit(1) + ColorLog("[ERRO]can't find the object: %s\n", str) + //os.Exit(1) } if len(rootapi.Definitions) == 0 { rootapi.Definitions = make(map[string]swagger.Schema) From c9d5fbfe64e330d6c0293f175c126d2c4bc07912 Mon Sep 17 00:00:00 2001 From: Kyaw Myint Thein Date: Sun, 21 Aug 2016 10:55:10 +0800 Subject: [PATCH 105/123] add runmode flag on bee run to set BEEGO_RUNMODE env --- run.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/run.go b/run.go index b2f94da..8aab6b5 100644 --- a/run.go +++ b/run.go @@ -24,7 +24,7 @@ import ( ) var cmdRun = &Command{ - UsageLine: "run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] [-vendor=true] [-e=folderToExclude] [-tags=goBuildTags]", + UsageLine: "run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] [-vendor=true] [-e=folderToExclude] [-tags=goBuildTags] [-runmode=BEEGO_RUNMODE]", Short: "run the app and start a Web server for development", Long: ` Run command will supervise the file system of the beego project using inotify, @@ -51,6 +51,8 @@ var ( vendorWatch bool // Current user workspace currentGoPath string + // Current runmode + runmode string ) func init() { @@ -61,6 +63,7 @@ func init() { cmdRun.Flag.Var(&excludedPaths, "e", "Excluded paths[].") cmdRun.Flag.BoolVar(&vendorWatch, "vendor", false, "Watch vendor folder") cmdRun.Flag.StringVar(&buildTags, "tags", "", "Build tags (https://golang.org/pkg/go/build/)") + cmdRun.Flag.StringVar(&runmode, "runmode", "", "Set BEEGO_RUNMODE env variable.") exit = make(chan bool) } @@ -100,6 +103,16 @@ func runApp(cmd *Command, args []string) int { Debugf("current path:%s\n", currpath) + if runmode == "prod" || runmode == "dev"{ + os.Setenv("BEEGO_RUNMODE", runmode) + ColorLog("[INFO] Using '%s' as 'runmode'\n", os.Getenv("BEEGO_RUNMODE")) + }else if runmode != ""{ + os.Setenv("BEEGO_RUNMODE", runmode) + ColorLog("[WARN] Using '%s' as 'runmode'\n", os.Getenv("BEEGO_RUNMODE")) + }else if os.Getenv("BEEGO_RUNMODE") != ""{ + ColorLog("[WARN] Using '%s' as 'runmode'\n", os.Getenv("BEEGO_RUNMODE")) + } + err := loadConfig() if err != nil { ColorLog("[ERRO] Fail to parse bee.json[ %s ]\n", err) From 368b69b73f82763c386ab9314f7b7d1c089b3939 Mon Sep 17 00:00:00 2001 From: Kyaw Myint Thein Date: Sun, 21 Aug 2016 10:56:28 +0800 Subject: [PATCH 106/123] update readme file for bee run --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fecb3e9..e9a60e1 100644 --- a/README.md +++ b/README.md @@ -288,7 +288,7 @@ For instance, to get more information about the `run` command: ```bash $ bee help run -usage: bee run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] +usage: bee run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] [-runmode=BEEGO_RUNMODE] start the appname throw exec.Command From 07ca4481b0e7b4a0633f573b52c86bedef4eed2c Mon Sep 17 00:00:00 2001 From: tnextday Date: Mon, 22 Aug 2016 16:11:06 +0800 Subject: [PATCH 107/123] add todo --- g_docs.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/g_docs.go b/g_docs.go index 1be9fba..f6cf29f 100644 --- a/g_docs.go +++ b/g_docs.go @@ -615,6 +615,7 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp ColorLog("Unknown type without TypeSec: %v\n", d) os.Exit(1) } + // TODO support other types, such as `ArrayType`, `MapType`, `InterfaceType` etc... st, ok := ts.Type.(*ast.StructType) if !ok { continue @@ -704,7 +705,8 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp } } if m.Title == "" { - ColorLog("[ERRO]can't find the object: %s\n", str) + ColorLog("[WARN]can't find the object: %s\n", str) + // TODO remove when all type have been supported //os.Exit(1) } if len(rootapi.Definitions) == 0 { From 98f4ff83c13bc871e618309f4d07a428474612f9 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Mon, 22 Aug 2016 18:29:11 +0200 Subject: [PATCH 108/123] docs: Updated README.md The README.md is updated to include the latest changes in bee and Beego. New submission guidelines are added to organize contributions to the project. --- README.md | 517 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 301 insertions(+), 216 deletions(-) diff --git a/README.md b/README.md index e9a60e1..16f6039 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,17 @@ bee === -[![Build Status](https://drone.io/github.com/beego/bee/status.png)](https://drone.io/github.com/beego/bee/latest) +Bee is a command-line tool facilitating development of Beego-based application. -Bee is a command line tool facilitating development with beego framework. +[![Build Status](https://drone.io/github.com/beego/bee/status.png)](https://drone.io/github.com/beego/bee/latest) ## Requirements - Go version >= 1.3. - ## Installation -Begin by installing `bee` using `go get` command. +To install `bee` use the `go get` command: ```bash go get github.com/beego/bee @@ -32,242 +31,225 @@ go get -u github.com/beego/bee ## Basic commands -Bee provides a variety of commands which can be helpful at various stage of development. The top level commands include: -```base - new create an application base on beego framework - run run the app which can hot compile - pack compress an beego project - api create an api application base on beego framework - bale packs non-Go files to Go source files - version show the bee & beego version - generate source code generator - migrate run database migrations - hprose create an rpc application use hprose base on beego framework +Bee provides a variety of commands which can be helpful at various stages of development. The top level commands include: ``` -## bee version + new Create a Beego application + run Run the app and start a Web server for development + pack Compress a beego project into a single file + api Create an API beego application + hprose Create an rpc application use hprose base on beego framework + bale Packs non-Go files to Go source files + version Prints the current Bee version + generate Source code generator + migrate Run database migrations + fix Fix the Beego application to make it compatible with Beego 1.6 +``` +### bee version -The first command is the easiest: displaying which version of `bee`, `beego` and `go` is installed on your machine: +To display the current version of `bee`, `beego` and `go` installed on your machine: ```bash $ bee version -bee :1.2.2 -beego :1.4.0 -Go :go version go1.2.1 linux/amd64 +______ +| ___ \ +| |_/ / ___ ___ +| ___ \ / _ \ / _ \ +| |_/ /| __/| __/ +\____/ \___| \___| v1.5.0 + +├── Beego : 1.7.0 +├── GoVersion : go1.6.2 +├── GOOS : windows +├── GOARCH : amd64 +├── NumCPU : 4 +├── GOPATH : C:\Users\beeuser\go +├── GOROOT : C:\go +├── Compiler : gc +└── Date : Monday, 22 Aug 2016 ``` -## bee new +### bee new -Creating a new beego web application is no big deal, too. +To create a new Beego web application: ```bash -$ bee new myapp -[INFO] Creating application... -/home/zheng/gopath/src/myapp/ -/home/zheng/gopath/src/myapp/conf/ -/home/zheng/gopath/src/myapp/controllers/ -/home/zheng/gopath/src/myapp/models/ -/home/zheng/gopath/src/myapp/routers/ -/home/zheng/gopath/src/myapp/tests/ -/home/zheng/gopath/src/myapp/static/ -/home/zheng/gopath/src/myapp/static/js/ -/home/zheng/gopath/src/myapp/static/css/ -/home/zheng/gopath/src/myapp/static/img/ -/home/zheng/gopath/src/myapp/views/ -/home/zheng/gopath/src/myapp/conf/app.conf -/home/zheng/gopath/src/myapp/controllers/default.go -/home/zheng/gopath/src/myapp/views/index.tpl -/home/zheng/gopath/src/myapp/routers/router.go -/home/zheng/gopath/src/myapp/tests/default_test.go -/home/zheng/gopath/src/myapp/main.go -2014/08/29 15:45:47 [SUCC] New application successfully created! +$ bee new my-web-app +______ +| ___ \ +| |_/ / ___ ___ +| ___ \ / _ \ / _ \ +| |_/ /| __/| __/ +\____/ \___| \___| v1.5.0 +2016/08/22 14:53:45 [INFO] Creating application... + create C:\Users\beeuser\go\src\github.com\user\my-web-app\ + create C:\Users\beeuser\go\src\github.com\user\my-web-app\conf\ + create C:\Users\beeuser\go\src\github.com\user\my-web-app\controllers\ + create C:\Users\beeuser\go\src\github.com\user\my-web-app\models\ + create C:\Users\beeuser\go\src\github.com\user\my-web-app\routers\ + create C:\Users\beeuser\go\src\github.com\user\my-web-app\tests\ + create C:\Users\beeuser\go\src\github.com\user\my-web-app\static\ + create C:\Users\beeuser\go\src\github.com\user\my-web-app\static\js\ + create C:\Users\beeuser\go\src\github.com\user\my-web-app\static\css\ + create C:\Users\beeuser\go\src\github.com\user\my-web-app\static\img\ + create C:\Users\beeuser\go\src\github.com\user\my-web-app\views\ + create C:\Users\beeuser\go\src\github.com\user\my-web-app\conf\app.conf + create C:\Users\beeuser\go\src\github.com\user\my-web-app\controllers\default.go + create C:\Users\beeuser\go\src\github.com\user\my-web-app\views\index.tpl + create C:\Users\beeuser\go\src\github.com\user\my-web-app\routers\router.go + create C:\Users\beeuser\go\src\github.com\user\my-web-app\tests\default_test.go + create C:\Users\beeuser\go\src\github.com\user\my-web-app\main.go +2016/08/22 14:53:45 [SUCC] New application successfully created! ``` -## bee run +For more information on the usage, run `bee help new`. -To run the application we just created, navigate to the application folder and execute `bee run`. +### bee run + +To run the application we just created, you can navigate to the application folder and execute: ```bash -$ cd myapp -$ bee run +$ cd my-web-app && bee run ``` -## bee pack +Or from anywhere in your machine: + +``` +$ bee run github.com/user/my-web-app +``` + +For more information on the usage, run `bee help run`. + +### bee pack + +To compress a Beego application into a single deployable file: ```bash -usage: bee pack - -compress an beego project - --p app path. default is current path --b build specify platform app. default true --ba additional args of go build --be=[] additional ENV Variables of go build. eg: GOARCH=arm --o compressed file output dir. default use current path --f="" format. [ tar.gz / zip ]. default tar.gz --exp="" relpath exclude prefix. default: . --exs="" relpath exclude suffix. default: .go:.DS_Store:.tmp - all path use : as separator --exr=[] file/directory name exclude by Regexp. default: ^. --fs=false follow symlink. default false --ss=false skip symlink. default false - default embed symlink into compressed file --v=false verbose +$ bee pack +______ +| ___ \ +| |_/ / ___ ___ +| ___ \ / _ \ / _ \ +| |_/ /| __/| __/ +\____/ \___| \___| v1.5.0 +2016/08/22 15:11:01 Packaging application: C:\Users\beeuser\go\src\github.com\user\my-web-app +2016/08/22 15:11:01 Building application... +2016/08/22 15:11:01 Env: GOOS=windows GOARCH=amd64 +2016/08/22 15:11:08 Build successful +2016/08/22 15:11:08 Excluding relpath prefix: . +2016/08/22 15:11:08 Excluding relpath suffix: .go:.DS_Store:.tmp +2016/08/22 15:11:10 Writing to output: `C:\Users\beeuser\go\src\github.com\user\my-web-app\my-web-app.tar.gz` ``` -## bee api +For more information on the usage, run `bee help pack`. + +### bee api + +To create a Beego API application: ```bash -usage: bee api [appname] - -create an api application base on beego framework - -bee api [appname] [-tables=""] [-driver="mysql"] [-conn="root:@tcp(127.0.0.1:3306)/test"] - -tables: a list of table names separated by ',', default is empty, indicating all tables - -driver: [mysql | postgres | sqlite], the default is mysql - -conn: the connection string used by the driver, the default is '' - e.g. for mysql: root:@tcp(127.0.0.1:3306)/test - e.g. for postgres: postgres://postgres:postgres@127.0.0.1:5432/postgres - -if conn is empty will create a example api application. otherwise generate api application based on an existing database. - -In the current path, will create a folder named [appname] - -In the appname folder has the follow struct: - - ├── conf - │ └── app.conf - ├── controllers - │ └── object.go - │ └── user.go - ├── routers - │ └── router.go - ├── tests - │ └── default_test.go - ├── main.go - └── models - └── object.go - └── user.go +$ bee api my-api +______ +| ___ \ +| |_/ / ___ ___ +| ___ \ / _ \ / _ \ +| |_/ /| __/| __/ +\____/ \___| \___| v1.5.0 +2016/08/22 15:14:10 [INFO] Creating API... + create C:\Users\beeuser\go\src\github.com\user\my-api + create C:\Users\beeuser\go\src\github.com\user\my-api\conf + create C:\Users\beeuser\go\src\github.com\user\my-api\controllers + create C:\Users\beeuser\go\src\github.com\user\my-api\tests + create C:\Users\beeuser\go\src\github.com\user\my-api\conf\app.conf + create C:\Users\beeuser\go\src\github.com\user\my-api\models + create C:\Users\beeuser\go\src\github.com\user\my-api\routers\ + create C:\Users\beeuser\go\src\github.com\user\my-api\controllers\object.go + create C:\Users\beeuser\go\src\github.com\user\my-api\controllers\user.go + create C:\Users\beeuser\go\src\github.com\user\my-api\tests\default_test.go + create C:\Users\beeuser\go\src\github.com\user\my-api\routers\router.go + create C:\Users\beeuser\go\src\github.com\user\my-api\models\object.go + create C:\Users\beeuser\go\src\github.com\user\my-api\models\user.go + create C:\Users\beeuser\go\src\github.com\user\my-api\main.go +2016/08/22 15:14:10 [SUCC] New API successfully created! ``` -## bee hprose +For more information on the usage, run `bee help api`. + +### bee hprose + +To create an Hprose RPC application based on Beego: ```bash -usage: bee hprose [appname] - -create an rpc application use hprose base on beego framework - -bee hprose [appname] [-tables=""] [-driver=mysql] [-conn=root:@tcp(127.0.0.1:3306)/test] - -tables: a list of table names separated by ',', default is empty, indicating all tables - -driver: [mysql | postgres | sqlite], the default is mysql - -conn: the connection string used by the driver, the default is '' - e.g. for mysql: root:@tcp(127.0.0.1:3306)/test - e.g. for postgres: postgres://postgres:postgres@127.0.0.1:5432/postgres - -if conn is empty will create a example rpc application. otherwise generate rpc application use hprose based on an existing database. - -In the current path, will create a folder named [appname] - -In the appname folder has the follow struct: - - ├── conf - │ └── app.conf - ├── main.go - └── models - └── object.go - └── user.go - +$ bee hprose my-rpc-app +______ +| ___ \ +| |_/ / ___ ___ +| ___ \ / _ \ / _ \ +| |_/ /| __/| __/ +\____/ \___| \___| v1.5.0 +2016/08/22 16:09:13 [INFO] Creating Hprose application... + create C:\Users\beeuser\go\src\github.com\user\my-rpc-app + create C:\Users\beeuser\go\src\github.com\user\my-rpc-app\conf + create C:\Users\beeuser\go\src\github.com\user\my-rpc-app\conf\app.conf + create C:\Users\beeuser\go\src\github.com\user\my-rpc-app\models + create C:\Users\beeuser\go\src\github.com\user\my-rpc-app\models\object.go + create C:\Users\beeuser\go\src\github.com\user\my-rpc-app\models\user.go + create C:\Users\beeuser\go\src\github.com\user\my-rpc-app\main.go +2016/08/22 16:09:13 [SUCC] New Hprose application successfully created! ``` -## bee bale +For more information on the usage, run `bee help hprose`. + +### bee bale + +To pack all the static files into Go source files: ```bash -usage: bee bale - -bale packs non-Go files to Go source files and - -auto-generate unpack function to main package then run it - -during the runtime. - -This is mainly used for zealots who are requiring 100% Go code. +$ bee bale +______ +| ___ \ +| |_/ / ___ ___ +| ___ \ / _ \ / _ \ +| |_/ /| __/| __/ +\____/ \___| \___| v1.5.0 +2016/08/22 16:37:24 [INFO] Detected bee.json +2016/08/22 16:37:24 [INFO] Packaging directory(static/js) +2016/08/22 16:37:24 [INFO] Packaging directory(static/css) +2016/08/22 16:37:24 [SUCC] Baled resources successfully! ``` -## bee migrate +For more information on the usage, run `bee help bale`. + +### bee migrate + +For database migrations, use `bee migrate`. + +For more information on the usage, run `bee help migrate`. + +### bee generate + +Bee also comes with a source code generator which speeds up the development. + +For example, to generate a new controller named `hello`: ```bash -usage: bee migrate [Command] - -bee migrate [-driver="mysql"] [-conn="root:@tcp(127.0.0.1:3306)/test"] - run all outstanding migrations - -driver: [mysql | postgres | sqlite], the default is mysql - -conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test - -bee migrate rollback [-driver="mysql"] [-conn="root:@tcp(127.0.0.1:3306)/test"] - rollback the last migration operation - -driver: [mysql | postgres | sqlite], the default is mysql - -conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test - -bee migrate reset [-driver="mysql"] [-conn="root:@tcp(127.0.0.1:3306)/test"] - rollback all migrations - -driver: [mysql | postgres| sqlite], the default is mysql - -conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test - -bee migrate refresh [-driver="mysql"] [-conn="root:@tcp(127.0.0.1:3306)/test"] - rollback all migrations and run them all again - -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 - -``` - -## bee generate - -Bee also comes with a souce code generator which speeds up the development. - -```bash -usage: bee generate [Command] - -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 table fields. Format: field:type, ... - -driver: [mysql | postgres | 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. Format: field:type, ... - -bee generate controller [controllerfile] - generate RESTFul controllers - -bee generate view [viewpath] - generate CRUD view in viewpath - -bee generate migration [migrationfile] [-fields=""] - generate migration file for making database schema update - -fields: a list of table fields. Format: field:type, ... - -bee generate docs - generate swagger doc file - -bee generate test [routerfile] - generate testcase - -bee generate appcode [-tables=""] [-driver="mysql"] [-conn="root:@tcp(127.0.0.1:3306)/test"] [-level=3] - generate appcode based on an existing database - -tables: a list of table names separated by ',', default is empty, indicating all tables - -driver: [mysql | postgres | sqlite], the default is mysql - -conn: the connection string used by the driver. - default for mysql: root:@tcp(127.0.0.1:3306)/test - default for postgres: postgres://postgres:postgres@127.0.0.1:5432/postgres - -level: [1 | 2 | 3], 1 = models; 2 = models,controllers; 3 = models,controllers,router - +$ bee generate controller hello +______ +| ___ \ +| |_/ / ___ ___ +| ___ \ / _ \ / _ \ +| |_/ /| __/| __/ +\____/ \___| \___| v1.5.0 +2016/08/22 16:55:30 [INFO] Using 'Hello' as controller name +2016/08/22 16:55:30 [INFO] Using 'controllers' as package name + create C:\Users\beeuser\go\src\github.com\user\my-web-app/controllers/hello.go +2016/08/22 16:55:30 [SUCC] Controller successfully generated! ``` +For more information on the usage, run `bee help generate`. ## Shortcuts -Because you'll likely type these generator commands over and over, it makes sense to create aliases. +Because you'll likely type these generator commands over and over, it makes sense to create aliases: ```bash # Generator Stuff @@ -278,32 +260,135 @@ alias g:v="bee generate view" alias g:mi="bee generate migration" ``` -These can be stored in, for example, your `~/.bash_profile` or `~/.bashrc` files. +These can be stored , for example, in your `~/.bash_profile` or `~/.bashrc` files. ## Help -If you happend to forget the usage of a command, you can always find the usage information by `bee help `. +To print more information on the usage of a particular command, use `bee help `. For instance, to get more information about the `run` command: ```bash $ bee help run -usage: bee run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] [-runmode=BEEGO_RUNMODE] +usage: bee run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] [-vendor=true] [-e=folderToExclude] [-tags=goBuildTags] -start the appname throw exec.Command +Run command will supervise the file system of the beego project using inotify, +it will recompile and restart the app after any modifications. +``` -then start a inotify watch for current dir - -when the file has changed bee will auto go build and restart the app +## Contributing +Bug reports, feature requests and pull requests are always welcome. - file changed - | - check if it's go file - | - yes no - | | - go build do nothing - | - restart app +We work on two branches: `master` for stable, released code and `develop`, a development branch. +It might be important to distinguish them when you are reading the commit history searching for a feature or a bugfix, +or when you are unsure of where to base your work from when contributing. + +### Found a bug? + +Please [submit an issue][new-issue] on GitHub and we will follow up. +Even better, we would appreciate a [Pull Request][new-pr] with a fix for it! + +- If the bug was found in a release, it is best to base your work on `master` and submit your PR against it. +- If the bug was found on `develop` (the development branch), base your work on `develop` and submit your PR against it. + +Please follow the [Pull Request Guidelines][new-pr]. + +### Want a feature? + +Feel free to request a feature by [submitting an issue][new-issue] on GitHub and open the discussion. + +If you'd like to implement a new feature, please consider opening an issue first to talk about it. +It may be that somebody is already working on it, or that there are particular issues that you should be aware of +before implementing the change. If you are about to open a Pull Request, please make sure to follow the [submissions guidelines][new-pr]. + +## Submission Guidelines + +### Submitting an issue + +Before you submit an issue, search the archive, maybe you will find that a similar one already exists. + +If you are submitting an issue for a bug, please include the following: + +- An overview of the issue +- Your use case (why is this a bug for you?) +- The version of `bee` you are running (include the output of `bee version`) +- Steps to reproduce the issue +- Eventually, logs from your application. +- Ideally, a suggested fix + +The more information you give us, the more able to help we will be! + +### Submitting a Pull Request + +- First of all, make sure to base your work on the `develop` branch (the development branch): ``` + # a bugfix branch for develop would be prefixed by fix/ + # a bugfix branch for master would be prefixed by hotfix/ + $ git checkout -b feature/my-feature develop +``` + +- Please create commits containing **related changes**. For example, two different bugfixes should produce two separate commits. +A feature should be made of commits splitted by **logical chunks** (no half-done changes). Use your best judgement as to +how many commits your changes require. + +- Write insightful and descriptive commit messages. It lets us and future contributors quickly understand your changes +without having to read your changes. Please provide a summary in the first line (50-72 characters) and eventually, +go to greater lengths in your message's body. A good example can be found in [Angular commit message format](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit-message-format). + +- Please **include the appropriate test cases** for your patch. + +- Make sure all tests pass before submitting your changes. + +- Rebase your commits. It may be that new commits have been introduced on `develop`. +Rebasing will update your branch with the most recent code and make your changes easier to review: + + ``` + $ git fetch + $ git rebase origin/develop + ``` + +- Push your changes: + + ``` + $ git push origin -u feature/my-feature + ``` + +- Open a pull request against the `develop` branch. + +- If we suggest changes: + - Please make the required updates (after discussion if any) + - Only create new commits if it makes sense. Generally, you will want to amend your latest commit or rebase your branch after the new changes: + + ``` + $ git rebase -i develop + # choose which commits to edit and perform the updates + ``` + + - Re-run the tests + - Force push to your branch: + + ``` + $ git push origin feature/my-feature -f + ``` + +[new-issue]: #submitting-an-issue +[new-pr]: #submitting-a-pull-request + +## Licence + +```text +Copyright 2016 bee authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` \ No newline at end of file From f813e990c0e5daa82c646c0a74e0a679928963a7 Mon Sep 17 00:00:00 2001 From: astaxie Date: Wed, 24 Aug 2016 10:54:54 +0800 Subject: [PATCH 109/123] hotfix: schema init --- g_docs.go | 1 + 1 file changed, 1 insertion(+) diff --git a/g_docs.go b/g_docs.go index 76d11f7..6c1e870 100644 --- a/g_docs.go +++ b/g_docs.go @@ -406,6 +406,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat modelsList[pkgpath+controllerName][st[2]] = mod appendModels(cmpath, pkgpath, controllerName, realTypes) } else if st[1] == "{array}" { + rs.Schema = &swagger.Schema{} rs.Schema.Type = "array" if sType, ok := basicTypes[st[2]]; ok { typeFormat := strings.Split(sType, ":") From 7e605092312175f0c6946236ba72772d53bd9059 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Thu, 25 Aug 2016 19:32:39 +0300 Subject: [PATCH 110/123] Separate and add @Description with @Summary params @Description -> is "descriptions" in swagger @Summary -> is "summary" in swagger this different options. --- g_docs.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/g_docs.go b/g_docs.go index 6c1e870..66cd973 100644 --- a/g_docs.go +++ b/g_docs.go @@ -354,7 +354,9 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat } else if strings.HasPrefix(t, "@Title") { opts.OperationID = controllerName + "." + strings.TrimSpace(t[len("@Title"):]) } else if strings.HasPrefix(t, "@Description") { - opts.Summary = strings.TrimSpace(t[len("@Description"):]) + opts.Description = strings.TrimSpace(t[len("@Description"):]) + } else if strings.HasPrefix(t, "@Summary") { + opts.Summary = strings.TrimSpace(t[len("@Summary"):]) } else if strings.HasPrefix(t, "@Success") { ss := strings.TrimSpace(t[len("@Success"):]) rs := swagger.Response{} From 004778c662d0445eb993488e8c8a55cde72cc103 Mon Sep 17 00:00:00 2001 From: Sergey Lanzman Date: Thu, 25 Aug 2016 01:42:23 +0300 Subject: [PATCH 111/123] swagger add embedded struct --- g_docs.go | 191 +++++++++++++++++++++++++++++------------------------- 1 file changed, 101 insertions(+), 90 deletions(-) diff --git a/g_docs.go b/g_docs.go index 25cf451..7cda8a7 100644 --- a/g_docs.go +++ b/g_docs.go @@ -610,96 +610,7 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp if k != objectname { continue } - ts, ok := d.Decl.(*ast.TypeSpec) - if !ok { - ColorLog("Unknown type without TypeSec: %v\n", d) - os.Exit(1) - } - // TODO support other types, such as `ArrayType`, `MapType`, `InterfaceType` etc... - st, ok := ts.Type.(*ast.StructType) - if !ok { - continue - } - m.Title = k - if st.Fields.List != nil { - m.Properties = make(map[string]swagger.Propertie) - for _, field := range st.Fields.List { - isSlice, realType, sType := typeAnalyser(field) - realTypes = append(realTypes, realType) - mp := swagger.Propertie{} - // add type slice - if isSlice { - mp.Type = "array" - if isBasicType(realType) { - typeFormat := strings.Split(sType, ":") - mp.Items = &swagger.Propertie{ - Type: typeFormat[0], - Format: typeFormat[1], - } - } else { - mp.Items = &swagger.Propertie{ - Ref: "#/definitions/" + realType, - } - } - } else { - if isBasicType(realType) { - typeFormat := strings.Split(sType, ":") - mp.Type = typeFormat[0] - mp.Format = typeFormat[1] - } else if sType == "object" { - mp.Ref = "#/definitions/" + realType - } - } - - // dont add property if anonymous field - if field.Names != nil { - - // set property name as field name - var name = field.Names[0].Name - - // if no tag skip tag processing - if field.Tag == nil { - m.Properties[name] = mp - continue - } - - var tagValues []string - stag := reflect.StructTag(strings.Trim(field.Tag.Value, "`")) - tag := stag.Get("json") - - if tag != "" { - tagValues = strings.Split(tag, ",") - } - - // dont add property if json tag first value is "-" - if len(tagValues) == 0 || tagValues[0] != "-" { - - // set property name to the left most json tag value only if is not omitempty - if len(tagValues) > 0 && tagValues[0] != "omitempty" { - name = tagValues[0] - } - - if thrifttag := stag.Get("thrift"); thrifttag != "" { - ts := strings.Split(thrifttag, ",") - if ts[0] != "" { - name = ts[0] - } - } - if required := stag.Get("required"); required != "" { - m.Required = append(m.Required, name) - } - if desc := stag.Get("description"); desc != "" { - mp.Description = desc - } - - m.Properties[name] = mp - } - if ignore := stag.Get("ignore"); ignore != "" { - continue - } - } - } - } + parseObject(d, k, &m, &realTypes, astPkgs) } } } @@ -716,6 +627,106 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTyp return } +func parseObject(d *ast.Object, k string, m *swagger.Schema, realTypes *[]string, astPkgs map[string]*ast.Package) { + ts, ok := d.Decl.(*ast.TypeSpec) + if !ok { + ColorLog("Unknown type without TypeSec: %v\n", d) + os.Exit(1) + } + // TODO support other types, such as `ArrayType`, `MapType`, `InterfaceType` etc... + st, ok := ts.Type.(*ast.StructType) + if !ok { + return + } + m.Title = k + if st.Fields.List != nil { + m.Properties = make(map[string]swagger.Propertie) + for _, field := range st.Fields.List { + isSlice, realType, sType := typeAnalyser(field) + *realTypes = append(*realTypes, realType) + mp := swagger.Propertie{} + if isSlice { + mp.Type = "array" + if isBasicType(realType) { + typeFormat := strings.Split(sType, ":") + mp.Items = &swagger.Propertie{ + Type: typeFormat[0], + Format: typeFormat[1], + } + } else { + mp.Items = &swagger.Propertie{ + Ref: "#/definitions/" + realType, + } + } + } else { + if isBasicType(realType) { + typeFormat := strings.Split(sType, ":") + mp.Type = typeFormat[0] + mp.Format = typeFormat[1] + } else if sType == "object" { + mp.Ref = "#/definitions/" + realType + } + } + if field.Names != nil { + + // set property name as field name + var name = field.Names[0].Name + + // if no tag skip tag processing + if field.Tag == nil { + m.Properties[name] = mp + continue + } + + var tagValues []string + stag := reflect.StructTag(strings.Trim(field.Tag.Value, "`")) + tag := stag.Get("json") + + if tag != "" { + tagValues = strings.Split(tag, ",") + } + + // dont add property if json tag first value is "-" + if len(tagValues) == 0 || tagValues[0] != "-" { + + // set property name to the left most json tag value only if is not omitempty + if len(tagValues) > 0 && tagValues[0] != "omitempty" { + name = tagValues[0] + } + + if thrifttag := stag.Get("thrift"); thrifttag != "" { + ts := strings.Split(thrifttag, ",") + if ts[0] != "" { + name = ts[0] + } + } + if required := stag.Get("required"); required != "" { + m.Required = append(m.Required, name) + } + if desc := stag.Get("description"); desc != "" { + mp.Description = desc + } + + m.Properties[name] = mp + } + if ignore := stag.Get("ignore"); ignore != "" { + continue + } + } else { + for _, pkg := range astPkgs { + for _, fl := range pkg.Files { + for nameOfObj, obj := range fl.Scope.Objects { + if obj.Name == fmt.Sprint(field.Type) { + parseObject(obj, nameOfObj, m, realTypes, astPkgs) + } + } + } + } + } + } + } +} + func typeAnalyser(f *ast.Field) (isSlice bool, realType, swaggerType string) { if arr, ok := f.Type.(*ast.ArrayType); ok { if isBasicType(fmt.Sprint(arr.Elt)) { From f45388586405a1241a3cdb324bff5d541531389e Mon Sep 17 00:00:00 2001 From: astaxie Date: Tue, 30 Aug 2016 00:18:17 +0800 Subject: [PATCH 112/123] update to 1.5.1 --- bee.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bee.go b/bee.go index 28ae437..76c5359 100644 --- a/bee.go +++ b/bee.go @@ -25,7 +25,7 @@ import ( "strings" ) -const version = "1.5.0" +const version = "1.5.1" type Command struct { // Run runs the command. From f6a219fb3a4f3c845bfddda7e1333141bba372d5 Mon Sep 17 00:00:00 2001 From: CodyGuo Date: Sun, 4 Sep 2016 13:53:45 +0800 Subject: [PATCH 113/123] Fix to issue #270 --- apiapp.go | 1 + 1 file changed, 1 insertion(+) diff --git a/apiapp.go b/apiapp.go index 4d4e58a..27e538d 100644 --- a/apiapp.go +++ b/apiapp.go @@ -650,6 +650,7 @@ func checkEnv(appname string) (apppath, packpath string, err error) { for _, gpath := range gps { gsrcpath := path.Join(gpath, "src") if strings.HasPrefix(currpath, gsrcpath) { + packpath = strings.Replace(currpath[len(gsrcpath)+1:], string(path.Separator), "/", -1) return currpath, currpath[len(gsrcpath)+1:], nil } } From ed67ef47e6825c5bfeb089559bf42fa44d83c394 Mon Sep 17 00:00:00 2001 From: CodyGuo Date: Sun, 4 Sep 2016 20:45:11 +0800 Subject: [PATCH 114/123] Fix to issue #270 --- apiapp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apiapp.go b/apiapp.go index 27e538d..892719b 100644 --- a/apiapp.go +++ b/apiapp.go @@ -651,7 +651,7 @@ func checkEnv(appname string) (apppath, packpath string, err error) { gsrcpath := path.Join(gpath, "src") if strings.HasPrefix(currpath, gsrcpath) { packpath = strings.Replace(currpath[len(gsrcpath)+1:], string(path.Separator), "/", -1) - return currpath, currpath[len(gsrcpath)+1:], nil + return currpath, packpath, nil } } From ad34b7be2a3dbbaa1ab6d113cea86ad022ba89bf Mon Sep 17 00:00:00 2001 From: ZetaChow Date: Fri, 9 Sep 2016 15:20:59 +0800 Subject: [PATCH 115/123] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=EF=BC=8C=E4=BB=A5=E7=AC=A6=E5=90=88Lint?= =?UTF-8?q?=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g_appcode.go | 8 +++++++- g_controllers.go | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/g_appcode.go b/g_appcode.go index 76d78ad..5d44663 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -1168,11 +1168,12 @@ import ( "github.com/astaxie/beego" ) -// oprations for {{ctrlName}} +// {{ctrlName}}Controller oprations for {{ctrlName}} type {{ctrlName}}Controller struct { beego.Controller } +// URLMapping ... func (c *{{ctrlName}}Controller) URLMapping() { c.Mapping("Post", c.Post) c.Mapping("GetOne", c.GetOne) @@ -1181,6 +1182,7 @@ func (c *{{ctrlName}}Controller) URLMapping() { c.Mapping("Delete", c.Delete) } +// Post ... // @Title Post // @Description create {{ctrlName}} // @Param body body models.{{ctrlName}} true "body for {{ctrlName}} content" @@ -1202,6 +1204,7 @@ func (c *{{ctrlName}}Controller) Post() { c.ServeJSON() } +// Get ... // @Title Get // @Description get {{ctrlName}} by id // @Param id path string true "The key for staticblock" @@ -1220,6 +1223,7 @@ func (c *{{ctrlName}}Controller) GetOne() { c.ServeJSON() } +// GetAll ... // @Title Get All // @Description get {{ctrlName}} // @Param query query string false "Filter. e.g. col1:v1,col2:v2 ..." @@ -1282,6 +1286,7 @@ func (c *{{ctrlName}}Controller) GetAll() { c.ServeJSON() } +// Update ... // @Title Update // @Description update the {{ctrlName}} // @Param id path string true "The id you want to update" @@ -1305,6 +1310,7 @@ func (c *{{ctrlName}}Controller) Put() { c.ServeJSON() } +// Delete ... // @Title Delete // @Description delete the {{ctrlName}} // @Param id path string true "The id you want to delete" diff --git a/g_controllers.go b/g_controllers.go index 79ed554..15ab0bd 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -82,11 +82,12 @@ import ( "github.com/astaxie/beego" ) -// operations for {{controllerName}} +// {{controllerName}}Controller operations for {{controllerName}} type {{controllerName}}Controller struct { beego.Controller } +// URLMapping ... func (c *{{controllerName}}Controller) URLMapping() { c.Mapping("Post", c.Post) c.Mapping("GetOne", c.GetOne) @@ -95,6 +96,7 @@ func (c *{{controllerName}}Controller) URLMapping() { c.Mapping("Delete", c.Delete) } +// Post ... // @Title Create // @Description create {{controllerName}} // @Param body body models.{{controllerName}} true "body for {{controllerName}} content" @@ -105,6 +107,7 @@ func (c *{{controllerName}}Controller) Post() { } +// GetOne ... // @Title GetOne // @Description get {{controllerName}} by id // @Param id path string true "The key for staticblock" @@ -115,6 +118,7 @@ func (c *{{controllerName}}Controller) GetOne() { } +// GetAll ... // @Title GetAll // @Description get {{controllerName}} // @Param query query string false "Filter. e.g. col1:v1,col2:v2 ..." @@ -130,6 +134,7 @@ func (c *{{controllerName}}Controller) GetAll() { } +// Update ... // @Title Update // @Description update the {{controllerName}} // @Param id path string true "The id you want to update" @@ -141,6 +146,7 @@ func (c *{{controllerName}}Controller) Put() { } +// Delete ... // @Title Delete // @Description delete the {{controllerName}} // @Param id path string true "The id you want to delete" @@ -164,11 +170,12 @@ import ( "github.com/astaxie/beego" ) -// oprations for {{controllerName}} +// {{controllerName}}Controller oprations for {{controllerName}} type {{controllerName}}Controller struct { beego.Controller } +// URLMapping ... func (c *{{controllerName}}Controller) URLMapping() { c.Mapping("Post", c.Post) c.Mapping("GetOne", c.GetOne) @@ -177,6 +184,7 @@ func (c *{{controllerName}}Controller) URLMapping() { c.Mapping("Delete", c.Delete) } +// Post ... // @Title Post // @Description create {{controllerName}} // @Param body body models.{{controllerName}} true "body for {{controllerName}} content" @@ -195,6 +203,7 @@ func (c *{{controllerName}}Controller) Post() { c.ServeJSON() } +// Get ... // @Title Get // @Description get {{controllerName}} by id // @Param id path string true "The key for staticblock" @@ -213,6 +222,7 @@ func (c *{{controllerName}}Controller) GetOne() { c.ServeJSON() } +// GetAll ... // @Title Get All // @Description get {{controllerName}} // @Param query query string false "Filter. e.g. col1:v1,col2:v2 ..." @@ -275,6 +285,7 @@ func (c *{{controllerName}}Controller) GetAll() { c.ServeJSON() } +// Update ... // @Title Update // @Description update the {{controllerName}} // @Param id path string true "The id you want to update" @@ -295,6 +306,7 @@ func (c *{{controllerName}}Controller) Put() { c.ServeJSON() } +// Delete ... // @Title Delete // @Description delete the {{controllerName}} // @Param id path string true "The id you want to delete" From 411aa430805140f9b56b5adbf71a295e189399d6 Mon Sep 17 00:00:00 2001 From: ZetaChow Date: Fri, 9 Sep 2016 15:27:36 +0800 Subject: [PATCH 116/123] =?UTF-8?q?=E4=BF=AE=E6=94=B9PUT=E5=92=8CGet=20One?= =?UTF-8?q?=20=E9=94=99=E8=AF=AF=E7=9A=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g_appcode.go | 8 ++++---- g_controllers.go | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/g_appcode.go b/g_appcode.go index 5d44663..9276360 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -1204,8 +1204,8 @@ func (c *{{ctrlName}}Controller) Post() { c.ServeJSON() } -// Get ... -// @Title Get +// GetOne ... +// @Title Get One // @Description get {{ctrlName}} by id // @Param id path string true "The key for staticblock" // @Success 200 {object} models.{{ctrlName}} @@ -1286,8 +1286,8 @@ func (c *{{ctrlName}}Controller) GetAll() { c.ServeJSON() } -// Update ... -// @Title Update +// Put ... +// @Title Put // @Description update the {{ctrlName}} // @Param id path string true "The id you want to update" // @Param body body models.{{ctrlName}} true "body for {{ctrlName}} content" diff --git a/g_controllers.go b/g_controllers.go index 15ab0bd..7c782b6 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -134,8 +134,8 @@ func (c *{{controllerName}}Controller) GetAll() { } -// Update ... -// @Title Update +// Put ... +// @Title Put // @Description update the {{controllerName}} // @Param id path string true "The id you want to update" // @Param body body models.{{controllerName}} true "body for {{controllerName}} content" @@ -203,8 +203,8 @@ func (c *{{controllerName}}Controller) Post() { c.ServeJSON() } -// Get ... -// @Title Get +// GetOne ... +// @Title Get One // @Description get {{controllerName}} by id // @Param id path string true "The key for staticblock" // @Success 200 {object} models.{{controllerName}} @@ -285,8 +285,8 @@ func (c *{{controllerName}}Controller) GetAll() { c.ServeJSON() } -// Update ... -// @Title Update +// Put ... +// @Title Put // @Description update the {{controllerName}} // @Param id path string true "The id you want to update" // @Param body body models.{{controllerName}} true "body for {{controllerName}} content" From 0d0bea81bf67f667ec45441e07a1f94a74a881a3 Mon Sep 17 00:00:00 2001 From: ZetaChow Date: Fri, 9 Sep 2016 15:38:44 +0800 Subject: [PATCH 117/123] =?UTF-8?q?=E5=8E=BB=E6=8E=89offset(int64)?= =?UTF-8?q?=E8=B5=8B0=E5=80=BC,=E5=8E=BB=E6=8E=89query=20(map[...]...)?= =?UTF-8?q?=E5=AE=9A=E4=B9=89,=E4=BB=A5=E7=AC=A6=E5=90=88Lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g_appcode.go | 4 ++-- g_controllers.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/g_appcode.go b/g_appcode.go index 9276360..4e90107 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -1239,9 +1239,9 @@ func (c *{{ctrlName}}Controller) GetAll() { var fields []string var sortby []string var order []string - var query map[string]string = make(map[string]string) + var query = make(map[string]string) var limit int64 = 10 - var offset int64 = 0 + var offset int64 // fields: col1,col2,entity.col3 if v := c.GetString("fields"); v != "" { diff --git a/g_controllers.go b/g_controllers.go index 7c782b6..9d0b0ae 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -238,9 +238,9 @@ func (c *{{controllerName}}Controller) GetAll() { var fields []string var sortby []string var order []string - var query map[string]string = make(map[string]string) + var query = make(map[string]string) var limit int64 = 10 - var offset int64 = 0 + var offset int64 // fields: col1,col2,entity.col3 if v := c.GetString("fields"); v != "" { From 1b75ccb9fe595062cc147586ad55364718fa7729 Mon Sep 17 00:00:00 2001 From: Sergey Lanzman Date: Thu, 15 Sep 2016 00:09:54 +0300 Subject: [PATCH 118/123] Improve swagger (Main params,yaml --- g_docs.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/g_docs.go b/g_docs.go index 83bca73..cd1b958 100644 --- a/g_docs.go +++ b/g_docs.go @@ -31,6 +31,8 @@ import ( "strings" "unicode" + "gopkg.in/yaml.v2" + "github.com/astaxie/beego/swagger" "github.com/astaxie/beego/utils" ) @@ -83,10 +85,18 @@ func generateDocs(curpath string) { rootapi.Infos.TermsOfService = strings.TrimSpace(s[len("@TermsOfServiceUrl"):]) } else if strings.HasPrefix(s, "@Contact") { rootapi.Infos.Contact.EMail = strings.TrimSpace(s[len("@Contact"):]) + } else if strings.HasPrefix(s, "@Name") { + rootapi.Infos.Contact.Name = strings.TrimSpace(s[len("@Name"):]) + } else if strings.HasPrefix(s, "@URL") { + rootapi.Infos.Contact.URL = strings.TrimSpace(s[len("@URL"):]) } else if strings.HasPrefix(s, "@License") { rootapi.Infos.License.Name = strings.TrimSpace(s[len("@License"):]) } else if strings.HasPrefix(s, "@LicenseUrl") { rootapi.Infos.License.URL = strings.TrimSpace(s[len("@LicenseUrl"):]) + } else if strings.HasPrefix(s, "@Schemes") { + rootapi.Schemes = strings.Split(strings.TrimSpace(s[len("@Schemes"):]), ",") + } else if strings.HasPrefix(s, "@Host") { + rootapi.Host = strings.TrimSpace(s[len("@Host"):]) } } } @@ -155,16 +165,20 @@ func generateDocs(curpath string) { } os.Mkdir(path.Join(curpath, "swagger"), 0755) fd, err := os.Create(path.Join(curpath, "swagger", "swagger.json")) + fdyml, err := os.Create(path.Join(curpath, "swagger", "swagger.yml")) if err != nil { panic(err) } + defer fdyml.Close() defer fd.Close() dt, err := json.MarshalIndent(rootapi, "", " ") - if err != nil { + dtyml, erryml := yaml.Marshal(rootapi) + if err != nil || erryml != nil { panic(err) } _, err = fd.Write(dt) - if err != nil { + _, erryml = fdyml.Write(dtyml) + if err != nil || erryml != nil { panic(err) } } From b282761292e7c51e4ac8e8daac16ec54f7ea5619 Mon Sep 17 00:00:00 2001 From: OTER Date: Thu, 15 Sep 2016 22:40:03 +0300 Subject: [PATCH 119/123] Fix .exe postfix issue on Windows platform. --- migrate.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/migrate.go b/migrate.go index a32cc8e..22bfac3 100644 --- a/migrate.go +++ b/migrate.go @@ -23,6 +23,7 @@ import ( "strconv" "strings" "time" + "runtime" ) var cmdMigrate = &Command{ @@ -145,8 +146,12 @@ func migrateRefresh(currpath, driver, connStr string) { // migrate generates source code, build it, and invoke the binary who does the actual migration func migrate(goal, currpath, driver, connStr string) { - dir := path.Join(currpath, "database", "migrations") - binary := "m" + dir := path.Join(currpath, "database", "migrations") + postfix := "" + if runtime.GOOS == "windows" { + postfix = ".exe" + } + binary := "m" + postfix source := binary + ".go" // connect to database db, err := sql.Open(driver, connStr) From 465115c28e20d837922b7b64b8f8671cc609bdeb Mon Sep 17 00:00:00 2001 From: Filip Date: Sat, 17 Sep 2016 21:54:00 +0200 Subject: [PATCH 120/123] Fix incorrect generation of postgres table id type --- g_migration.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/g_migration.go b/g_migration.go index c0485ef..ed3dfc4 100644 --- a/g_migration.go +++ b/g_migration.go @@ -129,7 +129,7 @@ func (m postgresqlDriver) generateSQLFromFields(fields string) string { return "" } if i == 0 && strings.ToLower(kv[0]) != "id" { - sql += "id interger serial primary key," + sql += "id serial primary key," } sql += snakeString(kv[0]) + " " + typ + "," if tag != "" { From 205428abcead96aac3aaf3fa8f8fe8ca5be1eff2 Mon Sep 17 00:00:00 2001 From: astaxie Date: Thu, 22 Sep 2016 22:26:39 +0800 Subject: [PATCH 121/123] fix the licence issue --- g_docs.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/g_docs.go b/g_docs.go index cd1b958..8a7f99d 100644 --- a/g_docs.go +++ b/g_docs.go @@ -90,9 +90,17 @@ func generateDocs(curpath string) { } else if strings.HasPrefix(s, "@URL") { rootapi.Infos.Contact.URL = strings.TrimSpace(s[len("@URL"):]) } else if strings.HasPrefix(s, "@License") { - rootapi.Infos.License.Name = strings.TrimSpace(s[len("@License"):]) + if rootapi.Infos.License == nil { + rootapi.Infos.License = &swagger.License{Name: strings.TrimSpace(s[len("@License"):])} + } else { + rootapi.Infos.License.Name = strings.TrimSpace(s[len("@License"):]) + } } else if strings.HasPrefix(s, "@LicenseUrl") { - rootapi.Infos.License.URL = strings.TrimSpace(s[len("@LicenseUrl"):]) + if rootapi.Infos.License == nil { + rootapi.Infos.License = &swagger.License{URL: strings.TrimSpace(s[len("@LicenseUrl"):])} + } else { + rootapi.Infos.License.URL = strings.TrimSpace(s[len("@LicenseUrl"):]) + } } else if strings.HasPrefix(s, "@Schemes") { rootapi.Schemes = strings.Split(strings.TrimSpace(s[len("@Schemes"):]), ",") } else if strings.HasPrefix(s, "@Host") { From 29c9e1bab765bd1b360edfbc1e3a6d8a50571206 Mon Sep 17 00:00:00 2001 From: astaxie Date: Thu, 22 Sep 2016 23:04:58 +0800 Subject: [PATCH 122/123] fix the map type generate --- g_docs.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/g_docs.go b/g_docs.go index 8a7f99d..a92c917 100644 --- a/g_docs.go +++ b/g_docs.go @@ -683,12 +683,18 @@ func parseObject(d *ast.Object, k string, m *swagger.Schema, realTypes *[]string } } } else { - if isBasicType(realType) { + if sType == "object" { + mp.Ref = "#/definitions/" + realType + } else if isBasicType(realType) { typeFormat := strings.Split(sType, ":") mp.Type = typeFormat[0] mp.Format = typeFormat[1] - } else if sType == "object" { - mp.Ref = "#/definitions/" + realType + } else if realType == "map" { + typeFormat := strings.Split(sType, ":") + mp.AdditionalProperties = &swagger.Propertie{ + Type: typeFormat[0], + Format: typeFormat[1], + } } } if field.Names != nil { @@ -768,7 +774,11 @@ func typeAnalyser(f *ast.Field) (isSlice bool, realType, swaggerType string) { case *ast.StarExpr: return false, fmt.Sprint(t.X), "object" case *ast.MapType: - return false, fmt.Sprint(t.Value), "object" + val := fmt.Sprintf("%v", t.Value) + if isBasicType(val) { + return false, "map", basicTypes[val] + } + return false, val, "object" } if k, ok := basicTypes[fmt.Sprint(f.Type)]; ok { return false, fmt.Sprint(f.Type), k From f7d2e04e070140f9ebee4f02c89f00f312c5e0a2 Mon Sep 17 00:00:00 2001 From: astaxie Date: Thu, 22 Sep 2016 23:12:55 +0800 Subject: [PATCH 123/123] change to 1.5.2 --- bee.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bee.go b/bee.go index 76c5359..f89e791 100644 --- a/bee.go +++ b/bee.go @@ -25,7 +25,7 @@ import ( "strings" ) -const version = "1.5.1" +const version = "1.5.2" type Command struct { // Run runs the command.