Added a version file to revel/cmd

Updated import path detection to make it smarter. You can now use absolute paths etc..
This commit is contained in:
NotZippy
2018-09-22 13:37:27 -07:00
parent 69e59efb14
commit 7a4e741d1c
11 changed files with 173 additions and 68 deletions

View File

@@ -1,5 +1,24 @@
package model 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 ( type (
// The Revel command type // The Revel command type
COMMAND int COMMAND int
@@ -28,13 +47,13 @@ type (
// The build command // The build command
Build struct { Build struct {
TargetPath string `short:"t" long:"target-path" description:"Path to target folder. Folder will be completely deleted if it exists" required:"true"` 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"` 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"` CopySource bool `short:"s" long:"include-source" description:"Copy the source code as well"`
} `command:"build"` } `command:"build"`
// The run command // The run command
Run struct { 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"` 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"` 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"` 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 // The package command
Package struct { Package struct {
Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` 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"` CopySource bool `short:"s" long:"include-source" description:"Copy the source code as well"`
} `command:"package"` } `command:"package"`
// The clean command // The clean command
Clean struct { 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"` } `command:"clean"`
// The test command // The test command
Test struct { Test struct {
Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` 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"` Function string `short:"f" long:"suite-function" description:"The suite.function"`
} `command:"test"` } `command:"test"`
// The version command // The version command
@@ -61,3 +80,59 @@ type (
} `command:"version"` } `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)
}

View File

@@ -37,7 +37,7 @@ func init() {
// 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 { func updateBuildConfig(c *model.CommandConfig, args []string) bool {
c.Index = BUILD c.Index = model.BUILD
if len(args) < 2 { if len(args) < 2 {
fmt.Fprintf(os.Stderr, "%s\n%s", cmdBuild.UsageLine, cmdBuild.Long) fmt.Fprintf(os.Stderr, "%s\n%s", cmdBuild.UsageLine, cmdBuild.Long)
return false return false
@@ -52,8 +52,7 @@ func updateBuildConfig(c *model.CommandConfig, args []string) bool {
// 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) { func buildApp(c *model.CommandConfig) {
c.ImportPath = c.Build.ImportPath appImportPath, destPath, mode := c.ImportPath, c.Build.TargetPath, DefaultRunMode
appImportPath, destPath, mode := c.Build.ImportPath, c.Build.TargetPath, DefaultRunMode
if len(c.Build.Mode) > 0 { if len(c.Build.Mode) > 0 {
mode = c.Build.Mode mode = c.Build.Mode
} }

View File

@@ -36,7 +36,7 @@ func init() {
// Update the clean command configuration, using old method // Update the clean command configuration, using old method
func updateCleanConfig(c *model.CommandConfig, args []string) bool { func updateCleanConfig(c *model.CommandConfig, args []string) bool {
c.Index = CLEAN c.Index = model.CLEAN
if len(args) == 0 { if len(args) == 0 {
fmt.Fprintf(os.Stderr, cmdClean.Long) fmt.Fprintf(os.Stderr, cmdClean.Long)
return false return false
@@ -47,8 +47,6 @@ func updateCleanConfig(c *model.CommandConfig, args []string) bool {
// Clean the source directory of generated files // Clean the source directory of generated files
func cleanApp(c *model.CommandConfig) { func cleanApp(c *model.CommandConfig) {
c.ImportPath = c.Clean.ImportPath
appPkg, err := build.Import(c.ImportPath, "", build.FindOnly) appPkg, err := build.Import(c.ImportPath, "", build.FindOnly)
if err != nil { if err != nil {
utils.Logger.Fatal("Abort: Failed to find import path:", "error", err) utils.Logger.Fatal("Abort: Failed to find import path:", "error", err)

View File

@@ -45,7 +45,7 @@ func init() {
// 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 { func updateNewConfig(c *model.CommandConfig, args []string) bool {
c.Index = NEW c.Index = model.NEW
if len(args) == 0 { if len(args) == 0 {
fmt.Fprintf(os.Stderr, cmdNew.Long) fmt.Fprintf(os.Stderr, cmdNew.Long)
return false return false
@@ -61,7 +61,6 @@ func updateNewConfig(c *model.CommandConfig, args []string) bool {
// Call to create a new application // Call to create a new application
func newApp(c *model.CommandConfig) { func newApp(c *model.CommandConfig) {
// check for proper args by count // check for proper args by count
c.ImportPath = c.New.ImportPath
c.SkeletonPath = c.New.Skeleton c.SkeletonPath = c.New.Skeleton
// Check for an existing folder so we dont clober it // 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) fmt.Fprintln(os.Stdout, "Your application is ready:\n ", c.AppPath)
// Check to see if it should be run right off // Check to see if it should be run right off
if c.New.Run { if c.New.Run {
c.Run.ImportPath = c.ImportPath
runApp(c) runApp(c)
} else { } 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)

View File

@@ -39,7 +39,7 @@ func init() {
// 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 { func updatePackageConfig(c *model.CommandConfig, args []string) bool {
c.Index = PACAKAGE c.Index = model.PACKAGE
if len(args) == 0 { if len(args) == 0 {
fmt.Fprintf(os.Stderr, cmdPackage.Long) fmt.Fprintf(os.Stderr, cmdPackage.Long)
return false return false
@@ -60,7 +60,7 @@ func packageApp(c *model.CommandConfig) {
mode = c.Package.Mode mode = c.Package.Mode
} }
appImportPath := c.Package.ImportPath appImportPath := c.ImportPath
revel_paths := model.NewRevelPaths(mode, appImportPath, "", model.DoNothingRevelCallback) revel_paths := model.NewRevelPaths(mode, appImportPath, "", model.DoNothingRevelCallback)
// Remove the archive if it already exists. // Remove the archive if it already exists.
@@ -75,7 +75,6 @@ func packageApp(c *model.CommandConfig) {
utils.PanicOnError(err, "Failed to get temp dir") utils.PanicOnError(err, "Failed to get temp dir")
// Build expects the command the build to contain the proper data // Build expects the command the build to contain the proper data
c.Build.ImportPath = appImportPath
if len(c.Package.Mode) >= 0 { if len(c.Package.Mode) >= 0 {
c.Build.Mode = c.Package.Mode c.Build.Mode = c.Package.Mode
} }

View File

@@ -52,16 +52,6 @@ func (cmd *Command) Name() string {
return name return name
} }
// The constants
const (
NEW model.COMMAND = iota +1
RUN
BUILD
PACAKAGE
CLEAN
TEST
VERSION
)
// The commands // The commands
var commands = []*Command{ var commands = []*Command{
nil, // Safety net, prevent missing index from running nil, // Safety net, prevent missing index from running
@@ -113,19 +103,19 @@ func main() {
} else { } else {
switch parser.Active.Name { switch parser.Active.Name {
case "new": case "new":
c.Index = NEW c.Index = model.NEW
case "run": case "run":
c.Index = RUN c.Index = model.RUN
case "build": case "build":
c.Index = BUILD c.Index = model.BUILD
case "package": case "package":
c.Index = PACAKAGE c.Index = model.PACKAGE
case "clean": case "clean":
c.Index = CLEAN c.Index = model.CLEAN
case "test": case "test":
c.Index = TEST c.Index = model.TEST
case "version": case "version":
c.Index = VERSION c.Index = model.VERSION
} }
} }
} }
@@ -136,10 +126,18 @@ func main() {
} else { } else {
utils.InitLogger(wd, logger.LvlWarn) 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) println("Revel executing:", commands[c.Index].Short)
// checking and setting go paths // checking and setting go paths
initGoPaths(c) initGoPaths(c)
commands[c.Index].RunWith(c) commands[c.Index].RunWith(c)
@@ -292,7 +290,10 @@ func initGoPaths(c *model.CommandConfig) {
} }
if len(c.SrcRoot) == 0 { 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 // set go src path

View File

@@ -101,7 +101,7 @@ func updateRunConfig(c *model.CommandConfig, args []string) bool {
case 0: case 0:
return false return false
} }
c.Index = RUN c.Index = model.RUN
return true return true
} }
@@ -109,9 +109,8 @@ func runApp(c *model.CommandConfig) {
if c.Run.Mode == "" { if c.Run.Mode == "" {
c.Run.Mode = "dev" 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 != "" { if c.Run.Port != "" {
port, err := strconv.Atoi(c.Run.Port) port, err := strconv.Atoi(c.Run.Port)
if err != nil { if err != nil {

View File

@@ -54,7 +54,7 @@ func init() {
// 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 { func updateTestConfig(c *model.CommandConfig, args []string) bool {
c.Index = TEST c.Index = model.TEST
// The full test runs // The full test runs
// revel test <import path> (run mode) (suite(.function)) // revel test <import path> (run mode) (suite(.function))
if len(args) < 1 { if len(args) < 1 {
@@ -78,10 +78,9 @@ func testApp(c *model.CommandConfig) {
if c.Test.Mode != "" { if c.Test.Mode != "" {
mode = c.Test.Mode mode = c.Test.Mode
} }
c.ImportPath = c.Test.ImportPath
// Find and parse app.conf // 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. // Ensure that the testrunner is loaded in this mode.
// todo checkTestRunner() // todo checkTestRunner()

View File

@@ -20,6 +20,7 @@ import (
"io/ioutil" "io/ioutil"
"path/filepath" "path/filepath"
"github.com/revel/cmd/utils" "github.com/revel/cmd/utils"
"github.com/revel/cmd"
) )
var cmdVersion = &Command{ var cmdVersion = &Command{
@@ -40,40 +41,60 @@ func init() {
// Displays the version of go and Revel // Displays the version of go and Revel
func versionApp(c *model.CommandConfig) { func versionApp(c *model.CommandConfig) {
revelPkg, err := build.Import(model.RevelImportPath, c.Version.ImportPath, build.FindOnly)
if err != nil { var (
utils.Logger.Errorf("Failed to find Revel with error:", "error", err) 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)
} }
utils.Logger.Info("Fullpath to revel", revelPkg.Dir) fmt.Println("\nRevel Framework")
fset := token.NewFileSet() // positions are relative to fset
version, err := ioutil.ReadFile(filepath.Join(revelPkg.Dir,"version.go"))
if err != nil { if err != nil {
utils.Logger.Errorf("Failed to find Revel version:", "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
// Parse src but stop after processing the imports. version, err := ioutil.ReadFile(filepath.Join(revelPkg.Dir, "version.go"))
f, err := parser.ParseFile(fset, "", version, parser.ParseComments) if err != nil {
if err != nil { utils.Logger.Errorf("Failed to find Revel version:", "error", err)
utils.Logger.Errorf("Failed to parse Revel version error:", "error", err)
}
// 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 // 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) // Print the imports from the file's AST.
r := spec.Values[0].(*ast.BasicLit) for _, s := range f.Decls {
fmt.Printf("Revel %s = %s\n",spec.Names[0].Name,r.Value) 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) fmt.Printf("\n %s %s/%s\n\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
} }

16
version.go Normal file
View File

@@ -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"
)

View File

@@ -12,7 +12,7 @@ import (
"github.com/revel/cmd/model" "github.com/revel/cmd/model"
"github.com/revel/cmd/utils" "github.com/revel/cmd/utils"
"gopkg.in/fsnotify.v1" "gopkg.in/fsnotify/fsnotify.v1"
"time" "time"
) )