mirror of
https://github.com/beego/bee.git
synced 2024-11-22 10:10:53 +00:00
commit
f8447477d9
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,6 +6,7 @@
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
.idea
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
|
20
Makefile
Normal file
20
Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
.PHONY: all test clean build install
|
||||
|
||||
GOFLAGS ?= $(GOFLAGS:)
|
||||
|
||||
all: install test
|
||||
|
||||
build:
|
||||
go build $(GOFLAGS) ./...
|
||||
|
||||
install:
|
||||
go get $(GOFLAGS) ./...
|
||||
|
||||
test: install
|
||||
go test $(GOFLAGS) ./...
|
||||
|
||||
bench: install
|
||||
go test -run=NONE -bench=. $(GOFLAGS) ./...
|
||||
|
||||
clean:
|
||||
go clean $(GOFLAGS) -i ./...
|
69
apiapp.go
69
apiapp.go
@ -298,7 +298,7 @@ type ObjectController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
// @Title create
|
||||
// @Title Create
|
||||
// @Description create object
|
||||
// @Param body body models.Object true "The object content"
|
||||
// @Success 200 {string} models.Object.Id
|
||||
@ -342,7 +342,7 @@ func (o *ObjectController) GetAll() {
|
||||
o.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title update
|
||||
// @Title Update
|
||||
// @Description update the object
|
||||
// @Param objectId path string true "The objectid you want to update"
|
||||
// @Param body body models.Object true "The body"
|
||||
@ -363,7 +363,7 @@ func (o *ObjectController) Put() {
|
||||
o.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title delete
|
||||
// @Title Delete
|
||||
// @Description delete the object
|
||||
// @Param objectId path string true "The objectId you want to delete"
|
||||
// @Success 200 {string} delete success!
|
||||
@ -391,7 +391,7 @@ type UserController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
// @Title createUser
|
||||
// @Title CreateUser
|
||||
// @Description create users
|
||||
// @Param body body models.User true "body for user content"
|
||||
// @Success 200 {int} models.User.Id
|
||||
@ -405,7 +405,7 @@ func (u *UserController) Post() {
|
||||
u.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title Get
|
||||
// @Title GetAll
|
||||
// @Description get all Users
|
||||
// @Success 200 {object} models.User
|
||||
// @router / [get]
|
||||
@ -434,7 +434,7 @@ func (u *UserController) Get() {
|
||||
u.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title update
|
||||
// @Title Update
|
||||
// @Description update the user
|
||||
// @Param uid path string true "The uid you want to update"
|
||||
// @Param body body models.User true "body for user content"
|
||||
@ -456,7 +456,7 @@ func (u *UserController) Put() {
|
||||
u.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title delete
|
||||
// @Title Delete
|
||||
// @Description delete the user
|
||||
// @Param uid path string true "The uid you want to delete"
|
||||
// @Success 200 {string} delete success!
|
||||
@ -469,7 +469,7 @@ func (u *UserController) Delete() {
|
||||
u.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title login
|
||||
// @Title Login
|
||||
// @Description Logs user into the system
|
||||
// @Param username query string true "The username for login"
|
||||
// @Param password query string true "The password for login"
|
||||
@ -548,6 +548,8 @@ func init() {
|
||||
func createapi(cmd *Command, args []string) int {
|
||||
ShowShortVersionBanner()
|
||||
|
||||
w := NewColorWriter(os.Stdout)
|
||||
|
||||
if len(args) < 1 {
|
||||
ColorLog("[ERRO] Argument [appname] is missing\n")
|
||||
os.Exit(2)
|
||||
@ -571,21 +573,21 @@ func createapi(cmd *Command, args []string) int {
|
||||
ColorLog("[INFO] Creating API...\n")
|
||||
|
||||
os.MkdirAll(apppath, 0755)
|
||||
fmt.Println("\tcreate\t", apppath)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "conf"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "conf"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf"), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "controllers"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "controllers"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers"), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "docs"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "docs"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "docs"), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "tests"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "tests"))
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "conf", "app.conf"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests"), "\x1b[0m")
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "conf", "app.conf"),
|
||||
strings.Replace(apiconf, "{{.Appname}}", path.Base(args[0]), -1))
|
||||
|
||||
if conn != "" {
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "main.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
maingoContent := strings.Replace(apiMainconngo, "{{.Appname}}", packpath, -1)
|
||||
maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(driver), -1)
|
||||
if driver == "mysql" {
|
||||
@ -607,36 +609,36 @@ func createapi(cmd *Command, args []string) int {
|
||||
generateAppcode(string(driver), string(conn), "3", string(tables), path.Join(apppath, args[0]))
|
||||
} else {
|
||||
os.Mkdir(path.Join(apppath, "models"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "models"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models"), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "routers"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "routers") + string(path.Separator))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers")+string(path.Separator), "\x1b[0m")
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "controllers", "object.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "object.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "controllers", "object.go"),
|
||||
strings.Replace(apiControllers, "{{.Appname}}", packpath, -1))
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "controllers", "user.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "user.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "controllers", "user.go"),
|
||||
strings.Replace(apiControllers2, "{{.Appname}}", packpath, -1))
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "tests", "default_test.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests", "default_test.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "tests", "default_test.go"),
|
||||
strings.Replace(apiTests, "{{.Appname}}", packpath, -1))
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "routers", "router.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "routers", "router.go"),
|
||||
strings.Replace(apirouter, "{{.Appname}}", packpath, -1))
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "models", "object.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "object.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "models", "object.go"), apiModels)
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "models", "user.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "user.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "models", "user.go"), apiModels2)
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "docs", "doc.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "docs", "doc.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "docs", "doc.go"), "package docs")
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "main.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "main.go"),
|
||||
strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1))
|
||||
}
|
||||
@ -645,19 +647,22 @@ func createapi(cmd *Command, args []string) int {
|
||||
}
|
||||
|
||||
func checkEnv(appname string) (apppath, packpath string, err error) {
|
||||
gopath := os.Getenv("GOPATH")
|
||||
Debugf("gopath:%s", gopath)
|
||||
if gopath == "" {
|
||||
err = fmt.Errorf("you should set GOPATH in the env")
|
||||
return
|
||||
gps := GetGOPATHs()
|
||||
if len(gps) == 0 {
|
||||
ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty")
|
||||
os.Exit(2)
|
||||
}
|
||||
// In case of multiple paths in the GOPATH, by default
|
||||
// we use the first path
|
||||
gopath := gps[0]
|
||||
Debugf("GOPATH: %s", gopath)
|
||||
|
||||
gosrcpath := path.Join(gopath, "src")
|
||||
apppath = path.Join(gosrcpath, appname)
|
||||
|
||||
if _, e := os.Stat(apppath); os.IsNotExist(e) == false {
|
||||
err = fmt.Errorf("Cannot create application without removing `%s` first.", apppath)
|
||||
ColorLog("[ERRO] Path `%s` already exists\n", apppath)
|
||||
err = fmt.Errorf("Cannot create application without removing '%s' first.", apppath)
|
||||
ColorLog("[ERRO] Path '%s' already exists\n", apppath)
|
||||
return
|
||||
}
|
||||
packpath = strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/")
|
||||
|
@ -21,11 +21,12 @@ type vars struct {
|
||||
BeegoVersion string
|
||||
}
|
||||
|
||||
// Now returns the current local time in the specified layout
|
||||
func Now(layout string) string {
|
||||
return time.Now().Format(layout)
|
||||
}
|
||||
|
||||
// Init load the banner and prints it to output
|
||||
// InitBanner loads the banner and prints it to output
|
||||
// All errors are ignored, the application will not
|
||||
// print the banner in case of error.
|
||||
func InitBanner(out io.Writer, in io.Reader) {
|
||||
@ -55,7 +56,7 @@ func show(out io.Writer, content string) {
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
t.Execute(out, vars{
|
||||
err = t.Execute(out, vars{
|
||||
runtime.Version(),
|
||||
runtime.GOOS,
|
||||
runtime.GOARCH,
|
||||
@ -66,4 +67,7 @@ func show(out io.Writer, content string) {
|
||||
version,
|
||||
getBeegoVersion(),
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
2
bee.go
2
bee.go
@ -25,7 +25,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const version = "1.4.1"
|
||||
const version = "1.5.0"
|
||||
|
||||
type Command struct {
|
||||
// Run runs the command.
|
||||
|
51
color.go
Normal file
51
color.go
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
|
||||
import "io"
|
||||
|
||||
type outputMode int
|
||||
|
||||
// DiscardNonColorEscSeq supports the divided color escape sequence.
|
||||
// But non-color escape sequence is not output.
|
||||
// Please use the OutputNonColorEscSeq If you want to output a non-color
|
||||
// escape sequences such as ncurses. However, it does not support the divided
|
||||
// color escape sequence.
|
||||
const (
|
||||
_ outputMode = iota
|
||||
DiscardNonColorEscSeq
|
||||
OutputNonColorEscSeq
|
||||
)
|
||||
|
||||
// NewColorWriter creates and initializes a new ansiColorWriter
|
||||
// using io.Writer w as its initial contents.
|
||||
// In the console of Windows, which change the foreground and background
|
||||
// colors of the text by the escape sequence.
|
||||
// In the console of other systems, which writes to w all text.
|
||||
func NewColorWriter(w io.Writer) io.Writer {
|
||||
return NewModeColorWriter(w, DiscardNonColorEscSeq)
|
||||
}
|
||||
|
||||
// NewModeColorWriter create and initializes a new ansiColorWriter
|
||||
// by specifying the outputMode.
|
||||
func NewModeColorWriter(w io.Writer, mode outputMode) io.Writer {
|
||||
if _, ok := w.(*colorWriter); !ok {
|
||||
return &colorWriter{
|
||||
w: w,
|
||||
mode: mode,
|
||||
}
|
||||
}
|
||||
return w
|
||||
}
|
28
colorwriter.go
Normal file
28
colorwriter.go
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
// +build !windows
|
||||
|
||||
package main
|
||||
|
||||
import "io"
|
||||
|
||||
type colorWriter struct {
|
||||
w io.Writer
|
||||
mode outputMode
|
||||
}
|
||||
|
||||
func (cw *colorWriter) Write(p []byte) (int, error) {
|
||||
return cw.w.Write(p)
|
||||
}
|
427
colorwriter_windows.go
Normal file
427
colorwriter_windows.go
Normal file
@ -0,0 +1,427 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type csiState int
|
||||
|
||||
const (
|
||||
outsideCsiCode csiState = iota
|
||||
firstCsiCode
|
||||
secondCsiCode
|
||||
)
|
||||
|
||||
type parseResult int
|
||||
|
||||
const (
|
||||
noConsole parseResult = iota
|
||||
changedColor
|
||||
unknown
|
||||
)
|
||||
|
||||
type colorWriter struct {
|
||||
w io.Writer
|
||||
mode outputMode
|
||||
state csiState
|
||||
paramStartBuf bytes.Buffer
|
||||
paramBuf bytes.Buffer
|
||||
}
|
||||
|
||||
const (
|
||||
firstCsiChar byte = '\x1b'
|
||||
secondeCsiChar byte = '['
|
||||
separatorChar byte = ';'
|
||||
sgrCode byte = 'm'
|
||||
)
|
||||
|
||||
const (
|
||||
foregroundBlue = uint16(0x0001)
|
||||
foregroundGreen = uint16(0x0002)
|
||||
foregroundRed = uint16(0x0004)
|
||||
foregroundIntensity = uint16(0x0008)
|
||||
backgroundBlue = uint16(0x0010)
|
||||
backgroundGreen = uint16(0x0020)
|
||||
backgroundRed = uint16(0x0040)
|
||||
backgroundIntensity = uint16(0x0080)
|
||||
underscore = uint16(0x8000)
|
||||
|
||||
foregroundMask = foregroundBlue | foregroundGreen | foregroundRed | foregroundIntensity
|
||||
backgroundMask = backgroundBlue | backgroundGreen | backgroundRed | backgroundIntensity
|
||||
)
|
||||
|
||||
const (
|
||||
ansiReset = "0"
|
||||
ansiIntensityOn = "1"
|
||||
ansiIntensityOff = "21"
|
||||
ansiUnderlineOn = "4"
|
||||
ansiUnderlineOff = "24"
|
||||
ansiBlinkOn = "5"
|
||||
ansiBlinkOff = "25"
|
||||
|
||||
ansiForegroundBlack = "30"
|
||||
ansiForegroundRed = "31"
|
||||
ansiForegroundGreen = "32"
|
||||
ansiForegroundYellow = "33"
|
||||
ansiForegroundBlue = "34"
|
||||
ansiForegroundMagenta = "35"
|
||||
ansiForegroundCyan = "36"
|
||||
ansiForegroundWhite = "37"
|
||||
ansiForegroundDefault = "39"
|
||||
|
||||
ansiBackgroundBlack = "40"
|
||||
ansiBackgroundRed = "41"
|
||||
ansiBackgroundGreen = "42"
|
||||
ansiBackgroundYellow = "43"
|
||||
ansiBackgroundBlue = "44"
|
||||
ansiBackgroundMagenta = "45"
|
||||
ansiBackgroundCyan = "46"
|
||||
ansiBackgroundWhite = "47"
|
||||
ansiBackgroundDefault = "49"
|
||||
|
||||
ansiLightForegroundGray = "90"
|
||||
ansiLightForegroundRed = "91"
|
||||
ansiLightForegroundGreen = "92"
|
||||
ansiLightForegroundYellow = "93"
|
||||
ansiLightForegroundBlue = "94"
|
||||
ansiLightForegroundMagenta = "95"
|
||||
ansiLightForegroundCyan = "96"
|
||||
ansiLightForegroundWhite = "97"
|
||||
|
||||
ansiLightBackgroundGray = "100"
|
||||
ansiLightBackgroundRed = "101"
|
||||
ansiLightBackgroundGreen = "102"
|
||||
ansiLightBackgroundYellow = "103"
|
||||
ansiLightBackgroundBlue = "104"
|
||||
ansiLightBackgroundMagenta = "105"
|
||||
ansiLightBackgroundCyan = "106"
|
||||
ansiLightBackgroundWhite = "107"
|
||||
)
|
||||
|
||||
type drawType int
|
||||
|
||||
const (
|
||||
foreground drawType = iota
|
||||
background
|
||||
)
|
||||
|
||||
type winColor struct {
|
||||
code uint16
|
||||
drawType drawType
|
||||
}
|
||||
|
||||
var colorMap = map[string]winColor{
|
||||
ansiForegroundBlack: {0, foreground},
|
||||
ansiForegroundRed: {foregroundRed, foreground},
|
||||
ansiForegroundGreen: {foregroundGreen, foreground},
|
||||
ansiForegroundYellow: {foregroundRed | foregroundGreen, foreground},
|
||||
ansiForegroundBlue: {foregroundBlue, foreground},
|
||||
ansiForegroundMagenta: {foregroundRed | foregroundBlue, foreground},
|
||||
ansiForegroundCyan: {foregroundGreen | foregroundBlue, foreground},
|
||||
ansiForegroundWhite: {foregroundRed | foregroundGreen | foregroundBlue, foreground},
|
||||
ansiForegroundDefault: {foregroundRed | foregroundGreen | foregroundBlue, foreground},
|
||||
|
||||
ansiBackgroundBlack: {0, background},
|
||||
ansiBackgroundRed: {backgroundRed, background},
|
||||
ansiBackgroundGreen: {backgroundGreen, background},
|
||||
ansiBackgroundYellow: {backgroundRed | backgroundGreen, background},
|
||||
ansiBackgroundBlue: {backgroundBlue, background},
|
||||
ansiBackgroundMagenta: {backgroundRed | backgroundBlue, background},
|
||||
ansiBackgroundCyan: {backgroundGreen | backgroundBlue, background},
|
||||
ansiBackgroundWhite: {backgroundRed | backgroundGreen | backgroundBlue, background},
|
||||
ansiBackgroundDefault: {0, background},
|
||||
|
||||
ansiLightForegroundGray: {foregroundIntensity, foreground},
|
||||
ansiLightForegroundRed: {foregroundIntensity | foregroundRed, foreground},
|
||||
ansiLightForegroundGreen: {foregroundIntensity | foregroundGreen, foreground},
|
||||
ansiLightForegroundYellow: {foregroundIntensity | foregroundRed | foregroundGreen, foreground},
|
||||
ansiLightForegroundBlue: {foregroundIntensity | foregroundBlue, foreground},
|
||||
ansiLightForegroundMagenta: {foregroundIntensity | foregroundRed | foregroundBlue, foreground},
|
||||
ansiLightForegroundCyan: {foregroundIntensity | foregroundGreen | foregroundBlue, foreground},
|
||||
ansiLightForegroundWhite: {foregroundIntensity | foregroundRed | foregroundGreen | foregroundBlue, foreground},
|
||||
|
||||
ansiLightBackgroundGray: {backgroundIntensity, background},
|
||||
ansiLightBackgroundRed: {backgroundIntensity | backgroundRed, background},
|
||||
ansiLightBackgroundGreen: {backgroundIntensity | backgroundGreen, background},
|
||||
ansiLightBackgroundYellow: {backgroundIntensity | backgroundRed | backgroundGreen, background},
|
||||
ansiLightBackgroundBlue: {backgroundIntensity | backgroundBlue, background},
|
||||
ansiLightBackgroundMagenta: {backgroundIntensity | backgroundRed | backgroundBlue, background},
|
||||
ansiLightBackgroundCyan: {backgroundIntensity | backgroundGreen | backgroundBlue, background},
|
||||
ansiLightBackgroundWhite: {backgroundIntensity | backgroundRed | backgroundGreen | backgroundBlue, background},
|
||||
}
|
||||
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute")
|
||||
procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
|
||||
defaultAttr *textAttributes
|
||||
)
|
||||
|
||||
func init() {
|
||||
screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout))
|
||||
if screenInfo != nil {
|
||||
colorMap[ansiForegroundDefault] = winColor{
|
||||
screenInfo.WAttributes & (foregroundRed | foregroundGreen | foregroundBlue),
|
||||
foreground,
|
||||
}
|
||||
colorMap[ansiBackgroundDefault] = winColor{
|
||||
screenInfo.WAttributes & (backgroundRed | backgroundGreen | backgroundBlue),
|
||||
background,
|
||||
}
|
||||
defaultAttr = convertTextAttr(screenInfo.WAttributes)
|
||||
}
|
||||
}
|
||||
|
||||
type coord struct {
|
||||
X, Y int16
|
||||
}
|
||||
|
||||
type smallRect struct {
|
||||
Left, Top, Right, Bottom int16
|
||||
}
|
||||
|
||||
type consoleScreenBufferInfo struct {
|
||||
DwSize coord
|
||||
DwCursorPosition coord
|
||||
WAttributes uint16
|
||||
SrWindow smallRect
|
||||
DwMaximumWindowSize coord
|
||||
}
|
||||
|
||||
func getConsoleScreenBufferInfo(hConsoleOutput uintptr) *consoleScreenBufferInfo {
|
||||
var csbi consoleScreenBufferInfo
|
||||
ret, _, _ := procGetConsoleScreenBufferInfo.Call(
|
||||
hConsoleOutput,
|
||||
uintptr(unsafe.Pointer(&csbi)))
|
||||
if ret == 0 {
|
||||
return nil
|
||||
}
|
||||
return &csbi
|
||||
}
|
||||
|
||||
func setConsoleTextAttribute(hConsoleOutput uintptr, wAttributes uint16) bool {
|
||||
ret, _, _ := procSetConsoleTextAttribute.Call(
|
||||
hConsoleOutput,
|
||||
uintptr(wAttributes))
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
type textAttributes struct {
|
||||
foregroundColor uint16
|
||||
backgroundColor uint16
|
||||
foregroundIntensity uint16
|
||||
backgroundIntensity uint16
|
||||
underscore uint16
|
||||
otherAttributes uint16
|
||||
}
|
||||
|
||||
func convertTextAttr(winAttr uint16) *textAttributes {
|
||||
fgColor := winAttr & (foregroundRed | foregroundGreen | foregroundBlue)
|
||||
bgColor := winAttr & (backgroundRed | backgroundGreen | backgroundBlue)
|
||||
fgIntensity := winAttr & foregroundIntensity
|
||||
bgIntensity := winAttr & backgroundIntensity
|
||||
underline := winAttr & underscore
|
||||
otherAttributes := winAttr &^ (foregroundMask | backgroundMask | underscore)
|
||||
return &textAttributes{fgColor, bgColor, fgIntensity, bgIntensity, underline, otherAttributes}
|
||||
}
|
||||
|
||||
func convertWinAttr(textAttr *textAttributes) uint16 {
|
||||
var winAttr uint16
|
||||
winAttr |= textAttr.foregroundColor
|
||||
winAttr |= textAttr.backgroundColor
|
||||
winAttr |= textAttr.foregroundIntensity
|
||||
winAttr |= textAttr.backgroundIntensity
|
||||
winAttr |= textAttr.underscore
|
||||
winAttr |= textAttr.otherAttributes
|
||||
return winAttr
|
||||
}
|
||||
|
||||
func changeColor(param []byte) parseResult {
|
||||
screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout))
|
||||
if screenInfo == nil {
|
||||
return noConsole
|
||||
}
|
||||
|
||||
winAttr := convertTextAttr(screenInfo.WAttributes)
|
||||
strParam := string(param)
|
||||
if len(strParam) <= 0 {
|
||||
strParam = "0"
|
||||
}
|
||||
csiParam := strings.Split(strParam, string(separatorChar))
|
||||
for _, p := range csiParam {
|
||||
c, ok := colorMap[p]
|
||||
switch {
|
||||
case !ok:
|
||||
switch p {
|
||||
case ansiReset:
|
||||
winAttr.foregroundColor = defaultAttr.foregroundColor
|
||||
winAttr.backgroundColor = defaultAttr.backgroundColor
|
||||
winAttr.foregroundIntensity = defaultAttr.foregroundIntensity
|
||||
winAttr.backgroundIntensity = defaultAttr.backgroundIntensity
|
||||
winAttr.underscore = 0
|
||||
winAttr.otherAttributes = 0
|
||||
case ansiIntensityOn:
|
||||
winAttr.foregroundIntensity = foregroundIntensity
|
||||
case ansiIntensityOff:
|
||||
winAttr.foregroundIntensity = 0
|
||||
case ansiUnderlineOn:
|
||||
winAttr.underscore = underscore
|
||||
case ansiUnderlineOff:
|
||||
winAttr.underscore = 0
|
||||
case ansiBlinkOn:
|
||||
winAttr.backgroundIntensity = backgroundIntensity
|
||||
case ansiBlinkOff:
|
||||
winAttr.backgroundIntensity = 0
|
||||
default:
|
||||
// unknown code
|
||||
}
|
||||
case c.drawType == foreground:
|
||||
winAttr.foregroundColor = c.code
|
||||
case c.drawType == background:
|
||||
winAttr.backgroundColor = c.code
|
||||
}
|
||||
}
|
||||
winTextAttribute := convertWinAttr(winAttr)
|
||||
setConsoleTextAttribute(uintptr(syscall.Stdout), winTextAttribute)
|
||||
|
||||
return changedColor
|
||||
}
|
||||
|
||||
func parseEscapeSequence(command byte, param []byte) parseResult {
|
||||
if defaultAttr == nil {
|
||||
return noConsole
|
||||
}
|
||||
|
||||
switch command {
|
||||
case sgrCode:
|
||||
return changeColor(param)
|
||||
default:
|
||||
return unknown
|
||||
}
|
||||
}
|
||||
|
||||
func (cw *colorWriter) flushBuffer() (int, error) {
|
||||
return cw.flushTo(cw.w)
|
||||
}
|
||||
|
||||
func (cw *colorWriter) resetBuffer() (int, error) {
|
||||
return cw.flushTo(nil)
|
||||
}
|
||||
|
||||
func (cw *colorWriter) flushTo(w io.Writer) (int, error) {
|
||||
var n1, n2 int
|
||||
var err error
|
||||
|
||||
startBytes := cw.paramStartBuf.Bytes()
|
||||
cw.paramStartBuf.Reset()
|
||||
if w != nil {
|
||||
n1, err = cw.w.Write(startBytes)
|
||||
if err != nil {
|
||||
return n1, err
|
||||
}
|
||||
} else {
|
||||
n1 = len(startBytes)
|
||||
}
|
||||
paramBytes := cw.paramBuf.Bytes()
|
||||
cw.paramBuf.Reset()
|
||||
if w != nil {
|
||||
n2, err = cw.w.Write(paramBytes)
|
||||
if err != nil {
|
||||
return n1 + n2, err
|
||||
}
|
||||
} else {
|
||||
n2 = len(paramBytes)
|
||||
}
|
||||
return n1 + n2, nil
|
||||
}
|
||||
|
||||
func isParameterChar(b byte) bool {
|
||||
return ('0' <= b && b <= '9') || b == separatorChar
|
||||
}
|
||||
|
||||
func (cw *colorWriter) Write(p []byte) (int, error) {
|
||||
r, nw, first, last := 0, 0, 0, 0
|
||||
if cw.mode != DiscardNonColorEscSeq {
|
||||
cw.state = outsideCsiCode
|
||||
cw.resetBuffer()
|
||||
}
|
||||
|
||||
var err error
|
||||
for i, ch := range p {
|
||||
switch cw.state {
|
||||
case outsideCsiCode:
|
||||
if ch == firstCsiChar {
|
||||
cw.paramStartBuf.WriteByte(ch)
|
||||
cw.state = firstCsiCode
|
||||
}
|
||||
case firstCsiCode:
|
||||
switch ch {
|
||||
case firstCsiChar:
|
||||
cw.paramStartBuf.WriteByte(ch)
|
||||
break
|
||||
case secondeCsiChar:
|
||||
cw.paramStartBuf.WriteByte(ch)
|
||||
cw.state = secondCsiCode
|
||||
last = i - 1
|
||||
default:
|
||||
cw.resetBuffer()
|
||||
cw.state = outsideCsiCode
|
||||
}
|
||||
case secondCsiCode:
|
||||
if isParameterChar(ch) {
|
||||
cw.paramBuf.WriteByte(ch)
|
||||
} else {
|
||||
nw, err = cw.w.Write(p[first:last])
|
||||
r += nw
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
first = i + 1
|
||||
result := parseEscapeSequence(ch, cw.paramBuf.Bytes())
|
||||
if result == noConsole || (cw.mode == OutputNonColorEscSeq && result == unknown) {
|
||||
cw.paramBuf.WriteByte(ch)
|
||||
nw, err := cw.flushBuffer()
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
r += nw
|
||||
} else {
|
||||
n, _ := cw.resetBuffer()
|
||||
// Add one more to the size of the buffer for the last ch
|
||||
r += n + 1
|
||||
}
|
||||
|
||||
cw.state = outsideCsiCode
|
||||
}
|
||||
default:
|
||||
cw.state = outsideCsiCode
|
||||
}
|
||||
}
|
||||
|
||||
if cw.mode != DiscardNonColorEscSeq || cw.state == outsideCsiCode {
|
||||
nw, err = cw.w.Write(p[first:len(p)])
|
||||
r += nw
|
||||
}
|
||||
|
||||
return r, err
|
||||
}
|
30
g.go
30
g.go
@ -35,7 +35,7 @@ bee generate model [modelname] [-fields=""]
|
||||
-fields: a list of table fields. Format: field:type, ...
|
||||
|
||||
bee generate controller [controllerfile]
|
||||
generate RESTFul controllers
|
||||
generate RESTful controllers
|
||||
|
||||
bee generate view [viewpath]
|
||||
generate CRUD view in viewpath
|
||||
@ -79,19 +79,19 @@ func init() {
|
||||
func generateCode(cmd *Command, args []string) int {
|
||||
ShowShortVersionBanner()
|
||||
|
||||
curpath, _ := os.Getwd()
|
||||
currpath, _ := os.Getwd()
|
||||
if len(args) < 1 {
|
||||
ColorLog("[ERRO] command is missing\n")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
gopath := os.Getenv("GOPATH")
|
||||
Debugf("gopath:%s", gopath)
|
||||
if gopath == "" {
|
||||
ColorLog("[ERRO] $GOPATH not found\n")
|
||||
ColorLog("[HINT] Set $GOPATH in your environment vairables\n")
|
||||
gps := GetGOPATHs()
|
||||
if len(gps) == 0 {
|
||||
ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty")
|
||||
os.Exit(2)
|
||||
}
|
||||
gopath := gps[0]
|
||||
Debugf("GOPATH: %s", gopath)
|
||||
|
||||
gcmd := args[0]
|
||||
switch gcmd {
|
||||
@ -124,9 +124,9 @@ func generateCode(cmd *Command, args []string) int {
|
||||
os.Exit(2)
|
||||
}
|
||||
sname := args[1]
|
||||
generateScaffold(sname, fields.String(), curpath, driver.String(), conn.String())
|
||||
generateScaffold(sname, fields.String(), currpath, driver.String(), conn.String())
|
||||
case "docs":
|
||||
generateDocs(curpath)
|
||||
generateDocs(currpath)
|
||||
case "appcode":
|
||||
// load config
|
||||
err := loadConfig()
|
||||
@ -157,7 +157,7 @@ func generateCode(cmd *Command, args []string) int {
|
||||
ColorLog("[INFO] Using '%s' as 'conn'\n", conn)
|
||||
ColorLog("[INFO] Using '%s' as 'tables'\n", tables)
|
||||
ColorLog("[INFO] Using '%s' as 'level'\n", level)
|
||||
generateAppcode(driver.String(), conn.String(), level.String(), tables.String(), curpath)
|
||||
generateAppcode(driver.String(), conn.String(), level.String(), tables.String(), currpath)
|
||||
case "migration":
|
||||
if len(args) < 2 {
|
||||
ColorLog("[ERRO] Wrong number of arguments\n")
|
||||
@ -176,11 +176,11 @@ func generateCode(cmd *Command, args []string) int {
|
||||
downsql = strings.Replace(downsql, "`", "", -1)
|
||||
}
|
||||
}
|
||||
generateMigration(mname, upsql, downsql, curpath)
|
||||
generateMigration(mname, upsql, downsql, currpath)
|
||||
case "controller":
|
||||
if len(args) == 2 {
|
||||
cname := args[1]
|
||||
generateController(cname, curpath)
|
||||
generateController(cname, currpath)
|
||||
} else {
|
||||
ColorLog("[ERRO] Wrong number of arguments\n")
|
||||
ColorLog("[HINT] Usage: bee generate controller [controllername]\n")
|
||||
@ -199,18 +199,18 @@ func generateCode(cmd *Command, args []string) int {
|
||||
os.Exit(2)
|
||||
}
|
||||
sname := args[1]
|
||||
generateModel(sname, fields.String(), curpath)
|
||||
generateModel(sname, fields.String(), currpath)
|
||||
case "view":
|
||||
if len(args) == 2 {
|
||||
cname := args[1]
|
||||
generateView(cname, curpath)
|
||||
generateView(cname, currpath)
|
||||
} else {
|
||||
ColorLog("[ERRO] Wrong number of arguments\n")
|
||||
ColorLog("[HINT] Usage: bee generate view [viewpath]\n")
|
||||
os.Exit(2)
|
||||
}
|
||||
default:
|
||||
ColorLog("[ERRO] command is missing\n")
|
||||
ColorLog("[ERRO] Command is missing\n")
|
||||
}
|
||||
ColorLog("[SUCC] %s successfully generated!\n", strings.Title(gcmd))
|
||||
return 0
|
||||
|
44
g_appcode.go
44
g_appcode.go
@ -499,7 +499,7 @@ func (mysqlDB *MysqlDB) GetColumns(db *sql.DB, table *Table, blackList map[strin
|
||||
}
|
||||
}
|
||||
|
||||
// getGoDataType maps an SQL data type to Golang data type
|
||||
// GetGoDataType maps an SQL data type to Golang data type
|
||||
func (*MysqlDB) GetGoDataType(sqlType string) (goType string) {
|
||||
var typeMapping = map[string]string{}
|
||||
typeMapping = typeMappingMysql
|
||||
@ -688,6 +688,8 @@ func (postgresDB *PostgresDB) GetColumns(db *sql.DB, table *Table, blackList map
|
||||
table.Columns = append(table.Columns, col)
|
||||
}
|
||||
}
|
||||
|
||||
// GetGoDataType returns the Go type from the mapped Postgres type
|
||||
func (*PostgresDB) GetGoDataType(sqlType string) (goType string) {
|
||||
if v, ok := typeMappingPostgres[sqlType]; ok {
|
||||
return v
|
||||
@ -730,6 +732,8 @@ func writeSourceFiles(pkgPath string, tables []*Table, mode byte, paths *MvcPath
|
||||
|
||||
// writeModelFiles generates model files
|
||||
func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bool) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
|
||||
for _, tb := range tables {
|
||||
// if selectedTables map is not nil and this table is not selected, ignore it
|
||||
if selectedTables != nil {
|
||||
@ -742,7 +746,7 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo
|
||||
var f *os.File
|
||||
var err error
|
||||
if isExist(fpath) {
|
||||
ColorLog("[WARN] %v is exist, do you want to overwrite it? Yes or No?\n", fpath)
|
||||
ColorLog("[WARN] '%v' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||
if askForConfirmation() {
|
||||
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
@ -750,7 +754,7 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
ColorLog("[WARN] skip create file\n")
|
||||
ColorLog("[WARN] Skipped create file '%s'\n", fpath)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
@ -782,14 +786,16 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo
|
||||
ColorLog("[ERRO] Could not write model file to %s\n", fpath)
|
||||
os.Exit(2)
|
||||
}
|
||||
f.Close()
|
||||
ColorLog("[INFO] model => %s\n", fpath)
|
||||
CloseFile(f)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
formatSourceCode(fpath)
|
||||
}
|
||||
}
|
||||
|
||||
// writeControllerFiles generates controller files
|
||||
func writeControllerFiles(tables []*Table, cPath string, selectedTables map[string]bool, pkgPath string) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
|
||||
for _, tb := range tables {
|
||||
// if selectedTables map is not nil and this table is not selected, ignore it
|
||||
if selectedTables != nil {
|
||||
@ -805,7 +811,7 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri
|
||||
var f *os.File
|
||||
var err error
|
||||
if isExist(fpath) {
|
||||
ColorLog("[WARN] %v is exist, do you want to overwrite it? Yes or No?\n", fpath)
|
||||
ColorLog("[WARN] '%v' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||
if askForConfirmation() {
|
||||
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
@ -813,7 +819,7 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
ColorLog("[WARN] skip create file\n")
|
||||
ColorLog("[WARN] Skipped create file '%s'\n", fpath)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
@ -829,14 +835,16 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri
|
||||
ColorLog("[ERRO] Could not write controller file to %s\n", fpath)
|
||||
os.Exit(2)
|
||||
}
|
||||
f.Close()
|
||||
ColorLog("[INFO] controller => %s\n", fpath)
|
||||
CloseFile(f)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
formatSourceCode(fpath)
|
||||
}
|
||||
}
|
||||
|
||||
// writeRouterFile generates router file
|
||||
func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bool, pkgPath string) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
|
||||
var nameSpaces []string
|
||||
for _, tb := range tables {
|
||||
// if selectedTables map is not nil and this table is not selected, ignore it
|
||||
@ -848,7 +856,7 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo
|
||||
if tb.Pk == "" {
|
||||
continue
|
||||
}
|
||||
// add name spaces
|
||||
// add namespaces
|
||||
nameSpace := strings.Replace(NamespaceTPL, "{{nameSpace}}", tb.Name, -1)
|
||||
nameSpace = strings.Replace(nameSpace, "{{ctrlName}}", camelCase(tb.Name), -1)
|
||||
nameSpaces = append(nameSpaces, nameSpace)
|
||||
@ -860,7 +868,7 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo
|
||||
var f *os.File
|
||||
var err error
|
||||
if isExist(fpath) {
|
||||
ColorLog("[WARN] %v is exist, do you want to overwrite it? Yes or No?\n", fpath)
|
||||
ColorLog("[WARN] '%v' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||
if askForConfirmation() {
|
||||
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
@ -868,7 +876,7 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo
|
||||
return
|
||||
}
|
||||
} else {
|
||||
ColorLog("[WARN] skip create file\n")
|
||||
ColorLog("[WARN] Skipped create file '%s'\n", fpath)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@ -879,11 +887,11 @@ func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bo
|
||||
}
|
||||
}
|
||||
if _, err := f.WriteString(routerStr); err != nil {
|
||||
ColorLog("[ERRO] Could not write router file to %s\n", fpath)
|
||||
ColorLog("[ERRO] Could not write router file to '%s'\n", fpath)
|
||||
os.Exit(2)
|
||||
}
|
||||
f.Close()
|
||||
ColorLog("[INFO] router => %s\n", fpath)
|
||||
CloseFile(f)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
formatSourceCode(fpath)
|
||||
}
|
||||
|
||||
@ -966,7 +974,7 @@ func getPackagePath(curpath string) (packpath string) {
|
||||
gopath := os.Getenv("GOPATH")
|
||||
Debugf("gopath:%s", gopath)
|
||||
if gopath == "" {
|
||||
ColorLog("[ERRO] you should set GOPATH in the env")
|
||||
ColorLog("[ERRO] You should set GOPATH in the env")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
@ -1097,7 +1105,7 @@ func GetAll{{modelName}}(query map[string]string, fields []string, sortby []stri
|
||||
|
||||
var l []{{modelName}}
|
||||
qs = qs.OrderBy(sortFields...)
|
||||
if _, err := qs.Limit(limit, offset).All(&l, fields...); err == nil {
|
||||
if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil {
|
||||
if len(fields) == 0 {
|
||||
for _, v := range l {
|
||||
ml = append(ml, v)
|
||||
@ -1254,7 +1262,7 @@ func (c *{{ctrlName}}Controller) GetAll() {
|
||||
// query: k:v,k:v
|
||||
if v := c.GetString("query"); v != "" {
|
||||
for _, cond := range strings.Split(v, ",") {
|
||||
kv := strings.Split(cond, ":")
|
||||
kv := strings.SplitN(cond, ":", 2)
|
||||
if len(kv) != 2 {
|
||||
c.Data["json"] = errors.New("Error: invalid query key/value pair")
|
||||
c.ServeJSON()
|
||||
|
@ -15,53 +15,62 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// article
|
||||
// cms/article
|
||||
//
|
||||
func generateController(cname, crupath string) {
|
||||
func generateController(cname, currpath string) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
|
||||
p, f := path.Split(cname)
|
||||
controllerName := strings.Title(f)
|
||||
packageName := "controllers"
|
||||
|
||||
if p != "" {
|
||||
i := strings.LastIndex(p[:len(p)-1], "/")
|
||||
packageName = p[i+1 : len(p)-1]
|
||||
}
|
||||
|
||||
ColorLog("[INFO] Using '%s' as controller name\n", controllerName)
|
||||
ColorLog("[INFO] Using '%s' as package name\n", packageName)
|
||||
fp := path.Join(crupath, "controllers", p)
|
||||
|
||||
fp := path.Join(currpath, "controllers", p)
|
||||
if _, err := os.Stat(fp); os.IsNotExist(err) {
|
||||
// create controller directory
|
||||
// Create the controller's directory
|
||||
if err := os.MkdirAll(fp, 0777); err != nil {
|
||||
ColorLog("[ERRO] Could not create controllers directory: %s\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
fpath := path.Join(fp, strings.ToLower(controllerName)+".go")
|
||||
if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer f.Close()
|
||||
modelPath := path.Join(crupath, "models", strings.ToLower(controllerName)+".go")
|
||||
defer CloseFile(f)
|
||||
|
||||
modelPath := path.Join(currpath, "models", strings.ToLower(controllerName)+".go")
|
||||
|
||||
var content string
|
||||
if _, err := os.Stat(modelPath); err == nil {
|
||||
ColorLog("[INFO] Using matching model '%s'\n", controllerName)
|
||||
content = strings.Replace(controllerModelTpl, "{{packageName}}", packageName, -1)
|
||||
pkgPath := getPackagePath(crupath)
|
||||
pkgPath := getPackagePath(currpath)
|
||||
content = strings.Replace(content, "{{pkgPath}}", pkgPath, -1)
|
||||
} else {
|
||||
content = strings.Replace(controllerTpl, "{{packageName}}", packageName, -1)
|
||||
}
|
||||
|
||||
content = strings.Replace(content, "{{controllerName}}", controllerName, -1)
|
||||
f.WriteString(content)
|
||||
// gofmt generated source code
|
||||
|
||||
// Run 'gofmt' on the generated source code
|
||||
formatSourceCode(fpath)
|
||||
fmt.Println("\tcreate\t", fpath)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
} else {
|
||||
// error creating file
|
||||
ColorLog("[ERRO] Could not create controller file: %s\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
@ -86,7 +95,7 @@ func (c *{{controllerName}}Controller) URLMapping() {
|
||||
c.Mapping("Delete", c.Delete)
|
||||
}
|
||||
|
||||
// @Title Post
|
||||
// @Title Create
|
||||
// @Description create {{controllerName}}
|
||||
// @Param body body models.{{controllerName}} true "body for {{controllerName}} content"
|
||||
// @Success 201 {object} models.{{controllerName}}
|
||||
@ -96,7 +105,7 @@ func (c *{{controllerName}}Controller) Post() {
|
||||
|
||||
}
|
||||
|
||||
// @Title Get
|
||||
// @Title GetOne
|
||||
// @Description get {{controllerName}} by id
|
||||
// @Param id path string true "The key for staticblock"
|
||||
// @Success 200 {object} models.{{controllerName}}
|
||||
@ -106,7 +115,7 @@ func (c *{{controllerName}}Controller) GetOne() {
|
||||
|
||||
}
|
||||
|
||||
// @Title Get All
|
||||
// @Title GetAll
|
||||
// @Description get {{controllerName}}
|
||||
// @Param query query string false "Filter. e.g. col1:v1,col2:v2 ..."
|
||||
// @Param fields query string false "Fields returned. e.g. col1,col2 ..."
|
||||
@ -246,7 +255,7 @@ func (c *{{controllerName}}Controller) GetAll() {
|
||||
// query: k:v,k:v
|
||||
if v := c.GetString("query"); v != "" {
|
||||
for _, cond := range strings.Split(v, ",") {
|
||||
kv := strings.Split(cond, ":")
|
||||
kv := strings.SplitN(cond, ":", 2)
|
||||
if len(kv) != 2 {
|
||||
c.Data["json"] = errors.New("Error: invalid query key/value pair")
|
||||
c.ServeJSON()
|
||||
|
427
g_docs.go
427
g_docs.go
@ -35,63 +35,6 @@ import (
|
||||
"github.com/astaxie/beego/utils"
|
||||
)
|
||||
|
||||
var globalDocsTemplate = `package docs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/swagger"
|
||||
)
|
||||
|
||||
const (
|
||||
Rootinfo string = {{.rootinfo}}
|
||||
Subapi string = {{.subapi}}
|
||||
BasePath string= "{{.version}}"
|
||||
)
|
||||
|
||||
var rootapi swagger.ResourceListing
|
||||
var apilist map[string]*swagger.APIDeclaration
|
||||
|
||||
func init() {
|
||||
if beego.BConfig.WebConfig.EnableDocs {
|
||||
err := json.Unmarshal([]byte(Rootinfo), &rootapi)
|
||||
if err != nil {
|
||||
beego.Error(err)
|
||||
}
|
||||
err = json.Unmarshal([]byte(Subapi), &apilist)
|
||||
if err != nil {
|
||||
beego.Error(err)
|
||||
}
|
||||
beego.GlobalDocAPI["Root"] = rootapi
|
||||
for k, v := range apilist {
|
||||
for i, a := range v.APIs {
|
||||
a.Path = urlReplace(k + a.Path)
|
||||
v.APIs[i] = a
|
||||
}
|
||||
v.BasePath = BasePath
|
||||
beego.GlobalDocAPI[strings.Trim(k, "/")] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func urlReplace(src string) string {
|
||||
pt := strings.Split(src, "/")
|
||||
for i, p := range pt {
|
||||
if len(p) > 0 {
|
||||
if p[0] == ':' {
|
||||
pt[i] = "{" + p[1:] + "}"
|
||||
} else if p[0] == '?' && p[1] == ':' {
|
||||
pt[i] = "{" + p[2:] + "}"
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.Join(pt, "/")
|
||||
}
|
||||
`
|
||||
|
||||
const (
|
||||
ajson = "application/json"
|
||||
axml = "application/xml"
|
||||
@ -99,21 +42,19 @@ const (
|
||||
ahtml = "text/html"
|
||||
)
|
||||
|
||||
var pkgCache map[string]bool //pkg:controller:function:comments comments: key:value
|
||||
var pkgCache map[string]struct{} //pkg:controller:function:comments comments: key:value
|
||||
var controllerComments map[string]string
|
||||
var importlist map[string]string
|
||||
var apilist map[string]*swagger.APIDeclaration
|
||||
var controllerList map[string][]swagger.API
|
||||
var modelsList map[string]map[string]swagger.Model
|
||||
var rootapi swagger.ResourceListing
|
||||
var controllerList map[string]map[string]*swagger.Item //controllername Paths items
|
||||
var modelsList map[string]map[string]swagger.Schema
|
||||
var rootapi swagger.Swagger
|
||||
|
||||
func init() {
|
||||
pkgCache = make(map[string]bool)
|
||||
pkgCache = make(map[string]struct{})
|
||||
controllerComments = make(map[string]string)
|
||||
importlist = make(map[string]string)
|
||||
apilist = make(map[string]*swagger.APIDeclaration)
|
||||
controllerList = make(map[string][]swagger.API)
|
||||
modelsList = make(map[string]map[string]swagger.Model)
|
||||
controllerList = make(map[string]map[string]*swagger.Item)
|
||||
modelsList = make(map[string]map[string]swagger.Schema)
|
||||
}
|
||||
|
||||
func generateDocs(curpath string) {
|
||||
@ -126,30 +67,31 @@ func generateDocs(curpath string) {
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
rootapi.Info = swagger.Information{}
|
||||
rootapi.SwaggerVersion = swagger.SwaggerVersion
|
||||
rootapi.Infos = swagger.Information{}
|
||||
rootapi.SwaggerVersion = "2.0"
|
||||
//analysis API comments
|
||||
if f.Comments != nil {
|
||||
for _, c := range f.Comments {
|
||||
for _, s := range strings.Split(c.Text(), "\n") {
|
||||
if strings.HasPrefix(s, "@APIVersion") {
|
||||
rootapi.APIVersion = strings.TrimSpace(s[len("@APIVersion"):])
|
||||
rootapi.Infos.Version = strings.TrimSpace(s[len("@APIVersion"):])
|
||||
} else if strings.HasPrefix(s, "@Title") {
|
||||
rootapi.Info.Title = strings.TrimSpace(s[len("@Title"):])
|
||||
rootapi.Infos.Title = strings.TrimSpace(s[len("@Title"):])
|
||||
} else if strings.HasPrefix(s, "@Description") {
|
||||
rootapi.Info.Description = strings.TrimSpace(s[len("@Description"):])
|
||||
rootapi.Infos.Description = strings.TrimSpace(s[len("@Description"):])
|
||||
} else if strings.HasPrefix(s, "@TermsOfServiceUrl") {
|
||||
rootapi.Info.TermsOfServiceURL = strings.TrimSpace(s[len("@TermsOfServiceUrl"):])
|
||||
rootapi.Infos.TermsOfService = strings.TrimSpace(s[len("@TermsOfServiceUrl"):])
|
||||
} else if strings.HasPrefix(s, "@Contact") {
|
||||
rootapi.Info.Contact = strings.TrimSpace(s[len("@Contact"):])
|
||||
rootapi.Infos.Contact.EMail = strings.TrimSpace(s[len("@Contact"):])
|
||||
} else if strings.HasPrefix(s, "@License") {
|
||||
rootapi.Info.License = strings.TrimSpace(s[len("@License"):])
|
||||
rootapi.Infos.License.Name = strings.TrimSpace(s[len("@License"):])
|
||||
} else if strings.HasPrefix(s, "@LicenseUrl") {
|
||||
rootapi.Info.LicenseURL = strings.TrimSpace(s[len("@LicenseUrl"):])
|
||||
rootapi.Infos.License.URL = strings.TrimSpace(s[len("@LicenseUrl"):])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// analisys controller package
|
||||
for _, im := range f.Imports {
|
||||
localName := ""
|
||||
if im.Name != nil {
|
||||
@ -161,33 +103,46 @@ func generateDocs(curpath string) {
|
||||
switch specDecl := d.(type) {
|
||||
case *ast.FuncDecl:
|
||||
for _, l := range specDecl.Body.List {
|
||||
switch smtp := l.(type) {
|
||||
switch stmt := l.(type) {
|
||||
case *ast.AssignStmt:
|
||||
for _, l := range smtp.Rhs {
|
||||
for _, l := range stmt.Rhs {
|
||||
if v, ok := l.(*ast.CallExpr); ok {
|
||||
f, params := analisysNewNamespace(v)
|
||||
globalDocsTemplate = strings.Replace(globalDocsTemplate, "{{.version}}", f, -1)
|
||||
// analisys NewNamespace, it will return version and the subfunction
|
||||
if selName := v.Fun.(*ast.SelectorExpr).Sel.String(); selName != "NewNamespace" {
|
||||
continue
|
||||
}
|
||||
version, params := analisysNewNamespace(v)
|
||||
if rootapi.BasePath == "" && version != "" {
|
||||
rootapi.BasePath = version
|
||||
}
|
||||
for _, p := range params {
|
||||
switch pp := p.(type) {
|
||||
case *ast.CallExpr:
|
||||
controllerName := ""
|
||||
if selname := pp.Fun.(*ast.SelectorExpr).Sel.String(); selname == "NSNamespace" {
|
||||
s, params := analisysNewNamespace(pp)
|
||||
subapi := swagger.APIRef{Path: s}
|
||||
controllerName := ""
|
||||
for _, sp := range params {
|
||||
switch pp := sp.(type) {
|
||||
case *ast.CallExpr:
|
||||
if pp.Fun.(*ast.SelectorExpr).Sel.String() == "NSInclude" {
|
||||
controllerName = analisysNSInclude(s, pp)
|
||||
}
|
||||
}
|
||||
}
|
||||
if v, ok := controllerComments[controllerName]; ok {
|
||||
subapi.Description = v
|
||||
rootapi.Tags = append(rootapi.Tags, swagger.Tag{
|
||||
Name: strings.Trim(s, "/"),
|
||||
Description: v,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rootapi.APIs = append(rootapi.APIs, subapi)
|
||||
} else if selname == "NSInclude" {
|
||||
analisysNSInclude(f, pp)
|
||||
controllerName = analisysNSInclude("", pp)
|
||||
if v, ok := controllerComments[controllerName]; ok {
|
||||
rootapi.Tags = append(rootapi.Tags, swagger.Tag{
|
||||
Name: controllerName, // if the NSInclude has no prefix, we use the controllername as the tag
|
||||
Description: v,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -198,25 +153,23 @@ func generateDocs(curpath string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
apiinfo, err := json.Marshal(rootapi)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
subapi, err := json.Marshal(apilist)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
os.Mkdir(path.Join(curpath, "docs"), 0755)
|
||||
fd, err := os.Create(path.Join(curpath, "docs", "docs.go"))
|
||||
os.Mkdir(path.Join(curpath, "swagger"), 0755)
|
||||
fd, err := os.Create(path.Join(curpath, "swagger", "swagger.json"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer fd.Close()
|
||||
a := strings.Replace(globalDocsTemplate, "{{.rootinfo}}", "`"+string(apiinfo)+"`", -1)
|
||||
a = strings.Replace(a, "{{.subapi}}", "`"+string(subapi)+"`", -1)
|
||||
fd.WriteString(a)
|
||||
dt, err := json.MarshalIndent(rootapi, "", " ")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = fd.Write(dt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// return version and the others params
|
||||
func analisysNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) {
|
||||
for i, p := range ce.Args {
|
||||
if i == 0 {
|
||||
@ -233,32 +186,49 @@ func analisysNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) {
|
||||
|
||||
func analisysNSInclude(baseurl string, ce *ast.CallExpr) string {
|
||||
cname := ""
|
||||
a := &swagger.APIDeclaration{}
|
||||
a.APIVersion = rootapi.APIVersion
|
||||
a.SwaggerVersion = swagger.SwaggerVersion
|
||||
a.ResourcePath = baseurl
|
||||
a.Produces = []string{"application/json", "application/xml", "text/plain", "text/html"}
|
||||
a.APIs = make([]swagger.API, 0)
|
||||
a.Models = make(map[string]swagger.Model)
|
||||
for _, p := range ce.Args {
|
||||
x := p.(*ast.UnaryExpr).X.(*ast.CompositeLit).Type.(*ast.SelectorExpr)
|
||||
if v, ok := importlist[fmt.Sprint(x.X)]; ok {
|
||||
cname = v + x.Sel.Name
|
||||
}
|
||||
if apis, ok := controllerList[cname]; ok {
|
||||
if len(a.APIs) > 0 {
|
||||
a.APIs = append(a.APIs, apis...)
|
||||
for rt, item := range apis {
|
||||
tag := ""
|
||||
if baseurl != "" {
|
||||
rt = baseurl + rt
|
||||
tag = strings.Trim(baseurl, "/")
|
||||
} else {
|
||||
a.APIs = apis
|
||||
tag = cname
|
||||
}
|
||||
if item.Get != nil {
|
||||
item.Get.Tags = []string{tag}
|
||||
}
|
||||
if models, ok := modelsList[cname]; ok {
|
||||
for _, m := range models {
|
||||
a.Models[m.ID] = m
|
||||
if item.Post != nil {
|
||||
item.Post.Tags = []string{tag}
|
||||
}
|
||||
if item.Put != nil {
|
||||
item.Put.Tags = []string{tag}
|
||||
}
|
||||
if item.Patch != nil {
|
||||
item.Patch.Tags = []string{tag}
|
||||
}
|
||||
if item.Head != nil {
|
||||
item.Head.Tags = []string{tag}
|
||||
}
|
||||
if item.Delete != nil {
|
||||
item.Delete.Tags = []string{tag}
|
||||
}
|
||||
if item.Options != nil {
|
||||
item.Options.Tags = []string{tag}
|
||||
}
|
||||
if len(rootapi.Paths) == 0 {
|
||||
rootapi.Paths = make(map[string]*swagger.Item)
|
||||
}
|
||||
rt = urlReplace(rt)
|
||||
rootapi.Paths[rt] = item
|
||||
}
|
||||
}
|
||||
}
|
||||
apilist[baseurl] = a
|
||||
return cname
|
||||
}
|
||||
|
||||
@ -267,15 +237,15 @@ func analisyscontrollerPkg(localName, pkgpath string) {
|
||||
if isSystemPackage(pkgpath) {
|
||||
return
|
||||
}
|
||||
if pkgpath == "github.com/astaxie/beego" {
|
||||
return
|
||||
}
|
||||
if localName != "" {
|
||||
importlist[localName] = pkgpath
|
||||
} else {
|
||||
pps := strings.Split(pkgpath, "/")
|
||||
importlist[pps[len(pps)-1]] = pkgpath
|
||||
}
|
||||
if pkgpath == "github.com/astaxie/beego" {
|
||||
return
|
||||
}
|
||||
gopath := os.Getenv("GOPATH")
|
||||
if gopath == "" {
|
||||
panic("please set gopath")
|
||||
@ -294,6 +264,7 @@ func analisyscontrollerPkg(localName, pkgpath string) {
|
||||
if _, ok := pkgCache[pkgpath]; ok {
|
||||
return
|
||||
}
|
||||
pkgCache[pkgpath] = struct{}{}
|
||||
} else {
|
||||
ColorLog("[ERRO] the %s pkg not exist in gopath\n", pkgpath)
|
||||
os.Exit(1)
|
||||
@ -315,15 +286,18 @@ func analisyscontrollerPkg(localName, pkgpath string) {
|
||||
case *ast.FuncDecl:
|
||||
if specDecl.Recv != nil && len(specDecl.Recv.List) > 0 {
|
||||
if t, ok := specDecl.Recv.List[0].Type.(*ast.StarExpr); ok {
|
||||
// parse controller method
|
||||
parserComments(specDecl.Doc, specDecl.Name.String(), fmt.Sprint(t.X), pkgpath)
|
||||
}
|
||||
}
|
||||
case *ast.GenDecl:
|
||||
if specDecl.Tok.String() == "type" {
|
||||
if specDecl.Tok == token.TYPE {
|
||||
for _, s := range specDecl.Specs {
|
||||
switch tp := s.(*ast.TypeSpec).Type.(type) {
|
||||
case *ast.StructType:
|
||||
_ = tp.Struct
|
||||
//parse controller definition comments
|
||||
if strings.TrimSpace(specDecl.Doc.Text()) != "" {
|
||||
controllerComments[pkgpath+s.(*ast.TypeSpec).Name.String()] = specDecl.Doc.Text()
|
||||
}
|
||||
}
|
||||
@ -332,6 +306,7 @@ func analisyscontrollerPkg(localName, pkgpath string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isSystemPackage(pkgpath string) bool {
|
||||
@ -355,8 +330,11 @@ func isSystemPackage(pkgpath string) bool {
|
||||
|
||||
// parse the func comments
|
||||
func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpath string) error {
|
||||
innerapi := swagger.API{}
|
||||
opts := swagger.Operation{}
|
||||
var routerPath string
|
||||
var HTTPMethod string
|
||||
opts := swagger.Operation{
|
||||
Responses: make(map[string]swagger.Response),
|
||||
}
|
||||
if comments != nil && comments.List != nil {
|
||||
for _, c := range comments.List {
|
||||
t := strings.TrimSpace(strings.TrimLeft(c.Text, "//"))
|
||||
@ -366,20 +344,20 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
||||
if len(e1) < 1 {
|
||||
return errors.New("you should has router infomation")
|
||||
}
|
||||
innerapi.Path = e1[0]
|
||||
routerPath = e1[0]
|
||||
if len(e1) == 2 && e1[1] != "" {
|
||||
e1 = strings.SplitN(e1[1], " ", 2)
|
||||
opts.HTTPMethod = strings.ToUpper(strings.Trim(e1[0], "[]"))
|
||||
HTTPMethod = strings.ToUpper(strings.Trim(e1[0], "[]"))
|
||||
} else {
|
||||
opts.HTTPMethod = "GET"
|
||||
HTTPMethod = "GET"
|
||||
}
|
||||
} else if strings.HasPrefix(t, "@Title") {
|
||||
opts.Nickname = strings.TrimSpace(t[len("@Title"):])
|
||||
opts.OperationID = controllerName + "." + strings.TrimSpace(t[len("@Title"):])
|
||||
} else if strings.HasPrefix(t, "@Description") {
|
||||
opts.Summary = strings.TrimSpace(t[len("@Description"):])
|
||||
} else if strings.HasPrefix(t, "@Success") {
|
||||
ss := strings.TrimSpace(t[len("@Success"):])
|
||||
rs := swagger.ResponseMessage{}
|
||||
rs := swagger.Response{}
|
||||
st := make([]string, 3)
|
||||
j := 0
|
||||
var tmp []rune
|
||||
@ -411,7 +389,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
||||
if len(tmp) > 0 && st[2] == "" {
|
||||
st[2] = strings.TrimSpace(string(tmp))
|
||||
}
|
||||
rs.Message = st[2]
|
||||
rs.Description = st[2]
|
||||
if st[1] == "{object}" {
|
||||
if st[2] == "" {
|
||||
panic(controllerName + " " + funcName + " has no object")
|
||||
@ -419,16 +397,16 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
||||
cmpath, m, mod, realTypes := getModel(st[2])
|
||||
//ll := strings.Split(st[2], ".")
|
||||
//opts.Type = ll[len(ll)-1]
|
||||
rs.ResponseModel = m
|
||||
rs.Schema = &swagger.Schema{
|
||||
Ref: "#/definitions/" + m,
|
||||
}
|
||||
if _, ok := modelsList[pkgpath+controllerName]; !ok {
|
||||
modelsList[pkgpath+controllerName] = make(map[string]swagger.Model, 0)
|
||||
modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema, 0)
|
||||
}
|
||||
modelsList[pkgpath+controllerName][st[2]] = mod
|
||||
appendModels(cmpath, pkgpath, controllerName, realTypes)
|
||||
}
|
||||
|
||||
rs.Code, _ = strconv.Atoi(st[0])
|
||||
opts.ResponseMessages = append(opts.ResponseMessages, rs)
|
||||
opts.Responses[st[0]] = rs
|
||||
} else if strings.HasPrefix(t, "@Param") {
|
||||
para := swagger.Parameter{}
|
||||
p := getparams(strings.TrimSpace(t[len("@Param "):]))
|
||||
@ -436,25 +414,61 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
||||
panic(controllerName + "_" + funcName + "'s comments @Param at least should has 4 params")
|
||||
}
|
||||
para.Name = p[0]
|
||||
para.ParamType = p[1]
|
||||
switch p[1] {
|
||||
case "query":
|
||||
fallthrough
|
||||
case "header":
|
||||
fallthrough
|
||||
case "path":
|
||||
fallthrough
|
||||
case "formData":
|
||||
fallthrough
|
||||
case "body":
|
||||
break
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "[%s.%s] Unknow param location: %s, Possible values are `query`, `header`, `path`, `formData` or `body`.\n", controllerName, funcName, p[1])
|
||||
}
|
||||
para.In = p[1]
|
||||
pp := strings.Split(p[2], ".")
|
||||
para.DataType = pp[len(pp)-1]
|
||||
typ := pp[len(pp)-1]
|
||||
if len(pp) >= 2 {
|
||||
cmpath, m, mod, realTypes := getModel(p[2])
|
||||
para.Schema = &swagger.Schema{
|
||||
Ref: "#/definitions/" + m,
|
||||
}
|
||||
if _, ok := modelsList[pkgpath+controllerName]; !ok {
|
||||
modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema, 0)
|
||||
}
|
||||
modelsList[pkgpath+controllerName][typ] = mod
|
||||
appendModels(cmpath, pkgpath, controllerName, realTypes)
|
||||
} else {
|
||||
if typ == "string" || typ == "number" || typ == "integer" || typ == "boolean" ||
|
||||
typ == "array" || typ == "file" {
|
||||
para.Type = typ
|
||||
} else if sType, ok := basicTypes[typ]; ok {
|
||||
typeFormat := strings.Split(sType, ":")
|
||||
para.Type = typeFormat[0]
|
||||
para.Format = typeFormat[1]
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "[%s.%s] Unknow param type: %s\n", controllerName, funcName, typ)
|
||||
}
|
||||
}
|
||||
if len(p) > 4 {
|
||||
para.Required, _ = strconv.ParseBool(p[3])
|
||||
para.Description = p[4]
|
||||
para.Description = strings.Trim(p[4], `" `)
|
||||
} else {
|
||||
para.Description = p[3]
|
||||
para.Description = strings.Trim(p[3], `" `)
|
||||
}
|
||||
opts.Parameters = append(opts.Parameters, para)
|
||||
} else if strings.HasPrefix(t, "@Failure") {
|
||||
rs := swagger.ResponseMessage{}
|
||||
rs := swagger.Response{}
|
||||
st := strings.TrimSpace(t[len("@Failure"):])
|
||||
var cd []rune
|
||||
var start bool
|
||||
for i, s := range st {
|
||||
if unicode.IsSpace(s) {
|
||||
if start {
|
||||
rs.Message = strings.TrimSpace(st[i+1:])
|
||||
rs.Description = strings.TrimSpace(st[i+1:])
|
||||
break
|
||||
} else {
|
||||
continue
|
||||
@ -463,10 +477,9 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
||||
start = true
|
||||
cd = append(cd, s)
|
||||
}
|
||||
rs.Code, _ = strconv.Atoi(string(cd))
|
||||
opts.ResponseMessages = append(opts.ResponseMessages, rs)
|
||||
} else if strings.HasPrefix(t, "@Type") {
|
||||
opts.Type = strings.TrimSpace(t[len("@Type"):])
|
||||
opts.Responses[string(cd)] = rs
|
||||
} else if strings.HasPrefix(t, "@Deprecated") {
|
||||
opts.Deprecated, _ = strconv.ParseBool(strings.TrimSpace(t[len("@Deprecated"):]))
|
||||
} else if strings.HasPrefix(t, "@Accept") {
|
||||
accepts := strings.Split(strings.TrimSpace(strings.TrimSpace(t[len("@Accept"):])), ",")
|
||||
for _, a := range accepts {
|
||||
@ -488,14 +501,35 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
||||
}
|
||||
}
|
||||
}
|
||||
innerapi.Operations = append(innerapi.Operations, opts)
|
||||
if innerapi.Path != "" {
|
||||
if _, ok := controllerList[pkgpath+controllerName]; ok {
|
||||
controllerList[pkgpath+controllerName] = append(controllerList[pkgpath+controllerName], innerapi)
|
||||
if routerPath != "" {
|
||||
var item *swagger.Item
|
||||
if itemList, ok := controllerList[pkgpath+controllerName]; ok {
|
||||
if it, ok := itemList[routerPath]; !ok {
|
||||
item = &swagger.Item{}
|
||||
} else {
|
||||
controllerList[pkgpath+controllerName] = make([]swagger.API, 1)
|
||||
controllerList[pkgpath+controllerName][0] = innerapi
|
||||
item = it
|
||||
}
|
||||
} else {
|
||||
controllerList[pkgpath+controllerName] = make(map[string]*swagger.Item)
|
||||
item = &swagger.Item{}
|
||||
}
|
||||
switch HTTPMethod {
|
||||
case "GET":
|
||||
item.Get = &opts
|
||||
case "POST":
|
||||
item.Post = &opts
|
||||
case "PUT":
|
||||
item.Put = &opts
|
||||
case "PATCH":
|
||||
item.Patch = &opts
|
||||
case "DELETE":
|
||||
item.Delete = &opts
|
||||
case "HEAD":
|
||||
item.Head = &opts
|
||||
case "OPTIONS":
|
||||
item.Options = &opts
|
||||
}
|
||||
controllerList[pkgpath+controllerName][routerPath] = item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -531,7 +565,7 @@ func getparams(str string) []string {
|
||||
return r
|
||||
}
|
||||
|
||||
func getModel(str string) (pkgpath, objectname string, m swagger.Model, realTypes []string) {
|
||||
func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTypes []string) {
|
||||
strs := strings.Split(str, ".")
|
||||
objectname = strs[len(strs)-1]
|
||||
pkgpath = strings.Join(strs[:len(strs)-1], "/")
|
||||
@ -547,7 +581,7 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Model, realType
|
||||
ColorLog("[ERRO] the model %s parser.ParseDir error\n", str)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
m.Type = "object"
|
||||
for _, pkg := range astPkgs {
|
||||
for _, fl := range pkg.Files {
|
||||
for k, d := range fl.Scope.Objects {
|
||||
@ -564,24 +598,36 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Model, realType
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
m.ID = k
|
||||
m.Title = k
|
||||
if st.Fields.List != nil {
|
||||
m.Properties = make(map[string]swagger.ModelProperty)
|
||||
m.Properties = make(map[string]swagger.Propertie)
|
||||
for _, field := range st.Fields.List {
|
||||
isSlice, realType := typeAnalyser(field)
|
||||
isSlice, realType, sType := typeAnalyser(field)
|
||||
realTypes = append(realTypes, realType)
|
||||
mp := swagger.ModelProperty{}
|
||||
mp := swagger.Propertie{}
|
||||
// add type slice
|
||||
if isSlice {
|
||||
if isBasicType(realType) {
|
||||
mp.Type = "[]" + realType
|
||||
} else {
|
||||
mp.Type = "array"
|
||||
mp.Items = make(map[string]string)
|
||||
mp.Items["$ref"] = realType
|
||||
if isBasicType(realType) {
|
||||
typeFormat := strings.Split(sType, ":")
|
||||
mp.Items = &swagger.Propertie{
|
||||
Type: typeFormat[0],
|
||||
Format: typeFormat[1],
|
||||
}
|
||||
|
||||
} else {
|
||||
mp.Items = &swagger.Propertie{
|
||||
Ref: "#/definitions/" + realType,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mp.Type = realType
|
||||
if isBasicType(realType) {
|
||||
typeFormat := strings.Split(sType, ":")
|
||||
mp.Type = typeFormat[0]
|
||||
mp.Format = typeFormat[1]
|
||||
} else if sType == "object" {
|
||||
mp.Ref = "#/definitions/" + realType
|
||||
}
|
||||
}
|
||||
|
||||
// dont add property if anonymous field
|
||||
@ -633,56 +679,63 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Model, realType
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if m.ID == "" {
|
||||
ColorLog("can't find the object: %v", str)
|
||||
if m.Title == "" {
|
||||
ColorLog("can't find the object: %s", str)
|
||||
os.Exit(1)
|
||||
}
|
||||
if len(rootapi.Definitions) == 0 {
|
||||
rootapi.Definitions = make(map[string]swagger.Schema)
|
||||
}
|
||||
rootapi.Definitions[objectname] = m
|
||||
return
|
||||
}
|
||||
|
||||
func typeAnalyser(f *ast.Field) (isSlice bool, realType string) {
|
||||
func typeAnalyser(f *ast.Field) (isSlice bool, realType, swaggerType string) {
|
||||
if arr, ok := f.Type.(*ast.ArrayType); ok {
|
||||
if isBasicType(fmt.Sprint(arr.Elt)) {
|
||||
return false, fmt.Sprintf("[]%v", arr.Elt)
|
||||
return false, fmt.Sprintf("[]%v", arr.Elt), basicTypes[fmt.Sprint(arr.Elt)]
|
||||
}
|
||||
if mp, ok := arr.Elt.(*ast.MapType); ok {
|
||||
return false, fmt.Sprintf("map[%v][%v]", mp.Key, mp.Value)
|
||||
return false, fmt.Sprintf("map[%v][%v]", mp.Key, mp.Value), "object"
|
||||
}
|
||||
if star, ok := arr.Elt.(*ast.StarExpr); ok {
|
||||
return true, fmt.Sprint(star.X)
|
||||
return true, fmt.Sprint(star.X), "object"
|
||||
}
|
||||
return true, fmt.Sprint(arr.Elt)
|
||||
return true, fmt.Sprint(arr.Elt), "object"
|
||||
}
|
||||
switch t := f.Type.(type) {
|
||||
case *ast.StarExpr:
|
||||
return false, fmt.Sprint(t.X)
|
||||
return false, fmt.Sprint(t.X), "object"
|
||||
case *ast.MapType:
|
||||
return false, fmt.Sprint(t.Value), "object"
|
||||
}
|
||||
return false, fmt.Sprint(f.Type)
|
||||
if k, ok := basicTypes[fmt.Sprint(f.Type)]; ok {
|
||||
return false, fmt.Sprint(f.Type), k
|
||||
}
|
||||
return false, fmt.Sprint(f.Type), "object"
|
||||
}
|
||||
|
||||
func isBasicType(Type string) bool {
|
||||
for _, v := range basicTypes {
|
||||
if v == Type {
|
||||
if _, ok := basicTypes[Type]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// refer to builtin.go
|
||||
var basicTypes = []string{
|
||||
"bool",
|
||||
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||
"int", "int8", "int16", "int32", "int64",
|
||||
"float32", "float64",
|
||||
"string",
|
||||
"complex64", "complex128",
|
||||
"byte", "rune", "uintptr",
|
||||
var basicTypes = map[string]string{
|
||||
"bool": "boolean:",
|
||||
"uint": "integer:int32", "uint8": "integer:int32", "uint16": "integer:int32", "uint32": "integer:int32", "uint64": "integer:int64",
|
||||
"int": "integer:int64", "int8": "integer:int32", "int16:int32": "integer:int32", "int32": "integer:int32", "int64": "integer:int64",
|
||||
"uintptr": "integer:int64",
|
||||
"float32": "number:float", "float64": "number:double",
|
||||
"string": "string:",
|
||||
"complex64": "number:float", "complex128": "number:double",
|
||||
"byte": "string:byte", "rune": "string:byte",
|
||||
}
|
||||
|
||||
// regexp get json tag
|
||||
@ -716,3 +769,17 @@ func appendModels(cmpath, pkgpath, controllerName string, realTypes []string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func urlReplace(src string) string {
|
||||
pt := strings.Split(src, "/")
|
||||
for i, p := range pt {
|
||||
if len(p) > 0 {
|
||||
if p[0] == ':' {
|
||||
pt[i] = "{" + p[1:] + "}"
|
||||
} else if p[0] == '?' && p[1] == ':' {
|
||||
pt[i] = "{" + p[2:] + "}"
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.Join(pt, "/")
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
@ -98,6 +99,8 @@ func writeHproseSourceFiles(pkgPath string, tables []*Table, mode byte, paths *M
|
||||
|
||||
// writeHproseModelFiles generates model files
|
||||
func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[string]bool) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
|
||||
for _, tb := range tables {
|
||||
// if selectedTables map is not nil and this table is not selected, ignore it
|
||||
if selectedTables != nil {
|
||||
@ -110,7 +113,7 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str
|
||||
var f *os.File
|
||||
var err error
|
||||
if isExist(fpath) {
|
||||
ColorLog("[WARN] %v is exist, do you want to overwrite it? Yes or No?\n", fpath)
|
||||
ColorLog("[WARN] '%v' already exists. Do you want to overwrite it? [Yes|No] ", fpath)
|
||||
if askForConfirmation() {
|
||||
f, err = os.OpenFile(fpath, os.O_RDWR|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
@ -118,7 +121,7 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
ColorLog("[WARN] skip create file\n")
|
||||
ColorLog("[WARN] Skipped create file '%s'\n", fpath)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
@ -147,11 +150,11 @@ func writeHproseModelFiles(tables []*Table, mPath string, selectedTables map[str
|
||||
fileStr = strings.Replace(fileStr, "{{timePkg}}", timePkg, -1)
|
||||
fileStr = strings.Replace(fileStr, "{{importTimePkg}}", importTimePkg, -1)
|
||||
if _, err := f.WriteString(fileStr); err != nil {
|
||||
ColorLog("[ERRO] Could not write model file to %s\n", fpath)
|
||||
ColorLog("[ERRO] Could not write model file to '%s'\n", fpath)
|
||||
os.Exit(2)
|
||||
}
|
||||
f.Close()
|
||||
ColorLog("[INFO] model => %s\n", fpath)
|
||||
CloseFile(f)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
formatSourceCode(fpath)
|
||||
}
|
||||
}
|
||||
@ -260,7 +263,7 @@ func GetAll{{modelName}}(query map[string]string, fields []string, sortby []stri
|
||||
|
||||
var l []{{modelName}}
|
||||
qs = qs.OrderBy(sortFields...)
|
||||
if _, err := qs.Limit(limit, offset).All(&l, fields...); err == nil {
|
||||
if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil {
|
||||
if len(fields) == 0 {
|
||||
for _, v := range l {
|
||||
ml = append(ml, v)
|
||||
|
@ -31,6 +31,8 @@ const (
|
||||
// The generated file template consists of an up() method for updating schema and
|
||||
// a down() method for reverting the update.
|
||||
func generateMigration(mname, upsql, downsql, curpath string) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
|
||||
migrationFilePath := path.Join(curpath, "database", MPath)
|
||||
if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) {
|
||||
// create migrations directory
|
||||
@ -43,17 +45,16 @@ func generateMigration(mname, upsql, downsql, curpath string) {
|
||||
today := time.Now().Format(MDateFormat)
|
||||
fpath := path.Join(migrationFilePath, fmt.Sprintf("%s_%s.go", today, mname))
|
||||
if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer f.Close()
|
||||
defer CloseFile(f)
|
||||
content := strings.Replace(MigrationTPL, "{{StructName}}", camelCase(mname)+"_"+today, -1)
|
||||
content = strings.Replace(content, "{{CurrTime}}", today, -1)
|
||||
content = strings.Replace(content, "{{UpSQL}}", upsql, -1)
|
||||
content = strings.Replace(content, "{{DownSQL}}", downsql, -1)
|
||||
f.WriteString(content)
|
||||
// gofmt generated source code
|
||||
// Run 'gofmt' on the generated source code
|
||||
formatSourceCode(fpath)
|
||||
fmt.Println("\tcreate\t", fpath)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
} else {
|
||||
// error creating file
|
||||
ColorLog("[ERRO] Could not create migration file: %s\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
49
g_model.go
49
g_model.go
@ -1,3 +1,17 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -8,7 +22,9 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func generateModel(mname, fields, crupath string) {
|
||||
func generateModel(mname, fields, currpath string) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
|
||||
p, f := path.Split(mname)
|
||||
modelName := strings.Title(f)
|
||||
packageName := "models"
|
||||
@ -16,24 +32,28 @@ func generateModel(mname, fields, crupath string) {
|
||||
i := strings.LastIndex(p[:len(p)-1], "/")
|
||||
packageName = p[i+1 : len(p)-1]
|
||||
}
|
||||
|
||||
modelStruct, hastime, err := getStruct(modelName, fields)
|
||||
if err != nil {
|
||||
ColorLog("[ERRO] Could not genrate models struct: %s\n", err)
|
||||
ColorLog("[ERRO] Could not generate the model struct: %s\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
ColorLog("[INFO] Using '%s' as model name\n", modelName)
|
||||
ColorLog("[INFO] Using '%s' as package name\n", packageName)
|
||||
fp := path.Join(crupath, "models", p)
|
||||
|
||||
fp := path.Join(currpath, "models", p)
|
||||
if _, err := os.Stat(fp); os.IsNotExist(err) {
|
||||
// create controller directory
|
||||
// Create the model's directory
|
||||
if err := os.MkdirAll(fp, 0777); err != nil {
|
||||
ColorLog("[ERRO] Could not create models directory: %s\n", err)
|
||||
ColorLog("[ERRO] Could not create the model directory: %s\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
fpath := path.Join(fp, strings.ToLower(modelName)+".go")
|
||||
if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer f.Close()
|
||||
defer CloseFile(f)
|
||||
content := strings.Replace(modelTpl, "{{packageName}}", packageName, -1)
|
||||
content = strings.Replace(content, "{{modelName}}", modelName, -1)
|
||||
content = strings.Replace(content, "{{modelStruct}}", modelStruct, -1)
|
||||
@ -43,11 +63,10 @@ func generateModel(mname, fields, crupath string) {
|
||||
content = strings.Replace(content, "{{timePkg}}", "", -1)
|
||||
}
|
||||
f.WriteString(content)
|
||||
// gofmt generated source code
|
||||
// Run 'gofmt' on the generated source code
|
||||
formatSourceCode(fpath)
|
||||
fmt.Println("\tcreate\t", fpath)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", fpath, "\x1b[0m")
|
||||
} else {
|
||||
// error creating file
|
||||
ColorLog("[ERRO] Could not create model file: %s\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
@ -55,23 +74,27 @@ func generateModel(mname, fields, crupath string) {
|
||||
|
||||
func getStruct(structname, fields string) (string, bool, error) {
|
||||
if fields == "" {
|
||||
return "", false, errors.New("fields can't empty")
|
||||
return "", false, errors.New("fields cannot be empty")
|
||||
}
|
||||
|
||||
hastime := false
|
||||
structStr := "type " + structname + " struct{\n"
|
||||
fds := strings.Split(fields, ",")
|
||||
for i, v := range fds {
|
||||
kv := strings.SplitN(v, ":", 2)
|
||||
if len(kv) != 2 {
|
||||
return "", false, errors.New("the filds format is wrong. should key:type,key:type " + v)
|
||||
return "", false, errors.New("the fields format is wrong. Should be key:type,key:type " + v)
|
||||
}
|
||||
|
||||
typ, tag, hastimeinner := getType(kv[1])
|
||||
if typ == "" {
|
||||
return "", false, errors.New("the filds format is wrong. should key:type,key:type " + v)
|
||||
return "", false, errors.New("the fields format is wrong. Should be key:type,key:type " + v)
|
||||
}
|
||||
|
||||
if i == 0 && strings.ToLower(kv[0]) != "id" {
|
||||
structStr = structStr + "Id int64 `orm:\"auto\"`\n"
|
||||
}
|
||||
|
||||
if hastimeinner {
|
||||
hastime = true
|
||||
}
|
||||
@ -202,7 +225,7 @@ func GetAll{{modelName}}(query map[string]string, fields []string, sortby []stri
|
||||
|
||||
var l []{{modelName}}
|
||||
qs = qs.OrderBy(sortFields...)
|
||||
if _, err := qs.Limit(limit, offset).All(&l, fields...); err == nil {
|
||||
if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil {
|
||||
if len(fields) == 0 {
|
||||
for _, v := range l {
|
||||
ml = append(ml, v)
|
||||
|
@ -5,25 +5,28 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func generateScaffold(sname, fields, crupath, driver, conn string) {
|
||||
// generate model
|
||||
ColorLog("[INFO] Do you want to create a %v model? [yes|no]] ", sname)
|
||||
func generateScaffold(sname, fields, currpath, driver, conn string) {
|
||||
ColorLog("[INFO] Do you want to create a '%v' model? [Yes|No] ", sname)
|
||||
|
||||
// Generate the model
|
||||
if askForConfirmation() {
|
||||
generateModel(sname, fields, crupath)
|
||||
generateModel(sname, fields, currpath)
|
||||
}
|
||||
|
||||
// generate controller
|
||||
ColorLog("[INFO] Do you want to create a %v controller? [yes|no]] ", sname)
|
||||
// Generate the controller
|
||||
ColorLog("[INFO] Do you want to create a '%v' controller? [Yes|No] ", sname)
|
||||
if askForConfirmation() {
|
||||
generateController(sname, crupath)
|
||||
generateController(sname, currpath)
|
||||
}
|
||||
// generate view
|
||||
ColorLog("[INFO] Do you want to create views for this %v resource? [yes|no]] ", sname)
|
||||
|
||||
// Generate the views
|
||||
ColorLog("[INFO] Do you want to create views for this '%v' resource? [Yes|No] ", sname)
|
||||
if askForConfirmation() {
|
||||
generateView(sname, crupath)
|
||||
generateView(sname, currpath)
|
||||
}
|
||||
// generate migration
|
||||
ColorLog("[INFO] Do you want to create a %v migration and schema for this resource? [yes|no]] ", sname)
|
||||
|
||||
// Generate a migration
|
||||
ColorLog("[INFO] Do you want to create a '%v' migration and schema for this resource? [Yes|No] ", sname)
|
||||
if askForConfirmation() {
|
||||
upsql := ""
|
||||
downsql := ""
|
||||
@ -34,12 +37,13 @@ func generateScaffold(sname, fields, crupath, driver, conn string) {
|
||||
downsql = strings.Replace(downsql, "`", "", -1)
|
||||
}
|
||||
}
|
||||
generateMigration(sname, upsql, downsql, crupath)
|
||||
generateMigration(sname, upsql, downsql, currpath)
|
||||
}
|
||||
// run migration
|
||||
ColorLog("[INFO] Do you want to migrate the database? [yes|no]] ")
|
||||
|
||||
// Run the migration
|
||||
ColorLog("[INFO] Do you want to migrate the database? [Yes|No] ")
|
||||
if askForConfirmation() {
|
||||
migrateUpdate(crupath, driver, conn)
|
||||
migrateUpdate(currpath, driver, conn)
|
||||
}
|
||||
ColorLog("[INFO] All done! Don't forget to add beego.Router(\"/%v\" ,&controllers.%vController{}) to routers/route.go\n", sname, strings.Title(sname))
|
||||
}
|
||||
|
57
g_views.go
57
g_views.go
@ -1,49 +1,74 @@
|
||||
// Copyright 2013 bee authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// recipe
|
||||
// admin/recipe
|
||||
func generateView(vpath, crupath string) {
|
||||
func generateView(viewpath, currpath string) {
|
||||
w := NewColorWriter(os.Stdout)
|
||||
|
||||
ColorLog("[INFO] Generating view...\n")
|
||||
absvpath := path.Join(crupath, "views", vpath)
|
||||
os.MkdirAll(absvpath, os.ModePerm)
|
||||
cfile := path.Join(absvpath, "index.tpl")
|
||||
|
||||
absViewPath := path.Join(currpath, "views", viewpath)
|
||||
err := os.MkdirAll(absViewPath, os.ModePerm)
|
||||
if err != nil {
|
||||
ColorLog("[ERRO] Could not create '%s' view: %s\n", viewpath, err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
cfile := path.Join(absViewPath, "index.tpl")
|
||||
if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer f.Close()
|
||||
defer CloseFile(f)
|
||||
f.WriteString(cfile)
|
||||
fmt.Println("\tcreate\t", cfile)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
||||
} else {
|
||||
ColorLog("[ERRO] Could not create view file: %s\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
cfile = path.Join(absvpath, "show.tpl")
|
||||
|
||||
cfile = path.Join(absViewPath, "show.tpl")
|
||||
if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer f.Close()
|
||||
defer CloseFile(f)
|
||||
f.WriteString(cfile)
|
||||
fmt.Println("\tcreate\t", cfile)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
||||
} else {
|
||||
ColorLog("[ERRO] Could not create view file: %s\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
cfile = path.Join(absvpath, "create.tpl")
|
||||
|
||||
cfile = path.Join(absViewPath, "create.tpl")
|
||||
if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer f.Close()
|
||||
defer CloseFile(f)
|
||||
f.WriteString(cfile)
|
||||
fmt.Println("\tcreate\t", cfile)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
||||
} else {
|
||||
ColorLog("[ERRO] Could not create view file: %s\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
cfile = path.Join(absvpath, "edit.tpl")
|
||||
|
||||
cfile = path.Join(absViewPath, "edit.tpl")
|
||||
if f, err := os.OpenFile(cfile, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
|
||||
defer f.Close()
|
||||
defer CloseFile(f)
|
||||
f.WriteString(cfile)
|
||||
fmt.Println("\tcreate\t", cfile)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", cfile, "\x1b[0m")
|
||||
} else {
|
||||
ColorLog("[ERRO] Could not create view file: %s\n", err)
|
||||
os.Exit(2)
|
||||
|
18
hproseapp.go
18
hproseapp.go
@ -257,6 +257,8 @@ func init() {
|
||||
func createhprose(cmd *Command, args []string) int {
|
||||
ShowShortVersionBanner()
|
||||
|
||||
w := NewColorWriter(os.Stdout)
|
||||
|
||||
curpath, _ := os.Getwd()
|
||||
if len(args) > 1 {
|
||||
cmd.Flag.Parse(args[1:])
|
||||
@ -275,10 +277,10 @@ func createhprose(cmd *Command, args []string) int {
|
||||
ColorLog("[INFO] Creating Hprose application...\n")
|
||||
|
||||
os.MkdirAll(apppath, 0755)
|
||||
fmt.Println("\tcreate\t", apppath)
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "conf"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "conf"))
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "conf", "app.conf"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf"), "\x1b[0m")
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "conf", "app.conf"),
|
||||
strings.Replace(hproseconf, "{{.Appname}}", args[0], -1))
|
||||
|
||||
@ -287,7 +289,7 @@ func createhprose(cmd *Command, args []string) int {
|
||||
ColorLog("[INFO] Using '%s' as 'conn'\n", conn)
|
||||
ColorLog("[INFO] Using '%s' as 'tables'\n", tables)
|
||||
generateHproseAppcode(string(driver), string(conn), "1", string(tables), path.Join(curpath, args[0]))
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "main.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
maingoContent := strings.Replace(hproseMainconngo, "{{.Appname}}", packpath, -1)
|
||||
maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(driver), -1)
|
||||
maingoContent = strings.Replace(maingoContent, "{{HproseFunctionList}}", strings.Join(hproseAddFunctions, ""), -1)
|
||||
@ -306,15 +308,15 @@ func createhprose(cmd *Command, args []string) int {
|
||||
)
|
||||
} else {
|
||||
os.Mkdir(path.Join(apppath, "models"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "models"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models"), "\x1b[0m")
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "models", "object.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "object.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "models", "object.go"), apiModels)
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "models", "user.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "user.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "models", "user.go"), apiModels2)
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "main.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "main.go"),
|
||||
strings.Replace(hproseMaingo, "{{.Appname}}", packpath, -1))
|
||||
}
|
||||
|
43
migrate.go
43
migrate.go
@ -64,15 +64,16 @@ func init() {
|
||||
func runMigration(cmd *Command, args []string) int {
|
||||
ShowShortVersionBanner()
|
||||
|
||||
crupath, _ := os.Getwd()
|
||||
currpath, _ := os.Getwd()
|
||||
|
||||
gopath := os.Getenv("GOPATH")
|
||||
Debugf("gopath:%s", gopath)
|
||||
if gopath == "" {
|
||||
ColorLog("[ERRO] $GOPATH not found\n")
|
||||
ColorLog("[HINT] Set $GOPATH in your environment vairables\n")
|
||||
gps := GetGOPATHs()
|
||||
if len(gps) == 0 {
|
||||
ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty")
|
||||
os.Exit(2)
|
||||
}
|
||||
gopath := gps[0]
|
||||
Debugf("GOPATH: %s", gopath)
|
||||
|
||||
// load config
|
||||
err := loadConfig()
|
||||
if err != nil {
|
||||
@ -100,19 +101,19 @@ func runMigration(cmd *Command, args []string) int {
|
||||
if len(args) == 0 {
|
||||
// run all outstanding migrations
|
||||
ColorLog("[INFO] Running all outstanding migrations\n")
|
||||
migrateUpdate(crupath, driverStr, connStr)
|
||||
migrateUpdate(currpath, driverStr, connStr)
|
||||
} else {
|
||||
mcmd := args[0]
|
||||
switch mcmd {
|
||||
case "rollback":
|
||||
ColorLog("[INFO] Rolling back the last migration operation\n")
|
||||
migrateRollback(crupath, driverStr, connStr)
|
||||
migrateRollback(currpath, driverStr, connStr)
|
||||
case "reset":
|
||||
ColorLog("[INFO] Reseting all migrations\n")
|
||||
migrateReset(crupath, driverStr, connStr)
|
||||
migrateReset(currpath, driverStr, connStr)
|
||||
case "refresh":
|
||||
ColorLog("[INFO] Refreshing all migrations\n")
|
||||
migrateRefresh(crupath, driverStr, connStr)
|
||||
migrateRefresh(currpath, driverStr, connStr)
|
||||
default:
|
||||
ColorLog("[ERRO] Command is missing\n")
|
||||
os.Exit(2)
|
||||
@ -123,28 +124,28 @@ func runMigration(cmd *Command, args []string) int {
|
||||
}
|
||||
|
||||
// migrateUpdate does the schema update
|
||||
func migrateUpdate(crupath, driver, connStr string) {
|
||||
migrate("upgrade", crupath, driver, connStr)
|
||||
func migrateUpdate(currpath, driver, connStr string) {
|
||||
migrate("upgrade", currpath, driver, connStr)
|
||||
}
|
||||
|
||||
// migrateRollback rolls back the latest migration
|
||||
func migrateRollback(crupath, driver, connStr string) {
|
||||
migrate("rollback", crupath, driver, connStr)
|
||||
func migrateRollback(currpath, driver, connStr string) {
|
||||
migrate("rollback", currpath, driver, connStr)
|
||||
}
|
||||
|
||||
// migrateReset rolls back all migrations
|
||||
func migrateReset(crupath, driver, connStr string) {
|
||||
migrate("reset", crupath, driver, connStr)
|
||||
func migrateReset(currpath, driver, connStr string) {
|
||||
migrate("reset", currpath, driver, connStr)
|
||||
}
|
||||
|
||||
// migrationRefresh rolls back all migrations and start over again
|
||||
func migrateRefresh(crupath, driver, connStr string) {
|
||||
migrate("refresh", crupath, driver, connStr)
|
||||
func migrateRefresh(currpath, driver, connStr string) {
|
||||
migrate("refresh", currpath, driver, connStr)
|
||||
}
|
||||
|
||||
// migrate generates source code, build it, and invoke the binary who does the actual migration
|
||||
func migrate(goal, crupath, driver, connStr string) {
|
||||
dir := path.Join(crupath, "database", "migrations")
|
||||
func migrate(goal, currpath, driver, connStr string) {
|
||||
dir := path.Join(currpath, "database", "migrations")
|
||||
binary := "m"
|
||||
source := binary + ".go"
|
||||
// connect to database
|
||||
@ -299,7 +300,7 @@ func writeMigrationSourceFile(dir, source, driver, connStr string, latestTime in
|
||||
ColorLog("[ERRO] Could not write to file: %s\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
f.Close()
|
||||
CloseFile(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
53
new.go
53
new.go
@ -57,25 +57,29 @@ func init() {
|
||||
func createApp(cmd *Command, args []string) int {
|
||||
ShowShortVersionBanner()
|
||||
|
||||
w := NewColorWriter(os.Stdout)
|
||||
|
||||
if len(args) != 1 {
|
||||
ColorLog("[ERRO] Argument [appname] is missing\n")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
gopath := os.Getenv("GOPATH")
|
||||
Debugf("gopath:%s", gopath)
|
||||
if gopath == "" {
|
||||
ColorLog("[ERRO] $GOPATH not found\n")
|
||||
ColorLog("[HINT] Set $GOPATH in your environment variables\n")
|
||||
gps := GetGOPATHs()
|
||||
if len(gps) == 0 {
|
||||
ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty")
|
||||
os.Exit(2)
|
||||
}
|
||||
// In case of multiple paths in the GOPATH, by default
|
||||
// we use the first path
|
||||
gopath := gps[0]
|
||||
Debugf("GOPATH: %s", gopath)
|
||||
|
||||
gosrcpath := path.Join(gopath, "src") // User's workspace
|
||||
apppath := path.Join(gosrcpath, args[0])
|
||||
|
||||
if isExist(apppath) {
|
||||
ColorLog("[ERRO] Path (%s) already exists\n", apppath)
|
||||
ColorLog("[WARN] Do you want to overwrite it? [yes|no]]")
|
||||
ColorLog("[WARN] Do you want to overwrite it? [Yes|No] ")
|
||||
if !askForConfirmation() {
|
||||
os.Exit(2)
|
||||
}
|
||||
@ -84,43 +88,43 @@ func createApp(cmd *Command, args []string) int {
|
||||
ColorLog("[INFO] Creating application...\n")
|
||||
|
||||
os.MkdirAll(apppath, 0755)
|
||||
fmt.Println("\tcreate\t", apppath + string(path.Separator))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "conf"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "conf") + string(path.Separator))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "controllers"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "controllers") + string(path.Separator))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "models"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "models") + string(path.Separator))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "routers"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "routers") + string(path.Separator))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "tests"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "tests") + string(path.Separator))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "static"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "static") + string(path.Separator))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "static", "js"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "static", "js") + string(path.Separator))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "js")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "static", "css"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "static", "css") + string(path.Separator))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "css")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "static", "img"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "static", "img") + string(path.Separator))
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "views") + string(path.Separator))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "img")+string(path.Separator), "\x1b[0m")
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views")+string(path.Separator), "\x1b[0m")
|
||||
os.Mkdir(path.Join(apppath, "views"), 0755)
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "conf", "app.conf"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(appconf, "{{.Appname}}", path.Base(args[0]), -1))
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "controllers", "default.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "default.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "controllers", "default.go"), controllers)
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "views", "index.tpl"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views", "index.tpl"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "views", "index.tpl"), indextpl)
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "routers", "router.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(router, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1))
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "tests", "default_test.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests", "default_test.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(test, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1))
|
||||
|
||||
fmt.Println("\tcreate\t", path.Join(apppath, "main.go"))
|
||||
fmt.Fprintf(w, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
|
||||
WriteToFile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/"), -1))
|
||||
|
||||
ColorLog("[SUCC] New application successfully created!\n")
|
||||
@ -309,9 +313,10 @@ var indextpl = `<!DOCTYPE html>
|
||||
</html>
|
||||
`
|
||||
|
||||
// WriteToFile creates a file and writes content to it
|
||||
func WriteToFile(filename, content string) {
|
||||
f, err := os.Create(filename)
|
||||
defer f.Close()
|
||||
defer CloseFile(f)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
10
pack.go
10
pack.go
@ -72,6 +72,7 @@ var (
|
||||
buildEnvs ListOpts
|
||||
verbose bool
|
||||
format string
|
||||
w io.Writer
|
||||
)
|
||||
|
||||
type ListOpts []string
|
||||
@ -101,6 +102,7 @@ func init() {
|
||||
fs.BoolVar(&verbose, "v", false, "verbose")
|
||||
cmdPack.Flag = *fs
|
||||
cmdPack.Run = packApp
|
||||
w = NewColorWriter(os.Stdout)
|
||||
}
|
||||
|
||||
func exitPrint(con string) {
|
||||
@ -242,7 +244,7 @@ func (wft *walkFileTree) walkLeaf(fpath string, fi os.FileInfo, err error) error
|
||||
|
||||
if added, err := wft.wak.compress(name, fpath, fi); added {
|
||||
if verbose {
|
||||
fmt.Printf("\t+ Compressed: %s\n", name)
|
||||
fmt.Fprintf(w, "\t%s%scompressed%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", name, "\x1b[0m")
|
||||
}
|
||||
wft.allfiles[name] = true
|
||||
return err
|
||||
@ -338,7 +340,7 @@ func (wft *tarWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer fr.Close()
|
||||
defer CloseFile(fr)
|
||||
_, err = io.Copy(tw, fr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@ -374,7 +376,7 @@ func (wft *zipWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer fr.Close()
|
||||
defer CloseFile(fr)
|
||||
_, err = io.Copy(w, fr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@ -559,7 +561,7 @@ func packApp(cmd *Command, args []string) int {
|
||||
}
|
||||
|
||||
if verbose {
|
||||
fmt.Println("\t+ go", strings.Join(args, " "))
|
||||
fmt.Fprintf(w, "\t%s%s+ go %s%s%s\n", "\x1b[32m", "\x1b[1m", strings.Join(args, " "), "\x1b[21m", "\x1b[0m")
|
||||
}
|
||||
|
||||
execmd := exec.Command("go", args...)
|
||||
|
102
run.go
102
run.go
@ -15,6 +15,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
path "path/filepath"
|
||||
@ -32,18 +33,25 @@ it will recompile and restart the app after any modifications.
|
||||
`,
|
||||
}
|
||||
|
||||
var mainFiles ListOpts
|
||||
|
||||
var downdoc docValue
|
||||
var gendoc docValue
|
||||
|
||||
// The flags list of the paths excluded from watching
|
||||
var excludedPaths strFlags
|
||||
|
||||
// Pass through to -tags arg of "go build"
|
||||
var buildTags string
|
||||
|
||||
var vendorWatch bool
|
||||
var (
|
||||
mainFiles ListOpts
|
||||
downdoc docValue
|
||||
gendoc docValue
|
||||
// The flags list of the paths excluded from watching
|
||||
excludedPaths strFlags
|
||||
// Pass through to -tags arg of "go build"
|
||||
buildTags string
|
||||
// Application path
|
||||
currpath string
|
||||
// Application name
|
||||
appname string
|
||||
// Channel to signal an Exit
|
||||
exit chan bool
|
||||
// Flag to watch the vendor folder
|
||||
vendorWatch bool
|
||||
// Current user workspace
|
||||
currentGoPath string
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmdRun.Run = runApp
|
||||
@ -53,31 +61,44 @@ func init() {
|
||||
cmdRun.Flag.Var(&excludedPaths, "e", "Excluded paths[].")
|
||||
cmdRun.Flag.BoolVar(&vendorWatch, "vendor", false, "Watch vendor folder")
|
||||
cmdRun.Flag.StringVar(&buildTags, "tags", "", "Build tags (https://golang.org/pkg/go/build/)")
|
||||
exit = make(chan bool)
|
||||
}
|
||||
|
||||
var appname string
|
||||
|
||||
func runApp(cmd *Command, args []string) int {
|
||||
ShowShortVersionBanner()
|
||||
|
||||
exit := make(chan bool)
|
||||
crupath, _ := os.Getwd()
|
||||
|
||||
if len(args) == 0 || args[0] == "watchall" {
|
||||
appname = path.Base(crupath)
|
||||
ColorLog("[INFO] Uses '%s' as 'appname'\n", appname)
|
||||
currpath, _ = os.Getwd()
|
||||
|
||||
if found, _gopath, _ := SearchGOPATHs(currpath); found {
|
||||
appname = path.Base(currpath)
|
||||
currentGoPath = _gopath
|
||||
} else {
|
||||
appname = args[0]
|
||||
ColorLog("[INFO] Uses '%s' as 'appname'\n", appname)
|
||||
if strings.HasSuffix(appname, ".go") && isExist(path.Join(crupath, appname)) {
|
||||
ColorLog("[WARN] The appname has conflic with crupath's file, do you want to build appname as %s\n", appname)
|
||||
exitPrint(fmt.Sprintf("Bee does not support non Beego project: %s", currpath))
|
||||
}
|
||||
ColorLog("[INFO] Using '%s' as 'appname'\n", appname)
|
||||
} else {
|
||||
// Check if passed Bee application path/name exists in the GOPATH(s)
|
||||
if found, _gopath, _path := SearchGOPATHs(args[0]); found {
|
||||
currpath = _path
|
||||
currentGoPath = _gopath
|
||||
appname = path.Base(currpath)
|
||||
} else {
|
||||
panic(fmt.Sprintf("No Beego application '%s' found in your GOPATH", args[0]))
|
||||
}
|
||||
|
||||
ColorLog("[INFO] Using '%s' as 'appname'\n", appname)
|
||||
|
||||
if strings.HasSuffix(appname, ".go") && isExist(currpath) {
|
||||
ColorLog("[WARN] The appname is in conflict with currpath's file, do you want to build appname as %s\n", appname)
|
||||
ColorLog("[INFO] Do you want to overwrite it? [yes|no]] ")
|
||||
if !askForConfirmation() {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
Debugf("current path:%s\n", crupath)
|
||||
|
||||
Debugf("current path:%s\n", currpath)
|
||||
|
||||
err := loadConfig()
|
||||
if err != nil {
|
||||
@ -85,19 +106,12 @@ func runApp(cmd *Command, args []string) int {
|
||||
}
|
||||
|
||||
var paths []string
|
||||
|
||||
readAppDirectories(crupath, &paths)
|
||||
readAppDirectories(currpath, &paths)
|
||||
|
||||
// Because monitor files has some issues, we watch current directory
|
||||
// and ignore non-go files.
|
||||
gps := GetGOPATHs()
|
||||
if len(gps) == 0 {
|
||||
ColorLog("[ERRO] Fail to start[ %s ]\n", "$GOPATH is not set or empty")
|
||||
os.Exit(2)
|
||||
}
|
||||
gopath := gps[0]
|
||||
for _, p := range conf.DirStruct.Others {
|
||||
paths = append(paths, strings.Replace(p, "$GOPATH", gopath, -1))
|
||||
paths = append(paths, strings.Replace(p, "$GOPATH", currentGoPath, -1))
|
||||
}
|
||||
|
||||
files := []string{}
|
||||
@ -106,7 +120,14 @@ func runApp(cmd *Command, args []string) int {
|
||||
files = append(files, arg)
|
||||
}
|
||||
}
|
||||
|
||||
if downdoc == "true" {
|
||||
if _, err := os.Stat(path.Join(currpath, "swagger", "index.html")); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
downloadFromURL(swaggerlink, "swagger.zip")
|
||||
unzipAndDelete("swagger.zip")
|
||||
}
|
||||
}
|
||||
}
|
||||
if gendoc == "true" {
|
||||
NewWatcher(paths, files, true)
|
||||
Autobuild(files, true)
|
||||
@ -114,14 +135,7 @@ func runApp(cmd *Command, args []string) int {
|
||||
NewWatcher(paths, files, false)
|
||||
Autobuild(files, false)
|
||||
}
|
||||
if downdoc == "true" {
|
||||
if _, err := os.Stat(path.Join(crupath, "swagger")); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
downloadFromURL(swaggerlink, "swagger.zip")
|
||||
unzipAndDelete("swagger.zip", "swagger")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-exit:
|
||||
@ -141,6 +155,9 @@ func readAppDirectories(directory string, paths *[]string) {
|
||||
if strings.HasSuffix(fileInfo.Name(), "docs") {
|
||||
continue
|
||||
}
|
||||
if strings.HasSuffix(fileInfo.Name(), "swagger") {
|
||||
continue
|
||||
}
|
||||
|
||||
if !vendorWatch && strings.HasSuffix(fileInfo.Name(), "vendor") {
|
||||
continue
|
||||
@ -164,7 +181,6 @@ func readAppDirectories(directory string, paths *[]string) {
|
||||
useDirectory = true
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
50
rundocs.go
50
rundocs.go
@ -20,7 +20,6 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var cmdRundocs = &Command{
|
||||
@ -33,8 +32,9 @@ var cmdRundocs = &Command{
|
||||
`,
|
||||
}
|
||||
|
||||
const (
|
||||
swaggerlink = "https://github.com/beego/swagger/archive/v1.zip"
|
||||
var (
|
||||
swaggerVersion = "2"
|
||||
swaggerlink = "https://github.com/beego/swagger/archive/v" + swaggerVersion + ".zip"
|
||||
)
|
||||
|
||||
type docValue string
|
||||
@ -60,7 +60,7 @@ func init() {
|
||||
func runDocs(cmd *Command, args []string) int {
|
||||
if isDownload == "true" {
|
||||
downloadFromURL(swaggerlink, "swagger.zip")
|
||||
err := unzipAndDelete("swagger.zip", "swagger")
|
||||
err := unzipAndDelete("swagger.zip")
|
||||
if err != nil {
|
||||
fmt.Println("has err exet unzipAndDelete", err)
|
||||
}
|
||||
@ -78,33 +78,42 @@ func runDocs(cmd *Command, args []string) int {
|
||||
}
|
||||
|
||||
func downloadFromURL(url, fileName string) {
|
||||
fmt.Println("Downloading", url, "to", fileName)
|
||||
|
||||
var down bool
|
||||
if fd, err := os.Stat(fileName); err != nil && os.IsNotExist(err) {
|
||||
down = true
|
||||
} else if fd.Size() == int64(0) {
|
||||
down = true
|
||||
} else {
|
||||
ColorLog("[%s] Filename %s already exist\n", INFO, fileName)
|
||||
return
|
||||
}
|
||||
if down {
|
||||
ColorLog("[%s]Downloading %s to %s\n", SUCC, url, fileName)
|
||||
output, err := os.Create(fileName)
|
||||
if err != nil {
|
||||
fmt.Println("Error while creating", fileName, "-", err)
|
||||
ColorLog("[%s]Error while creating %s: %s\n", ERRO, fileName, err)
|
||||
return
|
||||
}
|
||||
defer output.Close()
|
||||
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
fmt.Println("Error while downloading", url, "-", err)
|
||||
ColorLog("[%s]Error while downloading %s:%s\n", ERRO, url, err)
|
||||
return
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
n, err := io.Copy(output, response.Body)
|
||||
if err != nil {
|
||||
fmt.Println("Error while downloading", url, "-", err)
|
||||
ColorLog("[%s]Error while downloading %s:%s\n", ERRO, url, err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(n, "bytes downloaded.")
|
||||
ColorLog("[%s] %d bytes downloaded.\n", SUCC, n)
|
||||
}
|
||||
}
|
||||
|
||||
func unzipAndDelete(src, dest string) error {
|
||||
fmt.Println("start to unzip file from " + src + " to " + dest)
|
||||
func unzipAndDelete(src string) error {
|
||||
ColorLog("[%s]start to unzip file from %s\n", INFO, src)
|
||||
r, err := zip.OpenReader(src)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -118,12 +127,11 @@ func unzipAndDelete(src, dest string) error {
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
path := filepath.Join(dest, f.Name)
|
||||
if f.FileInfo().IsDir() {
|
||||
os.MkdirAll(path, f.Mode())
|
||||
os.MkdirAll(f.Name, f.Mode())
|
||||
} else {
|
||||
f, err := os.OpenFile(
|
||||
path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
f.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -135,11 +143,11 @@ func unzipAndDelete(src, dest string) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("Start delete src file " + src)
|
||||
err = os.RemoveAll(src)
|
||||
os.RemoveAll("swagger")
|
||||
err = os.Rename("swagger-"+swaggerVersion, "swagger")
|
||||
if err != nil {
|
||||
return err
|
||||
ColorLog("[%s]Rename swagger-%s to swagger:%s\n", ERRO, swaggerVersion, err)
|
||||
}
|
||||
return nil
|
||||
ColorLog("[%s]Start delete src file %s\n", INFO, src)
|
||||
return os.RemoveAll(src)
|
||||
}
|
||||
|
39
util.go
39
util.go
@ -15,13 +15,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
"path"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Go is a basic promise implementation: it wraps calls a function in a goroutine
|
||||
@ -173,6 +174,34 @@ func GetGOPATHs() []string {
|
||||
return paths
|
||||
}
|
||||
|
||||
func SearchGOPATHs(app string) (bool, string, string) {
|
||||
gps := GetGOPATHs()
|
||||
if len(gps) == 0 {
|
||||
ColorLog("[ERRO] Fail to start [ %s ]\n", "GOPATH environment variable is not set or empty")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
// Lookup the application inside the user workspace(s)
|
||||
for _, gopath := range gps {
|
||||
var currentPath string
|
||||
|
||||
if !strings.Contains(app, "src") {
|
||||
gopathsrc := path.Join(gopath, "src")
|
||||
currentPath = path.Join(gopathsrc, app)
|
||||
} else {
|
||||
currentPath = app
|
||||
}
|
||||
|
||||
if isExist(currentPath) {
|
||||
if !isBeegoProject(currentPath) {
|
||||
continue
|
||||
}
|
||||
return true, gopath, currentPath
|
||||
}
|
||||
}
|
||||
return false, "", ""
|
||||
}
|
||||
|
||||
// askForConfirmation uses Scanln to parse user input. A user must type in "yes" or "no" and
|
||||
// then press enter. It has fuzzy matching, so "y", "Y", "yes", "YES", and "Yes" all count as
|
||||
// confirmations. If the input is not recognized, it will ask again. The function does not return
|
||||
@ -258,3 +287,11 @@ func (s *strFlags) Set(value string) error {
|
||||
*s = append(*s, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CloseFile attempts to close the passed file
|
||||
// or panics with the actual error
|
||||
func CloseFile(f *os.File) {
|
||||
if err := f.Close(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
52
version.go
52
version.go
@ -2,54 +2,47 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
path "path/filepath"
|
||||
"regexp"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
var cmdVersion = &Command{
|
||||
UsageLine: "version",
|
||||
Short: "show the Bee, Beego and Go version",
|
||||
Short: "prints the current Bee version",
|
||||
Long: `
|
||||
show the Bee, Beego and Go version
|
||||
|
||||
bee version
|
||||
bee :1.2.3
|
||||
beego :1.4.2
|
||||
Go :go version go1.3.3 linux/amd64
|
||||
Prints the current Bee, Beego and Go version alongside the platform information
|
||||
|
||||
`,
|
||||
}
|
||||
|
||||
const verboseVersionBanner =
|
||||
`______
|
||||
const verboseVersionBanner string = `%s%s______
|
||||
| ___ \
|
||||
| |_/ / ___ ___
|
||||
| ___ \ / _ \ / _ \
|
||||
| |_/ /| __/| __/
|
||||
\____/ \___| \___| v{{ .BeeVersion }}
|
||||
|
||||
Beego : {{ .BeegoVersion }}
|
||||
GoVersion : {{ .GoVersion }}
|
||||
GOOS : {{ .GOOS }}
|
||||
GOARCH : {{ .GOARCH }}
|
||||
NumCPU : {{ .NumCPU }}
|
||||
GOPATH : {{ .GOPATH }}
|
||||
GOROOT : {{ .GOROOT }}
|
||||
Compiler : {{ .Compiler }}
|
||||
Date : {{ Now "Monday, 2 Jan 2006" }}
|
||||
\____/ \___| \___| v{{ .BeeVersion }}%s
|
||||
%s%s
|
||||
├── Beego : {{ .BeegoVersion }}
|
||||
├── GoVersion : {{ .GoVersion }}
|
||||
├── GOOS : {{ .GOOS }}
|
||||
├── GOARCH : {{ .GOARCH }}
|
||||
├── NumCPU : {{ .NumCPU }}
|
||||
├── GOPATH : {{ .GOPATH }}
|
||||
├── GOROOT : {{ .GOROOT }}
|
||||
├── Compiler : {{ .Compiler }}
|
||||
└── Date : {{ Now "Monday, 2 Jan 2006" }}%s
|
||||
`
|
||||
|
||||
const shortVersionBanner =
|
||||
`______
|
||||
const shortVersionBanner = `%s%s______
|
||||
| ___ \
|
||||
| |_/ / ___ ___
|
||||
| ___ \ / _ \ / _ \
|
||||
| |_/ /| __/| __/
|
||||
\____/ \___| \___| v{{ .BeeVersion }}
|
||||
\____/ \___| \___| v{{ .BeeVersion }}%s
|
||||
`
|
||||
|
||||
func init() {
|
||||
@ -61,12 +54,19 @@ func versionCmd(cmd *Command, args []string) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// ShowVerboseVersionBanner prints the verbose version banner
|
||||
func ShowVerboseVersionBanner() {
|
||||
InitBanner(os.Stdout, bytes.NewBufferString(verboseVersionBanner))
|
||||
w := NewColorWriter(os.Stdout)
|
||||
coloredBanner := fmt.Sprintf(verboseVersionBanner, "\x1b[35m", "\x1b[1m", "\x1b[0m",
|
||||
"\x1b[32m", "\x1b[1m", "\x1b[0m")
|
||||
InitBanner(w, bytes.NewBufferString(coloredBanner))
|
||||
}
|
||||
|
||||
// ShowShortVersionBanner prints the short version banner
|
||||
func ShowShortVersionBanner() {
|
||||
InitBanner(os.Stdout, bytes.NewBufferString(shortVersionBanner))
|
||||
w := NewColorWriter(os.Stdout)
|
||||
coloredBanner := fmt.Sprintf(shortVersionBanner, "\x1b[35m", "\x1b[1m", "\x1b[0m")
|
||||
InitBanner(w, bytes.NewBufferString(coloredBanner))
|
||||
}
|
||||
|
||||
func getBeegoVersion() string {
|
||||
|
33
watch.go
33
watch.go
@ -17,14 +17,14 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/howeyc/fsnotify"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/howeyc/fsnotify"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -47,8 +47,8 @@ func NewWatcher(paths []string, files []string, isgenerate bool) {
|
||||
case e := <-watcher.Event:
|
||||
isbuild := true
|
||||
|
||||
// Skip TMP files for Sublime Text.
|
||||
if checkTMPFile(e.Name) {
|
||||
// Skip ignored files
|
||||
if shouldIgnoreFile(e.Name) {
|
||||
continue
|
||||
}
|
||||
if !checkIfWatchExt(e.Name) {
|
||||
@ -121,8 +121,8 @@ func Autobuild(files []string, isgenerate bool) {
|
||||
defer state.Unlock()
|
||||
|
||||
ColorLog("[INFO] Start building...\n")
|
||||
path, _ := os.Getwd()
|
||||
os.Chdir(path)
|
||||
|
||||
os.Chdir(currpath)
|
||||
|
||||
cmdName := "go"
|
||||
if conf.Gopm.Enable {
|
||||
@ -230,15 +230,30 @@ func Start(appname string) {
|
||||
started <- true
|
||||
}
|
||||
|
||||
// checkTMPFile returns true if the event was for TMP files.
|
||||
func checkTMPFile(name string) bool {
|
||||
if strings.HasSuffix(strings.ToLower(name), ".tmp") {
|
||||
// Should ignore filenames generated by
|
||||
// Emacs, Vim or SublimeText
|
||||
func shouldIgnoreFile(filename string) bool {
|
||||
for _, regex := range ignoredFilesRegExps {
|
||||
r, err := regexp.Compile(regex)
|
||||
if err != nil {
|
||||
panic("Could not compile the regex: " + regex)
|
||||
}
|
||||
if r.MatchString(filename) {
|
||||
return true
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var watchExts = []string{".go"}
|
||||
var ignoredFilesRegExps = []string{
|
||||
`.#(\w+).go`,
|
||||
`.(\w+).go.swp`,
|
||||
`(\w+).go~`,
|
||||
`(\w+).tmp`,
|
||||
}
|
||||
|
||||
// checkIfWatchExt returns true if the name HasSuffix <watch_ext>.
|
||||
func checkIfWatchExt(name string) bool {
|
||||
|
Loading…
Reference in New Issue
Block a user