diff --git a/model/command_config.go b/model/command_config.go index 7486c67b..a3ccc4da 100644 --- a/model/command_config.go +++ b/model/command_config.go @@ -1,5 +1,24 @@ package model +// The constants +import ( + "go/build" + "os" + "path/filepath" + "strings" + "github.com/revel/cmd/utils" +) + +const ( + NEW COMMAND = iota + 1 + RUN + BUILD + PACKAGE + CLEAN + TEST + VERSION +) + type ( // The Revel command type COMMAND int @@ -28,13 +47,13 @@ type ( // The build command Build struct { TargetPath string `short:"t" long:"target-path" description:"Path to target folder. Folder will be completely deleted if it exists" required:"true"` - ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" required:"true"` + ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" ` 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"` } `command:"build"` // The run command Run struct { - ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" required:"true"` + ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" ` Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` Port string `short:"p" long:"port" 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"` @@ -42,17 +61,17 @@ type ( // The package command Package struct { Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` - ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" required:"true"` + ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" ` CopySource bool `short:"s" long:"include-source" description:"Copy the source code as well"` } `command:"package"` // The clean command Clean struct { - ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" required:"true"` + ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" ` } `command:"clean"` // The test command Test struct { Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` - ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" required:"true"` + ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" ` Function string `short:"f" long:"suite-function" description:"The suite.function"` } `command:"test"` // The version command @@ -61,3 +80,59 @@ type ( } `command:"version"` } ) + +// Updates the import path depending on the command +func (c *CommandConfig) UpdateImportPath() bool { + var importPath string + required := true + switch c.Index { + case NEW: + importPath = c.New.ImportPath + case RUN: + importPath = c.Run.ImportPath + case BUILD: + importPath = c.Build.ImportPath + case PACKAGE: + importPath = c.Package.ImportPath + case CLEAN: + importPath = c.Clean.ImportPath + case TEST: + importPath = c.Test.ImportPath + case VERSION: + importPath = c.Version.ImportPath + required = false + } + + if len(importPath) == 0 || filepath.IsAbs(importPath) || importPath[0] == '.' { + // Try to determine the import path from the GO paths and the command line + currentPath, err := os.Getwd() + if len(importPath) > 0 { + if importPath[0] == '.' { + // For a relative path + importPath = filepath.Join(currentPath, importPath) + } + // For an absolute path + currentPath, _ = filepath.Abs(importPath) + + } + 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) { + 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/" { + importPath = importPath[4:] + } else if importPath == "src" { + importPath = "" + } + utils.Logger.Info("Updated import path", "path", importPath) + } + } + } + } + + c.ImportPath = importPath + utils.Logger.Info("Returned import path", "path", importPath) + return (len(importPath) > 0 || !required) +} diff --git a/revel/build.go b/revel/build.go index 589f0984..c9a73874 100644 --- a/revel/build.go +++ b/revel/build.go @@ -37,7 +37,7 @@ func init() { // The update config updates the configuration command so that it can run func updateBuildConfig(c *model.CommandConfig, args []string) bool { - c.Index = BUILD + c.Index = model.BUILD if len(args) < 2 { fmt.Fprintf(os.Stderr, "%s\n%s", cmdBuild.UsageLine, cmdBuild.Long) return false @@ -52,8 +52,7 @@ func updateBuildConfig(c *model.CommandConfig, args []string) bool { // The main entry point to build application from command line func buildApp(c *model.CommandConfig) { - c.ImportPath = c.Build.ImportPath - appImportPath, destPath, mode := c.Build.ImportPath, c.Build.TargetPath, DefaultRunMode + appImportPath, destPath, mode := c.ImportPath, c.Build.TargetPath, DefaultRunMode if len(c.Build.Mode) > 0 { mode = c.Build.Mode } diff --git a/revel/clean.go b/revel/clean.go index 5eec24b8..a4aa9e15 100644 --- a/revel/clean.go +++ b/revel/clean.go @@ -36,7 +36,7 @@ func init() { // Update the clean command configuration, using old method func updateCleanConfig(c *model.CommandConfig, args []string) bool { - c.Index = CLEAN + c.Index = model.CLEAN if len(args) == 0 { fmt.Fprintf(os.Stderr, cmdClean.Long) return false @@ -47,8 +47,6 @@ func updateCleanConfig(c *model.CommandConfig, args []string) bool { // Clean the source directory of generated files func cleanApp(c *model.CommandConfig) { - c.ImportPath = c.Clean.ImportPath - appPkg, err := build.Import(c.ImportPath, "", build.FindOnly) if err != nil { utils.Logger.Fatal("Abort: Failed to find import path:", "error", err) diff --git a/revel/new.go b/revel/new.go index f6489128..15116fd1 100644 --- a/revel/new.go +++ b/revel/new.go @@ -45,7 +45,7 @@ func init() { // Called when unable to parse the command line automatically and assumes an old launch func updateNewConfig(c *model.CommandConfig, args []string) bool { - c.Index = NEW + c.Index = model.NEW if len(args) == 0 { fmt.Fprintf(os.Stderr, cmdNew.Long) return false @@ -61,7 +61,6 @@ func updateNewConfig(c *model.CommandConfig, args []string) bool { // Call to create a new application func newApp(c *model.CommandConfig) { // check for proper args by count - c.ImportPath = c.New.ImportPath c.SkeletonPath = c.New.Skeleton // Check for an existing folder so we dont clober it @@ -125,7 +124,6 @@ func newApp(c *model.CommandConfig) { fmt.Fprintln(os.Stdout, "Your application is ready:\n ", c.AppPath) // Check to see if it should be run right off if c.New.Run { - c.Run.ImportPath = c.ImportPath runApp(c) } else { fmt.Fprintln(os.Stdout, "\nYou can run it with:\n revel run -a ", c.ImportPath) diff --git a/revel/package.go b/revel/package.go index f5a0a7ca..c8b13143 100644 --- a/revel/package.go +++ b/revel/package.go @@ -39,7 +39,7 @@ func init() { // Called when unable to parse the command line automatically and assumes an old launch func updatePackageConfig(c *model.CommandConfig, args []string) bool { - c.Index = PACAKAGE + c.Index = model.PACKAGE if len(args) == 0 { fmt.Fprintf(os.Stderr, cmdPackage.Long) return false @@ -60,7 +60,7 @@ func packageApp(c *model.CommandConfig) { mode = c.Package.Mode } - appImportPath := c.Package.ImportPath + appImportPath := c.ImportPath revel_paths := model.NewRevelPaths(mode, appImportPath, "", model.DoNothingRevelCallback) // Remove the archive if it already exists. @@ -75,7 +75,6 @@ func packageApp(c *model.CommandConfig) { utils.PanicOnError(err, "Failed to get temp dir") // Build expects the command the build to contain the proper data - c.Build.ImportPath = appImportPath if len(c.Package.Mode) >= 0 { c.Build.Mode = c.Package.Mode } diff --git a/revel/revel.go b/revel/revel.go index ae967d53..e0cc6a71 100644 --- a/revel/revel.go +++ b/revel/revel.go @@ -52,16 +52,6 @@ func (cmd *Command) Name() string { return name } -// The constants -const ( - NEW model.COMMAND = iota +1 - RUN - BUILD - PACAKAGE - CLEAN - TEST - VERSION -) // The commands var commands = []*Command{ nil, // Safety net, prevent missing index from running @@ -113,19 +103,19 @@ func main() { } else { switch parser.Active.Name { case "new": - c.Index = NEW + c.Index = model.NEW case "run": - c.Index = RUN + c.Index = model.RUN case "build": - c.Index = BUILD + c.Index = model.BUILD case "package": - c.Index = PACAKAGE + c.Index = model.PACKAGE case "clean": - c.Index = CLEAN + c.Index = model.CLEAN case "test": - c.Index = TEST + c.Index = model.TEST case "version": - c.Index = VERSION + c.Index = model.VERSION } } } @@ -136,10 +126,18 @@ func main() { } else { utils.InitLogger(wd, logger.LvlWarn) } + + if c.Index==0 { + utils.Logger.Fatal("Unknown command line arguements") + } + if !c.UpdateImportPath() { + utils.Logger.Fatal("Unable to determine application path") + } println("Revel executing:", commands[c.Index].Short) // checking and setting go paths initGoPaths(c) + commands[c.Index].RunWith(c) @@ -292,7 +290,10 @@ func initGoPaths(c *model.CommandConfig) { } if len(c.SrcRoot) == 0 { - utils.Logger.Fatal("Abort: could not create a Revel application outside of GOPATH.") + if c.Index != model.VERSION { + utils.Logger.Fatal("Abort: could not create a Revel application outside of GOPATH.") + } + return } // set go src path diff --git a/revel/run.go b/revel/run.go index 4c4cb5f9..04f22ac5 100644 --- a/revel/run.go +++ b/revel/run.go @@ -101,7 +101,7 @@ func updateRunConfig(c *model.CommandConfig, args []string) bool { case 0: return false } - c.Index = RUN + c.Index = model.RUN return true } @@ -109,9 +109,8 @@ func runApp(c *model.CommandConfig) { if c.Run.Mode == "" { c.Run.Mode = "dev" } - c.ImportPath = c.Run.ImportPath - revel_path := model.NewRevelPaths(c.Run.Mode, c.Run.ImportPath, "", model.DoNothingRevelCallback) + revel_path := model.NewRevelPaths(c.Run.Mode, c.ImportPath, "", model.DoNothingRevelCallback) if c.Run.Port != "" { port, err := strconv.Atoi(c.Run.Port) if err != nil { diff --git a/revel/test.go b/revel/test.go index 1b1f022c..9f1d920f 100644 --- a/revel/test.go +++ b/revel/test.go @@ -54,7 +54,7 @@ func init() { // Called to update the config command with from the older stype func updateTestConfig(c *model.CommandConfig, args []string) bool { - c.Index = TEST + c.Index = model.TEST // The full test runs // revel test (run mode) (suite(.function)) if len(args) < 1 { @@ -78,10 +78,9 @@ func testApp(c *model.CommandConfig) { if c.Test.Mode != "" { mode = c.Test.Mode } - c.ImportPath = c.Test.ImportPath // Find and parse app.conf - revel_path := model.NewRevelPaths(mode, c.Test.ImportPath, "", model.DoNothingRevelCallback) + revel_path := model.NewRevelPaths(mode, c.ImportPath, "", model.DoNothingRevelCallback) // Ensure that the testrunner is loaded in this mode. // todo checkTestRunner() diff --git a/revel/version.go b/revel/version.go index 109545c0..7c7d1b11 100644 --- a/revel/version.go +++ b/revel/version.go @@ -20,6 +20,7 @@ import ( "io/ioutil" "path/filepath" "github.com/revel/cmd/utils" + "github.com/revel/cmd" ) var cmdVersion = &Command{ @@ -40,40 +41,60 @@ func init() { // Displays the version of go and Revel func versionApp(c *model.CommandConfig) { - revelPkg, err := build.Import(model.RevelImportPath, c.Version.ImportPath, build.FindOnly) - if err != nil { - utils.Logger.Errorf("Failed to find Revel with error:", "error", err) - } - utils.Logger.Info("Fullpath to revel", revelPkg.Dir) - fset := token.NewFileSet() // positions are relative to fset - - version, err := ioutil.ReadFile(filepath.Join(revelPkg.Dir,"version.go")) - if err != nil { - utils.Logger.Errorf("Failed to find Revel version:", "error", err) + var ( + revelPkg *build.Package + err error + ) + if len(c.ImportPath)>0 { + appPkg, err := build.Import(c.ImportPath, "", build.FindOnly) + if err != nil { + utils.Logger.Fatal("Failed to import " + c.ImportPath + " with error:", "error", err) + } + revelPkg, err = build.Import(model.RevelImportPath, appPkg.Dir, build.FindOnly) + } else { + revelPkg, err = build.Import(model.RevelImportPath, "" , build.FindOnly) } - // Parse src but stop after processing the imports. - f, err := parser.ParseFile(fset, "", version, parser.ParseComments) + fmt.Println("\nRevel Framework") if err != nil { - utils.Logger.Errorf("Failed to parse Revel version error:", "error", err) - } + utils.Logger.Info("Failed to find Revel in GOPATH with error:", "error", err, "gopath", build.Default.GOPATH) + fmt.Println("Information not available (not on GOPATH)") + } else { + utils.Logger.Info("Fullpath to revel", revelPkg.Dir) + fset := token.NewFileSet() // positions are relative to fset - // Print the imports from the file's AST. - for _, s := range f.Decls { - genDecl, ok := s.(*ast.GenDecl) - if !ok { - continue + version, err := ioutil.ReadFile(filepath.Join(revelPkg.Dir, "version.go")) + if err != nil { + utils.Logger.Errorf("Failed to find Revel version:", "error", err) } - if genDecl.Tok != token.CONST { - continue + + // Parse src but stop after processing the imports. + f, err := parser.ParseFile(fset, "", version, parser.ParseComments) + if err != nil { + utils.Logger.Errorf("Failed to parse Revel version error:", "error", err) } - for _, a := range genDecl.Specs { - spec := a.(*ast.ValueSpec) - r := spec.Values[0].(*ast.BasicLit) - fmt.Printf("Revel %s = %s\n",spec.Names[0].Name,r.Value) + + // Print the imports from the file's AST. + for _, s := range f.Decls { + genDecl, ok := s.(*ast.GenDecl) + if !ok { + continue + } + if genDecl.Tok != token.CONST { + continue + } + for _, a := range genDecl.Specs { + spec := a.(*ast.ValueSpec) + r := spec.Values[0].(*ast.BasicLit) + fmt.Printf("Revel %s = %s\n", spec.Names[0].Name, r.Value) + } } } + fmt.Println("\nRevel Command Utility Tool") + fmt.Println("Version", cmd.Version) + fmt.Println("Build Date", cmd.BuildDate) + fmt.Println("Minimum Go Version", cmd.MinimumGoVersion) fmt.Printf("\n %s %s/%s\n\n", runtime.Version(), runtime.GOOS, runtime.GOARCH) } diff --git a/version.go b/version.go new file mode 100644 index 00000000..3931cfc5 --- /dev/null +++ b/version.go @@ -0,0 +1,16 @@ +// Copyright (c) 2012-2017 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 cmd + +const ( + // Version current Revel Command version + Version = "0.20.0-dev" + + // BuildDate latest commit/release date + BuildDate = "2018-02-06" + + // MinimumGoVersion minimum required Go version for Revel + MinimumGoVersion = ">= go1.8" +) diff --git a/watcher/watcher.go b/watcher/watcher.go index 8df3dbbe..1e341012 100644 --- a/watcher/watcher.go +++ b/watcher/watcher.go @@ -12,7 +12,7 @@ import ( "github.com/revel/cmd/model" "github.com/revel/cmd/utils" - "gopkg.in/fsnotify.v1" + "gopkg.in/fsnotify/fsnotify.v1" "time" )