Skip to content

Commit 7f6714c

Browse files
committed
feat: 🎸 add support for "recursive" and "force" flags in .rm()
1 parent 2414fb6 commit 7f6714c

File tree

2 files changed

+108
-3
lines changed

2 files changed

+108
-3
lines changed

src/__tests__/volume/rmSync.test.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,98 @@ describe('rmSync', () => {
1414
'/oof': 'zab',
1515
});
1616
});
17+
18+
it('removes a single file', () => {
19+
const vol = create({
20+
'/a/b/c.txt': 'content',
21+
});
22+
23+
vol.rmSync('/a/b/c.txt');
24+
25+
expect(vol.toJSON()).toEqual({
26+
'/a/b': null,
27+
});
28+
});
29+
30+
describe('when file does not exist', () => {
31+
it('throws by default', () => {
32+
const vol = create({
33+
'/foo.txt': 'content',
34+
});
35+
36+
expect(() => vol.rmSync('/bar.txt')).toThrowError(new Error("ENOENT: no such file or directory, stat '/bar.txt'"));
37+
});
38+
39+
it('does not throw if "force" is set to true', () => {
40+
const vol = create({
41+
'/foo.txt': 'content',
42+
});
43+
44+
vol.rmSync('/bar.txt', {force: true});
45+
});
46+
});
47+
48+
describe('when deleting a directory', () => {
49+
it('throws by default', () => {
50+
const vol = create({
51+
'/usr/bin/bash': '...',
52+
});
53+
54+
expect(() => vol.rmSync('/usr/bin')).toThrowError(new Error("[ERR_FS_EISDIR]: Path is a directory: rm returned EISDIR (is a directory) /usr/bin"));
55+
});
56+
57+
it('throws by when force flag is set', () => {
58+
const vol = create({
59+
'/usr/bin/bash': '...',
60+
});
61+
62+
expect(() => vol.rmSync('/usr/bin', {force: true})).toThrowError(new Error("[ERR_FS_EISDIR]: Path is a directory: rm returned EISDIR (is a directory) /usr/bin"));
63+
});
64+
65+
it('deletes all directory contents when recursive flag is set', () => {
66+
const vol = create({
67+
'/usr/bin/bash': '...',
68+
});
69+
70+
vol.rmSync('/usr/bin', {recursive: true});
71+
72+
expect(vol.toJSON()).toEqual({'/usr': null});
73+
});
74+
75+
it('deletes all directory contents recursively when recursive flag is set', () => {
76+
const vol = create({
77+
'/a/a/a': '1',
78+
'/a/a/b': '2',
79+
'/a/a/c': '3',
80+
'/a/b/a': '4',
81+
'/a/b/b': '5',
82+
'/a/c/a': '6',
83+
});
84+
85+
vol.rmSync('/a/a', {recursive: true});
86+
87+
expect(vol.toJSON()).toEqual({
88+
'/a/b/a': '4',
89+
'/a/b/b': '5',
90+
'/a/c/a': '6',
91+
});
92+
93+
vol.rmSync('/a/c', {recursive: true});
94+
95+
expect(vol.toJSON()).toEqual({
96+
'/a/b/a': '4',
97+
'/a/b/b': '5',
98+
});
99+
100+
vol.rmSync('/a/b', {recursive: true});
101+
102+
expect(vol.toJSON()).toEqual({
103+
'/a': null,
104+
});
105+
106+
vol.rmSync('/a', {recursive: true});
107+
108+
expect(vol.toJSON()).toEqual({});
109+
});
110+
});
17111
});

src/volume.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ const EACCES = 'EACCES';
9999
const EISDIR = 'EISDIR';
100100
const ENOTEMPTY = 'ENOTEMPTY';
101101
const ENOSYS = 'ENOSYS';
102+
const ERR_FS_EISDIR = 'ERR_FS_EISDIR';
102103

103104
function formatError(errorCode: string, func = '', path = '', path2 = '') {
104105
let pathFormatted = '';
@@ -130,6 +131,8 @@ function formatError(errorCode: string, func = '', path = '', path2 = '') {
130131
return `EMFILE: too many open files, ${func}${pathFormatted}`;
131132
case ENOSYS:
132133
return `ENOSYS: function not implemented, ${func}${pathFormatted}`;
134+
case ERR_FS_EISDIR:
135+
return `[ERR_FS_EISDIR]: Path is a directory: ${func} returned EISDIR (is a directory) ${path}`
133136
default:
134137
return `${errorCode}: error occurred, ${func}${pathFormatted}`;
135138
}
@@ -1986,9 +1989,17 @@ export class Volume {
19861989
}
19871990

19881991
private rmBase(filename: string, options: IRmOptions = {}): void {
1989-
const force = !!options.force;
1990-
const recursive = !!options.recursive;
1991-
const link = this.getLinkAsDirOrThrow(filename, 'rm');
1992+
const link = this.getResolvedLink(filename);
1993+
if (!link) {
1994+
// "stat" is used to match Node's native error message.
1995+
if (!options.force) throw createError(ENOENT, 'stat', filename);
1996+
return;
1997+
}
1998+
if (link.getNode().isDirectory()) {
1999+
if (!options.recursive) {
2000+
throw createError(ERR_FS_EISDIR, 'rm', filename);
2001+
}
2002+
}
19922003
this.deleteLink(link);
19932004
}
19942005

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy