pax_global_header00006660000000000000000000000064125421033660014514gustar00rootroot0000000000000052 comment=645d8f4c783abf84204be704098fdd41f36ab195 node-mv-2.1.1/000077500000000000000000000000001254210336600130625ustar00rootroot00000000000000node-mv-2.1.1/.gitignore000066400000000000000000000000161254210336600150470ustar00rootroot00000000000000/node_modules node-mv-2.1.1/.travis.yml000066400000000000000000000000611254210336600151700ustar00rootroot00000000000000language: node_js node_js: - "0.12" - "0.10" node-mv-2.1.1/LICENSE000066400000000000000000000020411254210336600140640ustar00rootroot00000000000000Copyright (c) 2014 Andrew Kelley 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. node-mv-2.1.1/README.md000066400000000000000000000014771254210336600143520ustar00rootroot00000000000000[![Build Status](https://secure.travis-ci.org/andrewrk/node-mv.png)](http://travis-ci.org/andrewrk/node-mv) Usage: ------ ```js var mv = require('mv'); mv('source/file', 'dest/file', function(err) { // done. it tried fs.rename first, and then falls back to // piping the source file to the dest file and then unlinking // the source file. }); ``` Another example: ```js mv('source/dir', 'dest/a/b/c/dir', {mkdirp: true}, function(err) { // done. it first created all the necessary directories, and then // tried fs.rename, then falls back to using ncp to copy the dir // to dest and then rimraf to remove the source dir }); ``` Another example: ```js mv('source/file', 'dest/file', {clobber: false}, function(err) { // done. If 'dest/file' exists, an error is returned // with err.code === 'EEXIST'. }); ``` node-mv-2.1.1/index.js000066400000000000000000000047451254210336600145410ustar00rootroot00000000000000var fs = require('fs'); var ncp = require('ncp').ncp; var path = require('path'); var rimraf = require('rimraf'); var mkdirp = require('mkdirp'); module.exports = mv; function mv(source, dest, options, cb){ if (typeof options === 'function') { cb = options; options = {}; } var shouldMkdirp = !!options.mkdirp; var clobber = options.clobber !== false; var limit = options.limit || 16; if (shouldMkdirp) { mkdirs(); } else { doRename(); } function mkdirs() { mkdirp(path.dirname(dest), function(err) { if (err) return cb(err); doRename(); }); } function doRename() { if (clobber) { fs.rename(source, dest, function(err) { if (!err) return cb(); if (err.code !== 'EXDEV') return cb(err); moveFileAcrossDevice(source, dest, clobber, limit, cb); }); } else { fs.link(source, dest, function(err) { if (err) { if (err.code === 'EXDEV') { moveFileAcrossDevice(source, dest, clobber, limit, cb); return; } if (err.code === 'EISDIR' || err.code === 'EPERM') { moveDirAcrossDevice(source, dest, clobber, limit, cb); return; } cb(err); return; } fs.unlink(source, cb); }); } } } function moveFileAcrossDevice(source, dest, clobber, limit, cb) { var outFlags = clobber ? 'w' : 'wx'; var ins = fs.createReadStream(source); var outs = fs.createWriteStream(dest, {flags: outFlags}); ins.on('error', function(err){ ins.destroy(); outs.destroy(); outs.removeListener('close', onClose); if (err.code === 'EISDIR' || err.code === 'EPERM') { moveDirAcrossDevice(source, dest, clobber, limit, cb); } else { cb(err); } }); outs.on('error', function(err){ ins.destroy(); outs.destroy(); outs.removeListener('close', onClose); cb(err); }); outs.once('close', onClose); ins.pipe(outs); function onClose(){ fs.unlink(source, cb); } } function moveDirAcrossDevice(source, dest, clobber, limit, cb) { var options = { stopOnErr: true, clobber: false, limit: limit, }; if (clobber) { rimraf(dest, { disableGlob: true }, function(err) { if (err) return cb(err); startNcp(); }); } else { startNcp(); } function startNcp() { ncp(source, dest, options, function(errList) { if (errList) return cb(errList[0]); rimraf(source, { disableGlob: true }, cb); }); } } node-mv-2.1.1/package.json000066400000000000000000000014571254210336600153570ustar00rootroot00000000000000{ "name": "mv", "version": "2.1.1", "description": "fs.rename but works across devices. same as the unix utility 'mv'", "main": "index.js", "scripts": { "test": "mocha test/test.js --reporter spec" }, "repository": { "type": "git", "url": "git://github.com/andrewrk/node-mv.git" }, "keywords": [ "mv", "move", "rename", "device", "recursive", "folder" ], "author": "Andrew Kelley", "license": "MIT", "engines": { "node": ">=0.8.0" }, "devDependencies": { "mocha": "~2.2.5" }, "dependencies": { "mkdirp": "~0.5.1", "ncp": "~2.0.0", "rimraf": "~2.4.0" }, "bugs": { "url": "https://github.com/andrewrk/node-mv/issues" }, "homepage": "https://github.com/andrewrk/node-mv", "directories": { "test": "test" } } node-mv-2.1.1/test/000077500000000000000000000000001254210336600140415ustar00rootroot00000000000000node-mv-2.1.1/test/a-file000066400000000000000000000000231254210336600151140ustar00rootroot00000000000000sonic the hedgehog node-mv-2.1.1/test/a-folder/000077500000000000000000000000001254210336600155325ustar00rootroot00000000000000node-mv-2.1.1/test/a-folder/another-file000066400000000000000000000000061254210336600200260ustar00rootroot00000000000000tails node-mv-2.1.1/test/a-folder/another-folder/000077500000000000000000000000001254210336600204435ustar00rootroot00000000000000node-mv-2.1.1/test/a-folder/another-folder/file3000066400000000000000000000000111254210336600213600ustar00rootroot00000000000000knuckles node-mv-2.1.1/test/test.js000066400000000000000000000115171254210336600153630ustar00rootroot00000000000000var assert = require('assert'); var fs = require('fs'); var rimraf = require('rimraf'); var describe = global.describe; var it = global.it; var mv = require('../'); var realFsRename = fs.rename; function overrideFsRename() { // makes fs.rename return cross-device error. fs.rename = function(src, dest, cb) { setTimeout(function() { var err = new Error(); err.code = 'EXDEV'; cb(err); }, 10); }; } function restoreFsRename() { fs.rename = realFsRename; } describe("mv", function() { it("should rename a file on the same device", function (done) { mv("test/a-file", "test/a-file-dest", function (err) { assert.ifError(err); fs.readFile("test/a-file-dest", 'utf8', function (err, contents) { assert.ifError(err); assert.strictEqual(contents, "sonic the hedgehog\n"); // move it back mv("test/a-file-dest", "test/a-file", done); }); }); }); it("should not overwrite if clobber = false", function (done) { mv("test/a-file", "test/a-folder/another-file", {clobber: false}, function (err) { assert.ok(err && err.code === 'EEXIST', "throw EEXIST"); done(); }); }); it("should not create directory structure by default", function (done) { mv("test/a-file", "test/does/not/exist/a-file-dest", function (err) { assert.strictEqual(err.code, 'ENOENT'); done(); }); }); it("should create directory structure when mkdirp option set", function (done) { mv("test/a-file", "test/does/not/exist/a-file-dest", {mkdirp: true}, function (err) { assert.ifError(err); fs.readFile("test/does/not/exist/a-file-dest", 'utf8', function (err, contents) { assert.ifError(err); assert.strictEqual(contents, "sonic the hedgehog\n"); // move it back mv("test/does/not/exist/a-file-dest", "test/a-file", function(err) { assert.ifError(err); rimraf("test/does", { disableGlob: true }, done); }); }); }); }); it("should work across devices", function (done) { overrideFsRename(); mv("test/a-file", "test/a-file-dest", function (err) { assert.ifError(err); fs.readFile("test/a-file-dest", 'utf8', function (err, contents) { assert.ifError(err); assert.strictEqual(contents, "sonic the hedgehog\n"); // move it back mv("test/a-file-dest", "test/a-file", function(err) { restoreFsRename(); done(err); }); }); }); }); it("should work across devices, even with special characters", function (done) { overrideFsRename(); mv("test/a-file", "test/a-*", function (err) { assert.ifError(err); fs.readFile("test/a-*", 'utf8', function (err, contents) { assert.ifError(err); assert.strictEqual(contents, "sonic the hedgehog\n"); // move it back mv("test/a-*", "test/a-file", function(err) { assert.ifError(err); fs.readFile("test/a-file", 'utf8', function (err, contents) { assert.ifError(err); assert.strictEqual(contents, "sonic the hedgehog\n"); restoreFsRename(); done(err); }); }); }); }); }); it("should move folders", function (done) { mv("test/a-folder", "test/a-folder-dest", function (err) { assert.ifError(err); fs.readFile("test/a-folder-dest/another-file", 'utf8', function (err, contents) { assert.ifError(err); assert.strictEqual(contents, "tails\n"); // move it back mv("test/a-folder-dest", "test/a-folder", done); }); }); }); it("should move folders across devices", function (done) { overrideFsRename(); mv("test/a-folder", "test/a-folder-dest", function (err) { assert.ifError(err); fs.readFile("test/a-folder-dest/another-folder/file3", 'utf8', function (err, contents) { assert.ifError(err); assert.strictEqual(contents, "knuckles\n"); // move it back mv("test/a-folder-dest", "test/a-folder", function(err) { restoreFsRename(); done(err); }); }); }); }); it("should move folders across devices, even with special characters", function (done) { overrideFsRename(); mv("test/a-folder", "test/a-*", function (err) { assert.ifError(err); fs.readFile("test/a-*/another-folder/file3", 'utf8', function (err, contents) { assert.ifError(err); assert.strictEqual(contents, "knuckles\n"); // move it back mv("test/a-*", "test/a-folder", function(err) { assert.ifError(err); fs.readFile("test/a-folder/another-folder/file3", 'utf8', function (err, contents) { assert.ifError(err); assert.strictEqual(contents, "knuckles\n"); restoreFsRename(); done(err); }); }); }); }); }); });