Initial rewrite of revel/cmd to provide vendor support and enhanced CLI options

This commit is contained in:
NotZippy
2018-09-13 13:21:10 -07:00
parent d2ac018544
commit d0baaeb9e9
40 changed files with 4435 additions and 1125 deletions

View File

@@ -5,70 +5,86 @@
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/revel/cmd/harness"
"github.com/revel/revel"
"github.com/revel/cmd/model"
"go/build"
"github.com/revel/cmd/utils"
"fmt"
)
var cmdBuild = &Command{
UsageLine: "build [import path] [target path] [run mode]",
UsageLine: "build -i [import path] -t [target path] -r [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:
revel build github.com/revel/examples/chat /tmp/chat
revel build -a github.com/revel/examples/chat -t /tmp/chat
`,
}
func init() {
cmdBuild.Run = buildApp
cmdBuild.RunWith = buildApp
cmdBuild.UpdateConfig = updateBuildConfig
}
func buildApp(args []string) {
// The update config updates the configuration command so that it can run
func updateBuildConfig(c *model.CommandConfig, args []string) (bool) {
c.Index = BUILD
if len(args) < 2 {
fmt.Fprintf(os.Stderr, "%s\n%s", cmdBuild.UsageLine, cmdBuild.Long)
return
return false
}
c.Build.ImportPath = args[0]
c.Build.TargetPath = args[1]
if len(args)>2 {
c.Build.Mode = args[1]
}
return true
}
// 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
if len(c.Build.Mode) > 0 {
mode = c.Build.Mode
}
appImportPath, destPath, mode := args[0], args[1], DefaultRunMode
if len(args) >= 3 {
mode = args[2]
}
// Convert target to absolute path
destPath, _ = filepath.Abs(destPath)
if !revel.Initialized {
revel.Init(mode, appImportPath, "")
}
revel_paths := model.NewRevelPaths(mode, appImportPath, "", model.DoNothingRevelCallback)
// First, verify that it is either already empty or looks like a previous
// build (to avoid clobbering anything)
if exists(destPath) && !empty(destPath) && !exists(filepath.Join(destPath, "run.sh")) {
errorf("Abort: %s exists and does not look like a build directory.", destPath)
if utils.Exists(destPath) && !utils.Empty(destPath) && !utils.Exists(filepath.Join(destPath, "run.sh")) {
utils.Logger.Errorf("Abort: %s exists and does not look like a build directory.", destPath)
return
}
if err := os.RemoveAll(destPath); err != nil && !os.IsNotExist(err) {
revel.RevelLog.Fatal("Remove all error","error", err)
utils.Logger.Error("Remove all error","error", err)
return
}
if err := os.MkdirAll(destPath, 0777); err != nil {
revel.RevelLog.Fatal("makedir error","error",err)
utils.Logger.Error("makedir error","error",err)
return
}
app, reverr := harness.Build()
panicOnError(reverr, "Failed to build")
app, reverr := harness.Build(c,revel_paths)
if reverr!=nil {
utils.Logger.Error("Failed to build application","error",reverr)
return
}
// Included are:
// - run scripts
@@ -79,15 +95,15 @@ func buildApp(args []string) {
// Revel and the app are in a directory structure mirroring import path
srcPath := filepath.Join(destPath, "src")
destBinaryPath := filepath.Join(destPath, filepath.Base(app.BinaryPath))
tmpRevelPath := filepath.Join(srcPath, filepath.FromSlash(revel.RevelImportPath))
mustCopyFile(destBinaryPath, app.BinaryPath)
mustChmod(destBinaryPath, 0755)
_ = mustCopyDir(filepath.Join(tmpRevelPath, "conf"), filepath.Join(revel.RevelPath, "conf"), nil)
_ = mustCopyDir(filepath.Join(tmpRevelPath, "templates"), filepath.Join(revel.RevelPath, "templates"), nil)
_ = mustCopyDir(filepath.Join(srcPath, filepath.FromSlash(appImportPath)), revel.BasePath, nil)
tmpRevelPath := filepath.Join(srcPath, filepath.FromSlash(model.RevelImportPath))
utils.MustCopyFile(destBinaryPath, app.BinaryPath)
utils.MustChmod(destBinaryPath, 0755)
_ = utils.MustCopyDir(filepath.Join(tmpRevelPath, "conf"), filepath.Join(revel_paths.RevelPath, "conf"), nil)
_ = utils.MustCopyDir(filepath.Join(tmpRevelPath, "templates"), filepath.Join(revel_paths.RevelPath, "templates"), nil)
_ = utils.MustCopyDir(filepath.Join(srcPath, filepath.FromSlash(appImportPath)), revel_paths.BasePath, nil)
// Find all the modules used and copy them over.
config := revel.Config.Raw()
config := revel_paths.Config.Raw()
modulePaths := make(map[string]string) // import path => filesystem path
for _, section := range config.Sections() {
options, _ := config.SectionOptions(section)
@@ -99,32 +115,46 @@ func buildApp(args []string) {
if moduleImportPath == "" {
continue
}
modulePath, err := revel.ResolveImportPath(moduleImportPath)
modPkg, err := build.Import(c.ImportPath, revel_paths.RevelPath, build.FindOnly)
if err != nil {
revel.RevelLog.Fatalf("Failed to load module %s: %s", key[len("module."):], err)
utils.Logger.Fatalf("Failed to load module %s (%s): %s", key[len("module."):], c.ImportPath, err)
}
modulePaths[moduleImportPath] = modulePath
modulePaths[moduleImportPath] = modPkg.Dir
}
}
for importPath, fsPath := range modulePaths {
_ = mustCopyDir(filepath.Join(srcPath, importPath), fsPath, nil)
_ = utils.MustCopyDir(filepath.Join(srcPath, importPath), fsPath, nil)
}
tmplData, runShPath := map[string]interface{}{
tmplData := map[string]interface{}{
"BinName": filepath.Base(app.BinaryPath),
"ImportPath": appImportPath,
"Mode": mode,
}, filepath.Join(destPath, "run.sh")
}
mustRenderTemplate(
runShPath,
filepath.Join(revel.RevelPath, "..", "cmd", "revel", "package_run.sh.template"),
tmplData)
mustChmod(runShPath, 0755)
mustRenderTemplate(
utils.MustGenerateTemplate(
filepath.Join(destPath, "run.sh"),
PACKAGE_RUN_SH,
tmplData,
)
utils.MustChmod(filepath.Join(destPath, "run.sh"), 0755)
utils.MustGenerateTemplate(
filepath.Join(destPath, "run.bat"),
filepath.Join(revel.RevelPath, "..", "cmd", "revel", "package_run.bat.template"),
tmplData)
PACKAGE_RUN_BAT,
tmplData,
)
fmt.Println("Your application has been built in:", destPath)
}
const PACKAGE_RUN_SH = `#!/bin/sh
SCRIPTPATH=$(cd "$(dirname "$0")"; pwd)
"$SCRIPTPATH/{{.BinName}}" -importPath {{.ImportPath}} -srcPath "$SCRIPTPATH/src" -runMode {{.Mode}}
`
const PACKAGE_RUN_BAT = `@echo off
{{.BinName}} -importPath {{.ImportPath}} -srcPath "%CD%\src" -runMode {{.Mode}}
`