Skip to content

Commit

Permalink
provide dirent/stats as second arg to filter method
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacs committed Mar 8, 2023
1 parent a1268c9 commit bc6c09a
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 50 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 4.4

- Provide Dirent or Stats object as second argument to filter

# 4.3

- Return boolean indicating whether the path was fully removed
Expand Down
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,16 @@ Options:
`fs.rm` because that implementation does not support abort
signals.

- `filter` Method that receives a path string as an argument, and
returns a boolean indicating whether that path should be
deleted. With async rimraf methods, this may return a Promise
that resolves to a boolean. (Since Promises are truthy,
returning a Promise from a sync filter is the same as just not
filtering anything.)
- `filter` Method that returns a boolean indicating whether that
path should be deleted. With async rimraf methods, this may
return a Promise that resolves to a boolean. (Since Promises
are truthy, returning a Promise from a sync filter is the same
as just not filtering anything.)

The first argument to the filter is the path string. The
second argument is either a `Dirent` or `Stats` object for that
path. (The first path explored will be a `Stats`, the rest
will be `Dirent`.)

If a filter method is provided, it will _only_ remove entries
if the filter returns (or resolves to) a truthy value. Omitting
Expand Down
51 changes: 27 additions & 24 deletions src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { parse, relative, resolve } from 'path'
const cwd = process.cwd()

import { createInterface, Interface } from 'readline'
import { Dirent, Stats } from 'fs'

