Skip to content

Commit 1610728

Browse files
iansuBethGriggs
authored andcommitted
fs: add rm method
This PR introduces a new method fs.rm that provides the behaviour of rimraf when used with the recursive: true and force: true options. PR-URL: #35494 Reviewed-By: Ben Coe <[email protected]> Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Ruy Adorno <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
1 parent f552e5c commit 1610728

File tree

10 files changed

+518
-37
lines changed

10 files changed

+518
-37
lines changed

‎doc/api/errors.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,11 @@ added: v14.0.0
928928
Used when a feature that is not available
929929
to the current platform which is running Node.js is used.
930930

931+
<aid="ERR_FS_EISDIR"></a>
932+
### `ERR_FS_EISDIR`
933+
934+
Path is a directory.
935+
931936
<aid="ERR_FS_FILE_TOO_LARGE"></a>
932937
### `ERR_FS_FILE_TOO_LARGE`
933938

‎doc/api/fs.md‎

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3509,9 +3509,9 @@ changes:
35093509
*`options`{Object}
35103510
*`maxRetries`{integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or
35113511
`EPERM` error is encountered, Node.js will retry the operation with a linear
3512-
backoff wait of `retryDelay`ms longer on each try. This option represents
3513-
the number of retries. This option is ignored if the `recursive` option is
3514-
not `true`. **Default:**`0`.
3512+
backoff wait of `retryDelay`milliseconds longer on each try. This option
3513+
represents the number of retries. This option is ignored if the `recursive`
3514+
option is not `true`. **Default:**`0`.
35153515
*`recursive`{boolean} If `true`, perform a recursive directory removal. In
35163516
recursive mode, errors are not reported if `path` does not exist, and
35173517
operations are retried on failure. **Default:**`false`.
@@ -3560,9 +3560,9 @@ changes:
35603560
*`options`{Object}
35613561
*`maxRetries`{integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or
35623562
`EPERM` error is encountered, Node.js will retry the operation with a linear
3563-
backoff wait of `retryDelay`ms longer on each try. This option represents
3564-
the number of retries. This option is ignored if the `recursive` option is
3565-
not `true`. **Default:**`0`.
3563+
backoff wait of `retryDelay`milliseconds longer on each try. This option
3564+
represents the number of retries. This option is ignored if the `recursive`
3565+
option is not `true`. **Default:**`0`.
35663566
*`recursive`{boolean} If `true`, perform a recursive directory removal. In
35673567
recursive mode, errors are not reported if `path` does not exist, and
35683568
operations are retried on failure. **Default:**`false`.
@@ -3581,6 +3581,53 @@ that represent files will be deleted. The permissive behavior of the
35813581
`recursive` option is deprecated, `ENOTDIR` and `ENOENT` will be thrown in
35823582
the future.
35833583

3584+
## `fs.rm(path[, options], callback)`
3585+
<!-- YAML
3586+
added: REPLACEME
3587+
-->
3588+
3589+
*`path`{string|Buffer|URL}
3590+
*`options`{Object}
3591+
*`force` don't error on nonexistent path
3592+
*`maxRetries`{integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or
3593+
`EPERM` error is encountered, Node.js will retry the operation with a linear
3594+
backoff wait of `retryDelay` milliseconds longer on each try. This option
3595+
represents the number of retries. This option is ignored if the `recursive`
3596+
option is not `true`. **Default:**`0`.
3597+
*`recursive`{boolean} If `true`, perform a recursive removal. In
3598+
recursive mode operations are retried on failure. **Default:**`false`.
3599+
*`retryDelay`{integer} The amount of time in milliseconds to wait between
3600+
retries. This option is ignored if the `recursive` option is not `true`.
3601+
**Default:**`100`.
3602+
*`callback`{Function}
3603+
*`err`{Error}
3604+
3605+
Asynchronously removes files and directories (modeled on the standard POSIX `rm`
3606+
utility). No arguments other than a possible exception are given to the
3607+
completion callback.
3608+
3609+
## `fs.rmSync(path[, options])`
3610+
<!-- YAML
3611+
added: REPLACEME
3612+
-->
3613+
3614+
*`path`{string|Buffer|URL}
3615+
*`options`{Object}
3616+
*`force` Ignore errors
3617+
*`maxRetries`{integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or
3618+
`EPERM` error is encountered, Node.js will retry the operation with a linear
3619+
backoff wait of `retryDelay` milliseconds longer on each try. This option
3620+
represents the number of retries. This option is ignored if the `recursive`
3621+
option is not `true`. **Default:**`0`.
3622+
*`recursive`{boolean} If `true`, perform a recursive directory removal. In
3623+
recursive mode operations are retried on failure. **Default:**`false`.
3624+
*`retryDelay`{integer} The amount of time in milliseconds to wait between
3625+
retries. This option is ignored if the `recursive` option is not `true`.
3626+
**Default:**`100`.
3627+
3628+
Synchronously removes files and directories (modeled on the standard POSIX `rm`
3629+
utility). Returns `undefined`.
3630+
35843631
## `fs.stat(path[, options], callback)`
35853632
<!-- YAML
35863633
added: v0.0.2
@@ -5447,9 +5494,9 @@ changes:
54475494
*`options`{Object}
54485495
*`maxRetries`{integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or
54495496
`EPERM` error is encountered, Node.js will retry the operation with a linear
5450-
backoff wait of `retryDelay`ms longer on each try. This option represents
5451-
the number of retries. This option is ignored if the `recursive` option is
5452-
not `true`. **Default:**`0`.
5497+
backoff wait of `retryDelay`milliseconds longer on each try. This option
5498+
represents the number of retries. This option is ignored if the `recursive`
5499+
option is not `true`. **Default:**`0`.
54535500
*`recursive`{boolean} If `true`, perform a recursive directory removal. In
54545501
recursive mode, errors are not reported if `path` does not exist, and
54555502
operations are retried on failure. **Default:**`false`.
@@ -5471,6 +5518,28 @@ that represent files will be deleted. The permissive behavior of the
54715518
`recursive` option is deprecated, `ENOTDIR` and `ENOENT` will be thrown in
54725519
the future.
54735520

5521+
## `fsPromises.rm(path[, options])`
5522+
<!-- YAML
5523+
added: REPLACEME
5524+
-->
5525+
5526+
*`path`{string|Buffer|URL}
5527+
*`options`{Object}
5528+
*`force` Ignore errors
5529+
*`maxRetries`{integer} If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or
5530+
`EPERM` error is encountered, Node.js will retry the operation with a linear
5531+
backoff wait of `retryDelay` milliseconds longer on each try. This option
5532+
represents the number of retries. This option is ignored if the `recursive`
5533+
option is not `true`. **Default:**`0`.
5534+
*`recursive`{boolean} If `true`, perform a recursive directory removal. In
5535+
recursive mode operations are retried on failure. **Default:**`false`.
5536+
*`retryDelay`{integer} The amount of time in milliseconds to wait between
5537+
retries. This option is ignored if the `recursive` option is not `true`.
5538+
**Default:**`100`.
5539+
5540+
Synchronously removes files and directories (modeled on the standard POSIX `rm`
5541+
utility). Resolves the `Promise` with no arguments on success.
5542+
54745543
### `fsPromises.stat(path[, options])`
54755544
<!-- YAML
54765545
added: v10.0.0

‎lib/fs.js‎

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ const{
9797
validateOffsetLengthRead,
9898
validateOffsetLengthWrite,
9999
validatePath,
100+
validateRmOptions,
101+
validateRmOptionsSync,
100102
validateRmdirOptions,
101103
validateStringAfterArrayBufferView,
102104
warnOnNonPortableTemplate
@@ -855,30 +857,63 @@ function rmdir(path, options, callback){
855857

856858
callback=makeCallback(callback);
857859
path=pathModule.toNamespacedPath(getValidatedPath(path));
858-
options=validateRmdirOptions(options);
859860

860-
if(options.recursive){
861-
lazyLoadRimraf();
862-
returnrimraf(path,options,callback);
863-
}
861+
if(options&&options.recursive){
862+
options=validateRmOptions(
863+
path,
864+
{ ...options,force: true},
865+
(err,options)=>{
866+
if(err){
867+
returncallback(err);
868+
}
864869

865-
constreq=newFSReqCallback();
866-
req.oncomplete=callback;
867-
binding.rmdir(path,req);
870+
lazyLoadRimraf();
871+
returnrimraf(path,options,callback);
872+
});
873+
874+
}else{
875+
options=validateRmdirOptions(options);
876+
constreq=newFSReqCallback();
877+
req.oncomplete=callback;
878+
returnbinding.rmdir(path,req);
879+
}
868880
}
869881

870882
functionrmdirSync(path,options){
871883
path=getValidatedPath(path);
872-
options=validateRmdirOptions(options);
873884

874-
if(options.recursive){
885+
if(options&&options.recursive){
886+
options=validateRmOptionsSync(path,{ ...options,force: true});
875887
lazyLoadRimraf();
876888
returnrimrafSync(pathModule.toNamespacedPath(path),options);
877889
}
878890

891+
options=validateRmdirOptions(options);
879892
constctx={ path };
880893
binding.rmdir(pathModule.toNamespacedPath(path),undefined,ctx);
881-
handleErrorFromBinding(ctx);
894+
returnhandleErrorFromBinding(ctx);
895+
}
896+
897+
functionrm(path,options,callback){
898+
if(typeofoptions==='function'){
899+
callback=options;
900+
options=undefined;
901+
}
902+
903+
validateRmOptions(path,options,(err,options)=>{
904+
if(err){
905+
returncallback(err);
906+
}
907+
lazyLoadRimraf();
908+
returnrimraf(pathModule.toNamespacedPath(path),options,callback);
909+
});
910+
}
911+
912+
functionrmSync(path,options){
913+
options=validateRmOptionsSync(path,options);
914+
915+
lazyLoadRimraf();
916+
returnrimrafSync(pathModule.toNamespacedPath(path),options);
882917
}
883918

884919
functionfdatasync(fd,callback){
@@ -2040,6 +2075,8 @@ module.exports = fs ={
20402075
realpathSync,
20412076
rename,
20422077
renameSync,
2078+
rm,
2079+
rmSync,
20432080
rmdir,
20442081
rmdirSync,
20452082
stat,

‎lib/internal/errors.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,7 @@ E('ERR_FEATURE_UNAVAILABLE_ON_PLATFORM',
839839
'The feature %s is unavailable on the current platform'+
840840
', which is being used to run Node.js',
841841
TypeError);
842+
E('ERR_FS_EISDIR','Path is a directory',SystemError);
842843
E('ERR_FS_FILE_TOO_LARGE','File size (%s) is greater than 2 GB',RangeError);
843844
E('ERR_FS_INVALID_SYMLINK_TYPE',
844845
'Symlink type must be one of "dir", "file", or "junction". Received "%s"',

‎lib/internal/fs/promises.js‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const{
5252
validateBufferArray,
5353
validateOffsetLengthRead,
5454
validateOffsetLengthWrite,
55+
validateRmOptions,
5556
validateRmdirOptions,
5657
validateStringAfterArrayBufferView,
5758
warnOnNonPortableTemplate
@@ -79,6 +80,7 @@ const{
7980
}=require('internal/worker/js_transferable');
8081

8182
constgetDirectoryEntriesPromise=promisify(getDirents);
83+
constvalidateRmOptionsPromise=promisify(validateRmOptions);
8284

8385
classFileHandleextendsJSTransferable{
8486
constructor(filehandle){
@@ -417,6 +419,12 @@ async function ftruncate(handle, len = 0){
417419
returnbinding.ftruncate(handle.fd,len,kUsePromises);
418420
}
419421

422+
asyncfunctionrm(path,options){
423+
path=pathModule.toNamespacedPath(getValidatedPath(path));
424+
options=awaitvalidateRmOptionsPromise(path,options);
425+
returnrimrafPromises(path,options);
426+
}
427+
420428
asyncfunctionrmdir(path,options){
421429
path=pathModule.toNamespacedPath(getValidatedPath(path));
422430
options=validateRmdirOptions(options);
@@ -635,6 +643,7 @@ module.exports ={
635643
opendir: promisify(opendir),
636644
rename,
637645
truncate,
646+
rm,
638647
rmdir,
639648
mkdir,
640649
readdir,

0 commit comments

Comments
(0)