diff --git a/README.md b/README.md
index e2a39d8..1dce3c1 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,6 @@ aah - A secure, flexible, rapid Go web framework.
### News
- * aah CLI
[released](https://github.com/go-aah/tools/releases/latest) and tagged on Jul 06, 2018.
+ * aah CLI
[released](https://github.com/go-aah/tools/releases/latest) and tagged on Jul 08, 2018.
Visit official website https://aahframework.org to learn more about `aah` framework.
diff --git a/aah/aah.go b/aah/aah.go
index f7b953a..c40d67e 100644
--- a/aah/aah.go
+++ b/aah/aah.go
@@ -48,9 +48,10 @@ var (
var errStopHere = errors.New("stop here")
func checkPrerequisites() error {
+ gocmdName := goCmdName()
// check go is installed or not
- if !ess.LookExecutable("go") {
- return errors.New("Unable to find Go executable in PATH")
+ if !ess.LookExecutable(gocmdName) {
+ return fmt.Errorf("Unable to find '%s' executable in PATH", gocmdName)
}
var err error
@@ -61,36 +62,16 @@ func checkPrerequisites() error {
}
// Go executable
- gocmdName := goCmdName()
if gocmd, err = exec.LookPath(gocmdName); err != nil {
return err
}
- gosrcDir = filepath.Join(gopath, "src")
-
// git
if gitcmd, err = exec.LookPath("git"); err != nil {
return err
}
- // aah
- if aahVer, err = aahVersion(); err == errVersionNotExists {
- if collectYesOrNo(reader, "aah framework is not installed in GOPATH, would you like to install [Y]es or [N]o") {
- args := []string{"get"}
- if gocmdName == "go" {
- args = append(args, "-u")
- }
- args = append(args, "aahframework.org/aah.v0")
- if _, err := execCmd(gocmd, args, false); err != nil {
- return err
- }
- aahVer, _ = aahVersion()
- fmt.Printf("\naah framework successfully installed in GOPATH\n\n")
- return nil
- }
- fmt.Printf("\nOkay, you could do it manually, run '%s get aahframework.org/aah.v0'\n", gocmdName)
- return errStopHere
- }
+ gosrcDir = filepath.Join(gopath, "src")
return nil
}
@@ -135,6 +116,14 @@ func main() {
migrateCmd,
}
+ // Global flags
+ app.Flags = []cli.Flag{
+ cli.BoolFlag{
+ Name: "y, yes",
+ Usage: `Automatic yes to prompts. Assume "yes" as answer to all prompts and run non-interactively.`,
+ },
+ }
+
sort.Sort(cli.FlagsByName(app.Flags))
_ = app.Run(os.Args)
}
@@ -144,13 +133,14 @@ func main() {
//___________________________________
func printHeader(c *cli.Context) error {
- hdrCont := fmt.Sprintf("aah framework v%s", aahVer)
+ aahVer, _ = aahVersion(c)
+ hdr := fmt.Sprintf("aah framework v%s", aahVer)
improveRpt := "# Report improvements/bugs at https://aahframework.org/issues #"
cnt := len(improveRpt)
- sp := (cnt - len(hdrCont)) / 2
+ sp := ((cnt - len(hdr)) / 2) - 1
fmt.Println(chr2str("-", cnt))
- fmt.Println(chr2str(" ", sp) + hdrCont)
+ fmt.Println(chr2str(" ", sp) + hdr)
fmt.Println(chr2str("-", cnt))
fmt.Printf(improveRpt + "\n\n")
diff --git a/aah/compile.go b/aah/compile.go
index bfcf807..55ccc6f 100644
--- a/aah/compile.go
+++ b/aah/compile.go
@@ -5,7 +5,6 @@
package main
import (
- "bufio"
"bytes"
"errors"
"fmt"
@@ -232,30 +231,12 @@ var notExistRegex = regexp.MustCompile(`cannot find package "(.*)" in any of`)
// go list -f '{{ join .Imports "\n" }}' aah-app/import/path/app/...
//
func checkAndGetAppDeps(appImportPath string, cfg *config.Config) error {
- importPath := path.Join(appImportPath, "app", "...")
- args := []string{"list", "-f", "{{.Imports}}", importPath}
- output, err := execCmd(gocmd, args, false)
- if err != nil {
- return err
- }
-
- pkgList := make(map[string]string)
- replacer := strings.NewReplacer("[", "", "]", "")
- scanner := bufio.NewScanner(strings.NewReader(output))
- for scanner.Scan() {
- if ln := replacer.Replace(strings.TrimSpace(scanner.Text())); ln != "" {
- for _, p := range strings.Fields(ln) {
- if p := strings.TrimSpace(p); p != "" {
- pkgList[p] = p
- }
- }
- }
+ debList := libDependencyImports(path.Join(appImportPath, "app", "..."))
+ if len(debList) == 0 {
+ return nil
}
- args = []string{"list"}
- for _, p := range pkgList {
- args = append(args, p)
- }
+ args := append([]string{"list"}, debList...)
b, _ := exec.Command(gocmd, args...).CombinedOutput()
notExistsPkgs := []string{}
matches := notExistRegex.FindAllStringSubmatch(string(b), -1)
@@ -264,7 +245,8 @@ func checkAndGetAppDeps(appImportPath string, cfg *config.Config) error {
}
if cfg.BoolDefault("build.dep_get", true) && len(notExistsPkgs) > 0 {
- cliLog.Info("Getting application dependencies ...", notExistsPkgs)
+ cliLog.Infof("Getting application dependencies ...\n---> %s",
+ strings.Join(notExistsPkgs, "\n---> "))
if err := goGet(notExistsPkgs...); err != nil {
return err
}
diff --git a/aah/generate.go b/aah/generate.go
index f744207..89a5497 100644
--- a/aah/generate.go
+++ b/aah/generate.go
@@ -105,7 +105,7 @@ func generateSystemdScript(c *cli.Context) error {
fileName := fmt.Sprintf("%s.service", aah.AppName())
destFile := filepath.Join(aah.AppBaseDir(), fileName)
- if checkAndConfirmOverwrite(destFile) {
+ if checkAndConfirmOverwrite(c, destFile) {
return nil
}
@@ -143,13 +143,13 @@ func generateDockerScript(c *cli.Context) error {
devFileName := "Dockerfile.dev"
devDestFile := filepath.Join(aah.AppBaseDir(), devFileName)
- if checkAndConfirmOverwrite(devDestFile) {
+ if checkAndConfirmOverwrite(c, devDestFile) {
return nil
}
prodFileName := "Dockerfile.prod"
prodDestFile := filepath.Join(aah.AppBaseDir(), prodFileName)
- if checkAndConfirmOverwrite(prodDestFile) {
+ if checkAndConfirmOverwrite(c, prodDestFile) {
return nil
}
@@ -198,12 +198,17 @@ func generateDockerScript(c *cli.Context) error {
return nil
}
-func checkAndConfirmOverwrite(destFile string) bool {
+func checkAndConfirmOverwrite(c *cli.Context, destFile string) bool {
if ess.IsFileExists(destFile) {
cliLog.Warnf("File: %s already exists, it will be overwritten.", destFile)
+ if c.GlobalBool("y") || c.GlobalBool("yes") {
+ fmt.Println("\nWould you like to continue? [y/N]: y")
+ return true
+ }
+
var input string
for {
- input = readInput(reader, "\nWould you like to continue [Y]es or [N]o, default is 'N'? ")
+ input = readInput(reader, "\nWould you like to continue? [y/N]: ")
input = strings.ToLower(strings.TrimSpace(input))
if ess.IsStrEmpty(input) || input == "n" {
// do not overwrite the file, abort
diff --git a/aah/migrate.go b/aah/migrate.go
index 7141d11..27a82fa 100644
--- a/aah/migrate.go
+++ b/aah/migrate.go
@@ -6,6 +6,7 @@ package main
import (
"bytes"
+ "fmt"
"go/format"
"io/ioutil"
"os"
@@ -73,7 +74,9 @@ func migrateCodeAction(c *cli.Context) error {
cliLog = initCLILogger(projectCfg)
cliLog.Warn("Migrate command does not take file backup. It assumes application use version control.")
- if !collectYesOrNo(reader, "Would you like to continue ([Y]es or [N]o)? default is 'N'") {
+ if c.GlobalBool("y") || c.GlobalBool("yes") {
+ fmt.Println("\nWould you like to continue? [y/N]: y")
+ } else if !collectYesOrNo(reader, "Would you like to continue? [y/N]") {
cliLog.Info("Okay, I respect your choice. Bye.")
return nil
}
diff --git a/aah/new.go b/aah/new.go
index 0e0eeb0..8bad277 100644
--- a/aah/new.go
+++ b/aah/new.go
@@ -61,9 +61,9 @@ func newAction(c *cli.Context) error {
switch appType {
case typeWeb:
- collectInputsForWebApp(app)
+ collectInputsForWebApp(c, app)
case typeAPI:
- collectInputsForAPIApp(app)
+ collectInputsForAPIApp(c, app)
}
// Process it
@@ -143,7 +143,7 @@ func collectAppType(reader *bufio.Reader) string {
// Collecting inputs for Web App
//______________________________________________________________________________
-func collectInputsForWebApp(app *appTmplData) {
+func collectInputsForWebApp(c *cli.Context, app *appTmplData) {
viewEngine(reader, app)
authScheme(reader, app)
@@ -157,16 +157,16 @@ func collectInputsForWebApp(app *appTmplData) {
sessionInfo(reader, app)
// In the web application user may like to have API also WebSocket within it.
- collectAppSubTypesChoice(reader, app)
+ collectAppSubTypesChoice(c, reader, app)
- app.CORSEnable = collectYesOrNo(reader, "Would you like to enable CORS ([Y]es or [N]o)? default is 'N'")
+ app.CORSEnable = collectYesOrNo(reader, "Would you like to enable CORS? [y/N]")
}
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
// Collecting inputs for API App
//______________________________________________________________________________
-func collectInputsForAPIApp(app *appTmplData) {
+func collectInputsForAPIApp(c *cli.Context, app *appTmplData) {
authScheme(reader, app)
if app.AuthScheme == authBasic {
@@ -175,20 +175,20 @@ func collectInputsForAPIApp(app *appTmplData) {
passwordHashAlgorithm(reader, app)
- app.CORSEnable = collectYesOrNo(reader, "Would you like to enable CORS ([Y]es or [N]o)? default is 'N'")
+ app.CORSEnable = collectYesOrNo(reader, "Would you like to enable CORS? [y/N]")
}
-func collectAppSubTypesChoice(reader *bufio.Reader, app *appTmplData) {
+func collectAppSubTypesChoice(c *cli.Context, reader *bufio.Reader, app *appTmplData) {
app.SubTypes = make([]string, 0)
// API choice
- choice := collectYesOrNo(reader, "Would you like to add API [/api/v1/*] within your Web App ([Y]es or [N]o)? default is 'N'")
+ choice := collectYesOrNo(reader, "Would you like to add API (/api/v1/*) within your Web App? [y/N]")
if choice {
app.SubTypes = append(app.SubTypes, typeAPI)
}
// WebSocket choice
- choice = collectYesOrNo(reader, "Would you like to add WebSocket [/ws/*] within your Web App ([Y]es or [N]o)? default is 'N'")
+ choice = collectYesOrNo(reader, "Would you like to add WebSocket (/ws/*) within your Web App? [y/N]")
if choice {
app.SubTypes = append(app.SubTypes, typeWebSocket)
}
diff --git a/aah/switch.go b/aah/switch.go
index 7bcd7da..35d9038 100644
--- a/aah/switch.go
+++ b/aah/switch.go
@@ -67,7 +67,7 @@ func switchAction(c *cli.Context) error {
return doRefresh(branchName)
}
- return doSwitch(branchName, strings.ToLower(firstNonEmpty(c.String("v"), c.String("version"))))
+ return doSwitch(c, branchName, strings.ToLower(firstNonEmpty(c.String("v"), c.String("version"))))
}
func whoami(branchName string) error {
@@ -106,14 +106,20 @@ func doRefresh(branchName string) error {
return nil
}
-func doSwitch(branchName, target string) error {
+func doSwitch(c *cli.Context, branchName, target string) error {
fname := friendlyName(branchName)
if target == fname {
cliLog.Infof("Currently you're on aah '%s' version.\n", fname)
cliLog.Infof("To switch to release version. Run 'aah s -v release'\n")
if fname == "edge" {
- ans := collectYesOrNo(reader, "Would you like to refresh 'edge' to latest updates? ([Y]es or [N]o), default is 'N'")
+ var ans bool
+ if c.GlobalBool("y") || c.GlobalBool("yes") {
+ fmt.Println("\nWould you like to refresh 'edge' to latest updates? [y/N]: y")
+ ans = true
+ } else {
+ ans = collectYesOrNo(reader, "Would you like to refresh 'edge' to latest updates? [y/N]")
+ }
fmt.Println()
if ans {
doRefresh(branchName)
diff --git a/aah/util.go b/aah/util.go
index 334bf2e..6591c22 100644
--- a/aah/util.go
+++ b/aah/util.go
@@ -5,6 +5,7 @@
package main
import (
+ "bufio"
"fmt"
"io"
"io/ioutil"
@@ -259,6 +260,10 @@ func initCLILogger(cfg *config.Config) *log.Logger {
return l
}
+//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+// Git methods
+//___________________________________________________________________________
+
func gitCheckout(dir, branch string) error {
if ess.IsFileExists(filepath.Join(dir, ".git")) {
_, err := execCmd(gitcmd, []string{"-C", dir, "checkout", branch}, false)
@@ -267,15 +272,6 @@ func gitCheckout(dir, branch string) error {
return nil
}
-func libImportPath(name string) string {
- return fmt.Sprintf("%s/%s.%s", importPrefix, name, inferVersionSeries())
-}
-
-func libDir(name string) string {
- importPath := libImportPath(name)
- return filepath.FromSlash(filepath.Join(gopath, "src", importPath))
-}
-
func gitBranchName(dir string) string {
if !ess.IsDir(dir) {
cliLog.Tracef("Given path '%s' is not a directory", dir)
@@ -299,6 +295,35 @@ func gitPull(dir string) error {
return nil
}
+func checkoutBranch(aahLibDirs []string, branchName string) {
+ var wg sync.WaitGroup
+ for _, dir := range aahLibDirs {
+ wg.Add(1)
+ go func(d string) {
+ defer wg.Done()
+ baseName := filepath.Base(d)
+ if err := gitCheckout(d, branchName); err != nil {
+ logErrorf("Unable to switch library version, possibliy you may have local changes[%s]: %s", baseName, err)
+ }
+ cliLog.Tracef("Library '%s' have been switched to '%s' successfully", baseName, branchName)
+ }(dir)
+ }
+ wg.Wait()
+}
+
+//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+// aah discovery and processing methods
+//___________________________________________________________________________
+
+func libImportPath(name string) string {
+ return fmt.Sprintf("%s/%s.%s", importPrefix, name, inferVersionSeries())
+}
+
+func libDir(name string) string {
+ importPath := libImportPath(name)
+ return filepath.FromSlash(filepath.Join(gosrcDir, importPath))
+}
+
func goGet(pkgs ...string) error {
for _, pkg := range pkgs {
if _, err := execCmd(gocmd, []string{"get", pkg}, false); err != nil {
@@ -308,22 +333,6 @@ func goGet(pkgs ...string) error {
return nil
}
-func waitForConnReady(port string) {
- port = ":" + port
- startTime := time.Now()
- for {
- if _, err := net.Dial("tcp", port); err != nil {
- if time.Since(startTime).Seconds() > (30 * time.Second).Seconds() {
- return
- }
-
- time.Sleep(10 * time.Millisecond)
- continue
- }
- return
- }
-}
-
func installCLI() {
if CliPackaged != "" {
return
@@ -371,47 +380,6 @@ func refreshLibCode(libDirs []string) {
wg.Wait()
}
-func appImportPath(c *cli.Context) string {
- importPath := firstNonEmpty(c.String("i"), c.String("importpath"))
- if ess.IsStrEmpty(importPath) {
- importPath = importPathRelwd()
- }
-
- if !ess.IsImportPathExists(importPath) {
- logFatalf("Given import path '%s' does not exists", importPath)
- }
-
- return importPath
-}
-
-func logFatal(v ...interface{}) {
- if cliLog == nil {
- _ = log.SetPattern("%level %message")
- fatal(v...)
- _ = log.SetPattern(log.DefaultPattern)
- } else {
- cliLog.Fatal(append([]interface{}{"FATAL"}, v...))
- }
-}
-
-func logFatalf(format string, v ...interface{}) {
- if cliLog == nil {
- _ = log.SetPattern("%level %message")
- fatalf(format, v...)
- _ = log.SetPattern(log.DefaultPattern)
- } else {
- cliLog.Fatalf("FATAL "+format, v...)
- }
-}
-
-func logError(v ...interface{}) {
- cliLog.Error(append([]interface{}{"ERROR"}, v...))
-}
-
-func logErrorf(format string, v ...interface{}) {
- cliLog.Errorf("ERROR "+format, v...)
-}
-
func stripGoSrcPath(pkgFilePath string) string {
idx := strings.Index(pkgFilePath, "src")
return filepath.Clean(pkgFilePath[idx+4:])
@@ -449,33 +417,30 @@ func aahImportPaths() []string {
return importPaths
}
-func checkoutBranch(aahLibDirs []string, branchName string) {
- var wg sync.WaitGroup
- for _, dir := range aahLibDirs {
- wg.Add(1)
- go func(d string) {
- defer wg.Done()
- baseName := filepath.Base(d)
- if err := gitCheckout(d, branchName); err != nil {
- logErrorf("Unable to switch library version, possibliy you may have local changes[%s]: %s", baseName, err)
- }
- cliLog.Tracef("Library '%s' have been switched to '%s' successfully", baseName, branchName)
- }(dir)
- }
- wg.Wait()
-}
-
func libDependencyImports(importPath string) []string {
- var depList []string
- str, err := execCmd(gocmd, []string{"list", "-f", "{{.Imports}}", importPath}, false)
+ args := []string{"list", "-f", "{{.Imports}}", importPath}
+ output, err := execCmd(gocmd, args, false)
if err != nil {
logErrorf("Unable to infer dependency imports for %s", importPath)
return []string{}
}
- str = strings.TrimSpace(str)
- for _, i := range strings.Fields(str[1 : len(str)-1]) {
- depList = append(depList, strings.TrimSpace(i))
+ pkgList := make(map[string]string)
+ replacer := strings.NewReplacer("[", "", "]", "")
+ scanner := bufio.NewScanner(strings.NewReader(output))
+ for scanner.Scan() {
+ if ln := replacer.Replace(strings.TrimSpace(scanner.Text())); ln != "" {
+ for _, p := range strings.Fields(ln) {
+ if p := strings.TrimSpace(p); p != "" {
+ pkgList[p] = p
+ }
+ }
+ }
+ }
+
+ var depList []string
+ for _, p := range pkgList {
+ depList = append(depList, p)
}
return depList
@@ -510,6 +475,67 @@ func readVersionNo(baseDir string) (string, error) {
return "Unknown", nil
}
+//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+// other helper methods
+//___________________________________________________________________________
+
+func appImportPath(c *cli.Context) string {
+ importPath := firstNonEmpty(c.String("i"), c.String("importpath"))
+ if ess.IsStrEmpty(importPath) {
+ importPath = importPathRelwd()
+ }
+
+ if !ess.IsImportPathExists(importPath) {
+ logFatalf("Given import path '%s' does not exists", importPath)
+ }
+
+ return importPath
+}
+
+func logFatal(v ...interface{}) {
+ if cliLog == nil {
+ _ = log.SetPattern("%level %message")
+ fatal(v...)
+ _ = log.SetPattern(log.DefaultPattern)
+ } else {
+ cliLog.Fatal(append([]interface{}{"FATAL"}, v...))
+ }
+}
+
+func logFatalf(format string, v ...interface{}) {
+ if cliLog == nil {
+ _ = log.SetPattern("%level %message")
+ fatalf(format, v...)
+ _ = log.SetPattern(log.DefaultPattern)
+ } else {
+ cliLog.Fatalf("FATAL "+format, v...)
+ }
+}
+
+func logError(v ...interface{}) {
+ cliLog.Error(append([]interface{}{"ERROR"}, v...))
+}
+
+func logErrorf(format string, v ...interface{}) {
+ cliLog.Errorf("ERROR "+format, v...)
+}
+
+func waitForConnReady(port string) {
+ port = ":" + port
+ startTime := time.Now()
+ for {
+ if _, err := net.Dial("tcp", port); err != nil {
+ if time.Since(startTime).Seconds() > (30 * time.Second).Seconds() {
+ return
+ }
+
+ time.Sleep(10 * time.Millisecond)
+ continue
+ }
+ return
+ }
+}
+
func cleanupAutoGenFiles(appBaseDir string) {
appMainGoFile := filepath.Join(appBaseDir, "app", "aah.go")
appBuildDir := filepath.Join(appBaseDir, "build")
diff --git a/aah/version.go b/aah/version.go
index 585e5c8..62a4e5e 100644
--- a/aah/version.go
+++ b/aah/version.go
@@ -11,11 +11,13 @@ import (
"regexp"
"strings"
+ "aahframework.org/essentials.v0"
+
"gopkg.in/urfave/cli.v1"
)
// Version no. of aah framework CLI tool
-const Version = "0.11.0"
+const Version = "0.12.0"
var (
errVersionNotExists = errors.New("version not exists")
@@ -26,7 +28,10 @@ var (
func VersionPrinter(c *cli.Context) {
cliLog = initCLILogger(nil)
fmt.Printf("%-3s v%s\n", "cli", Version)
- fmt.Printf("%-3s v%s\n", "aah", aahVer)
+ aahVer, _ = aahVersion(c)
+ if len(aahVer) > 0 {
+ fmt.Printf("%-3s v%s\n", "aah", aahVer)
+ }
if goVer := goVersion(); len(goVer) > 0 {
fmt.Printf("%-3s v%s\n", "go", goVer)
}
@@ -46,8 +51,21 @@ func VersionPrinter(c *cli.Context) {
fmt.Println()
}
-func aahVersion() (string, error) {
- return readVersionNo(libDir("aah"))
+func aahVersion(c *cli.Context) (string, error) {
+ // Vendor Directory
+ importPath := importPathRelwd()
+ if len(importPath) > 0 {
+ vendorPath := filepath.Join(gosrcDir, importPath, "vendor")
+ if ess.IsFileExists(vendorPath) {
+ ver, _ := readVersionNo(filepath.Join(vendorPath, importPrefix, "aah.v0"))
+ if len(ver) > 0 && ver != "Unknown" {
+ return ver, nil
+ }
+ }
+ }
+
+ // GOPATH
+ return readVersionNo(filepath.Join(gosrcDir, importPrefix, "aah.v0"))
}
func goVersion() string {