summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorMartin Treusch von Buttlar <martin.tvb@vitraum.de>2017-05-15 22:39:14 +0200
committerMartin Treusch von Buttlar <martin.tvb@vitraum.de>2017-05-15 22:39:14 +0200
commit4c54cc43537fd15cc459030cb792f8171bcd0fd7 (patch)
tree9e81500281ea4a33685bbf77f7c5ad2bbb3636e2 /cmd
parent0cf8aa550a3da63cb1509678bf5add0d73925546 (diff)
add cobra commands
Diffstat (limited to 'cmd')
-rw-r--r--cmd/ponzu/add.go28
-rw-r--r--cmd/ponzu/build.go91
-rw-r--r--cmd/ponzu/generate.go38
-rw-r--r--cmd/ponzu/main.go265
-rw-r--r--cmd/ponzu/new.go176
-rw-r--r--cmd/ponzu/options.go305
-rw-r--r--cmd/ponzu/upgrade.go169
-rw-r--r--cmd/ponzu/usage.go194
8 files changed, 615 insertions, 651 deletions
diff --git a/cmd/ponzu/add.go b/cmd/ponzu/add.go
index 05d6f16..c1242db 100644
--- a/cmd/ponzu/add.go
+++ b/cmd/ponzu/add.go
@@ -8,15 +8,35 @@ import (
"os/exec"
"path/filepath"
"strings"
+
+ "github.com/spf13/cobra"
)
+var addCmd = &cobra.Command{
+ Use: "add <repo>",
+ Short: "Downloads addon from specified import path",
+ Long: `Downloads addon from specified import path to $GOPATH/src and copys it to the
+current project's ./addons directory. Must be called from within a
+Ponzu project directory.
+
+Example:
+$ ponzu add github.com/bosssauce/fbscheduler`,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ // expecting two args, add and the go gettable package uri
+ if len(args) < 1 {
+ return errors.New("repo not given")
+ }
+
+ return getAddon(args[0])
+ },
+}
+
// use `go get` to download addon and add to $GOPATH/src, useful
// for IDE auto-import and code completion, then copy entire directory
// tree to project's ./addons folder
-func getAddon(args []string) error {
+func getAddon(addonPath string) error {
var cmdOptions []string
- var addonPath = args[1]
// Go get
cmdOptions = append(cmdOptions, "get", addonPath)
@@ -165,3 +185,7 @@ func copyFileContents(src, dst string) (err error) {
func addError(err error) error {
return errors.New("Ponzu add failed. " + "\n" + err.Error())
}
+
+func init() {
+ rootCmd.AddCommand(addCmd)
+}
diff --git a/cmd/ponzu/build.go b/cmd/ponzu/build.go
new file mode 100644
index 0000000..3797e84
--- /dev/null
+++ b/cmd/ponzu/build.go
@@ -0,0 +1,91 @@
+package main
+
+import (
+ "errors"
+ "os"
+ "os/exec"
+ "path/filepath"
+
+ "github.com/spf13/cobra"
+)
+
+func buildPonzuServer() error {
+ pwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+
+ // copy all ./content files to internal vendor directory
+ src := "content"
+ dst := filepath.Join("cmd", "ponzu", "vendor", "github.com", "ponzu-cms", "ponzu", "content")
+ err = emptyDir(dst)
+ if err != nil {
+ return err
+ }
+ err = copyFilesWarnConflicts(src, dst, []string{"doc.go"})
+ if err != nil {
+ return err
+ }
+
+ // copy all ./addons files & dirs to internal vendor directory
+ src = "addons"
+ dst = filepath.Join("cmd", "ponzu", "vendor")
+ err = copyFilesWarnConflicts(src, dst, nil)
+ if err != nil {
+ return err
+ }
+
+ // execute go build -o ponzu-cms cmd/ponzu/*.go
+ buildOptions := []string{"build", "-o", buildOutputName()}
+ cmdBuildFiles := []string{
+ "main.go", "options.go", "generate.go",
+ "usage.go", "paths.go", "add.go",
+ }
+ var cmdBuildFilePaths []string
+ for _, file := range cmdBuildFiles {
+ p := filepath.Join(pwd, "cmd", "ponzu", file)
+ cmdBuildFilePaths = append(cmdBuildFilePaths, p)
+ }
+
+ build := exec.Command(gocmd, append(buildOptions, cmdBuildFilePaths...)...)
+ build.Stderr = os.Stderr
+ build.Stdout = os.Stdout
+
+ err = build.Start()
+ if err != nil {
+ return errors.New("Ponzu build step failed. Please try again. " + "\n" + err.Error())
+
+ }
+ err = build.Wait()
+ if err != nil {
+ return errors.New("Ponzu build step failed. Please try again. " + "\n" + err.Error())
+
+ }
+
+ return nil
+}
+
+var buildCmd = &cobra.Command{
+ Use: "build",
+ Short: "build will build/compile the project to then be run.",
+ Long: `From within your Ponzu project directory, running build will copy and move
+the necessary files from your workspace into the vendored directory, and
+will build/compile the project to then be run.
+
+Example:
+$ ponzu build
+(or)
+$ ponzu -gocmd=go1.8rc1 build
+
+By providing the 'gocmd' flag, you can specify which Go command to build the
+project, if testing a different release of Go.
+
+Errors will be reported, but successful build commands return nothing.`,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ return buildPonzuServer()
+ },
+}
+
+func init() {
+ rootCmd.AddCommand(buildCmd)
+}
diff --git a/cmd/ponzu/generate.go b/cmd/ponzu/generate.go
index 5211df8..cc2b93a 100644
--- a/cmd/ponzu/generate.go
+++ b/cmd/ponzu/generate.go
@@ -8,6 +8,8 @@ import (
"path/filepath"
"strings"
"text/template"
+
+ "github.com/spf13/cobra"
)
type generateType struct {
@@ -413,3 +415,39 @@ func generateContentType(args []string) error {
return nil
}
+
+var generateCmd = &cobra.Command{
+ Use: "generate <generator type (,...fields)>",
+ Short: "generate boilerplate code for various Ponzu components",
+ Long: `Generate boilerplate code for various Ponzu components, such as 'content'.
+
+Example:
+$ ponzu gen content review title:"string" body:"string" rating:"int" tags:"[]string"
+
+The command above will generate a file 'content/review.go' with boilerplate
+methods, as well as struct definition, and corresponding field tags like:
+
+type Review struct {
+ Title string ` + "`json:" + `"title"` + "`" + `
+ Body string ` + "`json:" + `"body"` + "`" + `
+ Rating int ` + "`json:" + `"rating"` + "`" + `
+ Tags []string ` + "`json:" + `"tags"` + "`" + `
+}
+
+The generate command will intelligently parse more sophisticated field names
+such as 'field_name' and convert it to 'FieldName' and vice versa, only where
+appropriate as per common Go idioms. Errors will be reported, but successful
+generate commands return nothing.`,
+}
+
+var contentCmd = &cobra.Command{
+ Use: "content <namespace> <field> <field>...",
+ RunE: func(cmd *cobra.Command, args []string) error {
+ return generateContentType(args)
+ },
+}
+
+func init() {
+ generateCmd.AddCommand(contentCmd)
+ rootCmd.AddCommand(generateCmd)
+}
diff --git a/cmd/ponzu/main.go b/cmd/ponzu/main.go
index d57e776..6b801f6 100644
--- a/cmd/ponzu/main.go
+++ b/cmd/ponzu/main.go
@@ -5,7 +5,7 @@
package main
import (
- "flag"
+ "errors"
"fmt"
"log"
"net/http"
@@ -13,19 +13,20 @@ import (
"os/exec"
"path/filepath"
"strings"
+ "time"
"github.com/ponzu-cms/ponzu/system/admin"
"github.com/ponzu-cms/ponzu/system/api"
"github.com/ponzu-cms/ponzu/system/api/analytics"
"github.com/ponzu-cms/ponzu/system/db"
"github.com/ponzu-cms/ponzu/system/tls"
+ "github.com/spf13/cobra"
+ "github.com/spf13/viper"
_ "github.com/ponzu-cms/ponzu/content"
)
var (
- usage = usageHeader + usageNew + usageGenerate +
- usageBuild + usageRun + usageUpgrade + usageAdd + usageVersion
port int
httpsport int
https bool
@@ -36,107 +37,46 @@ var (
dev bool
fork string
gocmd string
+ year = fmt.Sprintf("%d", time.Now().Year())
)
-func main() {
- flag.Usage = func() {
- fmt.Println(usage)
- }
-
- flag.IntVar(&port, "port", 8080, "port for ponzu to bind its HTTP listener")
- flag.IntVar(&httpsport, "httpsport", 443, "port for ponzu to bind its HTTPS listener")
- flag.BoolVar(&https, "https", false, "enable automatic TLS/SSL certificate management")
- flag.BoolVar(&devhttps, "devhttps", false, "[dev environment] enable automatic TLS/SSL certificate management")
- flag.BoolVar(&dev, "dev", false, "modify environment for Ponzu core development")
- flag.BoolVar(&cli, "cli", false, "specify that information should be returned about the CLI, not project")
- flag.StringVar(&fork, "fork", "", "modify repo source for Ponzu core development")
- flag.StringVar(&gocmd, "gocmd", "go", "custom go command if using beta or new release of Go")
- flag.Parse()
-
- args := flag.Args()
-
- if len(args) < 1 {
- fmt.Println(usage)
- os.Exit(0)
- }
-
- switch args[0] {
- case "help", "h":
- if len(args) < 2 {
- fmt.Println(usageHelp)
- fmt.Println(usage)
- os.Exit(0)
- }
-
- switch args[1] {
- case "new":
- fmt.Println(usageNew)
- os.Exit(0)
-
- case "generate", "gen", "g":
- fmt.Println(usageGenerate)
- os.Exit(0)
-
- case "build":
- fmt.Println(usageBuild)
- os.Exit(0)
-
- case "run":
- fmt.Println(usageRun)
- os.Exit(0)
-
- case "upgrade":
- fmt.Println(usageUpgrade)
- os.Exit(0)
-
- case "version", "v":
- fmt.Println(usageVersion)
- os.Exit(0)
-
- case "add", "a":
- fmt.Println(usageAdd)
- os.Exit(0)
- }
+var rootCmd = &cobra.Command{
+ Use: "ponzu",
+ Long: `Ponzu is a powerful and efficient open-source HTTP server framework and CMS. It
+provides automatic, free, and secure HTTP/2 over TLS (certificates obtained via
+[Let's Encrypt](https://letsencrypt.org)), a useful CMS and scaffolding to
+generate set-up code, and a fast HTTP API on which to build modern applications.
- case "new":
- if len(args) < 2 {
- fmt.Println(usageNew)
- os.Exit(0)
- }
-
- err := newProjectInDir(args[1])
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-
- case "generate", "gen", "g":
- if len(args) < 3 {
- fmt.Println(usageGenerate)
- os.Exit(0)
- }
-
- // check what we are asked to generate
- switch args[1] {
- case "content", "c":
- err := generateContentType(args[2:])
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- default:
- msg := fmt.Sprintf("Generator '%s' is not implemented.", args[1])
- fmt.Println(msg)
- }
-
- case "build":
- err := buildPonzuServer(args)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
+Ponzu is released under the BSD-3-Clause license (see LICENSE).
+(c) 2016 - ` + year + ` Boss Sauce Creative, LLC`,
+}
- case "run":
+var runCmd = &cobra.Command{
+ Use: "run <service(,service)>",
+ Short: "starts the 'ponzu' HTTP server for the JSON API and or Admin System.",
+ Long: `Starts the 'ponzu' HTTP server for the JSON API, Admin System, or both.
+The segments, separated by a comma, describe which services to start, either
+'admin' (Admin System / CMS backend) or 'api' (JSON API), and, optionally,
+if the server should utilize TLS encryption - served over HTTPS, which is
+automatically managed using Let's Encrypt (https://letsencrypt.org)
+
+Example:
+$ ponzu run
+(or)
+$ ponzu -port=8080 --https run admin,api
+(or)
+$ ponzu run admin
+(or)
+$ ponzu -port=8888 run api
+
+Defaults to '-port=8080 run admin,api' (running Admin & API on port 8080, without TLS)
+
+Note:
+Admin and API cannot run on separate processes unless you use a copy of the
+database, since the first process to open it receives a lock. If you intend
+to run the Admin and API on separate processes, you must call them with the
+'ponzu' command independently.`,
+ RunE: func(cmd *cobra.Command, args []string) error {
var addTLS string
if https {
addTLS = "--https"
@@ -149,8 +89,8 @@ func main() {
}
var services string
- if len(args) > 1 {
- services = args[1]
+ if len(args) > 0 {
+ services = args[0]
} else {
services = "admin,api"
}
@@ -167,32 +107,37 @@ func main() {
serve.Stderr = os.Stderr
serve.Stdout = os.Stdout
- err := serve.Run()
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
+ return serve.Run()
+ },
+}
+
+var ErrWrongOrMissingService = errors.New("To execute 'ponzu serve', " +
+ "you must specify which service to run.")
+
+var serveCmd = &cobra.Command{
+ Use: "serve <service,service>",
+ Short: "actually run the server",
+ Hidden: true,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if len(args) == 0 {
+ return ErrWrongOrMissingService
}
- case "serve", "s":
db.Init()
defer db.Close()
analytics.Init()
defer analytics.Close()
- if len(args) > 1 {
- services := strings.Split(args[1], ",")
-
- for _, service := range services {
- if service == "api" {
- api.Run()
- } else if service == "admin" {
- admin.Run()
- } else {
- fmt.Println("To execute 'ponzu serve', you must specify which service to run.")
- fmt.Println("$ ponzu --help")
- os.Exit(1)
- }
+ services := strings.Split(args[0], ",")
+
+ for _, service := range services {
+ if service == "api" {
+ api.Run()
+ } else if service == "admin" {
+ admin.Run()
+ } else {
+ return ErrWrongOrMissingService
}
}
@@ -229,69 +174,31 @@ func main() {
fmt.Printf("Server listening on :%d for HTTP requests...\n", port)
fmt.Println("\nvisit `/admin` to get started.")
log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
+ return nil
+ },
+}
- case "version", "v":
- // read ponzu.json value to Stdout
-
- p, err := ponzu(cli)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-
- fmt.Fprintf(os.Stdout, "Ponzu v%s\n", p["version"])
-
- case "upgrade":
- // confirm since upgrade will replace Ponzu core files
- path, err := os.Getwd()
- if err != nil {
- fmt.Println("Failed to find current directory.", err)
- os.Exit(1)
- }
-
- fmt.Println("Only files you added to this directory, 'addons' and 'content' will be preserved.")
- fmt.Println("Upgrade this project? (y/N):")
-
- answer, err := getAnswer()
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-
- switch answer {
- case "n", "no", "\r\n", "\n", "":
- fmt.Println("")
-
- case "y", "yes":
- err := upgradePonzuProjectDir(path)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-
- default:
- fmt.Println("Input not recognized. No upgrade made. Answer as 'y' or 'n' only.")
- }
+func init() {
+ for _, cmd := range []*cobra.Command{runCmd, serveCmd} {
+ cmd.Flags().IntVar(&port, "port", 8080, "port for ponzu to bind its HTTP listener")
+ cmd.Flags().IntVar(&httpsport, "httpsport", 443, "port for ponzu to bind its HTTPS listener")
+ cmd.Flags().BoolVar(&https, "https", false, "enable automatic TLS/SSL certificate management")
+ cmd.Flags().BoolVar(&devhttps, "devhttps", false, "[dev environment] enable automatic TLS/SSL certificate management")
+ }
- case "add", "a":
- // expecting two args, add and the go gettable package uri
- if len(args) < 2 {
- fmt.Println(usageAdd)
- os.Exit(0)
- }
+ rootCmd.AddCommand(runCmd, serveCmd)
- err := getAddon(args)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
+ pflags := rootCmd.PersistentFlags()
+ pflags.StringVar(&gocmd, "gocmd", "go", "custom go command if using beta or new release of Go")
- case "":
- fmt.Println(usage)
- fmt.Println(usageHelp)
+ viper.BindPFlag("dev", pflags.Lookup("dev"))
+ viper.BindPFlag("cli", pflags.Lookup("cli"))
+ viper.BindPFlag("gocmd", pflags.Lookup("gocmd"))
+}
- default:
- fmt.Println(usage)
- fmt.Println(usageHelp)
+func main() {
+ if err := rootCmd.Execute(); err != nil {
+ fmt.Println(err)
+ os.Exit(1)
}
}
diff --git a/cmd/ponzu/new.go b/cmd/ponzu/new.go
new file mode 100644
index 0000000..3c18a21
--- /dev/null
+++ b/cmd/ponzu/new.go
@@ -0,0 +1,176 @@
+package main
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+
+ "github.com/spf13/cobra"
+)
+
+var newCmd = &cobra.Command{
+ Use: "new <projectName>",
+ Short: "creates a 'ponzu' directory by the name supplied as a parameter",
+ Long: `Creates a 'ponzu' directory by the name supplied as a parameter
+immediately following the 'new' option in the $GOPATH/src directory. Note:
+'new' depends on the program 'git' and possibly a network connection. If
+there is no local repository to clone from at the local machine's $GOPATH,
+'new' will attempt to clone the 'github.com/ponzu-cms/ponzu' package from
+over the network.
+
+Example:
+$ ponzu new myProject
+> New ponzu project created at $GOPATH/src/myProject
+
+Errors will be reported, but successful commands return nothing.`,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if len(args) < 1 {
+ return errors.New("project name not supplied")
+ }
+
+ return newProjectInDir(args[0])
+ },
+}
+
+func newProjectInDir(path string) error {
+ // set path to be nested inside $GOPATH/src
+ gopath, err := getGOPATH()
+ if err != nil {
+ return err
+ }
+ path = filepath.Join(gopath, "src", path)
+
+ // check if anything exists at the path, ask if it should be overwritten
+ if _, err = os.Stat(path); !os.IsNotExist(err) {
+ fmt.Println("Path exists, overwrite contents? (y/N):")
+
+ answer, err := getAnswer()
+ if err != nil {
+ return err
+ }
+
+ switch answer {
+ case "n", "no", "\r\n", "\n", "":
+ fmt.Println("")
+
+ case "y", "yes":
+ err := os.RemoveAll(path)
+ if err != nil {
+ return fmt.Errorf("Failed to overwrite %s. \n%s", path, err)
+ }
+
+ return createProjectInDir(path)
+
+ default:
+ fmt.Println("Input not recognized. No files overwritten. Answer as 'y' or 'n' only.")
+ }
+
+ return nil
+ }
+
+ return createProjectInDir(path)
+}
+
+func createProjectInDir(path string) error {
+ gopath, err := getGOPATH()
+ if err != nil {
+ return err
+ }
+ repo := ponzuRepo
+ local := filepath.Join(gopath, "src", filepath.Join(repo...))
+ network := "https://" + strings.Join(repo, "/") + ".git"
+ if !strings.HasPrefix(path, gopath) {
+ path = filepath.Join(gopath, path)
+ }
+
+ // create the directory or overwrite it
+ err = os.MkdirAll(path, os.ModeDir|os.ModePerm)
+ if err != nil {
+ return err
+ }
+
+ if dev {
+ if fork != "" {
+ local = filepath.Join(gopath, "src", fork)
+ }
+
+ devClone := exec.Command("git", "clone", local, "--branch", "ponzu-dev", "--single-branch", path)
+ devClone.Stdout = os.Stdout
+ devClone.Stderr = os.Stderr
+
+ err = devClone.Start()
+ if err != nil {
+ return err
+ }
+
+ err = devClone.Wait()
+ if err != nil {
+ return err
+ }
+
+ err = vendorCorePackages(path)
+ if err != nil {
+ return err
+ }
+
+ fmt.Println("Dev build cloned from " + local + ":ponzu-dev")
+ return nil
+ }
+
+ // try to git clone the repository from the local machine's $GOPATH
+ localClone := exec.Command("git", "clone", local, path)
+ localClone.Stdout = os.Stdout
+ localClone.Stderr = os.Stderr
+
+ err = localClone.Start()
+ if err != nil {
+ return err
+ }
+ err = localClone.Wait()
+ if err != nil {
+ fmt.Println("Couldn't clone from", local, "- trying network...")
+
+ // try to git clone the repository over the network
+ networkClone := exec.Command("git", "clone", network, path)
+ networkClone.Stdout = os.Stdout
+ networkClone.Stderr = os.Stderr
+
+ err = networkClone.Start()
+ if err != nil {
+ fmt.Println("Network clone failed to start. Try again and make sure you have a network connection.")
+ return err
+ }
+ err = networkClone.Wait()
+ if err != nil {
+ fmt.Println("Network clone failure.")
+ // failed
+ return fmt.Errorf("Failed to clone files from local machine [%s] and over the network [%s].\n%s", local, network, err)
+ }
+ }
+
+ // create an internal vendor directory in ./cmd/ponzu and move content,
+ // management and system packages into it
+ err = vendorCorePackages(path)
+ if err != nil {
+ return err
+ }
+
+ gitDir := filepath.Join(path, ".git")
+ err = os.RemoveAll(gitDir)
+ if err != nil {
+ fmt.Println("Failed to remove .git directory from your project path. Consider removing it manually.")
+ }
+
+ fmt.Println("New ponzu project created at", path)
+ return nil
+}
+
+func init() {
+ newCmd.Flags().StringVar(&fork, "fork", "", "modify repo source for Ponzu core development")
+ newCmd.Flags().BoolVar(&dev, "dev", false, "modify environment for Ponzu core development")
+
+ rootCmd.AddCommand(newCmd)
+}
diff --git a/cmd/ponzu/options.go b/cmd/ponzu/options.go
index 77e842c..5cc05e4 100644
--- a/cmd/ponzu/options.go
+++ b/cmd/ponzu/options.go
@@ -4,53 +4,11 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"os"
- "os/exec"
"path/filepath"
"strings"
- "time"
)
-func newProjectInDir(path string) error {
- // set path to be nested inside $GOPATH/src
- gopath, err := getGOPATH()
- if err != nil {
- return err
- }
- path = filepath.Join(gopath, "src", path)
-
- // check if anything exists at the path, ask if it should be overwritten
- if _, err = os.Stat(path); !os.IsNotExist(err) {
- fmt.Println("Path exists, overwrite contents? (y/N):")
-
- answer, err := getAnswer()
- if err != nil {
- return err
- }
-
- switch answer {
- case "n", "no", "\r\n", "\n", "":
- fmt.Println("")
-
- case "y", "yes":
- err := os.RemoveAll(path)
- if err != nil {
- return fmt.Errorf("Failed to overwrite %s. \n%s", path, err)
- }
-
- return createProjectInDir(path)
-
- default:
- fmt.Println("Input not recognized. No files overwritten. Answer as 'y' or 'n' only.")
- }
-
- return nil
- }
-
- return createProjectInDir(path)
-}
-
var ponzuRepo = []string{"github.com", "ponzu-cms", "ponzu"}
func getAnswer() (string, error) {
@@ -69,100 +27,6 @@ func getAnswer() (string, error) {
return answer, nil
}
-func createProjectInDir(path string) error {
- gopath, err := getGOPATH()
- if err != nil {
- return err
- }
- repo := ponzuRepo
- local := filepath.Join(gopath, "src", filepath.Join(repo...))
- network := "https://" + strings.Join(repo, "/") + ".git"
- if !strings.HasPrefix(path, gopath) {
- path = filepath.Join(gopath, path)
- }
-
- // create the directory or overwrite it
- err = os.MkdirAll(path, os.ModeDir|os.ModePerm)
- if err != nil {
- return err
- }
-
- if dev {
- if fork != "" {
- local = filepath.Join(gopath, "src", fork)
- }
-
- devClone := exec.Command("git", "clone", local, "--branch", "ponzu-dev", "--single-branch", path)
- devClone.Stdout = os.Stdout
- devClone.Stderr = os.Stderr
-
- err = devClone.Start()
- if err != nil {
- return err
- }
-
- err = devClone.Wait()
- if err != nil {
- return err
- }
-
- err = vendorCorePackages(path)
- if err != nil {
- return err
- }
-
- fmt.Println("Dev build cloned from " + local + ":ponzu-dev")
- return nil
- }
-
- // try to git clone the repository from the local machine's $GOPATH
- localClone := exec.Command("git", "clone", local, path)
- localClone.Stdout = os.Stdout
- localClone.Stderr = os.Stderr
-
- err = localClone.Start()
- if err != nil {
- return err
- }
- err = localClone.Wait()
- if err != nil {
- fmt.Println("Couldn't clone from", local, "- trying network...")
-
- // try to git clone the repository over the network
- networkClone := exec.Command("git", "clone", network, path)
- networkClone.Stdout = os.Stdout
- networkClone.Stderr = os.Stderr
-
- err = networkClone.Start()
- if err != nil {
- fmt.Println("Network clone failed to start. Try again and make sure you have a network connection.")
- return err
- }
- err = networkClone.Wait()
- if err != nil {
- fmt.Println("Network clone failure.")
- // failed
- return fmt.Errorf("Failed to clone files from local machine [%s] and over the network [%s].\n%s", local, network, err)
- }
- }
-
- // create an internal vendor directory in ./cmd/ponzu and move content,
- // management and system packages into it
- err = vendorCorePackages(path)
- if err != nil {
- return err
- }
-
- gitDir := filepath.Join(path, ".git")
- err = os.RemoveAll(gitDir)
- if err != nil {
- fmt.Println("Failed to remove .git directory from your project path. Consider removing it manually.")
- }
-
- fmt.Println("New ponzu project created at", path)
- return nil
-}
-
func vendorCorePackages(path string) error {
vendorPath := filepath.Join(path, "cmd", "ponzu", "vendor", "github.com", "ponzu-cms", "ponzu")
err := os.MkdirAll(vendorPath, os.ModeDir|os.ModePerm)
@@ -281,62 +145,6 @@ func emptyDir(path string) error {
return nil
}
-func buildPonzuServer(args []string) error {
- pwd, err := os.Getwd()
- if err != nil {
- return err
- }
-
- // copy all ./content files to internal vendor directory
- src := "content"
- dst := filepath.Join("cmd", "ponzu", "vendor", "github.com", "ponzu-cms", "ponzu", "content")
- err = emptyDir(dst)
- if err != nil {
- return err
- }
- err = copyFilesWarnConflicts(src, dst, []string{"doc.go"})
- if err != nil {
- return err
- }
-
- // copy all ./addons files & dirs to internal vendor directory
- src = "addons"
- dst = filepath.Join("cmd", "ponzu", "vendor")
- err = copyFilesWarnConflicts(src, dst, nil)
- if err != nil {
- return err
- }
-
- // execute go build -o ponzu-cms cmd/ponzu/*.go
- buildOptions := []string{"build", "-o", buildOutputName()}
- cmdBuildFiles := []string{
- "main.go", "options.go", "generate.go",
- "usage.go", "paths.go", "add.go",
- }
- var cmdBuildFilePaths []string
- for _, file := range cmdBuildFiles {
- p := filepath.Join(pwd, "cmd", "ponzu", file)
- cmdBuildFilePaths = append(cmdBuildFilePaths, p)
- }
-
- build := exec.Command(gocmd, append(buildOptions, cmdBuildFilePaths...)...)
- build.Stderr = os.Stderr
- build.Stdout = os.Stdout
-
- err = build.Start()
- if err != nil {
- return errors.New("Ponzu build step failed. Please try again. " + "\n" + err.Error())
-
- }
- err = build.Wait()
- if err != nil {
- return errors.New("Ponzu build step failed. Please try again. " + "\n" + err.Error())
-
- }
-
- return nil
-}
-
func copyAll(src, dst string) error {
err := filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
if err != nil {
@@ -374,116 +182,3 @@ func copyAll(src, dst string) error {
return nil
}
-
-func upgradePonzuProjectDir(path string) error {
- core := []string{
- ".gitattributes",
- "LICENSE",
- "ponzu-banner.png",
- "README.md",
- "cmd",
- "deployment",
- "management",
- "system",
- }
-
- stamp := fmt.Sprintf("ponzu-%d.bak", time.Now().Unix())
- temp := filepath.Join(os.TempDir(), stamp)
- err := os.Mkdir(temp, os.ModeDir|os.ModePerm)
- if err != nil {
- return err
- }
-
- // track non-Ponzu core items (added by user)
- var user []os.FileInfo
- list, err := ioutil.ReadDir(path)
- if err != nil {
- return err
- }
-
- for _, item := range list {
- // check if in core
- var isCore bool
- for _, name := range core {
- if item.Name() == name {
- isCore = true
- break
- }
- }
-
- if !isCore {
- user = append(user, item)
- }
- }
-
- // move non-Ponzu files to temp location
- fmt.Println("Preserving files to be restored after upgrade...")
- for _, item := range user {
- src := filepath.Join(path, item.Name())
- if item.IsDir() {
- err := os.Mkdir(filepath.Join(temp, item.Name()), os.ModeDir|os.ModePerm)
- if err != nil {
- return err
- }
- }
-
- err := copyAll(src, temp)
- if err != nil {
- return err
- }
-
- fmt.Println(" [-]", item.Name())
-
- }
-
- // remove all files in path
- for _, item := range list {
- err := os.RemoveAll(filepath.Join(path, item.Name()))
- if err != nil {
- return fmt.Errorf("Failed to remove old Ponzu files.\n%s", err)
- }
- }
-
- err = createProjectInDir(path)
- if err != nil {
- fmt.Println("")
- fmt.Println("Upgrade failed...")
- fmt.Println("Your code is backed up at the following location:")
- fmt.Println(temp)
- fmt.Println("")
- fmt.Println("Manually create a new Ponzu project here and copy those files within it to fully restore.")
- fmt.Println("")
- return err
- }
-
- // move non-Ponzu files from temp location backed
- restore, err := ioutil.ReadDir(temp)
- if err != nil {
- return err
- }
-
- fmt.Println("Restoring files preserved before upgrade...")
- for _, r := range restore {
- p := filepath.Join(temp, r.Name())
- err = copyAll(p, path)
- if err != nil {
- fmt.Println("Couldn't merge your previous project files with upgraded one.")
- fmt.Println("Manually copy your files from the following directory:")
- fmt.Println(temp)
- return err
- }
-
- fmt.Println(" [+]", r.Name())
- }
-
- // clean-up
- backups := []string{filepath.Join(path, stamp), temp}
- for _, bak := range backups {
- err := os.RemoveAll(bak)
- if err != nil {
- return err
- }
- }
-
- return nil
-}
diff --git a/cmd/ponzu/upgrade.go b/cmd/ponzu/upgrade.go
new file mode 100644
index 0000000..252a4f8
--- /dev/null
+++ b/cmd/ponzu/upgrade.go
@@ -0,0 +1,169 @@
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/spf13/cobra"
+)
+
+var upgradeCmd = &cobra.Command{
+ Use: "upgrade",
+ Short: "upgrades your project to the current ponzu version",
+ Long: `Will backup your own custom project code (like content, addons, uploads, etc) so
+if necessary. Before running '$ ponzu upgrade', you should update the 'ponzu'
+package by running '$ go get -u github.com/ponzu-cms/ponzu/...'
+
+Example:
+$ ponzu upgrade`,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ // confirm since upgrade will replace Ponzu core files
+ path, err := os.Getwd()
+ if err != nil {
+ return fmt.Errorf("Failed to find current directory: %s", err)
+ }
+
+ fmt.Println("Only files you added to this directory, 'addons' and 'content' will be preserved.")
+ fmt.Println("Upgrade this project? (y/N):")
+
+ answer, err := getAnswer()
+ if err != nil {
+ return err
+ }
+
+ switch answer {
+ case "n", "no", "\r\n", "\n", "":
+ fmt.Println("")
+
+ case "y", "yes":
+ err := upgradePonzuProjectDir(path)
+ if err != nil {
+ return err
+ }
+
+ default:
+ fmt.Println("Input not recognized. No upgrade made. Answer as 'y' or 'n' only.")
+ }
+ return nil
+ },
+}
+
+func upgradePonzuProjectDir(path string) error {
+ core := []string{
+ ".gitattributes",
+ "LICENSE",
+ "ponzu-banner.png",
+ "README.md",
+ "cmd",
+ "deployment",
+ "management",
+ "system",
+ }
+
+ stamp := fmt.Sprintf("ponzu-%d.bak", time.Now().Unix())
+ temp := filepath.Join(os.TempDir(), stamp)
+ err := os.Mkdir(temp, os.ModeDir|os.ModePerm)
+ if err != nil {
+ return err
+ }
+
+ // track non-Ponzu core items (added by user)
+ var user []os.FileInfo
+ list, err := ioutil.ReadDir(path)
+ if err != nil {
+ return err
+ }
+
+ for _, item := range list {
+ // check if in core
+ var isCore bool
+ for _, name := range core {
+ if item.Name() == name {
+ isCore = true
+ break
+ }
+ }
+
+ if !isCore {
+ user = append(user, item)
+ }
+ }
+
+ // move non-Ponzu files to temp location
+ fmt.Println("Preserving files to be restored after upgrade...")
+ for _, item := range user {
+ src := filepath.Join(path, item.Name())
+ if item.IsDir() {
+ err := os.Mkdir(filepath.Join(temp, item.Name()), os.ModeDir|os.ModePerm)
+ if err != nil {
+ return err
+ }
+ }
+
+ err := copyAll(src, temp)
+ if err != nil {
+ return err
+ }
+
+ fmt.Println(" [-]", item.Name())
+
+ }
+
+ // remove all files in path
+ for _, item := range list {
+ err := os.RemoveAll(filepath.Join(path, item.Name()))
+ if err != nil {
+ return fmt.Errorf("Failed to remove old Ponzu files.\n%s", err)
+ }
+ }
+
+ err = createProjectInDir(path)
+ if err != nil {
+ fmt.Println("")
+ fmt.Println("Upgrade failed...")
+ fmt.Println("Your code is backed up at the following location:")
+ fmt.Println(temp)
+ fmt.Println("")
+ fmt.Println("Manually create a new Ponzu project here and copy those files within it to fully restore.")
+ fmt.Println("")
+ return err
+ }
+
+ // move non-Ponzu files from temp location backed
+ restore, err := ioutil.ReadDir(temp)
+ if err != nil {
+ return err
+ }
+
+ fmt.Println("Restoring files preserved before upgrade...")
+ for _, r := range restore {
+ p := filepath.Join(temp, r.Name())
+ err = copyAll(p, path)
+ if err != nil {
+ fmt.Println("Couldn't merge your previous project files with upgraded one.")
+ fmt.Println("Manually copy your files from the following directory:")
+ fmt.Println(temp)
+ return err
+ }
+
+ fmt.Println(" [+]", r.Name())
+ }
+
+ // clean-up
+ backups := []string{filepath.Join(path, stamp), temp}
+ for _, bak := range backups {
+ err := os.RemoveAll(bak)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func init() {
+ rootCmd.AddCommand(upgradeCmd)
+}
diff --git a/cmd/ponzu/usage.go b/cmd/ponzu/usage.go
index 1f1364d..1571ad0 100644
--- a/cmd/ponzu/usage.go
+++ b/cmd/ponzu/usage.go
@@ -4,175 +4,34 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
+ "os"
"path/filepath"
- "time"
-)
-
-var year = fmt.Sprintf("%d", time.Now().Year())
-
-var usageHeader = `
-$ ponzu [flags] command <params>
-
-Ponzu is a powerful and efficient open-source HTTP server framework and CMS. It
-provides automatic, free, and secure HTTP/2 over TLS (certificates obtained via
-[Let's Encrypt](https://letsencrypt.org)), a useful CMS and scaffolding to
-generate set-up code, and a fast HTTP API on which to build modern applications.
-
-Ponzu is released under the BSD-3-Clause license (see LICENSE).
-(c) 2016 - ` + year + ` Boss Sauce Creative, LLC
-
-COMMANDS:
-
-`
-
-var usageHelp = `
-help, h (command)
-
- Help command will print the usage for Ponzu, or if a command is entered, it
- will show only the usage for that specific command.
-
- Example:
- $ ponzu help generate
-
-
-`
-
-var usageNew = `
-new <directory>
-
- Creates a 'ponzu' directory, or one by the name supplied as a parameter
- immediately following the 'new' option in the $GOPATH/src directory. Note:
- 'new' depends on the program 'git' and possibly a network connection. If
- there is no local repository to clone from at the local machine's $GOPATH,
- 'new' will attempt to clone the 'github.com/ponzu-cms/ponzu' package from
- over the network.
-
- Example:
- $ ponzu new myProject
- > New ponzu project created at $GOPATH/src/myProject
-
- Errors will be reported, but successful commands return nothing.
-
-
-`
-
-var usageGenerate = `
-generate, gen, g <generator type (,...fields)>
-
- Generate boilerplate code for various Ponzu components, such as 'content'.
-
- Example:
- $ ponzu gen content review title:"string" body:"string" rating:"int" tags:"[]string"
-
- The command above will generate a file 'content/review.go' with boilerplate
- methods, as well as struct definition, and corresponding field tags like:
-
- type Review struct {
- Title string ` + "`json:" + `"title"` + "`" + `
- Body string ` + "`json:" + `"body"` + "`" + `
- Rating int ` + "`json:" + `"rating"` + "`" + `
- Tags []string ` + "`json:" + `"tags"` + "`" + `
- }
-
- The generate command will intelligently parse more sophisticated field names
- such as 'field_name' and convert it to 'FieldName' and vice versa, only where
- appropriate as per common Go idioms. Errors will be reported, but successful
- generate commands return nothing.
-
-
-`
-
-var usageBuild = `
-[-gocmd=go] build
-
- From within your Ponzu project directory, running build will copy and move
- the necessary files from your workspace into the vendored directory, and
- will build/compile the project to then be run.
-
- Example:
- $ ponzu build
- (or)
- $ ponzu -gocmd=go1.8rc1 build
-
- By providing the 'gocmd' flag, you can specify which Go command to build the
- project, if testing a different release of Go.
- Errors will be reported, but successful build commands return nothing.
-
-
-`
-
-var usageRun = `
-[[-port=8080] [--https|--devhttps]] run <service(,service)>
-
- Starts the 'ponzu' HTTP server for the JSON API, Admin System, or both.
- The segments, separated by a comma, describe which services to start, either
- 'admin' (Admin System / CMS backend) or 'api' (JSON API), and, optionally,
- if the server should utilize TLS encryption - served over HTTPS, which is
- automatically managed using Let's Encrypt (https://letsencrypt.org)
-
- Example:
- $ ponzu run
- (or)
- $ ponzu -port=8080 --https run admin,api
- (or)
- $ ponzu run admin
- (or)
- $ ponzu -port=8888 run api
-
- Defaults to '-port=8080 run admin,api' (running Admin & API on port 8080, without TLS)
-
- Note:
- Admin and API cannot run on separate processes unless you use a copy of the
- database, since the first process to open it receives a lock. If you intend
- to run the Admin and API on separate processes, you must call them with the
- 'ponzu' command independently.
-
-
-`
-
-var usageUpgrade = `
-upgrade
-
- Will backup your own custom project code (like content, addons, uploads, etc) so
- we can safely re-clone Ponzu from the latest version you have or from the network
- if necessary. Before running '$ ponzu upgrade', you should update the 'ponzu'
- package by running '$ go get -u github.com/ponzu-cms/ponzu/...'
-
- Example:
- $ ponzu upgrade
-
-
-`
-
-var usageVersion = `
-[--cli] version, v
-
- Prints the version of Ponzu your project is using. Must be called from
- within a Ponzu project directory.
-
- Example:
- $ ponzu version
- > Ponzu v0.7.1
- (or)
- $ ponzu --cli version
- > Ponzu v0.7.2
-
-
-`
-
-var usageAdd = `
-add, a <import path>
-
- Downloads addon from specified import path to $GOPATH/src and copys it to the
- current project's ./addons directory. Must be called from within a
- Ponzu project directory.
-
- Example:
- $ ponzu add github.com/bosssauce/fbscheduler
+ "github.com/spf13/cobra"
+)
+var versionCmd = &cobra.Command{
+ Use: "version",
+ Short: "Prints the version of Ponzu your project is using.",
+ Long: `Prints the version of Ponzu your project is using. Must be called from
+within a Ponzu project directory.
+
+Example:
+$ ponzu version
+> Ponzu v0.7.1
+(or)
+$ ponzu --cli version
+> Ponzu v0.7.2`,
+ Run: func(cmd *cobra.Command, args []string) {
+ p, err := ponzu(cli)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
-`
+ fmt.Fprintf(os.Stdout, "Ponzu v%s\n", p["version"])
+ },
+}
func ponzu(isCLI bool) (map[string]interface{}, error) {
kv := make(map[string]interface{})
@@ -199,3 +58,8 @@ func ponzu(isCLI bool) (map[string]interface{}, error) {
return kv, nil
}
+
+func init() {
+ versionCmd.Flags().BoolVar(&cli, "cli", false, "specify that information should be returned about the CLI, not project")
+ rootCmd.AddCommand(versionCmd)
+}