Skip to content

Commit

Permalink
Prevent race condition on macOS when deleting files (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisblossom authored and sindresorhus committed Jul 12, 2019
1 parent 9e7550b commit 8efdbcd
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 6 deletions.
8 changes: 6 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ module.exports = async (patterns, {force, dryRun, ...options} = {}) => {
...options
};

const files = await globby(patterns, options);
const files = (await globby(patterns, options))
.sort((a, b) => b.localeCompare(a));

const mapper = async file => {
if (!force) {
Expand All @@ -54,7 +55,10 @@ module.exports.sync = (patterns, {force, dryRun, ...options} = {}) => {
...options
};

return globby.sync(patterns, options).map(file => {
const files = globby.sync(patterns, options)
.sort((a, b) => b.localeCompare(a));

return files.map(file => {
if (!force) {
safeCheck(file);
}
Expand Down
79 changes: 75 additions & 4 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ test('don\'t delete files, but return them - async', async t => {
});
exists(t, ['1.tmp', '2.tmp', '3.tmp', '4.tmp', '.dot.tmp']);
t.deepEqual(deletedFiles, [
path.join(t.context.tmp, '2.tmp'),
path.join(t.context.tmp, '4.tmp'),
path.join(t.context.tmp, '3.tmp'),
path.join(t.context.tmp, '4.tmp')
path.join(t.context.tmp, '2.tmp')
]);
});

Expand All @@ -101,8 +101,79 @@ test('don\'t delete files, but return them - sync', t => {
});
exists(t, ['1.tmp', '2.tmp', '3.tmp', '4.tmp', '.dot.tmp']);
t.deepEqual(deletedFiles, [
path.join(t.context.tmp, '2.tmp'),
path.join(t.context.tmp, '4.tmp'),
path.join(t.context.tmp, '3.tmp'),
path.join(t.context.tmp, '4.tmp')
path.join(t.context.tmp, '2.tmp')
]);
});

// Currently this only testable locally on an osx machine.
// https://github.com/sindresorhus/del/issues/68
test.serial('does not throw EINVAL - async', async t => {
await del('**/*', {
cwd: t.context.tmp,
dot: true
});

const nestedFile = path.resolve(t.context.tmp, 'a/b/c/nested.js');
const totalAttempts = 200;

let count = 0;
while (count !== totalAttempts) {
makeDir.sync(nestedFile);

// eslint-disable-next-line no-await-in-loop
const removed = await del('**/*', {
cwd: t.context.tmp,
dot: true
});

const expected = [
path.resolve(t.context.tmp, 'a/b/c/nested.js'),
path.resolve(t.context.tmp, 'a/b/c'),
path.resolve(t.context.tmp, 'a/b'),
path.resolve(t.context.tmp, 'a')
];

t.deepEqual(removed, expected);

count += 1;
}

notExists(t, [...fixtures, 'a']);
t.is(count, totalAttempts);
});

test.serial('does not throw EINVAL - sync', t => {
del.sync('**/*', {
cwd: t.context.tmp,
dot: true
});

const nestedFile = path.resolve(t.context.tmp, 'a/b/c/nested.js');
const totalAttempts = 200;

let count = 0;
while (count !== totalAttempts) {
makeDir.sync(nestedFile);

const removed = del.sync('**/*', {
cwd: t.context.tmp,
dot: true
});

const expected = [
path.resolve(t.context.tmp, 'a/b/c/nested.js'),
path.resolve(t.context.tmp, 'a/b/c'),
path.resolve(t.context.tmp, 'a/b'),
path.resolve(t.context.tmp, 'a')
];

t.deepEqual(removed, expected);

count += 1;
}

notExists(t, [...fixtures, 'a']);
t.is(count, totalAttempts);
});

0 comments on commit 8efdbcd

Please sign in to comment.