Skip to content

Commit

Permalink
fix: ensure default beheviour is to return relative pathnames
Browse files Browse the repository at this point in the history
  • Loading branch information
wyattjoh committed Aug 28, 2023
1 parent 6a6a60b commit 28bb24b
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 15 deletions.
65 changes: 50 additions & 15 deletions packages/next/src/lib/recursive-readdir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,42 @@ import type { Dirent } from 'fs'
import fs from 'fs/promises'
import path from 'path'

type Filter = (pathname: string) => boolean

/**
*
* @param dir the directory to read
* @param pathnameFilter filter to ignore files with absolute pathnames, false to ignore
* @param ignoreFilter filter to ignore files and directories with absolute pathnames, false to ignore
* @param ignorePartFilter filter to ignore files and directories with the pathname part, false to ignore
* @param sortPathnames whether to sort the results, true by default
* @param relativePathnames whether to return relative pathnames, true by default
* @returns
*/
export async function recursiveReadDir(
dir: string,
pathnameFilter?: (absoluteFilePath: string) => boolean,
ignoreFilter?: (absoluteFilePath: string) => boolean,
ignorePartFilter?: (partName: string) => boolean,
sortPathnames: boolean = true
pathnameFilter?: Filter,
ignoreFilter?: Filter,
ignorePartFilter?: Filter,
sortPathnames: boolean = true,
relativePathnames: boolean = true
): Promise<string[]> {
// The list of pathnames to return.
const pathnames: string[] = []

/**
* Pushes the pathname to the list of pathnames and coerces it to be relative
* if requested.
*/
const push = relativePathnames
? (pathname: string) => {
pathnames.push(pathname.replace(dir, ''))
}
: (pathname: string) => {
pathnames.push(pathname)
}

// The queue of directories to scan.
let directories: string[] = [dir]

while (directories.length > 0) {
Expand Down Expand Up @@ -60,39 +78,56 @@ export async function recursiveReadDir(
}

// Handle each file.
const pathname = path.join(directory, file.name)
const absolutePathname = path.join(directory, file.name)

// If enabled, ignore the file if it matches the ignore filter.
if (ignoreFilter && ignoreFilter(pathname)) {
if (ignoreFilter && ignoreFilter(absolutePathname)) {
continue
}

// If the file is a directory, then add it to the list of directories,
// they'll be scanned on a later pass.
if (file.isDirectory()) {
directories.push(pathname)
directories.push(absolutePathname)
} else if (file.isSymbolicLink()) {
links.push(pathname)
} else if (!pathnameFilter || pathnameFilter(pathname)) {
pathnames.push(pathname)
links.push(absolutePathname)
} else if (!pathnameFilter || pathnameFilter(absolutePathname)) {
push(absolutePathname)
}
}
}

// Resolve all the symbolic links we found if any.
if (links.length > 0) {
const resolved = await Promise.all(
links.map(async (pathname) => fs.stat(pathname))
links.map(async (absolutePathname) => {
try {
return await fs.stat(absolutePathname)
} catch (err: any) {
// This can only happen when the underlying link was removed. If
// anything other than this error occurs, re-throw it.
if (err.code !== 'ENOENT') throw err

// The error occurred, so abandon reading this directory.
return null
}
})
)

for (let i = 0; i < links.length; i++) {
const pathname = links[i]
const stats = resolved[i]

// If the link was removed, then skip it.
if (!stats) continue

// We would have already ignored the file if it matched the ignore
// filter, so we don't need to check it again.
const absolutePathname = links[i]

if (stats.isDirectory()) {
directories.push(pathname)
} else if (!pathnameFilter || pathnameFilter(pathname)) {
pathnames.push(pathname)
directories.push(absolutePathname)
} else if (!pathnameFilter || pathnameFilter(absolutePathname)) {
push(absolutePathname)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ export class DefaultFileReader implements FileReader {
this.ignorePartFilter,
// We don't need to sort the results because we're not depending on the
// order of the results.
false,
// We want absolute pathnames because we're going to be comparing them
// with other absolute pathnames.
false
)
}
Expand Down

0 comments on commit 28bb24b

Please sign in to comment.