diff --git a/harness/app.go b/harness/app.go index 1ae5f81..3b855b8 100644 --- a/harness/app.go +++ b/harness/app.go @@ -15,6 +15,7 @@ import ( "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) @@ -101,11 +102,30 @@ func (cmd AppCmd) Run() { 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 { + // Server has already exited + utils.Logger.Info("Killing revel server pid", "pid", cmd.Process.Pid) + return + } + // Send an interrupt signal to allow for a graceful shutdown utils.Logger.Info("Killing revel server pid", "pid", cmd.Process.Pid) - err := cmd.Process.Signal(os.Interrupt) + var err error + if runtime.GOOS == "windows" { + // os.Interrupt is not available on windows + err = cmd.Process.Signal(os.Kill) + } else { + err = cmd.Process.Signal(os.Interrupt) + } + if err != nil { - utils.Logger.Fatal("Failed to kill revel server:", "error", err) + utils.Logger.Error( + "Revel app failed to kill process.", + "processid", cmd.Process.Pid,"error",err, + "killerror", cmd.Process.Kill()) + return } // Wait for the shutdown diff --git a/harness/build.go b/harness/build.go index c2c4228..ea6b7ef 100644 --- a/harness/build.go +++ b/harness/build.go @@ -136,10 +136,14 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err } for { + appVersion := getAppVersion(paths) + if appVersion == "" { + appVersion = "noVersionProvided" + } buildTime := time.Now().UTC().Format(time.RFC3339) - versionLinkerFlags := fmt.Sprintf("-X %s/app.AppVersion=%s -X %s/app.BuildTime=%s", + versionLinkerFlags := fmt.Sprintf("-X '%s/app.AppVersion=%s' -X '%s/app.BuildTime=%s'", paths.ImportPath, appVersion, paths.ImportPath, buildTime) // Append any build flags specified, they will override existing flags @@ -155,9 +159,13 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err if !contains(c.BuildFlags, "build") { flags = []string{"build"} } - flags = append(flags, c.BuildFlags...) if !contains(flags, "-ldflags") { - flags = append(flags, "-ldflags", versionLinkerFlags) + ldflags := "-ldflags= " + versionLinkerFlags + // Add in build flags + for i := range c.BuildFlags { + ldflags += "-X '" + c.BuildFlags[i] + "'" + } + flags = append(flags, ldflags) } if !contains(flags, "-tags") { flags = append(flags, "-tags", buildTags) @@ -167,9 +175,6 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err err } } - // Add in build flags - flags = append(flags, c.BuildFlags...) - // This is Go main path gopath := c.GoPath for _, o := range paths.ModulePathMap { @@ -400,7 +405,7 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.Error { // Extract the paths from the gopaths, and search for file there first gopaths := filepath.SplitList(build.Default.GOPATH) for _, gp := range gopaths { - newPath := filepath.Join(gp,"src", paths.ImportPath, relFilename) + newPath := filepath.Join(gp, "src", paths.ImportPath, relFilename) println(newPath) if utils.Exists(newPath) { return newPath @@ -411,7 +416,6 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.Error { return newPath } - // Read the source for the offending file. var ( relFilename = string(errorMatch[1]) // e.g. "src/revel/sample/app/controllers/app.go" diff --git a/model/command_config.go b/model/command_config.go index fa98c0a..93b355b 100644 --- a/model/command_config.go +++ b/model/command_config.go @@ -89,7 +89,7 @@ type ( // The version command Version struct { ImportPath string `short:"a" long:"application-path" description:"Path to application folder" required:"false"` - Update bool `short:"u" long:"Update the framework and modules" required:"false"` + Update bool `short:"u" long:"update" description:"Update the framework and modules" required:"false"` } `command:"version"` } ) diff --git a/parser/appends.go b/parser/appends.go index 2990795..2dcc562 100644 --- a/parser/appends.go +++ b/parser/appends.go @@ -134,7 +134,7 @@ func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPat var importPath string typeExpr := model.NewTypeExprFromAst(pkgName, field.Type) if !typeExpr.Valid { - utils.Logger.Warn("Warn: Didn't understand argument '%s' of action %s. Ignoring.", name, getFuncName(funcDecl)) + utils.Logger.Warnf("Warn: Didn't understand argument '%s' of action %s. Ignoring.", name, getFuncName(funcDecl)) return // We didn't understand one of the args. Ignore this action. } // Local object diff --git a/parser/imports.go b/parser/imports.go index d0edd15..150c6ed 100644 --- a/parser/imports.go +++ b/parser/imports.go @@ -29,7 +29,10 @@ func addImports(imports map[string]string, decl ast.Decl, srcDir string) { continue } } - quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\"" + quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\"" + if quotedPath == `"C"` { + continue + } fullPath := quotedPath[1 : len(quotedPath)-1] // Remove the quotes // If the package was not aliased (common case), we have to import it @@ -60,9 +63,10 @@ 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 -func importPathFromPath(root string) string { - if vendorIdx := strings.Index(root, "/vendor/"); vendorIdx != -1 { - return filepath.ToSlash(root[vendorIdx+8:]) +func importPathFromPath(root, basePath string) string { + vendorTest := filepath.Join(basePath, "vendor") + if len(root) > len(vendorTest) && root[:len(vendorTest)] == vendorTest { + return filepath.ToSlash(root[len(vendorTest)+1:]) } for _, gopath := range filepath.SplitList(build.Default.GOPATH) { srcPath := filepath.Join(gopath, "src") diff --git a/parser/reflect.go b/parser/reflect.go index 0822610..b4390f2 100644 --- a/parser/reflect.go +++ b/parser/reflect.go @@ -37,7 +37,7 @@ type methodMap map[string][]*model.MethodSpec func ProcessSource(paths *model.RevelContainer) (_ *model.SourceInfo, compileError error) { pc := &processContainer{paths: paths} for _, root := range paths.CodePaths { - rootImportPath := importPathFromPath(root) + rootImportPath := importPathFromPath(root, paths.BasePath) if rootImportPath == "" { utils.Logger.Info("Skipping empty code path", "path", root) continue diff --git a/revel/build.go b/revel/build.go index 71f1409..352fc0f 100644 --- a/revel/build.go +++ b/revel/build.go @@ -69,7 +69,9 @@ func buildApp(c *model.CommandConfig) (err error) { return } - buildSafetyCheck(destPath) + if err = buildSafetyCheck(destPath); err != nil { + return + } // Ensure the application can be built, this generates the main file app, err := harness.Build(c, revel_paths) diff --git a/revel/package.go b/revel/package.go index 963d62c..8967258 100644 --- a/revel/package.go +++ b/revel/package.go @@ -86,7 +86,9 @@ func packageApp(c *model.CommandConfig) (err error) { } c.Build.TargetPath = tmpDir c.Build.CopySource = c.Package.CopySource - buildApp(c) + if err = buildApp(c); err != nil { + return + } // Create the zip file.