summaryrefslogtreecommitdiffstats
path: root/lib/utils/fs.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/utils/fs.js')
-rw-r--r--lib/utils/fs.js178
1 files changed, 178 insertions, 0 deletions
diff --git a/lib/utils/fs.js b/lib/utils/fs.js
new file mode 100644
index 0000000..98a3a87
--- /dev/null
+++ b/lib/utils/fs.js
@@ -0,0 +1,178 @@
+var _ = require("lodash");
+var Q = require("q");
+var tmp = require("tmp");
+var path = require("path");
+var fs = require("graceful-fs");
+var fsExtra = require("fs-extra");
+var Ignore = require("fstream-ignore");
+
+var fsUtils = {
+ tmp: {
+ file: function(opt) {
+ return Q.nfcall(tmp.file.bind(tmp), opt).get(0)
+ },
+ dir: function() {
+ return Q.nfcall(tmp.dir.bind(tmp)).get(0)
+ }
+ },
+ list: listFiles,
+ stat: Q.denodeify(fs.stat),
+ readdir: Q.denodeify(fs.readdir),
+ readFile: Q.denodeify(fs.readFile),
+ writeFile: writeFile,
+ writeStream: writeStream,
+ mkdirp: Q.denodeify(fsExtra.mkdirp),
+ copy: Q.denodeify(fsExtra.copy),
+ remove: Q.denodeify(fsExtra.remove),
+ symlink: Q.denodeify(fsExtra.symlink),
+ exists: function(path) {
+ var d = Q.defer();
+ fs.exists(path, d.resolve);
+ return d.promise;
+ },
+ existsSync: fs.existsSync.bind(fs),
+ readFileSync: fs.readFileSync.bind(fs),
+ clean: cleanFolder,
+ getUniqueFilename: getUniqueFilename,
+}
+
+// Write a file
+function writeFile(filename, data, options) {
+ var d = Q.defer();
+
+ try {
+ fs.writeFileSync(filename, data, options)
+ } catch(err) {
+ d.reject(err);
+ }
+ d.resolve();
+
+
+ return d.promise;
+}
+
+// Write a stream to a file
+function writeStream(filename, st) {
+ var d = Q.defer();
+
+ var wstream = fs.createWriteStream(filename);
+
+ wstream.on('finish', function () {
+ d.resolve();
+ });
+ wstream.on('error', function (err) {
+ d.reject(err);
+ });
+
+ st.pipe(wstream);
+
+ return d.promise;
+}
+
+// Find a filename available
+function getUniqueFilename(base, filename) {
+ if (!filename) {
+ filename = base;
+ base = "/";
+ }
+
+ filename = path.resolve(base, filename);
+ var ext = path.extname(filename);
+ filename = path.join(path.dirname(filename), path.basename(filename, ext));
+
+ var _filename = filename+ext;
+
+ var i = 0;
+ while (1) {
+ if (!fs.existsSync(filename)) break;
+ _filename = filename+"_"+i+ext;
+ i = i + 1;
+ }
+
+ return path.relative(base, _filename);
+}
+
+
+// List files in a directory
+function listFiles(root, options) {
+ options = _.defaults(options || {}, {
+ ignoreFiles: [],
+ ignoreRules: []
+ });
+
+ var d = Q.defer();
+
+ // Our list of files
+ var files = [];
+
+ var ig = Ignore({
+ path: root,
+ ignoreFiles: options.ignoreFiles
+ });
+
+ // Add extra rules to ignore common folders
+ ig.addIgnoreRules(options.ignoreRules, '__custom_stuff');
+
+ // Push each file to our list
+ ig.on('child', function (c) {
+ files.push(
+ c.path.substr(c.root.path.length + 1) + (c.props.Directory === true ? '/' : '')
+ );
+ });
+
+ ig.on('end', function() {
+ // Normalize paths on Windows
+ if(process.platform === 'win32') {
+ return d.resolve(files.map(function(file) {
+ return file.replace(/\\/g, '/');
+ }));
+ }
+
+ // Simply return paths otherwise
+ return d.resolve(files);
+ });
+
+ ig.on('error', d.reject);
+
+ return d.promise;
+}
+
+// Clean a folder without removing .git and .svn
+// Creates it if non existant
+function cleanFolder(root) {
+ if (!fs.existsSync(root)) return fsUtils.mkdirp(root);
+
+ return listFiles(root, {
+ ignoreFiles: [],
+ ignoreRules: [
+ // Skip Git and SVN stuff
+ '.git/',
+ '.svn/'
+ ]
+ })
+ .then(function(files) {
+ var d = Q.defer();
+
+ _.reduce(files, function(prev, file, i) {
+ return prev.then(function() {
+ var _file = path.join(root, file);
+
+ d.notify({
+ i: i+1,
+ count: files.length,
+ file: _file
+ });
+ return fsUtils.remove(_file);
+ });
+ }, Q())
+ .then(function() {
+ d.resolve();
+ }, function(err) {
+ d.reject(err);
+ });
+
+ return d.promise;
+ });
+}
+
+module.exports = fsUtils;