* On Linux AppImage, process.resourcesPath resolves to an ephemeral mount point * (/tmp/.mount_Modly-XXXXXX/) that changes every launch, which breaks venv symlinks. * This copies the bundled Python runtime to a stable userData path once per app version.
(userData: string, win: BrowserWindow)
| 159 | * This copies the bundled Python runtime to a stable userData path once per app version. |
| 160 | */ |
| 161 | async function ensureStableEmbeddedPython(userData: string, win: BrowserWindow): Promise<string> { |
| 162 | const stableDir = join(userData, 'python-embed') |
| 163 | const stableExe = join(stableDir, 'bin', 'python3') |
| 164 | const versionFile = join(stableDir, '.app-version') |
| 165 | const currentVersion = app.getVersion() |
| 166 | |
| 167 | const alreadyCopied = |
| 168 | existsSync(stableExe) && |
| 169 | existsSync(versionFile) && |
| 170 | readFileSync(versionFile, 'utf-8').trim() === currentVersion |
| 171 | |
| 172 | if (!alreadyCopied) { |
| 173 | win.webContents.send('setup:progress', { step: 'venv', percent: 2 }) |
| 174 | console.log('[PythonSetup] Extracting Python runtime to stable path:', stableDir) |
| 175 | if (existsSync(stableDir)) { |
| 176 | await rm(stableDir, { recursive: true, force: true }) |
| 177 | } |
| 178 | await mkdir(stableDir, { recursive: true }) |
| 179 | await cp(getEmbeddedPythonDir(), stableDir, { recursive: true, preserveTimestamps: true }) |
| 180 | writeFileSync(versionFile, currentVersion, 'utf-8') |
| 181 | console.log('[PythonSetup] Python runtime ready at:', stableDir) |
| 182 | } |
| 183 | |
| 184 | return stableExe |
| 185 | } |
| 186 | |
| 187 | // ─── Setup steps ───────────────────────────────────────────────────────────── |
| 188 |
no test coverage detected