Compare commits

..

23 Commits

Author SHA1 Message Date
Steve
3cec19ee62 Merge pull request #187 from Laur1nMartins/master
Fixed parsing of user defined linker flags
2020-07-21 09:12:17 -07:00
Steve
236499f9e5 Merge pull request #192 from revel/hotfix-1
Added local import map to getControllerFunc lookup
2020-07-14 22:10:25 -07:00
notzippy@gmail.com
42e0e3bf2b Added local import map to getControllerFunc lookup 2020-07-14 21:46:37 -07:00
Steve
b0484c9279 Merge pull request #188 from revel/hotfix-1
Fixed issues with test cases and launching app using the run mode
2020-07-14 13:16:12 -07:00
notzippy@gmail.com
c7f4307a5d Changed the local code walker to include all go files in the base path, and not just the app path 2020-07-14 12:45:10 -07:00
notzippy@gmail.com
ebc9c73ba0 Modified run command so launching command would be properly treated 2020-07-13 22:35:22 -07:00
Steve
2e2f22ad7d remove go 1.12 test 2020-07-13 09:40:56 -07:00
Steve
357c382d96 Version compatible Check
Increase version compatibility to 1.0 - 1.9
2020-07-13 09:39:57 -07:00
Laurin
6d4ae81af9 Fixed parsing of user defined linker flags 2020-07-12 11:09:57 +02:00
notzippy@gmail.com
6ecc0a7c0a release v1.0.0 2020-07-11 22:57:36 -07:00
Steve
d8117a33d3 Merge pull request #186 from notzippy/go-mod
Removed version update from Revel
2020-06-06 07:50:58 -07:00
notzippy@gmail.com
6371373eb5 Removed version update
Version control is maintained through go.mod file
Modified harness to only kill the application if not responded after 60 seconds in windows
2020-06-06 07:49:10 -07:00
Steve
28ac65f1c1 Merge pull request #185 from notzippy/go-mod
Go mod updates
2020-05-19 02:42:57 -07:00
notzippy@gmail.com
5070fb8be0 Fixed issue with new and run flag
Updated tests to run final test in non gopath, with new name
2020-05-19 02:23:18 -07:00
notzippy@gmail.com
904cfa2995 Added some informational messages while download 2020-05-18 12:43:00 -07:00
notzippy@gmail.com
223bd3b7c0 Added manual scan on packages in app folder
This allows for source code generation. Packages in <application>/app folder are scanned manually as opposed to the `packages.Load` scan which will fast fail on compile error, and leave you with go files with no syntax.
2020-05-18 11:47:01 -07:00
notzippy@gmail.com
4987ee8319 Added verbose logging to building / testing a no-vendor app
Removed section which raises an error when examining packages, we dont need to check for errors on foreign packages since we are importing only a slice of the data
2020-05-17 05:58:28 -07:00
notzippy@gmail.com
4bab4409b9 Updated Revel command
Added a check to see if harness had already started, saves a recompile on load
Added check to source info for local import renames
Removed the go/build check for path and just check existence of the path
Formatting updates
2020-05-13 22:26:05 -07:00
notzippy@gmail.com
741f49236a Updated scanner
Removed scanning all the import statements, this is not needed
Added recursive scan for revel import path to pick up testunits
2020-05-08 15:41:20 -07:00
Steve
60b88a42c9 Merge pull request #180 from notzippy/go-mod
Initial commit to go mod
2020-05-03 21:47:09 -07:00
notzippy@gmail.com
49eef29bb5 Build and Historic build updates
Modified GOPATH to not modify build with go.mod
Updated go.mod to version 1.12
Updated harness to setup listener before killing process
Updated notvendored flag to --no-vendor
Updated command_config to ensure no-vendor can be build
Added additional checks in source path lookup
2020-05-03 13:39:48 -07:00
notzippy@gmail.com
9d3a554bec Updates
Updated NotVendored flag
Updated travis matrix
Updated build log
2020-04-29 22:01:28 -07:00
notzippy@gmail.com
36bd6b944a Corrected flags 2020-04-29 21:48:11 -07:00
24 changed files with 490 additions and 361 deletions

View File

@@ -1,15 +1,14 @@
language: go
go:
- "1.12.x"
# - "1.13.x"
# - "1.14.x"
# - "tip"
- "1.13.x"
- "1.14.x"
- "tip"
os:
# - osx
- osx
- linux
# - windows
- windows
sudo: false
@@ -19,22 +18,23 @@ branches:
- develop
env:
# Setting environments variables
- GO111MODULE=on
install:
# Setting environments variables
- export PATH=$PATH:$HOME/gopath/bin
- export REVEL_BRANCH="develop"
- 'if [[ "$TRAVIS_BRANCH" == "master" ]]; then export REVEL_BRANCH="master"; fi'
- 'echo "Travis branch: $TRAVIS_BRANCH, Revel dependency branch: $REVEL_BRANCH"'
#- git clone -b $REVEL_BRANCH git://github.com/revel/revel ../revel/
#- git clone -b $REVEL_BRANCH git://github.com/revel/modules ../modules/
# Since travis already checks out go build the commandline tool (revel)
- go get -t -v github.com/revel/cmd/revel
- echo $GOPATH
- echo $PATH
- mkdir $HOME/GOPATH_PROTECTED
- export GOPATH=$HOME/GOPATH_PROTECTED
- go build -o $HOME/gopath/bin/revel github.com/revel/cmd/revel
- pwd
- env
script:
- go test -v github.com/revel/cmd/revel/...
# Ensure the new-app flow works (plus the other commands).
#- revel version
#- revel new my/testapp
@@ -46,23 +46,25 @@ script:
#- revel package my/testapp prod
# Ensure the new-app flow works (plus the other commands).
- revel new --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v
- revel test --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v
- revel clean --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v
- revel build --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v -t build/testapp2
- revel build --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v -t build/testapp2 -m prod
- revel package --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v
- revel package --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v -m prod
- revel new --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 --package revelframework.com -v
- revel test --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 -v
- revel clean --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 -v
- revel build --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 -v -t build/testapp2
- revel build --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 -v -t build/testapp2 -m prod
- revel package --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 -v
- revel package --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 -v -m prod
- revel new --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -v -a my/testapp3 -V
- revel test --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -v -a my/testapp3
- revel clean --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -v -a my/testapp3
- revel build --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp3 -t build/testapp3
- revel build --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp3 -t build/testapp3 -m prod
- revel package --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp3
- revel package --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp3 -m prod
- export INITIALWD=$PWD
# Check build works with no-vendor flag
- cd $GOPATH
- export GO111MODULE=auto
- revel new -a my/testapp2 --no-vendor -v
- revel test -a my/testapp2 -v
- go test -v github.com/revel/cmd/revel/...
# Check non verbose build, outside of GO path
- cd $INITIALWD
- revel new --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp3 --package revelframework.com
- revel test --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp3
matrix:
allow_failures:

