refactor(grep): replace glob dependency with fs.readdirSync
- Add findFileRecursive function using native Node.js fs API - Remove glob package from dependencies - Add unit tests for findFileRecursive 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
103
src/tools/grep/downloader.test.ts
Normal file
103
src/tools/grep/downloader.test.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import { describe, test, expect, beforeEach, afterEach } from "bun:test"
|
||||
import { mkdirSync, rmSync, writeFileSync, existsSync } from "node:fs"
|
||||
import { join } from "node:path"
|
||||
import { tmpdir } from "node:os"
|
||||
|
||||
// Import the function we'll create to replace glob
|
||||
import { findFileRecursive } from "./downloader"
|
||||
|
||||
describe("findFileRecursive", () => {
|
||||
let testDir: string
|
||||
|
||||
beforeEach(() => {
|
||||
// #given - create temp directory for testing
|
||||
testDir = join(tmpdir(), `downloader-test-${Date.now()}`)
|
||||
mkdirSync(testDir, { recursive: true })
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
// cleanup
|
||||
if (existsSync(testDir)) {
|
||||
rmSync(testDir, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
test("should find file in root directory", () => {
|
||||
// #given
|
||||
const targetFile = join(testDir, "rg.exe")
|
||||
writeFileSync(targetFile, "dummy content")
|
||||
|
||||
// #when
|
||||
const result = findFileRecursive(testDir, "rg.exe")
|
||||
|
||||
// #then
|
||||
expect(result).toBe(targetFile)
|
||||
})
|
||||
|
||||
test("should find file in nested directory (ripgrep release structure)", () => {
|
||||
// #given - simulate ripgrep release zip structure
|
||||
const nestedDir = join(testDir, "ripgrep-14.1.1-x86_64-pc-windows-msvc")
|
||||
mkdirSync(nestedDir, { recursive: true })
|
||||
const targetFile = join(nestedDir, "rg.exe")
|
||||
writeFileSync(targetFile, "dummy content")
|
||||
|
||||
// #when
|
||||
const result = findFileRecursive(testDir, "rg.exe")
|
||||
|
||||
// #then
|
||||
expect(result).toBe(targetFile)
|
||||
})
|
||||
|
||||
test("should find file in deeply nested directory", () => {
|
||||
// #given
|
||||
const deepDir = join(testDir, "level1", "level2", "level3")
|
||||
mkdirSync(deepDir, { recursive: true })
|
||||
const targetFile = join(deepDir, "rg")
|
||||
writeFileSync(targetFile, "dummy content")
|
||||
|
||||
// #when
|
||||
const result = findFileRecursive(testDir, "rg")
|
||||
|
||||
// #then
|
||||
expect(result).toBe(targetFile)
|
||||
})
|
||||
|
||||
test("should return null when file not found", () => {
|
||||
// #given - empty directory
|
||||
|
||||
// #when
|
||||
const result = findFileRecursive(testDir, "nonexistent.exe")
|
||||
|
||||
// #then
|
||||
expect(result).toBeNull()
|
||||
})
|
||||
|
||||
test("should find first match when multiple files exist", () => {
|
||||
// #given
|
||||
const dir1 = join(testDir, "dir1")
|
||||
const dir2 = join(testDir, "dir2")
|
||||
mkdirSync(dir1, { recursive: true })
|
||||
mkdirSync(dir2, { recursive: true })
|
||||
writeFileSync(join(dir1, "rg"), "first")
|
||||
writeFileSync(join(dir2, "rg"), "second")
|
||||
|
||||
// #when
|
||||
const result = findFileRecursive(testDir, "rg")
|
||||
|
||||
// #then
|
||||
expect(result).not.toBeNull()
|
||||
expect(result!.endsWith("rg")).toBe(true)
|
||||
})
|
||||
|
||||
test("should match exact filename, not partial", () => {
|
||||
// #given
|
||||
writeFileSync(join(testDir, "rg.exe.bak"), "backup file")
|
||||
writeFileSync(join(testDir, "not-rg.exe"), "wrong file")
|
||||
|
||||
// #when
|
||||
const result = findFileRecursive(testDir, "rg.exe")
|
||||
|
||||
// #then
|
||||
expect(result).toBeNull()
|
||||
})
|
||||
})
|
||||
@@ -1,7 +1,21 @@
|
||||
import { existsSync, mkdirSync, chmodSync, unlinkSync } from "node:fs"
|
||||
import { existsSync, mkdirSync, chmodSync, unlinkSync, readdirSync } from "node:fs"
|
||||
import { join } from "node:path"
|
||||
import { spawn } from "bun"
|
||||
|
||||
export function findFileRecursive(dir: string, filename: string): string | null {
|
||||
try {
|
||||
const entries = readdirSync(dir, { withFileTypes: true, recursive: true })
|
||||
for (const entry of entries) {
|
||||
if (entry.isFile() && entry.name === filename) {
|
||||
return join(entry.parentPath ?? dir, entry.name)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const RG_VERSION = "14.1.1"
|
||||
|
||||
const PLATFORM_CONFIG: Record<string, { platform: string; extension: "tar.gz" | "zip" } | undefined> = {
|
||||
@@ -70,14 +84,12 @@ async function extractZipWindows(archivePath: string, destDir: string): Promise<
|
||||
throw new Error("Failed to extract zip with PowerShell")
|
||||
}
|
||||
|
||||
const { globSync } = await import("glob")
|
||||
const rgFiles = globSync("**/rg.exe", { cwd: destDir })
|
||||
if (rgFiles.length > 0) {
|
||||
const srcPath = join(destDir, rgFiles[0])
|
||||
const foundPath = findFileRecursive(destDir, "rg.exe")
|
||||
if (foundPath) {
|
||||
const destPath = join(destDir, "rg.exe")
|
||||
if (srcPath !== destPath) {
|
||||
if (foundPath !== destPath) {
|
||||
const { renameSync } = await import("node:fs")
|
||||
renameSync(srcPath, destPath)
|
||||
renameSync(foundPath, destPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,14 +104,12 @@ async function extractZipUnix(archivePath: string, destDir: string): Promise<voi
|
||||
throw new Error("Failed to extract zip")
|
||||
}
|
||||
|
||||
const { globSync } = await import("glob")
|
||||
const rgFiles = globSync("**/rg", { cwd: destDir })
|
||||
if (rgFiles.length > 0) {
|
||||
const srcPath = join(destDir, rgFiles[0])
|
||||
const foundPath = findFileRecursive(destDir, "rg")
|
||||
if (foundPath) {
|
||||
const destPath = join(destDir, "rg")
|
||||
if (srcPath !== destPath) {
|
||||
if (foundPath !== destPath) {
|
||||
const { renameSync } = await import("node:fs")
|
||||
renameSync(srcPath, destPath)
|
||||
renameSync(foundPath, destPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user