mirror of
https://github.com/beego/bee.git
synced 2024-11-25 20:10:55 +00:00
commit
6dce4df2cb
@ -3,3 +3,4 @@ language: go
|
|||||||
go:
|
go:
|
||||||
- 1.6.3
|
- 1.6.3
|
||||||
- 1.7.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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package apiapp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
path "path/filepath"
|
path "path/filepath"
|
||||||
"strings"
|
"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,
|
// CustomFlags: true,
|
||||||
UsageLine: "api [appname]",
|
UsageLine: "api [appname]",
|
||||||
Short: "Creates a Beego API application",
|
Short: "Creates a Beego API application",
|
||||||
@ -50,10 +56,9 @@ var cmdApiapp = &Command{
|
|||||||
└── object.go
|
└── object.go
|
||||||
└── user.go
|
└── user.go
|
||||||
`,
|
`,
|
||||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||||
Run: createapi,
|
Run: createapi,
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiconf = `appname = {{.Appname}}
|
var apiconf = `appname = {{.Appname}}
|
||||||
httpport = 8080
|
httpport = 8080
|
||||||
runmode = dev
|
runmode = dev
|
||||||
@ -134,7 +139,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
var apiModels = `package models
|
var ApiModels = `package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@ -189,7 +194,7 @@ func Delete(ObjectId string) {
|
|||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
var apiModels2 = `package models
|
var ApiModels2 = `package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@ -532,33 +537,32 @@ func TestGet(t *testing.T) {
|
|||||||
`
|
`
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdApiapp.Flag.Var(&tables, "tables", "List of table names separated by a comma.")
|
CmdApiapp.Flag.Var(&generate.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(&generate.SQLDriver, "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.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()
|
output := cmd.Out()
|
||||||
|
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
logger.Fatal("Argument [appname] is missing")
|
beeLogger.Log.Fatal("Argument [appname] is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
cmd.Flag.Parse(args[1:])
|
cmd.Flag.Parse(args[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
apppath, packpath, err := checkEnv(args[0])
|
apppath, packpath, err := utils.CheckEnv(args[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("%s", err)
|
beeLogger.Log.Fatalf("%s", err)
|
||||||
}
|
}
|
||||||
if driver == "" {
|
if generate.SQLDriver == "" {
|
||||||
driver = "mysql"
|
generate.SQLDriver = "mysql"
|
||||||
}
|
|
||||||
if conn == "" {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Creating API...")
|
beeLogger.Log.Info("Creating API...")
|
||||||
|
|
||||||
os.MkdirAll(apppath, 0755)
|
os.MkdirAll(apppath, 0755)
|
||||||
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m")
|
fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m")
|
||||||
@ -569,30 +573,30 @@ func createapi(cmd *Command, args []string) int {
|
|||||||
os.Mkdir(path.Join(apppath, "tests"), 0755)
|
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, "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")
|
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))
|
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")
|
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(apiMainconngo, "{{.Appname}}", packpath, -1)
|
||||||
maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(driver), -1)
|
maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(generate.SQLDriver), -1)
|
||||||
if driver == "mysql" {
|
if generate.SQLDriver == "mysql" {
|
||||||
maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/go-sql-driver/mysql"`, -1)
|
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)
|
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(
|
strings.Replace(
|
||||||
maingoContent,
|
maingoContent,
|
||||||
"{{.conn}}",
|
"{{.conn}}",
|
||||||
conn.String(),
|
generate.SQLConn.String(),
|
||||||
-1,
|
-1,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
logger.Infof("Using '%s' as 'driver'", driver)
|
beeLogger.Log.Infof("Using '%s' as 'driver'", generate.SQLDriver)
|
||||||
logger.Infof("Using '%s' as 'conn'", conn)
|
beeLogger.Log.Infof("Using '%s' as 'conn'", generate.SQLConn)
|
||||||
logger.Infof("Using '%s' as 'tables'", tables)
|
beeLogger.Log.Infof("Using '%s' as 'tables'", generate.Tables)
|
||||||
generateAppcode(string(driver), string(conn), "3", string(tables), apppath)
|
generate.GenerateAppcode(string(generate.SQLDriver), string(generate.SQLConn), "3", string(generate.Tables), apppath)
|
||||||
} else {
|
} else {
|
||||||
os.Mkdir(path.Join(apppath, "models"), 0755)
|
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"), "\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, "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")
|
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))
|
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")
|
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))
|
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")
|
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))
|
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")
|
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))
|
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")
|
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")
|
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")
|
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))
|
strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1))
|
||||||
}
|
}
|
||||||
logger.Success("New API successfully created!")
|
beeLogger.Log.Success("New API successfully created!")
|
||||||
return 0
|
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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package bale
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -24,9 +24,15 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"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",
|
UsageLine: "bale",
|
||||||
Short: "Transforms non-Go files to Go source files",
|
Short: "Transforms non-Go files to Go source files",
|
||||||
Long: `Bale command compress all the static files in to a single binary file.
|
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.
|
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.
|
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,
|
Run: runBale,
|
||||||
}
|
}
|
||||||
|
|
||||||
func runBale(cmd *Command, args []string) int {
|
func init() {
|
||||||
err := loadConfig()
|
commands.AvailableCommands = append(commands.AvailableCommands, CmdBale)
|
||||||
if err != nil {
|
|
||||||
logger.Fatalf("Failed to load configuration: %s", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runBale(cmd *commands.Command, args []string) int {
|
||||||
os.RemoveAll("bale")
|
os.RemoveAll("bale")
|
||||||
os.Mkdir("bale", os.ModePerm)
|
os.Mkdir("bale", os.ModePerm)
|
||||||
|
|
||||||
// Pack and compress data
|
// Pack and compress data
|
||||||
for _, p := range conf.Bale.Dirs {
|
for _, p := range config.Conf.Bale.Dirs {
|
||||||
if !isExist(p) {
|
if !utils.IsExist(p) {
|
||||||
logger.Warnf("Skipped directory: %s", p)
|
beeLogger.Log.Warnf("Skipped directory: %s", p)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
logger.Infof("Packaging directory: %s", p)
|
beeLogger.Log.Infof("Packaging directory: %s", p)
|
||||||
filepath.Walk(p, walkFn)
|
filepath.Walk(p, walkFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate auto-uncompress function.
|
// Generate auto-uncompress function.
|
||||||
buf := new(bytes.Buffer)
|
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\t\""),
|
||||||
strings.Join(resFiles, ",\n\t\tbale.R")))
|
strings.Join(resFiles, ",\n\t\tbale.R")))
|
||||||
|
|
||||||
fw, err := os.Create("bale.go")
|
fw, err := os.Create("bale.go")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("Failed to create file: %s", err)
|
beeLogger.Log.Fatalf("Failed to create file: %s", err)
|
||||||
}
|
}
|
||||||
defer fw.Close()
|
defer fw.Close()
|
||||||
|
|
||||||
_, err = fw.Write(buf.Bytes())
|
_, err = fw.Write(buf.Bytes())
|
||||||
if err != nil {
|
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
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +151,7 @@ func walkFn(resPath string, info os.FileInfo, err error) error {
|
|||||||
// Open resource files
|
// Open resource files
|
||||||
fr, err := os.Open(resPath)
|
fr, err := os.Open(resPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("Failed to read file: %s", err)
|
beeLogger.Log.Fatalf("Failed to read file: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert path
|
// Convert path
|
||||||
@ -164,7 +169,7 @@ func walkFn(resPath string, info os.FileInfo, err error) error {
|
|||||||
os.MkdirAll(path.Dir(resPath), os.ModePerm)
|
os.MkdirAll(path.Dir(resPath), os.ModePerm)
|
||||||
fw, err := os.Create("bale/" + resPath + ".go")
|
fw, err := os.Create("bale/" + resPath + ".go")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("Failed to create file: %s", err)
|
beeLogger.Log.Fatalf("Failed to create file: %s", err)
|
||||||
}
|
}
|
||||||
defer fw.Close()
|
defer fw.Close()
|
||||||
|
|
||||||
@ -184,7 +189,7 @@ func walkFn(resPath string, info os.FileInfo, err error) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func filterSuffix(name string) bool {
|
func filterSuffix(name string) bool {
|
||||||
for _, s := range conf.Bale.IngExt {
|
for _, s := range config.Conf.Bale.IngExt {
|
||||||
if strings.HasSuffix(name, s) {
|
if strings.HasSuffix(name, s) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package beefix
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -9,9 +9,14 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"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",
|
UsageLine: "fix",
|
||||||
Short: "Fixes your application by making it compatible with newer versions of Beego",
|
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.
|
Long: `As of {{"Beego 1.6"|bold}}, there are some backward compatibility issues.
|
||||||
@ -22,18 +27,19 @@ var cmdFix = &Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdFix.Run = runFix
|
CmdFix.Run = runFix
|
||||||
cmdFix.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() }
|
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()
|
output := cmd.Out()
|
||||||
|
|
||||||
logger.Info("Upgrading the application...")
|
beeLogger.Log.Info("Upgrading the application...")
|
||||||
|
|
||||||
dir, err := os.Getwd()
|
dir, err := os.Getwd()
|
||||||
if err != nil {
|
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 {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
err = fixFile(path)
|
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 {
|
if err != nil {
|
||||||
logger.Errorf("Could not fix file: %s", err)
|
beeLogger.Log.Errorf("Could not fix file: %s", err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
logger.Success("Upgrade Done!")
|
beeLogger.Log.Success("Upgrade Done!")
|
||||||
return 0
|
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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package dockerize
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
@ -21,22 +21,13 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"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}}
|
const dockerBuildTemplate = `FROM {{.BaseImage}}
|
||||||
|
|
||||||
# Godep for vendoring
|
# Godep for vendoring
|
||||||
@ -67,6 +58,20 @@ type Dockerfile struct {
|
|||||||
Expose string
|
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 (
|
var (
|
||||||
expose string
|
expose string
|
||||||
baseImage string
|
baseImage string
|
||||||
@ -76,19 +81,22 @@ func init() {
|
|||||||
fs := flag.NewFlagSet("dockerize", flag.ContinueOnError)
|
fs := flag.NewFlagSet("dockerize", flag.ContinueOnError)
|
||||||
fs.StringVar(&baseImage, "image", "library/golang", "Set the base image of the Docker container.")
|
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.")
|
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 {
|
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")
|
gopath := os.Getenv("GOPATH")
|
||||||
dir, err := filepath.Abs(".")
|
dir, err := filepath.Abs(".")
|
||||||
MustCheck(err)
|
if err != nil {
|
||||||
|
beeLogger.Log.Error(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
appdir := strings.Replace(dir, gopath, "", 1)
|
appdir := strings.Replace(dir, gopath, "", 1)
|
||||||
|
|
||||||
@ -112,15 +120,15 @@ func dockerizeApp(cmd *Command, args []string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func generateDockerfile(df Dockerfile) {
|
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")
|
f, err := os.Create("Dockerfile")
|
||||||
if err != nil {
|
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)
|
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
|
package migrate
|
||||||
//
|
|
||||||
// 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 (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
@ -23,9 +9,16 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"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]",
|
UsageLine: "migrate [Command]",
|
||||||
Short: "Runs database migrations",
|
Short: "Runs database migrations",
|
||||||
Long: `The command 'migrate' allows you to run database migrations to keep it up-to-date.
|
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"]
|
$ bee migrate refresh [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"]
|
||||||
`,
|
`,
|
||||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||||
Run: runMigration,
|
Run: RunMigration,
|
||||||
}
|
}
|
||||||
|
|
||||||
var mDriver docValue
|
var mDriver utils.DocValue
|
||||||
var mConn docValue
|
var mConn utils.DocValue
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdMigrate.Flag.Var(&mDriver, "driver", "Database driver. Either mysql, postgres or sqlite.")
|
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(&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
|
// 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()
|
currpath, _ := os.Getwd()
|
||||||
|
|
||||||
gps := GetGOPATHs()
|
gps := utils.GetGOPATHs()
|
||||||
if len(gps) == 0 {
|
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]
|
gopath := gps[0]
|
||||||
|
|
||||||
logger.Debugf("GOPATH: %s", __FILE__(), __LINE__(), gopath)
|
beeLogger.Log.Debugf("GOPATH: %s", utils.FILE(), utils.LINE(), gopath)
|
||||||
|
|
||||||
// Load the configuration
|
|
||||||
err := loadConfig()
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("Failed to load configuration: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getting command line arguments
|
// Getting command line arguments
|
||||||
if len(args) != 0 {
|
if len(args) != 0 {
|
||||||
cmd.Flag.Parse(args[1:])
|
cmd.Flag.Parse(args[1:])
|
||||||
}
|
}
|
||||||
if mDriver == "" {
|
if mDriver == "" {
|
||||||
mDriver = docValue(conf.Database.Driver)
|
mDriver = utils.DocValue(config.Conf.Database.Driver)
|
||||||
if mDriver == "" {
|
if mDriver == "" {
|
||||||
mDriver = "mysql"
|
mDriver = "mysql"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if mConn == "" {
|
if mConn == "" {
|
||||||
mConn = docValue(conf.Database.Conn)
|
mConn = utils.DocValue(config.Conf.Database.Conn)
|
||||||
if mConn == "" {
|
if mConn == "" {
|
||||||
mConn = "root:@tcp(127.0.0.1:3306)/test"
|
mConn = "root:@tcp(127.0.0.1:3306)/test"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.Infof("Using '%s' as 'driver'", mDriver)
|
beeLogger.Log.Infof("Using '%s' as 'driver'", mDriver)
|
||||||
logger.Infof("Using '%s' as 'conn'", mConn)
|
beeLogger.Log.Infof("Using '%s' as 'conn'", mConn)
|
||||||
driverStr, connStr := string(mDriver), string(mConn)
|
driverStr, connStr := string(mDriver), string(mConn)
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
// run all outstanding migrations
|
// run all outstanding migrations
|
||||||
logger.Info("Running all outstanding migrations")
|
beeLogger.Log.Info("Running all outstanding migrations")
|
||||||
migrateUpdate(currpath, driverStr, connStr)
|
MigrateUpdate(currpath, driverStr, connStr)
|
||||||
} else {
|
} else {
|
||||||
mcmd := args[0]
|
mcmd := args[0]
|
||||||
switch mcmd {
|
switch mcmd {
|
||||||
case "rollback":
|
case "rollback":
|
||||||
logger.Info("Rolling back the last migration operation")
|
beeLogger.Log.Info("Rolling back the last migration operation")
|
||||||
migrateRollback(currpath, driverStr, connStr)
|
MigrateRollback(currpath, driverStr, connStr)
|
||||||
case "reset":
|
case "reset":
|
||||||
logger.Info("Reseting all migrations")
|
beeLogger.Log.Info("Reseting all migrations")
|
||||||
migrateReset(currpath, driverStr, connStr)
|
MigrateReset(currpath, driverStr, connStr)
|
||||||
case "refresh":
|
case "refresh":
|
||||||
logger.Info("Refreshing all migrations")
|
beeLogger.Log.Info("Refreshing all migrations")
|
||||||
migrateRefresh(currpath, driverStr, connStr)
|
MigrateRefresh(currpath, driverStr, connStr)
|
||||||
default:
|
default:
|
||||||
logger.Fatal("Command is missing")
|
beeLogger.Log.Fatal("Command is missing")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.Success("Migration successful!")
|
beeLogger.Log.Success("Migration successful!")
|
||||||
return 0
|
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
|
// migrate generates source code, build it, and invoke the binary who does the actual migration
|
||||||
func migrate(goal, currpath, driver, connStr string) {
|
func migrate(goal, currpath, driver, connStr string) {
|
||||||
dir := path.Join(currpath, "database", "migrations")
|
dir := path.Join(currpath, "database", "migrations")
|
||||||
@ -153,7 +121,7 @@ func migrate(goal, currpath, driver, connStr string) {
|
|||||||
// Connect to database
|
// Connect to database
|
||||||
db, err := sql.Open(driver, connStr)
|
db, err := sql.Open(driver, connStr)
|
||||||
if err != nil {
|
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()
|
defer db.Close()
|
||||||
|
|
||||||
@ -171,44 +139,44 @@ func migrate(goal, currpath, driver, connStr string) {
|
|||||||
func checkForSchemaUpdateTable(db *sql.DB, driver string) {
|
func checkForSchemaUpdateTable(db *sql.DB, driver string) {
|
||||||
showTableSQL := showMigrationsTableSQL(driver)
|
showTableSQL := showMigrationsTableSQL(driver)
|
||||||
if rows, err := db.Query(showTableSQL); err != nil {
|
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() {
|
} else if !rows.Next() {
|
||||||
// No migrations table, create new ones
|
// No migrations table, create new ones
|
||||||
createTableSQL := createMigrationsTableSQL(driver)
|
createTableSQL := createMigrationsTableSQL(driver)
|
||||||
|
|
||||||
logger.Infof("Creating 'migrations' table...")
|
beeLogger.Log.Infof("Creating 'migrations' table...")
|
||||||
|
|
||||||
if _, err := db.Query(createTableSQL); err != nil {
|
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
|
// Checking that migrations table schema are expected
|
||||||
selectTableSQL := selectMigrationsTableSQL(driver)
|
selectTableSQL := selectMigrationsTableSQL(driver)
|
||||||
if rows, err := db.Query(selectTableSQL); err != nil {
|
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 {
|
} else {
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var fieldBytes, typeBytes, nullBytes, keyBytes, defaultBytes, extraBytes []byte
|
var fieldBytes, typeBytes, nullBytes, keyBytes, defaultBytes, extraBytes []byte
|
||||||
if err := rows.Scan(&fieldBytes, &typeBytes, &nullBytes, &keyBytes, &defaultBytes, &extraBytes); err != nil {
|
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 :=
|
fieldStr, typeStr, nullStr, keyStr, defaultStr, extraStr :=
|
||||||
string(fieldBytes), string(typeBytes), string(nullBytes), string(keyBytes), string(defaultBytes), string(extraBytes)
|
string(fieldBytes), string(typeBytes), string(nullBytes), string(keyBytes), string(defaultBytes), string(extraBytes)
|
||||||
if fieldStr == "id_migration" {
|
if fieldStr == "id_migration" {
|
||||||
if keyStr != "PRI" || extraStr != "auto_increment" {
|
if keyStr != "PRI" || extraStr != "auto_increment" {
|
||||||
logger.Hint("Expecting KEY: PRI, EXTRA: auto_increment")
|
beeLogger.Log.Hint("Expecting KEY: PRI, EXTRA: auto_increment")
|
||||||
logger.Fatalf("Column migration.id_migration type mismatch: KEY: %s, EXTRA: %s", keyStr, extraStr)
|
beeLogger.Log.Fatalf("Column migration.id_migration type mismatch: KEY: %s, EXTRA: %s", keyStr, extraStr)
|
||||||
}
|
}
|
||||||
} else if fieldStr == "name" {
|
} else if fieldStr == "name" {
|
||||||
if !strings.HasPrefix(typeStr, "varchar") || nullStr != "YES" {
|
if !strings.HasPrefix(typeStr, "varchar") || nullStr != "YES" {
|
||||||
logger.Hint("Expecting TYPE: varchar, NULL: YES")
|
beeLogger.Log.Hint("Expecting TYPE: varchar, NULL: YES")
|
||||||
logger.Fatalf("Column migration.name type mismatch: TYPE: %s, NULL: %s", typeStr, nullStr)
|
beeLogger.Log.Fatalf("Column migration.name type mismatch: TYPE: %s, NULL: %s", typeStr, nullStr)
|
||||||
}
|
}
|
||||||
} else if fieldStr == "created_at" {
|
} else if fieldStr == "created_at" {
|
||||||
if typeStr != "timestamp" || defaultStr != "CURRENT_TIMESTAMP" {
|
if typeStr != "timestamp" || defaultStr != "CURRENT_TIMESTAMP" {
|
||||||
logger.Hint("Expecting TYPE: timestamp, DEFAULT: CURRENT_TIMESTAMP")
|
beeLogger.Log.Hint("Expecting TYPE: timestamp, DEFAULT: CURRENT_TIMESTAMP")
|
||||||
logger.Fatalf("Column migration.timestamp type mismatch: TYPE: %s, DEFAULT: %s", typeStr, defaultStr)
|
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) {
|
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"
|
sql := "SELECT name FROM migrations where status = 'update' ORDER BY id_migration DESC LIMIT 1"
|
||||||
if rows, err := db.Query(sql); err != nil {
|
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 {
|
} else {
|
||||||
if rows.Next() {
|
if rows.Next() {
|
||||||
if err := rows.Scan(&file); err != nil {
|
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:]
|
createdAtStr := file[len(file)-15:]
|
||||||
if t, err := time.Parse("20060102_150405", createdAtStr); err != nil {
|
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 {
|
} else {
|
||||||
createdAt = t.Unix()
|
createdAt = t.Unix()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// migration table has no 'update' record, no point rolling back
|
// migration table has no 'update' record, no point rolling back
|
||||||
if goal == "rollback" {
|
if goal == "rollback" {
|
||||||
logger.Fatal("There is nothing to rollback")
|
beeLogger.Log.Fatal("There is nothing to rollback")
|
||||||
}
|
}
|
||||||
file, createdAt = "", 0
|
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) {
|
func writeMigrationSourceFile(dir, source, driver, connStr string, latestTime int64, latestName string, task string) {
|
||||||
changeDir(dir)
|
changeDir(dir)
|
||||||
if f, err := os.OpenFile(source, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err != nil {
|
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 {
|
} else {
|
||||||
content := strings.Replace(MigrationMainTPL, "{{DBDriver}}", driver, -1)
|
content := strings.Replace(MigrationMainTPL, "{{DBDriver}}", driver, -1)
|
||||||
content = strings.Replace(content, "{{ConnStr}}", connStr, -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, "{{LatestName}}", latestName, -1)
|
||||||
content = strings.Replace(content, "{{Task}}", task, -1)
|
content = strings.Replace(content, "{{Task}}", task, -1)
|
||||||
if _, err := f.WriteString(content); err != nil {
|
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)
|
changeDir(dir)
|
||||||
cmd := exec.Command("go", "build", "-o", binary)
|
cmd := exec.Command("go", "build", "-o", binary)
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
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))
|
formatShellErrOutput(string(out))
|
||||||
removeTempFile(dir, binary)
|
removeTempFile(dir, binary)
|
||||||
removeTempFile(dir, binary+".go")
|
removeTempFile(dir, binary+".go")
|
||||||
@ -312,7 +280,7 @@ func runMigrationBinary(dir, binary string) {
|
|||||||
cmd := exec.Command("./" + binary)
|
cmd := exec.Command("./" + binary)
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
formatShellOutput(string(out))
|
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)
|
||||||
removeTempFile(dir, binary+".go")
|
removeTempFile(dir, binary+".go")
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
@ -325,7 +293,7 @@ func runMigrationBinary(dir, binary string) {
|
|||||||
// It exits the system when encouter an error
|
// It exits the system when encouter an error
|
||||||
func changeDir(dir string) {
|
func changeDir(dir string) {
|
||||||
if err := os.Chdir(dir); err != nil {
|
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) {
|
func removeTempFile(dir, file string) {
|
||||||
changeDir(dir)
|
changeDir(dir)
|
||||||
if err := os.Remove(file); err != nil {
|
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) {
|
func formatShellErrOutput(o string) {
|
||||||
for _, line := range strings.Split(o, "\n") {
|
for _, line := range strings.Split(o, "\n") {
|
||||||
if line != "" {
|
if line != "" {
|
||||||
logger.Errorf("|> %s", line)
|
beeLogger.Log.Errorf("|> %s", line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,7 +318,7 @@ func formatShellErrOutput(o string) {
|
|||||||
func formatShellOutput(o string) {
|
func formatShellOutput(o string) {
|
||||||
for _, line := range strings.Split(o, "\n") {
|
for _, line := range strings.Split(o, "\n") {
|
||||||
if line != "" {
|
if line != "" {
|
||||||
logger.Infof("|> %s", line)
|
beeLogger.Log.Infof("|> %s", line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -421,3 +389,23 @@ CREATE TABLE migrations (
|
|||||||
status migrations_status
|
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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package new
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
path "path/filepath"
|
path "path/filepath"
|
||||||
"strings"
|
"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]",
|
UsageLine: "new [appname]",
|
||||||
Short: "Creates a Beego application",
|
Short: "Creates a Beego application",
|
||||||
Long: `
|
Long: `
|
||||||
@ -47,74 +53,8 @@ Creates a Beego application for the given app name in the current directory.
|
|||||||
└── index.tpl
|
└── index.tpl
|
||||||
|
|
||||||
`,
|
`,
|
||||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||||
Run: createApp,
|
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var appconf = `appname = {{.Appname}}
|
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)};
|
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
|
package pack
|
||||||
//
|
|
||||||
// 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 (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
@ -31,9 +17,14 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"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,
|
CustomFlags: true,
|
||||||
UsageLine: "pack",
|
UsageLine: "pack",
|
||||||
Short: "Compresses a Beego application into a single file",
|
Short: "Compresses a Beego application into a single file",
|
||||||
@ -43,7 +34,7 @@ var cmdPack = &Command{
|
|||||||
{{"Example:"|bold}}
|
{{"Example:"|bold}}
|
||||||
$ bee pack -v -ba="-ldflags '-s -w'"
|
$ 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,
|
Run: packApp,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,27 +43,16 @@ var (
|
|||||||
excludeP string
|
excludeP string
|
||||||
excludeS string
|
excludeS string
|
||||||
outputP string
|
outputP string
|
||||||
excludeR ListOpts
|
excludeR utils.ListOpts
|
||||||
fsym bool
|
fsym bool
|
||||||
ssym bool
|
ssym bool
|
||||||
build bool
|
build bool
|
||||||
buildArgs string
|
buildArgs string
|
||||||
buildEnvs ListOpts
|
buildEnvs utils.ListOpts
|
||||||
verbose bool
|
verbose bool
|
||||||
format string
|
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() {
|
func init() {
|
||||||
fs := flag.NewFlagSet("pack", flag.ContinueOnError)
|
fs := flag.NewFlagSet("pack", flag.ContinueOnError)
|
||||||
fs.StringVar(&appPath, "p", "", "Set the application path. Defaults to the current path.")
|
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(&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(&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.")
|
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 {
|
type walker interface {
|
||||||
@ -115,10 +96,6 @@ type walkFileTree struct {
|
|||||||
output *io.Writer
|
output *io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wft *walkFileTree) setPrefix(prefix string) {
|
|
||||||
wft.prefix = prefix
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wft *walkFileTree) isExclude(fPath string) bool {
|
func (wft *walkFileTree) isExclude(fPath string) bool {
|
||||||
if fPath == "" {
|
if fPath == "" {
|
||||||
return true
|
return true
|
||||||
@ -316,12 +293,12 @@ func (wft *tarWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if isSym == false {
|
if !isSym {
|
||||||
fr, err := os.Open(fpath)
|
fr, err := os.Open(fpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
defer CloseFile(fr)
|
defer utils.CloseFile(fr)
|
||||||
_, err = io.Copy(tw, fr)
|
_, err = io.Copy(tw, fr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -352,12 +329,12 @@ func (wft *zipWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if isSym == false {
|
if !isSym {
|
||||||
fr, err := os.Open(fpath)
|
fr, err := os.Open(fpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
defer CloseFile(fr)
|
defer utils.CloseFile(fr)
|
||||||
_, err = io.Copy(w, fr)
|
_, err = io.Copy(w, fr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
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,
|
func packDirectory(output io.Writer, excludePrefix []string, excludeSuffix []string,
|
||||||
excludeRegexp []*regexp.Regexp, includePath ...string) (err error) {
|
excludeRegexp []*regexp.Regexp, includePath ...string) (err error) {
|
||||||
|
|
||||||
logger.Infof("Excluding relpath prefix: %s", strings.Join(excludePrefix, ":"))
|
beeLogger.Log.Infof("Excluding relpath prefix: %s", strings.Join(excludePrefix, ":"))
|
||||||
logger.Infof("Excluding relpath suffix: %s", strings.Join(excludeSuffix, ":"))
|
beeLogger.Log.Infof("Excluding relpath suffix: %s", strings.Join(excludeSuffix, ":"))
|
||||||
if len(excludeRegexp) > 0 {
|
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)
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func packApp(cmd *Command, args []string) int {
|
func packApp(cmd *commands.Command, args []string) int {
|
||||||
output := cmd.Out()
|
output := cmd.Out()
|
||||||
curPath, _ := os.Getwd()
|
curPath, _ := os.Getwd()
|
||||||
thePath := ""
|
thePath := ""
|
||||||
@ -454,19 +431,19 @@ func packApp(cmd *Command, args []string) int {
|
|||||||
}
|
}
|
||||||
cmd.Flag.Parse(nArgs)
|
cmd.Flag.Parse(nArgs)
|
||||||
|
|
||||||
if path.IsAbs(appPath) == false {
|
if !path.IsAbs(appPath) {
|
||||||
appPath = path.Join(curPath, appPath)
|
appPath = path.Join(curPath, appPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
thePath, err := path.Abs(appPath)
|
thePath, err := path.Abs(appPath)
|
||||||
if err != nil {
|
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 {
|
if stat, err := os.Stat(thePath); os.IsNotExist(err) || !stat.IsDir() {
|
||||||
logger.Fatalf("Application path does not exist: %s", thePath)
|
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)
|
appName := path.Base(thePath)
|
||||||
|
|
||||||
@ -488,12 +465,12 @@ func packApp(cmd *Command, args []string) int {
|
|||||||
// Remove the tmpdir once bee pack is done
|
// Remove the tmpdir once bee pack is done
|
||||||
err := os.RemoveAll(tmpdir)
|
err := os.RemoveAll(tmpdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to remove the generated temp dir")
|
beeLogger.Log.Error("Failed to remove the generated temp dir")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if build {
|
if build {
|
||||||
logger.Info("Building application...")
|
beeLogger.Log.Info("Building application...")
|
||||||
var envs []string
|
var envs []string
|
||||||
for _, env := range buildEnvs {
|
for _, env := range buildEnvs {
|
||||||
parts := strings.SplitN(env, "=", 2)
|
parts := strings.SplitN(env, "=", 2)
|
||||||
@ -515,7 +492,7 @@ func packApp(cmd *Command, args []string) int {
|
|||||||
os.Setenv("GOOS", goos)
|
os.Setenv("GOOS", goos)
|
||||||
os.Setenv("GOARCH", goarch)
|
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)
|
binPath := path.Join(tmpdir, appName)
|
||||||
if goos == "windows" {
|
if goos == "windows" {
|
||||||
@ -538,10 +515,10 @@ func packApp(cmd *Command, args []string) int {
|
|||||||
execmd.Dir = thePath
|
execmd.Dir = thePath
|
||||||
err = execmd.Run()
|
err = execmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal(err.Error())
|
beeLogger.Log.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Success("Build Successful!")
|
beeLogger.Log.Success("Build Successful!")
|
||||||
}
|
}
|
||||||
|
|
||||||
switch format {
|
switch format {
|
||||||
@ -552,14 +529,14 @@ func packApp(cmd *Command, args []string) int {
|
|||||||
|
|
||||||
outputN := appName + "." + format
|
outputN := appName + "." + format
|
||||||
|
|
||||||
if outputP == "" || path.IsAbs(outputP) == false {
|
if outputP == "" || !path.IsAbs(outputP) {
|
||||||
outputP = path.Join(curPath, outputP)
|
outputP = path.Join(curPath, outputP)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(outputP); err != nil {
|
if _, err := os.Stat(outputP); err != nil {
|
||||||
err = os.MkdirAll(outputP, 0755)
|
err = os.MkdirAll(outputP, 0755)
|
||||||
if err != nil {
|
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 {
|
for _, r := range excludeR {
|
||||||
if len(r) > 0 {
|
if len(r) > 0 {
|
||||||
if re, err := regexp.Compile(r); err != nil {
|
if re, err := regexp.Compile(r); err != nil {
|
||||||
logger.Fatal(err.Error())
|
beeLogger.Log.Fatal(err.Error())
|
||||||
} else {
|
} else {
|
||||||
exr = append(exr, re)
|
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)
|
err = packDirectory(output, exp, exs, exr, tmpdir, thePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal(err.Error())
|
beeLogger.Log.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Success("Application packed!")
|
beeLogger.Log.Success("Application packed!")
|
||||||
return 0
|
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
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
// License for the specific language governing permissions and limitations
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
package main
|
package run
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
beeLogger "github.com/beego/bee/logger"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -70,7 +71,7 @@ func (c *wsClient) readPump() {
|
|||||||
_, _, err := c.conn.ReadMessage()
|
_, _, err := c.conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
|
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
|
break
|
||||||
}
|
}
|
||||||
@ -109,7 +110,7 @@ func (c *wsClient) writePump() {
|
|||||||
|
|
||||||
n := len(c.send)
|
n := len(c.send)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
w.Write(newline)
|
w.Write([]byte("/n"))
|
||||||
w.Write(<-c.send)
|
w.Write(<-c.send)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,13 +156,13 @@ func startReloadServer() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
go startServer()
|
go startServer()
|
||||||
logger.Infof("Reload server listening at %s", reloadAddress)
|
beeLogger.Log.Infof("Reload server listening at %s", reloadAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
func startServer() {
|
func startServer() {
|
||||||
err := http.ListenAndServe(reloadAddress, nil)
|
err := http.ListenAndServe(reloadAddress, nil)
|
||||||
if err != 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
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,7 +176,7 @@ func sendReload(payload string) {
|
|||||||
func handleWsRequest(broker *wsBroker, w http.ResponseWriter, r *http.Request) {
|
func handleWsRequest(broker *wsBroker, w http.ResponseWriter, r *http.Request) {
|
||||||
conn, err := upgrader.Upgrade(w, r, nil)
|
conn, err := upgrader.Upgrade(w, r, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("error while upgrading server connection: %v", err)
|
beeLogger.Log.Errorf("error while upgrading server connection: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -12,7 +12,7 @@
|
|||||||
// License for the specific language governing permissions and limitations
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package run
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -20,25 +20,31 @@ import (
|
|||||||
path "path/filepath"
|
path "path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"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]",
|
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",
|
Short: "Run the application by starting a local development server",
|
||||||
Long: `
|
Long: `
|
||||||
Run command will supervise the filesystem of the application for any changes, and recompile/restart it.
|
Run command will supervise the filesystem of the application for any changes, and recompile/restart it.
|
||||||
|
|
||||||
`,
|
`,
|
||||||
PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
|
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||||
Run: runApp,
|
Run: RunApp,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
mainFiles ListOpts
|
mainFiles utils.ListOpts
|
||||||
downdoc docValue
|
downdoc utils.DocValue
|
||||||
gendoc docValue
|
gendoc utils.DocValue
|
||||||
// The flags list of the paths excluded from watching
|
// The flags list of the paths excluded from watching
|
||||||
excludedPaths strFlags
|
excludedPaths utils.StrFlags
|
||||||
// Pass through to -tags arg of "go build"
|
// Pass through to -tags arg of "go build"
|
||||||
buildTags string
|
buildTags string
|
||||||
// Application path
|
// Application path
|
||||||
@ -54,66 +60,63 @@ var (
|
|||||||
// Current runmode
|
// Current runmode
|
||||||
runmode string
|
runmode string
|
||||||
// Extra directories
|
// Extra directories
|
||||||
extraPackages strFlags
|
extraPackages utils.StrFlags
|
||||||
)
|
)
|
||||||
|
var started = make(chan bool)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdRun.Flag.Var(&mainFiles, "main", "Specify main go files.")
|
CmdRun.Flag.Var(&mainFiles, "main", "Specify main go files.")
|
||||||
cmdRun.Flag.Var(&gendoc, "gendoc", "Enable auto-generate the docs.")
|
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(&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.Var(&excludedPaths, "e", "List of paths to exclude.")
|
||||||
cmdRun.Flag.BoolVar(&vendorWatch, "vendor", false, "Enable watch vendor folder.")
|
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(&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.StringVar(&runmode, "runmode", "", "Set the Beego run mode.")
|
||||||
cmdRun.Flag.Var(&extraPackages, "ex", "List of extra package to watch.")
|
CmdRun.Flag.Var(&extraPackages, "ex", "List of extra package to watch.")
|
||||||
exit = make(chan bool)
|
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" {
|
if len(args) == 0 || args[0] == "watchall" {
|
||||||
currpath, _ = os.Getwd()
|
currpath, _ = os.Getwd()
|
||||||
if found, _gopath, _ := SearchGOPATHs(currpath); found {
|
if found, _gopath, _ := utils.SearchGOPATHs(currpath); found {
|
||||||
appname = path.Base(currpath)
|
appname = path.Base(currpath)
|
||||||
currentGoPath = _gopath
|
currentGoPath = _gopath
|
||||||
} else {
|
} else {
|
||||||
logger.Fatalf("No application '%s' found in your GOPATH", currpath)
|
beeLogger.Log.Fatalf("No application '%s' found in your GOPATH", currpath)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Check if passed Bee application path/name exists in the GOPATH(s)
|
// 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
|
currpath = _path
|
||||||
currentGoPath = _gopath
|
currentGoPath = _gopath
|
||||||
appname = path.Base(currpath)
|
appname = path.Base(currpath)
|
||||||
} else {
|
} 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) {
|
if strings.HasSuffix(appname, ".go") && utils.IsExist(currpath) {
|
||||||
logger.Warnf("The appname is in conflict with file's current path. Do you want to build appname as '%s'", appname)
|
beeLogger.Log.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] ")
|
beeLogger.Log.Info("Do you want to overwrite it? [yes|no] ")
|
||||||
if !askForConfirmation() {
|
if !utils.AskForConfirmation() {
|
||||||
return 0
|
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" {
|
if runmode == "prod" || runmode == "dev" {
|
||||||
os.Setenv("BEEGO_RUNMODE", runmode)
|
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 != "" {
|
} else if runmode != "" {
|
||||||
os.Setenv("BEEGO_RUNMODE", 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") != "" {
|
} else if os.Getenv("BEEGO_RUNMODE") != "" {
|
||||||
logger.Warnf("Using '%s' as 'runmode'", os.Getenv("BEEGO_RUNMODE"))
|
beeLogger.Log.Warnf("Using '%s' as 'runmode'", os.Getenv("BEEGO_RUNMODE"))
|
||||||
}
|
|
||||||
|
|
||||||
err := loadConfig()
|
|
||||||
if err != nil {
|
|
||||||
logger.Fatalf("Failed to load configuration: %s", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var paths []string
|
var paths []string
|
||||||
@ -121,17 +124,17 @@ func runApp(cmd *Command, args []string) int {
|
|||||||
|
|
||||||
// Because monitor files has some issues, we watch current directory
|
// Because monitor files has some issues, we watch current directory
|
||||||
// and ignore non-go files.
|
// 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))
|
paths = append(paths, strings.Replace(p, "$GOPATH", currentGoPath, -1))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(extraPackages) > 0 {
|
if len(extraPackages) > 0 {
|
||||||
// get the full path
|
// get the full path
|
||||||
for _, packagePath := range extraPackages {
|
for _, packagePath := range extraPackages {
|
||||||
if found, _, _fullPath := SearchGOPATHs(packagePath); found {
|
if found, _, _fullPath := utils.SearchGOPATHs(packagePath); found {
|
||||||
readAppDirectories(_fullPath, &paths)
|
readAppDirectories(_fullPath, &paths)
|
||||||
} else {
|
} 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
|
// let paths unique
|
||||||
@ -163,7 +166,7 @@ func runApp(cmd *Command, args []string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start the Reload server (if enabled)
|
// Start the Reload server (if enabled)
|
||||||
if conf.EnableReload {
|
if config.Conf.EnableReload {
|
||||||
startReloadServer()
|
startReloadServer()
|
||||||
}
|
}
|
||||||
if gendoc == "true" {
|
if gendoc == "true" {
|
||||||
@ -205,16 +208,16 @@ func readAppDirectories(directory string, paths *[]string) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileInfo.IsDir() == true && fileInfo.Name()[0] != '.' {
|
if fileInfo.IsDir() && fileInfo.Name()[0] != '.' {
|
||||||
readAppDirectories(directory+"/"+fileInfo.Name(), paths)
|
readAppDirectories(directory+"/"+fileInfo.Name(), paths)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if useDirectory == true {
|
if useDirectory {
|
||||||
continue
|
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)
|
*paths = append(*paths, directory)
|
||||||
useDirectory = true
|
useDirectory = true
|
||||||
}
|
}
|
||||||
@ -227,16 +230,16 @@ func isExcluded(filePath string) bool {
|
|||||||
for _, p := range excludedPaths {
|
for _, p := range excludedPaths {
|
||||||
absP, err := path.Abs(p)
|
absP, err := path.Abs(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Cannot get absolute path of '%s'", p)
|
beeLogger.Log.Errorf("Cannot get absolute path of '%s'", p)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
absFilePath, err := path.Abs(filePath)
|
absFilePath, err := path.Abs(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Cannot get absolute path of '%s'", filePath)
|
beeLogger.Log.Errorf("Cannot get absolute path of '%s'", filePath)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(absFilePath, absP) {
|
if strings.HasPrefix(absFilePath, absP) {
|
||||||
logger.Infof("'%s' is not being watched", filePath)
|
beeLogger.Log.Infof("'%s' is not being watched", filePath)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,7 +12,7 @@
|
|||||||
// License for the specific language governing permissions and limitations
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package run
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -24,6 +24,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"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"
|
"github.com/fsnotify/fsnotify"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -46,7 +50,7 @@ var (
|
|||||||
func NewWatcher(paths []string, files []string, isgenerate bool) {
|
func NewWatcher(paths []string, files []string, isgenerate bool) {
|
||||||
watcher, err := fsnotify.NewWatcher()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("Failed to create watcher: %s", err)
|
beeLogger.Log.Fatalf("Failed to create watcher: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@ -55,7 +59,7 @@ func NewWatcher(paths []string, files []string, isgenerate bool) {
|
|||||||
case e := <-watcher.Events:
|
case e := <-watcher.Events:
|
||||||
isBuild := true
|
isBuild := true
|
||||||
|
|
||||||
if ifStaticFile(e.Name) && conf.EnableReload {
|
if ifStaticFile(e.Name) && config.Conf.EnableReload {
|
||||||
sendReload(e.String())
|
sendReload(e.String())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -69,14 +73,14 @@ func NewWatcher(paths []string, files []string, isgenerate bool) {
|
|||||||
|
|
||||||
mt := getFileModTime(e.Name)
|
mt := getFileModTime(e.Name)
|
||||||
if t := eventTime[e.Name]; mt == t {
|
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
|
isBuild = false
|
||||||
}
|
}
|
||||||
|
|
||||||
eventTime[e.Name] = mt
|
eventTime[e.Name] = mt
|
||||||
|
|
||||||
if isBuild {
|
if isBuild {
|
||||||
logger.Infof("Event fired: %s", e)
|
beeLogger.Log.Infof("Event fired: %s", e)
|
||||||
go func() {
|
go func() {
|
||||||
// Wait 1s before autobuild until there is no file change.
|
// Wait 1s before autobuild until there is no file change.
|
||||||
scheduleTime = time.Now().Add(1 * time.Second)
|
scheduleTime = time.Now().Add(1 * time.Second)
|
||||||
@ -85,17 +89,17 @@ func NewWatcher(paths []string, files []string, isgenerate bool) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
case err := <-watcher.Errors:
|
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 {
|
for _, path := range paths {
|
||||||
logger.Infof(bold("Watching: ")+"%s", path)
|
beeLogger.Log.Infof(colors.Bold("Watching: ")+"%s", path)
|
||||||
err = watcher.Add(path)
|
err = watcher.Add(path)
|
||||||
if err != nil {
|
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)
|
path = strings.Replace(path, "\\", "/", -1)
|
||||||
f, err := os.Open(path)
|
f, err := os.Open(path)
|
||||||
if err != nil {
|
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()
|
return time.Now().Unix()
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
fi, err := f.Stat()
|
fi, err := f.Stat()
|
||||||
if err != nil {
|
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()
|
return time.Now().Unix()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +131,7 @@ func AutoBuild(files []string, isgenerate bool) {
|
|||||||
os.Chdir(currpath)
|
os.Chdir(currpath)
|
||||||
|
|
||||||
cmdName := "go"
|
cmdName := "go"
|
||||||
if conf.Gopm.Enable {
|
if config.Conf.Gopm.Enable {
|
||||||
cmdName = "gopm"
|
cmdName = "gopm"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,14 +142,14 @@ func AutoBuild(files []string, isgenerate bool) {
|
|||||||
)
|
)
|
||||||
// For applications use full import path like "github.com/.../.."
|
// For applications use full import path like "github.com/.../.."
|
||||||
// are able to use "go install" to reduce build time.
|
// are able to use "go install" to reduce build time.
|
||||||
if conf.GoInstall {
|
if config.Conf.GoInstall {
|
||||||
icmd := exec.Command(cmdName, "install", "-v")
|
icmd := exec.Command(cmdName, "install", "-v")
|
||||||
icmd.Stdout = os.Stdout
|
icmd.Stdout = os.Stdout
|
||||||
icmd.Stderr = os.Stderr
|
icmd.Stderr = os.Stderr
|
||||||
icmd.Env = append(os.Environ(), "GOGC=off")
|
icmd.Env = append(os.Environ(), "GOGC=off")
|
||||||
icmd.Run()
|
icmd.Run()
|
||||||
}
|
}
|
||||||
if conf.Gopm.Install {
|
if config.Conf.Gopm.Install {
|
||||||
icmd := exec.Command("go", "list", "./...")
|
icmd := exec.Command("go", "list", "./...")
|
||||||
icmd.Stdout = &stdout
|
icmd.Stdout = &stdout
|
||||||
icmd.Env = append(os.Environ(), "GOGC=off")
|
icmd.Env = append(os.Environ(), "GOGC=off")
|
||||||
@ -169,15 +173,15 @@ func AutoBuild(files []string, isgenerate bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isgenerate {
|
if isgenerate {
|
||||||
logger.Info("Generating the docs...")
|
beeLogger.Log.Info("Generating the docs...")
|
||||||
icmd := exec.Command("bee", "generate", "docs")
|
icmd := exec.Command("bee", "generate", "docs")
|
||||||
icmd.Env = append(os.Environ(), "GOGC=off")
|
icmd.Env = append(os.Environ(), "GOGC=off")
|
||||||
err = icmd.Run()
|
err = icmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Failed to generate the docs.")
|
beeLogger.Log.Errorf("Failed to generate the docs.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Success("Docs generated!")
|
beeLogger.Log.Success("Docs generated!")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -198,12 +202,12 @@ func AutoBuild(files []string, isgenerate bool) {
|
|||||||
bcmd.Stderr = &stderr
|
bcmd.Stderr = &stderr
|
||||||
err = bcmd.Run()
|
err = bcmd.Run()
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Success("Built Successfully!")
|
beeLogger.Log.Success("Built Successfully!")
|
||||||
Restart(appname)
|
Restart(appname)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,39 +215,39 @@ func AutoBuild(files []string, isgenerate bool) {
|
|||||||
func Kill() {
|
func Kill() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
logger.Infof("Kill recover: %s", e)
|
beeLogger.Log.Infof("Kill recover: %s", e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
if cmd != nil && cmd.Process != nil {
|
if cmd != nil && cmd.Process != nil {
|
||||||
err := cmd.Process.Kill()
|
err := cmd.Process.Kill()
|
||||||
if err != nil {
|
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
|
// Restart kills the running command process and starts it again
|
||||||
func Restart(appname string) {
|
func Restart(appname string) {
|
||||||
logger.Debugf("Kill running process", __FILE__(), __LINE__())
|
beeLogger.Log.Debugf("Kill running process", utils.FILE(), utils.LINE())
|
||||||
Kill()
|
Kill()
|
||||||
go Start(appname)
|
go Start(appname)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts the command process
|
// Start starts the command process
|
||||||
func Start(appname string) {
|
func Start(appname string) {
|
||||||
logger.Infof("Restarting '%s'...", appname)
|
beeLogger.Log.Infof("Restarting '%s'...", appname)
|
||||||
if strings.Index(appname, "./") == -1 {
|
if !strings.Contains(appname, "./") {
|
||||||
appname = "./" + appname
|
appname = "./" + appname
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = exec.Command(appname)
|
cmd = exec.Command(appname)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Args = append([]string{appname}, conf.CmdArgs...)
|
cmd.Args = append([]string{appname}, config.Conf.CmdArgs...)
|
||||||
cmd.Env = append(os.Environ(), conf.Envs...)
|
cmd.Env = append(os.Environ(), config.Conf.Envs...)
|
||||||
|
|
||||||
go cmd.Run()
|
go cmd.Run()
|
||||||
logger.Successf("'%s' is running...", appname)
|
beeLogger.Log.Successf("'%s' is running...", appname)
|
||||||
started <- true
|
started <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,7 +266,7 @@ func shouldIgnoreFile(filename string) bool {
|
|||||||
for _, regex := range ignoredFilesRegExps {
|
for _, regex := range ignoredFilesRegExps {
|
||||||
r, err := regexp.Compile(regex)
|
r, err := regexp.Compile(regex)
|
||||||
if err != nil {
|
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) {
|
if r.MatchString(filename) {
|
||||||
return true
|
return true
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package version
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
@ -6,6 +6,10 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"time"
|
||||||
|
|
||||||
|
beeLogger "github.com/beego/bee/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RuntimeInfo holds information about the current runtime.
|
// RuntimeInfo holds information about the current runtime.
|
||||||
@ -26,12 +30,12 @@ type RuntimeInfo struct {
|
|||||||
// print the banner in case of error.
|
// print the banner in case of error.
|
||||||
func InitBanner(out io.Writer, in io.Reader) {
|
func InitBanner(out io.Writer, in io.Reader) {
|
||||||
if in == nil {
|
if in == nil {
|
||||||
logger.Fatal("The input is nil")
|
beeLogger.Log.Fatal("The input is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
banner, err := ioutil.ReadAll(in)
|
banner, err := ioutil.ReadAll(in)
|
||||||
if err != nil {
|
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))
|
show(out, string(banner))
|
||||||
@ -43,11 +47,11 @@ func show(out io.Writer, content string) {
|
|||||||
Parse(content)
|
Parse(content)
|
||||||
|
|
||||||
if err != nil {
|
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{
|
err = t.Execute(out, RuntimeInfo{
|
||||||
getGoVersion(),
|
GetGoVersion(),
|
||||||
runtime.GOOS,
|
runtime.GOOS,
|
||||||
runtime.GOARCH,
|
runtime.GOARCH,
|
||||||
runtime.NumCPU(),
|
runtime.NumCPU(),
|
||||||
@ -55,7 +59,14 @@ func show(out io.Writer, content string) {
|
|||||||
runtime.GOROOT(),
|
runtime.GOROOT(),
|
||||||
runtime.Compiler,
|
runtime.Compiler,
|
||||||
version,
|
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 (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
@ -14,18 +14,12 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/beego/bee/cmd/commands"
|
||||||
|
beeLogger "github.com/beego/bee/logger"
|
||||||
|
"github.com/beego/bee/logger/colors"
|
||||||
"gopkg.in/yaml.v2"
|
"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______
|
const verboseVersionBanner string = `%s%s______
|
||||||
| ___ \
|
| ___ \
|
||||||
| |_/ / ___ ___
|
| |_/ / ___ ___
|
||||||
@ -52,21 +46,33 @@ const shortVersionBanner = `______
|
|||||||
\____/ \___| \___| v{{ .BeeVersion }}
|
\____/ \___| \___| 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
|
var outputFormat string
|
||||||
|
|
||||||
|
const version = "1.8.0"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
fs := flag.NewFlagSet("version", flag.ContinueOnError)
|
fs := flag.NewFlagSet("version", flag.ContinueOnError)
|
||||||
fs.StringVar(&outputFormat, "o", "", "Set the output format. Either json or yaml.")
|
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)
|
cmd.Flag.Parse(args)
|
||||||
stdout := cmd.Out()
|
stdout := cmd.Out()
|
||||||
|
|
||||||
if outputFormat != "" {
|
if outputFormat != "" {
|
||||||
runtimeInfo := RuntimeInfo{
|
runtimeInfo := RuntimeInfo{
|
||||||
getGoVersion(),
|
GetGoVersion(),
|
||||||
runtime.GOOS,
|
runtime.GOOS,
|
||||||
runtime.GOARCH,
|
runtime.GOARCH,
|
||||||
runtime.NumCPU(),
|
runtime.NumCPU(),
|
||||||
@ -74,20 +80,24 @@ func versionCmd(cmd *Command, args []string) int {
|
|||||||
runtime.GOROOT(),
|
runtime.GOROOT(),
|
||||||
runtime.Compiler,
|
runtime.Compiler,
|
||||||
version,
|
version,
|
||||||
getBeegoVersion(),
|
GetBeegoVersion(),
|
||||||
}
|
}
|
||||||
switch outputFormat {
|
switch outputFormat {
|
||||||
case "json":
|
case "json":
|
||||||
{
|
{
|
||||||
b, err := json.MarshalIndent(runtimeInfo, "", " ")
|
b, err := json.MarshalIndent(runtimeInfo, "", " ")
|
||||||
MustCheck(err)
|
if err != nil {
|
||||||
|
beeLogger.Log.Error(err.Error())
|
||||||
|
}
|
||||||
fmt.Println(string(b))
|
fmt.Println(string(b))
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
case "yaml":
|
case "yaml":
|
||||||
{
|
{
|
||||||
b, err := yaml.Marshal(&runtimeInfo)
|
b, err := yaml.Marshal(&runtimeInfo)
|
||||||
MustCheck(err)
|
if err != nil {
|
||||||
|
beeLogger.Log.Error(err.Error())
|
||||||
|
}
|
||||||
fmt.Println(string(b))
|
fmt.Println(string(b))
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -102,11 +112,11 @@ func versionCmd(cmd *Command, args []string) int {
|
|||||||
|
|
||||||
// ShowShortVersionBanner prints the short version banner.
|
// ShowShortVersionBanner prints the short version banner.
|
||||||
func ShowShortVersionBanner() {
|
func ShowShortVersionBanner() {
|
||||||
output := NewColorWriter(os.Stdout)
|
output := colors.NewColorWriter(os.Stdout)
|
||||||
InitBanner(output, bytes.NewBufferString(MagentaBold(shortVersionBanner)))
|
InitBanner(output, bytes.NewBufferString(colors.MagentaBold(shortVersionBanner)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBeegoVersion() string {
|
func GetBeegoVersion() string {
|
||||||
gopath := os.Getenv("GOPATH")
|
gopath := os.Getenv("GOPATH")
|
||||||
re, err := regexp.Compile(`VERSION = "([0-9.]+)"`)
|
re, err := regexp.Compile(`VERSION = "([0-9.]+)"`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -125,11 +135,11 @@ func getBeegoVersion() string {
|
|||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
continue
|
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)
|
fd, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Error while reading 'beego.go'")
|
beeLogger.Log.Error("Error while reading 'beego.go'")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
reader := bufio.NewReader(fd)
|
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"
|
return "Beego is not installed. Please do consider installing it first: https://github.com/astaxie/beego"
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGoVersion() string {
|
func GetGoVersion() string {
|
||||||
var (
|
var (
|
||||||
cmdOut []byte
|
cmdOut []byte
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
if cmdOut, err = exec.Command("go", "version").Output(); err != nil {
|
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]
|
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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -22,6 +22,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
beeLogger "github.com/beego/bee/logger"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ var defaultConf = `{
|
|||||||
"enable_reload": false
|
"enable_reload": false
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
var conf struct {
|
var Conf struct {
|
||||||
Version int
|
Version int
|
||||||
// gopm support
|
// gopm support
|
||||||
Gopm struct {
|
Gopm struct {
|
||||||
@ -79,6 +80,10 @@ var conf struct {
|
|||||||
EnableReload bool `json:"enable_reload" yaml:"enable_reload"`
|
EnableReload bool `json:"enable_reload" yaml:"enable_reload"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
loadConfig()
|
||||||
|
}
|
||||||
|
|
||||||
// loadConfig loads customized configuration.
|
// loadConfig loads customized configuration.
|
||||||
func loadConfig() (err error) {
|
func loadConfig() (err error) {
|
||||||
err = filepath.Walk(".", func(path string, fileInfo os.FileInfo, err error) 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" {
|
if fileInfo.Name() == "bee.json" {
|
||||||
logger.Info("Loading configuration from 'bee.json'...")
|
beeLogger.Log.Info("Loading configuration from 'bee.json'...")
|
||||||
err = parseJSON(path, &conf)
|
err = parseJSON(path, &Conf)
|
||||||
if err != nil {
|
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 err
|
||||||
}
|
}
|
||||||
return io.EOF
|
return io.EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileInfo.Name() == "Beefile" {
|
if fileInfo.Name() == "Beefile" {
|
||||||
logger.Info("Loading configuration from 'Beefile'...")
|
beeLogger.Log.Info("Loading configuration from 'Beefile'...")
|
||||||
err = parseYAML(path, &conf)
|
err = parseYAML(path, &Conf)
|
||||||
if err != nil {
|
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 err
|
||||||
}
|
}
|
||||||
return io.EOF
|
return io.EOF
|
||||||
@ -115,8 +120,8 @@ func loadConfig() (err error) {
|
|||||||
// In case no configuration file found or an error different than io.EOF,
|
// In case no configuration file found or an error different than io.EOF,
|
||||||
// fallback to default configuration
|
// fallback to default configuration
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
logger.Info("Loading default configuration...")
|
beeLogger.Log.Info("Loading default configuration...")
|
||||||
err = json.Unmarshal([]byte(defaultConf), &conf)
|
err = json.Unmarshal([]byte(defaultConf), &Conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -126,21 +131,21 @@ func loadConfig() (err error) {
|
|||||||
err = nil
|
err = nil
|
||||||
|
|
||||||
// Check format version
|
// Check format version
|
||||||
if conf.Version != confVer {
|
if Conf.Version != confVer {
|
||||||
logger.Warn("Your configuration file is outdated. Please do consider updating it.")
|
beeLogger.Log.Warn("Your configuration file is outdated. Please do consider updating it.")
|
||||||
logger.Hint("Check the latest version of bee's configuration file.")
|
beeLogger.Log.Hint("Check the latest version of bee's configuration file.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set variables
|
// Set variables
|
||||||
if len(conf.DirStruct.Controllers) == 0 {
|
if len(Conf.DirStruct.Controllers) == 0 {
|
||||||
conf.DirStruct.Controllers = "controllers"
|
Conf.DirStruct.Controllers = "controllers"
|
||||||
}
|
}
|
||||||
if len(conf.DirStruct.Models) == 0 {
|
if len(Conf.DirStruct.Models) == 0 {
|
||||||
conf.DirStruct.Models = "models"
|
Conf.DirStruct.Models = "models"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append watch exts
|
// Append watch exts
|
||||||
watchExts = append(watchExts, conf.WatchExt...)
|
//watchExts = append(watchExts, Conf.WatchExt...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,11 +159,8 @@ func parseJSON(path string, v interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(data, v)
|
err = json.Unmarshal(data, v)
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseYAML(path string, v interface{}) error {
|
func parseYAML(path string, v interface{}) error {
|
||||||
var (
|
var (
|
||||||
@ -170,8 +172,5 @@ func parseYAML(path string, v interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = yaml.Unmarshal(data, v)
|
err = yaml.Unmarshal(data, v)
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package generate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
@ -23,6 +23,9 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"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/go-sql-driver/mysql"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
)
|
)
|
||||||
@ -183,7 +186,7 @@ type OrmTag struct {
|
|||||||
|
|
||||||
// String returns the source code string for the Table struct
|
// String returns the source code string for the Table struct
|
||||||
func (tb *Table) String() string {
|
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 {
|
for _, v := range tb.Columns {
|
||||||
rv += v.String() + "\n"
|
rv += v.String() + "\n"
|
||||||
}
|
}
|
||||||
@ -255,7 +258,7 @@ func (tag *OrmTag) String() string {
|
|||||||
return fmt.Sprintf("`orm:\"%s\"`", strings.Join(ormOptions, ";"))
|
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
|
var mode byte
|
||||||
switch level {
|
switch level {
|
||||||
case "1":
|
case "1":
|
||||||
@ -265,7 +268,7 @@ func generateAppcode(driver, connStr, level, tables, currpath string) {
|
|||||||
case "3":
|
case "3":
|
||||||
mode = OModel | OController | ORouter
|
mode = OModel | OController | ORouter
|
||||||
default:
|
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
|
var selectedTables map[string]bool
|
||||||
if tables != "" {
|
if tables != "" {
|
||||||
@ -278,9 +281,9 @@ func generateAppcode(driver, connStr, level, tables, currpath string) {
|
|||||||
case "mysql":
|
case "mysql":
|
||||||
case "postgres":
|
case "postgres":
|
||||||
case "sqlite":
|
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:
|
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)
|
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) {
|
func gen(dbms, connStr string, mode byte, selectedTableNames map[string]bool, apppath string) {
|
||||||
db, err := sql.Open(dbms, connStr)
|
db, err := sql.Open(dbms, connStr)
|
||||||
if err != nil {
|
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()
|
defer db.Close()
|
||||||
if trans, ok := dbDriver[dbms]; ok {
|
if trans, ok := dbDriver[dbms]; ok {
|
||||||
logger.Info("Analyzing database tables...")
|
beeLogger.Log.Info("Analyzing database tables...")
|
||||||
tableNames := trans.GetTableNames(db)
|
tableNames := trans.GetTableNames(db)
|
||||||
tables := getTableObjects(tableNames, db, trans)
|
tables := getTableObjects(tableNames, db, trans)
|
||||||
mvcPath := new(MvcPath)
|
mvcPath := new(MvcPath)
|
||||||
@ -305,7 +308,7 @@ func gen(dbms, connStr string, mode byte, selectedTableNames map[string]bool, ap
|
|||||||
pkgPath := getPackagePath(apppath)
|
pkgPath := getPackagePath(apppath)
|
||||||
writeSourceFiles(pkgPath, tables, mode, mvcPath, selectedTableNames)
|
writeSourceFiles(pkgPath, tables, mode, mvcPath, selectedTableNames)
|
||||||
} else {
|
} 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) {
|
func (*MysqlDB) GetTableNames(db *sql.DB) (tables []string) {
|
||||||
rows, err := db.Query("SHOW TABLES")
|
rows, err := db.Query("SHOW TABLES")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("Could not show tables: %s", err)
|
beeLogger.Log.Fatalf("Could not show tables: %s", err)
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var name string
|
var name string
|
||||||
if err := rows.Scan(&name); err != nil {
|
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)
|
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 = ?`,
|
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,
|
table.Name, table.Name) // u.position_in_unique_constraint,
|
||||||
if err != nil {
|
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() {
|
for rows.Next() {
|
||||||
var constraintTypeBytes, columnNameBytes, refTableSchemaBytes, refTableNameBytes, refColumnNameBytes, refOrdinalPosBytes []byte
|
var constraintTypeBytes, columnNameBytes, refTableSchemaBytes, refTableNameBytes, refColumnNameBytes, refOrdinalPosBytes []byte
|
||||||
if err := rows.Scan(&constraintTypeBytes, &columnNameBytes, &refTableSchemaBytes, &refTableNameBytes, &refColumnNameBytes, &refOrdinalPosBytes); err != nil {
|
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 :=
|
constraintType, columnName, refTableSchema, refTableName, refColumnName, refOrdinalPos :=
|
||||||
string(constraintTypeBytes), string(columnNameBytes), string(refTableSchemaBytes),
|
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_schema = database() AND table_name = ?`,
|
||||||
table.Name)
|
table.Name)
|
||||||
if err != nil {
|
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()
|
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
|
// datatype as bytes so that SQL <null> values can be retrieved
|
||||||
var colNameBytes, dataTypeBytes, columnTypeBytes, isNullableBytes, columnDefaultBytes, extraBytes []byte
|
var colNameBytes, dataTypeBytes, columnTypeBytes, isNullableBytes, columnDefaultBytes, extraBytes []byte
|
||||||
if err := colDefRows.Scan(&colNameBytes, &dataTypeBytes, &columnTypeBytes, &isNullableBytes, &columnDefaultBytes, &extraBytes); err != nil {
|
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 :=
|
colName, dataType, columnType, isNullable, columnDefault, extra :=
|
||||||
string(colNameBytes), string(dataTypeBytes), string(columnTypeBytes), string(isNullableBytes), string(columnDefaultBytes), string(extraBytes)
|
string(colNameBytes), string(dataTypeBytes), string(columnTypeBytes), string(isNullableBytes), string(columnDefaultBytes), string(extraBytes)
|
||||||
|
|
||||||
// create a column
|
// create a column
|
||||||
col := new(Column)
|
col := new(Column)
|
||||||
col.Name = camelCase(colName)
|
col.Name = utils.CamelCase(colName)
|
||||||
col.Type, err = mysqlDB.GetGoDataType(dataType)
|
col.Type, err = mysqlDB.GetGoDataType(dataType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("%s", err)
|
beeLogger.Log.Fatalf("%s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tag info
|
// Tag info
|
||||||
@ -449,8 +452,8 @@ func (mysqlDB *MysqlDB) GetColumns(db *sql.DB, table *Table, blackList map[strin
|
|||||||
if isFk && !isBl {
|
if isFk && !isBl {
|
||||||
tag.RelFk = true
|
tag.RelFk = true
|
||||||
refStructName := fkCol.RefTable
|
refStructName := fkCol.RefTable
|
||||||
col.Name = camelCase(colName)
|
col.Name = utils.CamelCase(colName)
|
||||||
col.Type = "*" + camelCase(refStructName)
|
col.Type = "*" + utils.CamelCase(refStructName)
|
||||||
} else {
|
} else {
|
||||||
// if the name of column is Id, and it's not primary key
|
// if the name of column is Id, and it's not primary key
|
||||||
if colName == "id" {
|
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" {
|
if sign == "unsigned" && extra != "auto_increment" {
|
||||||
col.Type, err = mysqlDB.GetGoDataType(dataType + " " + sign)
|
col.Type, err = mysqlDB.GetGoDataType(dataType + " " + sign)
|
||||||
if err != nil {
|
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_type = 'BASE TABLE' AND
|
||||||
table_schema NOT IN ('pg_catalog', 'information_schema')`)
|
table_schema NOT IN ('pg_catalog', 'information_schema')`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("Could not show tables: %s", err)
|
beeLogger.Log.Fatalf("Could not show tables: %s", err)
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var name string
|
var name string
|
||||||
if err := rows.Scan(&name); err != nil {
|
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)
|
tables = append(tables, name)
|
||||||
}
|
}
|
||||||
@ -553,13 +556,13 @@ func (*PostgresDB) GetConstraints(db *sql.DB, table *Table, blackList map[string
|
|||||||
AND u.table_name = $2`,
|
AND u.table_name = $2`,
|
||||||
table.Name, table.Name) // u.position_in_unique_constraint,
|
table.Name, table.Name) // u.position_in_unique_constraint,
|
||||||
if err != nil {
|
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() {
|
for rows.Next() {
|
||||||
var constraintTypeBytes, columnNameBytes, refTableSchemaBytes, refTableNameBytes, refColumnNameBytes, refOrdinalPosBytes []byte
|
var constraintTypeBytes, columnNameBytes, refTableSchemaBytes, refTableNameBytes, refColumnNameBytes, refOrdinalPosBytes []byte
|
||||||
if err := rows.Scan(&constraintTypeBytes, &columnNameBytes, &refTableSchemaBytes, &refTableNameBytes, &refColumnNameBytes, &refOrdinalPosBytes); err != nil {
|
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 :=
|
constraintType, columnName, refTableSchema, refTableName, refColumnName, refOrdinalPos :=
|
||||||
string(constraintTypeBytes), string(columnNameBytes), string(refTableSchemaBytes),
|
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`,
|
AND table_name = $1`,
|
||||||
table.Name)
|
table.Name)
|
||||||
if err != nil {
|
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()
|
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
|
// datatype as bytes so that SQL <null> values can be retrieved
|
||||||
var colNameBytes, dataTypeBytes, columnTypeBytes, isNullableBytes, columnDefaultBytes, extraBytes []byte
|
var colNameBytes, dataTypeBytes, columnTypeBytes, isNullableBytes, columnDefaultBytes, extraBytes []byte
|
||||||
if err := colDefRows.Scan(&colNameBytes, &dataTypeBytes, &columnTypeBytes, &isNullableBytes, &columnDefaultBytes, &extraBytes); err != nil {
|
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 :=
|
colName, dataType, columnType, isNullable, columnDefault, extra :=
|
||||||
string(colNameBytes), string(dataTypeBytes), string(columnTypeBytes), string(isNullableBytes), string(columnDefaultBytes), string(extraBytes)
|
string(colNameBytes), string(dataTypeBytes), string(columnTypeBytes), string(isNullableBytes), string(columnDefaultBytes), string(extraBytes)
|
||||||
// Create a column
|
// Create a column
|
||||||
col := new(Column)
|
col := new(Column)
|
||||||
col.Name = camelCase(colName)
|
col.Name = utils.CamelCase(colName)
|
||||||
col.Type, err = postgresDB.GetGoDataType(dataType)
|
col.Type, err = postgresDB.GetGoDataType(dataType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("%s", err)
|
beeLogger.Log.Fatalf("%s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tag info
|
// Tag info
|
||||||
@ -650,8 +653,8 @@ func (postgresDB *PostgresDB) GetColumns(db *sql.DB, table *Table, blackList map
|
|||||||
if isFk && !isBl {
|
if isFk && !isBl {
|
||||||
tag.RelFk = true
|
tag.RelFk = true
|
||||||
refStructName := fkCol.RefTable
|
refStructName := fkCol.RefTable
|
||||||
col.Name = camelCase(colName)
|
col.Name = utils.CamelCase(colName)
|
||||||
col.Type = "*" + camelCase(refStructName)
|
col.Type = "*" + utils.CamelCase(refStructName)
|
||||||
} else {
|
} else {
|
||||||
// if the name of column is Id, and it's not primary key
|
// if the name of column is Id, and it's not primary key
|
||||||
if colName == "id" {
|
if colName == "id" {
|
||||||
@ -716,22 +719,22 @@ func createPaths(mode byte, paths *MvcPath) {
|
|||||||
// Newly geneated files will be inside these folders.
|
// Newly geneated files will be inside these folders.
|
||||||
func writeSourceFiles(pkgPath string, tables []*Table, mode byte, paths *MvcPath, selectedTables map[string]bool) {
|
func writeSourceFiles(pkgPath string, tables []*Table, mode byte, paths *MvcPath, selectedTables map[string]bool) {
|
||||||
if (OModel & mode) == OModel {
|
if (OModel & mode) == OModel {
|
||||||
logger.Info("Creating model files...")
|
beeLogger.Log.Info("Creating model files...")
|
||||||
writeModelFiles(tables, paths.ModelPath, selectedTables)
|
writeModelFiles(tables, paths.ModelPath, selectedTables)
|
||||||
}
|
}
|
||||||
if (OController & mode) == OController {
|
if (OController & mode) == OController {
|
||||||
logger.Info("Creating controller files...")
|
beeLogger.Log.Info("Creating controller files...")
|
||||||
writeControllerFiles(tables, paths.ControllerPath, selectedTables, pkgPath)
|
writeControllerFiles(tables, paths.ControllerPath, selectedTables, pkgPath)
|
||||||
}
|
}
|
||||||
if (ORouter & mode) == ORouter {
|
if (ORouter & mode) == ORouter {
|
||||||
logger.Info("Creating router files...")
|
beeLogger.Log.Info("Creating router files...")
|
||||||
writeRouterFile(tables, paths.RouterPath, selectedTables, pkgPath)
|
writeRouterFile(tables, paths.RouterPath, selectedTables, pkgPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeModelFiles generates model files
|
// writeModelFiles generates model files
|
||||||
func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bool) {
|
func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bool) {
|
||||||
w := NewColorWriter(os.Stdout)
|
w := colors.NewColorWriter(os.Stdout)
|
||||||
|
|
||||||
for _, tb := range tables {
|
for _, tb := range tables {
|
||||||
// if selectedTables map is not nil and this table is not selected, ignore it
|
// if selectedTables map is not nil and this table is not selected, ignore it
|
||||||
@ -744,22 +747,22 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo
|
|||||||
fpath := path.Join(mPath, filename+".go")
|
fpath := path.Join(mPath, filename+".go")
|
||||||
var f *os.File
|
var f *os.File
|
||||||
var err error
|
var err error
|
||||||
if isExist(fpath) {
|
if utils.IsExist(fpath) {
|
||||||
logger.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
beeLogger.Log.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||||
if askForConfirmation() {
|
if utils.AskForConfirmation() {
|
||||||
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warnf("%s", err)
|
beeLogger.Log.Warnf("%s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Warnf("Skipped create file '%s'", fpath)
|
beeLogger.Log.Warnf("Skipped create file '%s'", fpath)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666)
|
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warnf("%s", err)
|
beeLogger.Log.Warnf("%s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -770,7 +773,7 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo
|
|||||||
template = ModelTPL
|
template = ModelTPL
|
||||||
}
|
}
|
||||||
fileStr := strings.Replace(template, "{{modelStruct}}", tb.String(), 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)
|
||||||
fileStr = strings.Replace(fileStr, "{{tableName}}", tb.Name, -1)
|
fileStr = strings.Replace(fileStr, "{{tableName}}", tb.Name, -1)
|
||||||
|
|
||||||
// If table contains time field, import time.Time package
|
// If table contains time field, import time.Time package
|
||||||
@ -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, "{{timePkg}}", timePkg, -1)
|
||||||
fileStr = strings.Replace(fileStr, "{{importTimePkg}}", importTimePkg, -1)
|
fileStr = strings.Replace(fileStr, "{{importTimePkg}}", importTimePkg, -1)
|
||||||
if _, err := f.WriteString(fileStr); err != nil {
|
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")
|
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
|
// writeControllerFiles generates controller files
|
||||||
func writeControllerFiles(tables []*Table, cPath string, selectedTables map[string]bool, pkgPath string) {
|
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 {
|
for _, tb := range tables {
|
||||||
// If selectedTables map is not nil and this table is not selected, ignore it
|
// If selectedTables map is not nil and this table is not selected, ignore it
|
||||||
@ -809,39 +812,39 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri
|
|||||||
fpath := path.Join(cPath, filename+".go")
|
fpath := path.Join(cPath, filename+".go")
|
||||||
var f *os.File
|
var f *os.File
|
||||||
var err error
|
var err error
|
||||||
if isExist(fpath) {
|
if utils.IsExist(fpath) {
|
||||||
logger.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
beeLogger.Log.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||||
if askForConfirmation() {
|
if utils.AskForConfirmation() {
|
||||||
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warnf("%s", err)
|
beeLogger.Log.Warnf("%s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Warnf("Skipped create file '%s'", fpath)
|
beeLogger.Log.Warnf("Skipped create file '%s'", fpath)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666)
|
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warnf("%s", err)
|
beeLogger.Log.Warnf("%s", err)
|
||||||
continue
|
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)
|
fileStr = strings.Replace(fileStr, "{{pkgPath}}", pkgPath, -1)
|
||||||
if _, err := f.WriteString(fileStr); err != nil {
|
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")
|
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
|
// writeRouterFile generates router file
|
||||||
func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bool, pkgPath string) {
|
func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bool, pkgPath string) {
|
||||||
w := NewColorWriter(os.Stdout)
|
w := colors.NewColorWriter(os.Stdout)
|
||||||
|
|
||||||
var nameSpaces []string
|
var nameSpaces []string
|
||||||
for _, tb := range tables {
|
for _, tb := range tables {
|
||||||
@ -856,7 +859,7 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo
|
|||||||
}
|
}
|
||||||
// Add namespaces
|
// Add namespaces
|
||||||
nameSpace := strings.Replace(NamespaceTPL, "{{nameSpace}}", tb.Name, -1)
|
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)
|
nameSpaces = append(nameSpaces, nameSpace)
|
||||||
}
|
}
|
||||||
// Add export controller
|
// Add export controller
|
||||||
@ -865,31 +868,31 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo
|
|||||||
routerStr = strings.Replace(routerStr, "{{pkgPath}}", pkgPath, 1)
|
routerStr = strings.Replace(routerStr, "{{pkgPath}}", pkgPath, 1)
|
||||||
var f *os.File
|
var f *os.File
|
||||||
var err error
|
var err error
|
||||||
if isExist(fpath) {
|
if utils.IsExist(fpath) {
|
||||||
logger.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
beeLogger.Log.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||||
if askForConfirmation() {
|
if utils.AskForConfirmation() {
|
||||||
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warnf("%s", err)
|
beeLogger.Log.Warnf("%s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Warnf("Skipped create file '%s'", fpath)
|
beeLogger.Log.Warnf("Skipped create file '%s'", fpath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666)
|
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warnf("%s", err)
|
beeLogger.Log.Warnf("%s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, err := f.WriteString(routerStr); err != nil {
|
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")
|
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 {
|
func isSQLTemporalType(t string) bool {
|
||||||
@ -952,10 +955,10 @@ func getFileName(tbName string) (filename string) {
|
|||||||
func getPackagePath(curpath string) (packpath string) {
|
func getPackagePath(curpath string) (packpath string) {
|
||||||
gopath := os.Getenv("GOPATH")
|
gopath := os.Getenv("GOPATH")
|
||||||
if 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 := ""
|
appsrcpath := ""
|
||||||
haspath := false
|
haspath := false
|
||||||
@ -964,7 +967,7 @@ func getPackagePath(curpath string) (packpath string) {
|
|||||||
for _, wg := range wgopath {
|
for _, wg := range wgopath {
|
||||||
wg, _ = filepath.EvalSymlinks(path.Join(wg, "src"))
|
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
|
haspath = true
|
||||||
appsrcpath = wg
|
appsrcpath = wg
|
||||||
break
|
break
|
||||||
@ -972,11 +975,11 @@ func getPackagePath(curpath string) (packpath string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !haspath {
|
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 {
|
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)), "/")
|
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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package generate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
beeLogger "github.com/beego/bee/logger"
|
||||||
|
"github.com/beego/bee/logger/colors"
|
||||||
|
"github.com/beego/bee/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generateController(cname, currpath string) {
|
func GenerateController(cname, currpath string) {
|
||||||
w := NewColorWriter(os.Stdout)
|
w := colors.NewColorWriter(os.Stdout)
|
||||||
|
|
||||||
p, f := path.Split(cname)
|
p, f := path.Split(cname)
|
||||||
controllerName := strings.Title(f)
|
controllerName := strings.Title(f)
|
||||||
@ -33,26 +37,26 @@ func generateController(cname, currpath string) {
|
|||||||
packageName = p[i+1 : len(p)-1]
|
packageName = p[i+1 : len(p)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infof("Using '%s' as controller name", controllerName)
|
beeLogger.Log.Infof("Using '%s' as controller name", controllerName)
|
||||||
logger.Infof("Using '%s' as package name", packageName)
|
beeLogger.Log.Infof("Using '%s' as package name", packageName)
|
||||||
|
|
||||||
fp := path.Join(currpath, "controllers", p)
|
fp := path.Join(currpath, "controllers", p)
|
||||||
if _, err := os.Stat(fp); os.IsNotExist(err) {
|
if _, err := os.Stat(fp); os.IsNotExist(err) {
|
||||||
// Create the controller's directory
|
// Create the controller's directory
|
||||||
if err := os.MkdirAll(fp, 0777); err != nil {
|
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")
|
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 {
|
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")
|
modelPath := path.Join(currpath, "models", strings.ToLower(controllerName)+".go")
|
||||||
|
|
||||||
var content string
|
var content string
|
||||||
if _, err := os.Stat(modelPath); err == nil {
|
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)
|
content = strings.Replace(controllerModelTpl, "{{packageName}}", packageName, -1)
|
||||||
pkgPath := getPackagePath(currpath)
|
pkgPath := getPackagePath(currpath)
|
||||||
content = strings.Replace(content, "{{pkgPath}}", pkgPath, -1)
|
content = strings.Replace(content, "{{pkgPath}}", pkgPath, -1)
|
||||||
@ -64,10 +68,10 @@ func generateController(cname, currpath string) {
|
|||||||
f.WriteString(content)
|
f.WriteString(content)
|
||||||
|
|
||||||
// Run 'gofmt' on the generated source code
|
// 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")
|
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||||
} else {
|
} 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 (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
@ -24,11 +24,256 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"strings"
|
"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/go-sql-driver/mysql"
|
||||||
_ "github.com/lib/pq"
|
_ "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
|
var mode byte
|
||||||
switch level {
|
switch level {
|
||||||
case "1":
|
case "1":
|
||||||
@ -38,7 +283,7 @@ func generateHproseAppcode(driver, connStr, level, tables, currpath string) {
|
|||||||
case "3":
|
case "3":
|
||||||
mode = OModel | OController | ORouter
|
mode = OModel | OController | ORouter
|
||||||
default:
|
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
|
var selectedTables map[string]bool
|
||||||
if tables != "" {
|
if tables != "" {
|
||||||
@ -51,9 +296,9 @@ func generateHproseAppcode(driver, connStr, level, tables, currpath string) {
|
|||||||
case "mysql":
|
case "mysql":
|
||||||
case "postgres":
|
case "postgres":
|
||||||
case "sqlite":
|
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:
|
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)
|
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) {
|
func genHprose(dbms, connStr string, mode byte, selectedTableNames map[string]bool, currpath string) {
|
||||||
db, err := sql.Open(dbms, connStr)
|
db, err := sql.Open(dbms, connStr)
|
||||||
if err != nil {
|
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()
|
defer db.Close()
|
||||||
if trans, ok := dbDriver[dbms]; ok {
|
if trans, ok := dbDriver[dbms]; ok {
|
||||||
logger.Info("Analyzing database tables...")
|
beeLogger.Log.Info("Analyzing database tables...")
|
||||||
tableNames := trans.GetTableNames(db)
|
tableNames := trans.GetTableNames(db)
|
||||||
tables := getTableObjects(tableNames, db, trans)
|
tables := getTableObjects(tableNames, db, trans)
|
||||||
mvcPath := new(MvcPath)
|
mvcPath := new(MvcPath)
|
||||||
@ -76,7 +321,7 @@ func genHprose(dbms, connStr string, mode byte, selectedTableNames map[string]bo
|
|||||||
pkgPath := getPackagePath(currpath)
|
pkgPath := getPackagePath(currpath)
|
||||||
writeHproseSourceFiles(pkgPath, tables, mode, mvcPath, selectedTableNames)
|
writeHproseSourceFiles(pkgPath, tables, mode, mvcPath, selectedTableNames)
|
||||||
} else {
|
} 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.
|
// Newly geneated files will be inside these folders.
|
||||||
func writeHproseSourceFiles(pkgPath string, tables []*Table, mode byte, paths *MvcPath, selectedTables map[string]bool) {
|
func writeHproseSourceFiles(pkgPath string, tables []*Table, mode byte, paths *MvcPath, selectedTables map[string]bool) {
|
||||||
if (OModel & mode) == OModel {
|
if (OModel & mode) == OModel {
|
||||||
logger.Info("Creating model files...")
|
beeLogger.Log.Info("Creating model files...")
|
||||||
writeHproseModelFiles(tables, paths.ModelPath, selectedTables)
|
writeHproseModelFiles(tables, paths.ModelPath, selectedTables)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeHproseModelFiles generates model files
|
// writeHproseModelFiles generates model files
|
||||||
func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[string]bool) {
|
func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[string]bool) {
|
||||||
w := NewColorWriter(os.Stdout)
|
w := colors.NewColorWriter(os.Stdout)
|
||||||
|
|
||||||
for _, tb := range tables {
|
for _, tb := range tables {
|
||||||
// if selectedTables map is not nil and this table is not selected, ignore it
|
// if selectedTables map is not nil and this table is not selected, ignore it
|
||||||
@ -105,22 +350,22 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str
|
|||||||
fpath := path.Join(mPath, filename+".go")
|
fpath := path.Join(mPath, filename+".go")
|
||||||
var f *os.File
|
var f *os.File
|
||||||
var err error
|
var err error
|
||||||
if isExist(fpath) {
|
if utils.IsExist(fpath) {
|
||||||
logger.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
beeLogger.Log.Warnf("'%s' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||||
if askForConfirmation() {
|
if utils.AskForConfirmation() {
|
||||||
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warnf("%s", err)
|
beeLogger.Log.Warnf("%s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Warnf("Skipped create file '%s'", fpath)
|
beeLogger.Log.Warnf("Skipped create file '%s'", fpath)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666)
|
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warnf("%s", err)
|
beeLogger.Log.Warnf("%s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,10 +374,10 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str
|
|||||||
template = HproseStructModelTPL
|
template = HproseStructModelTPL
|
||||||
} else {
|
} else {
|
||||||
template = HproseModelTPL
|
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(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
|
// if table contains time field, import time.Time package
|
||||||
timePkg := ""
|
timePkg := ""
|
||||||
importTimePkg := ""
|
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, "{{timePkg}}", timePkg, -1)
|
||||||
fileStr = strings.Replace(fileStr, "{{importTimePkg}}", importTimePkg, -1)
|
fileStr = strings.Replace(fileStr, "{{importTimePkg}}", importTimePkg, -1)
|
||||||
if _, err := f.WriteString(fileStr); err != nil {
|
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")
|
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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package generate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -20,6 +20,10 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
beeLogger "github.com/beego/bee/logger"
|
||||||
|
"github.com/beego/bee/logger/colors"
|
||||||
|
"github.com/beego/bee/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -29,18 +33,18 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type DBDriver interface {
|
type DBDriver interface {
|
||||||
generateCreateUp(tableName string) string
|
GenerateCreateUp(tableName string) string
|
||||||
generateCreateDown(tableName string) string
|
GenerateCreateDown(tableName string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
type mysqlDriver struct{}
|
type mysqlDriver struct{}
|
||||||
|
|
||||||
func (m mysqlDriver) generateCreateUp(tableName string) string {
|
func (m mysqlDriver) GenerateCreateUp(tableName string) string {
|
||||||
upsql := `m.SQL("CREATE TABLE ` + tableName + "(" + m.generateSQLFromFields(fields.String()) + `)");`
|
upsql := `m.SQL("CREATE TABLE ` + tableName + "(" + m.generateSQLFromFields(Fields.String()) + `)");`
|
||||||
return upsql
|
return upsql
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m mysqlDriver) generateCreateDown(tableName string) string {
|
func (m mysqlDriver) GenerateCreateDown(tableName string) string {
|
||||||
downsql := `m.SQL("DROP TABLE ` + "`" + tableName + "`" + `")`
|
downsql := `m.SQL("DROP TABLE ` + "`" + tableName + "`" + `")`
|
||||||
return downsql
|
return downsql
|
||||||
}
|
}
|
||||||
@ -51,21 +55,21 @@ func (m mysqlDriver) generateSQLFromFields(fields string) string {
|
|||||||
for i, v := range fds {
|
for i, v := range fds {
|
||||||
kv := strings.SplitN(v, ":", 2)
|
kv := strings.SplitN(v, ":", 2)
|
||||||
if len(kv) != 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 ""
|
return ""
|
||||||
}
|
}
|
||||||
typ, tag := m.getSQLType(kv[1])
|
typ, tag := m.getSQLType(kv[1])
|
||||||
if typ == "" {
|
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 ""
|
return ""
|
||||||
}
|
}
|
||||||
if i == 0 && strings.ToLower(kv[0]) != "id" {
|
if i == 0 && strings.ToLower(kv[0]) != "id" {
|
||||||
sql += "`id` int(11) NOT NULL AUTO_INCREMENT,"
|
sql += "`id` int(11) NOT NULL AUTO_INCREMENT,"
|
||||||
tags = tags + "PRIMARY KEY (`id`),"
|
tags = tags + "PRIMARY KEY (`id`),"
|
||||||
}
|
}
|
||||||
sql += "`" + snakeString(kv[0]) + "` " + typ + ","
|
sql += "`" + utils.SnakeString(kv[0]) + "` " + typ + ","
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
tags = tags + fmt.Sprintf(tag, "`"+snakeString(kv[0])+"`") + ","
|
tags = tags + fmt.Sprintf(tag, "`"+utils.SnakeString(kv[0])+"`") + ","
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sql = strings.TrimRight(sql+tags, ",")
|
sql = strings.TrimRight(sql+tags, ",")
|
||||||
@ -104,12 +108,12 @@ func (m mysqlDriver) getSQLType(ktype string) (tp, tag string) {
|
|||||||
|
|
||||||
type postgresqlDriver struct{}
|
type postgresqlDriver struct{}
|
||||||
|
|
||||||
func (m postgresqlDriver) generateCreateUp(tableName string) string {
|
func (m postgresqlDriver) GenerateCreateUp(tableName string) string {
|
||||||
upsql := `m.SQL("CREATE TABLE ` + tableName + "(" + m.generateSQLFromFields(fields.String()) + `)");`
|
upsql := `m.SQL("CREATE TABLE ` + tableName + "(" + m.generateSQLFromFields(Fields.String()) + `)");`
|
||||||
return upsql
|
return upsql
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m postgresqlDriver) generateCreateDown(tableName string) string {
|
func (m postgresqlDriver) GenerateCreateDown(tableName string) string {
|
||||||
downsql := `m.SQL("DROP TABLE ` + tableName + `")`
|
downsql := `m.SQL("DROP TABLE ` + tableName + `")`
|
||||||
return downsql
|
return downsql
|
||||||
}
|
}
|
||||||
@ -120,20 +124,20 @@ func (m postgresqlDriver) generateSQLFromFields(fields string) string {
|
|||||||
for i, v := range fds {
|
for i, v := range fds {
|
||||||
kv := strings.SplitN(v, ":", 2)
|
kv := strings.SplitN(v, ":", 2)
|
||||||
if len(kv) != 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 ""
|
return ""
|
||||||
}
|
}
|
||||||
typ, tag := m.getSQLType(kv[1])
|
typ, tag := m.getSQLType(kv[1])
|
||||||
if typ == "" {
|
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 ""
|
return ""
|
||||||
}
|
}
|
||||||
if i == 0 && strings.ToLower(kv[0]) != "id" {
|
if i == 0 && strings.ToLower(kv[0]) != "id" {
|
||||||
sql += "id serial primary key,"
|
sql += "id serial primary key,"
|
||||||
}
|
}
|
||||||
sql += snakeString(kv[0]) + " " + typ + ","
|
sql += utils.SnakeString(kv[0]) + " " + typ + ","
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
tags = tags + fmt.Sprintf(tag, snakeString(kv[0])) + ","
|
tags = tags + fmt.Sprintf(tag, utils.SnakeString(kv[0])) + ","
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tags != "" {
|
if tags != "" {
|
||||||
@ -170,14 +174,14 @@ func (m postgresqlDriver) getSQLType(ktype string) (tp, tag string) {
|
|||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDBDriver() DBDriver {
|
func NewDBDriver() DBDriver {
|
||||||
switch driver {
|
switch SQLDriver {
|
||||||
case "mysql":
|
case "mysql":
|
||||||
return mysqlDriver{}
|
return mysqlDriver{}
|
||||||
case "postgres":
|
case "postgres":
|
||||||
return postgresqlDriver{}
|
return postgresqlDriver{}
|
||||||
default:
|
default:
|
||||||
logger.Fatal("Driver not supported")
|
beeLogger.Log.Fatal("Driver not supported")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,30 +189,30 @@ func newDBDriver() DBDriver {
|
|||||||
// generateMigration generates migration file template for database schema update.
|
// generateMigration generates migration file template for database schema update.
|
||||||
// The generated file template consists of an up() method for updating schema and
|
// The generated file template consists of an up() method for updating schema and
|
||||||
// a down() method for reverting the update.
|
// a down() method for reverting the update.
|
||||||
func generateMigration(mname, upsql, downsql, curpath string) {
|
func GenerateMigration(mname, upsql, downsql, curpath string) {
|
||||||
w := NewColorWriter(os.Stdout)
|
w := colors.NewColorWriter(os.Stdout)
|
||||||
migrationFilePath := path.Join(curpath, DBPath, MPath)
|
migrationFilePath := path.Join(curpath, DBPath, MPath)
|
||||||
if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) {
|
if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) {
|
||||||
// create migrations directory
|
// create migrations directory
|
||||||
if err := os.MkdirAll(migrationFilePath, 0777); err != nil {
|
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
|
// create file
|
||||||
today := time.Now().Format(MDateFormat)
|
today := time.Now().Format(MDateFormat)
|
||||||
fpath := path.Join(migrationFilePath, fmt.Sprintf("%s_%s.go", today, mname))
|
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 {
|
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(MigrationTPL, "{{StructName}}", camelCase(mname)+"_"+today, -1)
|
content := strings.Replace(MigrationTPL, "{{StructName}}", utils.CamelCase(mname)+"_"+today, -1)
|
||||||
content = strings.Replace(content, "{{CurrTime}}", today, -1)
|
content = strings.Replace(content, "{{CurrTime}}", today, -1)
|
||||||
content = strings.Replace(content, "{{UpSQL}}", upsql, -1)
|
content = strings.Replace(content, "{{UpSQL}}", upsql, -1)
|
||||||
content = strings.Replace(content, "{{DownSQL}}", downsql, -1)
|
content = strings.Replace(content, "{{DownSQL}}", downsql, -1)
|
||||||
f.WriteString(content)
|
f.WriteString(content)
|
||||||
// Run 'gofmt' on the generated source code
|
// 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")
|
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||||
} else {
|
} 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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package generate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@ -20,10 +20,14 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
beeLogger "github.com/beego/bee/logger"
|
||||||
|
"github.com/beego/bee/logger/colors"
|
||||||
|
"github.com/beego/bee/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generateModel(mname, fields, currpath string) {
|
func GenerateModel(mname, fields, currpath string) {
|
||||||
w := NewColorWriter(os.Stdout)
|
w := colors.NewColorWriter(os.Stdout)
|
||||||
|
|
||||||
p, f := path.Split(mname)
|
p, f := path.Split(mname)
|
||||||
modelName := strings.Title(f)
|
modelName := strings.Title(f)
|
||||||
@ -35,23 +39,23 @@ func generateModel(mname, fields, currpath string) {
|
|||||||
|
|
||||||
modelStruct, hastime, err := getStruct(modelName, fields)
|
modelStruct, hastime, err := getStruct(modelName, fields)
|
||||||
if err != nil {
|
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)
|
beeLogger.Log.Infof("Using '%s' as model name", modelName)
|
||||||
logger.Infof("Using '%s' as package name", packageName)
|
beeLogger.Log.Infof("Using '%s' as package name", packageName)
|
||||||
|
|
||||||
fp := path.Join(currpath, "models", p)
|
fp := path.Join(currpath, "models", p)
|
||||||
if _, err := os.Stat(fp); os.IsNotExist(err) {
|
if _, err := os.Stat(fp); os.IsNotExist(err) {
|
||||||
// Create the model's directory
|
// Create the model's directory
|
||||||
if err := os.MkdirAll(fp, 0777); err != nil {
|
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")
|
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 {
|
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(modelTpl, "{{packageName}}", packageName, -1)
|
||||||
content = strings.Replace(content, "{{modelName}}", modelName, -1)
|
content = strings.Replace(content, "{{modelName}}", modelName, -1)
|
||||||
content = strings.Replace(content, "{{modelStruct}}", modelStruct, -1)
|
content = strings.Replace(content, "{{modelStruct}}", modelStruct, -1)
|
||||||
@ -62,10 +66,10 @@ func generateModel(mname, fields, currpath string) {
|
|||||||
}
|
}
|
||||||
f.WriteString(content)
|
f.WriteString(content)
|
||||||
// Run 'gofmt' on the generated source code
|
// 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")
|
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||||
} else {
|
} 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 {
|
if hastimeinner {
|
||||||
hastime = true
|
hastime = true
|
||||||
}
|
}
|
||||||
structStr = structStr + camelString(kv[0]) + " " + typ + " " + tag + "\n"
|
structStr = structStr + utils.CamelString(kv[0]) + " " + typ + " " + tag + "\n"
|
||||||
}
|
}
|
||||||
structStr += "}\n"
|
structStr += "}\n"
|
||||||
return structStr, hastime, nil
|
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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package generate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
|
beeLogger "github.com/beego/bee/logger"
|
||||||
|
"github.com/beego/bee/logger/colors"
|
||||||
|
"github.com/beego/bee/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// recipe
|
// recipe
|
||||||
// admin/recipe
|
// admin/recipe
|
||||||
func generateView(viewpath, currpath string) {
|
func GenerateView(viewpath, currpath string) {
|
||||||
w := NewColorWriter(os.Stdout)
|
w := colors.NewColorWriter(os.Stdout)
|
||||||
|
|
||||||
logger.Info("Generating view...")
|
beeLogger.Log.Info("Generating view...")
|
||||||
|
|
||||||
absViewPath := path.Join(currpath, "views", viewpath)
|
absViewPath := path.Join(currpath, "views", viewpath)
|
||||||
err := os.MkdirAll(absViewPath, os.ModePerm)
|
err := os.MkdirAll(absViewPath, os.ModePerm)
|
||||||
if err != nil {
|
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")
|
cfile := path.Join(absViewPath, "index.tpl")
|
||||||
if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
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)
|
f.WriteString(cfile)
|
||||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
||||||
} else {
|
} 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")
|
cfile = path.Join(absViewPath, "show.tpl")
|
||||||
if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
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)
|
f.WriteString(cfile)
|
||||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
||||||
} else {
|
} 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")
|
cfile = path.Join(absViewPath, "create.tpl")
|
||||||
if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
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)
|
f.WriteString(cfile)
|
||||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
||||||
} else {
|
} 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")
|
cfile = path.Join(absViewPath, "edit.tpl")
|
||||||
if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
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)
|
f.WriteString(cfile)
|
||||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
||||||
} else {
|
} 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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package swaggergen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -35,6 +35,7 @@ import (
|
|||||||
|
|
||||||
"github.com/astaxie/beego/swagger"
|
"github.com/astaxie/beego/swagger"
|
||||||
"github.com/astaxie/beego/utils"
|
"github.com/astaxie/beego/utils"
|
||||||
|
beeLogger "github.com/beego/bee/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -90,7 +91,7 @@ func init() {
|
|||||||
astPkgs = map[string]*ast.Package{}
|
astPkgs = map[string]*ast.Package{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePackagesFromDir(dirpath string) {
|
func ParsePackagesFromDir(dirpath string) {
|
||||||
c := make(chan error)
|
c := make(chan error)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@ -116,7 +117,7 @@ func parsePackagesFromDir(dirpath string) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
for err := range c {
|
for err := range c {
|
||||||
logger.Warnf("%s", err)
|
beeLogger.Log.Warnf("%s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,12 +138,12 @@ func parsePackageFromDir(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateDocs(curpath string) {
|
func GenerateDocs(curpath string) {
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
|
|
||||||
f, err := parser.ParseFile(fset, path.Join(curpath, "routers", "router.go"), nil, parser.ParseComments)
|
f, err := parser.ParseFile(fset, path.Join(curpath, "routers", "router.go"), nil, parser.ParseComments)
|
||||||
if err != nil {
|
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{}
|
rootapi.Infos = swagger.Information{}
|
||||||
@ -251,6 +252,9 @@ func generateDocs(curpath string) {
|
|||||||
}
|
}
|
||||||
os.Mkdir(path.Join(curpath, "swagger"), 0755)
|
os.Mkdir(path.Join(curpath, "swagger"), 0755)
|
||||||
fd, err := os.Create(path.Join(curpath, "swagger", "swagger.json"))
|
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"))
|
fdyml, err := os.Create(path.Join(curpath, "swagger", "swagger.yml"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -348,7 +352,7 @@ func analyseControllerPkg(localName, pkgpath string) {
|
|||||||
}
|
}
|
||||||
gopath := os.Getenv("GOPATH")
|
gopath := os.Getenv("GOPATH")
|
||||||
if 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 := ""
|
pkgRealpath := ""
|
||||||
|
|
||||||
@ -366,7 +370,7 @@ func analyseControllerPkg(localName, pkgpath string) {
|
|||||||
}
|
}
|
||||||
pkgCache[pkgpath] = struct{}{}
|
pkgCache[pkgpath] = struct{}{}
|
||||||
} else {
|
} 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()
|
fileSet := token.NewFileSet()
|
||||||
@ -375,7 +379,7 @@ func analyseControllerPkg(localName, pkgpath string) {
|
|||||||
return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
|
return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
|
||||||
}, parser.ParseComments)
|
}, parser.ParseComments)
|
||||||
if err != nil {
|
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 _, pkg := range astPkgs {
|
||||||
for _, fl := range pkg.Files {
|
for _, fl := range pkg.Files {
|
||||||
@ -413,7 +417,7 @@ func isSystemPackage(pkgpath string) bool {
|
|||||||
goroot = runtime.GOROOT()
|
goroot = runtime.GOROOT()
|
||||||
}
|
}
|
||||||
if 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))
|
wg, _ := filepath.EvalSymlinks(filepath.Join(goroot, "src", "pkg", pkgpath))
|
||||||
@ -423,11 +427,7 @@ func isSystemPackage(pkgpath string) bool {
|
|||||||
|
|
||||||
//TODO(zh):support go1.4
|
//TODO(zh):support go1.4
|
||||||
wg, _ = filepath.EvalSymlinks(filepath.Join(goroot, "src", pkgpath))
|
wg, _ = filepath.EvalSymlinks(filepath.Join(goroot, "src", pkgpath))
|
||||||
if utils.FileExists(wg) {
|
return utils.FileExists(wg)
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func peekNextSplitString(ss string) (s string, spacePos int) {
|
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:])
|
ss = strings.TrimSpace(ss[pos:])
|
||||||
schemaName, pos := peekNextSplitString(ss)
|
schemaName, pos := peekNextSplitString(ss)
|
||||||
if schemaName == "" {
|
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, "[]") {
|
if strings.HasPrefix(schemaName, "[]") {
|
||||||
schemaName = schemaName[2:]
|
schemaName = schemaName[2:]
|
||||||
@ -496,7 +496,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
m, mod, realTypes := getModel(schemaName)
|
m, mod, realTypes := getModel(schemaName)
|
||||||
schema.Ref = "#/definitions/" + m
|
schema.Ref = "#/definitions/" + m
|
||||||
if _, ok := modelsList[pkgpath+controllerName]; !ok {
|
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
|
modelsList[pkgpath+controllerName][schemaName] = mod
|
||||||
appendModels(pkgpath, controllerName, realTypes)
|
appendModels(pkgpath, controllerName, realTypes)
|
||||||
@ -518,7 +518,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
para := swagger.Parameter{}
|
para := swagger.Parameter{}
|
||||||
p := getparams(strings.TrimSpace(t[len("@Param "):]))
|
p := getparams(strings.TrimSpace(t[len("@Param "):]))
|
||||||
if len(p) < 4 {
|
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]
|
para.Name = p[0]
|
||||||
switch p[1] {
|
switch p[1] {
|
||||||
@ -533,7 +533,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
case "body":
|
case "body":
|
||||||
break
|
break
|
||||||
default:
|
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]
|
para.In = p[1]
|
||||||
pp := strings.Split(p[2], ".")
|
pp := strings.Split(p[2], ".")
|
||||||
@ -544,7 +544,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
Ref: "#/definitions/" + m,
|
Ref: "#/definitions/" + m,
|
||||||
}
|
}
|
||||||
if _, ok := modelsList[pkgpath+controllerName]; !ok {
|
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
|
modelsList[pkgpath+controllerName][typ] = mod
|
||||||
appendModels(pkgpath, controllerName, realTypes)
|
appendModels(pkgpath, controllerName, realTypes)
|
||||||
@ -564,7 +564,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
paraType = typeFormat[0]
|
paraType = typeFormat[0]
|
||||||
paraFormat = typeFormat[1]
|
paraFormat = typeFormat[1]
|
||||||
} else {
|
} 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 {
|
if isArray {
|
||||||
para.Type = "array"
|
para.Type = "array"
|
||||||
@ -717,7 +717,7 @@ func getModel(str string) (objectname string, m swagger.Schema, realTypes []stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m.Title == "" {
|
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
|
// TODO remove when all type have been supported
|
||||||
//os.Exit(1)
|
//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) {
|
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)
|
ts, ok := d.Decl.(*ast.TypeSpec)
|
||||||
if !ok {
|
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...
|
// TODO support other types, such as `ArrayType`, `MapType`, `InterfaceType` etc...
|
||||||
st, ok := ts.Type.(*ast.StructType)
|
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)
|
mp.Default = str2RealType(res[1], realType)
|
||||||
|
|
||||||
} else {
|
} 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
|
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
|
// append models
|
||||||
func appendModels(pkgpath, controllerName string, realTypes []string) {
|
func appendModels(pkgpath, controllerName string, realTypes []string) {
|
||||||
for _, realType := range realTypes {
|
for _, realType := range realTypes {
|
||||||
@ -956,7 +946,7 @@ func str2RealType(s string, typ string) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
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
|
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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package colors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -53,7 +53,7 @@ func NewModeColorWriter(w io.Writer, mode outputMode) io.Writer {
|
|||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
func bold(message string) string {
|
func Bold(message string) string {
|
||||||
return fmt.Sprintf("\x1b[1m%s\x1b[21m", message)
|
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)
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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
|
// +build !windows
|
||||||
|
|
||||||
package main
|
package colors
|
||||||
|
|
||||||
import "io"
|
import "io"
|
||||||
|
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package main
|
package colors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
@ -11,7 +11,7 @@
|
|||||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
// License for the specific language governing permissions and limitations
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
package main
|
package beeLogger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@ -22,6 +22,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/beego/bee/logger/colors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errInvalidLogLevel = errors.New("logger: invalid log level")
|
var errInvalidLogLevel = errors.New("logger: invalid log level")
|
||||||
@ -59,6 +62,8 @@ type LogRecord struct {
|
|||||||
LineNo int
|
LineNo int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var Log = GetBeeLogger(os.Stdout)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
logRecordTemplate *template.Template
|
logRecordTemplate *template.Template
|
||||||
debugLogRecordTemplate *template.Template
|
debugLogRecordTemplate *template.Template
|
||||||
@ -80,11 +85,15 @@ func GetBeeLogger(w io.Writer) *BeeLogger {
|
|||||||
"EndLine": EndLine,
|
"EndLine": EndLine,
|
||||||
}
|
}
|
||||||
logRecordTemplate, err = template.New("simpleLogFormat").Funcs(funcs).Parse(simpleLogFormat)
|
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)
|
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
|
return instance
|
||||||
}
|
}
|
||||||
@ -93,7 +102,17 @@ func GetBeeLogger(w io.Writer) *BeeLogger {
|
|||||||
func (l *BeeLogger) SetOutput(w io.Writer) {
|
func (l *BeeLogger) SetOutput(w io.Writer) {
|
||||||
l.mu.Lock()
|
l.mu.Lock()
|
||||||
defer l.mu.Unlock()
|
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 {
|
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 {
|
func (l *BeeLogger) getColorLevel(level int) string {
|
||||||
switch level {
|
switch level {
|
||||||
case levelCritical:
|
case levelCritical:
|
||||||
return RedBold(l.getLevelTag(level))
|
return colors.RedBold(l.getLevelTag(level))
|
||||||
case levelFatal:
|
case levelFatal:
|
||||||
return RedBold(l.getLevelTag(level))
|
return colors.RedBold(l.getLevelTag(level))
|
||||||
case levelInfo:
|
case levelInfo:
|
||||||
return BlueBold(l.getLevelTag(level))
|
return colors.BlueBold(l.getLevelTag(level))
|
||||||
case levelHint:
|
case levelHint:
|
||||||
return CyanBold(l.getLevelTag(level))
|
return colors.CyanBold(l.getLevelTag(level))
|
||||||
case levelDebug:
|
case levelDebug:
|
||||||
return YellowBold(l.getLevelTag(level))
|
return colors.YellowBold(l.getLevelTag(level))
|
||||||
case levelError:
|
case levelError:
|
||||||
return RedBold(l.getLevelTag(level))
|
return colors.RedBold(l.getLevelTag(level))
|
||||||
case levelWarn:
|
case levelWarn:
|
||||||
return YellowBold(l.getLevelTag(level))
|
return colors.YellowBold(l.getLevelTag(level))
|
||||||
case levelSuccess:
|
case levelSuccess:
|
||||||
return GreenBold(l.getLevelTag(level))
|
return colors.GreenBold(l.getLevelTag(level))
|
||||||
default:
|
default:
|
||||||
panic(errInvalidLogLevel)
|
panic(errInvalidLogLevel)
|
||||||
}
|
}
|
||||||
@ -157,15 +176,17 @@ func (l *BeeLogger) mustLog(level int, message string, args ...interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := logRecordTemplate.Execute(l.output, record)
|
err := logRecordTemplate.Execute(l.output, record)
|
||||||
MustCheck(err)
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mustLogDebug logs a debug message only if debug mode
|
// mustLogDebug logs a debug message only if debug mode
|
||||||
// is enabled. i.e. DEBUG_ENABLED="1"
|
// is enabled. i.e. DEBUG_ENABLED="1"
|
||||||
func (l *BeeLogger) mustLogDebug(message string, file string, line int, args ...interface{}) {
|
func (l *BeeLogger) mustLogDebug(message string, file string, line int, args ...interface{}) {
|
||||||
if !IsDebugEnabled() {
|
//if !IsDebugEnabled() {
|
||||||
return
|
// return
|
||||||
}
|
//}
|
||||||
|
|
||||||
// Change the output to Stderr
|
// Change the output to Stderr
|
||||||
l.SetOutput(os.Stderr)
|
l.SetOutput(os.Stderr)
|
||||||
@ -179,7 +200,9 @@ func (l *BeeLogger) mustLogDebug(message string, file string, line int, args ...
|
|||||||
Filename: filepath.Base(file),
|
Filename: filepath.Base(file),
|
||||||
}
|
}
|
||||||
err := debugLogRecordTemplate.Execute(l.output, record)
|
err := debugLogRecordTemplate.Execute(l.output, record)
|
||||||
MustCheck(err)
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug outputs a debug log message
|
// 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
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package main
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -26,7 +26,9 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"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
|
// 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
|
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.
|
// IsExist returns whether a file or directory exists.
|
||||||
func isExist(path string) bool {
|
func IsExist(path string) bool {
|
||||||
_, err := os.Stat(path)
|
_, err := os.Stat(path)
|
||||||
return err == nil || os.IsExist(err)
|
return err == nil || os.IsExist(err)
|
||||||
}
|
}
|
||||||
@ -99,7 +91,7 @@ func IsBeegoProject(thePath string) bool {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
if err := <-c; err != nil {
|
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 {
|
if len(mainFiles) > 0 {
|
||||||
@ -113,7 +105,7 @@ func IsBeegoProject(thePath string) bool {
|
|||||||
func SearchGOPATHs(app string) (bool, string, string) {
|
func SearchGOPATHs(app string) (bool, string, string) {
|
||||||
gps := GetGOPATHs()
|
gps := GetGOPATHs()
|
||||||
if len(gps) == 0 {
|
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)
|
// Lookup the application inside the user workspace(s)
|
||||||
@ -127,7 +119,7 @@ func SearchGOPATHs(app string) (bool, string, string) {
|
|||||||
currentPath = app
|
currentPath = app
|
||||||
}
|
}
|
||||||
|
|
||||||
if isExist(currentPath) {
|
if IsExist(currentPath) {
|
||||||
return true, gopath, 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
|
// 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
|
// 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)")
|
// before calling askForConfirmation. E.g. fmt.Println("WARNING: Are you sure? (yes/no)")
|
||||||
func askForConfirmation() bool {
|
func AskForConfirmation() bool {
|
||||||
var response string
|
var response string
|
||||||
_, err := fmt.Scanln(&response)
|
_, err := fmt.Scanln(&response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("%s", err)
|
beeLogger.Log.Fatalf("%s", err)
|
||||||
}
|
}
|
||||||
okayResponses := []string{"y", "Y", "yes", "Yes", "YES"}
|
okayResponses := []string{"y", "Y", "yes", "Yes", "YES"}
|
||||||
nokayResponses := []string{"n", "N", "no", "No", "NO"}
|
nokayResponses := []string{"n", "N", "no", "No", "NO"}
|
||||||
@ -153,7 +145,7 @@ func askForConfirmation() bool {
|
|||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Please type yes or no and then press enter:")
|
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
|
// snake string, XxYy to xx_yy
|
||||||
func snakeString(s string) string {
|
func SnakeString(s string) string {
|
||||||
data := make([]byte, 0, len(s)*2)
|
data := make([]byte, 0, len(s)*2)
|
||||||
j := false
|
j := false
|
||||||
num := len(s)
|
num := len(s)
|
||||||
@ -184,17 +176,17 @@ func snakeString(s string) string {
|
|||||||
return strings.ToLower(string(data[:]))
|
return strings.ToLower(string(data[:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func camelString(s string) string {
|
func CamelString(s string) string {
|
||||||
data := make([]byte, 0, len(s))
|
data := make([]byte, 0, len(s))
|
||||||
j := false
|
j := false
|
||||||
k := false
|
k := false
|
||||||
num := len(s) - 1
|
num := len(s) - 1
|
||||||
for i := 0; i <= num; i++ {
|
for i := 0; i <= num; i++ {
|
||||||
d := s[i]
|
d := s[i]
|
||||||
if k == false && d >= 'A' && d <= 'Z' {
|
if !k && d >= 'A' && d <= 'Z' {
|
||||||
k = true
|
k = true
|
||||||
}
|
}
|
||||||
if d >= 'a' && d <= 'z' && (j || k == false) {
|
if d >= 'a' && d <= 'z' && (j || !k) {
|
||||||
d = d - 32
|
d = d - 32
|
||||||
j = false
|
j = false
|
||||||
k = true
|
k = true
|
||||||
@ -210,7 +202,7 @@ func camelString(s string) string {
|
|||||||
|
|
||||||
// camelCase converts a _ delimited string to camel case
|
// camelCase converts a _ delimited string to camel case
|
||||||
// e.g. very_important_person => VeryImportantPerson
|
// e.g. very_important_person => VeryImportantPerson
|
||||||
func camelCase(in string) string {
|
func CamelCase(in string) string {
|
||||||
tokens := strings.Split(in, "_")
|
tokens := strings.Split(in, "_")
|
||||||
for i := range tokens {
|
for i := range tokens {
|
||||||
tokens[i] = strings.Title(strings.Trim(tokens[i], " "))
|
tokens[i] = strings.Title(strings.Trim(tokens[i], " "))
|
||||||
@ -219,25 +211,13 @@ func camelCase(in string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// formatSourceCode formats source files
|
// formatSourceCode formats source files
|
||||||
func formatSourceCode(filename string) {
|
func FormatSourceCode(filename string) {
|
||||||
cmd := exec.Command("gofmt", "-w", filename)
|
cmd := exec.Command("gofmt", "-w", filename)
|
||||||
if err := cmd.Run(); err != nil {
|
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
|
// CloseFile attempts to close the passed file
|
||||||
// or panics with the actual error
|
// or panics with the actual error
|
||||||
func CloseFile(f *os.File) {
|
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
|
// WriteToFile creates a file and writes content to it
|
||||||
func WriteToFile(filename, content string) {
|
func WriteToFile(filename, content string) {
|
||||||
f, err := os.Create(filename)
|
f, err := os.Create(filename)
|
||||||
@ -273,13 +248,13 @@ func IsDebugEnabled() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// __FILE__ returns the file name in which the function was invoked
|
// __FILE__ returns the file name in which the function was invoked
|
||||||
func __FILE__() string {
|
func FILE() string {
|
||||||
_, file, _, _ := runtime.Caller(1)
|
_, file, _, _ := runtime.Caller(1)
|
||||||
return file
|
return file
|
||||||
}
|
}
|
||||||
|
|
||||||
// __LINE__ returns the line number at which the function was invoked
|
// __LINE__ returns the line number at which the function was invoked
|
||||||
func __LINE__() int {
|
func LINE() int {
|
||||||
_, _, line, _ := runtime.Caller(1)
|
_, _, line, _ := runtime.Caller(1)
|
||||||
return line
|
return line
|
||||||
}
|
}
|
||||||
@ -288,9 +263,9 @@ func __LINE__() int {
|
|||||||
func BeeFuncMap() template.FuncMap {
|
func BeeFuncMap() template.FuncMap {
|
||||||
return template.FuncMap{
|
return template.FuncMap{
|
||||||
"trim": strings.TrimSpace,
|
"trim": strings.TrimSpace,
|
||||||
"bold": bold,
|
"bold": colors.Bold,
|
||||||
"headline": MagentaBold,
|
"headline": colors.MagentaBold,
|
||||||
"foldername": RedBold,
|
"foldername": colors.RedBold,
|
||||||
"endline": EndLine,
|
"endline": EndLine,
|
||||||
"tmpltostr": TmplToString,
|
"tmpltostr": TmplToString,
|
||||||
}
|
}
|
||||||
@ -307,3 +282,59 @@ func TmplToString(tmpl string, data interface{}) string {
|
|||||||
|
|
||||||
return doc.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)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user