# HG changeset patch # User sqwishy # Date 1385633540 28800 # Thu Nov 28 02:12:20 2013 -0800 # Node ID bb48410de931a5c91fa7e09c8b4099d0841cb2f3 # Parent 0a96ceefae55b8d79a719f470c17816ddc0f9159 Oh it's so sexy diff --git a/resources.go b/resources.go --- a/resources.go +++ b/resources.go @@ -23,7 +23,7 @@ type Request struct { Subscribe bool - Path string + Path WebPath } type Error struct { diff --git a/server.go b/server.go --- a/server.go +++ b/server.go @@ -23,7 +23,7 @@ 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 @@ 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) 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 @@ 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 @@ 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 @@ } } 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 @@ }) } - // 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, diff --git a/static/js.js b/static/js.js --- a/static/js.js +++ b/static/js.js @@ -7,6 +7,7 @@ that.open = function(addr) { that.ws = new WebSocket(addr); + console.log("this is a good sign"); that.ws.onopen = function(e) { that.trigger("open", e) }; that.ws.onerror = function(e) { that.trigger("error", e) }; that.ws.onclose = function(e) { that.trigger("close", e) }; diff --git a/watch.go b/watch.go --- a/watch.go +++ b/watch.go @@ -23,19 +23,38 @@ 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