diff --git a/.gitignore b/.gitignore index c2658d7..78f2710 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules/ +.idea/ diff --git a/lib/tmp.js b/lib/tmp.js index dcb5bbb..ea84faa 100644 --- a/lib/tmp.js +++ b/lib/tmp.js @@ -167,9 +167,13 @@ function _createTmpFile(options, callback) { fs.open(name, _c.O_CREAT | _c.O_EXCL | _c.O_RDWR, opts.mode || 0600, function _fileCreated(err, fd) { if (err) return cb(err); - if (!opts.keep) _removeObjects.unshift([ fs.unlinkSync, name ]); + var removeCallback = _prepareRemoveCallback(fs.unlinkSync.bind(fs), name); - cb(null, name, fd); + if (!opts.keep) { + _removeObjects.unshift(removeCallback); + } + + cb(null, name, fd, removeCallback); }); }); } @@ -177,7 +181,7 @@ function _createTmpFile(options, callback) { /** * Removes files and folders in a directory recursively. * - * @param {String} path + * @param {String} dir */ function _rmdirRecursiveSync(dir) { var files = fs.readdirSync(dir); @@ -197,6 +201,26 @@ function _rmdirRecursiveSync(dir) { fs.rmdirSync(dir); } +/** + * + * @param {Function} removeFunction + * @param {String} path + * @returns {Function} + * @private + */ +function _prepareRemoveCallback(removeFunction, path) { + var called = false; + return function() { + if (called) { + return; + } + + removeFunction(path); + + called = true; + }; +} + /** * Creates a temporary directory. * @@ -218,15 +242,18 @@ function _createTmpDir(options, callback) { fs.mkdir(name, opts.mode || 0700, function _dirCreated(err) { if (err) return cb(err); + var removeCallback = _prepareRemoveCallback( + opts.unsafeCleanup + ? _rmdirRecursiveSync + : fs.rmdirSync.bind(fs), + name + ); + if (!opts.keep) { - if (opts.unsafeCleanup) { - _removeObjects.unshift([ _rmdirRecursiveSync, name ]); - } else { - _removeObjects.unshift([ fs.rmdirSync, name ]); - } + _removeObjects.unshift(removeCallback); } - cb(null, name); + cb(null, name, removeCallback); }); }); } @@ -243,7 +270,7 @@ function _garbageCollector() { for (var i = 0, length = _removeObjects.length; i < length; i++) { try { - _removeObjects[i][0].call(null, _removeObjects[i][1]); + _removeObjects[i].call(null); } catch (e) { // already removed? } diff --git a/test/dir-test.js b/test/dir-test.js index 9b89009..2e4e529 100644 --- a/test/dir-test.js +++ b/test/dir-test.js @@ -179,5 +179,18 @@ vows.describe('Directory creation').addBatch({ 'should not return with an error': assert.isNull, 'should return with a name': Test.assertName, 'should be a directory': _testDir(040700) + }, + + 'remove callback': { + topic: function () { + tmp.dir(this.callback); + }, + + 'should not return with an error': assert.isNull, + 'should return with a name': Test.assertName, + 'removeCallback should remove directory': function (_err, name, removeCallback) { + removeCallback(); + assert.ok(!existsSync(name), "Directory should be removed"); + } } }).exportTo(module); diff --git a/test/file-test.js b/test/file-test.js index 150ca11..0cde37c 100644 --- a/test/file-test.js +++ b/test/file-test.js @@ -160,6 +160,19 @@ vows.describe('File creation').addBatch({ 'should not exist': function (err, name) { assert.ok(!existsSync(name), "File should be removed"); } + }, + + 'remove callback': { + topic: function () { + tmp.file(this.callback); + }, + + 'should not return with an error': assert.isNull, + 'should return with a name': Test.assertName, + 'removeCallback should remove file': function (_err, name, _fd, removeCallback) { + removeCallback(); + assert.ok(!existsSync(name), "File should be removed"); + } } }).exportTo(module);