7
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/revel/cmd
go 1.13
go 1.12
require (
github.com/BurntSushi/toml v0.3.1 // indirect
@@ -8,7 +8,7 @@ require (
github.com/fsnotify/fsnotify v1.4.7
github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1 // indirect
github.com/jessevdk/go-flags v1.4.0
github.com/mattn/go-colorable v0.1.4
github.com/mattn/go-colorable v0.1.6
github.com/myesui/uuid v1.0.0 // indirect
github.com/pkg/errors v0.9.1
github.com/revel/config v0.21.0
@@ -19,7 +19,8 @@ require (
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-20200202094626-16171245cfb2 // indirect
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 // indirect
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 // 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

60
go.sum Normal file
View File

@@ -0,0 +1,60 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/agtorre/gocolorize v1.0.0 h1:TvGQd+fAqWQlDjQxSKe//Y6RaxK+RHpEU9X/zPmHW50=
github.com/agtorre/gocolorize v1.0.0/go.mod h1:cH6imfTkHVBRJhSOeSeEZhB4zqEYSq0sXuIyehgZMIY=
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/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1 h1:KUDFlmBg2buRWNzIcwLlKvfcnujcHQRQ1As1LoaCLAM=
github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1/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-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=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
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/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/go.mod h1:TmlwoRLDvgRjoTe6rbsxIaka/CulzYrgfef7iNJcEWY=
github.com/revel/revel v0.21.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/go.mod h1:mMgcE1RHFUFqe5AfiwlINXisXfDGro23fWdPUfOMjRY=
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/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
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-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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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/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=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/stack.v0 v0.0.0-20141108040640-9b43fcefddd0 h1:lMH45EKqD8Nf6LwoF+43YOKjOAEEHQRVgDyG8RCV4MU=
gopkg.in/stack.v0 v0.0.0-20141108040640-9b43fcefddd0/go.mod h1:kl/bNzW/jgTgUOCGDj3XPn9/Hbfhw6pjfBRUnaTioFQ=
gopkg.in/stretchr/testify.v1 v1.2.2/go.mod h1:QI5V/q6UbPmuhtm10CaFZxED9NreB8PnFYN9JcR6TxU=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@@ -12,6 +12,7 @@ import (
"os"
"os/exec"
"time"
"sync"
"github.com/revel/cmd/model"
"github.com/revel/cmd/utils"
@@ -64,8 +65,8 @@ func NewAppCmd(binPath string, port int, runMode string, paths *model.RevelConta
func (cmd AppCmd) Start(c *model.CommandConfig) error {
listeningWriter := &startupListeningWriter{os.Stdout, make(chan bool), c, &bytes.Buffer{}}
cmd.Stdout = listeningWriter
utils.Logger.Info("Exec app:", "path", cmd.Path, "args", cmd.Args, "dir", cmd.Dir, "env", cmd.Env)
utils.CmdInit(cmd.Cmd, !c.Vendored, c.AppPath)
utils.Logger.Info("Exec app:", "path", cmd.Path, "args", cmd.Args, "dir", cmd.Dir, "env", cmd.Env)
if err := cmd.Cmd.Start(); err != nil {
utils.Logger.Fatal("Error running:", "error", err)
}
@@ -92,7 +93,8 @@ func (cmd AppCmd) Start(c *model.CommandConfig) error {
}
// Run the app server inline. Never returns.
func (cmd AppCmd) Run() {
func (cmd AppCmd) Run(c *model.CommandConfig) {
utils.CmdInit(cmd.Cmd, !c.Vendored, c.AppPath)
utils.Logger.Info("Exec app:", "path", cmd.Path, "args", cmd.Args)
if err := cmd.Cmd.Run(); err != nil {
utils.Logger.Fatal("Error running:", "error", err)
@@ -105,33 +107,18 @@ 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(int(cmd.Process.Pid)); err != nil {
// Server has already exited
utils.Logger.Info("Killing revel server pid", "pid", cmd.Process.Pid)
utils.Logger.Info("Server not running revel server pid", "pid", cmd.Process.Pid)
return
}
// Send an interrupt signal to allow for a graceful shutdown
utils.Logger.Info("Killing revel server pid", "pid", cmd.Process.Pid)
var err error
if runtime.GOOS == "windows" {
// os.Interrupt is not available on windows
err = cmd.Process.Signal(os.Kill)
} else {
err = cmd.Process.Signal(os.Interrupt)
}
if err != nil {
utils.Logger.Error(
"Revel app failed to kill process.",
"processid", cmd.Process.Pid,"error",err,
"killerror", cmd.Process.Kill())
return
}
// Wait for the shutdown
// Wait for the shutdown channel
waitMutex := &sync.WaitGroup{}
waitMutex.Add(1)
ch := make(chan bool, 1)
go func() {
waitMutex.Done()
s, err := cmd.Process.Wait()
defer func() {
ch <- true
@@ -143,6 +130,25 @@ func (cmd AppCmd) Kill() {
utils.Logger.Info("Revel App exited", "state", s.String())
}
}()
// Wait for the channel to begin waiting
waitMutex.Wait()
// Send an interrupt signal to allow for a graceful shutdown
utils.Logger.Info("Killing revel server pid", "pid", cmd.Process.Pid)
var err error
if runtime.GOOS != "windows" {
// os.Interrupt is not available on windows
err = cmd.Process.Signal(os.Interrupt)
}
if err != nil {
utils.Logger.Info(
"Revel app already exited.",
"processid", cmd.Process.Pid, "error", err,
"killerror", cmd.Process.Kill())
return
}
// Use a timer to ensure that the process exits
utils.Logger.Info("Waiting to exit")

View File

@@ -102,28 +102,8 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err
utils.Logger.Fatal("Go executable not found in PATH.")
}
// Detect if deps tool should be used (is there a vendor folder ?)
useVendor := utils.DirExists(filepath.Join(paths.BasePath, "vendor"))
basePath := paths.BasePath
for !useVendor {
basePath = filepath.Dir(basePath)
found := false
// Check to see if we are still in the GOPATH
for _, gopath := range filepath.SplitList(build.Default.GOPATH) {
if strings.HasPrefix(basePath, gopath) {
found = true
break
}
}
if !found {
break
} else {
useVendor = utils.DirExists(filepath.Join(basePath, "vendor"))
}
}
// Binary path is a combination of BasePath/target/app directory, app's import path and its name.
binName := filepath.Join(paths.BasePath, "target", "app", paths.ImportPath, filepath.Base(paths.BasePath))
// Binary path is a combination of target/app directory, app's import path and its name.
binName := filepath.Join("target", "app", paths.ImportPath, filepath.Base(paths.BasePath))
// Change binary path for Windows build
goos := runtime.GOOS
@@ -149,7 +129,7 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err
goModCmd := exec.Command(goPath, append([]string{"mod"}, strings.Split(gomod, " ")...)...)
utils.CmdInit(goModCmd, !c.Vendored, c.AppPath)
output, err := goModCmd.CombinedOutput()
utils.Logger.Infof("Gomod applied ", "output", string(output))
utils.Logger.Info("Gomod applied ", "output", string(output))
// If the build succeeded, we're done.
if err != nil {
@@ -165,7 +145,7 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err
}
buildTime := time.Now().UTC().Format(time.RFC3339)
versionLinkerFlags := fmt.Sprintf("-X %s/app.AppVersion=%s -X %s/app.BuildTime=%s",
versionLinkerFlags := fmt.Sprintf("-X '%s/app.AppVersion=%s' -X '%s/app.BuildTime=%s'",
paths.ImportPath, appVersion, paths.ImportPath, buildTime)
// Append any build flags specified, they will override existing flags
@@ -180,16 +160,15 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err
if !contains(c.BuildFlags, "build") {
flags = []string{"build"}
}
flags = append(flags, c.BuildFlags...)
if !contains(flags, "-ldflags") {
ldflags := "-ldflags= " + versionLinkerFlags
// Add in build flags
// Add user defined build flags
for i := range c.BuildFlags {
ldflags += "-X '" + c.BuildFlags[i] + "'"
ldflags += " -X '" + c.BuildFlags[i] + "'"
}
flags = append(flags, ldflags)
}
if !contains(flags, "-tags") {
if !contains(flags, "-tags") && buildTags != "" {
flags = append(flags, "-tags", buildTags)
}
if !contains(flags, "-o") {
@@ -197,9 +176,6 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err
}
}
// Add in build flags
flags = append(flags, c.BuildFlags...)
// Note: It's not applicable for filepath.* usage
flags = append(flags, path.Join(paths.ImportPath, "app", "tmp"))
@@ -478,7 +454,7 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.SourceEr
return compileError
}
// RevelMainTemplate template for app/tmp/main.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

View File

@@ -16,6 +16,7 @@ package harness
import (
"crypto/tls"
"fmt"
"time"
"go/build"
"io"
"net"
@@ -56,6 +57,8 @@ 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
}
func (h *Harness) renderError(iw http.ResponseWriter, ir *http.Request, err error) {
@@ -202,6 +205,21 @@ 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
func (h *Harness) Refresh() (err *utils.SourceError) {
t := time.Now();
fmt.Println("Changed detected, recompiling")
err = h.refresh()
if err!=nil && !h.ranOnce && h.useProxy {
addr := fmt.Sprintf("%s:%d", h.paths.HTTPAddr, h.paths.HTTPPort)
fmt.Printf("\nError compiling code, to view error details see proxy running on http://%s\n\n",addr)
}
h.ranOnce = true
fmt.Printf("\nTime to recompile %s\n",time.Now().Sub(t).String())
return
}
func (h *Harness) refresh() (err *utils.SourceError) {
// Allow only one thread to rebuild the process
// If multiple requests to rebuild are queued only the last one is executed on
// So before a build is started we wait for a second to determine if
@@ -281,7 +299,8 @@ func (h *Harness) Run() {
paths = append(paths, h.paths.CodePaths...)
h.watcher = watcher.NewWatcher(h.paths, false)
h.watcher.Listen(h, paths...)
h.watcher.Notify()
go h.Refresh()
// h.watcher.Notify()
if h.useProxy {
go func() {
@@ -292,6 +311,7 @@ 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(
@@ -308,10 +328,12 @@ func (h *Harness) Run() {
}()
}
// Kill the app on signal.
// Make a new channel to listen for the interrupt event
ch := make(chan os.Signal)
signal.Notify(ch, os.Interrupt, os.Kill)
<-ch
// Kill the app and exit
if h.app != nil {
h.app.Kill()
}

View File

@@ -6,7 +6,7 @@ type (
ImportCommand
SkeletonPath string `short:"s" long:"skeleton" description:"Path to skeleton folder (Must exist on GO PATH)" required:"false"`
Package string `short:"p" long:"package" description:"The package name, this becomes the repfix to the app name, if defined vendored is set to true" required:"false"`
NotVendored bool `short:"V" long:"vendor" description:"True if project should not be configured with a go.mod"`
NotVendored bool `long:"no-vendor" description:"True if project should not be configured with a go.mod, this requires you to have the project on the GOPATH, this is only compatible with go versions v1.12 or older"`
Run bool `short:"r" long:"run" description:"True if you want to run the application right away"`
Callback func() error
}

View File

@@ -2,7 +2,5 @@ package command
type (
Version struct {
ImportCommand
Update bool `short:"u" long:"update" description:"Update the framework and modules" required:"false"`
UpdateVersion string `long:"update-version" description:"Specify the version the revel and app will be switched to" required:"false"`
}
)

View File

@@ -41,14 +41,14 @@ type (
ImportPath string // The import path (relative to a GOPATH)
GoPath string // The GoPath
GoCmd string // The full path to the go executable
SrcRoot string // The source root
//SrcRoot string // The source root
AppPath string // The application path (absolute)
AppName string // The application name
HistoricBuildMode bool `long:"historic-build-mode" description:"If set the code is scanned using the original parsers, not the go.1.11+"` // True if debug is active
Vendored bool // True if the application is vendored
PackageResolver func(pkgName string) error // a package resolver for the config
BuildFlags []string `short:"X" long:"build-flags" description:"These flags will be used when building the application. May be specified multiple times, only applicable for Build, Run, Package, Test commands"`
GoModFlags []string `long:"gomod-flags" description:"These flags will execut go mod commands for each flag, this happens during the build process"`
GoModFlags []string `long:"gomod-flags" description:"These flags will execute go mod commands for each flag, this happens during the build process"`
New command.New `command:"new"`
Build command.Build `command:"build"`
Run command.Run `command:"run"`
@@ -143,7 +143,7 @@ func (c *CommandConfig) UpdateImportPath() error {
}
func (c *CommandConfig) initAppFolder() (err error) {
utils.Logger.Info("initAppFolder", "vendored", c.Vendored)
utils.Logger.Info("initAppFolder", "vendored", c.Vendored, "build-gopath", build.Default.GOPATH, "gopath-env", os.Getenv("GOPATH"))
// check for go executable
c.GoCmd, err = exec.LookPath("go")
@@ -174,8 +174,10 @@ func (c *CommandConfig) initAppFolder() (err error) {
// Use app folder to read the go.mod if it exists and extract the package information
goModFile := filepath.Join(appFolder, "go.mod")
utils.Logger.Info("Checking gomod, extracting from file", "path", goModFile,"exists", utils.Exists(goModFile))
if utils.Exists(goModFile) {
c.Vendored = true
utils.Logger.Info("Found go mod, extracting from file", "path", goModFile)
file, err := ioutil.ReadFile(goModFile)
if err != nil {
return err
@@ -184,30 +186,17 @@ func (c *CommandConfig) initAppFolder() (err error) {
if strings.Index(line, "module ") == 0 {
c.ImportPath = strings.TrimSpace(strings.Split(line, "module")[1])
c.AppPath = appFolder
c.SrcRoot = appFolder
utils.Logger.Info("Set application path and package based on go mod", "path", c.AppPath, "sourceroot", c.SrcRoot)
//c.SrcRoot = appFolder
utils.Logger.Info("Set application path and package based on go mod", "path", c.AppPath)
return nil
}
}
}
utils.Logger.Debug("Trying to set path based on gopath")
// lookup go path
c.GoPath = build.Default.GOPATH
if c.GoPath == "" {
utils.Logger.Fatal("Abort: GOPATH environment variable is not set. " +
"Please refer to http://golang.org/doc/code.html to configure your Go environment.")
}
// 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
// gopath, and discover which import exists - If none exist this is an error except in the case
// where we are dealing with new which is a special case where we will attempt to target the working directory first
workingDir, _ := os.Getwd()
goPathList := filepath.SplitList(c.GoPath)
bestpath := ""
if !c.Vendored {
// c.SrcRoot = appFolder
c.AppPath = appFolder
} else if c.Index != NEW || (c.Index == NEW && c.New.NotVendored) {
workingDir, _ := os.Getwd()
goPathList := filepath.SplitList(c.GoPath)
bestpath := ""
for _, path := range goPathList {
if c.Index == NEW {
// If the GOPATH is part of the working dir this is the most likely target
@@ -216,77 +205,59 @@ func (c *CommandConfig) initAppFolder() (err error) {
}
} else {
if utils.Exists(filepath.Join(path, "src", c.ImportPath)) {
c.SrcRoot = path
bestpath = path
break
}
}
}
if len(c.SrcRoot) == 0 && len(bestpath) > 0 {
c.SrcRoot = bestpath
utils.Logger.Info("Source root", "cwd", workingDir, "gopath", c.GoPath, "c.ImportPath", c.ImportPath, "bestpath", bestpath)
if len(bestpath) > 0 {
c.AppPath = filepath.Join(bestpath, "src", c.ImportPath)
}
// Recalculate the appFolder because we are using a GOPATH
} else {
c.SrcRoot = appFolder
// This is new and not vendored, so the app path is the appFolder
c.AppPath = appFolder
}
utils.Logger.Info("Source root", "path", c.SrcRoot, "cwd", workingDir, "gopath", c.GoPath, "bestpath", bestpath)
// If source root is empty and this isn't a version then skip it
if len(c.SrcRoot) == 0 {
if c.Index == NEW {
c.SrcRoot = c.New.ImportPath
} else {
if c.Index != VERSION {
utils.Logger.Fatal("Abort: could not create a Revel application outside of GOPATH.")
}
return nil
}
}
// set go src path
if c.Vendored {
c.AppPath = c.SrcRoot
} else {
c.SrcRoot = filepath.Join(c.SrcRoot, "src")
c.AppPath = filepath.Join(c.SrcRoot, filepath.FromSlash(c.ImportPath))
}
utils.Logger.Info("Set application path", "path", c.AppPath)
utils.Logger.Info("Set application path", "path", c.AppPath, "vendored",c.Vendored, "importpath",c.ImportPath)
return nil
}
// Used to initialize the package resolver
func (c *CommandConfig) InitPackageResolver() {
c.initGoPaths()
utils.Logger.Info("InitPackageResolver", "useVendor", c.Vendored, "path", c.AppPath)
// This should get called when needed
c.PackageResolver = func(pkgName string) error {
//useVendor := utils.DirExists(filepath.Join(c.AppPath, "vendor"))
//var getCmd *exec.Cmd
utils.Logger.Info("Request for package ", "package", pkgName, "use vendor", c.Vendored)
var getCmd *exec.Cmd
print("Downloading related packages ...")
if c.Vendored {
goModCmd := exec.Command("go", "mod", "tidy")
utils.CmdInit(goModCmd, !c.Vendored, c.AppPath)
goModCmd.Run()
return nil
getCmd = exec.Command(c.GoCmd, "mod", "tidy")
} else {
utils.Logger.Info("No vendor folder detected, not using dependency manager to import package", "package", pkgName)
getCmd = exec.Command(c.GoCmd, "get", "-u", pkgName)
}
utils.CmdInit(getCmd, !c.Vendored, c.AppPath)
utils.Logger.Info("Go get command ", "exec", getCmd.Path, "dir", getCmd.Dir, "args", getCmd.Args, "env", getCmd.Env, "package", pkgName)
output, err := getCmd.CombinedOutput()
if err != nil {
utils.Logger.Error("Failed to import package", "error", err, "gopath", build.Default.GOPATH, "GO-ROOT", build.Default.GOROOT, "output", string(output))
}
println(" completed.")
return nil
}
}
// lookup and set Go related variables
func (c *CommandConfig) InitGoPathsOld() {
utils.Logger.Info("InitGoPaths")
// lookup go path
c.GoPath = build.Default.GOPATH
if c.GoPath == "" {
utils.Logger.Fatal("Abort: GOPATH environment variable is not set. " +
"Please refer to http://golang.org/doc/code.html to configure your Go environment.")
}
func (c *CommandConfig) initGoPaths() {
utils.Logger.Info("InitGoPaths", "vendored", c.Vendored)
// check for go executable
var err error
c.GoCmd, err = exec.LookPath("go")
@@ -294,50 +265,46 @@ func (c *CommandConfig) InitGoPathsOld() {
utils.Logger.Fatal("Go executable not found in PATH.")
}
if c.Vendored {
return
}
// lookup go path
c.GoPath = build.Default.GOPATH
if c.GoPath == "" {
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
// gopath, and discover which import exists - If none exist this is an error except in the case
// where we are dealing with new which is a special case where we will attempt to target the working directory first
workingDir, _ := os.Getwd()
goPathList := filepath.SplitList(c.GoPath)
bestpath := ""
for _, path := range goPathList {
if c.Index == NEW {
// If the GOPATH is part of the working dir this is the most likely target
if strings.HasPrefix(workingDir, path) {
bestpath = path
}
} else {
if utils.Exists(filepath.Join(path, "src", c.ImportPath)) {
c.SrcRoot = path
break
/*
// If source root is empty and this isn't a version then skip it
if len(c.SrcRoot) == 0 {
if c.Index == NEW {
c.SrcRoot = c.New.ImportPath
} else {
if c.Index != VERSION {
utils.Logger.Fatal("Abort: could not create a Revel application outside of GOPATH.")
}
return
}
}
}
utils.Logger.Info("Source root", "path", c.SrcRoot, "cwd", workingDir, "gopath", c.GoPath, "bestpath", bestpath)
if len(c.SrcRoot) == 0 && len(bestpath) > 0 {
c.SrcRoot = bestpath
}
// set go src path
c.SrcRoot = filepath.Join(c.SrcRoot, "src")
// If source root is empty and this isn't a version then skip it
if len(c.SrcRoot) == 0 {
if c.Index == NEW {
c.SrcRoot = c.New.ImportPath
} else {
if c.Index != VERSION {
utils.Logger.Fatal("Abort: could not create a Revel application outside of GOPATH.")
}
return
}
}
c.AppPath = filepath.Join(c.SrcRoot, filepath.FromSlash(c.ImportPath))
utils.Logger.Info("Set application path", "path", c.AppPath)
// set go src path
c.SrcRoot = filepath.Join(c.SrcRoot, "src")
*/
c.AppPath = filepath.Join(c.SrcRoot, filepath.FromSlash(c.ImportPath))
utils.Logger.Info("Set application path", "path", c.AppPath)
}
// Sets the versions on the command config

View File

@@ -57,7 +57,6 @@ func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered
// Look through the embedded types to see if the current type is among them.
for _, embeddedType := range spec.EmbeddedTypes {
// If so, add this type's simple name to the nodeQueue, and its spec to
// the filtered list.
if typeSimpleName == embeddedType.String() {
@@ -111,6 +110,7 @@ func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered
// ControllerSpecs returns the all the controllers that embeds
// `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 {
s.controllerSpecs = s.TypesThatEmbed(RevelImportPath + ".Controller", "controllers")
}

View File

@@ -21,7 +21,7 @@ type Version struct {
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.1.0"}, // Compatible with Framework V 1.0 - 1.1
{"1.0.0", "1.9.0"}, // Compatible with Framework V 1.0 - 1.9
}
// Parses a version like v1.2.3a or 1.2

View File

@@ -8,6 +8,7 @@ import (
"go/token"
"strings"
"path/filepath"
"github.com/revel/cmd/logger"
)
type (
@@ -31,14 +32,21 @@ func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *m
strings.Contains(p.PkgPath, "/tests/")
methodMap = map[string][]*model.MethodSpec{}
)
localImportMap := map[string]string{}
log := s.sourceProcessor.log.New("package", p.PkgPath)
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)
//println("*** checking", p.Fset.Position(decl.Pos()).Filename)
if !s.addImport(decl, p, localImportMap, log) {
continue
}
spec, found := s.getStructTypeDecl(decl, p.Fset)
//log.Info("Checking file","filename", p.Fset.Position(decl.Pos()).Filename,"found",found)
if found {
if isController || isTest {
controllerSpec := s.getControllerSpec(spec, p)
controllerSpec := s.getControllerSpec(spec, p, localImportMap)
sourceInfo.StructSpecs = append(sourceInfo.StructSpecs, controllerSpec)
}
} else {
@@ -54,9 +62,9 @@ func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *m
funcDecl.Name.IsExported() && // be public
funcDecl.Type.Results != nil && len(funcDecl.Type.Results.List) == 1 {
// return one result
if m, receiver := s.getControllerFunc(funcDecl, p); m != nil {
if m, receiver := s.getControllerFunc(funcDecl, p, localImportMap); m != nil {
methodMap[receiver] = append(methodMap[receiver], m)
s.sourceProcessor.log.Info("Added method map to ", "receiver", receiver, "method", m.Name)
log.Info("Added method map to ", "receiver", receiver, "method", m.Name)
}
}
// Check for validation
@@ -183,7 +191,7 @@ func (s *SourceInfoProcessor) getValidationParameter(funcDecl *ast.FuncDecl) *a
}
return nil
}
func (s *SourceInfoProcessor) getControllerFunc(funcDecl *ast.FuncDecl, p *packages.Package) (method *model.MethodSpec, recvTypeName string) {
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 {
return
@@ -212,8 +220,11 @@ func (s *SourceInfoProcessor) getControllerFunc(funcDecl *ast.FuncDecl, p *packa
importPath = p.PkgPath
} else if typeExpr.PkgName != "" {
var ok bool
if importPath, ok = s.sourceProcessor.importMap[typeExpr.PkgName]; !ok {
utils.Logger.Fatalf("Failed to find import for arg of type: %s , %s", typeExpr.PkgName, typeExpr.TypeName(""))
if importPath, ok = localImportMap[typeExpr.PkgName]; !ok {
if importPath, ok = s.sourceProcessor.importMap[typeExpr.PkgName]; !ok {
utils.Logger.Error("Unable to find import", "importMap", s.sourceProcessor.importMap, "localimport", localImportMap)
utils.Logger.Fatalf("Failed to find import for arg of type: %s , %s", typeExpr.PkgName, typeExpr.TypeName(""))
}
}
}
method.Args = append(method.Args, &model.MethodArg{
@@ -271,7 +282,7 @@ func (s *SourceInfoProcessor) getControllerFunc(funcDecl *ast.FuncDecl, p *packa
}
return
}
func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.Package) (controllerSpec *model.TypeInfo) {
func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.Package, localImportMap map[string]string) (controllerSpec *model.TypeInfo) {
structType := spec.Type.(*ast.StructType)
// At this point we know it's a type declaration for a struct.
@@ -282,6 +293,7 @@ func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.
ImportPath: p.PkgPath,
PackageName: p.Name,
}
log := s.sourceProcessor.log.New("file", p.Fset.Position(spec.Pos()).Filename, "position", p.Fset.Position(spec.Pos()).Line)
for _, field := range structType.Fields.List {
// If field.Names is set, it's not an embedded type.
if field.Names != nil {
@@ -329,9 +341,12 @@ func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.
importPath = p.PkgPath
} else {
var ok bool
if importPath, ok = s.sourceProcessor.importMap[pkgName]; !ok {
s.sourceProcessor.log.Error("Error: Failed to find import path for ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap)
continue
if importPath, ok = localImportMap[pkgName]; !ok {
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", )
continue
}
}
}
@@ -376,4 +391,37 @@ func (s *SourceInfoProcessor) getFuncName(funcDecl *ast.FuncDecl) string {
prefix += "."
}
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)
if !ok {
return
}
if genDecl.Tok == token.IMPORT {
shouldContinue = false
for _, spec := range genDecl.Specs {
importSpec := spec.(*ast.ImportSpec)
//fmt.Printf("*** import specification %#v\n", importSpec)
var pkgAlias string
if importSpec.Name != nil {
pkgAlias = importSpec.Name.Name
if pkgAlias == "_" {
continue
}
}
quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\""
fullPath := quotedPath[1 : len(quotedPath) - 1] // Remove the quotes
if pkgAlias == "" {
pkgAlias = fullPath
if index := strings.LastIndex(pkgAlias, "/"); index > 0 {
pkgAlias = pkgAlias[index + 1:]
}
}
localImportMap[pkgAlias] = fullPath
}
}
return
}

View File

@@ -1,15 +1,17 @@
package parser2
import (
"go/ast"
"go/token"
"github.com/revel/cmd/model"
"golang.org/x/tools/go/packages"
"github.com/revel/cmd/utils"
"errors"
"go/parser"
"strings"
"github.com/revel/cmd/logger"
"os"
"path/filepath"
"go/ast"
"go/token"
"go/scanner"
)
type (
@@ -33,10 +35,6 @@ func ProcessSource(revelContainer *model.RevelContainer) (sourceInfo *model.Sour
processor.log.Infof("From parsers : Structures:%d InitImports:%d ValidationKeys:%d %v", len(sourceInfo.StructSpecs), len(sourceInfo.InitImportPaths), len(sourceInfo.ValidationKeys), sourceInfo.PackageMap)
}
if false {
compileError = errors.New("Incompleted")
utils.Logger.Panic("Not implemented")
}
return
}
@@ -45,16 +43,20 @@ func NewSourceProcessor(revelContainer *model.RevelContainer) *SourceProcessor {
s.sourceInfoProcessor = NewSourceInfoProcessor(s)
return s
}
func (s *SourceProcessor) parse() (compileError error) {
print("Parsing packages, (may require download if not cached)...")
if compileError = s.addPackages(); compileError != nil {
return
}
println(" Completed")
if compileError = s.addImportMap(); compileError != nil {
return
}
if compileError = s.addSourceInfo(); compileError != nil {
return
}
s.sourceInfo.PackageMap = map[string]string{}
getImportFromMap := func(packagePath string) string {
for path := range s.packageMap {
@@ -73,11 +75,15 @@ func (s *SourceProcessor) parse() (compileError error) {
return
}
// Using the packages.Load function load all the packages and type specifications (forces compile).
// this sets the SourceProcessor.packageList []*packages.Package
func (s *SourceProcessor) addPackages() (err error) {
allPackages := []string{s.revelContainer.ImportPath + "/...", model.RevelImportPath}
allPackages := []string{model.RevelImportPath + "/..."}
for _, module := range s.revelContainer.ModulePathMap {
allPackages = append(allPackages, module.ImportPath + "/...") // +"/app/controllers/...")
}
s.log.Info("Reading packages", "packageList", allPackages)
//allPackages = []string{s.revelContainer.ImportPath + "/..."} //+"/app/controllers/..."}
config := &packages.Config{
@@ -102,9 +108,117 @@ func (s *SourceProcessor) addPackages() (err error) {
Dir:s.revelContainer.AppPath,
}
s.packageList, err = packages.Load(config, allPackages...)
s.log.Info("Loaded packages ", "len results", len(s.packageList), "error", err)
s.log.Info("Loaded modules ", "len results", len(s.packageList), "error", err)
// Now process the files in the aap source folder s.revelContainer.ImportPath + "/...",
err = utils.Walk(s.revelContainer.BasePath, s.processPath)
s.log.Info("Loaded apps and modules ", "len results", len(s.packageList), "error", err)
return
}
// 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
func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error) error {
if err != nil {
s.log.Error("Error scanning app source:", "error", err)
return nil
}
// Ignore files and folders not marked tmp (since those are generated)
if !info.IsDir() || info.Name() == "tmp" {
return nil
}
// Real work for processing the folder
pkgImportPath := s.revelContainer.ImportPath
appPath := s.revelContainer.BasePath
if appPath != path {
pkgImportPath = s.revelContainer.ImportPath + "/" + filepath.ToSlash(path[len(appPath) + 1:])
}
s.log.Info("Processing source package folder", "package", pkgImportPath, "path", path)
// Parse files within the path.
var pkgMap map[string]*ast.Package
fset := token.NewFileSet()
pkgMap, err = parser.ParseDir(
fset,
path,
func(f os.FileInfo) bool {
return !f.IsDir() && !strings.HasPrefix(f.Name(), ".") && strings.HasSuffix(f.Name(), ".go")
},
0)
if err != nil {
if errList, ok := err.(scanner.ErrorList); ok {
var pos = errList[0].Pos
newError := &utils.SourceError{
SourceType: ".go source",
Title: "Go Compilation Error",
Path: pos.Filename,
Description: errList[0].Msg,
Line: pos.Line,
Column: pos.Column,
SourceLines: utils.MustReadLines(pos.Filename),
}
errorLink := s.revelContainer.Config.StringDefault("error.link", "")
if errorLink != "" {
newError.SetLink(errorLink)
}
return newError
}
// This is exception, err already checked above. Here just a print
ast.Print(nil, err)
s.log.Fatal("Failed to parse dir", "error", err)
}
// Skip "main" packages.
delete(pkgMap, "main")
// Ignore packages that end with _test
// 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" {
delete(pkgMap, i)
}
}
}
// If there is no code in this directory, skip it.
if len(pkgMap) == 0 {
return nil
}
// There should be only one package in this directory.
if len(pkgMap) > 1 {
for i := range pkgMap {
println("Found duplicate packages in single directory ", i)
}
utils.Logger.Fatal("Most unexpected! Multiple packages in a single directory:", "packages", pkgMap)
}
// At this point there is only one package in the pkgs map,
p := &packages.Package{}
p.PkgPath = pkgImportPath
p.Fset = fset
for _, pkg := range pkgMap {
p.Name = pkg.Name
s.log.Info("Found package", "pkg.Name", pkg.Name, "p.Name", p.PkgPath)
for filename, astFile := range pkg.Files {
p.Syntax = append(p.Syntax, astFile)
p.GoFiles = append(p.GoFiles, filename)
}
}
s.packageList = append(s.packageList, p)
return nil
}
// 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
func (s *SourceProcessor) addImportMap() (err error) {
s.importMap = map[string]string{}
s.packageMap = map[string]string{}
@@ -113,41 +227,11 @@ func (s *SourceProcessor) addImportMap() (err error) {
if len(p.Errors) > 0 {
// Generate a compile error
for _, e := range p.Errors {
if !strings.Contains(e.Msg, "fsnotify") {
err = utils.NewCompileError("", "", e)
}
s.log.Info("While reading packages encountered import error ignoring ", "PkgPath", p.PkgPath, "error", e)
}
}
for _, tree := range p.Syntax {
for _, decl := range tree.Decls {
genDecl, ok := decl.(*ast.GenDecl)
if !ok {
continue
}
if genDecl.Tok == token.IMPORT {
for _, spec := range genDecl.Specs {
importSpec := spec.(*ast.ImportSpec)
//fmt.Printf("*** import specification %#v\n", importSpec)
var pkgAlias string
if importSpec.Name != nil {
pkgAlias = importSpec.Name.Name
if pkgAlias == "_" {
continue
}
}
quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\""
fullPath := quotedPath[1 : len(quotedPath) - 1] // Remove the quotes
if pkgAlias == "" {
pkgAlias = fullPath
if index := strings.LastIndex(pkgAlias, "/"); index > 0 {
pkgAlias = pkgAlias[index + 1:]
}
}
s.importMap[pkgAlias] = fullPath
}
}
}
s.importMap[tree.Name.Name] = p.PkgPath
}
}
return
@@ -165,53 +249,3 @@ func (s *SourceProcessor) addSourceInfo() (err error) {
}
return
}
// 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 {
// return
// }
//
// if genDecl.Tok != token.IMPORT {
// return
// }
//
// for _, spec := range genDecl.Specs {
// importSpec := spec.(*ast.ImportSpec)
// var pkgAlias string
// if importSpec.Name != nil {
// pkgAlias = importSpec.Name.Name
// if pkgAlias == "_" {
// continue
// }
// }
// quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\""
// fullPath := quotedPath[1 : len(quotedPath)-1] // Remove the quotes
//
// // If the package was not aliased (common case), we have to import it
// // to see what the package name is.
// // TODO: Can improve performance here a lot:
// // 1. Do not import everything over and over again. Keep a cache.
// // 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 {
// // We expect this to happen for apps using reverse routing (since we
// // have not yet generated the routes). Don't log that.
// if !strings.HasSuffix(fullPath, "/app/routes") {
// utils.Logger.Warn("Could not find import:", "path", fullPath, "srcPath", srcDir, "error", err)
// }
// continue
// } else {
// utils.Logger.Debug("Found package in dir", "dir", pkg.Dir, "name", pkg.ImportPath)
// }
// pkgAlias = pkg.Name
// }
//
// imports[pkgAlias] = fullPath
// }
//}

View File

@@ -59,6 +59,7 @@ func updateBuildConfig(c *model.CommandConfig, args []string) bool {
// 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
@@ -113,7 +114,7 @@ func buildCopyFiles(c *model.CommandConfig, app *harness.App, revel_paths *model
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, app.BinaryPath); err != nil {
if err = utils.CopyFile(destBinaryPath, filepath.Join(revel_paths.BasePath, app.BinaryPath)); err != nil {
return
}
utils.MustChmod(destBinaryPath, 0755)

View File

@@ -1,19 +1,20 @@
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
func TestBuild(t *testing.T) {
a := assert.New(t)
gopath := setup("revel-test-build", a)
gopath := setup("revel-test-build", a)
t.Run("Build", func(t *testing.T) {
a := assert.New(t)
@@ -26,6 +27,21 @@ func TestBuild(t *testing.T) {
a.True(utils.Exists(filepath.Join(gopath, "build-test", "target")))
})
t.Run("Build-withFlags", func(t *testing.T) {
a := assert.New(t)
c := newApp("build-test-WithFlags", model.NEW, nil, a)
c.BuildFlags = []string{
"build-test-WithFlags/app.AppVersion=SomeValue",
"build-test-WithFlags/app.SomeOtherValue=SomeValue",
}
main.Commands[model.NEW].RunWith(c)
c.Index = model.BUILD
c.Build.TargetPath = filepath.Join(gopath, "build-test", "target")
c.Build.ImportPath = c.ImportPath
a.Nil(main.Commands[model.BUILD].RunWith(c), "Failed to run build-test-withFlags")
a.True(utils.Exists(filepath.Join(gopath, "build-test", "target")))
})
if !t.Failed() {
if err := os.RemoveAll(gopath); err != nil {
a.Fail("Failed to remove test path")

View File

@@ -72,7 +72,7 @@ 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)
if err == nil || !utils.Empty(c.AppPath) {
return utils.NewBuildError("Abort: Import path already exists.", "path", c.ImportPath)
return utils.NewBuildError("Abort: Import path already exists.", "path", c.ImportPath, "apppath", c.AppPath)
}
// checking and setting skeleton
@@ -112,6 +112,10 @@ func newApp(c *model.CommandConfig) (err error) {
fmt.Fprintln(os.Stdout, "Your application has been created in:\n ", c.AppPath)
// Check to see if it should be run right off
if c.New.Run {
// Need to prep the run command
c.Run.ImportPath = c.ImportPath
updateRunConfig(c,nil)
c.UpdateImportPath()
runApp(c)
} else {
fmt.Fprintln(os.Stdout, "\nYou can run it with:\n revel run -a ", c.ImportPath)
@@ -203,13 +207,13 @@ 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 "."
if filepath.IsAbs(c.ImportPath) || strings.HasPrefix(c.ImportPath, ".") {
utils.Logger.Fatalf("Abort: '%s' looks like a directory. Please provide a Go import path instead.",
c.ImportPath)
}
// If we are running a vendored version of Revel we do not need to check for it.
if !c.Vendored {
if filepath.IsAbs(c.ImportPath) || strings.HasPrefix(c.ImportPath, ".") {
utils.Logger.Fatalf("Abort: '%s' looks like a directory. Please provide a Go import path instead.",
c.ImportPath)
}
_, err = build.Import(model.RevelImportPath, "", build.FindOnly)
if err != nil {
//// Go get the revel project

View File

@@ -18,6 +18,12 @@ func TestNew(t *testing.T) {
c := newApp("new-test", model.NEW, nil, a)
a.Nil(main.Commands[model.NEW].RunWith(c), "New failed")
})
t.Run("New-NotVendoredmode", func(t *testing.T) {
a := assert.New(t)
c := newApp("new-notvendored", model.NEW, nil, a)
c.New.NotVendored = true
a.Nil(main.Commands[model.NEW].RunWith(c), "New failed")
})
t.Run("Path", func(t *testing.T) {
a := assert.New(t)
c := newApp("new/test/a", model.NEW, nil, a)

View File

@@ -91,6 +91,9 @@ func main() {
utils.InitLogger(wd, logger.LvlWarn)
}
// Setup package resolver
c.InitPackageResolver()
if err := c.UpdateImportPath(); err != nil {
utils.Logger.Error(err.Error())
parser.WriteHelp(os.Stdout)
@@ -100,12 +103,6 @@ func main() {
command := Commands[c.Index]
println("Revel executing:", command.Short)
// Setting go paths
// c.InitGoPaths()
// Setup package resolver
c.InitPackageResolver()
if err := command.RunWith(c); err != nil {
utils.Logger.Error("Unable to execute", "error", err)
os.Exit(1)

View File

@@ -11,9 +11,7 @@ import (
"github.com/revel/cmd/harness"
"github.com/revel/cmd/model"
"github.com/revel/cmd/utils"
"go/build"
"os"
"path/filepath"
)
var cmdRun = &Command{
@@ -116,10 +114,7 @@ func updateRunConfig(c *model.CommandConfig, args []string) bool {
// Returns true if this is an absolute path or a relative gopath
func runIsImportPath(pathToCheck string) bool {
if _, err := build.Import(pathToCheck, "", build.FindOnly); err == nil {
return true
}
return filepath.IsAbs(pathToCheck)
return utils.DirExists(pathToCheck)
}
// Called to run the app
@@ -167,6 +162,6 @@ func runApp(c *model.CommandConfig) (err error) {
if c.HistoricMode {
runMode = revel_path.RunMode
}
app.Cmd(runMode).Run()
app.Cmd(runMode).Run(c)
return
}

View File

@@ -110,16 +110,6 @@ func (v *VersionCommand) doRepoCheck(updateLibs bool) (versionInfo string, needs
}
// Only do an update on the first loop, and if specified to update
shouldUpdate := updateLibs && v.Command.Version.Update
if v.Command.Version.Update {
if localVersion == nil || (versonFromRepo != nil && versonFromRepo.Newer(localVersion)) {
needsUpdate = true
if shouldUpdate {
v.doUpdate(title, repo, localVersion, versonFromRepo)
v.updateLocalVersions()
}
}
}
versionInfo = versionInfo + v.outputVersion(title, repo, localVersion, versonFromRepo)
}
return
@@ -234,6 +224,10 @@ func (v *VersionCommand) updateLocalVersions() {
v.cmdVersion.BuildDate = cmd.BuildDate
v.cmdVersion.MinGoVersion = cmd.MinimumGoVersion
if v.Command.Version.ImportPath=="" {
return
}
pathMap, err := utils.FindSrcPaths(v.Command.AppPath, []string{model.RevelImportPath, model.RevelModulesImportPath}, v.Command.PackageResolver)
if err != nil {
utils.Logger.Warn("Unable to extract version information from Revel library", "path", pathMap[model.RevelImportPath], "error", err)

View File

@@ -34,8 +34,8 @@ func TestVersion(t *testing.T) {
a.Nil(main.Commands[model.VERSION].RunWith(c), "Failed to run version-test")
})
if !t.Failed() {
if err := os.RemoveAll(gopath); err != nil {
a.Fail("Failed to remove test path")
if err := os.RemoveAll(gopath); err != nil && err!=os.ErrNotExist {
a.Fail("Failed to remove test path",err.Error())
}
}
}

View File

@@ -203,7 +203,8 @@ func Walk(root string, walkFn filepath.WalkFunc) error {
return fsWalk(root, root, walkFn)
}
// Walk the tree using the function
// Walk the path tree using 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 {
@@ -308,9 +309,13 @@ func Exists(filename string) bool {
// empty returns true if the given directory is empty.
// the directory must exist.
func Empty(dirname string) bool {
if !DirExists(dirname) {
return true
}
dir, err := os.Open(dirname)
if err != nil {
Logger.Infof("error opening directory: %s", err)
return false
}
defer func() {
_ = dir.Close()
@@ -322,7 +327,8 @@ func Empty(dirname string) bool {
// 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 {
if err != nil && packageResolver != nil || len(missingList) > 0 {
Logger.Info("Failed to find package, attempting to call resolver for missing packages", "missing packages", missingList)
for _, item := range missingList {
if err = packageResolver(item); err != nil {
return
@@ -351,8 +357,10 @@ func findSrcPaths(appPath string, packagesList []string) (sourcePathsmap map[str
Dir:appPath,
}
sourcePathsmap = map[string]string{}
Logger.Infof("Environment path %s root %s config env %s", os.Getenv("GOPATH"), os.Getenv("GOROOT"), config.Env)
pkgs, err := packages.Load(config, packagesList...)
Logger.Infof("Environment path %s root %s config env %s", os.Getenv("GOPATH"), os.Getenv("GOROOT"), config.Env)
Logger.Info("Loaded packages ", "len results", len(pkgs), "error", err, "basedir", appPath)
for _, packageName := range packagesList {
found := false
@@ -361,12 +369,16 @@ func findSrcPaths(appPath string, packagesList []string) (sourcePathsmap map[str
log.Info("Found package", "package", pck.ID)
if pck.ID == packageName {
if pck.Errors != nil && len(pck.Errors) > 0 {
log.Info("Error ", "count", len(pck.Errors), "App Import Path", pck.ID, "errors", pck.Errors)
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)
sourcePathsmap[packageName] = filepath.Dir(pck.GoFiles[0])
found = true
if len(pck.GoFiles) > 0 {
sourcePathsmap[packageName] = filepath.Dir(pck.GoFiles[0])
found = true
}
}
}
if !found {
@@ -378,5 +390,6 @@ func findSrcPaths(appPath string, packagesList []string) (sourcePathsmap map[str
missingList = append(missingList, packageName)
}
}
return
}

View File

@@ -6,11 +6,11 @@ package cmd
const (
// Version current Revel version
Version = "1.0.0-dev"
Version = "1.0.0"
// BuildDate latest commit/release date
BuildDate = "2018-10-30"
BuildDate = "2020-07-11"
// MinimumGoVersion minimum required Go version for Revel
MinimumGoVersion = ">= go1.8"
MinimumGoVersion = ">= go1.12"
)

View File

@@ -33,7 +33,7 @@ type DiscerningListener interface {
// Watcher allows listeners to register to be notified of changes under a given
// directory.
type Watcher struct {
// Parallel arrays of watcher/listener pairs.
// Parallel arrays of watcher/listener pairs.
watchers []*fsnotify.Watcher
listeners []Listener
forceRefresh bool
@@ -42,8 +42,8 @@ type Watcher struct {
lastError int
notifyMutex sync.Mutex
paths *model.RevelContainer
refreshTimer *time.Timer // The timer to countdown the next refresh
timerMutex *sync.Mutex // A mutex to prevent concurrent updates
refreshTimer *time.Timer // The timer to countdown the next refresh
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
@@ -52,10 +52,10 @@ type Watcher struct {
// Creates a new watched based on the container
func NewWatcher(paths *model.RevelContainer, eagerRefresh bool) *Watcher {
return &Watcher{
forceRefresh: true,
forceRefresh: false,
lastError: -1,
paths: paths,
refreshTimerMS: time.Duration(paths.Config.IntDefault("watch.rebuild.delay", 10)),
refreshTimerMS: time.Duration(paths.Config.IntDefault("watch.rebuild.delay", 1000)),
eagerRefresh: eagerRefresh ||
paths.DevMode &&
paths.Config.BoolDefault("watch", true) &&
@@ -85,7 +85,7 @@ func (w *Watcher) Listen(listener Listener, roots ...string) {
for _, p := range roots {
// is the directory / file a symlink?
f, err := os.Lstat(p)
if err == nil && f.Mode()&os.ModeSymlink == os.ModeSymlink {
if err == nil && f.Mode() & os.ModeSymlink == os.ModeSymlink {
var realPath string
realPath, err = filepath.EvalSymlinks(p)
if err != nil {
@@ -200,12 +200,13 @@ func (w *Watcher) Notify() *utils.SourceError {
case <-watcher.Errors:
continue
default:
// No events left to pull
// No events left to pull
}
break
}
utils.Logger.Info("Watcher:Notify refresh state", "Current Index", i, " last error index", w.lastError)
utils.Logger.Info("Watcher:Notify refresh state", "Current Index", i, " last error index", w.lastError,
"force", w.forceRefresh, "refresh", refresh, "lastError", w.lastError == i)
if w.forceRefresh || refresh || w.lastError == i {
var err *utils.SourceError
if w.serial {
@@ -285,22 +286,10 @@ func (w *Watcher) rebuildRequired(ev fsnotify.Event, listener Listener) bool {
}
if dl, ok := listener.(DiscerningListener); ok {
if !dl.WatchFile(ev.Name) || ev.Op&fsnotify.Chmod == fsnotify.Chmod {
if !dl.WatchFile(ev.Name) || ev.Op & fsnotify.Chmod == fsnotify.Chmod {
return false
}
}
return true
}
/*
var WatchFilter = func(c *Controller, fc []Filter) {
if MainWatcher != nil {
err := MainWatcher.Notify()
if err != nil {
c.Result = c.RenderError(err)
return
}
}
fc[0](c, fc[1:])
}
*/