fs-jetpack
Advanced tools
Comparing version 0.13.2 to 0.13.3
@@ -0,1 +1,4 @@ | ||
# 0.13.3 (2017-03-25) | ||
- `removeAsync()` retries deletion attempts for errors like `EBUSY`. | ||
# 0.13.2 (2017-03-21) | ||
@@ -2,0 +5,0 @@ - Nested directory creation handles well race condition |
@@ -43,4 +43,27 @@ 'use strict'; | ||
var removeAsync = function (path) { | ||
var removeAsyncInternal = function (path, retryCount) { | ||
return new Promise(function (resolve, reject) { | ||
var retryInAWhileOrFail = function (err) { | ||
if (retryCount === 3) { | ||
// Too many retries already. Fail. | ||
reject(err); | ||
} else { | ||
// Try the same action after some pause. | ||
setTimeout(function () { | ||
removeAsyncInternal(path, retryCount + 1) | ||
.then(resolve, reject); | ||
}, 100); | ||
} | ||
}; | ||
var removeEverythingInsideDirectory = function () { | ||
return list.async(path) | ||
.then(function (filenamesInsideDir) { | ||
var promises = filenamesInsideDir.map(function (filename) { | ||
return removeAsyncInternal(pathUtil.join(path, filename), 0); | ||
}); | ||
return Promise.all(promises); | ||
}); | ||
}; | ||
// Assume the path is a file and just try to remove it. | ||
@@ -50,17 +73,22 @@ fs.unlink(path) | ||
.catch(function (err) { | ||
if (err.code === 'EPERM' || err.code === 'EISDIR' || err.code === 'ENOTEMPTY') { | ||
// It's not a file, it's a directory. | ||
// Must delete everything inside first. | ||
list.async(path).then(function (filenamesInsideDir) { | ||
var promises = filenamesInsideDir.map(function (filename) { | ||
return removeAsync(pathUtil.join(path, filename)); | ||
}); | ||
return Promise.all(promises); | ||
}) | ||
if (err.code === 'EBUSY') { | ||
retryInAWhileOrFail(err); | ||
} else if (err.code === 'EPERM' || err.code === 'EISDIR' || err.code === 'ENOTEMPTY') { | ||
// File deletion attempt failed. Probably it's not a file, it's a directory. | ||
// So try to proceed with that assumption. | ||
removeEverythingInsideDirectory() | ||
.then(function () { | ||
// Everything inside directory has been removed, | ||
// it's safe now to go for the directory itself. | ||
// Now go for the directory. | ||
return fs.rmdir(path); | ||
}) | ||
.then(resolve, reject); | ||
.then(resolve) | ||
.catch(function (err2) { | ||
if (err2.code === 'EBUSY' || err2.code === 'EPERM' || err2.code === 'ENOTEMPTY') { | ||
// Failed again. This might be due to other processes reading | ||
// something inside the directory. Let's take a nap and retry. | ||
retryInAWhileOrFail(err2); | ||
} else { | ||
reject(err2); | ||
} | ||
}); | ||
} else if (err.code === 'ENOENT') { | ||
@@ -77,2 +105,6 @@ // File already doesn't exist. We're done. | ||
var removeAsync = function (path) { | ||
return removeAsyncInternal(path, 0); | ||
}; | ||
// --------------------------------------------------------- | ||
@@ -79,0 +111,0 @@ // API |
{ | ||
"name": "fs-jetpack", | ||
"description": "Better file system API", | ||
"version": "0.13.2", | ||
"version": "0.13.3", | ||
"author": "Jakub Szwacz <jakub@szwacz.com>", | ||
@@ -6,0 +6,0 @@ "dependencies": { |
@@ -76,2 +76,36 @@ var fse = require('fs-extra'); | ||
describe('will retry attempt if file is locked', function () { | ||
var preparations = function () { | ||
fse.mkdirsSync('a/b/c'); | ||
fse.outputFileSync('a/f.txt', 'abc'); | ||
fse.outputFileSync('a/b/f.txt', '123'); | ||
}; | ||
var expectations = function () { | ||
path('a').shouldNotExist(); | ||
}; | ||
it('async', function (done) { | ||
preparations(); | ||
fse.open('a/f.txt', 'w', function (err, fd) { | ||
if (err) { | ||
done(err); | ||
} else { | ||
// Unlock the file after some time. | ||
setTimeout(function () { | ||
fse.close(fd); | ||
}, 150); | ||
jetpack.removeAsync('a') | ||
.then(function () { | ||
expectations(); | ||
done(); | ||
}) | ||
.catch(done); | ||
} | ||
}); | ||
}); | ||
}); | ||
describe('respects internal CWD of jetpack instance', function () { | ||
@@ -78,0 +112,0 @@ var preparations = function () { |
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
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
259238
7271