|
|
|
package caddyhugo
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"path"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/spf13/afero"
|
|
|
|
|
|
|
|
"git.stephensearles.com/stephen/acedoc"
|
|
|
|
"git.stephensearles.com/stephen/idleshut"
|
|
|
|
)
|
|
|
|
|
|
|
|
type editSession struct {
|
|
|
|
clients uint
|
|
|
|
docname string
|
|
|
|
filename string
|
|
|
|
doc *acedoc.Document
|
|
|
|
tmpfs afero.Fs
|
|
|
|
mtx sync.Mutex
|
|
|
|
}
|
|
|
|
|
|
|
|
func (es *editSession) Clients() uint {
|
|
|
|
es.mtx.Lock()
|
|
|
|
defer es.mtx.Unlock()
|
|
|
|
|
|
|
|
return es.clients
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ch *CaddyHugo) newEditSession(docName string) (*editSession, error) {
|
|
|
|
filename := ch.docFilename(docName)
|
|
|
|
|
|
|
|
fmt.Println("opening", filename)
|
|
|
|
contents, err := ioutil.ReadFile(filename)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpfs := afero.NewCopyOnWriteFs(afero.NewOsFs(), afero.NewMemMapFs())
|
|
|
|
|
|
|
|
es := &editSession{
|
|
|
|
docname: docName,
|
|
|
|
filename: filename,
|
|
|
|
doc: acedoc.NewString(string(contents)),
|
|
|
|
tmpfs: tmpfs,
|
|
|
|
}
|
|
|
|
|
|
|
|
err = es.doc.LogToFile(path.Join(ch.Dir, "logs", docName))
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
ch.docs[filename] = es
|
|
|
|
|
|
|
|
err = ch.renderDraft(es)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return es, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ch *CaddyHugo) renderDraft(es *editSession) error {
|
|
|
|
var proc *idleshut.Process
|
|
|
|
|
|
|
|
f := func() {
|
|
|
|
if es.clients != 0 {
|
|
|
|
proc.Touch()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg, err := HugoInternalProcessConfig(ch, es, f)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("rendering draft: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
proc = idleshut.New(cfg)
|
|
|
|
return proc.Start()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ch *CaddyHugo) persistAllEdits() error {
|
|
|
|
ch.mtx.Lock()
|
|
|
|
defer ch.mtx.Unlock()
|
|
|
|
for _, es := range ch.docs {
|
|
|
|
err := ch.persistEditsForSession(es)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ch *CaddyHugo) persistEditsForSession(es *editSession) error {
|
|
|
|
err := afero.WriteFile(afero.NewOsFs(), es.filename, []byte(es.doc.Contents()), 0644)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ch *CaddyHugo) hasEditSession(docName string) (*editSession, bool) {
|
|
|
|
dr, ok := ch.docs[ch.docFilename(docName)]
|
|
|
|
return dr, ok
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ch *CaddyHugo) editSession(docName string) (*editSession, error) {
|
|
|
|
ch.mtx.Lock()
|
|
|
|
defer ch.mtx.Unlock()
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
|
|
|
dr, ok := ch.hasEditSession(docName)
|
|
|
|
if !ok {
|
|
|
|
dr, err = ch.newEditSession(docName)
|
|
|
|
}
|
|
|
|
|
|
|
|
return dr, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func docNameFromEditRequest(r *http.Request) string {
|
|
|
|
return r.URL.Path[len("/hugo/edit/"):]
|
|
|
|
}
|
|
|
|
|
|
|
|
func docNameFromCommentRequest(r *http.Request) string {
|
|
|
|
return r.URL.Path[1 : len(r.URL.Path)-len("/comments")]
|
|
|
|
}
|