( searchPattern: string, searchDir: string, ignorePatterns: string[], abortSignal: AbortSignal, )
| 176 | } |
| 177 | |
| 178 | async function globDirectories( |
| 179 | searchPattern: string, |
| 180 | searchDir: string, |
| 181 | ignorePatterns: string[], |
| 182 | abortSignal: AbortSignal, |
| 183 | ): Promise<string[]> { |
| 184 | const fs = getFsImplementation() |
| 185 | const normalizedPattern = normalizeGlobPattern( |
| 186 | searchPattern.endsWith('/') ? searchPattern : `${searchPattern}/`, |
| 187 | ) |
| 188 | const matcher = picomatch(normalizedPattern, { |
| 189 | dot: true, |
| 190 | nocase: getPlatform() === 'windows', |
| 191 | }) |
| 192 | const ignoreMatchers = ignorePatterns.map(pattern => |
| 193 | picomatch(normalizeGlobPattern(pattern.replace(/^!/, '')), { |
| 194 | dot: true, |
| 195 | nocase: getPlatform() === 'windows', |
| 196 | }), |
| 197 | ) |
| 198 | const maxDepth = getDirectoryGlobMaxDepth(normalizedPattern) |
| 199 | const matches: Array<{ path: string; mtimeMs: number }> = [] |
| 200 | |
| 201 | function shouldIgnore(relativePath: string): boolean { |
| 202 | const withSlash = relativePath.endsWith('/') |
| 203 | ? relativePath |
| 204 | : `${relativePath}/` |
| 205 | return ignoreMatchers.some( |
| 206 | isMatch => isMatch(relativePath) || isMatch(withSlash), |
| 207 | ) |
| 208 | } |
| 209 | |
| 210 | async function scan(currentDir: string, relativeDir = ''): Promise<void> { |
| 211 | if (abortSignal.aborted) { |
| 212 | throw abortSignal.reason ?? new Error('Glob aborted') |
| 213 | } |
| 214 | |
| 215 | const entries = await fs.readdir(currentDir) |
| 216 | await Promise.all( |
| 217 | entries.map(async entry => { |
| 218 | if (!entry.isDirectory()) { |
| 219 | return |
| 220 | } |
| 221 | |
| 222 | const absolutePath = join(currentDir, entry.name) |
| 223 | const relativePath = relativeDir |
| 224 | ? `${relativeDir}/${entry.name}` |
| 225 | : entry.name |
| 226 | const relativePathWithSlash = `${relativePath}/` |
| 227 | |
| 228 | if (shouldIgnore(relativePath) || shouldIgnore(relativePathWithSlash)) { |
| 229 | return |
| 230 | } |
| 231 | |
| 232 | if (matcher(relativePathWithSlash)) { |
| 233 | const stats = await fs.stat(absolutePath) |
| 234 | matches.push({ path: absolutePath, mtimeMs: stats.mtimeMs }) |
| 235 | } |
no test coverage detected