This commit is contained in:
2025-11-08 19:29:39 +01:00
parent 5710d87295
commit b5aa11c46b
@@ -1,5 +1,5 @@
use std::{ use std::{
collections::{HashMap, HashSet}, collections::HashSet,
net::SocketAddr, net::SocketAddr,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Arc, sync::Arc,
@@ -21,8 +21,6 @@ struct LanSpreadState {
games: Arc<RwLock<GameDB>>, games: Arc<RwLock<GameDB>>,
games_in_download: Arc<RwLock<HashSet<String>>>, games_in_download: Arc<RwLock<HashSet<String>>>,
games_folder: Arc<RwLock<String>>, games_folder: Arc<RwLock<String>>,
// Track backup paths for games being updated
game_backups: Arc<RwLock<HashMap<String, PathBuf>>>,
} }
#[tauri::command] #[tauri::command]
@@ -156,16 +154,6 @@ fn update_game(id: String, state: tauri::State<LanSpreadState>) -> bool {
} }
}; };
// Store backup path for later cleanup/restore
tauri::async_runtime::block_on(async {
state
.inner()
.game_backups
.write()
.await
.insert(id.clone(), backup_path.clone());
});
log::info!("Starting update for game: {id}"); log::info!("Starting update for game: {id}");
// Start the download process // Start the download process
@@ -180,6 +168,7 @@ fn update_game(id: String, state: tauri::State<LanSpreadState>) -> bool {
if let Err(restore_err) = restore_game_folder(&game_path, &backup_path) { if let Err(restore_err) = restore_game_folder(&game_path, &backup_path) {
log::error!("Failed to restore backup after download failure: {restore_err}"); log::error!("Failed to restore backup after download failure: {restore_err}");
} }
return false; return false;
} }
@@ -470,7 +459,7 @@ async fn do_unrar(sidecar: Command, rar_file: &Path, dest_dir: &Path) -> eyre::R
bail!("failed to create directory: {dest_dir:?}"); bail!("failed to create directory: {dest_dir:?}");
} }
async fn unpack_game(id: &str, sidecar: Command, games_folder: String) { async fn unpack_game(id: &str, sidecar: Command, games_folder: &str) {
let game_path = PathBuf::from(games_folder).join(id); let game_path = PathBuf::from(games_folder).join(id);
let eti_rar = game_path.join(format!("{id}.eti")); let eti_rar = game_path.join(format!("{id}.eti"));
let local_path = game_path.join("local"); let local_path = game_path.join("local");
@@ -506,7 +495,6 @@ pub fn run() {
games: Arc::new(RwLock::new(GameDB::empty())), games: Arc::new(RwLock::new(GameDB::empty())),
games_in_download: Arc::new(RwLock::new(HashSet::new())), games_in_download: Arc::new(RwLock::new(HashSet::new())),
games_folder: Arc::new(RwLock::new(String::new())), games_folder: Arc::new(RwLock::new(String::new())),
game_backups: Arc::new(RwLock::new(std::collections::HashMap::new())),
}; };
tauri::Builder::default() tauri::Builder::default()
@@ -597,30 +585,24 @@ pub fn run() {
.clone(); .clone();
if let Ok(sidecar) = app_handle.shell().sidecar("unrar") { if let Ok(sidecar) = app_handle.shell().sidecar("unrar") {
let _games_folder_clone = games_folder.clone();
let id_clone = id.clone(); let app_handle = app_handle.clone();
let app_handle_clone = app_handle.clone();
// Spawn a separate task to handle unpacking and backup cleanup // Spawn a separate task to handle unpacking and backup cleanup
tauri::async_runtime::spawn(async move { tauri::async_runtime::spawn(async move {
unpack_game(&id, sidecar, games_folder).await; unpack_game(&id, sidecar, &games_folder).await;
// Check if this was an update and clean up backup if successful if !games_folder.is_empty() {
let backup_path = app_handle_clone let backup_name = format!("___TO_BE_DELETE___{id}");
.state::<LanSpreadState>() let backup_path = PathBuf::from(games_folder).join(backup_name);
.inner()
.game_backups
.write()
.await
.remove(&id_clone);
if let Some(backup_path) = backup_path if let Err(e) = cleanup_backup_folder(&backup_path) {
&& let Err(e) = cleanup_backup_folder(&backup_path) {
log::error!("Failed to cleanup backup folder after successful update: {e}"); log::error!("Failed to cleanup backup folder after successful update: {e}");
} }
}
log::info!("ClientEvent::UnpackGameFinished received"); log::info!("ClientEvent::UnpackGameFinished received");
if let Err(e) = app_handle_clone.emit("game-unpack-finished", Some(id_clone.clone())) { if let Err(e) = app_handle.emit("game-unpack-finished", Some(id.clone())) {
log::error!("ClientEvent::UnpackGameFinished: Failed to emit game-unpack-finished event: {e}"); log::error!("ClientEvent::UnpackGameFinished: Failed to emit game-unpack-finished event: {e}");
} }
}); });
@@ -641,16 +623,8 @@ pub fn run() {
.await .await
.remove(&id.clone()); .remove(&id.clone());
// Check if this was an update and restore backup if failed // Check if a backup exists and restore from backup if failed
let backup_path = app_handle // The backup folder name follows the pattern: ___TO_BE_DELETE___{game_name}
.state::<LanSpreadState>()
.inner()
.game_backups
.write()
.await
.remove(&id);
if let Some(backup_path) = backup_path {
let games_folder = app_handle let games_folder = app_handle
.state::<LanSpreadState>() .state::<LanSpreadState>()
.inner() .inner()
@@ -659,7 +633,21 @@ pub fn run() {
.await .await
.clone(); .clone();
let game_path = PathBuf::from(games_folder).join(&id); if !games_folder.is_empty() {
let backup_name = format!("___TO_BE_DELETE___{id}");
let backup_path = PathBuf::from(&games_folder).join(backup_name);
let game_path = PathBuf::from(&games_folder).join(&id);
// Delete the half-downloaded game folder if it exists
if game_path.exists() {
if let Err(e) = std::fs::remove_dir_all(&game_path) {
log::error!("Failed to delete half-downloaded game folder: {e}");
} else {
log::info!("Deleted half-downloaded game folder: {}", game_path.display());
}
}
// Restore the backup
if let Err(e) = restore_game_folder(&game_path, &backup_path) { if let Err(e) = restore_game_folder(&game_path, &backup_path) {
log::error!("Failed to restore backup after download failure: {e}"); log::error!("Failed to restore backup after download failure: {e}");
} }