Something went wrong. Try again.
opencode v2 mirror
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137import path from "path"import { Context, Effect, Layer, Stream } from "effect"import { HttpClient, HttpClientRequest } from "effect/unstable/http"import { ChildProcess } from "effect/unstable/process"import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner"import { CrossSpawnSpawner } from "@opencode/util/cross-spawn-spawner"import { makeGlobalNode } from "@opencode/util/effect/app-node"import { httpClient } from "@opencode/util/effect/app-node-platform"import { FSUtil } from "@opencode/util/fs-util"import { Global } from "@opencode/util/global"import { which } from "../util/which.js"
export namespace RipgrepBinary { const VERSION = "15.1.0" const PLATFORM = { "arm64-darwin": { platform: "aarch64-apple-darwin", extension: "tar.gz" }, "arm64-linux": { platform: "aarch64-unknown-linux-gnu", extension: "tar.gz" }, "x64-darwin": { platform: "x86_64-apple-darwin", extension: "tar.gz" }, "x64-linux": { platform: "x86_64-unknown-linux-musl", extension: "tar.gz" }, "arm64-win32": { platform: "aarch64-pc-windows-msvc", extension: "zip" }, "ia32-win32": { platform: "i686-pc-windows-msvc", extension: "zip" }, "x64-win32": { platform: "x86_64-pc-windows-msvc", extension: "zip" }, } as const
interface Interface { readonly filepath: Effect.Effect<string, Error> }
export class Service extends Context.Service<Service, Interface>()("@opencode/RipgrepBinary") {}
const layer = Layer.effect( Service, Effect.gen(function* () { const fs = yield* FSUtil.Service const http = HttpClient.filterStatusOk(yield* HttpClient.HttpClient) const spawner = yield* ChildProcessSpawner const global = yield* Global.Service const findExecutable = (name: string) => which(name, undefined, global.bin)
const run = Effect.fnUntraced(function* (command: string, args: string[]) { const handle = yield* spawner.spawn(ChildProcess.make(command, args, { extendEnv: true, stdin: "ignore" })) const [stdout, stderr, code] = yield* Effect.all( [ Stream.mkString(Stream.decodeText(handle.stdout)), Stream.mkString(Stream.decodeText(handle.stderr)), handle.exitCode, ], { concurrency: "unbounded" }, ) return { stdout, stderr, code } }, Effect.scoped)
const extract = Effect.fnUntraced(function* ( archive: string, config: (typeof PLATFORM)[keyof typeof PLATFORM], target: string, ) { const dir = yield* fs.makeTempDirectoryScoped({ directory: global.bin, prefix: "ripgrep-" })
if (config.extension === "zip") { const shell = (yield* Effect.sync(() => findExecutable("powershell.exe") ?? findExecutable("pwsh.exe"))) ?? "powershell.exe" const result = yield* run(shell, [ "-NoProfile", "-NonInteractive", "-Command", `$global:ProgressPreference = 'SilentlyContinue'; Expand-Archive -LiteralPath '${archive.replaceAll("'", "''")}' -DestinationPath '${dir.replaceAll("'", "''")}' -Force`, ]) if (result.code !== 0) throw new Error( result.stderr.trim() || result.stdout.trim() || `ripgrep extraction failed with code ${result.code}`, ) }
if (config.extension === "tar.gz") { const result = yield* run("tar", ["-xzf", archive, "-C", dir]) if (result.code !== 0) throw new Error( result.stderr.trim() || result.stdout.trim() || `ripgrep extraction failed with code ${result.code}`, ) }
const extracted = path.join( dir, `ripgrep-${VERSION}-${config.platform}`, process.platform === "win32" ? "rg.exe" : "rg", ) if (!(yield* fs.isFile(extracted))) throw new Error(`ripgrep archive did not contain executable: ${extracted}`)
yield* fs.copyFile(extracted, target) if (process.platform !== "win32") yield* fs.chmod(target, 0o755) }, Effect.scoped)
return Service.of({ filepath: yield* Effect.cached( Effect.gen(function* () { const system = yield* Effect.sync(() => findExecutable(process.platform === "win32" ? "rg.exe" : "rg")) if (system && (yield* fs.isFile(system).pipe(Effect.orDie))) return system
const target = path.join(global.bin, `rg${process.platform === "win32" ? ".exe" : ""}`) if (yield* fs.isFile(target).pipe(Effect.orDie)) return target
const platformKey = `${process.arch}-${process.platform}` as keyof typeof PLATFORM const config = PLATFORM[platformKey] if (!config) throw new Error(`unsupported platform for ripgrep: ${platformKey}`)
const filename = `ripgrep-${VERSION}-${config.platform}.${config.extension}` const url = `https://github.com/BurntSushi/ripgrep/releases/download/${VERSION}/${filename}` const archive = path.join(global.bin, filename)
yield* Effect.logInfo("downloading ripgrep", { url }) yield* fs.ensureDir(global.bin).pipe(Effect.orDie) const bytes = yield* HttpClientRequest.get(url).pipe( http.execute, Effect.flatMap((response) => response.arrayBuffer), Effect.mapError((cause) => (cause instanceof Error ? cause : new Error(String(cause)))), ) if (bytes.byteLength === 0) throw new Error(`failed to download ripgrep from ${url}`)
yield* fs.writeWithDirs(archive, new Uint8Array(bytes)) yield* extract(archive, config, target) yield* fs.remove(archive, { force: true }).pipe(Effect.ignore) return target }), ), }) }), )
export const node = makeGlobalNode({ service: Service, layer: layer, deps: [FSUtil.node, Global.node, httpClient, CrossSpawnSpawner.node], })}