Comparing version 0.0.1 to 0.0.2
81
index.js
@@ -7,28 +7,63 @@ var fs; | ||
fs.rename(source, dest, function(err){ | ||
var ins, outs; | ||
if (!err) { | ||
return cb(); | ||
} | ||
if (err.code !== 'EXDEV') { | ||
return cb(err); | ||
} | ||
ins = fs.createReadStream(source); | ||
outs = fs.createWriteStream(dest); | ||
ins.once('error', function(err){ | ||
outs.removeAllListeners('error'); | ||
outs.removeAllListeners('close'); | ||
outs.destroy(); | ||
cb(err); | ||
if (!err) return cb(); | ||
if (err.code !== 'EXDEV') return cb(err); | ||
fs.stat(source, function (err, stats) { | ||
if (err) return cb(err); | ||
if (stats.isFile()) { | ||
moveFileAcrossDevice(source, dest, cb); | ||
} else if (stats.isDirectory()) { | ||
moveDirAcrossDevice(source, dest, cb); | ||
} else { | ||
var err; | ||
err = new Error("source must be file or directory"); | ||
err.code = 'NOTFILEORDIR'; | ||
cb(err); | ||
} | ||
}); | ||
outs.once('error', function(err){ | ||
ins.removeAllListeners('error'); | ||
outs.removeAllListeners('close'); | ||
ins.destroy(); | ||
}); | ||
} | ||
function moveFileAcrossDevice(source, dest, cb) { | ||
var ins, outs; | ||
ins = fs.createReadStream(source); | ||
outs = fs.createWriteStream(dest); | ||
ins.once('error', function(err){ | ||
outs.removeAllListeners('error'); | ||
outs.removeAllListeners('close'); | ||
outs.destroy(); | ||
cb(err); | ||
}); | ||
outs.once('error', function(err){ | ||
ins.removeAllListeners('error'); | ||
outs.removeAllListeners('close'); | ||
ins.destroy(); | ||
cb(err); | ||
}); | ||
outs.once('close', function(){ | ||
fs.unlink(source, cb); | ||
}); | ||
ins.pipe(outs); | ||
} | ||
// TODO: do this natively instead of shelling out to `mv` | ||
function moveDirAcrossDevice(source, dest, cb) { | ||
var child, stdout, stderr, err; | ||
child = require('child_process').spawn('mv', [source, dest], {stdio: 'pipe'}); | ||
child.stderr.setEncoding('utf8'); | ||
child.stdout.setEncoding('utf8'); | ||
stderr = []; | ||
stdout = []; | ||
child.stderr.on('data', function(data) { stderr.push(data); }); | ||
child.stdout.on('data', function(data) { stdout.push(data); }); | ||
child.on('close', function(code) { | ||
if (code === 0) { | ||
cb(); | ||
} else { | ||
err = new Error("mv had nonzero exit code"); | ||
err.code = 'RETCODE'; | ||
err.stdout = stdout.join(''); | ||
err.stderr = stderr.join(''); | ||
cb(err); | ||
}); | ||
outs.once('close', function(){ | ||
fs.unlink(source, cb); | ||
}); | ||
ins.pipe(outs); | ||
} | ||
}); | ||
} |
{ | ||
"name": "mv", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "fs.rename but works across devices. same as the unix utility 'mv'", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -8,2 +8,15 @@ var assert, proxyquire, fs; | ||
describe("mv", function() { | ||
var mock_fs, mocked_mv; | ||
// makes fs.rename return cross-device error. | ||
mock_fs = {}; | ||
mock_fs.rename = function(src, dest, cb) { | ||
setTimeout(function() { | ||
var err; | ||
err = new Error(); | ||
err.code = 'EXDEV'; | ||
cb(err); | ||
}, 10); | ||
}; | ||
it("should rename a file on the same device", function (done) { | ||
@@ -26,17 +39,4 @@ var mv; | ||
it("should work across devices", function (done) { | ||
var mv, mock_fs; | ||
var mv; | ||
mock_fs = {}; | ||
mock_fs.createReadStream = fs.createReadStream; | ||
mock_fs.createWriteStream = fs.createWriteStream; | ||
mock_fs.unlink = fs.unlink; | ||
mock_fs.rename = function(src, dest, cb) { | ||
setTimeout(function() { | ||
var err; | ||
err = new Error(); | ||
err.code = 'EXDEV'; | ||
cb(err); | ||
}, 10); | ||
}; | ||
mv = proxyquire.resolve('../index', __dirname, {fs: mock_fs}); | ||
@@ -53,2 +53,34 @@ mv("test/a-file", "test/a-file-dest", function (err) { | ||
}); | ||
it("should move folders", function (done) { | ||
var mv; | ||
mv = proxyquire.resolve('../index', __dirname, {}); | ||
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) { | ||
var mv; | ||
mv = proxyquire.resolve('../index', __dirname, {fs: mock_fs}); | ||
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", done); | ||
}); | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
5205
133
1