summaryrefslogtreecommitdiff
path: root/examples/docker/admin/cmd/ponzu/options.go
diff options
context:
space:
mode:
Diffstat (limited to 'examples/docker/admin/cmd/ponzu/options.go')
-rw-r--r--examples/docker/admin/cmd/ponzu/options.go489
1 files changed, 489 insertions, 0 deletions
diff --git a/examples/docker/admin/cmd/ponzu/options.go b/examples/docker/admin/cmd/ponzu/options.go
new file mode 100644
index 0000000..77e842c
--- /dev/null
+++ b/examples/docker/admin/cmd/ponzu/options.go
@@ -0,0 +1,489 @@
+package main
+
+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) {
+ var answer string
+ _, err := fmt.Scanf("%s\n", &answer)
+ if err != nil {
+ if err.Error() == "unexpected newline" {
+ answer = ""
+ } else {
+ return "", err
+ }
+ }
+
+ answer = strings.ToLower(answer)
+
+ 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)
+ if err != nil {
+ return err
+ }
+
+ dirs := []string{"content", "management", "system"}
+ for _, dir := range dirs {
+ err = os.Rename(filepath.Join(path, dir), filepath.Join(vendorPath, dir))
+ if err != nil {
+ return err
+ }
+ }
+
+ // create a user content directory at project root
+ contentPath := filepath.Join(path, "content")
+ err = os.Mkdir(contentPath, os.ModeDir|os.ModePerm)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func copyFileNoRoot(src, dst string) error {
+ noRoot := strings.Split(src, string(filepath.Separator))[1:]
+ path := filepath.Join(noRoot...)
+ dstFile, err := os.Create(filepath.Join(dst, path))
+ defer dstFile.Close()
+ if err != nil {
+ return err
+ }
+
+ srcFile, err := os.Open(src)
+ defer srcFile.Close()
+ if err != nil {
+ return err
+ }
+
+ _, err = io.Copy(dstFile, srcFile)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func copyFilesWarnConflicts(srcDir, dstDir string, conflicts []string) error {
+ err := filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+
+ for _, conflict := range conflicts {
+ if info.Name() == conflict {
+ fmt.Println("Ponzu couldn't fully build your project:")
+ fmt.Println("You must rename the following file, as it conflicts with Ponzu core:")
+ fmt.Println(path)
+ fmt.Println("")
+ fmt.Println("Once the files above have been renamed, run '$ ponzu build' to retry.")
+ return errors.New("Ponzu has very few internal conflicts, sorry for the inconvenience.")
+ }
+ }
+
+ if info.IsDir() {
+ // don't copy root directory
+ if path == srcDir {
+ return nil
+ }
+
+ if len(path) > len(srcDir) {
+ path = path[len(srcDir)+1:]
+ }
+ dir := filepath.Join(dstDir, path)
+ err := os.MkdirAll(dir, os.ModeDir|os.ModePerm)
+ if err != nil {
+ return err
+ }
+
+ return nil
+ }
+
+ err = copyFileNoRoot(path, dstDir)
+ if err != nil {
+ return err
+ }
+
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func emptyDir(path string) error {
+ d, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ defer d.Close()
+
+ names, err := d.Readdirnames(-1)
+ if err != nil {
+ return err
+ }
+ for _, name := range names {
+ err = os.RemoveAll(filepath.Join(path, name))
+ if err != nil {
+ return err
+ }
+ }
+
+ 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 {
+ return err
+ }
+
+ sep := string(filepath.Separator)
+
+ // base == the ponzu project dir + string(filepath.Separator)
+ parts := strings.Split(src, sep)
+ base := strings.Join(parts[:len(parts)-1], sep)
+ base += sep
+
+ target := filepath.Join(dst, path[len(base):])
+
+ // if its a directory, make dir in dst
+ if info.IsDir() {
+ err := os.MkdirAll(target, os.ModeDir|os.ModePerm)
+ if err != nil {
+ return err
+ }
+ } else {
+ // if its a file, move file to dir of dst
+ err = os.Rename(path, target)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+
+ 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
+}