From 58380677c2790a038a7de983c785733f1ce1618c Mon Sep 17 00:00:00 2001 From: refaelos Date: Mon, 20 May 2013 19:17:12 +0300 Subject: [PATCH 01/32] assigning original file's mode to the copied file --- lib/wrench.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/wrench.js b/lib/wrench.js index 6cfa8c6..75125b7 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -202,6 +202,8 @@ exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) { var contents = fs.readFileSync(srcFile); fs.writeFileSync(destFile, contents); + var stat = fs.lstatSync(srcFile); + fs.chmodSync(destFile, stat.mode); }; if(currFile.isDirectory()) { -- 2.39.5 From 02bd67c8a6659b709579cacbd24c9800fcac4709 Mon Sep 17 00:00:00 2001 From: refaelos Date: Mon, 20 May 2013 19:38:17 +0300 Subject: [PATCH 02/32] in 'copyDirRecursive': - replaces 'forceDelete' with 'preserve'. - added an option to get 'excludeHiddenUnix' = added an option to get 'inflateSymlinks' --- lib/wrench.js | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/lib/wrench.js b/lib/wrench.js index 75125b7..b63a455 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -317,6 +317,78 @@ exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){ }); }; +exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) { + + if (typeof opts === 'function') + clbk = opts; + + var copyDirRecInner = function() { + fs.stat(srcDir, function (err1, srcDirStat) { + if (err1) return clbk(err1); + fs.readdir(srcDir, function (err, files) { + if (err) return clbk(err); + (function copyFiles(err) { + if (err) return clbk(err); + + var filename = files.shift(); + if (filename === null || typeof filename == 'undefined') { + return clbk(); + } + + if (opts.excludeHiddenUnix && /^\./.test(filename)) + return clbk(); + + var file = srcDir + '/' + filename, + newFile = newDir + '/' + filename; + + fs.stat(file, function (err, fileStat) { + if (fileStat.isDirectory()) + copyDirRecursive(file, newFile, opts, copyFiles); + else if (fileStat.isSymbolicLink()) { + fs.readlink(file, function (err, link) { + if (!opts.inflateSymlinks) { + fs.symlink(link, newFile, copyFiles); + } else { + fs.lstat(srcDir + '/' + link, function (err, stats) { + if (stats.isDirectory()) { + copyDirRecursive(srcDir + '/' + link, newFile, opts, copyFiles); + } else { + fs.readFile(srcDir + '/' + link, function (err, data) { + fs.writeFile(newFile, data, copyFiles); + }); + } + }); + } + }); + } + else + fs.readFile(file, function (err, data) { + fs.writeFile(newFile, data, copyFiles); + }); + }); + })(); + }); + }); + }; + + fs.stat(newDir, function(err, newDirStat){ + if (!err) { + if ((typeof opts !== 'undefined' && typeof opts !== 'function' && !opts.preserve) && (newDirStat.isDirectory())) { + return exports.rmdirRecursive(newDir, function(err){ + copyDirRecursive(srcDir, newDir, opts, clbk); + }); + } else { + copyDirRecInner(); + } + } else { + fs.mkdir(newDir, srcDirStat.mode, function(err){ + if (err) return clbk(err); + copyDirRecInner(); + }); + } + }); +}; + /* wrench.copyDirRecursive("directory_to_copy", "new_location", {forceDelete: bool}, callback); * * Recursively dives through a directory and moves all its files to a new -- 2.39.5 From fee7f769aef5006b761e00ea62535ee488a96775 Mon Sep 17 00:00:00 2001 From: refaelos Date: Mon, 20 May 2013 19:43:27 +0300 Subject: [PATCH 03/32] removed previous function fixed docs --- lib/wrench.js | 63 ++++++--------------------------------------------- 1 file changed, 7 insertions(+), 56 deletions(-) diff --git a/lib/wrench.js b/lib/wrench.js index b63a455..cc27397 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -317,6 +317,13 @@ exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){ }); }; +/* wrench.copyDirRecursive("directory_to_copy", "new_location", {preserve: bool, inflateSymlinks:bool, excludeHiddenUnix:bool }, callback); + * + * Recursively dives through a directory and moves all its files to a new + * location. + * + * Note: Directories should be passed to this function without a trailing slash. + */ exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) { if (typeof opts === 'function') @@ -389,62 +396,6 @@ exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) }); }; -/* wrench.copyDirRecursive("directory_to_copy", "new_location", {forceDelete: bool}, callback); - * - * Recursively dives through a directory and moves all its files to a new - * location. Specify forceDelete to force directory overwrite. - * - * Note: Directories should be passed to this function without a trailing slash. - */ -exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) { - fs.stat(newDir, function(err, newDirStat){ - if(!err) { - if(typeof opts !== 'undefined' && typeof opts !== 'function' && opts.forceDelete) - return exports.rmdirRecursive(newDir, function(err){ - copyDirRecursive.apply(this, arguments); - }); - else - return clbk(new Error('You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.')); - } - - if(typeof opts === 'function') - clbk = opts; - - fs.stat(srcDir, function(err, srcDirStat){ - if (err) return clbk(err); - fs.mkdir(newDir, srcDirStat.mode, function(err){ - if (err) return clbk(err); - fs.readdir(srcDir, function(err, files){ - if (err) return clbk(err); - (function copyFiles(err){ - if (err) return clbk(err); - - var filename = files.shift(); - if (filename === null || typeof filename == 'undefined') - return clbk(null); - - var file = srcDir+'/'+filename, - newFile = newDir+'/'+filename; - - fs.stat(file, function(err, fileStat){ - if (fileStat.isDirectory()) - copyDirRecursive(file, newFile, copyFiles); - else if (fileStat.isSymbolicLink()) - fs.readlink(file, function(err, link){ - fs.symlink(link, newFile, copyFiles); - }); - else - fs.readFile(file, function(err, data){ - fs.writeFile(newFile, data, copyFiles); - }); - }); - })(); - }); - }); - }); - }); -}; - var mkdirSyncRecursive = function(path, mode) { var self = this; path = _path.normalize(path) -- 2.39.5 From d32c9f46bca9aaca71f672fe91832a97e0a986ce Mon Sep 17 00:00:00 2001 From: refaelos Date: Wed, 22 May 2013 10:37:47 +0300 Subject: [PATCH 04/32] changed the way copyDirRecursive works. - paths needed to be normalized - using 'preserve' instead of 'forceDelete'. it makes more sense to let users decide if they want to keep the existing folders/subfolders then to ask them if they want to 'forceDelete' the old ones. The default operation will be to keep existing folders. - added (and fixed) 'inflateSymLinks'. It's a new option that allows users do decide if they want to copy symlinks from original folder as new folders or just copy the symlink. --- lib/wrench.js | 110 +++++++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 47 deletions(-) diff --git a/lib/wrench.js b/lib/wrench.js index cc27397..1066ee7 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -12,7 +12,8 @@ */ var fs = require("fs"), - _path = require("path"); + _path = require("path"), + mkdirp = require("mkdirp"); /* wrench.readdirSyncRecursive("directory_path"); @@ -166,7 +167,7 @@ exports.rmdirSyncRecursive = function(path, failSilent) { */ exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) { try { - if(fs.statSync(newDirLocation).isDirectory()) { + if(fs.statSync(newDirLocation).isDirectory()) { if(typeof opts !== 'undefined' && opts.forceDelete) { exports.rmdirSyncRecursive(newDirLocation); } else { @@ -292,7 +293,7 @@ exports.chownSyncRecursive = function(sourceDir, uid, gid) { */ exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){ fs.readdir(dir, function(err, files){ - if(err && typeof failSilent === 'boolean' && !failSilent) + if(err && typeof failSilent === 'boolean' && !failSilent) return clbk(err); if(typeof failSilent === 'function') @@ -328,53 +329,63 @@ exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) if (typeof opts === 'function') clbk = opts; + srcDir = _path.normalize(srcDir); + newDir = _path.normalize(newDir); + + var handleFile = function(file, newFile, clbk) { + fs.readFile(file, function (err, data) { + fs.writeFile(newFile, data, clbk); + }); + }; + + var handleSymlink = function(file, newFile, clbk) { + fs.readlink(file, function (err, link) { + if (!opts.inflateSymlinks) { + fs.symlink(link, newFile, clbk); + } else { + fs.lstat(srcDir + '/' + link, function (err, stats) { + if (stats.isDirectory()) { + copyDirRecursive(srcDir + '/' + link, newFile, opts, clbk); + } else { + handleFile(srcDir + '/' + link, newFile, clbk); + } + }); + } + }); + }; var copyDirRecInner = function() { - fs.stat(srcDir, function (err1, srcDirStat) { - if (err1) return clbk(err1); - fs.readdir(srcDir, function (err, files) { + fs.readdir(srcDir, function (err, files) { + if (err) return clbk(err); + (function copyFiles(err) { if (err) return clbk(err); - (function copyFiles(err) { - if (err) return clbk(err); - var filename = files.shift(); - if (filename === null || typeof filename == 'undefined') { - return clbk(); + var filename = files.shift(); + + while (filename && opts.excludeHiddenUnix && /^\./.test(filename)) { + filename = files.shift(); + } + + if (filename === null || typeof filename == 'undefined') { + return clbk(); + } + + var file = srcDir + '/' + filename, + newFile = newDir + '/' + filename; + + fs.stat(file, function (err, fileStat) { + if (fileStat.isDirectory()) { + copyDirRecursive(file, newFile, opts, copyFiles); + } + else if (fileStat.isSymbolicLink()) { + handleSymlink(file, newFile, copyFiles); + } + else { + handleFile(file, newFile, copyFiles); } - if (opts.excludeHiddenUnix && /^\./.test(filename)) - return clbk(); - - var file = srcDir + '/' + filename, - newFile = newDir + '/' + filename; - - fs.stat(file, function (err, fileStat) { - if (fileStat.isDirectory()) - copyDirRecursive(file, newFile, opts, copyFiles); - else if (fileStat.isSymbolicLink()) { - fs.readlink(file, function (err, link) { - if (!opts.inflateSymlinks) { - fs.symlink(link, newFile, copyFiles); - } else { - fs.lstat(srcDir + '/' + link, function (err, stats) { - if (stats.isDirectory()) { - copyDirRecursive(srcDir + '/' + link, newFile, opts, copyFiles); - } else { - fs.readFile(srcDir + '/' + link, function (err, data) { - fs.writeFile(newFile, data, copyFiles); - }); - } - }); - } - }); - } - else - fs.readFile(file, function (err, data) { - fs.writeFile(newFile, data, copyFiles); - }); - }); - })(); - }); + }); + })(); }); }; @@ -388,9 +399,14 @@ exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) copyDirRecInner(); } } else { - fs.mkdir(newDir, srcDirStat.mode, function(err){ - if (err) return clbk(err); - copyDirRecInner(); + fs.stat(srcDir, function (err, srcDirStat) { + if (err) { + clbk(new Error('The source directory (probably) doesn\'t exist. error: ' + err)); + } + mkdirp(newDir, srcDirStat.mode, function(err){ + if (err) return clbk(err); + copyDirRecInner(); + }); }); } }); -- 2.39.5 From 8fbe19ffed28ff2b3f36b4098948e872b6663657 Mon Sep 17 00:00:00 2001 From: refaelos Date: Wed, 22 May 2013 10:43:42 +0300 Subject: [PATCH 05/32] added 'mkdirp' to package,json 'mkdirp' is a useful tool to async mkdir recursive that doesn't fail if the folder exists. --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 065aeab..47cbc15 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ }, "dependencies": { + "mkdirp": "*" }, "devDependencies": { -- 2.39.5 From 5b747d9bb148f8185d4f900d5dedabdb365488c6 Mon Sep 17 00:00:00 2001 From: refaelos Date: Wed, 12 Jun 2013 18:56:12 +0300 Subject: [PATCH 06/32] fixed an issue with error handling in 'rmdirRecursive' --- lib/wrench.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/wrench.js b/lib/wrench.js index 1066ee7..3092012 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -293,11 +293,16 @@ exports.chownSyncRecursive = function(sourceDir, uid, gid) { */ exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){ fs.readdir(dir, function(err, files){ - if(err && typeof failSilent === 'boolean' && !failSilent) - return clbk(err); + if(err) { + if (typeof failSilent === 'boolean' && failSilent) { + return clbk(null); + } else { + return clbk(err); + } + } - if(typeof failSilent === 'function') - clbk = failSilent; + if(typeof failSilent === 'function') + clbk = failSilent; (function rmFile(err){ if (err) return clbk(err); -- 2.39.5 From 261c8d61a8cd39533684d43da2efa491801d0031 Mon Sep 17 00:00:00 2001 From: refaelos Date: Wed, 26 Jun 2013 17:53:19 +0300 Subject: [PATCH 07/32] if clbk is not given, create a dummy clbk --- lib/wrench.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/wrench.js b/lib/wrench.js index 3092012..c8b919b 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -292,6 +292,10 @@ exports.chownSyncRecursive = function(sourceDir, uid, gid) { * Recursively dives through directories and obliterates everything about it. */ exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){ + if (clbk === null || typeof clbk == 'undefined') { + clbk = function(err) {}; + } + fs.readdir(dir, function(err, files){ if(err) { if (typeof failSilent === 'boolean' && failSilent) { -- 2.39.5 From 5acb4ed037741d66830bcd045a043532155ee840 Mon Sep 17 00:00:00 2001 From: Patrick Steele-Idem Date: Wed, 24 Jul 2013 23:45:28 -0600 Subject: [PATCH 08/32] Added support for include and exclude filters and function filters. Also export copyFileSync method now --- lib/wrench.js | 116 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 89 insertions(+), 27 deletions(-) diff --git a/lib/wrench.js b/lib/wrench.js index 6cfa8c6..268df1b 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -121,6 +121,8 @@ exports.readdirRecursive = function(baseDir, fn) { + + /* wrench.rmdirSyncRecursive("directory_path", forceDelete, failSilent); * * Recursively dives through directories and obliterates everything about it. This is a @@ -156,6 +158,62 @@ exports.rmdirSyncRecursive = function(path, failSilent) { return fs.rmdirSync(path); }; + + +function isFileIncluded(opts, dir, filename) { + + function isMatch(filter) { + if (typeof filter === 'function') { + return filter(filename, dir) === true; + } + else { + // Maintain backwards compatibility and use just the filename + return filename.match(filter); + } + } + + if (opts.include || opts.exclude) { + if (opts.exclude) { + if (isMatch(opts.exclude)) { + return false; + } + } + + if (opts.include) { + if (isMatch(opts.include)) { + return true; + } + else { + return false; + } + } + + return true; + } + else if (opts.filter) { + var filter = opts.filter; + + if (!opts.whitelist) { + // if !opts.whitelist is false every file or directory + // which does match opts.filter will be ignored + return isMatch(filter) ? false : true; + } else { + // if opts.whitelist is true every file or directory + // which doesn't match opts.filter will be ignored + return !isMatch(filter) ? false : true; + } + } + + return true; +} + +exports.copyFileSync = function(srcFile, destFile, preserveFiles) { + if (preserveFiles && fs.existsSync(destFile)) return; + + var contents = fs.readFileSync(srcFile); + fs.writeFileSync(destFile, contents); +}; + /* wrench.copyDirSyncRecursive("directory_to_copy", "new_directory_location", opts); * * Recursively dives through a directory and moves all its files to a new location. This is a @@ -165,14 +223,16 @@ exports.rmdirSyncRecursive = function(path, failSilent) { * Note: Directories should be passed to this function without a trailing slash. */ exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) { + opts = opts || {}; + try { - if(fs.statSync(newDirLocation).isDirectory()) { - if(typeof opts !== 'undefined' && opts.forceDelete) { - exports.rmdirSyncRecursive(newDirLocation); - } else { - return new Error('You are trying to delete a directory that already exists. Specify forceDelete in the opts argument to override this. Bailing~'); - } - } + if(fs.statSync(newDirLocation).isDirectory()) { + if(typeof opts !== 'undefined' && opts.forceDelete) { + exports.rmdirSyncRecursive(newDirLocation); + } else { + return new Error('You are trying to delete a directory that already exists. Specify forceDelete in the opts argument to override this. Bailing~'); + } + } } catch(e) { } /* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */ @@ -185,23 +245,25 @@ exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) { } var files = fs.readdirSync(sourceDir); + var hasFilter = opts.filter || opts.include || opts.exclude; + var preserveFiles = opts.preserveFiles === true; for(var i = 0; i < files.length; i++) { // ignores all files or directories which match the RegExp in opts.filter - if(typeof opts !== 'undefined') { - if(!opts.whitelist && opts.filter && files[i].match(opts.filter)) continue; - // if opts.whitelist is true every file or directory which doesn't match opts.filter will be ignored - if(opts.whitelist && opts.filter && !files[i].match(opts.filter)) continue; + if(typeof opts !== 'undefined') { + if (hasFilter) { + if (!isFileIncluded(opts, sourceDir, files[i])) { + continue; + } + } + if (opts.excludeHiddenUnix && /^\./.test(files[i])) continue; } var currFile = fs.lstatSync(_path.join(sourceDir, files[i])); var fCopyFile = function(srcFile, destFile) { - if(typeof opts !== 'undefined' && opts.preserveFiles && fs.existsSync(destFile)) return; - - var contents = fs.readFileSync(srcFile); - fs.writeFileSync(destFile, contents); + exports.copyFileSync(srcFile, destFile, preserveFiles); }; if(currFile.isDirectory()) { @@ -291,10 +353,10 @@ exports.chownSyncRecursive = function(sourceDir, uid, gid) { exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){ fs.readdir(dir, function(err, files){ if(err && typeof failSilent === 'boolean' && !failSilent) - return clbk(err); + return clbk(err); - if(typeof failSilent === 'function') - clbk = failSilent; + if(typeof failSilent === 'function') + clbk = failSilent; (function rmFile(err){ if (err) return clbk(err); @@ -325,16 +387,16 @@ exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){ exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) { fs.stat(newDir, function(err, newDirStat){ if(!err) { - if(typeof opts !== 'undefined' && typeof opts !== 'function' && opts.forceDelete) - return exports.rmdirRecursive(newDir, function(err){ - copyDirRecursive.apply(this, arguments); - }); - else - return clbk(new Error('You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.')); - } + if(typeof opts !== 'undefined' && typeof opts !== 'function' && opts.forceDelete) + return exports.rmdirRecursive(newDir, function(err){ + copyDirRecursive.apply(this, arguments); + }); + else + return clbk(new Error('You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.')); + } - if(typeof opts === 'function') - clbk = opts; + if(typeof opts === 'function') + clbk = opts; fs.stat(srcDir, function(err, srcDirStat){ if (err) return clbk(err); -- 2.39.5 From c9c99d43b6f28d3ee5a590e768d551ae3467c40e Mon Sep 17 00:00:00 2001 From: Patrick Steele-Idem Date: Wed, 24 Jul 2013 23:45:49 -0600 Subject: [PATCH 09/32] Updated readme based on filter improvements --- readme.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 5d573a5..ff90456 100644 --- a/readme.md +++ b/readme.md @@ -66,10 +66,16 @@ wrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end excludeHiddenUnix: bool, // Whether to copy hidden Unix files or not (preceding .) preserveFiles: bool, // If we're overwriting something and the file already exists, keep the existing inflateSymlinks: bool, // Whether to follow symlinks or not when copying files - filter: regexp, // A filter to match files against; if matches, do nothing (exclude). + filter: regexpOrFunction, // A filter to match files against; if matches, do nothing (exclude). whitelist: bool, // if true every file or directory which doesn't match filter will be ignored + include: regexpOrFunction, // An include filter (either a regexp or a function) + exclude: regexpOrFunction // An include filter (either a regexp or a function) }); +*NOTE:* If a RegExp is provided then then it will be matched against the filename. If a function is + provided then the signature should be the following: + `function(filename, dir) { return result; }` + // Read lines in from a file until you hit the end var f = new wrench.LineReader('x.txt'); while(f.hasNextLine()) { -- 2.39.5 From ba0882a4d106432fa2448ea5dcef6d29b5fe76dc Mon Sep 17 00:00:00 2001 From: Patrick Steele-Idem Date: Wed, 24 Jul 2013 23:47:28 -0600 Subject: [PATCH 10/32] Update readme.md --- readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index ff90456..1db3ece 100644 --- a/readme.md +++ b/readme.md @@ -72,9 +72,9 @@ wrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end exclude: regexpOrFunction // An include filter (either a regexp or a function) }); -*NOTE:* If a RegExp is provided then then it will be matched against the filename. If a function is - provided then the signature should be the following: - `function(filename, dir) { return result; }` +// Note: If a RegExp is provided then then it will be matched against the filename. If a function is +// provided then the signature should be the following: +// function(filename, dir) { return result; } // Read lines in from a file until you hit the end var f = new wrench.LineReader('x.txt'); -- 2.39.5 From 7827a700ff8cb8b742e401e9876e86a63ae0c68a Mon Sep 17 00:00:00 2001 From: Patrick Steele-Idem Date: Wed, 24 Jul 2013 23:48:02 -0600 Subject: [PATCH 11/32] Update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 1db3ece..a4e0242 100644 --- a/readme.md +++ b/readme.md @@ -69,7 +69,7 @@ wrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end filter: regexpOrFunction, // A filter to match files against; if matches, do nothing (exclude). whitelist: bool, // if true every file or directory which doesn't match filter will be ignored include: regexpOrFunction, // An include filter (either a regexp or a function) - exclude: regexpOrFunction // An include filter (either a regexp or a function) + exclude: regexpOrFunction // An exclude filter (either a regexp or a function) }); // Note: If a RegExp is provided then then it will be matched against the filename. If a function is -- 2.39.5 From be1e0e24ffd31c6684a73274accf15dff0a6da0d Mon Sep 17 00:00:00 2001 From: Mario Balibrera Date: Thu, 1 Aug 2013 19:42:52 -0700 Subject: [PATCH 12/32] fixed getNextLine --- lib/wrench.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wrench.js b/lib/wrench.js index 6cfa8c6..a4e29b5 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -434,7 +434,7 @@ exports.LineReader.prototype = { getNextLine: function() { var lineEnd = this.buffer.indexOf("\n"), - result = this.buffer.substring(0, lineEnd ? lineEnd : this.buffer.length); + result = this.buffer.substring(0, lineEnd != -1 ? lineEnd : this.buffer.length); this.buffer = this.buffer.substring(result.length + 1, this.buffer.length); return result; -- 2.39.5 From e3a696c40fceeda0336be2523628cc8dab5becbf Mon Sep 17 00:00:00 2001 From: Adam Griffiths Date: Sun, 4 Aug 2013 19:12:53 +0100 Subject: [PATCH 13/32] Update wrench.js Fixes a bug (not sure if has been reported). `copyDirRecursive` calls itself from the `rmdirRecursive` callback when newDir exists. It should call itself with the original copyDirRecursive arguments, not the callback arguments. Also `fun.apply(thisArg, argsArray)` expects argsArray to be an array (see [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)) but `arguments` is not an array (see [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments)) --- lib/wrench.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/wrench.js b/lib/wrench.js index a4e29b5..9c9b400 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -323,11 +323,12 @@ exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){ * Note: Directories should be passed to this function without a trailing slash. */ exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) { + var originalArguments = Array.prototype.slice.apply(arguments); fs.stat(newDir, function(err, newDirStat){ if(!err) { if(typeof opts !== 'undefined' && typeof opts !== 'function' && opts.forceDelete) return exports.rmdirRecursive(newDir, function(err){ - copyDirRecursive.apply(this, arguments); + copyDirRecursive.apply(this, originalArguments); }); else return clbk(new Error('You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.')); -- 2.39.5 From 0f21829511ae44cac79d09c1b7ce7b8212ee34e5 Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Wed, 16 Oct 2013 07:17:56 +0900 Subject: [PATCH 14/32] Point release, adds some stuff from pull request #55 --- lib/wrench.js | 49 ++++++++++++++++++++++++++++--------------------- package.json | 2 +- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/lib/wrench.js b/lib/wrench.js index 9c9b400..bcd7a39 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -14,7 +14,6 @@ var fs = require("fs"), _path = require("path"); - /* wrench.readdirSyncRecursive("directory_path"); * * Recursively dives through directories and read the contents of all the @@ -202,6 +201,8 @@ exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) { var contents = fs.readFileSync(srcFile); fs.writeFileSync(destFile, contents); + var stat = fs.lstatSync(srcFile); + fs.chmodSync(destFile, stat.mode); }; if(currFile.isDirectory()) { @@ -289,29 +290,32 @@ exports.chownSyncRecursive = function(sourceDir, uid, gid) { * Recursively dives through directories and obliterates everything about it. */ exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){ - fs.readdir(dir, function(err, files){ + if(clbk === null || typeof clbk == 'undefined') + clbk = function(err) {}; + + fs.readdir(dir, function(err, files) { if(err && typeof failSilent === 'boolean' && !failSilent) return clbk(err); - if(typeof failSilent === 'function') - clbk = failSilent; + if(typeof failSilent === 'function') + clbk = failSilent; - (function rmFile(err){ - if (err) return clbk(err); - - var filename = files.shift(); - if (filename === null || typeof filename == 'undefined') - return fs.rmdir(dir, clbk); - - var file = dir+'/'+filename; - fs.lstat(file, function(err, stat){ + (function rmFile(err){ if (err) return clbk(err); - if (stat.isDirectory()) - rmdirRecursive(file, rmFile); - else - fs.unlink(file, rmFile); - }); - })(); + + var filename = files.shift(); + if (filename === null || typeof filename == 'undefined') + return fs.rmdir(dir, clbk); + + var file = dir+'/'+filename; + fs.lstat(file, function(err, stat){ + if (err) return clbk(err); + if (stat.isDirectory()) + rmdirRecursive(file, rmFile); + else + fs.unlink(file, rmFile); + }); + })(); }); }; @@ -324,12 +328,15 @@ exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){ */ exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) { var originalArguments = Array.prototype.slice.apply(arguments); + srcDir = _path.normalize(srcDir); + newDir = _path.normalize(newDir); + fs.stat(newDir, function(err, newDirStat){ if(!err) { if(typeof opts !== 'undefined' && typeof opts !== 'function' && opts.forceDelete) - return exports.rmdirRecursive(newDir, function(err){ + return exports.rmdirRecursive(newDir, function(err) { copyDirRecursive.apply(this, originalArguments); - }); + }); else return clbk(new Error('You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.')); } diff --git a/package.json b/package.json index 065aeab..260358f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wrench", "description": "Recursive filesystem (and other) operations that Node *should* have.", - "version": "1.5.1", + "version": "1.5.2", "author": "Ryan McGrath ", "repository": { -- 2.39.5 From 99686fbdc248031b8c494ec085cf6cf59c99530e Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Wed, 16 Oct 2013 07:23:32 +0900 Subject: [PATCH 15/32] . release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 260358f..45dc230 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wrench", "description": "Recursive filesystem (and other) operations that Node *should* have.", - "version": "1.5.2", + "version": "1.5.3", "author": "Ryan McGrath ", "repository": { -- 2.39.5 From 5c716f9c0d05213946612a259c9a3f476ad89c72 Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Wed, 16 Oct 2013 07:46:46 +0900 Subject: [PATCH 16/32] Resolve this merge conflict that I somehow 100% totally missed (fixes #63) --- lib/wrench.js | 64 ++++++++++++++++++--------------------------------- package.json | 2 +- 2 files changed, 24 insertions(+), 42 deletions(-) diff --git a/lib/wrench.js b/lib/wrench.js index 1e8b145..d2664ec 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -355,30 +355,25 @@ exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){ if(err && typeof failSilent === 'boolean' && !failSilent) return clbk(err); -<<<<<<< HEAD if(typeof failSilent === 'function') clbk = failSilent; -======= - if(typeof failSilent === 'function') - clbk = failSilent; ->>>>>>> 7827a700ff8cb8b742e401e9876e86a63ae0c68a + + (function rmFile(err){ + if (err) return clbk(err); - (function rmFile(err){ + var filename = files.shift(); + if (filename === null || typeof filename == 'undefined') + return fs.rmdir(dir, clbk); + + var file = dir+'/'+filename; + fs.lstat(file, function(err, stat){ if (err) return clbk(err); - - var filename = files.shift(); - if (filename === null || typeof filename == 'undefined') - return fs.rmdir(dir, clbk); - - var file = dir+'/'+filename; - fs.lstat(file, function(err, stat){ - if (err) return clbk(err); - if (stat.isDirectory()) - rmdirRecursive(file, rmFile); - else - fs.unlink(file, rmFile); - }); - })(); + if (stat.isDirectory()) + rmdirRecursive(file, rmFile); + else + fs.unlink(file, rmFile); + }); + })(); }); }; @@ -394,31 +389,18 @@ exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) srcDir = _path.normalize(srcDir); newDir = _path.normalize(newDir); - fs.stat(newDir, function(err, newDirStat){ + fs.stat(newDir, function(err, newDirStat) { if(!err) { -<<<<<<< HEAD - if(typeof opts !== 'undefined' && typeof opts !== 'function' && opts.forceDelete) - return exports.rmdirRecursive(newDir, function(err) { - copyDirRecursive.apply(this, originalArguments); - }); - else - return clbk(new Error('You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.')); - } + if(typeof opts !== 'undefined' && typeof opts !== 'function' && opts.forceDelete) + return exports.rmdirRecursive(newDir, function(err) { + copyDirRecursive.apply(this, originalArguments); + }); + else + return clbk(new Error('You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.')); + } if(typeof opts === 'function') clbk = opts; -======= - if(typeof opts !== 'undefined' && typeof opts !== 'function' && opts.forceDelete) - return exports.rmdirRecursive(newDir, function(err){ - copyDirRecursive.apply(this, arguments); - }); - else - return clbk(new Error('You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.')); - } - - if(typeof opts === 'function') - clbk = opts; ->>>>>>> 7827a700ff8cb8b742e401e9876e86a63ae0c68a fs.stat(srcDir, function(err, srcDirStat){ if (err) return clbk(err); diff --git a/package.json b/package.json index 45dc230..9b1c314 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wrench", "description": "Recursive filesystem (and other) operations that Node *should* have.", - "version": "1.5.3", + "version": "1.5.4", "author": "Ryan McGrath ", "repository": { -- 2.39.5 From f76a05e87403e76d270f05caa563af623c2a14ab Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Thu, 14 Nov 2013 01:44:35 +0100 Subject: [PATCH 17/32] copyDirSyncRecursive: Remove obsolete typeof check Variable `opts` is never undefined at this point because of "opts = opts || {};". --- lib/wrench.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wrench.js b/lib/wrench.js index d2664ec..83639eb 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -219,7 +219,7 @@ exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) { try { if(fs.statSync(newDirLocation).isDirectory()) { - if(typeof opts !== 'undefined' && opts.forceDelete) { + if(opts.forceDelete) { exports.rmdirSyncRecursive(newDirLocation); } else { return new Error('You are trying to delete a directory that already exists. Specify forceDelete in the opts argument to override this. Bailing~'); -- 2.39.5 From 793c61eec0557729c4c8fb77c63b4149e09dfe26 Mon Sep 17 00:00:00 2001 From: seanmwalker Date: Fri, 17 Jan 2014 00:45:26 -0600 Subject: [PATCH 18/32] Updating wrench rmdirSyncRecursive to support permissions issues for windows. --- lib/wrench.js | 30 +++++++++++++++++++++--------- tests/rmdirSyncRecursive.js | 22 ++++++++++++++++++++++ tests/runner.js | 3 ++- 3 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 tests/rmdirSyncRecursive.js diff --git a/lib/wrench.js b/lib/wrench.js index d2664ec..44bda99 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -12,7 +12,8 @@ */ var fs = require("fs"), - _path = require("path"); + _path = require("path"), + isWindows = !!process.platform.match(/^win/); /* wrench.readdirSyncRecursive("directory_path"); * @@ -122,7 +123,7 @@ exports.readdirRecursive = function(baseDir, fn) { -/* wrench.rmdirSyncRecursive("directory_path", forceDelete, failSilent); +/* wrench.rmdirSyncRecursive("directory_path", failSilent); * * Recursively dives through directories and obliterates everything about it. This is a * Sync-function, which blocks things until it's done. No idea why anybody would want an @@ -140,16 +141,27 @@ exports.rmdirSyncRecursive = function(path, failSilent) { /* Loop through and delete everything in the sub-tree after checking it */ for(var i = 0; i < files.length; i++) { - var currFile = fs.lstatSync(_path.join(path, files[i])); + var file = _path.join(path, files[i]); + var currFile = fs.lstatSync(file); - if(currFile.isDirectory()) // Recursive function back to the beginning - exports.rmdirSyncRecursive(_path.join(path, files[i])); + if(currFile.isDirectory()) { + // Recursive function back to the beginning + exports.rmdirSyncRecursive(file); + } else if(currFile.isSymbolicLink()) { + // Unlink symlinks + if (isWindows) { + fs.chmodSync(file, 666) // Windows needs this unless joyent/node#3006 is resolved.. + } - else if(currFile.isSymbolicLink()) // Unlink symlinks - fs.unlinkSync(_path.join(path, files[i])); + fs.unlinkSync(file); + } else { + // Assume it's a file - perhaps a try/catch belongs here? + if (isWindows) { + fs.chmodSync(file, 666) // Windows needs this unless joyent/node#3006 is resolved.. + } - else // Assume it's a file - perhaps a try/catch belongs here? - fs.unlinkSync(_path.join(path, files[i])); + fs.unlinkSync(file); + } } /* Now that we know everything in the sub-tree has been deleted, we can delete the main diff --git a/tests/rmdirSyncRecursive.js b/tests/rmdirSyncRecursive.js new file mode 100644 index 0000000..db4e9ef --- /dev/null +++ b/tests/rmdirSyncRecursive.js @@ -0,0 +1,22 @@ +var testCase = require('nodeunit').testCase; +var fs = require('fs'); +var wrench = require('../lib/wrench'); +var path = require('path'); + +module.exports = testCase({ + test_rmdirSyncRecursive: function(test) { + var dir = __dirname + '/_tmp/foo/bar'; + + wrench.mkdirSyncRecursive(dir, 0777); + + test.equals(fs.existsSync(dir), true, 'Dir should exist - mkdirSyncRecursive not working?'); + + wrench.rmdirSyncRecursive(dir); + + test.equals(fs.existsSync(dir), false, 'Dir should not exist now...'); + + test.done(); + }, +}); + +// vim: et ts=4 sw=4 diff --git a/tests/runner.js b/tests/runner.js index 8f90dae..e321a15 100644 --- a/tests/runner.js +++ b/tests/runner.js @@ -4,5 +4,6 @@ module.exports = { group_mkdir: require('./mkdir'), group_readdir: require('./readdir'), - group_copydir: require('./copydirsync_unix') + group_copydir: require('./copydirsync_unix'), + group_rmdir: require('./rmdirSyncRecursive') }; -- 2.39.5 From df61c7017f6abd116a5bcf3d139e084b83913323 Mon Sep 17 00:00:00 2001 From: seanmwalker Date: Fri, 17 Jan 2014 01:28:55 -0600 Subject: [PATCH 19/32] Updating test for rmdirSyncRecursive to check for files with alternative permissions being removed properly. --- lib/wrench.js | 5 ++++ tests/rmdirSyncRecursive.js | 56 +++++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/lib/wrench.js b/lib/wrench.js index 44bda99..d32b854 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -135,6 +135,8 @@ exports.rmdirSyncRecursive = function(path, failSilent) { try { files = fs.readdirSync(path); } catch (err) { + console.log('Error "' + err.message + '"\n'); + if(failSilent) return; throw new Error(err.message); } @@ -150,6 +152,7 @@ exports.rmdirSyncRecursive = function(path, failSilent) { } else if(currFile.isSymbolicLink()) { // Unlink symlinks if (isWindows) { + console.log('Remove file "' + file + '"\n'); fs.chmodSync(file, 666) // Windows needs this unless joyent/node#3006 is resolved.. } @@ -157,6 +160,7 @@ exports.rmdirSyncRecursive = function(path, failSilent) { } else { // Assume it's a file - perhaps a try/catch belongs here? if (isWindows) { + console.log('Remove file "' + file + '"\n'); fs.chmodSync(file, 666) // Windows needs this unless joyent/node#3006 is resolved.. } @@ -164,6 +168,7 @@ exports.rmdirSyncRecursive = function(path, failSilent) { } } + console.log('Remove dir "' + path + '"\n'); /* Now that we know everything in the sub-tree has been deleted, we can delete the main directory. Huzzah for the shopkeep. */ return fs.rmdirSync(path); diff --git a/tests/rmdirSyncRecursive.js b/tests/rmdirSyncRecursive.js index db4e9ef..f6b9442 100644 --- a/tests/rmdirSyncRecursive.js +++ b/tests/rmdirSyncRecursive.js @@ -5,18 +5,70 @@ var path = require('path'); module.exports = testCase({ test_rmdirSyncRecursive: function(test) { - var dir = __dirname + '/_tmp/foo/bar'; + var dir = __dirname + '/_tmp2/foo/bar'; - wrench.mkdirSyncRecursive(dir, 0777); + wrench.mkdirSyncRecursive(dir, '777'); + + var f1Path = path.join(dir, 'test1.txt'); + var f2Path = path.join(path.dirname(dir), 'test2.txt'); + var f3Path = path.join(path.dirname(path.dirname(dir)), 'test3.txt'); + + fs.writeFileSync(f1Path, 'foo bar baz'); + fs.writeFileSync(f2Path, 'foo bar baz'); + fs.writeFileSync(f3Path, 'foo bar baz'); + + fs.chmodSync(f1Path, '777'); + fs.chmodSync(f2Path, '777'); + fs.chmodSync(f3Path, '777'); test.equals(fs.existsSync(dir), true, 'Dir should exist - mkdirSyncRecursive not working?'); + test.equals(fs.existsSync(f1Path), true, 'File should exist'); + test.equals(fs.existsSync(f2Path), true, 'File should exist'); + test.equals(fs.existsSync(f3Path), true, 'File should exist'); wrench.rmdirSyncRecursive(dir); test.equals(fs.existsSync(dir), false, 'Dir should not exist now...'); + test.equals(fs.existsSync(f1Path), false, 'File should not exist'); + test.equals(fs.existsSync(f2Path), true, 'File should exist'); + test.equals(fs.existsSync(f3Path), true, 'File should exist'); + + wrench.rmdirSyncRecursive(path.dirname(path.dirname(dir))); test.done(); }, + + test_rmdirSyncRecursiveFromRoot: function(test) { + var dir = __dirname + '/_tmp3/foo/bar'; + + wrench.mkdirSyncRecursive(dir, '777'); + + var f1Path = path.join(dir, 'test1.txt'); + var f2Path = path.join(path.dirname(dir), 'test2.txt'); + var f3Path = path.join(path.dirname(path.dirname(dir)), 'test3.txt'); + + fs.writeFileSync(f1Path, 'foo bar baz'); + fs.writeFileSync(f2Path, 'foo bar baz'); + fs.writeFileSync(f3Path, 'foo bar baz'); + + fs.chmodSync(f1Path, '777'); + fs.chmodSync(f2Path, '777'); + fs.chmodSync(f3Path, '777'); + + test.equals(fs.existsSync(dir), true, 'Dir should exist - mkdirSyncRecursive not working?'); + test.equals(fs.existsSync(f1Path), true, 'File should exist'); + test.equals(fs.existsSync(f2Path), true, 'File should exist'); + test.equals(fs.existsSync(f3Path), true, 'File should exist'); + + wrench.rmdirSyncRecursive(path.dirname(path.dirname(dir))); + + test.equals(fs.existsSync(dir), false, 'Dir should not exist now...'); + test.equals(fs.existsSync(f1Path), false, 'File should not exist'); + test.equals(fs.existsSync(f2Path), false, 'File should not exist'); + test.equals(fs.existsSync(f3Path), false, 'File should not exist'); + + test.done(); + } }); // vim: et ts=4 sw=4 -- 2.39.5 From 99106ac7383232eaab68cd5c5475d2bdb2ea06f3 Mon Sep 17 00:00:00 2001 From: seanmwalker Date: Fri, 17 Jan 2014 01:33:47 -0600 Subject: [PATCH 20/32] Remove console.log statements to clean up the code. --- lib/wrench.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/wrench.js b/lib/wrench.js index d32b854..c546d43 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -135,7 +135,6 @@ exports.rmdirSyncRecursive = function(path, failSilent) { try { files = fs.readdirSync(path); } catch (err) { - console.log('Error "' + err.message + '"\n'); if(failSilent) return; throw new Error(err.message); @@ -152,7 +151,6 @@ exports.rmdirSyncRecursive = function(path, failSilent) { } else if(currFile.isSymbolicLink()) { // Unlink symlinks if (isWindows) { - console.log('Remove file "' + file + '"\n'); fs.chmodSync(file, 666) // Windows needs this unless joyent/node#3006 is resolved.. } @@ -160,7 +158,6 @@ exports.rmdirSyncRecursive = function(path, failSilent) { } else { // Assume it's a file - perhaps a try/catch belongs here? if (isWindows) { - console.log('Remove file "' + file + '"\n'); fs.chmodSync(file, 666) // Windows needs this unless joyent/node#3006 is resolved.. } @@ -168,7 +165,6 @@ exports.rmdirSyncRecursive = function(path, failSilent) { } } - console.log('Remove dir "' + path + '"\n'); /* Now that we know everything in the sub-tree has been deleted, we can delete the main directory. Huzzah for the shopkeep. */ return fs.rmdirSync(path); -- 2.39.5 From 354678e4ee93ecedb748315bb21a5a261e1d715e Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Fri, 17 Jan 2014 15:48:47 +0800 Subject: [PATCH 21/32] Version bump for Windows issue fix --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9b1c314..5e370ef 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wrench", "description": "Recursive filesystem (and other) operations that Node *should* have.", - "version": "1.5.4", + "version": "1.5.5", "author": "Ryan McGrath ", "repository": { -- 2.39.5 From fd7461dc446af9e34c592ab51168b529b04a2527 Mon Sep 17 00:00:00 2001 From: yeputons Date: Fri, 17 Jan 2014 14:40:30 +0400 Subject: [PATCH 22/32] tests/rmdirSyncRecursive: fixed files access rights from 777 to 444 to actually check something --- tests/rmdirSyncRecursive.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/rmdirSyncRecursive.js b/tests/rmdirSyncRecursive.js index f6b9442..3415e84 100644 --- a/tests/rmdirSyncRecursive.js +++ b/tests/rmdirSyncRecursive.js @@ -17,9 +17,9 @@ module.exports = testCase({ fs.writeFileSync(f2Path, 'foo bar baz'); fs.writeFileSync(f3Path, 'foo bar baz'); - fs.chmodSync(f1Path, '777'); - fs.chmodSync(f2Path, '777'); - fs.chmodSync(f3Path, '777'); + fs.chmodSync(f1Path, '444'); + fs.chmodSync(f2Path, '444'); + fs.chmodSync(f3Path, '444'); test.equals(fs.existsSync(dir), true, 'Dir should exist - mkdirSyncRecursive not working?'); test.equals(fs.existsSync(f1Path), true, 'File should exist'); @@ -51,9 +51,9 @@ module.exports = testCase({ fs.writeFileSync(f2Path, 'foo bar baz'); fs.writeFileSync(f3Path, 'foo bar baz'); - fs.chmodSync(f1Path, '777'); - fs.chmodSync(f2Path, '777'); - fs.chmodSync(f3Path, '777'); + fs.chmodSync(f1Path, '444'); + fs.chmodSync(f2Path, '444'); + fs.chmodSync(f3Path, '444'); test.equals(fs.existsSync(dir), true, 'Dir should exist - mkdirSyncRecursive not working?'); test.equals(fs.existsSync(f1Path), true, 'File should exist'); -- 2.39.5 From 65e80e5788b6a5854053d5793fb9d2e2c6682311 Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Sat, 18 Jan 2014 11:11:02 +0800 Subject: [PATCH 23/32] Version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5e370ef..234db19 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wrench", "description": "Recursive filesystem (and other) operations that Node *should* have.", - "version": "1.5.5", + "version": "1.5.6", "author": "Ryan McGrath ", "repository": { -- 2.39.5 From 39d89374c08fd0e4042fd6ed3a905d42486b772c Mon Sep 17 00:00:00 2001 From: Greg Warner Date: Wed, 22 Jan 2014 10:08:41 -0700 Subject: [PATCH 24/32] added preserveTimestamps --- lib/wrench.js | 4 ++++ readme.md | 1 + 2 files changed, 5 insertions(+) diff --git a/lib/wrench.js b/lib/wrench.js index a293fdd..6b13d20 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -252,6 +252,7 @@ exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) { var files = fs.readdirSync(sourceDir); var hasFilter = opts.filter || opts.include || opts.exclude; var preserveFiles = opts.preserveFiles === true; + var preserveTimestamps = opts.preserveTimestamps === true; for(var i = 0; i < files.length; i++) { // ignores all files or directories which match the RegExp in opts.filter @@ -274,6 +275,9 @@ exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) { fs.writeFileSync(destFile, contents); var stat = fs.lstatSync(srcFile); fs.chmodSync(destFile, stat.mode); + if (preserveTimestamps) { + fs.utimesSync(destFile, stat.atime, stat.mtime) + } }; if(currFile.isDirectory()) { diff --git a/readme.md b/readme.md index a4e0242..2d646d0 100644 --- a/readme.md +++ b/readme.md @@ -65,6 +65,7 @@ wrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end forceDelete: bool, // Whether to overwrite existing directory or not excludeHiddenUnix: bool, // Whether to copy hidden Unix files or not (preceding .) preserveFiles: bool, // If we're overwriting something and the file already exists, keep the existing + preserveTimestamps: bool, // Preserve the mtime and atime when copying files inflateSymlinks: bool, // Whether to follow symlinks or not when copying files filter: regexpOrFunction, // A filter to match files against; if matches, do nothing (exclude). whitelist: bool, // if true every file or directory which doesn't match filter will be ignored -- 2.39.5 From b655e26806c25bc6d8d811b61f700cbcef04fc3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samy=20Pess=C3=A9?= Date: Sun, 9 Feb 2014 10:32:01 +0100 Subject: [PATCH 25/32] Fix copyDirRecursive error callback --- lib/wrench.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/wrench.js b/lib/wrench.js index a293fdd..9f2d807 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -432,14 +432,17 @@ exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) newFile = newDir+'/'+filename; fs.stat(file, function(err, fileStat){ + if (err) return clbk(err); if (fileStat.isDirectory()) - copyDirRecursive(file, newFile, copyFiles); + copyDirRecursive(file, newFile, copyFiles, clbk); else if (fileStat.isSymbolicLink()) fs.readlink(file, function(err, link){ + if (err) return clbk(err); fs.symlink(link, newFile, copyFiles); }); else fs.readFile(file, function(err, data){ + if (err) return clbk(err); fs.writeFile(newFile, data, copyFiles); }); }); -- 2.39.5 From b46a97227d905ca79fdd940d9b7a680f8da8e7c4 Mon Sep 17 00:00:00 2001 From: xzyfer Date: Mon, 10 Feb 2014 16:57:35 +1100 Subject: [PATCH 26/32] Fix failing tests --- tests/copydirsync_unix.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/copydirsync_unix.js b/tests/copydirsync_unix.js index 676c9fa..5b34192 100644 --- a/tests/copydirsync_unix.js +++ b/tests/copydirsync_unix.js @@ -92,7 +92,6 @@ module.exports = testCase({ test.ok(fs.existsSync(dir), 'Folders should exist'); - wrench.mkdirSyncRecursive(testdir, 0777); wrench.copyDirSyncRecursive(dir, testdir, { excludeHiddenUnix: false }); var files = wrench.readdirSyncRecursive(testdir); @@ -109,7 +108,6 @@ module.exports = testCase({ test.ok(fs.existsSync(dir), 'Folders should exist'); - wrench.mkdirSyncRecursive(testdir, 0777); wrench.copyDirSyncRecursive(dir, testdir, { excludeHiddenUnix: true }); var files = wrench.readdirSyncRecursive(testdir); @@ -126,7 +124,6 @@ module.exports = testCase({ test.ok(fs.existsSync(dir), 'Folders should exist'); - wrench.mkdirSyncRecursive(testdir, 0777); wrench.copyDirSyncRecursive(dir, testdir, { excludeHiddenUnix: false, inflateSymlinks: true }); var files = wrench.readdirSyncRecursive(testdir); @@ -143,7 +140,6 @@ module.exports = testCase({ test.ok(fs.existsSync(dir), 'Folders should exist'); - wrench.mkdirSyncRecursive(testdir, 0777); wrench.copyDirSyncRecursive(dir, testdir, { excludeHiddenUnix: false, inflateSymlinks: false }); var files = wrench.readdirSyncRecursive(testdir); @@ -161,14 +157,14 @@ module.exports = testCase({ test.ok(fs.existsSync(dir), 'Folders should exist'); - wrench.mkdirSyncRecursive(testdir1, 0777); + // wrench.mkdirSyncRecursive(testdir1, 0777); wrench.copyDirSyncRecursive(dir, testdir1, { excludeHiddenUnix: false }); wrench.copyDirSyncRecursive(dir, testdir2, { excludeHiddenUnix: false }); fs.writeFileSync(path.join(testdir1, ".hidden.txt"), 'just some text for .hidden.txt'); fs.writeFileSync(path.join(testdir1, "bar.txt"), 'just some text for bar.txt'); - wrench.copyDirSyncRecursive(testdir1, testdir2, { preserve: true, excludeHiddenUnix: false, preserveFiles: true }); + wrench.copyDirSyncRecursive(testdir1, testdir2, { excludeHiddenUnix: false, preserveFiles: true }); var files = wrench.readdirSyncRecursive(testdir2); @@ -186,14 +182,14 @@ module.exports = testCase({ test.ok(fs.existsSync(dir), 'Folders should exist'); - wrench.mkdirSyncRecursive(testdir1, 0777); + // wrench.mkdirSyncRecursive(testdir1, 0777); wrench.copyDirSyncRecursive(dir, testdir1, { excludeHiddenUnix: false }); wrench.copyDirSyncRecursive(dir, testdir2, { excludeHiddenUnix: false }); fs.writeFileSync(path.join(testdir1, ".hidden.txt"), 'just some text for .hidden.txt'); fs.writeFileSync(path.join(testdir1, "bar.txt"), 'just some text for bar.txt'); - wrench.copyDirSyncRecursive(testdir1, testdir2, { preserve: true, excludeHiddenUnix: false, preserveFiles: false }); + wrench.copyDirSyncRecursive(testdir1, testdir2, { forceDelete: true, excludeHiddenUnix: false, preserveFiles: false }); var files = wrench.readdirSyncRecursive(testdir2); -- 2.39.5 From b0455c99bab89bbf469be0e241d43f8ee75afcf3 Mon Sep 17 00:00:00 2001 From: xzyfer Date: Mon, 10 Feb 2014 17:00:34 +1100 Subject: [PATCH 27/32] Fix inflateSymlinks flag errors for absolute symlinks --- lib/wrench.js | 7 ++++--- tests/copydirsync_unix.js | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/lib/wrench.js b/lib/wrench.js index a293fdd..a79a18c 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -281,18 +281,19 @@ exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) { exports.copyDirSyncRecursive(_path.join(sourceDir, files[i]), _path.join(newDirLocation, files[i]), opts); } else if(currFile.isSymbolicLink()) { var symlinkFull = fs.readlinkSync(_path.join(sourceDir, files[i])); + symlinkFull = _path.resolve(fs.realpathSync(sourceDir), symlinkFull); if (typeof opts !== 'undefined' && !opts.inflateSymlinks) { fs.symlinkSync(symlinkFull, _path.join(newDirLocation, files[i])); continue; } - var tmpCurrFile = fs.lstatSync(_path.join(sourceDir, symlinkFull)); + var tmpCurrFile = fs.lstatSync(symlinkFull); if (tmpCurrFile.isDirectory()) { - exports.copyDirSyncRecursive(_path.join(sourceDir, symlinkFull), _path.join(newDirLocation, files[i]), opts); + exports.copyDirSyncRecursive(symlinkFull, _path.join(newDirLocation, files[i]), opts); } else { /* At this point, we've hit a file actually worth copying... so copy it on over. */ - fCopyFile(_path.join(sourceDir, symlinkFull), _path.join(newDirLocation, files[i])); + fCopyFile(symlinkFull, _path.join(newDirLocation, files[i])); } } else { /* At this point, we've hit a file actually worth copying... so copy it on over. */ diff --git a/tests/copydirsync_unix.js b/tests/copydirsync_unix.js index 676c9fa..5584286 100644 --- a/tests/copydirsync_unix.js +++ b/tests/copydirsync_unix.js @@ -46,6 +46,21 @@ function checkResultInflate(test, files) { test.deepEqual(fs.lstatSync(path.join(__dirname, 'testdir/bar.txt')).isSymbolicLink(), false); } +function checkResultInflateAbsolute(test, files) { + var check = [ + '.hidden', + 'absolute-bar.txt', + 'bar.txt', + 'test', + path.join('.hidden', 'dolor.md') + ]; + + test.deepEqual(files, check); + + test.deepEqual(fs.lstatSync(path.join(__dirname, 'testdir/.hidden')).isSymbolicLink(), false); + test.deepEqual(fs.lstatSync(path.join(__dirname, 'testdir/bar.txt')).isSymbolicLink(), false); +} + function checkResultDontInflate(test, files) { var check = [ '.hidden', @@ -137,6 +152,27 @@ module.exports = testCase({ test.done(); }, + test_copyDirSyncRecursiveInflateAbsoluteSymlinks: function(test) { + var dir = path.join(__dirname, 'withsymlinks'); + var testdir = path.join(__dirname, 'testdir'); + + fs.symlinkSync( + path.resolve(__dirname, 'shown/bar.txt'), + path.join(dir, 'absolute-bar.txt') + ); + + wrench.mkdirSyncRecursive(testdir, 0777); + wrench.copyDirSyncRecursive(dir, testdir, { forceDelete: true, excludeHiddenUnix: false, inflateSymlinks: true }); + + var files = wrench.readdirSyncRecursive(testdir); + + checkResultInflateAbsolute(test, files); + + wrench.rmdirSyncRecursive(testdir); + fs.unlinkSync(path.join(dir, 'absolute-bar.txt')); + + test.done(); + }, test_copyDirSyncRecursiveDontInflate: function(test) { var dir = path.join(__dirname, 'withsymlinks'); var testdir = path.join(__dirname, 'testdir'); -- 2.39.5 From c2dce2f36b793d1e2d477353f113d9242473369d Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Mon, 10 Feb 2014 14:20:53 +0800 Subject: [PATCH 28/32] Version bump for npm --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 234db19..0763344 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wrench", "description": "Recursive filesystem (and other) operations that Node *should* have.", - "version": "1.5.6", + "version": "1.5.7", "author": "Ryan McGrath ", "repository": { -- 2.39.5 From de1d50dae90e0abdd17950889a203d749cfe3cd6 Mon Sep 17 00:00:00 2001 From: Corey Butler Date: Sat, 1 Mar 2014 16:27:27 -0600 Subject: [PATCH 29/32] Set isDir to false for non-existant directory The PR for issue #45 resolves problems for `readdirRecursive`, but not for `readdirRecursiveSync`. This patch sets `isDir = false` when a directory cannot be found, effectively ceasing further processing. --- lib/wrench.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wrench.js b/lib/wrench.js index 9c1977e..01f5e95 100644 --- a/lib/wrench.js +++ b/lib/wrench.js @@ -28,7 +28,7 @@ exports.readdirSyncRecursive = function(baseDir) { curFiles, nextDirs, isDir = function(fname){ - return fs.statSync( _path.join(baseDir, fname) ).isDirectory(); + return fs.existsSync(_path.join(baseDir, fname)) ? fs.statSync( _path.join(baseDir, fname) ).isDirectory() : false; }, prependBaseDir = function(fname){ return _path.join(baseDir, fname); -- 2.39.5 From 13f486d867d28fb72947c06f57ce4e5b8e656e86 Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Sun, 2 Mar 2014 06:36:09 +0800 Subject: [PATCH 30/32] Version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0763344..1d9b40c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wrench", "description": "Recursive filesystem (and other) operations that Node *should* have.", - "version": "1.5.7", + "version": "1.5.8", "author": "Ryan McGrath ", "repository": { -- 2.39.5 From d8e29aef0b4c1737ab107af74c2ba667645bbc82 Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Thu, 31 Mar 2016 01:42:20 +0900 Subject: [PATCH 31/32] Deprecate this project, which I should have done some time ago. So long and thanks for all the fish. --- readme.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/readme.md b/readme.md index 2d646d0..3749457 100644 --- a/readme.md +++ b/readme.md @@ -1,3 +1,15 @@ +Warning: This Project Is Deprecated! +---------------------------------------------------------------------------- +`wrench.js` is deprecated, and hasn't been updated in quite some time. **[I heavily recommend using fs-extra](https://github.com/jprichardson/node-fs-extra)** to do any extra filesystem operations. + +Wrench was built for the _early_ days of Node, and it solved a problem that needed solving. I'm proud of what it's done; at the time of writing this, it was still downloaded over 25,000 times yesterday, and over 500,000 times in the last month. The fact that it wound up being embedded in so many projects is humbling and a great source of fun for me, but I just don't have the time to keep up with this at the moment. No alternate maintainers have appeared, and fs-extra is very well maintained anyway - one community solution is likely better. + +So long, and thanks for all the fish. The original docs remain available here for anyone who may need them. If I could 301 a GitHub repository I'd do so. + +Cheers, +- Ryan McGrath + + wrench.js - Recursive file operations in Node.js ---------------------------------------------------------------------------- While I love Node.js, I've found myself missing some functions. Things like -- 2.39.5 From 2cffe4e3f4219dc94a9e0e3d9307391c4c5e1619 Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Thu, 31 Mar 2016 01:42:50 +0900 Subject: [PATCH 32/32] Deprecate this project, which I should have done some time ago. So long and thanks for all the fish. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d9b40c..742b2b3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wrench", "description": "Recursive filesystem (and other) operations that Node *should* have.", - "version": "1.5.8", + "version": "1.5.9", "author": "Ryan McGrath ", "repository": { -- 2.39.5