@@ 23,7 23,7 @@ type GoquiturHandler struct {
sublock *sync.Mutex
urlsubs map[WebPath][]*websocket.Conn
// what was I supposed to be using this for again?
- suburls map[*websocket.Conn][]WebPath
+ //suburls map[*websocket.Conn][]WebPath
}
func NewGoquiturHandler(watchdir string) (*GoquiturHandler, error) {
@@ 46,7 46,7 @@ func NewGoquiturHandler(watchdir string)
watcher: watcher,
sublock: new(sync.Mutex),
urlsubs: make(map[WebPath][]*websocket.Conn),
- suburls: make(map[*websocket.Conn][]WebPath),
+ //suburls: make(map[*websocket.Conn][]WebPath),
}
h.ServeMux.Handle("/", http.FileServer(http.Dir("static")))
h.ServeMux.Handle("/ws", websocket.Handler(h.serveWS))
@@ 73,7 73,13 @@ func (h *GoquiturHandler) LocationFromWe
}
func (h *GoquiturHandler) LocationFromFilePath(path FSPath) (*Location, error) {
+ // this could use some work ... and unit testing, sheesh ...
webpath, err := filepath.Rel(h.watchdir, string(path))
+ if webpath == "." {
+ webpath = "/"
+ } else {
+ webpath = "/" + webpath
+ }
if err != nil {
return nil, err
}
@@ 89,6 95,54 @@ func (h *GoquiturHandler) Subscribers(pa
return make([]*websocket.Conn, 0)
}
+func (h *GoquiturHandler) Subscribe(ws *websocket.Conn, path WebPath) {
+ h.sublock.Lock()
+ defer h.sublock.Unlock()
+
+ subs, ok := h.urlsubs[path]
+ if ok == false {
+ subs = make([]*websocket.Conn, 0)
+ }
+ h.urlsubs[path] = append(subs, ws)
+
+ //urls, ok := h.suburls[ws]
+ //if ok == false {
+ // urls = make([]WebPath, 0)
+ //}
+ //h.suburls[ws] = append(urls, path)
+}
+
+func (h *GoquiturHandler) Unsubscribe(ws *websocket.Conn, path WebPath) {
+ h.sublock.Lock()
+ defer h.sublock.Unlock()
+
+ // Remove ws from subs at loc.WebPath
+ subs, ok := h.urlsubs[path]
+ if ok {
+ for i := 0; i < len(subs); {
+ if subs[i] == ws {
+ subs = append(subs[:i], subs[i+1:]...)
+ } else {
+ i++
+ }
+ }
+ h.urlsubs[path] = subs
+ }
+
+ //// Remove path from subscribed paths for this URL
+ //urls, ok := h.suburls[ws]
+ //if ok == false {
+ // for i := 0; i < len(urls) {
+ // if urls[i] == path {
+ // urls = append(urls[:i], urls[i+1:]...)
+ // } else {
+ // i++
+ // }
+ // }
+ // h.suburls[ws] = append(urls, path)
+ //}
+}
+
func (h *GoquiturHandler) handleEvents(evchan <-chan *Event, errchan <-chan error) {
for {
select {
@@ 107,9 161,14 @@ func (h *GoquiturHandler) handleEvents(e
continue
}
+ log.Println(h.urlsubs)
+ log.Println(loc.WebPath)
+
switch ev.Type {
case EventCreate:
+ fallthrough
case EventModify:
+ fallthrough
case EventDelete:
var data []byte
for _, sub := range h.Subscribers(loc.WebPath) {
@@ 138,7 197,9 @@ func (h *GoquiturHandler) handleEvents(e
}
}
go func() {
+ log.Println("gonna write data for event to", sub)
_, err = sub.Write(data)
+ log.Println("wrote data", sub, err)
if err != nil {
log.Println("Error writing to a client:", err)
// todo, remove subscriber?
@@ 193,32 254,24 @@ func (h *GoquiturHandler) serveOneWS(ws
})
}
- // Get the payload
- payload, err := getPayload(validpath)
- if err != nil {
- return websocket.JSON.Send(ws, &Error{
- Message: "Could not read resource",
- Details: err.Error(),
- })
+ var payload interface{}
+
+ if r.Subscribe {
+ // Get the payload
+ payload, err = getPayload(validpath)
+ if err != nil {
+ return websocket.JSON.Send(ws, &Error{
+ Message: "Could not read resource",
+ Details: err.Error(),
+ })
+ }
+
+ h.Subscribe(ws, r.Path)
+ } else {
+ h.Unsubscribe(ws, r.Path)
}
- // Subscribe to the resource
- h.sublock.Lock()
- defer h.sublock.Unlock()
-
- subs, ok := h.urlsubs[loc.WebPath]
- if ok == false {
- subs = make([]*websocket.Conn, 0)
- }
- h.urlsubs[loc.WebPath] = append(subs, ws)
-
- urls, ok := h.suburls[ws]
- if ok == false {
- urls = make([]WebPath, 0)
- }
- h.suburls[ws] = append(urls, loc.WebPath)
-
- // Send the resource
+ log.Println("subscribing:", ws, loc.WebPath, r.Subscribe)
return websocket.JSON.Send(ws, &Message{
Path: loc.WebPath,
Payload: payload,
@@ 23,19 23,38 @@ func processLoop(w *fsnotify.Watcher, ev
continue
}
- ev := new(Event)
- ev.Path = path
- if fsev.IsDelete() || fsev.IsRename() {
- ev.Type = EventDelete
- } else if fsev.IsModify() {
- ev.Type = EventModify
+ if fsev.IsModify() {
+ evchan <- &Event{
+ Type: EventModify,
+ Path: path,
+ }
+ } else if fsev.IsDelete() || fsev.IsRename() {
+ evchan <- &Event{
+ Type: EventDelete,
+ Path: path,
+ }
+ parent := filepath.Dir(path)
+ if parent != "" && parent != path {
+ evchan <- &Event{
+ Type: EventModify,
+ Path: parent,
+ }
+ }
} else if fsev.IsCreate() {
- ev.Type = EventCreate
+ evchan <- &Event{
+ Type: EventCreate,
+ Path: path,
+ }
+ parent := filepath.Dir(path)
+ if parent != "" && parent != path {
+ evchan <- &Event{
+ Type: EventModify,
+ Path: parent,
+ }
+ }
} else {
log.Println("unhandled event, don't know what to do with event of this type")
- continue
}
- evchan <- ev
case err := <-w.Error:
errchan <- err