From 2865e3a47d89384ccaeddc7505fd05a505ead506 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 6 Nov 2026 13:28:09 +0000 Subject: [PATCH] fix: delete downloaded archive after successful install The archive and its partial file were kept until the user cleared the list. Remove them with the stage cleanup once the install is committed; a deletion failure is logged and does not fail the install. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01DGbCKVdcUfJfjZ93bYY9p3 --- src-tauri/src/finalize_install.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src-tauri/src/finalize_install.rs b/src-tauri/src/finalize_install.rs index 13b41f2..f2cf962 100644 --- a/src-tauri/src/finalize_install.rs +++ b/src-tauri/src/finalize_install.rs @@ -487,9 +487,26 @@ fn cleanup_stage(database: &Database, id: &str, stage: &Path) -> Result<(), Stri return clear_staged_path(database, id); } remove_stage_directory(stage)?; + remove_download_files(download_root, id); clear_staged_path(database, id) } +/// The installed game no longer needs its archive. A failure only wastes +/// disk space, so it is logged and never fails the install. +fn remove_download_files(download_root: &Path, id: &str) { + for extension in ["part", "archive"] { + let path = download_root.join(format!("{id}.{extension}")); + match fs::remove_file(&path) { + Ok(()) => {} + Err(error) if error.kind() == io::ErrorKind::NotFound => {} + Err(error) => crate::application_log::failure( + "remove_download_archive", + format!("Could not remove {extension} file: {error}"), + ), + } + } +} + /// Removes an app-owned staging directory. A path that is not a regular /// directory is never deleted so unexpected content stays available. pub(crate) fn remove_stage_directory(stage: &Path) -> Result<(), String> { @@ -808,6 +825,18 @@ mod tests { .unwrap() } + #[test] + fn install_removes_downloaded_archive() { + let (database, data_dir, id) = fixture(); + let downloads = data_dir.join("downloads"); + fs::write(downloads.join(format!("{id}.archive")), b"zip").unwrap(); + fs::write(downloads.join(format!("{id}.part")), b"zi").unwrap(); + finalize(&database, &data_dir, &id, "bin/game.exe").unwrap(); + assert_eq!(state(&database, &id).0, "installed"); + assert!(!downloads.join(format!("{id}.archive")).exists()); + assert!(!downloads.join(format!("{id}.part")).exists()); + } + #[test] fn readable_install_unwraps_game_and_records_library() { let (database, data_dir, id) = fixture();