Skip to content

Commit b7cc9da

Browse files
committed
fs: runtime deprecate rmdir recursive option
1 parent 33d3a2e commit b7cc9da

5 files changed

Lines changed: 53 additions & 35 deletions

File tree

doc/api/deprecations.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2663,19 +2663,25 @@ The [`crypto.Certificate()` constructor][] is deprecated. Use
26632663
### DEP0147: `fs.rmdir(path, { recursive: true })`
26642664
<!-- YAML
26652665
changes:
2666+
- version: REPLACEME
2667+
pr-url: https://github.com/nodejs/node/pull/37216
2668+
description: Runtime deprecation.
26662669
- version: v15.0.0
26672670
pr-url: https://github.com/nodejs/node/pull/35562
2668-
description: Runtime deprecation.
2671+
description: Runtime deprecation for permissive behavior.
26692672
- version: v14.14.0
26702673
pr-url: https://github.com/nodejs/node/pull/35579
26712674
description: Documentation-only deprecation.
26722675
-->
26732676

26742677
Type: Runtime
26752678

2676-
In future versions of Node.js, `fs.rmdir(path, { recursive: true })` will throw
2677-
if `path` does not exist or is a file.
2678-
Use `fs.rm(path, { recursive: true, force: true })` instead.
2679+
In future versions of Node.js, `recursive` option will be ignored for
2680+
`fs.rmdir`, `fs.rmdirSync`, and `fs.promises.rmdir`.
2681+
2682+
Use `fs.rm(path, { recursive: true, force: true })`,
2683+
`fs.rmSync(path, { recursive: true, force: true })` or
2684+
`fs.promises.rm(path, { recursive: true, force: true })` instead.
26792685

26802686
### DEP0148: Folder mappings in `"exports"` (trailing `"/"`)
26812687
<!-- YAML

doc/api/fs.md

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3589,6 +3589,10 @@ Synchronous rename(2). Returns `undefined`.
35893589
<!-- YAML
35903590
added: v0.0.2
35913591
changes:
3592+
- version: REPLACEME
3593+
pr-url: https://github.com/nodejs/node/pull/29168
3594+
description: The `recursive` option is deprecated, using it triggers a
3595+
deprecation warning.
35923596
- version:
35933597
- v13.3.0
35943598
- v12.16.0
@@ -3625,7 +3629,7 @@ changes:
36253629
option is not `true`. **Default:** `0`.
36263630
* `recursive` {boolean} If `true`, perform a recursive directory removal. In
36273631
recursive mode, errors are not reported if `path` does not exist, and
3628-
operations are retried on failure. **Default:** `false`.
3632+
operations are retried on failure. **Default:** `false`. **Deprecated**.
36293633
* `retryDelay` {integer} The amount of time in milliseconds to wait between
36303634
retries. This option is ignored if the `recursive` option is not `true`.
36313635
**Default:** `100`.
@@ -3640,14 +3644,17 @@ Windows and an `ENOTDIR` error on POSIX.
36403644

36413645
Setting `recursive` to `true` results in behavior similar to the Unix command
36423646
`rm -rf`: an error will not be raised for paths that do not exist, and paths
3643-
that represent files will be deleted. The permissive behavior of the
3644-
`recursive` option is deprecated, `ENOTDIR` and `ENOENT` will be thrown in
3645-
the future.
3647+
that represent files will be deleted. The `recursive` option is deprecated,
3648+
`ENOTDIR` and `ENOENT` will be thrown in the future.
36463649

36473650
## `fs.rmdirSync(path[, options])`
36483651
<!-- YAML
36493652
added: v0.1.21
36503653
changes:
3654+
- version: REPLACEME
3655+
pr-url: https://github.com/nodejs/node/pull/29168
3656+
description: The `recursive` option is deprecated, using it triggers a
3657+
deprecation warning.
36513658
- version:
36523659
- v13.3.0
36533660
- v12.16.0
@@ -3676,7 +3683,7 @@ changes:
36763683
option is not `true`. **Default:** `0`.
36773684
* `recursive` {boolean} If `true`, perform a recursive directory removal. In
36783685
recursive mode, errors are not reported if `path` does not exist, and
3679-
operations are retried on failure. **Default:** `false`.
3686+
operations are retried on failure. **Default:** `false`. **Deprecated**.
36803687
* `retryDelay` {integer} The amount of time in milliseconds to wait between
36813688
retries. This option is ignored if the `recursive` option is not `true`.
36823689
**Default:** `100`.
@@ -3688,9 +3695,8 @@ on Windows and an `ENOTDIR` error on POSIX.
36883695

36893696
Setting `recursive` to `true` results in behavior similar to the Unix command
36903697
`rm -rf`: an error will not be raised for paths that do not exist, and paths
3691-
that represent files will be deleted. The permissive behavior of the
3692-
`recursive` option is deprecated, `ENOTDIR` and `ENOENT` will be thrown in
3693-
the future.
3698+
that represent files will be deleted. The `recursive` option is deprecated,
3699+
`ENOTDIR` and `ENOENT` will be thrown in the future.
36943700

