@@ -4,14 +4,14 @@ import nodePath from 'node:path';
44import { Readable } from 'node:stream' ;
55import mergeStreams from '@sindresorhus/merge-streams' ;
66import fastGlob from 'fast-glob' ;
7- import { isDirectory , isDirectorySync } from 'path-type' ;
87import { toPath } from 'unicorn-magic' ;
98import {
109 GITIGNORE_FILES_PATTERN ,
1110 getIgnorePatternsAndPredicate ,
1211 getIgnorePatternsAndPredicateSync ,
1312} from './ignore.js' ;
1413import {
14+ bindFsMethod ,
1515 isNegativePattern ,
1616 normalizeDirectoryPatternForFastGlob ,
1717} from './utilities.js' ;
@@ -22,6 +22,33 @@ const assertPatternsInput = patterns => {
2222 }
2323} ;
2424
25+ const getStatMethod = fsImplementation =>
26+ bindFsMethod ( fsImplementation ?. promises , 'stat' )
27+ ?? bindFsMethod ( fsImplementation , 'stat' )
28+ ?? bindFsMethod ( fs . promises , 'stat' ) ;
29+
30+ const getStatSyncMethod = fsImplementation =>
31+ bindFsMethod ( fsImplementation , 'statSync' )
32+ ?? bindFsMethod ( fs , 'statSync' ) ;
33+
34+ const isDirectory = async ( path , fsImplementation ) => {
35+ try {
36+ const stats = await getStatMethod ( fsImplementation ) ( path ) ;
37+ return stats . isDirectory ( ) ;
38+ } catch {
39+ return false ;
40+ }
41+ } ;
42+
43+ const isDirectorySync = ( path , fsImplementation ) => {
44+ try {
45+ const stats = getStatSyncMethod ( fsImplementation ) ( path ) ;
46+ return stats . isDirectory ( ) ;
47+ } catch {
48+ return false ;
49+ }
50+ } ;
51+
2552const normalizePathForDirectoryGlob = ( filePath , cwd ) => {
2653 const path = isNegativePattern ( filePath ) ? filePath . slice ( 1 ) : filePath ;
2754 return nodePath . isAbsolute ( path ) ? path : nodePath . join ( cwd , path ) ;
@@ -51,6 +78,7 @@ const directoryToGlob = async (directoryPaths, {
5178 cwd = process . cwd ( ) ,
5279 files,
5380 extensions,
81+ fs : fsImplementation ,
5482} = { } ) => {
5583 const globs = await Promise . all ( directoryPaths . map ( async directoryPath => {
5684 // Check pattern without negative prefix
@@ -63,7 +91,7 @@ const directoryToGlob = async (directoryPaths, {
6391
6492 // Original logic for checking actual directories
6593 const pathToCheck = normalizePathForDirectoryGlob ( directoryPath , cwd ) ;
66- return ( await isDirectory ( pathToCheck ) ) ? getDirectoryGlob ( { directoryPath, files, extensions} ) : directoryPath ;
94+ return ( await isDirectory ( pathToCheck , fsImplementation ) ) ? getDirectoryGlob ( { directoryPath, files, extensions} ) : directoryPath ;
6795 } ) ) ;
6896
6997 return globs . flat ( ) ;
@@ -73,6 +101,7 @@ const directoryToGlobSync = (directoryPaths, {
73101 cwd = process . cwd ( ) ,
74102 files,
75103 extensions,
104+ fs : fsImplementation ,
76105} = { } ) => directoryPaths . flatMap ( directoryPath => {
77106 // Check pattern without negative prefix
78107 const checkPattern = isNegativePattern ( directoryPath ) ? directoryPath . slice ( 1 ) : directoryPath ;
@@ -84,7 +113,7 @@ const directoryToGlobSync = (directoryPaths, {
84113
85114 // Original logic for checking actual directories
86115 const pathToCheck = normalizePathForDirectoryGlob ( directoryPath , cwd ) ;
87- return isDirectorySync ( pathToCheck ) ? getDirectoryGlob ( { directoryPath, files, extensions} ) : directoryPath ;
116+ return isDirectorySync ( pathToCheck , fsImplementation ) ? getDirectoryGlob ( { directoryPath, files, extensions} ) : directoryPath ;
88117} ) ;
89118
90119const toPatternsArray = patterns => {
@@ -93,20 +122,19 @@ const toPatternsArray = patterns => {
93122 return patterns ;
94123} ;
95124
96- const checkCwdOption = cwd => {
97- if ( ! cwd ) {
125+ const checkCwdOption = ( cwd , fsImplementation = fs ) => {
126+ if ( ! cwd || ! fsImplementation . statSync ) {
98127 return ;
99128 }
100129
101- let stat ;
102130 try {
103- stat = fs . statSync ( cwd ) ;
104- } catch {
105- return ;
106- }
107-
108- if ( ! stat . isDirectory ( ) ) {
109- throw new Error ( 'The `cwd` option must be a path to a directory' ) ;
131+ if ( ! fsImplementation . statSync ( cwd ) . isDirectory ( ) ) {
132+ throw new Error ( 'The `cwd` option must be a path to a directory' ) ;
133+ }
134+ } catch ( error ) {
135+ if ( error . message === 'The `cwd` option must be a path to a directory' ) {
136+ throw error ;
137+ }
110138 }
111139} ;
112140
@@ -118,7 +146,7 @@ const normalizeOptions = (options = {}) => {
118146 cwd : toPath ( options . cwd ) ,
119147 } ;
120148
121- checkCwdOption ( options . cwd ) ;
149+ checkCwdOption ( options . cwd , options . fs ) ;
122150
123151 return options ;
124152} ;
@@ -284,13 +312,16 @@ const normalizeExpandDirectoriesOption = (options, cwd) => ({
284312const generateTasks = async ( patterns , options ) => {
285313 const globTasks = convertNegativePatterns ( patterns , options ) ;
286314
287- const { cwd, expandDirectories} = options ;
315+ const { cwd, expandDirectories, fs : fsImplementation } = options ;
288316
289317 if ( ! expandDirectories ) {
290318 return globTasks ;
291319 }
292320
293- const directoryToGlobOptions = normalizeExpandDirectoriesOption ( expandDirectories , cwd ) ;
321+ const directoryToGlobOptions = {
322+ ...normalizeExpandDirectoriesOption ( expandDirectories , cwd ) ,
323+ fs : fsImplementation ,
324+ } ;
294325
295326 return Promise . all ( globTasks . map ( async task => {
296327 let { patterns, options} = task ;
@@ -300,7 +331,7 @@ const generateTasks = async (patterns, options) => {
300331 options . ignore ,
301332 ] = await Promise . all ( [
302333 directoryToGlob ( patterns , directoryToGlobOptions ) ,
303- directoryToGlob ( options . ignore , { cwd} ) ,
334+ directoryToGlob ( options . ignore , { cwd, fs : fsImplementation } ) ,
304335 ] ) ;
305336
306337 return { patterns, options} ;
@@ -309,18 +340,21 @@ const generateTasks = async (patterns, options) => {
309340
310341const generateTasksSync = ( patterns , options ) => {
311342 const globTasks = convertNegativePatterns ( patterns , options ) ;
312- const { cwd, expandDirectories} = options ;
343+ const { cwd, expandDirectories, fs : fsImplementation } = options ;
313344
314345 if ( ! expandDirectories ) {
315346 return globTasks ;
316347 }
317348
318- const directoryToGlobSyncOptions = normalizeExpandDirectoriesOption ( expandDirectories , cwd ) ;
349+ const directoryToGlobSyncOptions = {
350+ ...normalizeExpandDirectoriesOption ( expandDirectories , cwd ) ,
351+ fs : fsImplementation ,
352+ } ;
319353
320354 return globTasks . map ( task => {
321355 let { patterns, options} = task ;
322356 patterns = directoryToGlobSync ( patterns , directoryToGlobSyncOptions ) ;
323- options . ignore = directoryToGlobSync ( options . ignore , { cwd} ) ;
357+ options . ignore = directoryToGlobSync ( options . ignore , { cwd, fs : fsImplementation } ) ;
324358 return { patterns, options} ;
325359 } ) ;
326360} ;
0 commit comments