72 lines
2.3 KiB
JavaScript
72 lines
2.3 KiB
JavaScript
#!/usr/bin/env node
|
|
import { access, mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import { createStaticArchive } from './archive.mjs';
|
|
import { sha256File } from './artifact.mjs';
|
|
import {
|
|
assertSafeRemovalTarget,
|
|
canonicalExistingPath,
|
|
canonicalPathsOverlap,
|
|
} from './path-safety.mjs';
|
|
import { publishStagedTargets } from './publication.mjs';
|
|
|
|
function argument(name, fallback) {
|
|
const index = process.argv.indexOf(name);
|
|
return index >= 0 ? process.argv[index + 1] : fallback;
|
|
}
|
|
|
|
const input = await canonicalExistingPath(
|
|
argument('--input', 'build/toolbox'),
|
|
'Static archive input'
|
|
);
|
|
const output = await assertSafeRemovalTarget(
|
|
argument('--output', 'artifacts/add-ideas-toolbox-static.zip')
|
|
);
|
|
const checksumOutput = await assertSafeRemovalTarget(`${output}.sha256`);
|
|
const force = process.argv.includes('--force');
|
|
|
|
if (path.extname(output).toLocaleLowerCase() !== '.zip')
|
|
throw new Error('Archive output must use a .zip extension.');
|
|
if (canonicalPathsOverlap(output, input))
|
|
throw new Error('Archive output and input directory must not overlap.');
|
|
|
|
const outputExists = await access(output).then(
|
|
() => true,
|
|
() => false
|
|
);
|
|
const checksumExists = await access(checksumOutput).then(
|
|
() => true,
|
|
() => false
|
|
);
|
|
if (outputExists && !force)
|
|
throw new Error(
|
|
`Archive already exists (use --force to replace it): ${output}`
|
|
);
|
|
if (checksumExists && !force)
|
|
throw new Error(
|
|
`Checksum already exists (use --force to replace it): ${checksumOutput}`
|
|
);
|
|
await mkdir(path.dirname(output), { recursive: true });
|
|
const staging = await mkdtemp(
|
|
path.join(path.dirname(output), '.toolbox-package-')
|
|
);
|
|
const stagedArchive = path.join(staging, path.basename(output));
|
|
const stagedChecksum = `${stagedArchive}.sha256`;
|
|
try {
|
|
await createStaticArchive(input, stagedArchive);
|
|
const checksum = await sha256File(stagedArchive);
|
|
await writeFile(stagedChecksum, `${checksum} ${path.basename(output)}\n`, {
|
|
flag: 'wx',
|
|
});
|
|
await publishStagedTargets(
|
|
[
|
|
{ staged: stagedArchive, target: output },
|
|
{ staged: stagedChecksum, target: checksumOutput },
|
|
],
|
|
{ force }
|
|
);
|
|
} finally {
|
|
await rm(staging, { recursive: true, force: true });
|
|
}
|
|
process.stdout.write(`Created ${output}\nChecksum: ${checksumOutput}\n`);
|