1 | 'use strict';
|
2 | const {promisify} = require('util');
|
3 | const path = require('path');
|
4 | const globby = require('globby');
|
5 | const isGlob = require('is-glob');
|
6 | const slash = require('slash');
|
7 | const gracefulFs = require('graceful-fs');
|
8 | const isPathCwd = require('is-path-cwd');
|
9 | const isPathInside = require('is-path-inside');
|
10 | const rimraf = require('rimraf');
|
11 | const pMap = require('p-map');
|
12 |
|
13 | const rimrafP = promisify(rimraf);
|
14 |
|
15 | const rimrafOptions = {
|
16 | glob: false,
|
17 | unlink: gracefulFs.unlink,
|
18 | unlinkSync: gracefulFs.unlinkSync,
|
19 | chmod: gracefulFs.chmod,
|
20 | chmodSync: gracefulFs.chmodSync,
|
21 | stat: gracefulFs.stat,
|
22 | statSync: gracefulFs.statSync,
|
23 | lstat: gracefulFs.lstat,
|
24 | lstatSync: gracefulFs.lstatSync,
|
25 | rmdir: gracefulFs.rmdir,
|
26 | rmdirSync: gracefulFs.rmdirSync,
|
27 | readdir: gracefulFs.readdir,
|
28 | readdirSync: gracefulFs.readdirSync
|
29 | };
|
30 |
|
31 | function safeCheck(file, cwd) {
|
32 | if (isPathCwd(file)) {
|
33 | throw new Error('Cannot delete the current working directory. Can be overridden with the `force` option.');
|
34 | }
|
35 |
|
36 | if (!isPathInside(file, cwd)) {
|
37 | throw new Error('Cannot delete files/directories outside the current working directory. Can be overridden with the `force` option.');
|
38 | }
|
39 | }
|
40 |
|
41 | function normalizePatterns(patterns) {
|
42 | patterns = Array.isArray(patterns) ? patterns : [patterns];
|
43 |
|
44 | patterns = patterns.map(pattern => {
|
45 | if (process.platform === 'win32' && isGlob(pattern) === false) {
|
46 | return slash(pattern);
|
47 | }
|
48 |
|
49 | return pattern;
|
50 | });
|
51 |
|
52 | return patterns;
|
53 | }
|
54 |
|
55 | module.exports = async (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => {
|
56 | options = {
|
57 | expandDirectories: false,
|
58 | onlyFiles: false,
|
59 | followSymbolicLinks: false,
|
60 | cwd,
|
61 | ...options
|
62 | };
|
63 |
|
64 | patterns = normalizePatterns(patterns);
|
65 |
|
66 | const files = (await globby(patterns, options))
|
67 | .sort((a, b) => b.localeCompare(a));
|
68 |
|
69 | const mapper = async file => {
|
70 | file = path.resolve(cwd, file);
|
71 |
|
72 | if (!force) {
|
73 | safeCheck(file, cwd);
|
74 | }
|
75 |
|
76 | if (!dryRun) {
|
77 | await rimrafP(file, rimrafOptions);
|
78 | }
|
79 |
|
80 | return file;
|
81 | };
|
82 |
|
83 | const removedFiles = await pMap(files, mapper, options);
|
84 |
|
85 | removedFiles.sort((a, b) => a.localeCompare(b));
|
86 |
|
87 | return removedFiles;
|
88 | };
|
89 |
|
90 | module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => {
|
91 | options = {
|
92 | expandDirectories: false,
|
93 | onlyFiles: false,
|
94 | followSymbolicLinks: false,
|
95 | cwd,
|
96 | ...options
|
97 | };
|
98 |
|
99 | patterns = normalizePatterns(patterns);
|
100 |
|
101 | const files = globby.sync(patterns, options)
|
102 | .sort((a, b) => b.localeCompare(a));
|
103 |
|
104 | const removedFiles = files.map(file => {
|
105 | file = path.resolve(cwd, file);
|
106 |
|
107 | if (!force) {
|
108 | safeCheck(file, cwd);
|
109 | }
|
110 |
|
111 | if (!dryRun) {
|
112 | rimraf.sync(file, rimrafOptions);
|
113 | }
|
114 |
|
115 | return file;
|
116 | });
|
117 |
|
118 | removedFiles.sort((a, b) => a.localeCompare(b));
|
119 |
|
120 | return removedFiles;
|
121 | };
|