fix: Implement two-stage update system to handle file-in-use errors

Replace direct file overwriting with a staging-based update mechanism to
resolve "file in use" errors during self-updates.

**Changes:**
- Stage updates to temporary directory instead of direct installation
- Apply staged updates on next application startup (before files are loaded)
- Add static methods for startup update detection and application
- Create update manifest to track staged update metadata
- Backup existing files before applying updates
- Update UI messaging to reflect staged update workflow

**Problem solved:**
The previous direct file replacement approach failed when trying to overwrite
DLLs and executables that were loaded into memory by the running process.
This two-stage approach stages files safely, then applies them on restart
when no files are in use.

**Workflow:**
1. Download and extract update to staging directory
2. Create manifest with update metadata
3. Show "Update ready" message to user
4. On next app startup: detect staged update, apply it, show success message
5. Clean up staging directory after successful application

This ensures reliable self-updates without file access conflicts.

Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
Zephyron
2025-07-11 17:01:37 +10:00
parent 5472256a2d
commit 00c3e7aea5
4 changed files with 142 additions and 16 deletions

View File

@@ -271,8 +271,8 @@ void UpdaterDialog::ShowInstallingState() {
void UpdaterDialog::ShowCompletedState() {
current_state = State::Completed;
ui->titleLabel->setText(QStringLiteral("Update completed!"));
ui->statusLabel->setText(QStringLiteral("The update has been installed successfully. Please restart Citron to use the new version."));
ui->titleLabel->setText(QStringLiteral("Update ready!"));
ui->statusLabel->setText(QStringLiteral("The update has been downloaded and prepared successfully. The update will be applied when you restart Citron."));
ui->progressGroup->setVisible(false);