mirror of
https://github.com/TiddlyWiki/TiddlyWiki5.git
synced 2026-05-04 03:57:01 +00:00
First step of turning the rabbit hole inside out
This commit is contained in:
149
archive/js/LocalFileSync.js
Normal file
149
archive/js/LocalFileSync.js
Normal file
@@ -0,0 +1,149 @@
|
||||
/*\
|
||||
title: js/LocalFileSync.js
|
||||
|
||||
Loads tiddlers from a given directory, and then keeps the files up to date as tiddlers are modified, created or deleted.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true */
|
||||
"use strict";
|
||||
|
||||
var retrieveFile = require("./FileRetriever.js").retrieveFile,
|
||||
utils = require("./Utils.js"),
|
||||
fs = require("fs"),
|
||||
path = require("path"),
|
||||
url = require("url"),
|
||||
util = require("util"),
|
||||
async = require("async");
|
||||
|
||||
function LocalFileSync(dirpath,store,callback) {
|
||||
this.dirpath = dirpath;
|
||||
this.store = store;
|
||||
this.callback = callback;
|
||||
this.tiddlers = {}; // A hashmap of <tiddlername>: {changeCount: <changeCount>, files: [name]}
|
||||
var self = this,
|
||||
sanitizeFilepath = function(filepath) {
|
||||
return filepath.replace(/\//mg,"-");
|
||||
};
|
||||
// Set up a queue for loading tiddler files, tasks are {filepath:,callback:}
|
||||
this.loadQueue = async.queue(function(task,callback) {
|
||||
task.files = [];
|
||||
retrieveFile(task.filepath,self.dirpath,function(err,data) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
} else {
|
||||
task.files.push(task.filepath);
|
||||
// Use the filepath as the default title for the tiddler
|
||||
var fields = {
|
||||
title: data.path
|
||||
};
|
||||
var tiddlers = self.store.deserializeTiddlers(data.extname,data.text,fields);
|
||||
// Check for the .meta file
|
||||
if(data.extname !== ".json" && tiddlers.length === 1) {
|
||||
var metafile = task.filepath + ".meta";
|
||||
retrieveFile(metafile,self.dirpath,function(err,data) {
|
||||
if(err && err.code !== "ENOENT" && err.code !== "404") {
|
||||
callback(err);
|
||||
} else {
|
||||
task.files.push(metafile);
|
||||
var fields = tiddlers[0];
|
||||
if(!err) {
|
||||
var text = data.text.split("\n\n")[0];
|
||||
if(text) {
|
||||
fields = self.store.deserializeTiddlers("application/x-tiddler",text,fields)[0];
|
||||
}
|
||||
}
|
||||
task.callback(task,[fields]);
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
task.callback(task,tiddlers);
|
||||
callback(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
},10);
|
||||
// Call the callback when all the files are loaded
|
||||
this.loadQueue.drain = function() {
|
||||
callback(null);
|
||||
};
|
||||
// Query the folder content to get all the tiddlers
|
||||
fs.readdir(this.dirpath,function(err,files) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
} else {
|
||||
var loadCallback = function(task,tiddlers) {
|
||||
for(var t=0; t<tiddlers.length; t++) {
|
||||
var tiddler = tiddlers[t];
|
||||
self.store.addTiddler(tiddler);
|
||||
self.tiddlers[tiddler.title] = {
|
||||
changeCount: self.store.getChangeCount(tiddler.title),
|
||||
files: task.files
|
||||
};
|
||||
}
|
||||
};
|
||||
for(var t=0; t<files.length; t++) {
|
||||
var f = files[t];
|
||||
if(["..",".",".DS_Store"].indexOf(f) === -1 && f.indexOf(".meta") !== f.length-5) {
|
||||
self.loadQueue.push({
|
||||
filepath: f,
|
||||
callback: loadCallback
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// Set up a queue for saving tiddler files
|
||||
this.saveQueue = async.queue(function(task,callback) {
|
||||
var data = task.data,
|
||||
encoding = "utf8";
|
||||
if(task.binary) {
|
||||
data = new Buffer(task.data,"base64").toString("binary");
|
||||
encoding = "binary";
|
||||
}
|
||||
fs.writeFile(self.dirpath + "/" + task.name,data,encoding,function(err) {
|
||||
callback(err);
|
||||
});
|
||||
},10);
|
||||
// Install our event listener to listen out for tiddler changes
|
||||
this.store.addEventListener("",function(changes) {
|
||||
var t;
|
||||
for(var title in changes) {
|
||||
// Get the information about the tiddler
|
||||
var tiddler = self.store.getTiddler(title),
|
||||
changeCount = self.store.getChangeCount(title),
|
||||
tiddlerInfo = self.tiddlers[title],
|
||||
files = [];
|
||||
if(tiddler) {
|
||||
// Construct a changecount record if we don't have one
|
||||
if(!tiddlerInfo) {
|
||||
tiddlerInfo = {changeCount: 0, files: []};
|
||||
self.tiddlers[title] = tiddlerInfo;
|
||||
}
|
||||
// Save the tiddler if the changecount has increased
|
||||
if(changeCount > tiddlerInfo.changeCount) {
|
||||
files = self.store.serializeTiddlers([tiddler],"application/x-tiddler");
|
||||
for(t=0; t<files.length; t++) {
|
||||
files[t].name = sanitizeFilepath(files[t].name);
|
||||
tiddlerInfo.files.push(files[t].name);
|
||||
self.saveQueue.push(files[t]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Delete the tiddler file if the tiddler has gone
|
||||
if(tiddlerInfo) {
|
||||
for(t=0; t<tiddlerInfo.files.length; t++) {
|
||||
fs.unlink(self.dirpath + "/" + tiddlerInfo.files[t]);
|
||||
}
|
||||
delete self.tiddlers[title];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
exports.LocalFileSync = LocalFileSync;
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user