const prompt = async (rl: Interface, q: string) =>
new Promise<string>(res => rl.question(q, res))
Expand All @@ -70,11 +71,11 @@ const interactiveRimraf = async (
processing = false
}
const oneAtATime =
(fn: (s: string) => Promise<boolean>) =>
async (s: string): Promise<boolean> => {
(fn: (s: string, e: Dirent | Stats) => Promise<boolean>) =>
async (s: string, e: Dirent | Stats): Promise<boolean> => {
const p = new Promise<boolean>(res => {
queue.push(async () => {
const result = await fn(s)
const result = await fn(s, e)
res(result)
return result
})
Expand All @@ -86,30 +87,32 @@ const interactiveRimraf = async (
input: process.stdin,
output: process.stdout,
})
opt.filter = oneAtATime(async (path: string): Promise<boolean> => {
if (noneRemaining) {
return false
}
while (!allRemaining) {
const a = (
await prompt(rl, `rm? ${relative(cwd, path)}\n[(Yes)/No/All/Quit] > `)
).trim()
if (/^n/i.test(a)) {
return false
} else if (/^a/i.test(a)) {
allRemaining = true
break
} else if (/^q/i.test(a)) {
noneRemaining = true
opt.filter = oneAtATime(
async (path: string, ent: Dirent | Stats): Promise<boolean> => {
if (noneRemaining) {
return false
} else if (a === '' || /^y/i.test(a)) {
break
} else {
continue
}
while (!allRemaining) {
const a = (
await prompt(rl, `rm? ${relative(cwd, path)}\n[(Yes)/No/All/Quit] > `)
).trim()
if (/^n/i.test(a)) {
return false
} else if (/^a/i.test(a)) {
allRemaining = true
break
} else if (/^q/i.test(a)) {
noneRemaining = true
return false
} else if (a === '' || /^y/i.test(a)) {
break
} else {
continue
}
}
return existingFilter(path, ent)
}
return existingFilter(path)
})
)
await impl(paths, opt)
rl.close()
}
Expand Down
7 changes: 5 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ export interface RimrafAsyncOptions {
maxBackoff?: number
signal?: AbortSignal
glob?: boolean | GlobOptions
filter?: ((path: string) => boolean) | ((path: string) => Promise<boolean>)
filter?:
| ((path: string, ent: Dirent | Stats) => boolean)
| ((path: string, ent: Dirent | Stats) => Promise<boolean>)
}

export interface RimrafSyncOptions extends RimrafAsyncOptions {
filter?: (path: string) => boolean
filter?: (path: string, ent: Dirent | Stats) => boolean
}

export type RimrafOptions = RimrafSyncOptions | RimrafAsyncOptions
Expand Down Expand Up @@ -44,6 +46,7 @@ export const assertRimrafOptions: (o: any) => void = (
}
}

import { Dirent, Stats } from 'fs'
import { rimrafManual, rimrafManualSync } from './rimraf-manual.js'
import { rimrafMoveRemove, rimrafMoveRemoveSync } from './rimraf-move-remove.js'
import { rimrafNative, rimrafNativeSync } from './rimraf-native.js'
Expand Down
8 changes: 4 additions & 4 deletions src/rimraf-move-remove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const rimrafMoveRemoveDir = async (
}
}
/* c8 ignore stop */
if (opt.filter && !(await opt.filter(path))) {
if (opt.filter && !(await opt.filter(path, ent))) {
return false
}
await ignoreENOENT(tmpUnlink(path, opt.tmp, unlinkFixEPERM))
Expand All @@ -141,7 +141,7 @@ const rimrafMoveRemoveDir = async (
if (opt.preserveRoot === false && path === parse(path).root) {
return false
}
if (opt.filter && !(await opt.filter(path))) {
if (opt.filter && !(await opt.filter(path, ent))) {
return false
}
await ignoreENOENT(tmpUnlink(path, opt.tmp, rmdir))
Expand Down Expand Up @@ -205,7 +205,7 @@ const rimrafMoveRemoveDirSync = (
}
}
/* c8 ignore stop */
if (opt.filter && !opt.filter(path)) {
if (opt.filter && !opt.filter(path, ent)) {
return false
}
ignoreENOENTSync(() => tmpUnlinkSync(path, tmp, unlinkFixEPERMSync))
Expand All @@ -223,7 +223,7 @@ const rimrafMoveRemoveDirSync = (
if (opt.preserveRoot === false && path === parse(path).root) {
return false
}
if (opt.filter && !opt.filter(path)) {
if (opt.filter && !opt.filter(path, ent)) {
return false
}
ignoreENOENTSync(() => tmpUnlinkSync(path, tmp, rmdirSync))
Expand Down
8 changes: 4 additions & 4 deletions src/rimraf-posix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const rimrafPosixDir = async (
}
}
/* c8 ignore stop */
if (opt.filter && !(await opt.filter(path))) {
if (opt.filter && !(await opt.filter(path, ent))) {
return false
}
await ignoreENOENT(unlink(path))
Expand All @@ -85,7 +85,7 @@ const rimrafPosixDir = async (
return false
}

if (opt.filter && !(await opt.filter(path))) {
if (opt.filter && !(await opt.filter(path, ent))) {
return false
}

Expand Down Expand Up @@ -115,7 +115,7 @@ const rimrafPosixDirSync = (
}
}
/* c8 ignore stop */
if (opt.filter && !opt.filter(path)) {
if (opt.filter && !opt.filter(path, ent)) {
return false
}
ignoreENOENTSync(() => unlinkSync(path))
Expand All @@ -134,7 +134,7 @@ const rimrafPosixDirSync = (
return false
}

if (opt.filter && !opt.filter(path)) {
if (opt.filter && !opt.filter(path, ent)) {
return false
}

Expand Down
8 changes: 4 additions & 4 deletions src/rimraf-windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ const rimrafWindowsDir = async (
}
}
/* c8 ignore stop */
if (opt.filter && !(await opt.filter(path))) {
if (opt.filter && !(await opt.filter(path, ent))) {
return false
}
// is a file
Expand All @@ -141,7 +141,7 @@ const rimrafWindowsDir = async (
if (!removedAll) {
return false
}
if (opt.filter && !(await opt.filter(path))) {
if (opt.filter && !(await opt.filter(path, ent))) {
return false
}
await ignoreENOENT(rimrafWindowsDirMoveRemoveFallback(path, opt))
Expand Down Expand Up @@ -169,7 +169,7 @@ const rimrafWindowsDirSync = (
}
}
/* c8 ignore stop */
if (opt.filter && !opt.filter(path)) {
if (opt.filter && !opt.filter(path, ent)) {
return false
}
// is a file
Expand All @@ -193,7 +193,7 @@ const rimrafWindowsDirSync = (
if (!removedAll) {
return false
}
if (opt.filter && !opt.filter(path)) {
if (opt.filter && !opt.filter(path, ent)) {
return false
}
ignoreENOENTSync(() => {
Expand Down
4 changes: 2 additions & 2 deletions test/rimraf-move-remove.js
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,8 @@ t.test(
const { signal } = ac
const opt = {
signal,
filter: p => {
if (basename(p) === 'g') {
filter: (p, st) => {
if (basename(p) === 'g' && st.isFile()) {
ac.abort(new Error('done'))
}
return true
Expand Down
4 changes: 2 additions & 2 deletions test/rimraf-posix.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ t.test(
const { signal } = ac
const opt = {
signal,
filter: p => {
if (basename(p) === 'g') {
filter: (p, st) => {
if (basename(p) === 'g' && st.isFile()) {
ac.abort(new Error('done'))
}
return true
Expand Down
4 changes: 2 additions & 2 deletions test/rimraf-windows.js
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,8 @@ t.test(
const { signal } = ac
const opt = {
signal,
filter: p => {
if (basename(p) === 'g') {
filter: (p, st) => {
if (basename(p) === 'g' && st.isFile()) {
ac.abort(new Error('done'))
}
return true
Expand Down

0 comments on commit bc6c09a

Please sign in to comment.