Skip to content

Instantly share code, notes, and snippets.

@bsorrentino
Last active August 29, 2015 14:02
Show Gist options
  • Save bsorrentino/6219e6132dc54358f551 to your computer and use it in GitHub Desktop.
Save bsorrentino/6219e6132dc54358f551 to your computer and use it in GitHub Desktop.
// ### removeRecursive, copyRecursive when/promise compliant
// NodeJS:
// Delete a file or delete a DIR recursively
// be aware that this is a power full delete function
// so best is to check if the PATH given is really
// the path you want to DELETE ENTIRELY
//
// Copy DIR to another location recursively
//
// ### usage example
// remove a folder recursively
//
// fs.removeRecursiveP( full_path_to_dir ).done( console.log, console.log );
//
// or just delete a file (works to)
//
// fs.removeRecursiveP( full_path_to_file ).done( console.log, console.log );
//
var fs = require("fs"),
path = require("path"),
mkdirp = require("mkdirp"),
when = require("when"),
fn = require('when/function'),
nodefn = require('when/node/function')
;
fs.removeRecursiveP = function(pt, canResolve) {
if (canResolve === undefined)
canResolve = true;
var d = when.defer();
var self = this;
fs.stat(pt, function(err, stats) {
if (err) {
if (err.errno === 34) { // ENOENT
d.resolve(pt);
}
else
d.reject(err);
return;
}
if (stats.isFile()) {
fs.unlink(pt, function(err) {
if (err) {
d.reject(err);
return;
}
d.notify(pt);
});
} else if (stats.isDirectory()) {
// A folder may contain files
// We need to delete the files first
// When all are deleted we could delete the
// dir itself
fs.readdir(pt, function(err, files) {
if (err) {
d.reject(err);
return;
}
var f_length = files.length;
var f_delete_index = 0;
// Check and keep track of deleted files
// Delete the folder itself when the files are deleted
var checkStatus = function() {
// We check the status
// and count till we r done
if (f_length === f_delete_index) {
fs.rmdir(pt, function(err) {
if (err)
d.reject(err);
else
d.notify(pt);
if (canResolve)
d.resolve(pt);
});
return true;
}
return false;
};
if (!checkStatus()) {
for (var i = 0; i < f_length; i++) {
// Create a local scope for filePath
// Not really needed, but just good practice
// (as strings arn't passed by reference)
(function() {
var filePath = path.join(pt, files[i]);
// Add a named function as callback
// just to enlighten debugging
self.removeRecursiveP(filePath, false).progress(function(path) {
f_delete_index++;
checkStatus();
});
})()
}
}
});
}
});
return d.promise;
};
fs.copyRecursiveP = function(src, dest, d) {
if (!d)
d = when.defer();
var self = this;
fs.exists(src, function(exists) {
if (!exists)
return;
fs.stat(src, function(err, stats) {
if (err) {
d.reject(err);
return;
}
var isDirectory = exists && stats.isDirectory();
if (exists && isDirectory) {
mkdirp(dest, function(err) {
//fs.mkdir(dest, function(err) {
if (err) {
d.reject(err);
return;
}
fs.readdir(src, function(err, files) {
if (err) {
d.reject(err);
return;
}
files.forEach(function(childItemName) {
self.copyRecursiveP(path.join(src, childItemName),
path.join(dest, childItemName), d);
});
});
});
} else {
fs.link(src, dest, function(err) {
if (err) {
d.reject(err);
return;
}
d.notify(src);
});
}
});
});
return d.promise;
};
// ### removeRecursive, copyRecursive when/promise compliant
// NodeJS:
// Delete a file or delete a DIR recursively
// be aware that this is a power full delete function
// so best is to check if the PATH given is really
// the path you want to DELETE ENTIRELY
//
// Copy DIR to another location recursively
//
// ### usage example
//
// var fsex = require("fsex");
//
// var userHome = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
//
// var __root = path.join( userHome, ".m2/repository/");
// var __root_tmp = "/tmp";
// var pkg = "it/soulsoftware";
//
// var f = function() {
// fsex.copyRecursiveP( path.join(__root, pkg), path.join(__root_tmp, pkg ) )
// .progress( function(f) { console.log( "cp", f ); });
// }
//
// fsex.removeRecursiveP( path.join(__root_tmp, pkg ) )
// .then( f,
// function(err) { console.error( err ); },
// function(f) { console.log("rm", f) } );
//
//
var fs = require("fs"),
path = require("path"),
mkdirp = require("mkdirp"),
when = require("when"),
fn = require('when/function'),
nodefn = require('when/node/function')
;
module.exports = {
removeRecursiveP: function(pt, canResolve) {
if (canResolve === undefined)
canResolve = true;
var d = when.defer();
var self = this;
fs.stat(pt, function(err, stats) {
if (err) {
if (err.errno === 34) { // ENOENT
d.resolve(pt);
}
else
d.reject(err);
return;
}
if (stats.isFile()) {
fs.unlink(pt, function(err) {
if (err) {
d.reject(err);
return;
}
d.notify(pt);
});
} else if (stats.isDirectory()) {
// A folder may contain files
// We need to delete the files first
// When all are deleted we could delete the
// dir itself
fs.readdir(pt, function(err, files) {
if (err) {
d.reject(err);
return;
}
var f_length = files.length;
var f_delete_index = 0;
// Check and keep track of deleted files
// Delete the folder itself when the files are deleted
var checkStatus = function() {
// We check the status
// and count till we r done
if (f_length === f_delete_index) {
fs.rmdir(pt, function(err) {
if (err)
d.reject(err);
else
d.notify(pt);
if (canResolve)
d.resolve(pt);
});
return true;
}
return false;
};
if (!checkStatus()) {
for (var i = 0; i < f_length; i++) {
// Create a local scope for filePath
// Not really needed, but just good practice
// (as strings arn't passed by reference)
(function() {
var filePath = path.join(pt, files[i]);
// Add a named function as callback
// just to enlighten debugging
self.removeRecursiveP(filePath, false).progress(function(path) {
f_delete_index++;
checkStatus();
});
})()
}
}
});
}
});
return d.promise;
},
copyRecursiveP: function(src, dest, d) {
if (!d)
d = when.defer();
var self = this;
fs.exists(src, function(exists) {
if (!exists)
return;
fs.stat(src, function(err, stats) {
if (err) {
d.reject(err);
return;
}
var isDirectory = exists && stats.isDirectory();
if (exists && isDirectory) {
mkdirp(dest, function(err) {
//fs.mkdir(dest, function(err) {
if (err) {
d.reject(err);
return;
}
fs.readdir(src, function(err, files) {
if (err) {
d.reject(err);
return;
}
files.forEach(function(childItemName) {
self.copyRecursiveP(path.join(src, childItemName),
path.join(dest, childItemName), d);
});
});
});
} else {
fs.link(src, dest, function(err) {
if (err) {
d.reject(err);
return;
}
d.notify(src);
});
}
});
});
return d.promise;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment