Merging develop to master for v0.13.0 release

This commit is contained in:
Jeevanandam M
2016-06-05 18:32:53 -07:00
14 changed files with 170 additions and 64 deletions

View File

@@ -80,6 +80,7 @@ func Build(buildFlags ...string) (app *App, compileError *revel.Error) {
versionLinkerFlags := fmt.Sprintf("-X %s/app.APP_VERSION \"%s\"", revel.ImportPath, appVersion)
flags := []string{
"build",
"-i",
"-ldflags", versionLinkerFlags,
"-tags", buildTags,
"-o", binName}
@@ -173,12 +174,16 @@ func cleanDir(dir string) {
tmpPath := path.Join(revel.AppPath, dir)
f, err := os.Open(tmpPath)
if err != nil {
revel.ERROR.Println("Failed to clean dir:", err)
if !os.IsNotExist(err) {
revel.ERROR.Println("Failed to clean dir:", err)
}
} else {
defer f.Close()
infos, err := f.Readdir(0)
if err != nil {
revel.ERROR.Println("Failed to clean dir:", err)
if !os.IsNotExist(err) {
revel.ERROR.Println("Failed to clean dir:", err)
}
} else {
for _, info := range infos {
path := path.Join(tmpPath, info.Name())
@@ -198,7 +203,6 @@ func cleanDir(dir string) {
}
}
// genSource renders the given template to produce source code, which it writes
// to the given directory and file.
func genSource(dir, filename, templateSource string, args map[string]interface{}) {

View File

@@ -13,7 +13,6 @@ package harness
import (
"crypto/tls"
"fmt"
"github.com/revel/revel"
"go/build"
"io"
"net"
@@ -22,10 +21,11 @@ import (
"net/url"
"os"
"os/signal"
"path"
"path/filepath"
"strings"
"sync/atomic"
"github.com/revel/revel"
)
var (
@@ -52,7 +52,7 @@ func renderError(w http.ResponseWriter, r *http.Request, err error) {
// ServeHTTP handles all requests.
// It checks for changes to app, rebuilds if necessary, and forwards the request.
func (hp *Harness) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func (h *Harness) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Don't rebuild the app for favicon requests.
if lastRequestHadError > 0 && r.URL.Path == "/favicon.ico" {
return
@@ -71,18 +71,19 @@ func (hp *Harness) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Reverse proxy the request.
// (Need special code for websockets, courtesy of bradfitz)
if strings.EqualFold(r.Header.Get("Upgrade"), "websocket") {
proxyWebsocket(w, r, hp.serverHost)
proxyWebsocket(w, r, h.serverHost)
} else {
hp.proxy.ServeHTTP(w, r)
h.proxy.ServeHTTP(w, r)
}
}
// Return a reverse proxy that forwards requests to the given port.
// NewHarness method returns a reverse proxy that forwards requests
// to the given port.
func NewHarness() *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(
[]string{path.Join(revel.RevelPath, "templates")})
[]string{filepath.Join(revel.RevelPath, "templates")})
revel.MainTemplateLoader.Refresh()
addr := revel.HttpAddr
@@ -101,12 +102,12 @@ func NewHarness() *Harness {
port = getFreePort()
}
serverUrl, _ := url.ParseRequestURI(fmt.Sprintf(scheme+"://%s:%d", addr, port))
serverURL, _ := url.ParseRequestURI(fmt.Sprintf(scheme+"://%s:%d", addr, port))
harness := &Harness{
port: port,
serverHost: serverUrl.String()[len(scheme+"://"):],
proxy: httputil.NewSingleHostReverseProxy(serverUrl),
serverHost: serverURL.String()[len(scheme+"://"):],
proxy: httputil.NewSingleHostReverseProxy(serverURL),
}
if revel.HttpSsl {
@@ -117,7 +118,7 @@ func NewHarness() *Harness {
return harness
}
// Rebuild the Revel application and run it on the given port.
// Refresh method rebuilds the Revel application and run it on the given port.
func (h *Harness) Refresh() (err *revel.Error) {
if h.app != nil {
h.app.Kill()
@@ -140,10 +141,14 @@ func (h *Harness) Refresh() (err *revel.Error) {
return
}
// WatchDir method returns false to file matches with doNotWatch
// otheriwse true
func (h *Harness) WatchDir(info os.FileInfo) bool {
return !revel.ContainsString(doNotWatch, info.Name())
}
// WatchFile method returns true given filename HasSuffix of ".go"
// otheriwse false
func (h *Harness) WatchFile(filename string) bool {
return strings.HasSuffix(filename, ".go")
}
@@ -204,7 +209,18 @@ func getFreePort() (port int) {
// proxyWebsocket copies data between websocket client and server until one side
// closes the connection. (ReverseProxy doesn't work with websocket requests.)
func proxyWebsocket(w http.ResponseWriter, r *http.Request, host string) {
d, err := net.Dial("tcp", host)
var (
d net.Conn
err error
)
if revel.HttpSsl {
// since this proxy isn't used in production,
// it's OK to set InsecureSkipVerify to true
// no need to add another configuration option.
d, err = tls.Dial("tcp", host, &tls.Config{InsecureSkipVerify: true})
} else {
d, err = net.Dial("tcp", host)
}
if err != nil {
http.Error(w, "Error contacting backend server.", 500)
revel.ERROR.Printf("Error dialing websocket backend %s: %v", host, err)

View File

@@ -96,7 +96,7 @@ func ProcessSource(roots []string) (*SourceInfo, *revel.Error) {
}
// Start walking the directory tree.
filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
_ = revel.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
log.Println("Error scanning app source:", err)
return nil
@@ -433,7 +433,8 @@ func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPat
var importPath string
typeExpr := NewTypeExpr(pkgName, field.Type)
if !typeExpr.Valid {
return // We didn't understand one of the args. Ignore this action. (Already logged)
log.Printf("Didn't understand argument '%s' of action %s. Ignoring.\n", name, getFuncName(funcDecl))
return // We didn't understand one of the args. Ignore this action.
}
if typeExpr.PkgName != "" {
var ok bool

View File

@@ -7,17 +7,22 @@ import (
"path/filepath"
"strings"
"github.com/revel/revel"
"github.com/revel/cmd/harness"
"github.com/revel/revel"
)
var cmdBuild = &Command{
UsageLine: "build [import path] [target path]",
UsageLine: "build [import path] [target path] [run mode]",
Short: "build a Revel application (e.g. for deployment)",
Long: `
Build the Revel web application named by the given import path.
This allows it to be deployed and run on a machine that lacks a Go installation.
The run mode is used to select which set of app.conf configuration should
apply and may be used to determine logic in the application itself.
Run mode defaults to "dev".
WARNING: The target path will be completely deleted, if it already exists!
For example:
@@ -31,14 +36,18 @@ func init() {
}
func buildApp(args []string) {
if len(args) != 2 {
if len(args) < 2 {
fmt.Fprintf(os.Stderr, "%s\n%s", cmdBuild.UsageLine, cmdBuild.Long)
return
}
appImportPath, destPath := args[0], args[1]
appImportPath, destPath, mode := args[0], args[1], "dev"
if len(args) >= 3 {
mode = args[2]
}
if !revel.Initialized {
revel.Init("", appImportPath, "")
revel.Init(mode, appImportPath, "")
}
// First, verify that it is either already empty or looks like a previous
@@ -96,6 +105,7 @@ func buildApp(args []string) {
tmplData, runShPath := map[string]interface{}{
"BinName": filepath.Base(app.BinaryPath),
"ImportPath": appImportPath,
"Mode": mode,
}, path.Join(destPath, "run.sh")
mustRenderTemplate(

View File

@@ -17,7 +17,7 @@ For example:
revel clean github.com/revel/samples/chat
It removes the app/tmp directory.
It removes the app/tmp and app/routes directory.
`,
}
@@ -37,12 +37,17 @@ func cleanApp(args []string) {
return
}
// Remove the app/tmp directory.
tmpDir := path.Join(appPkg.Dir, "app", "tmp")
fmt.Println("Removing:", tmpDir)
err = os.RemoveAll(tmpDir)
if err != nil {
fmt.Fprintln(os.Stderr, "Abort:", err)
return
purgeDirs := []string{
path.Join(appPkg.Dir, "app", "tmp"),
path.Join(appPkg.Dir, "app", "routes"),
}
for _, dir := range purgeDirs {
fmt.Println("Removing:", dir)
err = os.RemoveAll(dir)
if err != nil {
fmt.Fprintln(os.Stderr, "Abort:", err)
return
}
}
}

View File

@@ -4,10 +4,12 @@ import (
"bytes"
"fmt"
"go/build"
"log"
"math/rand"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/revel/revel"
)
@@ -60,6 +62,8 @@ func newApp(args []string) {
errorf("Too many arguments provided.\nRun 'revel help new' for usage.\n")
}
revel.ERROR.SetFlags(log.LstdFlags)
// checking and setting go paths
initGoPaths()
@@ -96,9 +100,6 @@ func initGoPaths() {
"Please refer to http://golang.org/doc/code.html to configure your Go environment.")
}
// set go src path
srcRoot = filepath.Join(filepath.SplitList(gopath)[0], "src")
// check for go executable
var err error
gocmd, err = exec.LookPath("go")
@@ -106,12 +107,38 @@ func initGoPaths() {
errorf("Go executable not found in PATH.")
}
// revel/revel#1004 choose go path relative to current working directory
workingDir, _ := os.Getwd()
goPathList := filepath.SplitList(gopath)
for _, path := range goPathList {
if strings.HasPrefix(strings.ToLower(workingDir), strings.ToLower(path)) {
srcRoot = path
break
}
path, _ = filepath.EvalSymlinks(path)
if len(path) > 0 && strings.HasPrefix(strings.ToLower(workingDir), strings.ToLower(path)) {
srcRoot = path
break
}
}
if len(srcRoot) == 0 {
revel.ERROR.Fatalln("Abort: could not create a Revel application outside of GOPATH.")
}
// set go src path
srcRoot = filepath.Join(srcRoot, "src")
}
func setApplicationPath(args []string) {
var err error
importPath = args[0]
if filepath.IsAbs(importPath) {
// revel/revel#1014 validate relative path, we cannot use built-in functions
// since Go import path is valid relative path too.
// so check basic part of the path, which is "."
if filepath.IsAbs(importPath) || strings.HasPrefix(importPath, ".") {
errorf("Abort: '%s' looks like a directory. Please provide a Go import path instead.",
importPath)
}

View File

@@ -2,19 +2,25 @@ package main
import (
"fmt"
"github.com/revel/revel"
"io/ioutil"
"os"
"path/filepath"
"github.com/revel/revel"
)
var cmdPackage = &Command{
UsageLine: "package [import path]",
UsageLine: "package [import path] [run mode]",
Short: "package a Revel application (e.g. for deployment)",
Long: `
Package the Revel web application named by the given import path.
This allows it to be deployed and run on a machine that lacks a Go installation.
The run mode is used to select which set of app.conf configuration should
apply and may be used to determine logic in the application itself.
Run mode defaults to "dev".
For example:
revel package github.com/revel/samples/chat
@@ -31,8 +37,14 @@ func packageApp(args []string) {
return
}
// Determine the run mode.
mode := "dev"
if len(args) >= 2 {
mode = args[1]
}
appImportPath := args[0]
revel.Init("", appImportPath, "")
revel.Init(mode, appImportPath, "")
// Remove the archive if it already exists.
destFile := filepath.Base(revel.BasePath) + ".tar.gz"
@@ -42,7 +54,7 @@ func packageApp(args []string) {
tmpDir, err := ioutil.TempDir("", filepath.Base(revel.BasePath))
panicOnError(err, "Failed to get temp dir")
buildApp([]string{args[0], tmpDir})
buildApp([]string{args[0], tmpDir, mode})
// Create the zip file.
archiveName := mustTarGzDir(destFile, tmpDir)

View File

@@ -1,2 +1,2 @@
@echo off
{{.BinName}} -importPath {{.ImportPath}} -srcPath %CD%\src -runMode prod
{{.BinName}} -importPath {{.ImportPath}} -srcPath %CD%\src -runMode {{.Mode}}

View File

@@ -1,3 +1,3 @@
#!/bin/sh
SCRIPTPATH=$(cd "$(dirname "$0")"; pwd)
"$SCRIPTPATH/{{.BinName}}" -importPath {{.ImportPath}} -srcPath "$SCRIPTPATH/src" -runMode prod
"$SCRIPTPATH/{{.BinName}}" -importPath {{.ImportPath}} -srcPath "$SCRIPTPATH/src" -runMode {{.Mode}}

View File

@@ -4,7 +4,6 @@ package main
import (
"flag"
"fmt"
"github.com/agtorre/gocolorize"
"io"
"math/rand"
"os"
@@ -12,9 +11,11 @@ import (
"strings"
"text/template"
"time"
"github.com/agtorre/gocolorize"
)
// Cribbed from the genius organization of the "go" command.
// Command structure cribbed from the genius organization of the "go" command.
type Command struct {
Run func(args []string)
UsageLine, Short, Long string
@@ -36,6 +37,7 @@ var commands = []*Command{
cmdPackage,
cmdClean,
cmdTest,
cmdVersion,
}
func main() {

View File

@@ -1,8 +1,8 @@
package main
import (
"github.com/revel/revel"
"github.com/revel/cmd/harness"
"github.com/revel/revel"
"strconv"
)
@@ -65,7 +65,7 @@ func runApp(args []string) {
}
// Else, just build and run the app.
revel.TRACE.Println("Running in live build mode.")
revel.TRACE.Println("Running in live build mode.")
app, err := harness.Build()
if err != nil {
errorf("Failed to build app: %s", err)

View File

@@ -3,9 +3,6 @@ package main
import (
"encoding/json"
"fmt"
"github.com/revel/revel"
"github.com/revel/cmd/harness"
"github.com/revel/modules/testrunner/app/controllers"
"io"
"io/ioutil"
"net/http"
@@ -13,6 +10,10 @@ import (
"path"
"strings"
"time"
"github.com/revel/cmd/harness"
"github.com/revel/modules/testrunner/app/controllers"
"github.com/revel/revel"
)
var cmdTest = &Command{
@@ -117,13 +118,19 @@ You can add it to a run mode configuration with the following line:
)
for i := 0; ; i++ {
if resp, err = http.Get(baseUrl + "/@tests.list"); err == nil {
break
if resp.StatusCode == http.StatusOK {
break
}
}
if i < 3 {
time.Sleep(3 * time.Second)
continue
}
errorf("Failed to request test list: %s", err)
if err != nil {
errorf("Failed to request test list: %s", err)
} else {
errorf("Failed to request test list: non-200 response")
}
}
defer resp.Body.Close()
json.NewDecoder(resp.Body).Decode(&testSuites)

View File

@@ -66,22 +66,10 @@ func mustChmod(filename string, mode os.FileMode) {
// Additionally, the trailing ".template" is stripped from the file name.
// Also, dot files and dot directories are skipped.
func mustCopyDir(destDir, srcDir string, data map[string]interface{}) error {
var fullSrcDir string
// Handle symlinked directories.
f, err := os.Lstat(srcDir)
if err == nil && f.Mode()&os.ModeSymlink == os.ModeSymlink {
fullSrcDir, err = os.Readlink(srcDir)
if err != nil {
panic(err)
}
} else {
fullSrcDir = srcDir
}
return filepath.Walk(fullSrcDir, func(srcPath string, info os.FileInfo, err error) error {
return revel.Walk(srcDir, func(srcPath string, info os.FileInfo, err error) error {
// Get the relative path from the source base, and the corresponding path in
// the dest directory.
relSrcPath := strings.TrimLeft(srcPath[len(fullSrcDir):], string(os.PathSeparator))
relSrcPath := strings.TrimLeft(srcPath[len(srcDir):], string(os.PathSeparator))
destPath := path.Join(destDir, relSrcPath)
// Skip dot files and dot directories.
@@ -124,7 +112,7 @@ func mustTarGzDir(destFilename, srcDir string) string {
tarWriter := tar.NewWriter(gzipWriter)
defer tarWriter.Close()
filepath.Walk(srcDir, func(srcPath string, info os.FileInfo, err error) error {
revel.Walk(srcDir, func(srcPath string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}

34
revel/version.go Normal file
View File

@@ -0,0 +1,34 @@
// Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved.
// Revel Framework source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"runtime"
"github.com/revel/revel"
)
var cmdVersion = &Command{
UsageLine: "version",
Short: "displays the Revel Framework and Go version",
Long: `
Displays the Revel Framework and Go version.
For example:
revel version
`,
}
func init() {
cmdVersion.Run = versionApp
}
func versionApp(args []string) {
fmt.Printf("Version(s):")
fmt.Printf("\n Revel v%v (%v)", revel.Version, revel.BuildDate)
fmt.Printf("\n %s %s/%s\n\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
}