Merge pull request #159 from notzippy/develop

Patchset for 21
This commit is contained in:
Steve
2018-10-29 16:29:03 -07:00
committed by GitHub
7 changed files with 256 additions and 94 deletions

View File

@@ -1,6 +1,7 @@
{
"GOLANG": {
"ABC":[25, 35, 50, 70],
"ARITY":[5,6,7,8],
"BLOCK_NESTING":[7, 9, 11, 13],
"CYCLO":[20, 30, 45, 60],
"TOO_MANY_IVARS": [20, 25, 40, 45],

View File

@@ -44,6 +44,7 @@ type (
SrcRoot string // The source root
AppPath string // The application path (absolute)
AppName string // The application name
Vendored bool // True if the application is vendored
PackageResolver func(pkgName string) error // a packge 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"`
// The new command
@@ -87,6 +88,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"`
} `command:"version"`
}
)
@@ -124,7 +126,6 @@ func (c *CommandConfig) UpdateImportPath() error {
}
// For an absolute path
currentPath, _ = filepath.Abs(importPath)
}
if err == nil {
@@ -136,7 +137,10 @@ func (c *CommandConfig) UpdateImportPath() error {
if len(importPath) > 4 && strings.ToLower(importPath[0:4]) == "src/" {
importPath = importPath[4:]
} else if importPath == "src" {
return fmt.Errorf("Invlaid import path, working dir is in GOPATH root")
if c.Index != VERSION {
return fmt.Errorf("Invlaid import path, working dir is in GOPATH root")
}
importPath = ""
}
utils.Logger.Info("Updated import path", "path", importPath)
}
@@ -167,18 +171,19 @@ func (c *CommandConfig) UpdateImportPath() error {
// Used to initialize the package resolver
func (c *CommandConfig) InitPackageResolver() {
useVendor := utils.DirExists(filepath.Join(c.AppPath, "vendor"))
c.Vendored = utils.DirExists(filepath.Join(c.AppPath, "vendor"))
if c.Index == NEW && c.New.Vendored {
useVendor = true
c.Vendored = true
}
utils.Logger.Info("InitPackageResolver", "useVendor", useVendor, "path", c.AppPath)
utils.Logger.Info("InitPackageResolver", "useVendor", c.Vendored, "path", c.AppPath)
var (
depPath string
err error
)
if useVendor {
if c.Vendored {
utils.Logger.Info("Vendor folder detected, scanning for deps in path")
depPath, err = exec.LookPath("dep")
if err != nil {
@@ -194,8 +199,8 @@ func (c *CommandConfig) InitPackageResolver() {
//useVendor := utils.DirExists(filepath.Join(c.AppPath, "vendor"))
var getCmd *exec.Cmd
utils.Logger.Info("Request for package ", "package", pkgName, "use vendor", useVendor)
if useVendor {
utils.Logger.Info("Request for package ", "package", pkgName, "use vendor", c.Vendored)
if c.Vendored {
utils.Logger.Info("Using dependency manager to import package", "package", pkgName)
if depPath == "" {
@@ -206,7 +211,15 @@ func (c *CommandConfig) InitPackageResolver() {
utils.Logger.Error("Missing package", "package", pkgName)
return fmt.Errorf("Missing package %s", pkgName)
}
getCmd = exec.Command(depPath, "ensure", "-add", pkgName)
// Check to see if the package exists locally
_, err := build.Import(pkgName, c.AppPath, build.FindOnly)
if err != nil {
getCmd = exec.Command(depPath, "ensure", "-add", pkgName)
} else {
getCmd = exec.Command(depPath, "ensure", "-update", pkgName)
}
} 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)
@@ -225,6 +238,7 @@ func (c *CommandConfig) InitPackageResolver() {
// lookup and set Go related variables
func (c *CommandConfig) InitGoPaths() {
utils.Logger.Info("InitGoPaths")
// lookup go path
c.GoPath = build.Default.GOPATH
if c.GoPath == "" {

View File

@@ -92,6 +92,7 @@ func (w *WrappedRevelCallback) PackageResolver(pkgName string) error {
// RevelImportPath Revel framework import path
var RevelImportPath = "github.com/revel/revel"
var 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.
@@ -226,7 +227,7 @@ func (rp *RevelContainer) loadModules(callback RevelCallback) (err error) {
modulePath, err := rp.ResolveImportPath(moduleImportPath)
if err != nil {
utils.Logger.Info("Missing module ", "module", 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 {

View File

@@ -13,6 +13,8 @@ type Version struct {
Minor int
Maintenance int
Suffix string
BuildDate string
MinGoVersion string
}
// The compatibility list
@@ -27,6 +29,13 @@ var versionRegExp = regexp.MustCompile(`([^\d]*)?([0-9]*)\.([0-9]*)(\.([0-9]*))?
// 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) {
parsedResult := versionRegExp.FindAllStringSubmatch(version, -1)
if len(parsedResult) != 1 {
err = errors.Errorf("Invalid version %s", version)
@@ -36,7 +45,7 @@ func ParseVersion(version string) (v *Version, err error) {
err = errors.Errorf("Invalid version %s", version)
return
}
v = &Version{}
v.Prefix = parsedResult[0][1]
v.Major = v.intOrZero(parsedResult[0][2])
v.Minor = v.intOrZero(parsedResult[0][3])
@@ -45,7 +54,6 @@ func ParseVersion(version string) (v *Version, err error) {
return
}
// Returns 0 or an int value for the string, errors are returned as 0
func (v *Version) intOrZero(input string) (value int) {
if input != "" {
@@ -105,6 +113,12 @@ func (v *Version) Newer(o *Version) bool {
}
// Convert the version to a string
func (v *Version) String() 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
func (v *Version) String() string {
return fmt.Sprintf("Version: %s%d.%d.%d%s\nBuild Date: %s\n Minimium Go Version: %s",
v.Prefix, v.Major, v.Minor, v.Maintenance, v.Suffix, v.BuildDate, v.MinGoVersion)
}

View File

@@ -16,9 +16,6 @@ import (
"github.com/revel/cmd/model"
"github.com/revel/cmd/utils"
"net/url"
"github.com/kr/pty"
"io"
"bytes"
)
var cmdNew = &Command{
@@ -117,16 +114,11 @@ func newApp(c *model.CommandConfig) (err error) {
getCmd := exec.Command("dep", "ensure", "-v")
utils.CmdInit(getCmd, c.AppPath)
f, err := pty.Start(getCmd);
stdout := new(bytes.Buffer)
io.Copy(io.MultiWriter(stdout, os.Stdout), f)
if err = getCmd.Wait(); err != nil {
}
utils.Logger.Info("Exec:", "args", getCmd.Args, "env", getCmd.Env, "workingdir",getCmd.Dir)
// getOutput, err := getCmd.CombinedOutput()
getOutput, err := getCmd.CombinedOutput()
if err != nil {
return utils.NewBuildIfError(err, stdout.String())
return utils.NewBuildIfError(err, string(getOutput))
}
}
@@ -207,7 +199,7 @@ func setApplicationPath(c *model.CommandConfig) (err error) {
// Set the skeleton path
func setSkeletonPath(c *model.CommandConfig) (err error) {
if len(c.New.SkeletonPath) == 0 {
c.New.SkeletonPath = "git://" + RevelSkeletonsImportPath + ":basic/bootstrap4"
c.New.SkeletonPath = "https://" + RevelSkeletonsImportPath + ":basic/bootstrap4"
}
// First check to see the protocol of the string
@@ -216,7 +208,7 @@ func setSkeletonPath(c *model.CommandConfig) (err error) {
utils.Logger.Info("Detected skeleton path", "path", sp)
switch strings.ToLower(sp.Scheme) {
// TODO Add support for https, http, ftp
// TODO Add support for ftp, sftp, scp ??
case "" :
sp.Scheme="file"
fallthrough
@@ -234,14 +226,13 @@ func setSkeletonPath(c *model.CommandConfig) (err error) {
return fmt.Errorf("Failed to find skeleton in filepath %s %s", fullpath, sp.String())
}
case "git":
fallthrough
case "http":
fallthrough
case "https":
if err := newLoadFromGit(c, sp); err != nil {
return err
}
//case "":
//if err := newLoadFromGo(c, sp); err != nil {
// return err
//}
default:
utils.Logger.Fatal("Unsupported skeleton schema ", "path", c.New.SkeletonPath)

View File

@@ -10,19 +10,30 @@ package main
import (
"fmt"
"runtime"
"github.com/revel/cmd"
"github.com/revel/cmd/model"
"github.com/revel/cmd/utils"
"go/ast"
"go/build"
"go/parser"
"go/token"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
"bytes"
)
type (
// The version container
VersionCommand struct {
Command *model.CommandConfig // The command
revelVersion *model.Version // The Revel framework version
modulesVersion *model.Version // The Revel modules version
cmdVersion *model.Version // The tool version
}
)
var cmdVersion = &Command{
@@ -38,12 +49,13 @@ For example:
}
func init() {
cmdVersion.RunWith = versionApp
cmdVersion.UpdateConfig = updateVersionConfig
v := &VersionCommand{}
cmdVersion.UpdateConfig = v.UpdateConfig
cmdVersion.RunWith = v.RunWith
}
// Update the version
func updateVersionConfig(c *model.CommandConfig, args []string) bool {
func (v *VersionCommand) UpdateConfig(c *model.CommandConfig, args []string) bool {
if len(args) > 0 {
c.Version.ImportPath = args[0]
}
@@ -51,71 +63,200 @@ func updateVersionConfig(c *model.CommandConfig, args []string) bool {
}
// Displays the version of go and Revel
func versionApp(c *model.CommandConfig) (err error) {
func (v *VersionCommand) RunWith(c *model.CommandConfig) (err error) {
utils.Logger.Info("Requesting version information", "config", c)
v.Command = c
var revelPath, appPath string
// Update the versions with the local values
v.updateLocalVersions()
appPath, revelPath, err = utils.FindSrcPaths(c.ImportPath, model.RevelImportPath, c.PackageResolver)
if err != nil {
return utils.NewBuildError("Failed to import "+c.ImportPath+" with error:", "error", err)
needsUpdates := true
versionInfo := ""
for x := 0; x < 2 && needsUpdates; x++ {
needsUpdates = false
versionInfo, needsUpdates = v.doRepoCheck(x==0)
}
revelPath = revelPath + model.RevelImportPath
fmt.Println("\nRevel Framework",revelPath, appPath )
if err != nil {
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)")
fmt.Println(versionInfo)
cmd := exec.Command(c.GoCmd, "version")
cmd.Stdout = os.Stdout
if e := cmd.Start(); e != nil {
fmt.Println("Go command error ", e)
} else {
utils.Logger.Info("Fullpath to revel", "dir", revelPath)
fset := token.NewFileSet() // positions are relative to fset
version, err := ioutil.ReadFile(filepath.Join(revelPath, "version.go"))
if err != nil {
utils.Logger.Error("Failed to find Revel version:", "error", err, "path", revelPath)
}
// Parse src but stop after processing the imports.
f, err := parser.ParseFile(fset, "", version, parser.ParseComments)
if err != nil {
return utils.NewBuildError("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
}
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("Compiled By %s %s/%s\n\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
// Extract the goversion detected
if len(c.GoCmd) > 0 {
cmd := exec.Command(c.GoCmd, "version")
cmd.Stdout = os.Stdout
if e := cmd.Start(); e != nil {
fmt.Println("Go command error ", e)
} else {
cmd.Wait()
}
} else {
fmt.Println("Go command not found ")
cmd.Wait()
}
return
}
// Checks the Revel repos for the latest version
func (v *VersionCommand) doRepoCheck(updateLibs bool) (versionInfo string, needsUpdate bool) {
var (
title string
localVersion *model.Version
)
for _, repo := range []string{"revel", "cmd", "modules"} {
versonFromRepo, err := v.versionFromRepo(repo, "", "version.go")
if err != nil {
utils.Logger.Info("Failed to get version from repo", "repo", repo, "error", err)
}
switch repo {
case "revel":
title, repo, localVersion = "Revel Framework", "github.com/revel/revel", v.revelVersion
case "cmd":
title, repo, localVersion = "Revel Cmd", "github.com/revel/cmd/revel", v.cmdVersion
case "modules":
title, repo, localVersion = "Revel Modules", "github.com/revel/modules", v.modulesVersion
}
// Only do an update on the first loop, and if specified to update
shouldUpdate := updateLibs && v.Command.Version.Update
if v.Command.Version.Update {
if localVersion == nil || (versonFromRepo != nil && versonFromRepo.Newer(localVersion)) {
needsUpdate = true
if shouldUpdate {
v.doUpdate(title, repo, localVersion, versonFromRepo)
v.updateLocalVersions()
}
}
}
versionInfo = 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
func (v *VersionCommand) outputVersion(title, repo string, local, remote *model.Version) (output string) {
buffer := &bytes.Buffer{}
remoteVersion := "Unknown"
if remote != nil {
remoteVersion = remote.VersionString()
}
localVersion := "Unknown"
if local != nil {
localVersion = local.VersionString()
}
fmt.Fprintf(buffer, "%s\t:\t%s\t(%s remote master branch)\n", title, localVersion, remoteVersion)
return buffer.String()
}
// Returns the version from the repository
func (v *VersionCommand) versionFromRepo(repoName, branchName, fileName string) (version *model.Version, err error) {
if branchName == "" {
branchName = "master"
}
// Try to download the version of file from the repo, just use an http connection to retrieve the source
// Assuming that the repo is github
fullurl := "https://raw.githubusercontent.com/revel/" + repoName + "/" + branchName + "/" + fileName
resp, err := http.Get(fullurl)
if err != nil {
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
utils.Logger.Info("Got version file", "from", fullurl, "content", string(body))
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)
sourceStream, err := ioutil.ReadFile(filepath.Join(sourcePath, "version.go"))
if err != nil {
return
}
return v.versionFromBytes(sourceStream)
}
// 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
// Parse src but stop after processing the imports.
f, err := parser.ParseFile(fset, "", sourceStream, parser.ParseComments)
if err != nil {
err = utils.NewBuildError("Failed to parse Revel version error:", "error", err)
return
}
version = &model.Version{}
// 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)
switch spec.Names[0].Name {
case "Version":
version.ParseVersion(strings.Replace(r.Value, `"`, "", -1))
case "BuildDate":
version.BuildDate = r.Value
case "MinimumGoVersion":
version.MinGoVersion = r.Value
}
}
}
return
}
// 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
var modulePath, revelPath string
_, revelPath, err := utils.FindSrcPaths(v.Command.ImportPath, model.RevelImportPath, v.Command.PackageResolver)
if err != nil {
utils.Logger.Warn("Unable to extract version information from Revel library", "error,err")
return
}
revelPath = revelPath + model.RevelImportPath
utils.Logger.Info("Fullpath to revel", "dir", revelPath)
v.revelVersion, err = v.versionFromFilepath(revelPath)
if err != nil {
utils.Logger.Warn("Unable to extract version information from Revel", "error,err")
}
_, modulePath, err = utils.FindSrcPaths(v.Command.ImportPath, model.RevelModulesImportPath, v.Command.PackageResolver)
if err != nil {
utils.Logger.Warn("Unable to extract version information from Revel library", "error,err")
return
}
modulePath = modulePath + model.RevelModulesImportPath
v.modulesVersion, err = v.versionFromFilepath(modulePath)
if err != nil {
utils.Logger.Warn("Unable to extract version information from Revel Modules", "error", err)
}
return
}

View File

@@ -6,7 +6,7 @@ package cmd
const (
// Version current Revel Command version
Version = "0.20.2"
Version = "0.21.0-dev"
// BuildDate latest commit/release date
BuildDate = "2018-10-02"