diff options
Diffstat (limited to 'cmd/cms')
-rw-r--r-- | cmd/cms/main.go | 119 | ||||
-rw-r--r-- | cmd/cms/options.go | 242 |
2 files changed, 0 insertions, 361 deletions
diff --git a/cmd/cms/main.go b/cmd/cms/main.go deleted file mode 100644 index c2f1bf1..0000000 --- a/cmd/cms/main.go +++ /dev/null @@ -1,119 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "log" - "net/http" - "os" - - "github.com/nilslice/cms/system/admin" - "github.com/nilslice/cms/system/api" - "github.com/nilslice/cms/system/db" -) - -var usage = ` -$ cms <option> <params> - -Options - -new <directory>: - - Creates a new 'cms' in the current directory, or one supplied - as a parameter immediately following the 'new' option. 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 'cms' package from over the network. - - Example: - $ cms new ~/Projects/my-project.dev - - - -generate, gen, g <type>: - - Generate a content type file with boilerplate code to implement - the editor.Editable interface. Must be given one (1) parameter of - the name of the type for the new content. - - Example: - $ cms gen review - - - -serve, s <service> <port> <tls>: - - Starts the 'cms' HTTP server for the JSON API, Admin System, or both. - Must be given at least one (1) parameter. The segments describe - which services to start, either 'admin' (Admin System / CMS - backend) or 'api' (JSON API), and, optionally, if the server(s) should - utilize TLS encryption (served over HTTPS), which is automatically managed - using Let's Encrypt (https://letsencrypt.org) - - Example: - $ cms serve admin|api 8080 tls - (or) - $ cms serve admin - (or) - $ cms serve api 8888 - - Defaults to 'admin|api 8080' (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 recieves a lock. If you intend - to run the Admin and API on separate processes, you must call them with the - 'cms' command independently. -` - -func init() { - flag.Usage = func() { - fmt.Println(usage) - } -} - -func main() { - flag.Parse() - - args := flag.Args() - - if len(args) < 1 { - flag.Usage() - os.Exit(0) - } - - switch args[0] { - case "new": - if len(args) < 2 { - flag.PrintDefaults() - os.Exit(0) - } - - err := newProjectInDir(args[1]) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - case "generate", "gen", "g": - if len(args) < 2 { - flag.PrintDefaults() - os.Exit(0) - } - - err := generateContentType(args[1]) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - case "serve", "s": - db.Init() - admin.Run() - api.Run() - log.Fatal(http.ListenAndServe(":8080", nil)) - case "": - flag.PrintDefaults() - default: - flag.PrintDefaults() - } -} diff --git a/cmd/cms/options.go b/cmd/cms/options.go deleted file mode 100644 index 94c809f..0000000 --- a/cmd/cms/options.go +++ /dev/null @@ -1,242 +0,0 @@ -package main - -import ( - "bytes" - "fmt" - "html/template" - "os" - "os/exec" - "path/filepath" - "strings" -) - -func generateContentType(name string) error { - fileName := strings.ToLower(name) + ".go" - typeName := strings.ToUpper(string(name[0])) + string(name[1:]) - - // contain processed name an info for template - data := map[string]string{ - "name": typeName, - "initial": string(fileName[0]), - } - - // open file in ./content/ dir - // if exists, alert user of conflict - pwd, err := os.Getwd() - if err != nil { - return err - } - - contentDir := filepath.Join(pwd, "content") - filePath := filepath.Join(contentDir, fileName) - - if _, err := os.Stat(filePath); !os.IsNotExist(err) { - return fmt.Errorf("Please remove '%s' before executing this command.", fileName) - } - - // no file exists.. ok to write new one - file, err := os.Create(filePath) - defer file.Close() - if err != nil { - return err - } - - // execute template - tmpl := template.Must(template.New("content").Parse(contentTypeTmpl)) - err = tmpl.Execute(file, data) - if err != nil { - return err - } - - return nil -} - -const contentTypeTmpl = ` -package content - -import ( - "fmt" - - "github.com/nilslice/cms/management/editor" -) - -// {{ .name }} is the generic content struct -type {{ .name }} struct { - Item - editor editor.Editor - - // required: all maintained {{ .name }} fields must have json tags! - Title string ` + "`json:" + `"title"` + "`" + ` - Content string ` + "`json:" + `"content"` + "`" + ` - Author string ` + "`json:" + `"author"` + "`" + ` - Category []string ` + "`json:" + `"category"` + "`" + ` - ThemeStyle string ` + "`json:" + `"theme"` + "`" + ` -} - -func init() { - Types["{{ .name }}"] = func() interface{} { return new({{ .name }}) } -} - -// SetContentID partially implements editor.Editable -func ({{ .initial }} *{{ .name }}) SetContentID(id int) { {{ .initial }}.ID = id } - -// ContentID partially implements editor.Editable -func ({{ .initial }} *{{ .name }}) ContentID() int { return {{ .initial }}.ID } - -// ContentName partially implements editor.Editable -func ({{ .initial }} *{{ .name }}) ContentName() string { return {{ .initial }}.Title } - -// SetSlug partially implements editor.Editable -func ({{ .initial }} *{{ .name }}) SetSlug(slug string) { {{ .initial }}.Slug = slug } - -// Editor partially implements editor.Editable -func ({{ .initial }} *{{ .name }}) Editor() *editor.Editor { return &{{ .initial }}.editor } - -// MarshalEditor writes a buffer of html to edit a {{ .name }} and partially implements editor.Editable -func ({{ .initial }} *{{ .name }}) MarshalEditor() ([]byte, error) { -/* EXAMPLE CODE (from post.go, the default content type) */ - view, err := editor.Form({{ .initial }}, - editor.Field{ - // Take careful note that the first argument to these Input-like methods - // is the string version of each {{ .name }} struct tag, and must follow this pattern - // for auto-decoding and -encoding reasons. - View: editor.Input("Title", {{ .initial }}, map[string]string{ - "label": "{{ .name }} Title", - "type": "text", - "placeholder": "Enter your {{ .name }} Title here", - }), - }, - editor.Field{ - View: editor.Textarea("Content", {{ .initial }}, map[string]string{ - "label": "Content", - "placeholder": "Add the content of your {{ .name }} here", - }), - }, - editor.Field{ - View: editor.Input("Author", {{ .initial }}, map[string]string{ - "label": "Author", - "type": "text", - "placeholder": "Enter the author name here", - }), - }, - editor.Field{ - View: editor.Checkbox("Category", {{ .initial }}, map[string]string{ - "label": "{{ .name }} Category", - }, map[string]string{ - "important": "Important", - "active": "Active", - "unplanned": "Unplanned", - }), - }, - editor.Field{ - View: editor.Select("ThemeStyle", {{ .initial }}, map[string]string{ - "label": "Theme Style", - }, map[string]string{ - "dark": "Dark", - "light": "Light", - }), - }, - ) - - if err != nil { - return nil, fmt.Errorf("Failed to render {{ .name }} editor view: %s", err.Error()) - } - - return view, nil -} -` - -func newProjectInDir(path string) error { - // 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):") - // input := bufio.NewReader(os.Stdin) - // answer, err := input.ReadString('\n') - - var answer string - _, err := fmt.Scanf("%s\n", &answer) - if err != nil { - return err - } - - answer = strings.ToLower(answer) - - switch answer { - case "n", "no", "": - fmt.Println("") - - case "y", "yes": - err := os.RemoveAll(path) - if err != nil { - return fmt.Errorf("Failed to overwrite %s. \n%s", path, err) - } - - return createProjInDir(path) - - default: - fmt.Println("Input not recognized. No files overwritten. Answer as 'y' or 'n' only.") - } - - return nil - } - - return createProjInDir(path) -} - -func createProjInDir(path string) error { - var buf = &bytes.Buffer{} - echo := exec.Command("echo", os.Getenv("GOPATH")) - echo.Stdout = buf - err := echo.Run() - if err != nil { - return err - } - - gopath := buf.String() - gopath = gopath[:len(gopath)-1] - gopath = filepath.Join(gopath, "src") - - repo := []string{"github.com", "nilslice", "cms"} - local := filepath.Join(gopath, filepath.Join(repo...)) - network := "https://" + strings.Join(repo, "/") + ".git" - - // create the directory or overwrite it - err = os.MkdirAll(path, os.ModeDir|os.ModePerm) - if err != nil { - return err - } - - // 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) - } - } - - fmt.Println("New project created at", path) - return nil -} |