36953701
## `fs.rm(path[, options], callback)`
36963702
<!-- YAML
@@ -5677,6 +5683,10 @@ upon success.
56775683
<!-- YAML
56785684
added: v10.0.0
56795685
changes:
5686+
- version: REPLACEME
5687+
pr-url: https://github.com/nodejs/node/pull/29168
5688+
description: The `recursive` option is deprecated, using it triggers a
5689+
deprecation warning.
56805690
- version:
56815691
- v13.3.0
56825692
- v12.16.0
@@ -5701,7 +5711,7 @@ changes:
57015711
option is not `true`. **Default:** `0`.
57025712
* `recursive` {boolean} If `true`, perform a recursive directory removal. In
57035713
recursive mode, errors are not reported if `path` does not exist, and
5704-
operations are retried on failure. **Default:** `false`.
5714+
operations are retried on failure. **Default:** `false`. **Deprecated**.
57055715
* `retryDelay` {integer} The amount of time in milliseconds to wait between
57065716
retries. This option is ignored if the `recursive` option is not `true`.
57075717
**Default:** `100`.
@@ -5716,9 +5726,8 @@ error on POSIX.
57165726

57175727
Setting `recursive` to `true` results in behavior similar to the Unix command
57185728
`rm -rf`: an error will not be raised for paths that do not exist, and paths
5719-
that represent files will be deleted. The permissive behavior of the
5720-
`recursive` option is deprecated, `ENOTDIR` and `ENOENT` will be thrown in
5721-
the future.
5729+
that represent files will be deleted. The `recursive` option is deprecated,
5730+
`ENOTDIR` and `ENOENT` will be thrown in the future.
57225731

57235732
### `fsPromises.rm(path[, options])`
57245733
<!-- YAML

lib/internal/fs/promises.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ const {
4141
ERR_INVALID_ARG_VALUE,
4242
ERR_METHOD_NOT_IMPLEMENTED,
4343
} = codes;
44-
const { isArrayBufferView } = require('internal/util/types');
44+
const {
45+
isArrayBufferView,
46+
emitRecursiveRmdirWarning,
47+
} = require('internal/util/types');
4548
const { rimrafPromises } = require('internal/fs/rimraf');
4649
const {
4750
copyObject,
@@ -488,6 +491,7 @@ async function rmdir(path, options) {
488491
options = validateRmdirOptions(options);
489492

490493
if (options.recursive) {
494+
emitRecursiveRmdirWarning();
491495
return rimrafPromises(path, options);
492496
}
493497

lib/internal/fs/utils.js

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -704,18 +704,11 @@ const validateRmOptions = hideStackFrames((path, options, warn, callback) => {
704704
lazyLoadFs().stat(path, (err, stats) => {
705705
if (err) {
706706
if (options.force && err.code === 'ENOENT') {
707-
if (warn) {
708-
emitPermissiveRmdirWarning();
709-
}
710707
return callback(null, options);
711708
}
712709
return callback(err, options);
713710
}
714711

715-
if (warn && !stats.isDirectory()) {
716-
emitPermissiveRmdirWarning();
717-
}
718-
719712
if (stats.isDirectory() && !options.recursive) {
720713
return callback(new ERR_FS_EISDIR({
721714
code: 'EISDIR',
@@ -737,10 +730,6 @@ const validateRmOptionsSync = hideStackFrames((path, options, warn) => {
737730
const isDirectory = lazyLoadFs()
738731
.statSync(path, { throwIfNoEntry: !options.force })?.isDirectory();
739732

740-
if (warn && !isDirectory) {
741-
emitPermissiveRmdirWarning();
742-
}
743-
744733
if (isDirectory && !options.recursive) {
745734
throw new ERR_FS_EISDIR({
746735
code: 'EISDIR',
@@ -755,18 +744,16 @@ const validateRmOptionsSync = hideStackFrames((path, options, warn) => {
755744
return options;
756745
});
757746

758-
let permissiveRmdirWarned = false;
759-
760-
function emitPermissiveRmdirWarning() {
761-
if (!permissiveRmdirWarned) {
747+
let recursiveRmdirWarned = process.noDeprecation;
748+
function emitRecursiveRmdirWarning() {
749+
if (!recursiveRmdirWarned) {
762750
process.emitWarning(
763751
'In future versions of Node.js, fs.rmdir(path, { recursive: true }) ' +
764-
'will throw if path does not exist or is a file. Use fs.rm(path, ' +
765-
'{ recursive: true, force: true }) instead',
752+
'will be removed. Use fs.rm(path, { recursive: true }) instead',
766753
'DeprecationWarning',
767754
'DEP0147'
768755
);
769-
permissiveRmdirWarned = true;
756+
recursiveRmdirWarned = true;
770757
}
771758
}
772759

@@ -782,6 +769,10 @@ const validateRmdirOptions = hideStackFrames(
782769
validateInt32(options.retryDelay, 'options.retryDelay', 0);
783770
validateUint32(options.maxRetries, 'options.maxRetries');
784771

772+
if (options.recursive) {
773+
emitRecursiveRmdirWarning();
774+
}
775+
785776
return options;
786777
});
787778

@@ -851,6 +842,7 @@ module.exports = {
851842
BigIntStats, // for testing
852843
copyObject,
853844
Dirent,
845+
emitRecursiveRmdirWarning,
854846
getDirent,
855847
getDirents,
856848
getOptions,

test/parallel/test-fs-rmdir-recursive.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ const fs = require('fs');
77
const path = require('path');
88
const { validateRmdirOptions } = require('internal/fs/utils');
99

10+
common.expectWarning(
11+
'In future versions of Node.js, fs.rmdir(path, { recursive: true }) ' +
12+
'will be removed. Use fs.rm(path, { recursive: true }) instead',
13+
'DeprecationWarning',
14+
'DEP0147'
15+
);
16+
1017
tmpdir.refresh();
1118

1219
let count = 0;

0 commit comments

Comments
 (0)