This commit is contained in:
Liang Ding 2015-03-13 21:04:31 +08:00
parent 1be7dc89e0
commit 7fcc39be60
3 changed files with 113 additions and 6 deletions

View File

@ -266,7 +266,12 @@ func NewFileHandler(w http.ResponseWriter, r *http.Request) {
if "f" == fileType { if "f" == fileType {
extension := filepath.Ext(path) extension := filepath.Ext(path)
data["mode"] = getEditorMode(extension) data["mode"] = getEditorMode(extension)
logger.Debugf("Created a file [%s] by user [%s]", path, wSession.Username)
} else {
logger.Debugf("Created a dir [%s] by user [%s]", path, wSession.Username)
} }
} }
// RemoveFileHandler handles request of removing file or directory. // RemoveFileHandler handles request of removing file or directory.
@ -293,7 +298,11 @@ func RemoveFileHandler(w http.ResponseWriter, r *http.Request) {
wSession.EventQueue.Queue <- &event.Event{Code: event.EvtCodeServerInternalError, Sid: sid, wSession.EventQueue.Queue <- &event.Event{Code: event.EvtCodeServerInternalError, Sid: sid,
Data: "can't remove file " + path} Data: "can't remove file " + path}
return
} }
logger.Debugf("Removed a file [%s] by user [%s]", path, wSession.Username)
} }
// RenameFileHandler handles request of renaming file or directory. // RenameFileHandler handles request of renaming file or directory.
@ -321,7 +330,11 @@ func RenameFileHandler(w http.ResponseWriter, r *http.Request) {
wSession.EventQueue.Queue <- &event.Event{Code: event.EvtCodeServerInternalError, Sid: sid, wSession.EventQueue.Queue <- &event.Event{Code: event.EvtCodeServerInternalError, Sid: sid,
Data: "can't rename file " + oldPath} Data: "can't rename file " + oldPath}
return
} }
logger.Debugf("Renamed a file [%s] to [%s] by user [%s]", oldPath, newPath, wSession.Username)
} }
// Use to find results sorting. // Use to find results sorting.
@ -582,7 +595,7 @@ func createFile(path, fileType string) bool {
defer file.Close() defer file.Close()
logger.Debugf("Created file [%s]", path) logger.Tracef("Created file [%s]", path)
return true return true
case "d": case "d":
@ -594,7 +607,7 @@ func createFile(path, fileType string) bool {
return false return false
} }
logger.Debugf("Created directory [%s]", path) logger.Tracef("Created directory [%s]", path)
return true return true
default: default:
@ -612,7 +625,7 @@ func removeFile(path string) bool {
return false return false
} }
logger.Debugf("Removed [%s]", path) logger.Tracef("Removed [%s]", path)
return true return true
} }
@ -625,7 +638,7 @@ func renameFile(oldPath, newPath string) bool {
return false return false
} }
logger.Debugf("Renamed [%s] to [%s]", oldPath, newPath) logger.Tracef("Renamed [%s] to [%s]", oldPath, newPath)
return true return true
} }

View File

