Upload via GUI (28 Dateien)

This commit is contained in:
2026-10-22 07:15:59 +00:00
parent 99d9629e25
commit 9b3aed6f0a
15 changed files with 4286 additions and 222 deletions
+117
View File
@@ -0,0 +1,117 @@
'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);
}