Skip to content

Commit bc6c09a

Browse files
committed
provide dirent/stats as second arg to filter method
1 parent a1268c9 commit bc6c09a

File tree

10 files changed

+64
-50
lines changed

10 files changed

+64
-50
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 4.4
2+
3+
- Provide Dirent or Stats object as second argument to filter
4+
15
# 4.3
26

37
- Return boolean indicating whether the path was fully removed

README.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,16 @@ Options:
7777
`fs.rm` because that implementation does not support abort
7878
signals.
7979

80-
- `filter` Method that receives a path string as an argument, and
81-
returns a boolean indicating whether that path should be
82-
deleted. With async rimraf methods, this may return a Promise
83-
that resolves to a boolean. (Since Promises are truthy,
84-
returning a Promise from a sync filter is the same as just not
85-
filtering anything.)
80+
- `filter` Method that returns a boolean indicating whether that
81+
path should be deleted. With async rimraf methods, this may
82+
return a Promise that resolves to a boolean. (Since Promises
83+
are truthy, returning a Promise from a sync filter is the same
84+
as just not filtering anything.)
85+
86+
The first argument to the filter is the path string. The
87+
second argument is either a `Dirent` or `Stats` object for that
88+
path. (The first path explored will be a `Stats`, the rest
89+
will be `Dirent`.)
8690

8791
If a filter method is provided, it will _only_ remove entries
8892
if the filter returns (or resolves to) a truthy value. Omitting

src/bin.ts

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import { parse, relative, resolve } from 'path'
4646
const cwd = process.cwd()
4747

4848
import { createInterface, Interface } from 'readline'
49+
import { Dirent, Stats } from 'fs'
4950

