mirror of
https://github.com/kevin-DL/revel-cmd.git
synced 2026-01-11 10:44:28 +00:00
Lint fixes
This commit is contained in:
@@ -11,12 +11,12 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// App contains the configuration for running a Revel app. (Not for the app itself)
|
||||
@@ -29,7 +29,7 @@ type App struct {
|
||||
Paths *model.RevelContainer
|
||||
}
|
||||
|
||||
// NewApp returns app instance with binary path in it
|
||||
// NewApp returns app instance with binary path in it.
|
||||
func NewApp(binPath string, paths *model.RevelContainer, packagePathMap map[string]string) *App {
|
||||
return &App{BinaryPath: binPath, Paths: paths, Port: paths.HTTPPort, PackagePathMap: packagePathMap}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ type AppCmd struct {
|
||||
*exec.Cmd
|
||||
}
|
||||
|
||||
// NewAppCmd returns the AppCmd with parameters initialized for running app
|
||||
// NewAppCmd returns the AppCmd with parameters initialized for running app.
|
||||
func NewAppCmd(binPath string, port int, runMode string, paths *model.RevelContainer) AppCmd {
|
||||
cmd := exec.Command(binPath,
|
||||
fmt.Sprintf("-port=%d", port),
|
||||
@@ -89,7 +89,6 @@ func (cmd AppCmd) Start(c *model.CommandConfig) error {
|
||||
println("Revel proxy is listening, point your browser to :", c.Run.Port)
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Run the app server inline. Never returns.
|
||||
@@ -103,11 +102,10 @@ func (cmd AppCmd) Run(c *model.CommandConfig) {
|
||||
|
||||
// Kill terminates the app server if it's running.
|
||||
func (cmd AppCmd) Kill() {
|
||||
|
||||
if cmd.Cmd != nil && (cmd.ProcessState == nil || !cmd.ProcessState.Exited()) {
|
||||
// Windows appears to send the kill to all threads, shutting down the
|
||||
// server before this can, this check will ensure the process is still running
|
||||
if _, err := os.FindProcess(int(cmd.Process.Pid)); err != nil {
|
||||
if _, err := os.FindProcess(cmd.Process.Pid); err != nil {
|
||||
// Server has already exited
|
||||
utils.Logger.Info("Server not running revel server pid", "pid", cmd.Process.Pid)
|
||||
return
|
||||
@@ -149,7 +147,6 @@ func (cmd AppCmd) Kill() {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Use a timer to ensure that the process exits
|
||||
utils.Logger.Info("Waiting to exit")
|
||||
select {
|
||||
@@ -193,7 +190,7 @@ type startupListeningWriter struct {
|
||||
buffer *bytes.Buffer
|
||||
}
|
||||
|
||||
// Writes to this output stream
|
||||
// Writes to this output stream.
|
||||
func (w *startupListeningWriter) Write(p []byte) (int, error) {
|
||||
if w.notifyReady != nil && bytes.Contains(p, []byte("Revel engine is listening on")) {
|
||||
w.notifyReady <- true
|
||||
@@ -210,10 +207,3 @@ func (w *startupListeningWriter) Write(p []byte) (int, error) {
|
||||
}
|
||||
return w.dest.Write(p)
|
||||
}
|
||||
|
||||
// Returns the cleaned output from the response
|
||||
// TODO clean the response more
|
||||
func (w *startupListeningWriter) getLastOutput() string {
|
||||
return w.buffer.String()
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
_ "github.com/revel/cmd/parser"
|
||||
"github.com/revel/cmd/utils"
|
||||
"github.com/revel/cmd/parser2"
|
||||
"github.com/revel/cmd/parser"
|
||||
"github.com/revel/cmd/parser2"
|
||||
"github.com/revel/cmd/utils"
|
||||
)
|
||||
|
||||
var importErrorPattern = regexp.MustCompile("cannot find package \"([^\"]+)\"")
|
||||
@@ -32,9 +31,11 @@ type ByString []*model.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()
|
||||
}
|
||||
@@ -155,7 +156,8 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err
|
||||
"build",
|
||||
"-ldflags", versionLinkerFlags,
|
||||
"-tags", buildTags,
|
||||
"-o", binName}
|
||||
"-o", binName,
|
||||
}
|
||||
} else {
|
||||
if !contains(c.BuildFlags, "build") {
|
||||
flags = []string{"build"}
|
||||
@@ -232,9 +234,7 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err
|
||||
// Success getting the import, attempt to build again.
|
||||
}
|
||||
|
||||
// TODO remove this unreachable code and document it
|
||||
utils.Logger.Fatal("Not reachable")
|
||||
return nil, nil
|
||||
// unreachable
|
||||
}
|
||||
|
||||
// Try to define a version string for the compiled app
|
||||
@@ -259,7 +259,6 @@ func getAppVersion(paths *model.RevelContainer) string {
|
||||
gitCmd := exec.Command(gitPath, "--git-dir="+gitDir, "--work-tree="+paths.BasePath, "describe", "--always", "--dirty")
|
||||
utils.Logger.Info("Exec:", "args", gitCmd.Args)
|
||||
output, err := gitCmd.Output()
|
||||
|
||||
if err != nil {
|
||||
utils.Logger.Error("Cannot determine git repository version:", "error", err)
|
||||
return ""
|
||||
@@ -317,7 +316,6 @@ func cleanDir(paths *model.RevelContainer, dir string) {
|
||||
// genSource renders the given template to produce source code, which it writes
|
||||
// to the given directory and file.
|
||||
func genSource(paths *model.RevelContainer, dir, filename, templateSource string, args map[string]interface{}) error {
|
||||
|
||||
return utils.GenerateTemplate(filepath.Join(paths.AppPath, dir, filename), templateSource, args)
|
||||
}
|
||||
|
||||
@@ -353,17 +351,16 @@ func calcImportAliases(src *model.SourceInfo) map[string]string {
|
||||
return aliases
|
||||
}
|
||||
|
||||
// Adds an alias to the map of alias names
|
||||
// Adds an alias to the map of alias names.
|
||||
func addAlias(aliases map[string]string, importPath, pkgName string) {
|
||||
alias, ok := aliases[importPath]
|
||||
_, ok := aliases[importPath]
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
alias = makePackageAlias(aliases, pkgName)
|
||||
aliases[importPath] = alias
|
||||
aliases[importPath] = makePackageAlias(aliases, pkgName)
|
||||
}
|
||||
|
||||
// Generates a package alias
|
||||
// Generates a package alias.
|
||||
func makePackageAlias(aliases map[string]string, pkgName string) string {
|
||||
i := 0
|
||||
alias := pkgName
|
||||
@@ -374,7 +371,7 @@ func makePackageAlias(aliases map[string]string, pkgName string) string {
|
||||
return alias
|
||||
}
|
||||
|
||||
// Returns true if this value is in the map
|
||||
// Returns true if this value is in the map.
|
||||
func containsValue(m map[string]string, val string) bool {
|
||||
for _, v := range m {
|
||||
if v == val {
|
||||
@@ -421,7 +418,6 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.SourceEr
|
||||
return newPath
|
||||
}
|
||||
|
||||
|
||||
// Read the source for the offending file.
|
||||
var (
|
||||
relFilename = string(errorMatch[1]) // e.g. "src/revel/sample/app/controllers/app.go"
|
||||
@@ -454,7 +450,7 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.SourceEr
|
||||
return compileError
|
||||
}
|
||||
|
||||
// RevelMainTemplate template for app/tmp/run/run.go
|
||||
// RevelMainTemplate template for app/tmp/run/run.go.
|
||||
const RevelRunTemplate = `// GENERATED CODE - DO NOT EDIT
|
||||
// This file is the run file for Revel.
|
||||
// It registers all the controllers and provides details for the Revel server engine to
|
||||
@@ -509,6 +505,7 @@ func Register() {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const RevelMainTemplate = `// GENERATED CODE - DO NOT EDIT
|
||||
// This file is the main file for Revel.
|
||||
// It registers all the controllers and provides details for the Revel server engine to
|
||||
@@ -536,7 +533,7 @@ func main() {
|
||||
}
|
||||
`
|
||||
|
||||
// RevelRoutesTemplate template for app/conf/routes
|
||||
// RevelRoutesTemplate template for app/conf/routes.
|
||||
const RevelRoutesTemplate = `// GENERATED CODE - DO NOT EDIT
|
||||
// This file provides a way of creating URL's based on all the actions
|
||||
// found in all the controllers.
|
||||
|
||||
@@ -15,10 +15,12 @@ package harness
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
"go/build"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
@@ -27,15 +29,13 @@ import (
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"github.com/revel/cmd/watcher"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -57,7 +57,6 @@ type Harness struct {
|
||||
paths *model.RevelContainer // The Revel container
|
||||
config *model.CommandConfig // The configuration
|
||||
runMode string // The runmode the harness is running in
|
||||
isError bool // True if harness is in error state
|
||||
ranOnce bool // True app compiled once
|
||||
}
|
||||
|
||||
@@ -90,7 +89,7 @@ func (h *Harness) renderError(iw http.ResponseWriter, ir *http.Request, err erro
|
||||
target := []string{seekViewOnPath("500.html"), seekViewOnPath("500-dev.html")}
|
||||
if !utils.Exists(target[0]) {
|
||||
fmt.Fprintf(iw, "Target template not found not found %s<br />\n", target[0])
|
||||
fmt.Fprintf(iw, "An error ocurred %s", err.Error())
|
||||
fmt.Fprintf(iw, "An error occurred %s", err.Error())
|
||||
return
|
||||
}
|
||||
var revelError *utils.SourceError
|
||||
@@ -203,9 +202,9 @@ func NewHarness(c *model.CommandConfig, paths *model.RevelContainer, runMode str
|
||||
}
|
||||
|
||||
// Refresh method rebuilds the Revel application and run it on the given port.
|
||||
// called by the watcher
|
||||
// called by the watcher.
|
||||
func (h *Harness) Refresh() (err *utils.SourceError) {
|
||||
t := time.Now();
|
||||
t := time.Now()
|
||||
fmt.Println("Changed detected, recompiling")
|
||||
err = h.refresh()
|
||||
if err != nil && !h.ranOnce && h.useProxy {
|
||||
@@ -215,7 +214,7 @@ func (h *Harness) Refresh() (err *utils.SourceError) {
|
||||
}
|
||||
|
||||
h.ranOnce = true
|
||||
fmt.Printf("\nTime to recompile %s\n",time.Now().Sub(t).String())
|
||||
fmt.Printf("\nTime to recompile %s\n", time.Since(t).String())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -257,7 +256,6 @@ func (h *Harness) refresh() (err *utils.SourceError) {
|
||||
paths, _ = json.Marshal(h.app.PackagePathMap)
|
||||
}
|
||||
runMode = fmt.Sprintf(`{"mode":"%s", "specialUseFlag":%v,"packagePathMap":%s}`, h.app.Paths.RunMode, h.config.Verbose, string(paths))
|
||||
|
||||
}
|
||||
if err2 := h.app.Cmd(runMode).Start(h.config); err2 != nil {
|
||||
utils.Logger.Error("Could not start application", "error", err2)
|
||||
@@ -277,13 +275,13 @@ func (h *Harness) refresh() (err *utils.SourceError) {
|
||||
}
|
||||
|
||||
// WatchDir method returns false to file matches with doNotWatch
|
||||
// otheriwse true
|
||||
// otheriwse true.
|
||||
func (h *Harness) WatchDir(info os.FileInfo) bool {
|
||||
return !utils.ContainsString(doNotWatch, info.Name())
|
||||
}
|
||||
|
||||
// WatchFile method returns true given filename HasSuffix of ".go"
|
||||
// otheriwse false - implements revel.DiscerningListener
|
||||
// otheriwse false - implements revel.DiscerningListener.
|
||||
func (h *Harness) WatchFile(filename string) bool {
|
||||
return strings.HasSuffix(filename, ".go")
|
||||
}
|
||||
@@ -310,8 +308,6 @@ func (h *Harness) Run() {
|
||||
}
|
||||
addr := fmt.Sprintf("%s:%d", h.paths.HTTPAddr, h.paths.HTTPPort)
|
||||
utils.Logger.Infof("Proxy server is listening on %s", addr)
|
||||
|
||||
|
||||
var err error
|
||||
if h.paths.HTTPSsl {
|
||||
err = http.ListenAndServeTLS(
|
||||
@@ -326,11 +322,11 @@ func (h *Harness) Run() {
|
||||
utils.Logger.Error("Failed to start reverse proxy:", "error", err)
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
// Make a new channel to listen for the interrupt event
|
||||
ch := make(chan os.Signal)
|
||||
//nolint:staticcheck // os.Kill ineffective on Unix, useful on Windows?
|
||||
signal.Notify(ch, os.Interrupt, os.Kill)
|
||||
<-ch
|
||||
// Kill the app and exit
|
||||
@@ -340,7 +336,7 @@ func (h *Harness) Run() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Find an unused port
|
||||
// Find an unused port.
|
||||
func getFreePort() (port int) {
|
||||
conn, err := net.Listen("tcp", ":0")
|
||||
if err != nil {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"github.com/mattn/go-colorable"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/mattn/go-colorable"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
)
|
||||
|
||||
type CompositeMultiHandler struct {
|
||||
@@ -19,8 +20,8 @@ func NewCompositeMultiHandler() (*CompositeMultiHandler, LogHandler) {
|
||||
cw := &CompositeMultiHandler{}
|
||||
return cw, cw
|
||||
}
|
||||
func (h *CompositeMultiHandler) Log(r *Record) (err error) {
|
||||
|
||||
func (h *CompositeMultiHandler) Log(r *Record) (err error) {
|
||||
var handler LogHandler
|
||||
|
||||
switch r.Level {
|
||||
@@ -78,7 +79,7 @@ func (h *CompositeMultiHandler) SetHandler(handler LogHandler, replace bool, lev
|
||||
}
|
||||
}
|
||||
|
||||
// For the multi handler set the handler, using the LogOptions defined
|
||||
// For the multi handler set the handler, using the LogOptions defined.
|
||||
func (h *CompositeMultiHandler) SetHandlers(handler LogHandler, options *LogOptions) {
|
||||
if len(options.Levels) == 0 {
|
||||
options.Levels = LvlAllList
|
||||
@@ -88,8 +89,8 @@ func (h *CompositeMultiHandler) SetHandlers(handler LogHandler, options *LogOpti
|
||||
for _, lvl := range options.Levels {
|
||||
h.SetHandler(handler, options.ReplaceExistingHandler, lvl)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (h *CompositeMultiHandler) SetJson(writer io.Writer, options *LogOptions) {
|
||||
handler := CallerFileHandler(StreamHandler(writer, JsonFormatEx(
|
||||
options.GetBoolDefault("pretty", false),
|
||||
@@ -101,7 +102,7 @@ func (h *CompositeMultiHandler) SetJson(writer io.Writer, options *LogOptions) {
|
||||
h.SetHandlers(handler, options)
|
||||
}
|
||||
|
||||
// Use built in rolling function
|
||||
// Use built in rolling function.
|
||||
func (h *CompositeMultiHandler) SetJsonFile(filePath string, options *LogOptions) {
|
||||
writer := &lumberjack.Logger{
|
||||
Filename: filePath,
|
||||
@@ -141,7 +142,7 @@ func (h *CompositeMultiHandler) SetTerminal(writer io.Writer, options *LogOption
|
||||
h.SetHandlers(handler, options)
|
||||
}
|
||||
|
||||
// Use built in rolling function
|
||||
// Use built in rolling function.
|
||||
func (h *CompositeMultiHandler) SetTerminalFile(filePath string, options *LogOptions) {
|
||||
writer := &lumberjack.Logger{
|
||||
Filename: filePath,
|
||||
|
||||
@@ -8,8 +8,5 @@
|
||||
2) Output handlers (log.error.output) replace any existing handlers
|
||||
3) Filter handlers (log.xxx.filter, log.xxx.nfilter) append to existing handlers,
|
||||
note log.all.filter is treated as a filter handler, so it will NOT replace existing ones
|
||||
|
||||
|
||||
|
||||
*/
|
||||
package logger
|
||||
|
||||
@@ -11,12 +11,12 @@ type LevelFilterHandler struct {
|
||||
}
|
||||
|
||||
// Filters out records which do not match the level
|
||||
// Uses the `log15.FilterHandler` to perform this task
|
||||
// Uses the `log15.FilterHandler` to perform this task.
|
||||
func LevelHandler(lvl LogLevel, h LogHandler) LogHandler {
|
||||
return &LevelFilterHandler{lvl, h}
|
||||
}
|
||||
|
||||
// The implementation of the Log
|
||||
// The implementation of the Log.
|
||||
func (h LevelFilterHandler) Log(r *Record) error {
|
||||
if r.Level == h.Level {
|
||||
return h.h.Log(r)
|
||||
@@ -25,7 +25,7 @@ func (h LevelFilterHandler) Log(r *Record) error {
|
||||
}
|
||||
|
||||
// Filters out records which do not match the level
|
||||
// Uses the `log15.FilterHandler` to perform this task
|
||||
// Uses the `log15.FilterHandler` to perform this task.
|
||||
func MinLevelHandler(lvl LogLevel, h LogHandler) LogHandler {
|
||||
return FilterHandler(func(r *Record) (pass bool) {
|
||||
return r.Level <= lvl
|
||||
@@ -33,7 +33,7 @@ func MinLevelHandler(lvl LogLevel, h LogHandler) LogHandler {
|
||||
}
|
||||
|
||||
// Filters out records which match the level
|
||||
// Uses the `log15.FilterHandler` to perform this task
|
||||
// Uses the `log15.FilterHandler` to perform this task.
|
||||
func NotLevelHandler(lvl LogLevel, h LogHandler) LogHandler {
|
||||
return FilterHandler(func(r *Record) (pass bool) {
|
||||
return r.Level != lvl
|
||||
@@ -48,13 +48,13 @@ func CallerFileHandler(h LogHandler) LogHandler {
|
||||
}
|
||||
|
||||
// Adds in a context called `caller` to the record (contains file name and line number like `foo.go:12`)
|
||||
// Uses the `log15.CallerFuncHandler` to perform this task
|
||||
// Uses the `log15.CallerFuncHandler` to perform this task.
|
||||
func CallerFuncHandler(h LogHandler) LogHandler {
|
||||
return CallerFuncHandler(h)
|
||||
}
|
||||
|
||||
// Filters out records which match the key value pair
|
||||
// Uses the `log15.MatchFilterHandler` to perform this task
|
||||
// Uses the `log15.MatchFilterHandler` to perform this task.
|
||||
func MatchHandler(key string, value interface{}, h LogHandler) LogHandler {
|
||||
return MatchFilterHandler(key, value, h)
|
||||
}
|
||||
@@ -72,7 +72,7 @@ func MatchFilterHandler(key string, value interface{}, h LogHandler) LogHandler
|
||||
}, h)
|
||||
}
|
||||
|
||||
// If match then A handler is called otherwise B handler is called
|
||||
// If match then A handler is called otherwise B handler is called.
|
||||
func MatchAbHandler(key string, value interface{}, a, b LogHandler) LogHandler {
|
||||
return FuncHandler(func(r *Record) error {
|
||||
if r.Context[key] == value {
|
||||
@@ -85,24 +85,24 @@ func MatchAbHandler(key string, value interface{}, a, b LogHandler) LogHandler {
|
||||
})
|
||||
}
|
||||
|
||||
// The nil handler is used if logging for a specific request needs to be turned off
|
||||
// The nil handler is used if logging for a specific request needs to be turned off.
|
||||
func NilHandler() LogHandler {
|
||||
return FuncHandler(func(r *Record) error {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Match all values in map to log
|
||||
// Match all values in map to log.
|
||||
func MatchMapHandler(matchMap map[string]interface{}, a LogHandler) LogHandler {
|
||||
return matchMapHandler(matchMap, false, a)
|
||||
}
|
||||
|
||||
// Match !(Match all values in map to log) The inverse of MatchMapHandler
|
||||
// Match !(Match all values in map to log) The inverse of MatchMapHandler.
|
||||
func NotMatchMapHandler(matchMap map[string]interface{}, a LogHandler) LogHandler {
|
||||
return matchMapHandler(matchMap, true, a)
|
||||
}
|
||||
|
||||
// Rather then chaining multiple filter handlers, process all here
|
||||
// Rather then chaining multiple filter handlers, process all here.
|
||||
func matchMapHandler(matchMap map[string]interface{}, inverse bool, a LogHandler) LogHandler {
|
||||
return FuncHandler(func(r *Record) error {
|
||||
matchCount := 0
|
||||
@@ -114,10 +114,11 @@ func matchMapHandler(matchMap map[string]interface{}, inverse bool, a LogHandler
|
||||
// Test for two failure cases
|
||||
if value == v && inverse || value != v && !inverse {
|
||||
return nil
|
||||
} else {
|
||||
}
|
||||
|
||||
matchCount++
|
||||
}
|
||||
}
|
||||
|
||||
if matchCount != len(matchMap) {
|
||||
return nil
|
||||
}
|
||||
@@ -126,7 +127,7 @@ func matchMapHandler(matchMap map[string]interface{}, inverse bool, a LogHandler
|
||||
}
|
||||
|
||||
// Filters out records which do not match the key value pair
|
||||
// Uses the `log15.FilterHandler` to perform this task
|
||||
// Uses the `log15.FilterHandler` to perform this task.
|
||||
func NotMatchHandler(key string, value interface{}, h LogHandler) LogHandler {
|
||||
return FilterHandler(func(r *Record) (pass bool) {
|
||||
return r.Context[key] != value
|
||||
@@ -158,7 +159,7 @@ func StreamHandler(wr io.Writer, fmtr LogFormat) LogHandler {
|
||||
return LazyHandler(SyncHandler(h))
|
||||
}
|
||||
|
||||
// Filter handler
|
||||
// Filter handler.
|
||||
func FilterHandler(fn func(r *Record) bool, h LogHandler) LogHandler {
|
||||
return FuncHandler(func(r *Record) error {
|
||||
if fn(r) {
|
||||
@@ -168,18 +169,18 @@ func FilterHandler(fn func(r *Record) bool, h LogHandler) LogHandler {
|
||||
})
|
||||
}
|
||||
|
||||
// List log handler handles a list of LogHandlers
|
||||
// List log handler handles a list of LogHandlers.
|
||||
type ListLogHandler struct {
|
||||
handlers []LogHandler
|
||||
}
|
||||
|
||||
// Create a new list of log handlers
|
||||
// Create a new list of log handlers.
|
||||
func NewListLogHandler(h1, h2 LogHandler) *ListLogHandler {
|
||||
ll := &ListLogHandler{handlers: []LogHandler{h1, h2}}
|
||||
return ll
|
||||
}
|
||||
|
||||
// Log the record
|
||||
// Log the record.
|
||||
func (ll *ListLogHandler) Log(r *Record) (err error) {
|
||||
for _, handler := range ll.handlers {
|
||||
if err == nil {
|
||||
@@ -191,14 +192,14 @@ func (ll *ListLogHandler) Log(r *Record) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Add another log handler
|
||||
// Add another log handler.
|
||||
func (ll *ListLogHandler) Add(h LogHandler) {
|
||||
if h != nil {
|
||||
ll.handlers = append(ll.handlers, h)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a log handler
|
||||
// Remove a log handler.
|
||||
func (ll *ListLogHandler) Del(h LogHandler) {
|
||||
if h != nil {
|
||||
for i, handler := range ll.handlers {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package logger
|
||||
|
||||
// Get all handlers based on the Config (if available)
|
||||
// Get all handlers based on the Config (if available).
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/revel/config"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/revel/config"
|
||||
)
|
||||
|
||||
func InitializeFromConfig(basePath string, config *config.Context) (c *CompositeMultiHandler) {
|
||||
@@ -43,7 +44,7 @@ func InitializeFromConfig(basePath string, config *config.Context) (c *Composite
|
||||
return c
|
||||
}
|
||||
|
||||
// Init the log.all configuration options
|
||||
// Init the log.all configuration options.
|
||||
func initAllLog(c *CompositeMultiHandler, basePath string, config *config.Context) {
|
||||
if config != nil {
|
||||
extraLogFlag := config.BoolDefault(SPECIAL_USE_FLAG, false)
|
||||
@@ -61,13 +62,13 @@ func initAllLog(c *CompositeMultiHandler, basePath string, config *config.Contex
|
||||
// log.all.filter ....
|
||||
// log.error.filter ....
|
||||
func initFilterLog(c *CompositeMultiHandler, basePath string, config *config.Context) {
|
||||
|
||||
if config != nil {
|
||||
extraLogFlag := config.BoolDefault(SPECIAL_USE_FLAG, false)
|
||||
|
||||
for _, logFilter := range logFilterList {
|
||||
// Init for all filters
|
||||
for _, name := range []string{"all", "debug", "info", "warn", "error", "crit",
|
||||
for _, name := range []string{
|
||||
"all", "debug", "info", "warn", "error", "crit",
|
||||
"trace", // TODO trace is deprecated
|
||||
} {
|
||||
optionList := config.Options(logFilter.LogPrefix + name + logFilter.LogSuffix)
|
||||
@@ -94,9 +95,10 @@ func initFilterLog(c *CompositeMultiHandler, basePath string, config *config.Con
|
||||
}
|
||||
}
|
||||
|
||||
// Init the log.error, log.warn etc configuration options
|
||||
// Init the log.error, log.warn etc configuration options.
|
||||
func initLogLevels(c *CompositeMultiHandler, basePath string, config *config.Context) {
|
||||
for _, name := range []string{"debug", "info", "warn", "error", "crit",
|
||||
for _, name := range []string{
|
||||
"debug", "info", "warn", "error", "crit",
|
||||
"trace", // TODO trace is deprecated
|
||||
} {
|
||||
if config != nil {
|
||||
@@ -115,7 +117,7 @@ func initLogLevels(c *CompositeMultiHandler, basePath string, config *config.Con
|
||||
}
|
||||
}
|
||||
|
||||
// Init the request log options
|
||||
// Init the request log options.
|
||||
func initRequestLog(c *CompositeMultiHandler, basePath string, config *config.Context) {
|
||||
// Request logging to a separate output handler
|
||||
// This takes the InfoHandlers and adds a MatchAbHandler handler to it to direct
|
||||
@@ -143,7 +145,7 @@ func initRequestLog(c *CompositeMultiHandler, basePath string, config *config.Co
|
||||
// Returns a handler for the level using the output string
|
||||
// Accept formats for output string are
|
||||
// LogFunctionMap[value] callback function
|
||||
// `stdout` `stderr` `full/file/path/to/location/app.log` `full/file/path/to/location/app.json`
|
||||
// `stdout` `stderr` `full/file/path/to/location/app.log` `full/file/path/to/location/app.json`.
|
||||
func initHandlerFor(c *CompositeMultiHandler, output, basePath string, options *LogOptions) {
|
||||
if options.Ctx != nil {
|
||||
options.SetExtendedOptions(
|
||||
@@ -185,5 +187,4 @@ func initHandlerFor(c *CompositeMultiHandler, output, basePath string, options *
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,46 +5,57 @@
|
||||
package logger_test
|
||||
|
||||
import (
|
||||
"github.com/revel/config"
|
||||
"github.com/revel/revel/logger"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/revel/cmd/logger"
|
||||
"github.com/revel/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type (
|
||||
// A counter for the tester
|
||||
// A counter for the tester.
|
||||
testCounter struct {
|
||||
debug, info, warn, error, critical int
|
||||
}
|
||||
// The data to tes
|
||||
// The data to tes.
|
||||
testData struct {
|
||||
config []string
|
||||
result testResult
|
||||
tc *testCounter
|
||||
}
|
||||
// The test result
|
||||
// The test result.
|
||||
testResult struct {
|
||||
debug, info, warn, error, critical int
|
||||
}
|
||||
)
|
||||
|
||||
// Single test cases
|
||||
// Single test cases.
|
||||
var singleCases = []testData{
|
||||
{config: []string{"log.crit.output"},
|
||||
result: testResult{0, 0, 0, 0, 1}},
|
||||
{config: []string{"log.error.output"},
|
||||
result: testResult{0, 0, 0, 1, 1}},
|
||||
{config: []string{"log.warn.output"},
|
||||
result: testResult{0, 0, 1, 0, 0}},
|
||||
{config: []string{"log.info.output"},
|
||||
result: testResult{0, 1, 0, 0, 0}},
|
||||
{config: []string{"log.debug.output"},
|
||||
result: testResult{1, 0, 0, 0, 0}},
|
||||
{
|
||||
config: []string{"log.crit.output"},
|
||||
result: testResult{0, 0, 0, 0, 1},
|
||||
},
|
||||
{
|
||||
config: []string{"log.error.output"},
|
||||
result: testResult{0, 0, 0, 1, 1},
|
||||
},
|
||||
{
|
||||
config: []string{"log.warn.output"},
|
||||
result: testResult{0, 0, 1, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.info.output"},
|
||||
result: testResult{0, 1, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.debug.output"},
|
||||
result: testResult{1, 0, 0, 0, 0},
|
||||
},
|
||||
}
|
||||
|
||||
// Test singles
|
||||
// Test singles.
|
||||
func TestSingleCases(t *testing.T) {
|
||||
rootLog := logger.New()
|
||||
for _, testCase := range singleCases {
|
||||
@@ -53,31 +64,51 @@ func TestSingleCases(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Filter test cases
|
||||
// Filter test cases.
|
||||
var filterCases = []testData{
|
||||
{config: []string{"log.crit.filter.module.app"},
|
||||
result: testResult{0, 0, 0, 0, 1}},
|
||||
{config: []string{"log.crit.filter.module.appa"},
|
||||
result: testResult{0, 0, 0, 0, 0}},
|
||||
{config: []string{"log.error.filter.module.app"},
|
||||
result: testResult{0, 0, 0, 1, 1}},
|
||||
{config: []string{"log.error.filter.module.appa"},
|
||||
result: testResult{0, 0, 0, 0, 0}},
|
||||
{config: []string{"log.warn.filter.module.app"},
|
||||
result: testResult{0, 0, 1, 0, 0}},
|
||||
{config: []string{"log.warn.filter.module.appa"},
|
||||
result: testResult{0, 0, 0, 0, 0}},
|
||||
{config: []string{"log.info.filter.module.app"},
|
||||
result: testResult{0, 1, 0, 0, 0}},
|
||||
{config: []string{"log.info.filter.module.appa"},
|
||||
result: testResult{0, 0, 0, 0, 0}},
|
||||
{config: []string{"log.debug.filter.module.app"},
|
||||
result: testResult{1, 0, 0, 0, 0}},
|
||||
{config: []string{"log.debug.filter.module.appa"},
|
||||
result: testResult{0, 0, 0, 0, 0}},
|
||||
{
|
||||
config: []string{"log.crit.filter.module.app"},
|
||||
result: testResult{0, 0, 0, 0, 1},
|
||||
},
|
||||
{
|
||||
config: []string{"log.crit.filter.module.appa"},
|
||||
result: testResult{0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.error.filter.module.app"},
|
||||
result: testResult{0, 0, 0, 1, 1},
|
||||
},
|
||||
{
|
||||
config: []string{"log.error.filter.module.appa"},
|
||||
result: testResult{0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.warn.filter.module.app"},
|
||||
result: testResult{0, 0, 1, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.warn.filter.module.appa"},
|
||||
result: testResult{0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.info.filter.module.app"},
|
||||
result: testResult{0, 1, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.info.filter.module.appa"},
|
||||
result: testResult{0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.debug.filter.module.app"},
|
||||
result: testResult{1, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.debug.filter.module.appa"},
|
||||
result: testResult{0, 0, 0, 0, 0},
|
||||
},
|
||||
}
|
||||
|
||||
// Filter test
|
||||
// Filter test.
|
||||
func TestFilterCases(t *testing.T) {
|
||||
rootLog := logger.New("module", "app")
|
||||
for _, testCase := range filterCases {
|
||||
@@ -86,33 +117,55 @@ func TestFilterCases(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Inverse test cases
|
||||
// Inverse test cases.
|
||||
var nfilterCases = []testData{
|
||||
{config: []string{"log.crit.nfilter.module.appa"},
|
||||
result: testResult{0, 0, 0, 0, 1}},
|
||||
{config: []string{"log.crit.nfilter.modules.appa"},
|
||||
result: testResult{0, 0, 0, 0, 0}},
|
||||
{config: []string{"log.crit.nfilter.module.app"},
|
||||
result: testResult{0, 0, 0, 0, 0}},
|
||||
{config: []string{"log.error.nfilter.module.appa"}, // Special case, when error is not nill critical inherits from error
|
||||
result: testResult{0, 0, 0, 1, 1}},
|
||||
{config: []string{"log.error.nfilter.module.app"},
|
||||
result: testResult{0, 0, 0, 0, 0}},
|
||||
{config: []string{"log.warn.nfilter.module.appa"},
|
||||
result: testResult{0, 0, 1, 0, 0}},
|
||||
{config: []string{"log.warn.nfilter.module.app"},
|
||||
result: testResult{0, 0, 0, 0, 0}},
|
||||
{config: []string{"log.info.nfilter.module.appa"},
|
||||
result: testResult{0, 1, 0, 0, 0}},
|
||||
{config: []string{"log.info.nfilter.module.app"},
|
||||
result: testResult{0, 0, 0, 0, 0}},
|
||||
{config: []string{"log.debug.nfilter.module.appa"},
|
||||
result: testResult{1, 0, 0, 0, 0}},
|
||||
{config: []string{"log.debug.nfilter.module.app"},
|
||||
result: testResult{0, 0, 0, 0, 0}},
|
||||
{
|
||||
config: []string{"log.crit.nfilter.module.appa"},
|
||||
result: testResult{0, 0, 0, 0, 1},
|
||||
},
|
||||
{
|
||||
config: []string{"log.crit.nfilter.modules.appa"},
|
||||
result: testResult{0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.crit.nfilter.module.app"},
|
||||
result: testResult{0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.error.nfilter.module.appa"}, // Special case, when error is not nill critical inherits from error
|
||||
result: testResult{0, 0, 0, 1, 1},
|
||||
},
|
||||
{
|
||||
config: []string{"log.error.nfilter.module.app"},
|
||||
result: testResult{0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.warn.nfilter.module.appa"},
|
||||
result: testResult{0, 0, 1, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.warn.nfilter.module.app"},
|
||||
result: testResult{0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.info.nfilter.module.appa"},
|
||||
result: testResult{0, 1, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.info.nfilter.module.app"},
|
||||
result: testResult{0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.debug.nfilter.module.appa"},
|
||||
result: testResult{1, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
config: []string{"log.debug.nfilter.module.app"},
|
||||
result: testResult{0, 0, 0, 0, 0},
|
||||
},
|
||||
}
|
||||
|
||||
// Inverse test
|
||||
// Inverse test.
|
||||
func TestNotFilterCases(t *testing.T) {
|
||||
rootLog := logger.New("module", "app")
|
||||
for _, testCase := range nfilterCases {
|
||||
@@ -121,13 +174,15 @@ func TestNotFilterCases(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// off test cases
|
||||
// off test cases.
|
||||
var offCases = []testData{
|
||||
{config: []string{"log.all.output", "log.error.output=off"},
|
||||
result: testResult{1, 1, 1, 0, 1}},
|
||||
{
|
||||
config: []string{"log.all.output", "log.error.output=off"},
|
||||
result: testResult{1, 1, 1, 0, 1},
|
||||
},
|
||||
}
|
||||
|
||||
// Off test
|
||||
// Off test.
|
||||
func TestOffCases(t *testing.T) {
|
||||
rootLog := logger.New("module", "app")
|
||||
for _, testCase := range offCases {
|
||||
@@ -136,13 +191,15 @@ func TestOffCases(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Duplicate test cases
|
||||
// Duplicate test cases.
|
||||
var duplicateCases = []testData{
|
||||
{config: []string{"log.all.output", "log.error.output", "log.error.filter.module.app"},
|
||||
result: testResult{1, 1, 1, 2, 1}},
|
||||
{
|
||||
config: []string{"log.all.output", "log.error.output", "log.error.filter.module.app"},
|
||||
result: testResult{1, 1, 1, 2, 1},
|
||||
},
|
||||
}
|
||||
|
||||
// test duplicate cases
|
||||
// test duplicate cases.
|
||||
func TestDuplicateCases(t *testing.T) {
|
||||
rootLog := logger.New("module", "app")
|
||||
for _, testCase := range duplicateCases {
|
||||
@@ -151,19 +208,27 @@ func TestDuplicateCases(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Contradicting cases
|
||||
// Contradicting cases.
|
||||
var contradictCases = []testData{
|
||||
{config: []string{"log.all.output", "log.error.output=off", "log.all.output"},
|
||||
result: testResult{1, 1, 1, 0, 1}},
|
||||
{config: []string{"log.all.output", "log.error.output=off", "log.debug.filter.module.app"},
|
||||
result: testResult{2, 1, 1, 0, 1}},
|
||||
{config: []string{"log.all.filter.module.app", "log.info.output=off", "log.info.filter.module.app"},
|
||||
result: testResult{1, 2, 1, 1, 1}},
|
||||
{config: []string{"log.all.output", "log.info.output=off", "log.info.filter.module.app"},
|
||||
result: testResult{1, 1, 1, 1, 1}},
|
||||
{
|
||||
config: []string{"log.all.output", "log.error.output=off", "log.all.output"},
|
||||
result: testResult{1, 1, 1, 0, 1},
|
||||
},
|
||||
{
|
||||
config: []string{"log.all.output", "log.error.output=off", "log.debug.filter.module.app"},
|
||||
result: testResult{2, 1, 1, 0, 1},
|
||||
},
|
||||
{
|
||||
config: []string{"log.all.filter.module.app", "log.info.output=off", "log.info.filter.module.app"},
|
||||
result: testResult{1, 2, 1, 1, 1},
|
||||
},
|
||||
{
|
||||
config: []string{"log.all.output", "log.info.output=off", "log.info.filter.module.app"},
|
||||
result: testResult{1, 1, 1, 1, 1},
|
||||
},
|
||||
}
|
||||
|
||||
// Contradiction test
|
||||
// Contradiction test.
|
||||
func TestContradictCases(t *testing.T) {
|
||||
rootLog := logger.New("module", "app")
|
||||
for _, testCase := range contradictCases {
|
||||
@@ -172,15 +237,19 @@ func TestContradictCases(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// All test cases
|
||||
// All test cases.
|
||||
var allCases = []testData{
|
||||
{config: []string{"log.all.filter.module.app"},
|
||||
result: testResult{1, 1, 1, 1, 1}},
|
||||
{config: []string{"log.all.output"},
|
||||
result: testResult{2, 2, 2, 2, 2}},
|
||||
{
|
||||
config: []string{"log.all.filter.module.app"},
|
||||
result: testResult{1, 1, 1, 1, 1},
|
||||
},
|
||||
{
|
||||
config: []string{"log.all.output"},
|
||||
result: testResult{2, 2, 2, 2, 2},
|
||||
},
|
||||
}
|
||||
|
||||
// All tests
|
||||
// All tests.
|
||||
func TestAllCases(t *testing.T) {
|
||||
rootLog := logger.New("module", "app")
|
||||
for i, testCase := range allCases {
|
||||
@@ -195,7 +264,6 @@ func TestAllCases(t *testing.T) {
|
||||
for _, testCase := range allCases {
|
||||
testCase.validate(t)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (c *testCounter) Log(r *logger.Record) error {
|
||||
@@ -215,6 +283,7 @@ func (c *testCounter) Log(r *logger.Record) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (td *testData) logTest(rootLog logger.MultiLogger, t *testing.T) {
|
||||
if td.tc == nil {
|
||||
td.tc = &testCounter{}
|
||||
@@ -256,7 +325,7 @@ func (td *testData) validate(t *testing.T) {
|
||||
assert.Equal(t, td.result.critical, td.tc.critical, "Critical failed "+strings.Join(td.config, " "))
|
||||
}
|
||||
|
||||
// Add test to the function map
|
||||
// Add test to the function map.
|
||||
func counterInit(tc *testCounter) {
|
||||
logger.LogFunctionMap["test"] = func(c *logger.CompositeMultiHandler, logOptions *logger.LogOptions) {
|
||||
// Output to the test log and the stdout
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// The log function map can be added to, so that you can specify your own logging mechanism
|
||||
// it has defaults for off, stdout, stderr
|
||||
// LogFunctionMap can be added to, so that you can specify your own logging mechanism
|
||||
// it has defaults for off, stdout, stderr.
|
||||
var LogFunctionMap = map[string]func(*CompositeMultiHandler, *LogOptions){
|
||||
// Do nothing - set the logger off
|
||||
"off": func(c *CompositeMultiHandler, logOptions *LogOptions) {
|
||||
|
||||
@@ -2,14 +2,15 @@ package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/revel/config"
|
||||
"time"
|
||||
|
||||
"github.com/revel/config"
|
||||
)
|
||||
|
||||
// The LogHandler defines the interface to handle the log records
|
||||
// The LogHandler defines the interface to handle the log records.
|
||||
type (
|
||||
// The Multilogger reduces the number of exposed defined logging variables,
|
||||
// and allows the output to be easily refined
|
||||
// and allows the output to be easily refined.
|
||||
MultiLogger interface {
|
||||
// New returns a new Logger that has this logger's context plus the given context
|
||||
New(ctx ...interface{}) MultiLogger
|
||||
@@ -63,32 +64,32 @@ type (
|
||||
Panicf(msg string, params ...interface{})
|
||||
}
|
||||
|
||||
// The log handler interface
|
||||
// The log handler interface.
|
||||
LogHandler interface {
|
||||
Log(*Record) error
|
||||
// log15.Handler
|
||||
}
|
||||
|
||||
// The log stack handler interface
|
||||
// The log stack handler interface.
|
||||
LogStackHandler interface {
|
||||
LogHandler
|
||||
GetStack() int
|
||||
}
|
||||
|
||||
// The log handler interface which has child logs
|
||||
// The log handler interface which has child logs.
|
||||
ParentLogHandler interface {
|
||||
SetChild(handler LogHandler) LogHandler
|
||||
}
|
||||
|
||||
// The log format interface
|
||||
// The log format interface.
|
||||
LogFormat interface {
|
||||
Format(r *Record) []byte
|
||||
}
|
||||
|
||||
// The log level type
|
||||
// The log level type.
|
||||
LogLevel int
|
||||
|
||||
// Used for the callback to LogFunctionMap
|
||||
// Used for the callback to LogFunctionMap.
|
||||
LogOptions struct {
|
||||
Ctx *config.Context
|
||||
ReplaceExistingHandler bool
|
||||
@@ -97,7 +98,7 @@ type (
|
||||
ExtendedOptions map[string]interface{}
|
||||
}
|
||||
|
||||
// The log record
|
||||
// The log record.
|
||||
Record struct {
|
||||
Message string // The message
|
||||
Time time.Time // The time
|
||||
@@ -106,13 +107,13 @@ type (
|
||||
Context ContextMap // The context
|
||||
}
|
||||
|
||||
// The lazy structure to implement a function to be invoked only if needed
|
||||
// The lazy structure to implement a function to be invoked only if needed.
|
||||
Lazy struct {
|
||||
Fn interface{} // the function
|
||||
}
|
||||
|
||||
// Currently the only requirement for the callstack is to support the Formatter method
|
||||
// which stack.Call does so we use that
|
||||
// which stack.Call does so we use that.
|
||||
CallStack interface {
|
||||
fmt.Formatter // Requirement
|
||||
}
|
||||
@@ -129,6 +130,7 @@ type formatFunc func(*Record) []byte
|
||||
func (f formatFunc) Format(r *Record) []byte {
|
||||
return f(r)
|
||||
}
|
||||
|
||||
func NewRecord(message string, level LogLevel) *Record {
|
||||
return &Record{Message: message, Context: ContextMap{}, Level: level}
|
||||
}
|
||||
@@ -141,25 +143,25 @@ const (
|
||||
LvlDebug // Debug
|
||||
)
|
||||
|
||||
// A list of all the log levels
|
||||
// LvlAllList is a list of all the log levels.
|
||||
var LvlAllList = []LogLevel{LvlDebug, LvlInfo, LvlWarn, LvlError, LvlCrit}
|
||||
|
||||
// Implements the ParentLogHandler
|
||||
// Implements the ParentLogHandler.
|
||||
type parentLogHandler struct {
|
||||
setChild func(handler LogHandler) LogHandler
|
||||
}
|
||||
|
||||
// Create a new parent log handler
|
||||
// Create a new parent log handler.
|
||||
func NewParentLogHandler(callBack func(child LogHandler) LogHandler) ParentLogHandler {
|
||||
return &parentLogHandler{callBack}
|
||||
}
|
||||
|
||||
// Sets the child of the log handler
|
||||
// Sets the child of the log handler.
|
||||
func (p *parentLogHandler) SetChild(child LogHandler) LogHandler {
|
||||
return p.setChild(child)
|
||||
}
|
||||
|
||||
// Create a new log options
|
||||
// Create a new log options.
|
||||
func NewLogOptions(cfg *config.Context, replaceHandler bool, phandler ParentLogHandler, lvl ...LogLevel) (logOptions *LogOptions) {
|
||||
logOptions = &LogOptions{
|
||||
Ctx: cfg,
|
||||
@@ -171,14 +173,14 @@ func NewLogOptions(cfg *config.Context, replaceHandler bool, phandler ParentLogH
|
||||
return
|
||||
}
|
||||
|
||||
// Assumes options will be an even number and have a string, value syntax
|
||||
// Assumes options will be an even number and have a string, value syntax.
|
||||
func (l *LogOptions) SetExtendedOptions(options ...interface{}) {
|
||||
for x := 0; x < len(options); x += 2 {
|
||||
l.ExtendedOptions[options[x].(string)] = options[x+1]
|
||||
}
|
||||
}
|
||||
|
||||
// Gets a string option with default
|
||||
// Gets a string option with default.
|
||||
func (l *LogOptions) GetStringDefault(option, value string) string {
|
||||
if v, found := l.ExtendedOptions[option]; found {
|
||||
return v.(string)
|
||||
@@ -186,7 +188,7 @@ func (l *LogOptions) GetStringDefault(option, value string) string {
|
||||
return value
|
||||
}
|
||||
|
||||
// Gets an int option with default
|
||||
// Gets an int option with default.
|
||||
func (l *LogOptions) GetIntDefault(option string, value int) int {
|
||||
if v, found := l.ExtendedOptions[option]; found {
|
||||
return v.(int)
|
||||
@@ -194,7 +196,7 @@ func (l *LogOptions) GetIntDefault(option string, value int) int {
|
||||
return value
|
||||
}
|
||||
|
||||
// Gets a boolean option with default
|
||||
// Gets a boolean option with default.
|
||||
func (l *LogOptions) GetBoolDefault(option string, value bool) bool {
|
||||
if v, found := l.ExtendedOptions[option]; found {
|
||||
return v.(bool)
|
||||
|
||||
@@ -2,18 +2,19 @@ package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/revel/log15"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/revel/log15"
|
||||
)
|
||||
|
||||
// This type implements the MultiLogger
|
||||
// This type implements the MultiLogger.
|
||||
type RevelLogger struct {
|
||||
log15.Logger
|
||||
}
|
||||
|
||||
// Set the systems default logger
|
||||
// Default logs will be captured and handled by revel at level info
|
||||
// Default logs will be captured and handled by revel at level info.
|
||||
func SetDefaultLog(fromLog MultiLogger) {
|
||||
log.SetOutput(loggerRewrite{Logger: fromLog, Level: log15.LvlInfo, hideDeprecated: true})
|
||||
// No need to show date and time, that will be logged with revel
|
||||
@@ -24,73 +25,73 @@ func (rl *RevelLogger) Debugf(msg string, param ...interface{}) {
|
||||
rl.Debug(fmt.Sprintf(msg, param...))
|
||||
}
|
||||
|
||||
// Print a formatted info message
|
||||
// Print a formatted info message.
|
||||
func (rl *RevelLogger) Infof(msg string, param ...interface{}) {
|
||||
rl.Info(fmt.Sprintf(msg, param...))
|
||||
}
|
||||
|
||||
// Print a formatted warn message
|
||||
// Print a formatted warn message.
|
||||
func (rl *RevelLogger) Warnf(msg string, param ...interface{}) {
|
||||
rl.Warn(fmt.Sprintf(msg, param...))
|
||||
}
|
||||
|
||||
// Print a formatted error message
|
||||
// Print a formatted error message.
|
||||
func (rl *RevelLogger) Errorf(msg string, param ...interface{}) {
|
||||
rl.Error(fmt.Sprintf(msg, param...))
|
||||
}
|
||||
|
||||
// Print a formatted critical message
|
||||
// Print a formatted critical message.
|
||||
func (rl *RevelLogger) Critf(msg string, param ...interface{}) {
|
||||
rl.Crit(fmt.Sprintf(msg, param...))
|
||||
}
|
||||
|
||||
// Print a formatted fatal message
|
||||
// Print a formatted fatal message.
|
||||
func (rl *RevelLogger) Fatalf(msg string, param ...interface{}) {
|
||||
rl.Fatal(fmt.Sprintf(msg, param...))
|
||||
}
|
||||
|
||||
// Print a formatted panic message
|
||||
// Print a formatted panic message.
|
||||
func (rl *RevelLogger) Panicf(msg string, param ...interface{}) {
|
||||
rl.Panic(fmt.Sprintf(msg, param...))
|
||||
}
|
||||
|
||||
// Print a critical message and call os.Exit(1)
|
||||
// Print a critical message and call os.Exit(1).
|
||||
func (rl *RevelLogger) Fatal(msg string, ctx ...interface{}) {
|
||||
rl.Crit(msg, ctx...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print a critical message and panic
|
||||
// Print a critical message and panic.
|
||||
func (rl *RevelLogger) Panic(msg string, ctx ...interface{}) {
|
||||
rl.Crit(msg, ctx...)
|
||||
panic(msg)
|
||||
}
|
||||
|
||||
// Override log15 method
|
||||
// Override log15 method.
|
||||
func (rl *RevelLogger) New(ctx ...interface{}) MultiLogger {
|
||||
old := &RevelLogger{Logger: rl.Logger.New(ctx...)}
|
||||
return old
|
||||
}
|
||||
|
||||
// Set the stack level to check for the caller
|
||||
// Set the stack level to check for the caller.
|
||||
func (rl *RevelLogger) SetStackDepth(amount int) MultiLogger {
|
||||
rl.Logger.SetStackDepth(amount) // Ignore the logger returned
|
||||
return rl
|
||||
}
|
||||
|
||||
// Create a new logger
|
||||
// Create a new logger.
|
||||
func New(ctx ...interface{}) MultiLogger {
|
||||
r := &RevelLogger{Logger: log15.New(ctx...)}
|
||||
r.SetStackDepth(0)
|
||||
return r
|
||||
}
|
||||
|
||||
// Set the handler in the Logger
|
||||
// Set the handler in the Logger.
|
||||
func (rl *RevelLogger) SetHandler(h LogHandler) {
|
||||
rl.Logger.SetHandler(callHandler(h.Log))
|
||||
}
|
||||
|
||||
// The function wrapper to implement the callback
|
||||
// The function wrapper to implement the callback.
|
||||
type callHandler func(r *Record) error
|
||||
|
||||
// Log implementation, reads the record and extracts the details from the log record
|
||||
@@ -116,16 +117,16 @@ func (c callHandler) Log(log *log15.Record) error {
|
||||
ctxMap[key] = value
|
||||
}
|
||||
} else {
|
||||
ctxMap = make(ContextMap, 0)
|
||||
ctxMap = make(ContextMap)
|
||||
}
|
||||
r := &Record{Message: log.Msg, Context: ctxMap, Time: log.Time, Level: LogLevel(log.Lvl), Call: CallStack(log.Call)}
|
||||
return c(r)
|
||||
}
|
||||
|
||||
// Internally used contextMap, allows conversion of map to map[string]string
|
||||
// Internally used contextMap, allows conversion of map to map[string]string.
|
||||
type ContextMap map[string]interface{}
|
||||
|
||||
// Convert the context map to be string only values, any non string values are ignored
|
||||
// Convert the context map to be string only values, any non string values are ignored.
|
||||
func (m ContextMap) StringMap() (newMap map[string]string) {
|
||||
if m != nil {
|
||||
newMap = map[string]string{}
|
||||
@@ -137,6 +138,7 @@ func (m ContextMap) StringMap() (newMap map[string]string) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m ContextMap) Add(key string, value interface{}) {
|
||||
m[key] = value
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@ const (
|
||||
errorKey = "REVEL_ERROR"
|
||||
)
|
||||
|
||||
var (
|
||||
levelString = map[LogLevel]string{LvlDebug: "DEBUG",
|
||||
LvlInfo: "INFO", LvlWarn: "WARN", LvlError: "ERROR", LvlCrit: "CRIT"}
|
||||
)
|
||||
var levelString = map[LogLevel]string{
|
||||
LvlDebug: "DEBUG",
|
||||
LvlInfo: "INFO", LvlWarn: "WARN", LvlError: "ERROR", LvlCrit: "CRIT",
|
||||
}
|
||||
|
||||
// Outputs to the terminal in a format like below
|
||||
// INFO 09:11:32 server-engine.go:169: Request Stats
|
||||
// INFO 09:11:32 server-engine.go:169: Request Stats.
|
||||
func TerminalFormatHandler(noColor bool, smallDate bool) LogFormat {
|
||||
dateFormat := termTimeFormat
|
||||
if smallDate {
|
||||
@@ -32,7 +32,7 @@ func TerminalFormatHandler(noColor bool, smallDate bool) LogFormat {
|
||||
}
|
||||
return FormatFunc(func(r *Record) []byte {
|
||||
// Bash coloring http://misc.flogisoft.com/bash/tip_colors_and_formatting
|
||||
var color = 0
|
||||
color := 0
|
||||
switch r.Level {
|
||||
case LvlCrit:
|
||||
// Magenta
|
||||
@@ -54,7 +54,7 @@ func TerminalFormatHandler(noColor bool, smallDate bool) LogFormat {
|
||||
b := &bytes.Buffer{}
|
||||
caller, _ := r.Context["caller"].(string)
|
||||
module, _ := r.Context["module"].(string)
|
||||
if noColor == false && color > 0 {
|
||||
if !noColor && color > 0 {
|
||||
if len(module) > 0 {
|
||||
fmt.Fprintf(b, "\x1b[%dm%-5s\x1b[0m %s %6s %13s: %-40s ", color, levelString[r.Level], r.Time.Format(dateFormat), module, caller, r.Message)
|
||||
} else {
|
||||
@@ -77,7 +77,7 @@ func TerminalFormatHandler(noColor bool, smallDate bool) LogFormat {
|
||||
v := formatLogfmtValue(v)
|
||||
|
||||
// TODO: we should probably check that all of your key bytes aren't invalid
|
||||
if noColor == false && color > 0 {
|
||||
if !noColor && color > 0 {
|
||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m=%s", color, k, v)
|
||||
} else {
|
||||
b.WriteString(k)
|
||||
@@ -92,7 +92,7 @@ func TerminalFormatHandler(noColor bool, smallDate bool) LogFormat {
|
||||
})
|
||||
}
|
||||
|
||||
// formatValue formats a value for serialization
|
||||
// formatValue formats a value for serialization.
|
||||
func formatLogfmtValue(value interface{}) string {
|
||||
if value == nil {
|
||||
return "nil"
|
||||
@@ -121,7 +121,7 @@ func formatLogfmtValue(value interface{}) string {
|
||||
}
|
||||
}
|
||||
|
||||
// Format the value in json format
|
||||
// Format the value in json format.
|
||||
func formatShared(value interface{}) (result interface{}) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
@@ -148,12 +148,12 @@ func formatShared(value interface{}) (result interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
// A reusuable buffer for outputting data
|
||||
// A reusuable buffer for outputting data.
|
||||
var stringBufPool = sync.Pool{
|
||||
New: func() interface{} { return new(bytes.Buffer) },
|
||||
}
|
||||
|
||||
// Escape the string when needed
|
||||
// Escape the string when needed.
|
||||
func escapeString(s string) string {
|
||||
needsQuotes := false
|
||||
needsEscape := false
|
||||
@@ -165,7 +165,7 @@ func escapeString(s string) string {
|
||||
needsEscape = true
|
||||
}
|
||||
}
|
||||
if needsEscape == false && needsQuotes == false {
|
||||
if !needsEscape && !needsQuotes {
|
||||
return s
|
||||
}
|
||||
e := stringBufPool.Get().(*bytes.Buffer)
|
||||
@@ -215,7 +215,7 @@ func JsonFormatEx(pretty, lineSeparated bool) LogFormat {
|
||||
props["lvl"] = levelString[r.Level]
|
||||
props["msg"] = r.Message
|
||||
for k, v := range r.Context {
|
||||
props[k] = formatJsonValue(v)
|
||||
props[k] = formatJSONValue(v)
|
||||
}
|
||||
|
||||
b, err := jsonMarshal(props)
|
||||
@@ -234,7 +234,7 @@ func JsonFormatEx(pretty, lineSeparated bool) LogFormat {
|
||||
})
|
||||
}
|
||||
|
||||
func formatJsonValue(value interface{}) interface{} {
|
||||
func formatJSONValue(value interface{}) interface{} {
|
||||
value = formatShared(value)
|
||||
switch value.(type) {
|
||||
case int, int8, int16, int32, int64, float32, float64, uint, uint8, uint16, uint32, uint64, string:
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/revel/log15"
|
||||
"gopkg.in/stack.v0"
|
||||
"log"
|
||||
)
|
||||
|
||||
// Utility package to make existing logging backwards compatible
|
||||
// Utility package to make existing logging backwards compatible.
|
||||
var (
|
||||
// Convert the string to LogLevel
|
||||
toLevel = map[string]LogLevel{"debug": LogLevel(log15.LvlDebug),
|
||||
// Convert the string to LogLevel.
|
||||
toLevel = map[string]LogLevel{
|
||||
"debug": LogLevel(log15.LvlDebug),
|
||||
"info": LogLevel(log15.LvlInfo), "request": LogLevel(log15.LvlInfo), "warn": LogLevel(log15.LvlWarn),
|
||||
"error": LogLevel(log15.LvlError), "crit": LogLevel(log15.LvlCrit),
|
||||
"trace": LogLevel(log15.LvlDebug), // TODO trace is deprecated, replaced by debug
|
||||
@@ -17,13 +19,13 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
// The test mode flag overrides the default log level and shows only errors
|
||||
// The test mode flag overrides the default log level and shows only errors.
|
||||
TEST_MODE_FLAG = "testModeFlag"
|
||||
// The special use flag enables showing messages when the logger is setup
|
||||
// The special use flag enables showing messages when the logger is setup.
|
||||
SPECIAL_USE_FLAG = "specialUseFlag"
|
||||
)
|
||||
|
||||
// Returns the logger for the name
|
||||
// Returns the logger for the name.
|
||||
func GetLogger(name string, logger MultiLogger) (l *log.Logger) {
|
||||
switch name {
|
||||
case "trace": // TODO trace is deprecated, replaced by debug
|
||||
@@ -41,10 +43,9 @@ func GetLogger(name string, logger MultiLogger) (l *log.Logger) {
|
||||
}
|
||||
|
||||
return l
|
||||
|
||||
}
|
||||
|
||||
// Used by the initFilterLog to handle the filters
|
||||
// Used by the initFilterLog to handle the filters.
|
||||
var logFilterList = []struct {
|
||||
LogPrefix, LogSuffix string
|
||||
parentHandler func(map[string]interface{}) ParentLogHandler
|
||||
@@ -54,7 +55,6 @@ var logFilterList = []struct {
|
||||
return NewParentLogHandler(func(child LogHandler) LogHandler {
|
||||
return MatchMapHandler(keyMap, child)
|
||||
})
|
||||
|
||||
},
|
||||
}, {
|
||||
"log.", ".nfilter",
|
||||
@@ -65,20 +65,20 @@ var logFilterList = []struct {
|
||||
},
|
||||
}}
|
||||
|
||||
// This structure and method will handle the old output format and log it to the new format
|
||||
// This structure and method will handle the old output format and log it to the new format.
|
||||
type loggerRewrite struct {
|
||||
Logger MultiLogger
|
||||
Level log15.Lvl
|
||||
hideDeprecated bool
|
||||
}
|
||||
|
||||
// The message indicating that a logger is using a deprecated log mechanism
|
||||
var log_deprecated = []byte("* LOG DEPRECATED * ")
|
||||
// The message indicating that a logger is using a deprecated log mechanism.
|
||||
var logDeprecated = []byte("* LOG DEPRECATED * ")
|
||||
|
||||
// Implements the Write of the logger
|
||||
// Implements the Write of the logger.
|
||||
func (lr loggerRewrite) Write(p []byte) (n int, err error) {
|
||||
if !lr.hideDeprecated {
|
||||
p = append(log_deprecated, p...)
|
||||
p = append(logDeprecated, p...)
|
||||
}
|
||||
n = len(p)
|
||||
if len(p) > 0 && p[n-1] == '\n' {
|
||||
@@ -104,7 +104,7 @@ func (lr loggerRewrite) Write(p []byte) (n int, err error) {
|
||||
|
||||
// For logging purposes the call stack can be used to record the stack trace of a bad error
|
||||
// simply pass it as a context field in your log statement like
|
||||
// `controller.Log.Crit("This should not occur","stack",revel.NewCallStack())`
|
||||
// `controller.Log.Crit("This should not occur","stack",revel.NewCallStack())`.
|
||||
func NewCallStack() interface{} {
|
||||
return stack.Trace()
|
||||
}
|
||||
|
||||
@@ -9,29 +9,29 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Function handler wraps the declared function and returns the handler for it
|
||||
// Function handler wraps the declared function and returns the handler for it.
|
||||
func FuncHandler(fn func(r *Record) error) LogHandler {
|
||||
return funcHandler(fn)
|
||||
}
|
||||
|
||||
// The type decleration for the function
|
||||
// The type declaration for the function.
|
||||
type funcHandler func(r *Record) error
|
||||
|
||||
// The implementation of the Log
|
||||
// The implementation of the Log.
|
||||
func (h funcHandler) Log(r *Record) error {
|
||||
return h(r)
|
||||
}
|
||||
|
||||
// This function allows you to do a full declaration for the log,
|
||||
// it is recommended you use FuncHandler instead
|
||||
// it is recommended you use FuncHandler instead.
|
||||
func HandlerFunc(log func(message string, time time.Time, level LogLevel, call CallStack, context ContextMap) error) LogHandler {
|
||||
return remoteHandler(log)
|
||||
}
|
||||
|
||||
// The type used for the HandlerFunc
|
||||
// The type used for the HandlerFunc.
|
||||
type remoteHandler func(message string, time time.Time, level LogLevel, call CallStack, context ContextMap) error
|
||||
|
||||
// The Log implementation
|
||||
// The Log implementation.
|
||||
func (c remoteHandler) Log(record *Record) error {
|
||||
return c(record.Message, record.Time, record.Level, record.Call, record.Context)
|
||||
}
|
||||
@@ -56,11 +56,9 @@ func LazyHandler(h LogHandler) LogHandler {
|
||||
return FuncHandler(func(r *Record) error {
|
||||
for k, v := range r.Context {
|
||||
if lz, ok := v.(Lazy); ok {
|
||||
value, err := evaluateLazy(lz)
|
||||
_, err := evaluateLazy(lz)
|
||||
if err != nil {
|
||||
r.Context[errorKey] = "bad lazy " + k
|
||||
} else {
|
||||
v = value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,11 +86,12 @@ func evaluateLazy(lz Lazy) (interface{}, error) {
|
||||
results := value.Call([]reflect.Value{})
|
||||
if len(results) == 1 {
|
||||
return results[0].Interface(), nil
|
||||
} else {
|
||||
}
|
||||
|
||||
values := make([]interface{}, len(results))
|
||||
for i, v := range results {
|
||||
values[i] = v.Interface()
|
||||
}
|
||||
|
||||
return values, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package command
|
||||
|
||||
type (
|
||||
Build struct {
|
||||
ImportCommand
|
||||
@@ -6,5 +7,4 @@ type (
|
||||
Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"`
|
||||
CopySource bool `short:"s" long:"include-source" description:"Copy the source code as well"`
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package command
|
||||
|
||||
type (
|
||||
Clean struct {
|
||||
ImportCommand
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package command
|
||||
|
||||
|
||||
type (
|
||||
New struct {
|
||||
ImportCommand
|
||||
@@ -10,5 +9,4 @@ type (
|
||||
Run bool `short:"r" long:"run" description:"True if you want to run the application right away"`
|
||||
Callback func() error
|
||||
}
|
||||
|
||||
)
|
||||
@@ -1,4 +1,5 @@
|
||||
package command
|
||||
|
||||
type (
|
||||
Package struct {
|
||||
ImportCommand
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package command
|
||||
|
||||
type (
|
||||
Run struct {
|
||||
ImportCommand
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package command
|
||||
|
||||
type (
|
||||
Version struct {
|
||||
ImportCommand
|
||||
|
||||
@@ -2,8 +2,6 @@ package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/revel/cmd"
|
||||
"github.com/revel/cmd/utils"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/parser"
|
||||
@@ -13,10 +11,13 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/revel/cmd"
|
||||
"github.com/revel/cmd/model/command"
|
||||
"github.com/revel/cmd/utils"
|
||||
)
|
||||
|
||||
// The constants
|
||||
// The constants.
|
||||
const (
|
||||
NEW COMMAND = iota + 1
|
||||
RUN
|
||||
@@ -28,10 +29,10 @@ const (
|
||||
)
|
||||
|
||||
type (
|
||||
// The Revel command type
|
||||
// The Revel command type.
|
||||
COMMAND int
|
||||
|
||||
// The Command config for the line input
|
||||
// The Command config for the line input.
|
||||
CommandConfig struct {
|
||||
Index COMMAND // The index
|
||||
Verbose []bool `short:"v" long:"debug" description:"If set the logger is set to verbose"` // True if debug is active
|
||||
@@ -59,7 +60,7 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// Updates the import path depending on the command
|
||||
// Updates the import path depending on the command.
|
||||
func (c *CommandConfig) UpdateImportPath() error {
|
||||
var importPath string
|
||||
required := true
|
||||
@@ -109,7 +110,7 @@ func (c *CommandConfig) UpdateImportPath() error {
|
||||
importPath = importPath[4:]
|
||||
} else if importPath == "src" {
|
||||
if c.Index != VERSION {
|
||||
return fmt.Errorf("Invlaid import path, working dir is in GOPATH root")
|
||||
return fmt.Errorf("invalid import path, working dir is in GOPATH root")
|
||||
}
|
||||
importPath = ""
|
||||
}
|
||||
@@ -137,7 +138,7 @@ func (c *CommandConfig) UpdateImportPath() error {
|
||||
return nil
|
||||
}
|
||||
if len(importPath) == 0 {
|
||||
return fmt.Errorf("Unable to determine import path from : %s", importPath)
|
||||
return fmt.Errorf("unable to determine import path from : %s", importPath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -153,7 +154,7 @@ func (c *CommandConfig) initAppFolder() (err error) {
|
||||
|
||||
// First try to determine where the application is located - this should be the import value
|
||||
appFolder := c.ImportPath
|
||||
wd, err := os.Getwd()
|
||||
wd, _ := os.Getwd()
|
||||
if len(appFolder) == 0 {
|
||||
// We will assume the working directory is the appFolder
|
||||
appFolder = wd
|
||||
@@ -216,7 +217,6 @@ func (c *CommandConfig) initAppFolder() (err error) {
|
||||
c.AppPath = filepath.Join(bestpath, "src", c.ImportPath)
|
||||
}
|
||||
// Recalculate the appFolder because we are using a GOPATH
|
||||
|
||||
} else {
|
||||
// This is new and not vendored, so the app path is the appFolder
|
||||
c.AppPath = appFolder
|
||||
@@ -226,7 +226,7 @@ func (c *CommandConfig) initAppFolder() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Used to initialize the package resolver
|
||||
// Used to initialize the package resolver.
|
||||
func (c *CommandConfig) InitPackageResolver() {
|
||||
c.initGoPaths()
|
||||
utils.Logger.Info("InitPackageResolver", "useVendor", c.Vendored, "path", c.AppPath)
|
||||
@@ -255,7 +255,7 @@ func (c *CommandConfig) InitPackageResolver() {
|
||||
}
|
||||
}
|
||||
|
||||
// lookup and set Go related variables
|
||||
// lookup and set Go related variables.
|
||||
func (c *CommandConfig) initGoPaths() {
|
||||
utils.Logger.Info("InitGoPaths", "vendored", c.Vendored)
|
||||
// check for go executable
|
||||
@@ -275,10 +275,7 @@ func (c *CommandConfig) initGoPaths() {
|
||||
utils.Logger.Fatal("Abort: GOPATH environment variable is not set. " +
|
||||
"Please refer to http://golang.org/doc/code.html to configure your Go environment.")
|
||||
}
|
||||
return
|
||||
// todo determine if the rest needs to happen
|
||||
|
||||
|
||||
// revel/revel#1004 choose go path relative to current working directory
|
||||
|
||||
// What we want to do is to add the import to the end of the
|
||||
@@ -304,10 +301,9 @@ func (c *CommandConfig) initGoPaths() {
|
||||
utils.Logger.Info("Set application path", "path", c.AppPath)
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
// Sets the versions on the command config
|
||||
// Sets the versions on the command config.
|
||||
func (c *CommandConfig) SetVersions() (err error) {
|
||||
c.CommandVersion, _ = ParseVersion(cmd.Version)
|
||||
pathMap, err := utils.FindSrcPaths(c.AppPath, []string{RevelImportPath}, c.PackageResolver)
|
||||
@@ -339,7 +335,7 @@ func (c *CommandConfig) SetVersions() (err error) {
|
||||
spec := a.(*ast.ValueSpec)
|
||||
r := spec.Values[0].(*ast.BasicLit)
|
||||
if spec.Names[0].Name == "Version" {
|
||||
c.FrameworkVersion, err = ParseVersion(strings.Replace(r.Value, `"`, ``, -1))
|
||||
c.FrameworkVersion, err = ParseVersion(strings.ReplaceAll(r.Value, `"`, ``))
|
||||
if err != nil {
|
||||
utils.Logger.Errorf("Failed to parse version")
|
||||
} else {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package model
|
||||
|
||||
// The embedded type name takes the import path and structure name
|
||||
// The embedded type name takes the import path and structure name.
|
||||
type EmbeddedTypeName struct {
|
||||
ImportPath, StructName string
|
||||
}
|
||||
|
||||
// Convert the type to a properly formatted import line
|
||||
// Convert the type to a properly formatted import line.
|
||||
func (s *EmbeddedTypeName) String() string {
|
||||
return s.ImportPath + "." + s.StructName
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package model
|
||||
|
||||
type (
|
||||
// The event type
|
||||
// The event type.
|
||||
Event int
|
||||
// The event response
|
||||
// The event response.
|
||||
EventResponse int
|
||||
// The handler signature
|
||||
// The handler signature.
|
||||
EventHandler func(typeOf Event, value interface{}) (responseOf EventResponse)
|
||||
RevelCallback interface {
|
||||
FireEvent(key Event, value interface{}) (response EventResponse)
|
||||
@@ -14,40 +14,40 @@ type (
|
||||
)
|
||||
|
||||
const (
|
||||
// Event type when templates are going to be refreshed (receivers are registered template engines added to the template.engine conf option)
|
||||
// Event type when templates are going to be refreshed (receivers are registered template engines added to the template.engine conf option).
|
||||
TEMPLATE_REFRESH_REQUESTED Event = iota
|
||||
// Event type when templates are refreshed (receivers are registered template engines added to the template.engine conf option)
|
||||
// Event type when templates are refreshed (receivers are registered template engines added to the template.engine conf option).
|
||||
TEMPLATE_REFRESH_COMPLETED
|
||||
// Event type before all module loads, events thrown to handlers added to AddInitEventHandler
|
||||
// Event type before all module loads, events thrown to handlers added to AddInitEventHandler.
|
||||
|
||||
// Event type before all module loads, events thrown to handlers added to AddInitEventHandler
|
||||
// Event type before all module loads, events thrown to handlers added to AddInitEventHandler.
|
||||
REVEL_BEFORE_MODULES_LOADED
|
||||
// Event type before module loads, events thrown to handlers added to AddInitEventHandler
|
||||
// Event type before module loads, events thrown to handlers added to AddInitEventHandler.
|
||||
REVEL_BEFORE_MODULE_LOADED
|
||||
// Event type after module loads, events thrown to handlers added to AddInitEventHandler
|
||||
// Event type after module loads, events thrown to handlers added to AddInitEventHandler.
|
||||
REVEL_AFTER_MODULE_LOADED
|
||||
// Event type after all module loads, events thrown to handlers added to AddInitEventHandler
|
||||
// Event type after all module loads, events thrown to handlers added to AddInitEventHandler.
|
||||
REVEL_AFTER_MODULES_LOADED
|
||||
|
||||
// Event type before server engine is initialized, receivers are active server engine and handlers added to AddInitEventHandler
|
||||
// Event type before server engine is initialized, receivers are active server engine and handlers added to AddInitEventHandler.
|
||||
ENGINE_BEFORE_INITIALIZED
|
||||
// Event type before server engine is started, receivers are active server engine and handlers added to AddInitEventHandler
|
||||
// Event type before server engine is started, receivers are active server engine and handlers added to AddInitEventHandler.
|
||||
ENGINE_STARTED
|
||||
// Event type after server engine is stopped, receivers are active server engine and handlers added to AddInitEventHandler
|
||||
// Event type after server engine is stopped, receivers are active server engine and handlers added to AddInitEventHandler.
|
||||
ENGINE_SHUTDOWN
|
||||
|
||||
// Called before routes are refreshed
|
||||
// Called before routes are refreshed.
|
||||
ROUTE_REFRESH_REQUESTED
|
||||
// Called after routes have been refreshed
|
||||
// Called after routes have been refreshed.
|
||||
ROUTE_REFRESH_COMPLETED
|
||||
|
||||
// Fired when a panic is caught during the startup process
|
||||
// Fired when a panic is caught during the startup process.
|
||||
REVEL_FAILURE
|
||||
)
|
||||
|
||||
var initEventList = []EventHandler{} // Event handler list for receiving events
|
||||
|
||||
// Fires system events from revel
|
||||
// Fires system events from revel.
|
||||
func RaiseEvent(key Event, value interface{}) (response EventResponse) {
|
||||
for _, handler := range initEventList {
|
||||
response |= handler(key, value)
|
||||
@@ -55,8 +55,7 @@ func RaiseEvent(key Event, value interface{}) (response EventResponse) {
|
||||
return
|
||||
}
|
||||
|
||||
// Add event handler to listen for all system events
|
||||
// Add event handler to listen for all system events.
|
||||
func AddInitEventHandler(handler EventHandler) {
|
||||
initEventList = append(initEventList, handler)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package model_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/revel/revel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test that the event handler can be attached and it dispatches the event received
|
||||
// Test that the event handler can be attached and it dispatches the event received.
|
||||
func TestEventHandler(t *testing.T) {
|
||||
counter := 0
|
||||
newListener := func(typeOf revel.Event, value interface{}) (responseOf revel.EventResponse) {
|
||||
@@ -21,4 +22,3 @@ func TestEventHandler(t *testing.T) {
|
||||
revel.StopServer(1)
|
||||
assert.Equal(t, counter, 2, "Expected event handler to have been called")
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,14 @@ type MethodCall struct {
|
||||
Names []string
|
||||
}
|
||||
|
||||
// MethodSpec holds the information of one Method
|
||||
// MethodSpec holds the information of one Method.
|
||||
type MethodSpec struct {
|
||||
Name string // Name of the method, e.g. "Index"
|
||||
Args []*MethodArg // Argument descriptors
|
||||
RenderCalls []*MethodCall // Descriptions of Render() invocations from this Method.
|
||||
}
|
||||
|
||||
// MethodArg holds the information of one argument
|
||||
// MethodArg holds the information of one argument.
|
||||
type MethodArg struct {
|
||||
Name string // Name of the argument.
|
||||
TypeExpr TypeExpr // The name of the type, e.g. "int", "*pkg.UserType"
|
||||
|
||||
@@ -2,18 +2,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/utils"
|
||||
"github.com/revel/config"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/revel/cmd/utils"
|
||||
"github.com/revel/config"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
type (
|
||||
// The container object for describing all Revels variables
|
||||
// The container object for describing all Revels variables.
|
||||
RevelContainer struct {
|
||||
BuildPaths struct {
|
||||
Revel string
|
||||
@@ -77,25 +78,28 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// Simple Wrapped RevelCallback
|
||||
// Simple Wrapped RevelCallback.
|
||||
func NewWrappedRevelCallback(fe func(key Event, value interface{}) (response EventResponse), ie func(pkgName string) error) RevelCallback {
|
||||
return &WrappedRevelCallback{fe, ie}
|
||||
}
|
||||
|
||||
// Function to implement the FireEvent
|
||||
// Function to implement the FireEvent.
|
||||
func (w *WrappedRevelCallback) FireEvent(key Event, value interface{}) (response EventResponse) {
|
||||
if w.FireEventFunction != nil {
|
||||
response = w.FireEventFunction(key, value)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (w *WrappedRevelCallback) PackageResolver(pkgName string) error {
|
||||
return w.ImportFunction(pkgName)
|
||||
}
|
||||
|
||||
// RevelImportPath Revel framework import path
|
||||
var RevelImportPath = "github.com/revel/revel"
|
||||
var RevelModulesImportPath = "github.com/revel/modules"
|
||||
// RevelImportPath Revel framework import path.
|
||||
var (
|
||||
RevelImportPath = "github.com/revel/revel"
|
||||
RevelModulesImportPath = "github.com/revel/modules"
|
||||
)
|
||||
|
||||
// This function returns a container object describing the revel application
|
||||
// eventually this type of function will replace the global variables.
|
||||
@@ -119,10 +123,10 @@ func NewRevelPaths(mode, importPath, appSrcPath string, callback RevelCallback)
|
||||
|
||||
// Sanity check , ensure app and conf paths exist
|
||||
if !utils.DirExists(rp.AppPath) {
|
||||
return rp, fmt.Errorf("No application found at path %s", rp.AppPath)
|
||||
return rp, fmt.Errorf("no application found at path %s", rp.AppPath)
|
||||
}
|
||||
if !utils.DirExists(filepath.Join(rp.BasePath, "conf")) {
|
||||
return rp, fmt.Errorf("No configuration found at path %s", filepath.Join(rp.BasePath, "conf"))
|
||||
return rp, fmt.Errorf("no configuration found at path %s", filepath.Join(rp.BasePath, "conf"))
|
||||
}
|
||||
|
||||
rp.ViewsPath = filepath.Join(rp.AppPath, "views")
|
||||
@@ -146,7 +150,7 @@ func NewRevelPaths(mode, importPath, appSrcPath string, callback RevelCallback)
|
||||
|
||||
rp.Config, err = config.LoadContext("app.conf", rp.ConfPaths)
|
||||
if err != nil {
|
||||
return rp, fmt.Errorf("Unable to load configuartion file %s", err)
|
||||
return rp, fmt.Errorf("unable to load configuration file %s", err)
|
||||
}
|
||||
|
||||
// Ensure that the selected runmode appears in app.conf.
|
||||
@@ -168,10 +172,10 @@ func NewRevelPaths(mode, importPath, appSrcPath string, callback RevelCallback)
|
||||
rp.HTTPSslKey = rp.Config.StringDefault("http.sslkey", "")
|
||||
if rp.HTTPSsl {
|
||||
if rp.HTTPSslCert == "" {
|
||||
return rp, errors.New("No http.sslcert provided.")
|
||||
return rp, errors.New("no http.sslcert provided")
|
||||
}
|
||||
if rp.HTTPSslKey == "" {
|
||||
return rp, errors.New("No http.sslkey provided.")
|
||||
return rp, errors.New("no http.sslkey provided")
|
||||
}
|
||||
}
|
||||
//
|
||||
@@ -197,7 +201,7 @@ func NewRevelPaths(mode, importPath, appSrcPath string, callback RevelCallback)
|
||||
func (rp *RevelContainer) LoadMimeConfig() (err error) {
|
||||
rp.MimeConfig, err = config.LoadContext("mime-types.conf", rp.ConfPaths)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to load mime type config: %s %s", "error", err)
|
||||
return fmt.Errorf("failed to load mime type config: %s %s", "error", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -206,12 +210,10 @@ func (rp *RevelContainer) LoadMimeConfig() (err error) {
|
||||
// This will fire the REVEL_BEFORE_MODULE_LOADED, REVEL_AFTER_MODULE_LOADED
|
||||
// for each module loaded. The callback will receive the RevelContainer, name, moduleImportPath and modulePath
|
||||
// It will automatically add in the code paths for the module to the
|
||||
// container object
|
||||
// container object.
|
||||
func (rp *RevelContainer) loadModules(callback RevelCallback) (err error) {
|
||||
keys := []string{}
|
||||
for _, key := range rp.Config.Options("module.") {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
keys = append(keys, rp.Config.Options("module.")...)
|
||||
|
||||
// Reorder module order by key name, a poor mans sort but at least it is consistent
|
||||
sort.Strings(keys)
|
||||
@@ -227,7 +229,7 @@ func (rp *RevelContainer) loadModules(callback RevelCallback) (err error) {
|
||||
callback.PackageResolver(moduleImportPath)
|
||||
modulePath, err = rp.ResolveImportPath(moduleImportPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to load module. Import of path failed %s:%s %s:%s ", "modulePath", moduleImportPath, "error", err)
|
||||
return fmt.Errorf("failed to load module. Import of path failed %s:%s %s:%s ", "modulePath", moduleImportPath, "error", err)
|
||||
}
|
||||
}
|
||||
// Drop anything between module.???.<name of module>
|
||||
@@ -242,7 +244,7 @@ func (rp *RevelContainer) loadModules(callback RevelCallback) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Adds a module paths to the container object
|
||||
// Adds a module paths to the container object.
|
||||
func (rp *RevelContainer) addModulePaths(name, importPath, modulePath string) {
|
||||
utils.Logger.Info("Adding module path", "name", name, "import path", importPath, "system path", modulePath)
|
||||
if codePath := filepath.Join(modulePath, "app"); utils.DirExists(codePath) {
|
||||
@@ -271,6 +273,8 @@ func (rp *RevelContainer) ResolveImportPath(importPath string) (string, error) {
|
||||
return filepath.Join(rp.SourcePath, importPath), nil
|
||||
}
|
||||
config := &packages.Config{
|
||||
// TODO: packages.LoadSyntax deprecated, Need instead
|
||||
//nolint:staticcheck
|
||||
Mode: packages.LoadSyntax,
|
||||
Dir: rp.AppPath,
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@ package model
|
||||
// SourceInfo is the top-level struct containing all extracted information
|
||||
// about the app source code, used to generate main.go.
|
||||
import (
|
||||
"github.com/revel/cmd/utils"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/revel/cmd/utils"
|
||||
)
|
||||
|
||||
type SourceInfo struct {
|
||||
@@ -35,7 +36,7 @@ type SourceInfo struct {
|
||||
|
||||
// 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"
|
||||
// e.g. "github.com/revel/revel.Controller".
|
||||
func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered []*TypeInfo) {
|
||||
// Do a search in the "embedded type graph", starting with the target type.
|
||||
var (
|
||||
@@ -76,6 +77,7 @@ func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered
|
||||
"type", filteredItem.StructName,
|
||||
"package", filteredItem.ImportPath)
|
||||
filtered = append(filtered[:i], filtered[i+1:]...)
|
||||
//nolint:ineffassign // huh?
|
||||
exit = false
|
||||
break
|
||||
}
|
||||
@@ -108,7 +110,7 @@ func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered
|
||||
}
|
||||
|
||||
// ControllerSpecs returns the all the controllers that embeds
|
||||
// `revel.Controller`
|
||||
// `revel.Controller`.
|
||||
func (s *SourceInfo) ControllerSpecs() []*TypeInfo {
|
||||
utils.Logger.Info("Scanning controller specifications for types ", "typePath", RevelImportPath+".Controller", "speclen", len(s.controllerSpecs))
|
||||
if s.controllerSpecs == nil {
|
||||
@@ -118,7 +120,7 @@ func (s *SourceInfo) ControllerSpecs() []*TypeInfo {
|
||||
}
|
||||
|
||||
// TestSuites returns the all the Application tests that embeds
|
||||
// `testing.TestSuite`
|
||||
// `testing.TestSuite`.
|
||||
func (s *SourceInfo) TestSuites() []*TypeInfo {
|
||||
if s.testSuites == nil {
|
||||
s.testSuites = s.TypesThatEmbed(RevelImportPath+"/testing.TestSuite", "testsuite")
|
||||
|
||||
@@ -13,7 +13,7 @@ type TypeExpr struct {
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Returns a new type from the data
|
||||
// Returns a new type from the data.
|
||||
func NewTypeExprFromData(expr, pkgName string, pkgIndex int, valid bool) TypeExpr {
|
||||
return TypeExpr{expr, pkgName, pkgIndex, valid}
|
||||
}
|
||||
@@ -47,7 +47,6 @@ func NewTypeExprFromAst(pkgName string, expr ast.Expr) TypeExpr {
|
||||
return NewTypeExprFromData("[]"+e.Expr, e.PkgName, e.pkgIndex+2, e.Valid)
|
||||
default:
|
||||
error = fmt.Sprintf("Failed to generate name for field: %v Package: %v. Make sure the field name is valid.", expr, pkgName)
|
||||
|
||||
}
|
||||
return NewTypeExprFromData(error, "", 0, false)
|
||||
}
|
||||
@@ -85,13 +84,13 @@ var builtInTypes = map[string]struct{}{
|
||||
"uintptr": {},
|
||||
}
|
||||
|
||||
// IsBuiltinType checks the given type is built-in types of Go
|
||||
// IsBuiltinType checks the given type is built-in types of Go.
|
||||
func IsBuiltinType(name string) bool {
|
||||
_, ok := builtInTypes[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Returns the first non empty string from a list of arguements
|
||||
// Returns the first non empty string from a list of arguments.
|
||||
func FirstNonEmpty(strs ...string) string {
|
||||
for _, str := range strs {
|
||||
if len(str) > 0 {
|
||||
|
||||
@@ -9,7 +9,7 @@ type TypeInfo struct {
|
||||
EmbeddedTypes []*EmbeddedTypeName // Used internally to identify controllers that indirectly embed *revel.Controller.
|
||||
}
|
||||
|
||||
// Return the type information as a properly formatted import string
|
||||
// Return the type information as a properly formatted import string.
|
||||
func (s *TypeInfo) String() string {
|
||||
return s.ImportPath + "." + s.StructName
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@ package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Version struct {
|
||||
@@ -17,26 +18,24 @@ type Version struct {
|
||||
MinGoVersion string
|
||||
}
|
||||
|
||||
// The compatibility list
|
||||
// The compatibility list.
|
||||
var frameworkCompatibleRangeList = [][]string{
|
||||
{"0.0.0", "0.20.0"}, // minimum Revel version to use with this version of the tool
|
||||
{"0.19.99", "0.30.0"}, // Compatible with Framework V 0.19.99 - 0.30.0
|
||||
{"1.0.0", "1.9.0"}, // Compatible with Framework V 1.0 - 1.9
|
||||
}
|
||||
|
||||
// Parses a version like v1.2.3a or 1.2
|
||||
// Parses a version like v1.2.3a or 1.2.
|
||||
var versionRegExp = regexp.MustCompile(`([^\d]*)?([0-9]*)\.([0-9]*)(\.([0-9]*))?(.*)`)
|
||||
|
||||
// Parse the version and return it as a Version object
|
||||
// Parse the version and return it as a Version object.
|
||||
func ParseVersion(version string) (v *Version, err error) {
|
||||
|
||||
v = &Version{}
|
||||
return v, v.ParseVersion(version)
|
||||
}
|
||||
|
||||
// Parse the version and return it as a Version object
|
||||
// Parse the version and return it as a Version object.
|
||||
func (v *Version) ParseVersion(version string) (err error) {
|
||||
|
||||
parsedResult := versionRegExp.FindAllStringSubmatch(version, -1)
|
||||
if len(parsedResult) != 1 {
|
||||
err = errors.Errorf("Invalid version %s", version)
|
||||
@@ -55,7 +54,8 @@ func (v *Version)ParseVersion(version string) (err error) {
|
||||
|
||||
return
|
||||
}
|
||||
// Returns 0 or an int value for the string, errors are returned as 0
|
||||
|
||||
// Returns 0 or an int value for the string, errors are returned as 0.
|
||||
func (v *Version) intOrZero(input string) (value int) {
|
||||
if input != "" {
|
||||
value, _ = strconv.Atoi(input)
|
||||
@@ -63,7 +63,7 @@ func (v *Version) intOrZero(input string) (value int) {
|
||||
return value
|
||||
}
|
||||
|
||||
// Returns true if this major revision is compatible
|
||||
// Returns true if this major revision is compatible.
|
||||
func (v *Version) CompatibleFramework(c *CommandConfig) error {
|
||||
for i, rv := range frameworkCompatibleRangeList {
|
||||
start, _ := ParseVersion(rv[0])
|
||||
@@ -81,7 +81,7 @@ func (v *Version) CompatibleFramework(c *CommandConfig) error {
|
||||
return errors.New("Tool out of date - do a 'go get -u github.com/revel/cmd/revel'")
|
||||
}
|
||||
|
||||
// Returns true if this major revision is newer then the passed in
|
||||
// Returns true if this major revision is newer then the passed in.
|
||||
func (v *Version) MajorNewer(o *Version) bool {
|
||||
if v.Major != o.Major {
|
||||
return v.Major > o.Major
|
||||
@@ -89,7 +89,7 @@ func (v *Version) MajorNewer(o *Version) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Returns true if this major or major and minor revision is newer then the value passed in
|
||||
// Returns true if this major or major and minor revision is newer then the value passed in.
|
||||
func (v *Version) MinorNewer(o *Version) bool {
|
||||
if v.Major != o.Major {
|
||||
return v.Major > o.Major
|
||||
@@ -100,7 +100,7 @@ func (v *Version) MinorNewer(o *Version) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Returns true if the version is newer then the current on
|
||||
// Returns true if the version is newer then the current on.
|
||||
func (v *Version) Newer(o *Version) bool {
|
||||
if v.Major != o.Major {
|
||||
return v.Major > o.Major
|
||||
@@ -114,13 +114,13 @@ func (v *Version) Newer(o *Version) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Convert the version to a string
|
||||
// Convert the version to a string.
|
||||
func (v *Version) VersionString() string {
|
||||
return fmt.Sprintf("%s%d.%d.%d%s", v.Prefix, v.Major, v.Minor, v.Maintenance, v.Suffix)
|
||||
}
|
||||
|
||||
// Convert the version build date and go version to a string
|
||||
// Convert the version build date and go version to a string.
|
||||
func (v *Version) String() string {
|
||||
return fmt.Sprintf("Version: %s%d.%d.%d%s\nBuild Date: %s\n Minimium Go Version: %s",
|
||||
return fmt.Sprintf("Version: %s%d.%d.%d%s\nBuild Date: %s\n Minimum Go Version: %s",
|
||||
v.Prefix, v.Major, v.Minor, v.Maintenance, v.Suffix, v.BuildDate, v.MinGoVersion)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package model_test
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var versionTests = [][]string{
|
||||
@@ -12,7 +13,8 @@ var versionTests = [][]string{
|
||||
{"v0.20.", "v0.20.0"},
|
||||
{"2.0", "2.0.0"},
|
||||
}
|
||||
// Test that the event handler can be attached and it dispatches the event received
|
||||
|
||||
// Test that the event handler can be attached and it dispatches the event received.
|
||||
func TestVersion(t *testing.T) {
|
||||
for _, v := range versionTests {
|
||||
p, e := model.ParseVersion(v[0])
|
||||
@@ -21,7 +23,7 @@ func TestVersion(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// test the ranges
|
||||
// test the ranges.
|
||||
func TestVersionRange(t *testing.T) {
|
||||
a, _ := model.ParseVersion("0.1.2")
|
||||
b, _ := model.ParseVersion("0.2.1")
|
||||
|
||||
@@ -2,9 +2,10 @@ package parser
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"github.com/revel/cmd/utils"
|
||||
"github.com/revel/cmd/model"
|
||||
"go/token"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
)
|
||||
|
||||
// If this Decl is a struct type definition, it is summarized and added to specs.
|
||||
@@ -91,7 +92,7 @@ func appendStruct(fileName string, specs []*model.TypeInfo, pkgImportPath string
|
||||
|
||||
// If decl is a Method declaration, it is summarized and added to the array
|
||||
// underneath its receiver type.
|
||||
// e.g. "Login" => {MethodSpec, MethodSpec, ..}
|
||||
// e.g. "Login" => {MethodSpec, MethodSpec, ..}.
|
||||
func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPath, pkgName string, imports map[string]string) {
|
||||
// Func declaration?
|
||||
funcDecl, ok := decl.(*ast.FuncDecl)
|
||||
@@ -194,7 +195,7 @@ func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPat
|
||||
})
|
||||
|
||||
var recvTypeName string
|
||||
var recvType = funcDecl.Recv.List[0].Type
|
||||
recvType := funcDecl.Recv.List[0].Type
|
||||
if recvStarType, ok := recvType.(*ast.StarExpr); ok {
|
||||
recvTypeName = recvStarType.X.(*ast.Ident).Name
|
||||
} else {
|
||||
@@ -204,7 +205,7 @@ func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPat
|
||||
mm[recvTypeName] = append(mm[recvTypeName], method)
|
||||
}
|
||||
|
||||
// Combine the 2 source info models into one
|
||||
// Combine the 2 source info models into one.
|
||||
func appendSourceInfo(srcInfo1, srcInfo2 *model.SourceInfo) *model.SourceInfo {
|
||||
if srcInfo1 == nil {
|
||||
return srcInfo2
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/utils"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/token"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/revel/cmd/utils"
|
||||
)
|
||||
|
||||
// Add imports to the map from the source dir
|
||||
// Add imports to the map from the source dir.
|
||||
func addImports(imports map[string]string, decl ast.Decl, srcDir string) {
|
||||
genDecl, ok := decl.(*ast.GenDecl)
|
||||
if !ok {
|
||||
@@ -42,7 +43,6 @@ func addImports(imports map[string]string, decl ast.Decl, srcDir string) {
|
||||
// 2. Exempt the standard library; their directories always match the package name.
|
||||
// 3. Can use build.FindOnly and then use parser.ParseDir with mode PackageClauseOnly
|
||||
if pkgAlias == "" {
|
||||
|
||||
utils.Logger.Debug("Reading from build", "path", fullPath, "srcPath", srcDir, "gopath", build.Default.GOPATH)
|
||||
pkg, err := build.Import(fullPath, srcDir, 0)
|
||||
if err != nil {
|
||||
@@ -63,7 +63,7 @@ func addImports(imports map[string]string, decl ast.Decl, srcDir string) {
|
||||
}
|
||||
|
||||
// Returns a valid import string from the path
|
||||
// using the build.Defaul.GOPATH to determine the root
|
||||
// using the build.Defaul.GOPATH to determine the root.
|
||||
func importPathFromPath(root, basePath string) string {
|
||||
vendorTest := filepath.Join(basePath, "vendor")
|
||||
if len(root) > len(vendorTest) && root[:len(vendorTest)] == vendorTest {
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"github.com/revel/cmd/utils"
|
||||
)
|
||||
|
||||
// A container used to support the reflection package
|
||||
// A container used to support the reflection package.
|
||||
type processContainer struct {
|
||||
root, rootImportPath string // The paths
|
||||
paths *model.RevelContainer // The Revel paths
|
||||
@@ -54,7 +54,7 @@ func ProcessSource(paths *model.RevelContainer) (_ *model.SourceInfo, compileErr
|
||||
return pc.srcInfo, compileError
|
||||
}
|
||||
|
||||
// Called during the "walk process"
|
||||
// Called during the "walk process".
|
||||
func (pc *processContainer) processPath(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
utils.Logger.Error("Error scanning app source:", "error", err)
|
||||
@@ -84,7 +84,7 @@ func (pc *processContainer) processPath(path string, info os.FileInfo, err error
|
||||
|
||||
if err != nil {
|
||||
if errList, ok := err.(scanner.ErrorList); ok {
|
||||
var pos = errList[0].Pos
|
||||
pos := errList[0].Pos
|
||||
newError := &utils.SourceError{
|
||||
SourceType: ".go source",
|
||||
Title: "Go Compilation Error",
|
||||
@@ -114,7 +114,7 @@ func (pc *processContainer) processPath(path string, info os.FileInfo, err error
|
||||
// These cannot be included in source code that is not generated specifically as a test
|
||||
for i := range pkgs {
|
||||
if len(i) > 6 {
|
||||
if string(i[len(i)-5:]) == "_test" {
|
||||
if i[len(i)-5:] == "_test" {
|
||||
delete(pkgs, i)
|
||||
}
|
||||
}
|
||||
@@ -146,7 +146,7 @@ func (pc *processContainer) processPath(path string, info os.FileInfo, err error
|
||||
return nil
|
||||
}
|
||||
|
||||
// Process a single package within a file
|
||||
// Process a single package within a file.
|
||||
func processPackage(fset *token.FileSet, pkgImportPath, pkgPath string, pkg *ast.Package) *model.SourceInfo {
|
||||
var (
|
||||
structSpecs []*model.TypeInfo
|
||||
|
||||
@@ -67,7 +67,7 @@ var expectedValidationKeys = []map[int]string{
|
||||
},
|
||||
}
|
||||
|
||||
// This tests the recording of line number to validation key of the preceeding
|
||||
// This tests the recording of line number to validation key of the preceding
|
||||
// example source.
|
||||
func TestGetValidationKeys(t *testing.T) {
|
||||
fset := token.NewFileSet()
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
)
|
||||
|
||||
// Scan app source code for calls to X.Y(), where X is of type *Validation.
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package parser2
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/utils"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"github.com/revel/cmd/model"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"strings"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/revel/cmd/logger"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -37,7 +38,6 @@ func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *m
|
||||
log.Info("Processing package")
|
||||
for _, tree := range p.Syntax {
|
||||
for _, decl := range tree.Decls {
|
||||
|
||||
s.sourceProcessor.packageMap[p.PkgPath] = filepath.Dir(p.Fset.Position(decl.Pos()).Filename)
|
||||
if !s.addImport(decl, p, localImportMap, log) {
|
||||
continue
|
||||
@@ -85,6 +85,7 @@ func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *m
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Scan app source code for calls to X.Y(), where X is of type *Validation.
|
||||
//
|
||||
// Recognize these scenarios:
|
||||
@@ -99,7 +100,7 @@ func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *m
|
||||
//
|
||||
// The end result is that we can set the default validation key for each call to
|
||||
// be the same as the local variable.
|
||||
func (s *SourceInfoProcessor) getValidation(funcDecl *ast.FuncDecl, p *packages.Package) (map[int]string) {
|
||||
func (s *SourceInfoProcessor) getValidation(funcDecl *ast.FuncDecl, p *packages.Package) map[int]string {
|
||||
var (
|
||||
lineKeys = make(map[int]string)
|
||||
|
||||
@@ -165,8 +166,8 @@ func (s *SourceInfoProcessor) getValidation(funcDecl *ast.FuncDecl, p *packages.
|
||||
})
|
||||
|
||||
return lineKeys
|
||||
|
||||
}
|
||||
|
||||
// Check to see if there is a *revel.Validation as an argument.
|
||||
func (s *SourceInfoProcessor) getValidationParameter(funcDecl *ast.FuncDecl) *ast.Object {
|
||||
for _, field := range funcDecl.Type.Params.List {
|
||||
@@ -191,6 +192,7 @@ func (s *SourceInfoProcessor) getValidationParameter(funcDecl *ast.FuncDecl) *a
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SourceInfoProcessor) getControllerFunc(funcDecl *ast.FuncDecl, p *packages.Package, localImportMap map[string]string) (method *model.MethodSpec, recvTypeName string) {
|
||||
selExpr, ok := funcDecl.Type.Results.List[0].Type.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
@@ -274,7 +276,7 @@ func (s *SourceInfoProcessor) getControllerFunc(funcDecl *ast.FuncDecl, p *packa
|
||||
return true
|
||||
})
|
||||
|
||||
var recvType = funcDecl.Recv.List[0].Type
|
||||
recvType := funcDecl.Recv.List[0].Type
|
||||
if recvStarType, ok := recvType.(*ast.StarExpr); ok {
|
||||
recvTypeName = recvStarType.X.(*ast.Ident).Name
|
||||
} else {
|
||||
@@ -282,6 +284,7 @@ func (s *SourceInfoProcessor) getControllerFunc(funcDecl *ast.FuncDecl, p *packa
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.Package, localImportMap map[string]string) (controllerSpec *model.TypeInfo) {
|
||||
structType := spec.Type.(*ast.StructType)
|
||||
|
||||
@@ -342,9 +345,9 @@ func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.
|
||||
} else {
|
||||
var ok bool
|
||||
if importPath, ok = localImportMap[pkgName]; !ok {
|
||||
log.Debug("Debug: Unusual, failed to find package locally ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap, "usedin", )
|
||||
log.Debug("Debug: Unusual, failed to find package locally ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap, "usedin")
|
||||
if importPath, ok = s.sourceProcessor.importMap[pkgName]; !ok {
|
||||
log.Error("Error: Failed to find import path for ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap, "usedin", )
|
||||
log.Error("Error: Failed to find import path for ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap, "usedin")
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -358,6 +361,7 @@ func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.
|
||||
s.sourceProcessor.log.Info("Added controller spec", "name", controllerSpec.StructName, "package", controllerSpec.ImportPath)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *SourceInfoProcessor) getStructTypeDecl(decl ast.Decl, fset *token.FileSet) (spec *ast.TypeSpec, found bool) {
|
||||
genDecl, ok := decl.(*ast.GenDecl)
|
||||
if !ok {
|
||||
@@ -377,8 +381,8 @@ func (s *SourceInfoProcessor) getStructTypeDecl(decl ast.Decl, fset *token.FileS
|
||||
_, found = spec.Type.(*ast.StructType)
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func (s *SourceInfoProcessor) getFuncName(funcDecl *ast.FuncDecl) string {
|
||||
prefix := ""
|
||||
if funcDecl.Recv != nil {
|
||||
@@ -392,6 +396,7 @@ func (s *SourceInfoProcessor) getFuncName(funcDecl *ast.FuncDecl) string {
|
||||
}
|
||||
return prefix + funcDecl.Name.Name
|
||||
}
|
||||
|
||||
func (s *SourceInfoProcessor) addImport(decl ast.Decl, p *packages.Package, localImportMap map[string]string, log logger.MultiLogger) (shouldContinue bool) {
|
||||
shouldContinue = true
|
||||
genDecl, ok := decl.(*ast.GenDecl)
|
||||
@@ -421,7 +426,6 @@ func (s *SourceInfoProcessor) addImport(decl ast.Decl, p *packages.Package, loca
|
||||
}
|
||||
localImportMap[pkgAlias] = fullPath
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
package parser2
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/model"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"github.com/revel/cmd/utils"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"strings"
|
||||
"github.com/revel/cmd/logger"
|
||||
"go/scanner"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/scanner"
|
||||
"strings"
|
||||
|
||||
"github.com/revel/cmd/logger"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -77,7 +78,7 @@ func (s *SourceProcessor) parse() (compileError error) {
|
||||
}
|
||||
|
||||
// Using the packages.Load function load all the packages and type specifications (forces compile).
|
||||
// this sets the SourceProcessor.packageList []*packages.Package
|
||||
// this sets the SourceProcessor.packageList []*packages.Package.
|
||||
func (s *SourceProcessor) addPackages() (err error) {
|
||||
allPackages := []string{model.RevelImportPath + "/..."}
|
||||
for _, module := range s.revelContainer.ModulePathMap {
|
||||
@@ -88,8 +89,7 @@ func (s *SourceProcessor) addPackages() (err error) {
|
||||
|
||||
config := &packages.Config{
|
||||
// ode: packages.NeedSyntax | packages.NeedCompiledGoFiles,
|
||||
Mode:
|
||||
packages.NeedTypes | // For compile error
|
||||
Mode: packages.NeedTypes | // For compile error
|
||||
packages.NeedDeps | // To load dependent files
|
||||
packages.NeedName | // Loads the full package name
|
||||
packages.NeedSyntax, // To load ast tree (for end points)
|
||||
@@ -118,7 +118,7 @@ func (s *SourceProcessor) addPackages() (err error) {
|
||||
|
||||
// This callback is used to build the packages for the "app" package. This allows us to
|
||||
// parse the source files without doing a full compile on them
|
||||
// This callback only processes folders, so any files passed to this will return a nil
|
||||
// This callback only processes folders, so any files passed to this will return a nil.
|
||||
func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
s.log.Error("Error scanning app source:", "error", err)
|
||||
@@ -151,7 +151,7 @@ func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error)
|
||||
|
||||
if err != nil {
|
||||
if errList, ok := err.(scanner.ErrorList); ok {
|
||||
var pos = errList[0].Pos
|
||||
pos := errList[0].Pos
|
||||
newError := &utils.SourceError{
|
||||
SourceType: ".go source",
|
||||
Title: "Go Compilation Error",
|
||||
@@ -181,7 +181,7 @@ func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error)
|
||||
// These cannot be included in source code that is not generated specifically as a test
|
||||
for i := range pkgMap {
|
||||
if len(i) > 6 {
|
||||
if string(i[len(i) - 5:]) == "_test" {
|
||||
if i[len(i)-5:] == "_test" {
|
||||
delete(pkgMap, i)
|
||||
}
|
||||
}
|
||||
@@ -218,12 +218,11 @@ func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error)
|
||||
}
|
||||
|
||||
// This function is used to populate a map so that we can lookup controller embedded types in order to determine
|
||||
// if a Struct inherits from from revel.Controller
|
||||
// if a Struct inherits from from revel.Controller.
|
||||
func (s *SourceProcessor) addImportMap() (err error) {
|
||||
s.importMap = map[string]string{}
|
||||
s.packageMap = map[string]string{}
|
||||
for _, p := range s.packageList {
|
||||
|
||||
if len(p.Errors) > 0 {
|
||||
// Generate a compile error
|
||||
for _, e := range p.Errors {
|
||||
|
||||
@@ -9,5 +9,4 @@
|
||||
// 2. Monitor the user source and restart the program when necessary.
|
||||
//
|
||||
// Source files are generated in the app/tmp directory.
|
||||
|
||||
package proxy
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"fmt"
|
||||
"github.com/revel/cmd/harness"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
@@ -34,7 +34,7 @@ func init() {
|
||||
cmdBuild.UpdateConfig = updateBuildConfig
|
||||
}
|
||||
|
||||
// The update config updates the configuration command so that it can run
|
||||
// The update config updates the configuration command so that it can run.
|
||||
func updateBuildConfig(c *model.CommandConfig, args []string) bool {
|
||||
c.Index = model.BUILD
|
||||
if c.Build.TargetPath == "" {
|
||||
@@ -57,9 +57,8 @@ func updateBuildConfig(c *model.CommandConfig, args []string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// The main entry point to build application from command line
|
||||
// The main entry point to build application from command line.
|
||||
func buildApp(c *model.CommandConfig) (err error) {
|
||||
|
||||
appImportPath, destPath, mode := c.ImportPath, c.Build.TargetPath, DefaultRunMode
|
||||
if len(c.Build.Mode) > 0 {
|
||||
mode = c.Build.Mode
|
||||
@@ -70,7 +69,7 @@ func buildApp(c *model.CommandConfig) (err error) {
|
||||
c.Build.Mode = mode
|
||||
c.Build.ImportPath = appImportPath
|
||||
|
||||
revel_paths, err := model.NewRevelPaths(mode, appImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver))
|
||||
revelPaths, err := model.NewRevelPaths(mode, appImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -80,7 +79,7 @@ func buildApp(c *model.CommandConfig) (err error) {
|
||||
}
|
||||
|
||||
// Ensure the application can be built, this generates the main file
|
||||
app, err := harness.Build(c, revel_paths)
|
||||
app, err := harness.Build(c, revelPaths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -91,11 +90,11 @@ func buildApp(c *model.CommandConfig) (err error) {
|
||||
// - revel
|
||||
// - app
|
||||
|
||||
packageFolders, err := buildCopyFiles(c, app, revel_paths)
|
||||
packageFolders, err := buildCopyFiles(c, app, revelPaths)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = buildCopyModules(c, revel_paths, packageFolders, app)
|
||||
err = buildCopyModules(c, revelPaths, packageFolders, app)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -106,36 +105,36 @@ func buildApp(c *model.CommandConfig) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Copy the files to the target
|
||||
func buildCopyFiles(c *model.CommandConfig, app *harness.App, revel_paths *model.RevelContainer) (packageFolders []string, err error) {
|
||||
// Copy the files to the target.
|
||||
func buildCopyFiles(c *model.CommandConfig, app *harness.App, revelPaths *model.RevelContainer) (packageFolders []string, err error) {
|
||||
appImportPath, destPath := c.ImportPath, c.Build.TargetPath
|
||||
|
||||
// Revel and the app are in a directory structure mirroring import path
|
||||
srcPath := filepath.Join(destPath, "src")
|
||||
destBinaryPath := filepath.Join(destPath, filepath.Base(app.BinaryPath))
|
||||
tmpRevelPath := filepath.Join(srcPath, filepath.FromSlash(model.RevelImportPath))
|
||||
if err = utils.CopyFile(destBinaryPath, filepath.Join(revel_paths.BasePath, app.BinaryPath)); err != nil {
|
||||
if err = utils.CopyFile(destBinaryPath, filepath.Join(revelPaths.BasePath, app.BinaryPath)); err != nil {
|
||||
return
|
||||
}
|
||||
utils.MustChmod(destBinaryPath, 0755)
|
||||
|
||||
// Copy the templates from the revel
|
||||
if err = utils.CopyDir(filepath.Join(tmpRevelPath, "conf"), filepath.Join(revel_paths.RevelPath, "conf"), nil); err != nil {
|
||||
if err = utils.CopyDir(filepath.Join(tmpRevelPath, "conf"), filepath.Join(revelPaths.RevelPath, "conf"), nil); err != nil {
|
||||
return
|
||||
}
|
||||
if err = utils.CopyDir(filepath.Join(tmpRevelPath, "templates"), filepath.Join(revel_paths.RevelPath, "templates"), nil); err != nil {
|
||||
if err = utils.CopyDir(filepath.Join(tmpRevelPath, "templates"), filepath.Join(revelPaths.RevelPath, "templates"), nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Get the folders to be packaged
|
||||
packageFolders = strings.Split(revel_paths.Config.StringDefault("package.folders", "conf,public,app/views"), ",")
|
||||
packageFolders = strings.Split(revelPaths.Config.StringDefault("package.folders", "conf,public,app/views"), ",")
|
||||
for i, p := range packageFolders {
|
||||
// Clean spaces, reformat slash to filesystem
|
||||
packageFolders[i] = filepath.FromSlash(strings.TrimSpace(p))
|
||||
}
|
||||
|
||||
if c.Build.CopySource {
|
||||
err = utils.CopyDir(filepath.Join(srcPath, filepath.FromSlash(appImportPath)), revel_paths.BasePath, nil)
|
||||
err = utils.CopyDir(filepath.Join(srcPath, filepath.FromSlash(appImportPath)), revelPaths.BasePath, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -143,7 +142,7 @@ func buildCopyFiles(c *model.CommandConfig, app *harness.App, revel_paths *model
|
||||
for _, folder := range packageFolders {
|
||||
err = utils.CopyDir(
|
||||
filepath.Join(srcPath, filepath.FromSlash(appImportPath), folder),
|
||||
filepath.Join(revel_paths.BasePath, folder),
|
||||
filepath.Join(revelPaths.BasePath, folder),
|
||||
nil)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -154,11 +153,11 @@ func buildCopyFiles(c *model.CommandConfig, app *harness.App, revel_paths *model
|
||||
return
|
||||
}
|
||||
|
||||
// Based on the section copy over the build modules
|
||||
func buildCopyModules(c *model.CommandConfig, revel_paths *model.RevelContainer, packageFolders []string, app *harness.App) (err error) {
|
||||
// Based on the section copy over the build modules.
|
||||
func buildCopyModules(c *model.CommandConfig, revelPaths *model.RevelContainer, packageFolders []string, app *harness.App) (err error) {
|
||||
destPath := filepath.Join(c.Build.TargetPath, "src")
|
||||
// Find all the modules used and copy them over.
|
||||
config := revel_paths.Config.Raw()
|
||||
config := revelPaths.Config.Raw()
|
||||
|
||||
// We should only copy over the section of options what the build is targeted for
|
||||
// We will default to prod
|
||||
@@ -178,7 +177,6 @@ func buildCopyModules(c *model.CommandConfig, revel_paths *model.RevelContainer,
|
||||
continue
|
||||
}
|
||||
moduleImportList = append(moduleImportList, moduleImportPath)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +205,7 @@ func buildCopyModules(c *model.CommandConfig, revel_paths *model.RevelContainer,
|
||||
return
|
||||
}
|
||||
|
||||
// Write the run scripts for the build
|
||||
// Write the run scripts for the build.
|
||||
func buildWriteScripts(c *model.CommandConfig, app *harness.App) (err error) {
|
||||
tmplData := map[string]interface{}{
|
||||
"BinName": filepath.Base(app.BinaryPath),
|
||||
@@ -238,9 +236,8 @@ func buildWriteScripts(c *model.CommandConfig, app *harness.App) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Checks to see if the target folder exists and can be created
|
||||
// Checks to see if the target folder exists and can be created.
|
||||
func buildSafetyCheck(destPath string) error {
|
||||
|
||||
// First, verify that it is either already empty or looks like a previous
|
||||
// build (to avoid clobbering anything)
|
||||
if utils.Exists(destPath) && !utils.Empty(destPath) && !utils.Exists(filepath.Join(destPath, "run.sh")) {
|
||||
@@ -262,6 +259,7 @@ const PACKAGE_RUN_SH = `#!/bin/sh
|
||||
SCRIPTPATH=$(cd "$(dirname "$0")"; pwd)
|
||||
"$SCRIPTPATH/{{.BinName}}" -importPath {{.ImportPath}} -srcPath "$SCRIPTPATH/src" -runMode {{.Mode}}
|
||||
`
|
||||
|
||||
const PACKAGE_RUN_BAT = `@echo off
|
||||
|
||||
{{.BinName}} -importPath {{.ImportPath}} -srcPath "%CD%\src" -runMode {{.Mode}}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// test the commands
|
||||
// test the commands.
|
||||
func TestBuild(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
gopath := setup("revel-test-build", a)
|
||||
|
||||
@@ -6,11 +6,11 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
)
|
||||
|
||||
var cmdClean = &Command{
|
||||
@@ -34,7 +34,7 @@ func init() {
|
||||
cmdClean.RunWith = cleanApp
|
||||
}
|
||||
|
||||
// Update the clean command configuration, using old method
|
||||
// Update the clean command configuration, using old method.
|
||||
func updateCleanConfig(c *model.CommandConfig, args []string) bool {
|
||||
c.Index = model.CLEAN
|
||||
if len(args) == 0 && c.Clean.ImportPath != "" {
|
||||
@@ -48,9 +48,8 @@ func updateCleanConfig(c *model.CommandConfig, args []string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Clean the source directory of generated files
|
||||
// Clean the source directory of generated files.
|
||||
func cleanApp(c *model.CommandConfig) (err error) {
|
||||
|
||||
purgeDirs := []string{
|
||||
filepath.Join(c.AppPath, "app", "tmp"),
|
||||
filepath.Join(c.AppPath, "app", "routes"),
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/revel"
|
||||
"github.com/revel/cmd/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
main "github.com/revel/cmd/revel"
|
||||
"github.com/revel/cmd/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// test the commands
|
||||
// test the commands.
|
||||
func TestClean(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
gopath := setup("revel-test-clean", a)
|
||||
|
||||
|
||||
t.Run("Clean", func(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
c := newApp("clean-test", model.NEW, nil, a)
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/logger"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"fmt"
|
||||
|
||||
"github.com/revel/cmd/logger"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// Test that the event handler can be attached and it dispatches the event received
|
||||
func setup(suffix string, a *assert.Assertions) (string) {
|
||||
// Test that the event handler can be attached and it dispatches the event received.
|
||||
func setup(suffix string, a *assert.Assertions) string {
|
||||
temp := os.TempDir()
|
||||
wd, _ := os.Getwd()
|
||||
utils.InitLogger(wd, logger.LvlInfo)
|
||||
@@ -43,7 +44,7 @@ func setup(suffix string, a *assert.Assertions) (string) {
|
||||
return gopath
|
||||
}
|
||||
|
||||
// Create a new app for the name
|
||||
// Create a new app for the name.
|
||||
func newApp(name string, command model.COMMAND, precall func(c *model.CommandConfig), a *assert.Assertions) *model.CommandConfig {
|
||||
c := &model.CommandConfig{Vendored: true}
|
||||
switch command {
|
||||
@@ -62,7 +63,6 @@ func newApp(name string, command model.COMMAND, precall func(c *model.CommandCon
|
||||
getOutput, _ = goModCmd.CombinedOutput()
|
||||
fmt.Printf("Calling go mod edit %v", string(getOutput))
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
case model.BUILD:
|
||||
|
||||
137
revel/new.go
137
revel/new.go
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"go/build"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -15,7 +16,6 @@ import (
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
var cmdNew = &Command{
|
||||
@@ -43,7 +43,7 @@ func init() {
|
||||
cmdNew.UpdateConfig = updateNewConfig
|
||||
}
|
||||
|
||||
// Called when unable to parse the command line automatically and assumes an old launch
|
||||
// Called when unable to parse the command line automatically and assumes an old launch.
|
||||
func updateNewConfig(c *model.CommandConfig, args []string) bool {
|
||||
c.Index = model.NEW
|
||||
if len(c.New.Package) > 0 {
|
||||
@@ -64,10 +64,9 @@ func updateNewConfig(c *model.CommandConfig, args []string) bool {
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
// Call to create a new application
|
||||
// Call to create a new application.
|
||||
func newApp(c *model.CommandConfig) (err error) {
|
||||
// Check for an existing folder so we don't clobber it
|
||||
_, err = build.Import(c.ImportPath, "", build.FindOnly)
|
||||
@@ -124,7 +123,6 @@ func newApp(c *model.CommandConfig) (err error) {
|
||||
}
|
||||
|
||||
func createModVendor(c *model.CommandConfig) (err error) {
|
||||
|
||||
utils.Logger.Info("Creating a new mod app")
|
||||
goModCmd := exec.Command("go", "mod", "init", filepath.Join(c.New.Package, c.AppName))
|
||||
|
||||
@@ -141,69 +139,21 @@ func createModVendor(c *model.CommandConfig) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func createDepVendor(c *model.CommandConfig) (err error) {
|
||||
|
||||
utils.Logger.Info("Creating a new vendor app")
|
||||
|
||||
vendorPath := filepath.Join(c.AppPath, "vendor")
|
||||
if !utils.DirExists(vendorPath) {
|
||||
|
||||
if err := os.MkdirAll(vendorPath, os.ModePerm); err != nil {
|
||||
return utils.NewBuildError("Failed to create " + vendorPath, "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
// In order for dep to run there needs to be a source file in the folder
|
||||
tempPath := filepath.Join(c.AppPath, "tmp")
|
||||
utils.Logger.Info("Checking for temp folder for source code", "path", tempPath)
|
||||
if !utils.DirExists(tempPath) {
|
||||
if err := os.MkdirAll(tempPath, os.ModePerm); err != nil {
|
||||
return utils.NewBuildIfError(err, "Failed to create " + vendorPath)
|
||||
}
|
||||
|
||||
if err = utils.GenerateTemplate(filepath.Join(tempPath, "main.go"), NEW_MAIN_FILE, nil); err != nil {
|
||||
return utils.NewBuildIfError(err, "Failed to create main file " + vendorPath)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a package template file if it does not exist
|
||||
packageFile := filepath.Join(c.AppPath, "Gopkg.toml")
|
||||
utils.Logger.Info("Checking for Gopkg.toml", "path", packageFile)
|
||||
if !utils.Exists(packageFile) {
|
||||
utils.Logger.Info("Generating Gopkg.toml", "path", packageFile)
|
||||
if err := utils.GenerateTemplate(packageFile, VENDOR_GOPKG, nil); err != nil {
|
||||
return utils.NewBuildIfError(err, "Failed to generate template")
|
||||
}
|
||||
} else {
|
||||
utils.Logger.Info("Package file exists in skeleto, skipping adding")
|
||||
}
|
||||
|
||||
getCmd := exec.Command("dep", "ensure", "-v")
|
||||
utils.CmdInit(getCmd, !c.Vendored, c.AppPath)
|
||||
|
||||
utils.Logger.Info("Exec:", "args", getCmd.Args, "env", getCmd.Env, "workingdir", getCmd.Dir)
|
||||
getOutput, err := getCmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return utils.NewBuildIfError(err, string(getOutput))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Used to generate a new secret key
|
||||
// Used to generate a new secret key.
|
||||
const alphaNumeric = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
||||
// Generate a secret key
|
||||
// Generate a secret key.
|
||||
func generateSecret() string {
|
||||
chars := make([]byte, 64)
|
||||
for i := 0; i < 64; i++ {
|
||||
chars[i] = alphaNumeric[rand.Intn(len(alphaNumeric))]
|
||||
}
|
||||
|
||||
return string(chars)
|
||||
}
|
||||
|
||||
// Sets the applicaiton path
|
||||
// Sets the application path.
|
||||
func setApplicationPath(c *model.CommandConfig) (err error) {
|
||||
|
||||
// revel/revel#1014 validate relative path, we cannot use built-in functions
|
||||
// since Go import path is valid relative path too.
|
||||
// so check basic part of the path, which is "."
|
||||
@@ -216,7 +166,7 @@ func setApplicationPath(c *model.CommandConfig) (err error) {
|
||||
}
|
||||
_, err = build.Import(model.RevelImportPath, "", build.FindOnly)
|
||||
if err != nil {
|
||||
//// Go get the revel project
|
||||
// Go get the revel project
|
||||
err = c.PackageResolver(model.RevelImportPath)
|
||||
if err != nil {
|
||||
return utils.NewBuildIfError(err, "Failed to fetch revel "+model.RevelImportPath)
|
||||
@@ -229,7 +179,7 @@ func setApplicationPath(c *model.CommandConfig) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set the skeleton path
|
||||
// Set the skeleton path.
|
||||
func setSkeletonPath(c *model.CommandConfig) (err error) {
|
||||
if len(c.New.SkeletonPath) == 0 {
|
||||
c.New.SkeletonPath = "https://" + RevelSkeletonsImportPath + ":basic/bootstrap4"
|
||||
@@ -256,7 +206,7 @@ func setSkeletonPath(c *model.CommandConfig) (err error) {
|
||||
c.New.SkeletonPath = fullpath
|
||||
utils.Logger.Info("Set skeleton path to ", fullpath)
|
||||
if !utils.DirExists(fullpath) {
|
||||
return fmt.Errorf("Failed to find skeleton in filepath %s %s", fullpath, sp.String())
|
||||
return fmt.Errorf("failed to find skeleton in filepath %s %s", fullpath, sp.String())
|
||||
}
|
||||
case "git":
|
||||
fallthrough
|
||||
@@ -268,7 +218,6 @@ func setSkeletonPath(c *model.CommandConfig) (err error) {
|
||||
}
|
||||
default:
|
||||
utils.Logger.Fatal("Unsupported skeleton schema ", "path", c.New.SkeletonPath)
|
||||
|
||||
}
|
||||
// TODO check to see if the path needs to be extracted
|
||||
} else {
|
||||
@@ -277,7 +226,7 @@ func setSkeletonPath(c *model.CommandConfig) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Load skeleton from git
|
||||
// Load skeleton from git.
|
||||
func newLoadFromGit(c *model.CommandConfig, sp *url.URL) (err error) {
|
||||
// This method indicates we need to fetch from a repository using git
|
||||
// Execute "git clone get <pkg>"
|
||||
@@ -323,68 +272,4 @@ func copyNewAppFiles(c *model.CommandConfig) (err error) {
|
||||
// Dotfiles are skipped by mustCopyDir, so we have to explicitly copy the .gitignore.
|
||||
gitignore := ".gitignore"
|
||||
return utils.CopyFile(filepath.Join(c.AppPath, gitignore), filepath.Join(c.New.SkeletonPath, gitignore))
|
||||
|
||||
}
|
||||
|
||||
const (
|
||||
VENDOR_GOPKG = `#
|
||||
# Revel Gopkg.toml
|
||||
#
|
||||
# If you want to use a specific version of Revel change the branches below
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
required = ["github.com/revel/revel", "github.com/revel/modules"]
|
||||
|
||||
# Note to use a specific version changes this to
|
||||
#
|
||||
# [[override]]
|
||||
# version = "0.20.1"
|
||||
# name = "github.com/revel/modules"
|
||||
|
||||
[[override]]
|
||||
branch = "master"
|
||||
name = "github.com/revel/modules"
|
||||
|
||||
# Note to use a specific version changes this to
|
||||
#
|
||||
# [[override]]
|
||||
# version = "0.20.0"
|
||||
# name = "github.com/revel/revel"
|
||||
[[override]]
|
||||
branch = "master"
|
||||
name = "github.com/revel/revel"
|
||||
|
||||
[[override]]
|
||||
branch = "master"
|
||||
name = "github.com/revel/log15"
|
||||
|
||||
[[override]]
|
||||
branch = "master"
|
||||
name = "github.com/revel/cron"
|
||||
|
||||
[[override]]
|
||||
branch = "master"
|
||||
name = "github.com/xeonx/timeago"
|
||||
|
||||
`
|
||||
NEW_MAIN_FILE = `package main
|
||||
|
||||
`
|
||||
)
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/revel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
main "github.com/revel/cmd/revel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// test the commands
|
||||
// test the commands.
|
||||
func TestNew(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
gopath := setup("revel-test-new", a)
|
||||
@@ -52,4 +53,3 @@ func TestNew(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ func init() {
|
||||
cmdPackage.UpdateConfig = updatePackageConfig
|
||||
}
|
||||
|
||||
// Called when unable to parse the command line automatically and assumes an old launch
|
||||
// Called when unable to parse the command line automatically and assumes an old launch.
|
||||
func updatePackageConfig(c *model.CommandConfig, args []string) bool {
|
||||
c.Index = model.PACKAGE
|
||||
if len(args) == 0 && c.Package.ImportPath != "" {
|
||||
@@ -48,26 +48,21 @@ func updatePackageConfig(c *model.CommandConfig, args []string) bool {
|
||||
c.Package.Mode = args[1]
|
||||
}
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
// Called to package the app
|
||||
// Called to package the app.
|
||||
func packageApp(c *model.CommandConfig) (err error) {
|
||||
|
||||
// Determine the run mode.
|
||||
mode := DefaultRunMode
|
||||
if len(c.Package.Mode) >= 0 {
|
||||
mode = c.Package.Mode
|
||||
}
|
||||
mode := c.Package.Mode
|
||||
|
||||
appImportPath := c.ImportPath
|
||||
revel_paths, err := model.NewRevelPaths(mode, appImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver))
|
||||
revelPaths, err := model.NewRevelPaths(mode, appImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Remove the archive if it already exists.
|
||||
destFile := filepath.Join(c.AppPath, filepath.Base(revel_paths.BasePath)+".tar.gz")
|
||||
destFile := filepath.Join(c.AppPath, filepath.Base(revelPaths.BasePath)+".tar.gz")
|
||||
if c.Package.TargetPath != "" {
|
||||
if filepath.IsAbs(c.Package.TargetPath) {
|
||||
destFile = c.Package.TargetPath
|
||||
@@ -80,13 +75,11 @@ func packageApp(c *model.CommandConfig) (err error) {
|
||||
}
|
||||
|
||||
// Collect stuff in a temp directory.
|
||||
tmpDir, err := ioutil.TempDir("", filepath.Base(revel_paths.BasePath))
|
||||
tmpDir, err := ioutil.TempDir("", filepath.Base(revelPaths.BasePath))
|
||||
utils.PanicOnError(err, "Failed to get temp dir")
|
||||
|
||||
// Build expects the command the build to contain the proper data
|
||||
if len(c.Package.Mode) >= 0 {
|
||||
c.Build.Mode = c.Package.Mode
|
||||
}
|
||||
c.Build.TargetPath = tmpDir
|
||||
c.Build.CopySource = c.Package.CopySource
|
||||
if err = buildApp(c); err != nil {
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/revel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
main "github.com/revel/cmd/revel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// test the commands
|
||||
// test the commands.
|
||||
func TestPackage(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
gopath := setup("revel-test-package", a)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
@@ -14,23 +15,18 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jessevdk/go-flags"
|
||||
|
||||
"github.com/agtorre/gocolorize"
|
||||
"github.com/jessevdk/go-flags"
|
||||
"github.com/revel/cmd/logger"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
const (
|
||||
// RevelCmdImportPath Revel framework cmd tool import path
|
||||
RevelCmdImportPath = "github.com/revel/cmd"
|
||||
|
||||
// RevelCmdImportPath Revel framework cmd tool import path
|
||||
// RevelCmdImportPath Revel framework cmd tool import path.
|
||||
RevelSkeletonsImportPath = "github.com/revel/skeletons"
|
||||
|
||||
// DefaultRunMode for revel's application
|
||||
// DefaultRunMode for revel's application.
|
||||
DefaultRunMode = "dev"
|
||||
)
|
||||
|
||||
@@ -41,7 +37,7 @@ type Command struct {
|
||||
UsageLine, Short, Long string
|
||||
}
|
||||
|
||||
// Name returns command name from usage line
|
||||
// Name returns command name from usage line.
|
||||
func (cmd *Command) Name() string {
|
||||
name := cmd.UsageLine
|
||||
i := strings.Index(name, " ")
|
||||
@@ -51,7 +47,7 @@ func (cmd *Command) Name() string {
|
||||
return name
|
||||
}
|
||||
|
||||
// The commands
|
||||
// Commands defines the available commands.
|
||||
var Commands = []*Command{
|
||||
nil, // Safety net, prevent missing index from running
|
||||
cmdNew,
|
||||
@@ -109,7 +105,7 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the arguments passed into the model.CommandConfig
|
||||
// Parse the arguments passed into the model.CommandConfig.
|
||||
func ParseArgs(c *model.CommandConfig, parser *flags.Parser, args []string) (err error) {
|
||||
var extraArgs []string
|
||||
if ini := flag.String("ini", "none", ""); *ini != "none" {
|
||||
@@ -119,7 +115,8 @@ func ParseArgs(c *model.CommandConfig, parser *flags.Parser, args []string) (err
|
||||
} else {
|
||||
if extraArgs, err = parser.ParseArgs(args); err != nil {
|
||||
return
|
||||
} else {
|
||||
}
|
||||
|
||||
switch parser.Active.Name {
|
||||
case "new":
|
||||
c.Index = model.NEW
|
||||
@@ -137,12 +134,11 @@ func ParseArgs(c *model.CommandConfig, parser *flags.Parser, args []string) (err
|
||||
c.Index = model.VERSION
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !Commands[c.Index].UpdateConfig(c, extraArgs) {
|
||||
buffer := &bytes.Buffer{}
|
||||
parser.WriteHelp(buffer)
|
||||
err = fmt.Errorf("Invalid command line arguements %v\n%s", extraArgs, buffer.String())
|
||||
err = fmt.Errorf("invalid command line arguments %v\n%s", extraArgs, buffer.String())
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
40
revel/run.go
40
revel/run.go
@@ -5,13 +5,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/revel/cmd/harness"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"os"
|
||||
)
|
||||
|
||||
var cmdRun = &Command{
|
||||
@@ -34,13 +35,6 @@ You can set a port as well. For example:
|
||||
revel run -m prod -p 8080 github.com/revel/examples/chat `,
|
||||
}
|
||||
|
||||
// RunArgs holds revel run parameters
|
||||
type RunArgs struct {
|
||||
ImportPath string
|
||||
Mode string
|
||||
Port int
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRun.RunWith = runApp
|
||||
cmdRun.UpdateConfig = updateRunConfig
|
||||
@@ -112,55 +106,55 @@ func updateRunConfig(c *model.CommandConfig, args []string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Returns true if this is an absolute path or a relative gopath
|
||||
// Returns true if this is an absolute path or a relative gopath.
|
||||
func runIsImportPath(pathToCheck string) bool {
|
||||
return utils.DirExists(pathToCheck)
|
||||
}
|
||||
|
||||
// Called to run the app
|
||||
// Called to run the app.
|
||||
func runApp(c *model.CommandConfig) (err error) {
|
||||
if c.Run.Mode == "" {
|
||||
c.Run.Mode = "dev"
|
||||
}
|
||||
|
||||
revel_path, err := model.NewRevelPaths(c.Run.Mode, c.ImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver))
|
||||
revelPath, err := model.NewRevelPaths(c.Run.Mode, c.ImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver))
|
||||
if err != nil {
|
||||
return utils.NewBuildIfError(err, "Revel paths")
|
||||
}
|
||||
if c.Run.Port > -1 {
|
||||
revel_path.HTTPPort = c.Run.Port
|
||||
revelPath.HTTPPort = c.Run.Port
|
||||
} else {
|
||||
c.Run.Port = revel_path.HTTPPort
|
||||
c.Run.Port = revelPath.HTTPPort
|
||||
}
|
||||
|
||||
utils.Logger.Infof("Running %s (%s) in %s mode\n", revel_path.AppName, revel_path.ImportPath, revel_path.RunMode)
|
||||
utils.Logger.Debug("Base path:", "path", revel_path.BasePath)
|
||||
utils.Logger.Infof("Running %s (%s) in %s mode\n", revelPath.AppName, revelPath.ImportPath, revelPath.RunMode)
|
||||
utils.Logger.Debug("Base path:", "path", revelPath.BasePath)
|
||||
|
||||
// If the app is run in "watched" mode, use the harness to run it.
|
||||
if revel_path.Config.BoolDefault("watch", true) && revel_path.Config.BoolDefault("watch.code", true) {
|
||||
if revelPath.Config.BoolDefault("watch", true) && revelPath.Config.BoolDefault("watch.code", true) {
|
||||
utils.Logger.Info("Running in watched mode.")
|
||||
runMode := fmt.Sprintf(`{"mode":"%s", "specialUseFlag":%v}`, revel_path.RunMode, c.Verbose)
|
||||
runMode := fmt.Sprintf(`{"mode":"%s", "specialUseFlag":%v}`, revelPath.RunMode, c.Verbose)
|
||||
if c.HistoricMode {
|
||||
runMode = revel_path.RunMode
|
||||
runMode = revelPath.RunMode
|
||||
}
|
||||
// **** Never returns.
|
||||
harness.NewHarness(c, revel_path, runMode, c.Run.NoProxy).Run()
|
||||
harness.NewHarness(c, revelPath, runMode, c.Run.NoProxy).Run()
|
||||
}
|
||||
|
||||
// Else, just build and run the app.
|
||||
utils.Logger.Debug("Running in live build mode.")
|
||||
app, err := harness.Build(c, revel_path)
|
||||
app, err := harness.Build(c, revelPath)
|
||||
if err != nil {
|
||||
utils.Logger.Errorf("Failed to build app: %s", err)
|
||||
}
|
||||
app.Port = revel_path.HTTPPort
|
||||
app.Port = revelPath.HTTPPort
|
||||
var paths []byte
|
||||
if len(app.PackagePathMap) > 0 {
|
||||
paths, _ = json.Marshal(app.PackagePathMap)
|
||||
}
|
||||
runMode := fmt.Sprintf(`{"mode":"%s", "specialUseFlag":%v,"packagePathMap":%s}`, app.Paths.RunMode, c.Verbose, string(paths))
|
||||
if c.HistoricMode {
|
||||
runMode = revel_path.RunMode
|
||||
runMode = revelPath.RunMode
|
||||
}
|
||||
app.Cmd(runMode).Run(c)
|
||||
return
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// test the commands
|
||||
// test the commands.
|
||||
func TestRun(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
gopath := setup("revel-test-run", a)
|
||||
|
||||
@@ -52,7 +52,7 @@ func init() {
|
||||
cmdTest.UpdateConfig = updateTestConfig
|
||||
}
|
||||
|
||||
// Called to update the config command with from the older stype
|
||||
// Called to update the config command with from the older stype.
|
||||
func updateTestConfig(c *model.CommandConfig, args []string) bool {
|
||||
c.Index = model.TEST
|
||||
if len(args) == 0 && c.Test.ImportPath != "" {
|
||||
@@ -74,7 +74,7 @@ func updateTestConfig(c *model.CommandConfig, args []string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Called to test the application
|
||||
// Called to test the application.
|
||||
func testApp(c *model.CommandConfig) (err error) {
|
||||
mode := DefaultRunMode
|
||||
if c.Test.Mode != "" {
|
||||
@@ -82,7 +82,7 @@ func testApp(c *model.CommandConfig) (err error) {
|
||||
}
|
||||
|
||||
// Find and parse app.conf
|
||||
revel_path, err := model.NewRevelPaths(mode, c.ImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver))
|
||||
revelPath, err := model.NewRevelPaths(mode, c.ImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -90,7 +90,7 @@ func testApp(c *model.CommandConfig) (err error) {
|
||||
// todo Ensure that the testrunner is loaded in this mode.
|
||||
|
||||
// Create a directory to hold the test result files.
|
||||
resultPath := filepath.Join(revel_path.BasePath, "test-results")
|
||||
resultPath := filepath.Join(revelPath.BasePath, "test-results")
|
||||
if err = os.RemoveAll(resultPath); err != nil {
|
||||
return utils.NewBuildError("Failed to remove test result directory ", "path", resultPath, "error", err)
|
||||
}
|
||||
@@ -104,7 +104,7 @@ func testApp(c *model.CommandConfig) (err error) {
|
||||
return utils.NewBuildError("Failed to create test result log file: ", "error", err)
|
||||
}
|
||||
|
||||
app, reverr := harness.Build(c, revel_path)
|
||||
app, reverr := harness.Build(c, revelPath)
|
||||
if reverr != nil {
|
||||
return utils.NewBuildIfError(reverr, "Error building: ")
|
||||
}
|
||||
@@ -128,20 +128,20 @@ func testApp(c *model.CommandConfig) (err error) {
|
||||
}
|
||||
defer cmd.Kill()
|
||||
|
||||
var httpAddr = revel_path.HTTPAddr
|
||||
httpAddr := revelPath.HTTPAddr
|
||||
if httpAddr == "" {
|
||||
httpAddr = "localhost"
|
||||
}
|
||||
|
||||
var httpProto = "http"
|
||||
if revel_path.HTTPSsl {
|
||||
httpProto := "http"
|
||||
if revelPath.HTTPSsl {
|
||||
httpProto = "https"
|
||||
}
|
||||
|
||||
// Get a list of tests
|
||||
var baseURL = fmt.Sprintf("%s://%s:%d", httpProto, httpAddr, revel_path.HTTPPort)
|
||||
baseURL := fmt.Sprintf("%s://%s:%d", httpProto, httpAddr, revelPath.HTTPPort)
|
||||
|
||||
utils.Logger.Infof("Testing %s (%s) in %s mode URL %s \n", revel_path.AppName, revel_path.ImportPath, mode, baseURL)
|
||||
utils.Logger.Infof("Testing %s (%s) in %s mode URL %s \n", revelPath.AppName, revelPath.ImportPath, mode, baseURL)
|
||||
testSuites, _ := getTestsList(baseURL)
|
||||
|
||||
// If a specific TestSuite[.Method] is specified, only run that suite/test
|
||||
@@ -154,7 +154,7 @@ func testApp(c *model.CommandConfig) (err error) {
|
||||
fmt.Println()
|
||||
|
||||
// Run each suite.
|
||||
failedResults, overallSuccess := runTestSuites(revel_path, baseURL, resultPath, testSuites)
|
||||
failedResults, overallSuccess := runTestSuites(revelPath, baseURL, resultPath, testSuites)
|
||||
|
||||
fmt.Println()
|
||||
if overallSuccess {
|
||||
@@ -177,14 +177,14 @@ func testApp(c *model.CommandConfig) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Outputs the results to a file
|
||||
// Outputs the results to a file.
|
||||
func writeResultFile(resultPath, name, content string) {
|
||||
if err := ioutil.WriteFile(filepath.Join(resultPath, name), []byte(content), 0666); err != nil {
|
||||
utils.Logger.Errorf("Failed to write result file %s: %s", filepath.Join(resultPath, name), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Determines if response should be plural
|
||||
// Determines if response should be plural.
|
||||
func pluralize(num int, singular, plural string) string {
|
||||
if num == 1 {
|
||||
return singular
|
||||
@@ -193,7 +193,7 @@ func pluralize(num int, singular, plural string) string {
|
||||
}
|
||||
|
||||
// Filters test suites and individual tests to match
|
||||
// the parsed command line parameter
|
||||
// the parsed command line parameter.
|
||||
func filterTestSuites(suites *[]tests.TestSuiteDesc, suiteArgument string) *[]tests.TestSuiteDesc {
|
||||
var suiteName, testName string
|
||||
argArray := strings.Split(suiteArgument, ".")
|
||||
@@ -263,9 +263,8 @@ func getTestsList(baseURL string) (*[]tests.TestSuiteDesc, error) {
|
||||
return &testSuites, err
|
||||
}
|
||||
|
||||
// Run the testsuites using the container
|
||||
// Run the testsuites using the container.
|
||||
func runTestSuites(paths *model.RevelContainer, baseURL, resultPath string, testSuites *[]tests.TestSuiteDesc) (*[]tests.TestSuiteResult, bool) {
|
||||
|
||||
// We can determine the testsuite location by finding the test module and extracting the data from it
|
||||
resultFilePath := filepath.Join(paths.ModulePathMap["testrunner"].Path, "app", "views", "TestRunner/SuiteResult.html")
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/revel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
main "github.com/revel/cmd/revel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
||||
// test the commands
|
||||
// test the commands.
|
||||
func TestRevelTest(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
gopath := setup("revel-test-test", a)
|
||||
|
||||
@@ -9,11 +9,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/revel/cmd"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
@@ -23,11 +20,14 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"bytes"
|
||||
|
||||
"github.com/revel/cmd"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
)
|
||||
|
||||
type (
|
||||
// The version container
|
||||
// The version container.
|
||||
VersionCommand struct {
|
||||
Command *model.CommandConfig // The command
|
||||
revelVersion *model.Version // The Revel framework version
|
||||
@@ -54,7 +54,7 @@ func init() {
|
||||
cmdVersion.RunWith = v.RunWith
|
||||
}
|
||||
|
||||
// Update the version
|
||||
// Update the version.
|
||||
func (v *VersionCommand) UpdateConfig(c *model.CommandConfig, args []string) bool {
|
||||
if len(args) > 0 {
|
||||
c.Version.ImportPath = args[0]
|
||||
@@ -62,7 +62,7 @@ func (v *VersionCommand) UpdateConfig(c *model.CommandConfig, args []string) boo
|
||||
return true
|
||||
}
|
||||
|
||||
// Displays the version of go and Revel
|
||||
// Displays the version of go and Revel.
|
||||
func (v *VersionCommand) RunWith(c *model.CommandConfig) (err error) {
|
||||
utils.Logger.Info("Requesting version information", "config", c)
|
||||
v.Command = c
|
||||
@@ -73,7 +73,6 @@ func (v *VersionCommand) RunWith(c *model.CommandConfig) (err error) {
|
||||
needsUpdates := true
|
||||
versionInfo := ""
|
||||
for x := 0; x < 2 && needsUpdates; x++ {
|
||||
needsUpdates = false
|
||||
versionInfo, needsUpdates = v.doRepoCheck(x == 0)
|
||||
}
|
||||
|
||||
@@ -89,7 +88,7 @@ func (v *VersionCommand) RunWith(c *model.CommandConfig) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Checks the Revel repos for the latest version
|
||||
// Checks the Revel repos for the latest version.
|
||||
func (v *VersionCommand) doRepoCheck(updateLibs bool) (versionInfo string, needsUpdate bool) {
|
||||
var (
|
||||
title string
|
||||
@@ -110,25 +109,12 @@ func (v *VersionCommand) doRepoCheck(updateLibs bool) (versionInfo string, needs
|
||||
}
|
||||
|
||||
// Only do an update on the first loop, and if specified to update
|
||||
versionInfo = versionInfo + v.outputVersion(title, repo, localVersion, versonFromRepo)
|
||||
versionInfo += v.outputVersion(title, repo, localVersion, versonFromRepo)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Checks for updates if needed
|
||||
func (v *VersionCommand) doUpdate(title, repo string, local, remote *model.Version) {
|
||||
utils.Logger.Info("Updating package", "package", title, "repo", repo)
|
||||
fmt.Println("Attempting to update package", title)
|
||||
if err := v.Command.PackageResolver(repo); err != nil {
|
||||
utils.Logger.Error("Unable to update repo", "repo", repo, "error", err)
|
||||
} else if repo == "github.com/revel/cmd/revel" {
|
||||
// One extra step required here to run the install for the command
|
||||
utils.Logger.Fatal("Revel command tool was updated, you must manually run the following command before continuing\ngo install github.com/revel/cmd/revel")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Prints out the local and remote versions, calls update if needed
|
||||
// Prints out the local and remote versions, calls update if needed.
|
||||
func (v *VersionCommand) outputVersion(title, repo string, local, remote *model.Version) (output string) {
|
||||
buffer := &bytes.Buffer{}
|
||||
remoteVersion := "Unknown"
|
||||
@@ -144,7 +130,7 @@ func (v *VersionCommand) outputVersion(title, repo string, local, remote *model.
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// Returns the version from the repository
|
||||
// Returns the version from the repository.
|
||||
func (v *VersionCommand) versionFromRepo(repoName, branchName, fileName string) (version *model.Version, err error) {
|
||||
if branchName == "" {
|
||||
branchName = "master"
|
||||
@@ -166,10 +152,6 @@ func (v *VersionCommand) versionFromRepo(repoName, branchName, fileName string)
|
||||
return v.versionFromBytes(body)
|
||||
}
|
||||
|
||||
// Returns version information from a file called version on the gopath
|
||||
func (v *VersionCommand) compareAndUpdateVersion(remoteVersion *model.Version, localVersion *model.Version) (err error) {
|
||||
return
|
||||
}
|
||||
func (v *VersionCommand) versionFromFilepath(sourcePath string) (version *model.Version, err error) {
|
||||
utils.Logger.Info("Fullpath to revel", "dir", sourcePath)
|
||||
|
||||
@@ -180,7 +162,7 @@ func (v *VersionCommand) versionFromFilepath(sourcePath string) (version *model.
|
||||
return v.versionFromBytes(sourceStream)
|
||||
}
|
||||
|
||||
// Returns version information from a file called version on the gopath
|
||||
// Returns version information from a file called version on the gopath.
|
||||
func (v *VersionCommand) versionFromBytes(sourceStream []byte) (version *model.Version, err error) {
|
||||
fset := token.NewFileSet() // positions are relative to fset
|
||||
|
||||
@@ -206,7 +188,7 @@ func (v *VersionCommand) versionFromBytes(sourceStream []byte) (version *model.V
|
||||
r := spec.Values[0].(*ast.BasicLit)
|
||||
switch spec.Names[0].Name {
|
||||
case "Version":
|
||||
version.ParseVersion(strings.Replace(r.Value, `"`, "", -1))
|
||||
version.ParseVersion(strings.ReplaceAll(r.Value, `"`, ""))
|
||||
case "BuildDate":
|
||||
version.BuildDate = r.Value
|
||||
case "MinimumGoVersion":
|
||||
@@ -217,7 +199,7 @@ func (v *VersionCommand) versionFromBytes(sourceStream []byte) (version *model.V
|
||||
return
|
||||
}
|
||||
|
||||
// Fetch the local version of revel from the file system
|
||||
// Fetch the local version of revel from the file system.
|
||||
func (v *VersionCommand) updateLocalVersions() {
|
||||
v.cmdVersion = &model.Version{}
|
||||
v.cmdVersion.ParseVersion(cmd.Version)
|
||||
@@ -243,6 +225,4 @@ func (v *VersionCommand) updateLocalVersions() {
|
||||
if err != nil {
|
||||
utils.Logger.Warn("Unable to extract version information from Revel Modules", "path", pathMap[model.RevelModulesImportPath], "error", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/revel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
main "github.com/revel/cmd/revel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// test the commands
|
||||
// test the commands.
|
||||
func TestVersion(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
gopath := setup("revel-test-version", a)
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/revel/cmd/utils"
|
||||
)
|
||||
|
||||
// TestSuiteDesc is used for storing information about a single test suite.
|
||||
@@ -46,111 +42,3 @@ type TestResult struct {
|
||||
ErrorHTML template.HTML
|
||||
ErrorSummary string
|
||||
}
|
||||
|
||||
var (
|
||||
testSuites []TestSuiteDesc // A list of all available tests.
|
||||
|
||||
none = []reflect.Value{} // It is used as input for reflect call in a few places.
|
||||
|
||||
// registeredTests simplifies the search of test suites by their name.
|
||||
// "TestSuite.TestName" is used as a key. Value represents index in testSuites.
|
||||
registeredTests map[string]int
|
||||
)
|
||||
|
||||
/*
|
||||
Below are helper functions.
|
||||
*/
|
||||
|
||||
// describeSuite expects testsuite interface as input parameter
|
||||
// and returns its description in a form of TestSuiteDesc structure.
|
||||
func describeSuite(testSuite interface{}) TestSuiteDesc {
|
||||
t := reflect.TypeOf(testSuite)
|
||||
|
||||
// Get a list of methods of the embedded test type.
|
||||
// It will be used to make sure the same tests are not included in multiple test suites.
|
||||
super := t.Elem().Field(0).Type
|
||||
superMethods := map[string]bool{}
|
||||
for i := 0; i < super.NumMethod(); i++ {
|
||||
// Save the current method's name.
|
||||
superMethods[super.Method(i).Name] = true
|
||||
}
|
||||
|
||||
// Get a list of methods on the test suite that take no parameters, return
|
||||
// no results, and were not part of the embedded type's method set.
|
||||
var tests []TestDesc
|
||||
for i := 0; i < t.NumMethod(); i++ {
|
||||
m := t.Method(i)
|
||||
mt := m.Type
|
||||
|
||||
// Make sure the test method meets the criterias:
|
||||
// - method of testSuite without input parameters;
|
||||
// - nothing is returned;
|
||||
// - has "Test" prefix;
|
||||
// - doesn't belong to the embedded structure.
|
||||
methodWithoutParams := (mt.NumIn() == 1 && mt.In(0) == t)
|
||||
nothingReturned := (mt.NumOut() == 0)
|
||||
hasTestPrefix := (strings.HasPrefix(m.Name, "Test"))
|
||||
if methodWithoutParams && nothingReturned && hasTestPrefix && !superMethods[m.Name] {
|
||||
// Register the test suite's index so we can quickly find it by test's name later.
|
||||
registeredTests[t.Elem().Name()+"."+m.Name] = len(testSuites)
|
||||
|
||||
// Add test to the list of tests.
|
||||
tests = append(tests, TestDesc{m.Name})
|
||||
}
|
||||
}
|
||||
|
||||
return TestSuiteDesc{
|
||||
Name: t.Elem().Name(),
|
||||
Tests: tests,
|
||||
Elem: t.Elem(),
|
||||
}
|
||||
}
|
||||
|
||||
// errorSummary gets an error and returns its summary in human readable format.
|
||||
func errorSummary(err *utils.SourceError) (message string) {
|
||||
expectedPrefix := "(expected)"
|
||||
actualPrefix := "(actual)"
|
||||
errDesc := err.Description
|
||||
//strip the actual/expected stuff to provide more condensed display.
|
||||
if strings.Index(errDesc, expectedPrefix) == 0 {
|
||||
errDesc = errDesc[len(expectedPrefix):]
|
||||
}
|
||||
if strings.LastIndex(errDesc, actualPrefix) > 0 {
|
||||
errDesc = errDesc[0 : len(errDesc)-len(actualPrefix)]
|
||||
}
|
||||
|
||||
errFile := err.Path
|
||||
slashIdx := strings.LastIndex(errFile, "/")
|
||||
if slashIdx > 0 {
|
||||
errFile = errFile[slashIdx+1:]
|
||||
}
|
||||
|
||||
message = fmt.Sprintf("%s %s#%d", errDesc, errFile, err.Line)
|
||||
|
||||
/*
|
||||
// If line of error isn't known return the message as is.
|
||||
if err.Line == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Otherwise, include info about the line number and the relevant
|
||||
// source code lines.
|
||||
message += fmt.Sprintf(" (around line %d): ", err.Line)
|
||||
for _, line := range err.ContextSource() {
|
||||
if line.IsError {
|
||||
message += line.Source
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
//sortbySuiteName sorts the testsuites by name.
|
||||
type sortBySuiteName []interface{}
|
||||
|
||||
func (a sortBySuiteName) Len() int { return len(a) }
|
||||
func (a sortBySuiteName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a sortBySuiteName) Less(i, j int) bool {
|
||||
return reflect.TypeOf(a[i]).Elem().Name() < reflect.TypeOf(a[j]).Elem().Name()
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@ package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/revel/cmd/logger"
|
||||
"strconv"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/revel/cmd/logger"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -15,7 +16,7 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// Returns a new builed error
|
||||
// Returns a new builed error.
|
||||
func NewBuildError(message string, args ...interface{}) (b *BuildError) {
|
||||
Logger.Info(message, args...)
|
||||
b = &BuildError{}
|
||||
@@ -26,22 +27,23 @@ func NewBuildError(message string, args ...interface{}) (b *BuildError) {
|
||||
return b
|
||||
}
|
||||
|
||||
// Returns a new BuildError if err is not nil
|
||||
// Returns a new BuildError if err is not nil.
|
||||
func NewBuildIfError(err error, message string, args ...interface{}) (b error) {
|
||||
if err != nil {
|
||||
if berr, ok := err.(*BuildError); ok {
|
||||
// This is already a build error so just append the args
|
||||
berr.Args = append(berr.Args, args...)
|
||||
return berr
|
||||
} else {
|
||||
}
|
||||
|
||||
args = append(args, "error", err.Error())
|
||||
b = NewBuildError(message, args...)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// BuildError implements Error() string
|
||||
// BuildError implements Error() string.
|
||||
func (b *BuildError) Error() string {
|
||||
return fmt.Sprint(b.Message, b.Args)
|
||||
}
|
||||
@@ -70,7 +72,6 @@ func NewCompileError(importPath, errorLink string, error error) *SourceError {
|
||||
Logger.Error("Build errors", "errors", error)
|
||||
}
|
||||
|
||||
|
||||
// Read the source for the offending file.
|
||||
var (
|
||||
relFilename = string(errorMatch[1]) // e.g. "src/revel/sample/app/controllers/app.go"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/build"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"bytes"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Initialize the command based on the GO environment
|
||||
// Initialize the command based on the GO environment.
|
||||
func CmdInit(c *exec.Cmd, addGoPath bool, basePath string) {
|
||||
c.Dir = basePath
|
||||
// Dep does not like paths that are not real, convert all paths in go to real paths
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// The error is a wrapper for the
|
||||
// The error is a wrapper for the.
|
||||
type (
|
||||
SourceError struct {
|
||||
SourceType string // The type of source that failed to build.
|
||||
@@ -23,7 +23,8 @@ type (
|
||||
IsError bool
|
||||
}
|
||||
)
|
||||
// Return a new error object
|
||||
|
||||
// Return a new error object.
|
||||
func NewError(source, title, path, description string) *SourceError {
|
||||
return &SourceError{
|
||||
SourceType: source,
|
||||
@@ -33,17 +34,17 @@ func NewError(source, title, path, description string) *SourceError {
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a link based on the configuration setting "errors.link"
|
||||
// Creates a link based on the configuration setting "errors.link".
|
||||
func (e *SourceError) SetLink(errorLink string) {
|
||||
errorLink = strings.Replace(errorLink, "{{Path}}", e.Path, -1)
|
||||
errorLink = strings.Replace(errorLink, "{{Line}}", strconv.Itoa(e.Line), -1)
|
||||
errorLink = strings.ReplaceAll(errorLink, "{{Path}}", e.Path)
|
||||
errorLink = strings.ReplaceAll(errorLink, "{{Line}}", strconv.Itoa(e.Line))
|
||||
|
||||
e.Link = "<a href=" + errorLink + ">" + e.Path + ":" + strconv.Itoa(e.Line) + "</a>"
|
||||
}
|
||||
|
||||
// Error method constructs a plaintext version of the error, taking
|
||||
// account that fields are optionally set. Returns e.g. Compilation Error
|
||||
// (in views/header.html:51): expected right delim in end; got "}"
|
||||
// (in views/header.html:51): expected right delim in end; got "}".
|
||||
func (e *SourceError) Error() string {
|
||||
if e == nil {
|
||||
panic("opps")
|
||||
|
||||
@@ -4,14 +4,15 @@ import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
@@ -39,9 +40,8 @@ func ReadLines(filename string) ([]string, error) {
|
||||
return strings.Split(string(dataBytes), "\n"), nil
|
||||
}
|
||||
|
||||
// Copy file returns error
|
||||
// Copy file returns error.
|
||||
func CopyFile(destFilename, srcFilename string) (err error) {
|
||||
|
||||
destFile, err := os.Create(destFilename)
|
||||
if err != nil {
|
||||
return NewBuildIfError(err, "Failed to create file", "file", destFilename)
|
||||
@@ -105,7 +105,7 @@ func GenerateTemplate(filename, templateSource string, args map[string]interface
|
||||
return
|
||||
}
|
||||
|
||||
// Given the target path and source path and data. A template
|
||||
// Given the target path and source path and data. A template.
|
||||
func RenderTemplate(destPath, srcPath string, data interface{}) (err error) {
|
||||
tmpl, err := template.ParseFiles(srcPath)
|
||||
if err != nil {
|
||||
@@ -129,7 +129,7 @@ func RenderTemplate(destPath, srcPath string, data interface{}) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Given the target path and source path and data. A template
|
||||
// Given the target path and source path and data. A template.
|
||||
func RenderTemplateToStream(output io.Writer, srcPath []string, data interface{}) (err error) {
|
||||
tmpl, err := template.ParseFiles(srcPath...)
|
||||
if err != nil {
|
||||
@@ -148,7 +148,7 @@ func MustChmod(filename string, mode os.FileMode) {
|
||||
PanicOnError(err, fmt.Sprintf("Failed to chmod %d %q", mode, filename))
|
||||
}
|
||||
|
||||
// Called if panic
|
||||
// Called if panic.
|
||||
func PanicOnError(err error, msg string) {
|
||||
if revErr, ok := err.(*SourceError); (ok && revErr != nil) || (!ok && err != nil) {
|
||||
Logger.Panicf("Abort: %s: %s %s", msg, revErr, err)
|
||||
@@ -188,7 +188,6 @@ func CopyDir(destDir, srcDir string, data map[string]interface{}) error {
|
||||
|
||||
// If this file ends in ".template", render it as a template.
|
||||
if strings.HasSuffix(relSrcPath, ".template") {
|
||||
|
||||
return RenderTemplate(destPath[:len(destPath)-len(".template")], srcPath, data)
|
||||
}
|
||||
|
||||
@@ -198,13 +197,13 @@ func CopyDir(destDir, srcDir string, data map[string]interface{}) error {
|
||||
})
|
||||
}
|
||||
|
||||
// Shortcut to fsWalk
|
||||
// Shortcut to fsWalk.
|
||||
func Walk(root string, walkFn filepath.WalkFunc) error {
|
||||
return fsWalk(root, root, walkFn)
|
||||
}
|
||||
|
||||
// Walk the path tree using the function
|
||||
// Every file found will call the function
|
||||
// Every file found will call the function.
|
||||
func fsWalk(fname string, linkName string, walkFn filepath.WalkFunc) error {
|
||||
fsWalkFunc := func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
@@ -244,7 +243,7 @@ func fsWalk(fname string, linkName string, walkFn filepath.WalkFunc) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Tar gz the folder
|
||||
// Tar gz the folder.
|
||||
func TarGzDir(destFilename, srcDir string) (name string, err error) {
|
||||
zipFile, err := os.Create(destFilename)
|
||||
if err != nil {
|
||||
@@ -266,6 +265,10 @@ func TarGzDir(destFilename, srcDir string) (name string, err error) {
|
||||
}()
|
||||
|
||||
err = fsWalk(srcDir, srcDir, func(srcPath string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
Logger.Debugf("error in walkFn: %s", err)
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
@@ -300,7 +303,7 @@ func TarGzDir(destFilename, srcDir string) (name string, err error) {
|
||||
return zipFile.Name(), err
|
||||
}
|
||||
|
||||
// Return true if the file exists
|
||||
// Return true if the file exists.
|
||||
func Exists(filename string) bool {
|
||||
_, err := os.Stat(filename)
|
||||
return err == nil
|
||||
@@ -324,7 +327,7 @@ func Empty(dirname string) bool {
|
||||
return len(results) == 0
|
||||
}
|
||||
|
||||
// Find the full source dir for the import path, uses the build.Default.GOPATH to search for the directory
|
||||
// Find the full source dir for the import path, uses the build.Default.GOPATH to search for the directory.
|
||||
func FindSrcPaths(appPath string, packageList []string, packageResolver func(pkgName string) error) (sourcePathsmap map[string]string, err error) {
|
||||
sourcePathsmap, missingList, err := findSrcPaths(appPath, packageList)
|
||||
if err != nil && packageResolver != nil || len(missingList) > 0 {
|
||||
@@ -345,10 +348,12 @@ func FindSrcPaths(appPath string, packageList []string, packageResolver func(pkg
|
||||
return
|
||||
}
|
||||
|
||||
var NO_APP_FOUND = errors.New("No app found")
|
||||
var NO_REVEL_FOUND = errors.New("No revel found")
|
||||
var (
|
||||
NO_APP_FOUND = errors.New("no app found")
|
||||
NO_REVEL_FOUND = errors.New("no revel found")
|
||||
)
|
||||
|
||||
// Find the full source dir for the import path, uses the build.Default.GOPATH to search for the directory
|
||||
// Find the full source dir for the import path, uses the build.Default.GOPATH to search for the directory.
|
||||
func findSrcPaths(appPath string, packagesList []string) (sourcePathsmap map[string]string, missingList []string, err error) {
|
||||
// Use packages to fetch
|
||||
// by not specifying env, we will use the default env
|
||||
@@ -371,7 +376,6 @@ func findSrcPaths(appPath string, packagesList []string) (sourcePathsmap map[str
|
||||
if pck.Errors != nil && len(pck.Errors) > 0 {
|
||||
log.Error("Error ", "count", len(pck.Errors), "App Import Path", pck.ID, "filesystem path", pck.PkgPath, "errors", pck.Errors)
|
||||
// continue
|
||||
|
||||
}
|
||||
// a,_ := pck.MarshalJSON()
|
||||
log.Info("Found ", "count", len(pck.GoFiles), "App Import Path", pck.ID, "apppath", appPath)
|
||||
|
||||
@@ -2,10 +2,11 @@ package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/revel/cmd/logger"
|
||||
"github.com/revel/config"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/revel/cmd/logger"
|
||||
"github.com/revel/config"
|
||||
)
|
||||
|
||||
var Logger = logger.New()
|
||||
@@ -31,7 +32,7 @@ func InitLogger(basePath string, logLevel logger.LogLevel) {
|
||||
}
|
||||
|
||||
// This function is to throw a panic that may be caught by the packger so it can perform the needed
|
||||
// imports
|
||||
// imports.
|
||||
func Retry(format string, args ...interface{}) {
|
||||
// Ensure the user's command prompt starts on the next line.
|
||||
if !strings.HasSuffix(format, "\n") {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package utils
|
||||
|
||||
// Return true if the target string is in the list
|
||||
// Return true if the target string is in the list.
|
||||
func ContainsString(list []string, target string) bool {
|
||||
for _, el := range list {
|
||||
if el == target {
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
package cmd
|
||||
|
||||
const (
|
||||
// Version current Revel version
|
||||
// Version current Revel version.
|
||||
Version = "1.0.0"
|
||||
|
||||
// BuildDate latest commit/release date
|
||||
// BuildDate latest commit/release date.
|
||||
BuildDate = "2020-07-11"
|
||||
|
||||
// MinimumGoVersion minimum required Go version for Revel
|
||||
// MinimumGoVersion minimum required Go version for Revel.
|
||||
MinimumGoVersion = ">= go1.12"
|
||||
)
|
||||
|
||||
@@ -9,11 +9,11 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Listener is an interface for receivers of filesystem events.
|
||||
@@ -49,7 +49,7 @@ type Watcher struct {
|
||||
refreshTimerMS time.Duration // The number of milliseconds between refreshing builds
|
||||
}
|
||||
|
||||
// Creates a new watched based on the container
|
||||
// Creates a new watched based on the container.
|
||||
func NewWatcher(paths *model.RevelContainer, eagerRefresh bool) *Watcher {
|
||||
return &Watcher{
|
||||
forceRefresh: false,
|
||||
@@ -109,9 +109,7 @@ func (w *Watcher) Listen(listener Listener, roots ...string) {
|
||||
continue
|
||||
}
|
||||
|
||||
var watcherWalker func(path string, info os.FileInfo, err error) error
|
||||
|
||||
watcherWalker = func(path string, info os.FileInfo, err error) error {
|
||||
watcherWalker := func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
utils.Logger.Fatal("Watcher: Error walking path:", "error", err)
|
||||
return nil
|
||||
@@ -150,7 +148,6 @@ func (w *Watcher) Listen(listener Listener, roots ...string) {
|
||||
|
||||
// NotifyWhenUpdated notifies the watcher when a file event is received.
|
||||
func (w *Watcher) NotifyWhenUpdated(listener Listener, watcher *fsnotify.Watcher) {
|
||||
|
||||
for {
|
||||
select {
|
||||
case ev := <-watcher.Events:
|
||||
@@ -218,18 +215,18 @@ func (w *Watcher) Notify() *utils.SourceError {
|
||||
w.lastError = i
|
||||
w.forceRefresh = true
|
||||
return err
|
||||
} else {
|
||||
}
|
||||
|
||||
w.lastError = -1
|
||||
w.forceRefresh = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build a queue for refresh notifications
|
||||
// this will not return until one of the queue completes
|
||||
// this will not return until one of the queue completes.
|
||||
func (w *Watcher) notifyInProcess(listener Listener) (err *utils.SourceError) {
|
||||
shouldReturn := false
|
||||
// This code block ensures that either a timer is created
|
||||
@@ -292,4 +289,3 @@ func (w *Watcher) rebuildRequired(ev fsnotify.Event, listener Listener) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user