From aad8c93befd190725da95a234d3419a79697ea24 Mon Sep 17 00:00:00 2001 From: David Pate Date: Thu, 5 Mar 2015 15:54:30 -0500 Subject: [PATCH] Added the ability to pass a custom FS implementation and documentation around it. --- README.md | 13 +++++++++++++ lib/ncp.js | 27 ++++++++++++++------------- test/ncp.js | 23 +++++++++++++++++++++++ 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 9480032..4cda9b6 100644 --- a/README.md +++ b/README.md @@ -60,4 +60,17 @@ You can also call ncp like `ncp(source, destination, options, callback)`. * `options.errs` - stream. If `options.stopOnErr` is `false`, a stream can be provided, and errors will be written to this stream. + * `options.fs` - [Node.JS File System](http://nodejs.org/api/fs.html) compliant implementation. If provided, this will be used instead of `fs`. + The custom implementation must have the following methods implemented: + * [`fs.stat(path, callback)`](http://nodejs.org/api/fs.html#fs_fs_stat_path_callback) + * [`fs.lstat(path, callback)`](http://nodejs.org/api/fs.html#fs_fs_lstat_path_callback) + * [`fs.createReadStream(path[, options])`](http://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options) + * [`fs.createWriteStream(path[, options])`](http://nodejs.org/api/fs.html#fs_fs_createwritestream_path_options) + * [`fs.utimesSync(path, atime, mtime)`](http://nodejs.org/api/fs.html#fs_fs_utimessync_path_atime_mtime) + * [`fs.unlink(path, callback)`](http://nodejs.org/api/fs.html#fs_fs_unlink_path_callback) + * [`fs.mkdir(path[, mode], callback)`](http://nodejs.org/api/fs.html#fs_fs_mkdir_path_mode_callback) + * [`fs.readdir(path, callback)`](http://nodejs.org/api/fs.html#fs_fs_readdir_path_callback) + * [`fs.readlink(path, callback)`](http://nodejs.org/api/fs.html#fs_fs_readlink_path_callback) + * [`fs.symlink(srcpath, dstpath[, type], callback)`](http://nodejs.org/api/fs.html#fs_fs_symlink_srcpath_dstpath_type_callback) + Please open an issue if any bugs arise. As always, I accept (working) pull requests, and refunds are available at `/dev/null`. diff --git a/lib/ncp.js b/lib/ncp.js index 96eed47..036080c 100644 --- a/lib/ncp.js +++ b/lib/ncp.js @@ -21,6 +21,7 @@ function ncp (source, dest, options, callback) { clobber = options.clobber !== false, modified = options.modified, dereference = options.dereference, + xfs = options.fs || fs, errs = null, started = 0, finished = 0, @@ -49,7 +50,7 @@ function ncp (source, dest, options, callback) { } function getStats(source) { - var stat = dereference ? fs.stat : fs.lstat; + var stat = dereference ? xfs.stat : xfs.lstat; if (running >= limit) { return setImmediate(function () { getStats(source); @@ -96,7 +97,7 @@ function ncp (source, dest, options, callback) { }); } if (modified) { - var stat = dereference ? fs.stat : fs.lstat; + var stat = dereference ? xfs.stat : xfs.lstat; stat(target, function(err, stats) { //if souce modified time greater to target modified time copy file if (file.mtime.getTime()>stats.mtime.getTime()) @@ -111,8 +112,8 @@ function ncp (source, dest, options, callback) { } function copyFile(file, target) { - var readStream = fs.createReadStream(file.name), - writeStream = fs.createWriteStream(target, { mode: file.mode }); + var readStream = xfs.createReadStream(file.name), + writeStream = xfs.createWriteStream(target, { mode: file.mode }); readStream.on('error', onError); writeStream.on('error', onError); @@ -127,7 +128,7 @@ function ncp (source, dest, options, callback) { writeStream.once('finish', function() { if (modified) { //target file modified date sync. - fs.utimesSync(target, file.atime, file.mtime); + xfs.utimesSync(target, file.atime, file.mtime); cb(); } else cb(); @@ -135,7 +136,7 @@ function ncp (source, dest, options, callback) { } function rmFile(file, done) { - fs.unlink(file, function (err) { + xfs.unlink(file, function (err) { if (err) { return onError(err); } @@ -154,7 +155,7 @@ function ncp (source, dest, options, callback) { } function mkDir(dir, target) { - fs.mkdir(target, dir.mode, function (err) { + xfs.mkdir(target, dir.mode, function (err) { if (err) { return onError(err); } @@ -163,7 +164,7 @@ function ncp (source, dest, options, callback) { } function copyDir(dir) { - fs.readdir(dir, function (err, items) { + xfs.readdir(dir, function (err, items) { if (err) { return onError(err); } @@ -176,7 +177,7 @@ function ncp (source, dest, options, callback) { function onLink(link) { var target = link.replace(currentPath, targetPath); - fs.readlink(link, function (err, resolvedPath) { + xfs.readlink(link, function (err, resolvedPath) { if (err) { return onError(err); } @@ -192,7 +193,7 @@ function ncp (source, dest, options, callback) { if (writable) { return makeLink(resolvedPath, target); } - fs.readlink(target, function (err, targetDest) { + xfs.readlink(target, function (err, targetDest) { if (err) { return onError(err); } @@ -210,7 +211,7 @@ function ncp (source, dest, options, callback) { } function makeLink(linkPath, target) { - fs.symlink(linkPath, target, function (err) { + xfs.symlink(linkPath, target, function (err) { if (err) { return onError(err); } @@ -219,7 +220,7 @@ function ncp (source, dest, options, callback) { } function isWritable(path, done) { - fs.lstat(path, function (err) { + xfs.lstat(path, function (err) { if (err) { if (err.code === 'ENOENT') return done(true); return done(false); @@ -233,7 +234,7 @@ function ncp (source, dest, options, callback) { return cback(err); } else if (!errs && options.errs) { - errs = fs.createWriteStream(options.errs); + errs = xfs.createWriteStream(options.errs); } else if (!errs) { errs = []; diff --git a/test/ncp.js b/test/ncp.js index ffe1244..39df025 100644 --- a/test/ncp.js +++ b/test/ncp.js @@ -194,4 +194,27 @@ describe('ncp', function () { }); }); + + describe('copies with custom fs', function() { + var fixtures = path.join(__dirname, 'modified-files'), + src = path.join(fixtures, 'src'), + out = path.join(fixtures, 'out'); + + it ('with custom fs provided', function(cb) { + rimraf(out, function() { + ncp(src, out, {fs: fs}, function (err) { + assert.equal(fs.existsSync(out), true); + cb(err); + }); + }); + }); + it ('without custom fs provided', function(cb) { + rimraf(out, function() { + ncp(src, out, {fs: undefined}, function (err) { + assert.equal(fs.existsSync(out), true); + cb(err); + }); + }); + }); + }); });