mirror of
https://github.com/kevin-DL/revel-cmd.git
synced 2026-01-12 02:55:16 +00:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97ec142262 | ||
|
|
dfc873bc15 | ||
|
|
cca02dd5ff | ||
|
|
91f43bf94c | ||
|
|
0583fe7d32 | ||
|
|
6ca1d73b61 | ||
|
|
4c87861642 | ||
|
|
a2d7517ca0 | ||
|
|
8efaff19ce | ||
|
|
ac056d17af | ||
|
|
fc904827cd | ||
|
|
c240b05369 | ||
|
|
29e594435c | ||
|
|
a2acbe32bf | ||
|
|
29c6237caf | ||
|
|
2d4ccf289c | ||
|
|
f38fb6a15d | ||
|
|
637ccbd250 | ||
|
|
2da4734499 | ||
|
|
aa9e0f8600 | ||
|
|
db4054233b | ||
|
|
3907c6575e | ||
|
|
27e9fab270 | ||
|
|
17e7d40d31 | ||
|
|
54ce8d3699 | ||
|
|
8ab98db556 | ||
|
|
baf5e9f848 | ||
|
|
9d57681ae6 | ||
|
|
3f136726db | ||
|
|
c0a515facf | ||
|
|
01494f75fb | ||
|
|
e6b34786bb | ||
|
|
79b2afb5e5 | ||
|
|
5fcde12193 | ||
|
|
ad68773b9e | ||
|
|
e5255cd373 | ||
|
|
3cf6d5094e | ||
|
|
efcd02de37 | ||
|
|
7eda33eb71 | ||
|
|
1c5fb4a6f8 | ||
|
|
a699dab33d | ||
|
|
e1776bda3c | ||
|
|
d68b27ae81 | ||
|
|
ce84b78204 | ||
|
|
19ca52182d | ||
|
|
bf30aab381 | ||
|
|
bd4663b651 | ||
|
|
b81860de5f | ||
|
|
d2b1730439 | ||
|
|
0381636044 | ||
|
|
fb3980ce9d |
@@ -58,11 +58,11 @@ func NewAppCmd(binPath string, port int) AppCmd {
|
||||
|
||||
// Start the app server, and wait until it is ready to serve requests.
|
||||
func (cmd AppCmd) Start() error {
|
||||
listeningWriter := startupListeningWriter{os.Stdout, make(chan bool)}
|
||||
listeningWriter := &startupListeningWriter{os.Stdout, make(chan bool)}
|
||||
cmd.Stdout = listeningWriter
|
||||
revel.TRACE.Println("Exec app:", cmd.Path, cmd.Args)
|
||||
revel.RevelLog.Debug("Exec app:", "path", cmd.Path, "args", cmd.Args)
|
||||
if err := cmd.Cmd.Start(); err != nil {
|
||||
revel.ERROR.Fatalln("Error running:", err)
|
||||
revel.RevelLog.Fatal("Error running:", "error", err)
|
||||
}
|
||||
|
||||
select {
|
||||
@@ -70,6 +70,7 @@ func (cmd AppCmd) Start() error {
|
||||
return errors.New("revel/harness: app died")
|
||||
|
||||
case <-time.After(30 * time.Second):
|
||||
revel.RevelLog.Debug("Killing revel server process did not respond after wait timeout", "processid", cmd.Process.Pid)
|
||||
cmd.Kill()
|
||||
return errors.New("revel/harness: app timed out")
|
||||
|
||||
@@ -83,19 +84,19 @@ func (cmd AppCmd) Start() error {
|
||||
|
||||
// Run the app server inline. Never returns.
|
||||
func (cmd AppCmd) Run() {
|
||||
revel.TRACE.Println("Exec app:", cmd.Path, cmd.Args)
|
||||
revel.RevelLog.Debug("Exec app:", "path", cmd.Path, "args", cmd.Args)
|
||||
if err := cmd.Cmd.Run(); err != nil {
|
||||
revel.ERROR.Fatalln("Error running:", err)
|
||||
revel.RevelLog.Fatal("Error running:", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Kill terminates the app server if it's running.
|
||||
func (cmd AppCmd) Kill() {
|
||||
if cmd.Cmd != nil && (cmd.ProcessState == nil || !cmd.ProcessState.Exited()) {
|
||||
revel.TRACE.Println("Killing revel server pid", cmd.Process.Pid)
|
||||
revel.RevelLog.Debug("Killing revel server pid", "pid", cmd.Process.Pid)
|
||||
err := cmd.Process.Kill()
|
||||
if err != nil {
|
||||
revel.ERROR.Fatalln("Failed to kill revel server:", err)
|
||||
revel.RevelLog.Fatal("Failed to kill revel server:", "error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,7 +119,7 @@ type startupListeningWriter struct {
|
||||
notifyReady chan bool
|
||||
}
|
||||
|
||||
func (w startupListeningWriter) Write(p []byte) (n int, err error) {
|
||||
func (w *startupListeningWriter) Write(p []byte) (n int, err error) {
|
||||
if w.notifyReady != nil && bytes.Contains(p, []byte("Listening")) {
|
||||
w.notifyReady <- true
|
||||
w.notifyReady = nil
|
||||
|
||||
149
harness/build.go
Executable file → Normal file
149
harness/build.go
Executable file → Normal file
@@ -17,12 +17,19 @@ import (
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
"sort"
|
||||
|
||||
"github.com/revel/revel"
|
||||
)
|
||||
|
||||
var importErrorPattern = regexp.MustCompile("cannot find package \"([^\"]+)\"")
|
||||
|
||||
type ByString []*TypeInfo
|
||||
|
||||
func (c ByString) Len() int { return len(c) }
|
||||
func (c ByString) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
||||
func (c ByString) Less(i, j int) bool { return c[i].String() < c[j].String() }
|
||||
|
||||
// Build the app:
|
||||
// 1. Generate the the main.go file.
|
||||
// 2. Run the appropriate "go build" command.
|
||||
@@ -39,12 +46,16 @@ func Build(buildFlags ...string) (app *App, compileError *revel.Error) {
|
||||
|
||||
// Add the db.import to the import paths.
|
||||
if dbImportPath, found := revel.Config.String("db.import"); found {
|
||||
sourceInfo.InitImportPaths = append(sourceInfo.InitImportPaths, dbImportPath)
|
||||
sourceInfo.InitImportPaths = append(sourceInfo.InitImportPaths, strings.Split(dbImportPath, ",")...)
|
||||
}
|
||||
|
||||
// Sort controllers so that file generation is reproducible
|
||||
controllers := sourceInfo.ControllerSpecs()
|
||||
sort.Stable(ByString(controllers))
|
||||
|
||||
// Generate two source files.
|
||||
templateArgs := map[string]interface{}{
|
||||
"Controllers": sourceInfo.ControllerSpecs(),
|
||||
"Controllers": controllers,
|
||||
"ValidationKeys": sourceInfo.ValidationKeys,
|
||||
"ImportPaths": calcImportAliases(sourceInfo),
|
||||
"TestSuites": sourceInfo.TestSuites(),
|
||||
@@ -59,12 +70,46 @@ func Build(buildFlags ...string) (app *App, compileError *revel.Error) {
|
||||
// It relies on the user having "go" installed.
|
||||
goPath, err := exec.LookPath("go")
|
||||
if err != nil {
|
||||
revel.ERROR.Fatalf("Go executable not found in PATH.")
|
||||
revel.RevelLog.Fatalf("Go executable not found in PATH.")
|
||||
}
|
||||
|
||||
// Detect if deps tool should be used (is there a vendor folder ?)
|
||||
useVendor := revel.DirExists(filepath.Join(revel.BasePath, "vendor"))
|
||||
basePath := revel.BasePath
|
||||
for !useVendor {
|
||||
basePath = filepath.Dir(basePath)
|
||||
found := false
|
||||
// Check to see if we are still in the GOPATH
|
||||
for _, path := range filepath.SplitList(build.Default.GOPATH) {
|
||||
if strings.HasPrefix(basePath, path) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
break
|
||||
} else {
|
||||
useVendor = revel.DirExists(filepath.Join(basePath, "vendor"))
|
||||
}
|
||||
}
|
||||
|
||||
var depPath string
|
||||
if useVendor {
|
||||
revel.RevelLog.Info("Vendor folder detected, scanning for deps in path")
|
||||
depPath, err = exec.LookPath("dep")
|
||||
if err != nil {
|
||||
// Do not halt build unless a new package needs to be imported
|
||||
revel.RevelLog.Warn("Build: `dep` executable not found in PATH, but vendor folder detected." +
|
||||
"Packages can only be added automatically to the vendor folder using the `dep` tool. " +
|
||||
"You can install the `dep` tool by doing a `go get -u github.com/golang/dep/cmd/dep`")
|
||||
}
|
||||
} else {
|
||||
revel.RevelLog.Info("No vendor folder detected, not using dependency manager to import files")
|
||||
}
|
||||
|
||||
pkg, err := build.Default.Import(revel.ImportPath, "", build.FindOnly)
|
||||
if err != nil {
|
||||
revel.ERROR.Fatalln("Failure importing", revel.ImportPath)
|
||||
revel.RevelLog.Fatal("Failure importing", "path", revel.ImportPath)
|
||||
}
|
||||
|
||||
// Binary path is a combination of $GOBIN/revel.d directory, app's import path and its name.
|
||||
@@ -87,12 +132,6 @@ func Build(buildFlags ...string) (app *App, compileError *revel.Error) {
|
||||
versionLinkerFlags := fmt.Sprintf("-X %s/app.AppVersion=%s -X %s/app.BuildTime=%s",
|
||||
revel.ImportPath, appVersion, revel.ImportPath, buildTime)
|
||||
|
||||
// TODO remove version check for versionLinkerFlags after Revel becomes Go min version to go1.5
|
||||
goVersion, _ := strconv.ParseFloat(runtime.Version()[2:5], 64)
|
||||
if goVersion < 1.5 {
|
||||
versionLinkerFlags = fmt.Sprintf("-X %s/app.AppVersion \"%s\" -X %s/app.BuildTime \"%s\"",
|
||||
revel.ImportPath, appVersion, revel.ImportPath, buildTime)
|
||||
}
|
||||
flags := []string{
|
||||
"build",
|
||||
"-i",
|
||||
@@ -108,42 +147,58 @@ func Build(buildFlags ...string) (app *App, compileError *revel.Error) {
|
||||
flags = append(flags, path.Join(revel.ImportPath, "app", "tmp"))
|
||||
|
||||
buildCmd := exec.Command(goPath, flags...)
|
||||
revel.TRACE.Println("Exec:", buildCmd.Args)
|
||||
revel.RevelLog.Debug("Exec:", "args", buildCmd.Args)
|
||||
output, err := buildCmd.CombinedOutput()
|
||||
|
||||
// If the build succeeded, we're done.
|
||||
if err == nil {
|
||||
return NewApp(binName), nil
|
||||
}
|
||||
revel.ERROR.Println(string(output))
|
||||
revel.RevelLog.Error(string(output))
|
||||
|
||||
// See if it was an import error that we can go get.
|
||||
matches := importErrorPattern.FindStringSubmatch(string(output))
|
||||
matches := importErrorPattern.FindAllStringSubmatch(string(output), -1)
|
||||
if matches == nil {
|
||||
return nil, newCompileError(output)
|
||||
}
|
||||
for _, match := range matches {
|
||||
// Ensure we haven't already tried to go get it.
|
||||
pkgName := match[1]
|
||||
if _, alreadyTried := gotten[pkgName]; alreadyTried {
|
||||
return nil, newCompileError(output)
|
||||
}
|
||||
gotten[pkgName] = struct{}{}
|
||||
|
||||
// Ensure we haven't already tried to go get it.
|
||||
pkgName := matches[1]
|
||||
if _, alreadyTried := gotten[pkgName]; alreadyTried {
|
||||
return nil, newCompileError(output)
|
||||
}
|
||||
gotten[pkgName] = struct{}{}
|
||||
|
||||
// Execute "go get <pkg>"
|
||||
getCmd := exec.Command(goPath, "get", pkgName)
|
||||
revel.TRACE.Println("Exec:", getCmd.Args)
|
||||
getOutput, err := getCmd.CombinedOutput()
|
||||
if err != nil {
|
||||
revel.ERROR.Println(string(getOutput))
|
||||
return nil, newCompileError(output)
|
||||
// Execute "go get <pkg>"
|
||||
// Or dep `dep ensure -add <pkg>` if it is there
|
||||
var getCmd *exec.Cmd
|
||||
if useVendor {
|
||||
if depPath == "" {
|
||||
revel.RevelLog.Error("Build: Vendor folder found, but the `dep` tool was not found, " +
|
||||
"if you use a different vendoring (package management) tool please add the following packages by hand, " +
|
||||
"or install the `dep` tool into your gopath by doing a `go get -u github.com/golang/dep/cmd/dep`. " +
|
||||
"For more information and usage of the tool please see http://github.com/golang/dep")
|
||||
for _, pkg := range matches {
|
||||
revel.RevelLog.Error("Missing package", "package", pkg[1])
|
||||
}
|
||||
}
|
||||
getCmd = exec.Command(depPath, "ensure", "-add", pkgName)
|
||||
} else {
|
||||
getCmd = exec.Command(goPath, "get", pkgName)
|
||||
}
|
||||
revel.RevelLog.Debug("Exec:", "args", getCmd.Args)
|
||||
getOutput, err := getCmd.CombinedOutput()
|
||||
if err != nil {
|
||||
revel.RevelLog.Error(string(getOutput))
|
||||
return nil, newCompileError(output)
|
||||
}
|
||||
}
|
||||
|
||||
// Success getting the import, attempt to build again.
|
||||
}
|
||||
|
||||
// TODO remove this unreachable code and document it
|
||||
revel.ERROR.Fatalf("Not reachable")
|
||||
revel.RevelLog.Fatalf("Not reachable")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -166,12 +221,12 @@ func getAppVersion() string {
|
||||
if (err != nil && os.IsNotExist(err)) || !info.IsDir() {
|
||||
return ""
|
||||
}
|
||||
gitCmd := exec.Command(gitPath, "--git-dir="+gitDir, "describe", "--always", "--dirty")
|
||||
revel.TRACE.Println("Exec:", gitCmd.Args)
|
||||
gitCmd := exec.Command(gitPath, "--git-dir="+gitDir, "--work-tree="+revel.BasePath, "describe", "--always", "--dirty")
|
||||
revel.RevelLog.Debug("Exec:", "args", gitCmd.Args)
|
||||
output, err := gitCmd.Output()
|
||||
|
||||
if err != nil {
|
||||
revel.WARN.Println("Cannot determine git repository version:", err)
|
||||
revel.RevelLog.Warn("Cannot determine git repository version:", "error", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -188,12 +243,12 @@ func cleanSource(dirs ...string) {
|
||||
}
|
||||
|
||||
func cleanDir(dir string) {
|
||||
revel.INFO.Println("Cleaning dir " + dir)
|
||||
revel.RevelLog.Info("Cleaning dir " + dir)
|
||||
tmpPath := filepath.Join(revel.AppPath, dir)
|
||||
f, err := os.Open(tmpPath)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
revel.ERROR.Println("Failed to clean dir:", err)
|
||||
revel.RevelLog.Error("Failed to clean dir:", "error", err)
|
||||
}
|
||||
} else {
|
||||
defer func() {
|
||||
@@ -203,20 +258,20 @@ func cleanDir(dir string) {
|
||||
infos, err := f.Readdir(0)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
revel.ERROR.Println("Failed to clean dir:", err)
|
||||
revel.RevelLog.Error("Failed to clean dir:", "error", err)
|
||||
}
|
||||
} else {
|
||||
for _, info := range infos {
|
||||
path := filepath.Join(tmpPath, info.Name())
|
||||
pathName := filepath.Join(tmpPath, info.Name())
|
||||
if info.IsDir() {
|
||||
err := os.RemoveAll(path)
|
||||
err := os.RemoveAll(pathName)
|
||||
if err != nil {
|
||||
revel.ERROR.Println("Failed to remove dir:", err)
|
||||
revel.RevelLog.Error("Failed to remove dir:", "error", err)
|
||||
}
|
||||
} else {
|
||||
err := os.Remove(path)
|
||||
err := os.Remove(pathName)
|
||||
if err != nil {
|
||||
revel.ERROR.Println("Failed to remove file:", err)
|
||||
revel.RevelLog.Error("Failed to remove file:", "error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,20 +291,20 @@ func genSource(dir, filename, templateSource string, args map[string]interface{}
|
||||
tmpPath := filepath.Join(revel.AppPath, dir)
|
||||
err := os.Mkdir(tmpPath, 0777)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
revel.ERROR.Fatalf("Failed to make '%v' directory: %v", dir, err)
|
||||
revel.RevelLog.Fatalf("Failed to make '%v' directory: %v", dir, err)
|
||||
}
|
||||
|
||||
// Create the file
|
||||
file, err := os.Create(filepath.Join(tmpPath, filename))
|
||||
if err != nil {
|
||||
revel.ERROR.Fatalf("Failed to create file: %v", err)
|
||||
revel.RevelLog.Fatalf("Failed to create file: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = file.Close()
|
||||
}()
|
||||
|
||||
if _, err = file.WriteString(sourceCode); err != nil {
|
||||
revel.ERROR.Fatalf("Failed to write to file: %v", err)
|
||||
revel.RevelLog.Fatalf("Failed to write to file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,7 +352,7 @@ func addAlias(aliases map[string]string, importPath, pkgName string) {
|
||||
func makePackageAlias(aliases map[string]string, pkgName string) string {
|
||||
i := 0
|
||||
alias := pkgName
|
||||
for containsValue(aliases, alias) {
|
||||
for containsValue(aliases, alias) || alias == "revel" {
|
||||
alias = fmt.Sprintf("%s%d", pkgName, i)
|
||||
i++
|
||||
}
|
||||
@@ -322,7 +377,7 @@ func newCompileError(output []byte) *revel.Error {
|
||||
errorMatch = regexp.MustCompile(`(?m)^(.*?)\:(\d+)\:\s(.*?)$`).FindSubmatch(output)
|
||||
|
||||
if errorMatch == nil {
|
||||
revel.ERROR.Println("Failed to parse build errors:\n", string(output))
|
||||
revel.RevelLog.Error("Failed to parse build errors", "error", string(output))
|
||||
return &revel.Error{
|
||||
SourceType: "Go code",
|
||||
Title: "Go Compilation Error",
|
||||
@@ -332,7 +387,7 @@ func newCompileError(output []byte) *revel.Error {
|
||||
|
||||
errorMatch = append(errorMatch, errorMatch[3])
|
||||
|
||||
revel.ERROR.Println("Build errors:\n", string(output))
|
||||
revel.RevelLog.Error("Build errors", "errors", string(output))
|
||||
}
|
||||
|
||||
// Read the source for the offending file.
|
||||
@@ -359,7 +414,7 @@ func newCompileError(output []byte) *revel.Error {
|
||||
fileStr, err := revel.ReadLines(absFilename)
|
||||
if err != nil {
|
||||
compileError.MetaError = absFilename + ": " + err.Error()
|
||||
revel.ERROR.Println(compileError.MetaError)
|
||||
revel.RevelLog.Error(compileError.MetaError)
|
||||
return compileError
|
||||
}
|
||||
|
||||
@@ -392,7 +447,7 @@ var (
|
||||
func main() {
|
||||
flag.Parse()
|
||||
revel.Init(*runMode, *importPath, *srcPath)
|
||||
revel.INFO.Println("Running revel server")
|
||||
revel.AppLog.Info("Running revel server")
|
||||
{{range $i, $c := .Controllers}}
|
||||
revel.RegisterController((*{{index $.ImportPaths .ImportPath}}.{{.StructName}})(nil),
|
||||
[]*revel.MethodType{
|
||||
|
||||
@@ -29,10 +29,10 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/revel/revel"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
watcher *revel.Watcher
|
||||
doNotWatch = []string{"tmp", "views", "routes"}
|
||||
|
||||
lastRequestHadError int32
|
||||
@@ -45,12 +45,16 @@ type Harness struct {
|
||||
serverHost string
|
||||
port int
|
||||
proxy *httputil.ReverseProxy
|
||||
watcher *revel.Watcher
|
||||
mutex *sync.Mutex
|
||||
}
|
||||
|
||||
func renderError(w http.ResponseWriter, r *http.Request, err error) {
|
||||
req, resp := revel.NewRequest(r), revel.NewResponse(w)
|
||||
c := revel.NewController(req, resp)
|
||||
c.RenderError(err).Apply(req, resp)
|
||||
func renderError(iw http.ResponseWriter, ir *http.Request, err error) {
|
||||
context := revel.NewGoContext(nil)
|
||||
context.Request.SetRequest(ir)
|
||||
context.Response.SetResponse(iw)
|
||||
c := revel.NewController(context)
|
||||
c.RenderError(err).Apply(c.Request, c.Response)
|
||||
}
|
||||
|
||||
// ServeHTTP handles all requests.
|
||||
@@ -63,12 +67,17 @@ func (h *Harness) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Flush any change events and rebuild app if necessary.
|
||||
// Render an error page if the rebuild / restart failed.
|
||||
err := watcher.Notify()
|
||||
err := h.watcher.Notify()
|
||||
if err != nil {
|
||||
// In a thread safe manner update the flag so that a request for
|
||||
// /favicon.ico does not trigger a rebuild
|
||||
atomic.CompareAndSwapInt32(&lastRequestHadError, 0, 1)
|
||||
renderError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
// In a thread safe manner update the flag so that a request for
|
||||
// /favicon.ico is allowed
|
||||
atomic.CompareAndSwapInt32(&lastRequestHadError, 1, 0)
|
||||
|
||||
// Reverse proxy the request.
|
||||
@@ -88,7 +97,7 @@ func NewHarness() *Harness {
|
||||
revel.MainTemplateLoader = revel.NewTemplateLoader(
|
||||
[]string{filepath.Join(revel.RevelPath, "templates")})
|
||||
if err := revel.MainTemplateLoader.Refresh(); err != nil {
|
||||
revel.ERROR.Println(err)
|
||||
revel.RevelLog.Error("Template loader error", "error", err)
|
||||
}
|
||||
|
||||
addr := revel.HTTPAddr
|
||||
@@ -109,27 +118,32 @@ func NewHarness() *Harness {
|
||||
|
||||
serverURL, _ := url.ParseRequestURI(fmt.Sprintf(scheme+"://%s:%d", addr, port))
|
||||
|
||||
harness := &Harness{
|
||||
serverHarness := &Harness{
|
||||
port: port,
|
||||
serverHost: serverURL.String()[len(scheme+"://"):],
|
||||
proxy: httputil.NewSingleHostReverseProxy(serverURL),
|
||||
mutex: &sync.Mutex{},
|
||||
}
|
||||
|
||||
if revel.HTTPSsl {
|
||||
harness.proxy.Transport = &http.Transport{
|
||||
serverHarness.proxy.Transport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
}
|
||||
return harness
|
||||
return serverHarness
|
||||
}
|
||||
|
||||
// Refresh method rebuilds the Revel application and run it on the given port.
|
||||
func (h *Harness) Refresh() (err *revel.Error) {
|
||||
// Allow only one thread to rebuild the process
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
|
||||
if h.app != nil {
|
||||
h.app.Kill()
|
||||
}
|
||||
|
||||
revel.TRACE.Println("Rebuild")
|
||||
revel.RevelLog.Debug("Rebuild Called")
|
||||
h.app, err = Build()
|
||||
if err != nil {
|
||||
return
|
||||
@@ -153,7 +167,7 @@ func (h *Harness) WatchDir(info os.FileInfo) bool {
|
||||
}
|
||||
|
||||
// WatchFile method returns true given filename HasSuffix of ".go"
|
||||
// otheriwse false
|
||||
// otheriwse false - implements revel.DiscerningListener
|
||||
func (h *Harness) WatchFile(filename string) bool {
|
||||
return strings.HasSuffix(filename, ".go")
|
||||
}
|
||||
@@ -167,12 +181,13 @@ func (h *Harness) Run() {
|
||||
paths = append(paths, gopaths...)
|
||||
}
|
||||
paths = append(paths, revel.CodePaths...)
|
||||
watcher = revel.NewWatcher()
|
||||
watcher.Listen(h, paths...)
|
||||
h.watcher = revel.NewWatcher()
|
||||
h.watcher.Listen(h, paths...)
|
||||
h.watcher.Notify()
|
||||
|
||||
go func() {
|
||||
addr := fmt.Sprintf("%s:%d", revel.HTTPAddr, revel.HTTPPort)
|
||||
revel.INFO.Printf("Listening on %s", addr)
|
||||
revel.RevelLog.Infof("Listening on %s", addr)
|
||||
|
||||
var err error
|
||||
if revel.HTTPSsl {
|
||||
@@ -185,7 +200,7 @@ func (h *Harness) Run() {
|
||||
err = http.ListenAndServe(addr, h)
|
||||
}
|
||||
if err != nil {
|
||||
revel.ERROR.Fatalln("Failed to start reverse proxy:", err)
|
||||
revel.RevelLog.Error("Failed to start reverse proxy:", "error", err)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -203,13 +218,13 @@ func (h *Harness) Run() {
|
||||
func getFreePort() (port int) {
|
||||
conn, err := net.Listen("tcp", ":0")
|
||||
if err != nil {
|
||||
revel.ERROR.Fatal(err)
|
||||
revel.RevelLog.Fatal("Unable to fetch a freee port address", "error", err)
|
||||
}
|
||||
|
||||
port = conn.Addr().(*net.TCPAddr).Port
|
||||
err = conn.Close()
|
||||
if err != nil {
|
||||
revel.ERROR.Fatal(err)
|
||||
revel.RevelLog.Fatal("Unable to close port", "error", err)
|
||||
}
|
||||
return port
|
||||
}
|
||||
@@ -231,7 +246,7 @@ func proxyWebsocket(w http.ResponseWriter, r *http.Request, host string) {
|
||||
}
|
||||
if err != nil {
|
||||
http.Error(w, "Error contacting backend server.", 500)
|
||||
revel.ERROR.Printf("Error dialing websocket backend %s: %v", host, err)
|
||||
revel.RevelLog.Error("Error dialing websocket backend ", "host", host, "error", err)
|
||||
return
|
||||
}
|
||||
hj, ok := w.(http.Hijacker)
|
||||
@@ -241,21 +256,21 @@ func proxyWebsocket(w http.ResponseWriter, r *http.Request, host string) {
|
||||
}
|
||||
nc, _, err := hj.Hijack()
|
||||
if err != nil {
|
||||
revel.ERROR.Printf("Hijack error: %v", err)
|
||||
revel.RevelLog.Error("Hijack error", "error", err)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err = nc.Close(); err != nil {
|
||||
revel.ERROR.Println(err)
|
||||
revel.RevelLog.Error("Connection close error", "error", err)
|
||||
}
|
||||
if err = d.Close(); err != nil {
|
||||
revel.ERROR.Println(err)
|
||||
revel.RevelLog.Error("Dial close error", "error", err)
|
||||
}
|
||||
}()
|
||||
|
||||
err = r.Write(d)
|
||||
if err != nil {
|
||||
revel.ERROR.Printf("Error copying request to target: %v", err)
|
||||
revel.RevelLog.Error("Error copying request to target", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,14 @@ import (
|
||||
"go/parser"
|
||||
"go/scanner"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"unicode"
|
||||
|
||||
"github.com/revel/revel"
|
||||
"log"
|
||||
)
|
||||
|
||||
// SourceInfo is the top-level struct containing all extracted information
|
||||
@@ -98,14 +100,14 @@ func ProcessSource(roots []string) (*SourceInfo, *revel.Error) {
|
||||
for _, root := range roots {
|
||||
rootImportPath := importPathFromPath(root)
|
||||
if rootImportPath == "" {
|
||||
revel.WARN.Println("Skipping code path", root)
|
||||
revel.RevelLog.Warn("Skipping empty code path", "path", root)
|
||||
continue
|
||||
}
|
||||
|
||||
// Start walking the directory tree.
|
||||
_ = revel.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
log.Println("Error scanning app source:", err)
|
||||
revel.RevelLog.Error("Error scanning app source:", "error", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -149,7 +151,7 @@ func ProcessSource(roots []string) (*SourceInfo, *revel.Error) {
|
||||
|
||||
// This is exception, err alredy checked above. Here just a print
|
||||
ast.Print(nil, err)
|
||||
log.Fatalf("Failed to parse dir: %s", err)
|
||||
revel.RevelLog.Fatal("Failed to parse dir", "error", err)
|
||||
}
|
||||
|
||||
// Skip "main" packages.
|
||||
@@ -160,9 +162,21 @@ func ProcessSource(roots []string) (*SourceInfo, *revel.Error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ignore packages that end with _test
|
||||
for i := range pkgs {
|
||||
if len(i) > 6 {
|
||||
if string(i[len(i)-5:]) == "_test" {
|
||||
delete(pkgs, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There should be only one package in this directory.
|
||||
if len(pkgs) > 1 {
|
||||
log.Println("Most unexpected! Multiple packages in a single directory:", pkgs)
|
||||
for i := range pkgs {
|
||||
println("Found package ", i)
|
||||
}
|
||||
revel.RevelLog.Error("Most unexpected! Multiple packages in a single directory:", "packages", pkgs)
|
||||
}
|
||||
|
||||
var pkg *ast.Package
|
||||
@@ -187,7 +201,7 @@ func appendSourceInfo(srcInfo1, srcInfo2 *SourceInfo) *SourceInfo {
|
||||
srcInfo1.InitImportPaths = append(srcInfo1.InitImportPaths, srcInfo2.InitImportPaths...)
|
||||
for k, v := range srcInfo2.ValidationKeys {
|
||||
if _, ok := srcInfo1.ValidationKeys[k]; ok {
|
||||
log.Println("Key conflict when scanning validation calls:", k)
|
||||
revel.RevelLog.Warn("Key conflict when scanning validation calls:", "key", k)
|
||||
continue
|
||||
}
|
||||
srcInfo1.ValidationKeys[k] = v
|
||||
@@ -209,8 +223,8 @@ func processPackage(fset *token.FileSet, pkgImportPath, pkgPath string, pkg *ast
|
||||
)
|
||||
|
||||
// For each source file in the package...
|
||||
log.Println("Exaiming files in path", pkgPath)
|
||||
for _, file := range pkg.Files {
|
||||
|
||||
// Imports maps the package key to the full import path.
|
||||
// e.g. import "sample/app/models" => "models": "sample/app/models"
|
||||
imports := map[string]string{}
|
||||
@@ -227,8 +241,8 @@ func processPackage(fset *token.FileSet, pkgImportPath, pkgPath string, pkg *ast
|
||||
structSpecs = appendStruct(structSpecs, pkgImportPath, pkg, decl, imports, fset)
|
||||
}
|
||||
|
||||
// If this is a func...
|
||||
if funcDecl, ok := decl.(*ast.FuncDecl); ok {
|
||||
// If this is a func... (ignore nil for external (non-Go) function)
|
||||
if funcDecl, ok := decl.(*ast.FuncDecl); ok && funcDecl.Body != nil {
|
||||
// Scan it for validation calls
|
||||
lineKeys := getValidationKeys(fset, funcDecl, imports)
|
||||
if len(lineKeys) > 0 {
|
||||
@@ -305,7 +319,7 @@ func addImports(imports map[string]string, decl ast.Decl, srcDir string) {
|
||||
// We expect this to happen for apps using reverse routing (since we
|
||||
// have not yet generated the routes). Don't log that.
|
||||
if !strings.HasSuffix(fullPath, "/app/routes") {
|
||||
revel.TRACE.Println("Could not find import:", fullPath)
|
||||
revel.RevelLog.Debug("Could not find import:", "path", fullPath)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -324,6 +338,7 @@ func appendStruct(specs []*TypeInfo, pkgImportPath string, pkg *ast.Package, dec
|
||||
if !found {
|
||||
return specs
|
||||
}
|
||||
|
||||
structType := spec.Type.(*ast.StructType)
|
||||
|
||||
// At this point we know it's a type declaration for a struct.
|
||||
@@ -383,7 +398,7 @@ func appendStruct(specs []*TypeInfo, pkgImportPath string, pkg *ast.Package, dec
|
||||
} else {
|
||||
var ok bool
|
||||
if importPath, ok = imports[pkgName]; !ok {
|
||||
log.Print("Failed to find import path for ", pkgName, ".", typeName)
|
||||
revel.RevelLog.Error("Failed to find import path for ", "package", pkgName, "type", typeName)
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -442,13 +457,16 @@ func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPat
|
||||
var importPath string
|
||||
typeExpr := NewTypeExpr(pkgName, field.Type)
|
||||
if !typeExpr.Valid {
|
||||
log.Printf("Didn't understand argument '%s' of action %s. Ignoring.\n", name, getFuncName(funcDecl))
|
||||
revel.RevelLog.Warnf("Didn't understand argument '%s' of action %s. Ignoring.", name, getFuncName(funcDecl))
|
||||
return // We didn't understand one of the args. Ignore this action.
|
||||
}
|
||||
if typeExpr.PkgName != "" {
|
||||
// Local object
|
||||
if typeExpr.PkgName == pkgName {
|
||||
importPath = pkgImportPath
|
||||
} else if typeExpr.PkgName != "" {
|
||||
var ok bool
|
||||
if importPath, ok = imports[typeExpr.PkgName]; !ok {
|
||||
log.Println("Failed to find import for arg of type:", typeExpr.TypeName(""))
|
||||
revel.RevelLog.Errorf("Failed to find import for arg of type: %s , %s", typeExpr.PkgName, typeExpr.TypeName(""))
|
||||
}
|
||||
}
|
||||
method.Args = append(method.Args, &MethodArg{
|
||||
@@ -482,7 +500,7 @@ func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPat
|
||||
}
|
||||
|
||||
// Add this call's args to the renderArgs.
|
||||
pos := fset.Position(callExpr.Rparen)
|
||||
pos := fset.Position(callExpr.Lparen)
|
||||
methodCall := &methodCall{
|
||||
Line: pos.Line,
|
||||
Names: []string{},
|
||||
@@ -634,7 +652,7 @@ func getStructTypeDecl(decl ast.Decl, fset *token.FileSet) (spec *ast.TypeSpec,
|
||||
}
|
||||
|
||||
if len(genDecl.Specs) == 0 {
|
||||
revel.WARN.Printf("Surprising: %s:%d Decl contains no specifications", fset.Position(decl.Pos()).Filename, fset.Position(decl.Pos()).Line)
|
||||
revel.RevelLog.Warnf("Surprising: %s:%d Decl contains no specifications", fset.Position(decl.Pos()).Filename, fset.Position(decl.Pos()).Line)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -647,7 +665,7 @@ func getStructTypeDecl(decl ast.Decl, fset *token.FileSet) (spec *ast.TypeSpec,
|
||||
// TypesThatEmbed returns all types that (directly or indirectly) embed the
|
||||
// target type, which must be a fully qualified type name,
|
||||
// e.g. "github.com/revel/revel.Controller"
|
||||
func (s *SourceInfo) TypesThatEmbed(targetType string) (filtered []*TypeInfo) {
|
||||
func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered []*TypeInfo) {
|
||||
// Do a search in the "embedded type graph", starting with the target type.
|
||||
var (
|
||||
nodeQueue = []string{targetType}
|
||||
@@ -679,6 +697,37 @@ func (s *SourceInfo) TypesThatEmbed(targetType string) (filtered []*TypeInfo) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Strip out any specifications that contain a lower case
|
||||
for exit := false; !exit; exit = true {
|
||||
for i, filteredItem := range filtered {
|
||||
if unicode.IsLower([]rune(filteredItem.StructName)[0]) {
|
||||
revel.RevelLog.Debug("Skipping adding spec for unexported type",
|
||||
"type", filteredItem.StructName,
|
||||
"package", filteredItem.ImportPath)
|
||||
filtered = append(filtered[:i], filtered[i+1:]...)
|
||||
exit = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for any missed types that where from expected packages
|
||||
for _, spec := range s.StructSpecs {
|
||||
if spec.PackageName == packageFilter {
|
||||
found := false
|
||||
for _, filteredItem := range filtered {
|
||||
if filteredItem.StructName == spec.StructName {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
revel.RevelLog.Warn("Type found in package: "+packageFilter+
|
||||
", but did not embed from: "+filepath.Base(targetType),
|
||||
"name", spec.StructName, "path", spec.ImportPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -686,7 +735,7 @@ func (s *SourceInfo) TypesThatEmbed(targetType string) (filtered []*TypeInfo) {
|
||||
// `revel.Controller`
|
||||
func (s *SourceInfo) ControllerSpecs() []*TypeInfo {
|
||||
if s.controllerSpecs == nil {
|
||||
s.controllerSpecs = s.TypesThatEmbed(revel.RevelImportPath + ".Controller")
|
||||
s.controllerSpecs = s.TypesThatEmbed(revel.RevelImportPath+".Controller", "controllers")
|
||||
}
|
||||
return s.controllerSpecs
|
||||
}
|
||||
@@ -695,7 +744,7 @@ func (s *SourceInfo) ControllerSpecs() []*TypeInfo {
|
||||
// `testing.TestSuite`
|
||||
func (s *SourceInfo) TestSuites() []*TypeInfo {
|
||||
if s.testSuites == nil {
|
||||
s.testSuites = s.TypesThatEmbed(revel.RevelImportPath + "/testing.TestSuite")
|
||||
s.testSuites = s.TypesThatEmbed(revel.RevelImportPath+"/testing.TestSuite", "testsuite")
|
||||
}
|
||||
return s.testSuites
|
||||
}
|
||||
@@ -735,11 +784,18 @@ func NewTypeExpr(pkgName string, expr ast.Expr) TypeExpr {
|
||||
case *ast.ArrayType:
|
||||
e := NewTypeExpr(pkgName, t.Elt)
|
||||
return TypeExpr{"[]" + e.Expr, e.PkgName, e.pkgIndex + 2, e.Valid}
|
||||
case *ast.MapType:
|
||||
if identKey, ok := t.Key.(*ast.Ident); ok && IsBuiltinType(identKey.Name) {
|
||||
e := NewTypeExpr(pkgName, t.Value)
|
||||
return TypeExpr{"map[" + identKey.Name + "]" + e.Expr, e.PkgName, e.pkgIndex + len("map["+identKey.Name+"]"), e.Valid}
|
||||
}
|
||||
|
||||
revel.RevelLog.Error("Failed to generate name for field. Make sure the field name is valid.")
|
||||
case *ast.Ellipsis:
|
||||
e := NewTypeExpr(pkgName, t.Elt)
|
||||
return TypeExpr{"[]" + e.Expr, e.PkgName, e.pkgIndex + 2, e.Valid}
|
||||
default:
|
||||
log.Println("Failed to generate name for field. Make sure the field name is valid.")
|
||||
revel.RevelLog.Error("Failed to generate name for field. Make sure the field name is valid.", "package", pkgName, "expresion",expr)
|
||||
}
|
||||
return TypeExpr{Valid: false}
|
||||
}
|
||||
@@ -774,9 +830,8 @@ func IsBuiltinType(name string) bool {
|
||||
}
|
||||
|
||||
func importPathFromPath(root string) string {
|
||||
vendoringPath := revel.BasePath + "/vendor/"
|
||||
if strings.HasPrefix(root, vendoringPath) {
|
||||
return filepath.ToSlash(root[len(vendoringPath):])
|
||||
if vendorIdx := strings.Index(root, "/vendor/"); vendorIdx != -1 {
|
||||
return filepath.ToSlash(root[vendorIdx+8:])
|
||||
}
|
||||
for _, gopath := range filepath.SplitList(build.Default.GOPATH) {
|
||||
srcPath := filepath.Join(gopath, "src")
|
||||
@@ -787,10 +842,10 @@ func importPathFromPath(root string) string {
|
||||
|
||||
srcPath := filepath.Join(build.Default.GOROOT, "src", "pkg")
|
||||
if strings.HasPrefix(root, srcPath) {
|
||||
revel.WARN.Println("Code path should be in GOPATH, but is in GOROOT:", root)
|
||||
revel.RevelLog.Warn("Code path should be in GOPATH, but is in GOROOT:", "path", root)
|
||||
return filepath.ToSlash(root[len(srcPath)+1:])
|
||||
}
|
||||
|
||||
revel.ERROR.Println("Unexpected! Code path is not in GOPATH:", root)
|
||||
revel.RevelLog.Error("Unexpected! Code path is not in GOPATH:", "path", root)
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -96,18 +94,20 @@ func TestGetValidationKeys(t *testing.T) {
|
||||
}
|
||||
|
||||
var TypeExprs = map[string]TypeExpr{
|
||||
"int": {"int", "", 0, true},
|
||||
"*int": {"*int", "", 1, true},
|
||||
"[]int": {"[]int", "", 2, true},
|
||||
"...int": {"[]int", "", 2, true},
|
||||
"[]*int": {"[]*int", "", 3, true},
|
||||
"...*int": {"[]*int", "", 3, true},
|
||||
"MyType": {"MyType", "pkg", 0, true},
|
||||
"*MyType": {"*MyType", "pkg", 1, true},
|
||||
"[]MyType": {"[]MyType", "pkg", 2, true},
|
||||
"...MyType": {"[]MyType", "pkg", 2, true},
|
||||
"[]*MyType": {"[]*MyType", "pkg", 3, true},
|
||||
"...*MyType": {"[]*MyType", "pkg", 3, true},
|
||||
"int": {"int", "", 0, true},
|
||||
"*int": {"*int", "", 1, true},
|
||||
"[]int": {"[]int", "", 2, true},
|
||||
"...int": {"[]int", "", 2, true},
|
||||
"[]*int": {"[]*int", "", 3, true},
|
||||
"...*int": {"[]*int", "", 3, true},
|
||||
"MyType": {"MyType", "pkg", 0, true},
|
||||
"*MyType": {"*MyType", "pkg", 1, true},
|
||||
"[]MyType": {"[]MyType", "pkg", 2, true},
|
||||
"...MyType": {"[]MyType", "pkg", 2, true},
|
||||
"[]*MyType": {"[]*MyType", "pkg", 3, true},
|
||||
"...*MyType": {"[]*MyType", "pkg", 3, true},
|
||||
"map[int]MyType": {"map[int]MyType", "pkg", 8, true},
|
||||
"map[int]*MyType": {"map[int]*MyType", "pkg", 9, true},
|
||||
}
|
||||
|
||||
func TestTypeExpr(t *testing.T) {
|
||||
@@ -183,7 +183,7 @@ NEXT_TEST:
|
||||
|
||||
func BenchmarkProcessBookingSource(b *testing.B) {
|
||||
revel.Init("", "github.com/revel/examples/booking", "")
|
||||
revel.TRACE = log.New(ioutil.Discard, "", 0)
|
||||
revel.GetRootLogHandler().Disable()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
||||
@@ -60,11 +60,11 @@ func buildApp(args []string) {
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(destPath); err != nil && !os.IsNotExist(err) {
|
||||
revel.ERROR.Fatalln(err)
|
||||
revel.RevelLog.Fatal("Remove all error","error", err)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(destPath, 0777); err != nil {
|
||||
revel.ERROR.Fatalln(err)
|
||||
revel.RevelLog.Fatal("makedir error","error",err)
|
||||
}
|
||||
|
||||
app, reverr := harness.Build()
|
||||
@@ -101,7 +101,7 @@ func buildApp(args []string) {
|
||||
}
|
||||
modulePath, err := revel.ResolveImportPath(moduleImportPath)
|
||||
if err != nil {
|
||||
revel.ERROR.Fatalln("Failed to load module %s: %s", key[len("module."):], err)
|
||||
revel.RevelLog.Fatalf("Failed to load module %s: %s", key[len("module."):], err)
|
||||
}
|
||||
modulePaths[moduleImportPath] = modulePath
|
||||
}
|
||||
|
||||
10
revel/new.go
10
revel/new.go
@@ -8,7 +8,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -67,8 +66,6 @@ func newApp(args []string) {
|
||||
errorf("Too many arguments provided.\nRun 'revel help new' for usage.\n")
|
||||
}
|
||||
|
||||
revel.ERROR.SetFlags(log.LstdFlags)
|
||||
|
||||
// checking and setting go paths
|
||||
initGoPaths()
|
||||
|
||||
@@ -129,7 +126,7 @@ func initGoPaths() {
|
||||
}
|
||||
|
||||
if len(srcRoot) == 0 {
|
||||
revel.ERROR.Fatalln("Abort: could not create a Revel application outside of GOPATH.")
|
||||
revel.RevelLog.Fatal("Abort: could not create a Revel application outside of GOPATH.")
|
||||
}
|
||||
|
||||
// set go src path
|
||||
@@ -148,8 +145,10 @@ func setApplicationPath(args []string) {
|
||||
importPath)
|
||||
}
|
||||
|
||||
appPath = filepath.Join(srcRoot, filepath.FromSlash(importPath))
|
||||
|
||||
_, err = build.Import(importPath, "", build.FindOnly)
|
||||
if err == nil {
|
||||
if err == nil && !empty(appPath) {
|
||||
errorf("Abort: Import path %s already exists.\n", importPath)
|
||||
}
|
||||
|
||||
@@ -158,7 +157,6 @@ func setApplicationPath(args []string) {
|
||||
errorf("Abort: Could not find Revel source code: %s\n", err)
|
||||
}
|
||||
|
||||
appPath = filepath.Join(srcRoot, filepath.FromSlash(importPath))
|
||||
appName = filepath.Base(appPath)
|
||||
basePath = filepath.ToSlash(filepath.Dir(importPath))
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ func packageApp(args []string) {
|
||||
// Remove the archive if it already exists.
|
||||
destFile := filepath.Base(revel.BasePath) + ".tar.gz"
|
||||
if err := os.Remove(destFile); err != nil && !os.IsNotExist(err) {
|
||||
revel.ERROR.Fatal(err)
|
||||
revel.RevelLog.Fatal("Unable to remove target file","error",err,"file",destFile)
|
||||
}
|
||||
|
||||
// Collect stuff in a temp directory.
|
||||
|
||||
21
revel/run.go
21
revel/run.go
@@ -51,7 +51,7 @@ func parseRunArgs(args []string) *RunArgs {
|
||||
}
|
||||
switch len(args) {
|
||||
case 3:
|
||||
// Possibile combinations
|
||||
// Possible combinations
|
||||
// revel run [import-path] [run-mode] [port]
|
||||
port, err := strconv.Atoi(args[2])
|
||||
if err != nil {
|
||||
@@ -61,7 +61,7 @@ func parseRunArgs(args []string) *RunArgs {
|
||||
inputArgs.Mode = args[1]
|
||||
inputArgs.Port = port
|
||||
case 2:
|
||||
// Possibile combinations
|
||||
// Possible combinations
|
||||
// 1. revel run [import-path] [run-mode]
|
||||
// 2. revel run [import-path] [port]
|
||||
// 3. revel run [run-mode] [port]
|
||||
@@ -85,11 +85,16 @@ func parseRunArgs(args []string) *RunArgs {
|
||||
inputArgs.Port = port
|
||||
}
|
||||
case 1:
|
||||
// Possibile combinations
|
||||
// Possible combinations
|
||||
// 1. revel run [import-path]
|
||||
// 2. revel run [port]
|
||||
// 3. revel run [run-mode]
|
||||
if _, err := build.Import(args[0], "", build.FindOnly); err == nil {
|
||||
_, err := build.Import(args[0], "", build.FindOnly)
|
||||
if err != nil {
|
||||
revel.RevelLog.Warn("Unable to run using an import path, assuming import path is working directory %s %s", "Argument", args[0], "error", err.Error())
|
||||
}
|
||||
println("Trying to build with", args[0], err)
|
||||
if err == nil {
|
||||
// 1st arg is the import path
|
||||
inputArgs.ImportPath = args[0]
|
||||
} else if port, err := strconv.Atoi(args[0]); err == nil {
|
||||
@@ -116,18 +121,18 @@ func runApp(args []string) {
|
||||
runArgs.Port = revel.HTTPPort
|
||||
}
|
||||
|
||||
revel.INFO.Printf("Running %s (%s) in %s mode\n", revel.AppName, revel.ImportPath, runArgs.Mode)
|
||||
revel.TRACE.Println("Base path:", revel.BasePath)
|
||||
revel.RevelLog.Infof("Running %s (%s) in %s mode\n", revel.AppName, revel.ImportPath, runArgs.Mode)
|
||||
revel.RevelLog.Debug("Base path:", "path", revel.BasePath)
|
||||
|
||||
// If the app is run in "watched" mode, use the harness to run it.
|
||||
if revel.Config.BoolDefault("watch", true) && revel.Config.BoolDefault("watch.code", true) {
|
||||
revel.TRACE.Println("Running in watched mode.")
|
||||
revel.RevelLog.Debug("Running in watched mode.")
|
||||
revel.HTTPPort = runArgs.Port
|
||||
harness.NewHarness().Run() // Never returns.
|
||||
}
|
||||
|
||||
// Else, just build and run the app.
|
||||
revel.TRACE.Println("Running in live build mode.")
|
||||
revel.RevelLog.Debug("Running in live build mode.")
|
||||
app, err := harness.Build()
|
||||
if err != nil {
|
||||
errorf("Failed to build app: %s", err)
|
||||
|
||||
@@ -29,8 +29,7 @@ func init() {
|
||||
revel.ActionInvoker, // Invoke the action.
|
||||
}
|
||||
|
||||
|
||||
// register startup functions with OnAppStart
|
||||
// Register startup functions with OnAppStart
|
||||
// revel.DevMode and revel.RunMode only work inside of OnAppStart. See Example Startup Script
|
||||
// ( order dependent )
|
||||
// revel.OnAppStart(ExampleStartupScript)
|
||||
@@ -39,13 +38,13 @@ func init() {
|
||||
}
|
||||
|
||||
// HeaderFilter adds common security headers
|
||||
// TODO turn this into revel.HeaderFilter
|
||||
// should probably also have a filter for CSRF
|
||||
// not sure if it can go in the same filter or not
|
||||
// There is a full implementation of a CSRF filter in
|
||||
// https://github.com/revel/modules/tree/master/csrf
|
||||
var HeaderFilter = func(c *revel.Controller, fc []revel.Filter) {
|
||||
c.Response.Out.Header().Add("X-Frame-Options", "SAMEORIGIN")
|
||||
c.Response.Out.Header().Add("X-XSS-Protection", "1; mode=block")
|
||||
c.Response.Out.Header().Add("X-Content-Type-Options", "nosniff")
|
||||
c.Response.Out.Header().Add("Referrer-Policy", "strict-origin-when-cross-origin")
|
||||
|
||||
fc[0](c, fc[1:]) // Execute the next filter stage.
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
# More info at http://revel.github.io/manual/appconf.html
|
||||
################################################################################
|
||||
|
||||
# Sets the `AppName` variable which can be used in your code as
|
||||
# Sets `revel.AppName` for use in-app.
|
||||
# Example:
|
||||
# `if revel.AppName {...}`
|
||||
app.name = {{ .AppName }}
|
||||
|
||||
@@ -13,7 +14,7 @@ app.name = {{ .AppName }}
|
||||
# into your application
|
||||
app.secret = {{ .Secret }}
|
||||
|
||||
# Revel running behind proxy like nginx, haproxy, etc
|
||||
# Revel running behind proxy like nginx, haproxy, etc.
|
||||
app.behind.proxy = false
|
||||
|
||||
|
||||
@@ -57,10 +58,11 @@ cookie.prefix = REVEL
|
||||
# as false.
|
||||
# cookie.secure = false
|
||||
|
||||
# Limit cookie access to a given domain
|
||||
# Limit cookie access to a given domain.
|
||||
#cookie.domain =
|
||||
|
||||
# Define when your session cookie expires. Possible values:
|
||||
# Define when your session cookie expires.
|
||||
# Values:
|
||||
# "720h"
|
||||
# A time duration (http://golang.org/pkg/time/#ParseDuration) after which
|
||||
# the cookie expires and the session is invalid.
|
||||
@@ -82,15 +84,6 @@ format.datetime = 2006-01-02 15:04
|
||||
results.chunked = false
|
||||
|
||||
|
||||
# Prefixes for each log message line
|
||||
# User can override these prefix values within any section
|
||||
# For e.g: [dev], [prod], etc
|
||||
log.trace.prefix = "TRACE "
|
||||
log.info.prefix = "INFO "
|
||||
log.warn.prefix = "WARN "
|
||||
log.error.prefix = "ERROR "
|
||||
|
||||
|
||||
# The default language of this application.
|
||||
i18n.default_language = en
|
||||
|
||||
@@ -102,35 +95,62 @@ i18n.default_language = en
|
||||
# Module to serve static content such as CSS, JavaScript and Media files
|
||||
# Allows Routes like this:
|
||||
# `Static.ServeModule("modulename","public")`
|
||||
module.static=github.com/revel/modules/static
|
||||
module.static = github.com/revel/modules/static
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
# Section: dev
|
||||
# This section is evaluated when running Revel in dev mode. Like so:
|
||||
# `revel run path/to/myapp`
|
||||
[dev]
|
||||
# This sets `DevMode` variable to `true` which can be used in your code as
|
||||
|
||||
# This sets `revel.DevMode` for use in-app.
|
||||
# Example:
|
||||
# `if revel.DevMode {...}`
|
||||
# or in your templates with
|
||||
# `{{.DevMode}}`
|
||||
# Values:
|
||||
# "true"
|
||||
# Sets `DevMode` to `true`.
|
||||
# "false"
|
||||
# Sets `DevMode` to `false`.
|
||||
mode.dev = true
|
||||
|
||||
|
||||
# Pretty print JSON/XML when calling RenderJSON/RenderXML
|
||||
# Values:
|
||||
# "true"
|
||||
# Enables pretty printing.
|
||||
# "false"
|
||||
# Disables pretty printing.
|
||||
results.pretty = true
|
||||
|
||||
|
||||
# Automatically watches your applicaton files and recompiles on-demand
|
||||
# Watch your applicaton files for changes and automatically rebuild
|
||||
# Values:
|
||||
# "true"
|
||||
# Enables auto rebuilding.
|
||||
# "false"
|
||||
# Disables auto rebuilding.
|
||||
watch = true
|
||||
|
||||
|
||||
# If you set watch.mode = "eager", the server starts to recompile
|
||||
# your application every time your application's files change.
|
||||
watch.mode = "normal"
|
||||
# Define when to rebuild new changes.
|
||||
# Values:
|
||||
# "normal"
|
||||
# Rebuild when a new request is received and changes have been detected.
|
||||
# "eager"
|
||||
# Rebuild as soon as changes are detected.
|
||||
watch.mode = normal
|
||||
|
||||
# Watch the entire $GOPATH for code changes. Default is false.
|
||||
# Watch the entire `$GOPATH` for changes.
|
||||
# Values:
|
||||
# "true"
|
||||
# Includes `$GOPATH` in watch path.
|
||||
# "false"
|
||||
# Excludes `$GOPATH` from watch path. Default value.
|
||||
#watch.gopath = true
|
||||
|
||||
|
||||
@@ -141,32 +161,24 @@ module.testrunner = github.com/revel/modules/testrunner
|
||||
|
||||
|
||||
# Where to log the various Revel logs
|
||||
log.trace.output = off
|
||||
log.info.output = stderr
|
||||
log.warn.output = stderr
|
||||
log.error.output = stderr
|
||||
|
||||
|
||||
# Revel log flags. Possible flags defined by the Go `log` package,
|
||||
# please refer https://golang.org/pkg/log/#pkg-constants
|
||||
# Go log is "Bits or'ed together to control what's printed"
|
||||
# Examples:
|
||||
# 0 => just log the message, turn off the flags
|
||||
# 3 => log.LstdFlags (log.Ldate|log.Ltime)
|
||||
# 19 => log.Ldate|log.Ltime|log.Lshortfile
|
||||
# 23 => log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile
|
||||
log.trace.flags = 19
|
||||
log.info.flags = 19
|
||||
log.warn.flags = 19
|
||||
log.error.flags = 19
|
||||
|
||||
# Values:
|
||||
# "off"
|
||||
# Disable log output.
|
||||
# "stdout"
|
||||
# Log to OS's standard output.
|
||||
# "stderr"
|
||||
# Log to Os's standard error output. Default value.
|
||||
# "relative/path/to/log"
|
||||
# Log to file.
|
||||
log.all.filter.module.app = stdout # Log all loggers for the application to the stdout
|
||||
log.error.nfilter.module.app = stderr # Everything else that logs an error to stderr
|
||||
log.crit.output = stderr # Everything that logs something as critical goes to this
|
||||
|
||||
# Revel request access log
|
||||
# Access log line format:
|
||||
# RequestStartTime ClientIP ResponseStatus RequestLatency HTTPMethod URLPath
|
||||
# Sample format:
|
||||
# 2016/05/25 17:46:37.112 127.0.0.1 200 270.157µs GET /
|
||||
log.request.output = stderr
|
||||
# INFO 21:53:55 static server-engine.go:169: Request Stats ip=127.0.0.1 path=/public/vendors/datatables.net-buttons/js/buttons.html5.min.js method=GET start=2017/08/31 21:53:55 status=200 duration_seconds=0.0002583 section=requestlog
|
||||
log.request.output = stdout
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
@@ -176,42 +188,20 @@ log.request.output = stderr
|
||||
# See:
|
||||
# [dev] section for documentation of the various settings
|
||||
[prod]
|
||||
mode.dev = false
|
||||
|
||||
mode.dev = false
|
||||
|
||||
results.pretty = false
|
||||
|
||||
|
||||
watch = false
|
||||
|
||||
|
||||
module.testrunner =
|
||||
|
||||
log.warn.output = log/%(app.name)-warn.json # Log all warn messages to file
|
||||
log.error.output = log/%(app.name)-error.json # Log all errors to file
|
||||
log.crit.output = log/%(app.name)-critical.json # Log all critical to file
|
||||
|
||||
log.trace.output = off
|
||||
log.info.output = off
|
||||
log.warn.output = log/%(app.name)s.log
|
||||
log.error.output = log/%(app.name)s.log
|
||||
|
||||
# Revel log flags. Possible flags defined by the Go `log` package,
|
||||
# please refer https://golang.org/pkg/log/#pkg-constants
|
||||
# Go log is "Bits or'ed together to control what's printed"
|
||||
# Examples:
|
||||
# 0 => just log the message, turn off the flags
|
||||
# 3 => log.LstdFlags (log.Ldate|log.Ltime)
|
||||
# 19 => log.Ldate|log.Ltime|log.Lshortfile
|
||||
# 23 => log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile
|
||||
log.trace.flags = 3
|
||||
log.info.flags = 3
|
||||
log.warn.flags = 3
|
||||
log.error.flags = 3
|
||||
|
||||
|
||||
# Revel request access log
|
||||
# Access log line format:
|
||||
# RequestStartTime ClientIP ResponseStatus RequestLatency HTTPMethod URLPath
|
||||
# Sample format:
|
||||
# 2016/05/25 17:46:37.112 127.0.0.1 200 270.157µs GET /
|
||||
# Revel request access log (json format)
|
||||
# Example:
|
||||
# log.request.output = %(app.name)s-request.log
|
||||
log.request.output = off
|
||||
# log.request.output = %(app.name)s-request.json
|
||||
log.request.output = log/%(app.name)s-requests.json
|
||||
|
||||
@@ -15,5 +15,12 @@ GET /favicon.ico 404
|
||||
# Map static resources from the /app/public folder to the /public path
|
||||
GET /public/*filepath Static.Serve("public")
|
||||
|
||||
# Catch all
|
||||
* /:controller/:action :controller.:action
|
||||
# Catch all, this will route any request into the controller path
|
||||
#
|
||||
# **** WARNING ****
|
||||
# Enabling this exposes any controller and function to the web.
|
||||
# ** This is a serious security issue if used online **
|
||||
#
|
||||
# For rapid development uncomment the following to add new controller.action endpoints
|
||||
# without having to add them to the routes table.
|
||||
# * /:controller/:action :controller.:action
|
||||
|
||||
@@ -97,8 +97,18 @@ func testApp(args []string) {
|
||||
defer cmd.Kill()
|
||||
revel.INFO.Printf("Testing %s (%s) in %s mode\n", revel.AppName, revel.ImportPath, mode)
|
||||
|
||||
var httpAddr = revel.HTTPAddr
|
||||
if httpAddr == "" {
|
||||
httpAddr = "127.0.0.1"
|
||||
}
|
||||
|
||||
var httpProto = "http"
|
||||
if revel.HTTPSsl {
|
||||
httpProto = "https"
|
||||
}
|
||||
|
||||
// Get a list of tests
|
||||
var baseURL = fmt.Sprintf("http://127.0.0.1:%d", revel.HTTPPort)
|
||||
var baseURL = fmt.Sprintf("%s://%s:%d", httpProto, httpAddr, revel.HTTPPort)
|
||||
testSuites, _ := getTestsList(baseURL)
|
||||
|
||||
// If a specific TestSuite[.Method] is specified, only run that suite/test
|
||||
|
||||
Reference in New Issue
Block a user