ignore: improve file ignore performance and cross-platform support

- Replace glob patterns with Set lookup for common folders to speed up matching
- Use path.sep for cross-platform compatibility on Windows/Unix systems
- Add comprehensive test coverage for nested and non-nested folder matching
- Simplify implementation by removing unnecessary caching complexity
This commit is contained in:
Dax Raad
2025-10-09 15:53:45 -04:00
parent c2950d26f0
commit dfc7ac4cf0
2 changed files with 43 additions and 28 deletions

View File

@@ -1,28 +1,26 @@
import { sep } from "node:path"
export namespace FileIgnore {
const DEFAULT_PATTERNS = [
// Dependencies
"**/node_modules/**",
"**/bower_components/**",
"**/.pnpm-store/**",
"**/vendor/**",
const FOLDERS = new Set([
"node_modules",
"bower_components",
".pnpm-store",
"vendor",
"dist",
"build",
"out",
".next",
"target",
"bin",
"obj",
".git",
".svn",
".hg",
".vscode",
".idea",
])
// Build outputs
"**/dist/**",
"**/build/**",
"**/out/**",
"**/.next/**",
"**/target/**", // Rust
"**/bin/**",
"**/obj/**", // .NET
// Version control
"**/.git/**",
"**/.svn/**",
"**/.hg/**",
// IDE/Editor
"**/.vscode/**",
"**/.idea/**",
const FILES = [
"**/*.swp",
"**/*.swo",
@@ -41,22 +39,29 @@ export namespace FileIgnore {
"**/.nyc_output/**",
]
const GLOBS = DEFAULT_PATTERNS.map((p) => new Bun.Glob(p))
const FILE_GLOBS = FILES.map((p) => new Bun.Glob(p))
export function match(
filepath: string,
opts: {
opts?: {
extra?: Bun.Glob[]
whitelist?: Bun.Glob[]
},
) {
for (const glob of opts.whitelist || []) {
for (const glob of opts?.whitelist || []) {
if (glob.match(filepath)) return false
}
const extra = opts.extra || []
for (const glob of [...GLOBS, ...extra]) {
const parts = filepath.split(sep)
for (let i = 0; i < parts.length; i++) {
if (FOLDERS.has(parts[i])) return true
}
const extra = opts?.extra || []
for (const glob of [...FILE_GLOBS, ...extra]) {
if (glob.match(filepath)) return true
}
return false
}
}

View File

@@ -0,0 +1,10 @@
import { test, expect } from "bun:test"
import { FileIgnore } from "../../src/file/ignore"
test("match nested and non-nested", () => {
expect(FileIgnore.match("node_modules/index.js")).toBe(true)
expect(FileIgnore.match("node_modules")).toBe(true)
expect(FileIgnore.match("node_modules/")).toBe(true)
expect(FileIgnore.match("node_modules/bar")).toBe(true)
expect(FileIgnore.match("node_modules/bar/")).toBe(true)
})