summaryrefslogtreecommitdiffstats
path: root/lib/fs
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2016-01-22 21:04:36 +0100
committerSamy Pessé <samypesse@gmail.com>2016-01-22 21:04:36 +0100
commit877f2e477b010f9f37a9044606f110a90f077680 (patch)
tree5cd61cf3b00ba10dc6110535ed9fdf67d8baba72 /lib/fs
parentc8e2fc0e57d223c01a51d6ee186fc1662cd74d13 (diff)
downloadgitbook-877f2e477b010f9f37a9044606f110a90f077680.zip
gitbook-877f2e477b010f9f37a9044606f110a90f077680.tar.gz
gitbook-877f2e477b010f9f37a9044606f110a90f077680.tar.bz2
Start rewrite
Diffstat (limited to 'lib/fs')
-rw-r--r--lib/fs/index.js148
-rw-r--r--lib/fs/node.js72
2 files changed, 220 insertions, 0 deletions
diff --git a/lib/fs/index.js b/lib/fs/index.js
new file mode 100644
index 0000000..1961b07
--- /dev/null
+++ b/lib/fs/index.js
@@ -0,0 +1,148 @@
+var Q = require('q');
+var _ = require('lodash');
+var path = require('path');
+var Buffer = require('buffer').Buffer;
+var destroy = require('destroy');
+
+/*
+A filesystem is an interface to read/write files
+GitBook can works with a virtual filesystem, for example in the browser.
+*/
+
+// .readdir return files/folder as a list of string, folder ending with '/'
+function pathIsFolder(filename) {
+ return _.last(filename) == '/' || _.last(filename) == '\\';
+}
+
+
+function FS() {
+
+}
+
+// Check if a file exists, run a Promise(true) if that's the case, Promise(false) otherwise
+FS.prototype.exists = function(filename) {
+ // To implement for each fs
+};
+
+// Read a file and returns a promise with the content as a buffer
+FS.prototype.read = function(filename) {
+ // To implement for each fs
+};
+
+// Write a file and returns a promise
+FS.prototype.write = function(filename, buffer) {
+ // To implement for each fs
+};
+
+// List files/directories in a directory
+FS.prototype.readdir = function(folder) {
+ // To implement for each fs
+};
+
+
+// These methods don't require to be redefined, by default it uses .exists, .read, .write, .list
+// For optmization, it can be redefined:
+
+// List files in a directory
+FS.prototype.listFiles = function(folder) {
+ return this.readdir(folder)
+ .then(function(files) {
+ return _.reject(files, pathIsFolder);
+ });
+};
+
+// List all files in the fs
+FS.prototype.listAllFiles = function(folder) {
+ var that = this;
+
+ return this.readdir(folder)
+ .then(function(files) {
+ return _.reduce(files, function(prev, file) {
+ return prev.then(function(output) {
+ var isDirectory = pathIsFolder(file);
+
+ if (!isDirectory) {
+ output.push(file);
+ return output;
+ } else {
+ return that.listAllFiles(path.join(folder, file))
+ .then(function(files) {
+ return output.concat(_.map(files, function(_file) {
+ return path.join(file, _file);
+ }));
+ });
+ }
+ });
+ }, Q([]));
+ });
+};
+
+// Read a file as a string (utf-8)
+FS.prototype.readAsString = function(filename) {
+ return this.read(filename)
+ .then(function(buf) {
+ return buf.toString('utf-8');
+ });
+};
+
+// Write a stream to a file and returns a promise
+FS.prototype.writeStream = function(filename, stream) {
+ var bufs = [];
+ var d = Q.defer();
+
+ var cleanup = function() {
+ destroy(stream);
+ stream.removeAllListeners();
+ };
+
+ stream.on('data', function(d) {
+ bufs.push(d);
+ });
+
+ stream.on('error', function(err) {
+ cleanup();
+
+ d.reject(err);
+ });
+
+ stream.on('end', function(){
+ cleanup();
+
+ var buf = Buffer.concat(bufs);
+ d.resolve(buf);
+ });
+
+ return d.promise;
+};
+
+// Copy a file
+FS.prototype.copy = function(from, to) {
+ var that = this;
+
+ return this.read(from)
+ .then(function(buf) {
+ return that.write(to, buf);
+ });
+};
+
+// Find a file in a folder (case incensitive)
+// Return the real filename
+FS.prototype.findFile = function findFile(root, filename) {
+ return this.listFiles(root)
+ .then(function(files) {
+ return _.find(files, function(file) {
+ return (file.toLowerCase() == filename.toLowerCase());
+ });
+ });
+};
+
+// Load a JSON file
+// By default, fs only supports JSON
+FS.prototype.loadAsObject = function(filename) {
+ return this.readAsString(filename)
+ .then(function(str) {
+ return JSON.parse(str);
+ });
+};
+
+module.exports = FS;
diff --git a/lib/fs/node.js b/lib/fs/node.js
new file mode 100644
index 0000000..0c470d7
--- /dev/null
+++ b/lib/fs/node.js
@@ -0,0 +1,72 @@
+var Q = require('q');
+var _ = require('lodash');
+var util = require('util');
+var path = require('path');
+var fs = require('fs');
+
+var BaseFS = require('./');
+
+function NodeFS() {
+ BaseFS.call(this);
+}
+util.inherits(NodeFS, BaseFS);
+
+// Check if a file exists, run a Promise(true) if that's the case, Promise(false) otherwise
+NodeFS.prototype.exists = function(filename) {
+ var d = Q.defer();
+
+ fs.exists(filename, function(exists) {
+ d.resolve(exists);
+ });
+
+ return d.promise;
+};
+
+// Read a file and returns a promise with the content as a buffer
+NodeFS.prototype.read = function(filename) {
+ return Q.nfcall(fs.readFile, filename);
+};
+
+// Write a file and returns a promise
+NodeFS.prototype.write = function(filename, buffer) {
+ return Q.nfcall(fs.writeFile, filename, buffer);
+};
+
+// List files in a directory
+NodeFS.prototype.readdir = function(folder) {
+ return Q.nfcall(fs.readdir, folder)
+ .then(function(files) {
+ return _.chain(files)
+ .map(function(file) {
+ if (file == '.' || file == '..') return;
+
+ var stat = fs.statSync(path.join(folder, file));
+ if (stat.isDirectory()) file = file + path.sep;
+ return file;
+ })
+ .compact()
+ .value();
+ });
+};
+
+// Load a JSON/JS file
+NodeFS.prototype.loadAsObject = function(filename) {
+ return Q()
+ .then(function() {
+ var jsFile;
+
+ try {
+ jsFile = require.resolve(filename);
+
+ // Invalidate node.js cache for livreloading
+ delete require.cache[jsFile];
+
+ return require(jsFile);
+ }
+ catch(err) {
+ return Q.reject(err);
+ }
+ });
+};
+
+module.exports = NodeFS;