diff --git a/apiapp.go b/apiapp.go index 4c39c96..3e2a9be 100644 --- a/apiapp.go +++ b/apiapp.go @@ -24,39 +24,34 @@ import ( var cmdApiapp = &Command{ // CustomFlags: true, UsageLine: "api [appname]", - Short: "create an API beego application", + Short: "Creates a Beego API application", Long: ` -Create an API beego application. + The command 'api' creates a Beego API application. -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] (default: 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 + {{"Example:"|bold}} + $ bee api [appname] [-tables=""] [-driver=mysql] [-conn=root:@tcp(127.0.0.1:3306)/test] -If 'conn' argument is empty, bee api creates an example API application, -when 'conn' argument is provided, bee api generates an API application based -on the existing database. + If 'conn' argument is empty, the command will generate an example API application. Otherwise the command + will connect to your database and generate models based on the existing tables. -The command 'api' creates a folder named [appname] and inside the folder deploy -the following files/directories structure: - - ├── conf - │ └── app.conf - ├── controllers - │ └── object.go - │ └── user.go - ├── routers - │ └── router.go - ├── tests - │ └── default_test.go - ├── main.go - └── models - └── object.go - └── user.go + The command 'api' creates a folder named [appname] with the following structure: + ├── main.go + ├── {{"conf"|foldername}} + │ └── app.conf + ├── {{"controllers"|foldername}} + │ └── object.go + │ └── user.go + ├── {{"routers"|foldername}} + │ └── router.go + ├── {{"tests"|foldername}} + │ └── default_test.go + └── {{"models"|foldername}} + └── object.go + └── user.go `, + PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() }, + Run: createapi, } var apiconf = `appname = {{.Appname}} @@ -537,15 +532,13 @@ func TestGet(t *testing.T) { ` func init() { - cmdApiapp.Run = createapi - cmdApiapp.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() } - cmdApiapp.Flag.Var(&tables, "tables", "specify tables to generate model") - cmdApiapp.Flag.Var(&driver, "driver", "database driver: mysql, postgresql, etc.") - cmdApiapp.Flag.Var(&conn, "conn", "connection string used by the driver to connect to a database instance") + cmdApiapp.Flag.Var(&tables, "tables", "List of table names separated by a comma.") + cmdApiapp.Flag.Var(&driver, "driver", "Database driver. Either mysql, postgres or sqlite.") + cmdApiapp.Flag.Var(&conn, "conn", "Connection string used by the driver to connect to a database instance.") } func createapi(cmd *Command, args []string) int { - w := NewColorWriter(os.Stdout) + output := cmd.Out() if len(args) < 1 { logger.Fatal("Argument [appname] is missing") @@ -568,19 +561,19 @@ func createapi(cmd *Command, args []string) int { logger.Info("Creating API...") os.MkdirAll(apppath, 0755) - fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m") + fmt.Fprintf(output, "\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.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf"), "\x1b[0m") + fmt.Fprintf(output, "\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") + fmt.Fprintf(output, "\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, "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") + fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests"), "\x1b[0m") + fmt.Fprintf(output, "\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.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m") + fmt.Fprintf(output, "\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" { @@ -602,33 +595,33 @@ func createapi(cmd *Command, args []string) int { 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") + fmt.Fprintf(output, "\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.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.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers")+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, "controllers", "object.go"), "\x1b[0m") + fmt.Fprintf(output, "\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.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "user.go"), "\x1b[0m") + fmt.Fprintf(output, "\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.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") + fmt.Fprintf(output, "\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.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m") + fmt.Fprintf(output, "\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.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "object.go"), "\x1b[0m") + fmt.Fprintf(output, "\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.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "user.go"), "\x1b[0m") + fmt.Fprintf(output, "\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, "main.go"), "\x1b[0m") + fmt.Fprintf(output, "\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/bale.go b/bale.go index e7a9aa1..2cd6667 100644 --- a/bale.go +++ b/bale.go @@ -28,22 +28,17 @@ import ( var cmdBale = &Command{ UsageLine: "bale", - Short: "packs non-Go files to Go source files", - Long: ` -Bale command compress all the static files in to a single binary file. + Short: "Transforms non-Go files to Go source files", + Long: `Bale command compress all the static files in to a single binary file. -This is useful to not have to carry static files including js, css, images -and views when publishing a project. - -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. + This is useful to not have to carry static files including js, css, images and + views when deploying a Web application. + It will auto-generate an unpack function to the main package then run it during the runtime. + This is mainly used for zealots who are requiring 100% Go code. `, -} - -func init() { - cmdBale.Run = runBale - cmdBale.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() } + PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() }, + Run: runBale, } func runBale(cmd *Command, args []string) int { diff --git a/bee.go b/bee.go index 11e14fd..397ce9d 100644 --- a/bee.go +++ b/bee.go @@ -18,11 +18,11 @@ package main import ( "flag" "fmt" - "html/template" "io" "log" "os" "strings" + "text/template" ) const version = "1.5.2" @@ -41,10 +41,10 @@ type Command struct { UsageLine string // Short is the short description shown in the 'go help' output. - Short template.HTML + Short string // Long is the long message shown in the 'go help ' output. - Long template.HTML + Long string // Flag is a set of flags specific to this command. Flag flag.FlagSet @@ -52,6 +52,9 @@ type Command struct { // CustomFlags indicates that the command will do its own // flag parsing. CustomFlags bool + + // output out writer if set in SetOutput(w) + output *io.Writer } // Name returns the command's name: the first word in the usage line. @@ -64,10 +67,24 @@ func (c *Command) Name() string { return name } +// SetOutput sets the destination for usage and error messages. +// If output is nil, os.Stderr is used. +func (c *Command) SetOutput(output io.Writer) { + c.output = &output +} + +// Out returns the out writer of the current command. +// If cmd.output is nil, os.Stderr is used. +func (c *Command) Out() io.Writer { + if c.output != nil { + return *c.output + } + return NewColorWriter(os.Stderr) +} + // Usage puts out the usage for the command. func (c *Command) Usage() { - fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine) - fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(string(c.Long))) + tmpl(cmdUsage, c) os.Exit(2) } @@ -77,7 +94,25 @@ func (c *Command) Runnable() bool { return c.Run != nil } -var commands = []*Command{ +func (c *Command) Options() map[string]string { + options := make(map[string]string) + c.Flag.VisitAll(func(f *flag.Flag) { + defaultVal := f.DefValue + if len(defaultVal) > 0 { + if strings.Contains(defaultVal, ":") { + // Truncate the flag's default value by appending '...' at the end + options[f.Name+"="+strings.Split(defaultVal, ":")[0]+":..."] = f.Usage + } else { + options[f.Name+"="+defaultVal] = f.Usage + } + } else { + options[f.Name] = f.Usage + } + }) + return options +} + +var availableCommands = []*Command{ cmdNew, cmdRun, cmdPack, @@ -103,6 +138,7 @@ func main() { log.SetFlags(0) args := flag.Args() + if len(args) < 1 { usage() } @@ -112,7 +148,7 @@ func main() { return } - for _, cmd := range commands { + for _, cmd := range availableCommands { if cmd.Name() == args[0] && cmd.Run != nil { cmd.Flag.Usage = func() { cmd.Usage() } if cmd.CustomFlags { @@ -137,71 +173,76 @@ func main() { } } - fmt.Fprintf(os.Stderr, "bee: unknown subcommand %q\nRun 'bee help' for usage.\n", args[0]) - os.Exit(2) + printErrorAndExit("Unknown subcommand") } -var usageTemplate = `Bee is a tool for managing beego framework. +var usageTemplate = `Bee is a Fast and Flexible tool for managing your Beego Web Application. -Usage: +{{"USAGE" | headline}} + {{"bee command [arguments]" | bold}} - bee command [arguments] - -The commands are: +{{"AVAILABLE COMMANDS" | headline}} {{range .}}{{if .Runnable}} - {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}} + {{.Name | printf "%-11s" | bold}} {{.Short}}{{end}}{{end}} -Use "bee help [command]" for more information about a command. +Use {{"bee help [command]" | bold}} for more information about a command. -Additional help topics: +{{"ADDITIONAL HELP TOPICS" | headline}} {{range .}}{{if not .Runnable}} {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}} -Use "bee help [topic]" for more information about that topic. +Use {{"bee help [topic]" | bold}} for more information about that topic. ` -var helpTemplate = `{{if .Runnable}}usage: bee {{.UsageLine}} - -{{end}}{{.Long | trim}} +var helpTemplate = `{{"USAGE" | headline}} + {{.UsageLine | printf "bee %s" | bold}} +{{if .Options}}{{endline}}{{"OPTIONS" | headline}}{{range $k,$v := .Options}} + {{$k | printf "-%-12s" | bold}} {{$v}}{{end}}{{endline}}{{end}} +{{"DESCRIPTION" | headline}} + {{tmpltostr .Long . | trim}} ` +var errorTemplate = `bee: %s. +Use {{"bee help" | bold}} for more information. +` + +var cmdUsage = `Use {{printf "bee help %s" .Name | bold}} for more information.{{endline}}` + func usage() { - tmpl(os.Stdout, usageTemplate, commands) + tmpl(usageTemplate, availableCommands) os.Exit(2) } -func tmpl(w io.Writer, text string, data interface{}) { - t := template.New("top") - t.Funcs(template.FuncMap{"trim": func(s template.HTML) template.HTML { - return template.HTML(strings.TrimSpace(string(s))) - }}) +func tmpl(text string, data interface{}) { + output := NewColorWriter(os.Stderr) + + t := template.New("usage").Funcs(BeeFuncMap()) template.Must(t.Parse(text)) - if err := t.Execute(w, data); err != nil { - panic(err) - } + + err := t.Execute(output, data) + MustCheck(err) } func help(args []string) { if len(args) == 0 { usage() - // not exit 2: succeeded at 'go help'. - return } if len(args) != 1 { - fmt.Fprintf(os.Stdout, "usage: bee help command\n\nToo many arguments given.\n") - os.Exit(2) // failed at 'bee help' + printErrorAndExit("Too many arguments") } arg := args[0] - for _, cmd := range commands { + for _, cmd := range availableCommands { if cmd.Name() == arg { - tmpl(os.Stdout, helpTemplate, cmd) - // not exit 2: succeeded at 'go help cmd'. + tmpl(helpTemplate, cmd) return } } - - fmt.Fprintf(os.Stdout, "Unknown help topic %#q. Run 'bee help'.\n", arg) - os.Exit(2) // failed at 'bee help cmd' + printErrorAndExit("Unknown help topic") +} + +func printErrorAndExit(message string) { + tmpl(fmt.Sprintf(errorTemplate, message), nil) + os.Exit(2) } diff --git a/fix.go b/fix.go index 929297c..13453e6 100644 --- a/fix.go +++ b/fix.go @@ -13,11 +13,11 @@ import ( var cmdFix = &Command{ UsageLine: "fix", - 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. + Short: "Fixes your application by making it compatible with newer versions of Beego", + Long: `As of {{"Beego 1.6"|bold}}, there are some backward compatibility issues. -bee fix help to upgrade the application to beego 1.6 + The command 'fix' will try to solve those issues by upgrading your code base + to be compatible with Beego version 1.6+. `, } @@ -27,6 +27,8 @@ func init() { } func runFix(cmd *Command, args []string) int { + output := cmd.Out() + logger.Info("Upgrading the application...") dir, err := os.Getwd() @@ -48,13 +50,13 @@ func runFix(cmd *Command, args []string) int { return nil } err = fixFile(path) - fmt.Println("\tfix\t", path) + fmt.Fprintf(output, GreenBold("\tfix\t")+"%s\n", path) if err != nil { logger.Errorf("Could not fix file: %s", err) } return err }) - logger.Success("Upgrade done!") + logger.Success("Upgrade Done!") return 0 } diff --git a/g.go b/g.go index e25bdb1..8c133d9 100644 --- a/g.go +++ b/g.go @@ -20,45 +20,42 @@ import ( ) var cmdGenerate = &Command{ - UsageLine: "generate [Command]", - Short: "source code generator", - Long: ` -bee generate scaffold [scaffoldname] [-fields=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] - The generate scaffold command will do a number of things for you. - -fields: a list of 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" + UsageLine: "generate [command]", + Short: "Source code generator", + Long: `▶ {{"To scaffold out your entire application:"|bold}} -bee generate model [modelname] [-fields=""] - generate RESTFul model based on fields - -fields: a list of table fields. Format: field:type, ... + $ bee generate scaffold [scaffoldname] [-fields="title:string,body:text"] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] -bee generate controller [controllerfile] - generate RESTful controllers + ▶ {{"To generate a Model based on fields:"|bold}} -bee generate view [viewpath] - generate CRUD view in viewpath + $ bee generate model [modelname] [-fields="name:type"] -bee generate migration [migrationfile] [-fields=""] - generate migration file for making database schema update - -fields: a list of table fields. Format: field:type, ... + ▶ {{"To generate a controller:"|bold}} -bee generate docs - generate swagger doc file + $ bee generate controller [controllerfile] -bee generate test [routerfile] - generate testcase + ▶ {{"To generate a CRUD view:"|bold}} -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 view [viewpath] + + ▶ {{"To generate a migration file for making database schema updates:"|bold}} + + $ bee generate migration [migrationfile] [-fields="name:type"] + + ▶ {{"To generate swagger doc file:"|bold}} + + $ bee generate docs + + ▶ {{"To generate a test case:"|bold}} + + $ bee generate test [routerfile] + + ▶ {{"To generate appcode based on an existing database:"|bold}} + + $ bee generate appcode [-tables=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] [-level=3] `, + PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() }, + Run: generateCode, } var driver docValue @@ -68,13 +65,11 @@ var tables docValue var fields docValue func init() { - cmdGenerate.Run = generateCode - cmdGenerate.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() } - cmdGenerate.Flag.Var(&tables, "tables", "specify tables to generate model") - cmdGenerate.Flag.Var(&driver, "driver", "database driver: mysql, postgresql, etc.") - cmdGenerate.Flag.Var(&conn, "conn", "connection string used by the driver to connect to a database instance") - cmdGenerate.Flag.Var(&level, "level", "1 = models only; 2 = models and controllers; 3 = models, controllers and routers") - cmdGenerate.Flag.Var(&fields, "fields", "specify the fields want to generate.") + cmdGenerate.Flag.Var(&tables, "tables", "List of table names separated by a comma.") + cmdGenerate.Flag.Var(&driver, "driver", "Database driver. Either mysql, postgres or sqlite.") + cmdGenerate.Flag.Var(&conn, "conn", "Connection string used by the driver to connect to a database instance.") + cmdGenerate.Flag.Var(&level, "level", "Either 1, 2 or 3. i.e. 1=models; 2=models and controllers; 3=models, controllers and routers.") + cmdGenerate.Flag.Var(&fields, "fields", "List of table fields.") } func generateCode(cmd *Command, args []string) int { diff --git a/hproseapp.go b/hproseapp.go index 6b2cf6f..edd01b1 100644 --- a/hproseapp.go +++ b/hproseapp.go @@ -1,19 +1,16 @@ -/**********************************************************\ -| | -| hprose | -| | -| Official WebSite: http://www.hprose.com/ | -| http://www.hprose.org/ | -| | -\**********************************************************/ -/**********************************************************\ - * * - * Build rpc application use Hprose base on beego * - * * - * LastModified: Oct 31, 2016 * - * Author: Liu jian * - * * -\**********************************************************/ +// 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 @@ -27,30 +24,28 @@ import ( var cmdHproseapp = &Command{ // CustomFlags: true, UsageLine: "hprose [appname]", - Short: "create an rpc application use hprose base on beego framework", + Short: "Creates an RPC application based on Hprose and Beego frameworks", Long: ` -create an rpc application use hprose base on beego framework + The command 'hprose' creates an RPC application based on both Beego and Hprose (http://hprose.com/). -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 + {{"To scaffold out your application, use:"|bold}} -if conn is empty will create a example rpc application. otherwise generate rpc application use hprose based on an existing database. + $ bee hprose [appname] [-tables=""] [-driver=mysql] [-conn=root:@tcp(127.0.0.1:3306)/test] -In the current path, will create a folder named [appname] + If 'conn' is empty, the command will generate a sample application. Otherwise the command + will connect to your database and generate models based on the existing tables. -In the appname folder has the follow struct: + The command 'hprose' creates a folder named [appname] with the following structure: - ├── conf - │ └── app.conf - ├── main.go - └── models - └── object.go - └── user.go + ├── main.go + ├── {{"conf"|foldername}} + │ └── app.conf + └── {{"models"|foldername}} + └── object.go + └── user.go `, + PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() }, + Run: createhprose, } var hproseconf = `appname = {{.Appname}} @@ -297,15 +292,13 @@ func DeleteUser(uid string) { var hproseAddFunctions = []string{} func init() { - cmdHproseapp.Run = createhprose - cmdHproseapp.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() } - cmdHproseapp.Flag.Var(&tables, "tables", "specify tables to generate model") - cmdHproseapp.Flag.Var(&driver, "driver", "database driver: mysql, postgresql, etc.") - cmdHproseapp.Flag.Var(&conn, "conn", "connection string used by the driver to connect to a database instance") + cmdHproseapp.Flag.Var(&tables, "tables", "List of table names separated by a comma.") + cmdHproseapp.Flag.Var(&driver, "driver", "Database driver. Either mysql, postgres or sqlite.") + cmdHproseapp.Flag.Var(&conn, "conn", "Connection string used by the driver to connect to a database instance.") } func createhprose(cmd *Command, args []string) int { - w := NewColorWriter(os.Stdout) + output := cmd.Out() curpath, _ := os.Getwd() if len(args) > 1 { @@ -324,10 +317,10 @@ func createhprose(cmd *Command, args []string) int { logger.Info("Creating Hprose application...") os.MkdirAll(apppath, 0755) - fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m") + fmt.Fprintf(output, "\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.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") + fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf"), "\x1b[0m") + fmt.Fprintf(output, "\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)) @@ -336,7 +329,7 @@ func createhprose(cmd *Command, args []string) int { logger.Infof("Using '%s' as 'conn'", conn) logger.Infof("Using '%s' as 'tables'", tables) generateHproseAppcode(string(driver), string(conn), "1", string(tables), path.Join(curpath, args[0])) - fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m") + fmt.Fprintf(output, "\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) @@ -355,15 +348,15 @@ func createhprose(cmd *Command, args []string) int { ) } 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") + fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models"), "\x1b[0m") - 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") + fmt.Fprintf(output, "\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.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "user.go"), "\x1b[0m") + fmt.Fprintf(output, "\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, "main.go"), "\x1b[0m") + fmt.Fprintf(output, "\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 3d89991..5ef4681 100644 --- a/migrate.go +++ b/migrate.go @@ -27,38 +27,35 @@ import ( var cmdMigrate = &Command{ UsageLine: "migrate [Command]", - Short: "run database migrations", - Long: ` -bee migrate [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] - run all outstanding migrations - -driver: [mysql | postgres | sqlite] (default: mysql) - -conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test + Short: "Runs database migrations", + Long: `The command 'migrate' allows you to run database migrations to keep it up-to-date. -bee migrate rollback [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] - rollback the last migration operation - -driver: [mysql | postgres | sqlite] (default: mysql) - -conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test + ▶ {{"To run all the migrations:"|bold}} -bee migrate reset [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] - rollback all migrations - -driver: [mysql | postgres | sqlite] (default: mysql) - -conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test + $ bee migrate [-driver=mysql] [-conn="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 | postgres | sqlite] (default: mysql) - -conn: the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test + ▶ {{"To rollback the last migration:"|bold}} + + $ bee migrate rollback [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] + + ▶ {{"To do a reset, which will rollback all the migrations:"|bold}} + + $ bee migrate reset [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] + + ▶ {{"To update your schema:"|bold}} + + $ bee migrate refresh [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] `, + PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() }, + Run: runMigration, } var mDriver docValue var mConn docValue func init() { - cmdMigrate.Run = runMigration - cmdMigrate.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() } - cmdMigrate.Flag.Var(&mDriver, "driver", "database driver: mysql, postgres, sqlite, etc.") - cmdMigrate.Flag.Var(&mConn, "conn", "connection string used by the driver to connect to a database instance") + cmdMigrate.Flag.Var(&mDriver, "driver", "Database driver. Either mysql, postgres or sqlite.") + cmdMigrate.Flag.Var(&mConn, "conn", "Connection string used by the driver to connect to a database instance.") } // runMigration is the entry point for starting a migration diff --git a/new.go b/new.go index b8be305..eb3ab60 100644 --- a/new.go +++ b/new.go @@ -23,41 +23,36 @@ import ( var cmdNew = &Command{ UsageLine: "new [appname]", - Short: "Create a Beego application", + Short: "Creates a Beego application", Long: ` Creates a Beego application for the given app name in the current directory. -The command 'new' creates a folder named [appname] and inside the folder deploy -the following files/directories structure: + The command 'new' creates a folder named [appname] and generates the following structure: - |- main.go - |- conf - |- app.conf - |- controllers - |- default.go - |- models - |- routers - |- router.go - |- tests - |- default_test.go - |- static - |- js - |- css - |- img - |- views - index.tpl + ├── main.go + ├── {{"conf"|foldername}} + │ └── app.conf + ├── {{"controllers"|foldername}} + │ └── default.go + ├── {{"models"|foldername}} + ├── {{"routers"|foldername}} + │ └── router.go + ├── {{"tests"|foldername}} + │ └── default_test.go + ├── {{"static"|foldername}} + │ └── {{"js"|foldername}} + │ └── {{"css"|foldername}} + │ └── {{"img"|foldername}} + └── {{"views"|foldername}} + └── index.tpl `, -} - -func init() { - cmdNew.Run = createApp - cmdNew.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() } + PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() }, + Run: createApp, } func createApp(cmd *Command, args []string) int { - w := NewColorWriter(os.Stdout) - + output := cmd.Out() if len(args) != 1 { logger.Fatal("Argument [appname] is missing") } @@ -78,43 +73,43 @@ func createApp(cmd *Command, args []string) int { logger.Info("Creating application...") os.MkdirAll(apppath, 0755) - fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath+string(path.Separator), "\x1b[0m") + fmt.Fprintf(output, "\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.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") + fmt.Fprintf(output, "\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.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") + fmt.Fprintf(output, "\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.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") + fmt.Fprintf(output, "\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.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.Fprintf(output, "\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.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") + fmt.Fprintf(output, "\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.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") + fmt.Fprintf(output, "\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.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") + fmt.Fprintf(output, "\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.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") + fmt.Fprintf(output, "\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.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") + fmt.Fprintf(output, "\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(output, "\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.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m") + fmt.Fprintf(output, "\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.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "default.go"), "\x1b[0m") + fmt.Fprintf(output, "\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.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views", "index.tpl"), "\x1b[0m") + fmt.Fprintf(output, "\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.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m") + fmt.Fprintf(output, "\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}}", 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") + fmt.Fprintf(output, "\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}}", 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") + fmt.Fprintf(output, "\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}}", packpath, -1)) logger.Success("New application successfully created!") diff --git a/pack.go b/pack.go index 4e16086..75aaaa7 100644 --- a/pack.go +++ b/pack.go @@ -36,26 +36,15 @@ import ( var cmdPack = &Command{ CustomFlags: true, UsageLine: "pack", - Short: "Compress a beego project into a single file", - Long: ` -Pack is used to compress a beego project into a single file. -This eases the deployment by extracting the zip file to a server. + Short: "Compresses a Beego application into a single file", + Long: `Pack is used to compress Beego applications into a tarball/zip file. + This eases the deployment by directly extracting the file to a server. --p app path (default is the 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: .). 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). --ss=false skip symlink (default: false) - default embed symlink into compressed file --v=false verbose + {{"Example:"|bold}} + $ bee pack -v -ba="-ldflags '-s -w'" `, + PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() }, + Run: packApp, } var ( @@ -71,7 +60,6 @@ var ( buildEnvs ListOpts verbose bool format string - w io.Writer ) type ListOpts []string @@ -87,22 +75,19 @@ func (opts *ListOpts) Set(value string) error { func init() { fs := flag.NewFlagSet("pack", flag.ContinueOnError) - fs.StringVar(&appPath, "p", "", "app path. default is current path") - fs.BoolVar(&build, "b", true, "build specify platform app") - fs.StringVar(&buildArgs, "ba", "", "additional args of go build") - fs.Var(&buildEnvs, "be", "additional ENV Variables of go build. eg: GOARCH=arm") - fs.StringVar(&outputP, "o", "", "compressed file output dir. default use current path") - fs.StringVar(&format, "f", "tar.gz", "format. [ tar.gz / zip ]") - fs.StringVar(&excludeP, "exp", ".", "path exclude prefix. use : as separator") - fs.StringVar(&excludeS, "exs", ".go:.DS_Store:.tmp", "path exclude suffix. use : as separator") - fs.Var(&excludeR, "exr", "filename exclude by Regexp") - fs.BoolVar(&fsym, "fs", false, "follow symlink") - fs.BoolVar(&ssym, "ss", false, "skip symlink") - fs.BoolVar(&verbose, "v", false, "verbose") + fs.StringVar(&appPath, "p", "", "Set the application path. Defaults to the current path.") + fs.BoolVar(&build, "b", true, "Tell the command to do a build for the current platform. Defaults to true.") + fs.StringVar(&buildArgs, "ba", "", "Specify additional args for Go build.") + fs.Var(&buildEnvs, "be", "Specify additional env variables for Go build. e.g. GOARCH=arm.") + fs.StringVar(&outputP, "o", "", "Set the compressed file output path. Defaults to the current path.") + fs.StringVar(&format, "f", "tar.gz", "Set file format. Either tar.gz or zip. Defaults to tar.gz.") + fs.StringVar(&excludeP, "exp", ".", "Set prefixes of paths to be excluded. Uses a column (:) as separator.") + fs.StringVar(&excludeS, "exs", ".go:.DS_Store:.tmp", "Set suffixes of paths to be excluded. Uses a column (:) as separator.") + fs.Var(&excludeR, "exr", "Set a regular expression of files to be excluded.") + fs.BoolVar(&fsym, "fs", false, "Tell the command to follow symlinks. Defaults to false.") + fs.BoolVar(&ssym, "ss", false, "Tell the command to skip symlinks. Defaults to false.") + fs.BoolVar(&verbose, "v", false, "Be more verbose during the operation. Defaults to false.") cmdPack.Flag = *fs - cmdPack.Run = packApp - cmdPack.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() } - w = NewColorWriter(os.Stdout) } type walker interface { @@ -127,6 +112,7 @@ type walkFileTree struct { excludeRegexp []*regexp.Regexp excludeSuffix []string allfiles map[string]bool + output *io.Writer } func (wft *walkFileTree) setPrefix(prefix string) { @@ -239,7 +225,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.Fprintf(w, "\t%s%scompressed%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", name, "\x1b[0m") + fmt.Fprintf(*wft.output, "\t%s%scompressed%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", name, "\x1b[0m") } wft.allfiles[name] = true return err @@ -390,7 +376,7 @@ func (wft *zipWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) { return true, nil } -func packDirectory(excludePrefix []string, excludeSuffix []string, +func packDirectory(output io.Writer, excludePrefix []string, excludeSuffix []string, excludeRegexp []*regexp.Regexp, includePath ...string) (err error) { logger.Infof("Excluding relpath prefix: %s", strings.Join(excludePrefix, ":")) @@ -408,6 +394,7 @@ func packDirectory(excludePrefix []string, excludeSuffix []string, if format == "zip" { walk := new(zipWalk) + walk.output = &output zw := zip.NewWriter(w) defer func() { zw.Close() @@ -421,6 +408,7 @@ func packDirectory(excludePrefix []string, excludeSuffix []string, wft = walk } else { walk := new(tarWalk) + walk.output = &output cw := gzip.NewWriter(w) tw := tar.NewWriter(cw) @@ -450,6 +438,7 @@ func packDirectory(excludePrefix []string, excludeSuffix []string, } func packApp(cmd *Command, args []string) int { + output := cmd.Out() curPath, _ := os.Getwd() thePath := "" @@ -463,7 +452,7 @@ func packApp(cmd *Command, args []string) int { nArgs = append(nArgs, a) } } - cmdPack.Flag.Parse(nArgs) + cmd.Flag.Parse(nArgs) if path.IsAbs(appPath) == false { appPath = path.Join(curPath, appPath) @@ -532,7 +521,7 @@ func packApp(cmd *Command, args []string) int { } if verbose { - fmt.Fprintf(w, "\t%s%s+ go %s%s%s\n", "\x1b[32m", "\x1b[1m", strings.Join(args, " "), "\x1b[21m", "\x1b[0m") + fmt.Fprintf(output, "\t%s%s+ go %s%s%s\n", "\x1b[32m", "\x1b[1m", strings.Join(args, " "), "\x1b[21m", "\x1b[0m") } execmd := exec.Command("go", args...) @@ -545,7 +534,7 @@ func packApp(cmd *Command, args []string) int { logger.Fatal(err.Error()) } - logger.Success("Build successful!") + logger.Success("Build Successful!") } switch format { @@ -594,7 +583,7 @@ func packApp(cmd *Command, args []string) int { logger.Infof("Writing to output: %s", outputP) - err = packDirectory(exp, exs, exr, tmpdir, thePath) + err = packDirectory(output, exp, exs, exr, tmpdir, thePath) if err != nil { logger.Fatal(err.Error()) } diff --git a/run.go b/run.go index b7526e2..951cfa8 100644 --- a/run.go +++ b/run.go @@ -24,12 +24,13 @@ import ( var cmdRun = &Command{ 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", + Short: "Run the application by starting a local development server", Long: ` -Run command will supervise the file system of the beego project using inotify, -it will recompile and restart the app after any modifications. +Run command will supervise the filesystem of the application for any changes, and recompile/restart it. `, + PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() }, + Run: runApp, } var ( @@ -55,15 +56,13 @@ var ( ) func init() { - cmdRun.Run = runApp - cmdRun.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() } - 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/)") - cmdRun.Flag.StringVar(&runmode, "runmode", "", "Set BEEGO_RUNMODE env variable.") + cmdRun.Flag.Var(&mainFiles, "main", "Specify main go files.") + cmdRun.Flag.Var(&gendoc, "gendoc", "Enable auto-generate the docs.") + cmdRun.Flag.Var(&downdoc, "downdoc", "Enable auto-download of the swagger file if it does not exist.") + cmdRun.Flag.Var(&excludedPaths, "e", "List of paths to exclude.") + cmdRun.Flag.BoolVar(&vendorWatch, "vendor", false, "Enable watch vendor folder.") + cmdRun.Flag.StringVar(&buildTags, "tags", "", "Set the build tags. See: https://golang.org/pkg/go/build/") + cmdRun.Flag.StringVar(&runmode, "runmode", "", "Set the Beego run mode.") exit = make(chan bool) } diff --git a/util.go b/util.go index a13ade2..0893144 100644 --- a/util.go +++ b/util.go @@ -15,6 +15,7 @@ package main import ( + "bytes" "fmt" "io/ioutil" "os" @@ -24,6 +25,7 @@ import ( "regexp" "runtime" "strings" + "text/template" "time" ) @@ -281,3 +283,27 @@ func __LINE__() int { _, _, line, _ := runtime.Caller(1) return line } + +// BeeFuncMap returns a FuncMap of functions used in different templates. +func BeeFuncMap() template.FuncMap { + return template.FuncMap{ + "trim": strings.TrimSpace, + "bold": bold, + "headline": MagentaBold, + "foldername": RedBold, + "endline": EndLine, + "tmpltostr": TmplToString, + } +} + +// TmplToString parses a text template and return the result as a string. +func TmplToString(tmpl string, data interface{}) string { + t := template.New("tmpl").Funcs(BeeFuncMap()) + template.Must(t.Parse(tmpl)) + + var doc bytes.Buffer + err := t.Execute(&doc, data) + MustCheck(err) + + return doc.String() +} diff --git a/version.go b/version.go index 60dbfd7..721a885 100644 --- a/version.go +++ b/version.go @@ -14,9 +14,9 @@ import ( var cmdVersion = &Command{ UsageLine: "version", - Short: "prints the current Bee version", + Short: "Prints the current Bee version", Long: ` -Prints the current Bee, Beego and Go version alongside the platform information +Prints the current Bee, Beego and Go version alongside the platform information. `, }