diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9276550 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,39 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Help", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceRoot}/revel", + "args": [] + }, + { + "name": "Create new", + "type": "go", + "request": "launch", + "preLaunchTask": "Clean", + "mode": "auto", + "program": "${workspaceRoot}/revel", + "args": ["new", "-a", "/tmp/revel/aaa"], + "env": { + "GOPATH": "/tmp/revel/GOPATH" + }, + }, + { + "name": "Run program", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceRoot}/revel", + "args": ["run","-v", "-a", "/tmp/revel/aaa"], + "env": { + "GOPATH": "/tmp/revel/GOPATH" + }, + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..7dd4621 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,12 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Clean", + "type": "shell", + "command": "rm -rf /tmp/revel/aaa" + } + ] +} \ No newline at end of file diff --git a/go.mod b/go.mod index 268f752..d1a0de4 100644 --- a/go.mod +++ b/go.mod @@ -3,28 +3,18 @@ module github.com/revel/cmd 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.5.1 github.com/jessevdk/go-flags v1.4.0 - github.com/mattn/go-colorable v0.1.6 - github.com/myesui/uuid v1.0.0 // indirect + github.com/mattn/go-colorable v0.1.12 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/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 + github.com/stretchr/testify v1.7.0 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 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/stack.v0 v0.0.0-20141108040640-9b43fcefddd0 - gopkg.in/stretchr/testify.v1 v1.2.2 // indirect ) + +replace github.com/revel/revel v0.21.0 => ../revel diff --git a/go.sum b/go.sum index 464c37b..e340928 100644 --- a/go.sum +++ b/go.sum @@ -1,60 +1,76 @@ -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= +github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= 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/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= 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/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/garyburd/redigo v1.6.3/go.mod h1:rTb6epsqigu3kYKBnaF028A7Tf/Aw5s0cqA47doKKqw= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +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-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/myesui/uuid v1.0.0 h1:xCBmH4l5KuvLYc5L7AS7SZg9/jKdIFubM7OVoLqaQUI= github.com/myesui/uuid v1.0.0/go.mod h1:2CDfNgU0LR8mIdO8vdWd8i9gWWxLlcoIGGpSNgafq84= +github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= 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/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/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/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +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 h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E= 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/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 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/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +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 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 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 h1:yhQC6Uy5CqibAIlk1wlusa/MJ3iAN49/BsR/dCCKz3M= 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= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/harness/app.go b/harness/app.go index 24ab4ee..ac6520c 100644 --- a/harness/app.go +++ b/harness/app.go @@ -11,12 +11,11 @@ import ( "io" "os" "os/exec" - "time" "sync" + "time" "github.com/revel/cmd/model" "github.com/revel/cmd/utils" - "runtime" ) // App contains the configuration for running a Revel app. (Not for the app itself) @@ -29,9 +28,9 @@ type App struct { Paths *model.RevelContainer } -// NewApp returns app instance with binary path in it +// NewApp returns app instance with binary path in it. func NewApp(binPath string, paths *model.RevelContainer, packagePathMap map[string]string) *App { - return &App{BinaryPath: binPath, Paths: paths, Port: paths.HTTPPort, PackagePathMap:packagePathMap} + return &App{BinaryPath: binPath, Paths: paths, Port: paths.HTTPPort, PackagePathMap: packagePathMap} } // Cmd returns a command to run the app server using the current configuration. @@ -51,7 +50,7 @@ type AppCmd struct { *exec.Cmd } -// NewAppCmd returns the AppCmd with parameters initialized for running app +// NewAppCmd returns the AppCmd with parameters initialized for running app. func NewAppCmd(binPath string, port int, runMode string, paths *model.RevelContainer) AppCmd { cmd := exec.Command(binPath, fmt.Sprintf("-port=%d", port), @@ -74,9 +73,9 @@ func (cmd AppCmd) Start(c *model.CommandConfig) error { select { case exitState := <-cmd.waitChan(): fmt.Println("Startup failure view previous messages, \n Proxy is listening :", c.Run.Port) - err := utils.NewError("", "Revel Run Error", "starting your application there was an exception. See terminal output, " + exitState, "") - // TODO pretiffy command line output - // err.MetaError = listeningWriter.getLastOutput() + err := utils.NewError("", "Revel Run Error", "starting your application there was an exception. See terminal output, "+exitState, "") + // TODO pretiffy command line output + // err.MetaError = listeningWriter.getLastOutput() return err case <-time.After(60 * time.Second): @@ -89,7 +88,6 @@ func (cmd AppCmd) Start(c *model.CommandConfig) error { println("Revel proxy is listening, point your browser to :", c.Run.Port) return nil } - } // Run the app server inline. Never returns. @@ -103,11 +101,10 @@ func (cmd AppCmd) Run(c *model.CommandConfig) { // Kill terminates the app server if it's running. func (cmd AppCmd) Kill() { - if cmd.Cmd != nil && (cmd.ProcessState == nil || !cmd.ProcessState.Exited()) { // Windows appears to send the kill to all threads, shutting down the // server before this can, this check will ensure the process is still running - if _, err := os.FindProcess(int(cmd.Process.Pid)); err != nil { + if _, err := os.FindProcess(cmd.Process.Pid); err != nil { // Server has already exited utils.Logger.Info("Server not running revel server pid", "pid", cmd.Process.Pid) return @@ -135,11 +132,8 @@ func (cmd AppCmd) Kill() { // 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) - } + + err := cmd.Process.Signal(os.Interrupt) if err != nil { utils.Logger.Info( @@ -149,14 +143,13 @@ func (cmd AppCmd) Kill() { return } - // Use a timer to ensure that the process exits utils.Logger.Info("Waiting to exit") select { case <-ch: return case <-time.After(60 * time.Second): - // Kill the process + // Kill the process utils.Logger.Error( "Revel app failed to exit in 60 seconds - killing.", "processid", cmd.Process.Pid, @@ -193,7 +186,7 @@ type startupListeningWriter struct { buffer *bytes.Buffer } -// Writes to this output stream +// Writes to this output stream. func (w *startupListeningWriter) Write(p []byte) (int, error) { if w.notifyReady != nil && bytes.Contains(p, []byte("Revel engine is listening on")) { w.notifyReady <- true @@ -210,10 +203,3 @@ func (w *startupListeningWriter) Write(p []byte) (int, error) { } return w.dest.Write(p) } - -// Returns the cleaned output from the response -// TODO clean the response more -func (w *startupListeningWriter) getLastOutput() string { - return w.buffer.String() -} - diff --git a/harness/build.go b/harness/build.go index 687ec6f..ff8009e 100644 --- a/harness/build.go +++ b/harness/build.go @@ -19,22 +19,24 @@ import ( "time" "github.com/revel/cmd/model" - _ "github.com/revel/cmd/parser" - "github.com/revel/cmd/utils" - "github.com/revel/cmd/parser2" "github.com/revel/cmd/parser" + "github.com/revel/cmd/parser2" + "github.com/revel/cmd/utils" ) var importErrorPattern = regexp.MustCompile("cannot find package \"([^\"]+)\"") +var importErrorPattern2 = regexp.MustCompile("no required module provides package ([^;]+)+") type ByString []*model.TypeInfo func (c ByString) Len() int { return len(c) } + func (c ByString) Swap(i, j int) { c[i], c[j] = c[j], c[i] } + func (c ByString) Less(i, j int) bool { return c[i].String() < c[j].String() } @@ -155,7 +157,8 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err "build", "-ldflags", versionLinkerFlags, "-tags", buildTags, - "-o", binName} + "-o", binName, + } } else { if !contains(c.BuildFlags, "build") { flags = []string{"build"} @@ -188,7 +191,7 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err } buildCmd.Env = append(os.Environ(), - "GOPATH=" + gopath, + "GOPATH="+gopath, ) } utils.CmdInit(buildCmd, !c.Vendored, c.AppPath) @@ -208,6 +211,9 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err // See if it was an import error that we can go get. matches := importErrorPattern.FindAllStringSubmatch(stOutput, -1) + if matches == nil { + matches = importErrorPattern2.FindAllStringSubmatch(stOutput, -1) + } utils.Logger.Info("Build failed checking for missing imports", "message", stOutput, "missing_imports", len(matches)) if matches == nil { utils.Logger.Info("Build failed no missing imports", "message", stOutput) @@ -224,6 +230,7 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err } gotten[pkgName] = struct{}{} if err := c.PackageResolver(pkgName); err != nil { + panic("failed to resolve") utils.Logger.Error("Unable to resolve package", "package", pkgName, "error", err) return nil, newCompileError(paths, []byte(err.Error())) } @@ -232,9 +239,7 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err // Success getting the import, attempt to build again. } - // TODO remove this unreachable code and document it - utils.Logger.Fatal("Not reachable") - return nil, nil + // unreachable } // Try to define a version string for the compiled app @@ -256,10 +261,9 @@ func getAppVersion(paths *model.RevelContainer) string { if (err != nil && os.IsNotExist(err)) || !info.IsDir() { return "" } - gitCmd := exec.Command(gitPath, "--git-dir=" + gitDir, "--work-tree=" + paths.BasePath, "describe", "--always", "--dirty") + gitCmd := exec.Command(gitPath, "--git-dir="+gitDir, "--work-tree="+paths.BasePath, "describe", "--always", "--dirty") utils.Logger.Info("Exec:", "args", gitCmd.Args) output, err := gitCmd.Output() - if err != nil { utils.Logger.Error("Cannot determine git repository version:", "error", err) return "" @@ -317,7 +321,6 @@ func cleanDir(paths *model.RevelContainer, dir string) { // genSource renders the given template to produce source code, which it writes // to the given directory and file. func genSource(paths *model.RevelContainer, dir, filename, templateSource string, args map[string]interface{}) error { - return utils.GenerateTemplate(filepath.Join(paths.AppPath, dir, filename), templateSource, args) } @@ -353,17 +356,16 @@ func calcImportAliases(src *model.SourceInfo) map[string]string { return aliases } -// Adds an alias to the map of alias names +// Adds an alias to the map of alias names. func addAlias(aliases map[string]string, importPath, pkgName string) { - alias, ok := aliases[importPath] + _, ok := aliases[importPath] if ok { return } - alias = makePackageAlias(aliases, pkgName) - aliases[importPath] = alias + aliases[importPath] = makePackageAlias(aliases, pkgName) } -// Generates a package alias +// Generates a package alias. func makePackageAlias(aliases map[string]string, pkgName string) string { i := 0 alias := pkgName @@ -374,7 +376,7 @@ func makePackageAlias(aliases map[string]string, pkgName string) string { return alias } -// Returns true if this value is in the map +// Returns true if this value is in the map. func containsValue(m map[string]string, val string) bool { for _, v := range m { if v == val { @@ -421,13 +423,12 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.SourceEr return newPath } - // Read the source for the offending file. var ( - relFilename = string(errorMatch[1]) // e.g. "src/revel/sample/app/controllers/app.go" - absFilename = findInPaths(relFilename) - line, _ = strconv.Atoi(string(errorMatch[2])) - description = string(errorMatch[4]) + relFilename = string(errorMatch[1]) // e.g. "src/revel/sample/app/controllers/app.go" + absFilename = findInPaths(relFilename) + line, _ = strconv.Atoi(string(errorMatch[2])) + description = string(errorMatch[4]) compileError = &utils.SourceError{ SourceType: "Go code", Title: "Go Compilation Error", @@ -446,7 +447,7 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.SourceEr fileStr, err := utils.ReadLines(absFilename) if err != nil { compileError.MetaError = absFilename + ": " + err.Error() - utils.Logger.Info("Unable to readlines " + compileError.MetaError, "error", err) + utils.Logger.Info("Unable to readlines "+compileError.MetaError, "error", err) return compileError } @@ -454,7 +455,7 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.SourceEr return compileError } -// RevelMainTemplate template for app/tmp/run/run.go +// RevelMainTemplate template for app/tmp/run/run.go. const RevelRunTemplate = `// GENERATED CODE - DO NOT EDIT // This file is the run file for Revel. // It registers all the controllers and provides details for the Revel server engine to @@ -509,6 +510,7 @@ func Register() { } } ` + const RevelMainTemplate = `// GENERATED CODE - DO NOT EDIT // This file is the main file for Revel. // It registers all the controllers and provides details for the Revel server engine to @@ -536,7 +538,7 @@ func main() { } ` -// RevelRoutesTemplate template for app/conf/routes +// RevelRoutesTemplate template for app/conf/routes. const RevelRoutesTemplate = `// GENERATED CODE - DO NOT EDIT // This file provides a way of creating URL's based on all the actions // found in all the controllers. diff --git a/harness/harness.go b/harness/harness.go index d264f98..68a83d1 100644 --- a/harness/harness.go +++ b/harness/harness.go @@ -15,10 +15,12 @@ package harness import ( "crypto/tls" + "encoding/json" "fmt" - "time" "go/build" + "html/template" "io" + "io/ioutil" "net" "net/http" "net/http/httputil" @@ -27,15 +29,13 @@ import ( "os/signal" "path/filepath" "strings" + "sync" "sync/atomic" + "time" "github.com/revel/cmd/model" "github.com/revel/cmd/utils" "github.com/revel/cmd/watcher" - "html/template" - "io/ioutil" - "sync" - "encoding/json" ) var ( @@ -57,7 +57,6 @@ type Harness struct { paths *model.RevelContainer // The Revel container config *model.CommandConfig // The configuration runMode string // The runmode the harness is running in - isError bool // True if harness is in error state ranOnce bool // True app compiled once } @@ -90,7 +89,7 @@ func (h *Harness) renderError(iw http.ResponseWriter, ir *http.Request, err erro target := []string{seekViewOnPath("500.html"), seekViewOnPath("500-dev.html")} if !utils.Exists(target[0]) { fmt.Fprintf(iw, "Target template not found not found %s
\n", target[0]) - fmt.Fprintf(iw, "An error ocurred %s", err.Error()) + fmt.Fprintf(iw, "An error occurred %s", err.Error()) return } var revelError *utils.SourceError @@ -156,11 +155,11 @@ func (h *Harness) ServeHTTP(w http.ResponseWriter, r *http.Request) { func NewHarness(c *model.CommandConfig, paths *model.RevelContainer, runMode string, noProxy bool) *Harness { // Get a template loader to render errors. // Prefer the app's views/errors directory, and fall back to the stock error pages. - //revel.MainTemplateLoader = revel.NewTemplateLoader( + // revel.MainTemplateLoader = revel.NewTemplateLoader( // []string{filepath.Join(revel.RevelPath, "templates")}) - //if err := revel.MainTemplateLoader.Refresh(); err != nil { + // if err := revel.MainTemplateLoader.Refresh(); err != nil { // revel.RevelLog.Error("Template loader error", "error", err) - //} + // } addr := paths.HTTPAddr port := paths.Config.IntDefault("harness.port", 0) @@ -203,19 +202,19 @@ func NewHarness(c *model.CommandConfig, paths *model.RevelContainer, runMode str } // Refresh method rebuilds the Revel application and run it on the given port. -// called by the watcher +// called by the watcher. func (h *Harness) Refresh() (err *utils.SourceError) { t := time.Now(); fmt.Println("Change detected, recompiling") err = h.refresh() - if err!=nil && !h.ranOnce && h.useProxy { + 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) + 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()) + fmt.Printf("\nTime to recompile %s\n", time.Since(t).String()) return } @@ -253,15 +252,14 @@ func (h *Harness) refresh() (err *utils.SourceError) { if !h.config.HistoricMode { // Recalulate run mode based on the config var paths []byte - if len(h.app.PackagePathMap)>0 { + 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 { + if err, k := err2.(*utils.SourceError); k { return err } return &utils.SourceError{ @@ -277,13 +275,13 @@ func (h *Harness) refresh() (err *utils.SourceError) { } // WatchDir method returns false to file matches with doNotWatch -// otheriwse true +// otheriwse true. func (h *Harness) WatchDir(info os.FileInfo) bool { return !utils.ContainsString(doNotWatch, info.Name()) } // WatchFile method returns true given filename HasSuffix of ".go" -// otheriwse false - implements revel.DiscerningListener +// otheriwse false - implements revel.DiscerningListener. func (h *Harness) WatchFile(filename string) bool { return strings.HasSuffix(filename, ".go") } @@ -310,8 +308,6 @@ func (h *Harness) Run() { } addr := fmt.Sprintf("%s:%d", h.paths.HTTPAddr, h.paths.HTTPPort) utils.Logger.Infof("Proxy server is listening on %s", addr) - - var err error if h.paths.HTTPSsl { err = http.ListenAndServeTLS( @@ -326,11 +322,11 @@ func (h *Harness) Run() { utils.Logger.Error("Failed to start reverse proxy:", "error", err) } }() - } // Make a new channel to listen for the interrupt event ch := make(chan os.Signal) + //nolint:staticcheck // os.Kill ineffective on Unix, useful on Windows? signal.Notify(ch, os.Interrupt, os.Kill) <-ch // Kill the app and exit @@ -340,7 +336,7 @@ func (h *Harness) Run() { os.Exit(1) } -// Find an unused port +// Find an unused port. func getFreePort() (port int) { conn, err := net.Listen("tcp", ":0") if err != nil { diff --git a/logger/composite_multihandler.go b/logger/composite_multihandler.go index fb15e8a..79f0019 100644 --- a/logger/composite_multihandler.go +++ b/logger/composite_multihandler.go @@ -1,10 +1,11 @@ package logger import ( - "github.com/mattn/go-colorable" - "gopkg.in/natefinch/lumberjack.v2" "io" "os" + + "github.com/mattn/go-colorable" + "gopkg.in/natefinch/lumberjack.v2" ) type CompositeMultiHandler struct { @@ -19,8 +20,8 @@ func NewCompositeMultiHandler() (*CompositeMultiHandler, LogHandler) { cw := &CompositeMultiHandler{} return cw, cw } -func (h *CompositeMultiHandler) Log(r *Record) (err error) { +func (h *CompositeMultiHandler) Log(r *Record) (err error) { var handler LogHandler switch r.Level { @@ -78,7 +79,7 @@ func (h *CompositeMultiHandler) SetHandler(handler LogHandler, replace bool, lev } } -// For the multi handler set the handler, using the LogOptions defined +// For the multi handler set the handler, using the LogOptions defined. func (h *CompositeMultiHandler) SetHandlers(handler LogHandler, options *LogOptions) { if len(options.Levels) == 0 { options.Levels = LvlAllList @@ -88,8 +89,8 @@ func (h *CompositeMultiHandler) SetHandlers(handler LogHandler, options *LogOpti for _, lvl := range options.Levels { h.SetHandler(handler, options.ReplaceExistingHandler, lvl) } - } + func (h *CompositeMultiHandler) SetJson(writer io.Writer, options *LogOptions) { handler := CallerFileHandler(StreamHandler(writer, JsonFormatEx( options.GetBoolDefault("pretty", false), @@ -101,12 +102,12 @@ func (h *CompositeMultiHandler) SetJson(writer io.Writer, options *LogOptions) { h.SetHandlers(handler, options) } -// Use built in rolling function +// Use built in rolling function. func (h *CompositeMultiHandler) SetJsonFile(filePath string, options *LogOptions) { writer := &lumberjack.Logger{ Filename: filePath, MaxSize: options.GetIntDefault("maxSizeMB", 1024), // megabytes - MaxAge: options.GetIntDefault("maxAgeDays", 7), //days + MaxAge: options.GetIntDefault("maxAgeDays", 7), // days MaxBackups: options.GetIntDefault("maxBackups", 7), Compress: options.GetBoolDefault("compress", true), } @@ -141,12 +142,12 @@ func (h *CompositeMultiHandler) SetTerminal(writer io.Writer, options *LogOption h.SetHandlers(handler, options) } -// Use built in rolling function +// Use built in rolling function. func (h *CompositeMultiHandler) SetTerminalFile(filePath string, options *LogOptions) { writer := &lumberjack.Logger{ Filename: filePath, MaxSize: options.GetIntDefault("maxSizeMB", 1024), // megabytes - MaxAge: options.GetIntDefault("maxAgeDays", 7), //days + MaxAge: options.GetIntDefault("maxAgeDays", 7), // days MaxBackups: options.GetIntDefault("maxBackups", 7), Compress: options.GetBoolDefault("compress", true), } diff --git a/logger/doc.go b/logger/doc.go index 0f6156a..6cb68e6 100644 --- a/logger/doc.go +++ b/logger/doc.go @@ -1,15 +1,12 @@ /* - Package logger contains filters and handles for the logging utilities in Revel. - These facilities all currently use the logging library called log15 at - https://github.com/inconshreveable/log15 +Package logger contains filters and handles for the logging utilities in Revel. +These facilities all currently use the logging library called log15 at + https://github.com/inconshreveable/log15 Defining handlers happens as follows 1) ALL handlers (log.all.output) replace any existing handlers 2) Output handlers (log.error.output) replace any existing handlers 3) Filter handlers (log.xxx.filter, log.xxx.nfilter) append to existing handlers, note log.all.filter is treated as a filter handler, so it will NOT replace existing ones - - - */ package logger diff --git a/logger/handlers.go b/logger/handlers.go index dee850e..16a4ff5 100644 --- a/logger/handlers.go +++ b/logger/handlers.go @@ -11,12 +11,12 @@ type LevelFilterHandler struct { } // Filters out records which do not match the level -// Uses the `log15.FilterHandler` to perform this task +// Uses the `log15.FilterHandler` to perform this task. func LevelHandler(lvl LogLevel, h LogHandler) LogHandler { return &LevelFilterHandler{lvl, h} } -// The implementation of the Log +// The implementation of the Log. func (h LevelFilterHandler) Log(r *Record) error { if r.Level == h.Level { return h.h.Log(r) @@ -25,7 +25,7 @@ func (h LevelFilterHandler) Log(r *Record) error { } // Filters out records which do not match the level -// Uses the `log15.FilterHandler` to perform this task +// Uses the `log15.FilterHandler` to perform this task. func MinLevelHandler(lvl LogLevel, h LogHandler) LogHandler { return FilterHandler(func(r *Record) (pass bool) { return r.Level <= lvl @@ -33,7 +33,7 @@ func MinLevelHandler(lvl LogLevel, h LogHandler) LogHandler { } // Filters out records which match the level -// Uses the `log15.FilterHandler` to perform this task +// Uses the `log15.FilterHandler` to perform this task. func NotLevelHandler(lvl LogLevel, h LogHandler) LogHandler { return FilterHandler(func(r *Record) (pass bool) { return r.Level != lvl @@ -48,13 +48,13 @@ func CallerFileHandler(h LogHandler) LogHandler { } // Adds in a context called `caller` to the record (contains file name and line number like `foo.go:12`) -// Uses the `log15.CallerFuncHandler` to perform this task +// Uses the `log15.CallerFuncHandler` to perform this task. func CallerFuncHandler(h LogHandler) LogHandler { return CallerFuncHandler(h) } // Filters out records which match the key value pair -// Uses the `log15.MatchFilterHandler` to perform this task +// Uses the `log15.MatchFilterHandler` to perform this task. func MatchHandler(key string, value interface{}, h LogHandler) LogHandler { return MatchFilterHandler(key, value, h) } @@ -72,7 +72,7 @@ func MatchFilterHandler(key string, value interface{}, h LogHandler) LogHandler }, h) } -// If match then A handler is called otherwise B handler is called +// If match then A handler is called otherwise B handler is called. func MatchAbHandler(key string, value interface{}, a, b LogHandler) LogHandler { return FuncHandler(func(r *Record) error { if r.Context[key] == value { @@ -85,24 +85,24 @@ func MatchAbHandler(key string, value interface{}, a, b LogHandler) LogHandler { }) } -// The nil handler is used if logging for a specific request needs to be turned off +// The nil handler is used if logging for a specific request needs to be turned off. func NilHandler() LogHandler { return FuncHandler(func(r *Record) error { return nil }) } -// Match all values in map to log +// Match all values in map to log. func MatchMapHandler(matchMap map[string]interface{}, a LogHandler) LogHandler { return matchMapHandler(matchMap, false, a) } -// Match !(Match all values in map to log) The inverse of MatchMapHandler +// Match !(Match all values in map to log) The inverse of MatchMapHandler. func NotMatchMapHandler(matchMap map[string]interface{}, a LogHandler) LogHandler { return matchMapHandler(matchMap, true, a) } -// Rather then chaining multiple filter handlers, process all here +// Rather then chaining multiple filter handlers, process all here. func matchMapHandler(matchMap map[string]interface{}, inverse bool, a LogHandler) LogHandler { return FuncHandler(func(r *Record) error { matchCount := 0 @@ -114,10 +114,11 @@ func matchMapHandler(matchMap map[string]interface{}, inverse bool, a LogHandler // Test for two failure cases if value == v && inverse || value != v && !inverse { return nil - } else { - matchCount++ } + + matchCount++ } + if matchCount != len(matchMap) { return nil } @@ -126,7 +127,7 @@ func matchMapHandler(matchMap map[string]interface{}, inverse bool, a LogHandler } // Filters out records which do not match the key value pair -// Uses the `log15.FilterHandler` to perform this task +// Uses the `log15.FilterHandler` to perform this task. func NotMatchHandler(key string, value interface{}, h LogHandler) LogHandler { return FilterHandler(func(r *Record) (pass bool) { return r.Context[key] != value @@ -158,7 +159,7 @@ func StreamHandler(wr io.Writer, fmtr LogFormat) LogHandler { return LazyHandler(SyncHandler(h)) } -// Filter handler +// Filter handler. func FilterHandler(fn func(r *Record) bool, h LogHandler) LogHandler { return FuncHandler(func(r *Record) error { if fn(r) { @@ -168,18 +169,18 @@ func FilterHandler(fn func(r *Record) bool, h LogHandler) LogHandler { }) } -// List log handler handles a list of LogHandlers +// List log handler handles a list of LogHandlers. type ListLogHandler struct { handlers []LogHandler } -// Create a new list of log handlers +// Create a new list of log handlers. func NewListLogHandler(h1, h2 LogHandler) *ListLogHandler { ll := &ListLogHandler{handlers: []LogHandler{h1, h2}} return ll } -// Log the record +// Log the record. func (ll *ListLogHandler) Log(r *Record) (err error) { for _, handler := range ll.handlers { if err == nil { @@ -191,14 +192,14 @@ func (ll *ListLogHandler) Log(r *Record) (err error) { return } -// Add another log handler +// Add another log handler. func (ll *ListLogHandler) Add(h LogHandler) { if h != nil { ll.handlers = append(ll.handlers, h) } } -// Remove a log handler +// Remove a log handler. func (ll *ListLogHandler) Del(h LogHandler) { if h != nil { for i, handler := range ll.handlers { diff --git a/logger/init.go b/logger/init.go index 6a02cf8..5f2d307 100644 --- a/logger/init.go +++ b/logger/init.go @@ -1,13 +1,14 @@ package logger -// Get all handlers based on the Config (if available) +// Get all handlers based on the Config (if available). import ( "fmt" - "github.com/revel/config" "log" "os" "path/filepath" "strings" + + "github.com/revel/config" ) func InitializeFromConfig(basePath string, config *config.Context) (c *CompositeMultiHandler) { @@ -43,7 +44,7 @@ func InitializeFromConfig(basePath string, config *config.Context) (c *Composite return c } -// Init the log.all configuration options +// Init the log.all configuration options. func initAllLog(c *CompositeMultiHandler, basePath string, config *config.Context) { if config != nil { extraLogFlag := config.BoolDefault(SPECIAL_USE_FLAG, false) @@ -61,13 +62,13 @@ func initAllLog(c *CompositeMultiHandler, basePath string, config *config.Contex // log.all.filter .... // log.error.filter .... func initFilterLog(c *CompositeMultiHandler, basePath string, config *config.Context) { - if config != nil { extraLogFlag := config.BoolDefault(SPECIAL_USE_FLAG, false) for _, logFilter := range logFilterList { // Init for all filters - for _, name := range []string{"all", "debug", "info", "warn", "error", "crit", + for _, name := range []string{ + "all", "debug", "info", "warn", "error", "crit", "trace", // TODO trace is deprecated } { optionList := config.Options(logFilter.LogPrefix + name + logFilter.LogSuffix) @@ -94,9 +95,10 @@ func initFilterLog(c *CompositeMultiHandler, basePath string, config *config.Con } } -// Init the log.error, log.warn etc configuration options +// Init the log.error, log.warn etc configuration options. func initLogLevels(c *CompositeMultiHandler, basePath string, config *config.Context) { - for _, name := range []string{"debug", "info", "warn", "error", "crit", + for _, name := range []string{ + "debug", "info", "warn", "error", "crit", "trace", // TODO trace is deprecated } { if config != nil { @@ -115,7 +117,7 @@ func initLogLevels(c *CompositeMultiHandler, basePath string, config *config.Con } } -// Init the request log options +// Init the request log options. func initRequestLog(c *CompositeMultiHandler, basePath string, config *config.Context) { // Request logging to a separate output handler // This takes the InfoHandlers and adds a MatchAbHandler handler to it to direct @@ -143,7 +145,7 @@ func initRequestLog(c *CompositeMultiHandler, basePath string, config *config.Co // Returns a handler for the level using the output string // Accept formats for output string are // LogFunctionMap[value] callback function -// `stdout` `stderr` `full/file/path/to/location/app.log` `full/file/path/to/location/app.json` +// `stdout` `stderr` `full/file/path/to/location/app.log` `full/file/path/to/location/app.json`. func initHandlerFor(c *CompositeMultiHandler, output, basePath string, options *LogOptions) { if options.Ctx != nil { options.SetExtendedOptions( @@ -185,5 +187,4 @@ func initHandlerFor(c *CompositeMultiHandler, output, basePath string, options * } } } - return } diff --git a/logger/init_test.go b/logger/init_test.go index 50fcd61..5793048 100644 --- a/logger/init_test.go +++ b/logger/init_test.go @@ -5,46 +5,57 @@ package logger_test import ( - "github.com/revel/config" - "github.com/revel/revel/logger" - "github.com/stretchr/testify/assert" "os" "strings" "testing" + + "github.com/revel/cmd/logger" + "github.com/revel/config" + "github.com/stretchr/testify/assert" ) type ( - // A counter for the tester + // A counter for the tester. testCounter struct { debug, info, warn, error, critical int } - // The data to tes + // The data to tes. testData struct { config []string result testResult tc *testCounter } - // The test result + // The test result. testResult struct { debug, info, warn, error, critical int } ) -// Single test cases +// Single test cases. var singleCases = []testData{ - {config: []string{"log.crit.output"}, - result: testResult{0, 0, 0, 0, 1}}, - {config: []string{"log.error.output"}, - result: testResult{0, 0, 0, 1, 1}}, - {config: []string{"log.warn.output"}, - result: testResult{0, 0, 1, 0, 0}}, - {config: []string{"log.info.output"}, - result: testResult{0, 1, 0, 0, 0}}, - {config: []string{"log.debug.output"}, - result: testResult{1, 0, 0, 0, 0}}, + { + config: []string{"log.crit.output"}, + result: testResult{0, 0, 0, 0, 1}, + }, + { + config: []string{"log.error.output"}, + result: testResult{0, 0, 0, 1, 1}, + }, + { + config: []string{"log.warn.output"}, + result: testResult{0, 0, 1, 0, 0}, + }, + { + config: []string{"log.info.output"}, + result: testResult{0, 1, 0, 0, 0}, + }, + { + config: []string{"log.debug.output"}, + result: testResult{1, 0, 0, 0, 0}, + }, } -// Test singles +// Test singles. func TestSingleCases(t *testing.T) { rootLog := logger.New() for _, testCase := range singleCases { @@ -53,31 +64,51 @@ func TestSingleCases(t *testing.T) { } } -// Filter test cases +// Filter test cases. var filterCases = []testData{ - {config: []string{"log.crit.filter.module.app"}, - result: testResult{0, 0, 0, 0, 1}}, - {config: []string{"log.crit.filter.module.appa"}, - result: testResult{0, 0, 0, 0, 0}}, - {config: []string{"log.error.filter.module.app"}, - result: testResult{0, 0, 0, 1, 1}}, - {config: []string{"log.error.filter.module.appa"}, - result: testResult{0, 0, 0, 0, 0}}, - {config: []string{"log.warn.filter.module.app"}, - result: testResult{0, 0, 1, 0, 0}}, - {config: []string{"log.warn.filter.module.appa"}, - result: testResult{0, 0, 0, 0, 0}}, - {config: []string{"log.info.filter.module.app"}, - result: testResult{0, 1, 0, 0, 0}}, - {config: []string{"log.info.filter.module.appa"}, - result: testResult{0, 0, 0, 0, 0}}, - {config: []string{"log.debug.filter.module.app"}, - result: testResult{1, 0, 0, 0, 0}}, - {config: []string{"log.debug.filter.module.appa"}, - result: testResult{0, 0, 0, 0, 0}}, + { + config: []string{"log.crit.filter.module.app"}, + result: testResult{0, 0, 0, 0, 1}, + }, + { + config: []string{"log.crit.filter.module.appa"}, + result: testResult{0, 0, 0, 0, 0}, + }, + { + config: []string{"log.error.filter.module.app"}, + result: testResult{0, 0, 0, 1, 1}, + }, + { + config: []string{"log.error.filter.module.appa"}, + result: testResult{0, 0, 0, 0, 0}, + }, + { + config: []string{"log.warn.filter.module.app"}, + result: testResult{0, 0, 1, 0, 0}, + }, + { + config: []string{"log.warn.filter.module.appa"}, + result: testResult{0, 0, 0, 0, 0}, + }, + { + config: []string{"log.info.filter.module.app"}, + result: testResult{0, 1, 0, 0, 0}, + }, + { + config: []string{"log.info.filter.module.appa"}, + result: testResult{0, 0, 0, 0, 0}, + }, + { + config: []string{"log.debug.filter.module.app"}, + result: testResult{1, 0, 0, 0, 0}, + }, + { + config: []string{"log.debug.filter.module.appa"}, + result: testResult{0, 0, 0, 0, 0}, + }, } -// Filter test +// Filter test. func TestFilterCases(t *testing.T) { rootLog := logger.New("module", "app") for _, testCase := range filterCases { @@ -86,33 +117,55 @@ func TestFilterCases(t *testing.T) { } } -// Inverse test cases +// Inverse test cases. var nfilterCases = []testData{ - {config: []string{"log.crit.nfilter.module.appa"}, - result: testResult{0, 0, 0, 0, 1}}, - {config: []string{"log.crit.nfilter.modules.appa"}, - result: testResult{0, 0, 0, 0, 0}}, - {config: []string{"log.crit.nfilter.module.app"}, - result: testResult{0, 0, 0, 0, 0}}, - {config: []string{"log.error.nfilter.module.appa"}, // Special case, when error is not nill critical inherits from error - result: testResult{0, 0, 0, 1, 1}}, - {config: []string{"log.error.nfilter.module.app"}, - result: testResult{0, 0, 0, 0, 0}}, - {config: []string{"log.warn.nfilter.module.appa"}, - result: testResult{0, 0, 1, 0, 0}}, - {config: []string{"log.warn.nfilter.module.app"}, - result: testResult{0, 0, 0, 0, 0}}, - {config: []string{"log.info.nfilter.module.appa"}, - result: testResult{0, 1, 0, 0, 0}}, - {config: []string{"log.info.nfilter.module.app"}, - result: testResult{0, 0, 0, 0, 0}}, - {config: []string{"log.debug.nfilter.module.appa"}, - result: testResult{1, 0, 0, 0, 0}}, - {config: []string{"log.debug.nfilter.module.app"}, - result: testResult{0, 0, 0, 0, 0}}, + { + config: []string{"log.crit.nfilter.module.appa"}, + result: testResult{0, 0, 0, 0, 1}, + }, + { + config: []string{"log.crit.nfilter.modules.appa"}, + result: testResult{0, 0, 0, 0, 0}, + }, + { + config: []string{"log.crit.nfilter.module.app"}, + result: testResult{0, 0, 0, 0, 0}, + }, + { + config: []string{"log.error.nfilter.module.appa"}, // Special case, when error is not nill critical inherits from error + result: testResult{0, 0, 0, 1, 1}, + }, + { + config: []string{"log.error.nfilter.module.app"}, + result: testResult{0, 0, 0, 0, 0}, + }, + { + config: []string{"log.warn.nfilter.module.appa"}, + result: testResult{0, 0, 1, 0, 0}, + }, + { + config: []string{"log.warn.nfilter.module.app"}, + result: testResult{0, 0, 0, 0, 0}, + }, + { + config: []string{"log.info.nfilter.module.appa"}, + result: testResult{0, 1, 0, 0, 0}, + }, + { + config: []string{"log.info.nfilter.module.app"}, + result: testResult{0, 0, 0, 0, 0}, + }, + { + config: []string{"log.debug.nfilter.module.appa"}, + result: testResult{1, 0, 0, 0, 0}, + }, + { + config: []string{"log.debug.nfilter.module.app"}, + result: testResult{0, 0, 0, 0, 0}, + }, } -// Inverse test +// Inverse test. func TestNotFilterCases(t *testing.T) { rootLog := logger.New("module", "app") for _, testCase := range nfilterCases { @@ -121,13 +174,15 @@ func TestNotFilterCases(t *testing.T) { } } -// off test cases +// off test cases. var offCases = []testData{ - {config: []string{"log.all.output", "log.error.output=off"}, - result: testResult{1, 1, 1, 0, 1}}, + { + config: []string{"log.all.output", "log.error.output=off"}, + result: testResult{1, 1, 1, 0, 1}, + }, } -// Off test +// Off test. func TestOffCases(t *testing.T) { rootLog := logger.New("module", "app") for _, testCase := range offCases { @@ -136,13 +191,15 @@ func TestOffCases(t *testing.T) { } } -// Duplicate test cases +// Duplicate test cases. var duplicateCases = []testData{ - {config: []string{"log.all.output", "log.error.output", "log.error.filter.module.app"}, - result: testResult{1, 1, 1, 2, 1}}, + { + config: []string{"log.all.output", "log.error.output", "log.error.filter.module.app"}, + result: testResult{1, 1, 1, 2, 1}, + }, } -// test duplicate cases +// test duplicate cases. func TestDuplicateCases(t *testing.T) { rootLog := logger.New("module", "app") for _, testCase := range duplicateCases { @@ -151,19 +208,27 @@ func TestDuplicateCases(t *testing.T) { } } -// Contradicting cases +// Contradicting cases. var contradictCases = []testData{ - {config: []string{"log.all.output", "log.error.output=off", "log.all.output"}, - result: testResult{1, 1, 1, 0, 1}}, - {config: []string{"log.all.output", "log.error.output=off", "log.debug.filter.module.app"}, - result: testResult{2, 1, 1, 0, 1}}, - {config: []string{"log.all.filter.module.app", "log.info.output=off", "log.info.filter.module.app"}, - result: testResult{1, 2, 1, 1, 1}}, - {config: []string{"log.all.output", "log.info.output=off", "log.info.filter.module.app"}, - result: testResult{1, 1, 1, 1, 1}}, + { + config: []string{"log.all.output", "log.error.output=off", "log.all.output"}, + result: testResult{1, 1, 1, 0, 1}, + }, + { + config: []string{"log.all.output", "log.error.output=off", "log.debug.filter.module.app"}, + result: testResult{2, 1, 1, 0, 1}, + }, + { + config: []string{"log.all.filter.module.app", "log.info.output=off", "log.info.filter.module.app"}, + result: testResult{1, 2, 1, 1, 1}, + }, + { + config: []string{"log.all.output", "log.info.output=off", "log.info.filter.module.app"}, + result: testResult{1, 1, 1, 1, 1}, + }, } -// Contradiction test +// Contradiction test. func TestContradictCases(t *testing.T) { rootLog := logger.New("module", "app") for _, testCase := range contradictCases { @@ -172,15 +237,19 @@ func TestContradictCases(t *testing.T) { } } -// All test cases +// All test cases. var allCases = []testData{ - {config: []string{"log.all.filter.module.app"}, - result: testResult{1, 1, 1, 1, 1}}, - {config: []string{"log.all.output"}, - result: testResult{2, 2, 2, 2, 2}}, + { + config: []string{"log.all.filter.module.app"}, + result: testResult{1, 1, 1, 1, 1}, + }, + { + config: []string{"log.all.output"}, + result: testResult{2, 2, 2, 2, 2}, + }, } -// All tests +// All tests. func TestAllCases(t *testing.T) { rootLog := logger.New("module", "app") for i, testCase := range allCases { @@ -195,7 +264,6 @@ func TestAllCases(t *testing.T) { for _, testCase := range allCases { testCase.validate(t) } - } func (c *testCounter) Log(r *logger.Record) error { @@ -215,6 +283,7 @@ func (c *testCounter) Log(r *logger.Record) error { } return nil } + func (td *testData) logTest(rootLog logger.MultiLogger, t *testing.T) { if td.tc == nil { td.tc = &testCounter{} @@ -256,7 +325,7 @@ func (td *testData) validate(t *testing.T) { assert.Equal(t, td.result.critical, td.tc.critical, "Critical failed "+strings.Join(td.config, " ")) } -// Add test to the function map +// Add test to the function map. func counterInit(tc *testCounter) { logger.LogFunctionMap["test"] = func(c *logger.CompositeMultiHandler, logOptions *logger.LogOptions) { // Output to the test log and the stdout diff --git a/logger/log_function_map.go b/logger/log_function_map.go index ebbc76d..3218091 100644 --- a/logger/log_function_map.go +++ b/logger/log_function_map.go @@ -4,8 +4,8 @@ import ( "os" ) -// The log function map can be added to, so that you can specify your own logging mechanism -// it has defaults for off, stdout, stderr +// LogFunctionMap can be added to, so that you can specify your own logging mechanism +// it has defaults for off, stdout, stderr. var LogFunctionMap = map[string]func(*CompositeMultiHandler, *LogOptions){ // Do nothing - set the logger off "off": func(c *CompositeMultiHandler, logOptions *LogOptions) { diff --git a/logger/logger.go b/logger/logger.go index b9abdaf..8b27d35 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -2,14 +2,15 @@ package logger import ( "fmt" - "github.com/revel/config" "time" + + "github.com/revel/config" ) -// The LogHandler defines the interface to handle the log records +// The LogHandler defines the interface to handle the log records. type ( // The Multilogger reduces the number of exposed defined logging variables, - // and allows the output to be easily refined + // and allows the output to be easily refined. MultiLogger interface { // New returns a new Logger that has this logger's context plus the given context New(ctx ...interface{}) MultiLogger @@ -63,32 +64,32 @@ type ( Panicf(msg string, params ...interface{}) } - // The log handler interface + // The log handler interface. LogHandler interface { Log(*Record) error - //log15.Handler + // log15.Handler } - // The log stack handler interface + // The log stack handler interface. LogStackHandler interface { LogHandler GetStack() int } - // The log handler interface which has child logs + // The log handler interface which has child logs. ParentLogHandler interface { SetChild(handler LogHandler) LogHandler } - // The log format interface + // The log format interface. LogFormat interface { Format(r *Record) []byte } - // The log level type + // The log level type. LogLevel int - // Used for the callback to LogFunctionMap + // Used for the callback to LogFunctionMap. LogOptions struct { Ctx *config.Context ReplaceExistingHandler bool @@ -97,22 +98,22 @@ type ( ExtendedOptions map[string]interface{} } - // The log record + // The log record. Record struct { Message string // The message Time time.Time // The time - Level LogLevel //The level + Level LogLevel // The level Call CallStack // The call stack if built Context ContextMap // The context } - // The lazy structure to implement a function to be invoked only if needed + // The lazy structure to implement a function to be invoked only if needed. Lazy struct { Fn interface{} // the function } // Currently the only requirement for the callstack is to support the Formatter method - // which stack.Call does so we use that + // which stack.Call does so we use that. CallStack interface { fmt.Formatter // Requirement } @@ -129,6 +130,7 @@ type formatFunc func(*Record) []byte func (f formatFunc) Format(r *Record) []byte { return f(r) } + func NewRecord(message string, level LogLevel) *Record { return &Record{Message: message, Context: ContextMap{}, Level: level} } @@ -141,28 +143,28 @@ const ( LvlDebug // Debug ) -// A list of all the log levels +// LvlAllList is a list of all the log levels. var LvlAllList = []LogLevel{LvlDebug, LvlInfo, LvlWarn, LvlError, LvlCrit} -// Implements the ParentLogHandler +// Implements the ParentLogHandler. type parentLogHandler struct { setChild func(handler LogHandler) LogHandler } -// Create a new parent log handler +// Create a new parent log handler. func NewParentLogHandler(callBack func(child LogHandler) LogHandler) ParentLogHandler { return &parentLogHandler{callBack} } -// Sets the child of the log handler +// Sets the child of the log handler. func (p *parentLogHandler) SetChild(child LogHandler) LogHandler { return p.setChild(child) } -// Create a new log options +// Create a new log options. func NewLogOptions(cfg *config.Context, replaceHandler bool, phandler ParentLogHandler, lvl ...LogLevel) (logOptions *LogOptions) { logOptions = &LogOptions{ - Ctx: cfg, + Ctx: cfg, ReplaceExistingHandler: replaceHandler, HandlerWrap: phandler, Levels: lvl, @@ -171,14 +173,14 @@ func NewLogOptions(cfg *config.Context, replaceHandler bool, phandler ParentLogH return } -// Assumes options will be an even number and have a string, value syntax +// Assumes options will be an even number and have a string, value syntax. func (l *LogOptions) SetExtendedOptions(options ...interface{}) { for x := 0; x < len(options); x += 2 { l.ExtendedOptions[options[x].(string)] = options[x+1] } } -// Gets a string option with default +// Gets a string option with default. func (l *LogOptions) GetStringDefault(option, value string) string { if v, found := l.ExtendedOptions[option]; found { return v.(string) @@ -186,7 +188,7 @@ func (l *LogOptions) GetStringDefault(option, value string) string { return value } -// Gets an int option with default +// Gets an int option with default. func (l *LogOptions) GetIntDefault(option string, value int) int { if v, found := l.ExtendedOptions[option]; found { return v.(int) @@ -194,7 +196,7 @@ func (l *LogOptions) GetIntDefault(option string, value int) int { return value } -// Gets a boolean option with default +// Gets a boolean option with default. func (l *LogOptions) GetBoolDefault(option string, value bool) bool { if v, found := l.ExtendedOptions[option]; found { return v.(bool) diff --git a/logger/revel_logger.go b/logger/revel_logger.go index 0097421..8e73451 100644 --- a/logger/revel_logger.go +++ b/logger/revel_logger.go @@ -2,18 +2,19 @@ package logger import ( "fmt" - "github.com/revel/log15" "log" "os" + + "github.com/revel/log15" ) -// This type implements the MultiLogger +// This type implements the MultiLogger. type RevelLogger struct { log15.Logger } // Set the systems default logger -// Default logs will be captured and handled by revel at level info +// Default logs will be captured and handled by revel at level info. func SetDefaultLog(fromLog MultiLogger) { log.SetOutput(loggerRewrite{Logger: fromLog, Level: log15.LvlInfo, hideDeprecated: true}) // No need to show date and time, that will be logged with revel @@ -24,73 +25,73 @@ func (rl *RevelLogger) Debugf(msg string, param ...interface{}) { rl.Debug(fmt.Sprintf(msg, param...)) } -// Print a formatted info message +// Print a formatted info message. func (rl *RevelLogger) Infof(msg string, param ...interface{}) { rl.Info(fmt.Sprintf(msg, param...)) } -// Print a formatted warn message +// Print a formatted warn message. func (rl *RevelLogger) Warnf(msg string, param ...interface{}) { rl.Warn(fmt.Sprintf(msg, param...)) } -// Print a formatted error message +// Print a formatted error message. func (rl *RevelLogger) Errorf(msg string, param ...interface{}) { rl.Error(fmt.Sprintf(msg, param...)) } -// Print a formatted critical message +// Print a formatted critical message. func (rl *RevelLogger) Critf(msg string, param ...interface{}) { rl.Crit(fmt.Sprintf(msg, param...)) } -// Print a formatted fatal message +// Print a formatted fatal message. func (rl *RevelLogger) Fatalf(msg string, param ...interface{}) { rl.Fatal(fmt.Sprintf(msg, param...)) } -// Print a formatted panic message +// Print a formatted panic message. func (rl *RevelLogger) Panicf(msg string, param ...interface{}) { rl.Panic(fmt.Sprintf(msg, param...)) } -// Print a critical message and call os.Exit(1) +// Print a critical message and call os.Exit(1). func (rl *RevelLogger) Fatal(msg string, ctx ...interface{}) { rl.Crit(msg, ctx...) os.Exit(1) } -// Print a critical message and panic +// Print a critical message and panic. func (rl *RevelLogger) Panic(msg string, ctx ...interface{}) { rl.Crit(msg, ctx...) panic(msg) } -// Override log15 method +// Override log15 method. func (rl *RevelLogger) New(ctx ...interface{}) MultiLogger { old := &RevelLogger{Logger: rl.Logger.New(ctx...)} return old } -// Set the stack level to check for the caller +// Set the stack level to check for the caller. func (rl *RevelLogger) SetStackDepth(amount int) MultiLogger { rl.Logger.SetStackDepth(amount) // Ignore the logger returned return rl } -// Create a new logger +// Create a new logger. func New(ctx ...interface{}) MultiLogger { r := &RevelLogger{Logger: log15.New(ctx...)} r.SetStackDepth(0) return r } -// Set the handler in the Logger +// Set the handler in the Logger. func (rl *RevelLogger) SetHandler(h LogHandler) { rl.Logger.SetHandler(callHandler(h.Log)) } -// The function wrapper to implement the callback +// The function wrapper to implement the callback. type callHandler func(r *Record) error // Log implementation, reads the record and extracts the details from the log record @@ -99,7 +100,7 @@ func (c callHandler) Log(log *log15.Record) error { ctx := log.Ctx var ctxMap ContextMap if len(ctx) > 0 { - ctxMap = make(ContextMap, len(ctx) / 2) + ctxMap = make(ContextMap, len(ctx)/2) for i := 0; i < len(ctx); i += 2 { v := ctx[i] @@ -108,24 +109,24 @@ func (c callHandler) Log(log *log15.Record) error { key = fmt.Sprintf("LOGGER_INVALID_KEY %v", v) } var value interface{} - if len(ctx) > i + 1 { - value = ctx[i + 1] + if len(ctx) > i+1 { + value = ctx[i+1] } else { value = "LOGGER_VALUE_MISSING" } ctxMap[key] = value } } else { - ctxMap = make(ContextMap, 0) + ctxMap = make(ContextMap) } r := &Record{Message: log.Msg, Context: ctxMap, Time: log.Time, Level: LogLevel(log.Lvl), Call: CallStack(log.Call)} return c(r) } -// Internally used contextMap, allows conversion of map to map[string]string +// Internally used contextMap, allows conversion of map to map[string]string. type ContextMap map[string]interface{} -// Convert the context map to be string only values, any non string values are ignored +// Convert the context map to be string only values, any non string values are ignored. func (m ContextMap) StringMap() (newMap map[string]string) { if m != nil { newMap = map[string]string{} @@ -137,6 +138,7 @@ func (m ContextMap) StringMap() (newMap map[string]string) { } return } + func (m ContextMap) Add(key string, value interface{}) { m[key] = value } diff --git a/logger/terminal_format.go b/logger/terminal_format.go index ca2cd15..fd2e3a3 100644 --- a/logger/terminal_format.go +++ b/logger/terminal_format.go @@ -18,13 +18,13 @@ const ( errorKey = "REVEL_ERROR" ) -var ( - levelString = map[LogLevel]string{LvlDebug: "DEBUG", - LvlInfo: "INFO", LvlWarn: "WARN", LvlError: "ERROR", LvlCrit: "CRIT"} -) +var levelString = map[LogLevel]string{ + LvlDebug: "DEBUG", + LvlInfo: "INFO", LvlWarn: "WARN", LvlError: "ERROR", LvlCrit: "CRIT", +} // Outputs to the terminal in a format like below -// INFO 09:11:32 server-engine.go:169: Request Stats +// INFO 09:11:32 server-engine.go:169: Request Stats. func TerminalFormatHandler(noColor bool, smallDate bool) LogFormat { dateFormat := termTimeFormat if smallDate { @@ -32,7 +32,7 @@ func TerminalFormatHandler(noColor bool, smallDate bool) LogFormat { } return FormatFunc(func(r *Record) []byte { // Bash coloring http://misc.flogisoft.com/bash/tip_colors_and_formatting - var color = 0 + color := 0 switch r.Level { case LvlCrit: // Magenta @@ -54,7 +54,7 @@ func TerminalFormatHandler(noColor bool, smallDate bool) LogFormat { b := &bytes.Buffer{} caller, _ := r.Context["caller"].(string) module, _ := r.Context["module"].(string) - if noColor == false && color > 0 { + if !noColor && color > 0 { if len(module) > 0 { fmt.Fprintf(b, "\x1b[%dm%-5s\x1b[0m %s %6s %13s: %-40s ", color, levelString[r.Level], r.Time.Format(dateFormat), module, caller, r.Message) } else { @@ -77,7 +77,7 @@ func TerminalFormatHandler(noColor bool, smallDate bool) LogFormat { v := formatLogfmtValue(v) // TODO: we should probably check that all of your key bytes aren't invalid - if noColor == false && color > 0 { + if !noColor && color > 0 { fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m=%s", color, k, v) } else { b.WriteString(k) @@ -92,7 +92,7 @@ func TerminalFormatHandler(noColor bool, smallDate bool) LogFormat { }) } -// formatValue formats a value for serialization +// formatValue formats a value for serialization. func formatLogfmtValue(value interface{}) string { if value == nil { return "nil" @@ -121,7 +121,7 @@ func formatLogfmtValue(value interface{}) string { } } -// Format the value in json format +// Format the value in json format. func formatShared(value interface{}) (result interface{}) { defer func() { if err := recover(); err != nil { @@ -148,12 +148,12 @@ func formatShared(value interface{}) (result interface{}) { } } -// A reusuable buffer for outputting data +// A reusuable buffer for outputting data. var stringBufPool = sync.Pool{ New: func() interface{} { return new(bytes.Buffer) }, } -// Escape the string when needed +// Escape the string when needed. func escapeString(s string) string { needsQuotes := false needsEscape := false @@ -165,7 +165,7 @@ func escapeString(s string) string { needsEscape = true } } - if needsEscape == false && needsQuotes == false { + if !needsEscape && !needsQuotes { return s } e := stringBufPool.Get().(*bytes.Buffer) @@ -215,7 +215,7 @@ func JsonFormatEx(pretty, lineSeparated bool) LogFormat { props["lvl"] = levelString[r.Level] props["msg"] = r.Message for k, v := range r.Context { - props[k] = formatJsonValue(v) + props[k] = formatJSONValue(v) } b, err := jsonMarshal(props) @@ -234,7 +234,7 @@ func JsonFormatEx(pretty, lineSeparated bool) LogFormat { }) } -func formatJsonValue(value interface{}) interface{} { +func formatJSONValue(value interface{}) interface{} { value = formatShared(value) switch value.(type) { case int, int8, int16, int32, int64, float32, float64, uint, uint8, uint16, uint32, uint64, string: diff --git a/logger/utils.go b/logger/utils.go index 3918cc1..f77dfde 100644 --- a/logger/utils.go +++ b/logger/utils.go @@ -1,29 +1,31 @@ package logger import ( + "log" + "github.com/revel/log15" "gopkg.in/stack.v0" - "log" ) -// Utility package to make existing logging backwards compatible +// Utility package to make existing logging backwards compatible. var ( - // Convert the string to LogLevel - toLevel = map[string]LogLevel{"debug": LogLevel(log15.LvlDebug), - "info": LogLevel(log15.LvlInfo), "request": LogLevel(log15.LvlInfo), "warn": LogLevel(log15.LvlWarn), + // Convert the string to LogLevel. + toLevel = map[string]LogLevel{ + "debug": LogLevel(log15.LvlDebug), + "info": LogLevel(log15.LvlInfo), "request": LogLevel(log15.LvlInfo), "warn": LogLevel(log15.LvlWarn), "error": LogLevel(log15.LvlError), "crit": LogLevel(log15.LvlCrit), "trace": LogLevel(log15.LvlDebug), // TODO trace is deprecated, replaced by debug } ) const ( - // The test mode flag overrides the default log level and shows only errors + // The test mode flag overrides the default log level and shows only errors. TEST_MODE_FLAG = "testModeFlag" - // The special use flag enables showing messages when the logger is setup + // The special use flag enables showing messages when the logger is setup. SPECIAL_USE_FLAG = "specialUseFlag" ) -// Returns the logger for the name +// Returns the logger for the name. func GetLogger(name string, logger MultiLogger) (l *log.Logger) { switch name { case "trace": // TODO trace is deprecated, replaced by debug @@ -41,10 +43,9 @@ func GetLogger(name string, logger MultiLogger) (l *log.Logger) { } return l - } -// Used by the initFilterLog to handle the filters +// Used by the initFilterLog to handle the filters. var logFilterList = []struct { LogPrefix, LogSuffix string parentHandler func(map[string]interface{}) ParentLogHandler @@ -54,7 +55,6 @@ var logFilterList = []struct { return NewParentLogHandler(func(child LogHandler) LogHandler { return MatchMapHandler(keyMap, child) }) - }, }, { "log.", ".nfilter", @@ -65,20 +65,20 @@ var logFilterList = []struct { }, }} -// This structure and method will handle the old output format and log it to the new format +// This structure and method will handle the old output format and log it to the new format. type loggerRewrite struct { Logger MultiLogger Level log15.Lvl hideDeprecated bool } -// The message indicating that a logger is using a deprecated log mechanism -var log_deprecated = []byte("* LOG DEPRECATED * ") +// The message indicating that a logger is using a deprecated log mechanism. +var logDeprecated = []byte("* LOG DEPRECATED * ") -// Implements the Write of the logger +// Implements the Write of the logger. func (lr loggerRewrite) Write(p []byte) (n int, err error) { if !lr.hideDeprecated { - p = append(log_deprecated, p...) + p = append(logDeprecated, p...) } n = len(p) if len(p) > 0 && p[n-1] == '\n' { @@ -104,7 +104,7 @@ func (lr loggerRewrite) Write(p []byte) (n int, err error) { // For logging purposes the call stack can be used to record the stack trace of a bad error // simply pass it as a context field in your log statement like -// `controller.Log.Crit("This should not occur","stack",revel.NewCallStack())` +// `controller.Log.Crit("This should not occur","stack",revel.NewCallStack())`. func NewCallStack() interface{} { return stack.Trace() } diff --git a/logger/wrap_handlers.go b/logger/wrap_handlers.go index 3d68e75..2901c88 100644 --- a/logger/wrap_handlers.go +++ b/logger/wrap_handlers.go @@ -9,29 +9,29 @@ import ( "time" ) -// Function handler wraps the declared function and returns the handler for it +// Function handler wraps the declared function and returns the handler for it. func FuncHandler(fn func(r *Record) error) LogHandler { return funcHandler(fn) } -// The type decleration for the function +// The type declaration for the function. type funcHandler func(r *Record) error -// The implementation of the Log +// The implementation of the Log. func (h funcHandler) Log(r *Record) error { return h(r) } // This function allows you to do a full declaration for the log, -// it is recommended you use FuncHandler instead +// it is recommended you use FuncHandler instead. func HandlerFunc(log func(message string, time time.Time, level LogLevel, call CallStack, context ContextMap) error) LogHandler { return remoteHandler(log) } -// The type used for the HandlerFunc +// The type used for the HandlerFunc. type remoteHandler func(message string, time time.Time, level LogLevel, call CallStack, context ContextMap) error -// The Log implementation +// The Log implementation. func (c remoteHandler) Log(record *Record) error { return c(record.Message, record.Time, record.Level, record.Call, record.Context) } @@ -56,11 +56,9 @@ func LazyHandler(h LogHandler) LogHandler { return FuncHandler(func(r *Record) error { for k, v := range r.Context { if lz, ok := v.(Lazy); ok { - value, err := evaluateLazy(lz) + _, err := evaluateLazy(lz) if err != nil { r.Context[errorKey] = "bad lazy " + k - } else { - v = value } } } @@ -88,11 +86,12 @@ func evaluateLazy(lz Lazy) (interface{}, error) { results := value.Call([]reflect.Value{}) if len(results) == 1 { return results[0].Interface(), nil - } else { - values := make([]interface{}, len(results)) - for i, v := range results { - values[i] = v.Interface() - } - return values, nil } + + values := make([]interface{}, len(results)) + for i, v := range results { + values[i] = v.Interface() + } + + return values, nil } diff --git a/model/command/build.go b/model/command/build.go index 61e3cbb..2628b6f 100644 --- a/model/command/build.go +++ b/model/command/build.go @@ -1,4 +1,5 @@ package command + type ( Build struct { ImportCommand @@ -6,5 +7,4 @@ type ( Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` CopySource bool `short:"s" long:"include-source" description:"Copy the source code as well"` } - ) diff --git a/model/command/clean.go b/model/command/clean.go index 644cca7..98160fb 100644 --- a/model/command/clean.go +++ b/model/command/clean.go @@ -1,4 +1,5 @@ package command + type ( Clean struct { ImportCommand diff --git a/model/command/new.go b/model/command/new.go index 5ff685f..9c70419 100644 --- a/model/command/new.go +++ b/model/command/new.go @@ -1,6 +1,5 @@ package command - type ( New struct { ImportCommand @@ -8,7 +7,6 @@ type ( 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 `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 + Callback func() error } - -) \ No newline at end of file +) diff --git a/model/command/package.go b/model/command/package.go index 264ea12..bc9d2d1 100644 --- a/model/command/package.go +++ b/model/command/package.go @@ -1,4 +1,5 @@ package command + type ( Package struct { ImportCommand @@ -6,4 +7,4 @@ type ( Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` CopySource bool `short:"s" long:"include-source" description:"Copy the source code as well"` } -) \ No newline at end of file +) diff --git a/model/command/run.go b/model/command/run.go index 1c745e6..79de82c 100644 --- a/model/command/run.go +++ b/model/command/run.go @@ -1,9 +1,10 @@ package command + type ( Run struct { ImportCommand - Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` - Port int `short:"p" long:"port" default:"-1" description:"The port to listen" ` - NoProxy bool `short:"n" long:"no-proxy" description:"True if proxy server should not be started. This will only update the main and routes files on change"` + Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` + Port int `short:"p" long:"port" default:"-1" description:"The port to listen" ` + NoProxy bool `short:"n" long:"no-proxy" description:"True if proxy server should not be started. This will only update the main and routes files on change"` } -) \ No newline at end of file +) diff --git a/model/command/test_command.go b/model/command/test_command.go index 0822441..58539e1 100644 --- a/model/command/test_command.go +++ b/model/command/test_command.go @@ -3,7 +3,7 @@ package command type ( Test struct { ImportCommand - Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` - Function string `short:"f" long:"suite-function" description:"The suite.function"` + Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` + Function string `short:"f" long:"suite-function" description:"The suite.function"` } -) \ No newline at end of file +) diff --git a/model/command/version.go b/model/command/version.go index 71bfe2b..df16068 100644 --- a/model/command/version.go +++ b/model/command/version.go @@ -1,4 +1,5 @@ package command + type ( Version struct { ImportCommand diff --git a/model/command_config.go b/model/command_config.go index fc8776a..aa0ad8f 100644 --- a/model/command_config.go +++ b/model/command_config.go @@ -2,8 +2,6 @@ package model import ( "fmt" - "github.com/revel/cmd" - "github.com/revel/cmd/utils" "go/ast" "go/build" "go/parser" @@ -13,10 +11,13 @@ import ( "os/exec" "path/filepath" "strings" + + "github.com/revel/cmd" "github.com/revel/cmd/model/command" + "github.com/revel/cmd/utils" ) -// The constants +// The constants. const ( NEW COMMAND = iota + 1 RUN @@ -28,38 +29,38 @@ const ( ) type ( - // The Revel command type + // The Revel command type. COMMAND int - // The Command config for the line input + // The Command config for the line input. CommandConfig struct { - Index COMMAND // The index - Verbose []bool `short:"v" long:"debug" description:"If set the logger is set to verbose"` // True if debug is active - FrameworkVersion *Version // The framework version - CommandVersion *Version // The command version - HistoricMode bool `long:"historic-run-mode" description:"If set the runmode is passed a string not json"` // True if debug is active - 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 - 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 + Index COMMAND // The index + Verbose []bool `short:"v" long:"debug" description:"If set the logger is set to verbose"` // True if debug is active + FrameworkVersion *Version // The framework version + CommandVersion *Version // The command version + HistoricMode bool `long:"historic-run-mode" description:"If set the runmode is passed a string not json"` // True if debug is active + 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 + 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 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"` - Package command.Package `command:"package"` - Clean command.Clean `command:"clean"` - Test command.Test `command:"test"` - Version command.Version `command:"version"` + 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"` + Package command.Package `command:"package"` + Clean command.Clean `command:"clean"` + Test command.Test `command:"test"` + Version command.Version `command:"version"` } ) -// Updates the import path depending on the command +// Updates the import path depending on the command. func (c *CommandConfig) UpdateImportPath() error { var importPath string required := true @@ -102,14 +103,14 @@ func (c *CommandConfig) UpdateImportPath() error { if err == nil { for _, path := range strings.Split(build.Default.GOPATH, string(filepath.ListSeparator)) { utils.Logger.Infof("Checking import path %s with %s", currentPath, path) - if strings.HasPrefix(currentPath, path) && len(currentPath) > len(path) + 1 { - importPath = currentPath[len(path) + 1:] + if strings.HasPrefix(currentPath, path) && len(currentPath) > len(path)+1 { + importPath = currentPath[len(path)+1:] // Remove the source from the path if it is there if len(importPath) > 4 && (strings.ToLower(importPath[0:4]) == "src/" || strings.ToLower(importPath[0:4]) == "src\\") { importPath = importPath[4:] } else if importPath == "src" { if c.Index != VERSION { - return fmt.Errorf("Invlaid import path, working dir is in GOPATH root") + return fmt.Errorf("invalid import path, working dir is in GOPATH root") } importPath = "" } @@ -137,7 +138,7 @@ func (c *CommandConfig) UpdateImportPath() error { return nil } if len(importPath) == 0 { - return fmt.Errorf("Unable to determine import path from : %s", importPath) + return fmt.Errorf("unable to determine import path from : %s", importPath) } return nil } @@ -153,11 +154,11 @@ func (c *CommandConfig) initAppFolder() (err error) { // First try to determine where the application is located - this should be the import value appFolder := c.ImportPath - wd, err := os.Getwd() + wd, _ := os.Getwd() if len(appFolder) == 0 { // We will assume the working directory is the appFolder appFolder = wd - } else if strings.LastIndex(wd, appFolder) == len(wd) - len(appFolder) { + } else if strings.LastIndex(wd, appFolder) == len(wd)-len(appFolder) { // Check for existence of an /app folder if utils.Exists(filepath.Join(wd, "app")) { appFolder = wd @@ -174,7 +175,7 @@ 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)) + 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) @@ -186,7 +187,7 @@ 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 + // c.SrcRoot = appFolder utils.Logger.Info("Set application path and package based on go mod", "path", c.AppPath) return nil } @@ -216,17 +217,16 @@ func (c *CommandConfig) initAppFolder() (err error) { c.AppPath = filepath.Join(bestpath, "src", c.ImportPath) } // Recalculate the appFolder because we are using a GOPATH - } else { // This is new and not vendored, so the app path is the appFolder c.AppPath = appFolder } - utils.Logger.Info("Set application path", "path", c.AppPath, "vendored",c.Vendored, "importpath",c.ImportPath) + utils.Logger.Info("Set application path", "path", c.AppPath, "vendored", c.Vendored, "importpath", c.ImportPath) return nil } -// Used to initialize the package resolver +// Used to initialize the package resolver. func (c *CommandConfig) InitPackageResolver() { c.initGoPaths() utils.Logger.Info("InitPackageResolver", "useVendor", c.Vendored, "path", c.AppPath) @@ -237,7 +237,7 @@ func (c *CommandConfig) InitPackageResolver() { var getCmd *exec.Cmd print("Downloading related packages ...") if c.Vendored { - getCmd = exec.Command(c.GoCmd, "mod", "tidy") + getCmd = exec.Command(c.GoCmd, "mod", "tidy", "-v") } 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) @@ -255,7 +255,7 @@ func (c *CommandConfig) InitPackageResolver() { } } -// lookup and set Go related variables +// lookup and set Go related variables. func (c *CommandConfig) initGoPaths() { utils.Logger.Info("InitGoPaths", "vendored", c.Vendored) // check for go executable @@ -275,10 +275,7 @@ func (c *CommandConfig) initGoPaths() { utils.Logger.Fatal("Abort: GOPATH environment variable is not set. " + "Please refer to http://golang.org/doc/code.html to configure your Go environment.") } - return - //todo determine if the rest needs to happen - - + // 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 @@ -303,11 +300,10 @@ func (c *CommandConfig) initGoPaths() { 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 +// Sets the versions on the command config. func (c *CommandConfig) SetVersions() (err error) { c.CommandVersion, _ = ParseVersion(cmd.Version) pathMap, err := utils.FindSrcPaths(c.AppPath, []string{RevelImportPath}, c.PackageResolver) @@ -339,7 +335,7 @@ func (c *CommandConfig) SetVersions() (err error) { spec := a.(*ast.ValueSpec) r := spec.Values[0].(*ast.BasicLit) if spec.Names[0].Name == "Version" { - c.FrameworkVersion, err = ParseVersion(strings.Replace(r.Value, `"`, ``, -1)) + c.FrameworkVersion, err = ParseVersion(strings.ReplaceAll(r.Value, `"`, ``)) if err != nil { utils.Logger.Errorf("Failed to parse version") } else { diff --git a/model/embedded_type_name.go b/model/embedded_type_name.go index f6d6172..f935626 100644 --- a/model/embedded_type_name.go +++ b/model/embedded_type_name.go @@ -1,11 +1,11 @@ package model -// The embedded type name takes the import path and structure name +// The embedded type name takes the import path and structure name. type EmbeddedTypeName struct { ImportPath, StructName string } -// Convert the type to a properly formatted import line +// Convert the type to a properly formatted import line. func (s *EmbeddedTypeName) String() string { return s.ImportPath + "." + s.StructName } diff --git a/model/event.go b/model/event.go index 7032443..b95c1c1 100644 --- a/model/event.go +++ b/model/event.go @@ -1,11 +1,11 @@ package model type ( - // The event type + // The event type. Event int - // The event response + // The event response. EventResponse int - // The handler signature + // The handler signature. EventHandler func(typeOf Event, value interface{}) (responseOf EventResponse) RevelCallback interface { FireEvent(key Event, value interface{}) (response EventResponse) @@ -14,40 +14,40 @@ type ( ) const ( - // Event type when templates are going to be refreshed (receivers are registered template engines added to the template.engine conf option) + // Event type when templates are going to be refreshed (receivers are registered template engines added to the template.engine conf option). TEMPLATE_REFRESH_REQUESTED Event = iota - // Event type when templates are refreshed (receivers are registered template engines added to the template.engine conf option) + // Event type when templates are refreshed (receivers are registered template engines added to the template.engine conf option). TEMPLATE_REFRESH_COMPLETED - // Event type before all module loads, events thrown to handlers added to AddInitEventHandler + // Event type before all module loads, events thrown to handlers added to AddInitEventHandler. - // Event type before all module loads, events thrown to handlers added to AddInitEventHandler + // Event type before all module loads, events thrown to handlers added to AddInitEventHandler. REVEL_BEFORE_MODULES_LOADED - // Event type before module loads, events thrown to handlers added to AddInitEventHandler + // Event type before module loads, events thrown to handlers added to AddInitEventHandler. REVEL_BEFORE_MODULE_LOADED - // Event type after module loads, events thrown to handlers added to AddInitEventHandler + // Event type after module loads, events thrown to handlers added to AddInitEventHandler. REVEL_AFTER_MODULE_LOADED - // Event type after all module loads, events thrown to handlers added to AddInitEventHandler + // Event type after all module loads, events thrown to handlers added to AddInitEventHandler. REVEL_AFTER_MODULES_LOADED - // Event type before server engine is initialized, receivers are active server engine and handlers added to AddInitEventHandler + // Event type before server engine is initialized, receivers are active server engine and handlers added to AddInitEventHandler. ENGINE_BEFORE_INITIALIZED - // Event type before server engine is started, receivers are active server engine and handlers added to AddInitEventHandler + // Event type before server engine is started, receivers are active server engine and handlers added to AddInitEventHandler. ENGINE_STARTED - // Event type after server engine is stopped, receivers are active server engine and handlers added to AddInitEventHandler + // Event type after server engine is stopped, receivers are active server engine and handlers added to AddInitEventHandler. ENGINE_SHUTDOWN - // Called before routes are refreshed + // Called before routes are refreshed. ROUTE_REFRESH_REQUESTED - // Called after routes have been refreshed + // Called after routes have been refreshed. ROUTE_REFRESH_COMPLETED - // Fired when a panic is caught during the startup process + // Fired when a panic is caught during the startup process. REVEL_FAILURE ) var initEventList = []EventHandler{} // Event handler list for receiving events -// Fires system events from revel +// Fires system events from revel. func RaiseEvent(key Event, value interface{}) (response EventResponse) { for _, handler := range initEventList { response |= handler(key, value) @@ -55,8 +55,7 @@ func RaiseEvent(key Event, value interface{}) (response EventResponse) { return } -// Add event handler to listen for all system events +// Add event handler to listen for all system events. func AddInitEventHandler(handler EventHandler) { initEventList = append(initEventList, handler) - return } diff --git a/model/event_test.go b/model/event_test.go index d1612aa..8b88f70 100644 --- a/model/event_test.go +++ b/model/event_test.go @@ -1,12 +1,13 @@ package model_test import ( + "testing" + "github.com/revel/revel" "github.com/stretchr/testify/assert" - "testing" ) -// Test that the event handler can be attached and it dispatches the event received +// Test that the event handler can be attached and it dispatches the event received. func TestEventHandler(t *testing.T) { counter := 0 newListener := func(typeOf revel.Event, value interface{}) (responseOf revel.EventResponse) { @@ -21,4 +22,3 @@ func TestEventHandler(t *testing.T) { revel.StopServer(1) assert.Equal(t, counter, 2, "Expected event handler to have been called") } - diff --git a/model/method.go b/model/method.go index ea5357d..ddff518 100644 --- a/model/method.go +++ b/model/method.go @@ -8,14 +8,14 @@ type MethodCall struct { Names []string } -// MethodSpec holds the information of one Method +// MethodSpec holds the information of one Method. type MethodSpec struct { Name string // Name of the method, e.g. "Index" Args []*MethodArg // Argument descriptors RenderCalls []*MethodCall // Descriptions of Render() invocations from this Method. } -// MethodArg holds the information of one argument +// MethodArg holds the information of one argument. type MethodArg struct { Name string // Name of the argument. TypeExpr TypeExpr // The name of the type, e.g. "int", "*pkg.UserType" diff --git a/model/revel_container.go b/model/revel_container.go index 0647208..9632910 100644 --- a/model/revel_container.go +++ b/model/revel_container.go @@ -2,18 +2,19 @@ package model import ( - "github.com/revel/cmd/utils" - "github.com/revel/config" "errors" "fmt" "path/filepath" "sort" "strings" + + "github.com/revel/cmd/utils" + "github.com/revel/config" "golang.org/x/tools/go/packages" ) type ( - // The container object for describing all Revels variables + // The container object for describing all Revels variables. RevelContainer struct { BuildPaths struct { Revel string @@ -39,36 +40,36 @@ type ( Root string } - ImportPath string // The import path - SourcePath string // The full source path - RunMode string // The current run mode - RevelPath string // The path to the Revel source code - BasePath string // The base path to the application - AppPath string // The application path (BasePath + "/app") - ViewsPath string // The application views path - CodePaths []string // All the code paths - TemplatePaths []string // All the template paths - ConfPaths []string // All the configuration paths - Config *config.Context // The global config object - Packaged bool // True if packaged - DevMode bool // True if running in dev mode - HTTPPort int // The http port - HTTPAddr string // The http address - HTTPSsl bool // True if running https - HTTPSslCert string // The SSL certificate - HTTPSslKey string // The SSL key - AppName string // The application name - AppRoot string // The application root from the config `app.root` - CookiePrefix string // The cookie prefix - CookieDomain string // The cookie domain - CookieSecure bool // True if cookie is secure - SecretStr string // The secret string - MimeConfig *config.Context // The mime configuration + ImportPath string // The import path + SourcePath string // The full source path + RunMode string // The current run mode + RevelPath string // The path to the Revel source code + BasePath string // The base path to the application + AppPath string // The application path (BasePath + "/app") + ViewsPath string // The application views path + CodePaths []string // All the code paths + TemplatePaths []string // All the template paths + ConfPaths []string // All the configuration paths + Config *config.Context // The global config object + Packaged bool // True if packaged + DevMode bool // True if running in dev mode + HTTPPort int // The http port + HTTPAddr string // The http address + HTTPSsl bool // True if running https + HTTPSslCert string // The SSL certificate + HTTPSslKey string // The SSL key + AppName string // The application name + AppRoot string // The application root from the config `app.root` + CookiePrefix string // The cookie prefix + CookieDomain string // The cookie domain + CookieSecure bool // True if cookie is secure + SecretStr string // The secret string + MimeConfig *config.Context // The mime configuration ModulePathMap map[string]*ModuleInfo // The module path map } ModuleInfo struct { ImportPath string - Path string + Path string } WrappedRevelCallback struct { @@ -77,25 +78,28 @@ type ( } ) -// Simple Wrapped RevelCallback +// Simple Wrapped RevelCallback. func NewWrappedRevelCallback(fe func(key Event, value interface{}) (response EventResponse), ie func(pkgName string) error) RevelCallback { return &WrappedRevelCallback{fe, ie} } -// Function to implement the FireEvent +// Function to implement the FireEvent. func (w *WrappedRevelCallback) FireEvent(key Event, value interface{}) (response EventResponse) { if w.FireEventFunction != nil { response = w.FireEventFunction(key, value) } return } + func (w *WrappedRevelCallback) PackageResolver(pkgName string) error { return w.ImportFunction(pkgName) } -// RevelImportPath Revel framework import path -var RevelImportPath = "github.com/revel/revel" -var RevelModulesImportPath = "github.com/revel/modules" +// RevelImportPath Revel framework import path. +var ( + RevelImportPath = "github.com/revel/revel" + RevelModulesImportPath = "github.com/revel/modules" +) // This function returns a container object describing the revel application // eventually this type of function will replace the global variables. @@ -107,7 +111,7 @@ func NewRevelPaths(mode, importPath, appSrcPath string, callback RevelCallback) rp.RunMode = mode // We always need to determine the paths for files - pathMap, err := utils.FindSrcPaths(appSrcPath, []string{importPath+"/app", RevelImportPath}, callback.PackageResolver) + pathMap, err := utils.FindSrcPaths(appSrcPath, []string{importPath + "/app", RevelImportPath}, callback.PackageResolver) if err != nil { return } @@ -118,11 +122,11 @@ func NewRevelPaths(mode, importPath, appSrcPath string, callback RevelCallback) rp.AppPath = filepath.Join(rp.BasePath, "app") // 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) + if !utils.DirExists(rp.AppPath) { + return rp, fmt.Errorf("no application found at path %s", rp.AppPath) } if !utils.DirExists(filepath.Join(rp.BasePath, "conf")) { - return rp, fmt.Errorf("No configuration found at path %s", filepath.Join(rp.BasePath, "conf")) + return rp, fmt.Errorf("no configuration found at path %s", filepath.Join(rp.BasePath, "conf")) } rp.ViewsPath = filepath.Join(rp.AppPath, "views") @@ -146,7 +150,7 @@ func NewRevelPaths(mode, importPath, appSrcPath string, callback RevelCallback) rp.Config, err = config.LoadContext("app.conf", rp.ConfPaths) if err != nil { - return rp, fmt.Errorf("Unable to load configuartion file %s", err) + return rp, fmt.Errorf("unable to load configuration file %s", err) } // Ensure that the selected runmode appears in app.conf. @@ -168,10 +172,10 @@ func NewRevelPaths(mode, importPath, appSrcPath string, callback RevelCallback) rp.HTTPSslKey = rp.Config.StringDefault("http.sslkey", "") if rp.HTTPSsl { if rp.HTTPSslCert == "" { - return rp, errors.New("No http.sslcert provided.") + return rp, errors.New("no http.sslcert provided") } if rp.HTTPSslKey == "" { - return rp, errors.New("No http.sslkey provided.") + return rp, errors.New("no http.sslkey provided") } } // @@ -197,7 +201,7 @@ func NewRevelPaths(mode, importPath, appSrcPath string, callback RevelCallback) func (rp *RevelContainer) LoadMimeConfig() (err error) { rp.MimeConfig, err = config.LoadContext("mime-types.conf", rp.ConfPaths) if err != nil { - return fmt.Errorf("Failed to load mime type config: %s %s", "error", err) + return fmt.Errorf("failed to load mime type config: %s %s", "error", err) } return } @@ -206,12 +210,10 @@ func (rp *RevelContainer) LoadMimeConfig() (err error) { // This will fire the REVEL_BEFORE_MODULE_LOADED, REVEL_AFTER_MODULE_LOADED // for each module loaded. The callback will receive the RevelContainer, name, moduleImportPath and modulePath // It will automatically add in the code paths for the module to the -// container object +// container object. func (rp *RevelContainer) loadModules(callback RevelCallback) (err error) { keys := []string{} - for _, key := range rp.Config.Options("module.") { - keys = append(keys, key) - } + keys = append(keys, rp.Config.Options("module.")...) // Reorder module order by key name, a poor mans sort but at least it is consistent sort.Strings(keys) @@ -223,11 +225,11 @@ 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) + utils.Logger.Info("Missing module ", "module_import_path", moduleImportPath, "error", err) callback.PackageResolver(moduleImportPath) modulePath, err = rp.ResolveImportPath(moduleImportPath) if err != nil { - return fmt.Errorf("Failed to load module. Import of path failed %s:%s %s:%s ", "modulePath", moduleImportPath, "error", err) + return fmt.Errorf("failed to load module. Import of path failed %s:%s %s:%s ", "modulePath", moduleImportPath, "error", err) } } // Drop anything between module.???. @@ -242,9 +244,9 @@ func (rp *RevelContainer) loadModules(callback RevelCallback) (err error) { return } -// Adds a module paths to the container object +// Adds a module paths to the container object. func (rp *RevelContainer) addModulePaths(name, importPath, modulePath string) { - utils.Logger.Info("Adding module path","name", name,"import path", importPath,"system path", modulePath) + utils.Logger.Info("Adding module path", "name", name, "import path", importPath, "system path", modulePath) if codePath := filepath.Join(modulePath, "app"); utils.DirExists(codePath) { rp.CodePaths = append(rp.CodePaths, codePath) rp.ModulePathMap[name] = &ModuleInfo{importPath, modulePath} @@ -271,19 +273,20 @@ func (rp *RevelContainer) ResolveImportPath(importPath string) (string, error) { return filepath.Join(rp.SourcePath, importPath), nil } config := &packages.Config{ - Mode: packages.LoadSyntax, - Dir:rp.AppPath, + Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | + packages.NeedTypes | packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo, + Dir: rp.AppPath, } - - pkgs, err := packages.Load(config, importPath) - if len(pkgs)==0 { - return "", errors.New("No packages found for import " + importPath +" using app path "+ rp.AppPath) + config.Env = utils.ReducedEnv(false) + pkgs, err := packages.Load(config, importPath) + if len(pkgs) == 0 { + return "", errors.New("No packages found for import " + importPath + " using app path " + rp.AppPath) } -// modPkg, err := build.Import(importPath, rp.AppPath, build.FindOnly) + // modPkg, err := build.Import(importPath, rp.AppPath, build.FindOnly) if err != nil { return "", err } - if len(pkgs[0].GoFiles)>0 { + 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) diff --git a/model/source_info.go b/model/source_info.go index 8da1b26..e304fbb 100644 --- a/model/source_info.go +++ b/model/source_info.go @@ -3,23 +3,24 @@ package model // SourceInfo is the top-level struct containing all extracted information // about the app source code, used to generate main.go. import ( - "github.com/revel/cmd/utils" "path/filepath" "strings" "unicode" + + "github.com/revel/cmd/utils" ) type SourceInfo struct { // StructSpecs lists type info for all structs found under the code paths. // They may be queried to determine which ones (transitively) embed certain types. - StructSpecs []*TypeInfo + StructSpecs []*TypeInfo // ValidationKeys provides a two-level lookup. The keys are: // 1. The fully-qualified function name, // e.g. "github.com/revel/examples/chat/app/controllers.(*Application).Action" // 2. Within that func's file, the line number of the (overall) expression statement. // e.g. the line returned from runtime.Caller() // The result of the lookup the name of variable being validated. - ValidationKeys map[string]map[int]string + ValidationKeys map[string]map[int]string // A list of import paths. // Revel notices files with an init() function and imports that package. InitImportPaths []string @@ -28,14 +29,14 @@ type SourceInfo struct { // app/controllers/... that embed (directly or indirectly) revel.Controller controllerSpecs []*TypeInfo // testSuites list the types that constitute the set of application tests. - testSuites []*TypeInfo + testSuites []*TypeInfo // packageMap a map of import to system directory (if available) - PackageMap map[string]string + PackageMap map[string]string } // TypesThatEmbed returns all types that (directly or indirectly) embed the // target type, which must be a fully qualified type name, -// e.g. "github.com/revel/revel.Controller" +// e.g. "github.com/revel/revel.Controller". func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered []*TypeInfo) { // Do a search in the "embedded type graph", starting with the target type. var ( @@ -75,7 +76,8 @@ func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered utils.Logger.Info("Debug: Skipping adding spec for unexported type", "type", filteredItem.StructName, "package", filteredItem.ImportPath) - filtered = append(filtered[:i], filtered[i + 1:]...) + filtered = append(filtered[:i], filtered[i+1:]...) + //nolint:ineffassign // huh? exit = false break } @@ -98,8 +100,8 @@ func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered // Report non controller structures in controller folder. if !found && !strings.HasPrefix(spec.StructName, "Test") { - utils.Logger.Warn("Type found in package: " + packageFilter + - ", but did not embed from: " + filepath.Base(targetType), + utils.Logger.Warn("Type found in package: "+packageFilter+ + ", but did not embed from: "+filepath.Base(targetType), "name", spec.StructName, "importpath", spec.ImportPath, "foundstructures", unfoundNames) } } @@ -108,20 +110,20 @@ func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered } // ControllerSpecs returns the all the controllers that embeds -// `revel.Controller` +// `revel.Controller`. func (s *SourceInfo) ControllerSpecs() []*TypeInfo { - utils.Logger.Info("Scanning controller specifications for types ","typePath",RevelImportPath + ".Controller", "speclen",len(s.controllerSpecs)) + 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") + s.controllerSpecs = s.TypesThatEmbed(RevelImportPath+".Controller", "controllers") } return s.controllerSpecs } // TestSuites returns the all the Application tests that embeds -// `testing.TestSuite` +// `testing.TestSuite`. func (s *SourceInfo) TestSuites() []*TypeInfo { if s.testSuites == nil { - s.testSuites = s.TypesThatEmbed(RevelImportPath + "/testing.TestSuite", "testsuite") + s.testSuites = s.TypesThatEmbed(RevelImportPath+"/testing.TestSuite", "testsuite") } return s.testSuites } @@ -136,4 +138,4 @@ func (s *SourceInfo) Merge(srcInfo2 *SourceInfo) { } s.ValidationKeys[k] = v } -} \ No newline at end of file +} diff --git a/model/type_expr.go b/model/type_expr.go index 9f8d2b9..4263e21 100644 --- a/model/type_expr.go +++ b/model/type_expr.go @@ -13,7 +13,7 @@ type TypeExpr struct { Valid bool } -// Returns a new type from the data +// Returns a new type from the data. func NewTypeExprFromData(expr, pkgName string, pkgIndex int, valid bool) TypeExpr { return TypeExpr{expr, pkgName, pkgIndex, valid} } @@ -47,7 +47,6 @@ func NewTypeExprFromAst(pkgName string, expr ast.Expr) TypeExpr { return NewTypeExprFromData("[]"+e.Expr, e.PkgName, e.pkgIndex+2, e.Valid) default: error = fmt.Sprintf("Failed to generate name for field: %v Package: %v. Make sure the field name is valid.", expr, pkgName) - } return NewTypeExprFromData(error, "", 0, false) } @@ -85,13 +84,13 @@ var builtInTypes = map[string]struct{}{ "uintptr": {}, } -// IsBuiltinType checks the given type is built-in types of Go +// IsBuiltinType checks the given type is built-in types of Go. func IsBuiltinType(name string) bool { _, ok := builtInTypes[name] return ok } -// Returns the first non empty string from a list of arguements +// Returns the first non empty string from a list of arguments. func FirstNonEmpty(strs ...string) string { for _, str := range strs { if len(str) > 0 { diff --git a/model/type_info.go b/model/type_info.go index 97fb6bb..cb1ba02 100644 --- a/model/type_info.go +++ b/model/type_info.go @@ -9,7 +9,7 @@ type TypeInfo struct { EmbeddedTypes []*EmbeddedTypeName // Used internally to identify controllers that indirectly embed *revel.Controller. } -// Return the type information as a properly formatted import string +// Return the type information as a properly formatted import string. func (s *TypeInfo) String() string { return s.ImportPath + "." + s.StructName } diff --git a/model/version.go b/model/version.go index 1951790..1f70345 100644 --- a/model/version.go +++ b/model/version.go @@ -2,9 +2,10 @@ package model import ( "fmt" - "github.com/pkg/errors" "regexp" "strconv" + + "github.com/pkg/errors" ) type Version struct { @@ -17,26 +18,24 @@ type Version struct { MinGoVersion string } -// The compatibility list +// The compatibility list. var frameworkCompatibleRangeList = [][]string{ - {"0.0.0", "0.20.0"}, // minimum Revel version to use with this version of the tool + {"0.0.0", "0.20.0"}, // minimum Revel version to use with this version of the tool {"0.19.99", "0.30.0"}, // Compatible with Framework V 0.19.99 - 0.30.0 - {"1.0.0", "1.9.0"}, // Compatible with Framework V 1.0 - 1.9 + {"1.0.0", "1.9.0"}, // Compatible with Framework V 1.0 - 1.9 } -// Parses a version like v1.2.3a or 1.2 +// Parses a version like v1.2.3a or 1.2. var versionRegExp = regexp.MustCompile(`([^\d]*)?([0-9]*)\.([0-9]*)(\.([0-9]*))?(.*)`) -// Parse the version and return it as a Version object +// Parse the version and return it as a Version object. func ParseVersion(version string) (v *Version, err error) { - v = &Version{} return v, v.ParseVersion(version) } -// Parse the version and return it as a Version object -func (v *Version)ParseVersion(version string) (err error) { - +// Parse the version and return it as a Version object. +func (v *Version) ParseVersion(version string) (err error) { parsedResult := versionRegExp.FindAllStringSubmatch(version, -1) if len(parsedResult) != 1 { err = errors.Errorf("Invalid version %s", version) @@ -55,7 +54,8 @@ func (v *Version)ParseVersion(version string) (err error) { return } -// Returns 0 or an int value for the string, errors are returned as 0 + +// Returns 0 or an int value for the string, errors are returned as 0. func (v *Version) intOrZero(input string) (value int) { if input != "" { value, _ = strconv.Atoi(input) @@ -63,7 +63,7 @@ func (v *Version) intOrZero(input string) (value int) { return value } -// Returns true if this major revision is compatible +// Returns true if this major revision is compatible. func (v *Version) CompatibleFramework(c *CommandConfig) error { for i, rv := range frameworkCompatibleRangeList { start, _ := ParseVersion(rv[0]) @@ -81,7 +81,7 @@ func (v *Version) CompatibleFramework(c *CommandConfig) error { return errors.New("Tool out of date - do a 'go get -u github.com/revel/cmd/revel'") } -// Returns true if this major revision is newer then the passed in +// Returns true if this major revision is newer then the passed in. func (v *Version) MajorNewer(o *Version) bool { if v.Major != o.Major { return v.Major > o.Major @@ -89,7 +89,7 @@ func (v *Version) MajorNewer(o *Version) bool { return false } -// Returns true if this major or major and minor revision is newer then the value passed in +// Returns true if this major or major and minor revision is newer then the value passed in. func (v *Version) MinorNewer(o *Version) bool { if v.Major != o.Major { return v.Major > o.Major @@ -100,7 +100,7 @@ func (v *Version) MinorNewer(o *Version) bool { return false } -// Returns true if the version is newer then the current on +// Returns true if the version is newer then the current on. func (v *Version) Newer(o *Version) bool { if v.Major != o.Major { return v.Major > o.Major @@ -114,13 +114,13 @@ func (v *Version) Newer(o *Version) bool { return true } -// Convert the version to a string +// Convert the version to a string. func (v *Version) VersionString() string { return fmt.Sprintf("%s%d.%d.%d%s", v.Prefix, v.Major, v.Minor, v.Maintenance, v.Suffix) } -// Convert the version build date and go version to a string +// Convert the version build date and go version to a string. func (v *Version) String() string { - return fmt.Sprintf("Version: %s%d.%d.%d%s\nBuild Date: %s\n Minimium Go Version: %s", + return fmt.Sprintf("Version: %s%d.%d.%d%s\nBuild Date: %s\n Minimum Go Version: %s", v.Prefix, v.Major, v.Minor, v.Maintenance, v.Suffix, v.BuildDate, v.MinGoVersion) } diff --git a/model/version_test.go b/model/version_test.go index 7998066..b34477e 100644 --- a/model/version_test.go +++ b/model/version_test.go @@ -1,9 +1,10 @@ package model_test import ( - "github.com/stretchr/testify/assert" "testing" + "github.com/revel/cmd/model" + "github.com/stretchr/testify/assert" ) var versionTests = [][]string{ @@ -12,22 +13,23 @@ var versionTests = [][]string{ {"v0.20.", "v0.20.0"}, {"2.0", "2.0.0"}, } -// Test that the event handler can be attached and it dispatches the event received + +// Test that the event handler can be attached and it dispatches the event received. func TestVersion(t *testing.T) { - for _, v:= range versionTests { - p,e:=model.ParseVersion(v[0]) - assert.Nil(t,e,"Should have parsed %s",v) - assert.Equal(t,p.String(),v[1], "Should be equal %s==%s",p.String(),v) + for _, v := range versionTests { + p, e := model.ParseVersion(v[0]) + assert.Nil(t, e, "Should have parsed %s", v) + assert.Equal(t, p.String(), v[1], "Should be equal %s==%s", p.String(), v) } } -// test the ranges +// test the ranges. func TestVersionRange(t *testing.T) { - a,_ := model.ParseVersion("0.1.2") - b,_ := model.ParseVersion("0.2.1") - c,_ := model.ParseVersion("1.0.1") + a, _ := model.ParseVersion("0.1.2") + b, _ := model.ParseVersion("0.2.1") + c, _ := model.ParseVersion("1.0.1") assert.True(t, b.MinorNewer(a), "B is newer then A") assert.False(t, b.MajorNewer(a), "B is not major newer then A") assert.False(t, b.MajorNewer(c), "B is not major newer then A") assert.True(t, c.MajorNewer(b), "C is major newer then b") -} \ No newline at end of file +} diff --git a/parser/appends.go b/parser/appends.go index 2dcc562..0b192f1 100644 --- a/parser/appends.go +++ b/parser/appends.go @@ -2,9 +2,10 @@ package parser import ( "go/ast" - "github.com/revel/cmd/utils" - "github.com/revel/cmd/model" "go/token" + + "github.com/revel/cmd/model" + "github.com/revel/cmd/utils" ) // If this Decl is a struct type definition, it is summarized and added to specs. @@ -91,7 +92,7 @@ func appendStruct(fileName string, specs []*model.TypeInfo, pkgImportPath string // If decl is a Method declaration, it is summarized and added to the array // underneath its receiver type. -// e.g. "Login" => {MethodSpec, MethodSpec, ..} +// e.g. "Login" => {MethodSpec, MethodSpec, ..}. func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPath, pkgName string, imports map[string]string) { // Func declaration? funcDecl, ok := decl.(*ast.FuncDecl) @@ -194,7 +195,7 @@ func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPat }) var recvTypeName string - var recvType = funcDecl.Recv.List[0].Type + recvType := funcDecl.Recv.List[0].Type if recvStarType, ok := recvType.(*ast.StarExpr); ok { recvTypeName = recvStarType.X.(*ast.Ident).Name } else { @@ -204,7 +205,7 @@ func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPat mm[recvTypeName] = append(mm[recvTypeName], method) } -// Combine the 2 source info models into one +// Combine the 2 source info models into one. func appendSourceInfo(srcInfo1, srcInfo2 *model.SourceInfo) *model.SourceInfo { if srcInfo1 == nil { return srcInfo2 diff --git a/parser/imports.go b/parser/imports.go index 8f40285..7589af9 100644 --- a/parser/imports.go +++ b/parser/imports.go @@ -1,15 +1,16 @@ package parser import ( - "github.com/revel/cmd/utils" "go/ast" "go/build" "go/token" "path/filepath" "strings" + + "github.com/revel/cmd/utils" ) -// Add imports to the map from the source dir +// Add imports to the map from the source dir. func addImports(imports map[string]string, decl ast.Decl, srcDir string) { genDecl, ok := decl.(*ast.GenDecl) if !ok { @@ -42,7 +43,6 @@ func addImports(imports map[string]string, decl ast.Decl, srcDir string) { // 2. Exempt the standard library; their directories always match the package name. // 3. Can use build.FindOnly and then use parser.ParseDir with mode PackageClauseOnly if pkgAlias == "" { - utils.Logger.Debug("Reading from build", "path", fullPath, "srcPath", srcDir, "gopath", build.Default.GOPATH) pkg, err := build.Import(fullPath, srcDir, 0) if err != nil { @@ -63,7 +63,7 @@ func addImports(imports map[string]string, decl ast.Decl, srcDir string) { } // Returns a valid import string from the path -// using the build.Defaul.GOPATH to determine the root +// using the build.Defaul.GOPATH to determine the root. func importPathFromPath(root, basePath string) string { vendorTest := filepath.Join(basePath, "vendor") if len(root) > len(vendorTest) && root[:len(vendorTest)] == vendorTest { diff --git a/parser/reflect.go b/parser/reflect.go index 212e14e..0d663d9 100644 --- a/parser/reflect.go +++ b/parser/reflect.go @@ -20,7 +20,7 @@ import ( "github.com/revel/cmd/utils" ) -// A container used to support the reflection package +// A container used to support the reflection package. type processContainer struct { root, rootImportPath string // The paths paths *model.RevelContainer // The Revel paths @@ -54,7 +54,7 @@ func ProcessSource(paths *model.RevelContainer) (_ *model.SourceInfo, compileErr return pc.srcInfo, compileError } -// Called during the "walk process" +// Called during the "walk process". func (pc *processContainer) processPath(path string, info os.FileInfo, err error) error { if err != nil { utils.Logger.Error("Error scanning app source:", "error", err) @@ -84,7 +84,7 @@ func (pc *processContainer) processPath(path string, info os.FileInfo, err error if err != nil { if errList, ok := err.(scanner.ErrorList); ok { - var pos = errList[0].Pos + pos := errList[0].Pos newError := &utils.SourceError{ SourceType: ".go source", Title: "Go Compilation Error", @@ -114,7 +114,7 @@ func (pc *processContainer) processPath(path string, info os.FileInfo, err error // These cannot be included in source code that is not generated specifically as a test for i := range pkgs { if len(i) > 6 { - if string(i[len(i)-5:]) == "_test" { + if i[len(i)-5:] == "_test" { delete(pkgs, i) } } @@ -146,7 +146,7 @@ func (pc *processContainer) processPath(path string, info os.FileInfo, err error return nil } -// Process a single package within a file +// Process a single package within a file. func processPackage(fset *token.FileSet, pkgImportPath, pkgPath string, pkg *ast.Package) *model.SourceInfo { var ( structSpecs []*model.TypeInfo diff --git a/parser/reflect_test.go b/parser/reflect_test.go index ad8038e..1b5ac6c 100644 --- a/parser/reflect_test.go +++ b/parser/reflect_test.go @@ -67,7 +67,7 @@ var expectedValidationKeys = []map[int]string{ }, } -// This tests the recording of line number to validation key of the preceeding +// This tests the recording of line number to validation key of the preceding // example source. func TestGetValidationKeys(t *testing.T) { fset := token.NewFileSet() diff --git a/parser/validation.go b/parser/validation.go index 018fdda..ade0214 100644 --- a/parser/validation.go +++ b/parser/validation.go @@ -1,10 +1,11 @@ package parser import ( - "github.com/revel/cmd/model" - "github.com/revel/cmd/utils" "go/ast" "go/token" + + "github.com/revel/cmd/model" + "github.com/revel/cmd/utils" ) // Scan app source code for calls to X.Y(), where X is of type *Validation. diff --git a/parser2/source_info_processor.go b/parser2/source_info_processor.go index a18ad0f..b30d3b0 100644 --- a/parser2/source_info_processor.go +++ b/parser2/source_info_processor.go @@ -1,14 +1,15 @@ package parser2 import ( - "github.com/revel/cmd/utils" - "golang.org/x/tools/go/packages" - "github.com/revel/cmd/model" "go/ast" "go/token" - "strings" "path/filepath" + "strings" + "github.com/revel/cmd/logger" + "github.com/revel/cmd/model" + "github.com/revel/cmd/utils" + "golang.org/x/tools/go/packages" ) type ( @@ -18,7 +19,7 @@ type ( ) func NewSourceInfoProcessor(sourceProcessor *SourceProcessor) *SourceInfoProcessor { - return &SourceInfoProcessor{sourceProcessor:sourceProcessor} + return &SourceInfoProcessor{sourceProcessor: sourceProcessor} } func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *model.SourceInfo) { @@ -37,13 +38,12 @@ func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *m log.Info("Processing package") for _, tree := range p.Syntax { for _, decl := range tree.Decls { - s.sourceProcessor.packageMap[p.PkgPath] = filepath.Dir(p.Fset.Position(decl.Pos()).Filename) if !s.addImport(decl, p, localImportMap, log) { continue } spec, found := s.getStructTypeDecl(decl, p.Fset) - //log.Info("Checking file","filename", p.Fset.Position(decl.Pos()).Filename,"found",found) + // log.Info("Checking file","filename", p.Fset.Position(decl.Pos()).Filename,"found",found) if found { if isController || isTest { controllerSpec := s.getControllerSpec(spec, p, localImportMap) @@ -69,7 +69,7 @@ func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *m } // Check for validation if lineKeyMap := s.getValidation(funcDecl, p); len(lineKeyMap) > 1 { - sourceInfo.ValidationKeys[p.PkgPath + "." + s.getFuncName(funcDecl)] = lineKeyMap + sourceInfo.ValidationKeys[p.PkgPath+"."+s.getFuncName(funcDecl)] = lineKeyMap } if funcDecl.Name.Name == "init" { sourceInfo.InitImportPaths = append(sourceInfo.InitImportPaths, p.PkgPath) @@ -85,6 +85,7 @@ func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *m return } + // Scan app source code for calls to X.Y(), where X is of type *Validation. // // Recognize these scenarios: @@ -99,7 +100,7 @@ func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *m // // The end result is that we can set the default validation key for each call to // be the same as the local variable. -func (s *SourceInfoProcessor) getValidation(funcDecl *ast.FuncDecl, p *packages.Package) (map[int]string) { +func (s *SourceInfoProcessor) getValidation(funcDecl *ast.FuncDecl, p *packages.Package) map[int]string { var ( lineKeys = make(map[int]string) @@ -165,10 +166,10 @@ func (s *SourceInfoProcessor) getValidation(funcDecl *ast.FuncDecl, p *packages. }) return lineKeys - } + // Check to see if there is a *revel.Validation as an argument. -func (s *SourceInfoProcessor) getValidationParameter(funcDecl *ast.FuncDecl) *ast.Object { +func (s *SourceInfoProcessor) getValidationParameter(funcDecl *ast.FuncDecl) *ast.Object { for _, field := range funcDecl.Type.Params.List { starExpr, ok := field.Type.(*ast.StarExpr) // e.g. *revel.Validation if !ok { @@ -191,6 +192,7 @@ func (s *SourceInfoProcessor) getValidationParameter(funcDecl *ast.FuncDecl) *a } return nil } + func (s *SourceInfoProcessor) getControllerFunc(funcDecl *ast.FuncDecl, p *packages.Package, localImportMap map[string]string) (method *model.MethodSpec, recvTypeName string) { selExpr, ok := funcDecl.Type.Results.List[0].Type.(*ast.SelectorExpr) if !ok { @@ -274,7 +276,7 @@ func (s *SourceInfoProcessor) getControllerFunc(funcDecl *ast.FuncDecl, p *packa return true }) - var recvType = funcDecl.Recv.List[0].Type + recvType := funcDecl.Recv.List[0].Type if recvStarType, ok := recvType.(*ast.StarExpr); ok { recvTypeName = recvStarType.X.(*ast.Ident).Name } else { @@ -282,6 +284,7 @@ func (s *SourceInfoProcessor) getControllerFunc(funcDecl *ast.FuncDecl, p *packa } return } + func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.Package, localImportMap map[string]string) (controllerSpec *model.TypeInfo) { structType := spec.Type.(*ast.StructType) @@ -342,9 +345,9 @@ func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages. } else { var ok bool if importPath, ok = localImportMap[pkgName]; !ok { - log.Debug("Debug: Unusual, failed to find package locally ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap, "usedin", ) + log.Debug("Debug: Unusual, failed to find package locally ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap, "usedin") if importPath, ok = s.sourceProcessor.importMap[pkgName]; !ok { - log.Error("Error: Failed to find import path for ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap, "usedin", ) + log.Error("Error: Failed to find import path for ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap, "usedin") continue } } @@ -358,6 +361,7 @@ func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages. s.sourceProcessor.log.Info("Added controller spec", "name", controllerSpec.StructName, "package", controllerSpec.ImportPath) return } + func (s *SourceInfoProcessor) getStructTypeDecl(decl ast.Decl, fset *token.FileSet) (spec *ast.TypeSpec, found bool) { genDecl, ok := decl.(*ast.GenDecl) if !ok { @@ -377,8 +381,8 @@ func (s *SourceInfoProcessor) getStructTypeDecl(decl ast.Decl, fset *token.FileS _, found = spec.Type.(*ast.StructType) return - } + func (s *SourceInfoProcessor) getFuncName(funcDecl *ast.FuncDecl) string { prefix := "" if funcDecl.Recv != nil { @@ -392,6 +396,7 @@ func (s *SourceInfoProcessor) getFuncName(funcDecl *ast.FuncDecl) string { } return prefix + funcDecl.Name.Name } + func (s *SourceInfoProcessor) addImport(decl ast.Decl, p *packages.Package, localImportMap map[string]string, log logger.MultiLogger) (shouldContinue bool) { shouldContinue = true genDecl, ok := decl.(*ast.GenDecl) @@ -403,7 +408,7 @@ func (s *SourceInfoProcessor) addImport(decl ast.Decl, p *packages.Package, loca shouldContinue = false for _, spec := range genDecl.Specs { importSpec := spec.(*ast.ImportSpec) - //fmt.Printf("*** import specification %#v\n", importSpec) + // fmt.Printf("*** import specification %#v\n", importSpec) var pkgAlias string if importSpec.Name != nil { pkgAlias = importSpec.Name.Name @@ -412,16 +417,15 @@ func (s *SourceInfoProcessor) addImport(decl ast.Decl, p *packages.Package, loca } } quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\"" - fullPath := quotedPath[1 : len(quotedPath) - 1] // Remove the quotes + fullPath := quotedPath[1 : len(quotedPath)-1] // Remove the quotes if pkgAlias == "" { pkgAlias = fullPath if index := strings.LastIndex(pkgAlias, "/"); index > 0 { - pkgAlias = pkgAlias[index + 1:] + pkgAlias = pkgAlias[index+1:] } } localImportMap[pkgAlias] = fullPath } - } return -} \ No newline at end of file +} diff --git a/parser2/source_processor.go b/parser2/source_processor.go index a665c6a..fd84fb9 100644 --- a/parser2/source_processor.go +++ b/parser2/source_processor.go @@ -1,17 +1,18 @@ package parser2 import ( - "github.com/revel/cmd/model" - "golang.org/x/tools/go/packages" - "github.com/revel/cmd/utils" + "go/ast" "go/parser" - "strings" - "github.com/revel/cmd/logger" + "go/scanner" + "go/token" "os" "path/filepath" - "go/ast" - "go/token" - "go/scanner" + "strings" + + "github.com/revel/cmd/logger" + "github.com/revel/cmd/model" + "github.com/revel/cmd/utils" + "golang.org/x/tools/go/packages" ) type ( @@ -39,7 +40,7 @@ func ProcessSource(revelContainer *model.RevelContainer) (sourceInfo *model.Sour } func NewSourceProcessor(revelContainer *model.RevelContainer) *SourceProcessor { - s := &SourceProcessor{revelContainer:revelContainer, log:utils.Logger.New("parser", "SourceProcessor")} + s := &SourceProcessor{revelContainer: revelContainer, log: utils.Logger.New("parser", "SourceProcessor")} s.sourceInfoProcessor = NewSourceInfoProcessor(s) return s } @@ -77,36 +78,36 @@ func (s *SourceProcessor) parse() (compileError error) { } // Using the packages.Load function load all the packages and type specifications (forces compile). -// this sets the SourceProcessor.packageList []*packages.Package +// this sets the SourceProcessor.packageList []*packages.Package. func (s *SourceProcessor) addPackages() (err error) { allPackages := []string{model.RevelImportPath + "/..."} for _, module := range s.revelContainer.ModulePathMap { - allPackages = append(allPackages, module.ImportPath + "/...") // +"/app/controllers/...") + allPackages = append(allPackages, module.ImportPath+"/...") // +"/app/controllers/...") } s.log.Info("Reading packages", "packageList", allPackages) - //allPackages = []string{s.revelContainer.ImportPath + "/..."} //+"/app/controllers/..."} + // allPackages = []string{s.revelContainer.ImportPath + "/..."} //+"/app/controllers/..."} config := &packages.Config{ // ode: packages.NeedSyntax | packages.NeedCompiledGoFiles, - Mode: - packages.NeedTypes | // For compile error + Mode: packages.NeedTypes | // For compile error packages.NeedDeps | // To load dependent files packages.NeedName | // Loads the full package name packages.NeedSyntax, // To load ast tree (for end points) - //Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | + // Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | // packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile | // packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | // packages.NeedTypesSizes, - //Mode: packages.NeedName | packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile | packages.NeedFiles | + // Mode: packages.NeedName | packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile | packages.NeedFiles | // packages.NeedCompiledGoFiles | packages.NeedTypesSizes | // packages.NeedSyntax | packages.NeedCompiledGoFiles , - //Mode: packages.NeedSyntax | packages.NeedCompiledGoFiles | packages.NeedName | packages.NeedFiles | + // Mode: packages.NeedSyntax | packages.NeedCompiledGoFiles | packages.NeedName | packages.NeedFiles | // packages.LoadTypes | packages.NeedTypes | packages.NeedDeps, //, // | // packages.NeedTypes, // packages.LoadTypes | packages.NeedSyntax | packages.NeedTypesInfo, - //packages.LoadSyntax | packages.NeedDeps, - Dir:s.revelContainer.AppPath, + // packages.LoadSyntax | packages.NeedDeps, + Dir: s.revelContainer.AppPath, } + config.Env = utils.ReducedEnv(false) s.packageList, err = packages.Load(config, allPackages...) s.log.Info("Loaded modules ", "len results", len(s.packageList), "error", err) @@ -118,7 +119,7 @@ func (s *SourceProcessor) addPackages() (err error) { // This callback is used to build the packages for the "app" package. This allows us to // parse the source files without doing a full compile on them -// This callback only processes folders, so any files passed to this will return a nil +// This callback only processes folders, so any files passed to this will return a nil. func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error) error { if err != nil { s.log.Error("Error scanning app source:", "error", err) @@ -134,7 +135,7 @@ func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error) pkgImportPath := s.revelContainer.ImportPath appPath := s.revelContainer.BasePath if appPath != path { - pkgImportPath = s.revelContainer.ImportPath + "/" + filepath.ToSlash(path[len(appPath) + 1:]) + pkgImportPath = s.revelContainer.ImportPath + "/" + filepath.ToSlash(path[len(appPath)+1:]) } s.log.Info("Processing source package folder", "package", pkgImportPath, "path", path) @@ -151,7 +152,7 @@ func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error) if err != nil { if errList, ok := err.(scanner.ErrorList); ok { - var pos = errList[0].Pos + pos := errList[0].Pos newError := &utils.SourceError{ SourceType: ".go source", Title: "Go Compilation Error", @@ -181,7 +182,7 @@ func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error) // These cannot be included in source code that is not generated specifically as a test for i := range pkgMap { if len(i) > 6 { - if string(i[len(i) - 5:]) == "_test" { + if i[len(i)-5:] == "_test" { delete(pkgMap, i) } } @@ -218,12 +219,11 @@ func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error) } // This function is used to populate a map so that we can lookup controller embedded types in order to determine -// if a Struct inherits from from revel.Controller +// if a Struct inherits from from revel.Controller. func (s *SourceProcessor) addImportMap() (err error) { s.importMap = map[string]string{} s.packageMap = map[string]string{} for _, p := range s.packageList { - if len(p.Errors) > 0 { // Generate a compile error for _, e := range p.Errors { diff --git a/proxy/proxy.go b/proxy/proxy.go index 278aa77..a59cedd 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -9,5 +9,4 @@ // 2. Monitor the user source and restart the program when necessary. // // Source files are generated in the app/tmp directory. - package proxy diff --git a/revel/build.go b/revel/build.go index 1106cc5..e31b06a 100644 --- a/revel/build.go +++ b/revel/build.go @@ -5,11 +5,11 @@ package main import ( + "fmt" "os" "path/filepath" "strings" - "fmt" "github.com/revel/cmd/harness" "github.com/revel/cmd/model" "github.com/revel/cmd/utils" @@ -34,7 +34,7 @@ func init() { cmdBuild.UpdateConfig = updateBuildConfig } -// The update config updates the configuration command so that it can run +// The update config updates the configuration command so that it can run. func updateBuildConfig(c *model.CommandConfig, args []string) bool { c.Index = model.BUILD if c.Build.TargetPath == "" { @@ -57,9 +57,8 @@ func updateBuildConfig(c *model.CommandConfig, args []string) bool { return true } -// The main entry point to build application from command line +// The main entry point to build application from command line. func buildApp(c *model.CommandConfig) (err error) { - appImportPath, destPath, mode := c.ImportPath, c.Build.TargetPath, DefaultRunMode if len(c.Build.Mode) > 0 { mode = c.Build.Mode @@ -70,7 +69,7 @@ func buildApp(c *model.CommandConfig) (err error) { c.Build.Mode = mode c.Build.ImportPath = appImportPath - revel_paths, err := model.NewRevelPaths(mode, appImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver)) + revelPaths, err := model.NewRevelPaths(mode, appImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver)) if err != nil { return } @@ -80,7 +79,7 @@ func buildApp(c *model.CommandConfig) (err error) { } // Ensure the application can be built, this generates the main file - app, err := harness.Build(c, revel_paths) + app, err := harness.Build(c, revelPaths) if err != nil { return err } @@ -91,11 +90,11 @@ func buildApp(c *model.CommandConfig) (err error) { // - revel // - app - packageFolders, err := buildCopyFiles(c, app, revel_paths) + packageFolders, err := buildCopyFiles(c, app, revelPaths) if err != nil { return } - err = buildCopyModules(c, revel_paths, packageFolders, app) + err = buildCopyModules(c, revelPaths, packageFolders, app) if err != nil { return } @@ -106,36 +105,36 @@ func buildApp(c *model.CommandConfig) (err error) { return } -// Copy the files to the target -func buildCopyFiles(c *model.CommandConfig, app *harness.App, revel_paths *model.RevelContainer) (packageFolders []string, err error) { +// Copy the files to the target. +func buildCopyFiles(c *model.CommandConfig, app *harness.App, revelPaths *model.RevelContainer) (packageFolders []string, err error) { appImportPath, destPath := c.ImportPath, c.Build.TargetPath // Revel and the app are in a directory structure mirroring import path srcPath := filepath.Join(destPath, "src") destBinaryPath := filepath.Join(destPath, filepath.Base(app.BinaryPath)) tmpRevelPath := filepath.Join(srcPath, filepath.FromSlash(model.RevelImportPath)) - if err = utils.CopyFile(destBinaryPath, filepath.Join(revel_paths.BasePath, app.BinaryPath)); err != nil { + if err = utils.CopyFile(destBinaryPath, filepath.Join(revelPaths.BasePath, app.BinaryPath)); err != nil { return } utils.MustChmod(destBinaryPath, 0755) // Copy the templates from the revel - if err = utils.CopyDir(filepath.Join(tmpRevelPath, "conf"), filepath.Join(revel_paths.RevelPath, "conf"), nil); err != nil { + if err = utils.CopyDir(filepath.Join(tmpRevelPath, "conf"), filepath.Join(revelPaths.RevelPath, "conf"), nil); err != nil { return } - if err = utils.CopyDir(filepath.Join(tmpRevelPath, "templates"), filepath.Join(revel_paths.RevelPath, "templates"), nil); err != nil { + if err = utils.CopyDir(filepath.Join(tmpRevelPath, "templates"), filepath.Join(revelPaths.RevelPath, "templates"), nil); err != nil { return } // Get the folders to be packaged - packageFolders = strings.Split(revel_paths.Config.StringDefault("package.folders", "conf,public,app/views"), ",") + packageFolders = strings.Split(revelPaths.Config.StringDefault("package.folders", "conf,public,app/views"), ",") for i, p := range packageFolders { // Clean spaces, reformat slash to filesystem packageFolders[i] = filepath.FromSlash(strings.TrimSpace(p)) } if c.Build.CopySource { - err = utils.CopyDir(filepath.Join(srcPath, filepath.FromSlash(appImportPath)), revel_paths.BasePath, nil) + err = utils.CopyDir(filepath.Join(srcPath, filepath.FromSlash(appImportPath)), revelPaths.BasePath, nil) if err != nil { return } @@ -143,7 +142,7 @@ func buildCopyFiles(c *model.CommandConfig, app *harness.App, revel_paths *model for _, folder := range packageFolders { err = utils.CopyDir( filepath.Join(srcPath, filepath.FromSlash(appImportPath), folder), - filepath.Join(revel_paths.BasePath, folder), + filepath.Join(revelPaths.BasePath, folder), nil) if err != nil { return @@ -154,11 +153,11 @@ func buildCopyFiles(c *model.CommandConfig, app *harness.App, revel_paths *model return } -// Based on the section copy over the build modules -func buildCopyModules(c *model.CommandConfig, revel_paths *model.RevelContainer, packageFolders []string, app *harness.App) (err error) { +// Based on the section copy over the build modules. +func buildCopyModules(c *model.CommandConfig, revelPaths *model.RevelContainer, packageFolders []string, app *harness.App) (err error) { destPath := filepath.Join(c.Build.TargetPath, "src") // Find all the modules used and copy them over. - config := revel_paths.Config.Raw() + config := revelPaths.Config.Raw() // We should only copy over the section of options what the build is targeted for // We will default to prod @@ -178,7 +177,6 @@ func buildCopyModules(c *model.CommandConfig, revel_paths *model.RevelContainer, continue } moduleImportList = append(moduleImportList, moduleImportPath) - } } @@ -207,7 +205,7 @@ func buildCopyModules(c *model.CommandConfig, revel_paths *model.RevelContainer, return } -// Write the run scripts for the build +// Write the run scripts for the build. func buildWriteScripts(c *model.CommandConfig, app *harness.App) (err error) { tmplData := map[string]interface{}{ "BinName": filepath.Base(app.BinaryPath), @@ -238,9 +236,8 @@ func buildWriteScripts(c *model.CommandConfig, app *harness.App) (err error) { return } -// Checks to see if the target folder exists and can be created +// Checks to see if the target folder exists and can be created. func buildSafetyCheck(destPath string) error { - // First, verify that it is either already empty or looks like a previous // build (to avoid clobbering anything) if utils.Exists(destPath) && !utils.Empty(destPath) && !utils.Exists(filepath.Join(destPath, "run.sh")) { @@ -262,6 +259,7 @@ const PACKAGE_RUN_SH = `#!/bin/sh SCRIPTPATH=$(cd "$(dirname "$0")"; pwd) "$SCRIPTPATH/{{.BinName}}" -importPath {{.ImportPath}} -srcPath "$SCRIPTPATH/src" -runMode {{.Mode}} ` + const PACKAGE_RUN_BAT = `@echo off {{.BinName}} -importPath {{.ImportPath}} -srcPath "%CD%\src" -runMode {{.Mode}} diff --git a/revel/build_test.go b/revel/build_test.go index f134fa0..4b2ef2b 100644 --- a/revel/build_test.go +++ b/revel/build_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/assert" ) -// test the commands +// test the commands. func TestBuild(t *testing.T) { a := assert.New(t) gopath := setup("revel-test-build", a) diff --git a/revel/clean.go b/revel/clean.go index ebbae09..263fa17 100644 --- a/revel/clean.go +++ b/revel/clean.go @@ -6,11 +6,11 @@ package main import ( "fmt" - "github.com/revel/cmd/model" - "github.com/revel/cmd/utils" - "os" "path/filepath" + + "github.com/revel/cmd/model" + "github.com/revel/cmd/utils" ) var cmdClean = &Command{ @@ -34,7 +34,7 @@ func init() { cmdClean.RunWith = cleanApp } -// Update the clean command configuration, using old method +// Update the clean command configuration, using old method. func updateCleanConfig(c *model.CommandConfig, args []string) bool { c.Index = model.CLEAN if len(args) == 0 && c.Clean.ImportPath != "" { @@ -48,9 +48,8 @@ func updateCleanConfig(c *model.CommandConfig, args []string) bool { return true } -// Clean the source directory of generated files +// Clean the source directory of generated files. func cleanApp(c *model.CommandConfig) (err error) { - purgeDirs := []string{ filepath.Join(c.AppPath, "app", "tmp"), filepath.Join(c.AppPath, "app", "routes"), diff --git a/revel/clean_test.go b/revel/clean_test.go index 0b6c218..27c3e0a 100644 --- a/revel/clean_test.go +++ b/revel/clean_test.go @@ -1,20 +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 +// test the commands. func TestClean(t *testing.T) { a := assert.New(t) - gopath := setup("revel-test-clean", a) - + gopath := setup("revel-test-clean", a) t.Run("Clean", func(t *testing.T) { a := assert.New(t) diff --git a/revel/command_test.go b/revel/command_test.go index 57e8306..74c4fd6 100644 --- a/revel/command_test.go +++ b/revel/command_test.go @@ -1,23 +1,24 @@ package main_test import ( - "github.com/revel/cmd/logger" - "github.com/revel/cmd/model" - "github.com/revel/cmd/utils" - "github.com/stretchr/testify/assert" + "fmt" "go/build" "os" "os/exec" "path/filepath" - "fmt" + + "github.com/revel/cmd/logger" + "github.com/revel/cmd/model" + "github.com/revel/cmd/utils" + "github.com/stretchr/testify/assert" ) -// Test that the event handler can be attached and it dispatches the event received -func setup(suffix string, a *assert.Assertions) (string) { +// Test that the event handler can be attached and it dispatches the event received. +func setup(suffix string, a *assert.Assertions) string { temp := os.TempDir() wd, _ := os.Getwd() utils.InitLogger(wd, logger.LvlInfo) - gopath := filepath.Join(temp, "revel-test",suffix) + gopath := filepath.Join(temp, "revel-test", suffix) if utils.Exists(gopath) { utils.Logger.Info("Removing test path", "path", gopath) if err := os.RemoveAll(gopath); err != nil { @@ -38,30 +39,29 @@ func setup(suffix string, a *assert.Assertions) (string) { defaultBuild := build.Default defaultBuild.GOPATH = gopath build.Default = defaultBuild - utils.Logger.Info("Setup stats", "original wd", wd, "new wd", newwd, "gopath",gopath, "gopath exists", utils.DirExists(gopath), "wd exists", utils.DirExists(newwd)) + utils.Logger.Info("Setup stats", "original wd", wd, "new wd", newwd, "gopath", gopath, "gopath exists", utils.DirExists(gopath), "wd exists", utils.DirExists(newwd)) return gopath } -// Create a new app for the name +// Create a new app for the name. func newApp(name string, command model.COMMAND, precall func(c *model.CommandConfig), a *assert.Assertions) *model.CommandConfig { - c := &model.CommandConfig{Vendored:true} + c := &model.CommandConfig{Vendored: true} switch command { case model.NEW: c.New.ImportPath = name - c.New.Callback=func() error { + c.New.Callback = func() error { // On callback we will invoke a specific branch of revel so that it works goModCmd := exec.Command("go", "mod", "tidy") utils.CmdInit(goModCmd, !c.Vendored, c.AppPath) getOutput, _ := goModCmd.CombinedOutput() - fmt.Printf("Calling go mod tidy %s",string(getOutput)) + fmt.Printf("Calling go mod tidy %s", string(getOutput)) goModCmd = exec.Command("go", "mod", "edit", "-replace=github.com/revel/revel=github.com/revel/revel@develop") utils.CmdInit(goModCmd, !c.Vendored, c.AppPath) getOutput, _ = goModCmd.CombinedOutput() - fmt.Printf("Calling go mod edit %v",string(getOutput)) - + fmt.Printf("Calling go mod edit %v", string(getOutput)) return nil } @@ -83,7 +83,7 @@ func newApp(name string, command model.COMMAND, precall func(c *model.CommandCon if precall != nil { precall(c) } - if c.UpdateImportPath()!=nil { + if c.UpdateImportPath() != nil { a.Fail("Unable to update import path") } diff --git a/revel/new.go b/revel/new.go index 21fe5b2..67b6653 100644 --- a/revel/new.go +++ b/revel/new.go @@ -8,6 +8,7 @@ import ( "fmt" "go/build" "math/rand" + "net/url" "os" "os/exec" "path/filepath" @@ -15,7 +16,6 @@ import ( "github.com/revel/cmd/model" "github.com/revel/cmd/utils" - "net/url" ) var cmdNew = &Command{ @@ -43,7 +43,7 @@ func init() { cmdNew.UpdateConfig = updateNewConfig } -// Called when unable to parse the command line automatically and assumes an old launch +// Called when unable to parse the command line automatically and assumes an old launch. func updateNewConfig(c *model.CommandConfig, args []string) bool { c.Index = model.NEW if len(c.New.Package) > 0 { @@ -64,10 +64,9 @@ func updateNewConfig(c *model.CommandConfig, args []string) bool { } return true - } -// Call to create a new application +// Call to create a new application. func newApp(c *model.CommandConfig) (err error) { // Check for an existing folder so we don't clobber it _, err = build.Import(c.ImportPath, "", build.FindOnly) @@ -114,17 +113,16 @@ func newApp(c *model.CommandConfig) (err error) { if c.New.Run { // Need to prep the run command c.Run.ImportPath = c.ImportPath - updateRunConfig(c,nil) + updateRunConfig(c, nil) c.UpdateImportPath() runApp(c) } else { - fmt.Fprintln(os.Stdout, "\nYou can run it with:\n revel run -a ", c.ImportPath) + fmt.Fprintln(os.Stdout, "\nYou can run it with:\n revel run -a", c.ImportPath) } return } func createModVendor(c *model.CommandConfig) (err error) { - utils.Logger.Info("Creating a new mod app") goModCmd := exec.Command("go", "mod", "init", filepath.Join(c.New.Package, c.AppName)) @@ -141,69 +139,21 @@ func createModVendor(c *model.CommandConfig) (err error) { return } -func createDepVendor(c *model.CommandConfig) (err error) { - - utils.Logger.Info("Creating a new vendor app") - - vendorPath := filepath.Join(c.AppPath, "vendor") - if !utils.DirExists(vendorPath) { - - if err := os.MkdirAll(vendorPath, os.ModePerm); err != nil { - return utils.NewBuildError("Failed to create " + vendorPath, "error", err) - } - } - - // In order for dep to run there needs to be a source file in the folder - tempPath := filepath.Join(c.AppPath, "tmp") - utils.Logger.Info("Checking for temp folder for source code", "path", tempPath) - if !utils.DirExists(tempPath) { - if err := os.MkdirAll(tempPath, os.ModePerm); err != nil { - return utils.NewBuildIfError(err, "Failed to create " + vendorPath) - } - - if err = utils.GenerateTemplate(filepath.Join(tempPath, "main.go"), NEW_MAIN_FILE, nil); err != nil { - return utils.NewBuildIfError(err, "Failed to create main file " + vendorPath) - } - } - - // Create a package template file if it does not exist - packageFile := filepath.Join(c.AppPath, "Gopkg.toml") - utils.Logger.Info("Checking for Gopkg.toml", "path", packageFile) - if !utils.Exists(packageFile) { - utils.Logger.Info("Generating Gopkg.toml", "path", packageFile) - if err := utils.GenerateTemplate(packageFile, VENDOR_GOPKG, nil); err != nil { - return utils.NewBuildIfError(err, "Failed to generate template") - } - } else { - utils.Logger.Info("Package file exists in skeleto, skipping adding") - } - - getCmd := exec.Command("dep", "ensure", "-v") - utils.CmdInit(getCmd, !c.Vendored, c.AppPath) - - utils.Logger.Info("Exec:", "args", getCmd.Args, "env", getCmd.Env, "workingdir", getCmd.Dir) - getOutput, err := getCmd.CombinedOutput() - if err != nil { - return utils.NewBuildIfError(err, string(getOutput)) - } - return -} - -// Used to generate a new secret key +// Used to generate a new secret key. const alphaNumeric = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" -// Generate a secret key +// Generate a secret key. func generateSecret() string { chars := make([]byte, 64) for i := 0; i < 64; i++ { chars[i] = alphaNumeric[rand.Intn(len(alphaNumeric))] } + return string(chars) } -// Sets the applicaiton path +// Sets the application path. func setApplicationPath(c *model.CommandConfig) (err error) { - // revel/revel#1014 validate relative path, we cannot use built-in functions // since Go import path is valid relative path too. // so check basic part of the path, which is "." @@ -216,10 +166,10 @@ func setApplicationPath(c *model.CommandConfig) (err error) { } _, err = build.Import(model.RevelImportPath, "", build.FindOnly) if err != nil { - //// Go get the revel project + // Go get the revel project err = c.PackageResolver(model.RevelImportPath) if err != nil { - return utils.NewBuildIfError(err, "Failed to fetch revel " + model.RevelImportPath) + return utils.NewBuildIfError(err, "Failed to fetch revel "+model.RevelImportPath) } } } @@ -229,7 +179,7 @@ func setApplicationPath(c *model.CommandConfig) (err error) { return nil } -// Set the skeleton path +// Set the skeleton path. func setSkeletonPath(c *model.CommandConfig) (err error) { if len(c.New.SkeletonPath) == 0 { c.New.SkeletonPath = "https://" + RevelSkeletonsImportPath + ":basic/bootstrap4" @@ -242,10 +192,10 @@ func setSkeletonPath(c *model.CommandConfig) (err error) { switch strings.ToLower(sp.Scheme) { // TODO Add support for ftp, sftp, scp ?? - case "" : + case "": sp.Scheme = "file" fallthrough - case "file" : + case "file": fullpath := sp.String()[7:] if !filepath.IsAbs(fullpath) { fullpath, err = filepath.Abs(fullpath) @@ -256,7 +206,7 @@ func setSkeletonPath(c *model.CommandConfig) (err error) { c.New.SkeletonPath = fullpath utils.Logger.Info("Set skeleton path to ", fullpath) if !utils.DirExists(fullpath) { - return fmt.Errorf("Failed to find skeleton in filepath %s %s", fullpath, sp.String()) + return fmt.Errorf("failed to find skeleton in filepath %s %s", fullpath, sp.String()) } case "git": fallthrough @@ -268,7 +218,6 @@ func setSkeletonPath(c *model.CommandConfig) (err error) { } default: utils.Logger.Fatal("Unsupported skeleton schema ", "path", c.New.SkeletonPath) - } // TODO check to see if the path needs to be extracted } else { @@ -277,14 +226,14 @@ func setSkeletonPath(c *model.CommandConfig) (err error) { return } -// Load skeleton from git +// Load skeleton from git. func newLoadFromGit(c *model.CommandConfig, sp *url.URL) (err error) { // This method indicates we need to fetch from a repository using git // Execute "git clone get " targetPath := filepath.Join(os.TempDir(), "revel", "skeleton") os.RemoveAll(targetPath) pathpart := strings.Split(sp.Path, ":") - getCmd := exec.Command("git", "clone", sp.Scheme + "://" + sp.Host + pathpart[0], targetPath) + getCmd := exec.Command("git", "clone", sp.Scheme+"://"+sp.Host+pathpart[0], targetPath) utils.Logger.Info("Exec:", "args", getCmd.Args) getOutput, err := getCmd.CombinedOutput() if err != nil { @@ -323,68 +272,4 @@ func copyNewAppFiles(c *model.CommandConfig) (err error) { // Dotfiles are skipped by mustCopyDir, so we have to explicitly copy the .gitignore. gitignore := ".gitignore" return utils.CopyFile(filepath.Join(c.AppPath, gitignore), filepath.Join(c.New.SkeletonPath, gitignore)) - } - -const ( - VENDOR_GOPKG = `# -# Revel Gopkg.toml -# -# If you want to use a specific version of Revel change the branches below -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -required = ["github.com/revel/revel", "github.com/revel/modules"] - -# Note to use a specific version changes this to -# -# [[override]] -# version = "0.20.1" -# name = "github.com/revel/modules" - -[[override]] - branch = "master" - name = "github.com/revel/modules" - -# Note to use a specific version changes this to -# -# [[override]] -# version = "0.20.0" -# name = "github.com/revel/revel" -[[override]] - branch = "master" - name = "github.com/revel/revel" - -[[override]] - branch = "master" - name = "github.com/revel/log15" - -[[override]] - branch = "master" - name = "github.com/revel/cron" - -[[override]] - branch = "master" - name = "github.com/xeonx/timeago" - -` - NEW_MAIN_FILE = `package main - - ` -) diff --git a/revel/new_test.go b/revel/new_test.go index 2deac86..5b727e6 100644 --- a/revel/new_test.go +++ b/revel/new_test.go @@ -1,14 +1,15 @@ package main_test import ( - "github.com/revel/cmd/model" - "github.com/revel/cmd/revel" - "github.com/stretchr/testify/assert" "os" "testing" + + "github.com/revel/cmd/model" + main "github.com/revel/cmd/revel" + "github.com/stretchr/testify/assert" ) -// test the commands +// test the commands. func TestNew(t *testing.T) { a := assert.New(t) gopath := setup("revel-test-new", a) @@ -52,4 +53,3 @@ func TestNew(t *testing.T) { } } } - diff --git a/revel/package.go b/revel/package.go index 723e7a9..9665c2a 100644 --- a/revel/package.go +++ b/revel/package.go @@ -37,10 +37,10 @@ func init() { cmdPackage.UpdateConfig = updatePackageConfig } -// Called when unable to parse the command line automatically and assumes an old launch +// Called when unable to parse the command line automatically and assumes an old launch. func updatePackageConfig(c *model.CommandConfig, args []string) bool { c.Index = model.PACKAGE - if len(args)==0 && c.Package.ImportPath!="" { + if len(args) == 0 && c.Package.ImportPath != "" { return true } c.Package.ImportPath = args[0] @@ -48,26 +48,21 @@ func updatePackageConfig(c *model.CommandConfig, args []string) bool { c.Package.Mode = args[1] } return true - } -// Called to package the app +// Called to package the app. func packageApp(c *model.CommandConfig) (err error) { - // Determine the run mode. - mode := DefaultRunMode - if len(c.Package.Mode) >= 0 { - mode = c.Package.Mode - } + mode := c.Package.Mode appImportPath := c.ImportPath - revel_paths, err := model.NewRevelPaths(mode, appImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver)) + revelPaths, err := model.NewRevelPaths(mode, appImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver)) if err != nil { return } // Remove the archive if it already exists. - destFile := filepath.Join(c.AppPath, filepath.Base(revel_paths.BasePath)+".tar.gz") + destFile := filepath.Join(c.AppPath, filepath.Base(revelPaths.BasePath)+".tar.gz") if c.Package.TargetPath != "" { if filepath.IsAbs(c.Package.TargetPath) { destFile = c.Package.TargetPath @@ -80,13 +75,11 @@ func packageApp(c *model.CommandConfig) (err error) { } // Collect stuff in a temp directory. - tmpDir, err := ioutil.TempDir("", filepath.Base(revel_paths.BasePath)) + tmpDir, err := ioutil.TempDir("", filepath.Base(revelPaths.BasePath)) utils.PanicOnError(err, "Failed to get temp dir") // Build expects the command the build to contain the proper data - if len(c.Package.Mode) >= 0 { - c.Build.Mode = c.Package.Mode - } + c.Build.Mode = c.Package.Mode c.Build.TargetPath = tmpDir c.Build.CopySource = c.Package.CopySource if err = buildApp(c); err != nil { diff --git a/revel/package_test.go b/revel/package_test.go index 02e7e35..eb179fa 100644 --- a/revel/package_test.go +++ b/revel/package_test.go @@ -1,17 +1,18 @@ package main_test import ( - "github.com/revel/cmd/model" - "github.com/revel/cmd/revel" - "github.com/stretchr/testify/assert" "os" "testing" + + "github.com/revel/cmd/model" + main "github.com/revel/cmd/revel" + "github.com/stretchr/testify/assert" ) -// test the commands +// test the commands. func TestPackage(t *testing.T) { a := assert.New(t) - gopath := setup("revel-test-package", a) + gopath := setup("revel-test-package", a) t.Run("Package", func(t *testing.T) { a := assert.New(t) diff --git a/revel/revel.go b/revel/revel.go index 06be182..73512f4 100644 --- a/revel/revel.go +++ b/revel/revel.go @@ -6,6 +6,7 @@ package main import ( + "bytes" "flag" "fmt" "math/rand" @@ -14,23 +15,18 @@ import ( "strings" "time" - "github.com/jessevdk/go-flags" - "github.com/agtorre/gocolorize" + "github.com/jessevdk/go-flags" "github.com/revel/cmd/logger" "github.com/revel/cmd/model" "github.com/revel/cmd/utils" - "bytes" ) const ( - // RevelCmdImportPath Revel framework cmd tool import path - RevelCmdImportPath = "github.com/revel/cmd" - - // RevelCmdImportPath Revel framework cmd tool import path + // RevelCmdImportPath Revel framework cmd tool import path. RevelSkeletonsImportPath = "github.com/revel/skeletons" - // DefaultRunMode for revel's application + // DefaultRunMode for revel's application. DefaultRunMode = "dev" ) @@ -41,7 +37,7 @@ type Command struct { UsageLine, Short, Long string } -// Name returns command name from usage line +// Name returns command name from usage line. func (cmd *Command) Name() string { name := cmd.UsageLine i := strings.Index(name, " ") @@ -51,7 +47,7 @@ func (cmd *Command) Name() string { return name } -// The commands +// Commands defines the available commands. var Commands = []*Command{ nil, // Safety net, prevent missing index from running cmdNew, @@ -71,14 +67,14 @@ func main() { wd, _ := os.Getwd() utils.InitLogger(wd, logger.LvlError) - parser := flags.NewParser(c, flags.HelpFlag | flags.PassDoubleDash) + parser := flags.NewParser(c, flags.HelpFlag|flags.PassDoubleDash) if len(os.Args) < 2 { parser.WriteHelp(os.Stdout) os.Exit(1) } if err := ParseArgs(c, parser, os.Args[1:]); err != nil { - fmt.Fprint(os.Stderr, err.Error() + "\n") + fmt.Fprint(os.Stderr, err.Error()+"\n") os.Exit(1) } @@ -109,7 +105,7 @@ func main() { } } -// Parse the arguments passed into the model.CommandConfig +// Parse the arguments passed into the model.CommandConfig. func ParseArgs(c *model.CommandConfig, parser *flags.Parser, args []string) (err error) { var extraArgs []string if ini := flag.String("ini", "none", ""); *ini != "none" { @@ -119,30 +115,30 @@ func ParseArgs(c *model.CommandConfig, parser *flags.Parser, args []string) (err } else { if extraArgs, err = parser.ParseArgs(args); err != nil { return - } else { - switch parser.Active.Name { - case "new": - c.Index = model.NEW - case "run": - c.Index = model.RUN - case "build": - c.Index = model.BUILD - case "package": - c.Index = model.PACKAGE - case "clean": - c.Index = model.CLEAN - case "test": - c.Index = model.TEST - case "version": - c.Index = model.VERSION - } + } + + switch parser.Active.Name { + case "new": + c.Index = model.NEW + case "run": + c.Index = model.RUN + case "build": + c.Index = model.BUILD + case "package": + c.Index = model.PACKAGE + case "clean": + c.Index = model.CLEAN + case "test": + c.Index = model.TEST + case "version": + c.Index = model.VERSION } } if !Commands[c.Index].UpdateConfig(c, extraArgs) { buffer := &bytes.Buffer{} parser.WriteHelp(buffer) - err = fmt.Errorf("Invalid command line arguements %v\n%s", extraArgs, buffer.String()) + err = fmt.Errorf("invalid command line arguments %v\n%s", extraArgs, buffer.String()) } return diff --git a/revel/run.go b/revel/run.go index b04f9f6..1bbb619 100644 --- a/revel/run.go +++ b/revel/run.go @@ -5,13 +5,14 @@ package main import ( - "strconv" "encoding/json" "fmt" + "os" + "strconv" + "github.com/revel/cmd/harness" "github.com/revel/cmd/model" "github.com/revel/cmd/utils" - "os" ) var cmdRun = &Command{ @@ -34,13 +35,6 @@ You can set a port as well. For example: revel run -m prod -p 8080 github.com/revel/examples/chat `, } -// RunArgs holds revel run parameters -type RunArgs struct { - ImportPath string - Mode string - Port int -} - func init() { cmdRun.RunWith = runApp cmdRun.UpdateConfig = updateRunConfig @@ -112,55 +106,55 @@ func updateRunConfig(c *model.CommandConfig, args []string) bool { return true } -// Returns true if this is an absolute path or a relative gopath +// Returns true if this is an absolute path or a relative gopath. func runIsImportPath(pathToCheck string) bool { return utils.DirExists(pathToCheck) } -// Called to run the app +// Called to run the app. func runApp(c *model.CommandConfig) (err error) { if c.Run.Mode == "" { c.Run.Mode = "dev" } - revel_path, err := model.NewRevelPaths(c.Run.Mode, c.ImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver)) + revelPath, err := model.NewRevelPaths(c.Run.Mode, c.ImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver)) if err != nil { return utils.NewBuildIfError(err, "Revel paths") } if c.Run.Port > -1 { - revel_path.HTTPPort = c.Run.Port + revelPath.HTTPPort = c.Run.Port } else { - c.Run.Port = revel_path.HTTPPort + c.Run.Port = revelPath.HTTPPort } - utils.Logger.Infof("Running %s (%s) in %s mode\n", revel_path.AppName, revel_path.ImportPath, revel_path.RunMode) - utils.Logger.Debug("Base path:", "path", revel_path.BasePath) + utils.Logger.Infof("Running %s (%s) in %s mode\n", revelPath.AppName, revelPath.ImportPath, revelPath.RunMode) + utils.Logger.Debug("Base path:", "path", revelPath.BasePath) // If the app is run in "watched" mode, use the harness to run it. - if revel_path.Config.BoolDefault("watch", true) && revel_path.Config.BoolDefault("watch.code", true) { + if revelPath.Config.BoolDefault("watch", true) && revelPath.Config.BoolDefault("watch.code", true) { utils.Logger.Info("Running in watched mode.") - runMode := fmt.Sprintf(`{"mode":"%s", "specialUseFlag":%v}`, revel_path.RunMode, c.Verbose) + runMode := fmt.Sprintf(`{"mode":"%s", "specialUseFlag":%v}`, revelPath.RunMode, c.Verbose) if c.HistoricMode { - runMode = revel_path.RunMode + runMode = revelPath.RunMode } // **** Never returns. - harness.NewHarness(c, revel_path, runMode, c.Run.NoProxy).Run() + harness.NewHarness(c, revelPath, runMode, c.Run.NoProxy).Run() } // Else, just build and run the app. utils.Logger.Debug("Running in live build mode.") - app, err := harness.Build(c, revel_path) + app, err := harness.Build(c, revelPath) if err != nil { utils.Logger.Errorf("Failed to build app: %s", err) } - app.Port = revel_path.HTTPPort + app.Port = revelPath.HTTPPort var paths []byte if len(app.PackagePathMap) > 0 { paths, _ = json.Marshal(app.PackagePathMap) } runMode := fmt.Sprintf(`{"mode":"%s", "specialUseFlag":%v,"packagePathMap":%s}`, app.Paths.RunMode, c.Verbose, string(paths)) if c.HistoricMode { - runMode = revel_path.RunMode + runMode = revelPath.RunMode } app.Cmd(runMode).Run(c) return diff --git a/revel/run_test.go b/revel/run_test.go index 7a39b77..63c3f7a 100644 --- a/revel/run_test.go +++ b/revel/run_test.go @@ -1,15 +1,16 @@ package main_test import ( - "github.com/stretchr/testify/assert" "os" "testing" + + "github.com/stretchr/testify/assert" ) -// test the commands +// test the commands. func TestRun(t *testing.T) { a := assert.New(t) - gopath := setup("revel-test-run", a) + gopath := setup("revel-test-run", a) // TODO Testing run diff --git a/revel/test.go b/revel/test.go index a82fb6b..dcba329 100644 --- a/revel/test.go +++ b/revel/test.go @@ -52,7 +52,7 @@ func init() { cmdTest.UpdateConfig = updateTestConfig } -// Called to update the config command with from the older stype +// Called to update the config command with from the older stype. func updateTestConfig(c *model.CommandConfig, args []string) bool { c.Index = model.TEST if len(args) == 0 && c.Test.ImportPath != "" { @@ -74,7 +74,7 @@ func updateTestConfig(c *model.CommandConfig, args []string) bool { return true } -// Called to test the application +// Called to test the application. func testApp(c *model.CommandConfig) (err error) { mode := DefaultRunMode if c.Test.Mode != "" { @@ -82,7 +82,7 @@ func testApp(c *model.CommandConfig) (err error) { } // Find and parse app.conf - revel_path, err := model.NewRevelPaths(mode, c.ImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver)) + revelPath, err := model.NewRevelPaths(mode, c.ImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver)) if err != nil { return } @@ -90,7 +90,7 @@ func testApp(c *model.CommandConfig) (err error) { // todo Ensure that the testrunner is loaded in this mode. // Create a directory to hold the test result files. - resultPath := filepath.Join(revel_path.BasePath, "test-results") + resultPath := filepath.Join(revelPath.BasePath, "test-results") if err = os.RemoveAll(resultPath); err != nil { return utils.NewBuildError("Failed to remove test result directory ", "path", resultPath, "error", err) } @@ -99,12 +99,12 @@ func testApp(c *model.CommandConfig) (err error) { } // Direct all the output into a file in the test-results directory. - file, err := os.OpenFile(filepath.Join(resultPath, "app.log"), os.O_CREATE | os.O_WRONLY | os.O_APPEND, 0666) + file, err := os.OpenFile(filepath.Join(resultPath, "app.log"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { return utils.NewBuildError("Failed to create test result log file: ", "error", err) } - app, reverr := harness.Build(c, revel_path) + app, reverr := harness.Build(c, revelPath) if reverr != nil { return utils.NewBuildIfError(reverr, "Error building: ") } @@ -128,20 +128,20 @@ func testApp(c *model.CommandConfig) (err error) { } defer cmd.Kill() - var httpAddr = revel_path.HTTPAddr + httpAddr := revelPath.HTTPAddr if httpAddr == "" { httpAddr = "localhost" } - var httpProto = "http" - if revel_path.HTTPSsl { + httpProto := "http" + if revelPath.HTTPSsl { httpProto = "https" } // Get a list of tests - var baseURL = fmt.Sprintf("%s://%s:%d", httpProto, httpAddr, revel_path.HTTPPort) + baseURL := fmt.Sprintf("%s://%s:%d", httpProto, httpAddr, revelPath.HTTPPort) - utils.Logger.Infof("Testing %s (%s) in %s mode URL %s \n", revel_path.AppName, revel_path.ImportPath, mode, baseURL) + utils.Logger.Infof("Testing %s (%s) in %s mode URL %s \n", revelPath.AppName, revelPath.ImportPath, mode, baseURL) testSuites, _ := getTestsList(baseURL) // If a specific TestSuite[.Method] is specified, only run that suite/test @@ -154,7 +154,7 @@ func testApp(c *model.CommandConfig) (err error) { fmt.Println() // Run each suite. - failedResults, overallSuccess := runTestSuites(revel_path, baseURL, resultPath, testSuites) + failedResults, overallSuccess := runTestSuites(revelPath, baseURL, resultPath, testSuites) fmt.Println() if overallSuccess { @@ -177,14 +177,14 @@ func testApp(c *model.CommandConfig) (err error) { return } -// Outputs the results to a file +// Outputs the results to a file. func writeResultFile(resultPath, name, content string) { if err := ioutil.WriteFile(filepath.Join(resultPath, name), []byte(content), 0666); err != nil { utils.Logger.Errorf("Failed to write result file %s: %s", filepath.Join(resultPath, name), err) } } -// Determines if response should be plural +// Determines if response should be plural. func pluralize(num int, singular, plural string) string { if num == 1 { return singular @@ -193,7 +193,7 @@ func pluralize(num int, singular, plural string) string { } // Filters test suites and individual tests to match -// the parsed command line parameter +// the parsed command line parameter. func filterTestSuites(suites *[]tests.TestSuiteDesc, suiteArgument string) *[]tests.TestSuiteDesc { var suiteName, testName string argArray := strings.Split(suiteArgument, ".") @@ -234,7 +234,7 @@ func filterTestSuites(suites *[]tests.TestSuiteDesc, suiteArgument string) *[]te // in case it hasn't finished starting up yet. func getTestsList(baseURL string) (*[]tests.TestSuiteDesc, error) { var ( - err error + err error resp *http.Response testSuites []tests.TestSuiteDesc ) @@ -263,9 +263,8 @@ func getTestsList(baseURL string) (*[]tests.TestSuiteDesc, error) { return &testSuites, err } -// Run the testsuites using the container +// Run the testsuites using the container. func runTestSuites(paths *model.RevelContainer, baseURL, resultPath string, testSuites *[]tests.TestSuiteDesc) (*[]tests.TestSuiteResult, bool) { - // We can determine the testsuite location by finding the test module and extracting the data from it resultFilePath := filepath.Join(paths.ModulePathMap["testrunner"].Path, "app", "views", "TestRunner/SuiteResult.html") diff --git a/revel/test_test.go b/revel/test_test.go index adf5f5b..21e0b2c 100644 --- a/revel/test_test.go +++ b/revel/test_test.go @@ -1,18 +1,18 @@ package main_test import ( - "github.com/revel/cmd/model" - "github.com/revel/cmd/revel" - "github.com/stretchr/testify/assert" "os" "testing" + + "github.com/revel/cmd/model" + main "github.com/revel/cmd/revel" + "github.com/stretchr/testify/assert" ) - -// test the commands +// test the commands. func TestRevelTest(t *testing.T) { a := assert.New(t) - gopath := setup("revel-test-test", a) + gopath := setup("revel-test-test", a) t.Run("Test", func(t *testing.T) { a := assert.New(t) diff --git a/revel/version.go b/revel/version.go index ff70964..452c757 100644 --- a/revel/version.go +++ b/revel/version.go @@ -9,11 +9,8 @@ package main import ( + "bytes" "fmt" - - "github.com/revel/cmd" - "github.com/revel/cmd/model" - "github.com/revel/cmd/utils" "go/ast" "go/parser" "go/token" @@ -23,11 +20,14 @@ import ( "os/exec" "path/filepath" "strings" - "bytes" + + "github.com/revel/cmd" + "github.com/revel/cmd/model" + "github.com/revel/cmd/utils" ) type ( - // The version container + // The version container. VersionCommand struct { Command *model.CommandConfig // The command revelVersion *model.Version // The Revel framework version @@ -54,7 +54,7 @@ func init() { cmdVersion.RunWith = v.RunWith } -// Update the version +// Update the version. func (v *VersionCommand) UpdateConfig(c *model.CommandConfig, args []string) bool { if len(args) > 0 { c.Version.ImportPath = args[0] @@ -62,7 +62,7 @@ func (v *VersionCommand) UpdateConfig(c *model.CommandConfig, args []string) boo return true } -// Displays the version of go and Revel +// Displays the version of go and Revel. func (v *VersionCommand) RunWith(c *model.CommandConfig) (err error) { utils.Logger.Info("Requesting version information", "config", c) v.Command = c @@ -73,7 +73,6 @@ func (v *VersionCommand) RunWith(c *model.CommandConfig) (err error) { needsUpdates := true versionInfo := "" for x := 0; x < 2 && needsUpdates; x++ { - needsUpdates = false versionInfo, needsUpdates = v.doRepoCheck(x == 0) } @@ -89,10 +88,10 @@ func (v *VersionCommand) RunWith(c *model.CommandConfig) (err error) { return } -// Checks the Revel repos for the latest version +// Checks the Revel repos for the latest version. func (v *VersionCommand) doRepoCheck(updateLibs bool) (versionInfo string, needsUpdate bool) { var ( - title string + title string localVersion *model.Version ) for _, repo := range []string{"revel", "cmd", "modules"} { @@ -110,25 +109,12 @@ func (v *VersionCommand) doRepoCheck(updateLibs bool) (versionInfo string, needs } // Only do an update on the first loop, and if specified to update - versionInfo = versionInfo + v.outputVersion(title, repo, localVersion, versonFromRepo) + versionInfo += v.outputVersion(title, repo, localVersion, versonFromRepo) } return } -// Checks for updates if needed -func (v *VersionCommand) doUpdate(title, repo string, local, remote *model.Version) { - utils.Logger.Info("Updating package", "package", title, "repo", repo) - fmt.Println("Attempting to update package", title) - if err := v.Command.PackageResolver(repo); err != nil { - utils.Logger.Error("Unable to update repo", "repo", repo, "error", err) - } else if repo == "github.com/revel/cmd/revel" { - // One extra step required here to run the install for the command - utils.Logger.Fatal("Revel command tool was updated, you must manually run the following command before continuing\ngo install github.com/revel/cmd/revel") - } - return -} - -// Prints out the local and remote versions, calls update if needed +// Prints out the local and remote versions, calls update if needed. func (v *VersionCommand) outputVersion(title, repo string, local, remote *model.Version) (output string) { buffer := &bytes.Buffer{} remoteVersion := "Unknown" @@ -144,7 +130,7 @@ func (v *VersionCommand) outputVersion(title, repo string, local, remote *model. return buffer.String() } -// Returns the version from the repository +// Returns the version from the repository. func (v *VersionCommand) versionFromRepo(repoName, branchName, fileName string) (version *model.Version, err error) { if branchName == "" { branchName = "master" @@ -166,10 +152,6 @@ func (v *VersionCommand) versionFromRepo(repoName, branchName, fileName string) return v.versionFromBytes(body) } -// Returns version information from a file called version on the gopath -func (v *VersionCommand) compareAndUpdateVersion(remoteVersion *model.Version, localVersion *model.Version) (err error) { - return -} func (v *VersionCommand) versionFromFilepath(sourcePath string) (version *model.Version, err error) { utils.Logger.Info("Fullpath to revel", "dir", sourcePath) @@ -180,7 +162,7 @@ func (v *VersionCommand) versionFromFilepath(sourcePath string) (version *model. return v.versionFromBytes(sourceStream) } -// Returns version information from a file called version on the gopath +// Returns version information from a file called version on the gopath. func (v *VersionCommand) versionFromBytes(sourceStream []byte) (version *model.Version, err error) { fset := token.NewFileSet() // positions are relative to fset @@ -206,7 +188,7 @@ func (v *VersionCommand) versionFromBytes(sourceStream []byte) (version *model.V r := spec.Values[0].(*ast.BasicLit) switch spec.Names[0].Name { case "Version": - version.ParseVersion(strings.Replace(r.Value, `"`, "", -1)) + version.ParseVersion(strings.ReplaceAll(r.Value, `"`, "")) case "BuildDate": version.BuildDate = r.Value case "MinimumGoVersion": @@ -217,14 +199,14 @@ func (v *VersionCommand) versionFromBytes(sourceStream []byte) (version *model.V return } -// Fetch the local version of revel from the file system +// Fetch the local version of revel from the file system. func (v *VersionCommand) updateLocalVersions() { v.cmdVersion = &model.Version{} v.cmdVersion.ParseVersion(cmd.Version) v.cmdVersion.BuildDate = cmd.BuildDate v.cmdVersion.MinGoVersion = cmd.MinimumGoVersion - if v.Command.Version.ImportPath=="" { + if v.Command.Version.ImportPath == "" { return } @@ -243,6 +225,4 @@ func (v *VersionCommand) updateLocalVersions() { if err != nil { utils.Logger.Warn("Unable to extract version information from Revel Modules", "path", pathMap[model.RevelModulesImportPath], "error", err) } - - return } diff --git a/revel/version_test.go b/revel/version_test.go index ad13685..59f1751 100644 --- a/revel/version_test.go +++ b/revel/version_test.go @@ -1,18 +1,19 @@ package main_test import ( - "github.com/revel/cmd/model" - "github.com/revel/cmd/revel" - "github.com/stretchr/testify/assert" "os" "path/filepath" "testing" + + "github.com/revel/cmd/model" + main "github.com/revel/cmd/revel" + "github.com/stretchr/testify/assert" ) -// test the commands +// test the commands. func TestVersion(t *testing.T) { a := assert.New(t) - gopath := setup("revel-test-version", a) + gopath := setup("revel-test-version", a) t.Run("Version", func(t *testing.T) { a := assert.New(t) @@ -34,8 +35,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 && err!=os.ErrNotExist { - a.Fail("Failed to remove test path",err.Error()) + if err := os.RemoveAll(gopath); err != nil && err != os.ErrNotExist { + a.Fail("Failed to remove test path", err.Error()) } } } diff --git a/tests/testrunner.go b/tests/testrunner.go index a2fb9bd..e18adbe 100644 --- a/tests/testrunner.go +++ b/tests/testrunner.go @@ -5,12 +5,8 @@ package tests import ( - "fmt" "html/template" "reflect" - "strings" - - "github.com/revel/cmd/utils" ) // TestSuiteDesc is used for storing information about a single test suite. @@ -46,111 +42,3 @@ type TestResult struct { ErrorHTML template.HTML ErrorSummary string } - -var ( - testSuites []TestSuiteDesc // A list of all available tests. - - none = []reflect.Value{} // It is used as input for reflect call in a few places. - - // registeredTests simplifies the search of test suites by their name. - // "TestSuite.TestName" is used as a key. Value represents index in testSuites. - registeredTests map[string]int -) - -/* - Below are helper functions. -*/ - -// describeSuite expects testsuite interface as input parameter -// and returns its description in a form of TestSuiteDesc structure. -func describeSuite(testSuite interface{}) TestSuiteDesc { - t := reflect.TypeOf(testSuite) - - // Get a list of methods of the embedded test type. - // It will be used to make sure the same tests are not included in multiple test suites. - super := t.Elem().Field(0).Type - superMethods := map[string]bool{} - for i := 0; i < super.NumMethod(); i++ { - // Save the current method's name. - superMethods[super.Method(i).Name] = true - } - - // Get a list of methods on the test suite that take no parameters, return - // no results, and were not part of the embedded type's method set. - var tests []TestDesc - for i := 0; i < t.NumMethod(); i++ { - m := t.Method(i) - mt := m.Type - - // Make sure the test method meets the criterias: - // - method of testSuite without input parameters; - // - nothing is returned; - // - has "Test" prefix; - // - doesn't belong to the embedded structure. - methodWithoutParams := (mt.NumIn() == 1 && mt.In(0) == t) - nothingReturned := (mt.NumOut() == 0) - hasTestPrefix := (strings.HasPrefix(m.Name, "Test")) - if methodWithoutParams && nothingReturned && hasTestPrefix && !superMethods[m.Name] { - // Register the test suite's index so we can quickly find it by test's name later. - registeredTests[t.Elem().Name()+"."+m.Name] = len(testSuites) - - // Add test to the list of tests. - tests = append(tests, TestDesc{m.Name}) - } - } - - return TestSuiteDesc{ - Name: t.Elem().Name(), - Tests: tests, - Elem: t.Elem(), - } -} - -// errorSummary gets an error and returns its summary in human readable format. -func errorSummary(err *utils.SourceError) (message string) { - expectedPrefix := "(expected)" - actualPrefix := "(actual)" - errDesc := err.Description - //strip the actual/expected stuff to provide more condensed display. - if strings.Index(errDesc, expectedPrefix) == 0 { - errDesc = errDesc[len(expectedPrefix):] - } - if strings.LastIndex(errDesc, actualPrefix) > 0 { - errDesc = errDesc[0 : len(errDesc)-len(actualPrefix)] - } - - errFile := err.Path - slashIdx := strings.LastIndex(errFile, "/") - if slashIdx > 0 { - errFile = errFile[slashIdx+1:] - } - - message = fmt.Sprintf("%s %s#%d", errDesc, errFile, err.Line) - - /* - // If line of error isn't known return the message as is. - if err.Line == 0 { - return - } - - // Otherwise, include info about the line number and the relevant - // source code lines. - message += fmt.Sprintf(" (around line %d): ", err.Line) - for _, line := range err.ContextSource() { - if line.IsError { - message += line.Source - } - } - */ - - return -} - -//sortbySuiteName sorts the testsuites by name. -type sortBySuiteName []interface{} - -func (a sortBySuiteName) Len() int { return len(a) } -func (a sortBySuiteName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a sortBySuiteName) Less(i, j int) bool { - return reflect.TypeOf(a[i]).Elem().Name() < reflect.TypeOf(a[j]).Elem().Name() -} diff --git a/utils/build_error.go b/utils/build_error.go index faa8614..1c529b5 100644 --- a/utils/build_error.go +++ b/utils/build_error.go @@ -2,9 +2,10 @@ package utils import ( "fmt" - "github.com/revel/cmd/logger" - "strconv" "regexp" + "strconv" + + "github.com/revel/cmd/logger" ) type ( @@ -15,7 +16,7 @@ type ( } ) -// Returns a new builed error +// Returns a new builed error. func NewBuildError(message string, args ...interface{}) (b *BuildError) { Logger.Info(message, args...) b = &BuildError{} @@ -26,22 +27,23 @@ func NewBuildError(message string, args ...interface{}) (b *BuildError) { return b } -// Returns a new BuildError if err is not nil +// Returns a new BuildError if err is not nil. func NewBuildIfError(err error, message string, args ...interface{}) (b error) { if err != nil { if berr, ok := err.(*BuildError); ok { // This is already a build error so just append the args berr.Args = append(berr.Args, args...) return berr - } else { - args = append(args, "error", err.Error()) - b = NewBuildError(message, args...) } + + args = append(args, "error", err.Error()) + b = NewBuildError(message, args...) } + return } -// BuildError implements Error() string +// BuildError implements Error() string. func (b *BuildError) Error() string { return fmt.Sprint(b.Message, b.Args) } @@ -70,13 +72,12 @@ func NewCompileError(importPath, errorLink string, error error) *SourceError { Logger.Error("Build errors", "errors", error) } - // Read the source for the offending file. var ( - relFilename = string(errorMatch[1]) // e.g. "src/revel/sample/app/controllers/app.go" - absFilename = relFilename - line, _ = strconv.Atoi(string(errorMatch[2])) - description = string(errorMatch[4]) + relFilename = string(errorMatch[1]) // e.g. "src/revel/sample/app/controllers/app.go" + absFilename = relFilename + line, _ = strconv.Atoi(string(errorMatch[2])) + description = string(errorMatch[4]) compileError = &SourceError{ SourceType: "Go code", Title: "Go Compilation Error", @@ -95,10 +96,10 @@ func NewCompileError(importPath, errorLink string, error error) *SourceError { fileStr, err := ReadLines(absFilename) if err != nil { compileError.MetaError = absFilename + ": " + err.Error() - Logger.Info("Unable to readlines " + compileError.MetaError, "error", err) + Logger.Info("Unable to readlines "+compileError.MetaError, "error", err) return compileError } compileError.SourceLines = fileStr return compileError -} \ No newline at end of file +} diff --git a/utils/command.go b/utils/command.go index e00b4e1..a233659 100644 --- a/utils/command.go +++ b/utils/command.go @@ -1,19 +1,25 @@ package utils import ( + "bytes" "go/build" "os" "os/exec" - "strings" - "bytes" "path/filepath" + "strings" ) -// Initialize the command based on the GO environment +// Initialize the command based on the GO environment. func CmdInit(c *exec.Cmd, addGoPath bool, basePath string) { c.Dir = basePath // Dep does not like paths that are not real, convert all paths in go to real paths + // Fetch the rest of the env variables + c.Env = ReducedEnv(addGoPath) + +} +func ReducedEnv(addGoPath bool) []string { realPath := &bytes.Buffer{} + env := []string{} if addGoPath { for _, p := range filepath.SplitList(build.Default.GOPATH) { rp, _ := filepath.EvalSymlinks(p) @@ -23,14 +29,18 @@ func CmdInit(c *exec.Cmd, addGoPath bool, basePath string) { realPath.WriteString(rp) } // Go 1.8 fails if we do not include the GOROOT - c.Env = []string{"GOPATH=" + realPath.String(), "GOROOT=" + os.Getenv("GOROOT")} + env = []string{"GOPATH=" + realPath.String(), "GOROOT=" + os.Getenv("GOROOT")} } - // Fetch the rest of the env variables + for _, e := range os.Environ() { pair := strings.Split(e, "=") - if pair[0] == "GOPATH" || pair[0] == "GOROOT" { + // Always exclude gomodcache + if pair[0] == "GOMODCACHE" { continue + } else if !addGoPath && (pair[0] == "GOPATH" || pair[0] == "GOROOT") { + } - c.Env = append(c.Env, e) + env = append(env, e) } -} \ No newline at end of file + return env +} diff --git a/utils/error.go b/utils/error.go index 93143d8..520722a 100644 --- a/utils/error.go +++ b/utils/error.go @@ -6,7 +6,7 @@ import ( "strings" ) -// The error is a wrapper for the +// The error is a wrapper for the. type ( SourceError struct { SourceType string // The type of source that failed to build. @@ -23,27 +23,28 @@ type ( IsError bool } ) -// Return a new error object + +// Return a new error object. func NewError(source, title, path, description string) *SourceError { return &SourceError{ - SourceType:source, - Title:title, - Path:path, - Description:description, + SourceType: source, + Title: title, + Path: path, + Description: description, } } -// Creates a link based on the configuration setting "errors.link" +// Creates a link based on the configuration setting "errors.link". func (e *SourceError) SetLink(errorLink string) { - errorLink = strings.Replace(errorLink, "{{Path}}", e.Path, -1) - errorLink = strings.Replace(errorLink, "{{Line}}", strconv.Itoa(e.Line), -1) + errorLink = strings.ReplaceAll(errorLink, "{{Path}}", e.Path) + errorLink = strings.ReplaceAll(errorLink, "{{Line}}", strconv.Itoa(e.Line)) e.Link = "" + e.Path + ":" + strconv.Itoa(e.Line) + "" } // Error method constructs a plaintext version of the error, taking // account that fields are optionally set. Returns e.g. Compilation Error -// (in views/header.html:51): expected right delim in end; got "}" +// (in views/header.html:51): expected right delim in end; got "}". func (e *SourceError) Error() string { if e == nil { panic("opps") @@ -82,7 +83,7 @@ func (e *SourceError) ContextSource() []SourceLine { end = len(e.SourceLines) } - lines := make([]SourceLine, end - start) + lines := make([]SourceLine, end-start) for i, src := range e.SourceLines[start:end] { fileLine := start + i + 1 lines[i] = SourceLine{src, fileLine, fileLine == e.Line} diff --git a/utils/file.go b/utils/file.go index 92a2cfd..4fe0eef 100644 --- a/utils/file.go +++ b/utils/file.go @@ -4,14 +4,15 @@ import ( "archive/tar" "bytes" "compress/gzip" - "fmt" "errors" + "fmt" "html/template" "io" "io/ioutil" "os" "path/filepath" "strings" + "golang.org/x/tools/go/packages" ) @@ -39,9 +40,8 @@ func ReadLines(filename string) ([]string, error) { return strings.Split(string(dataBytes), "\n"), nil } -// Copy file returns error +// Copy file returns error. func CopyFile(destFilename, srcFilename string) (err error) { - destFile, err := os.Create(destFilename) if err != nil { return NewBuildIfError(err, "Failed to create file", "file", destFilename) @@ -105,11 +105,11 @@ func GenerateTemplate(filename, templateSource string, args map[string]interface return } -// Given the target path and source path and data. A template +// Given the target path and source path and data. A template. func RenderTemplate(destPath, srcPath string, data interface{}) (err error) { tmpl, err := template.ParseFiles(srcPath) if err != nil { - return NewBuildIfError(err, "Failed to parse template " + srcPath) + return NewBuildIfError(err, "Failed to parse template "+srcPath) } f, err := os.Create(destPath) @@ -119,26 +119,26 @@ func RenderTemplate(destPath, srcPath string, data interface{}) (err error) { err = tmpl.Execute(f, data) if err != nil { - return NewBuildIfError(err, "Failed to Render template " + srcPath) + return NewBuildIfError(err, "Failed to Render template "+srcPath) } err = f.Close() if err != nil { - return NewBuildIfError(err, "Failed to close file stream " + destPath) + return NewBuildIfError(err, "Failed to close file stream "+destPath) } return } -// Given the target path and source path and data. A template +// Given the target path and source path and data. A template. func RenderTemplateToStream(output io.Writer, srcPath []string, data interface{}) (err error) { tmpl, err := template.ParseFiles(srcPath...) if err != nil { - return NewBuildIfError(err, "Failed to parse template " + srcPath[0]) + return NewBuildIfError(err, "Failed to parse template "+srcPath[0]) } err = tmpl.Execute(output, data) if err != nil { - return NewBuildIfError(err, "Failed to render template " + srcPath[0]) + return NewBuildIfError(err, "Failed to render template "+srcPath[0]) } return } @@ -148,7 +148,7 @@ func MustChmod(filename string, mode os.FileMode) { PanicOnError(err, fmt.Sprintf("Failed to chmod %d %q", mode, filename)) } -// Called if panic +// Called if panic. func PanicOnError(err error, msg string) { if revErr, ok := err.(*SourceError); (ok && revErr != nil) || (!ok && err != nil) { Logger.Panicf("Abort: %s: %s %s", msg, revErr, err) @@ -181,15 +181,14 @@ func CopyDir(destDir, srcDir string, data map[string]interface{}) error { if info.IsDir() { err := os.MkdirAll(filepath.Join(destDir, relSrcPath), 0777) if !os.IsExist(err) { - return NewBuildIfError(err, "Failed to create directory", "path", destDir + "/" + relSrcPath) + return NewBuildIfError(err, "Failed to create directory", "path", destDir+"/"+relSrcPath) } return nil } // If this file ends in ".template", render it as a template. if strings.HasSuffix(relSrcPath, ".template") { - - return RenderTemplate(destPath[:len(destPath) - len(".template")], srcPath, data) + return RenderTemplate(destPath[:len(destPath)-len(".template")], srcPath, data) } // Else, just copy it over. @@ -198,13 +197,13 @@ func CopyDir(destDir, srcDir string, data map[string]interface{}) error { }) } -// Shortcut to fsWalk +// Shortcut to fsWalk. func Walk(root string, walkFn filepath.WalkFunc) error { return fsWalk(root, root, walkFn) } // Walk the path tree using the function -// Every file found will call the function +// Every file found will call the function. func fsWalk(fname string, linkName string, walkFn filepath.WalkFunc) error { fsWalkFunc := func(path string, info os.FileInfo, err error) error { if err != nil { @@ -219,7 +218,7 @@ func fsWalk(fname string, linkName string, walkFn filepath.WalkFunc) error { path = filepath.Join(linkName, name) - if err == nil && info.Mode() & os.ModeSymlink == os.ModeSymlink { + if err == nil && info.Mode()&os.ModeSymlink == os.ModeSymlink { var symlinkPath string symlinkPath, err = filepath.EvalSymlinks(path) if err != nil { @@ -244,7 +243,7 @@ func fsWalk(fname string, linkName string, walkFn filepath.WalkFunc) error { return err } -// Tar gz the folder +// Tar gz the folder. func TarGzDir(destFilename, srcDir string) (name string, err error) { zipFile, err := os.Create(destFilename) if err != nil { @@ -266,6 +265,10 @@ func TarGzDir(destFilename, srcDir string) (name string, err error) { }() err = fsWalk(srcDir, srcDir, func(srcPath string, info os.FileInfo, err error) error { + if err != nil { + Logger.Debugf("error in walkFn: %s", err) + } + if info.IsDir() { return nil } @@ -300,7 +303,7 @@ func TarGzDir(destFilename, srcDir string) (name string, err error) { return zipFile.Name(), err } -// Return true if the file exists +// Return true if the file exists. func Exists(filename string) bool { _, err := os.Stat(filename) return err == nil @@ -324,7 +327,7 @@ func Empty(dirname string) bool { return len(results) == 0 } -// Find the full source dir for the import path, uses the build.Default.GOPATH to search for the directory +// Find the full source dir for the import path, uses the build.Default.GOPATH to search for the directory. func FindSrcPaths(appPath string, packageList []string, packageResolver func(pkgName string) error) (sourcePathsmap map[string]string, err error) { sourcePathsmap, missingList, err := findSrcPaths(appPath, packageList) if err != nil && packageResolver != nil || len(missingList) > 0 { @@ -345,17 +348,20 @@ func FindSrcPaths(appPath string, packageList []string, packageResolver func(pkg return } -var NO_APP_FOUND = errors.New("No app found") -var NO_REVEL_FOUND = errors.New("No revel found") +var ( + NO_APP_FOUND = errors.New("no app found") + NO_REVEL_FOUND = errors.New("no revel found") +) -// Find the full source dir for the import path, uses the build.Default.GOPATH to search for the directory -func findSrcPaths(appPath string, packagesList []string) (sourcePathsmap map[string]string, missingList[] string, err error) { +// Find the full source dir for the import path, uses the build.Default.GOPATH to search for the directory. +func findSrcPaths(appPath string, packagesList []string) (sourcePathsmap map[string]string, missingList []string, err error) { // Use packages to fetch // by not specifying env, we will use the default env config := &packages.Config{ - Mode: packages.NeedName | packages.NeedFiles, - Dir:appPath, + Mode: packages.NeedName | packages.NeedFiles | packages.NeedDeps, + Dir: appPath, } + config.Env = ReducedEnv(false) sourcePathsmap = map[string]string{} Logger.Infof("Environment path %s root %s config env %s", os.Getenv("GOPATH"), os.Getenv("GOROOT"), config.Env) @@ -371,9 +377,8 @@ func findSrcPaths(appPath string, packagesList []string) (sourcePathsmap map[str if pck.Errors != nil && len(pck.Errors) > 0 { log.Error("Error ", "count", len(pck.Errors), "App Import Path", pck.ID, "filesystem path", pck.PkgPath, "errors", pck.Errors) // continue - } - //a,_ := pck.MarshalJSON() + // a,_ := pck.MarshalJSON() log.Info("Found ", "count", len(pck.GoFiles), "App Import Path", pck.ID, "apppath", appPath) if len(pck.GoFiles) > 0 { sourcePathsmap[packageName] = filepath.Dir(pck.GoFiles[0]) diff --git a/utils/log.go b/utils/log.go index 29a61fb..6da97e1 100644 --- a/utils/log.go +++ b/utils/log.go @@ -2,10 +2,11 @@ package utils import ( "fmt" - "github.com/revel/cmd/logger" - "github.com/revel/config" "os" "strings" + + "github.com/revel/cmd/logger" + "github.com/revel/config" ) var Logger = logger.New() @@ -31,7 +32,7 @@ func InitLogger(basePath string, logLevel logger.LogLevel) { } // This function is to throw a panic that may be caught by the packger so it can perform the needed -// imports +// imports. func Retry(format string, args ...interface{}) { // Ensure the user's command prompt starts on the next line. if !strings.HasSuffix(format, "\n") { diff --git a/utils/strings.go b/utils/strings.go index 1230be6..1dd30d6 100644 --- a/utils/strings.go +++ b/utils/strings.go @@ -1,6 +1,6 @@ package utils -// Return true if the target string is in the list +// Return true if the target string is in the list. func ContainsString(list []string, target string) bool { for _, el := range list { if el == target { diff --git a/version.go b/version.go index 03ac174..9fca510 100644 --- a/version.go +++ b/version.go @@ -6,11 +6,11 @@ package cmd const ( // Version current Revel version - Version = "1.0.0" + Version = "1.1.0-dev" - // BuildDate latest commit/release date + // BuildDate latest commit/release date. BuildDate = "2020-07-11" - // MinimumGoVersion minimum required Go version for Revel + // MinimumGoVersion minimum required Go version for Revel. MinimumGoVersion = ">= go1.12" ) diff --git a/watcher/watcher.go b/watcher/watcher.go index be7ab0a..9a7c3f2 100644 --- a/watcher/watcher.go +++ b/watcher/watcher.go @@ -9,11 +9,11 @@ import ( "path/filepath" "strings" "sync" + "time" + "github.com/fsnotify/fsnotify" "github.com/revel/cmd/model" "github.com/revel/cmd/utils" - "github.com/fsnotify/fsnotify" - "time" ) // Listener is an interface for receivers of filesystem events. @@ -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,14 +42,14 @@ 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 } -// Creates a new watched based on the container +// Creates a new watched based on the container. func NewWatcher(paths *model.RevelContainer, eagerRefresh bool) *Watcher { return &Watcher{ forceRefresh: false, @@ -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 { @@ -109,9 +109,7 @@ func (w *Watcher) Listen(listener Listener, roots ...string) { continue } - var watcherWalker func(path string, info os.FileInfo, err error) error - - watcherWalker = func(path string, info os.FileInfo, err error) error { + watcherWalker := func(path string, info os.FileInfo, err error) error { if err != nil { utils.Logger.Fatal("Watcher: Error walking path:", "error", err) return nil @@ -150,7 +148,6 @@ func (w *Watcher) Listen(listener Listener, roots ...string) { // NotifyWhenUpdated notifies the watcher when a file event is received. func (w *Watcher) NotifyWhenUpdated(listener Listener, watcher *fsnotify.Watcher) { - for { select { case ev := <-watcher.Events: @@ -200,7 +197,7 @@ func (w *Watcher) Notify() *utils.SourceError { case <-watcher.Errors: continue default: - // No events left to pull + // No events left to pull } break } @@ -218,10 +215,10 @@ func (w *Watcher) Notify() *utils.SourceError { w.lastError = i w.forceRefresh = true return err - } else { - w.lastError = -1 - w.forceRefresh = false } + + w.lastError = -1 + w.forceRefresh = false } } @@ -229,7 +226,7 @@ func (w *Watcher) Notify() *utils.SourceError { } // Build a queue for refresh notifications -// this will not return until one of the queue completes +// this will not return until one of the queue completes. func (w *Watcher) notifyInProcess(listener Listener) (err *utils.SourceError) { shouldReturn := false // This code block ensures that either a timer is created @@ -286,10 +283,9 @@ 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 } -