diff options
| author | 2026-01-18 12:16:05 +0800 | |
|---|---|---|
| committer | 2026-01-18 12:16:05 +0800 | |
| commit | 079ee0a6611499db68d1eb4894fab64739d5d2e7 (patch) | |
| tree | f7cab9f6dded91a25a16f85a3e99f6299ea5a0a1 /src-tauri/src/core | |
| parent | 16047ca6aa8eea7f5495e938faebb01bf96d09de (diff) | |
| download | DropOut-079ee0a6611499db68d1eb4894fab64739d5d2e7.tar.gz DropOut-079ee0a6611499db68d1eb4894fab64739d5d2e7.zip | |
fix(instance): copy directory BEFORE creating metadata in duplicate_instance
Prevent race condition in duplicate_instance by copying the source
game directory BEFORE creating and saving the new instance metadata.
This ensures that if the copy fails, no orphaned metadata is created.
Also copy the icon_path from source instance to maintain visual consistency.
Diffstat (limited to 'src-tauri/src/core')
| -rw-r--r-- | src-tauri/src/core/instance.rs | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/src-tauri/src/core/instance.rs b/src-tauri/src/core/instance.rs index 90ec34e..738dbd8 100644 --- a/src-tauri/src/core/instance.rs +++ b/src-tauri/src/core/instance.rs @@ -218,21 +218,42 @@ impl InstanceState { .get_instance(id) .ok_or_else(|| format!("Instance {} not found", id))?; - // Create new instance - let mut new_instance = self.create_instance(new_name, app_handle)?; - - // Copy instance properties - new_instance.version_id = source_instance.version_id.clone(); - new_instance.mod_loader = source_instance.mod_loader.clone(); - new_instance.mod_loader_version = source_instance.mod_loader_version.clone(); - new_instance.notes = source_instance.notes.clone(); - - // Copy directory contents + // Prepare new instance metadata (but don't save yet) + let new_id = uuid::Uuid::new_v4().to_string(); + let instances_dir = app_handle + .path() + .app_data_dir() + .map_err(|e| e.to_string())? + .join("instances"); + let new_game_dir = instances_dir.join(&new_id); + + // Copy directory FIRST - if this fails, don't create metadata if source_instance.game_dir.exists() { - copy_dir_all(&source_instance.game_dir, &new_instance.game_dir) + copy_dir_all(&source_instance.game_dir, &new_game_dir) .map_err(|e| format!("Failed to copy instance directory: {}", e))?; + } else { + // If source dir doesn't exist, create new empty game dir + std::fs::create_dir_all(&new_game_dir) + .map_err(|e| format!("Failed to create instance directory: {}", e))?; } + // NOW create metadata and save + let new_instance = Instance { + id: new_id, + name: new_name, + game_dir: new_game_dir, + version_id: source_instance.version_id.clone(), + mod_loader: source_instance.mod_loader.clone(), + mod_loader_version: source_instance.mod_loader_version.clone(), + notes: source_instance.notes.clone(), + icon_path: source_instance.icon_path.clone(), + created_at: std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs() as i64, + last_played: None, + }; + self.update_instance(new_instance.clone())?; Ok(new_instance) |