You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
3.0 KiB
139 lines
3.0 KiB
'use strict'; |
|
const {promisify} = require('util'); |
|
const path = require('path'); |
|
const globby = require('globby'); |
|
const isGlob = require('is-glob'); |
|
const slash = require('slash'); |
|
const gracefulFs = require('graceful-fs'); |
|
const isPathCwd = require('is-path-cwd'); |
|
const isPathInside = require('is-path-inside'); |
|
const rimraf = require('rimraf'); |
|
const pMap = require('p-map'); |
|
|
|
const rimrafP = promisify(rimraf); |
|
|
|
const rimrafOptions = { |
|
glob: false, |
|
unlink: gracefulFs.unlink, |
|
unlinkSync: gracefulFs.unlinkSync, |
|
chmod: gracefulFs.chmod, |
|
chmodSync: gracefulFs.chmodSync, |
|
stat: gracefulFs.stat, |
|
statSync: gracefulFs.statSync, |
|
lstat: gracefulFs.lstat, |
|
lstatSync: gracefulFs.lstatSync, |
|
rmdir: gracefulFs.rmdir, |
|
rmdirSync: gracefulFs.rmdirSync, |
|
readdir: gracefulFs.readdir, |
|
readdirSync: gracefulFs.readdirSync |
|
}; |
|
|
|
function safeCheck(file, cwd) { |
|
if (isPathCwd(file)) { |
|
throw new Error('Cannot delete the current working directory. Can be overridden with the `force` option.'); |
|
} |
|
|
|
if (!isPathInside(file, cwd)) { |
|
throw new Error('Cannot delete files/directories outside the current working directory. Can be overridden with the `force` option.'); |
|
} |
|
} |
|
|
|
function normalizePatterns(patterns) { |
|
patterns = Array.isArray(patterns) ? patterns : [patterns]; |
|
|
|
patterns = patterns.map(pattern => { |
|
if (process.platform === 'win32' && isGlob(pattern) === false) { |
|
return slash(pattern); |
|
} |
|
|
|
return pattern; |
|
}); |
|
|
|
return patterns; |
|
} |
|
|
|
module.exports = async (patterns, {force, dryRun, cwd = process.cwd(), onProgress = () => {}, ...options} = {}) => { |
|
options = { |
|
expandDirectories: false, |
|
onlyFiles: false, |
|
followSymbolicLinks: false, |
|
cwd, |
|
...options |
|
}; |
|
|
|
patterns = normalizePatterns(patterns); |
|
|
|
const files = (await globby(patterns, options)) |
|
.sort((a, b) => b.localeCompare(a)); |
|
|
|
if (files.length === 0) { |
|
onProgress({ |
|
totalCount: 0, |
|
deletedCount: 0, |
|
percent: 1 |
|
}); |
|
} |
|
|
|
let deletedCount = 0; |
|
|
|
const mapper = async file => { |
|
file = path.resolve(cwd, file); |
|
|
|
if (!force) { |
|
safeCheck(file, cwd); |
|
} |
|
|
|
if (!dryRun) { |
|
await rimrafP(file, rimrafOptions); |
|
} |
|
|
|
deletedCount += 1; |
|
|
|
onProgress({ |
|
totalCount: files.length, |
|
deletedCount, |
|
percent: deletedCount / files.length |
|
}); |
|
|
|
return file; |
|
}; |
|
|
|
const removedFiles = await pMap(files, mapper, options); |
|
|
|
removedFiles.sort((a, b) => a.localeCompare(b)); |
|
|
|
return removedFiles; |
|
}; |
|
|
|
module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => { |
|
options = { |
|
expandDirectories: false, |
|
onlyFiles: false, |
|
followSymbolicLinks: false, |
|
cwd, |
|
...options |
|
}; |
|
|
|
patterns = normalizePatterns(patterns); |
|
|
|
const files = globby.sync(patterns, options) |
|
.sort((a, b) => b.localeCompare(a)); |
|
|
|
const removedFiles = files.map(file => { |
|
file = path.resolve(cwd, file); |
|
|
|
if (!force) { |
|
safeCheck(file, cwd); |
|
} |
|
|
|
if (!dryRun) { |
|
rimraf.sync(file, rimrafOptions); |
|
} |
|
|
|
return file; |
|
}); |
|
|
|
removedFiles.sort((a, b) => a.localeCompare(b)); |
|
|
|
return removedFiles; |
|
};
|
|
|