forked from google-gemini/gemini-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdownload-ripgrep-binaries.ts
More file actions
146 lines (131 loc) · 4.99 KB
/
Copy pathdownload-ripgrep-binaries.ts
File metadata and controls
146 lines (131 loc) · 4.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview This script downloads pre-built ripgrep binaries for all supported
* architectures and platforms. These binaries are checked into the repository
* under packages/core/vendor/ripgrep.
*
* Maintainers should periodically run this script to upgrade the version
* of ripgrep being distributed.
*
* Usage: npx tsx scripts/download-ripgrep-binaries.ts
*/
import fs from 'node:fs';
import fsPromises from 'node:fs/promises';
import path from 'node:path';
import { pipeline } from 'node:stream/promises';
import { fileURLToPath } from 'node:url';
import { createWriteStream } from 'node:fs';
import { Readable } from 'node:stream';
import type { ReadableStream } from 'node:stream/web';
import { execFileSync } from 'node:child_process';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const CORE_VENDOR_DIR = path.join(__dirname, '../packages/core/vendor/ripgrep');
const VERSION = 'v13.0.0-10';
interface Target {
platform: string;
arch: string;
file: string;
}
const targets: Target[] = [
{ platform: 'darwin', arch: 'arm64', file: 'aarch64-apple-darwin.tar.gz' },
{ platform: 'darwin', arch: 'x64', file: 'x86_64-apple-darwin.tar.gz' },
{
platform: 'linux',
arch: 'arm64',
file: 'aarch64-unknown-linux-gnu.tar.gz',
},
{ platform: 'linux', arch: 'x64', file: 'x86_64-unknown-linux-musl.tar.gz' },
{ platform: 'win32', arch: 'x64', file: 'x86_64-pc-windows-msvc.zip' },
];
async function downloadBinary() {
await fsPromises.mkdir(CORE_VENDOR_DIR, { recursive: true });
for (const target of targets) {
const url = `https://github.com/microsoft/ripgrep-prebuilt/releases/download/${VERSION}/ripgrep-${VERSION}-${target.file}`;
const archivePath = path.join(CORE_VENDOR_DIR, target.file);
const binName = `rg-${target.platform}-${target.arch}${target.platform === 'win32' ? '.exe' : ''}`;
const finalBinPath = path.join(CORE_VENDOR_DIR, binName);
if (fs.existsSync(finalBinPath)) {
console.log(`[Cache] ${binName} already exists.`);
continue;
}
console.log(`[Download] ${url} -> ${archivePath}`);
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
}
if (!response.body) {
throw new Error(`Response body is null for ${url}`);
}
const fileStream = createWriteStream(archivePath);
// Node 18+ global fetch response.body is a ReadableStream (web stream)
// pipeline(Readable.fromWeb(response.body), fileStream) works in Node 18+
await pipeline(
Readable.fromWeb(response.body as ReadableStream),
fileStream,
);
console.log(`[Extract] Extracting ${archivePath}...`);
// Extract using shell commands for simplicity
if (target.file.endsWith('.tar.gz')) {
execFileSync('tar', ['-xzf', archivePath, '-C', CORE_VENDOR_DIR]);
// Microsoft's ripgrep release extracts directly to `rg` inside the current directory sometimes
const sourceBin = path.join(CORE_VENDOR_DIR, 'rg');
if (fs.existsSync(sourceBin)) {
await fsPromises.rename(sourceBin, finalBinPath);
} else {
// Fallback for sub-directory if it happens
const extractedDirName = `ripgrep-${VERSION}-${target.file.replace('.tar.gz', '')}`;
const fallbackSourceBin = path.join(
CORE_VENDOR_DIR,
extractedDirName,
'rg',
);
if (fs.existsSync(fallbackSourceBin)) {
await fsPromises.rename(fallbackSourceBin, finalBinPath);
await fsPromises.rm(path.join(CORE_VENDOR_DIR, extractedDirName), {
recursive: true,
force: true,
});
} else {
throw new Error(
`Could not find extracted 'rg' binary for ${target.platform} ${target.arch}`,
);
}
}
} else if (target.file.endsWith('.zip')) {
execFileSync('unzip', ['-o', '-q', archivePath, '-d', CORE_VENDOR_DIR]);
const sourceBin = path.join(CORE_VENDOR_DIR, 'rg.exe');
if (fs.existsSync(sourceBin)) {
await fsPromises.rename(sourceBin, finalBinPath);
} else {
const extractedDirName = `ripgrep-${VERSION}-${target.file.replace('.zip', '')}`;
const fallbackSourceBin = path.join(
CORE_VENDOR_DIR,
extractedDirName,
'rg.exe',
);
if (fs.existsSync(fallbackSourceBin)) {
await fsPromises.rename(fallbackSourceBin, finalBinPath);
await fsPromises.rm(path.join(CORE_VENDOR_DIR, extractedDirName), {
recursive: true,
force: true,
});
} else {
throw new Error(
`Could not find extracted 'rg.exe' binary for ${target.platform} ${target.arch}`,
);
}
}
}
// Clean up archive
await fsPromises.unlink(archivePath);
console.log(`[Success] Saved to ${finalBinPath}`);
}
}
downloadBinary().catch((err) => {
console.error(err);
process.exit(1);
});