Files
Git-Manager-Gui/scripts/build-setup.js
T
2026-10-22 07:15:59 +00:00

118 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'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);
}