diff --git a/src/main/updater.js b/src/main/updater.js index 2fec910..ccf46a9 100644 --- a/src/main/updater.js +++ b/src/main/updater.js @@ -7,7 +7,40 @@ const os = require('os'); const path = require('path'); const i18n = require('../i18n'); -const DEFAULT_REPO = 'https://git.mrblake.cc/MrBlake/MrTerm'; +// Startet ein Programm und liefert den Exit-Code ('ENOENT', falls es nicht existiert) +function run(cmd, args) { + return new Promise((resolve) => { + const p = spawn(cmd, args, { stdio: 'ignore' }); + p.on('error', (e) => resolve(e.code === 'ENOENT' ? 'ENOENT' : e.message)); + p.on('exit', (c) => resolve(c)); + }); +} + +// Fallback ohne Polkit-Agent: pacman -U per sudo in einem Terminalfenster; wartet, bis das Fenster geschlossen ist. +// Der Erfolg wird über eine Marker-Datei erkannt, da nicht jedes Terminal den Exit-Code durchreicht. +async function installInTerminal(file) { + const q = (s) => `'${String(s).replace(/'/g, `'\\''`)}'`; + const marker = file + '.ok'; + try { fs.unlinkSync(marker); } catch {} + const script = `sudo /usr/bin/pacman -U --noconfirm ${q(file)} && touch ${q(marker)} || { echo; read -rp "[Enter]"; }`; + const terms = [ + ['konsole', ['--nofork', '-e', 'bash', '-c', script]], + ['gnome-terminal', ['--wait', '--', 'bash', '-c', script]], + ['kitty', ['bash', '-c', script]], + ['alacritty', ['-e', 'bash', '-c', script]], + ['foot', ['bash', '-c', script]], + ['xfce4-terminal', ['--disable-server', '-x', 'bash', '-c', script]], + ['xterm', ['-e', 'bash', '-c', script]], + ]; + for (const [cmd, args] of terms) { + const c = await run(cmd, args); + if (c === 'ENOENT') continue; + return fs.existsSync(marker) ? 0 : c || 1; + } + return 'ENOENT'; +} + +const DEFAULT_REPO ='https://git.mrblake.cc/MrBlake/MrTerm'; function parseRepo(url) { const u = new URL((url || DEFAULT_REPO).replace(/\.git$/, '').replace(/\/+$/, '')); @@ -134,11 +167,12 @@ class Updater { app.relaunch({ execPath: target }); app.exit(0); } else if (kind === 'pacman' && /\.(pacman|pkg\.tar\.zst)$/.test(file)) { - await new Promise((resolve, reject) => { - const p = spawn('pkexec', ['pacman', '-U', '--noconfirm', file], { stdio: 'ignore' }); - p.on('error', reject); - p.on('exit', (c) => (c === 0 ? resolve() : reject(new Error(i18n.t('pacman exited with code {code}', { code: c }))))); - }); + // 1. pkexec (grafische Passwortabfrage über den Polkit-Agent) + let code = await run('pkexec', ['/usr/bin/pacman', '-U', '--noconfirm', file]); + // 126/127 = Abfrage abgebrochen bzw. kein Polkit-Agent → Terminal mit sudo öffnen + if (code === 126 || code === 127 || code === 'ENOENT') code = await installInTerminal(file); + if (code === 'ENOENT') throw new Error(i18n.t('Automatic installation is not possible here. The file is located at: {file}', { file })); + if (code !== 0) throw new Error(i18n.t('pacman exited with code {code}', { code })); app.relaunch(); app.exit(0); } else {