UNPKG

@gitkraken/gk

Version:

gk is GitKraken on the command line. It makes working across multiple repos easier with Workspaces, provides access to pull requests and issues from multiple services (GitHub, GitLab, Bitbucket, etc.), and seamlessly connects with GitKraken Client and Git

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, };