Skip to content

Commit

Permalink
Merge pull request #7 from altid/testing
Browse files Browse the repository at this point in the history
#6 - start work on providing a mock control type
  • Loading branch information
halfwit authored Feb 28, 2020
2 parents 62ed344 + 316a345 commit 6e0d53a
Show file tree
Hide file tree
Showing 8 changed files with 621 additions and 406 deletions.
372 changes: 99 additions & 273 deletions fs/ctl.go

Large diffs are not rendered by default.

302 changes: 302 additions & 0 deletions fs/default_ctl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,302 @@
package fs

import (
"bufio"
"context"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"strings"
)

type control struct {
rundir string
logdir string
doctype string
tabs []string
req chan string
done chan struct{}
}

func (c *control) event(eventmsg string) error {
err := validateString(eventmsg)
if err != nil {
return err
}

file := path.Join(c.rundir, "event")
if _, err := os.Stat(path.Dir(file)); os.IsNotExist(err) {
os.MkdirAll(path.Dir(file), 0755)
}

f, err := os.OpenFile(file, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
defer f.Close()
if err != nil {
return err
}

f.WriteString(eventmsg + "\n")
return nil
}

func (c *control) cleanup() {
if runtime.GOOS == "plan9" {
glob := path.Join(c.rundir, "*", c.doctype)
files, err := filepath.Glob(glob)
if err != nil {
log.Print(err)
}
for _, f := range files {
command := exec.Command("/bin/unmount", f)
log.Print(command.Run())
}
}
os.RemoveAll(c.rundir)
}

func (c *control) createBuffer(name, doctype string) error {
if name == "" {
return fmt.Errorf("no buffer name given")
}

fp := path.Join(c.rundir, name)
d := path.Join(fp, doctype)

if _, e := os.Stat(fp); !os.IsNotExist(e) {
return e
}

if e := os.MkdirAll(fp, 0755); e != nil {
return e
}

if e := ioutil.WriteFile(d, []byte("Welcome!\n"), 0644); e != nil {
return e
}

if e := c.pushTab(name); e != nil {
return e
}

// If there is no log, we're done otherwise create symlink
if c.logdir == "none" {
return nil
}

logfile := path.Join(c.logdir, name)

return symlink(logfile, d)
}

func (c *control) deleteBuffer(name, doctype string) error {
if c.logdir != "none" {
d := path.Join(c.rundir, name, doctype)
if e := unlink(d); e != nil {
return e
}
}

defer os.RemoveAll(path.Join(c.rundir, name))

return c.popTab(name)
}

func (c *control) hasBuffer(name, doctype string) bool {
d := path.Join(c.rundir, name, doctype)

if _, e := os.Stat(d); os.IsNotExist(e) {
return false
}

return true
}
func (c *control) listen() error {
if e := os.MkdirAll(c.rundir, 0755); e != nil {
return e
}

cfile := path.Join(c.rundir, "ctl")

r, err := newReader(cfile)
if err != nil {
return err
}

c.event(cfile)
scanner := bufio.NewScanner(r)

for scanner.Scan() {
line := scanner.Text()
if line == "quit" {
close(c.done)
break
}

c.req <- line
}

close(c.req)
return nil
}

func (c *control) remove(buffer, filename string) error {
doc := path.Join(c.rundir, buffer, filename)
// Don't try to delete that which isn't there
if _, e := os.Stat(doc); os.IsNotExist(e) {
return nil
}
c.event(doc)
return os.Remove(doc)
}

func (c *control) start() (context.Context, error) {
if e := os.MkdirAll(c.rundir, 0755); e != nil {
return nil, e
}

cfile := path.Join(c.rundir, "ctl")
c.event(cfile)

r, err := newReader(cfile)
if err != nil {
return nil, err
}

ctx, cancel := context.WithCancel(context.Background())

go func() {
defer close(c.req)
scanner := bufio.NewScanner(r)

for scanner.Scan() {
line := scanner.Text()
if line == "quit" {
cancel()
close(c.done)
break
}

c.req <- line
}
}()

return ctx, nil
}

func (c *control) notification(buff, from, msg string) error {
nfile := path.Join(c.rundir, buff, "notification")
if _, e := os.Stat(path.Dir(nfile)); os.IsNotExist(e) {
os.MkdirAll(path.Dir(nfile), 0755)
}

f, err := os.OpenFile(nfile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return err
}

defer f.Close()

c.event(nfile)
fmt.Fprintf(f, "%s\n%s\n", from, msg)

return nil
}

func (c *control) popTab(tabname string) error {
for n := range c.tabs {
if c.tabs[n] == tabname {
c.tabs = append(c.tabs[:n], c.tabs[n+1:]...)
return tabs(c)
}
}
return fmt.Errorf("entry not found: %s", tabname)
}

func (c *control) pushTab(tabname string) error {
err := validateString(tabname)
if err != nil {
return err
}
for n := range c.tabs {
if c.tabs[n] == tabname {
return fmt.Errorf("entry already exists: %s", tabname)
}
}
c.tabs = append(c.tabs, tabname)

return tabs(c)
}

func tabs(c *control) error {
// Create truncates and opens file in a single step, utilize this.
file := path.Join(c.rundir, "tabs")
f, err := os.Create(file)
defer f.Close()
if err != nil {
return err
}
f.WriteString(strings.Join(c.tabs, "\n") + "\n")
c.event(file)

return nil
}

func (c *control) errorwriter() (*WriteCloser, error) {
ep := path.Join(c.rundir, "errors")

fp, err := os.OpenFile(ep, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {

return nil, err
}

w := &WriteCloser{
c: c,
fp: fp,
buffer: "errors",
}

return w, nil
}

func (c *control) fileWriter(buffer, doctype string) (*WriteCloser, error) {
doc := path.Join(c.rundir, buffer, doctype)
if doctype == "feed" {
fp, err := os.OpenFile(doc, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {

return nil, err
}
w := &WriteCloser{
fp: fp,
c: c,
buffer: doc,
}

return w, nil
}

// Abuse truncation semantics of Create so we clear any old data
fp, err := os.Create(doc)
if err != nil {
return nil, err
}

w := &WriteCloser{
fp: fp,
c: c,
buffer: doc,
}

return w, nil
}

func (c *control) imageWriter(buffer, resource string) (*WriteCloser, error) {
os.MkdirAll(path.Dir(path.Join(c.rundir, buffer, "images", resource)), 0755)
return c.fileWriter(buffer, path.Join("images", resource))
}
Loading

0 comments on commit 6e0d53a

Please sign in to comment.