118 lines
4.5 KiB
JavaScript
118 lines
4.5 KiB
JavaScript
'use strict';
|
||
|
||
/*
|
||
* build-setup.js – eigenes Setup (installer/) mit der App zusammenbauen
|
||
* ---------------------------------------------------------------------
|
||
* Läuft nach "electron-builder --win dir" (siehe "build" in package.json):
|
||
*
|
||
* 1. dist/win-unpacked (die fertige App inkl. eingebautem Git) als ZIP packen
|
||
* 2. installer/ (WPF, .NET Framework 4.8) mit der Version aus package.json bauen
|
||
* 3. ZIP hinten an die Setup-.exe hängen:
|
||
* [Setup.exe][ZIP][8 Byte ZIP-Länge][8 Byte "GITMGRPK"]
|
||
* (das Setup liest den Anhang selbst aus, siehe installer/Payload.cs)
|
||
* 4. SHA-256-Prüfsumme daneben schreiben (der Updater der App prüft sie)
|
||
* 5. Zwischenstände wegräumen → übrig bleibt dist/Git-Manager-GUI-Setup-<version>.exe
|
||
*
|
||
* Benötigt das .NET SDK (dotnet) – das Setup selbst läuft danach auf jedem
|
||
* Windows 10/11 ohne Zusatzinstallation.
|
||
*/
|
||
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const crypto = require('crypto');
|
||
const { execFileSync } = require('child_process');
|
||
|
||
const ROOT = path.join(__dirname, '..');
|
||
const DIST = path.join(ROOT, 'dist');
|
||
const APP_DIR = path.join(DIST, 'win-unpacked');
|
||
const APP_EXE = 'Git Manager GUI.exe';
|
||
const WORK = path.join(DIST, '.setup');
|
||
const ZIP = path.join(WORK, 'app.zip');
|
||
const MAGIC = Buffer.from('GITMGRPK', 'ascii');
|
||
|
||
function schritt(text) {
|
||
console.log(`\n» ${text}`);
|
||
}
|
||
|
||
function sha256(file) {
|
||
const hash = crypto.createHash('sha256');
|
||
const fd = fs.openSync(file, 'r');
|
||
try {
|
||
const buf = Buffer.alloc(8 * 1024 * 1024);
|
||
let n;
|
||
while ((n = fs.readSync(fd, buf, 0, buf.length, null)) > 0) hash.update(buf.subarray(0, n));
|
||
} finally { fs.closeSync(fd); }
|
||
return hash.digest('hex');
|
||
}
|
||
|
||
function main() {
|
||
const version = require(path.join(ROOT, 'package.json')).version;
|
||
const outName = `Git-Manager-GUI-Setup-${version}.exe`;
|
||
const OUT = path.join(DIST, outName);
|
||
|
||
if (!fs.existsSync(path.join(APP_DIR, APP_EXE))) {
|
||
throw new Error(`${APP_DIR}\\${APP_EXE} fehlt – vorher "electron-builder --win dir" ausführen.`);
|
||
}
|
||
if (!fs.existsSync(path.join(APP_DIR, 'resources', 'mingit', 'cmd', 'git.exe'))) {
|
||
throw new Error('Eingebautes Git fehlt in resources/mingit – extraResources in package.json prüfen.');
|
||
}
|
||
fs.rmSync(WORK, { recursive: true, force: true });
|
||
fs.mkdirSync(WORK, { recursive: true });
|
||
|
||
schritt('App wird gepackt …');
|
||
// .NET-ZIP über PowerShell: in jedem Windows enthalten, keine zusätzliche npm-Abhängigkeit
|
||
const ps = [
|
||
'Add-Type -AssemblyName System.IO.Compression.FileSystem',
|
||
`[System.IO.Compression.ZipFile]::CreateFromDirectory('${APP_DIR.replace(/'/g, "''")}', '${ZIP.replace(/'/g, "''")}', [System.IO.Compression.CompressionLevel]::Optimal, $false)`,
|
||
].join('; ');
|
||
execFileSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', ps], { stdio: 'inherit' });
|
||
|
||
schritt(`Setup ${version} wird gebaut …`);
|
||
const stubDir = path.join(WORK, 'stub');
|
||
execFileSync('dotnet', [
|
||
'build', path.join(ROOT, 'installer', 'GitManagerSetup.csproj'),
|
||
'-c', 'Release', `-p:Version=${version}`, '-p:DebugType=none',
|
||
'--nologo', '-v', 'q', '-o', stubDir,
|
||
], { stdio: 'inherit' });
|
||
const stub = path.join(stubDir, 'Git-Manager-GUI-Setup.exe');
|
||
if (!fs.existsSync(stub)) throw new Error('Build des Setups fehlgeschlagen.');
|
||
|
||
schritt('App wird ans Setup angehängt …');
|
||
const zipSize = fs.statSync(ZIP).size;
|
||
const footer = Buffer.alloc(16);
|
||
footer.writeBigInt64LE(BigInt(zipSize), 0);
|
||
MAGIC.copy(footer, 8);
|
||
fs.rmSync(OUT, { force: true });
|
||
fs.copyFileSync(stub, OUT);
|
||
// ZIP in Blöcken anhängen statt komplett in den Speicher zu laden
|
||
const fd = fs.openSync(OUT, 'a');
|
||
try {
|
||
const src = fs.openSync(ZIP, 'r');
|
||
try {
|
||
const buf = Buffer.alloc(8 * 1024 * 1024);
|
||
let n;
|
||
while ((n = fs.readSync(src, buf, 0, buf.length, null)) > 0) fs.writeSync(fd, buf, 0, n);
|
||
} finally { fs.closeSync(src); }
|
||
fs.writeSync(fd, footer);
|
||
} finally { fs.closeSync(fd); }
|
||
|
||
schritt('Prüfsumme wird geschrieben …');
|
||
const sum = sha256(OUT);
|
||
fs.writeFileSync(`${OUT}.sha256`, `${sum} ${outName}\n`);
|
||
|
||
schritt('Aufräumen …');
|
||
for (const t of [WORK, APP_DIR, path.join(DIST, 'builder-debug.yml'), path.join(DIST, 'builder-effective-config.yaml')]) {
|
||
fs.rmSync(t, { recursive: true, force: true });
|
||
}
|
||
|
||
const mb = (fs.statSync(OUT).size / 1024 / 1024).toFixed(1);
|
||
console.log(`\nFertig: ${OUT} (${mb} MB)\nSHA-256: ${sum}`);
|
||
}
|
||
|
||
try {
|
||
main();
|
||
} catch (err) {
|
||
console.error(`\nFehler: ${err.message}`);
|
||
process.exit(1);
|
||
}
|