mirror of
https://github.com/beego/bee.git
synced 2024-12-22 15:10:49 +00:00
commit
6dce4df2cb
@ -3,3 +3,4 @@ language: go
|
||||
go:
|
||||
- 1.6.3
|
||||
- 1.7.3
|
||||
- 1.8
|
||||
|
280
autorouter.go
280
autorouter.go
@ -1,280 +0,0 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
gobuild "go/build"
|
||||
"go/doc"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var cmdRouter = &Command{
|
||||
UsageLine: "router",
|
||||
Short: "auto-generate routers for the app controllers",
|
||||
Long: `
|
||||
|
||||
`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRouter.Run = autoRouter
|
||||
}
|
||||
|
||||
func autoRouter(cmd *Command, args []string) int {
|
||||
fmt.Println("[INFO] Starting auto-generating routers...")
|
||||
return 0
|
||||
}
|
||||
|
||||
// getControllerInfo returns controllers that embeded "beego.controller"
|
||||
// and their methods of package in given path.
|
||||
func getControllerInfo(path string) (map[string][]string, error) {
|
||||
now := time.Now()
|
||||
path = strings.TrimSuffix(path, "/")
|
||||
dir, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fis, err := dir.Readdir(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
files := make([]*source, 0, len(fis))
|
||||
for _, fi := range fis {
|
||||
// Only load Go files
|
||||
if strings.HasSuffix(fi.Name(), ".go") {
|
||||
f, err := os.Open(path + "/" + fi.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p := make([]byte, fi.Size())
|
||||
_, err = f.Read(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f.Close()
|
||||
files = append(files, &source{
|
||||
name: path + "/" + fi.Name(),
|
||||
data: p,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
rw := &routerWalker{
|
||||
pdoc: &Package{
|
||||
ImportPath: path,
|
||||
},
|
||||
}
|
||||
|
||||
cm := make(map[string][]string)
|
||||
pdoc, err := rw.build(files)
|
||||
for _, t := range pdoc.Types {
|
||||
// Check if embeded "beego.Controller".
|
||||
if strings.Index(t.Decl, "beego.Controller") > -1 {
|
||||
for _, f := range t.Methods {
|
||||
cm[t.Name] = append(cm[t.Name], f.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println(time.Since(now))
|
||||
return cm, nil
|
||||
}
|
||||
|
||||
// source represents a source code file.
|
||||
type source struct {
|
||||
name string
|
||||
data []byte
|
||||
}
|
||||
|
||||
func (s *source) Name() string { return s.name }
|
||||
func (s *source) Size() int64 { return int64(len(s.data)) }
|
||||
func (s *source) Mode() os.FileMode { return 0 }
|
||||
func (s *source) ModTime() time.Time { return time.Time{} }
|
||||
func (s *source) IsDir() bool { return false }
|
||||
func (s *source) Sys() interface{} { return nil }
|
||||
|
||||
// routerWalker holds the state used when building the documentation.
|
||||
type routerWalker struct {
|
||||
pdoc *Package
|
||||
srcs map[string]*source // Source files
|
||||
fset *token.FileSet
|
||||
buf []byte // scratch space for printNode method
|
||||
}
|
||||
|
||||
// Package represents full information and documentation for a package.
|
||||
type Package struct {
|
||||
ImportPath string
|
||||
Types []*Type // Top-level declarations
|
||||
}
|
||||
|
||||
// Type represents structs and interfaces.
|
||||
type Type struct {
|
||||
Name string // Type name
|
||||
Decl string
|
||||
Methods []*Func // Exported methods
|
||||
}
|
||||
|
||||
// Func represents functions
|
||||
type Func struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// build generates data from source files.
|
||||
func (w *routerWalker) build(srcs []*source) (*Package, error) {
|
||||
// Add source files to walker, I skipped references here
|
||||
w.srcs = make(map[string]*source)
|
||||
for _, src := range srcs {
|
||||
w.srcs[src.name] = src
|
||||
}
|
||||
|
||||
w.fset = token.NewFileSet()
|
||||
|
||||
// Find the package and associated files
|
||||
ctxt := gobuild.Context{
|
||||
GOOS: runtime.GOOS,
|
||||
GOARCH: runtime.GOARCH,
|
||||
CgoEnabled: true,
|
||||
JoinPath: path.Join,
|
||||
IsAbsPath: path.IsAbs,
|
||||
SplitPathList: func(list string) []string { return strings.Split(list, ":") },
|
||||
IsDir: func(path string) bool { panic("unexpected") },
|
||||
HasSubdir: func(root, dir string) (rel string, ok bool) { panic("unexpected") },
|
||||
ReadDir: func(dir string) (fi []os.FileInfo, err error) { return w.readDir(dir) },
|
||||
OpenFile: func(path string) (r io.ReadCloser, err error) { return w.openFile(path) },
|
||||
Compiler: "gc",
|
||||
}
|
||||
|
||||
bpkg, err := ctxt.ImportDir(w.pdoc.ImportPath, 0)
|
||||
// Continue if there are no Go source files; we still want the directory info
|
||||
_, nogo := err.(*gobuild.NoGoError)
|
||||
if err != nil {
|
||||
if nogo {
|
||||
err = nil
|
||||
} else {
|
||||
return nil, errors.New("routerWalker.build -> " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the Go files
|
||||
files := make(map[string]*ast.File)
|
||||
for _, name := range append(bpkg.GoFiles, bpkg.CgoFiles...) {
|
||||
file, err := parser.ParseFile(w.fset, name, w.srcs[name].data, parser.ParseComments)
|
||||
if err != nil {
|
||||
return nil, errors.New("routerWalker.build -> parse go files: " + err.Error())
|
||||
}
|
||||
files[name] = file
|
||||
}
|
||||
|
||||
apkg, _ := ast.NewPackage(w.fset, files, simpleImporter, nil)
|
||||
|
||||
mode := doc.Mode(0)
|
||||
if w.pdoc.ImportPath == "builtin" {
|
||||
mode |= doc.AllDecls
|
||||
}
|
||||
|
||||
pdoc := doc.New(apkg, w.pdoc.ImportPath, mode)
|
||||
|
||||
w.pdoc.Types = w.types(pdoc.Types)
|
||||
|
||||
return w.pdoc, err
|
||||
}
|
||||
|
||||
func (w *routerWalker) funcs(fdocs []*doc.Func) []*Func {
|
||||
var result []*Func
|
||||
for _, d := range fdocs {
|
||||
result = append(result, &Func{
|
||||
Name: d.Name,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (w *routerWalker) types(tdocs []*doc.Type) []*Type {
|
||||
var result []*Type
|
||||
for _, d := range tdocs {
|
||||
result = append(result, &Type{
|
||||
Decl: w.printDecl(d.Decl),
|
||||
Name: d.Name,
|
||||
Methods: w.funcs(d.Methods),
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (w *routerWalker) printDecl(decl ast.Node) string {
|
||||
var d Code
|
||||
d, w.buf = printDecl(decl, w.fset, w.buf)
|
||||
return d.Text
|
||||
}
|
||||
|
||||
func (w *routerWalker) readDir(dir string) ([]os.FileInfo, error) {
|
||||
if dir != w.pdoc.ImportPath {
|
||||
panic("unexpected")
|
||||
}
|
||||
fis := make([]os.FileInfo, 0, len(w.srcs))
|
||||
for _, src := range w.srcs {
|
||||
fis = append(fis, src)
|
||||
}
|
||||
return fis, nil
|
||||
}
|
||||
|
||||
func (w *routerWalker) openFile(path string) (io.ReadCloser, error) {
|
||||
if strings.HasPrefix(path, w.pdoc.ImportPath+"/") {
|
||||
if src, ok := w.srcs[path[len(w.pdoc.ImportPath)+1:]]; ok {
|
||||
return ioutil.NopCloser(bytes.NewReader(src.data)), nil
|
||||
}
|
||||
}
|
||||
panic("unexpected")
|
||||
}
|
||||
|
||||
func simpleImporter(imports map[string]*ast.Object, path string) (*ast.Object, error) {
|
||||
pkg := imports[path]
|
||||
if pkg == nil {
|
||||
// Guess the package name without importing it. Start with the last
|
||||
// element of the path.
|
||||
name := path[strings.LastIndex(path, "/")+1:]
|
||||
|
||||
// Trim commonly used prefixes and suffixes containing illegal name
|
||||
// runes.
|
||||
name = strings.TrimSuffix(name, ".go")
|
||||
name = strings.TrimSuffix(name, "-go")
|
||||
name = strings.TrimPrefix(name, "go.")
|
||||
name = strings.TrimPrefix(name, "go-")
|
||||
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.
|
||||
pkg = ast.NewObj(ast.Pkg, name)
|
||||
pkg.Data = ast.NewScope(nil)
|
||||
imports[path] = pkg
|
||||
}
|
||||
return pkg, nil
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetControllerInfo(t *testing.T) {
|
||||
getControllerInfo("testdata/router/")
|
||||
}
|
258
bee.go
258
bee.go
@ -1,258 +0,0 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
// Bee is a tool for developing applications based on beego framework.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
const version = "1.8.0"
|
||||
|
||||
// Command is the unit of execution
|
||||
type Command struct {
|
||||
// Run runs the command.
|
||||
// The args are the arguments after the command name.
|
||||
Run func(cmd *Command, args []string) int
|
||||
|
||||
// PreRun performs an operation before running the command
|
||||
PreRun func(cmd *Command, args []string)
|
||||
|
||||
// UsageLine is the one-line usage message.
|
||||
// The first word in the line is taken to be the command name.
|
||||
UsageLine string
|
||||
|
||||
// Short is the short description shown in the 'go help' output.
|
||||
Short string
|
||||
|
||||
// Long is the long message shown in the 'go help <this-command>' output.
|
||||
Long string
|
||||
|
||||
// Flag is a set of flags specific to this command.
|
||||
Flag flag.FlagSet
|
||||
|
||||
// CustomFlags indicates that the command will do its own
|
||||
// flag parsing.
|
||||
CustomFlags bool
|
||||
|
||||
// output out writer if set in SetOutput(w)
|
||||
output *io.Writer
|
||||
}
|
||||
|
||||
// Name returns the command's name: the first word in the usage line.
|
||||
func (c *Command) Name() string {
|
||||
name := c.UsageLine
|
||||
i := strings.Index(name, " ")
|
||||
if i >= 0 {
|
||||
name = name[:i]
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// SetOutput sets the destination for usage and error messages.
|
||||
// If output is nil, os.Stderr is used.
|
||||
func (c *Command) SetOutput(output io.Writer) {
|
||||
c.output = &output
|
||||
}
|
||||
|
||||
// Out returns the out writer of the current command.
|
||||
// If cmd.output is nil, os.Stderr is used.
|
||||
func (c *Command) Out() io.Writer {
|
||||
if c.output != nil {
|
||||
return *c.output
|
||||
}
|
||||
return NewColorWriter(os.Stderr)
|
||||
}
|
||||
|
||||
// Usage puts out the usage for the command.
|
||||
func (c *Command) Usage() {
|
||||
tmpl(cmdUsage, c)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
// Runnable reports whether the command can be run; otherwise
|
||||
// it is a documentation pseudo-command such as import path.
|
||||
func (c *Command) Runnable() bool {
|
||||
return c.Run != nil
|
||||
}
|
||||
|
||||
func (c *Command) Options() map[string]string {
|
||||
options := make(map[string]string)
|
||||
c.Flag.VisitAll(func(f *flag.Flag) {
|
||||
defaultVal := f.DefValue
|
||||
if len(defaultVal) > 0 {
|
||||
options[f.Name+"="+defaultVal] = f.Usage
|
||||
} else {
|
||||
options[f.Name] = f.Usage
|
||||
}
|
||||
})
|
||||
return options
|
||||
}
|
||||
|
||||
var availableCommands = []*Command{
|
||||
cmdNew,
|
||||
cmdRun,
|
||||
cmdPack,
|
||||
cmdApiapp,
|
||||
cmdHproseapp,
|
||||
//cmdRouter,
|
||||
//cmdTest,
|
||||
cmdBale,
|
||||
cmdVersion,
|
||||
cmdGenerate,
|
||||
//cmdRundocs,
|
||||
cmdMigrate,
|
||||
cmdFix,
|
||||
cmdDockerize,
|
||||
}
|
||||
|
||||
var logger = GetBeeLogger(os.Stdout)
|
||||
|
||||
func main() {
|
||||
currentpath, _ := os.Getwd()
|
||||
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
log.SetFlags(0)
|
||||
|
||||
args := flag.Args()
|
||||
|
||||
if len(args) < 1 {
|
||||
usage()
|
||||
}
|
||||
|
||||
if args[0] == "help" {
|
||||
help(args[1:])
|
||||
return
|
||||
}
|
||||
|
||||
for _, cmd := range availableCommands {
|
||||
if cmd.Name() == args[0] && cmd.Run != nil {
|
||||
cmd.Flag.Usage = func() { cmd.Usage() }
|
||||
if cmd.CustomFlags {
|
||||
args = args[1:]
|
||||
} else {
|
||||
cmd.Flag.Parse(args[1:])
|
||||
args = cmd.Flag.Args()
|
||||
}
|
||||
|
||||
if cmd.PreRun != nil {
|
||||
cmd.PreRun(cmd, args)
|
||||
}
|
||||
|
||||
// Check if current directory is inside the GOPATH,
|
||||
// if so parse the packages inside it.
|
||||
if strings.Contains(currentpath, GetGOPATHs()[0]+"/src") && isGenerateDocs(cmd.Name(), args) {
|
||||
parsePackagesFromDir(currentpath)
|
||||
}
|
||||
|
||||
os.Exit(cmd.Run(cmd, args))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
printErrorAndExit("Unknown subcommand")
|
||||
}
|
||||
|
||||
func isGenerateDocs(name string, args []string) bool {
|
||||
if name != "generate" {
|
||||
return false
|
||||
}
|
||||
for _, a := range args {
|
||||
if a == "docs" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var usageTemplate = `Bee is a Fast and Flexible tool for managing your Beego Web Application.
|
||||
|
||||
{{"USAGE" | headline}}
|
||||
{{"bee command [arguments]" | bold}}
|
||||
|
||||
{{"AVAILABLE COMMANDS" | headline}}
|
||||
{{range .}}{{if .Runnable}}
|
||||
{{.Name | printf "%-11s" | bold}} {{.Short}}{{end}}{{end}}
|
||||
|
||||
Use {{"bee help [command]" | bold}} for more information about a command.
|
||||
|
||||
{{"ADDITIONAL HELP TOPICS" | headline}}
|
||||
{{range .}}{{if not .Runnable}}
|
||||
{{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
|
||||
|
||||
Use {{"bee help [topic]" | bold}} for more information about that topic.
|
||||
`
|
||||
|
||||
var helpTemplate = `{{"USAGE" | headline}}
|
||||
{{.UsageLine | printf "bee %s" | bold}}
|
||||
{{if .Options}}{{endline}}{{"OPTIONS" | headline}}{{range $k,$v := .Options}}
|
||||
{{$k | printf "-%s" | bold}}
|
||||
{{$v}}
|
||||
{{end}}{{end}}
|
||||
{{"DESCRIPTION" | headline}}
|
||||
{{tmpltostr .Long . | trim}}
|
||||
`
|
||||
|
||||
var errorTemplate = `bee: %s.
|
||||
Use {{"bee help" | bold}} for more information.
|
||||
`
|
||||
|
||||
var cmdUsage = `Use {{printf "bee help %s" .Name | bold}} for more information.{{endline}}`
|
||||
|
||||
func usage() {
|
||||
tmpl(usageTemplate, availableCommands)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
func tmpl(text string, data interface{}) {
|
||||
output := NewColorWriter(os.Stderr)
|
||||
|
||||
t := template.New("usage").Funcs(BeeFuncMap())
|
||||
template.Must(t.Parse(text))
|
||||
|
||||
err := t.Execute(output, data)
|
||||
MustCheck(err)
|
||||
}
|
||||
|
||||
func help(args []string) {
|
||||
if len(args) == 0 {
|
||||
usage()
|
||||
}
|
||||
if len(args) != 1 {
|
||||
printErrorAndExit("Too many arguments")
|
||||
}
|
||||
|
||||
arg := args[0]
|
||||
|
||||
for _, cmd := range availableCommands {
|
||||
if cmd.Name() == arg {
|
||||
tmpl(helpTemplate, cmd)
|
||||
return
|
||||
}
|
||||
}
|
||||
printErrorAndExit("Unknown help topic")
|
||||
}
|
||||
|
||||
func printErrorAndExit(message string) {
|
||||
tmpl(fmt.Sprintf(errorTemplate, message), nil)
|
||||
os.Exit(2)
|
||||
}
|
102
cmd/bee.go
Normal file
102
cmd/bee.go
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
// Bee is a tool for developing applications based on beego framework.
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
_ "github.com/beego/bee/cmd/commands/api"
|
||||
_ "github.com/beego/bee/cmd/commands/bale"
|
||||
_ "github.com/beego/bee/cmd/commands/beefix"
|
||||
_ "github.com/beego/bee/cmd/commands/dockerize"
|
||||
_ "github.com/beego/bee/cmd/commands/generate"
|
||||
_ "github.com/beego/bee/cmd/commands/hprose"
|
||||
_ "github.com/beego/bee/cmd/commands/migrate"
|
||||
_ "github.com/beego/bee/cmd/commands/new"
|
||||
_ "github.com/beego/bee/cmd/commands/pack"
|
||||
_ "github.com/beego/bee/cmd/commands/run"
|
||||
_ "github.com/beego/bee/cmd/commands/version"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
func IfGenerateDocs(name string, args []string) bool {
|
||||
if name != "generate" {
|
||||
return false
|
||||
}
|
||||
for _, a := range args {
|
||||
if a == "docs" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var usageTemplate = `Bee is a Fast and Flexible tool for managing your Beego Web Application.
|
||||
|
||||
{{"USAGE" | headline}}
|
||||
{{"bee command [arguments]" | bold}}
|
||||
|
||||
{{"AVAILABLE COMMANDS" | headline}}
|
||||
{{range .}}{{if .Runnable}}
|
||||
{{.Name | printf "%-11s" | bold}} {{.Short}}{{end}}{{end}}
|
||||
|
||||
Use {{"bee help [command]" | bold}} for more information about a command.
|
||||
|
||||
{{"ADDITIONAL HELP TOPICS" | headline}}
|
||||
{{range .}}{{if not .Runnable}}
|
||||
{{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
|
||||
|
||||
Use {{"bee help [topic]" | bold}} for more information about that topic.
|
||||
`
|
||||
|
||||
var helpTemplate = `{{"USAGE" | headline}}
|
||||
{{.UsageLine | printf "bee %s" | bold}}
|
||||
{{if .Options}}{{endline}}{{"OPTIONS" | headline}}{{range $k,$v := .Options}}
|
||||
{{$k | printf "-%s" | bold}}
|
||||
{{$v}}
|
||||
{{end}}{{end}}
|
||||
{{"DESCRIPTION" | headline}}
|
||||
{{tmpltostr .Long . | trim}}
|
||||
`
|
||||
|
||||
var ErrorTemplate = `bee: %s.
|
||||
Use {{"bee help" | bold}} for more information.
|
||||
`
|
||||
|
||||
func Usage() {
|
||||
utils.Tmpl(usageTemplate, commands.AvailableCommands)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
func Help(args []string) {
|
||||
if len(args) == 0 {
|
||||
Usage()
|
||||
}
|
||||
if len(args) != 1 {
|
||||
utils.PrintErrorAndExit("Too many arguments", ErrorTemplate)
|
||||
}
|
||||
|
||||
arg := args[0]
|
||||
|
||||
for _, cmd := range commands.AvailableCommands {
|
||||
if cmd.Name() == arg {
|
||||
utils.Tmpl(helpTemplate, cmd)
|
||||
return
|
||||
}
|
||||
}
|
||||
utils.PrintErrorAndExit("Unknown help topic", ErrorTemplate)
|
||||
}
|
@ -12,16 +12,22 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package apiapp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
path "path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
"github.com/beego/bee/cmd/commands/version"
|
||||
"github.com/beego/bee/generate"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
var cmdApiapp = &Command{
|
||||
var CmdApiapp = &commands.Command{
|
||||
// CustomFlags: true,
|
||||
UsageLine: "api [appname]",
|
||||
Short: "Creates a Beego API application",
|
||||
@ -50,10 +56,9 @@ var cmdApiapp = &Command{
|
||||
└── object.go
|
||||
└── user.go
|
||||
`,
|
||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
||||
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||
Run: createapi,
|
||||
}
|
||||
|
||||
var apiconf = `appname = {{.Appname}}
|
||||
httpport = 8080
|
||||
runmode = dev
|
||||
@ -134,7 +139,7 @@ func init() {
|
||||
}
|
||||
`
|
||||
|
||||
var apiModels = `package models
|
||||
var ApiModels = `package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -189,7 +194,7 @@ func Delete(ObjectId string) {
|
||||
|
||||
`
|
||||
|
||||
var apiModels2 = `package models
|
||||
var ApiModels2 = `package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -532,33 +537,32 @@ func TestGet(t *testing.T) {
|
||||
`
|
||||
|
||||
func init() {
|
||||
cmdApiapp.Flag.Var(&tables, "tables", "List of table names separated by a comma.")
|
||||
cmdApiapp.Flag.Var(&driver, "driver", "Database driver. Either mysql, postgres or sqlite.")
|
||||
cmdApiapp.Flag.Var(&conn, "conn", "Connection string used by the driver to connect to a database instance.")
|
||||
CmdApiapp.Flag.Var(&generate.Tables, "tables", "List of table names separated by a comma.")
|
||||
CmdApiapp.Flag.Var(&generate.SQLDriver, "driver", "Database driver. Either mysql, postgres or sqlite.")
|
||||
CmdApiapp.Flag.Var(&generate.SQLConn, "conn", "Connection string used by the driver to connect to a database instance.")
|
||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdApiapp)
|
||||
}
|
||||
|
||||
func createapi(cmd *Command, args []string) int {
|
||||
func createapi(cmd *commands.Command, args []string) int {
|
||||
output := cmd.Out()
|
||||
|
||||
if len(args) < 1 {
|
||||
logger.Fatal("Argument [appname] is missing")
|
||||
beeLogger.Log.Fatal("Argument [appname] is missing")
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
cmd.Flag.Parse(args[1:])
|
||||
}
|
||||
|
||||
apppath, packpath, err := checkEnv(args[0])
|
||||
apppath, packpath, err := utils.CheckEnv(args[0])
|
||||
if err != nil {
|
||||
logger.Fatalf("%s", err)
|
||||
beeLogger.Log.Fatalf("%s", err)
|
||||
}
|
||||
if driver == "" {
|
||||
driver = "mysql"
|
||||
}
|
||||
if conn == "" {
|
||||
if generate.SQLDriver == "" {
|
||||
generate.SQLDriver = "mysql"
|
||||
}
|
||||
|
||||
logger.Info("Creating API...")
|
||||
beeLogger.Log.Info("Creating API...")
|
||||
|
||||
os.MkdirAll(apppath, 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m")
|
||||
@ -569,30 +573,30 @@ func createapi(cmd *Command, args []string) int {
|
||||
os.Mkdir(path.Join(apppath, "tests"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests"), "\x1b[0m")
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "conf", "app.conf"),
|
||||
utils.WriteToFile(path.Join(apppath, "conf", "app.conf"),
|
||||
strings.Replace(apiconf, "{{.Appname}}", path.Base(args[0]), -1))
|
||||
|
||||
if conn != "" {
|
||||
if generate.SQLConn != "" {
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
maingoContent := strings.Replace(apiMainconngo, "{{.Appname}}", packpath, -1)
|
||||
maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(driver), -1)
|
||||
if driver == "mysql" {
|
||||
maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(generate.SQLDriver), -1)
|
||||
if generate.SQLDriver == "mysql" {
|
||||
maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/go-sql-driver/mysql"`, -1)
|
||||
} else if driver == "postgres" {
|
||||
} else if generate.SQLDriver == "postgres" {
|
||||
maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/lib/pq"`, -1)
|
||||
}
|
||||
WriteToFile(path.Join(apppath, "main.go"),
|
||||
utils.WriteToFile(path.Join(apppath, "main.go"),
|
||||
strings.Replace(
|
||||
maingoContent,
|
||||
"{{.conn}}",
|
||||
conn.String(),
|
||||
generate.SQLConn.String(),
|
||||
-1,
|
||||
),
|
||||
)
|
||||
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)
|
||||
beeLogger.Log.Infof("Using '%s' as 'driver'", generate.SQLDriver)
|
||||
beeLogger.Log.Infof("Using '%s' as 'conn'", generate.SQLConn)
|
||||
beeLogger.Log.Infof("Using '%s' as 'tables'", generate.Tables)
|
||||
generate.GenerateAppcode(string(generate.SQLDriver), string(generate.SQLConn), "3", string(generate.Tables), apppath)
|
||||
} else {
|
||||
os.Mkdir(path.Join(apppath, "models"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models"), "\x1b[0m")
|
||||
@ -600,65 +604,31 @@ func createapi(cmd *Command, args []string) int {
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers")+string(path.Separator), "\x1b[0m")
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "object.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "controllers", "object.go"),
|
||||
utils.WriteToFile(path.Join(apppath, "controllers", "object.go"),
|
||||
strings.Replace(apiControllers, "{{.Appname}}", packpath, -1))
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "user.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "controllers", "user.go"),
|
||||
utils.WriteToFile(path.Join(apppath, "controllers", "user.go"),
|
||||
strings.Replace(apiControllers2, "{{.Appname}}", packpath, -1))
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests", "default_test.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "tests", "default_test.go"),
|
||||
utils.WriteToFile(path.Join(apppath, "tests", "default_test.go"),
|
||||
strings.Replace(apiTests, "{{.Appname}}", packpath, -1))
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "routers", "router.go"),
|
||||
utils.WriteToFile(path.Join(apppath, "routers", "router.go"),
|
||||
strings.Replace(apirouter, "{{.Appname}}", packpath, -1))
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "object.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "models", "object.go"), apiModels)
|
||||
utils.WriteToFile(path.Join(apppath, "models", "object.go"), ApiModels)
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "user.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "models", "user.go"), apiModels2)
|
||||
utils.WriteToFile(path.Join(apppath, "models", "user.go"), ApiModels2)
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "main.go"),
|
||||
utils.WriteToFile(path.Join(apppath, "main.go"),
|
||||
strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1))
|
||||
}
|
||||
logger.Success("New API successfully created!")
|
||||
beeLogger.Log.Success("New API successfully created!")
|
||||
return 0
|
||||
}
|
||||
|
||||
func checkEnv(appname string) (apppath, packpath string, err error) {
|
||||
gps := GetGOPATHs()
|
||||
if len(gps) == 0 {
|
||||
logger.Fatal("GOPATH environment variable is not set or empty")
|
||||
}
|
||||
currpath, _ := os.Getwd()
|
||||
currpath = path.Join(currpath, appname)
|
||||
for _, gpath := range gps {
|
||||
gsrcpath := path.Join(gpath, "src")
|
||||
if strings.HasPrefix(currpath, gsrcpath) {
|
||||
packpath = strings.Replace(currpath[len(gsrcpath)+1:], string(path.Separator), "/", -1)
|
||||
return currpath, packpath, nil
|
||||
}
|
||||
}
|
||||
|
||||
// In case of multiple paths in the GOPATH, by default
|
||||
// we use the first path
|
||||
gopath := gps[0]
|
||||
|
||||
logger.Warn("You current workdir is not inside $GOPATH/src.")
|
||||
logger.Debugf("GOPATH: %s", __FILE__(), __LINE__(), 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)
|
||||
logger.Errorf("Path '%s' already exists", apppath)
|
||||
return
|
||||
}
|
||||
packpath = strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/")
|
||||
return
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package bale
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -24,9 +24,15 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
"github.com/beego/bee/cmd/commands/version"
|
||||
"github.com/beego/bee/config"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
var cmdBale = &Command{
|
||||
var CmdBale = &commands.Command{
|
||||
UsageLine: "bale",
|
||||
Short: "Transforms non-Go files to Go source files",
|
||||
Long: `Bale command compress all the static files in to a single binary file.
|
||||
@ -37,47 +43,46 @@ var cmdBale = &Command{
|
||||
It will auto-generate an unpack function to the main package then run it during the runtime.
|
||||
This is mainly used for zealots who are requiring 100% Go code.
|
||||
`,
|
||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
||||
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||
Run: runBale,
|
||||
}
|
||||
|
||||
func runBale(cmd *Command, args []string) int {
|
||||
err := loadConfig()
|
||||
if err != nil {
|
||||
logger.Fatalf("Failed to load configuration: %s", err)
|
||||
}
|
||||
func init() {
|
||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdBale)
|
||||
}
|
||||
|
||||
func runBale(cmd *commands.Command, args []string) int {
|
||||
os.RemoveAll("bale")
|
||||
os.Mkdir("bale", os.ModePerm)
|
||||
|
||||
// Pack and compress data
|
||||
for _, p := range conf.Bale.Dirs {
|
||||
if !isExist(p) {
|
||||
logger.Warnf("Skipped directory: %s", p)
|
||||
for _, p := range config.Conf.Bale.Dirs {
|
||||
if !utils.IsExist(p) {
|
||||
beeLogger.Log.Warnf("Skipped directory: %s", p)
|
||||
continue
|
||||
}
|
||||
logger.Infof("Packaging directory: %s", p)
|
||||
beeLogger.Log.Infof("Packaging directory: %s", p)
|
||||
filepath.Walk(p, walkFn)
|
||||
}
|
||||
|
||||
// Generate auto-uncompress function.
|
||||
buf := new(bytes.Buffer)
|
||||
buf.WriteString(fmt.Sprintf(BaleHeader, conf.Bale.Import,
|
||||
buf.WriteString(fmt.Sprintf(BaleHeader, config.Conf.Bale.Import,
|
||||
strings.Join(resFiles, "\",\n\t\t\""),
|
||||
strings.Join(resFiles, ",\n\t\tbale.R")))
|
||||
|
||||
fw, err := os.Create("bale.go")
|
||||
if err != nil {
|
||||
logger.Fatalf("Failed to create file: %s", err)
|
||||
beeLogger.Log.Fatalf("Failed to create file: %s", err)
|
||||
}
|
||||
defer fw.Close()
|
||||
|
||||
_, err = fw.Write(buf.Bytes())
|
||||
if err != nil {
|
||||
logger.Fatalf("Failed to write data: %s", err)
|
||||
beeLogger.Log.Fatalf("Failed to write data: %s", err)
|
||||
}
|
||||
|
||||
logger.Success("Baled resources successfully!")
|
||||
beeLogger.Log.Success("Baled resources successfully!")
|
||||
return 0
|
||||
}
|
||||
|
||||
@ -146,7 +151,7 @@ func walkFn(resPath string, info os.FileInfo, err error) error {
|
||||
// Open resource files
|
||||
fr, err := os.Open(resPath)
|
||||
if err != nil {
|
||||
logger.Fatalf("Failed to read file: %s", err)
|
||||
beeLogger.Log.Fatalf("Failed to read file: %s", err)
|
||||
}
|
||||
|
||||
// Convert path
|
||||
@ -164,7 +169,7 @@ func walkFn(resPath string, info os.FileInfo, err error) error {
|
||||
os.MkdirAll(path.Dir(resPath), os.ModePerm)
|
||||
fw, err := os.Create("bale/" + resPath + ".go")
|
||||
if err != nil {
|
||||
logger.Fatalf("Failed to create file: %s", err)
|
||||
beeLogger.Log.Fatalf("Failed to create file: %s", err)
|
||||
}
|
||||
defer fw.Close()
|
||||
|
||||
@ -184,7 +189,7 @@ func walkFn(resPath string, info os.FileInfo, err error) error {
|
||||
}
|
||||
|
||||
func filterSuffix(name string) bool {
|
||||
for _, s := range conf.Bale.IngExt {
|
||||
for _, s := range config.Conf.Bale.IngExt {
|
||||
if strings.HasSuffix(name, s) {
|
||||
return true
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package beefix
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -9,9 +9,14 @@ import (
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
"github.com/beego/bee/cmd/commands/version"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/logger/colors"
|
||||
)
|
||||
|
||||
var cmdFix = &Command{
|
||||
var CmdFix = &commands.Command{
|
||||
UsageLine: "fix",
|
||||
Short: "Fixes your application by making it compatible with newer versions of Beego",
|
||||
Long: `As of {{"Beego 1.6"|bold}}, there are some backward compatibility issues.
|
||||
@ -22,18 +27,19 @@ var cmdFix = &Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdFix.Run = runFix
|
||||
cmdFix.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() }
|
||||
CmdFix.Run = runFix
|
||||
CmdFix.PreRun = func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() }
|
||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdFix)
|
||||
}
|
||||
|
||||
func runFix(cmd *Command, args []string) int {
|
||||
func runFix(cmd *commands.Command, args []string) int {
|
||||
output := cmd.Out()
|
||||
|
||||
logger.Info("Upgrading the application...")
|
||||
beeLogger.Log.Info("Upgrading the application...")
|
||||
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
logger.Fatalf("Error while getting the current working directory: %s", err)
|
||||
beeLogger.Log.Fatalf("Error while getting the current working directory: %s", err)
|
||||
}
|
||||
|
||||
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
@ -50,13 +56,13 @@ func runFix(cmd *Command, args []string) int {
|
||||
return nil
|
||||
}
|
||||
err = fixFile(path)
|
||||
fmt.Fprintf(output, GreenBold("\tfix\t")+"%s\n", path)
|
||||
fmt.Fprintf(output, colors.GreenBold("\tfix\t")+"%s\n", path)
|
||||
if err != nil {
|
||||
logger.Errorf("Could not fix file: %s", err)
|
||||
beeLogger.Log.Errorf("Could not fix file: %s", err)
|
||||
}
|
||||
return err
|
||||
})
|
||||
logger.Success("Upgrade Done!")
|
||||
beeLogger.Log.Success("Upgrade Done!")
|
||||
return 0
|
||||
}
|
||||
|
94
cmd/commands/command.go
Normal file
94
cmd/commands/command.go
Normal file
@ -0,0 +1,94 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/bee/logger/colors"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
// Command is the unit of execution
|
||||
type Command struct {
|
||||
// Run runs the command.
|
||||
// The args are the arguments after the command name.
|
||||
Run func(cmd *Command, args []string) int
|
||||
|
||||
// PreRun performs an operation before running the command
|
||||
PreRun func(cmd *Command, args []string)
|
||||
|
||||
// UsageLine is the one-line Usage message.
|
||||
// The first word in the line is taken to be the command name.
|
||||
UsageLine string
|
||||
|
||||
// Short is the short description shown in the 'go help' output.
|
||||
Short string
|
||||
|
||||
// Long is the long message shown in the 'go help <this-command>' output.
|
||||
Long string
|
||||
|
||||
// Flag is a set of flags specific to this command.
|
||||
Flag flag.FlagSet
|
||||
|
||||
// CustomFlags indicates that the command will do its own
|
||||
// flag parsing.
|
||||
CustomFlags bool
|
||||
|
||||
// output out writer if set in SetOutput(w)
|
||||
output *io.Writer
|
||||
}
|
||||
|
||||
var AvailableCommands = []*Command{}
|
||||
var cmdUsage = `Use {{printf "bee help %s" .Name | bold}} for more information.{{endline}}`
|
||||
|
||||
// Name returns the command's name: the first word in the Usage line.
|
||||
func (c *Command) Name() string {
|
||||
name := c.UsageLine
|
||||
i := strings.Index(name, " ")
|
||||
if i >= 0 {
|
||||
name = name[:i]
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// SetOutput sets the destination for Usage and error messages.
|
||||
// If output is nil, os.Stderr is used.
|
||||
func (c *Command) SetOutput(output io.Writer) {
|
||||
c.output = &output
|
||||
}
|
||||
|
||||
// Out returns the out writer of the current command.
|
||||
// If cmd.output is nil, os.Stderr is used.
|
||||
func (c *Command) Out() io.Writer {
|
||||
if c.output != nil {
|
||||
return *c.output
|
||||
}
|
||||
return colors.NewColorWriter(os.Stderr)
|
||||
}
|
||||
|
||||
// Usage puts out the Usage for the command.
|
||||
func (c *Command) Usage() {
|
||||
utils.Tmpl(cmdUsage, c)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
// Runnable reports whether the command can be run; otherwise
|
||||
// it is a documentation pseudo-command such as import path.
|
||||
func (c *Command) Runnable() bool {
|
||||
return c.Run != nil
|
||||
}
|
||||
|
||||
func (c *Command) Options() map[string]string {
|
||||
options := make(map[string]string)
|
||||
c.Flag.VisitAll(func(f *flag.Flag) {
|
||||
defaultVal := f.DefValue
|
||||
if len(defaultVal) > 0 {
|
||||
options[f.Name+"="+defaultVal] = f.Usage
|
||||
} else {
|
||||
options[f.Name] = f.Usage
|
||||
}
|
||||
})
|
||||
return options
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package dockerize
|
||||
|
||||
import (
|
||||
"flag"
|
||||
@ -21,22 +21,13 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
"github.com/beego/bee/cmd/commands/version"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
var cmdDockerize = &Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "dockerize",
|
||||
Short: "Generates a Dockerfile for your Beego application",
|
||||
Long: `Dockerize generates a Dockerfile for your Beego Web Application.
|
||||
The Dockerfile will compile, get the dependencies with {{"godep"|bold}}, and set the entrypoint.
|
||||
|
||||
{{"Example:"|bold}}
|
||||
$ bee dockerize -expose="3000,80,25"
|
||||
`,
|
||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
||||
Run: dockerizeApp,
|
||||
}
|
||||
|
||||
const dockerBuildTemplate = `FROM {{.BaseImage}}
|
||||
|
||||
# Godep for vendoring
|
||||
@ -67,6 +58,20 @@ type Dockerfile struct {
|
||||
Expose string
|
||||
}
|
||||
|
||||
var CmdDockerize = &commands.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "dockerize",
|
||||
Short: "Generates a Dockerfile for your Beego application",
|
||||
Long: `Dockerize generates a Dockerfile for your Beego Web Application.
|
||||
The Dockerfile will compile, get the dependencies with {{"godep"|bold}}, and set the entrypoint.
|
||||
|
||||
{{"Example:"|bold}}
|
||||
$ bee dockerize -expose="3000,80,25"
|
||||
`,
|
||||
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||
Run: dockerizeApp,
|
||||
}
|
||||
|
||||
var (
|
||||
expose string
|
||||
baseImage string
|
||||
@ -76,19 +81,22 @@ func init() {
|
||||
fs := flag.NewFlagSet("dockerize", flag.ContinueOnError)
|
||||
fs.StringVar(&baseImage, "image", "library/golang", "Set the base image of the Docker container.")
|
||||
fs.StringVar(&expose, "expose", "8080", "Port(s) to expose in the Docker container.")
|
||||
cmdDockerize.Flag = *fs
|
||||
CmdDockerize.Flag = *fs
|
||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdDockerize)
|
||||
}
|
||||
|
||||
func dockerizeApp(cmd *Command, args []string) int {
|
||||
func dockerizeApp(cmd *commands.Command, args []string) int {
|
||||
if err := cmd.Flag.Parse(args); err != nil {
|
||||
logger.Fatalf("Error parsing flags: %v", err.Error())
|
||||
beeLogger.Log.Fatalf("Error parsing flags: %v", err.Error())
|
||||
}
|
||||
|
||||
logger.Info("Generating Dockerfile...")
|
||||
beeLogger.Log.Info("Generating Dockerfile...")
|
||||
|
||||
gopath := os.Getenv("GOPATH")
|
||||
dir, err := filepath.Abs(".")
|
||||
MustCheck(err)
|
||||
if err != nil {
|
||||
beeLogger.Log.Error(err.Error())
|
||||
}
|
||||
|
||||
appdir := strings.Replace(dir, gopath, "", 1)
|
||||
|
||||
@ -112,15 +120,15 @@ func dockerizeApp(cmd *Command, args []string) int {
|
||||
}
|
||||
|
||||
func generateDockerfile(df Dockerfile) {
|
||||
t := template.Must(template.New("dockerBuildTemplate").Parse(dockerBuildTemplate)).Funcs(BeeFuncMap())
|
||||
t := template.Must(template.New("dockerBuildTemplate").Parse(dockerBuildTemplate)).Funcs(utils.BeeFuncMap())
|
||||
|
||||
f, err := os.Create("Dockerfile")
|
||||
if err != nil {
|
||||
logger.Fatalf("Error writing Dockerfile: %v", err.Error())
|
||||
beeLogger.Log.Fatalf("Error writing Dockerfile: %v", err.Error())
|
||||
}
|
||||
defer CloseFile(f)
|
||||
defer utils.CloseFile(f)
|
||||
|
||||
t.Execute(f, df)
|
||||
|
||||
logger.Success("Dockerfile generated.")
|
||||
beeLogger.Log.Success("Dockerfile generated.")
|
||||
}
|
203
cmd/commands/generate/generate.go
Normal file
203
cmd/commands/generate/generate.go
Normal file
@ -0,0 +1,203 @@
|
||||
package generate
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
"github.com/beego/bee/cmd/commands/version"
|
||||
"github.com/beego/bee/config"
|
||||
"github.com/beego/bee/generate"
|
||||
"github.com/beego/bee/generate/swaggergen"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
var CmdGenerate = &commands.Command{
|
||||
UsageLine: "generate [command]",
|
||||
Short: "Source code generator",
|
||||
Long: `▶ {{"To scaffold out your entire application:"|bold}}
|
||||
|
||||
$ bee generate scaffold [scaffoldname] [-fields="title:string,body:text"] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"]
|
||||
|
||||
▶ {{"To generate a Model based on fields:"|bold}}
|
||||
|
||||
$ bee generate model [modelname] [-fields="name:type"]
|
||||
|
||||
▶ {{"To generate a controller:"|bold}}
|
||||
|
||||
$ bee generate controller [controllerfile]
|
||||
|
||||
▶ {{"To generate a CRUD view:"|bold}}
|
||||
|
||||
$ bee generate view [viewpath]
|
||||
|
||||
▶ {{"To generate a migration file for making database schema updates:"|bold}}
|
||||
|
||||
$ bee generate migration [migrationfile] [-fields="name:type"]
|
||||
|
||||
▶ {{"To generate swagger doc file:"|bold}}
|
||||
|
||||
$ bee generate docs
|
||||
|
||||
▶ {{"To generate a test case:"|bold}}
|
||||
|
||||
$ bee generate test [routerfile]
|
||||
|
||||
▶ {{"To generate appcode based on an existing database:"|bold}}
|
||||
|
||||
$ bee generate appcode [-tables=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] [-level=3]
|
||||
`,
|
||||
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||
Run: GenerateCode,
|
||||
}
|
||||
|
||||
func init() {
|
||||
CmdGenerate.Flag.Var(&generate.Tables, "Tables", "List of table names separated by a comma.")
|
||||
CmdGenerate.Flag.Var(&generate.SQLDriver, "SQLDriver", "Database SQLDriver. Either mysql, postgres or sqlite.")
|
||||
CmdGenerate.Flag.Var(&generate.SQLConn, "SQLConn", "Connection string used by the SQLDriver to connect to a database instance.")
|
||||
CmdGenerate.Flag.Var(&generate.Level, "Level", "Either 1, 2 or 3. i.e. 1=models; 2=models and controllers; 3=models, controllers and routers.")
|
||||
CmdGenerate.Flag.Var(&generate.Fields, "Fields", "List of table Fields.")
|
||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdGenerate)
|
||||
}
|
||||
|
||||
func GenerateCode(cmd *commands.Command, args []string) int {
|
||||
currpath, _ := os.Getwd()
|
||||
if len(args) < 1 {
|
||||
beeLogger.Log.Fatal("Command is missing")
|
||||
}
|
||||
|
||||
gps := utils.GetGOPATHs()
|
||||
if len(gps) == 0 {
|
||||
beeLogger.Log.Fatal("GOPATH environment variable is not set or empty")
|
||||
}
|
||||
|
||||
gopath := gps[0]
|
||||
|
||||
beeLogger.Log.Debugf("GOPATH: %s", utils.FILE(), utils.LINE(), gopath)
|
||||
|
||||
gcmd := args[0]
|
||||
switch gcmd {
|
||||
case "scaffold":
|
||||
scaffold(cmd, args, currpath)
|
||||
case "docs":
|
||||
swaggergen.GenerateDocs(currpath)
|
||||
case "appcode":
|
||||
appCode(cmd, args, currpath)
|
||||
case "migration":
|
||||
migration(cmd, args, currpath)
|
||||
case "controller":
|
||||
controller(args, currpath)
|
||||
case "model":
|
||||
model(cmd, args, currpath)
|
||||
case "view":
|
||||
view(args, currpath)
|
||||
default:
|
||||
beeLogger.Log.Fatal("Command is missing")
|
||||
}
|
||||
beeLogger.Log.Successf("%s successfully generated!", strings.Title(gcmd))
|
||||
return 0
|
||||
}
|
||||
|
||||
func scaffold(cmd *commands.Command, args []string, currpath string) {
|
||||
if len(args) < 2 {
|
||||
beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
}
|
||||
|
||||
cmd.Flag.Parse(args[2:])
|
||||
if generate.SQLDriver == "" {
|
||||
generate.SQLDriver = utils.DocValue(config.Conf.Database.Driver)
|
||||
if generate.SQLDriver == "" {
|
||||
generate.SQLDriver = "mysql"
|
||||
}
|
||||
}
|
||||
if generate.SQLConn == "" {
|
||||
generate.SQLConn = utils.DocValue(config.Conf.Database.Conn)
|
||||
if generate.SQLConn == "" {
|
||||
generate.SQLConn = "root:@tcp(127.0.0.1:3306)/test"
|
||||
}
|
||||
}
|
||||
if generate.Fields == "" {
|
||||
beeLogger.Log.Hint("Fields option should not be empty, i.e. -Fields=\"title:string,body:text\"")
|
||||
beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
}
|
||||
sname := args[1]
|
||||
generate.GenerateScaffold(sname, generate.Fields.String(), currpath, generate.SQLDriver.String(), generate.SQLConn.String())
|
||||
}
|
||||
|
||||
func appCode(cmd *commands.Command, args []string, currpath string) {
|
||||
cmd.Flag.Parse(args[1:])
|
||||
if generate.SQLDriver == "" {
|
||||
generate.SQLDriver = utils.DocValue(config.Conf.Database.Driver)
|
||||
if generate.SQLDriver == "" {
|
||||
generate.SQLDriver = "mysql"
|
||||
}
|
||||
}
|
||||
if generate.SQLConn == "" {
|
||||
generate.SQLConn = utils.DocValue(config.Conf.Database.Conn)
|
||||
if generate.SQLConn == "" {
|
||||
if generate.SQLDriver == "mysql" {
|
||||
generate.SQLConn = "root:@tcp(127.0.0.1:3306)/test"
|
||||
} else if generate.SQLDriver == "postgres" {
|
||||
generate.SQLConn = "postgres://postgres:postgres@127.0.0.1:5432/postgres"
|
||||
}
|
||||
}
|
||||
}
|
||||
if generate.Level == "" {
|
||||
generate.Level = "3"
|
||||
}
|
||||
beeLogger.Log.Infof("Using '%s' as 'SQLDriver'", generate.SQLDriver)
|
||||
beeLogger.Log.Infof("Using '%s' as 'SQLConn'", generate.SQLConn)
|
||||
beeLogger.Log.Infof("Using '%s' as 'Tables'", generate.Tables)
|
||||
beeLogger.Log.Infof("Using '%s' as 'Level'", generate.Level)
|
||||
generate.GenerateAppcode(generate.SQLDriver.String(), generate.SQLConn.String(), generate.Level.String(), generate.Tables.String(), currpath)
|
||||
}
|
||||
func migration(cmd *commands.Command, args []string, currpath string) {
|
||||
if len(args) < 2 {
|
||||
beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
}
|
||||
cmd.Flag.Parse(args[2:])
|
||||
mname := args[1]
|
||||
|
||||
beeLogger.Log.Infof("Using '%s' as migration name", mname)
|
||||
|
||||
upsql := ""
|
||||
downsql := ""
|
||||
if generate.Fields != "" {
|
||||
dbMigrator := generate.NewDBDriver()
|
||||
upsql = dbMigrator.GenerateCreateUp(mname)
|
||||
downsql = dbMigrator.GenerateCreateDown(mname)
|
||||
}
|
||||
generate.GenerateMigration(mname, upsql, downsql, currpath)
|
||||
}
|
||||
|
||||
func controller(args []string, currpath string) {
|
||||
if len(args) == 2 {
|
||||
cname := args[1]
|
||||
generate.GenerateController(cname, currpath)
|
||||
} else {
|
||||
beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
}
|
||||
}
|
||||
|
||||
func model(cmd *commands.Command, args []string, currpath string) {
|
||||
if len(args) < 2 {
|
||||
beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
}
|
||||
cmd.Flag.Parse(args[2:])
|
||||
if generate.Fields == "" {
|
||||
beeLogger.Log.Hint("Fields option should not be empty, i.e. -Fields=\"title:string,body:text\"")
|
||||
beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
}
|
||||
sname := args[1]
|
||||
generate.GenerateModel(sname, generate.Fields.String(), currpath)
|
||||
}
|
||||
|
||||
func view(args []string, currpath string) {
|
||||
if len(args) == 2 {
|
||||
cname := args[1]
|
||||
generate.GenerateView(cname, currpath)
|
||||
} else {
|
||||
beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
}
|
||||
}
|
119
cmd/commands/hprose/hprose.go
Normal file
119
cmd/commands/hprose/hprose.go
Normal file
@ -0,0 +1,119 @@
|
||||
package hprose
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
"github.com/beego/bee/cmd/commands/api"
|
||||
"github.com/beego/bee/cmd/commands/version"
|
||||
"github.com/beego/bee/generate"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
var CmdHproseapp = &commands.Command{
|
||||
// CustomFlags: true,
|
||||
UsageLine: "hprose [appname]",
|
||||
Short: "Creates an RPC application based on Hprose and Beego frameworks",
|
||||
Long: `
|
||||
The command 'hprose' creates an RPC application based on both Beego and Hprose (http://hprose.com/).
|
||||
|
||||
{{"To scaffold out your application, use:"|bold}}
|
||||
|
||||
$ bee hprose [appname] [-tables=""] [-driver=mysql] [-conn=root:@tcp(127.0.0.1:3306)/test]
|
||||
|
||||
If 'conn' is empty, the command will generate a sample application. Otherwise the command
|
||||
will connect to your database and generate models based on the existing tables.
|
||||
|
||||
The command 'hprose' creates a folder named [appname] with the following structure:
|
||||
|
||||
├── main.go
|
||||
├── {{"conf"|foldername}}
|
||||
│ └── app.conf
|
||||
└── {{"models"|foldername}}
|
||||
└── object.go
|
||||
└── user.go
|
||||
`,
|
||||
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||
Run: createhprose,
|
||||
}
|
||||
|
||||
func init() {
|
||||
CmdHproseapp.Flag.Var(&generate.Tables, "tables", "List of table names separated by a comma.")
|
||||
CmdHproseapp.Flag.Var(&generate.SQLDriver, "driver", "Database driver. Either mysql, postgres or sqlite.")
|
||||
CmdHproseapp.Flag.Var(&generate.SQLConn, "conn", "Connection string used by the driver to connect to a database instance.")
|
||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdHproseapp)
|
||||
}
|
||||
|
||||
func createhprose(cmd *commands.Command, args []string) int {
|
||||
output := cmd.Out()
|
||||
|
||||
if len(args) != 1 {
|
||||
beeLogger.Log.Fatal("Argument [appname] is missing")
|
||||
}
|
||||
|
||||
curpath, _ := os.Getwd()
|
||||
if len(args) > 1 {
|
||||
cmd.Flag.Parse(args[1:])
|
||||
}
|
||||
apppath, packpath, err := utils.CheckEnv(args[0])
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("%s", err)
|
||||
}
|
||||
if generate.SQLDriver == "" {
|
||||
generate.SQLDriver = "mysql"
|
||||
}
|
||||
beeLogger.Log.Info("Creating Hprose application...")
|
||||
|
||||
os.MkdirAll(apppath, 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "conf"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf"), "\x1b[0m")
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m")
|
||||
utils.WriteToFile(path.Join(apppath, "conf", "app.conf"),
|
||||
strings.Replace(generate.Hproseconf, "{{.Appname}}", args[0], -1))
|
||||
|
||||
if generate.SQLConn != "" {
|
||||
beeLogger.Log.Infof("Using '%s' as 'driver'", generate.SQLDriver)
|
||||
beeLogger.Log.Infof("Using '%s' as 'conn'", generate.SQLConn)
|
||||
beeLogger.Log.Infof("Using '%s' as 'tables'", generate.Tables)
|
||||
generate.GenerateHproseAppcode(string(generate.SQLDriver), string(generate.SQLConn), "1", string(generate.Tables), path.Join(curpath, args[0]))
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
maingoContent := strings.Replace(generate.HproseMainconngo, "{{.Appname}}", packpath, -1)
|
||||
maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(generate.SQLDriver), -1)
|
||||
maingoContent = strings.Replace(maingoContent, "{{HproseFunctionList}}", strings.Join(generate.HproseAddFunctions, ""), -1)
|
||||
if generate.SQLDriver == "mysql" {
|
||||
maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/go-sql-driver/mysql"`, -1)
|
||||
} else if generate.SQLDriver == "postgres" {
|
||||
maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/lib/pq"`, -1)
|
||||
}
|
||||
utils.WriteToFile(path.Join(apppath, "main.go"),
|
||||
strings.Replace(
|
||||
maingoContent,
|
||||
"{{.conn}}",
|
||||
generate.SQLConn.String(),
|
||||
-1,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
os.Mkdir(path.Join(apppath, "models"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models"), "\x1b[0m")
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "object.go"), "\x1b[0m")
|
||||
utils.WriteToFile(path.Join(apppath, "models", "object.go"), apiapp.ApiModels)
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "user.go"), "\x1b[0m")
|
||||
utils.WriteToFile(path.Join(apppath, "models", "user.go"), apiapp.ApiModels2)
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
utils.WriteToFile(path.Join(apppath, "main.go"),
|
||||
strings.Replace(generate.HproseMaingo, "{{.Appname}}", packpath, -1))
|
||||
}
|
||||
beeLogger.Log.Success("New Hprose application successfully created!")
|
||||
return 0
|
||||
}
|
@ -1,18 +1,4 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@ -23,9 +9,16 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
"github.com/beego/bee/cmd/commands/version"
|
||||
"github.com/beego/bee/config"
|
||||
"github.com/beego/bee/utils"
|
||||
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
)
|
||||
|
||||
var cmdMigrate = &Command{
|
||||
var CmdMigrate = &commands.Command{
|
||||
UsageLine: "migrate [Command]",
|
||||
Short: "Runs database migrations",
|
||||
Long: `The command 'migrate' allows you to run database migrations to keep it up-to-date.
|
||||
@ -46,100 +39,75 @@ var cmdMigrate = &Command{
|
||||
|
||||
$ bee migrate refresh [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"]
|
||||
`,
|
||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
||||
Run: runMigration,
|
||||
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||
Run: RunMigration,
|
||||
}
|
||||
|
||||
var mDriver docValue
|
||||
var mConn docValue
|
||||
var mDriver utils.DocValue
|
||||
var mConn utils.DocValue
|
||||
|
||||
func init() {
|
||||
cmdMigrate.Flag.Var(&mDriver, "driver", "Database driver. Either mysql, postgres or sqlite.")
|
||||
cmdMigrate.Flag.Var(&mConn, "conn", "Connection string used by the driver to connect to a database instance.")
|
||||
CmdMigrate.Flag.Var(&mDriver, "driver", "Database driver. Either mysql, postgres or sqlite.")
|
||||
CmdMigrate.Flag.Var(&mConn, "conn", "Connection string used by the driver to connect to a database instance.")
|
||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdMigrate)
|
||||
}
|
||||
|
||||
// runMigration is the entry point for starting a migration
|
||||
func runMigration(cmd *Command, args []string) int {
|
||||
func RunMigration(cmd *commands.Command, args []string) int {
|
||||
currpath, _ := os.Getwd()
|
||||
|
||||
gps := GetGOPATHs()
|
||||
gps := utils.GetGOPATHs()
|
||||
if len(gps) == 0 {
|
||||
logger.Fatal("GOPATH environment variable is not set or empty")
|
||||
beeLogger.Log.Fatal("GOPATH environment variable is not set or empty")
|
||||
}
|
||||
|
||||
gopath := gps[0]
|
||||
|
||||
logger.Debugf("GOPATH: %s", __FILE__(), __LINE__(), gopath)
|
||||
|
||||
// Load the configuration
|
||||
err := loadConfig()
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to load configuration: %s", err)
|
||||
}
|
||||
beeLogger.Log.Debugf("GOPATH: %s", utils.FILE(), utils.LINE(), gopath)
|
||||
|
||||
// Getting command line arguments
|
||||
if len(args) != 0 {
|
||||
cmd.Flag.Parse(args[1:])
|
||||
}
|
||||
if mDriver == "" {
|
||||
mDriver = docValue(conf.Database.Driver)
|
||||
mDriver = utils.DocValue(config.Conf.Database.Driver)
|
||||
if mDriver == "" {
|
||||
mDriver = "mysql"
|
||||
}
|
||||
}
|
||||
if mConn == "" {
|
||||
mConn = docValue(conf.Database.Conn)
|
||||
mConn = utils.DocValue(config.Conf.Database.Conn)
|
||||
if mConn == "" {
|
||||
mConn = "root:@tcp(127.0.0.1:3306)/test"
|
||||
}
|
||||
}
|
||||
logger.Infof("Using '%s' as 'driver'", mDriver)
|
||||
logger.Infof("Using '%s' as 'conn'", mConn)
|
||||
beeLogger.Log.Infof("Using '%s' as 'driver'", mDriver)
|
||||
beeLogger.Log.Infof("Using '%s' as 'conn'", mConn)
|
||||
driverStr, connStr := string(mDriver), string(mConn)
|
||||
if len(args) == 0 {
|
||||
// run all outstanding migrations
|
||||
logger.Info("Running all outstanding migrations")
|
||||
migrateUpdate(currpath, driverStr, connStr)
|
||||
beeLogger.Log.Info("Running all outstanding migrations")
|
||||
MigrateUpdate(currpath, driverStr, connStr)
|
||||
} else {
|
||||
mcmd := args[0]
|
||||
switch mcmd {
|
||||
case "rollback":
|
||||
logger.Info("Rolling back the last migration operation")
|
||||
migrateRollback(currpath, driverStr, connStr)
|
||||
beeLogger.Log.Info("Rolling back the last migration operation")
|
||||
MigrateRollback(currpath, driverStr, connStr)
|
||||
case "reset":
|
||||
logger.Info("Reseting all migrations")
|
||||
migrateReset(currpath, driverStr, connStr)
|
||||
beeLogger.Log.Info("Reseting all migrations")
|
||||
MigrateReset(currpath, driverStr, connStr)
|
||||
case "refresh":
|
||||
logger.Info("Refreshing all migrations")
|
||||
migrateRefresh(currpath, driverStr, connStr)
|
||||
beeLogger.Log.Info("Refreshing all migrations")
|
||||
MigrateRefresh(currpath, driverStr, connStr)
|
||||
default:
|
||||
logger.Fatal("Command is missing")
|
||||
beeLogger.Log.Fatal("Command is missing")
|
||||
}
|
||||
}
|
||||
logger.Success("Migration successful!")
|
||||
beeLogger.Log.Success("Migration successful!")
|
||||
return 0
|
||||
}
|
||||
|
||||
// migrateUpdate does the schema update
|
||||
func migrateUpdate(currpath, driver, connStr string) {
|
||||
migrate("upgrade", currpath, driver, connStr)
|
||||
}
|
||||
|
||||
// migrateRollback rolls back the latest migration
|
||||
func migrateRollback(currpath, driver, connStr string) {
|
||||
migrate("rollback", currpath, driver, connStr)
|
||||
}
|
||||
|
||||
// migrateReset rolls back all migrations
|
||||
func migrateReset(currpath, driver, connStr string) {
|
||||
migrate("reset", currpath, driver, connStr)
|
||||
}
|
||||
|
||||
// migrationRefresh rolls back all migrations and start over again
|
||||
func migrateRefresh(currpath, driver, connStr string) {
|
||||
migrate("refresh", currpath, driver, connStr)
|
||||
}
|
||||
|
||||
// migrate generates source code, build it, and invoke the binary who does the actual migration
|
||||
func migrate(goal, currpath, driver, connStr string) {
|
||||
dir := path.Join(currpath, "database", "migrations")
|
||||
@ -153,7 +121,7 @@ func migrate(goal, currpath, driver, connStr string) {
|
||||
// Connect to database
|
||||
db, err := sql.Open(driver, connStr)
|
||||
if err != nil {
|
||||
logger.Fatalf("Could not connect to database using '%s': %s", connStr, err)
|
||||
beeLogger.Log.Fatalf("Could not connect to database using '%s': %s", connStr, err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
@ -171,44 +139,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 {
|
||||
logger.Fatalf("Could not show migrations table: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not show migrations table: %s", err)
|
||||
} else if !rows.Next() {
|
||||
// No migrations table, create new ones
|
||||
createTableSQL := createMigrationsTableSQL(driver)
|
||||
|
||||
logger.Infof("Creating 'migrations' table...")
|
||||
beeLogger.Log.Infof("Creating 'migrations' table...")
|
||||
|
||||
if _, err := db.Query(createTableSQL); err != nil {
|
||||
logger.Fatalf("Could not create migrations table: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not create migrations table: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Checking that migrations table schema are expected
|
||||
selectTableSQL := selectMigrationsTableSQL(driver)
|
||||
if rows, err := db.Query(selectTableSQL); err != nil {
|
||||
logger.Fatalf("Could not show columns of migrations table: %s", err)
|
||||
beeLogger.Log.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 {
|
||||
logger.Fatalf("Could not read column information: %s", err)
|
||||
beeLogger.Log.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" {
|
||||
logger.Hint("Expecting KEY: PRI, EXTRA: auto_increment")
|
||||
logger.Fatalf("Column migration.id_migration type mismatch: KEY: %s, EXTRA: %s", keyStr, extraStr)
|
||||
beeLogger.Log.Hint("Expecting KEY: PRI, EXTRA: auto_increment")
|
||||
beeLogger.Log.Fatalf("Column migration.id_migration type mismatch: KEY: %s, EXTRA: %s", keyStr, extraStr)
|
||||
}
|
||||
} else if fieldStr == "name" {
|
||||
if !strings.HasPrefix(typeStr, "varchar") || nullStr != "YES" {
|
||||
logger.Hint("Expecting TYPE: varchar, NULL: YES")
|
||||
logger.Fatalf("Column migration.name type mismatch: TYPE: %s, NULL: %s", typeStr, nullStr)
|
||||
beeLogger.Log.Hint("Expecting TYPE: varchar, NULL: YES")
|
||||
beeLogger.Log.Fatalf("Column migration.name type mismatch: TYPE: %s, NULL: %s", typeStr, nullStr)
|
||||
}
|
||||
} else if fieldStr == "created_at" {
|
||||
if typeStr != "timestamp" || defaultStr != "CURRENT_TIMESTAMP" {
|
||||
logger.Hint("Expecting TYPE: timestamp, DEFAULT: CURRENT_TIMESTAMP")
|
||||
logger.Fatalf("Column migration.timestamp type mismatch: TYPE: %s, DEFAULT: %s", typeStr, defaultStr)
|
||||
beeLogger.Log.Hint("Expecting TYPE: timestamp, DEFAULT: CURRENT_TIMESTAMP")
|
||||
beeLogger.Log.Fatalf("Column migration.timestamp type mismatch: TYPE: %s, DEFAULT: %s", typeStr, defaultStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -252,22 +220,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 {
|
||||
logger.Fatalf("Could not retrieve migrations: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not retrieve migrations: %s", err)
|
||||
} else {
|
||||
if rows.Next() {
|
||||
if err := rows.Scan(&file); err != nil {
|
||||
logger.Fatalf("Could not read migrations in database: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not read migrations in database: %s", err)
|
||||
}
|
||||
createdAtStr := file[len(file)-15:]
|
||||
if t, err := time.Parse("20060102_150405", createdAtStr); err != nil {
|
||||
logger.Fatalf("Could not parse time: %s", err)
|
||||
beeLogger.Log.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" {
|
||||
logger.Fatal("There is nothing to rollback")
|
||||
beeLogger.Log.Fatal("There is nothing to rollback")
|
||||
}
|
||||
file, createdAt = "", 0
|
||||
}
|
||||
@ -279,7 +247,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 {
|
||||
logger.Fatalf("Could not create file: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not create file: %s", err)
|
||||
} else {
|
||||
content := strings.Replace(MigrationMainTPL, "{{DBDriver}}", driver, -1)
|
||||
content = strings.Replace(content, "{{ConnStr}}", connStr, -1)
|
||||
@ -287,9 +255,9 @@ 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 {
|
||||
logger.Fatalf("Could not write to file: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not write to file: %s", err)
|
||||
}
|
||||
CloseFile(f)
|
||||
utils.CloseFile(f)
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,7 +266,7 @@ func buildMigrationBinary(dir, binary string) {
|
||||
changeDir(dir)
|
||||
cmd := exec.Command("go", "build", "-o", binary)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
logger.Errorf("Could not build migration binary: %s", err)
|
||||
beeLogger.Log.Errorf("Could not build migration binary: %s", err)
|
||||
formatShellErrOutput(string(out))
|
||||
removeTempFile(dir, binary)
|
||||
removeTempFile(dir, binary+".go")
|
||||
@ -312,7 +280,7 @@ func runMigrationBinary(dir, binary string) {
|
||||
cmd := exec.Command("./" + binary)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
formatShellOutput(string(out))
|
||||
logger.Errorf("Could not run migration binary: %s", err)
|
||||
beeLogger.Log.Errorf("Could not run migration binary: %s", err)
|
||||
removeTempFile(dir, binary)
|
||||
removeTempFile(dir, binary+".go")
|
||||
os.Exit(2)
|
||||
@ -325,7 +293,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 {
|
||||
logger.Fatalf("Could not find migration directory: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not find migration directory: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,7 +301,7 @@ func changeDir(dir string) {
|
||||
func removeTempFile(dir, file string) {
|
||||
changeDir(dir)
|
||||
if err := os.Remove(file); err != nil {
|
||||
logger.Warnf("Could not remove temporary file: %s", err)
|
||||
beeLogger.Log.Warnf("Could not remove temporary file: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,7 +309,7 @@ func removeTempFile(dir, file string) {
|
||||
func formatShellErrOutput(o string) {
|
||||
for _, line := range strings.Split(o, "\n") {
|
||||
if line != "" {
|
||||
logger.Errorf("|> %s", line)
|
||||
beeLogger.Log.Errorf("|> %s", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -350,7 +318,7 @@ func formatShellErrOutput(o string) {
|
||||
func formatShellOutput(o string) {
|
||||
for _, line := range strings.Split(o, "\n") {
|
||||
if line != "" {
|
||||
logger.Infof("|> %s", line)
|
||||
beeLogger.Log.Infof("|> %s", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -421,3 +389,23 @@ CREATE TABLE migrations (
|
||||
status migrations_status
|
||||
)`
|
||||
)
|
||||
|
||||
// MigrateUpdate does the schema update
|
||||
func MigrateUpdate(currpath, driver, connStr string) {
|
||||
migrate("upgrade", currpath, driver, connStr)
|
||||
}
|
||||
|
||||
// MigrateRollback rolls back the latest migration
|
||||
func MigrateRollback(currpath, driver, connStr string) {
|
||||
migrate("rollback", currpath, driver, connStr)
|
||||
}
|
||||
|
||||
// MigrateReset rolls back all migrations
|
||||
func MigrateReset(currpath, driver, connStr string) {
|
||||
migrate("reset", currpath, driver, connStr)
|
||||
}
|
||||
|
||||
// migrationRefresh rolls back all migrations and start over again
|
||||
func MigrateRefresh(currpath, driver, connStr string) {
|
||||
migrate("refresh", currpath, driver, connStr)
|
||||
}
|
@ -12,16 +12,22 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package new
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
path "path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
"github.com/beego/bee/cmd/commands/version"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/logger/colors"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
var cmdNew = &Command{
|
||||
var CmdNew = &commands.Command{
|
||||
UsageLine: "new [appname]",
|
||||
Short: "Creates a Beego application",
|
||||
Long: `
|
||||
@ -47,74 +53,8 @@ Creates a Beego application for the given app name in the current directory.
|
||||
└── index.tpl
|
||||
|
||||
`,
|
||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
||||
Run: createApp,
|
||||
}
|
||||
|
||||
func createApp(cmd *Command, args []string) int {
|
||||
output := cmd.Out()
|
||||
if len(args) != 1 {
|
||||
logger.Fatal("Argument [appname] is missing")
|
||||
}
|
||||
|
||||
apppath, packpath, err := checkEnv(args[0])
|
||||
if err != nil {
|
||||
logger.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
if isExist(apppath) {
|
||||
logger.Errorf(bold("Application '%s' already exists"), apppath)
|
||||
logger.Warn(bold("Do you want to overwrite it? [Yes|No] "))
|
||||
if !askForConfirmation() {
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info("Creating application...")
|
||||
|
||||
os.MkdirAll(apppath, 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "conf"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "controllers"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "models"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "routers"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "tests"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "static"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "static", "js"), 0755)
|
||||
WriteToFile(path.Join(apppath, "static", "js", "reload.min.js"), reloadJsClient)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "js")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "static", "css"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "css")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "static", "img"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "img")+string(path.Separator), "\x1b[0m")
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "views"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(appconf, "{{.Appname}}", path.Base(args[0]), -1))
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "default.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "controllers", "default.go"), controllers)
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views", "index.tpl"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "views", "index.tpl"), indextpl)
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(router, "{{.Appname}}", packpath, -1))
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests", "default_test.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(test, "{{.Appname}}", packpath, -1))
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", packpath, -1))
|
||||
|
||||
logger.Success("New application successfully created!")
|
||||
return 0
|
||||
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||
Run: CreateApp,
|
||||
}
|
||||
|
||||
var appconf = `appname = {{.Appname}}
|
||||
@ -303,3 +243,73 @@ var indextpl = `<!DOCTYPE html>
|
||||
|
||||
var reloadJsClient = `function b(a){var c=new WebSocket(a);c.onclose=function(){setTimeout(function(){b(a)},2E3)};c.onmessage=function(){location.reload()}}try{if(window.WebSocket)try{b("ws://localhost:12450/reload")}catch(a){console.error(a)}else console.log("Your browser does not support WebSockets.")}catch(a){console.error("Exception during connecting to Reload:",a)};
|
||||
`
|
||||
|
||||
func init() {
|
||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdNew)
|
||||
}
|
||||
|
||||
func CreateApp(cmd *commands.Command, args []string) int {
|
||||
output := cmd.Out()
|
||||
if len(args) != 1 {
|
||||
beeLogger.Log.Fatal("Argument [appname] is missing")
|
||||
}
|
||||
|
||||
apppath, packpath, err := utils.CheckEnv(args[0])
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
if utils.IsExist(apppath) {
|
||||
beeLogger.Log.Errorf(colors.Bold("Application '%s' already exists"), apppath)
|
||||
beeLogger.Log.Warn(colors.Bold("Do you want to overwrite it? [Yes|No] "))
|
||||
if !utils.AskForConfirmation() {
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
beeLogger.Log.Info("Creating application...")
|
||||
|
||||
os.MkdirAll(apppath, 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "conf"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "controllers"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "models"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "routers"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "tests"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "static"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "static", "js"), 0755)
|
||||
utils.WriteToFile(path.Join(apppath, "static", "js", "reload.min.js"), reloadJsClient)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "js")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "static", "css"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "css")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "static", "img"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "img")+string(path.Separator), "\x1b[0m")
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "views"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m")
|
||||
utils.WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(appconf, "{{.Appname}}", path.Base(args[0]), -1))
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "default.go"), "\x1b[0m")
|
||||
utils.WriteToFile(path.Join(apppath, "controllers", "default.go"), controllers)
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views", "index.tpl"), "\x1b[0m")
|
||||
utils.WriteToFile(path.Join(apppath, "views", "index.tpl"), indextpl)
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m")
|
||||
utils.WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(router, "{{.Appname}}", packpath, -1))
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests", "default_test.go"), "\x1b[0m")
|
||||
utils.WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(test, "{{.Appname}}", packpath, -1))
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
utils.WriteToFile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", packpath, -1))
|
||||
|
||||
beeLogger.Log.Success("New application successfully created!")
|
||||
return 0
|
||||
}
|
@ -1,18 +1,4 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package pack
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
@ -31,9 +17,14 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
"github.com/beego/bee/cmd/commands/version"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
var cmdPack = &Command{
|
||||
var CmdPack = &commands.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "pack",
|
||||
Short: "Compresses a Beego application into a single file",
|
||||
@ -43,7 +34,7 @@ var cmdPack = &Command{
|
||||
{{"Example:"|bold}}
|
||||
$ bee pack -v -ba="-ldflags '-s -w'"
|
||||
`,
|
||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
||||
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||
Run: packApp,
|
||||
}
|
||||
|
||||
@ -52,27 +43,16 @@ var (
|
||||
excludeP string
|
||||
excludeS string
|
||||
outputP string
|
||||
excludeR ListOpts
|
||||
excludeR utils.ListOpts
|
||||
fsym bool
|
||||
ssym bool
|
||||
build bool
|
||||
buildArgs string
|
||||
buildEnvs ListOpts
|
||||
buildEnvs utils.ListOpts
|
||||
verbose bool
|
||||
format string
|
||||
)
|
||||
|
||||
type ListOpts []string
|
||||
|
||||
func (opts *ListOpts) String() string {
|
||||
return fmt.Sprint(*opts)
|
||||
}
|
||||
|
||||
func (opts *ListOpts) Set(value string) error {
|
||||
*opts = append(*opts, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
fs := flag.NewFlagSet("pack", flag.ContinueOnError)
|
||||
fs.StringVar(&appPath, "p", "", "Set the application path. Defaults to the current path.")
|
||||
@ -87,7 +67,8 @@ func init() {
|
||||
fs.BoolVar(&fsym, "fs", false, "Tell the command to follow symlinks. Defaults to false.")
|
||||
fs.BoolVar(&ssym, "ss", false, "Tell the command to skip symlinks. Defaults to false.")
|
||||
fs.BoolVar(&verbose, "v", false, "Be more verbose during the operation. Defaults to false.")
|
||||
cmdPack.Flag = *fs
|
||||
CmdPack.Flag = *fs
|
||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdPack)
|
||||
}
|
||||
|
||||
type walker interface {
|
||||
@ -115,10 +96,6 @@ type walkFileTree struct {
|
||||
output *io.Writer
|
||||
}
|
||||
|
||||
func (wft *walkFileTree) setPrefix(prefix string) {
|
||||
wft.prefix = prefix
|
||||
}
|
||||
|
||||
func (wft *walkFileTree) isExclude(fPath string) bool {
|
||||
if fPath == "" {
|
||||
return true
|
||||
@ -316,12 +293,12 @@ func (wft *tarWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if isSym == false {
|
||||
if !isSym {
|
||||
fr, err := os.Open(fpath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer CloseFile(fr)
|
||||
defer utils.CloseFile(fr)
|
||||
_, err = io.Copy(tw, fr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@ -352,12 +329,12 @@ func (wft *zipWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if isSym == false {
|
||||
if !isSym {
|
||||
fr, err := os.Open(fpath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer CloseFile(fr)
|
||||
defer utils.CloseFile(fr)
|
||||
_, err = io.Copy(w, fr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@ -379,10 +356,10 @@ func (wft *zipWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
|
||||
func packDirectory(output io.Writer, excludePrefix []string, excludeSuffix []string,
|
||||
excludeRegexp []*regexp.Regexp, includePath ...string) (err error) {
|
||||
|
||||
logger.Infof("Excluding relpath prefix: %s", strings.Join(excludePrefix, ":"))
|
||||
logger.Infof("Excluding relpath suffix: %s", strings.Join(excludeSuffix, ":"))
|
||||
beeLogger.Log.Infof("Excluding relpath prefix: %s", strings.Join(excludePrefix, ":"))
|
||||
beeLogger.Log.Infof("Excluding relpath suffix: %s", strings.Join(excludeSuffix, ":"))
|
||||
if len(excludeRegexp) > 0 {
|
||||
logger.Infof("Excluding filename regex: `%s`", strings.Join(excludeR, "`, `"))
|
||||
beeLogger.Log.Infof("Excluding filename regex: `%s`", strings.Join(excludeR, "`, `"))
|
||||
}
|
||||
|
||||
w, err := os.OpenFile(outputP, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
@ -437,7 +414,7 @@ func packDirectory(output io.Writer, excludePrefix []string, excludeSuffix []str
|
||||
return
|
||||
}
|
||||
|
||||
func packApp(cmd *Command, args []string) int {
|
||||
func packApp(cmd *commands.Command, args []string) int {
|
||||
output := cmd.Out()
|
||||
curPath, _ := os.Getwd()
|
||||
thePath := ""
|
||||
@ -454,19 +431,19 @@ func packApp(cmd *Command, args []string) int {
|
||||
}
|
||||
cmd.Flag.Parse(nArgs)
|
||||
|
||||
if path.IsAbs(appPath) == false {
|
||||
if !path.IsAbs(appPath) {
|
||||
appPath = path.Join(curPath, appPath)
|
||||
}
|
||||
|
||||
thePath, err := path.Abs(appPath)
|
||||
if err != nil {
|
||||
logger.Fatalf("Wrong application path: %s", thePath)
|
||||
beeLogger.Log.Fatalf("Wrong application path: %s", thePath)
|
||||
}
|
||||
if stat, err := os.Stat(thePath); os.IsNotExist(err) || stat.IsDir() == false {
|
||||
logger.Fatalf("Application path does not exist: %s", thePath)
|
||||
if stat, err := os.Stat(thePath); os.IsNotExist(err) || !stat.IsDir() {
|
||||
beeLogger.Log.Fatalf("Application path does not exist: %s", thePath)
|
||||
}
|
||||
|
||||
logger.Infof("Packaging application on '%s'...", thePath)
|
||||
beeLogger.Log.Infof("Packaging application on '%s'...", thePath)
|
||||
|
||||
appName := path.Base(thePath)
|
||||
|
||||
@ -488,12 +465,12 @@ func packApp(cmd *Command, args []string) int {
|
||||
// Remove the tmpdir once bee pack is done
|
||||
err := os.RemoveAll(tmpdir)
|
||||
if err != nil {
|
||||
logger.Error("Failed to remove the generated temp dir")
|
||||
beeLogger.Log.Error("Failed to remove the generated temp dir")
|
||||
}
|
||||
}()
|
||||
|
||||
if build {
|
||||
logger.Info("Building application...")
|
||||
beeLogger.Log.Info("Building application...")
|
||||
var envs []string
|
||||
for _, env := range buildEnvs {
|
||||
parts := strings.SplitN(env, "=", 2)
|
||||
@ -515,7 +492,7 @@ func packApp(cmd *Command, args []string) int {
|
||||
os.Setenv("GOOS", goos)
|
||||
os.Setenv("GOARCH", goarch)
|
||||
|
||||
logger.Infof("Using: GOOS=%s GOARCH=%s", goos, goarch)
|
||||
beeLogger.Log.Infof("Using: GOOS=%s GOARCH=%s", goos, goarch)
|
||||
|
||||
binPath := path.Join(tmpdir, appName)
|
||||
if goos == "windows" {
|
||||
@ -538,10 +515,10 @@ func packApp(cmd *Command, args []string) int {
|
||||
execmd.Dir = thePath
|
||||
err = execmd.Run()
|
||||
if err != nil {
|
||||
logger.Fatal(err.Error())
|
||||
beeLogger.Log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
logger.Success("Build Successful!")
|
||||
beeLogger.Log.Success("Build Successful!")
|
||||
}
|
||||
|
||||
switch format {
|
||||
@ -552,14 +529,14 @@ func packApp(cmd *Command, args []string) int {
|
||||
|
||||
outputN := appName + "." + format
|
||||
|
||||
if outputP == "" || path.IsAbs(outputP) == false {
|
||||
if outputP == "" || !path.IsAbs(outputP) {
|
||||
outputP = path.Join(curPath, outputP)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(outputP); err != nil {
|
||||
err = os.MkdirAll(outputP, 0755)
|
||||
if err != nil {
|
||||
logger.Fatal(err.Error())
|
||||
beeLogger.Log.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@ -581,20 +558,20 @@ func packApp(cmd *Command, args []string) int {
|
||||
for _, r := range excludeR {
|
||||
if len(r) > 0 {
|
||||
if re, err := regexp.Compile(r); err != nil {
|
||||
logger.Fatal(err.Error())
|
||||
beeLogger.Log.Fatal(err.Error())
|
||||
} else {
|
||||
exr = append(exr, re)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.Infof("Writing to output: %s", outputP)
|
||||
beeLogger.Log.Infof("Writing to output: %s", outputP)
|
||||
|
||||
err = packDirectory(output, exp, exs, exr, tmpdir, thePath)
|
||||
if err != nil {
|
||||
logger.Fatal(err.Error())
|
||||
beeLogger.Log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
logger.Success("Application packed!")
|
||||
beeLogger.Log.Success("Application packed!")
|
||||
return 0
|
||||
}
|
88
cmd/commands/run/docs.go
Normal file
88
cmd/commands/run/docs.go
Normal file
@ -0,0 +1,88 @@
|
||||
package run
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
swaggerVersion = "2"
|
||||
swaggerlink = "https://github.com/beego/swagger/archive/v" + swaggerVersion + ".zip"
|
||||
)
|
||||
|
||||
func downloadFromURL(url, fileName string) {
|
||||
var down bool
|
||||
if fd, err := os.Stat(fileName); err != nil && os.IsNotExist(err) {
|
||||
down = true
|
||||
} else if fd.Size() == int64(0) {
|
||||
down = true
|
||||
} else {
|
||||
beeLogger.Log.Infof("'%s' already exists", fileName)
|
||||
return
|
||||
}
|
||||
if down {
|
||||
beeLogger.Log.Infof("Downloading '%s' to '%s'...", url, fileName)
|
||||
output, err := os.Create(fileName)
|
||||
if err != nil {
|
||||
beeLogger.Log.Errorf("Error while creating '%s': %s", fileName, err)
|
||||
return
|
||||
}
|
||||
defer output.Close()
|
||||
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
beeLogger.Log.Errorf("Error while downloading '%s': %s", url, err)
|
||||
return
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
n, err := io.Copy(output, response.Body)
|
||||
if err != nil {
|
||||
beeLogger.Log.Errorf("Error while downloading '%s': %s", url, err)
|
||||
return
|
||||
}
|
||||
beeLogger.Log.Successf("%d bytes downloaded!", n)
|
||||
}
|
||||
}
|
||||
|
||||
func unzipAndDelete(src string) error {
|
||||
beeLogger.Log.Infof("Unzipping '%s'...", src)
|
||||
r, err := zip.OpenReader(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
rp := strings.NewReplacer("swagger-"+swaggerVersion, "swagger")
|
||||
for _, f := range r.File {
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
fname := rp.Replace(f.Name)
|
||||
if f.FileInfo().IsDir() {
|
||||
os.MkdirAll(fname, f.Mode())
|
||||
} else {
|
||||
f, err := os.OpenFile(
|
||||
fname, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
_, err = io.Copy(f, rc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
beeLogger.Log.Successf("Done! Deleting '%s'...", src)
|
||||
return os.RemoveAll(src)
|
||||
}
|
@ -11,13 +11,14 @@
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package main
|
||||
package run
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
@ -70,7 +71,7 @@ func (c *wsClient) readPump() {
|
||||
_, _, err := c.conn.ReadMessage()
|
||||
if err != nil {
|
||||
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
|
||||
logger.Errorf("An error happened when reading from the Websocket client: %v", err)
|
||||
beeLogger.Log.Errorf("An error happened when reading from the Websocket client: %v", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
@ -109,7 +110,7 @@ func (c *wsClient) writePump() {
|
||||
|
||||
n := len(c.send)
|
||||
for i := 0; i < n; i++ {
|
||||
w.Write(newline)
|
||||
w.Write([]byte("/n"))
|
||||
w.Write(<-c.send)
|
||||
}
|
||||
|
||||
@ -155,13 +156,13 @@ func startReloadServer() {
|
||||
})
|
||||
|
||||
go startServer()
|
||||
logger.Infof("Reload server listening at %s", reloadAddress)
|
||||
beeLogger.Log.Infof("Reload server listening at %s", reloadAddress)
|
||||
}
|
||||
|
||||
func startServer() {
|
||||
err := http.ListenAndServe(reloadAddress, nil)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to start up the Reload server: %v", err)
|
||||
beeLogger.Log.Errorf("Failed to start up the Reload server: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -175,7 +176,7 @@ func sendReload(payload string) {
|
||||
func handleWsRequest(broker *wsBroker, w http.ResponseWriter, r *http.Request) {
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
logger.Errorf("error while upgrading server connection: %v", err)
|
||||
beeLogger.Log.Errorf("error while upgrading server connection: %v", err)
|
||||
return
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package run
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
@ -20,25 +20,31 @@ import (
|
||||
path "path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
"github.com/beego/bee/cmd/commands/version"
|
||||
"github.com/beego/bee/config"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
var cmdRun = &Command{
|
||||
var CmdRun = &commands.Command{
|
||||
UsageLine: "run [appname] [watchall] [-main=*.go] [-downdoc=true] [-gendoc=true] [-vendor=true] [-e=folderToExclude] [-ex=extraPackageToWatch] [-tags=goBuildTags] [-runmode=BEEGO_RUNMODE]",
|
||||
Short: "Run the application by starting a local development server",
|
||||
Long: `
|
||||
Run command will supervise the filesystem of the application for any changes, and recompile/restart it.
|
||||
|
||||
`,
|
||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
||||
Run: runApp,
|
||||
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||
Run: RunApp,
|
||||
}
|
||||
|
||||
var (
|
||||
mainFiles ListOpts
|
||||
downdoc docValue
|
||||
gendoc docValue
|
||||
mainFiles utils.ListOpts
|
||||
downdoc utils.DocValue
|
||||
gendoc utils.DocValue
|
||||
// The flags list of the paths excluded from watching
|
||||
excludedPaths strFlags
|
||||
excludedPaths utils.StrFlags
|
||||
// Pass through to -tags arg of "go build"
|
||||
buildTags string
|
||||
// Application path
|
||||
@ -54,66 +60,63 @@ var (
|
||||
// Current runmode
|
||||
runmode string
|
||||
// Extra directories
|
||||
extraPackages strFlags
|
||||
extraPackages utils.StrFlags
|
||||
)
|
||||
var started = make(chan bool)
|
||||
|
||||
func init() {
|
||||
cmdRun.Flag.Var(&mainFiles, "main", "Specify main go files.")
|
||||
cmdRun.Flag.Var(&gendoc, "gendoc", "Enable auto-generate the docs.")
|
||||
cmdRun.Flag.Var(&downdoc, "downdoc", "Enable auto-download of the swagger file if it does not exist.")
|
||||
cmdRun.Flag.Var(&excludedPaths, "e", "List of paths to exclude.")
|
||||
cmdRun.Flag.BoolVar(&vendorWatch, "vendor", false, "Enable watch vendor folder.")
|
||||
cmdRun.Flag.StringVar(&buildTags, "tags", "", "Set the build tags. See: https://golang.org/pkg/go/build/")
|
||||
cmdRun.Flag.StringVar(&runmode, "runmode", "", "Set the Beego run mode.")
|
||||
cmdRun.Flag.Var(&extraPackages, "ex", "List of extra package to watch.")
|
||||
CmdRun.Flag.Var(&mainFiles, "main", "Specify main go files.")
|
||||
CmdRun.Flag.Var(&gendoc, "gendoc", "Enable auto-generate the docs.")
|
||||
CmdRun.Flag.Var(&downdoc, "downdoc", "Enable auto-download of the swagger file if it does not exist.")
|
||||
CmdRun.Flag.Var(&excludedPaths, "e", "List of paths to exclude.")
|
||||
CmdRun.Flag.BoolVar(&vendorWatch, "vendor", false, "Enable watch vendor folder.")
|
||||
CmdRun.Flag.StringVar(&buildTags, "tags", "", "Set the build tags. See: https://golang.org/pkg/go/build/")
|
||||
CmdRun.Flag.StringVar(&runmode, "runmode", "", "Set the Beego run mode.")
|
||||
CmdRun.Flag.Var(&extraPackages, "ex", "List of extra package to watch.")
|
||||
exit = make(chan bool)
|
||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdRun)
|
||||
}
|
||||
|
||||
func runApp(cmd *Command, args []string) int {
|
||||
func RunApp(cmd *commands.Command, args []string) int {
|
||||
if len(args) == 0 || args[0] == "watchall" {
|
||||
currpath, _ = os.Getwd()
|
||||
if found, _gopath, _ := SearchGOPATHs(currpath); found {
|
||||
if found, _gopath, _ := utils.SearchGOPATHs(currpath); found {
|
||||
appname = path.Base(currpath)
|
||||
currentGoPath = _gopath
|
||||
} else {
|
||||
logger.Fatalf("No application '%s' found in your GOPATH", currpath)
|
||||
beeLogger.Log.Fatalf("No application '%s' found in your GOPATH", currpath)
|
||||
}
|
||||
} else {
|
||||
// Check if passed Bee application path/name exists in the GOPATH(s)
|
||||
if found, _gopath, _path := SearchGOPATHs(args[0]); found {
|
||||
if found, _gopath, _path := utils.SearchGOPATHs(args[0]); found {
|
||||
currpath = _path
|
||||
currentGoPath = _gopath
|
||||
appname = path.Base(currpath)
|
||||
} else {
|
||||
logger.Fatalf("No application '%s' found in your GOPATH", args[0])
|
||||
beeLogger.Log.Fatalf("No application '%s' found in your GOPATH", args[0])
|
||||
}
|
||||
|
||||
if strings.HasSuffix(appname, ".go") && isExist(currpath) {
|
||||
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() {
|
||||
if strings.HasSuffix(appname, ".go") && utils.IsExist(currpath) {
|
||||
beeLogger.Log.Warnf("The appname is in conflict with file's current path. Do you want to build appname as '%s'", appname)
|
||||
beeLogger.Log.Info("Do you want to overwrite it? [yes|no] ")
|
||||
if !utils.AskForConfirmation() {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.Infof("Using '%s' as 'appname'", appname)
|
||||
beeLogger.Log.Infof("Using '%s' as 'appname'", appname)
|
||||
|
||||
logger.Debugf("Current path: %s", __FILE__(), __LINE__(), currpath)
|
||||
beeLogger.Log.Debugf("Current path: %s", utils.FILE(), utils.LINE(), currpath)
|
||||
|
||||
if runmode == "prod" || runmode == "dev" {
|
||||
os.Setenv("BEEGO_RUNMODE", runmode)
|
||||
logger.Infof("Using '%s' as 'runmode'", os.Getenv("BEEGO_RUNMODE"))
|
||||
beeLogger.Log.Infof("Using '%s' as 'runmode'", os.Getenv("BEEGO_RUNMODE"))
|
||||
} else if runmode != "" {
|
||||
os.Setenv("BEEGO_RUNMODE", runmode)
|
||||
logger.Warnf("Using '%s' as 'runmode'", os.Getenv("BEEGO_RUNMODE"))
|
||||
beeLogger.Log.Warnf("Using '%s' as 'runmode'", os.Getenv("BEEGO_RUNMODE"))
|
||||
} else if os.Getenv("BEEGO_RUNMODE") != "" {
|
||||
logger.Warnf("Using '%s' as 'runmode'", os.Getenv("BEEGO_RUNMODE"))
|
||||
}
|
||||
|
||||
err := loadConfig()
|
||||
if err != nil {
|
||||
logger.Fatalf("Failed to load configuration: %s", err)
|
||||
beeLogger.Log.Warnf("Using '%s' as 'runmode'", os.Getenv("BEEGO_RUNMODE"))
|
||||
}
|
||||
|
||||
var paths []string
|
||||
@ -121,17 +124,17 @@ func runApp(cmd *Command, args []string) int {
|
||||
|
||||
// Because monitor files has some issues, we watch current directory
|
||||
// and ignore non-go files.
|
||||
for _, p := range conf.DirStruct.Others {
|
||||
for _, p := range config.Conf.DirStruct.Others {
|
||||
paths = append(paths, strings.Replace(p, "$GOPATH", currentGoPath, -1))
|
||||
}
|
||||
|
||||
if len(extraPackages) > 0 {
|
||||
// get the full path
|
||||
for _, packagePath := range extraPackages {
|
||||
if found, _, _fullPath := SearchGOPATHs(packagePath); found {
|
||||
if found, _, _fullPath := utils.SearchGOPATHs(packagePath); found {
|
||||
readAppDirectories(_fullPath, &paths)
|
||||
} else {
|
||||
logger.Warnf("No extra package '%s' found in your GOPATH", packagePath)
|
||||
beeLogger.Log.Warnf("No extra package '%s' found in your GOPATH", packagePath)
|
||||
}
|
||||
}
|
||||
// let paths unique
|
||||
@ -163,7 +166,7 @@ func runApp(cmd *Command, args []string) int {
|
||||
}
|
||||
|
||||
// Start the Reload server (if enabled)
|
||||
if conf.EnableReload {
|
||||
if config.Conf.EnableReload {
|
||||
startReloadServer()
|
||||
}
|
||||
if gendoc == "true" {
|
||||
@ -205,16 +208,16 @@ func readAppDirectories(directory string, paths *[]string) {
|
||||
continue
|
||||
}
|
||||
|
||||
if fileInfo.IsDir() == true && fileInfo.Name()[0] != '.' {
|
||||
if fileInfo.IsDir() && fileInfo.Name()[0] != '.' {
|
||||
readAppDirectories(directory+"/"+fileInfo.Name(), paths)
|
||||
continue
|
||||
}
|
||||
|
||||
if useDirectory == true {
|
||||
if useDirectory {
|
||||
continue
|
||||
}
|
||||
|
||||
if path.Ext(fileInfo.Name()) == ".go" || (ifStaticFile(fileInfo.Name()) && conf.EnableReload) {
|
||||
if path.Ext(fileInfo.Name()) == ".go" || (ifStaticFile(fileInfo.Name()) && config.Conf.EnableReload) {
|
||||
*paths = append(*paths, directory)
|
||||
useDirectory = true
|
||||
}
|
||||
@ -227,16 +230,16 @@ func isExcluded(filePath string) bool {
|
||||
for _, p := range excludedPaths {
|
||||
absP, err := path.Abs(p)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot get absolute path of '%s'", p)
|
||||
beeLogger.Log.Errorf("Cannot get absolute path of '%s'", p)
|
||||
continue
|
||||
}
|
||||
absFilePath, err := path.Abs(filePath)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot get absolute path of '%s'", filePath)
|
||||
beeLogger.Log.Errorf("Cannot get absolute path of '%s'", filePath)
|
||||
break
|
||||
}
|
||||
if strings.HasPrefix(absFilePath, absP) {
|
||||
logger.Infof("'%s' is not being watched", filePath)
|
||||
beeLogger.Log.Infof("'%s' is not being watched", filePath)
|
||||
return true
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package run
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -24,6 +24,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/beego/bee/config"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/logger/colors"
|
||||
"github.com/beego/bee/utils"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
@ -46,7 +50,7 @@ var (
|
||||
func NewWatcher(paths []string, files []string, isgenerate bool) {
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
logger.Fatalf("Failed to create watcher: %s", err)
|
||||
beeLogger.Log.Fatalf("Failed to create watcher: %s", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
@ -55,7 +59,7 @@ func NewWatcher(paths []string, files []string, isgenerate bool) {
|
||||
case e := <-watcher.Events:
|
||||
isBuild := true
|
||||
|
||||
if ifStaticFile(e.Name) && conf.EnableReload {
|
||||
if ifStaticFile(e.Name) && config.Conf.EnableReload {
|
||||
sendReload(e.String())
|
||||
continue
|
||||
}
|
||||
@ -69,14 +73,14 @@ func NewWatcher(paths []string, files []string, isgenerate bool) {
|
||||
|
||||
mt := getFileModTime(e.Name)
|
||||
if t := eventTime[e.Name]; mt == t {
|
||||
logger.Infof(bold("Skipping: ")+"%s", e.String())
|
||||
beeLogger.Log.Infof(colors.Bold("Skipping: ")+"%s", e.String())
|
||||
isBuild = false
|
||||
}
|
||||
|
||||
eventTime[e.Name] = mt
|
||||
|
||||
if isBuild {
|
||||
logger.Infof("Event fired: %s", e)
|
||||
beeLogger.Log.Infof("Event fired: %s", e)
|
||||
go func() {
|
||||
// Wait 1s before autobuild until there is no file change.
|
||||
scheduleTime = time.Now().Add(1 * time.Second)
|
||||
@ -85,17 +89,17 @@ func NewWatcher(paths []string, files []string, isgenerate bool) {
|
||||
}()
|
||||
}
|
||||
case err := <-watcher.Errors:
|
||||
logger.Warnf("Watcher error: %s", err.Error()) // No need to exit here
|
||||
beeLogger.Log.Warnf("Watcher error: %s", err.Error()) // No need to exit here
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
logger.Info("Initializing watcher...")
|
||||
beeLogger.Log.Info("Initializing watcher...")
|
||||
for _, path := range paths {
|
||||
logger.Infof(bold("Watching: ")+"%s", path)
|
||||
beeLogger.Log.Infof(colors.Bold("Watching: ")+"%s", path)
|
||||
err = watcher.Add(path)
|
||||
if err != nil {
|
||||
logger.Fatalf("Failed to watch directory: %s", err)
|
||||
beeLogger.Log.Fatalf("Failed to watch directory: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -105,14 +109,14 @@ func getFileModTime(path string) int64 {
|
||||
path = strings.Replace(path, "\\", "/", -1)
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to open file on '%s': %s", path, err)
|
||||
beeLogger.Log.Errorf("Failed to open file on '%s': %s", path, err)
|
||||
return time.Now().Unix()
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to get file stats: %s", err)
|
||||
beeLogger.Log.Errorf("Failed to get file stats: %s", err)
|
||||
return time.Now().Unix()
|
||||
}
|
||||
|
||||
@ -127,7 +131,7 @@ func AutoBuild(files []string, isgenerate bool) {
|
||||
os.Chdir(currpath)
|
||||
|
||||
cmdName := "go"
|
||||
if conf.Gopm.Enable {
|
||||
if config.Conf.Gopm.Enable {
|
||||
cmdName = "gopm"
|
||||
}
|
||||
|
||||
@ -138,14 +142,14 @@ func AutoBuild(files []string, isgenerate bool) {
|
||||
)
|
||||
// For applications use full import path like "github.com/.../.."
|
||||
// are able to use "go install" to reduce build time.
|
||||
if conf.GoInstall {
|
||||
if config.Conf.GoInstall {
|
||||
icmd := exec.Command(cmdName, "install", "-v")
|
||||
icmd.Stdout = os.Stdout
|
||||
icmd.Stderr = os.Stderr
|
||||
icmd.Env = append(os.Environ(), "GOGC=off")
|
||||
icmd.Run()
|
||||
}
|
||||
if conf.Gopm.Install {
|
||||
if config.Conf.Gopm.Install {
|
||||
icmd := exec.Command("go", "list", "./...")
|
||||
icmd.Stdout = &stdout
|
||||
icmd.Env = append(os.Environ(), "GOGC=off")
|
||||
@ -169,15 +173,15 @@ func AutoBuild(files []string, isgenerate bool) {
|
||||
}
|
||||
|
||||
if isgenerate {
|
||||
logger.Info("Generating the docs...")
|
||||
beeLogger.Log.Info("Generating the docs...")
|
||||
icmd := exec.Command("bee", "generate", "docs")
|
||||
icmd.Env = append(os.Environ(), "GOGC=off")
|
||||
err = icmd.Run()
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to generate the docs.")
|
||||
beeLogger.Log.Errorf("Failed to generate the docs.")
|
||||
return
|
||||
}
|
||||
logger.Success("Docs generated!")
|
||||
beeLogger.Log.Success("Docs generated!")
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
@ -198,12 +202,12 @@ func AutoBuild(files []string, isgenerate bool) {
|
||||
bcmd.Stderr = &stderr
|
||||
err = bcmd.Run()
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to build the application: %s", stderr.String())
|
||||
beeLogger.Log.Errorf("Failed to build the application: %s", stderr.String())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
logger.Success("Built Successfully!")
|
||||
beeLogger.Log.Success("Built Successfully!")
|
||||
Restart(appname)
|
||||
}
|
||||
|
||||
@ -211,39 +215,39 @@ func AutoBuild(files []string, isgenerate bool) {
|
||||
func Kill() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
logger.Infof("Kill recover: %s", e)
|
||||
beeLogger.Log.Infof("Kill recover: %s", e)
|
||||
}
|
||||
}()
|
||||
if cmd != nil && cmd.Process != nil {
|
||||
err := cmd.Process.Kill()
|
||||
if err != nil {
|
||||
logger.Errorf("Error while killing cmd process: %s", err)
|
||||
beeLogger.Log.Errorf("Error while killing cmd process: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restart kills the running command process and starts it again
|
||||
func Restart(appname string) {
|
||||
logger.Debugf("Kill running process", __FILE__(), __LINE__())
|
||||
beeLogger.Log.Debugf("Kill running process", utils.FILE(), utils.LINE())
|
||||
Kill()
|
||||
go Start(appname)
|
||||
}
|
||||
|
||||
// Start starts the command process
|
||||
func Start(appname string) {
|
||||
logger.Infof("Restarting '%s'...", appname)
|
||||
if strings.Index(appname, "./") == -1 {
|
||||
beeLogger.Log.Infof("Restarting '%s'...", appname)
|
||||
if !strings.Contains(appname, "./") {
|
||||
appname = "./" + appname
|
||||
}
|
||||
|
||||
cmd = exec.Command(appname)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Args = append([]string{appname}, conf.CmdArgs...)
|
||||
cmd.Env = append(os.Environ(), conf.Envs...)
|
||||
cmd.Args = append([]string{appname}, config.Conf.CmdArgs...)
|
||||
cmd.Env = append(os.Environ(), config.Conf.Envs...)
|
||||
|
||||
go cmd.Run()
|
||||
logger.Successf("'%s' is running...", appname)
|
||||
beeLogger.Log.Successf("'%s' is running...", appname)
|
||||
started <- true
|
||||
}
|
||||
|
||||
@ -262,7 +266,7 @@ func shouldIgnoreFile(filename string) bool {
|
||||
for _, regex := range ignoredFilesRegExps {
|
||||
r, err := regexp.Compile(regex)
|
||||
if err != nil {
|
||||
logger.Fatalf("Could not compile regular expression: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not compile regular expression: %s", err)
|
||||
}
|
||||
if r.MatchString(filename) {
|
||||
return true
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package version
|
||||
|
||||
import (
|
||||
"io"
|
||||
@ -6,6 +6,10 @@ import (
|
||||
"os"
|
||||
"runtime"
|
||||
"text/template"
|
||||
|
||||
"time"
|
||||
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
)
|
||||
|
||||
// RuntimeInfo holds information about the current runtime.
|
||||
@ -26,12 +30,12 @@ type RuntimeInfo struct {
|
||||
// print the banner in case of error.
|
||||
func InitBanner(out io.Writer, in io.Reader) {
|
||||
if in == nil {
|
||||
logger.Fatal("The input is nil")
|
||||
beeLogger.Log.Fatal("The input is nil")
|
||||
}
|
||||
|
||||
banner, err := ioutil.ReadAll(in)
|
||||
if err != nil {
|
||||
logger.Fatalf("Error while trying to read the banner: %s", err)
|
||||
beeLogger.Log.Fatalf("Error while trying to read the banner: %s", err)
|
||||
}
|
||||
|
||||
show(out, string(banner))
|
||||
@ -43,11 +47,11 @@ func show(out io.Writer, content string) {
|
||||
Parse(content)
|
||||
|
||||
if err != nil {
|
||||
logger.Fatalf("Cannot parse the banner template: %s", err)
|
||||
beeLogger.Log.Fatalf("Cannot parse the banner template: %s", err)
|
||||
}
|
||||
|
||||
err = t.Execute(out, RuntimeInfo{
|
||||
getGoVersion(),
|
||||
GetGoVersion(),
|
||||
runtime.GOOS,
|
||||
runtime.GOARCH,
|
||||
runtime.NumCPU(),
|
||||
@ -55,7 +59,14 @@ func show(out io.Writer, content string) {
|
||||
runtime.GOROOT(),
|
||||
runtime.Compiler,
|
||||
version,
|
||||
getBeegoVersion(),
|
||||
GetBeegoVersion(),
|
||||
})
|
||||
MustCheck(err)
|
||||
if err != nil {
|
||||
beeLogger.Log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Now returns the current local time in the specified layout
|
||||
func Now(layout string) string {
|
||||
return time.Now().Format(layout)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package version
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@ -14,18 +14,12 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/logger/colors"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var cmdVersion = &Command{
|
||||
UsageLine: "version",
|
||||
Short: "Prints the current Bee version",
|
||||
Long: `
|
||||
Prints the current Bee, Beego and Go version alongside the platform information.
|
||||
`,
|
||||
Run: versionCmd,
|
||||
}
|
||||
|
||||
const verboseVersionBanner string = `%s%s______
|
||||
| ___ \
|
||||
| |_/ / ___ ___
|
||||
@ -52,21 +46,33 @@ const shortVersionBanner = `______
|
||||
\____/ \___| \___| v{{ .BeeVersion }}
|
||||
`
|
||||
|
||||
var CmdVersion = &commands.Command{
|
||||
UsageLine: "version",
|
||||
Short: "Prints the current Bee version",
|
||||
Long: `
|
||||
Prints the current Bee, Beego and Go version alongside the platform information.
|
||||
`,
|
||||
Run: versionCmd,
|
||||
}
|
||||
var outputFormat string
|
||||
|
||||
const version = "1.8.0"
|
||||
|
||||
func init() {
|
||||
fs := flag.NewFlagSet("version", flag.ContinueOnError)
|
||||
fs.StringVar(&outputFormat, "o", "", "Set the output format. Either json or yaml.")
|
||||
cmdVersion.Flag = *fs
|
||||
CmdVersion.Flag = *fs
|
||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdVersion)
|
||||
}
|
||||
|
||||
func versionCmd(cmd *Command, args []string) int {
|
||||
func versionCmd(cmd *commands.Command, args []string) int {
|
||||
|
||||
cmd.Flag.Parse(args)
|
||||
stdout := cmd.Out()
|
||||
|
||||
if outputFormat != "" {
|
||||
runtimeInfo := RuntimeInfo{
|
||||
getGoVersion(),
|
||||
GetGoVersion(),
|
||||
runtime.GOOS,
|
||||
runtime.GOARCH,
|
||||
runtime.NumCPU(),
|
||||
@ -74,20 +80,24 @@ func versionCmd(cmd *Command, args []string) int {
|
||||
runtime.GOROOT(),
|
||||
runtime.Compiler,
|
||||
version,
|
||||
getBeegoVersion(),
|
||||
GetBeegoVersion(),
|
||||
}
|
||||
switch outputFormat {
|
||||
case "json":
|
||||
{
|
||||
b, err := json.MarshalIndent(runtimeInfo, "", " ")
|
||||
MustCheck(err)
|
||||
if err != nil {
|
||||
beeLogger.Log.Error(err.Error())
|
||||
}
|
||||
fmt.Println(string(b))
|
||||
return 0
|
||||
}
|
||||
case "yaml":
|
||||
{
|
||||
b, err := yaml.Marshal(&runtimeInfo)
|
||||
MustCheck(err)
|
||||
if err != nil {
|
||||
beeLogger.Log.Error(err.Error())
|
||||
}
|
||||
fmt.Println(string(b))
|
||||
return 0
|
||||
}
|
||||
@ -102,11 +112,11 @@ func versionCmd(cmd *Command, args []string) int {
|
||||
|
||||
// ShowShortVersionBanner prints the short version banner.
|
||||
func ShowShortVersionBanner() {
|
||||
output := NewColorWriter(os.Stdout)
|
||||
InitBanner(output, bytes.NewBufferString(MagentaBold(shortVersionBanner)))
|
||||
output := colors.NewColorWriter(os.Stdout)
|
||||
InitBanner(output, bytes.NewBufferString(colors.MagentaBold(shortVersionBanner)))
|
||||
}
|
||||
|
||||
func getBeegoVersion() string {
|
||||
func GetBeegoVersion() string {
|
||||
gopath := os.Getenv("GOPATH")
|
||||
re, err := regexp.Compile(`VERSION = "([0-9.]+)"`)
|
||||
if err != nil {
|
||||
@ -125,11 +135,11 @@ func getBeegoVersion() string {
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
logger.Error("Error while getting stats of 'beego.go'")
|
||||
beeLogger.Log.Error("Error while getting stats of 'beego.go'")
|
||||
}
|
||||
fd, err := os.Open(filename)
|
||||
if err != nil {
|
||||
logger.Error("Error while reading 'beego.go'")
|
||||
beeLogger.Log.Error("Error while reading 'beego.go'")
|
||||
continue
|
||||
}
|
||||
reader := bufio.NewReader(fd)
|
||||
@ -152,14 +162,14 @@ func getBeegoVersion() string {
|
||||
return "Beego is not installed. Please do consider installing it first: https://github.com/astaxie/beego"
|
||||
}
|
||||
|
||||
func getGoVersion() string {
|
||||
func GetGoVersion() string {
|
||||
var (
|
||||
cmdOut []byte
|
||||
err error
|
||||
)
|
||||
|
||||
if cmdOut, err = exec.Command("go", "version").Output(); err != nil {
|
||||
logger.Fatalf("There was an error running 'go version' command: %s", err)
|
||||
beeLogger.Log.Fatalf("There was an error running 'go version' command: %s", err)
|
||||
}
|
||||
return strings.Split(string(cmdOut), " ")[2]
|
||||
}
|
261
code.go
261
code.go
@ -1,261 +0,0 @@
|
||||
// Copyright 2011 Gary Burd
|
||||
// Copyright 2013 Unknown
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/printer"
|
||||
"go/scanner"
|
||||
"go/token"
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
notPredeclared = iota
|
||||
predeclaredType
|
||||
predeclaredConstant
|
||||
predeclaredFunction
|
||||
)
|
||||
|
||||
// predeclared represents the set of all predeclared identifiers.
|
||||
var predeclared = map[string]int{
|
||||
"bool": predeclaredType,
|
||||
"byte": predeclaredType,
|
||||
"complex128": predeclaredType,
|
||||
"complex64": predeclaredType,
|
||||
"error": predeclaredType,
|
||||
"float32": predeclaredType,
|
||||
"float64": predeclaredType,
|
||||
"int16": predeclaredType,
|
||||
"int32": predeclaredType,
|
||||
"int64": predeclaredType,
|
||||
"int8": predeclaredType,
|
||||
"int": predeclaredType,
|
||||
"rune": predeclaredType,
|
||||
"string": predeclaredType,
|
||||
"uint16": predeclaredType,
|
||||
"uint32": predeclaredType,
|
||||
"uint64": predeclaredType,
|
||||
"uint8": predeclaredType,
|
||||
"uint": predeclaredType,
|
||||
"uintptr": predeclaredType,
|
||||
|
||||
"true": predeclaredConstant,
|
||||
"false": predeclaredConstant,
|
||||
"iota": predeclaredConstant,
|
||||
"nil": predeclaredConstant,
|
||||
|
||||
"append": predeclaredFunction,
|
||||
"cap": predeclaredFunction,
|
||||
"close": predeclaredFunction,
|
||||
"complex": predeclaredFunction,
|
||||
"copy": predeclaredFunction,
|
||||
"delete": predeclaredFunction,
|
||||
"imag": predeclaredFunction,
|
||||
"len": predeclaredFunction,
|
||||
"make": predeclaredFunction,
|
||||
"new": predeclaredFunction,
|
||||
"panic": predeclaredFunction,
|
||||
"print": predeclaredFunction,
|
||||
"println": predeclaredFunction,
|
||||
"real": predeclaredFunction,
|
||||
"recover": predeclaredFunction,
|
||||
}
|
||||
|
||||
const (
|
||||
ExportLinkAnnotation AnnotationKind = iota
|
||||
AnchorAnnotation
|
||||
CommentAnnotation
|
||||
PackageLinkAnnotation
|
||||
BuiltinAnnotation
|
||||
)
|
||||
|
||||
// annotationVisitor collects annotations.
|
||||
type annotationVisitor struct {
|
||||
annotations []Annotation
|
||||
}
|
||||
|
||||
func (v *annotationVisitor) add(kind AnnotationKind, importPath string) {
|
||||
v.annotations = append(v.annotations, Annotation{Kind: kind, ImportPath: importPath})
|
||||
}
|
||||
|
||||
func (v *annotationVisitor) ignoreName() {
|
||||
v.add(-1, "")
|
||||
}
|
||||
|
||||
func (v *annotationVisitor) Visit(n ast.Node) ast.Visitor {
|
||||
switch n := n.(type) {
|
||||
case *ast.TypeSpec:
|
||||
v.ignoreName()
|
||||
ast.Walk(v, n.Type)
|
||||
case *ast.FuncDecl:
|
||||
if n.Recv != nil {
|
||||
ast.Walk(v, n.Recv)
|
||||
}
|
||||
v.ignoreName()
|
||||
ast.Walk(v, n.Type)
|
||||
case *ast.Field:
|
||||
for range n.Names {
|
||||
v.ignoreName()
|
||||
}
|
||||
ast.Walk(v, n.Type)
|
||||
case *ast.ValueSpec:
|
||||
for range n.Names {
|
||||
v.add(AnchorAnnotation, "")
|
||||
}
|
||||
if n.Type != nil {
|
||||
ast.Walk(v, n.Type)
|
||||
}
|
||||
for _, x := range n.Values {
|
||||
ast.Walk(v, x)
|
||||
}
|
||||
case *ast.Ident:
|
||||
switch {
|
||||
case n.Obj == nil && predeclared[n.Name] != notPredeclared:
|
||||
v.add(BuiltinAnnotation, "")
|
||||
case n.Obj != nil && ast.IsExported(n.Name):
|
||||
v.add(ExportLinkAnnotation, "")
|
||||
default:
|
||||
v.ignoreName()
|
||||
}
|
||||
case *ast.SelectorExpr:
|
||||
if x, _ := n.X.(*ast.Ident); x != nil {
|
||||
if obj := x.Obj; obj != nil && obj.Kind == ast.Pkg {
|
||||
if spec, _ := obj.Decl.(*ast.ImportSpec); spec != nil {
|
||||
if path, err := strconv.Unquote(spec.Path.Value); err == nil {
|
||||
v.add(PackageLinkAnnotation, path)
|
||||
if path == "C" {
|
||||
v.ignoreName()
|
||||
} else {
|
||||
v.add(ExportLinkAnnotation, path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.Walk(v, n.X)
|
||||
v.ignoreName()
|
||||
default:
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printDecl(decl ast.Node, fset *token.FileSet, buf []byte) (Code, []byte) {
|
||||
v := &annotationVisitor{}
|
||||
ast.Walk(v, decl)
|
||||
|
||||
buf = buf[:0]
|
||||
err := (&printer.Config{Mode: printer.UseSpaces, Tabwidth: 4}).Fprint(sliceWriter{&buf}, fset, decl)
|
||||
if err != nil {
|
||||
return Code{Text: err.Error()}, buf
|
||||
}
|
||||
|
||||
var annotations []Annotation
|
||||
var s scanner.Scanner
|
||||
fset = token.NewFileSet()
|
||||
file := fset.AddFile("", fset.Base(), len(buf))
|
||||
s.Init(file, buf, nil, scanner.ScanComments)
|
||||
loop:
|
||||
for {
|
||||
pos, tok, lit := s.Scan()
|
||||
switch tok {
|
||||
case token.EOF:
|
||||
break loop
|
||||
case token.COMMENT:
|
||||
p := file.Offset(pos)
|
||||
e := p + len(lit)
|
||||
if p > math.MaxInt16 || e > math.MaxInt16 {
|
||||
break loop
|
||||
}
|
||||
annotations = append(annotations, Annotation{Kind: CommentAnnotation, Pos: int16(p), End: int16(e)})
|
||||
case token.IDENT:
|
||||
if len(v.annotations) == 0 {
|
||||
// Oops!
|
||||
break loop
|
||||
}
|
||||
annotation := v.annotations[0]
|
||||
v.annotations = v.annotations[1:]
|
||||
if annotation.Kind == -1 {
|
||||
continue
|
||||
}
|
||||
p := file.Offset(pos)
|
||||
e := p + len(lit)
|
||||
if p > math.MaxInt16 || e > math.MaxInt16 {
|
||||
break loop
|
||||
}
|
||||
annotation.Pos = int16(p)
|
||||
annotation.End = int16(e)
|
||||
if len(annotations) > 0 && annotation.Kind == ExportLinkAnnotation {
|
||||
prev := annotations[len(annotations)-1]
|
||||
if prev.Kind == PackageLinkAnnotation &&
|
||||
prev.ImportPath == annotation.ImportPath &&
|
||||
prev.End+1 == annotation.Pos {
|
||||
// merge with previous
|
||||
annotation.Pos = prev.Pos
|
||||
annotations[len(annotations)-1] = annotation
|
||||
continue loop
|
||||
}
|
||||
}
|
||||
annotations = append(annotations, annotation)
|
||||
}
|
||||
}
|
||||
return Code{Text: string(buf), Annotations: annotations}, buf
|
||||
}
|
||||
|
||||
type AnnotationKind int16
|
||||
|
||||
type Annotation struct {
|
||||
Pos, End int16
|
||||
Kind AnnotationKind
|
||||
ImportPath string
|
||||
}
|
||||
|
||||
type Code struct {
|
||||
Text string
|
||||
Annotations []Annotation
|
||||
}
|
||||
|
||||
func commentAnnotations(src string) []Annotation {
|
||||
var annotations []Annotation
|
||||
var s scanner.Scanner
|
||||
fset := token.NewFileSet()
|
||||
file := fset.AddFile("", fset.Base(), len(src))
|
||||
s.Init(file, []byte(src), nil, scanner.ScanComments)
|
||||
for {
|
||||
pos, tok, lit := s.Scan()
|
||||
switch tok {
|
||||
case token.EOF:
|
||||
return annotations
|
||||
case token.COMMENT:
|
||||
p := file.Offset(pos)
|
||||
e := p + len(lit)
|
||||
if p > math.MaxInt16 || e > math.MaxInt16 {
|
||||
return annotations
|
||||
}
|
||||
annotations = append(annotations, Annotation{Kind: CommentAnnotation, Pos: int16(p), End: int16(e)})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type sliceWriter struct{ p *[]byte }
|
||||
|
||||
func (w sliceWriter) Write(p []byte) (int, error) {
|
||||
*w.p = append(*w.p, p...)
|
||||
return len(p), nil
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@ -22,6 +22,7 @@ import (
|
||||
"io"
|
||||
"path/filepath"
|
||||
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
@ -49,7 +50,7 @@ var defaultConf = `{
|
||||
"enable_reload": false
|
||||
}
|
||||
`
|
||||
var conf struct {
|
||||
var Conf struct {
|
||||
Version int
|
||||
// gopm support
|
||||
Gopm struct {
|
||||
@ -79,6 +80,10 @@ var conf struct {
|
||||
EnableReload bool `json:"enable_reload" yaml:"enable_reload"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
loadConfig()
|
||||
}
|
||||
|
||||
// loadConfig loads customized configuration.
|
||||
func loadConfig() (err error) {
|
||||
err = filepath.Walk(".", func(path string, fileInfo os.FileInfo, err error) error {
|
||||
@ -91,20 +96,20 @@ func loadConfig() (err error) {
|
||||
}
|
||||
|
||||
if fileInfo.Name() == "bee.json" {
|
||||
logger.Info("Loading configuration from 'bee.json'...")
|
||||
err = parseJSON(path, &conf)
|
||||
beeLogger.Log.Info("Loading configuration from 'bee.json'...")
|
||||
err = parseJSON(path, &Conf)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to parse JSON file: %s", err)
|
||||
beeLogger.Log.Errorf("Failed to parse JSON file: %s", err)
|
||||
return err
|
||||
}
|
||||
return io.EOF
|
||||
}
|
||||
|
||||
if fileInfo.Name() == "Beefile" {
|
||||
logger.Info("Loading configuration from 'Beefile'...")
|
||||
err = parseYAML(path, &conf)
|
||||
beeLogger.Log.Info("Loading configuration from 'Beefile'...")
|
||||
err = parseYAML(path, &Conf)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to parse YAML file: %s", err)
|
||||
beeLogger.Log.Errorf("Failed to parse YAML file: %s", err)
|
||||
return err
|
||||
}
|
||||
return io.EOF
|
||||
@ -115,8 +120,8 @@ 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 {
|
||||
logger.Info("Loading default configuration...")
|
||||
err = json.Unmarshal([]byte(defaultConf), &conf)
|
||||
beeLogger.Log.Info("Loading default configuration...")
|
||||
err = json.Unmarshal([]byte(defaultConf), &Conf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -126,21 +131,21 @@ func loadConfig() (err error) {
|
||||
err = nil
|
||||
|
||||
// Check format version
|
||||
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.")
|
||||
if Conf.Version != confVer {
|
||||
beeLogger.Log.Warn("Your configuration file is outdated. Please do consider updating it.")
|
||||
beeLogger.Log.Hint("Check the latest version of bee's configuration file.")
|
||||
}
|
||||
|
||||
// Set variables
|
||||
if len(conf.DirStruct.Controllers) == 0 {
|
||||
conf.DirStruct.Controllers = "controllers"
|
||||
if len(Conf.DirStruct.Controllers) == 0 {
|
||||
Conf.DirStruct.Controllers = "controllers"
|
||||
}
|
||||
if len(conf.DirStruct.Models) == 0 {
|
||||
conf.DirStruct.Models = "models"
|
||||
if len(Conf.DirStruct.Models) == 0 {
|
||||
Conf.DirStruct.Models = "models"
|
||||
}
|
||||
|
||||
// Append watch exts
|
||||
watchExts = append(watchExts, conf.WatchExt...)
|
||||
//watchExts = append(watchExts, Conf.WatchExt...)
|
||||
return
|
||||
}
|
||||
|
||||
@ -154,10 +159,7 @@ func parseJSON(path string, v interface{}) error {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(data, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func parseYAML(path string, v interface{}) error {
|
||||
@ -170,8 +172,5 @@ func parseYAML(path string, v interface{}) error {
|
||||
return err
|
||||
}
|
||||
err = yaml.Unmarshal(data, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
200
g.go
200
g.go
@ -1,200 +0,0 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var cmdGenerate = &Command{
|
||||
UsageLine: "generate [command]",
|
||||
Short: "Source code generator",
|
||||
Long: `▶ {{"To scaffold out your entire application:"|bold}}
|
||||
|
||||
$ bee generate scaffold [scaffoldname] [-fields="title:string,body:text"] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"]
|
||||
|
||||
▶ {{"To generate a Model based on fields:"|bold}}
|
||||
|
||||
$ bee generate model [modelname] [-fields="name:type"]
|
||||
|
||||
▶ {{"To generate a controller:"|bold}}
|
||||
|
||||
$ bee generate controller [controllerfile]
|
||||
|
||||
▶ {{"To generate a CRUD view:"|bold}}
|
||||
|
||||
$ bee generate view [viewpath]
|
||||
|
||||
▶ {{"To generate a migration file for making database schema updates:"|bold}}
|
||||
|
||||
$ bee generate migration [migrationfile] [-fields="name:type"]
|
||||
|
||||
▶ {{"To generate swagger doc file:"|bold}}
|
||||
|
||||
$ bee generate docs
|
||||
|
||||
▶ {{"To generate a test case:"|bold}}
|
||||
|
||||
$ bee generate test [routerfile]
|
||||
|
||||
▶ {{"To generate appcode based on an existing database:"|bold}}
|
||||
|
||||
$ bee generate appcode [-tables=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] [-level=3]
|
||||
`,
|
||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
||||
Run: generateCode,
|
||||
}
|
||||
|
||||
var driver docValue
|
||||
var conn docValue
|
||||
var level docValue
|
||||
var tables docValue
|
||||
var fields docValue
|
||||
|
||||
func init() {
|
||||
cmdGenerate.Flag.Var(&tables, "tables", "List of table names separated by a comma.")
|
||||
cmdGenerate.Flag.Var(&driver, "driver", "Database driver. Either mysql, postgres or sqlite.")
|
||||
cmdGenerate.Flag.Var(&conn, "conn", "Connection string used by the driver to connect to a database instance.")
|
||||
cmdGenerate.Flag.Var(&level, "level", "Either 1, 2 or 3. i.e. 1=models; 2=models and controllers; 3=models, controllers and routers.")
|
||||
cmdGenerate.Flag.Var(&fields, "fields", "List of table fields.")
|
||||
}
|
||||
|
||||
func generateCode(cmd *Command, args []string) int {
|
||||
currpath, _ := os.Getwd()
|
||||
if len(args) < 1 {
|
||||
logger.Fatal("Command is missing")
|
||||
}
|
||||
|
||||
gps := GetGOPATHs()
|
||||
if len(gps) == 0 {
|
||||
logger.Fatal("GOPATH environment variable is not set or empty")
|
||||
}
|
||||
|
||||
gopath := gps[0]
|
||||
|
||||
logger.Debugf("GOPATH: %s", __FILE__(), __LINE__(), gopath)
|
||||
|
||||
gcmd := args[0]
|
||||
switch gcmd {
|
||||
case "scaffold":
|
||||
if len(args) < 2 {
|
||||
logger.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
}
|
||||
// Load the configuration
|
||||
err := loadConfig()
|
||||
if err != nil {
|
||||
logger.Fatalf("Failed to load configuration: %s", err)
|
||||
}
|
||||
cmd.Flag.Parse(args[2:])
|
||||
if driver == "" {
|
||||
driver = docValue(conf.Database.Driver)
|
||||
if driver == "" {
|
||||
driver = "mysql"
|
||||
}
|
||||
}
|
||||
if conn == "" {
|
||||
conn = docValue(conf.Database.Conn)
|
||||
if conn == "" {
|
||||
conn = "root:@tcp(127.0.0.1:3306)/test"
|
||||
}
|
||||
}
|
||||
if fields == "" {
|
||||
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 the configuration
|
||||
err := loadConfig()
|
||||
if err != nil {
|
||||
logger.Fatalf("Failed to load configuration: %s", err)
|
||||
}
|
||||
cmd.Flag.Parse(args[1:])
|
||||
if driver == "" {
|
||||
driver = docValue(conf.Database.Driver)
|
||||
if driver == "" {
|
||||
driver = "mysql"
|
||||
}
|
||||
}
|
||||
if conn == "" {
|
||||
conn = docValue(conf.Database.Conn)
|
||||
if conn == "" {
|
||||
if driver == "mysql" {
|
||||
conn = "root:@tcp(127.0.0.1:3306)/test"
|
||||
} else if driver == "postgres" {
|
||||
conn = "postgres://postgres:postgres@127.0.0.1:5432/postgres"
|
||||
}
|
||||
}
|
||||
}
|
||||
if level == "" {
|
||||
level = "3"
|
||||
}
|
||||
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 {
|
||||
logger.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
}
|
||||
cmd.Flag.Parse(args[2:])
|
||||
mname := args[1]
|
||||
|
||||
logger.Infof("Using '%s' as migration name", mname)
|
||||
|
||||
upsql := ""
|
||||
downsql := ""
|
||||
if fields != "" {
|
||||
dbMigrator := newDBDriver()
|
||||
upsql = dbMigrator.generateCreateUp(mname)
|
||||
downsql = dbMigrator.generateCreateDown(mname)
|
||||
}
|
||||
generateMigration(mname, upsql, downsql, currpath)
|
||||
case "controller":
|
||||
if len(args) == 2 {
|
||||
cname := args[1]
|
||||
generateController(cname, currpath)
|
||||
} else {
|
||||
logger.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
}
|
||||
case "model":
|
||||
if len(args) < 2 {
|
||||
logger.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
}
|
||||
cmd.Flag.Parse(args[2:])
|
||||
if fields == "" {
|
||||
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)
|
||||
case "view":
|
||||
if len(args) == 2 {
|
||||
cname := args[1]
|
||||
generateView(cname, currpath)
|
||||
} else {
|
||||
logger.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
}
|
||||
default:
|
||||
logger.Fatal("Command is missing")
|
||||
}
|
||||
logger.Successf("%s successfully generated!", strings.Title(gcmd))
|
||||
return 0
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package main
|
||||
|
||||
import "strings"
|
||||
|
||||
func generateScaffold(sname, fields, currpath, driver, conn string) {
|
||||
logger.Infof("Do you want to create a '%s' model? [Yes|No] ", sname)
|
||||
|
||||
// Generate the model
|
||||
if askForConfirmation() {
|
||||
generateModel(sname, fields, currpath)
|
||||
}
|
||||
|
||||
// Generate the controller
|
||||
logger.Infof("Do you want to create a '%s' controller? [Yes|No] ", sname)
|
||||
if askForConfirmation() {
|
||||
generateController(sname, currpath)
|
||||
}
|
||||
|
||||
// Generate the views
|
||||
logger.Infof("Do you want to create views for this '%s' resource? [Yes|No] ", sname)
|
||||
if askForConfirmation() {
|
||||
generateView(sname, currpath)
|
||||
}
|
||||
|
||||
// Generate a migration
|
||||
logger.Infof("Do you want to create a '%s' migration and schema for this resource? [Yes|No] ", sname)
|
||||
if askForConfirmation() {
|
||||
upsql := ""
|
||||
downsql := ""
|
||||
if fields != "" {
|
||||
dbMigrator := newDBDriver()
|
||||
upsql = dbMigrator.generateCreateUp(sname)
|
||||
downsql = dbMigrator.generateCreateDown(sname)
|
||||
//todo remove
|
||||
//if driver == "" {
|
||||
// downsql = strings.Replace(downsql, "`", "", -1)
|
||||
//}
|
||||
}
|
||||
generateMigration(sname, upsql, downsql, currpath)
|
||||
}
|
||||
|
||||
// Run the migration
|
||||
logger.Infof("Do you want to migrate the database? [Yes|No] ")
|
||||
if askForConfirmation() {
|
||||
migrateUpdate(currpath, driver, conn)
|
||||
}
|
||||
logger.Successf("All done! Don't forget to add beego.Router(\"/%s\" ,&controllers.%sController{}) to routers/route.go\n", sname, strings.Title(sname))
|
||||
}
|
23
generate/g.go
Normal file
23
generate/g.go
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package generate
|
||||
|
||||
import "github.com/beego/bee/utils"
|
||||
|
||||
var SQLDriver utils.DocValue
|
||||
var SQLConn utils.DocValue
|
||||
var Level utils.DocValue
|
||||
var Tables utils.DocValue
|
||||
var Fields utils.DocValue
|
@ -12,7 +12,7 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package generate
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@ -23,6 +23,9 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/logger/colors"
|
||||
"github.com/beego/bee/utils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
@ -183,7 +186,7 @@ type OrmTag struct {
|
||||
|
||||
// String returns the source code string for the Table struct
|
||||
func (tb *Table) String() string {
|
||||
rv := fmt.Sprintf("type %s struct {\n", camelCase(tb.Name))
|
||||
rv := fmt.Sprintf("type %s struct {\n", utils.CamelCase(tb.Name))
|
||||
for _, v := range tb.Columns {
|
||||
rv += v.String() + "\n"
|
||||
}
|
||||
@ -255,7 +258,7 @@ func (tag *OrmTag) String() string {
|
||||
return fmt.Sprintf("`orm:\"%s\"`", strings.Join(ormOptions, ";"))
|
||||
}
|
||||
|
||||
func generateAppcode(driver, connStr, level, tables, currpath string) {
|
||||
func GenerateAppcode(driver, connStr, level, tables, currpath string) {
|
||||
var mode byte
|
||||
switch level {
|
||||
case "1":
|
||||
@ -265,7 +268,7 @@ func generateAppcode(driver, connStr, level, tables, currpath string) {
|
||||
case "3":
|
||||
mode = OModel | OController | ORouter
|
||||
default:
|
||||
logger.Fatal("Invalid level value. Must be either \"1\", \"2\", or \"3\"")
|
||||
beeLogger.Log.Fatal("Invalid level value. Must be either \"1\", \"2\", or \"3\"")
|
||||
}
|
||||
var selectedTables map[string]bool
|
||||
if tables != "" {
|
||||
@ -278,9 +281,9 @@ func generateAppcode(driver, connStr, level, tables, currpath string) {
|
||||
case "mysql":
|
||||
case "postgres":
|
||||
case "sqlite":
|
||||
logger.Fatal("Generating app code from SQLite database is not supported yet.")
|
||||
beeLogger.Log.Fatal("Generating app code from SQLite database is not supported yet.")
|
||||
default:
|
||||
logger.Fatal("Unknown database driver. Must be either \"mysql\", \"postgres\" or \"sqlite\"")
|
||||
beeLogger.Log.Fatal("Unknown database driver. Must be either \"mysql\", \"postgres\" or \"sqlite\"")
|
||||
}
|
||||
gen(driver, connStr, mode, selectedTables, currpath)
|
||||
}
|
||||
@ -290,11 +293,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 {
|
||||
logger.Fatalf("Could not connect to '%s' database using '%s': %s", dbms, connStr, err)
|
||||
beeLogger.Log.Fatalf("Could not connect to '%s' database using '%s': %s", dbms, connStr, err)
|
||||
}
|
||||
defer db.Close()
|
||||
if trans, ok := dbDriver[dbms]; ok {
|
||||
logger.Info("Analyzing database tables...")
|
||||
beeLogger.Log.Info("Analyzing database tables...")
|
||||
tableNames := trans.GetTableNames(db)
|
||||
tables := getTableObjects(tableNames, db, trans)
|
||||
mvcPath := new(MvcPath)
|
||||
@ -305,7 +308,7 @@ func gen(dbms, connStr string, mode byte, selectedTableNames map[string]bool, ap
|
||||
pkgPath := getPackagePath(apppath)
|
||||
writeSourceFiles(pkgPath, tables, mode, mvcPath, selectedTableNames)
|
||||
} else {
|
||||
logger.Fatalf("Generating app code from '%s' database is not supported yet.", dbms)
|
||||
beeLogger.Log.Fatalf("Generating app code from '%s' database is not supported yet.", dbms)
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,13 +316,13 @@ func gen(dbms, connStr string, mode byte, selectedTableNames map[string]bool, ap
|
||||
func (*MysqlDB) GetTableNames(db *sql.DB) (tables []string) {
|
||||
rows, err := db.Query("SHOW TABLES")
|
||||
if err != nil {
|
||||
logger.Fatalf("Could not show tables: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not show tables: %s", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var name string
|
||||
if err := rows.Scan(&name); err != nil {
|
||||
logger.Fatalf("Could not show tables: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not show tables: %s", err)
|
||||
}
|
||||
tables = append(tables, name)
|
||||
}
|
||||
@ -362,12 +365,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 {
|
||||
logger.Fatal("Could not query INFORMATION_SCHEMA for PK/UK/FK information")
|
||||
beeLogger.Log.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 {
|
||||
logger.Fatal("Could not read INFORMATION_SCHEMA for PK/UK/FK information")
|
||||
beeLogger.Log.Fatal("Could not read INFORMATION_SCHEMA for PK/UK/FK information")
|
||||
}
|
||||
constraintType, columnName, refTableSchema, refTableName, refColumnName, refOrdinalPos :=
|
||||
string(constraintTypeBytes), string(columnNameBytes), string(refTableSchemaBytes),
|
||||
@ -407,7 +410,7 @@ func (mysqlDB *MysqlDB) GetColumns(db *sql.DB, table *Table, blackList map[strin
|
||||
table_schema = database() AND table_name = ?`,
|
||||
table.Name)
|
||||
if err != nil {
|
||||
logger.Fatalf("Could not query the database: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not query the database: %s", err)
|
||||
}
|
||||
defer colDefRows.Close()
|
||||
|
||||
@ -415,17 +418,17 @@ func (mysqlDB *MysqlDB) GetColumns(db *sql.DB, table *Table, blackList map[strin
|
||||
// datatype as bytes so that SQL <null> values can be retrieved
|
||||
var colNameBytes, dataTypeBytes, columnTypeBytes, isNullableBytes, columnDefaultBytes, extraBytes []byte
|
||||
if err := colDefRows.Scan(&colNameBytes, &dataTypeBytes, &columnTypeBytes, &isNullableBytes, &columnDefaultBytes, &extraBytes); err != nil {
|
||||
logger.Fatal("Could not query INFORMATION_SCHEMA for column information")
|
||||
beeLogger.Log.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.Name = utils.CamelCase(colName)
|
||||
col.Type, err = mysqlDB.GetGoDataType(dataType)
|
||||
if err != nil {
|
||||
logger.Fatalf("%s", err)
|
||||
beeLogger.Log.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
// Tag info
|
||||
@ -449,8 +452,8 @@ func (mysqlDB *MysqlDB) GetColumns(db *sql.DB, table *Table, blackList map[strin
|
||||
if isFk && !isBl {
|
||||
tag.RelFk = true
|
||||
refStructName := fkCol.RefTable
|
||||
col.Name = camelCase(colName)
|
||||
col.Type = "*" + camelCase(refStructName)
|
||||
col.Name = utils.CamelCase(colName)
|
||||
col.Type = "*" + utils.CamelCase(refStructName)
|
||||
} else {
|
||||
// if the name of column is Id, and it's not primary key
|
||||
if colName == "id" {
|
||||
@ -464,7 +467,7 @@ func (mysqlDB *MysqlDB) GetColumns(db *sql.DB, table *Table, blackList map[strin
|
||||
if sign == "unsigned" && extra != "auto_increment" {
|
||||
col.Type, err = mysqlDB.GetGoDataType(dataType + " " + sign)
|
||||
if err != nil {
|
||||
logger.Fatalf("%s", err)
|
||||
beeLogger.Log.Fatalf("%s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -516,14 +519,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 {
|
||||
logger.Fatalf("Could not show tables: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not show tables: %s", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var name string
|
||||
if err := rows.Scan(&name); err != nil {
|
||||
logger.Fatalf("Could not show tables: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not show tables: %s", err)
|
||||
}
|
||||
tables = append(tables, name)
|
||||
}
|
||||
@ -553,13 +556,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 {
|
||||
logger.Fatalf("Could not query INFORMATION_SCHEMA for PK/UK/FK information: %s", err)
|
||||
beeLogger.Log.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 {
|
||||
logger.Fatalf("Could not read INFORMATION_SCHEMA for PK/UK/FK information: %s", err)
|
||||
beeLogger.Log.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),
|
||||
@ -609,7 +612,7 @@ func (postgresDB *PostgresDB) GetColumns(db *sql.DB, table *Table, blackList map
|
||||
AND table_name = $1`,
|
||||
table.Name)
|
||||
if err != nil {
|
||||
logger.Fatalf("Could not query INFORMATION_SCHEMA for column information: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not query INFORMATION_SCHEMA for column information: %s", err)
|
||||
}
|
||||
defer colDefRows.Close()
|
||||
|
||||
@ -617,16 +620,16 @@ func (postgresDB *PostgresDB) GetColumns(db *sql.DB, table *Table, blackList map
|
||||
// datatype as bytes so that SQL <null> values can be retrieved
|
||||
var colNameBytes, dataTypeBytes, columnTypeBytes, isNullableBytes, columnDefaultBytes, extraBytes []byte
|
||||
if err := colDefRows.Scan(&colNameBytes, &dataTypeBytes, &columnTypeBytes, &isNullableBytes, &columnDefaultBytes, &extraBytes); err != nil {
|
||||
logger.Fatalf("Could not query INFORMATION_SCHEMA for column information: %s", err)
|
||||
beeLogger.Log.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
|
||||
col := new(Column)
|
||||
col.Name = camelCase(colName)
|
||||
col.Name = utils.CamelCase(colName)
|
||||
col.Type, err = postgresDB.GetGoDataType(dataType)
|
||||
if err != nil {
|
||||
logger.Fatalf("%s", err)
|
||||
beeLogger.Log.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
// Tag info
|
||||
@ -650,8 +653,8 @@ func (postgresDB *PostgresDB) GetColumns(db *sql.DB, table *Table, blackList map
|
||||
if isFk && !isBl {
|
||||
tag.RelFk = true
|
||||
refStructName := fkCol.RefTable
|
||||
col.Name = camelCase(colName)
|
||||
col.Type = "*" + camelCase(refStructName)
|
||||
col.Name = utils.CamelCase(colName)
|
||||
col.Type = "*" + utils.CamelCase(refStructName)
|
||||
} else {
|
||||
// if the name of column is Id, and it's not primary key
|
||||
if colName == "id" {
|
||||
@ -716,22 +719,22 @@ 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 {
|
||||
logger.Info("Creating model files...")
|
||||
beeLogger.Log.Info("Creating model files...")
|
||||
writeModelFiles(tables, paths.ModelPath, selectedTables)
|
||||
}
|
||||
if (OController & mode) == OController {
|
||||
logger.Info("Creating controller files...")
|
||||
beeLogger.Log.Info("Creating controller files...")
|
||||
writeControllerFiles(tables, paths.ControllerPath, selectedTables, pkgPath)
|
||||
}
|
||||
if (ORouter & mode) == ORouter {
|
||||
logger.Info("Creating router files...")
|
||||
beeLogger.Log.Info("Creating router files...")
|
||||
writeRouterFile(tables, paths.RouterPath, selectedTables, pkgPath)
|
||||
}
|
||||
}
|
||||
|
||||
// writeModelFiles generates model files
|
||||
func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bool) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
w := colors.NewColorWriter(os.Stdout)
|
||||
|
||||
for _, tb := range tables {
|
||||
// if selectedTables map is not nil and this table is not selected, ignore it
|
||||
@ -744,22 +747,22 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo
|
||||
fpath := path.Join(mPath, filename+".go")
|
||||
var f *os.File
|
||||
var err error
|
||||
if isExist(fpath) {
|
||||
logger.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||
if askForConfirmation() {
|
||||
if utils.IsExist(fpath) {
|
||||
beeLogger.Log.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||
if utils.AskForConfirmation() {
|
||||
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
logger.Warnf("%s", err)
|
||||
beeLogger.Log.Warnf("%s", err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
logger.Warnf("Skipped create file '%s'", fpath)
|
||||
beeLogger.Log.Warnf("Skipped create file '%s'", fpath)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666)
|
||||
if err != nil {
|
||||
logger.Warnf("%s", err)
|
||||
beeLogger.Log.Warnf("%s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -770,7 +773,7 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo
|
||||
template = ModelTPL
|
||||
}
|
||||
fileStr := strings.Replace(template, "{{modelStruct}}", tb.String(), 1)
|
||||
fileStr = strings.Replace(fileStr, "{{modelName}}", camelCase(tb.Name), -1)
|
||||
fileStr = strings.Replace(fileStr, "{{modelName}}", utils.CamelCase(tb.Name), -1)
|
||||
fileStr = strings.Replace(fileStr, "{{tableName}}", tb.Name, -1)
|
||||
|
||||
// If table contains time field, import time.Time package
|
||||
@ -783,17 +786,17 @@ 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 {
|
||||
logger.Fatalf("Could not write model file to '%s': %s", fpath, err)
|
||||
beeLogger.Log.Fatalf("Could not write model file to '%s': %s", fpath, err)
|
||||
}
|
||||
CloseFile(f)
|
||||
utils.CloseFile(f)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
formatSourceCode(fpath)
|
||||
utils.FormatSourceCode(fpath)
|
||||
}
|
||||
}
|
||||
|
||||
// writeControllerFiles generates controller files
|
||||
func writeControllerFiles(tables []*Table, cPath string, selectedTables map[string]bool, pkgPath string) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
w := colors.NewColorWriter(os.Stdout)
|
||||
|
||||
for _, tb := range tables {
|
||||
// If selectedTables map is not nil and this table is not selected, ignore it
|
||||
@ -809,39 +812,39 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri
|
||||
fpath := path.Join(cPath, filename+".go")
|
||||
var f *os.File
|
||||
var err error
|
||||
if isExist(fpath) {
|
||||
logger.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||
if askForConfirmation() {
|
||||
if utils.IsExist(fpath) {
|
||||
beeLogger.Log.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||
if utils.AskForConfirmation() {
|
||||
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
logger.Warnf("%s", err)
|
||||
beeLogger.Log.Warnf("%s", err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
logger.Warnf("Skipped create file '%s'", fpath)
|
||||
beeLogger.Log.Warnf("Skipped create file '%s'", fpath)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666)
|
||||
if err != nil {
|
||||
logger.Warnf("%s", err)
|
||||
beeLogger.Log.Warnf("%s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
fileStr := strings.Replace(CtrlTPL, "{{ctrlName}}", camelCase(tb.Name), -1)
|
||||
fileStr := strings.Replace(CtrlTPL, "{{ctrlName}}", utils.CamelCase(tb.Name), -1)
|
||||
fileStr = strings.Replace(fileStr, "{{pkgPath}}", pkgPath, -1)
|
||||
if _, err := f.WriteString(fileStr); err != nil {
|
||||
logger.Fatalf("Could not write controller file to '%s': %s", fpath, err)
|
||||
beeLogger.Log.Fatalf("Could not write controller file to '%s': %s", fpath, err)
|
||||
}
|
||||
CloseFile(f)
|
||||
utils.CloseFile(f)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
formatSourceCode(fpath)
|
||||
utils.FormatSourceCode(fpath)
|
||||
}
|
||||
}
|
||||
|
||||
// writeRouterFile generates router file
|
||||
func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bool, pkgPath string) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
w := colors.NewColorWriter(os.Stdout)
|
||||
|
||||
var nameSpaces []string
|
||||
for _, tb := range tables {
|
||||
@ -856,7 +859,7 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo
|
||||
}
|
||||
// Add namespaces
|
||||
nameSpace := strings.Replace(NamespaceTPL, "{{nameSpace}}", tb.Name, -1)
|
||||
nameSpace = strings.Replace(nameSpace, "{{ctrlName}}", camelCase(tb.Name), -1)
|
||||
nameSpace = strings.Replace(nameSpace, "{{ctrlName}}", utils.CamelCase(tb.Name), -1)
|
||||
nameSpaces = append(nameSpaces, nameSpace)
|
||||
}
|
||||
// Add export controller
|
||||
@ -865,31 +868,31 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo
|
||||
routerStr = strings.Replace(routerStr, "{{pkgPath}}", pkgPath, 1)
|
||||
var f *os.File
|
||||
var err error
|
||||
if isExist(fpath) {
|
||||
logger.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||
if askForConfirmation() {
|
||||
if utils.IsExist(fpath) {
|
||||
beeLogger.Log.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||
if utils.AskForConfirmation() {
|
||||
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
logger.Warnf("%s", err)
|
||||
beeLogger.Log.Warnf("%s", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
logger.Warnf("Skipped create file '%s'", fpath)
|
||||
beeLogger.Log.Warnf("Skipped create file '%s'", fpath)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666)
|
||||
if err != nil {
|
||||
logger.Warnf("%s", err)
|
||||
beeLogger.Log.Warnf("%s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if _, err := f.WriteString(routerStr); err != nil {
|
||||
logger.Fatalf("Could not write router file to '%s': %s", fpath, err)
|
||||
beeLogger.Log.Fatalf("Could not write router file to '%s': %s", fpath, err)
|
||||
}
|
||||
CloseFile(f)
|
||||
utils.CloseFile(f)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
formatSourceCode(fpath)
|
||||
utils.FormatSourceCode(fpath)
|
||||
}
|
||||
|
||||
func isSQLTemporalType(t string) bool {
|
||||
@ -952,10 +955,10 @@ func getFileName(tbName string) (filename string) {
|
||||
func getPackagePath(curpath string) (packpath string) {
|
||||
gopath := os.Getenv("GOPATH")
|
||||
if gopath == "" {
|
||||
logger.Fatal("GOPATH environment variable is not set or empty")
|
||||
beeLogger.Log.Fatal("GOPATH environment variable is not set or empty")
|
||||
}
|
||||
|
||||
logger.Debugf("GOPATH: %s", __FILE__(), __LINE__(), gopath)
|
||||
beeLogger.Log.Debugf("GOPATH: %s", utils.FILE(), utils.LINE(), gopath)
|
||||
|
||||
appsrcpath := ""
|
||||
haspath := false
|
||||
@ -964,7 +967,7 @@ func getPackagePath(curpath string) (packpath string) {
|
||||
for _, wg := range wgopath {
|
||||
wg, _ = filepath.EvalSymlinks(path.Join(wg, "src"))
|
||||
|
||||
if filepath.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) {
|
||||
if strings.HasPrefix(strings.ToLower(curpath), strings.ToLower(wg)) {
|
||||
haspath = true
|
||||
appsrcpath = wg
|
||||
break
|
||||
@ -972,11 +975,11 @@ func getPackagePath(curpath string) (packpath string) {
|
||||
}
|
||||
|
||||
if !haspath {
|
||||
logger.Fatalf("Cannot generate application code outside of GOPATH '%s'", gopath)
|
||||
beeLogger.Log.Fatalf("Cannot generate application code outside of GOPATH '%s'", gopath)
|
||||
}
|
||||
|
||||
if curpath == appsrcpath {
|
||||
logger.Fatal("Cannot generate application code outside of application path")
|
||||
beeLogger.Log.Fatal("Cannot generate application code outside of application path")
|
||||
}
|
||||
|
||||
packpath = strings.Join(strings.Split(curpath[len(appsrcpath)+1:], string(filepath.Separator)), "/")
|
@ -12,17 +12,21 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package generate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/logger/colors"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
func generateController(cname, currpath string) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
func GenerateController(cname, currpath string) {
|
||||
w := colors.NewColorWriter(os.Stdout)
|
||||
|
||||
p, f := path.Split(cname)
|
||||
controllerName := strings.Title(f)
|
||||
@ -33,26 +37,26 @@ func generateController(cname, currpath string) {
|
||||
packageName = p[i+1 : len(p)-1]
|
||||
}
|
||||
|
||||
logger.Infof("Using '%s' as controller name", controllerName)
|
||||
logger.Infof("Using '%s' as package name", packageName)
|
||||
beeLogger.Log.Infof("Using '%s' as controller name", controllerName)
|
||||
beeLogger.Log.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 {
|
||||
logger.Fatalf("Could not create controllers directory: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not create controllers directory: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
fpath := path.Join(fp, strings.ToLower(controllerName)+".go")
|
||||
if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer CloseFile(f)
|
||||
defer utils.CloseFile(f)
|
||||
|
||||
modelPath := path.Join(currpath, "models", strings.ToLower(controllerName)+".go")
|
||||
|
||||
var content string
|
||||
if _, err := os.Stat(modelPath); err == nil {
|
||||
logger.Infof("Using matching model '%s'", controllerName)
|
||||
beeLogger.Log.Infof("Using matching model '%s'", controllerName)
|
||||
content = strings.Replace(controllerModelTpl, "{{packageName}}", packageName, -1)
|
||||
pkgPath := getPackagePath(currpath)
|
||||
content = strings.Replace(content, "{{pkgPath}}", pkgPath, -1)
|
||||
@ -64,10 +68,10 @@ func generateController(cname, currpath string) {
|
||||
f.WriteString(content)
|
||||
|
||||
// Run 'gofmt' on the generated source code
|
||||
formatSourceCode(fpath)
|
||||
utils.FormatSourceCode(fpath)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
} else {
|
||||
logger.Fatalf("Could not create controller file: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not create controller file: %s", err)
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
* *
|
||||
\**********************************************************/
|
||||
|
||||
package main
|
||||
package generate
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@ -24,11 +24,256 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/logger/colors"
|
||||
"github.com/beego/bee/utils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
func generateHproseAppcode(driver, connStr, level, tables, currpath string) {
|
||||
var Hproseconf = `appname = {{.Appname}}
|
||||
httpport = 8080
|
||||
runmode = dev
|
||||
autorender = false
|
||||
copyrequestbody = true
|
||||
EnableDocs = true
|
||||
`
|
||||
var HproseMaingo = `package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"{{.Appname}}/models"
|
||||
"github.com/hprose/hprose-golang/rpc"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
func logInvokeHandler(
|
||||
name string,
|
||||
args []reflect.Value,
|
||||
context rpc.Context,
|
||||
next rpc.NextInvokeHandler) (results []reflect.Value, err error) {
|
||||
fmt.Printf("%s(%v) = ", name, args)
|
||||
results, err = next(name, args, context)
|
||||
fmt.Printf("%v %v\r\n", results, err)
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Create WebSocketServer
|
||||
// service := rpc.NewWebSocketService()
|
||||
|
||||
// Create Http Server
|
||||
service := rpc.NewHTTPService()
|
||||
|
||||
// Use Logger Middleware
|
||||
service.AddInvokeHandler(logInvokeHandler)
|
||||
|
||||
// Publish Functions
|
||||
service.AddFunction("AddOne", models.AddOne)
|
||||
service.AddFunction("GetOne", models.GetOne)
|
||||
|
||||
// Start Service
|
||||
beego.Handler("/", service)
|
||||
beego.Run()
|
||||
}
|
||||
`
|
||||
|
||||
var HproseMainconngo = `package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"{{.Appname}}/models"
|
||||
"github.com/hprose/hprose-golang/rpc"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/orm"
|
||||
{{.DriverPkg}}
|
||||
)
|
||||
|
||||
func init() {
|
||||
orm.RegisterDataBase("default", "{{.DriverName}}", "{{.conn}}")
|
||||
}
|
||||
|
||||
func logInvokeHandler(
|
||||
name string,
|
||||
args []reflect.Value,
|
||||
context rpc.Context,
|
||||
next rpc.NextInvokeHandler) (results []reflect.Value, err error) {
|
||||
fmt.Printf("%s(%v) = ", name, args)
|
||||
results, err = next(name, args, context)
|
||||
fmt.Printf("%v %v\r\n", results, err)
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Create WebSocketServer
|
||||
// service := rpc.NewWebSocketService()
|
||||
|
||||
// Create Http Server
|
||||
service := rpc.NewHTTPService()
|
||||
|
||||
// Use Logger Middleware
|
||||
service.AddInvokeHandler(logInvokeHandler)
|
||||
|
||||
{{HproseFunctionList}}
|
||||
|
||||
// Start Service
|
||||
beego.Handler("/", service)
|
||||
beego.Run()
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
var HproseModels = `package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
Objects map[string]*Object
|
||||
)
|
||||
|
||||
type Object struct {
|
||||
ObjectId string
|
||||
Score int64
|
||||
PlayerName string
|
||||
}
|
||||
|
||||
func init() {
|
||||
Objects = make(map[string]*Object)
|
||||
Objects["hjkhsbnmn123"] = &Object{"hjkhsbnmn123", 100, "astaxie"}
|
||||
Objects["mjjkxsxsaa23"] = &Object{"mjjkxsxsaa23", 101, "someone"}
|
||||
}
|
||||
|
||||
func AddOne(object Object) (ObjectId string) {
|
||||
object.ObjectId = "astaxie" + strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||
Objects[object.ObjectId] = &object
|
||||
return object.ObjectId
|
||||
}
|
||||
|
||||
func GetOne(ObjectId string) (object *Object, err error) {
|
||||
if v, ok := Objects[ObjectId]; ok {
|
||||
return v, nil
|
||||
}
|
||||
return nil, errors.New("ObjectId Not Exist")
|
||||
}
|
||||
|
||||
func GetAll() map[string]*Object {
|
||||
return Objects
|
||||
}
|
||||
|
||||
func Update(ObjectId string, Score int64) (err error) {
|
||||
if v, ok := Objects[ObjectId]; ok {
|
||||
v.Score = Score
|
||||
return nil
|
||||
}
|
||||
return errors.New("ObjectId Not Exist")
|
||||
}
|
||||
|
||||
func Delete(ObjectId string) {
|
||||
delete(Objects, ObjectId)
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
var HproseModels2 = `package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
UserList map[string]*User
|
||||
)
|
||||
|
||||
func init() {
|
||||
UserList = make(map[string]*User)
|
||||
u := User{"user_11111", "astaxie", "11111", Profile{"male", 20, "Singapore", "astaxie@gmail.com"}}
|
||||
UserList["user_11111"] = &u
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Id string
|
||||
Username string
|
||||
Password string
|
||||
Profile Profile
|
||||
}
|
||||
|
||||
type Profile struct {
|
||||
Gender string
|
||||
Age int
|
||||
Address string
|
||||
Email string
|
||||
}
|
||||
|
||||
func AddUser(u User) string {
|
||||
u.Id = "user_" + strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||
UserList[u.Id] = &u
|
||||
return u.Id
|
||||
}
|
||||
|
||||
func GetUser(uid string) (u *User, err error) {
|
||||
if u, ok := UserList[uid]; ok {
|
||||
return u, nil
|
||||
}
|
||||
return nil, errors.New("User not exists")
|
||||
}
|
||||
|
||||
func GetAllUsers() map[string]*User {
|
||||
return UserList
|
||||
}
|
||||
|
||||
func UpdateUser(uid string, uu *User) (a *User, err error) {
|
||||
if u, ok := UserList[uid]; ok {
|
||||
if uu.Username != "" {
|
||||
u.Username = uu.Username
|
||||
}
|
||||
if uu.Password != "" {
|
||||
u.Password = uu.Password
|
||||
}
|
||||
if uu.Profile.Age != 0 {
|
||||
u.Profile.Age = uu.Profile.Age
|
||||
}
|
||||
if uu.Profile.Address != "" {
|
||||
u.Profile.Address = uu.Profile.Address
|
||||
}
|
||||
if uu.Profile.Gender != "" {
|
||||
u.Profile.Gender = uu.Profile.Gender
|
||||
}
|
||||
if uu.Profile.Email != "" {
|
||||
u.Profile.Email = uu.Profile.Email
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
return nil, errors.New("User Not Exist")
|
||||
}
|
||||
|
||||
func Login(username, password string) bool {
|
||||
for _, u := range UserList {
|
||||
if u.Username == username && u.Password == password {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func DeleteUser(uid string) {
|
||||
delete(UserList, uid)
|
||||
}
|
||||
`
|
||||
var HproseAddFunctions = []string{}
|
||||
|
||||
func GenerateHproseAppcode(driver, connStr, level, tables, currpath string) {
|
||||
var mode byte
|
||||
switch level {
|
||||
case "1":
|
||||
@ -38,7 +283,7 @@ func generateHproseAppcode(driver, connStr, level, tables, currpath string) {
|
||||
case "3":
|
||||
mode = OModel | OController | ORouter
|
||||
default:
|
||||
logger.Fatal("Invalid 'level' option. Level must be either \"1\", \"2\" or \"3\"")
|
||||
beeLogger.Log.Fatal("Invalid 'level' option. Level must be either \"1\", \"2\" or \"3\"")
|
||||
}
|
||||
var selectedTables map[string]bool
|
||||
if tables != "" {
|
||||
@ -51,9 +296,9 @@ func generateHproseAppcode(driver, connStr, level, tables, currpath string) {
|
||||
case "mysql":
|
||||
case "postgres":
|
||||
case "sqlite":
|
||||
logger.Fatal("Generating app code from SQLite database is not supported yet")
|
||||
beeLogger.Log.Fatal("Generating app code from SQLite database is not supported yet")
|
||||
default:
|
||||
logger.Fatalf("Unknown database driver '%s'. Driver must be one of mysql, postgres or sqlite", driver)
|
||||
beeLogger.Log.Fatalf("Unknown database driver '%s'. Driver must be one of mysql, postgres or sqlite", driver)
|
||||
}
|
||||
genHprose(driver, connStr, mode, selectedTables, currpath)
|
||||
}
|
||||
@ -63,11 +308,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 {
|
||||
logger.Fatalf("Could not connect to '%s' database using '%s': %s", dbms, connStr, err)
|
||||
beeLogger.Log.Fatalf("Could not connect to '%s' database using '%s': %s", dbms, connStr, err)
|
||||
}
|
||||
defer db.Close()
|
||||
if trans, ok := dbDriver[dbms]; ok {
|
||||
logger.Info("Analyzing database tables...")
|
||||
beeLogger.Log.Info("Analyzing database tables...")
|
||||
tableNames := trans.GetTableNames(db)
|
||||
tables := getTableObjects(tableNames, db, trans)
|
||||
mvcPath := new(MvcPath)
|
||||
@ -76,7 +321,7 @@ func genHprose(dbms, connStr string, mode byte, selectedTableNames map[string]bo
|
||||
pkgPath := getPackagePath(currpath)
|
||||
writeHproseSourceFiles(pkgPath, tables, mode, mvcPath, selectedTableNames)
|
||||
} else {
|
||||
logger.Fatalf("Generating app code from '%s' database is not supported yet", dbms)
|
||||
beeLogger.Log.Fatalf("Generating app code from '%s' database is not supported yet", dbms)
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,14 +330,14 @@ 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 {
|
||||
logger.Info("Creating model files...")
|
||||
beeLogger.Log.Info("Creating model files...")
|
||||
writeHproseModelFiles(tables, paths.ModelPath, selectedTables)
|
||||
}
|
||||
}
|
||||
|
||||
// writeHproseModelFiles generates model files
|
||||
func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[string]bool) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
w := colors.NewColorWriter(os.Stdout)
|
||||
|
||||
for _, tb := range tables {
|
||||
// if selectedTables map is not nil and this table is not selected, ignore it
|
||||
@ -105,22 +350,22 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str
|
||||
fpath := path.Join(mPath, filename+".go")
|
||||
var f *os.File
|
||||
var err error
|
||||
if isExist(fpath) {
|
||||
logger.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||
if askForConfirmation() {
|
||||
if utils.IsExist(fpath) {
|
||||
beeLogger.Log.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||
if utils.AskForConfirmation() {
|
||||
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
logger.Warnf("%s", err)
|
||||
beeLogger.Log.Warnf("%s", err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
logger.Warnf("Skipped create file '%s'", fpath)
|
||||
beeLogger.Log.Warnf("Skipped create file '%s'", fpath)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666)
|
||||
if err != nil {
|
||||
logger.Warnf("%s", err)
|
||||
beeLogger.Log.Warnf("%s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -129,10 +374,10 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str
|
||||
template = HproseStructModelTPL
|
||||
} else {
|
||||
template = HproseModelTPL
|
||||
hproseAddFunctions = append(hproseAddFunctions, strings.Replace(HproseAddFunction, "{{modelName}}", camelCase(tb.Name), -1))
|
||||
HproseAddFunctions = append(HproseAddFunctions, strings.Replace(HproseAddFunction, "{{modelName}}", utils.CamelCase(tb.Name), -1))
|
||||
}
|
||||
fileStr := strings.Replace(template, "{{modelStruct}}", tb.String(), 1)
|
||||
fileStr = strings.Replace(fileStr, "{{modelName}}", camelCase(tb.Name), -1)
|
||||
fileStr = strings.Replace(fileStr, "{{modelName}}", utils.CamelCase(tb.Name), -1)
|
||||
// if table contains time field, import time.Time package
|
||||
timePkg := ""
|
||||
importTimePkg := ""
|
||||
@ -143,11 +388,11 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str
|
||||
fileStr = strings.Replace(fileStr, "{{timePkg}}", timePkg, -1)
|
||||
fileStr = strings.Replace(fileStr, "{{importTimePkg}}", importTimePkg, -1)
|
||||
if _, err := f.WriteString(fileStr); err != nil {
|
||||
logger.Fatalf("Could not write model file to '%s'", fpath)
|
||||
beeLogger.Log.Fatalf("Could not write model file to '%s'", fpath)
|
||||
}
|
||||
CloseFile(f)
|
||||
utils.CloseFile(f)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
formatSourceCode(fpath)
|
||||
utils.FormatSourceCode(fpath)
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package generate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -20,6 +20,10 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/logger/colors"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -29,18 +33,18 @@ const (
|
||||
)
|
||||
|
||||
type DBDriver interface {
|
||||
generateCreateUp(tableName string) string
|
||||
generateCreateDown(tableName string) string
|
||||
GenerateCreateUp(tableName string) string
|
||||
GenerateCreateDown(tableName string) string
|
||||
}
|
||||
|
||||
type mysqlDriver struct{}
|
||||
|
||||
func (m mysqlDriver) generateCreateUp(tableName string) string {
|
||||
upsql := `m.SQL("CREATE TABLE ` + tableName + "(" + m.generateSQLFromFields(fields.String()) + `)");`
|
||||
func (m mysqlDriver) GenerateCreateUp(tableName string) string {
|
||||
upsql := `m.SQL("CREATE TABLE ` + tableName + "(" + m.generateSQLFromFields(Fields.String()) + `)");`
|
||||
return upsql
|
||||
}
|
||||
|
||||
func (m mysqlDriver) generateCreateDown(tableName string) string {
|
||||
func (m mysqlDriver) GenerateCreateDown(tableName string) string {
|
||||
downsql := `m.SQL("DROP TABLE ` + "`" + tableName + "`" + `")`
|
||||
return downsql
|
||||
}
|
||||
@ -51,21 +55,21 @@ func (m mysqlDriver) generateSQLFromFields(fields string) string {
|
||||
for i, v := range fds {
|
||||
kv := strings.SplitN(v, ":", 2)
|
||||
if len(kv) != 2 {
|
||||
logger.Error("Fields format is wrong. Should be: key:type,key:type " + v)
|
||||
beeLogger.Log.Error("Fields format is wrong. Should be: key:type,key:type " + v)
|
||||
return ""
|
||||
}
|
||||
typ, tag := m.getSQLType(kv[1])
|
||||
if typ == "" {
|
||||
logger.Error("Fields format is wrong. Should be: key:type,key:type " + v)
|
||||
beeLogger.Log.Error("Fields format is wrong. Should be: key:type,key:type " + v)
|
||||
return ""
|
||||
}
|
||||
if i == 0 && strings.ToLower(kv[0]) != "id" {
|
||||
sql += "`id` int(11) NOT NULL AUTO_INCREMENT,"
|
||||
tags = tags + "PRIMARY KEY (`id`),"
|
||||
}
|
||||
sql += "`" + snakeString(kv[0]) + "` " + typ + ","
|
||||
sql += "`" + utils.SnakeString(kv[0]) + "` " + typ + ","
|
||||
if tag != "" {
|
||||
tags = tags + fmt.Sprintf(tag, "`"+snakeString(kv[0])+"`") + ","
|
||||
tags = tags + fmt.Sprintf(tag, "`"+utils.SnakeString(kv[0])+"`") + ","
|
||||
}
|
||||
}
|
||||
sql = strings.TrimRight(sql+tags, ",")
|
||||
@ -104,12 +108,12 @@ func (m mysqlDriver) getSQLType(ktype string) (tp, tag string) {
|
||||
|
||||
type postgresqlDriver struct{}
|
||||
|
||||
func (m postgresqlDriver) generateCreateUp(tableName string) string {
|
||||
upsql := `m.SQL("CREATE TABLE ` + tableName + "(" + m.generateSQLFromFields(fields.String()) + `)");`
|
||||
func (m postgresqlDriver) GenerateCreateUp(tableName string) string {
|
||||
upsql := `m.SQL("CREATE TABLE ` + tableName + "(" + m.generateSQLFromFields(Fields.String()) + `)");`
|
||||
return upsql
|
||||
}
|
||||
|
||||
func (m postgresqlDriver) generateCreateDown(tableName string) string {
|
||||
func (m postgresqlDriver) GenerateCreateDown(tableName string) string {
|
||||
downsql := `m.SQL("DROP TABLE ` + tableName + `")`
|
||||
return downsql
|
||||
}
|
||||
@ -120,20 +124,20 @@ func (m postgresqlDriver) generateSQLFromFields(fields string) string {
|
||||
for i, v := range fds {
|
||||
kv := strings.SplitN(v, ":", 2)
|
||||
if len(kv) != 2 {
|
||||
logger.Error("Fields format is wrong. Should be: key:type,key:type " + v)
|
||||
beeLogger.Log.Error("Fields format is wrong. Should be: key:type,key:type " + v)
|
||||
return ""
|
||||
}
|
||||
typ, tag := m.getSQLType(kv[1])
|
||||
if typ == "" {
|
||||
logger.Error("Fields format is wrong. Should be: key:type,key:type " + v)
|
||||
beeLogger.Log.Error("Fields format is wrong. Should be: key:type,key:type " + v)
|
||||
return ""
|
||||
}
|
||||
if i == 0 && strings.ToLower(kv[0]) != "id" {
|
||||
sql += "id serial primary key,"
|
||||
}
|
||||
sql += snakeString(kv[0]) + " " + typ + ","
|
||||
sql += utils.SnakeString(kv[0]) + " " + typ + ","
|
||||
if tag != "" {
|
||||
tags = tags + fmt.Sprintf(tag, snakeString(kv[0])) + ","
|
||||
tags = tags + fmt.Sprintf(tag, utils.SnakeString(kv[0])) + ","
|
||||
}
|
||||
}
|
||||
if tags != "" {
|
||||
@ -170,14 +174,14 @@ func (m postgresqlDriver) getSQLType(ktype string) (tp, tag string) {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
func newDBDriver() DBDriver {
|
||||
switch driver {
|
||||
func NewDBDriver() DBDriver {
|
||||
switch SQLDriver {
|
||||
case "mysql":
|
||||
return mysqlDriver{}
|
||||
case "postgres":
|
||||
return postgresqlDriver{}
|
||||
default:
|
||||
logger.Fatal("Driver not supported")
|
||||
beeLogger.Log.Fatal("Driver not supported")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -185,30 +189,30 @@ func newDBDriver() DBDriver {
|
||||
// generateMigration generates migration file template for database schema update.
|
||||
// The generated file template consists of an up() method for updating schema and
|
||||
// a down() method for reverting the update.
|
||||
func generateMigration(mname, upsql, downsql, curpath string) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
func GenerateMigration(mname, upsql, downsql, curpath string) {
|
||||
w := colors.NewColorWriter(os.Stdout)
|
||||
migrationFilePath := path.Join(curpath, DBPath, MPath)
|
||||
if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) {
|
||||
// create migrations directory
|
||||
if err := os.MkdirAll(migrationFilePath, 0777); err != nil {
|
||||
logger.Fatalf("Could not create migration directory: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not create migration directory: %s", err)
|
||||
}
|
||||
}
|
||||
// create file
|
||||
today := time.Now().Format(MDateFormat)
|
||||
fpath := path.Join(migrationFilePath, fmt.Sprintf("%s_%s.go", today, mname))
|
||||
if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer CloseFile(f)
|
||||
content := strings.Replace(MigrationTPL, "{{StructName}}", camelCase(mname)+"_"+today, -1)
|
||||
defer utils.CloseFile(f)
|
||||
content := strings.Replace(MigrationTPL, "{{StructName}}", utils.CamelCase(mname)+"_"+today, -1)
|
||||
content = strings.Replace(content, "{{CurrTime}}", today, -1)
|
||||
content = strings.Replace(content, "{{UpSQL}}", upsql, -1)
|
||||
content = strings.Replace(content, "{{DownSQL}}", downsql, -1)
|
||||
f.WriteString(content)
|
||||
// Run 'gofmt' on the generated source code
|
||||
formatSourceCode(fpath)
|
||||
utils.FormatSourceCode(fpath)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
} else {
|
||||
logger.Fatalf("Could not create migration file: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not create migration file: %s", err)
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package generate
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -20,10 +20,14 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/logger/colors"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
func generateModel(mname, fields, currpath string) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
func GenerateModel(mname, fields, currpath string) {
|
||||
w := colors.NewColorWriter(os.Stdout)
|
||||
|
||||
p, f := path.Split(mname)
|
||||
modelName := strings.Title(f)
|
||||
@ -35,23 +39,23 @@ func generateModel(mname, fields, currpath string) {
|
||||
|
||||
modelStruct, hastime, err := getStruct(modelName, fields)
|
||||
if err != nil {
|
||||
logger.Fatalf("Could not generate the model struct: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not generate the model struct: %s", err)
|
||||
}
|
||||
|
||||
logger.Infof("Using '%s' as model name", modelName)
|
||||
logger.Infof("Using '%s' as package name", packageName)
|
||||
beeLogger.Log.Infof("Using '%s' as model name", modelName)
|
||||
beeLogger.Log.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 {
|
||||
logger.Fatalf("Could not create the model directory: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not create the model directory: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
fpath := path.Join(fp, strings.ToLower(modelName)+".go")
|
||||
if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer CloseFile(f)
|
||||
defer utils.CloseFile(f)
|
||||
content := strings.Replace(modelTpl, "{{packageName}}", packageName, -1)
|
||||
content = strings.Replace(content, "{{modelName}}", modelName, -1)
|
||||
content = strings.Replace(content, "{{modelStruct}}", modelStruct, -1)
|
||||
@ -62,10 +66,10 @@ func generateModel(mname, fields, currpath string) {
|
||||
}
|
||||
f.WriteString(content)
|
||||
// Run 'gofmt' on the generated source code
|
||||
formatSourceCode(fpath)
|
||||
utils.FormatSourceCode(fpath)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
} else {
|
||||
logger.Fatalf("Could not create model file: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not create model file: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,7 +99,7 @@ func getStruct(structname, fields string) (string, bool, error) {
|
||||
if hastimeinner {
|
||||
hastime = true
|
||||
}
|
||||
structStr = structStr + camelString(kv[0]) + " " + typ + " " + tag + "\n"
|
||||
structStr = structStr + utils.CamelString(kv[0]) + " " + typ + " " + tag + "\n"
|
||||
}
|
||||
structStr += "}\n"
|
||||
return structStr, hastime, nil
|
50
generate/g_scaffold.go
Normal file
50
generate/g_scaffold.go
Normal file
@ -0,0 +1,50 @@
|
||||
package generate
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/beego/bee/cmd/commands/migrate"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
func GenerateScaffold(sname, fields, currpath, driver, conn string) {
|
||||
beeLogger.Log.Infof("Do you want to create a '%s' model? [Yes|No] ", sname)
|
||||
|
||||
// Generate the model
|
||||
if utils.AskForConfirmation() {
|
||||
GenerateModel(sname, fields, currpath)
|
||||
}
|
||||
|
||||
// Generate the controller
|
||||
beeLogger.Log.Infof("Do you want to create a '%s' controller? [Yes|No] ", sname)
|
||||
if utils.AskForConfirmation() {
|
||||
GenerateController(sname, currpath)
|
||||
}
|
||||
|
||||
// Generate the views
|
||||
beeLogger.Log.Infof("Do you want to create views for this '%s' resource? [Yes|No] ", sname)
|
||||
if utils.AskForConfirmation() {
|
||||
GenerateView(sname, currpath)
|
||||
}
|
||||
|
||||
// Generate a migration
|
||||
beeLogger.Log.Infof("Do you want to create a '%s' migration and schema for this resource? [Yes|No] ", sname)
|
||||
if utils.AskForConfirmation() {
|
||||
upsql := ""
|
||||
downsql := ""
|
||||
if fields != "" {
|
||||
dbMigrator := NewDBDriver()
|
||||
upsql = dbMigrator.GenerateCreateUp(sname)
|
||||
downsql = dbMigrator.GenerateCreateDown(sname)
|
||||
}
|
||||
GenerateMigration(sname, upsql, downsql, currpath)
|
||||
}
|
||||
|
||||
// Run the migration
|
||||
beeLogger.Log.Infof("Do you want to migrate the database? [Yes|No] ")
|
||||
if utils.AskForConfirmation() {
|
||||
migrate.MigrateUpdate(currpath, driver, conn)
|
||||
}
|
||||
beeLogger.Log.Successf("All done! Don't forget to add beego.Router(\"/%s\" ,&controllers.%sController{}) to routers/route.go\n", sname, strings.Title(sname))
|
||||
}
|
@ -12,60 +12,64 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package generate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/logger/colors"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
// recipe
|
||||
// admin/recipe
|
||||
func generateView(viewpath, currpath string) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
func GenerateView(viewpath, currpath string) {
|
||||
w := colors.NewColorWriter(os.Stdout)
|
||||
|
||||
logger.Info("Generating view...")
|
||||
beeLogger.Log.Info("Generating view...")
|
||||
|
||||
absViewPath := path.Join(currpath, "views", viewpath)
|
||||
err := os.MkdirAll(absViewPath, os.ModePerm)
|
||||
if err != nil {
|
||||
logger.Fatalf("Could not create '%s' view: %s", viewpath, err)
|
||||
beeLogger.Log.Fatalf("Could not create '%s' view: %s", viewpath, err)
|
||||
}
|
||||
|
||||
cfile := path.Join(absViewPath, "index.tpl")
|
||||
if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer CloseFile(f)
|
||||
defer utils.CloseFile(f)
|
||||
f.WriteString(cfile)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
||||
} else {
|
||||
logger.Fatalf("Could not create view file: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not create view file: %s", err)
|
||||
}
|
||||
|
||||
cfile = path.Join(absViewPath, "show.tpl")
|
||||
if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer CloseFile(f)
|
||||
defer utils.CloseFile(f)
|
||||
f.WriteString(cfile)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
||||
} else {
|
||||
logger.Fatalf("Could not create view file: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not create view file: %s", err)
|
||||
}
|
||||
|
||||
cfile = path.Join(absViewPath, "create.tpl")
|
||||
if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer CloseFile(f)
|
||||
defer utils.CloseFile(f)
|
||||
f.WriteString(cfile)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
||||
} else {
|
||||
logger.Fatalf("Could not create view file: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not create view file: %s", err)
|
||||
}
|
||||
|
||||
cfile = path.Join(absViewPath, "edit.tpl")
|
||||
if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer CloseFile(f)
|
||||
defer utils.CloseFile(f)
|
||||
f.WriteString(cfile)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
||||
} else {
|
||||
logger.Fatalf("Could not create view file: %s", err)
|
||||
beeLogger.Log.Fatalf("Could not create view file: %s", err)
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package swaggergen
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@ -35,6 +35,7 @@ import (
|
||||
|
||||
"github.com/astaxie/beego/swagger"
|
||||
"github.com/astaxie/beego/utils"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -74,7 +75,7 @@ var basicTypes = map[string]string{
|
||||
"byte": "string:byte",
|
||||
"rune": "string:byte",
|
||||
// builtin golang objects
|
||||
"time.Time": "string:string",
|
||||
"time.Time": "string:string",
|
||||
}
|
||||
|
||||
var stdlibObject = map[string]string{
|
||||
@ -90,7 +91,7 @@ func init() {
|
||||
astPkgs = map[string]*ast.Package{}
|
||||
}
|
||||
|
||||
func parsePackagesFromDir(dirpath string) {
|
||||
func ParsePackagesFromDir(dirpath string) {
|
||||
c := make(chan error)
|
||||
|
||||
go func() {
|
||||
@ -116,7 +117,7 @@ func parsePackagesFromDir(dirpath string) {
|
||||
}()
|
||||
|
||||
for err := range c {
|
||||
logger.Warnf("%s", err)
|
||||
beeLogger.Log.Warnf("%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,12 +138,12 @@ func parsePackageFromDir(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateDocs(curpath string) {
|
||||
func GenerateDocs(curpath string) {
|
||||
fset := token.NewFileSet()
|
||||
|
||||
f, err := parser.ParseFile(fset, path.Join(curpath, "routers", "router.go"), nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
logger.Fatalf("Error while parsing router.go: %s", err)
|
||||
// beeLogger.Log.Fatalf("Error while parsing router.go: %s", err)
|
||||
}
|
||||
|
||||
rootapi.Infos = swagger.Information{}
|
||||
@ -251,6 +252,9 @@ func generateDocs(curpath string) {
|
||||
}
|
||||
os.Mkdir(path.Join(curpath, "swagger"), 0755)
|
||||
fd, err := os.Create(path.Join(curpath, "swagger", "swagger.json"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fdyml, err := os.Create(path.Join(curpath, "swagger", "swagger.yml"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -348,7 +352,7 @@ func analyseControllerPkg(localName, pkgpath string) {
|
||||
}
|
||||
gopath := os.Getenv("GOPATH")
|
||||
if gopath == "" {
|
||||
logger.Fatal("GOPATH environment variable is not set or empty")
|
||||
// beeLogger.Log.Fatal("GOPATH environment variable is not set or empty")
|
||||
}
|
||||
pkgRealpath := ""
|
||||
|
||||
@ -366,7 +370,7 @@ func analyseControllerPkg(localName, pkgpath string) {
|
||||
}
|
||||
pkgCache[pkgpath] = struct{}{}
|
||||
} else {
|
||||
logger.Fatalf("Package '%s' does not exist in the GOPATH", pkgpath)
|
||||
// beeLogger.Log.Fatalf("Package '%s' does not exist in the GOPATH", pkgpath)
|
||||
}
|
||||
|
||||
fileSet := token.NewFileSet()
|
||||
@ -375,7 +379,7 @@ func analyseControllerPkg(localName, pkgpath string) {
|
||||
return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
|
||||
}, parser.ParseComments)
|
||||
if err != nil {
|
||||
logger.Fatalf("Error while parsing dir at '%s': %s", pkgpath, err)
|
||||
// beeLogger.Log.Fatalf("Error while parsing dir at '%s': %s", pkgpath, err)
|
||||
}
|
||||
for _, pkg := range astPkgs {
|
||||
for _, fl := range pkg.Files {
|
||||
@ -413,7 +417,7 @@ func isSystemPackage(pkgpath string) bool {
|
||||
goroot = runtime.GOROOT()
|
||||
}
|
||||
if goroot == "" {
|
||||
logger.Fatalf("GOROOT environment variable is not set or empty")
|
||||
// beeLogger.Log.Fatalf("GOROOT environment variable is not set or empty")
|
||||
}
|
||||
|
||||
wg, _ := filepath.EvalSymlinks(filepath.Join(goroot, "src", "pkg", pkgpath))
|
||||
@ -423,11 +427,7 @@ func isSystemPackage(pkgpath string) bool {
|
||||
|
||||
//TODO(zh):support go1.4
|
||||
wg, _ = filepath.EvalSymlinks(filepath.Join(goroot, "src", pkgpath))
|
||||
if utils.FileExists(wg) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return utils.FileExists(wg)
|
||||
}
|
||||
|
||||
func peekNextSplitString(ss string) (s string, spacePos int) {
|
||||
@ -481,7 +481,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
||||
ss = strings.TrimSpace(ss[pos:])
|
||||
schemaName, pos := peekNextSplitString(ss)
|
||||
if schemaName == "" {
|
||||
logger.Fatalf("[%s.%s] Schema must follow {object} or {array}", controllerName, funcName)
|
||||
// beeLogger.Log.Fatalf("[%s.%s] Schema must follow {object} or {array}", controllerName, funcName)
|
||||
}
|
||||
if strings.HasPrefix(schemaName, "[]") {
|
||||
schemaName = schemaName[2:]
|
||||
@ -496,7 +496,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
||||
m, mod, realTypes := getModel(schemaName)
|
||||
schema.Ref = "#/definitions/" + m
|
||||
if _, ok := modelsList[pkgpath+controllerName]; !ok {
|
||||
modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema, 0)
|
||||
modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema)
|
||||
}
|
||||
modelsList[pkgpath+controllerName][schemaName] = mod
|
||||
appendModels(pkgpath, controllerName, realTypes)
|
||||
@ -518,7 +518,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
||||
para := swagger.Parameter{}
|
||||
p := getparams(strings.TrimSpace(t[len("@Param "):]))
|
||||
if len(p) < 4 {
|
||||
logger.Fatal(controllerName + "_" + funcName + "'s comments @Param should have at least 4 params")
|
||||
// beeLogger.Log.Fatal(controllerName + "_" + funcName + "'s comments @Param should have at least 4 params")
|
||||
}
|
||||
para.Name = p[0]
|
||||
switch p[1] {
|
||||
@ -533,7 +533,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
||||
case "body":
|
||||
break
|
||||
default:
|
||||
logger.Warnf("[%s.%s] Unknown param location: %s. Possible values are `query`, `header`, `path`, `formData` or `body`.\n", controllerName, funcName, p[1])
|
||||
// beeLogger.Log.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 +544,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
||||
Ref: "#/definitions/" + m,
|
||||
}
|
||||
if _, ok := modelsList[pkgpath+controllerName]; !ok {
|
||||
modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema, 0)
|
||||
modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema)
|
||||
}
|
||||
modelsList[pkgpath+controllerName][typ] = mod
|
||||
appendModels(pkgpath, controllerName, realTypes)
|
||||
@ -564,7 +564,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
||||
paraType = typeFormat[0]
|
||||
paraFormat = typeFormat[1]
|
||||
} else {
|
||||
logger.Warnf("[%s.%s] Unknown param type: %s\n", controllerName, funcName, typ)
|
||||
// beeLogger.Log.Warnf("[%s.%s] Unknown param type: %s\n", controllerName, funcName, typ)
|
||||
}
|
||||
if isArray {
|
||||
para.Type = "array"
|
||||
@ -717,7 +717,7 @@ func getModel(str string) (objectname string, m swagger.Schema, realTypes []stri
|
||||
}
|
||||
}
|
||||
if m.Title == "" {
|
||||
logger.Warnf("Cannot find the object: %s", str)
|
||||
// beeLogger.Log.Warnf("Cannot find the object: %s", str)
|
||||
// TODO remove when all type have been supported
|
||||
//os.Exit(1)
|
||||
}
|
||||
@ -732,7 +732,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 {
|
||||
logger.Fatalf("Unknown type without TypeSec: %v\n", d)
|
||||
// beeLogger.Log.Fatalf("Unknown type without TypeSec: %v\n", d)
|
||||
}
|
||||
// TODO support other types, such as `ArrayType`, `MapType`, `InterfaceType` etc...
|
||||
st, ok := ts.Type.(*ast.StructType)
|
||||
@ -808,7 +808,7 @@ func parseObject(d *ast.Object, k string, m *swagger.Schema, realTypes *[]string
|
||||
mp.Default = str2RealType(res[1], realType)
|
||||
|
||||
} else {
|
||||
logger.Warnf("Invalid default value: %s", defaultValue)
|
||||
// beeLogger.Log.Warnf("Invalid default value: %s", defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
@ -899,16 +899,6 @@ func isBasicType(Type string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// regexp get json tag
|
||||
func grepJSONTag(tag string) string {
|
||||
r, _ := regexp.Compile(`json:"([^"]*)"`)
|
||||
matches := r.FindAllStringSubmatch(tag, -1)
|
||||
if len(matches) > 0 {
|
||||
return matches[0][1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// append models
|
||||
func appendModels(pkgpath, controllerName string, realTypes []string) {
|
||||
for _, realType := range realTypes {
|
||||
@ -956,7 +946,7 @@ func str2RealType(s string, typ string) interface{} {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logger.Warnf("Invalid default value type '%s': %s", typ, s)
|
||||
// beeLogger.Log.Warnf("Invalid default value type '%s': %s", typ, s)
|
||||
return s
|
||||
}
|
||||
|
369
hproseapp.go
369
hproseapp.go
@ -1,369 +0,0 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
path "path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var cmdHproseapp = &Command{
|
||||
// CustomFlags: true,
|
||||
UsageLine: "hprose [appname]",
|
||||
Short: "Creates an RPC application based on Hprose and Beego frameworks",
|
||||
Long: `
|
||||
The command 'hprose' creates an RPC application based on both Beego and Hprose (http://hprose.com/).
|
||||
|
||||
{{"To scaffold out your application, use:"|bold}}
|
||||
|
||||
$ bee hprose [appname] [-tables=""] [-driver=mysql] [-conn=root:@tcp(127.0.0.1:3306)/test]
|
||||
|
||||
If 'conn' is empty, the command will generate a sample application. Otherwise the command
|
||||
will connect to your database and generate models based on the existing tables.
|
||||
|
||||
The command 'hprose' creates a folder named [appname] with the following structure:
|
||||
|
||||
├── main.go
|
||||
├── {{"conf"|foldername}}
|
||||
│ └── app.conf
|
||||
└── {{"models"|foldername}}
|
||||
└── object.go
|
||||
└── user.go
|
||||
`,
|
||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
||||
Run: createhprose,
|
||||
}
|
||||
|
||||
var hproseconf = `appname = {{.Appname}}
|
||||
httpport = 8080
|
||||
runmode = dev
|
||||
autorender = false
|
||||
copyrequestbody = true
|
||||
EnableDocs = true
|
||||
`
|
||||
var hproseMaingo = `package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"{{.Appname}}/models"
|
||||
"github.com/hprose/hprose-golang/rpc"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
func logInvokeHandler(
|
||||
name string,
|
||||
args []reflect.Value,
|
||||
context rpc.Context,
|
||||
next rpc.NextInvokeHandler) (results []reflect.Value, err error) {
|
||||
fmt.Printf("%s(%v) = ", name, args)
|
||||
results, err = next(name, args, context)
|
||||
fmt.Printf("%v %v\r\n", results, err)
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Create WebSocketServer
|
||||
// service := rpc.NewWebSocketService()
|
||||
|
||||
// Create Http Server
|
||||
service := rpc.NewHTTPService()
|
||||
|
||||
// Use Logger Middleware
|
||||
service.AddInvokeHandler(logInvokeHandler)
|
||||
|
||||
// Publish Functions
|
||||
service.AddFunction("AddOne", models.AddOne)
|
||||
service.AddFunction("GetOne", models.GetOne)
|
||||
|
||||
// Start Service
|
||||
beego.Handler("/", service)
|
||||
beego.Run()
|
||||
}
|
||||
`
|
||||
|
||||
var hproseMainconngo = `package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"{{.Appname}}/models"
|
||||
"github.com/hprose/hprose-golang/rpc"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/orm"
|
||||
{{.DriverPkg}}
|
||||
)
|
||||
|
||||
func init() {
|
||||
orm.RegisterDataBase("default", "{{.DriverName}}", "{{.conn}}")
|
||||
}
|
||||
|
||||
func logInvokeHandler(
|
||||
name string,
|
||||
args []reflect.Value,
|
||||
context rpc.Context,
|
||||
next rpc.NextInvokeHandler) (results []reflect.Value, err error) {
|
||||
fmt.Printf("%s(%v) = ", name, args)
|
||||
results, err = next(name, args, context)
|
||||
fmt.Printf("%v %v\r\n", results, err)
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Create WebSocketServer
|
||||
// service := rpc.NewWebSocketService()
|
||||
|
||||
// Create Http Server
|
||||
service := rpc.NewHTTPService()
|
||||
|
||||
// Use Logger Middleware
|
||||
service.AddInvokeHandler(logInvokeHandler)
|
||||
|
||||
{{HproseFunctionList}}
|
||||
|
||||
// Start Service
|
||||
beego.Handler("/", service)
|
||||
beego.Run()
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
var hproseModels = `package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
Objects map[string]*Object
|
||||
)
|
||||
|
||||
type Object struct {
|
||||
ObjectId string
|
||||
Score int64
|
||||
PlayerName string
|
||||
}
|
||||
|
||||
func init() {
|
||||
Objects = make(map[string]*Object)
|
||||
Objects["hjkhsbnmn123"] = &Object{"hjkhsbnmn123", 100, "astaxie"}
|
||||
Objects["mjjkxsxsaa23"] = &Object{"mjjkxsxsaa23", 101, "someone"}
|
||||
}
|
||||
|
||||
func AddOne(object Object) (ObjectId string) {
|
||||
object.ObjectId = "astaxie" + strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||
Objects[object.ObjectId] = &object
|
||||
return object.ObjectId
|
||||
}
|
||||
|
||||
func GetOne(ObjectId string) (object *Object, err error) {
|
||||
if v, ok := Objects[ObjectId]; ok {
|
||||
return v, nil
|
||||
}
|
||||
return nil, errors.New("ObjectId Not Exist")
|
||||
}
|
||||
|
||||
func GetAll() map[string]*Object {
|
||||
return Objects
|
||||
}
|
||||
|
||||
func Update(ObjectId string, Score int64) (err error) {
|
||||
if v, ok := Objects[ObjectId]; ok {
|
||||
v.Score = Score
|
||||
return nil
|
||||
}
|
||||
return errors.New("ObjectId Not Exist")
|
||||
}
|
||||
|
||||
func Delete(ObjectId string) {
|
||||
delete(Objects, ObjectId)
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
var hproseModels2 = `package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
UserList map[string]*User
|
||||
)
|
||||
|
||||
func init() {
|
||||
UserList = make(map[string]*User)
|
||||
u := User{"user_11111", "astaxie", "11111", Profile{"male", 20, "Singapore", "astaxie@gmail.com"}}
|
||||
UserList["user_11111"] = &u
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Id string
|
||||
Username string
|
||||
Password string
|
||||
Profile Profile
|
||||
}
|
||||
|
||||
type Profile struct {
|
||||
Gender string
|
||||
Age int
|
||||
Address string
|
||||
Email string
|
||||
}
|
||||
|
||||
func AddUser(u User) string {
|
||||
u.Id = "user_" + strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||
UserList[u.Id] = &u
|
||||
return u.Id
|
||||
}
|
||||
|
||||
func GetUser(uid string) (u *User, err error) {
|
||||
if u, ok := UserList[uid]; ok {
|
||||
return u, nil
|
||||
}
|
||||
return nil, errors.New("User not exists")
|
||||
}
|
||||
|
||||
func GetAllUsers() map[string]*User {
|
||||
return UserList
|
||||
}
|
||||
|
||||
func UpdateUser(uid string, uu *User) (a *User, err error) {
|
||||
if u, ok := UserList[uid]; ok {
|
||||
if uu.Username != "" {
|
||||
u.Username = uu.Username
|
||||
}
|
||||
if uu.Password != "" {
|
||||
u.Password = uu.Password
|
||||
}
|
||||
if uu.Profile.Age != 0 {
|
||||
u.Profile.Age = uu.Profile.Age
|
||||
}
|
||||
if uu.Profile.Address != "" {
|
||||
u.Profile.Address = uu.Profile.Address
|
||||
}
|
||||
if uu.Profile.Gender != "" {
|
||||
u.Profile.Gender = uu.Profile.Gender
|
||||
}
|
||||
if uu.Profile.Email != "" {
|
||||
u.Profile.Email = uu.Profile.Email
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
return nil, errors.New("User Not Exist")
|
||||
}
|
||||
|
||||
func Login(username, password string) bool {
|
||||
for _, u := range UserList {
|
||||
if u.Username == username && u.Password == password {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func DeleteUser(uid string) {
|
||||
delete(UserList, uid)
|
||||
}
|
||||
`
|
||||
|
||||
var hproseAddFunctions = []string{}
|
||||
|
||||
func init() {
|
||||
cmdHproseapp.Flag.Var(&tables, "tables", "List of table names separated by a comma.")
|
||||
cmdHproseapp.Flag.Var(&driver, "driver", "Database driver. Either mysql, postgres or sqlite.")
|
||||
cmdHproseapp.Flag.Var(&conn, "conn", "Connection string used by the driver to connect to a database instance.")
|
||||
}
|
||||
|
||||
func createhprose(cmd *Command, args []string) int {
|
||||
output := cmd.Out()
|
||||
|
||||
if len(args) != 1 {
|
||||
logger.Fatal("Argument [appname] is missing")
|
||||
}
|
||||
|
||||
curpath, _ := os.Getwd()
|
||||
if len(args) > 1 {
|
||||
cmd.Flag.Parse(args[1:])
|
||||
}
|
||||
apppath, packpath, err := checkEnv(args[0])
|
||||
if err != nil {
|
||||
logger.Fatalf("%s", err)
|
||||
}
|
||||
if driver == "" {
|
||||
driver = "mysql"
|
||||
}
|
||||
if conn == "" {
|
||||
}
|
||||
|
||||
logger.Info("Creating Hprose application...")
|
||||
|
||||
os.MkdirAll(apppath, 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "conf"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf"), "\x1b[0m")
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "conf", "app.conf"),
|
||||
strings.Replace(hproseconf, "{{.Appname}}", args[0], -1))
|
||||
|
||||
if conn != "" {
|
||||
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(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
maingoContent := strings.Replace(hproseMainconngo, "{{.Appname}}", packpath, -1)
|
||||
maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(driver), -1)
|
||||
maingoContent = strings.Replace(maingoContent, "{{HproseFunctionList}}", strings.Join(hproseAddFunctions, ""), -1)
|
||||
if driver == "mysql" {
|
||||
maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/go-sql-driver/mysql"`, -1)
|
||||
} else if driver == "postgres" {
|
||||
maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/lib/pq"`, -1)
|
||||
}
|
||||
WriteToFile(path.Join(apppath, "main.go"),
|
||||
strings.Replace(
|
||||
maingoContent,
|
||||
"{{.conn}}",
|
||||
conn.String(),
|
||||
-1,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
os.Mkdir(path.Join(apppath, "models"), 0755)
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models"), "\x1b[0m")
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "object.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "models", "object.go"), apiModels)
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "user.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "models", "user.go"), apiModels2)
|
||||
|
||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "main.go"),
|
||||
strings.Replace(hproseMaingo, "{{.Appname}}", packpath, -1))
|
||||
}
|
||||
logger.Success("New Hprose application successfully created!")
|
||||
return 0
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package colors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -53,7 +53,7 @@ func NewModeColorWriter(w io.Writer, mode outputMode) io.Writer {
|
||||
return w
|
||||
}
|
||||
|
||||
func bold(message string) string {
|
||||
func Bold(message string) string {
|
||||
return fmt.Sprintf("\x1b[1m%s\x1b[21m", message)
|
||||
}
|
||||
|
||||
@ -102,47 +102,47 @@ func Magenta(message string) string {
|
||||
return fmt.Sprintf("\x1b[35m%s\x1b[0m", message)
|
||||
}
|
||||
|
||||
// BlackBold returns a black bold string
|
||||
// BlackBold returns a black Bold string
|
||||
func BlackBold(message string) string {
|
||||
return fmt.Sprintf("\x1b[30m%s\x1b[0m", bold(message))
|
||||
return fmt.Sprintf("\x1b[30m%s\x1b[0m", Bold(message))
|
||||
}
|
||||
|
||||
// WhiteBold returns a white bold string
|
||||
// WhiteBold returns a white Bold string
|
||||
func WhiteBold(message string) string {
|
||||
return fmt.Sprintf("\x1b[37m%s\x1b[0m", bold(message))
|
||||
return fmt.Sprintf("\x1b[37m%s\x1b[0m", Bold(message))
|
||||
}
|
||||
|
||||
// CyanBold returns a cyan bold string
|
||||
// CyanBold returns a cyan Bold string
|
||||
func CyanBold(message string) string {
|
||||
return fmt.Sprintf("\x1b[36m%s\x1b[0m", bold(message))
|
||||
return fmt.Sprintf("\x1b[36m%s\x1b[0m", Bold(message))
|
||||
}
|
||||
|
||||
// BlueBold returns a blue bold string
|
||||
// BlueBold returns a blue Bold string
|
||||
func BlueBold(message string) string {
|
||||
return fmt.Sprintf("\x1b[34m%s\x1b[0m", bold(message))
|
||||
return fmt.Sprintf("\x1b[34m%s\x1b[0m", Bold(message))
|
||||
}
|
||||
|
||||
// RedBold returns a red bold string
|
||||
// RedBold returns a red Bold string
|
||||
func RedBold(message string) string {
|
||||
return fmt.Sprintf("\x1b[31m%s\x1b[0m", bold(message))
|
||||
return fmt.Sprintf("\x1b[31m%s\x1b[0m", Bold(message))
|
||||
}
|
||||
|
||||
// GreenBold returns a green bold string
|
||||
// GreenBold returns a green Bold string
|
||||
func GreenBold(message string) string {
|
||||
return fmt.Sprintf("\x1b[32m%s\x1b[0m", bold(message))
|
||||
return fmt.Sprintf("\x1b[32m%s\x1b[0m", Bold(message))
|
||||
}
|
||||
|
||||
// YellowBold returns a yellow bold string
|
||||
// YellowBold returns a yellow Bold string
|
||||
func YellowBold(message string) string {
|
||||
return fmt.Sprintf("\x1b[33m%s\x1b[0m", bold(message))
|
||||
return fmt.Sprintf("\x1b[33m%s\x1b[0m", Bold(message))
|
||||
}
|
||||
|
||||
// GrayBold returns a gray bold string
|
||||
// GrayBold returns a gray Bold string
|
||||
func GrayBold(message string) string {
|
||||
return fmt.Sprintf("\x1b[37m%s\x1b[0m", bold(message))
|
||||
return fmt.Sprintf("\x1b[37m%s\x1b[0m", Bold(message))
|
||||
}
|
||||
|
||||
// MagentaBold returns a magenta bold string
|
||||
// MagentaBold returns a magenta Bold string
|
||||
func MagentaBold(message string) string {
|
||||
return fmt.Sprintf("\x1b[35m%s\x1b[0m", bold(message))
|
||||
return fmt.Sprintf("\x1b[35m%s\x1b[0m", Bold(message))
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
|
||||
// +build !windows
|
||||
|
||||
package main
|
||||
package colors
|
||||
|
||||
import "io"
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
package colors
|
||||
|
||||
import (
|
||||
"bytes"
|
@ -11,7 +11,7 @@
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package main
|
||||
package beeLogger
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -22,6 +22,9 @@ import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/beego/bee/logger/colors"
|
||||
)
|
||||
|
||||
var errInvalidLogLevel = errors.New("logger: invalid log level")
|
||||
@ -59,6 +62,8 @@ type LogRecord struct {
|
||||
LineNo int
|
||||
}
|
||||
|
||||
var Log = GetBeeLogger(os.Stdout)
|
||||
|
||||
var (
|
||||
logRecordTemplate *template.Template
|
||||
debugLogRecordTemplate *template.Template
|
||||
@ -80,11 +85,15 @@ func GetBeeLogger(w io.Writer) *BeeLogger {
|
||||
"EndLine": EndLine,
|
||||
}
|
||||
logRecordTemplate, err = template.New("simpleLogFormat").Funcs(funcs).Parse(simpleLogFormat)
|
||||
MustCheck(err)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
debugLogRecordTemplate, err = template.New("debugLogFormat").Funcs(funcs).Parse(debugLogFormat)
|
||||
MustCheck(err)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
instance = &BeeLogger{output: NewColorWriter(w)}
|
||||
instance = &BeeLogger{output: colors.NewColorWriter(w)}
|
||||
})
|
||||
return instance
|
||||
}
|
||||
@ -93,7 +102,17 @@ func GetBeeLogger(w io.Writer) *BeeLogger {
|
||||
func (l *BeeLogger) SetOutput(w io.Writer) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
l.output = NewColorWriter(w)
|
||||
l.output = colors.NewColorWriter(w)
|
||||
}
|
||||
|
||||
// Now returns the current local time in the specified layout
|
||||
func Now(layout string) string {
|
||||
return time.Now().Format(layout)
|
||||
}
|
||||
|
||||
// EndLine returns the a newline escape character
|
||||
func EndLine() string {
|
||||
return "\n"
|
||||
}
|
||||
|
||||
func (l *BeeLogger) getLevelTag(level int) string {
|
||||
@ -122,21 +141,21 @@ func (l *BeeLogger) getLevelTag(level int) string {
|
||||
func (l *BeeLogger) getColorLevel(level int) string {
|
||||
switch level {
|
||||
case levelCritical:
|
||||
return RedBold(l.getLevelTag(level))
|
||||
return colors.RedBold(l.getLevelTag(level))
|
||||
case levelFatal:
|
||||
return RedBold(l.getLevelTag(level))
|
||||
return colors.RedBold(l.getLevelTag(level))
|
||||
case levelInfo:
|
||||
return BlueBold(l.getLevelTag(level))
|
||||
return colors.BlueBold(l.getLevelTag(level))
|
||||
case levelHint:
|
||||
return CyanBold(l.getLevelTag(level))
|
||||
return colors.CyanBold(l.getLevelTag(level))
|
||||
case levelDebug:
|
||||
return YellowBold(l.getLevelTag(level))
|
||||
return colors.YellowBold(l.getLevelTag(level))
|
||||
case levelError:
|
||||
return RedBold(l.getLevelTag(level))
|
||||
return colors.RedBold(l.getLevelTag(level))
|
||||
case levelWarn:
|
||||
return YellowBold(l.getLevelTag(level))
|
||||
return colors.YellowBold(l.getLevelTag(level))
|
||||
case levelSuccess:
|
||||
return GreenBold(l.getLevelTag(level))
|
||||
return colors.GreenBold(l.getLevelTag(level))
|
||||
default:
|
||||
panic(errInvalidLogLevel)
|
||||
}
|
||||
@ -157,15 +176,17 @@ func (l *BeeLogger) mustLog(level int, message string, args ...interface{}) {
|
||||
}
|
||||
|
||||
err := logRecordTemplate.Execute(l.output, record)
|
||||
MustCheck(err)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// mustLogDebug logs a debug message only if debug mode
|
||||
// is enabled. i.e. DEBUG_ENABLED="1"
|
||||
func (l *BeeLogger) mustLogDebug(message string, file string, line int, args ...interface{}) {
|
||||
if !IsDebugEnabled() {
|
||||
return
|
||||
}
|
||||
//if !IsDebugEnabled() {
|
||||
// return
|
||||
//}
|
||||
|
||||
// Change the output to Stderr
|
||||
l.SetOutput(os.Stderr)
|
||||
@ -179,7 +200,9 @@ func (l *BeeLogger) mustLogDebug(message string, file string, line int, args ...
|
||||
Filename: filepath.Base(file),
|
||||
}
|
||||
err := debugLogRecordTemplate.Execute(l.output, record)
|
||||
MustCheck(err)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Debug outputs a debug log message
|
59
main.go
Normal file
59
main.go
Normal file
@ -0,0 +1,59 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/bee/cmd"
|
||||
"github.com/beego/bee/cmd/commands"
|
||||
"github.com/beego/bee/generate/swaggergen"
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
func main() {
|
||||
currentpath, _ := os.Getwd()
|
||||
|
||||
flag.Usage = cmd.Usage
|
||||
flag.Parse()
|
||||
log.SetFlags(0)
|
||||
|
||||
args := flag.Args()
|
||||
|
||||
if len(args) < 1 {
|
||||
cmd.Usage()
|
||||
}
|
||||
|
||||
if args[0] == "help" {
|
||||
cmd.Help(args[1:])
|
||||
return
|
||||
}
|
||||
|
||||
for _, c := range commands.AvailableCommands {
|
||||
if c.Name() == args[0] && c.Run != nil {
|
||||
c.Flag.Usage = func() { c.Usage() }
|
||||
if c.CustomFlags {
|
||||
args = args[1:]
|
||||
} else {
|
||||
c.Flag.Parse(args[1:])
|
||||
args = c.Flag.Args()
|
||||
}
|
||||
|
||||
if c.PreRun != nil {
|
||||
c.PreRun(c, args)
|
||||
}
|
||||
|
||||
// Check if current directory is inside the GOPATH,
|
||||
// if so parse the packages inside it.
|
||||
if strings.Contains(currentpath, utils.GetGOPATHs()[0]+"/src") && cmd.IfGenerateDocs(c.Name(), args) {
|
||||
swaggergen.ParsePackagesFromDir(currentpath)
|
||||
}
|
||||
|
||||
os.Exit(c.Run(c, args))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
utils.PrintErrorAndExit("Unknown subcommand", cmd.ErrorTemplate)
|
||||
}
|
155
rundocs.go
155
rundocs.go
@ -1,155 +0,0 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var cmdRundocs = &Command{
|
||||
UsageLine: "rundocs [-isDownload=true] [-docport=8888]",
|
||||
Short: "rundocs will run the docs server,default is 8089",
|
||||
Long: `
|
||||
-d meaning will download the docs file from github
|
||||
-p meaning server the Server on which port, default is 8089
|
||||
|
||||
`,
|
||||
}
|
||||
|
||||
var (
|
||||
swaggerVersion = "2"
|
||||
swaggerlink = "https://github.com/beego/swagger/archive/v" + swaggerVersion + ".zip"
|
||||
)
|
||||
|
||||
type docValue string
|
||||
|
||||
func (d *docValue) String() string {
|
||||
return fmt.Sprint(*d)
|
||||
}
|
||||
|
||||
func (d *docValue) Set(value string) error {
|
||||
*d = docValue(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
var isDownload docValue
|
||||
var docport docValue
|
||||
|
||||
func init() {
|
||||
cmdRundocs.Run = runDocs
|
||||
cmdRundocs.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() }
|
||||
cmdRundocs.Flag.Var(&isDownload, "isDownload", "weather download the Swagger Docs")
|
||||
cmdRundocs.Flag.Var(&docport, "docport", "doc server port")
|
||||
}
|
||||
|
||||
func runDocs(cmd *Command, args []string) int {
|
||||
if isDownload == "true" {
|
||||
downloadFromURL(swaggerlink, "swagger.zip")
|
||||
err := unzipAndDelete("swagger.zip")
|
||||
if err != nil {
|
||||
logger.Errorf("Error while unzipping 'swagger.zip' file: %s", err)
|
||||
}
|
||||
}
|
||||
if docport == "" {
|
||||
docport = "8089"
|
||||
}
|
||||
if _, err := os.Stat("swagger"); err != nil && os.IsNotExist(err) {
|
||||
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)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func downloadFromURL(url, fileName string) {
|
||||
var down bool
|
||||
if fd, err := os.Stat(fileName); err != nil && os.IsNotExist(err) {
|
||||
down = true
|
||||
} else if fd.Size() == int64(0) {
|
||||
down = true
|
||||
} else {
|
||||
logger.Infof("'%s' already exists", fileName)
|
||||
return
|
||||
}
|
||||
if down {
|
||||
logger.Infof("Downloading '%s' to '%s'...", url, fileName)
|
||||
output, err := os.Create(fileName)
|
||||
if err != nil {
|
||||
logger.Errorf("Error while creating '%s': %s", fileName, err)
|
||||
return
|
||||
}
|
||||
defer output.Close()
|
||||
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
logger.Errorf("Error while downloading '%s': %s", url, err)
|
||||
return
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
n, err := io.Copy(output, response.Body)
|
||||
if err != nil {
|
||||
logger.Errorf("Error while downloading '%s': %s", url, err)
|
||||
return
|
||||
}
|
||||
logger.Successf("%d bytes downloaded!", n)
|
||||
}
|
||||
}
|
||||
|
||||
func unzipAndDelete(src string) error {
|
||||
logger.Infof("Unzipping '%s'...", src)
|
||||
r, err := zip.OpenReader(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
rp := strings.NewReplacer("swagger-"+swaggerVersion, "swagger")
|
||||
for _, f := range r.File {
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
fname := rp.Replace(f.Name)
|
||||
if f.FileInfo().IsDir() {
|
||||
os.MkdirAll(fname, f.Mode())
|
||||
} else {
|
||||
f, err := os.OpenFile(
|
||||
fname, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
_, err = io.Copy(f, rc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.Successf("Done! Deleting '%s'...", src)
|
||||
return os.RemoveAll(src)
|
||||
}
|
102
test.go
102
test.go
@ -1,102 +0,0 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
path "path/filepath"
|
||||
"time"
|
||||
|
||||
_ "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var cmdTest = &Command{
|
||||
UsageLine: "test [appname]",
|
||||
Short: "test the app",
|
||||
Long: ``,
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdTest.Run = testApp
|
||||
cmdTest.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() }
|
||||
}
|
||||
|
||||
func safePathAppend(arr []string, paths ...string) []string {
|
||||
for _, path := range paths {
|
||||
if pathExists(path) {
|
||||
arr = append(arr, path)
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
func pathExists(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
||||
|
||||
var started = make(chan bool)
|
||||
|
||||
func testApp(cmd *Command, args []string) int {
|
||||
if len(args) != 1 {
|
||||
logger.Fatalf("Failed to start: %s", "argument 'appname' is missing")
|
||||
}
|
||||
|
||||
currpath, _ := os.Getwd()
|
||||
|
||||
logger.Debugf("Current path: %s", __FILE__(), __LINE__(), currpath)
|
||||
|
||||
err := loadConfig()
|
||||
if err != nil {
|
||||
logger.Fatalf("Failed to load configuration: %s", err)
|
||||
}
|
||||
var paths []string
|
||||
readAppDirectories(currpath, &paths)
|
||||
|
||||
NewWatcher(paths, nil, false)
|
||||
appname = args[0]
|
||||
for {
|
||||
select {
|
||||
case <-started:
|
||||
runTest()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func runTest() {
|
||||
logger.Info("Start testing...")
|
||||
time.Sleep(time.Second * 1)
|
||||
crupwd, _ := os.Getwd()
|
||||
testDir := path.Join(crupwd, "tests")
|
||||
if pathExists(testDir) {
|
||||
os.Chdir(testDir)
|
||||
}
|
||||
|
||||
var err error
|
||||
icmd := exec.Command("go", "test")
|
||||
icmd.Stdout = os.Stdout
|
||||
icmd.Stderr = os.Stderr
|
||||
logger.Info("============== Test Begin ===================")
|
||||
err = icmd.Run()
|
||||
logger.Info("============== Test End =====================")
|
||||
|
||||
if err != nil {
|
||||
logger.Error("============== Test failed ===================")
|
||||
logger.Errorf("Cause: %s", err)
|
||||
return
|
||||
}
|
||||
logger.Success("Test Completed")
|
||||
}
|
28
testdata/router/router.go
vendored
28
testdata/router/router.go
vendored
@ -1,28 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
type Router struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
func (r *Router) Get() {
|
||||
|
||||
}
|
||||
|
||||
func (r *Router) Post() {
|
||||
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
}
|
||||
|
||||
func (c *Controller) Put() {
|
||||
|
||||
}
|
||||
|
||||
func (c *Controller) Delete() {
|
||||
|
||||
}
|
14
utils/doc_value.go
Normal file
14
utils/doc_value.go
Normal file
@ -0,0 +1,14 @@
|
||||
package utils
|
||||
|
||||
import "fmt"
|
||||
|
||||
type DocValue string
|
||||
|
||||
func (d *DocValue) String() string {
|
||||
return fmt.Sprint(*d)
|
||||
}
|
||||
|
||||
func (d *DocValue) Set(value string) error {
|
||||
*d = DocValue(value)
|
||||
return nil
|
||||
}
|
14
utils/list_opts.go
Normal file
14
utils/list_opts.go
Normal file
@ -0,0 +1,14 @@
|
||||
package utils
|
||||
|
||||
import "fmt"
|
||||
|
||||
type ListOpts []string
|
||||
|
||||
func (opts *ListOpts) String() string {
|
||||
return fmt.Sprint(*opts)
|
||||
}
|
||||
|
||||
func (opts *ListOpts) Set(value string) error {
|
||||
*opts = append(*opts, value)
|
||||
return nil
|
||||
}
|
15
utils/str_flag.go
Normal file
15
utils/str_flag.go
Normal file
@ -0,0 +1,15 @@
|
||||
package utils
|
||||
|
||||
import "fmt"
|
||||
|
||||
// The string flag list, implemented flag.Value interface
|
||||
type StrFlags []string
|
||||
|
||||
func (s *StrFlags) String() string {
|
||||
return fmt.Sprintf("%s", *s)
|
||||
}
|
||||
|
||||
func (s *StrFlags) Set(value string) error {
|
||||
*s = append(*s, value)
|
||||
return nil
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -26,7 +26,9 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/logger/colors"
|
||||
)
|
||||
|
||||
// Go is a basic promise implementation: it wraps calls a function in a goroutine
|
||||
@ -39,18 +41,8 @@ func Go(f func() error) chan error {
|
||||
return ch
|
||||
}
|
||||
|
||||
// Now returns the current local time in the specified layout
|
||||
func Now(layout string) string {
|
||||
return time.Now().Format(layout)
|
||||
}
|
||||
|
||||
// EndLine returns the a newline escape character
|
||||
func EndLine() string {
|
||||
return "\n"
|
||||
}
|
||||
|
||||
// IsExist returns whether a file or directory exists.
|
||||
func isExist(path string) bool {
|
||||
func IsExist(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
||||
@ -99,7 +91,7 @@ func IsBeegoProject(thePath string) bool {
|
||||
}()
|
||||
|
||||
if err := <-c; err != nil {
|
||||
logger.Fatalf("Unable to walk '%s' tree: %s", thePath, err)
|
||||
beeLogger.Log.Fatalf("Unable to walk '%s' tree: %s", thePath, err)
|
||||
}
|
||||
|
||||
if len(mainFiles) > 0 {
|
||||
@ -113,7 +105,7 @@ func IsBeegoProject(thePath string) bool {
|
||||
func SearchGOPATHs(app string) (bool, string, string) {
|
||||
gps := GetGOPATHs()
|
||||
if len(gps) == 0 {
|
||||
logger.Fatal("GOPATH environment variable is not set or empty")
|
||||
beeLogger.Log.Fatal("GOPATH environment variable is not set or empty")
|
||||
}
|
||||
|
||||
// Lookup the application inside the user workspace(s)
|
||||
@ -127,7 +119,7 @@ func SearchGOPATHs(app string) (bool, string, string) {
|
||||
currentPath = app
|
||||
}
|
||||
|
||||
if isExist(currentPath) {
|
||||
if IsExist(currentPath) {
|
||||
return true, gopath, currentPath
|
||||
}
|
||||
}
|
||||
@ -139,11 +131,11 @@ func SearchGOPATHs(app string) (bool, string, string) {
|
||||
// confirmations. If the input is not recognized, it will ask again. The function does not return
|
||||
// until it gets a valid response from the user. Typically, you should use fmt to print out a question
|
||||
// before calling askForConfirmation. E.g. fmt.Println("WARNING: Are you sure? (yes/no)")
|
||||
func askForConfirmation() bool {
|
||||
func AskForConfirmation() bool {
|
||||
var response string
|
||||
_, err := fmt.Scanln(&response)
|
||||
if err != nil {
|
||||
logger.Fatalf("%s", err)
|
||||
beeLogger.Log.Fatalf("%s", err)
|
||||
}
|
||||
okayResponses := []string{"y", "Y", "yes", "Yes", "YES"}
|
||||
nokayResponses := []string{"n", "N", "no", "No", "NO"}
|
||||
@ -153,7 +145,7 @@ func askForConfirmation() bool {
|
||||
return false
|
||||
} else {
|
||||
fmt.Println("Please type yes or no and then press enter:")
|
||||
return askForConfirmation()
|
||||
return AskForConfirmation()
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,7 +159,7 @@ func containsString(slice []string, element string) bool {
|
||||
}
|
||||
|
||||
// snake string, XxYy to xx_yy
|
||||
func snakeString(s string) string {
|
||||
func SnakeString(s string) string {
|
||||
data := make([]byte, 0, len(s)*2)
|
||||
j := false
|
||||
num := len(s)
|
||||
@ -184,17 +176,17 @@ func snakeString(s string) string {
|
||||
return strings.ToLower(string(data[:]))
|
||||
}
|
||||
|
||||
func camelString(s string) string {
|
||||
func CamelString(s string) string {
|
||||
data := make([]byte, 0, len(s))
|
||||
j := false
|
||||
k := false
|
||||
num := len(s) - 1
|
||||
for i := 0; i <= num; i++ {
|
||||
d := s[i]
|
||||
if k == false && d >= 'A' && d <= 'Z' {
|
||||
if !k && d >= 'A' && d <= 'Z' {
|
||||
k = true
|
||||
}
|
||||
if d >= 'a' && d <= 'z' && (j || k == false) {
|
||||
if d >= 'a' && d <= 'z' && (j || !k) {
|
||||
d = d - 32
|
||||
j = false
|
||||
k = true
|
||||
@ -210,7 +202,7 @@ func camelString(s string) string {
|
||||
|
||||
// camelCase converts a _ delimited string to camel case
|
||||
// e.g. very_important_person => VeryImportantPerson
|
||||
func camelCase(in string) string {
|
||||
func CamelCase(in string) string {
|
||||
tokens := strings.Split(in, "_")
|
||||
for i := range tokens {
|
||||
tokens[i] = strings.Title(strings.Trim(tokens[i], " "))
|
||||
@ -219,25 +211,13 @@ func camelCase(in string) string {
|
||||
}
|
||||
|
||||
// formatSourceCode formats source files
|
||||
func formatSourceCode(filename string) {
|
||||
func FormatSourceCode(filename string) {
|
||||
cmd := exec.Command("gofmt", "-w", filename)
|
||||
if err := cmd.Run(); err != nil {
|
||||
logger.Warnf("Error while running gofmt: %s", err)
|
||||
beeLogger.Log.Warnf("Error while running gofmt: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// The string flag list, implemented flag.Value interface
|
||||
type strFlags []string
|
||||
|
||||
func (s *strFlags) String() string {
|
||||
return fmt.Sprintf("%s", *s)
|
||||
}
|
||||
|
||||
func (s *strFlags) Set(value string) error {
|
||||
*s = append(*s, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CloseFile attempts to close the passed file
|
||||
// or panics with the actual error
|
||||
func CloseFile(f *os.File) {
|
||||
@ -252,11 +232,6 @@ func MustCheck(err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func exitPrint(con string) {
|
||||
fmt.Fprintln(os.Stderr, con)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
// WriteToFile creates a file and writes content to it
|
||||
func WriteToFile(filename, content string) {
|
||||
f, err := os.Create(filename)
|
||||
@ -273,13 +248,13 @@ func IsDebugEnabled() bool {
|
||||
}
|
||||
|
||||
// __FILE__ returns the file name in which the function was invoked
|
||||
func __FILE__() string {
|
||||
func FILE() string {
|
||||
_, file, _, _ := runtime.Caller(1)
|
||||
return file
|
||||
}
|
||||
|
||||
// __LINE__ returns the line number at which the function was invoked
|
||||
func __LINE__() int {
|
||||
func LINE() int {
|
||||
_, _, line, _ := runtime.Caller(1)
|
||||
return line
|
||||
}
|
||||
@ -288,9 +263,9 @@ func __LINE__() int {
|
||||
func BeeFuncMap() template.FuncMap {
|
||||
return template.FuncMap{
|
||||
"trim": strings.TrimSpace,
|
||||
"bold": bold,
|
||||
"headline": MagentaBold,
|
||||
"foldername": RedBold,
|
||||
"bold": colors.Bold,
|
||||
"headline": colors.MagentaBold,
|
||||
"foldername": colors.RedBold,
|
||||
"endline": EndLine,
|
||||
"tmpltostr": TmplToString,
|
||||
}
|
||||
@ -307,3 +282,59 @@ func TmplToString(tmpl string, data interface{}) string {
|
||||
|
||||
return doc.String()
|
||||
}
|
||||
|
||||
// EndLine returns the a newline escape character
|
||||
func EndLine() string {
|
||||
return "\n"
|
||||
}
|
||||
|
||||
func Tmpl(text string, data interface{}) {
|
||||
output := colors.NewColorWriter(os.Stderr)
|
||||
|
||||
t := template.New("Usage").Funcs(BeeFuncMap())
|
||||
template.Must(t.Parse(text))
|
||||
|
||||
err := t.Execute(output, data)
|
||||
if err != nil {
|
||||
beeLogger.Log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func CheckEnv(appname string) (apppath, packpath string, err error) {
|
||||
gps := GetGOPATHs()
|
||||
if len(gps) == 0 {
|
||||
beeLogger.Log.Fatal("GOPATH environment variable is not set or empty")
|
||||
}
|
||||
currpath, _ := os.Getwd()
|
||||
currpath = path.Join(currpath, appname)
|
||||
for _, gpath := range gps {
|
||||
gsrcpath := path.Join(gpath, "src")
|
||||
if strings.HasPrefix(currpath, gsrcpath) {
|
||||
packpath = strings.Replace(currpath[len(gsrcpath)+1:], string(filepath.Separator), "/", -1)
|
||||
return currpath, packpath, nil
|
||||
}
|
||||
}
|
||||
|
||||
// In case of multiple paths in the GOPATH, by default
|
||||
// we use the first path
|
||||
gopath := gps[0]
|
||||
|
||||
beeLogger.Log.Warn("You current workdir is not inside $GOPATH/src.")
|
||||
beeLogger.Log.Debugf("GOPATH: %s", FILE(), LINE(), gopath)
|
||||
|
||||
gosrcpath := path.Join(gopath, "src")
|
||||
apppath = path.Join(gosrcpath, appname)
|
||||
|
||||
if _, e := os.Stat(apppath); !os.IsNotExist(e) {
|
||||
err = fmt.Errorf("Cannot create application without removing '%s' first.", apppath)
|
||||
beeLogger.Log.Errorf("Path '%s' already exists", apppath)
|
||||
return
|
||||
}
|
||||
packpath = strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(filepath.Separator)), "/")
|
||||
return
|
||||
}
|
||||
|
||||
func PrintErrorAndExit(message, errorTemplate string) {
|
||||
Tmpl(fmt.Sprintf(errorTemplate, message), nil)
|
||||
os.Exit(2)
|
||||
}
|
@ -23,7 +23,7 @@ func transformDescription(m Matcher, newDesc string) Matcher {
|
||||
}
|
||||
|
||||
type transformDescriptionMatcher struct {
|
||||
desc string
|
||||
desc string
|
||||
wrappedMatcher Matcher
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user