[Pkg-javascript-commits] [node-wrench] 01/01: Imported Upstream version 1.5.8
Julien Puydt
julien.puydt at laposte.net
Sat May 30 08:24:11 UTC 2015
This is an automated email from the git hooks/post-receive script.
jpuydt-guest pushed a commit to annotated tag upstream/1.5.8
in repository node-wrench.
commit 37356c36c45f838b4f1efeaa1f44d1e022b780ef
Author: Julien Puydt <julien.puydt at laposte.net>
Date: Fri May 29 16:34:33 2015 +0200
Imported Upstream version 1.5.8
---
.npmignore | 3 +
LICENSE | 21 ++
lib/wrench.js | 531 +++++++++++++++++++++++++++++++++++++++++
package.json | 39 +++
readme.md | 103 ++++++++
tests/copydirsync_unix.js | 242 +++++++++++++++++++
tests/mkdir.js | 26 ++
tests/readdir.js | 61 +++++
tests/readdir/bar.txt | 0
tests/readdir/foo/bar/ipsum.js | 0
tests/readdir/foo/dolor.md | 0
tests/readdir/foo/lorem.txt | 0
tests/rmdirSyncRecursive.js | 74 ++++++
tests/runner.js | 9 +
tests/shown/.hidden.txt | 1 +
tests/shown/.hidden/dolor.md | 0
tests/shown/bar.txt | 1 +
tests/shown/foo/bar/ipsum.js | 0
tests/shown/foo/dolor.md | 0
tests/shown/foo/lorem.txt | 0
tests/withsymlinks/test | 1 +
21 files changed, 1112 insertions(+)
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..05ade97
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,3 @@
+node_modules
+npm-debug.log
+.idea
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..a85a94a
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2010 Ryan McGrath
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/lib/wrench.js b/lib/wrench.js
new file mode 100644
index 0000000..01f5e95
--- /dev/null
+++ b/lib/wrench.js
@@ -0,0 +1,531 @@
+/* wrench.js
+ *
+ * A collection of various utility functions I've found myself in need of
+ * for use with Node.js (http://nodejs.org/). This includes things like:
+ *
+ * - Recursively deleting directories in Node.js (Sync, not Async)
+ * - Recursively copying directories in Node.js (Sync, not Async)
+ * - Recursively chmoding a directory structure from Node.js (Sync, not Async)
+ * - Other things that I'll add here as time goes on. Shhhh...
+ *
+ * ~ Ryan McGrath (ryan [at] venodesigns.net)
+ */
+
+var fs = require("fs"),
+ _path = require("path"),
+ isWindows = !!process.platform.match(/^win/);
+
+/* wrench.readdirSyncRecursive("directory_path");
+ *
+ * Recursively dives through directories and read the contents of all the
+ * children directories.
+ */
+exports.readdirSyncRecursive = function(baseDir) {
+ baseDir = baseDir.replace(/\/$/, '');
+
+ var readdirSyncRecursive = function(baseDir) {
+ var files = [],
+ curFiles,
+ nextDirs,
+ isDir = function(fname){
+ return fs.existsSync(_path.join(baseDir, fname)) ? fs.statSync( _path.join(baseDir, fname) ).isDirectory() : false;
+ },
+ prependBaseDir = function(fname){
+ return _path.join(baseDir, fname);
+ };
+
+ curFiles = fs.readdirSync(baseDir);
+ nextDirs = curFiles.filter(isDir);
+ curFiles = curFiles.map(prependBaseDir);
+
+ files = files.concat( curFiles );
+
+ while (nextDirs.length) {
+ files = files.concat( readdirSyncRecursive( _path.join(baseDir, nextDirs.shift()) ) );
+ }
+
+ return files;
+ };
+
+ // convert absolute paths to relative
+ var fileList = readdirSyncRecursive(baseDir).map(function(val){
+ return _path.relative(baseDir, val);
+ });
+
+ return fileList;
+};
+
+/* wrench.readdirRecursive("directory_path", function(error, files) {});
+ *
+ * Recursively dives through directories and read the contents of all the
+ * children directories.
+ *
+ * Asynchronous, so returns results/error in callback.
+ * Callback receives the of files in currently recursed directory.
+ * When no more directories are left, callback is called with null for all arguments.
+ *
+ */
+exports.readdirRecursive = function(baseDir, fn) {
+ baseDir = baseDir.replace(/\/$/, '');
+
+ var waitCount = 0;
+
+ function readdirRecursive(curDir) {
+ var prependcurDir = function(fname){
+ return _path.join(curDir, fname);
+ };
+
+ waitCount++;
+ fs.readdir(curDir, function(e, curFiles) {
+ if (e) {
+ fn(e);
+ return;
+ }
+ waitCount--;
+
+ curFiles = curFiles.map(prependcurDir);
+
+ curFiles.forEach(function(it) {
+ waitCount++;
+
+ fs.stat(it, function(e, stat) {
+ waitCount--;
+
+ if (e) {
+ fn(e);
+ } else {
+ if (stat.isDirectory()) {
+ readdirRecursive(it);
+ }
+ }
+
+ if (waitCount == 0) {
+ fn(null, null);
+ }
+ });
+ });
+
+ fn(null, curFiles.map(function(val) {
+ // convert absolute paths to relative
+ return _path.relative(baseDir, val);
+ }));
+
+ if (waitCount == 0) {
+ fn(null, null);
+ }
+ });
+ };
+
+ readdirRecursive(baseDir);
+};
+
+
+
+
+
+/* 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
+ * Asynchronous version. :\
+ */
+exports.rmdirSyncRecursive = function(path, failSilent) {
+ var files;
+
+ try {
+ files = fs.readdirSync(path);
+ } catch (err) {
+
+ if(failSilent) return;
+ throw new Error(err.message);
+ }
+
+ /* Loop through and delete everything in the sub-tree after checking it */
+ for(var i = 0; i < files.length; i++) {
+ var file = _path.join(path, files[i]);
+ var currFile = fs.lstatSync(file);
+
+ 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..
+ }
+
+ 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..
+ }
+
+ fs.unlinkSync(file);
+ }
+ }
+
+ /* 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);
+};
+
+
+
+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;
+}
+
+/* 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
+ * Synchronous function, which blocks things until it's done. If you need/want to do this in
+ * an Asynchronous manner, look at wrench.copyDirRecursively() below. Specify forceDelete to force directory overwrite.
+ *
+ * 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(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 */
+ var checkDir = fs.statSync(sourceDir);
+ try {
+ fs.mkdirSync(newDirLocation, checkDir.mode);
+ } catch (e) {
+ //if the directory already exists, that's okay
+ if (e.code !== 'EEXIST') throw e;
+ }
+
+ 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
+ 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);
+ var stat = fs.lstatSync(srcFile);
+ fs.chmodSync(destFile, stat.mode);
+ if (preserveTimestamps) {
+ fs.utimesSync(destFile, stat.atime, stat.mtime)
+ }
+ };
+
+ if(currFile.isDirectory()) {
+ /* recursion this thing right on back. */
+ 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(symlinkFull);
+ if (tmpCurrFile.isDirectory()) {
+ 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(symlinkFull, _path.join(newDirLocation, files[i]));
+ }
+ } else {
+ /* At this point, we've hit a file actually worth copying... so copy it on over. */
+ fCopyFile(_path.join(sourceDir, files[i]), _path.join(newDirLocation, files[i]));
+ }
+ }
+};
+
+/* wrench.chmodSyncRecursive("directory", filemode);
+ *
+ * Recursively dives through a directory and chmods everything to the desired mode. This is a
+ * Synchronous function, which blocks things until it's done.
+ *
+ * Note: Directories should be passed to this function without a trailing slash.
+ */
+exports.chmodSyncRecursive = function(sourceDir, filemode) {
+ var files = fs.readdirSync(sourceDir);
+
+ for(var i = 0; i < files.length; i++) {
+ var currFile = fs.lstatSync(_path.join(sourceDir, files[i]));
+
+ if(currFile.isDirectory()) {
+ /* ...and recursion this thing right on back. */
+ exports.chmodSyncRecursive(_path.join(sourceDir, files[i]), filemode);
+ } else {
+ /* At this point, we've hit a file actually worth copying... so copy it on over. */
+ fs.chmod(_path.join(sourceDir, files[i]), filemode);
+ }
+ }
+
+ /* Finally, chmod the parent directory */
+ fs.chmod(sourceDir, filemode);
+};
+
+
+/* wrench.chownSyncRecursive("directory", uid, gid);
+ *
+ * Recursively dives through a directory and chowns everything to the desired user and group. This is a
+ * Synchronous function, which blocks things until it's done.
+ *
+ * Note: Directories should be passed to this function without a trailing slash.
+ */
+exports.chownSyncRecursive = function(sourceDir, uid, gid) {
+ var files = fs.readdirSync(sourceDir);
+
+ for(var i = 0; i < files.length; i++) {
+ var currFile = fs.lstatSync(_path.join(sourceDir, files[i]));
+
+ if(currFile.isDirectory()) {
+ /* ...and recursion this thing right on back. */
+ exports.chownSyncRecursive(_path.join(sourceDir, files[i]), uid, gid);
+ } else {
+ /* At this point, we've hit a file actually worth chowning... so own it. */
+ fs.chownSync(_path.join(sourceDir, files[i]), uid, gid);
+ }
+ }
+
+ /* Finally, chown the parent directory */
+ fs.chownSync(sourceDir, uid, gid);
+};
+
+
+
+/* wrench.rmdirRecursive("directory_path", callback);
+ *
+ * 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 && typeof failSilent === 'boolean' && !failSilent)
+ return clbk(err);
+
+ 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){
+ if (err) return clbk(err);
+ if (stat.isDirectory())
+ rmdirRecursive(file, rmFile);
+ else
+ fs.unlink(file, rmFile);
+ });
+ })();
+ });
+};
+
+/* 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) {
+ 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) {
+ 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;
+
+ 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 (err) return clbk(err);
+ if (fileStat.isDirectory())
+ 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);
+ });
+ });
+ })();
+ });
+ });
+ });
+ });
+};
+
+var mkdirSyncRecursive = function(path, mode) {
+ var self = this;
+ path = _path.normalize(path)
+
+ try {
+ fs.mkdirSync(path, mode);
+ } catch(err) {
+ if(err.code == "ENOENT") {
+ var slashIdx = path.lastIndexOf(_path.sep);
+
+ if(slashIdx > 0) {
+ var parentPath = path.substring(0, slashIdx);
+ mkdirSyncRecursive(parentPath, mode);
+ mkdirSyncRecursive(path, mode);
+ } else {
+ throw err;
+ }
+ } else if(err.code == "EEXIST") {
+ return;
+ } else {
+ throw err;
+ }
+ }
+};
+exports.mkdirSyncRecursive = mkdirSyncRecursive;
+
+exports.LineReader = function(filename, bufferSize) {
+ this.bufferSize = bufferSize || 8192;
+ this.buffer = "";
+ this.fd = fs.openSync(filename, "r");
+ this.currentPosition = 0;
+};
+
+exports.LineReader.prototype = {
+ close: function() {
+ return fs.closeSync(this.fd);
+ },
+
+ getBufferAndSetCurrentPosition: function(position) {
+ var res = fs.readSync(this.fd, this.bufferSize, position, "ascii");
+
+ this.buffer += res[0];
+ if(res[1] === 0) {
+ this.currentPosition = -1;
+ } else {
+ this.currentPosition = position + res[1];
+ }
+
+ return this.currentPosition;
+ },
+
+ hasNextLine: function() {
+ while(this.buffer.indexOf('\n') === -1) {
+ this.getBufferAndSetCurrentPosition(this.currentPosition);
+ if(this.currentPosition === -1) return false;
+ }
+
+ if(this.buffer.indexOf("\n") > -1 || this.buffer.length !== 0) return true;
+ return false;
+ },
+
+ getNextLine: function() {
+ var lineEnd = this.buffer.indexOf("\n"),
+ result = this.buffer.substring(0, lineEnd != -1 ? lineEnd : this.buffer.length);
+
+ this.buffer = this.buffer.substring(result.length + 1, this.buffer.length);
+ return result;
+ }
+};
+
+// vim: et ts=4 sw=4
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..1d9b40c
--- /dev/null
+++ b/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "wrench",
+ "description": "Recursive filesystem (and other) operations that Node *should* have.",
+ "version": "1.5.8",
+ "author": "Ryan McGrath <ryan at venodesigns.net>",
+
+ "repository": {
+ "type" : "git",
+ "url": "https://ryanmcgrath@github.com/ryanmcgrath/wrench-js.git"
+ },
+
+ "bugs": {
+ "url": "http://github.com/ryanmcgrath/wrench-js/issues"
+ },
+
+ "directories": {
+ "lib": "./lib/"
+ },
+
+ "dependencies": {
+ },
+
+ "devDependencies": {
+ "nodeunit": ">= 0.6.4"
+ },
+
+ "main": "./lib/wrench",
+
+ "engines": {
+ "node": ">=0.1.97"
+ },
+
+ "scripts": { "test": "nodeunit tests/runner.js" },
+
+ "licenses": [{
+ "type" : "MIT",
+ "url" : "http://github.com/ryanmcgrath/wrench-js/raw/master/LICENSE"
+ }]
+}
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..2d646d0
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,103 @@
+wrench.js - Recursive file operations in Node.js
+----------------------------------------------------------------------------
+While I love Node.js, I've found myself missing some functions. Things like
+recursively deleting/chmodding a directory (or even deep copying a directory),
+or even a basic line reader, shouldn't need to be re-invented time and time again.
+
+That said, here's my attempt at a re-usable solution, at least until something
+more formalized gets integrated into Node.js (*hint hint*). wrench.js is fairly simple
+to use - check out the documentation/examples below:
+
+Possibly Breaking Change in v1.5.0
+-----------------------------------------------------------------------------
+In previous versions of Wrench, we went against the OS-default behavior of not
+deleting a directory unless the operation is forced. In 1.5.0, this has been
+changed to be the behavior people expect there to be - if you try to copy over
+a directory that already exists, you'll get an Error returned or thrown stating
+that you need to force it.
+
+Something like this will do the trick:
+
+``` javascript
+wrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end_up', {
+ forceDelete: true
+});
+```
+
+If you desire the older behavior of Wrench... hit up your package.json. If you
+happen to find bugs in the 1.5.0 release please feel free to file them on the
+GitHub issues tracker for this project, or send me a pull request and I'll get to
+it as fast as I can. Thanks!
+
+**If this breaks enough projects I will consider rolling it back. Please hit me up if this seems to be the case.**
+
+Installation
+-----------------------------------------------------------------------------
+
+ npm install wrench
+
+Usage
+-----------------------------------------------------------------------------
+``` javascript
+var wrench = require('wrench'),
+ util = require('util');
+```
+
+### Synchronous operations
+``` javascript
+// Recursively create directories, sub-trees and all.
+wrench.mkdirSyncRecursive(dir, 0777);
+
+// Recursively delete the entire sub-tree of a directory, then kill the directory
+wrench.rmdirSyncRecursive('my_directory_name', failSilently);
+
+// Recursively read directories contents.
+wrench.readdirSyncRecursive('my_directory_name');
+
+// Recursively chmod the entire sub-tree of a directory
+wrench.chmodSyncRecursive('my_directory_name', 0755);
+
+// Recursively chown the entire sub-tree of a directory
+wrench.chownSyncRecursive("directory", uid, gid);
+
+// Deep-copy an existing directory
+wrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end_up', {
+ 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
+ include: 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
+// 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()) {
+ util.puts(f.getNextLine());
+}
+
+// Note: You will need to close that above line reader at some point, otherwise
+// you will run into a "too many open files" error. f.close() or fs.closeSync(f.fd) are
+// your friends, as only you know when it is safe to close.
+```
+
+### Asynchronous operations
+``` javascript
+// Recursively read directories contents
+var files = [];
+wrench.readdirRecursive('my_directory_name', function(error, curFiles) {
+ // curFiles is what you want
+});
+
+// If you're feeling somewhat masochistic
+wrench.copyDirRecursive(srcDir, newDir, {forceDelete: bool /* See sync version */}, callbackfn);
+```
+
+Questions, comments? Hit me up. (ryan [at] venodesigns.net | http://twitter.com/ryanmcgrath)
diff --git a/tests/copydirsync_unix.js b/tests/copydirsync_unix.js
new file mode 100644
index 0000000..c48bb62
--- /dev/null
+++ b/tests/copydirsync_unix.js
@@ -0,0 +1,242 @@
+var testCase = require('nodeunit').testCase;
+var fs = require('fs');
+var wrench = require('../lib/wrench');
+var path = require('path');
+
+function checkResultHidden(test, files) {
+ var check = [
+ '.hidden',
+ '.hidden.txt',
+ 'bar.txt',
+ 'foo',
+ path.join('.hidden', 'dolor.md'),
+ path.join('foo', 'bar'),
+ path.join('foo', 'dolor.md'),
+ path.join('foo', 'lorem.txt'),
+ path.join('foo', 'bar', 'ipsum.js')
+ ];
+
+ test.deepEqual(files, check);
+}
+
+function checkResultShown(test, files) {
+ var check = [
+ 'bar.txt',
+ 'foo',
+ path.join('foo', 'bar'),
+ path.join('foo', 'dolor.md'),
+ path.join('foo', 'lorem.txt'),
+ path.join('foo', 'bar', 'ipsum.js')
+ ];
+
+ test.deepEqual(files, check);
+}
+
+function checkResultInflate(test, files) {
+ var check = [
+ '.hidden',
+ '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 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',
+ 'bar.txt',
+ 'test',
+ path.join('.hidden', 'dolor.md')
+ ];
+
+ test.deepEqual(files, check);
+
+ test.deepEqual(fs.lstatSync(path.join(__dirname, 'testdir/.hidden')).isSymbolicLink(), true);
+ test.deepEqual(fs.lstatSync(path.join(__dirname, 'testdir/bar.txt')).isSymbolicLink(), true);
+}
+
+function checkResultPreserveFiles(test, files) {
+ checkResultHidden(test, files);
+ var contents = fs.readFileSync(path.join(__dirname, path.join('testdir2', '.hidden.txt')), "utf8");
+ test.deepEqual(contents, 'hidden file');
+ contents = fs.readFileSync(path.join(__dirname, path.join('testdir2', 'bar.txt')), "utf8");
+ test.deepEqual(contents, 'shown file');
+}
+
+function checkResultOverwriteFiles(test, files) {
+ checkResultHidden(test, files);
+ var contents = fs.readFileSync(path.join(__dirname, path.join('testdir2', '.hidden.txt')), "utf8");
+ test.deepEqual(contents, 'just some text for .hidden.txt');
+ contents = fs.readFileSync(path.join(__dirname, path.join('testdir2', 'bar.txt')), "utf8");
+ test.deepEqual(contents, 'just some text for bar.txt');
+}
+
+module.exports = testCase({
+ test_copyDirSyncRecursiveWithoutOptions: function(test) {
+ var dir = path.join(__dirname, 'shown');
+ var testdir = path.join(__dirname, 'testdir');
+
+ wrench.copyDirSyncRecursive(dir, testdir);
+
+ wrench.rmdirSyncRecursive(testdir);
+ test.done();
+ },
+ test_copyDirSyncRecursiveHidden: function(test) {
+ var dir = path.join(__dirname, 'shown');
+ var testdir = path.join(__dirname, 'testdir');
+
+ test.ok(fs.existsSync(dir), 'Folders should exist');
+
+ wrench.copyDirSyncRecursive(dir, testdir, { excludeHiddenUnix: false });
+
+ var files = wrench.readdirSyncRecursive(testdir);
+
+ checkResultHidden(test, files);
+
+ wrench.rmdirSyncRecursive(testdir);
+
+ test.done();
+ },
+ test_copyDirSyncRecursiveShown: function(test) {
+ var dir = path.join(__dirname, 'shown');
+ var testdir = path.join(__dirname, 'testdir');
+
+ test.ok(fs.existsSync(dir), 'Folders should exist');
+
+ wrench.copyDirSyncRecursive(dir, testdir, { excludeHiddenUnix: true });
+
+ var files = wrench.readdirSyncRecursive(testdir);
+
+ checkResultShown(test, files);
+
+ wrench.rmdirSyncRecursive(testdir);
+
+ test.done();
+ },
+ test_copyDirSyncRecursiveInflate: function(test) {
+ var dir = path.join(__dirname, 'withsymlinks');
+ var testdir = path.join(__dirname, 'testdir');
+
+ test.ok(fs.existsSync(dir), 'Folders should exist');
+
+ wrench.copyDirSyncRecursive(dir, testdir, { excludeHiddenUnix: false, inflateSymlinks: true });
+
+ var files = wrench.readdirSyncRecursive(testdir);
+
+ checkResultInflate(test, files);
+
+ wrench.rmdirSyncRecursive(testdir);
+
+ 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');
+
+ test.ok(fs.existsSync(dir), 'Folders should exist');
+
+ wrench.copyDirSyncRecursive(dir, testdir, { excludeHiddenUnix: false, inflateSymlinks: false });
+
+ var files = wrench.readdirSyncRecursive(testdir);
+
+ checkResultDontInflate(test, files);
+
+ wrench.rmdirSyncRecursive(testdir);
+
+ test.done();
+ },
+ test_copyDirSyncRecursivePreserveFiles: function(test) {
+ var dir = path.join(__dirname, 'shown'),
+ testdir1 = path.join(__dirname, 'testdir1'),
+ testdir2 = path.join(__dirname, 'testdir2');
+
+ test.ok(fs.existsSync(dir), 'Folders should exist');
+
+ // 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, { excludeHiddenUnix: false, preserveFiles: true });
+
+ var files = wrench.readdirSyncRecursive(testdir2);
+
+ checkResultPreserveFiles(test, files);
+
+ wrench.rmdirSyncRecursive(testdir1);
+ wrench.rmdirSyncRecursive(testdir2);
+
+ test.done();
+ },
+ test_copyDirSyncRecursiveOverwriteFiles: function(test) {
+ var dir = path.join(__dirname, 'shown'),
+ testdir1 = path.join(__dirname, 'testdir1'),
+ testdir2 = path.join(__dirname, 'testdir2');
+
+ test.ok(fs.existsSync(dir), 'Folders should exist');
+
+ // 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, { forceDelete: true, excludeHiddenUnix: false, preserveFiles: false });
+
+ var files = wrench.readdirSyncRecursive(testdir2);
+
+ checkResultOverwriteFiles(test, files);
+
+ wrench.rmdirSyncRecursive(testdir1);
+ wrench.rmdirSyncRecursive(testdir2);
+
+ test.done();
+ }
+
+});
+
+// vim: et ts=4 sw=4
diff --git a/tests/mkdir.js b/tests/mkdir.js
new file mode 100644
index 0000000..933887b
--- /dev/null
+++ b/tests/mkdir.js
@@ -0,0 +1,26 @@
+var testCase = require('nodeunit').testCase;
+var fs = require('fs');
+var wrench = require('../lib/wrench');
+var path = require('path');
+
+module.exports = testCase({
+ test_mkdirSyncRecursive: function(test) {
+ var dir = __dirname + '/_tmp/foo/bar';
+
+ test.equals(fs.existsSync(dir), false, 'Dir shouldn\'t exist - clean it up manually?');
+
+ wrench.mkdirSyncRecursive(dir, 0777);
+
+ test.equals(fs.existsSync(dir), true, 'Dir should exist now');
+
+ // clean up
+ while (dir != __dirname) {
+ fs.rmdirSync(dir);
+ dir = path.dirname(dir);
+ }
+
+ test.done();
+ },
+});
+
+// vim: et ts=4 sw=4
diff --git a/tests/readdir.js b/tests/readdir.js
new file mode 100644
index 0000000..5e8abf0
--- /dev/null
+++ b/tests/readdir.js
@@ -0,0 +1,61 @@
+var testCase = require('nodeunit').testCase;
+var fs = require('fs');
+var wrench = require('../lib/wrench');
+var path = require('path');
+
+
+function checkResult(test, files) {
+ var check = [
+ 'bar.txt',
+ 'foo',
+ path.join('foo', 'bar'),
+ path.join('foo', 'dolor.md'),
+ path.join('foo', 'lorem.txt'),
+ path.join('foo', 'bar', 'ipsum.js')
+ ];
+
+ test.deepEqual(files, check);
+
+ test.done();
+}
+
+module.exports = testCase({
+ test_readdirSyncRecursive: function(test) {
+ var dir = path.join(__dirname, 'readdir');
+
+ test.ok(fs.existsSync(dir), 'Folders should exist');
+
+ var files = wrench.readdirSyncRecursive(dir);
+
+ checkResult(test, files);
+ },
+
+ test_readdirRecursive: function(test) {
+ var dir = path.join(__dirname, 'readdir');
+
+ test.ok(fs.existsSync(dir), 'Folders should exist');
+
+ var allFiles = [];
+
+ wrench.readdirRecursive(dir, function(e, files) {
+ if (e) throw e;
+
+ if (files) {
+ allFiles = allFiles.concat(files);
+ } else {
+ checkResult(test, allFiles);
+ }
+ });
+ },
+
+ test_readdirRecursiveWithNonExistentDirectory: function(test) {
+ wrench.readdirRecursive('', function (e, files) {
+ test.ok(e);
+ test.equal(e.code, 'ENOENT');
+ test.equal(files, null);
+ test.done();
+ });
+ }
+});
+
+// vim: et ts=4 sw=4
diff --git a/tests/readdir/bar.txt b/tests/readdir/bar.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/readdir/foo/bar/ipsum.js b/tests/readdir/foo/bar/ipsum.js
new file mode 100644
index 0000000..e69de29
diff --git a/tests/readdir/foo/dolor.md b/tests/readdir/foo/dolor.md
new file mode 100644
index 0000000..e69de29
diff --git a/tests/readdir/foo/lorem.txt b/tests/readdir/foo/lorem.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/rmdirSyncRecursive.js b/tests/rmdirSyncRecursive.js
new file mode 100644
index 0000000..3415e84
--- /dev/null
+++ b/tests/rmdirSyncRecursive.js
@@ -0,0 +1,74 @@
+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 + '/_tmp2/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, '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');
+ 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, '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');
+ 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
diff --git a/tests/runner.js b/tests/runner.js
new file mode 100644
index 0000000..e321a15
--- /dev/null
+++ b/tests/runner.js
@@ -0,0 +1,9 @@
+// `nodeunit tests/runner`
+// will run all the tests
+
+module.exports = {
+ group_mkdir: require('./mkdir'),
+ group_readdir: require('./readdir'),
+ group_copydir: require('./copydirsync_unix'),
+ group_rmdir: require('./rmdirSyncRecursive')
+};
diff --git a/tests/shown/.hidden.txt b/tests/shown/.hidden.txt
new file mode 100644
index 0000000..b96b725
--- /dev/null
+++ b/tests/shown/.hidden.txt
@@ -0,0 +1 @@
+hidden file
\ No newline at end of file
diff --git a/tests/shown/.hidden/dolor.md b/tests/shown/.hidden/dolor.md
new file mode 100644
index 0000000..e69de29
diff --git a/tests/shown/bar.txt b/tests/shown/bar.txt
new file mode 100644
index 0000000..3d36c5c
--- /dev/null
+++ b/tests/shown/bar.txt
@@ -0,0 +1 @@
+shown file
\ No newline at end of file
diff --git a/tests/shown/foo/bar/ipsum.js b/tests/shown/foo/bar/ipsum.js
new file mode 100644
index 0000000..e69de29
diff --git a/tests/shown/foo/dolor.md b/tests/shown/foo/dolor.md
new file mode 100644
index 0000000..e69de29
diff --git a/tests/shown/foo/lorem.txt b/tests/shown/foo/lorem.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/withsymlinks/test b/tests/withsymlinks/test
new file mode 100644
index 0000000..dba6882
--- /dev/null
+++ b/tests/withsymlinks/test
@@ -0,0 +1 @@
+aaa bbb ccc ddd
\ No newline at end of file
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-wrench.git
More information about the Pkg-javascript-commits
mailing list