@ -27,6 +27,7 @@ import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"os" "os"
"path/filepath"
"sort" "sort"
"strconv" "strconv"
"sync" "sync"
@ -36,6 +37,7 @@ import (
"github.com/b3log/wide/event" "github.com/b3log/wide/event"
"github.com/b3log/wide/log" "github.com/b3log/wide/log"
"github.com/b3log/wide/util" "github.com/b3log/wide/util"
"github.com/go-fsnotify/fsnotify"
"github.com/gorilla/sessions" "github.com/gorilla/sessions"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
@ -77,6 +79,7 @@ type WideSession struct {
EventQueue *event.UserEventQueue // event queue EventQueue *event.UserEventQueue // event queue
State int // state State int // state
Content *conf.LatestSessionContent // the latest session content Content *conf.LatestSessionContent // the latest session content
FileWatcher *fsnotify.Watcher // files change watcher
Created time.Time // create time Created time.Time // create time
Updated time.Time // the latest use time Updated time.Time // the latest use time
} }
@ -300,9 +303,11 @@ func (sessions *wSessions) New(httpSession *sessions.Session, sid string) *WideS
// create user event queue // create user event queue
userEventQueue := event.UserEventQueues.New(sid) userEventQueue := event.UserEventQueues.New(sid)
username := httpSession.Values["username"].(string)
ret := &WideSession{ ret := &WideSession{
ID: sid, ID: sid,
Username: httpSession.Values["username"].(string), Username: username,
HTTPSession: httpSession, HTTPSession: httpSession,
EventQueue: userEventQueue, EventQueue: userEventQueue,
State: sessionStateActive, State: sessionStateActive,
@ -313,6 +318,81 @@ func (sessions *wSessions) New(httpSession *sessions.Session, sid string) *WideS
*sessions = append(*sessions, ret) *sessions = append(*sessions, ret)
if "playground" == username {
return ret
}
// add a filesystem watcher to notify front-end after the files changed
watcher, err := fsnotify.NewWatcher()
if err != nil {
logger.Error(err)
return ret
}
go func() {
workspaces := filepath.SplitList(conf.GetUserWorkspace(username))
for _, workspace := range workspaces {
filepath.Walk(filepath.Join(workspace, "src"), func(dirPath string, f os.FileInfo, err error) error {
if ".git" == f.Name() { // XXX: discard other unconcered dirs
return filepath.SkipDir
}
if f.IsDir() {
if err = watcher.Add(dirPath); nil != err {
logger.Error(err, dirPath)
}
logger.Tracef("Added a file watcher [%s]", dirPath)
}
return nil
})
}
ret.FileWatcher = watcher
}()
go func() {
for {
select {
case event := <-watcher.Events:
path := event.Name
dir := filepath.Dir(path)
ch := SessionWS[sid]
if nil == ch {
break
}
if event.Op&fsnotify.Create == fsnotify.Create {
if err = watcher.Add(path); nil != err {
logger.Warn(err, path)
}
logger.Tracef("Added a file watcher [%s]", path)
cmd := map[string]interface{}{"path": path, "dir": dir, "cmd": "create-file"}
ch.WriteJSON(&cmd)
} else if event.Op&fsnotify.Remove == fsnotify.Remove {
cmd := map[string]interface{}{"path": path, "dir": dir, "cmd": "remove-file"}
ch.WriteJSON(&cmd)
} else if event.Op&fsnotify.Rename == fsnotify.Rename {
cmd := map[string]interface{}{"path": path, "dir": dir, "cmd": "rename-file"}
ch.WriteJSON(&cmd)
}
case err := <-watcher.Errors:
if nil != err {
logger.Error("File watcher ERROR: ", err)
}
}
}
}()
return ret return ret
} }
@ -337,6 +417,7 @@ func (sessions *wSessions) Get(sid string) *WideSession {
// 1. user event queue // 1. user event queue
// 2. process set // 2. process set
// 3. websocket channels // 3. websocket channels
// 4. file watcher
func (sessions *wSessions) Remove(sid string) { func (sessions *wSessions) Remove(sid string) {
mutex.Lock() mutex.Lock()
defer mutex.Unlock() defer mutex.Unlock()
@ -379,6 +460,11 @@ func (sessions *wSessions) Remove(sid string) {
delete(PlaygroundWS, sid) delete(PlaygroundWS, sid)
} }
// file watcher
if nil != s.FileWatcher {
s.FileWatcher.Close()
}
cnt := 0 // count wide sessions associated with HTTP session cnt := 0 // count wide sessions associated with HTTP session
for _, ses := range *sessions { for _, ses := range *sessions {
if ses.Username == s.Username { if ses.Username == s.Username {

View File

@ -136,7 +136,7 @@ var session = {
"m+": date.getMinutes(), "m+": date.getMinutes(),
"s+": date.getSeconds(), "s+": date.getSeconds(),
"q+": Math.floor((date.getMonth() + 3) / 3), "q+": Math.floor((date.getMonth() + 3) / 3),
"S": date.getMilliseconds() "S": date.getMilliseconds()
}; };
if (/(y+)/.test(fmt)) if (/(y+)/.test(fmt))
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)); fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
@ -161,6 +161,14 @@ var session = {
sessionWS.onmessage = function (e) { sessionWS.onmessage = function (e) {
console.log('[session onmessage]' + e.data); console.log('[session onmessage]' + e.data);
var data = JSON.parse(e.data);
switch (data.cmd) {
case 'create-file':
break;
case 'remove-file':
break;
}
}; };
sessionWS.onclose = function (e) { sessionWS.onclose = function (e) {
console.log('[session onclose] disconnected (' + e.code + ')'); console.log('[session onclose] disconnected (' + e.code + ')');