|
@@ -1,124 +0,0 @@
|
|
|
-import path from "path"
|
|
|
|
|
-import { Global } from "../global"
|
|
|
|
|
-import fs from "fs/promises"
|
|
|
|
|
-import z from "zod"
|
|
|
|
|
-import { NamedError } from "@opencode-ai/util/error"
|
|
|
|
|
-import { lazy } from "../util/lazy"
|
|
|
|
|
-import { Log } from "../util/log"
|
|
|
|
|
-import { ZipReader, BlobReader, BlobWriter } from "@zip.js/zip.js"
|
|
|
|
|
-
|
|
|
|
|
-export namespace Fzf {
|
|
|
|
|
- const log = Log.create({ service: "fzf" })
|
|
|
|
|
-
|
|
|
|
|
- const VERSION = "0.62.0"
|
|
|
|
|
- const PLATFORM = {
|
|
|
|
|
- darwin: { extension: "tar.gz" },
|
|
|
|
|
- linux: { extension: "tar.gz" },
|
|
|
|
|
- win32: { extension: "zip" },
|
|
|
|
|
- } as const
|
|
|
|
|
-
|
|
|
|
|
- export const ExtractionFailedError = NamedError.create(
|
|
|
|
|
- "FzfExtractionFailedError",
|
|
|
|
|
- z.object({
|
|
|
|
|
- filepath: z.string(),
|
|
|
|
|
- stderr: z.string(),
|
|
|
|
|
- }),
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
- export const UnsupportedPlatformError = NamedError.create(
|
|
|
|
|
- "FzfUnsupportedPlatformError",
|
|
|
|
|
- z.object({
|
|
|
|
|
- platform: z.string(),
|
|
|
|
|
- }),
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
- export const DownloadFailedError = NamedError.create(
|
|
|
|
|
- "FzfDownloadFailedError",
|
|
|
|
|
- z.object({
|
|
|
|
|
- url: z.string(),
|
|
|
|
|
- status: z.number(),
|
|
|
|
|
- }),
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
- const state = lazy(async () => {
|
|
|
|
|
- let filepath = Bun.which("fzf")
|
|
|
|
|
- if (filepath) {
|
|
|
|
|
- log.info("found", { filepath })
|
|
|
|
|
- return { filepath }
|
|
|
|
|
- }
|
|
|
|
|
- filepath = path.join(Global.Path.bin, "fzf" + (process.platform === "win32" ? ".exe" : ""))
|
|
|
|
|
-
|
|
|
|
|
- const file = Bun.file(filepath)
|
|
|
|
|
- if (!(await file.exists())) {
|
|
|
|
|
- const archMap = { x64: "amd64", arm64: "arm64" } as const
|
|
|
|
|
- const arch = archMap[process.arch as keyof typeof archMap] ?? "amd64"
|
|
|
|
|
-
|
|
|
|
|
- const config = PLATFORM[process.platform as keyof typeof PLATFORM]
|
|
|
|
|
- if (!config) throw new UnsupportedPlatformError({ platform: process.platform })
|
|
|
|
|
-
|
|
|
|
|
- const version = VERSION
|
|
|
|
|
- const platformName = process.platform === "win32" ? "windows" : process.platform
|
|
|
|
|
- const filename = `fzf-${version}-${platformName}_${arch}.${config.extension}`
|
|
|
|
|
- const url = `https://github.com/junegunn/fzf/releases/download/v${version}/${filename}`
|
|
|
|
|
-
|
|
|
|
|
- const response = await fetch(url)
|
|
|
|
|
- if (!response.ok) throw new DownloadFailedError({ url, status: response.status })
|
|
|
|
|
-
|
|
|
|
|
- const buffer = await response.arrayBuffer()
|
|
|
|
|
- const archivePath = path.join(Global.Path.bin, filename)
|
|
|
|
|
- await Bun.write(archivePath, buffer)
|
|
|
|
|
- if (config.extension === "tar.gz") {
|
|
|
|
|
- const proc = Bun.spawn(["tar", "-xzf", archivePath, "fzf"], {
|
|
|
|
|
- cwd: Global.Path.bin,
|
|
|
|
|
- stderr: "pipe",
|
|
|
|
|
- stdout: "pipe",
|
|
|
|
|
- })
|
|
|
|
|
- await proc.exited
|
|
|
|
|
- if (proc.exitCode !== 0)
|
|
|
|
|
- throw new ExtractionFailedError({
|
|
|
|
|
- filepath,
|
|
|
|
|
- stderr: await Bun.readableStreamToText(proc.stderr),
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- if (config.extension === "zip") {
|
|
|
|
|
- const zipFileReader = new ZipReader(new BlobReader(new Blob([await Bun.file(archivePath).arrayBuffer()])))
|
|
|
|
|
- const entries = await zipFileReader.getEntries()
|
|
|
|
|
- let fzfEntry: any
|
|
|
|
|
- for (const entry of entries) {
|
|
|
|
|
- if (entry.filename === "fzf.exe") {
|
|
|
|
|
- fzfEntry = entry
|
|
|
|
|
- break
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!fzfEntry) {
|
|
|
|
|
- throw new ExtractionFailedError({
|
|
|
|
|
- filepath: archivePath,
|
|
|
|
|
- stderr: "fzf.exe not found in zip archive",
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const fzfBlob = await fzfEntry.getData(new BlobWriter())
|
|
|
|
|
- if (!fzfBlob) {
|
|
|
|
|
- throw new ExtractionFailedError({
|
|
|
|
|
- filepath: archivePath,
|
|
|
|
|
- stderr: "Failed to extract fzf.exe from zip archive",
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- await Bun.write(filepath, await fzfBlob.arrayBuffer())
|
|
|
|
|
- await zipFileReader.close()
|
|
|
|
|
- }
|
|
|
|
|
- await fs.unlink(archivePath)
|
|
|
|
|
- if (process.platform !== "win32") await fs.chmod(filepath, 0o755)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return {
|
|
|
|
|
- filepath,
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- export async function filepath() {
|
|
|
|
|
- const { filepath } = await state()
|
|
|
|
|
- return filepath
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|