Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ed2293e

Browse filesBrowse files
cjihrigBridgeAR
authored andcommitted
fs: add recursive option to rmdir()
This commit adds a recursive option to fs.rmdir(), fs.rmdirSync(), and fs.promises.rmdir(). The implementation is a port of the npm module rimraf. PR-URL: #29168 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Roman Reiss <me@silverwind.io> Reviewed-By: Ben Coe <bencoe@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
1 parent 6a4f156 commit ed2293e
Copy full SHA for ed2293e

File tree

Expand file treeCollapse file tree

9 files changed

+550
-11
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

9 files changed

+550
-11
lines changed
Open diff view settings
Collapse file

‎LICENSE‎

Copy file name to clipboardExpand all lines: LICENSE
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,3 +1507,22 @@ The externally maintained libraries used by Node.js are:
15071507
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15081508
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15091509
"""
1510+
1511+
- rimraf, located at lib/internal/fs/rimraf.js, is licensed as follows:
1512+
"""
1513+
The ISC License
1514+
1515+
Copyright (c) Isaac Z. Schlueter and Contributors
1516+
1517+
Permission to use, copy, modify, and/or distribute this software for any
1518+
purpose with or without fee is hereby granted, provided that the above
1519+
copyright notice and this permission notice appear in all copies.
1520+
1521+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1522+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1523+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1524+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1525+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1526+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
1527+
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1528+
"""
Collapse file

‎doc/api/fs.md‎

Copy file name to clipboardExpand all lines: doc/api/fs.md
+51-4Lines changed: 51 additions & 4 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -3017,10 +3017,14 @@ changes:
30173017

30183018
Synchronous rename(2). Returns `undefined`.
30193019

3020-
## fs.rmdir(path, callback)
3020+
## fs.rmdir(path[, options], callback)
30213021
<!-- YAML
30223022
added: v0.0.2
30233023
changes:
3024+
- version: REPLACEME
3025+
pr-url: https://github.com/nodejs/node/pull/29168
3026+
description: The `recursive`, `maxBusyTries`, and `emfileWait` options are
3027+
now supported.
30243028
- version: v10.0.0
30253029
pr-url: https://github.com/nodejs/node/pull/12562
30263030
description: The `callback` parameter is no longer optional. Not passing
@@ -3035,7 +3039,21 @@ changes:
30353039
it will emit a deprecation warning with id DEP0013.
30363040
-->
30373041

3042+
> Stability: 1 - Recursive removal is experimental.
3043+
30383044
* `path` {string|Buffer|URL}
3045+
* `options` {Object}
3046+
* `emfileWait` {integer} If an `EMFILE` error is encountered, Node.js will
3047+
retry the operation with a linear backoff of 1ms longer on each try until the
3048+
timeout duration passes this limit. This option is ignored if the `recursive`
3049+
option is not `true`. **Default:** `1000`.
3050+
* `maxBusyTries` {integer} If an `EBUSY`, `ENOTEMPTY`, or `EPERM` error is
3051+
encountered, Node.js will retry the operation with a linear backoff wait of
3052+
100ms longer on each try. This option represents the number of retries. This
3053+
option is ignored if the `recursive` option is not `true`. **Default:** `3`.
3054+
* `recursive` {boolean} If `true`, perform a recursive directory removal. In
3055+
recursive mode, errors are not reported if `path` does not exist, and
3056+
operations are retried on failure. **Default:** `false`.
30393057
* `callback` {Function}
30403058
* `err` {Error}
30413059

@@ -3045,17 +3063,27 @@ to the completion callback.
30453063
Using `fs.rmdir()` on a file (not a directory) results in an `ENOENT` error on
30463064
Windows and an `ENOTDIR` error on POSIX.
30473065

3048-
## fs.rmdirSync(path)
3066+
## fs.rmdirSync(path[, options])
30493067
<!-- YAML
30503068
added: v0.1.21
30513069
changes:
3070+
- version: REPLACEME
3071+
pr-url: https://github.com/nodejs/node/pull/29168
3072+
description: The `recursive`, `maxBusyTries`, and `emfileWait` options are
3073+
now supported.
30523074
- version: v7.6.0
30533075
pr-url: https://github.com/nodejs/node/pull/10739
30543076
description: The `path` parameters can be a WHATWG `URL` object using
30553077
`file:` protocol. Support is currently still *experimental*.
30563078
-->
30573079

3080+
> Stability: 1 - Recursive removal is experimental.
3081+
30583082
* `path` {string|Buffer|URL}
3083+
* `options` {Object}
3084+
* `recursive` {boolean} If `true`, perform a recursive directory removal. In
3085+
recursive mode, errors are not reported if `path` does not exist, and
3086+
operations are retried on failure. **Default:** `false`.
30593087

30603088
Synchronous rmdir(2). Returns `undefined`.
30613089

@@ -4694,12 +4722,31 @@ added: v10.0.0
46944722
Renames `oldPath` to `newPath` and resolves the `Promise` with no arguments
46954723
upon success.
46964724

4697-
### fsPromises.rmdir(path)
4725+
### fsPromises.rmdir(path[, options])
46984726
<!-- YAML
46994727
added: v10.0.0
4728+
changes:
4729+
- version: REPLACEME
4730+
pr-url: https://github.com/nodejs/node/pull/29168
4731+
description: The `recursive`, `maxBusyTries`, and `emfileWait` options are
4732+
now supported.
47004733
-->
47014734

4735+
> Stability: 1 - Recursive removal is experimental.
4736+
47024737
* `path` {string|Buffer|URL}
4738+
* `options` {Object}
4739+
* `emfileWait` {integer} If an `EMFILE` error is encountered, Node.js will
4740+
retry the operation with a linear backoff of 1ms longer on each try until the
4741+
timeout duration passes this limit. This option is ignored if the `recursive`
4742+
option is not `true`. **Default:** `1000`.
4743+
* `maxBusyTries` {integer} If an `EBUSY`, `ENOTEMPTY`, or `EPERM` error is
4744+
encountered, Node.js will retry the operation with a linear backoff wait of
4745+
100ms longer on each try. This option represents the number of retries. This
4746+
option is ignored if the `recursive` option is not `true`. **Default:** `3`.
4747+
* `recursive` {boolean} If `true`, perform a recursive directory removal. In
4748+
recursive mode, errors are not reported if `path` does not exist, and
4749+
operations are retried on failure. **Default:** `false`.
47034750
* Returns: {Promise}
47044751

47054752
Removes the directory identified by `path` then resolves the `Promise` with
@@ -5193,7 +5240,7 @@ the file contents.
51935240
[`fs.readdir()`]: #fs_fs_readdir_path_options_callback
51945241
[`fs.readdirSync()`]: #fs_fs_readdirsync_path_options
51955242
[`fs.realpath()`]: #fs_fs_realpath_path_options_callback
5196-
[`fs.rmdir()`]: #fs_fs_rmdir_path_callback
5243+
[`fs.rmdir()`]: #fs_fs_rmdir_path_options_callback
51975244
[`fs.stat()`]: #fs_fs_stat_path_options_callback
51985245
[`fs.symlink()`]: #fs_fs_symlink_target_path_type_callback
51995246
[`fs.utimes()`]: #fs_fs_utimes_path_atime_mtime_callback
Collapse file

‎lib/fs.js‎

Copy file name to clipboardExpand all lines: lib/fs.js
+32-4Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ const {
7676
validateOffsetLengthRead,
7777
validateOffsetLengthWrite,
7878
validatePath,
79+
validateRmdirOptions,
7980
warnOnNonPortableTemplate
8081
} = require('internal/fs/utils');
8182
const {
@@ -100,6 +101,8 @@ let watchers;
100101
let ReadFileContext;
101102
let ReadStream;
102103
let WriteStream;
104+
let rimraf;
105+
let rimrafSync;
103106

104107
// These have to be separate because of how graceful-fs happens to do it's
105108
// monkeypatching.
@@ -720,16 +723,41 @@ function ftruncateSync(fd, len = 0) {
720723
handleErrorFromBinding(ctx);
721724
}
722725

723-
function rmdir(path, callback) {
726+
727+
function lazyLoadRimraf() {
728+
if (rimraf === undefined)
729+
({ rimraf, rimrafSync } = require('internal/fs/rimraf'));
730+
}
731+
732+
function rmdir(path, options, callback) {
733+
if (typeof options === 'function') {
734+
callback = options;
735+
options = undefined;
736+
}
737+
724738
callback = makeCallback(callback);
725-
path = getValidatedPath(path);
739+
path = pathModule.toNamespacedPath(getValidatedPath(path));
740+
options = validateRmdirOptions(options);
741+
742+
if (options.recursive) {
743+
lazyLoadRimraf();
744+
return rimraf(path, options, callback);
745+
}
746+
726747
const req = new FSReqCallback();
727748
req.oncomplete = callback;
728-
binding.rmdir(pathModule.toNamespacedPath(path), req);
749+
binding.rmdir(path, req);
729750
}
730751

731-
function rmdirSync(path) {
752+
function rmdirSync(path, options) {
732753
path = getValidatedPath(path);
754+
options = validateRmdirOptions(options);
755+
756+
if (options.recursive) {
757+
lazyLoadRimraf();
758+
return rimrafSync(pathModule.toNamespacedPath(path), options);
759+
}
760+
733761
const ctx = { path };
734762
binding.rmdir(pathModule.toNamespacedPath(path), undefined, ctx);
735763
handleErrorFromBinding(ctx);
Collapse file

‎lib/internal/fs/promises.js‎

Copy file name to clipboardExpand all lines: lib/internal/fs/promises.js
+11-3Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const {
1818
ERR_METHOD_NOT_IMPLEMENTED
1919
} = require('internal/errors').codes;
2020
const { isUint8Array } = require('internal/util/types');
21+
const { rimrafPromises } = require('internal/fs/rimraf');
2122
const {
2223
copyObject,
2324
getDirents,
@@ -32,6 +33,7 @@ const {
3233
validateBufferArray,
3334
validateOffsetLengthRead,
3435
validateOffsetLengthWrite,
36+
validateRmdirOptions,
3537
warnOnNonPortableTemplate
3638
} = require('internal/fs/utils');
3739
const {
@@ -291,9 +293,15 @@ async function ftruncate(handle, len = 0) {
291293
return binding.ftruncate(handle.fd, len, kUsePromises);
292294
}
293295

294-
async function rmdir(path) {
295-
path = getValidatedPath(path);
296-
return binding.rmdir(pathModule.toNamespacedPath(path), kUsePromises);
296+
async function rmdir(path, options) {
297+
path = pathModule.toNamespacedPath(getValidatedPath(path));
298+
options = validateRmdirOptions(options);
299+
300+
if (options.recursive) {
301+
return rimrafPromises(path, options);
302+
}
303+
304+
return binding.rmdir(path, kUsePromises);
297305
}
298306

299307
async function fdatasync(handle) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.