From ee236060c749b7a9570cd1aec54a5c8e7962d4ee Mon Sep 17 00:00:00 2001 From: natecain Date: Fri, 11 Oct 2013 17:10:10 -0400 Subject: [PATCH 1/3] Rudimentary fs.watch usage in filesystemadaptor Will only watch for changes on wiki files loaded during startup or created by runtime (Does not yet track renames/deletes) (Will not notice new files) May become confused by directory structure changes on some platforms (see node docs on fs.watch for caveats!) --- .../filesystem/filesystemadaptor.js | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/plugins/tiddlywiki/filesystem/filesystemadaptor.js b/plugins/tiddlywiki/filesystem/filesystemadaptor.js index c425e3f54..c5eb61bcc 100644 --- a/plugins/tiddlywiki/filesystem/filesystemadaptor.js +++ b/plugins/tiddlywiki/filesystem/filesystemadaptor.js @@ -15,8 +15,30 @@ A sync adaptor module for synchronising with the local filesystem via node.js AP // Get a reference to the file system var fs = !$tw.browser ? require("fs") : null; + function FileSystemAdaptor(syncer) { this.syncer = syncer; + this.watchers = {}; + this.pending = {}; + + this.setwatcher = function(filename, title) { + return this.watchers[filename] = this.watchers[filename] || + fs.watch(filename, {persistent: false}, function(e) { + console.log("Filesystem:", e, filename); + if(e === "change") { + var tiddlers = $tw.loadTiddlersFromFile(filename).tiddlers; + for(var t in tiddlers) { + $tw.wiki.tiddlers[tiddlers[t].title] = new $tw.Tiddler(tiddlers[t]); + } + } + }); + } + + + for(var f in $tw.boot.files) { + var fileInfo = $tw.boot.files[f]; + this.setwatcher(fileInfo.filepath, f); + } } FileSystemAdaptor.prototype.getTiddlerInfo = function(tiddler) { @@ -63,6 +85,7 @@ FileSystemAdaptor.prototype.getTiddlerFileInfo = function(tiddler,callback) { fileInfo.hasMetaFile = typeInfo.hasMetaFile; // Save the newly created fileInfo $tw.boot.files[title] = fileInfo; + self.pending[fileInfo.filepath] = title; // Pass it to the callback callback(null,fileInfo); }); @@ -96,8 +119,16 @@ FileSystemAdaptor.prototype.generateTiddlerFilename = function(title,extension,e Save a tiddler and invoke the callback with (err,adaptorInfo,revision) */ FileSystemAdaptor.prototype.saveTiddler = function(tiddler,callback) { + var self = this; this.getTiddlerFileInfo(tiddler,function(err,fileInfo) { var template, content, encoding; + function _finish() { + if(self.pending[fileInfo.filepath]) { + self.setwatcher(fileInfo.filepath, tiddler.fields.title); + delete self.pending[fileInfo.filepath]; + } + callback(null, {}, 0); + } if(err) { return callback(err); } @@ -117,7 +148,7 @@ FileSystemAdaptor.prototype.saveTiddler = function(tiddler,callback) { return callback(err); } console.log("FileSystem: Saved file",fileInfo.filepath); - callback(null,{},0); + _finish(); }); }); } else { @@ -129,7 +160,7 @@ console.log("FileSystem: Saved file",fileInfo.filepath); return callback(err); } console.log("FileSystem: Saved file",fileInfo.filepath); - callback(null,{},0); + _finish(); }); } }); @@ -155,6 +186,9 @@ FileSystemAdaptor.prototype.deleteTiddler = function(title,callback) { // Don't delete the tiddler if it is on the blacklist callback(null); } else { + if(this.watchers[fileInfo.filepath]) { + this.watchers[fileInfo.filepath].close(); + } // Delete the file fs.unlink(fileInfo.filepath,function(err) { if(err) { From 4849bd43c87d5cfde096ab60fc2de652d3aa45fb Mon Sep 17 00:00:00 2001 From: natecain Date: Fri, 11 Oct 2013 17:54:47 -0400 Subject: [PATCH 2/3] More graceful handling of tiddler delete in filesystemadaptor watch code --- plugins/tiddlywiki/filesystem/filesystemadaptor.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/tiddlywiki/filesystem/filesystemadaptor.js b/plugins/tiddlywiki/filesystem/filesystemadaptor.js index c5eb61bcc..9f4e422b8 100644 --- a/plugins/tiddlywiki/filesystem/filesystemadaptor.js +++ b/plugins/tiddlywiki/filesystem/filesystemadaptor.js @@ -188,7 +188,9 @@ FileSystemAdaptor.prototype.deleteTiddler = function(title,callback) { } else { if(this.watchers[fileInfo.filepath]) { this.watchers[fileInfo.filepath].close(); + delete this.watchers[fileInfo.filepath]; } + delete this.pending[fileInfo.filepath]; // Delete the file fs.unlink(fileInfo.filepath,function(err) { if(err) { From 2c02b6d6bcc763b5ce209766d381cb52a5dfa430 Mon Sep 17 00:00:00 2001 From: natecain Date: Fri, 11 Oct 2013 18:43:51 -0400 Subject: [PATCH 3/3] Remove watcher while saving, and use AddTiddler instead of modifying tiddlers directly --- .../tiddlywiki/filesystem/filesystemadaptor.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/plugins/tiddlywiki/filesystem/filesystemadaptor.js b/plugins/tiddlywiki/filesystem/filesystemadaptor.js index 9f4e422b8..24f606763 100644 --- a/plugins/tiddlywiki/filesystem/filesystemadaptor.js +++ b/plugins/tiddlywiki/filesystem/filesystemadaptor.js @@ -17,6 +17,7 @@ var fs = !$tw.browser ? require("fs") : null; function FileSystemAdaptor(syncer) { + var self = this; this.syncer = syncer; this.watchers = {}; this.pending = {}; @@ -28,7 +29,9 @@ function FileSystemAdaptor(syncer) { if(e === "change") { var tiddlers = $tw.loadTiddlersFromFile(filename).tiddlers; for(var t in tiddlers) { - $tw.wiki.tiddlers[tiddlers[t].title] = new $tw.Tiddler(tiddlers[t]); + if(tiddlers[t].title) { + $tw.wiki.addTiddler(tiddlers[t]); + } } } }); @@ -134,8 +137,14 @@ FileSystemAdaptor.prototype.saveTiddler = function(tiddler,callback) { } if($tw.boot.wikiInfo.doNotSave && $tw.boot.wikiInfo.doNotSave.indexOf(tiddler.fields.title) !== -1) { // Don't save the tiddler if it is on the blacklist - callback(null,{},0); - } else if(fileInfo.hasMetaFile) { + return callback(null,{},0); + } + if(self.watchers[fileInfo.filepath]) { + self.watchers[fileInfo.filepath].close(); + delete self.watchers[fileInfo.filepath]; + self.pending[fileInfo.filepath] = tiddler.fields.title; + } + if(fileInfo.hasMetaFile) { // Save the tiddler as a separate body and meta file var typeInfo = $tw.config.contentTypeInfo[fileInfo.type]; fs.writeFile(fileInfo.filepath,tiddler.fields.text,{encoding: typeInfo.encoding},function(err) {