From 93b02091320687702505350876c8f0ee72bab4b7 Mon Sep 17 00:00:00 2001 From: Chris Blossom Date: Thu, 11 Jul 2019 16:48:53 -0700 Subject: [PATCH 1/4] Run all tests as serial --- test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test.js b/test.js index 6d6fee5..90cf420 100644 --- a/test.js +++ b/test.js @@ -1,6 +1,6 @@ import path from 'path'; import fs from 'fs'; -import test from 'ava'; +import {serial as test} from 'ava'; import tempy from 'tempy'; import makeDir from 'make-dir'; import del from '.'; @@ -67,7 +67,7 @@ test('take options into account - sync', t => { notExists(t, ['2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); }); -test.serial('return deleted files - async', async t => { +test('return deleted files - async', async t => { t.deepEqual( await del('1.tmp', {cwd: t.context.tmp}), [path.join(t.context.tmp, '1.tmp')] From e8ab0fb32035d026443b1c4108a6f9824a9b017e Mon Sep 17 00:00:00 2001 From: Chris Blossom Date: Thu, 11 Jul 2019 16:28:14 -0700 Subject: [PATCH 2/4] Fix safeCheck to take into account cwd option --- index.js | 24 +++++++++++++----------- package.json | 2 +- test.js | 30 ++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index 408a9a6..9d8251c 100644 --- a/index.js +++ b/index.js @@ -3,27 +3,28 @@ const {promisify} = require('util'); const path = require('path'); const globby = require('globby'); const isPathCwd = require('is-path-cwd'); -const isPathInCwd = require('is-path-in-cwd'); +const isPathInside = require('is-path-inside'); const rimraf = require('rimraf'); const pMap = require('p-map'); const rimrafP = promisify(rimraf); -function safeCheck(file) { +function safeCheck(file, cwd) { if (isPathCwd(file)) { throw new Error('Cannot delete the current working directory. Can be overridden with the `force` option.'); } - if (!isPathInCwd(file)) { + if (!isPathInside(file, cwd)) { throw new Error('Cannot delete files/directories outside the current working directory. Can be overridden with the `force` option.'); } } -module.exports = async (patterns, {force, dryRun, ...options} = {}) => { +module.exports = async (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => { options = { expandDirectories: false, onlyFiles: false, followSymbolicLinks: false, + cwd, ...options }; @@ -31,12 +32,12 @@ module.exports = async (patterns, {force, dryRun, ...options} = {}) => { .sort((a, b) => b.localeCompare(a)); const mapper = async file => { + file = path.resolve(cwd, file); + if (!force) { - safeCheck(file); + safeCheck(file, cwd); } - file = path.resolve(options.cwd || '', file); - if (!dryRun) { await rimrafP(file, {glob: false}); } @@ -47,11 +48,12 @@ module.exports = async (patterns, {force, dryRun, ...options} = {}) => { return pMap(files, mapper, options); }; -module.exports.sync = (patterns, {force, dryRun, ...options} = {}) => { +module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => { options = { expandDirectories: false, onlyFiles: false, followSymbolicLinks: false, + cwd, ...options }; @@ -59,12 +61,12 @@ module.exports.sync = (patterns, {force, dryRun, ...options} = {}) => { .sort((a, b) => b.localeCompare(a)); return files.map(file => { + file = path.resolve(cwd, file); + if (!force) { - safeCheck(file); + safeCheck(file, cwd); } - file = path.resolve(options.cwd || '', file); - if (!dryRun) { rimraf.sync(file, {glob: false}); } diff --git a/package.json b/package.json index c4bbb12..054bfb2 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "dependencies": { "globby": "^10.0.0", "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", + "is-path-inside": "^3.0.1", "p-map": "^2.0.0", "rimraf": "^2.6.3" }, diff --git a/test.js b/test.js index 90cf420..ac6844f 100644 --- a/test.js +++ b/test.js @@ -177,3 +177,33 @@ test.serial('does not throw EINVAL - sync', t => { notExists(t, [...fixtures, 'a']); t.is(count, totalAttempts); }); + +test('delete relative files outside of process.cwd using cwd - async', async t => { + await del(['1.tmp'], {cwd: t.context.tmp}); + + exists(t, ['2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); + notExists(t, ['1.tmp']); +}); + +test('delete relative files outside of process.cwd using cwd - sync', t => { + del.sync(['1.tmp'], {cwd: t.context.tmp}); + + exists(t, ['2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); + notExists(t, ['1.tmp']); +}); + +test('delete absolute files outside of process.cwd using cwd - async', async t => { + const absolutePath = path.resolve(t.context.tmp, '1.tmp'); + await del([absolutePath], {cwd: t.context.tmp}); + + exists(t, ['2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); + notExists(t, ['1.tmp']); +}); + +test('delete absolute files outside of process.cwd using cwd - sync', t => { + const absolutePath = path.resolve(t.context.tmp, '1.tmp'); + del.sync([absolutePath], {cwd: t.context.tmp}); + + exists(t, ['2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); + notExists(t, ['1.tmp']); +}); From 16f4deef7522822861bf270ba9f33e7d9e58f0d7 Mon Sep 17 00:00:00 2001 From: Chris Blossom Date: Thu, 11 Jul 2019 16:49:50 -0700 Subject: [PATCH 3/4] Add more tests --- test.js | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/test.js b/test.js index ac6844f..e2a9015 100644 --- a/test.js +++ b/test.js @@ -5,6 +5,8 @@ import tempy from 'tempy'; import makeDir from 'make-dir'; import del from '.'; +const processCwd = process.cwd(); + function exists(t, files) { for (const file of files) { t.true(fs.existsSync(path.join(t.context.tmp, file))); @@ -207,3 +209,101 @@ test('delete absolute files outside of process.cwd using cwd - sync', t => { exists(t, ['2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); notExists(t, ['1.tmp']); }); + +test('cannot delete actual working directory without force: true - async', async t => { + process.chdir(t.context.tmp); + + await t.throwsAsync(() => del([t.context.tmp]), { + instanceOf: Error, + message: 'Cannot delete the current working directory. Can be overridden with the `force` option.' + }); + + exists(t, ['', '1.tmp', '2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); + process.chdir(processCwd); +}); + +test('cannot delete actual working directory without force: true - sync', t => { + process.chdir(t.context.tmp); + + t.throws(() => del.sync([t.context.tmp]), { + instanceOf: Error, + message: 'Cannot delete the current working directory. Can be overridden with the `force` option.' + }); + + exists(t, ['', '1.tmp', '2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); + process.chdir(processCwd); +}); + +test('cannot delete actual working directory with cwd option without force: true - async', async t => { + process.chdir(t.context.tmp); + + await t.throwsAsync(() => del([t.context.tmp], {cwd: __dirname}), { + instanceOf: Error, + message: 'Cannot delete the current working directory. Can be overridden with the `force` option.' + }); + + exists(t, ['', '1.tmp', '2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); + process.chdir(processCwd); +}); + +test('cannot delete actual working directory with cwd option without force: true - sync', t => { + process.chdir(t.context.tmp); + + t.throws(() => del.sync([t.context.tmp], {cwd: __dirname}), { + instanceOf: Error, + message: 'Cannot delete the current working directory. Can be overridden with the `force` option.' + }); + + exists(t, ['', '1.tmp', '2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); + process.chdir(processCwd); +}); + +test('cannot delete files outside cwd without force: true - async', async t => { + const absolutePath = path.resolve(t.context.tmp, '1.tmp'); + + await t.throwsAsync(() => del([absolutePath]), { + instanceOf: Error, + message: 'Cannot delete files/directories outside the current working directory. Can be overridden with the `force` option.' + }); + + exists(t, ['1.tmp', '2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); +}); + +test('cannot delete files outside cwd without force: true - sync', t => { + const absolutePath = path.resolve(t.context.tmp, '1.tmp'); + + t.throws(() => del.sync([absolutePath]), { + instanceOf: Error, + message: 'Cannot delete files/directories outside the current working directory. Can be overridden with the `force` option.' + }); + + exists(t, ['', '1.tmp', '2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); +}); + +test('cannot delete files inside process.cwd when outside cwd without force: true - async', async t => { + process.chdir(t.context.tmp); + const removeFile = path.resolve(t.context.tmp, '2.tmp'); + const cwd = path.resolve(t.context.tmp, '1.tmp'); + + await t.throwsAsync(() => del([removeFile], {cwd}), { + instanceOf: Error, + message: 'Cannot delete files/directories outside the current working directory. Can be overridden with the `force` option.' + }); + + exists(t, ['1.tmp', '2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); + process.chdir(processCwd); +}); + +test('cannot delete files inside process.cwd when outside cwd without force: true - sync', t => { + process.chdir(t.context.tmp); + const removeFile = path.resolve(t.context.tmp, '2.tmp'); + const cwd = path.resolve(t.context.tmp, '1.tmp'); + + t.throws(() => del.sync([removeFile], {cwd}), { + instanceOf: Error, + message: 'Cannot delete files/directories outside the current working directory. Can be overridden with the `force` option.' + }); + + exists(t, ['1.tmp', '2.tmp', '3.tmp', '4.tmp', '.dot.tmp']); + process.chdir(processCwd); +}); From 2dc7c750edf96b3c318b5053ada4a7a42265d97b Mon Sep 17 00:00:00 2001 From: Chris Blossom Date: Fri, 12 Jul 2019 11:38:13 -0700 Subject: [PATCH 4/4] Remove accidental `test.serial` --- test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test.js b/test.js index e2a9015..a106823 100644 --- a/test.js +++ b/test.js @@ -111,7 +111,7 @@ test('don\'t delete files, but return them - sync', t => { // 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 => { +test('does not throw EINVAL - async', async t => { await del('**/*', { cwd: t.context.tmp, dot: true @@ -146,7 +146,7 @@ test.serial('does not throw EINVAL - async', async t => { t.is(count, totalAttempts); }); -test.serial('does not throw EINVAL - sync', t => { +test('does not throw EINVAL - sync', t => { del.sync('**/*', { cwd: t.context.tmp, dot: true