diff --git a/apiapp.go b/apiapp.go index 892719b..6ecd3ae 100644 --- a/apiapp.go +++ b/apiapp.go @@ -549,8 +549,7 @@ func createapi(cmd *Command, args []string) int { w := NewColorWriter(os.Stdout) if len(args) < 1 { - ColorLog("[ERRO] Argument [appname] is missing\n") - os.Exit(2) + logger.Fatal("Argument [appname] is missing") } if len(args) > 1 { @@ -568,7 +567,7 @@ func createapi(cmd *Command, args []string) int { if conn == "" { } - ColorLog("[INFO] Creating API...\n") + 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") @@ -599,9 +598,9 @@ func createapi(cmd *Command, args []string) int { -1, ), ) - ColorLog("[INFO] Using '%s' as 'driver'\n", driver) - ColorLog("[INFO] Using '%s' as 'conn'\n", conn) - ColorLog("[INFO] Using '%s' as 'tables'\n", tables) + logger.Infof("Using '%s' as 'driver'", driver) + logger.Infof("Using '%s' as 'conn'", conn) + logger.Infof("Using '%s' as 'tables'", tables) generateAppcode(string(driver), string(conn), "3", string(tables), apppath) } else { os.Mkdir(path.Join(apppath, "models"), 0755) @@ -635,15 +634,14 @@ func createapi(cmd *Command, args []string) int { WriteToFile(path.Join(apppath, "main.go"), strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1)) } - ColorLog("[SUCC] New API successfully created!\n") + logger.Success("New API successfully created!") return 0 } func checkEnv(appname string) (apppath, packpath string, err error) { gps := GetGOPATHs() if len(gps) == 0 { - ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty") - os.Exit(2) + logger.Fatal("GOPATH environment variable is not set or empty") } currpath, _ := os.Getwd() currpath = path.Join(currpath, appname) @@ -658,15 +656,16 @@ func checkEnv(appname string) (apppath, packpath string, err error) { // 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) + + logger.Warn("You current workdir is not inside $GOPATH/src") + logger.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) + logger.Errorf("Path '%s' already exists", apppath) return } packpath = strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/") diff --git a/autorouter.go b/autorouter.go index 1273551..259f5da 100644 --- a/autorouter.go +++ b/autorouter.go @@ -66,7 +66,7 @@ func getControllerInfo(path string) (map[string][]string, error) { files := make([]*source, 0, len(fis)) for _, fi := range fis { - // Only load go files. + // Only load Go files if strings.HasSuffix(fi.Name(), ".go") { f, err := os.Open(path + "/" + fi.Name()) if err != nil { @@ -107,7 +107,7 @@ func getControllerInfo(path string) (map[string][]string, error) { return cm, nil } -// A source describles a source code file. +// source represents a source code file. type source struct { name string data []byte @@ -120,27 +120,25 @@ func (s *source) ModTime() time.Time { return time.Time{} } func (s *source) IsDir() bool { return false } func (s *source) Sys() interface{} { return nil } -// A routerWalker holds the state used when building the documentation. +// routerWalker holds the state used when building the documentation. type routerWalker struct { pdoc *Package - srcs map[string]*source // Source files. + srcs map[string]*source // Source files fset *token.FileSet - buf []byte // scratch space for printNode method. + buf []byte // scratch space for printNode method } // Package represents full information and documentation for a package. type Package struct { ImportPath string - - // Top-level declarations. - Types []*Type + Types []*Type // Top-level declarations } // Type represents structs and interfaces. type Type struct { - Name string // Type name. + Name string // Type name Decl string - Methods []*Func // Exported methods. + Methods []*Func // Exported methods } // Func represents functions @@ -150,7 +148,7 @@ type Func struct { // build generates data from source files. func (w *routerWalker) build(srcs []*source) (*Package, error) { - // Add source files to walker, I skipped references here. + // Add source files to walker, I skipped references here w.srcs = make(map[string]*source) for _, src := range srcs { w.srcs[src.name] = src @@ -158,7 +156,7 @@ func (w *routerWalker) build(srcs []*source) (*Package, error) { w.fset = token.NewFileSet() - // Find the package and associated files. + // Find the package and associated files ctxt := gobuild.Context{ GOOS: runtime.GOOS, GOARCH: runtime.GOARCH, @@ -174,7 +172,7 @@ func (w *routerWalker) build(srcs []*source) (*Package, error) { } bpkg, err := ctxt.ImportDir(w.pdoc.ImportPath, 0) - // Continue if there are no Go source files; we still want the directory info. + // Continue if there are no Go source files; we still want the directory info _, nogo := err.(*gobuild.NoGoError) if err != nil { if nogo { @@ -272,9 +270,8 @@ func simpleImporter(imports map[string]*ast.Object, path string) (*ast.Object, e name = strings.TrimPrefix(name, "biogo.") // It's also common for the last element of the path to contain an - // extra "go" prefix, but not always. TODO: examine unresolved ids to - // detect when trimming the "go" prefix is appropriate. - + // extra "go" prefix, but not always. + // TODO: examine unresolved ids to detect when trimming the "go" prefix is appropriate. pkg = ast.NewObj(ast.Pkg, name) pkg.Data = ast.NewScope(nil) imports[path] = pkg diff --git a/bale.go b/bale.go index 2bf14f9..df599b5 100644 --- a/bale.go +++ b/bale.go @@ -50,19 +50,19 @@ func runBale(cmd *Command, args []string) int { err := loadConfig() if err != nil { - ColorLog("[ERRO] Fail to parse bee.json[ %s ]\n", err) + logger.Fatalf("Failed to load configuration: %s", err) } os.RemoveAll("bale") os.Mkdir("bale", os.ModePerm) - // Pack and compress data. + // Pack and compress data for _, p := range conf.Bale.Dirs { if !isExist(p) { - ColorLog("[WARN] Skipped directory( %s )\n", p) + logger.Warnf("Skipped directory: %s", p) continue } - ColorLog("[INFO] Packaging directory( %s )\n", p) + logger.Infof("Packaging directory: %s", p) filepath.Walk(p, walkFn) } @@ -74,22 +74,21 @@ func runBale(cmd *Command, args []string) int { fw, err := os.Create("bale.go") if err != nil { - ColorLog("[ERRO] Fail to create file[ %s ]\n", err) - os.Exit(2) + logger.Fatalf("Failed to create file: %s", err) } defer fw.Close() _, err = fw.Write(buf.Bytes()) if err != nil { - ColorLog("[ERRO] Fail to write data[ %s ]\n", err) - os.Exit(2) + logger.Fatalf("Failed to write data: %s", err) } - ColorLog("[SUCC] Baled resources successfully!\n") + logger.Success("Baled resources successfully!") return 0 } const ( + // BaleHeader ... BaleHeader = `package main import( @@ -150,14 +149,13 @@ func walkFn(resPath string, info os.FileInfo, err error) error { return nil } - // Open resource files. + // Open resource files fr, err := os.Open(resPath) if err != nil { - ColorLog("[ERRO] Fail to read file[ %s ]\n", err) - os.Exit(2) + logger.Fatalf("Failed to read file: %s", err) } - // Convert path. + // Convert path resPath = strings.Replace(resPath, "_", "_0_", -1) resPath = strings.Replace(resPath, ".", "_1_", -1) resPath = strings.Replace(resPath, "-", "_2_", -1) @@ -168,19 +166,18 @@ func walkFn(resPath string, info os.FileInfo, err error) error { } resPath = strings.Replace(resPath, sep, "_4_", -1) - // Create corresponding Go source files. + // Create corresponding Go source files os.MkdirAll(path.Dir(resPath), os.ModePerm) fw, err := os.Create("bale/" + resPath + ".go") if err != nil { - ColorLog("[ERRO] Fail to create file[ %s ]\n", err) - os.Exit(2) + logger.Fatalf("Failed to create file: %s", err) } defer fw.Close() - // Write header. + // Write header fmt.Fprintf(fw, Header, resPath) - // Copy and compress data. + // Copy and compress data gz := gzip.NewWriter(&ByteWriter{Writer: fw}) io.Copy(gz, fr) gz.Close() @@ -202,6 +199,7 @@ func filterSuffix(name string) bool { } const ( + // Header ... Header = `package bale import( @@ -212,6 +210,7 @@ import( func R%s() []byte { gz, err := gzip.NewReader(bytes.NewBuffer([]byte{` + // Footer ... Footer = ` })) @@ -229,6 +228,7 @@ func R%s() []byte { var newline = []byte{'\n'} +// ByteWriter ... type ByteWriter struct { io.Writer c int @@ -244,12 +244,9 @@ func (w *ByteWriter) Write(p []byte) (n int, err error) { w.Writer.Write(newline) w.c = 0 } - fmt.Fprintf(w.Writer, "0x%02x,", p[n]) w.c++ } - n++ - return } diff --git a/banner.go b/banner.go index fefa37b..b9a4789 100644 --- a/banner.go +++ b/banner.go @@ -6,7 +6,6 @@ import ( "os" "runtime" "text/template" - "time" ) type vars struct { @@ -21,25 +20,17 @@ 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) -} - // 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) { if in == nil { - ColorLog("[ERRO] The input is nil\n") - os.Exit(2) + logger.Fatal("The input is nil") } 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) + logger.Fatalf("Error while trying to read the banner: %s", err) } show(out, string(banner)) @@ -51,9 +42,7 @@ func show(out io.Writer, content string) { Parse(content) if err != nil { - ColorLog("[ERRO] Cannot parse the banner template\n") - ColorLog("[HINT] %v\n", err) - os.Exit(2) + logger.Fatalf("Cannot parse the banner template: %s", err) } err = t.Execute(out, vars{ @@ -67,7 +56,5 @@ func show(out io.Writer, content string) { version, getBeegoVersion(), }) - if err != nil { - panic(err) - } + MustCheck(err) } diff --git a/bee.go b/bee.go index f89e791..4ae5111 100644 --- a/bee.go +++ b/bee.go @@ -27,6 +27,7 @@ import ( const version = "1.5.2" +// Command is the unit of execution type Command struct { // Run runs the command. // The args are the arguments after the command name. @@ -60,6 +61,7 @@ func (c *Command) Name() string { return name } +// 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))) diff --git a/code.go b/code.go index c341a74..335b021 100644 --- a/code.go +++ b/code.go @@ -109,12 +109,12 @@ func (v *annotationVisitor) Visit(n ast.Node) ast.Visitor { v.ignoreName() ast.Walk(v, n.Type) case *ast.Field: - for _ = range n.Names { + for range n.Names { v.ignoreName() } ast.Walk(v, n.Type) case *ast.ValueSpec: - for _ = range n.Names { + for range n.Names { v.add(AnchorAnnotation, "") } if n.Type != nil { diff --git a/conf.go b/conf.go index 68422bb..e02d701 100644 --- a/conf.go +++ b/conf.go @@ -25,7 +25,7 @@ import ( "gopkg.in/yaml.v2" ) -const ConfVer = 0 +const confVer = 0 var defaultConf = `{ "version": 0, @@ -89,20 +89,20 @@ func loadConfig() (err error) { } if fileInfo.Name() == "bee.json" { - ColorLog("[INFO] Loading configuration from 'bee.json'...\n") + logger.Info("Loading configuration from 'bee.json'...") err = parseJSON(path, conf) if err != nil { - ColorLog("[ERRO] Failed to parse JSON file: %v\n", err) + logger.Errorf("Failed to parse JSON file: %s", err) return err } return io.EOF } if fileInfo.Name() == "Beefile" { - ColorLog("[INFO] Loading configuration from 'Beefile'...\n") + logger.Info("Loading configuration from 'Beefile'...") err = parseYAML(path, conf) if err != nil { - ColorLog("[ERRO] Failed to parse YAML file: %v\n", err) + logger.Errorf("Failed to parse YAML file: %s", err) return err } return io.EOF @@ -113,7 +113,7 @@ func loadConfig() (err error) { // In case no configuration file found or an error different than io.EOF, // fallback to default configuration if err != io.EOF { - ColorLog("[INFO] Loading default configuration...\n") + logger.Info("Loading default configuration...") err = json.Unmarshal([]byte(defaultConf), &conf) if err != nil { return @@ -124,9 +124,9 @@ func loadConfig() (err error) { err = nil // Check format version - if conf.Version != ConfVer { - ColorLog("[WARN] Your bee.json is outdated. Please do consider updating it.\n") - ColorLog("[HINT] Compare bee.json under bee source code path and yours\n") + if conf.Version != confVer { + logger.Warn("Your configuration file is outdated. Please do consider updating it.") + logger.Hint("Check the latest version of bee's configuration file.") } // Set variables diff --git a/fix.go b/fix.go index e4adde6..60e166b 100644 --- a/fix.go +++ b/fix.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "go/parser" "go/token" "io/ioutil" @@ -8,7 +9,6 @@ import ( "path/filepath" "regexp" "strings" - "fmt" ) var cmdFix = &Command{ @@ -28,11 +28,12 @@ func init() { func runFix(cmd *Command, args []string) int { ShowShortVersionBanner() - ColorLog("[INFO] Upgrading the application...\n") + logger.Info("Upgrading the application...") dir, err := os.Getwd() if err != nil { - ColorLog("[ERRO] GetCurrent Path:%s\n", err) + logger.Fatalf("Error while getting the current working directory: %s", err) } + filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if info.IsDir() { if strings.HasPrefix(info.Name(), ".") { @@ -49,11 +50,11 @@ func runFix(cmd *Command, args []string) int { err = fixFile(path) fmt.Println("\tfix\t", path) if err != nil { - ColorLog("[ERRO] Could not fix file: %s\n", err) + logger.Errorf("Could not fix file: %s", err) } return err }) - ColorLog("[INFO] Upgrade done!\n") + logger.Success("Upgrade done!") return 0 } @@ -167,18 +168,18 @@ func fixFile(file string) error { } fixed := rp.Replace(string(content)) - // forword the RequestBody from the replace + // Forword the RequestBody from the replace // "Input.Request", "Input.Context.Request", fixed = strings.Replace(fixed, "Input.Context.RequestBody", "Input.RequestBody", -1) - // regexp replace + // Regexp replace pareg := regexp.MustCompile(`(Input.Params\[")(.*)("])`) 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\")") - // fix the cache object Put method + // 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)") @@ -199,11 +200,11 @@ func fixFile(file string) error { fixed = strings.Replace(fixed, "import (", "import (\n\t\"time\"", 1) } } - // replace the v.Apis in docs.go + // Replace the v.Apis in docs.go if strings.Contains(file, "docs.go") { fixed = strings.Replace(fixed, "v.Apis", "v.APIs", -1) } - // replace the config file + // Replace the config file if strings.HasSuffix(file, ".conf") { fixed = strings.Replace(fixed, "HttpCertFile", "HTTPSCertFile", -1) fixed = strings.Replace(fixed, "HttpKeyFile", "HTTPSKeyFile", -1) diff --git a/g.go b/g.go index bc4b123..e3a18d2 100644 --- a/g.go +++ b/g.go @@ -81,29 +81,28 @@ func generateCode(cmd *Command, args []string) int { currpath, _ := os.Getwd() if len(args) < 1 { - ColorLog("[ERRO] command is missing\n") - os.Exit(2) + logger.Fatal("Command is missing") } gps := GetGOPATHs() if len(gps) == 0 { - ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty") - os.Exit(2) + logger.Fatal("GOPATH environment variable is not set or empty") } + gopath := gps[0] - Debugf("GOPATH: %s", gopath) + + logger.Debugf("GOPATH: %s", gopath) gcmd := args[0] switch gcmd { case "scaffold": if len(args) < 2 { - ColorLog("[ERRO] Wrong number of arguments\n") - ColorLog("[HINT] Usage: bee generate scaffold [scaffoldname] [-fields=\"\"]\n") - os.Exit(2) + logger.Fatal("Wrong number of arguments. Run: bee help generate") } + // Load the configuration err := loadConfig() if err != nil { - ColorLog("[ERRO] Fail to parse bee.json[ %s ]\n", err) + logger.Fatalf("Failed to load configuration: %s", err) } cmd.Flag.Parse(args[2:]) if driver == "" { @@ -119,19 +118,18 @@ func generateCode(cmd *Command, args []string) int { } } if fields == "" { - ColorLog("[ERRO] Wrong number of arguments\n") - ColorLog("[HINT] Usage: bee generate scaffold [scaffoldname] [-fields=\"title:string,body:text\"]\n") - os.Exit(2) + logger.Hint("fields option should not be empty, i.e. -fields=\"title:string,body:text\"") + logger.Fatal("Wrong number of arguments. Run: bee help generate") } sname := args[1] generateScaffold(sname, fields.String(), currpath, driver.String(), conn.String()) case "docs": generateDocs(currpath) case "appcode": - // load config + // Load the configuration err := loadConfig() if err != nil { - ColorLog("[ERRO] Fail to parse bee.json[ %s ]\n", err) + logger.Fatalf("Failed to load configuration: %s", err) } cmd.Flag.Parse(args[1:]) if driver == "" { @@ -153,20 +151,20 @@ func generateCode(cmd *Command, args []string) int { if level == "" { level = "3" } - ColorLog("[INFO] Using '%s' as 'driver'\n", driver) - ColorLog("[INFO] Using '%s' as 'conn'\n", conn) - ColorLog("[INFO] Using '%s' as 'tables'\n", tables) - ColorLog("[INFO] Using '%s' as 'level'\n", level) + logger.Infof("Using '%s' as 'driver'", driver) + logger.Infof("Using '%s' as 'conn'", conn) + logger.Infof("Using '%s' as 'tables'", tables) + logger.Infof("Using '%s' as 'level'", level) generateAppcode(driver.String(), conn.String(), level.String(), tables.String(), currpath) case "migration": if len(args) < 2 { - ColorLog("[ERRO] Wrong number of arguments\n") - ColorLog("[HINT] Usage: bee generate migration [migrationname] [-fields=\"\"]\n") - os.Exit(2) + logger.Fatal("Wrong number of arguments. Run: bee help generate") } cmd.Flag.Parse(args[2:]) mname := args[1] - ColorLog("[INFO] Using '%s' as migration name\n", mname) + + logger.Infof("Using '%s' as migration name", mname) + upsql := "" downsql := "" if fields != "" { @@ -180,21 +178,16 @@ func generateCode(cmd *Command, args []string) int { cname := args[1] generateController(cname, currpath) } else { - ColorLog("[ERRO] Wrong number of arguments\n") - ColorLog("[HINT] Usage: bee generate controller [controllername]\n") - os.Exit(2) + logger.Fatal("Wrong number of arguments. Run: bee help generate") } case "model": if len(args) < 2 { - ColorLog("[ERRO] Wrong number of arguments\n") - ColorLog("[HINT] Usage: bee generate model [modelname] [-fields=\"\"]\n") - os.Exit(2) + logger.Fatal("Wrong number of arguments. Run: bee help generate") } cmd.Flag.Parse(args[2:]) if fields == "" { - ColorLog("[ERRO] Wrong number of arguments\n") - ColorLog("[HINT] Usage: bee generate model [modelname] [-fields=\"title:string,body:text\"]\n") - os.Exit(2) + logger.Hint("fields option should not be empty, i.e. -fields=\"title:string,body:text\"") + logger.Fatal("Wrong number of arguments. Run: bee help generate") } sname := args[1] generateModel(sname, fields.String(), currpath) @@ -203,13 +196,11 @@ func generateCode(cmd *Command, args []string) int { cname := args[1] generateView(cname, currpath) } else { - ColorLog("[ERRO] Wrong number of arguments\n") - ColorLog("[HINT] Usage: bee generate view [viewpath]\n") - os.Exit(2) + logger.Fatal("Wrong number of arguments. Run: bee help generate") } default: - ColorLog("[ERRO] Command is missing\n") + logger.Fatal("Command is missing") } - ColorLog("[SUCC] %s successfully generated!\n", strings.Title(gcmd)) + logger.Successf("%s successfully generated!", strings.Title(gcmd)) return 0 } diff --git a/g_appcode.go b/g_appcode.go index 4e90107..7778c82 100644 --- a/g_appcode.go +++ b/g_appcode.go @@ -18,7 +18,6 @@ import ( "database/sql" "fmt" "os" - "os/exec" "path" "path/filepath" "regexp" @@ -39,7 +38,7 @@ type DbTransformer interface { GetTableNames(conn *sql.DB) []string GetConstraints(conn *sql.DB, table *Table, blackList map[string]bool) GetColumns(conn *sql.DB, table *Table, blackList map[string]bool) - GetGoDataType(sqlType string) string + GetGoDataType(sqlType string) (string, error) } // MysqlDB is the MySQL version of DbTransformer @@ -265,9 +264,7 @@ func generateAppcode(driver, connStr, level, tables, currpath string) { case "3": mode = OModel | OController | ORouter default: - ColorLog("[ERRO] Invalid 'level' option: %s\n", level) - ColorLog("[HINT] Level must be either 1, 2 or 3\n") - os.Exit(2) + logger.Fatal("Invalid level value. Must be either \"1\", \"2\", or \"3\"") } var selectedTables map[string]bool if tables != "" { @@ -280,12 +277,9 @@ func generateAppcode(driver, connStr, level, tables, currpath string) { case "mysql": case "postgres": case "sqlite": - ColorLog("[ERRO] Generating app code from SQLite database is not supported yet.\n") - os.Exit(2) + logger.Fatal("Generating app code from SQLite database is not supported yet.") default: - ColorLog("[ERRO] Unknown database driver: %s\n", driver) - ColorLog("[HINT] Driver must be one of mysql, postgres or sqlite\n") - os.Exit(2) + logger.Fatal("Unknown database driver. Must be either \"mysql\", \"postgres\" or \"sqlite\"") } gen(driver, connStr, mode, selectedTables, currpath) } @@ -295,12 +289,11 @@ func generateAppcode(driver, connStr, level, tables, 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) - os.Exit(2) + logger.Fatalf("Could not connect to '%s' database using '%s': %s", dbms, connStr, err) } defer db.Close() if trans, ok := dbDriver[dbms]; ok { - ColorLog("[INFO] Analyzing database tables...\n") + logger.Info("Analyzing database tables...") tableNames := trans.GetTableNames(db) tables := getTableObjects(tableNames, db, trans) mvcPath := new(MvcPath) @@ -311,25 +304,21 @@ func gen(dbms, connStr string, mode byte, selectedTableNames map[string]bool, ap pkgPath := getPackagePath(apppath) writeSourceFiles(pkgPath, tables, mode, mvcPath, selectedTableNames) } else { - ColorLog("[ERRO] Generating app code from %s database is not supported yet.\n", dbms) - os.Exit(2) + logger.Fatalf("Generating app code from '%s' database is not supported yet.", dbms) } } -// getTables gets a list table names in current database +// GetTableNames returns a slice of table names in the current database func (*MysqlDB) GetTableNames(db *sql.DB) (tables []string) { rows, err := db.Query("SHOW TABLES") if err != nil { - ColorLog("[ERRO] Could not show tables\n") - ColorLog("[HINT] Check your connection string\n") - os.Exit(2) + logger.Fatalf("Could not show tables: %s", err) } defer rows.Close() for rows.Next() { var name string if err := rows.Scan(&name); err != nil { - ColorLog("[ERRO] Could not show tables\n") - os.Exit(2) + logger.Fatalf("Could not show tables: %s", err) } tables = append(tables, name) } @@ -358,8 +347,8 @@ func getTableObjects(tableNames []string, db *sql.DB, dbTransformer DbTransforme return } -// getConstraints gets primary key, unique key and foreign keys of a table from information_schema -// and fill in Table struct +// GetConstraints gets primary key, unique key and foreign keys of a table from +// information_schema and fill in the Table struct func (*MysqlDB) GetConstraints(db *sql.DB, table *Table, blackList map[string]bool) { rows, err := db.Query( `SELECT @@ -372,14 +361,12 @@ func (*MysqlDB) GetConstraints(db *sql.DB, table *Table, blackList map[string]bo 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, if err != nil { - ColorLog("[ERRO] Could not query INFORMATION_SCHEMA for PK/UK/FK information\n") - os.Exit(2) + logger.Fatal("Could not query INFORMATION_SCHEMA for PK/UK/FK information") } for rows.Next() { var constraintTypeBytes, columnNameBytes, refTableSchemaBytes, refTableNameBytes, refColumnNameBytes, refOrdinalPosBytes []byte if err := rows.Scan(&constraintTypeBytes, &columnNameBytes, &refTableSchemaBytes, &refTableNameBytes, &refColumnNameBytes, &refOrdinalPosBytes); err != nil { - ColorLog("[ERRO] Could not read INFORMATION_SCHEMA for PK/UK/FK information\n") - os.Exit(2) + logger.Fatal("Could not read INFORMATION_SCHEMA for PK/UK/FK information") } constraintType, columnName, refTableSchema, refTableName, refColumnName, refOrdinalPos := string(constraintTypeBytes), string(columnNameBytes), string(refTableSchemaBytes), @@ -389,7 +376,7 @@ func (*MysqlDB) GetConstraints(db *sql.DB, table *Table, blackList map[string]bo table.Pk = columnName } else { table.Pk = "" - // add table to blacklist so that other struct will not reference it, because we are not + // Add table to blacklist so that other struct will not reference it, because we are not // registering blacklisted tables blackList[table.Name] = true } @@ -406,11 +393,11 @@ func (*MysqlDB) GetConstraints(db *sql.DB, table *Table, blackList map[string]bo } } -// getColumns retrieve columns details from information_schema -// and fill in the Column struct +// GetColumns retrieves columns details from +// information_schema and fill in the Column struct func (mysqlDB *MysqlDB) GetColumns(db *sql.DB, table *Table, blackList map[string]bool) { // retrieve columns - colDefRows, _ := db.Query( + colDefRows, err := db.Query( `SELECT column_name, data_type, column_type, is_nullable, column_default, extra FROM @@ -418,20 +405,28 @@ func (mysqlDB *MysqlDB) GetColumns(db *sql.DB, table *Table, blackList map[strin WHERE table_schema = database() AND table_name = ?`, table.Name) + if err != nil { + logger.Fatalf("Could not query the database: %s", err) + } defer colDefRows.Close() + for colDefRows.Next() { // datatype as bytes so that SQL values can be retrieved var colNameBytes, dataTypeBytes, columnTypeBytes, isNullableBytes, columnDefaultBytes, extraBytes []byte if err := colDefRows.Scan(&colNameBytes, &dataTypeBytes, &columnTypeBytes, &isNullableBytes, &columnDefaultBytes, &extraBytes); err != nil { - ColorLog("[ERRO] Could not query INFORMATION_SCHEMA for column information\n") - os.Exit(2) + logger.Fatal("Could not query INFORMATION_SCHEMA for column information") } colName, dataType, columnType, isNullable, columnDefault, extra := string(colNameBytes), string(dataTypeBytes), string(columnTypeBytes), string(isNullableBytes), string(columnDefaultBytes), string(extraBytes) + // create a column col := new(Column) col.Name = camelCase(colName) - col.Type = mysqlDB.GetGoDataType(dataType) + col.Type, err = mysqlDB.GetGoDataType(dataType) + if err != nil { + logger.Fatalf("%s", err) + } + // Tag info tag := new(OrmTag) tag.Column = colName @@ -466,7 +461,10 @@ func (mysqlDB *MysqlDB) GetColumns(db *sql.DB, table *Table, blackList map[strin if isSQLSignedIntType(dataType) { sign := extractIntSignness(columnType) if sign == "unsigned" && extra != "auto_increment" { - col.Type = mysqlDB.GetGoDataType(dataType + " " + sign) + col.Type, err = mysqlDB.GetGoDataType(dataType + " " + sign) + if err != nil { + logger.Fatalf("%s", err) + } } } if isSQLStringType(dataType) { @@ -500,15 +498,13 @@ func (mysqlDB *MysqlDB) GetColumns(db *sql.DB, table *Table, blackList map[strin } // GetGoDataType maps an SQL data type to Golang data type -func (*MysqlDB) GetGoDataType(sqlType string) (goType string) { +func (*MysqlDB) GetGoDataType(sqlType string) (string, error) { var typeMapping = map[string]string{} typeMapping = typeMappingMysql if v, ok := typeMapping[sqlType]; ok { - return v + return v, nil } - ColorLog("[ERRO] data type (%s) not found!\n", sqlType) - os.Exit(2) - return goType + return "", fmt.Errorf("data type '%s' not found", sqlType) } // GetTableNames for PostgreSQL @@ -519,16 +515,14 @@ func (*PostgresDB) GetTableNames(db *sql.DB) (tables []string) { 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") - os.Exit(2) + logger.Fatalf("Could not show tables: %s", err) } defer rows.Close() + for rows.Next() { var name string if err := rows.Scan(&name); err != nil { - ColorLog("[ERRO] Could not show tables\n") - os.Exit(2) + logger.Fatalf("Could not show tables: %s", err) } tables = append(tables, name) } @@ -558,14 +552,13 @@ func (*PostgresDB) GetConstraints(db *sql.DB, table *Table, blackList map[string 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) - os.Exit(2) + logger.Fatalf("Could not query INFORMATION_SCHEMA for PK/UK/FK information: %s", err) } + for rows.Next() { var constraintTypeBytes, columnNameBytes, refTableSchemaBytes, refTableNameBytes, refColumnNameBytes, refOrdinalPosBytes []byte if err := rows.Scan(&constraintTypeBytes, &columnNameBytes, &refTableSchemaBytes, &refTableNameBytes, &refColumnNameBytes, &refOrdinalPosBytes); err != nil { - ColorLog("[ERRO] Could not read INFORMATION_SCHEMA for PK/UK/FK information\n") - os.Exit(2) + logger.Fatalf("Could not read INFORMATION_SCHEMA for PK/UK/FK information: %s", err) } constraintType, columnName, refTableSchema, refTableName, refColumnName, refOrdinalPos := string(constraintTypeBytes), string(columnNameBytes), string(refTableSchemaBytes), @@ -595,7 +588,7 @@ func (*PostgresDB) GetConstraints(db *sql.DB, table *Table, blackList map[string // GetColumns for PostgreSQL func (postgresDB *PostgresDB) GetColumns(db *sql.DB, table *Table, blackList map[string]bool) { // retrieve columns - colDefRows, _ := db.Query( + colDefRows, err := db.Query( `SELECT column_name, data_type, @@ -614,20 +607,27 @@ func (postgresDB *PostgresDB) GetColumns(db *sql.DB, table *Table, blackList map table_catalog = current_database() AND table_schema NOT IN ('pg_catalog', 'information_schema') AND table_name = $1`, table.Name) + if err != nil { + logger.Fatalf("Could not query INFORMATION_SCHEMA for column information: %s", err) + } defer colDefRows.Close() + for colDefRows.Next() { // datatype as bytes so that SQL values can be retrieved var colNameBytes, dataTypeBytes, columnTypeBytes, isNullableBytes, columnDefaultBytes, extraBytes []byte if err := colDefRows.Scan(&colNameBytes, &dataTypeBytes, &columnTypeBytes, &isNullableBytes, &columnDefaultBytes, &extraBytes); err != nil { - ColorLog("[ERRO] Could not query INFORMATION_SCHEMA for column information\n") - os.Exit(2) + logger.Fatalf("Could not query INFORMATION_SCHEMA for column information: %s", err) } colName, dataType, columnType, isNullable, columnDefault, extra := string(colNameBytes), string(dataTypeBytes), string(columnTypeBytes), string(isNullableBytes), string(columnDefaultBytes), string(extraBytes) - // create a column + // Create a column col := new(Column) col.Name = camelCase(colName) - col.Type = postgresDB.GetGoDataType(dataType) + col.Type, err = postgresDB.GetGoDataType(dataType) + if err != nil { + logger.Fatalf("%s", err) + } + // Tag info tag := new(OrmTag) tag.Column = colName @@ -690,13 +690,11 @@ func (postgresDB *PostgresDB) GetColumns(db *sql.DB, table *Table, blackList map } // GetGoDataType returns the Go type from the mapped Postgres type -func (*PostgresDB) GetGoDataType(sqlType string) (goType string) { +func (*PostgresDB) GetGoDataType(sqlType string) (string, error) { if v, ok := typeMappingPostgres[sqlType]; ok { - return v + return v, nil } - ColorLog("[ERRO] data type (%s) not found!\n", sqlType) - os.Exit(2) - return goType + return "", fmt.Errorf("data type '%s' not found", sqlType) } // deleteAndRecreatePaths removes several directories completely @@ -717,15 +715,15 @@ func createPaths(mode byte, paths *MvcPath) { // Newly geneated files will be inside these folders. func writeSourceFiles(pkgPath string, tables []*Table, mode byte, paths *MvcPath, selectedTables map[string]bool) { if (OModel & mode) == OModel { - ColorLog("[INFO] Creating model files...\n") + logger.Info("Creating model files...") writeModelFiles(tables, paths.ModelPath, selectedTables) } if (OController & mode) == OController { - ColorLog("[INFO] Creating controller files...\n") + logger.Info("Creating controller files...") writeControllerFiles(tables, paths.ControllerPath, selectedTables, pkgPath) } if (ORouter & mode) == ORouter { - ColorLog("[INFO] Creating router files...\n") + logger.Info("Creating router files...") writeRouterFile(tables, paths.RouterPath, selectedTables, pkgPath) } } @@ -746,21 +744,21 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo var f *os.File var err error if isExist(fpath) { - ColorLog("[WARN] '%v' already exists. Do you want to overwrite it? [Yes|No] ", fpath) + logger.Warnf("'%s' 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 { - ColorLog("[WARN] %v\n", err) + logger.Warnf("%s", err) continue } } else { - ColorLog("[WARN] Skipped create file '%s'\n", fpath) + logger.Warnf("Skipped create file '%s'", fpath) continue } } else { f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666) if err != nil { - ColorLog("[WARN] %v\n", err) + logger.Warnf("%s", err) continue } } @@ -773,7 +771,8 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo fileStr := strings.Replace(template, "{{modelStruct}}", tb.String(), 1) fileStr = strings.Replace(fileStr, "{{modelName}}", camelCase(tb.Name), -1) fileStr = strings.Replace(fileStr, "{{tableName}}", tb.Name, -1) - // if table contains time field, import time.Time package + + // If table contains time field, import time.Time package timePkg := "" importTimePkg := "" if tb.ImportTimePkg { @@ -783,8 +782,7 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo 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) - os.Exit(2) + logger.Fatalf("Could not write model file to '%s': %s", fpath, err) } CloseFile(f) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") @@ -797,7 +795,7 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri w := NewColorWriter(os.Stdout) for _, tb := range tables { - // if selectedTables map is not nil and this table is not selected, ignore it + // If selectedTables map is not nil and this table is not selected, ignore it if selectedTables != nil { if _, selected := selectedTables[tb.Name]; !selected { continue @@ -811,29 +809,28 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri var f *os.File var err error if isExist(fpath) { - ColorLog("[WARN] '%v' already exists. Do you want to overwrite it? [Yes|No] ", fpath) + logger.Warnf("'%s' 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 { - ColorLog("[WARN] %v\n", err) + logger.Warnf("%s", err) continue } } else { - ColorLog("[WARN] Skipped create file '%s'\n", fpath) + logger.Warnf("Skipped create file '%s'", fpath) continue } } else { f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666) if err != nil { - ColorLog("[WARN] %v\n", err) + logger.Warnf("%s", err) continue } } 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) - os.Exit(2) + logger.Fatalf("Could not write controller file to '%s': %s", fpath, err) } CloseFile(f) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") @@ -847,7 +844,7 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo var nameSpaces []string for _, tb := range tables { - // if selectedTables map is not nil and this table is not selected, ignore it + // If selectedTables map is not nil and this table is not selected, ignore it if selectedTables != nil { if _, selected := selectedTables[tb.Name]; !selected { continue @@ -856,63 +853,44 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo if tb.Pk == "" { continue } - // add namespaces + // Add namespaces nameSpace := strings.Replace(NamespaceTPL, "{{nameSpace}}", tb.Name, -1) nameSpace = strings.Replace(nameSpace, "{{ctrlName}}", camelCase(tb.Name), -1) nameSpaces = append(nameSpaces, nameSpace) } - // add export controller + // Add export controller fpath := path.Join(rPath, "router.go") routerStr := strings.Replace(RouterTPL, "{{nameSpaces}}", strings.Join(nameSpaces, ""), 1) routerStr = strings.Replace(routerStr, "{{pkgPath}}", pkgPath, 1) var f *os.File var err error if isExist(fpath) { - ColorLog("[WARN] '%v' already exists. Do you want to overwrite it? [Yes|No] ", fpath) + logger.Warnf("'%s' 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 { - ColorLog("[WARN] %v\n", err) + logger.Warnf("%s", err) return } } else { - ColorLog("[WARN] Skipped create file '%s'\n", fpath) + logger.Warnf("Skipped create file '%s'", fpath) return } } else { f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666) if err != nil { - ColorLog("[WARN] %v\n", err) + logger.Warnf("%s", err) return } } if _, err := f.WriteString(routerStr); err != nil { - ColorLog("[ERRO] Could not write router file to '%s'\n", fpath) - os.Exit(2) + logger.Fatalf("Could not write router file to '%s': %s", fpath, err) } CloseFile(f) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") formatSourceCode(fpath) } -// formatSourceCode formats source files -func formatSourceCode(filename string) { - cmd := exec.Command("gofmt", "-w", filename) - if err := cmd.Run(); err != nil { - ColorLog("[WARN] gofmt err: %s\n", err) - } -} - -// camelCase converts a _ delimited string to camel case -// e.g. very_important_person => VeryImportantPerson -func camelCase(in string) string { - tokens := strings.Split(in, "_") - for i := range tokens { - tokens[i] = strings.Title(strings.Trim(tokens[i], " ")) - } - return strings.Join(tokens, "") -} - func isSQLTemporalType(t string) bool { return t == "date" || t == "datetime" || t == "timestamp" || t == "time" } @@ -972,12 +950,12 @@ func getFileName(tbName string) (filename string) { 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") - os.Exit(2) + logger.Fatal("GOPATH environment variable is not set or empty") } + logger.Debugf("GOPATH: %s", gopath) + appsrcpath := "" haspath := false wgopath := filepath.SplitList(gopath) @@ -993,13 +971,11 @@ func getPackagePath(curpath string) (packpath string) { } if !haspath { - ColorLog("[ERRO] Can't generate application code outside of GOPATH '%s'\n", gopath) - os.Exit(2) + logger.Fatalf("Cannot generate application code outside of GOPATH '%s'", gopath) } if curpath == appsrcpath { - ColorLog("[ERRO] Can't generate application code outside of application PATH \n") - os.Exit(2) + logger.Fatal("Cannot generate application code outside of application path") } packpath = strings.Join(strings.Split(curpath[len(appsrcpath)+1:], string(filepath.Separator)), "/") diff --git a/g_controllers.go b/g_controllers.go index 9d0b0ae..5220210 100644 --- a/g_controllers.go +++ b/g_controllers.go @@ -21,9 +21,6 @@ import ( "strings" ) -// article -// cms/article -// func generateController(cname, currpath string) { w := NewColorWriter(os.Stdout) @@ -36,15 +33,14 @@ func generateController(cname, currpath string) { 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) + logger.Infof("Using '%s' as controller name", controllerName) + logger.Infof("Using '%s' as package name", packageName) fp := path.Join(currpath, "controllers", p) if _, err := os.Stat(fp); os.IsNotExist(err) { // 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) + logger.Fatalf("Could not create controllers directory: %s", err) } } @@ -56,7 +52,7 @@ func generateController(cname, currpath string) { var content string if _, err := os.Stat(modelPath); err == nil { - ColorLog("[INFO] Using matching model '%s'\n", controllerName) + logger.Infof("Using matching model '%s'", controllerName) content = strings.Replace(controllerModelTpl, "{{packageName}}", packageName, -1) pkgPath := getPackagePath(currpath) content = strings.Replace(content, "{{pkgPath}}", pkgPath, -1) @@ -71,8 +67,7 @@ func generateController(cname, currpath string) { formatSourceCode(fpath) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") } else { - ColorLog("[ERRO] Could not create controller file: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not create controller file: %s", err) } } diff --git a/g_docs.go b/g_docs.go index d7216cd..f3ddc16 100644 --- a/g_docs.go +++ b/g_docs.go @@ -26,7 +26,6 @@ import ( "path/filepath" "reflect" "regexp" - "runtime" "strconv" "strings" "unicode" @@ -92,8 +91,7 @@ func parsePackagesFromDir(path string) { parsePackageFromDir(path) list, err := ioutil.ReadDir(path) if err != nil { - ColorLog("[ERRO] Can't read directory %s : %s\n", path, err) - os.Exit(1) + logger.Fatalf("Cannot read directory '%s': %s", path, err) } for _, item := range list { if item.IsDir() && item.Name() != "vendor" { @@ -108,11 +106,10 @@ func parsePackageFromDir(path string) { name := info.Name() return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") }, parser.ParseComments) - if err != nil { - ColorLog("[ERRO] the model %s parser.ParseDir error: %s\n", path, err) - os.Exit(1) + logger.Fatalf("Error while parsing dir at '%s': %s", path, err) } + for k, v := range folderPkgs { astPkgs[k] = v } @@ -124,13 +121,13 @@ func generateDocs(curpath string) { f, err := parser.ParseFile(fset, path.Join(curpath, "routers", "router.go"), nil, parser.ParseComments) if err != nil { - ColorLog("[ERRO] parse router.go error\n") - os.Exit(2) + logger.Fatalf("Error while parsing router.go: %s", err) } rootapi.Infos = swagger.Information{} rootapi.SwaggerVersion = "2.0" - //analysis API comments + + // Analyse API comments if f.Comments != nil { for _, c := range f.Comments { for _, s := range strings.Split(c.Text(), "\n") { @@ -168,13 +165,14 @@ func generateDocs(curpath string) { } } } - // analisys controller package + + // Analyse controller package for _, im := range f.Imports { localName := "" if im.Name != nil { localName = im.Name.Name } - analisyscontrollerPkg(localName, im.Path.Value) + analyseControllerPkg(localName, im.Path.Value) } for _, d := range f.Decls { switch specDecl := d.(type) { @@ -184,11 +182,11 @@ func generateDocs(curpath string) { case *ast.AssignStmt: for _, l := range stmt.Rhs { if v, ok := l.(*ast.CallExpr); ok { - // analisys NewNamespace, it will return version and the subfunction + // Analyse NewNamespace, it will return version and the subfunction if selName := v.Fun.(*ast.SelectorExpr).Sel.String(); selName != "NewNamespace" { continue } - version, params := analisysNewNamespace(v) + version, params := analyseNewNamespace(v) if rootapi.BasePath == "" && version != "" { rootapi.BasePath = version } @@ -197,12 +195,12 @@ func generateDocs(curpath string) { case *ast.CallExpr: controllerName := "" if selname := pp.Fun.(*ast.SelectorExpr).Sel.String(); selname == "NSNamespace" { - s, params := analisysNewNamespace(pp) + s, params := analyseNewNamespace(pp) for _, sp := range params { switch pp := sp.(type) { case *ast.CallExpr: if pp.Fun.(*ast.SelectorExpr).Sel.String() == "NSInclude" { - controllerName = analisysNSInclude(s, pp) + controllerName = analyseNSInclude(s, pp) if v, ok := controllerComments[controllerName]; ok { rootapi.Tags = append(rootapi.Tags, swagger.Tag{ Name: strings.Trim(s, "/"), @@ -213,7 +211,7 @@ func generateDocs(curpath string) { } } } else if selname == "NSInclude" { - controllerName = analisysNSInclude("", pp) + controllerName = analyseNSInclude("", 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 @@ -250,8 +248,8 @@ func generateDocs(curpath string) { } } -// return version and the others params -func analisysNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) { +// analyseNewNamespace returns version and the others params +func analyseNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) { for i, p := range ce.Args { if i == 0 { switch pp := p.(type) { @@ -265,7 +263,7 @@ func analisysNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) { return } -func analisysNSInclude(baseurl string, ce *ast.CallExpr) string { +func analyseNSInclude(baseurl string, ce *ast.CallExpr) string { cname := "" for _, p := range ce.Args { x := p.(*ast.UnaryExpr).X.(*ast.CompositeLit).Type.(*ast.SelectorExpr) @@ -313,7 +311,7 @@ func analisysNSInclude(baseurl string, ce *ast.CallExpr) string { return cname } -func analisyscontrollerPkg(localName, pkgpath string) { +func analyseControllerPkg(localName, pkgpath string) { pkgpath = strings.Trim(pkgpath, "\"") if isSystemPackage(pkgpath) { return @@ -329,7 +327,7 @@ func analisyscontrollerPkg(localName, pkgpath string) { } gopath := os.Getenv("GOPATH") if gopath == "" { - panic("please set gopath") + logger.Fatal("GOPATH environment variable is not set or empty") } pkgRealpath := "" @@ -347,18 +345,16 @@ func analisyscontrollerPkg(localName, pkgpath string) { } pkgCache[pkgpath] = struct{}{} } else { - ColorLog("[ERRO] the %s pkg not exist in gopath\n", pkgpath) - os.Exit(1) + logger.Fatalf("Package '%s' does not exist in the GOPATH", pkgpath) } + fileSet := token.NewFileSet() astPkgs, err := parser.ParseDir(fileSet, pkgRealpath, func(info os.FileInfo) bool { name := info.Name() return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") }, parser.ParseComments) - if err != nil { - ColorLog("[ERRO] the %s pkg parser.ParseDir error: %s\n", pkgpath, err) - os.Exit(1) + logger.Fatalf("Error while parsing dir at '%s': %s", pkgpath, err) } for _, pkg := range astPkgs { for _, fl := range pkg.Files { @@ -367,7 +363,7 @@ 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 + // Parse controller method parserComments(specDecl.Doc, specDecl.Name.String(), fmt.Sprint(t.X), pkgpath) } } @@ -377,7 +373,7 @@ func analisyscontrollerPkg(localName, pkgpath string) { switch tp := s.(*ast.TypeSpec).Type.(type) { case *ast.StructType: _ = tp.Struct - //parse controller definition comments + // Parse controller definition comments if strings.TrimSpace(specDecl.Doc.Text()) != "" { controllerComments[pkgpath+s.(*ast.TypeSpec).Name.String()] = specDecl.Doc.Text() } @@ -391,10 +387,11 @@ func analisyscontrollerPkg(localName, pkgpath string) { } func isSystemPackage(pkgpath string) bool { - goroot := runtime.GOROOT() + goroot := os.Getenv("GOROOT") if goroot == "" { - panic("goroot is empty, do you install Go right?") + logger.Fatalf("GOROOT environment variable is not set or empty") } + wg, _ := filepath.EvalSymlinks(filepath.Join(goroot, "src", "pkg", pkgpath)) if utils.FileExists(wg) { return true @@ -460,8 +457,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat 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) + logger.Fatalf("[%s.%s] Schema must follow {object} or {array}", controllerName, funcName) } if strings.HasPrefix(schemaName, "[]") { schemaName = schemaName[2:] @@ -498,7 +494,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat para := swagger.Parameter{} p := getparams(strings.TrimSpace(t[len("@Param "):])) if len(p) < 4 { - panic(controllerName + "_" + funcName + "'s comments @Param at least should has 4 params") + logger.Fatal(controllerName + "_" + funcName + "'s comments @Param should have at least 4 params") } para.Name = p[0] switch p[1] { @@ -513,7 +509,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat case "body": break default: - ColorLog("[WARN][%s.%s] Unknow param location: %s, Possible values are `query`, `header`, `path`, `formData` or `body`.\n", controllerName, funcName, p[1]) + logger.Warnf("[%s.%s] Unknown 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], ".") @@ -544,7 +540,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat paraType = typeFormat[0] paraFormat = typeFormat[1] } else { - ColorLog("[WARN][%s.%s] Unknow param type: %s\n", controllerName, funcName, typ) + logger.Warnf("[%s.%s] Unknown param type: %s\n", controllerName, funcName, typ) } if isArray { para.Type = "array" @@ -697,7 +693,7 @@ func getModel(str string) (objectname string, m swagger.Schema, realTypes []stri } } if m.Title == "" { - ColorLog("[WARN]can't find the object: %s\n", str) + logger.Warnf("Cannot find the object: %s", str) // TODO remove when all type have been supported //os.Exit(1) } @@ -712,8 +708,7 @@ func getModel(str string) (objectname string, m swagger.Schema, realTypes []stri func parseObject(d *ast.Object, k string, m *swagger.Schema, realTypes *[]string, astPkgs map[string]*ast.Package, packageName string) { ts, ok := d.Decl.(*ast.TypeSpec) if !ok { - ColorLog("Unknown type without TypeSec: %v\n", d) - os.Exit(1) + logger.Fatalf("Unknown type without TypeSec: %v\n", d) } // TODO support other types, such as `ArrayType`, `MapType`, `InterfaceType` etc... st, ok := ts.Type.(*ast.StructType) @@ -789,7 +784,7 @@ func parseObject(d *ast.Object, k string, m *swagger.Schema, realTypes *[]string mp.Default = str2RealType(res[1], realType) } else { - ColorLog("[WARN] Invalid default value: %s\n", defaultValue) + logger.Warnf("Invalid default value: %s", defaultValue) } } @@ -933,7 +928,7 @@ func str2RealType(s string, typ string) interface{} { } if err != nil { - ColorLog("[WARN] Invalid default value type(%s): %s\n", typ, s) + logger.Warnf("Invalid default value type '%s': %s", typ, s) return s } diff --git a/g_hproseappcode.go b/g_hproseappcode.go index 2d95aec..3ce52ae 100644 --- a/g_hproseappcode.go +++ b/g_hproseappcode.go @@ -38,9 +38,7 @@ func generateHproseAppcode(driver, connStr, level, tables, currpath string) { case "3": mode = OModel | OController | ORouter default: - ColorLog("[ERRO] Invalid 'level' option: %s\n", level) - ColorLog("[HINT] Level must be either 1, 2 or 3\n") - os.Exit(2) + logger.Fatal("Invalid 'level' option. Level must be either \"1\", \"2\" or \"3\"") } var selectedTables map[string]bool if tables != "" { @@ -53,12 +51,9 @@ func generateHproseAppcode(driver, connStr, level, tables, currpath string) { case "mysql": case "postgres": case "sqlite": - ColorLog("[ERRO] Generating app code from SQLite database is not supported yet.\n") - os.Exit(2) + logger.Fatal("Generating app code from SQLite database is not supported yet") default: - ColorLog("[ERRO] Unknown database driver: %s\n", driver) - ColorLog("[HINT] Driver must be one of mysql, postgres or sqlite\n") - os.Exit(2) + logger.Fatalf("Unknown database driver '%s'. Driver must be one of mysql, postgres or sqlite", driver) } genHprose(driver, connStr, mode, selectedTables, currpath) } @@ -68,12 +63,11 @@ func generateHproseAppcode(driver, connStr, level, tables, currpath string) { func genHprose(dbms, connStr string, mode byte, selectedTableNames map[string]bool, currpath string) { db, err := sql.Open(dbms, connStr) if err != nil { - ColorLog("[ERRO] Could not connect to %s database: %s, %s\n", dbms, connStr, err) - os.Exit(2) + logger.Fatalf("Could not connect to '%s' database using '%s': %s", dbms, connStr, err) } defer db.Close() if trans, ok := dbDriver[dbms]; ok { - ColorLog("[INFO] Analyzing database tables...\n") + logger.Info("Analyzing database tables...") tableNames := trans.GetTableNames(db) tables := getTableObjects(tableNames, db, trans) mvcPath := new(MvcPath) @@ -82,8 +76,7 @@ func genHprose(dbms, connStr string, mode byte, selectedTableNames map[string]bo pkgPath := getPackagePath(currpath) writeHproseSourceFiles(pkgPath, tables, mode, mvcPath, selectedTableNames) } else { - ColorLog("[ERRO] Generating app code from %s database is not supported yet.\n", dbms) - os.Exit(2) + logger.Fatalf("Generating app code from '%s' database is not supported yet", dbms) } } @@ -92,7 +85,7 @@ func genHprose(dbms, connStr string, mode byte, selectedTableNames map[string]bo // Newly geneated files will be inside these folders. func writeHproseSourceFiles(pkgPath string, tables []*Table, mode byte, paths *MvcPath, selectedTables map[string]bool) { if (OModel & mode) == OModel { - ColorLog("[INFO] Creating model files...\n") + logger.Info("Creating model files...") writeHproseModelFiles(tables, paths.ModelPath, selectedTables) } } @@ -113,21 +106,21 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str var f *os.File var err error if isExist(fpath) { - ColorLog("[WARN] '%v' already exists. Do you want to overwrite it? [Yes|No] ", fpath) + logger.Warnf("'%s' 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 { - ColorLog("[WARN] %v\n", err) + logger.Warnf("%s", err) continue } } else { - ColorLog("[WARN] Skipped create file '%s'\n", fpath) + logger.Warnf("Skipped create file '%s'", fpath) continue } } else { f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666) if err != nil { - ColorLog("[WARN] %v\n", err) + logger.Warnf("%s", err) continue } } @@ -150,8 +143,7 @@ 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) - os.Exit(2) + logger.Fatalf("Could not write model file to '%s'", fpath) } CloseFile(f) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") diff --git a/g_migration.go b/g_migration.go index ed3dfc4..8ab3f1f 100644 --- a/g_migration.go +++ b/g_migration.go @@ -51,12 +51,12 @@ func (m mysqlDriver) generateSQLFromFields(fields string) string { 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") + logger.Error("Fields format is wrong. Should be: key:type,key:type " + v) return "" } typ, tag := m.getSQLType(kv[1]) if typ == "" { - ColorLog("[ERRO] Fields format is wrong. Should be: key:type,key:type " + v + "\n") + logger.Error("Fields format is wrong. Should be: key:type,key:type " + v) return "" } if i == 0 && strings.ToLower(kv[0]) != "id" { @@ -120,12 +120,12 @@ func (m postgresqlDriver) generateSQLFromFields(fields string) string { 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") + logger.Error("Fields format is wrong. Should be: key:type,key:type " + v) return "" } typ, tag := m.getSQLType(kv[1]) if typ == "" { - ColorLog("[ERRO] Fields format is wrong. Should be: key:type,key:type " + v + "\n") + logger.Error("Fields format is wrong. Should be: key:type,key:type " + v) return "" } if i == 0 && strings.ToLower(kv[0]) != "id" { @@ -177,7 +177,8 @@ func newDBDriver() DBDriver { case "postgres": return postgresqlDriver{} default: - panic("driver not supported") + logger.Fatal("Driver not supported") + return nil } } @@ -190,8 +191,7 @@ func generateMigration(mname, upsql, downsql, curpath string) { if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) { // create migrations directory if err := os.MkdirAll(migrationFilePath, 0777); err != nil { - ColorLog("[ERRO] Could not create migration directory: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not create migration directory: %s", err) } } // create file @@ -208,8 +208,7 @@ func generateMigration(mname, upsql, downsql, curpath string) { formatSourceCode(fpath) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") } else { - ColorLog("[ERRO] Could not create migration file: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not create migration file: %s", err) } } diff --git a/g_model.go b/g_model.go index ae23731..fc94309 100644 --- a/g_model.go +++ b/g_model.go @@ -35,19 +35,17 @@ func generateModel(mname, fields, currpath string) { modelStruct, hastime, err := getStruct(modelName, fields) if err != nil { - ColorLog("[ERRO] Could not generate the model struct: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not generate the model struct: %s", err) } - ColorLog("[INFO] Using '%s' as model name\n", modelName) - ColorLog("[INFO] Using '%s' as package name\n", packageName) + logger.Infof("Using '%s' as model name", modelName) + logger.Infof("Using '%s' as package name", packageName) fp := path.Join(currpath, "models", p) if _, err := os.Stat(fp); os.IsNotExist(err) { // Create the model's directory if err := os.MkdirAll(fp, 0777); err != nil { - ColorLog("[ERRO] Could not create the model directory: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not create the model directory: %s", err) } } @@ -67,8 +65,7 @@ func generateModel(mname, fields, currpath string) { formatSourceCode(fpath) fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m") } else { - ColorLog("[ERRO] Could not create model file: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not create model file: %s", err) } } diff --git a/g_scaffold.go b/g_scaffold.go index cccda16..dd43425 100644 --- a/g_scaffold.go +++ b/g_scaffold.go @@ -3,7 +3,7 @@ package main import "strings" func generateScaffold(sname, fields, currpath, driver, conn string) { - ColorLog("[INFO] Do you want to create a '%v' model? [Yes|No] ", sname) + logger.Infof("Do you want to create a '%s' model? [Yes|No] ", sname) // Generate the model if askForConfirmation() { @@ -11,19 +11,19 @@ func generateScaffold(sname, fields, currpath, driver, conn string) { } // Generate the controller - ColorLog("[INFO] Do you want to create a '%v' controller? [Yes|No] ", sname) + logger.Infof("Do you want to create a '%s' controller? [Yes|No] ", sname) if askForConfirmation() { generateController(sname, currpath) } // Generate the views - ColorLog("[INFO] Do you want to create views for this '%v' resource? [Yes|No] ", sname) + logger.Infof("Do you want to create views for this '%s' resource? [Yes|No] ", sname) if askForConfirmation() { generateView(sname, currpath) } // Generate a migration - ColorLog("[INFO] Do you want to create a '%v' migration and schema for this resource? [Yes|No] ", sname) + logger.Infof("Do you want to create a '%s' migration and schema for this resource? [Yes|No] ", sname) if askForConfirmation() { upsql := "" downsql := "" @@ -40,9 +40,9 @@ func generateScaffold(sname, fields, currpath, driver, conn string) { } // Run the migration - ColorLog("[INFO] Do you want to migrate the database? [Yes|No] ") + logger.Infof("Do you want to migrate the database? [Yes|No] ") if askForConfirmation() { 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)) + logger.Successf("All done! Don't forget to add beego.Router(\"/%s\" ,&controllers.%sController{}) to routers/route.go\n", sname, strings.Title(sname)) } diff --git a/g_views.go b/g_views.go index c078223..aa7815e 100644 --- a/g_views.go +++ b/g_views.go @@ -25,13 +25,12 @@ import ( func generateView(viewpath, currpath string) { w := NewColorWriter(os.Stdout) - ColorLog("[INFO] Generating view...\n") + logger.Info("Generating view...") 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) + logger.Fatalf("Could not create '%s' view: %s", viewpath, err) } cfile := path.Join(absViewPath, "index.tpl") @@ -40,8 +39,7 @@ func generateView(viewpath, currpath string) { f.WriteString(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) + logger.Fatalf("Could not create view file: %s", err) } cfile = path.Join(absViewPath, "show.tpl") @@ -50,8 +48,7 @@ func generateView(viewpath, currpath string) { f.WriteString(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) + logger.Fatalf("Could not create view file: %s", err) } cfile = path.Join(absViewPath, "create.tpl") @@ -60,8 +57,7 @@ func generateView(viewpath, currpath string) { f.WriteString(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) + logger.Fatalf("Could not create view file: %s", err) } cfile = path.Join(absViewPath, "edit.tpl") @@ -70,7 +66,6 @@ func generateView(viewpath, currpath string) { f.WriteString(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) + logger.Fatalf("Could not create view file: %s", err) } } diff --git a/hproseapp.go b/hproseapp.go index 82d3dad..c9a4dfd 100644 --- a/hproseapp.go +++ b/hproseapp.go @@ -65,7 +65,7 @@ var hproseMaingo = `package main import ( "fmt" "reflect" - + "{{.Appname}}/models" "github.com/hprose/hprose-golang/rpc" @@ -90,7 +90,7 @@ func main() { // Create Http Server service := rpc.NewHTTPService() - // Use Logger Middleware + // Use Logger Middleware service.AddInvokeHandler(logInvokeHandler) // Publish Functions @@ -139,7 +139,7 @@ func main() { // Create Http Server service := rpc.NewHTTPService() - // Use Logger Middleware + // Use Logger Middleware service.AddInvokeHandler(logInvokeHandler) {{HproseFunctionList}} @@ -314,8 +314,7 @@ func createhprose(cmd *Command, args []string) int { } apppath, packpath, err := checkEnv(args[0]) if err != nil { - fmt.Println(err) - os.Exit(2) + logger.Fatalf("%s", err) } if driver == "" { driver = "mysql" @@ -323,7 +322,7 @@ func createhprose(cmd *Command, args []string) int { if conn == "" { } - ColorLog("[INFO] Creating Hprose application...\n") + 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") @@ -334,9 +333,9 @@ func createhprose(cmd *Command, args []string) int { strings.Replace(hproseconf, "{{.Appname}}", args[0], -1)) if conn != "" { - ColorLog("[INFO] Using '%s' as 'driver'\n", driver) - ColorLog("[INFO] Using '%s' as 'conn'\n", conn) - ColorLog("[INFO] Using '%s' as 'tables'\n", tables) + logger.Infof("Using '%s' as 'driver'", driver) + 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") maingoContent := strings.Replace(hproseMainconngo, "{{.Appname}}", packpath, -1) @@ -369,6 +368,6 @@ func createhprose(cmd *Command, args []string) int { WriteToFile(path.Join(apppath, "main.go"), strings.Replace(hproseMaingo, "{{.Appname}}", packpath, -1)) } - ColorLog("[SUCC] New Hprose application successfully created!\n") + logger.Success("New Hprose application successfully created!") return 0 } diff --git a/migrate.go b/migrate.go index 22bfac3..873fbb5 100644 --- a/migrate.go +++ b/migrate.go @@ -16,14 +16,13 @@ package main import ( "database/sql" - "fmt" "os" "os/exec" "path" + "runtime" "strconv" "strings" "time" - "runtime" ) var cmdMigrate = &Command{ @@ -69,18 +68,20 @@ func runMigration(cmd *Command, args []string) int { gps := GetGOPATHs() if len(gps) == 0 { - ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty") - os.Exit(2) + logger.Fatal("GOPATH environment variable is not set or empty") } - gopath := gps[0] - Debugf("GOPATH: %s", gopath) - // load config + gopath := gps[0] + + logger.Debugf("GOPATH: %s", gopath) + + // Load the configuration err := loadConfig() if err != nil { - ColorLog("[ERRO] Fail to parse bee.json[ %s ]\n", err) + logger.Errorf("Failed to load configuration: %s", err) } - // getting command line arguments + + // Getting command line arguments if len(args) != 0 { cmd.Flag.Parse(args[1:]) } @@ -96,31 +97,30 @@ func runMigration(cmd *Command, args []string) int { mConn = "root:@tcp(127.0.0.1:3306)/test" } } - ColorLog("[INFO] Using '%s' as 'driver'\n", mDriver) - ColorLog("[INFO] Using '%s' as 'conn'\n", mConn) + logger.Infof("Using '%s' as 'driver'", mDriver) + logger.Infof("Using '%s' as 'conn'", mConn) driverStr, connStr := string(mDriver), string(mConn) if len(args) == 0 { // run all outstanding migrations - ColorLog("[INFO] Running all outstanding migrations\n") + logger.Info("Running all outstanding migrations") migrateUpdate(currpath, driverStr, connStr) } else { mcmd := args[0] switch mcmd { case "rollback": - ColorLog("[INFO] Rolling back the last migration operation\n") + logger.Info("Rolling back the last migration operation") migrateRollback(currpath, driverStr, connStr) case "reset": - ColorLog("[INFO] Reseting all migrations\n") + logger.Info("Reseting all migrations") migrateReset(currpath, driverStr, connStr) case "refresh": - ColorLog("[INFO] Refreshing all migrations\n") + logger.Info("Refreshing all migrations") migrateRefresh(currpath, driverStr, connStr) default: - ColorLog("[ERRO] Command is missing\n") - os.Exit(2) + logger.Fatal("Command is missing") } } - ColorLog("[SUCC] Migration successful!\n") + logger.Success("Migration successful!") return 0 } @@ -146,21 +146,21 @@ 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") + dir := path.Join(currpath, "database", "migrations") postfix := "" if runtime.GOOS == "windows" { postfix = ".exe" } binary := "m" + postfix source := binary + ".go" - // connect to database + + // Connect to database db, err := sql.Open(driver, connStr) if err != nil { - ColorLog("[ERRO] Could not connect to %s: %s\n", driver, connStr) - ColorLog("[ERRO] Error: %v", err.Error()) - os.Exit(2) + logger.Fatalf("Could not connect to database using '%s': %s", connStr, err) } defer db.Close() + checkForSchemaUpdateTable(db, driver) latestName, latestTime := getLatestMigration(db, goal) writeMigrationSourceFile(dir, source, driver, connStr, latestTime, latestName, goal) @@ -175,50 +175,44 @@ func migrate(goal, currpath, driver, connStr string) { func checkForSchemaUpdateTable(db *sql.DB, driver string) { showTableSQL := showMigrationsTableSQL(driver) if rows, err := db.Query(showTableSQL); err != nil { - ColorLog("[ERRO] Could not show migrations table: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not show migrations table: %s", err) } else if !rows.Next() { - // no migrations table, create anew + // No migrations table, create new ones createTableSQL := createMigrationsTableSQL(driver) - ColorLog("[INFO] Creating 'migrations' table...\n") + + logger.Infof("Creating 'migrations' table...") + if _, err := db.Query(createTableSQL); err != nil { - ColorLog("[ERRO] Could not create migrations table: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not create migrations table: %s", err) } } - // checking that migrations table schema are expected + // Checking that migrations table schema are expected 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) + logger.Fatalf("Could not show columns of migrations table: %s", err) } else { for rows.Next() { var fieldBytes, typeBytes, nullBytes, keyBytes, defaultBytes, extraBytes []byte if err := rows.Scan(&fieldBytes, &typeBytes, &nullBytes, &keyBytes, &defaultBytes, &extraBytes); err != nil { - ColorLog("[ERRO] Could not read column information: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not read column information: %s", err) } fieldStr, typeStr, nullStr, keyStr, defaultStr, extraStr := string(fieldBytes), string(typeBytes), string(nullBytes), string(keyBytes), string(defaultBytes), string(extraBytes) if fieldStr == "id_migration" { if keyStr != "PRI" || extraStr != "auto_increment" { - ColorLog("[ERRO] Column migration.id_migration type mismatch: KEY: %s, EXTRA: %s\n", keyStr, extraStr) - ColorLog("[HINT] Expecting KEY: PRI, EXTRA: auto_increment\n") - os.Exit(2) + logger.Hint("Expecting KEY: PRI, EXTRA: auto_increment") + logger.Fatalf("Column migration.id_migration type mismatch: KEY: %s, EXTRA: %s", keyStr, extraStr) } } else if fieldStr == "name" { if !strings.HasPrefix(typeStr, "varchar") || nullStr != "YES" { - ColorLog("[ERRO] Column migration.name type mismatch: TYPE: %s, NULL: %s\n", typeStr, nullStr) - ColorLog("[HINT] Expecting TYPE: varchar, NULL: YES\n") - os.Exit(2) + logger.Hint("Expecting TYPE: varchar, NULL: YES") + logger.Fatalf("Column migration.name type mismatch: TYPE: %s, NULL: %s", typeStr, nullStr) } - } else if fieldStr == "created_at" { if typeStr != "timestamp" || defaultStr != "CURRENT_TIMESTAMP" { - ColorLog("[ERRO] Column migration.timestamp type mismatch: TYPE: %s, DEFAULT: %s\n", typeStr, defaultStr) - ColorLog("[HINT] Expecting TYPE: timestamp, DEFAULT: CURRENT_TIMESTAMP\n") - os.Exit(2) + logger.Hint("Expecting TYPE: timestamp, DEFAULT: CURRENT_TIMESTAMP") + logger.Fatalf("Column migration.timestamp type mismatch: TYPE: %s, DEFAULT: %s", typeStr, defaultStr) } } } @@ -262,26 +256,22 @@ func selectMigrationsTableSQL(driver string) string { func getLatestMigration(db *sql.DB, goal string) (file string, createdAt int64) { sql := "SELECT name FROM migrations where status = 'update' ORDER BY id_migration DESC LIMIT 1" if rows, err := db.Query(sql); err != nil { - ColorLog("[ERRO] Could not retrieve migrations: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not retrieve migrations: %s", err) } else { if rows.Next() { if err := rows.Scan(&file); err != nil { - ColorLog("[ERRO] Could not read migrations in database: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not read migrations in database: %s", err) } createdAtStr := file[len(file)-15:] if t, err := time.Parse("20060102_150405", createdAtStr); err != nil { - ColorLog("[ERRO] Could not parse time: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not parse time: %s", err) } else { createdAt = t.Unix() } } else { // migration table has no 'update' record, no point rolling back if goal == "rollback" { - ColorLog("[ERRO] There is nothing to rollback\n") - os.Exit(2) + logger.Fatal("There is nothing to rollback") } file, createdAt = "", 0 } @@ -293,8 +283,7 @@ func getLatestMigration(db *sql.DB, goal string) (file string, createdAt int64) func writeMigrationSourceFile(dir, source, driver, connStr string, latestTime int64, latestName string, task string) { changeDir(dir) if f, err := os.OpenFile(source, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err != nil { - ColorLog("[ERRO] Could not create file: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not create file: %s", err) } else { content := strings.Replace(MigrationMainTPL, "{{DBDriver}}", driver, -1) content = strings.Replace(content, "{{ConnStr}}", connStr, -1) @@ -302,8 +291,7 @@ func writeMigrationSourceFile(dir, source, driver, connStr string, latestTime in content = strings.Replace(content, "{{LatestName}}", latestName, -1) content = strings.Replace(content, "{{Task}}", task, -1) if _, err := f.WriteString(content); err != nil { - ColorLog("[ERRO] Could not write to file: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not write to file: %s", err) } CloseFile(f) } @@ -314,7 +302,7 @@ func buildMigrationBinary(dir, binary string) { changeDir(dir) cmd := exec.Command("go", "build", "-o", binary) if out, err := cmd.CombinedOutput(); err != nil { - ColorLog("[ERRO] Could not build migration binary: %s\n", err) + logger.Errorf("Could not build migration binary: %s", err) formatShellErrOutput(string(out)) removeTempFile(dir, binary) removeTempFile(dir, binary+".go") @@ -328,7 +316,7 @@ func runMigrationBinary(dir, binary string) { cmd := exec.Command("./" + binary) if out, err := cmd.CombinedOutput(); err != nil { formatShellOutput(string(out)) - ColorLog("[ERRO] Could not run migration binary: %s\n", err) + logger.Errorf("Could not run migration binary: %s", err) removeTempFile(dir, binary) removeTempFile(dir, binary+".go") os.Exit(2) @@ -341,8 +329,7 @@ func runMigrationBinary(dir, binary string) { // It exits the system when encouter an error func changeDir(dir string) { if err := os.Chdir(dir); err != nil { - ColorLog("[ERRO] Could not find migration directory: %s\n", err) - os.Exit(2) + logger.Fatalf("Could not find migration directory: %s", err) } } @@ -350,7 +337,7 @@ func changeDir(dir string) { func removeTempFile(dir, file string) { changeDir(dir) if err := os.Remove(file); err != nil { - ColorLog("[WARN] Could not remove temporary file: %s\n", err) + logger.Warnf("Could not remove temporary file: %s", err) } } @@ -358,8 +345,7 @@ func removeTempFile(dir, file string) { func formatShellErrOutput(o string) { for _, line := range strings.Split(o, "\n") { if line != "" { - ColorLog("[ERRO] -| ") - fmt.Println(line) + logger.Errorf("|> %s", line) } } } @@ -368,13 +354,13 @@ func formatShellErrOutput(o string) { func formatShellOutput(o string) { for _, line := range strings.Split(o, "\n") { if line != "" { - ColorLog("[INFO] -| ") - fmt.Println(line) + logger.Infof("|> %s", line) } } } const ( + // MigrationMainTPL migration main template MigrationMainTPL = `package main import( @@ -414,6 +400,7 @@ func main(){ } ` + // MYSQLMigrationDDL MySQL migration SQL MYSQLMigrationDDL = ` CREATE TABLE migrations ( id_migration int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'surrogate key', @@ -425,7 +412,7 @@ CREATE TABLE migrations ( PRIMARY KEY (id_migration) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ` - + // POSTGRESMigrationDDL Postgres migration SQL POSTGRESMigrationDDL = ` CREATE TYPE migrations_status AS ENUM('update', 'rollback'); diff --git a/new.go b/new.go index 2f9e406..6ff411c 100644 --- a/new.go +++ b/new.go @@ -58,7 +58,7 @@ func createApp(cmd *Command, args []string) int { ShowShortVersionBanner() w := NewColorWriter(os.Stdout) if len(args) != 1 { - ColorLog("[ERRO] Argument [appname] is missing\n") + logger.Error("Argument [appname] is missing") os.Exit(2) } apppath, packpath, err := checkEnv(args[0]) @@ -68,14 +68,14 @@ 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] ") + logger.Errorf("Path (%s) already exists", apppath) + logger.Warn("Do you want to overwrite it? [Yes|No] ") if !askForConfirmation() { os.Exit(2) } } - ColorLog("[INFO] Creating application...\n") + 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") @@ -117,7 +117,7 @@ func createApp(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, "main.go"), "\x1b[0m") WriteToFile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", packpath, -1)) - ColorLog("[SUCC] New application successfully created!\n") + logger.Success("New application successfully created!") return 0 } @@ -302,13 +302,3 @@ var indextpl = ` ` - -// WriteToFile creates a file and writes content to it -func WriteToFile(filename, content string) { - f, err := os.Create(filename) - defer CloseFile(f) - if err != nil { - panic(err) - } - f.WriteString(content) -} diff --git a/pack.go b/pack.go index d6d84e4..2695840 100644 --- a/pack.go +++ b/pack.go @@ -104,11 +104,6 @@ func init() { w = NewColorWriter(os.Stdout) } -func exitPrint(con string) { - fmt.Fprintln(os.Stderr, con) - os.Exit(2) -} - type walker interface { isExclude(string) bool isEmpty(string) bool @@ -397,10 +392,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) { - ColorLog("Excluding relpath prefix: %s\n", strings.Join(excludePrefix, ":")) - ColorLog("Excluding relpath suffix: %s\n", strings.Join(excludeSuffix, ":")) + logger.Infof("Excluding relpath prefix: %s", strings.Join(excludePrefix, ":")) + logger.Infof("Excluding relpath suffix: %s", strings.Join(excludeSuffix, ":")) if len(excludeRegexp) > 0 { - ColorLog("Excluding filename regex: `%s`\n", strings.Join(excludeR, "`, `")) + logger.Infof("Excluding filename regex: `%s`", strings.Join(excludeR, "`, `")) } w, err := os.OpenFile(outputP, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) @@ -477,17 +472,17 @@ func packApp(cmd *Command, args []string) int { thePath, err := path.Abs(appPath) if err != nil { - exitPrint(fmt.Sprintf("Wrong app path: %s", thePath)) + logger.Fatalf("Wrong application path: %s", thePath) } if stat, err := os.Stat(thePath); os.IsNotExist(err) || stat.IsDir() == false { - exitPrint(fmt.Sprintf("App path does not exist: %s", thePath)) + logger.Fatalf("Application path does not exist: %s", thePath) } if isBeegoProject(thePath) == false { - exitPrint(fmt.Sprintf("Bee does not support non Beego project")) + logger.Fatal("Bee does not support non Beego project") } - ColorLog("Packaging application: %s\n", thePath) + logger.Infof("Packaging application on '%s'...", thePath) appName := path.Base(thePath) @@ -507,7 +502,7 @@ func packApp(cmd *Command, args []string) int { os.Mkdir(tmpdir, 0700) if build { - ColorLog("Building application...\n") + logger.Info("Building application...") var envs []string for _, env := range buildEnvs { parts := strings.SplitN(env, "=", 2) @@ -529,7 +524,7 @@ func packApp(cmd *Command, args []string) int { os.Setenv("GOOS", goos) os.Setenv("GOARCH", goarch) - ColorLog("Env: GOOS=%s GOARCH=%s\n", goos, goarch) + logger.Infof("Using: GOOS=%s GOARCH=%s", goos, goarch) binPath := path.Join(tmpdir, appName) if goos == "windows" { @@ -552,10 +547,10 @@ func packApp(cmd *Command, args []string) int { execmd.Dir = thePath err = execmd.Run() if err != nil { - exitPrint(err.Error()) + logger.Fatal(err.Error()) } - ColorLog("Build successful\n") + logger.Success("Build successful!") } switch format { @@ -573,7 +568,7 @@ func packApp(cmd *Command, args []string) int { if _, err := os.Stat(outputP); err != nil { err = os.MkdirAll(outputP, 0755) if err != nil { - exitPrint(err.Error()) + logger.Fatal(err.Error()) } } @@ -595,7 +590,7 @@ func packApp(cmd *Command, args []string) int { for _, r := range excludeR { if len(r) > 0 { if re, err := regexp.Compile(r); err != nil { - exitPrint(err.Error()) + logger.Fatal(err.Error()) } else { exr = append(exr, re) } @@ -604,9 +599,9 @@ func packApp(cmd *Command, args []string) int { err = packDirectory(exp, exs, exr, tmpdir, thePath) if err != nil { - exitPrint(err.Error()) + logger.Fatal(err.Error()) } - ColorLog("Writing to output: `%s`\n", outputP) + logger.Infof("Writing to output: %s", outputP) return 0 } diff --git a/run.go b/run.go index 8f4d3a3..88797ab 100644 --- a/run.go +++ b/run.go @@ -15,7 +15,6 @@ package main import ( - "fmt" "io/ioutil" "os" path "path/filepath" @@ -77,9 +76,8 @@ func runApp(cmd *Command, args []string) int { appname = path.Base(currpath) currentGoPath = _gopath } else { - exitPrint(fmt.Sprintf("Bee does not support non Beego project: %s", currpath)) + logger.Fatalf("No Beego application '%s' found in your GOPATH", currpath) } - ColorLog("[INFO] Using '%s' as 'appname'\n", appname) } else { // Check if passed Bee application path/name exists in the GOPATH(s) if found, _gopath, _path := SearchGOPATHs(args[0]); found { @@ -87,35 +85,35 @@ func runApp(cmd *Command, args []string) int { currentGoPath = _gopath appname = path.Base(currpath) } else { - exitPrint(fmt.Sprintf("No Beego application '%s' found in your GOPATH", args[0])) + logger.Fatalf("No Beego application '%s' found in your GOPATH", args[0]) } - 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]] ") + logger.Warnf("The appname is in conflict with file's current path. Do you want to build appname as '%s'", appname) + logger.Info("Do you want to overwrite it? [yes|no] ") if !askForConfirmation() { return 0 } } } - Debugf("current path:%s\n", currpath) + logger.Infof("Using '%s' as 'appname'", appname) + + logger.Debugf("Current path: %s", currpath) if runmode == "prod" || runmode == "dev" { os.Setenv("BEEGO_RUNMODE", runmode) - ColorLog("[INFO] Using '%s' as 'runmode'\n", os.Getenv("BEEGO_RUNMODE")) + logger.Infof("Using '%s' as 'runmode'", os.Getenv("BEEGO_RUNMODE")) } else if runmode != "" { os.Setenv("BEEGO_RUNMODE", runmode) - ColorLog("[WARN] Using '%s' as 'runmode'\n", os.Getenv("BEEGO_RUNMODE")) + logger.Warnf("Using '%s' as 'runmode'", os.Getenv("BEEGO_RUNMODE")) } else if os.Getenv("BEEGO_RUNMODE") != "" { - ColorLog("[WARN] Using '%s' as 'runmode'\n", os.Getenv("BEEGO_RUNMODE")) + logger.Warnf("Using '%s' as 'runmode'", os.Getenv("BEEGO_RUNMODE")) } err := loadConfig() if err != nil { - ColorLog("[ERRO] Failed to load configuration [ %s ]\n", err) + logger.Fatalf("Failed to load configuration: %s", err) } var paths []string @@ -143,10 +141,10 @@ func runApp(cmd *Command, args []string) int { } if gendoc == "true" { NewWatcher(paths, files, true) - Autobuild(files, true) + AutoBuild(files, true) } else { NewWatcher(paths, files, false) - Autobuild(files, false) + AutoBuild(files, false) } for { @@ -202,16 +200,16 @@ func isExcluded(filePath string) bool { for _, p := range excludedPaths { absP, err := path.Abs(p) if err != nil { - ColorLog("[ERROR] Can not get absolute path of [ %s ]\n", p) + logger.Errorf("Cannot get absolute path of '%s'", p) continue } absFilePath, err := path.Abs(filePath) if err != nil { - ColorLog("[ERROR] Can not get absolute path of [ %s ]\n", filePath) + logger.Errorf("Cannot get absolute path of '%s'", filePath) break } if strings.HasPrefix(absFilePath, absP) { - ColorLog("[INFO] Excluding from watching [ %s ]\n", filePath) + logger.Infof("'%s' is not being watched", filePath) return true } } diff --git a/rundocs.go b/rundocs.go index 35eef7e..e374329 100644 --- a/rundocs.go +++ b/rundocs.go @@ -17,7 +17,6 @@ import ( "archive/zip" "fmt" "io" - "log" "net/http" "os" "strings" @@ -63,18 +62,22 @@ func runDocs(cmd *Command, args []string) int { downloadFromURL(swaggerlink, "swagger.zip") err := unzipAndDelete("swagger.zip") if err != nil { - fmt.Println("has err exet unzipAndDelete", err) + logger.Errorf("Error while unzipping 'swagger.zip' file: %s", err) } } if docport == "" { docport = "8089" } if _, err := os.Stat("swagger"); err != nil && os.IsNotExist(err) { - fmt.Println("there's no swagger, please use bee rundocs -isDownload=true downlaod first") - os.Exit(2) + logger.Fatal("No Swagger dist found. Run: bee rundocs -isDownload=true") + } + + logger.Infof("Starting the docs server on: http://127.0.0.1:%s", docport) + + err := http.ListenAndServe(":"+string(docport), http.FileServer(http.Dir("swagger"))) + if err != nil { + logger.Fatalf("%s", err) } - fmt.Println("start the docs server on: http://127.0.0.1:" + docport) - log.Fatal(http.ListenAndServe(":"+string(docport), http.FileServer(http.Dir("swagger")))) return 0 } @@ -85,36 +88,36 @@ func downloadFromURL(url, fileName string) { } else if fd.Size() == int64(0) { down = true } else { - ColorLog("[%s] Filename %s already exist\n", INFO, fileName) + logger.Infof("'%s' already exists", fileName) return } if down { - ColorLog("[%s]Downloading %s to %s\n", SUCC, url, fileName) + logger.Infof("Downloading '%s' to '%s'...", url, fileName) output, err := os.Create(fileName) if err != nil { - ColorLog("[%s]Error while creating %s: %s\n", ERRO, fileName, err) + logger.Errorf("Error while creating '%s': %s", fileName, err) return } defer output.Close() response, err := http.Get(url) if err != nil { - ColorLog("[%s]Error while downloading %s:%s\n", ERRO, url, err) + logger.Errorf("Error while downloading '%s': %s", 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) + logger.Errorf("Error while downloading '%s': %s", url, err) return } - ColorLog("[%s] %d bytes downloaded.\n", SUCC, n) + logger.Successf("%d bytes downloaded!", n) } } func unzipAndDelete(src string) error { - ColorLog("[%s]start to unzip file from %s\n", INFO, src) + logger.Infof("Unzipping '%s'...", src) r, err := zip.OpenReader(src) if err != nil { return err @@ -146,6 +149,6 @@ func unzipAndDelete(src string) error { } } } - ColorLog("[%s]Start delete src file %s\n", INFO, src) + logger.Successf("Done! Deleting '%s'...", src) return os.RemoveAll(src) } diff --git a/test.go b/test.go index de5116d..b05c10b 100644 --- a/test.go +++ b/test.go @@ -51,19 +51,19 @@ var started = make(chan bool) func testApp(cmd *Command, args []string) int { if len(args) != 1 { - ColorLog("[ERRO] Cannot start running[ %s ]\n", - "argument 'appname' is missing") - os.Exit(2) + logger.Fatalf("Failed to start: %s", "argument 'appname' is missing") } - crupath, _ := os.Getwd() - Debugf("current path:%s\n", crupath) + + currpath, _ := os.Getwd() + + logger.Debugf("Current path: %s", currpath) err := loadConfig() if err != nil { - ColorLog("[ERRO] Fail to parse bee.json[ %s ]\n", err) + logger.Fatalf("Failed to load configuration: %s", err) } var paths []string - readAppDirectories(crupath, &paths) + readAppDirectories(currpath, &paths) NewWatcher(paths, nil, false) appname = args[0] @@ -76,7 +76,7 @@ func testApp(cmd *Command, args []string) int { } func runTest() { - ColorLog("[INFO] Start testing...\n") + logger.Info("Start testing...") time.Sleep(time.Second * 1) crupwd, _ := os.Getwd() testDir := path.Join(crupwd, "tests") @@ -88,14 +88,14 @@ func runTest() { icmd := exec.Command("go", "test") icmd.Stdout = os.Stdout icmd.Stderr = os.Stderr - ColorLog("[TRAC] ============== Test Begin ===================\n") + logger.Info("============== Test Begin ===================") err = icmd.Run() - ColorLog("[TRAC] ============== Test End ===================\n") + logger.Info("============== Test End =====================") if err != nil { - ColorLog("[ERRO] ============== Test failed ===================\n") - ColorLog("[ERRO] %s", err) + logger.Error("============== Test failed ===================") + logger.Errorf("Cause: %s", err) return } - ColorLog("[SUCC] Test finish\n") + logger.Success("Test Completed") } diff --git a/version.go b/version.go index b95c3ea..02e1414 100644 --- a/version.go +++ b/version.go @@ -78,7 +78,7 @@ func getBeegoVersion() string { return "" } if gopath == "" { - err = fmt.Errorf("You should set GOPATH env variable") + err = fmt.Errorf("You need to set GOPATH environment variable") return "" } wgopath := path.SplitList(gopath) @@ -90,11 +90,11 @@ func getBeegoVersion() string { if os.IsNotExist(err) { continue } - ColorLog("[ERRO] Get `beego.go` has error\n") + logger.Error("Error while getting stats of 'beego.go'") } fd, err := os.Open(filename) if err != nil { - ColorLog("[ERRO] Open `beego.go` has error\n") + logger.Error("Error while reading 'beego.go'") continue } reader := bufio.NewReader(fd) @@ -114,7 +114,7 @@ func getBeegoVersion() string { } } - return "Beego not installed. Please install it first: https://github.com/astaxie/beego" + return "Beego is not installed. Please do consider installing it first: https://github.com/astaxie/beego" } func getGoVersion() string { @@ -124,8 +124,7 @@ func getGoVersion() string { ) if cmdOut, err = exec.Command("go", "version").Output(); err != nil { - fmt.Fprintln(os.Stderr, "There was an error running go version command:", err) - os.Exit(2) + logger.Fatalf("There was an error running go version command: %s", err) } return strings.Split(string(cmdOut), " ")[2] } diff --git a/watch.go b/watch.go index 1c8f593..34c03b3 100644 --- a/watch.go +++ b/watch.go @@ -16,7 +16,6 @@ package main import ( "bytes" - "fmt" "github.com/howeyc/fsnotify" "os" "os/exec" @@ -34,11 +33,11 @@ var ( scheduleTime time.Time ) +// NewWatcher starts an fsnotify Watcher on the specified paths func NewWatcher(paths []string, files []string, isgenerate bool) { watcher, err := fsnotify.NewWatcher() if err != nil { - ColorLog("[ERRO] Fail to create new Watcher[ %s ]\n", err) - os.Exit(2) + logger.Fatalf("Failed to create watcher: %s", err) } go func() { @@ -57,14 +56,14 @@ func NewWatcher(paths []string, files []string, isgenerate bool) { mt := getFileModTime(e.Name) if t := eventTime[e.Name]; mt == t { - ColorLog("[SKIP] # %s #\n", e.String()) + logger.Infof(bold("Skipping: ")+"%s", e.String()) isbuild = false } eventTime[e.Name] = mt if isbuild { - ColorLog("[EVEN] %s\n", e) + logger.Infof("Event fired: %s", e) go func() { // Wait 1s before autobuild util there is no file change. scheduleTime = time.Now().Add(1 * time.Second) @@ -76,22 +75,21 @@ func NewWatcher(paths []string, files []string, isgenerate bool) { return } - Autobuild(files, isgenerate) + AutoBuild(files, isgenerate) }() } case err := <-watcher.Error: - ColorLog("[WARN] %s\n", err.Error()) // No need to exit here + logger.Warnf("Watcher error: %s", err.Error()) // No need to exit here } } }() - ColorLog("[INFO] Initializing watcher...\n") + logger.Info("Initializing watcher...") for _, path := range paths { - ColorLog("[TRAC] Directory( %s )\n", path) + logger.Infof(bold("Watching: ")+"%s", path) err = watcher.Watch(path) if err != nil { - ColorLog("[ERRO] Fail to watch directory[ %s ]\n", err) - os.Exit(2) + logger.Fatalf("Failed to watch directory: %s", err) } } @@ -102,25 +100,26 @@ func getFileModTime(path string) int64 { path = strings.Replace(path, "\\", "/", -1) f, err := os.Open(path) if err != nil { - ColorLog("[ERRO] Fail to open file[ %s ]\n", err) + logger.Errorf("Failed to open file on '%s': %s", path, err) return time.Now().Unix() } defer f.Close() fi, err := f.Stat() if err != nil { - ColorLog("[ERRO] Fail to get file information[ %s ]\n", err) + logger.Errorf("Failed to get file stats: %s", err) return time.Now().Unix() } return fi.ModTime().Unix() } -func Autobuild(files []string, isgenerate bool) { +// AutoBuild builds the specified set of files +func AutoBuild(files []string, isgenerate bool) { state.Lock() defer state.Unlock() - ColorLog("[INFO] Start building...\n") + logger.Info("Start building...") os.Chdir(currpath) @@ -162,7 +161,7 @@ func Autobuild(files []string, isgenerate bool) { icmd.Stdout = os.Stdout icmd.Stderr = os.Stderr icmd.Run() - ColorLog("============== generate docs ===================\n") + logger.Info("============== Generate Docs ===================") } if err == nil { @@ -186,35 +185,38 @@ func Autobuild(files []string, isgenerate bool) { } if err != nil { - ColorLog("[ERRO] ============== Build failed ===================\n") + logger.Error("============== Build Failed ===================") return } - ColorLog("[SUCC] Build was successful\n") + logger.Success("Built Successfully!") Restart(appname) } +// Kill kills the running command process func Kill() { defer func() { if e := recover(); e != nil { - fmt.Println("Kill.recover -> ", e) + logger.Infof("Kill recover: %s", e) } }() if cmd != nil && cmd.Process != nil { err := cmd.Process.Kill() if err != nil { - fmt.Println("Kill -> ", err) + logger.Errorf("Error while killing cmd process: %s", err) } } } +// Restart kills the running command process and starts it again func Restart(appname string) { - Debugf("kill running process") + logger.Debugf("Kill running process") Kill() go Start(appname) } +// Start starts the command process func Start(appname string) { - ColorLog("[INFO] Restarting %s ...\n", appname) + logger.Infof("Restarting '%s'...", appname) if strings.Index(appname, "./") == -1 { appname = "./" + appname } @@ -226,17 +228,17 @@ func Start(appname string) { cmd.Env = append(os.Environ(), conf.Envs...) go cmd.Run() - ColorLog("[INFO] %s is running...\n", appname) + logger.Successf("'%s' is running...", appname) started <- true } -// Should ignore filenames generated by -// Emacs, Vim or SublimeText +// shouldIgnoreFile ignores filenames generated by Emacs, Vim or SublimeText. +// It returns true if the file should be ignored, false otherwise. func shouldIgnoreFile(filename string) bool { for _, regex := range ignoredFilesRegExps { r, err := regexp.Compile(regex) if err != nil { - panic("Could not compile the regex: " + regex) + logger.Fatalf("Could not compile regular expression: %s", err) } if r.MatchString(filename) { return true