|
| 1 | +#!/usr/bin/env node |
| 2 | +import { createHash } from "node:crypto"; |
| 3 | +import { createWriteStream, mkdirSync, rmSync } from "node:fs"; |
| 4 | +import { readFile, writeFile } from "node:fs/promises"; |
| 5 | +import { resolve } from "node:path"; |
| 6 | +import { pipeline } from "node:stream/promises"; |
| 7 | +import { spawnSync } from "node:child_process"; |
| 8 | + |
| 9 | +const version = process.argv[2] ?? process.env.INTERSCRIPT_MAPS_VERSION; |
| 10 | +const outDir = resolve( |
| 11 | + process.argv[3] ?? process.env.INTERSCRIPT_MAPS_DIR ?? "maps", |
| 12 | +); |
| 13 | +if (!version) { |
| 14 | + console.error("usage: fetch-maps-artifact.mjs <version> [out-dir]"); |
| 15 | + process.exit(2); |
| 16 | +} |
| 17 | + |
| 18 | +const base = `https://github.com/interscript/maps/releases/download/v${version}`; |
| 19 | +const tarball = `interscript-maps-ir-${version}.tar.gz`; |
| 20 | +const tmp = resolve(`.tmp-${tarball}`); |
| 21 | +const checksumFile = `${tmp}.sha256`; |
| 22 | + |
| 23 | +async function download(url, path) { |
| 24 | + const res = await fetch(url); |
| 25 | + if (!res.ok || !res.body) throw new Error(`${url}: HTTP ${res.status}`); |
| 26 | + await pipeline(res.body, createWriteStream(path)); |
| 27 | +} |
| 28 | + |
| 29 | +await download(`${base}/${tarball}`, tmp); |
| 30 | +await download(`${base}/${tarball}.sha256`, checksumFile); |
| 31 | + |
| 32 | +const expected = (await readFile(checksumFile, "utf8")).trim().split(/\s+/)[0]; |
| 33 | +const actual = createHash("sha256") |
| 34 | + .update(await readFile(tmp)) |
| 35 | + .digest("hex"); |
| 36 | +if (actual !== expected) { |
| 37 | + throw new Error( |
| 38 | + `${tarball}: sha256 mismatch; expected ${expected}, got ${actual}`, |
| 39 | + ); |
| 40 | +} |
| 41 | + |
| 42 | +rmSync(outDir, { recursive: true, force: true }); |
| 43 | +mkdirSync(outDir, { recursive: true }); |
| 44 | +const result = spawnSync("tar", ["-xzf", tmp, "-C", outDir], { |
| 45 | + stdio: "inherit", |
| 46 | +}); |
| 47 | +if (result.status !== 0) process.exit(result.status ?? 1); |
| 48 | + |
| 49 | +const manifest = JSON.parse( |
| 50 | + await readFile(resolve(outDir, "manifest.json"), "utf8"), |
| 51 | +); |
| 52 | +if (manifest.schema !== "interscript.maps.ir.v1") |
| 53 | + throw new Error(`unexpected artifact schema ${manifest.schema}`); |
| 54 | +if (manifest.count !== 289) |
| 55 | + throw new Error(`expected 289 maps, got ${manifest.count}`); |
| 56 | + |
| 57 | +await writeFile(resolve(outDir, ".artifact-version"), `${version}\n`); |
| 58 | +console.log( |
| 59 | + `fetched ${manifest.count} compiled maps (${version}) into ${outDir}`, |
| 60 | +); |
0 commit comments