Updater (pacman): pkexec mit absolutem Pfad; bei fehlendem Polkit-Agent/abgebrochener Abfrage (126/127) Installation per sudo im Terminal

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-25 18:27:26 +02:00
co-authored by Claude Opus 5.5
parent d53bd1a4c1
commit 0cefd5a21f
+40 -6
View File
@@ -7,7 +7,40 @@ const os = require('os');
const path = require('path'); const path = require('path');
const i18n = require('../i18n'); 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) { function parseRepo(url) {
const u = new URL((url || DEFAULT_REPO).replace(/\.git$/, '').replace(/\/+$/, '')); const u = new URL((url || DEFAULT_REPO).replace(/\.git$/, '').replace(/\/+$/, ''));
@@ -134,11 +167,12 @@ class Updater {
app.relaunch({ execPath: target }); app.relaunch({ execPath: target });
app.exit(0); app.exit(0);
} else if (kind === 'pacman' && /\.(pacman|pkg\.tar\.zst)$/.test(file)) { } else if (kind === 'pacman' && /\.(pacman|pkg\.tar\.zst)$/.test(file)) {
await new Promise((resolve, reject) => { // 1. pkexec (grafische Passwortabfrage über den Polkit-Agent)
const p = spawn('pkexec', ['pacman', '-U', '--noconfirm', file], { stdio: 'ignore' }); let code = await run('pkexec', ['/usr/bin/pacman', '-U', '--noconfirm', file]);
p.on('error', reject); // 126/127 = Abfrage abgebrochen bzw. kein Polkit-Agent → Terminal mit sudo öffnen
p.on('exit', (c) => (c === 0 ? resolve() : reject(new Error(i18n.t('pacman exited with code {code}', { code: c }))))); 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.relaunch();
app.exit(0); app.exit(0);
} else { } else {