5051
const prompt = async (rl: Interface, q: string) =>
5152
new Promise<string>(res => rl.question(q, res))
@@ -70,11 +71,11 @@ const interactiveRimraf = async (
7071
processing = false
7172
}
7273
const oneAtATime =
73-
(fn: (s: string) => Promise<boolean>) =>
74-
async (s: string): Promise<boolean> => {
74+
(fn: (s: string, e: Dirent | Stats) => Promise<boolean>) =>
75+
async (s: string, e: Dirent | Stats): Promise<boolean> => {
7576
const p = new Promise<boolean>(res => {
7677
queue.push(async () => {
77-
const result = await fn(s)
78+
const result = await fn(s, e)
7879
res(result)
7980
return result
8081
})
@@ -86,30 +87,32 @@ const interactiveRimraf = async (
8687
input: process.stdin,
8788
output: process.stdout,
8889
})
89-
opt.filter = oneAtATime(async (path: string): Promise<boolean> => {
90-
if (noneRemaining) {
91-
return false
92-
}
93-
while (!allRemaining) {
94-
const a = (
95-
await prompt(rl, `rm? ${relative(cwd, path)}\n[(Yes)/No/All/Quit] > `)
96-
).trim()
97-
if (/^n/i.test(a)) {
98-
return false
99-
} else if (/^a/i.test(a)) {
100-
allRemaining = true
101-
break
102-
} else if (/^q/i.test(a)) {
103-
noneRemaining = true
90+
opt.filter = oneAtATime(
91+
async (path: string, ent: Dirent | Stats): Promise<boolean> => {
92+
if (noneRemaining) {
10493
return false
105-
} else if (a === '' || /^y/i.test(a)) {
106-
break
107-
} else {
108-
continue
10994
}
95+
while (!allRemaining) {
96+
const a = (
97+
await prompt(rl, `rm? ${relative(cwd, path)}\n[(Yes)/No/All/Quit] > `)
98+
).trim()
99+
if (/^n/i.test(a)) {
100+
return false
101+
} else if (/^a/i.test(a)) {
102+
allRemaining = true
103+
break
104+
} else if (/^q/i.test(a)) {
105+
noneRemaining = true
106+
return false
107+
} else if (a === '' || /^y/i.test(a)) {
108+
break
109+
} else {
110+
continue
111+
}
112+
}
113+
return existingFilter(path, ent)
110114
}
111-
return existingFilter(path)
112-
})
115+
)
113116
await impl(paths, opt)
114117
rl.close()
115118
}

src/index.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ export interface RimrafAsyncOptions {
1212
maxBackoff?: number
1313
signal?: AbortSignal
1414
glob?: boolean | GlobOptions
15-
filter?: ((path: string) => boolean) | ((path: string) => Promise<boolean>)
15+
filter?:
16+
| ((path: string, ent: Dirent | Stats) => boolean)
17+
| ((path: string, ent: Dirent | Stats) => Promise<boolean>)
1618
}
1719

1820
export interface RimrafSyncOptions extends RimrafAsyncOptions {
19-
filter?: (path: string) => boolean
21+
filter?: (path: string, ent: Dirent | Stats) => boolean
2022
}
2123

2224
export type RimrafOptions = RimrafSyncOptions | RimrafAsyncOptions
@@ -44,6 +46,7 @@ export const assertRimrafOptions: (o: any) => void = (
4446
}
4547
}
4648

49+
import { Dirent, Stats } from 'fs'
4750
import { rimrafManual, rimrafManualSync } from './rimraf-manual.js'
4851
import { rimrafMoveRemove, rimrafMoveRemoveSync } from './rimraf-move-remove.js'
4952
import { rimrafNative, rimrafNativeSync } from './rimraf-native.js'

src/rimraf-move-remove.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ const rimrafMoveRemoveDir = async (
119119
}
120120
}
121121
/* c8 ignore stop */
122-
if (opt.filter && !(await opt.filter(path))) {
122+
if (opt.filter && !(await opt.filter(path, ent))) {
123123
return false
124124
}
125125
await ignoreENOENT(tmpUnlink(path, opt.tmp, unlinkFixEPERM))
@@ -141,7 +141,7 @@ const rimrafMoveRemoveDir = async (
141141
if (opt.preserveRoot === false && path === parse(path).root) {
142142
return false
143143
}
144-
if (opt.filter && !(await opt.filter(path))) {
144+
if (opt.filter && !(await opt.filter(path, ent))) {
145145
return false
146146
}
147147
await ignoreENOENT(tmpUnlink(path, opt.tmp, rmdir))
@@ -205,7 +205,7 @@ const rimrafMoveRemoveDirSync = (
205205
}
206206
}
207207
/* c8 ignore stop */
208-
if (opt.filter && !opt.filter(path)) {
208+
if (opt.filter && !opt.filter(path, ent)) {
209209
return false
210210
}
211211
ignoreENOENTSync(() => tmpUnlinkSync(path, tmp, unlinkFixEPERMSync))
@@ -223,7 +223,7 @@ const rimrafMoveRemoveDirSync = (
223223
if (opt.preserveRoot === false && path === parse(path).root) {
224224
return false
225225
}
226-
if (opt.filter && !opt.filter(path)) {
226+
if (opt.filter && !opt.filter(path, ent)) {
227227
return false
228228
}
229229
ignoreENOENTSync(() => tmpUnlinkSync(path, tmp, rmdirSync))

src/rimraf-posix.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const rimrafPosixDir = async (
6161
}
6262
}
6363
/* c8 ignore stop */
64-
if (opt.filter && !(await opt.filter(path))) {
64+
if (opt.filter && !(await opt.filter(path, ent))) {
6565
return false
6666
}
6767
await ignoreENOENT(unlink(path))
@@ -85,7 +85,7 @@ const rimrafPosixDir = async (
8585
return false
8686
}
8787

88-
if (opt.filter && !(await opt.filter(path))) {
88+
if (opt.filter && !(await opt.filter(path, ent))) {
8989
return false
9090
}
9191

@@ -115,7 +115,7 @@ const rimrafPosixDirSync = (
115115
}
116116
}
117117
/* c8 ignore stop */
118-
if (opt.filter && !opt.filter(path)) {
118+
if (opt.filter && !opt.filter(path, ent)) {
119119
return false
120120
}
121121
ignoreENOENTSync(() => unlinkSync(path))
@@ -134,7 +134,7 @@ const rimrafPosixDirSync = (
134134
return false
135135
}
136136

137-
if (opt.filter && !opt.filter(path)) {
137+
if (opt.filter && !opt.filter(path, ent)) {
138138
return false
139139
}
140140

src/rimraf-windows.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ const rimrafWindowsDir = async (
117117
}
118118
}
119119
/* c8 ignore stop */
120-
if (opt.filter && !(await opt.filter(path))) {
120+
if (opt.filter && !(await opt.filter(path, ent))) {
121121
return false
122122
}
123123
// is a file
@@ -141,7 +141,7 @@ const rimrafWindowsDir = async (
141141
if (!removedAll) {
142142
return false
143143
}
144-
if (opt.filter && !(await opt.filter(path))) {
144+
if (opt.filter && !(await opt.filter(path, ent))) {
145145
return false
146146
}
147147
await ignoreENOENT(rimrafWindowsDirMoveRemoveFallback(path, opt))
@@ -169,7 +169,7 @@ const rimrafWindowsDirSync = (
169169
}
170170
}
171171
/* c8 ignore stop */
172-
if (opt.filter && !opt.filter(path)) {
172+
if (opt.filter && !opt.filter(path, ent)) {
173173
return false
174174
}
175175
// is a file
@@ -193,7 +193,7 @@ const rimrafWindowsDirSync = (
193193
if (!removedAll) {
194194
return false
195195
}
196-
if (opt.filter && !opt.filter(path)) {
196+
if (opt.filter && !opt.filter(path, ent)) {
197197
return false
198198
}
199199
ignoreENOENTSync(() => {

test/rimraf-move-remove.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,8 +528,8 @@ t.test(
528528
const { signal } = ac
529529
const opt = {
530530
signal,
531-
filter: p => {
532-
if (basename(p) === 'g') {
531+
filter: (p, st) => {
532+
if (basename(p) === 'g' && st.isFile()) {
533533
ac.abort(new Error('done'))
534534
}
535535
return true

test/rimraf-posix.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ t.test(
229229
const { signal } = ac
230230
const opt = {
231231
signal,
232-
filter: p => {
233-
if (basename(p) === 'g') {
232+
filter: (p, st) => {
233+
if (basename(p) === 'g' && st.isFile()) {
234234
ac.abort(new Error('done'))
235235
}
236236
return true

test/rimraf-windows.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,8 @@ t.test(
508508
const { signal } = ac
509509
const opt = {
510510
signal,
511-
filter: p => {
512-
if (basename(p) === 'g') {
511+
filter: (p, st) => {
512+
if (basename(p) === 'g' && st.isFile()) {
513513
ac.abort(new Error('done'))
514514
}
515515
return true

0 commit comments

Comments
 (0)