feat(desktop): self-update appimages in place (#2843)

This commit is contained in:
Hampus authored and GitHub committed 2026-09-19 19:06:53 +02:00
1 parent 98a42f612b
commit c4f0b2ece0
20 files changed
+2210 -57

No files matched your search

+52 -11
View File
@@ -1,16 +1,57 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
export function getStableLinuxLaunchPath(): string {
if (process.platform === 'linux') {
const appImage = process.env.APPIMAGE;
if (appImage && appImage.length > 0) return appImage;
}
return process.execPath;
import {spawn} from 'node:child_process';
import {existsSync} from 'node:fs';
import {homedir} from 'node:os';
import {createChildLogger} from '@electron/common/Logger';
import {app} from 'electron';
const logger = createChildLogger('LinuxLaunchPath');
const PREFERRED_RELAUNCH_SHELL = '/bin/bash';
const FALLBACK_RELAUNCH_SHELL = '/bin/sh';
const RELAUNCH_AFTER_EXIT =
'pid="$1"; app="$2"; home="$3"; shift 3; cd /proc/self/fd && for n in *; do case "$n" in 0|1|2) ;; [0-9]) eval "exec $n>&-";; *) [ -n "$BASH_VERSION" ] && eval "exec $n>&-";; esac; done; cd "$home" || cd /; attempt=0; while [ "$attempt" -lt 300 ] && kill -0 "$pid"; do sleep 0.1; attempt=$((attempt + 1)); done; kill -0 "$pid" || exec "$app" "$@"';
function getAppImagePath(): string | null {
if (process.platform !== 'linux') return null;
const appImage = process.env.APPIMAGE;
return appImage && appImage.length > 0 ? appImage : null;
}
export function getStableRelaunchOptions(): {execPath: string} | undefined {
if (process.platform !== 'linux') return undefined;
const execPath = getStableLinuxLaunchPath();
if (execPath === process.execPath) return undefined;
return {execPath};
export function getStableLinuxLaunchPath(): string {
return getAppImagePath() ?? process.execPath;
}
export function relaunchStableLaunchPath(): void {
const appImagePath = getAppImagePath();
if (appImagePath == null) {
app.relaunch();
return;
}
try {
const child = spawn(
existsSync(PREFERRED_RELAUNCH_SHELL) ? PREFERRED_RELAUNCH_SHELL : FALLBACK_RELAUNCH_SHELL,
[
'-c',
RELAUNCH_AFTER_EXIT,
'fluxer-relaunch',
String(process.pid),
appImagePath,
homedir(),
...process.argv.slice(1),
],
{
cwd: homedir(),
detached: true,
stdio: 'ignore',
},
);
child.unref();
logger.info('Relaunching the AppImage once this process exits', {path: appImagePath, pid: child.pid});
} catch (error) {
logger.error('Failed to start the AppImage replacement process', {error});
app.relaunch({execPath: appImagePath});
}
}