()
| 101 | } |
| 102 | |
| 103 | async function downloadFd(): Promise<string | null> { |
| 104 | const assetName = getFdAssetName(); |
| 105 | if (assetName === null) return null; |
| 106 | const expectedSha256 = FD_ARCHIVE_SHA256[assetName]; |
| 107 | if (expectedSha256 === undefined) return null; |
| 108 | |
| 109 | const binDir = getBinDir(); |
| 110 | mkdirSync(binDir, { recursive: true }); |
| 111 | |
| 112 | const binaryPath = getManagedFdBinaryPath(); |
| 113 | const extractDir = join( |
| 114 | binDir, |
| 115 | `fd_extract_${process.pid}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`, |
| 116 | ); |
| 117 | mkdirSync(extractDir, { recursive: true }); |
| 118 | const archivePath = join(extractDir, assetName); |
| 119 | |
| 120 | try { |
| 121 | const downloadUrl = `${FD_BASE_URL}/${assetName}`; |
| 122 | await downloadFile(downloadUrl, archivePath); |
| 123 | verifyArchive(archivePath, expectedSha256); |
| 124 | extractArchive(archivePath, extractDir, assetName); |
| 125 | |
| 126 | const binaryName = platform() === 'win32' ? 'fd.exe' : 'fd'; |
| 127 | const extractedBinary = findBinaryRecursively(extractDir, binaryName); |
| 128 | if (extractedBinary === null) return null; |
| 129 | |
| 130 | rmSync(binaryPath, { force: true }); |
| 131 | renameSync(extractedBinary, binaryPath); |
| 132 | if (platform() !== 'win32') { |
| 133 | chmodSync(binaryPath, 0o755); |
| 134 | } |
| 135 | return binaryPath; |
| 136 | } finally { |
| 137 | rmSync(extractDir, { recursive: true, force: true }); |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | function verifyArchive(path: string, expectedSha256: string): void { |
| 142 | const actualSha256 = createHash('sha256').update(readFileSync(path)).digest('hex'); |
no test coverage detected