From ddec572d5d8338cf919838b4ead051fedeac0489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20T=C3=B6tterman?= Date: Wed, 10 Feb 2021 16:34:20 +0200 Subject: [PATCH] More linting --- go.mod | 15 +++++----- go.sum | 27 ++++++++++++++++++ harness/app.go | 14 ++++++++-- harness/harness.go | 33 ++++++++++++++++------ logger/composite_multihandler.go | 13 +++++---- logger/handlers.go | 7 +++-- logger/init.go | 14 +++++----- logger/init_test.go | 22 +++++++++------ logger/terminal_format.go | 4 +-- logger/utils.go | 4 +-- logger/wrap_handlers.go | 20 +++++++++++-- model/command_config.go | 14 ++++++++-- model/revel_container.go | 48 +++++++++++++++++++++++--------- model/type_expr.go | 10 +++---- parser/reflect.go | 4 ++- parser2/source_processor.go | 4 ++- revel/build_test.go | 4 +-- revel/clean_test.go | 7 +++-- revel/command_test.go | 5 +++- revel/new.go | 22 ++++++++++++--- revel/package_test.go | 2 +- revel/revel.go | 12 +++++++- revel/version.go | 15 ++++++++-- revel/version_test.go | 4 ++- utils/build_error.go | 14 ++++++---- utils/file.go | 21 ++++++++++---- utils/log.go | 2 +- version.go | 2 +- watcher/watcher.go | 19 +++++++------ 29 files changed, 275 insertions(+), 107 deletions(-) diff --git a/go.mod b/go.mod index 268f752..b878f96 100644 --- a/go.mod +++ b/go.mod @@ -5,22 +5,23 @@ go 1.12 require ( github.com/BurntSushi/toml v0.3.1 // indirect github.com/agtorre/gocolorize v1.0.0 - github.com/fsnotify/fsnotify v1.4.7 - github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1 // indirect + github.com/fsnotify/fsnotify v1.4.9 + github.com/go-stack/stack v1.8.0 // indirect + github.com/inconshreveable/log15 v0.0.0-20201112154412-8562bdadbbac // indirect github.com/jessevdk/go-flags v1.4.0 - github.com/mattn/go-colorable v0.1.6 + github.com/mattn/go-colorable v0.1.8 github.com/myesui/uuid v1.0.0 // indirect github.com/pkg/errors v0.9.1 - github.com/revel/config v0.21.0 + github.com/revel/config v1.0.0 github.com/revel/log15 v2.11.20+incompatible github.com/revel/modules v0.21.0 // indirect github.com/revel/pathtree v0.0.0-20140121041023-41257a1839e9 // indirect - github.com/revel/revel v0.21.0 + github.com/revel/revel v1.0.0 github.com/stretchr/testify v1.4.0 github.com/twinj/uuid v1.0.0 // indirect github.com/xeonx/timeago v1.0.0-rc4 // indirect - golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 // indirect - golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 // indirect + golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect + golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect golang.org/x/tools v0.0.0-20200219054238-753a1d49df85 gopkg.in/fsnotify/fsnotify.v1 v1.4.7 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 diff --git a/go.sum b/go.sum index 464c37b..62a4fd2 100644 --- a/go.sum +++ b/go.sum @@ -5,12 +5,20 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1 h1:KUDFlmBg2buRWNzIcwLlKvfcnujcHQRQ1As1LoaCLAM= github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o= +github.com/inconshreveable/log15 v0.0.0-20201112154412-8562bdadbbac h1:n1DqxAo4oWPMvH1+v+DLYlMCecgumhhgnxAPdqDIFHI= +github.com/inconshreveable/log15 v0.0.0-20201112154412-8562bdadbbac/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/myesui/uuid v1.0.0/go.mod h1:2CDfNgU0LR8mIdO8vdWd8i9gWWxLlcoIGGpSNgafq84= @@ -20,35 +28,54 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/revel/config v0.21.0 h1:Bw4iXLGAuD/Di2HEhPSOyDywrTlFIXUMbds91lXTtTU= github.com/revel/config v0.21.0/go.mod h1:GT4a9px5kDGRqLizcw/md0QFErrhen76toz4qS3oIoI= +github.com/revel/config v1.0.0 h1:UAzLPQ+x9nJeP6a+H93G+AKEosg3OO2oVLBXK9oSN2U= +github.com/revel/config v1.0.0/go.mod h1:GT4a9px5kDGRqLizcw/md0QFErrhen76toz4qS3oIoI= github.com/revel/log15 v2.11.20+incompatible h1:JkA4tbwIo/UGEMumY50zndKq816RQW3LQ0wIpRc+32U= github.com/revel/log15 v2.11.20+incompatible/go.mod h1:l0WmLRs+IM1hBl4noJiBc2tZQiOgZyXzS1mdmFt+5Gc= github.com/revel/modules v0.21.0/go.mod h1:UBlNmO9VGZo4j6Ptn2uC/26Iclefuic+V40jYRPBxQE= +github.com/revel/pathtree v0.0.0-20140121041023-41257a1839e9 h1:/d6kfjzjyx19ieWqMOXHSTLFuRxLOH15ZubtcAXExKw= github.com/revel/pathtree v0.0.0-20140121041023-41257a1839e9/go.mod h1:TmlwoRLDvgRjoTe6rbsxIaka/CulzYrgfef7iNJcEWY= +github.com/revel/revel v0.21.0 h1:E6kDJmpJSDb0F8XwbyG5h4ayzpZ+8Wcw2IiPZW/2qSc= github.com/revel/revel v0.21.0/go.mod h1:VZWJnHjpDEtuGUuZJ2NO42XryitrtwsdVaJxfDeo5yc= +github.com/revel/revel v1.0.0 h1:BsPFnKuuzXEkPtrjdjZHiDcvDmbBiBQvh7Z5c6kLb/Y= +github.com/revel/revel v1.0.0/go.mod h1:VZWJnHjpDEtuGUuZJ2NO42XryitrtwsdVaJxfDeo5yc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/twinj/uuid v1.0.0 h1:fzz7COZnDrXGTAOHGuUGYd6sG+JMq+AoE7+Jlu0przk= github.com/twinj/uuid v1.0.0/go.mod h1:mMgcE1RHFUFqe5AfiwlINXisXfDGro23fWdPUfOMjRY= +github.com/xeonx/timeago v1.0.0-rc4 h1:9rRzv48GlJC0vm+iBpLcWAr8YbETyN9Vij+7h2ammz4= github.com/xeonx/timeago v1.0.0-rc4/go.mod h1:qDLrYEFynLO7y5Ho7w3GwgtYgpy5UfhcXIIQvMKVDkA= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 h1:WQ8q63x+f/zpC8Ac1s9wLElVoHhm32p6tudrU72n1QA= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3rzIsrrXfAQBWnYfn+w= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20200219054238-753a1d49df85 h1:XNHaQ2CZDl/SjEZlUXGh7+OQvfLuFgmk3oNWkCFfERE= golang.org/x/tools v0.0.0-20200219054238-753a1d49df85/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify/fsnotify.v1 v1.4.7 h1:XNNYLJHt73EyYiCZi6+xjupS9CpvmiDgjPTAjrBlQbo= gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE= gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= diff --git a/harness/app.go b/harness/app.go index 3536dc9..2f00de9 100644 --- a/harness/app.go +++ b/harness/app.go @@ -6,7 +6,6 @@ package harness import ( "bytes" - "errors" "fmt" "io" "os" @@ -19,6 +18,16 @@ import ( "github.com/revel/cmd/utils" ) +// Error is used for constant errors. +type Error string + +// Error implements the error interface. +func (e Error) Error() string { + return string(e) +} + +const ErrTimedOut Error = "app timed out" + // App contains the configuration for running a Revel app. (Not for the app itself) // Its only purpose is constructing the command to execute. type App struct { @@ -83,7 +92,8 @@ func (cmd AppCmd) Start(c *model.CommandConfig) error { println("Revel proxy is listening, point your browser to :", c.Run.Port) utils.Logger.Error("Killing revel server process did not respond after wait timeout.", "processid", cmd.Process.Pid) cmd.Kill() - return errors.New("revel/harness: app timed out") + + return fmt.Errorf("revel/harness: %w", ErrTimedOut) case <-listeningWriter.notifyReady: println("Revel proxy is listening, point your browser to :", c.Run.Port) diff --git a/harness/harness.go b/harness/harness.go index 0bad2b0..bc07288 100644 --- a/harness/harness.go +++ b/harness/harness.go @@ -16,6 +16,7 @@ package harness import ( "crypto/tls" "encoding/json" + "errors" "fmt" "go/build" "html/template" @@ -69,6 +70,7 @@ func (h *Harness) renderError(iw http.ResponseWriter, ir *http.Request, err erro if err == nil { utils.Logger.Panic("Caller passed in a nil error") } + templateSet := template.New("__root__") seekViewOnPath := func(view string) (path string) { path = filepath.Join(h.paths.ViewsPath, "errors", view) @@ -86,26 +88,27 @@ func (h *Harness) renderError(iw http.ResponseWriter, ir *http.Request, err erro } return } + target := []string{seekViewOnPath("500.html"), seekViewOnPath("500-dev.html")} if !utils.Exists(target[0]) { fmt.Fprintf(iw, "Target template not found not found %s
\n", target[0]) fmt.Fprintf(iw, "An error occurred %s", err.Error()) return } + var revelError *utils.SourceError - switch e := err.(type) { - case *utils.SourceError: - revelError = e - case error: + + if !errors.As(err, &revelError) { revelError = &utils.SourceError{ Title: "Server Error", - Description: e.Error(), + Description: err.Error(), } } if revelError == nil { panic("no error provided") } + viewArgs := map[string]interface{}{} viewArgs["RunMode"] = h.paths.RunMode viewArgs["DevMode"] = h.paths.DevMode @@ -236,32 +239,42 @@ func (h *Harness) refresh() (err *utils.SourceError) { h.app, newErr = Build(h.config, h.paths) if newErr != nil { utils.Logger.Error("Build detected an error", "error", newErr) - if castErr, ok := newErr.(*utils.SourceError); ok { + + var castErr *utils.SourceError + if errors.As(newErr, &castErr) { return castErr } + err = &utils.SourceError{ Title: "App failed to start up", Description: err.Error(), } + return } if h.useProxy { h.app.Port = h.port runMode := h.runMode + if !h.config.HistoricMode { // Recalulate run mode based on the config var paths []byte if len(h.app.PackagePathMap) > 0 { 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) - if err, k := err2.(*utils.SourceError); k { + + var serr *utils.SourceError + if errors.As(err2, &serr) { return err } + return &utils.SourceError{ Title: "App failed to start up", Description: err2.Error(), @@ -297,7 +310,11 @@ func (h *Harness) Run() { paths = append(paths, h.paths.CodePaths...) h.watcher = watcher.NewWatcher(h.paths, false) h.watcher.Listen(h, paths...) - go h.Refresh() + go func() { + if err := h.Refresh(); err != nil { + utils.Logger.Error("Failed to refresh", "error", err) + } + }() // h.watcher.Notify() if h.useProxy { diff --git a/logger/composite_multihandler.go b/logger/composite_multihandler.go index 79f0019..ab322fe 100644 --- a/logger/composite_multihandler.go +++ b/logger/composite_multihandler.go @@ -39,8 +39,11 @@ func (h *CompositeMultiHandler) Log(r *Record) (err error) { // Embed the caller function in the context if handler != nil { - handler.Log(r) + if err := handler.Log(r); err != nil { + panic(err) + } } + return } @@ -91,8 +94,8 @@ func (h *CompositeMultiHandler) SetHandlers(handler LogHandler, options *LogOpti } } -func (h *CompositeMultiHandler) SetJson(writer io.Writer, options *LogOptions) { - handler := CallerFileHandler(StreamHandler(writer, JsonFormatEx( +func (h *CompositeMultiHandler) SetJSON(writer io.Writer, options *LogOptions) { + handler := CallerFileHandler(StreamHandler(writer, JSONFormatEx( options.GetBoolDefault("pretty", false), options.GetBoolDefault("lineSeparated", true), ))) @@ -103,7 +106,7 @@ func (h *CompositeMultiHandler) SetJson(writer io.Writer, options *LogOptions) { } // Use built in rolling function. -func (h *CompositeMultiHandler) SetJsonFile(filePath string, options *LogOptions) { +func (h *CompositeMultiHandler) SetJSONFile(filePath string, options *LogOptions) { writer := &lumberjack.Logger{ Filename: filePath, MaxSize: options.GetIntDefault("maxSizeMB", 1024), // megabytes @@ -111,7 +114,7 @@ func (h *CompositeMultiHandler) SetJsonFile(filePath string, options *LogOptions MaxBackups: options.GetIntDefault("maxBackups", 7), Compress: options.GetBoolDefault("compress", true), } - h.SetJson(writer, options) + h.SetJSON(writer, options) } func (h *CompositeMultiHandler) SetTerminal(writer io.Writer, options *LogOptions) { diff --git a/logger/handlers.go b/logger/handlers.go index 16a4ff5..3c9a76f 100644 --- a/logger/handlers.go +++ b/logger/handlers.go @@ -50,6 +50,7 @@ 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. func CallerFuncHandler(h LogHandler) LogHandler { + // TODO: infinite recursion return CallerFuncHandler(h) } @@ -137,8 +138,9 @@ func NotMatchHandler(key string, value interface{}, h LogHandler) LogHandler { func MultiHandler(hs ...LogHandler) LogHandler { return FuncHandler(func(r *Record) error { for _, h := range hs { - // what to do about failures? - h.Log(r) + if err := h.Log(r); err != nil { + panic(err) + } } return nil }) @@ -189,6 +191,7 @@ func (ll *ListLogHandler) Log(r *Record) (err error) { handler.Log(r) } } + return } diff --git a/logger/init.go b/logger/init.go index 5f2d307..8e3b2a1 100644 --- a/logger/init.go +++ b/logger/init.go @@ -13,7 +13,7 @@ import ( func InitializeFromConfig(basePath string, config *config.Context) (c *CompositeMultiHandler) { // If running in test mode suppress anything that is not an error - if config != nil && config.BoolDefault(TEST_MODE_FLAG, false) { + if config != nil && config.BoolDefault(TestModeFlag, false) { // Preconfigure all the options config.SetOption("log.info.output", "none") config.SetOption("log.debug.output", "none") @@ -26,14 +26,14 @@ func InitializeFromConfig(basePath string, config *config.Context) (c *Composite c, _ = NewCompositeMultiHandler() // Filters are assigned first, non filtered items override filters - if config != nil && !config.BoolDefault(TEST_MODE_FLAG, false) { + if config != nil && !config.BoolDefault(TestModeFlag, false) { initAllLog(c, basePath, config) } initLogLevels(c, basePath, config) if c.CriticalHandler == nil && c.ErrorHandler != nil { c.CriticalHandler = c.ErrorHandler } - if config != nil && !config.BoolDefault(TEST_MODE_FLAG, false) { + if config != nil && !config.BoolDefault(TestModeFlag, false) { initFilterLog(c, basePath, config) if c.CriticalHandler == nil && c.ErrorHandler != nil { c.CriticalHandler = c.ErrorHandler @@ -47,7 +47,7 @@ func InitializeFromConfig(basePath string, config *config.Context) (c *Composite // 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) + extraLogFlag := config.BoolDefault(SpecialUseFlag, false) if output, found := config.String("log.all.output"); found { // Set all output for the specified handler if extraLogFlag { @@ -63,7 +63,7 @@ func initAllLog(c *CompositeMultiHandler, basePath string, config *config.Contex // log.error.filter .... func initFilterLog(c *CompositeMultiHandler, basePath string, config *config.Context) { if config != nil { - extraLogFlag := config.BoolDefault(SPECIAL_USE_FLAG, false) + extraLogFlag := config.BoolDefault(SpecialUseFlag, false) for _, logFilter := range logFilterList { // Init for all filters @@ -102,7 +102,7 @@ func initLogLevels(c *CompositeMultiHandler, basePath string, config *config.Con "trace", // TODO trace is deprecated } { if config != nil { - extraLogFlag := config.BoolDefault(SPECIAL_USE_FLAG, false) + extraLogFlag := config.BoolDefault(SpecialUseFlag, false) output, found := config.String("log." + name + ".output") if found { if extraLogFlag { @@ -178,7 +178,7 @@ func initHandlerFor(c *CompositeMultiHandler, output, basePath string, options * } if strings.HasSuffix(output, "json") { - c.SetJsonFile(output, options) + c.SetJSONFile(output, options) } else { // Override defaults for a terminal file options.SetExtendedOptions("noColor", true) diff --git a/logger/init_test.go b/logger/init_test.go index 5793048..215e2da 100644 --- a/logger/init_test.go +++ b/logger/init_test.go @@ -59,7 +59,7 @@ var singleCases = []testData{ func TestSingleCases(t *testing.T) { rootLog := logger.New() for _, testCase := range singleCases { - testCase.logTest(rootLog, t) + testCase.logTest(t, rootLog) testCase.validate(t) } } @@ -112,7 +112,7 @@ var filterCases = []testData{ func TestFilterCases(t *testing.T) { rootLog := logger.New("module", "app") for _, testCase := range filterCases { - testCase.logTest(rootLog, t) + testCase.logTest(t, rootLog) testCase.validate(t) } } @@ -169,7 +169,7 @@ var nfilterCases = []testData{ func TestNotFilterCases(t *testing.T) { rootLog := logger.New("module", "app") for _, testCase := range nfilterCases { - testCase.logTest(rootLog, t) + testCase.logTest(t, rootLog) testCase.validate(t) } } @@ -186,7 +186,7 @@ var offCases = []testData{ func TestOffCases(t *testing.T) { rootLog := logger.New("module", "app") for _, testCase := range offCases { - testCase.logTest(rootLog, t) + testCase.logTest(t, rootLog) testCase.validate(t) } } @@ -203,7 +203,7 @@ var duplicateCases = []testData{ func TestDuplicateCases(t *testing.T) { rootLog := logger.New("module", "app") for _, testCase := range duplicateCases { - testCase.logTest(rootLog, t) + testCase.logTest(t, rootLog) testCase.validate(t) } } @@ -232,7 +232,7 @@ var contradictCases = []testData{ func TestContradictCases(t *testing.T) { rootLog := logger.New("module", "app") for _, testCase := range contradictCases { - testCase.logTest(rootLog, t) + testCase.logTest(t, rootLog) testCase.validate(t) } } @@ -253,12 +253,12 @@ var allCases = []testData{ func TestAllCases(t *testing.T) { rootLog := logger.New("module", "app") for i, testCase := range allCases { - testCase.logTest(rootLog, t) + testCase.logTest(t, rootLog) allCases[i] = testCase } rootLog = logger.New() for i, testCase := range allCases { - testCase.logTest(rootLog, t) + testCase.logTest(t, rootLog) allCases[i] = testCase } for _, testCase := range allCases { @@ -284,7 +284,9 @@ func (c *testCounter) Log(r *logger.Record) error { return nil } -func (td *testData) logTest(rootLog logger.MultiLogger, t *testing.T) { +func (td *testData) logTest(t *testing.T, rootLog logger.MultiLogger) { + t.Helper() + if td.tc == nil { td.tc = &testCounter{} counterInit(td.tc) @@ -317,6 +319,8 @@ func (td *testData) runLogTest(log logger.MultiLogger) { } func (td *testData) validate(t *testing.T) { + t.Helper() + t.Logf("Test %#v expected %#v", td.tc, td.result) assert.Equal(t, td.result.debug, td.tc.debug, "Debug failed "+strings.Join(td.config, " ")) assert.Equal(t, td.result.info, td.tc.info, "Info failed "+strings.Join(td.config, " ")) diff --git a/logger/terminal_format.go b/logger/terminal_format.go index fd2e3a3..9f20463 100644 --- a/logger/terminal_format.go +++ b/logger/terminal_format.go @@ -197,10 +197,10 @@ func escapeString(s string) string { return ret } -// JsonFormatEx formats log records as JSON objects. If pretty is true, +// JSONFormatEx formats log records as JSON objects. If pretty is true, // records will be pretty-printed. If lineSeparated is true, records // will be logged with a new line between each record. -func JsonFormatEx(pretty, lineSeparated bool) LogFormat { +func JSONFormatEx(pretty, lineSeparated bool) LogFormat { jsonMarshal := json.Marshal if pretty { jsonMarshal = func(v interface{}) ([]byte, error) { diff --git a/logger/utils.go b/logger/utils.go index f77dfde..81d491b 100644 --- a/logger/utils.go +++ b/logger/utils.go @@ -20,9 +20,9 @@ var ( const ( // The test mode flag overrides the default log level and shows only errors. - TEST_MODE_FLAG = "testModeFlag" + TestModeFlag = "testModeFlag" // The special use flag enables showing messages when the logger is setup. - SPECIAL_USE_FLAG = "specialUseFlag" + SpecialUseFlag = "specialUseFlag" ) // Returns the logger for the name. diff --git a/logger/wrap_handlers.go b/logger/wrap_handlers.go index 2901c88..8d9200a 100644 --- a/logger/wrap_handlers.go +++ b/logger/wrap_handlers.go @@ -9,6 +9,20 @@ import ( "time" ) +// Error is used for constant errors. +type Error string + +// Error implements the error interface. +func (e Error) Error() string { + return string(e) +} + +const ( + ErrNotFunc Error = "not a function" + ErrTakesArgs Error = "takes arguments" + ErrNoReturn Error = "no return value" +) + // Function handler wraps the declared function and returns the handler for it. func FuncHandler(fn func(r *Record) error) LogHandler { return funcHandler(fn) @@ -71,15 +85,15 @@ func evaluateLazy(lz Lazy) (interface{}, error) { t := reflect.TypeOf(lz.Fn) if t.Kind() != reflect.Func { - return nil, fmt.Errorf("INVALID_LAZY, not func: %+v", lz.Fn) + return nil, fmt.Errorf("%w %+v", ErrNotFunc, lz.Fn) } if t.NumIn() > 0 { - return nil, fmt.Errorf("INVALID_LAZY, func takes args: %+v", lz.Fn) + return nil, fmt.Errorf("%w %+v", ErrTakesArgs, lz.Fn) } if t.NumOut() == 0 { - return nil, fmt.Errorf("INVALID_LAZY, no func return val: %+v", lz.Fn) + return nil, fmt.Errorf("%w %+v", ErrNoReturn, lz.Fn) } value := reflect.ValueOf(lz.Fn) diff --git a/model/command_config.go b/model/command_config.go index 87e4a89..03c6cf0 100644 --- a/model/command_config.go +++ b/model/command_config.go @@ -28,6 +28,11 @@ const ( VERSION ) +const ( + ErrImportInvalid Error = "invalid import path, working dir is in GOPATH root" + ErrUnableToImport Error = "unable to determine import path from" +) + type ( // The Revel command type. COMMAND int @@ -110,7 +115,7 @@ func (c *CommandConfig) UpdateImportPath() error { importPath = importPath[4:] } else if importPath == "src" { if c.Index != VERSION { - return fmt.Errorf("invalid import path, working dir is in GOPATH root") + return ErrImportInvalid } importPath = "" } @@ -122,7 +127,10 @@ func (c *CommandConfig) UpdateImportPath() error { c.ImportPath = importPath // We need the source root determined at this point to check the setversions - c.initAppFolder() + if err := c.initAppFolder(); err != nil { + utils.Logger.Error("Error initing app folder", "error", err) + } + utils.Logger.Info("Returned import path", "path", importPath) if required && c.Index != NEW { if err := c.SetVersions(); err != nil { @@ -138,7 +146,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("%w: %s", ErrUnableToImport, importPath) } return nil } diff --git a/model/revel_container.go b/model/revel_container.go index 659c256..0ea4fdc 100644 --- a/model/revel_container.go +++ b/model/revel_container.go @@ -2,7 +2,6 @@ package model import ( - "errors" "fmt" "path/filepath" "sort" @@ -13,6 +12,24 @@ import ( "golang.org/x/tools/go/packages" ) +// Error is used for constant errors. +type Error string + +// Error implements the error interface. +func (e Error) Error() string { + return string(e) +} + +const ( + ErrNoApp Error = "no app found at path" + ErrNoConfig Error = "no config found at path" + ErrNotFound Error = "not found" + ErrMissingCert Error = "no http.sslcert provided" + ErrMissingKey Error = "no http.sslkey provided" + ErrNoFiles Error = "no files found in import path" + ErrNoPackages Error = "no packages found for import" +) + type ( // The container object for describing all Revels variables. RevelContainer struct { @@ -123,10 +140,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("%w: %s", ErrNoApp, 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("%w: %s", ErrNoConfig, filepath.Join(rp.BasePath, "conf")) } rp.ViewsPath = filepath.Join(rp.AppPath, "views") @@ -150,7 +167,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 configuration file %s", err) + return rp, fmt.Errorf("unable to load configuration file %w", err) } // Ensure that the selected runmode appears in app.conf. @@ -159,7 +176,7 @@ func NewRevelPaths(mode, importPath, appSrcPath string, callback RevelCallback) mode = config.DefaultSection } if !rp.Config.HasSection(mode) { - return rp, fmt.Errorf("app.conf: No mode found: %s %s", "run-mode", mode) + return rp, fmt.Errorf("app.conf: %w %s %s", ErrNotFound, "run-mode", mode) } rp.Config.SetSection(mode) @@ -172,13 +189,14 @@ 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, ErrMissingCert } + if rp.HTTPSslKey == "" { - return rp, errors.New("no http.sslkey provided") + return rp, ErrMissingKey } } - // + rp.AppName = rp.Config.StringDefault("app.name", "(not set)") rp.AppRoot = rp.Config.StringDefault("app.root", "") rp.CookiePrefix = rp.Config.StringDefault("cookie.prefix", "REVEL") @@ -201,7 +219,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 %w", "error", err) } return } @@ -226,10 +244,14 @@ func (rp *RevelContainer) loadModules(callback RevelCallback) (err error) { modulePath, err := rp.ResolveImportPath(moduleImportPath) if err != nil { utils.Logger.Info("Missing module ", "module_import_path", moduleImportPath, "error", err) - callback.PackageResolver(moduleImportPath) + + if err := callback.PackageResolver(moduleImportPath); err != nil { + return fmt.Errorf("failed to resolve package %w", err) + } + 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:%w ", "modulePath", moduleImportPath, "error", err) } } // Drop anything between module.???. @@ -281,7 +303,7 @@ func (rp *RevelContainer) ResolveImportPath(importPath string) (string, error) { pkgs, err := packages.Load(config, importPath) if len(pkgs) == 0 { - return "", errors.New("No packages found for import " + importPath + " using app path " + rp.AppPath) + return "", fmt.Errorf("%w %s using app path %s", ErrNoPackages, importPath, rp.AppPath) } // modPkg, err := build.Import(importPath, rp.AppPath, build.FindOnly) if err != nil { @@ -290,5 +312,5 @@ func (rp *RevelContainer) ResolveImportPath(importPath string) (string, error) { if len(pkgs[0].GoFiles) > 0 { return filepath.Dir(pkgs[0].GoFiles[0]), nil } - return pkgs[0].PkgPath, errors.New("No files found in import path " + importPath) + return pkgs[0].PkgPath, fmt.Errorf("%w: %s", ErrNoFiles, importPath) } diff --git a/model/type_expr.go b/model/type_expr.go index 4263e21..0da0732 100644 --- a/model/type_expr.go +++ b/model/type_expr.go @@ -20,7 +20,7 @@ func NewTypeExprFromData(expr, pkgName string, pkgIndex int, valid bool) TypeExp // NewTypeExpr returns the syntactic expression for referencing this type in Go. func NewTypeExprFromAst(pkgName string, expr ast.Expr) TypeExpr { - error := "" + err := "" switch t := expr.(type) { case *ast.Ident: if IsBuiltinType(t.Name) { @@ -41,14 +41,14 @@ func NewTypeExprFromAst(pkgName string, expr ast.Expr) TypeExpr { e := NewTypeExprFromAst(pkgName, t.Value) return NewTypeExprFromData("map["+identKey.Name+"]"+e.Expr, e.PkgName, e.pkgIndex+len("map["+identKey.Name+"]"), e.Valid) } - error = fmt.Sprintf("Failed to generate name for Map field :%v. Make sure the field name is valid.", t.Key) + err = fmt.Sprintf("Failed to generate name for Map field :%v. Make sure the field name is valid.", t.Key) case *ast.Ellipsis: e := NewTypeExprFromAst(pkgName, t.Elt) 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) + err = 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) + return NewTypeExprFromData(err, "", 0, false) } // TypeName returns the fully-qualified type name for this expression. @@ -61,7 +61,7 @@ func (e TypeExpr) TypeName(pkgOverride string) string { return e.Expr[:e.pkgIndex] + pkgName + "." + e.Expr[e.pkgIndex:] } -var builtInTypes = map[string]struct{}{ +var builtInTypes = map[string]struct{}{ //nolint:gochecknoglobals "bool": {}, "byte": {}, "complex128": {}, diff --git a/parser/reflect.go b/parser/reflect.go index 0d663d9..f27eb1b 100644 --- a/parser/reflect.go +++ b/parser/reflect.go @@ -8,6 +8,7 @@ package parser // It catalogs the controllers, their methods, and their arguments. import ( + "errors" "go/ast" "go/parser" "go/scanner" @@ -83,7 +84,8 @@ func (pc *processContainer) processPath(path string, info os.FileInfo, err error 0) if err != nil { - if errList, ok := err.(scanner.ErrorList); ok { + var errList scanner.ErrorList + if errors.As(err, &errList) { pos := errList[0].Pos newError := &utils.SourceError{ SourceType: ".go source", diff --git a/parser2/source_processor.go b/parser2/source_processor.go index c42e12d..a262535 100644 --- a/parser2/source_processor.go +++ b/parser2/source_processor.go @@ -1,6 +1,7 @@ package parser2 import ( + "errors" "go/ast" "go/parser" "go/scanner" @@ -150,7 +151,8 @@ func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error) 0) if err != nil { - if errList, ok := err.(scanner.ErrorList); ok { + var errList scanner.ErrorList + if errors.As(err, &errList) { pos := errList[0].Pos newError := &utils.SourceError{ SourceType: ".go source", diff --git a/revel/build_test.go b/revel/build_test.go index 4b2ef2b..021050b 100644 --- a/revel/build_test.go +++ b/revel/build_test.go @@ -19,7 +19,7 @@ func TestBuild(t *testing.T) { t.Run("Build", func(t *testing.T) { a := assert.New(t) c := newApp("build-test", model.NEW, nil, a) - main.Commands[model.NEW].RunWith(c) + a.Nil(main.Commands[model.NEW].RunWith(c), "failed to run new") c.Index = model.BUILD c.Build.TargetPath = filepath.Join(gopath, "build-test", "target") c.Build.ImportPath = c.ImportPath @@ -34,7 +34,7 @@ func TestBuild(t *testing.T) { "build-test-WithFlags/app.AppVersion=SomeValue", "build-test-WithFlags/app.SomeOtherValue=SomeValue", } - main.Commands[model.NEW].RunWith(c) + a.Nil(main.Commands[model.NEW].RunWith(c), "failed to run new") c.Index = model.BUILD c.Build.TargetPath = filepath.Join(gopath, "build-test", "target") c.Build.ImportPath = c.ImportPath diff --git a/revel/clean_test.go b/revel/clean_test.go index 27c3e0a..3fd0179 100644 --- a/revel/clean_test.go +++ b/revel/clean_test.go @@ -19,9 +19,12 @@ func TestClean(t *testing.T) { t.Run("Clean", func(t *testing.T) { a := assert.New(t) c := newApp("clean-test", model.NEW, nil, a) - main.Commands[model.NEW].RunWith(c) + + a.Nil(main.Commands[model.NEW].RunWith(c), "failed to run new") + c.Index = model.TEST - main.Commands[model.TEST].RunWith(c) + a.Nil(main.Commands[model.TEST].RunWith(c), "failed to run test") + a.True(utils.Exists(filepath.Join(gopath, "clean-test", "app", "tmp", "main.go")), "Missing main from path "+filepath.Join(gopath, "clean-test", "app", "tmp", "main.go")) c.Clean.ImportPath = c.ImportPath diff --git a/revel/command_test.go b/revel/command_test.go index 74c4fd6..e07940d 100644 --- a/revel/command_test.go +++ b/revel/command_test.go @@ -33,7 +33,10 @@ func setup(suffix string, a *assert.Assertions) string { // But if you change into that directory and read the current folder it is // /private/var/folders/nz/vv4_9tw56nv9k3tkvyszvwg80000gn/T/revel-test/revel-test-build // So to make this work on darwin this code was added - os.Chdir(gopath) + if err := os.Chdir(gopath); err != nil { + panic(err) + } + newwd, _ := os.Getwd() gopath = newwd defaultBuild := build.Default diff --git a/revel/new.go b/revel/new.go index a1461ab..7363738 100644 --- a/revel/new.go +++ b/revel/new.go @@ -18,6 +18,8 @@ import ( "github.com/revel/cmd/utils" ) +const ErrNoSkeleton Error = "failed to find skeleton in filepath" + var cmdNew = &Command{ UsageLine: "new -i [path] -s [skeleton]", Short: "create a skeleton Revel application", @@ -92,7 +94,9 @@ func newApp(c *model.CommandConfig) (err error) { // This kicked off the download of the revel app, not needed for vendor if !c.Vendored { // At this point the versions can be set - c.SetVersions() + if err = c.SetVersions(); err != nil { + return + } } // copy files to new app directory @@ -114,11 +118,18 @@ func newApp(c *model.CommandConfig) (err error) { // Need to prep the run command c.Run.ImportPath = c.ImportPath updateRunConfig(c, nil) - c.UpdateImportPath() - runApp(c) + + if err = c.UpdateImportPath(); err != nil { + return + } + + if err = runApp(c); err != nil { + return + } } else { fmt.Fprintln(os.Stdout, "\nYou can run it with:\n revel run -a ", c.ImportPath) } + return } @@ -129,13 +140,16 @@ func createModVendor(c *model.CommandConfig) (err error) { utils.CmdInit(goModCmd, !c.Vendored, c.AppPath) utils.Logger.Info("Exec:", "args", goModCmd.Args, "env", goModCmd.Env, "workingdir", goModCmd.Dir) + getOutput, err := goModCmd.CombinedOutput() if c.New.Callback != nil { err = c.New.Callback() } + if err != nil { return utils.NewBuildIfError(err, string(getOutput)) } + return } @@ -206,7 +220,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("%w %s %s", ErrNoSkeleton, fullpath, sp.String()) } case "git": fallthrough diff --git a/revel/package_test.go b/revel/package_test.go index eb179fa..edb7e8a 100644 --- a/revel/package_test.go +++ b/revel/package_test.go @@ -17,7 +17,7 @@ func TestPackage(t *testing.T) { t.Run("Package", func(t *testing.T) { a := assert.New(t) c := newApp("package-test", model.NEW, nil, a) - main.Commands[model.NEW].RunWith(c) + a.Nil(main.Commands[model.NEW].RunWith(c), "failed to run new") c.Index = model.PACKAGE c.Package.ImportPath = c.ImportPath a.Nil(main.Commands[model.PACKAGE].RunWith(c), "Failed to run package-test") diff --git a/revel/revel.go b/revel/revel.go index 73512f4..cd5069a 100644 --- a/revel/revel.go +++ b/revel/revel.go @@ -22,6 +22,16 @@ import ( "github.com/revel/cmd/utils" ) +// Error is used for constant errors. +type Error string + +// Error implements the error interface. +func (e Error) Error() string { + return string(e) +} + +const ErrInvalidCommandLine Error = "invalid command line arguments" + const ( // RevelCmdImportPath Revel framework cmd tool import path. RevelSkeletonsImportPath = "github.com/revel/skeletons" @@ -138,7 +148,7 @@ func ParseArgs(c *model.CommandConfig, parser *flags.Parser, args []string) (err if !Commands[c.Index].UpdateConfig(c, extraArgs) { buffer := &bytes.Buffer{} parser.WriteHelp(buffer) - err = fmt.Errorf("invalid command line arguments %v\n%s", extraArgs, buffer.String()) + err = fmt.Errorf("%w %v\n%s", ErrInvalidCommandLine, extraArgs, buffer.String()) } return diff --git a/revel/version.go b/revel/version.go index 452c757..c7d72de 100644 --- a/revel/version.go +++ b/revel/version.go @@ -82,7 +82,9 @@ func (v *VersionCommand) RunWith(c *model.CommandConfig) (err error) { if e := cmd.Start(); e != nil { fmt.Println("Go command error ", e) } else { - cmd.Wait() + if err = cmd.Wait(); err != nil { + return + } } return @@ -188,7 +190,9 @@ 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.ReplaceAll(r.Value, `"`, "")) + if err = version.ParseVersion(strings.ReplaceAll(r.Value, `"`, "")); err != nil { + return + } case "BuildDate": version.BuildDate = r.Value case "MinimumGoVersion": @@ -202,7 +206,12 @@ func (v *VersionCommand) versionFromBytes(sourceStream []byte) (version *model.V // Fetch the local version of revel from the file system. func (v *VersionCommand) updateLocalVersions() { v.cmdVersion = &model.Version{} - v.cmdVersion.ParseVersion(cmd.Version) + + if err := v.cmdVersion.ParseVersion(cmd.Version); err != nil { + utils.Logger.Warn("Error parsing version", "error", err, "version", cmd.Version) + return + } + v.cmdVersion.BuildDate = cmd.BuildDate v.cmdVersion.MinGoVersion = cmd.MinimumGoVersion diff --git a/revel/version_test.go b/revel/version_test.go index 59f1751..e907438 100644 --- a/revel/version_test.go +++ b/revel/version_test.go @@ -1,6 +1,7 @@ package main_test import ( + "errors" "os" "path/filepath" "testing" @@ -34,8 +35,9 @@ func TestVersion(t *testing.T) { c.Version.ImportPath = c.ImportPath a.Nil(main.Commands[model.VERSION].RunWith(c), "Failed to run version-test") }) + if !t.Failed() { - if err := os.RemoveAll(gopath); err != nil && err != os.ErrNotExist { + if err := os.RemoveAll(gopath); err != nil && !errors.Is(err, os.ErrNotExist) { a.Fail("Failed to remove test path", err.Error()) } } diff --git a/utils/build_error.go b/utils/build_error.go index 1c529b5..6b6de3e 100644 --- a/utils/build_error.go +++ b/utils/build_error.go @@ -1,6 +1,7 @@ package utils import ( + "errors" "fmt" "regexp" "strconv" @@ -30,7 +31,8 @@ func NewBuildError(message string, args ...interface{}) (b *BuildError) { // 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 { + var berr *BuildError + if errors.As(err, &berr) { // This is already a build error so just append the args berr.Args = append(berr.Args, args...) return berr @@ -50,16 +52,16 @@ func (b *BuildError) Error() string { // Parse the output of the "go build" command. // Return a detailed Error. -func NewCompileError(importPath, errorLink string, error error) *SourceError { +func NewCompileError(importPath, errorLink string, err error) *SourceError { // Get the stack from the error errorMatch := regexp.MustCompile(`(?m)^([^:#]+):(\d+):(\d+:)? (.*)$`). - FindSubmatch([]byte(error.Error())) + FindSubmatch([]byte(err.Error())) if errorMatch == nil { - errorMatch = regexp.MustCompile(`(?m)^(.*?):(\d+):\s(.*?)$`).FindSubmatch([]byte(error.Error())) + errorMatch = regexp.MustCompile(`(?m)^(.*?):(\d+):\s(.*?)$`).FindSubmatch([]byte(err.Error())) if errorMatch == nil { - Logger.Error("Failed to parse build errors", "error", error) + Logger.Error("Failed to parse build errors", "error", err) return &SourceError{ SourceType: "Go code", Title: "Go Compilation Error", @@ -69,7 +71,7 @@ func NewCompileError(importPath, errorLink string, error error) *SourceError { errorMatch = append(errorMatch, errorMatch[3]) - Logger.Error("Build errors", "errors", error) + Logger.Error("Build errors", "errors", err) } // Read the source for the offending file. diff --git a/utils/file.go b/utils/file.go index f0637de..e1b720c 100644 --- a/utils/file.go +++ b/utils/file.go @@ -150,8 +150,9 @@ func MustChmod(filename string, mode os.FileMode) { // 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) + var serr *SourceError + if (errors.As(err, &serr) && serr != nil) || err != nil { + Logger.Panicf("Abort: %s: %s %s", msg, serr, err) } } @@ -348,9 +349,17 @@ func FindSrcPaths(appPath string, packageList []string, packageResolver func(pkg return } +// Error is used for constant errors. +type Error string + +// Error implements the error interface. +func (e Error) Error() string { + return string(e) +} + var ( - NO_APP_FOUND = errors.New("no app found") - NO_REVEL_FOUND = errors.New("no revel found") + ErrNoApp Error = "no app found" + ErrNoRevel Error = "no revel found" ) // Find the full source dir for the import path, uses the build.Default.GOPATH to search for the directory. @@ -387,9 +396,9 @@ func findSrcPaths(appPath string, packagesList []string) (sourcePathsmap map[str } if !found { if packageName == "github.com/revel/revel" { - err = NO_REVEL_FOUND + err = ErrNoRevel } else { - err = NO_APP_FOUND + err = ErrNoApp } missingList = append(missingList, packageName) } diff --git a/utils/log.go b/utils/log.go index 6da97e1..5aa060a 100644 --- a/utils/log.go +++ b/utils/log.go @@ -33,7 +33,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. -func Retry(format string, args ...interface{}) { +func Retryf(format string, args ...interface{}) { // Ensure the user's command prompt starts on the next line. if !strings.HasSuffix(format, "\n") { format += "\n" diff --git a/version.go b/version.go index 9fca510..3542e12 100644 --- a/version.go +++ b/version.go @@ -5,7 +5,7 @@ package cmd const ( - // Version current Revel version + // Version current Revel version. Version = "1.1.0-dev" // BuildDate latest commit/release date. diff --git a/watcher/watcher.go b/watcher/watcher.go index 9a7c3f2..c50587c 100644 --- a/watcher/watcher.go +++ b/watcher/watcher.go @@ -46,16 +46,16 @@ type Watcher struct { timerMutex *sync.Mutex // A mutex to prevent concurrent updates refreshChannel chan *utils.SourceError refreshChannelCount int - refreshTimerMS time.Duration // The number of milliseconds between refreshing builds + refreshInterval time.Duration // The interval between refreshing builds } // Creates a new watched based on the container. func NewWatcher(paths *model.RevelContainer, eagerRefresh bool) *Watcher { return &Watcher{ - forceRefresh: false, - lastError: -1, - paths: paths, - refreshTimerMS: time.Duration(paths.Config.IntDefault("watch.rebuild.delay", 1000)), + forceRefresh: false, + lastError: -1, + paths: paths, + refreshInterval: time.Duration(paths.Config.IntDefault("watch.rebuild.delay", 1000)) * time.Millisecond, eagerRefresh: eagerRefresh || paths.DevMode && paths.Config.BoolDefault("watch", true) && @@ -163,7 +163,10 @@ func (w *Watcher) NotifyWhenUpdated(listener Listener, watcher *fsnotify.Watcher } else { // Run refresh in parallel go func() { - w.notifyInProcess(listener) + if err := w.notifyInProcess(listener); err != nil { + utils.Logger.Error("failed to notify", + "error", err) + } }() } } @@ -238,11 +241,11 @@ func (w *Watcher) notifyInProcess(listener Listener) (err *utils.SourceError) { w.forceRefresh = true if w.refreshTimer != nil { utils.Logger.Info("Found existing timer running, resetting") - w.refreshTimer.Reset(time.Millisecond * w.refreshTimerMS) + w.refreshTimer.Reset(w.refreshInterval) shouldReturn = true w.refreshChannelCount++ } else { - w.refreshTimer = time.NewTimer(time.Millisecond * w.refreshTimerMS) + w.refreshTimer = time.NewTimer(w.refreshInterval) } }()