From b320768e4c1a9edb692f82d9847966c6e4d18546 Mon Sep 17 00:00:00 2001 From: lex Date: Tue, 12 May 2026 12:32:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A(prefetch-ripgrep)?= =?UTF-8?q?=20Windows=20=E8=B5=B0=E5=8E=9F=E7=94=9F=20tar.exe=20=E8=A7=84?= =?UTF-8?q?=E9=81=BF=20cygwin=20=E8=B7=AF=E5=BE=84=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/opencode/script/prefetch-ripgrep.ts | 22 +++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/opencode/script/prefetch-ripgrep.ts b/packages/opencode/script/prefetch-ripgrep.ts index 7763c4ee25..fa955be124 100644 --- a/packages/opencode/script/prefetch-ripgrep.ts +++ b/packages/opencode/script/prefetch-ripgrep.ts @@ -111,12 +111,28 @@ async function extractRg(archive: string, rgKey: RgKey, targetBinDir: string): P return } fs.mkdirSync(targetBinDir, { recursive: true }) - // Extract to a sibling temp dir, then copy. Use bsdtar / GNU tar — both handle - // .tar.gz and .zip on Linux/macOS/modern Windows (libarchive-backed `tar`). + // Extract to a sibling temp dir, then copy. + // On Windows, Git Bash's cygwin tar treats `D:\foo` as a remote `host:path`, + // so spawn the Windows-native tar.exe (libarchive, accepts native paths and + // handles both .tar.gz and .zip) directly via Bun.spawnSync — bypassing the + // shell entirely. On POSIX, just use system tar the same way. const tmp = path.join(cacheDir, `extract-${rgKey}`) fs.rmSync(tmp, { recursive: true, force: true }) fs.mkdirSync(tmp, { recursive: true }) - await $`tar -xf ${archive} -C ${tmp}`.quiet() + const tarBin = + process.platform === "win32" && fs.existsSync("C:\\Windows\\System32\\tar.exe") + ? "C:\\Windows\\System32\\tar.exe" + : "tar" + const proc = Bun.spawnSync({ + cmd: [tarBin, "-xf", archive, "-C", tmp], + stdout: "pipe", + stderr: "pipe", + }) + if (proc.exitCode !== 0) { + throw new Error( + `tar extract failed (exit ${proc.exitCode}) for ${archive}\nstderr: ${proc.stderr?.toString() ?? ""}`, + ) + } // ripgrep archives extract to ripgrep--/rg(.exe) const subdirs = fs.readdirSync(tmp, { withFileTypes: true }).filter((e) => e.isDirectory()) let extractedRg: string | undefined