UNPKG

@goreleaser/goreleaser-pro

Version:

Release engineering, simplified.

260 lines (232 loc) 6.32 kB
// This file was generated by GoReleaser. DO NOT EDIT. import fs from "fs"; import crypto from "crypto"; import http from "http"; import https from "https"; import path from "path"; import JSZip from "jszip"; import { x as tarExtract } from "tar"; import { ProxyAgent } from "proxy-agent"; import { spawnSync } from "child_process"; import { fileURLToPath } from "url"; const { archives, name, version } = JSON.parse( fs.readFileSync(new URL("./package.json", import.meta.url), "utf8"), ); const agent = new ProxyAgent(); const __dirname = path.dirname(fileURLToPath(import.meta.url)); const getArchive = () => { let target = `${process.platform}-${process.arch}`; const archive = archives[target]; if (!archive) { throw new Error(`No archive available for ${target}`); } return archive; }; const binDir = path.join(__dirname, "bin"); async function extractTar(tarPath, binaries, dir, wrappedIn) { try { const filesToExtract = wrappedIn ? binaries.map((bin) => path.join(wrappedIn, bin).replace(/\\/g, "/"), ) : binaries; await tarExtract({ file: tarPath, cwd: dir, filter: (path) => filesToExtract.includes(path), }); // If wrapped, move files from wrapped directory to bin directory if (wrappedIn) { const wrappedDir = path.join(dir, wrappedIn); for (const binary of binaries) { const srcPath = path.join(wrappedDir, binary); const destPath = path.join(dir, binary); if (fs.existsSync(srcPath)) { fs.renameSync(srcPath, destPath); } } // Clean up empty wrapped directory try { fs.rmSync(wrappedDir, { recursive: true, force: true }); } catch (err) { // Ignore cleanup errors } } console.log(`Successfully extracted ${binaries} to "${dir}"`); } catch (err) { throw new Error(`Extraction failed: ${err.message}`); } } async function extractZip(zipPath, binaries, dir, wrappedIn) { try { const zipData = fs.readFileSync(zipPath); const zip = await JSZip.loadAsync(zipData); for (const binary of binaries) { const binaryPath = wrappedIn ? path.join(wrappedIn, binary).replace(/\\/g, "/") : binary; if (!zip.files[binaryPath]) { throw new Error( `Error: ${binaryPath} does not exist in ${zipPath}`, ); } const content = await zip.files[binaryPath].async("nodebuffer"); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } const file = path.join(dir, binary); fs.writeFileSync(file, content); fs.chmodSync(file, "755"); console.log(`Successfully extracted "${binary}" to "${dir}"`); } } catch (err) { throw new Error(`Extraction failed: ${err.message}`); } } const run = async (bin) => { await install(); if (process.platform === "win32") { bin += ".exe"; } const [, , ...args] = process.argv; let result = spawnSync(path.join(binDir, bin), args, { cwd: process.cwd(), stdio: "inherit", }); if (result.error) { console.error(result.error); } return result.status; }; const install = async () => { try { let archive = getArchive(); if (await exists(archive)) { return; } let tmp = fs.mkdtempSync("archive-"); let archivePath = path.join(tmp, archive.name); await download(archive.url, archivePath); verify(archivePath, archive.checksum); if (!fs.existsSync(binDir)) { fs.mkdirSync(binDir); } switch (archive.format) { case "binary": const bin = path.join(binDir, archive.bins[0]); fs.copyFileSync(archivePath, bin); fs.chmodSync(bin, 0o755); break; case "zip": await extractZip( archivePath, archive.bins, binDir, archive.wrappedIn, ); break; case "tar": case "tar.gz": case "tgz": await extractTar( archivePath, archive.bins, binDir, archive.wrappedIn, ); break; case "tar.zst": case "tzst": case "tar.xz": case "txz": default: throw new Error(`unsupported format: ${archive.format}`); } console.log(`Installed ${name} ${version} to ${binDir}`); } catch (err) { throw new Error(`Installation failed: ${err.message}`); } }; const verify = (filename, checksum) => { if (checksum.algorithm == "" || checksum.digest == "") { console.warn("Warning: No checksum provided for verification"); return; } let digest = crypto .createHash(checksum.algorithm) .update(fs.readFileSync(filename)) .digest("hex"); if (digest != checksum.digest) { throw new Error( `${filename}: ${checksum.algorithm} does not match, expected ${checksum.digest}, got ${digest}`, ); } }; const download = async (url, filename, maxRedirects = 10) => { try { console.log(`Downloading ${url} to ${filename}...`); const dir = path.dirname(filename); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } return new Promise((resolve, reject) => { const parsedUrl = new URL(url); const mod = parsedUrl.protocol === "https:" ? https : http; const request = mod.get(url, { agent }, (response) => { if ( response.statusCode >= 300 && response.statusCode < 400 && response.headers.location ) { if (maxRedirects <= 0) { reject(new Error("Too many redirects")); return; } download(response.headers.location, filename, maxRedirects - 1) .then(resolve) .catch(reject); return; } if (response.statusCode !== 200) { reject( new Error( `HTTP ${response.statusCode}: ${response.statusMessage}`, ), ); return; } const writer = fs.createWriteStream(filename); response.pipe(writer); writer.on("finish", () => { console.log(`Download complete: ${filename}`); resolve(dir); }); writer.on("error", (err) => { console.error(`Error writing file: ${err.message}`); reject(err); }); }); request.on("error", (err) => { reject(new Error(`Request failed: ${err.message}`)); }); request.setTimeout(300000, () => { request.destroy(); reject(new Error("Request timed out")); }); }); } catch (err) { throw new Error(`Download failed: ${err.message}`); } }; function exists(archive) { if (!fs.existsSync(binDir)) { return false; } return archive.bins.every((bin) => fs.existsSync(path.join(binDir, bin))); } export { install, run, getArchive, download, };