From 9c0e47987cdeb5bfba2693e7fd44067ce8c89c87 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Sun, 16 Jul 2023 19:13:19 +0200 Subject: [PATCH 01/25] feat: Initial support for reading NS packages dir --- src-tauri/src/mod_management/mod.rs | 200 +++++++++++++++++++++++++++- 1 file changed, 196 insertions(+), 4 deletions(-) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index a2aca85a0..2ca613ca9 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -4,15 +4,17 @@ use crate::constants::{BLACKLISTED_MODS, CORE_MODS}; use async_recursion::async_recursion; use crate::NorthstarMod; -use anyhow::Result; +use anyhow::{anyhow, Result}; use serde::{Deserialize, Serialize}; +use std::str::FromStr; +use std::string::ToString; use std::{fs, path::PathBuf}; mod legacy; use crate::GameInstall; #[derive(Debug, Clone)] -struct ParsedThunderstoreModString { +pub struct ParsedThunderstoreModString { author_name: String, mod_name: String, version: String, @@ -22,6 +24,12 @@ impl std::str::FromStr for ParsedThunderstoreModString { type Err = &'static str; // todo use an better error management fn from_str(s: &str) -> Result { + // Check whether Thunderstore string passse reges + let re = regex::Regex::new(r"^[a-zA-Z0-9_]+-[a-zA-Z0-9_]+-\d+\.\d+\.\d++$").unwrap(); + if !re.is_match(s) { + return Err("Incorrect format"); + } + let mut parts = s.split('-'); let author_name = parts.next().ok_or("None value on author_name")?.to_string(); @@ -36,6 +44,12 @@ impl std::str::FromStr for ParsedThunderstoreModString { } } +impl ToString for ParsedThunderstoreModString { + fn to_string(&self) -> String { + format!("{}-{}-{}", self.author_name, self.mod_name, self.version) + } +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ThunderstoreManifest { name: String, @@ -170,6 +184,175 @@ pub fn set_mod_enabled_status( Ok(()) } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ModJson { + #[serde(rename = "Name")] + name: String, + #[serde(rename = "Version")] + version: Option, +} + +/// Parse `mods` folder for installed mods. +pub fn parse_mods_in_package( + package_mods_path: PathBuf, + thunderstore_mod_string: ParsedThunderstoreModString, +) -> Result, anyhow::Error> { + dbg!(package_mods_path.clone()); + let paths = match std::fs::read_dir(package_mods_path) { + Ok(paths) => paths, + Err(_err) => return Err(anyhow!("No mods folder found")), + }; + + let mut directories: Vec = Vec::new(); + let mut mods: Vec = Vec::new(); + + log::info!("----------- {paths:?}"); + + // Get list of folders in `mods` directory + for path in paths { + // dbg!(path); + log::info!("{path:?}"); + let my_path = path.unwrap().path(); + log::info!("{my_path:?}"); + + let md = std::fs::metadata(my_path.clone()).unwrap(); + if md.is_dir() { + directories.push(my_path); + } + } + + dbg!(directories.clone()); + // todo!(); + // Iterate over folders and check if they are Northstar mods + for directory in directories { + let directory_str = directory.to_str().unwrap().to_string(); + // Check if mod.json exists + let mod_json_path = format!("{}/mod.json", directory_str); + if !std::path::Path::new(&mod_json_path).exists() { + continue; + } + + // Parse mod.json and get mod name + + // Read file into string and parse it + let data = std::fs::read_to_string(mod_json_path.clone())?; + let parsed_mod_json: ModJson = match json5::from_str(&data) { + Ok(parsed_json) => parsed_json, + Err(err) => { + log::warn!("Failed parsing {} with {}", mod_json_path, err.to_string()); + continue; + } + }; + + // Get directory path + let mod_directory = directory.to_str().unwrap().to_string(); + + let ns_mod = NorthstarMod { + name: parsed_mod_json.name, + version: parsed_mod_json.version, + thunderstore_mod_string: Some(thunderstore_mod_string.to_string()), + enabled: false, // Placeholder + directory: mod_directory, + }; + + mods.push(ns_mod); + } + + // Return found mod names + Ok(mods) +} + +/// Parse `packages` folder for installed mods. +pub fn parse_installed_package_mods( + game_install: &GameInstall, +) -> Result, anyhow::Error> { + let mut collected_mods: Vec = Vec::new(); + + let packages_folder = format!("{}/R2Northstar/packages/", game_install.game_path); + + let packages_dir = match fs::read_dir(packages_folder) { + Ok(res) => res, + Err(err) => { + // We couldn't read directory, probably cause it doesn't exist yet. + // In that case we just say no package mods installed. + log::warn!("{err}"); + return Ok(vec![]); + } + }; + + // Iteratore over folders in `packages` dir + for entry in packages_dir { + let entry = entry?; + let entry_path = entry.path(); + let entry_str = entry_path.file_name().unwrap().to_str().unwrap(); + log::warn!("Trying: {entry_str}"); + + // Use the struct's from_str function to verify format + if entry_path.is_dir() { + let package_thunderstore_string = match ParsedThunderstoreModString::from_str(entry_str) + { + Ok(res) => res, + Err(err) => { + log::warn!( + "Not a Thunderstore mod string \"{}\" cause: {}", + entry_path.display(), + err + ); + continue; + } + }; + let manifest_path = entry_path.join("manifest.json"); + let mods_path = entry_path.join("mods"); + + // Ensure `manifest.json` and `mods/` dir exist + if manifest_path.exists() && mods_path.is_dir() { + dbg!(mods_path.clone()); + + // Do something with mod path here + log::warn!("{}", mods_path.to_string_lossy()); + + // let paths = match std::fs::read_dir(mods_path) { + // Ok(paths) => paths, + // Err(_err) => todo!(), + // }; + + // // Get list of folders in `mods` directory + // for path in paths { + // log::info!("{path:?}"); + // let my_path = path.unwrap().path(); + // log::info!("{my_path:?}"); + + // let md = std::fs::metadata(my_path.clone()).unwrap(); + // if !md.is_dir() { + // continue; + // } + log::warn!("Found: {}", mods_path.display()); + let mods = + match parse_mods_in_package(mods_path, package_thunderstore_string.clone()) { + Ok(res) => res, + Err(err) => { + log::warn!("Failed parsing cause: {err}"); + continue; + } + }; + dbg!(mods.clone()); + collected_mods.extend(mods); + // } + + // let ns_mod = NorthstarMod { + // name: parsed_mod_json.name, + // version: parsed_mod_json.version, + // thunderstore_mod_string, + // enabled: false, // Placeholder + // directory: mod_directory, + // }; + } + } + } + + Ok(collected_mods) +} + /// Gets list of installed mods and their properties /// - name /// - is enabled? @@ -177,12 +360,21 @@ pub fn set_mod_enabled_status( pub fn get_installed_mods_and_properties( game_install: GameInstall, ) -> Result, String> { - // Get actually installed mods - let found_installed_mods = match legacy::parse_installed_mods(&game_install) { + log::info!("{game_install:?}"); + // Get installed mods from packages + let mut found_installed_mods = match parse_installed_package_mods(&game_install) { + Ok(res) => res, + Err(err) => return Err(err.to_string()), + }; + // Get installed legacy mods + let found_installed_legacy_mods = match legacy::parse_installed_mods(&game_install) { Ok(res) => res, Err(err) => return Err(err.to_string()), }; + // Combine list of package and legacy mods + found_installed_mods.extend(found_installed_legacy_mods); + // Get enabled mods as JSON let enabled_mods: serde_json::Value = match get_enabled_mods(&game_install) { Ok(enabled_mods) => enabled_mods, From babb50234988d4d17c5803c392a414b07fac30d6 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Mon, 17 Jul 2023 22:09:04 +0200 Subject: [PATCH 02/25] chore: Code cleanup --- src-tauri/src/mod_management/mod.rs | 48 ++--------------------------- 1 file changed, 2 insertions(+), 46 deletions(-) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index 2ca613ca9..683b06a7b 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -184,6 +184,7 @@ pub fn set_mod_enabled_status( Ok(()) } +/// Resembles the bare minimum keys in Northstar `mods.json` #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ModJson { #[serde(rename = "Name")] @@ -197,7 +198,6 @@ pub fn parse_mods_in_package( package_mods_path: PathBuf, thunderstore_mod_string: ParsedThunderstoreModString, ) -> Result, anyhow::Error> { - dbg!(package_mods_path.clone()); let paths = match std::fs::read_dir(package_mods_path) { Ok(paths) => paths, Err(_err) => return Err(anyhow!("No mods folder found")), @@ -206,23 +206,15 @@ pub fn parse_mods_in_package( let mut directories: Vec = Vec::new(); let mut mods: Vec = Vec::new(); - log::info!("----------- {paths:?}"); - // Get list of folders in `mods` directory for path in paths { - // dbg!(path); - log::info!("{path:?}"); let my_path = path.unwrap().path(); - log::info!("{my_path:?}"); - let md = std::fs::metadata(my_path.clone()).unwrap(); if md.is_dir() { directories.push(my_path); } } - dbg!(directories.clone()); - // todo!(); // Iterate over folders and check if they are Northstar mods for directory in directories { let directory_str = directory.to_str().unwrap().to_string(); @@ -232,8 +224,6 @@ pub fn parse_mods_in_package( continue; } - // Parse mod.json and get mod name - // Read file into string and parse it let data = std::fs::read_to_string(mod_json_path.clone())?; let parsed_mod_json: ModJson = match json5::from_str(&data) { @@ -282,10 +272,8 @@ pub fn parse_installed_package_mods( // Iteratore over folders in `packages` dir for entry in packages_dir { - let entry = entry?; - let entry_path = entry.path(); + let entry_path = entry?.path(); let entry_str = entry_path.file_name().unwrap().to_str().unwrap(); - log::warn!("Trying: {entry_str}"); // Use the struct's from_str function to verify format if entry_path.is_dir() { @@ -306,27 +294,6 @@ pub fn parse_installed_package_mods( // Ensure `manifest.json` and `mods/` dir exist if manifest_path.exists() && mods_path.is_dir() { - dbg!(mods_path.clone()); - - // Do something with mod path here - log::warn!("{}", mods_path.to_string_lossy()); - - // let paths = match std::fs::read_dir(mods_path) { - // Ok(paths) => paths, - // Err(_err) => todo!(), - // }; - - // // Get list of folders in `mods` directory - // for path in paths { - // log::info!("{path:?}"); - // let my_path = path.unwrap().path(); - // log::info!("{my_path:?}"); - - // let md = std::fs::metadata(my_path.clone()).unwrap(); - // if !md.is_dir() { - // continue; - // } - log::warn!("Found: {}", mods_path.display()); let mods = match parse_mods_in_package(mods_path, package_thunderstore_string.clone()) { Ok(res) => res, @@ -335,17 +302,7 @@ pub fn parse_installed_package_mods( continue; } }; - dbg!(mods.clone()); collected_mods.extend(mods); - // } - - // let ns_mod = NorthstarMod { - // name: parsed_mod_json.name, - // version: parsed_mod_json.version, - // thunderstore_mod_string, - // enabled: false, // Placeholder - // directory: mod_directory, - // }; } } } @@ -360,7 +317,6 @@ pub fn parse_installed_package_mods( pub fn get_installed_mods_and_properties( game_install: GameInstall, ) -> Result, String> { - log::info!("{game_install:?}"); // Get installed mods from packages let mut found_installed_mods = match parse_installed_package_mods(&game_install) { Ok(res) => res, From 7e301bdede6b31e752c82390d219d1a363a6d504 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Tue, 18 Jul 2023 01:29:50 +0200 Subject: [PATCH 03/25] feat: Add ability to delete a Thunderstore package --- src-tauri/src/mod_management/mod.rs | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index 2ac26ede4..864f5448f 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -548,11 +548,57 @@ pub fn delete_northstar_mod(game_install: GameInstall, nsmod_name: String) -> Re Err(format!("Mod {nsmod_name} not found to be installed")) } +/// Deletes a given Thunderstore package +fn delete_package_folder(ts_package_directory: &str) -> Result<(), String> { + let ns_mod_dir_path = std::path::Path::new(&ts_package_directory); + + // Safety check: Check whether `manifest.json` exists and exit early if not + // If it does not exist, we might not be dealing with a Thunderstore package + let mod_json_path = ns_mod_dir_path.join("manifest.json"); + if !mod_json_path.exists() { + // If it doesn't exist, return an error + return Err(format!("manifest.json does not exist in {}", ts_package_directory)); + } + + match std::fs::remove_dir_all(ts_package_directory) { + Ok(()) => Ok(()), + Err(err) => Err(format!("Failed deleting package: {err}")), + } +} + /// Deletes all NorthstarMods related to a Thunderstore mod #[tauri::command] pub fn delete_thunderstore_mod( game_install: GameInstall, thunderstore_mod_string: String, ) -> Result<(), String> { + // Check packages + let packages_folder = format!("{}/R2Northstar/packages", game_install.game_path); + if std::path::Path::new(&packages_folder).exists() { + println!("Directory {} exists. Listing subdirectories...", packages_folder); + for entry in fs::read_dir(packages_folder).unwrap() { + let entry = entry.unwrap(); + + // Check if it's a folder and skip if otherwise + if !entry.file_type().unwrap().is_dir() { + log::warn!("Skipping \"{}\", not a file", entry.path().display()); + continue; + } + + let entry_path = entry.path(); + let package_folder_ts_string = entry_path.file_name().unwrap().to_string_lossy(); + dbg!(package_folder_ts_string.clone()); + + if package_folder_ts_string != thunderstore_mod_string { + // Not the mod folder we are looking for, try the next one\ + continue; + } + + // All checks passed, this is the matching mod + return delete_package_folder(&entry.path().display().to_string()); + } + } + + // Try legacy mod installs as fallback legacy::delete_thunderstore_mod(game_install, thunderstore_mod_string) } From 0fc68de30150746721be31728e84f86434086bc7 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Tue, 18 Jul 2023 01:31:20 +0200 Subject: [PATCH 04/25] fix: Formatting --- src-tauri/src/mod_management/mod.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index 864f5448f..d0ce34767 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -557,7 +557,10 @@ fn delete_package_folder(ts_package_directory: &str) -> Result<(), String> { let mod_json_path = ns_mod_dir_path.join("manifest.json"); if !mod_json_path.exists() { // If it doesn't exist, return an error - return Err(format!("manifest.json does not exist in {}", ts_package_directory)); + return Err(format!( + "manifest.json does not exist in {}", + ts_package_directory + )); } match std::fs::remove_dir_all(ts_package_directory) { @@ -575,14 +578,17 @@ pub fn delete_thunderstore_mod( // Check packages let packages_folder = format!("{}/R2Northstar/packages", game_install.game_path); if std::path::Path::new(&packages_folder).exists() { - println!("Directory {} exists. Listing subdirectories...", packages_folder); + println!( + "Directory {} exists. Listing subdirectories...", + packages_folder + ); for entry in fs::read_dir(packages_folder).unwrap() { let entry = entry.unwrap(); - + // Check if it's a folder and skip if otherwise if !entry.file_type().unwrap().is_dir() { log::warn!("Skipping \"{}\", not a file", entry.path().display()); - continue; + continue; } let entry_path = entry.path(); @@ -593,7 +599,7 @@ pub fn delete_thunderstore_mod( // Not the mod folder we are looking for, try the next one\ continue; } - + // All checks passed, this is the matching mod return delete_package_folder(&entry.path().display().to_string()); } From 6d0d813c9af9fb43e2732652c5ec14d914dcea42 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Tue, 18 Jul 2023 14:16:18 +0200 Subject: [PATCH 05/25] feat: Initial support for installing packages --- src-tauri/Cargo.lock | 46 +++++++++++++++++++++++------ src-tauri/Cargo.toml | 2 +- src-tauri/src/mod_management/mod.rs | 11 +++---- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 77064841e..a1699c164 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -44,6 +44,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -1453,7 +1462,7 @@ version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.20", "bstr", "fnv", "log", @@ -1983,11 +1992,12 @@ checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libthermite" -version = "0.6.5" +version = "0.7.0-alpha" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27cd844bbc25676cd14fa9ad04cc40e0f3c4d5c66107ef3a99896db1f81324c0" +checksum = "b3927ebe9945316ba6a70f4384045fba7da9261e23b44faa7fddf9238f8916fa" dependencies = [ "json5", + "regex", "serde", "serde_json", "thiserror", @@ -2114,7 +2124,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -3055,13 +3065,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ - "aho-corasick", + "aho-corasick 1.0.2", "memchr", - "regex-syntax", + "regex-automata 0.3.3", + "regex-syntax 0.7.4", ] [[package]] @@ -3070,7 +3081,18 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax", + "regex-syntax 0.6.28", +] + +[[package]] +name = "regex-automata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick 1.0.2", + "memchr", + "regex-syntax 0.7.4", ] [[package]] @@ -3079,6 +3101,12 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "regex-syntax" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" + [[package]] name = "reqwest" version = "0.11.14" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ed523a4b3..1ce47b8a0 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -33,7 +33,7 @@ steamlocate = "1.2" # Error messages anyhow = "1.0" # libthermite for Northstar/mod install handling -libthermite = "0.6.5" +libthermite = "0.7.0-alpha" # zip stuff zip = "0.6.2" # Regex diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index 825cba377..adc466611 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -285,7 +285,6 @@ pub async fn fc_download_mod_and_install( "{}/___flightcore-temp-download-dir/", game_install.game_path ); - let mods_directory = format!("{}/R2Northstar/mods/", game_install.game_path); // Early return on empty string if thunderstore_mod_string.is_empty() { @@ -350,14 +349,16 @@ pub async fn fc_download_mod_and_install( Err(err) => return Err(err.to_string()), }; - // Get Thunderstore mod author - let author = thunderstore_mod_string.split('-').next().unwrap(); + // Get directory to install to made up of packages directory and Thunderstore mod string + let install_directory = format!( + "{}/R2Northstar/packages/{}", + game_install.game_path, thunderstore_mod_string + ); // Extract the mod to the mods directory match thermite::core::manage::install_mod( - author, temp_file.file(), - std::path::Path::new(&mods_directory), + std::path::Path::new(&install_directory), ) { Ok(_) => (), Err(err) => { From 24090dd1a134b593aa0a77180f2ae16fab3227a0 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Tue, 18 Jul 2023 15:21:35 +0200 Subject: [PATCH 06/25] feat: Give wrong version number on legacy TS mods to prompt to "update" mod --- src-tauri/src/mod_management/legacy.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/mod_management/legacy.rs b/src-tauri/src/mod_management/legacy.rs index f24f44b63..568aadfc8 100644 --- a/src-tauri/src/mod_management/legacy.rs +++ b/src-tauri/src/mod_management/legacy.rs @@ -88,7 +88,7 @@ pub fn parse_installed_mods( } }; // Get Thunderstore mod string if it exists - let thunderstore_mod_string = match parsed_mod_json.thunderstore_mod_string { + let mut thunderstore_mod_string = match parsed_mod_json.thunderstore_mod_string { // Attempt legacy method for getting Thunderstore string first Some(ts_mod_string) => Some(ts_mod_string), // Legacy method failed @@ -100,6 +100,17 @@ pub fn parse_installed_mods( // Get directory path let mod_directory = directory.to_str().unwrap().to_string(); + // This is a stupid way to show a legacy installed mod as outdated by simply giving back a wrong version number + if thunderstore_mod_string.is_some() { + // Parse the string + let mut parsed_string: ParsedThunderstoreModString = + thunderstore_mod_string.clone().unwrap().parse().unwrap(); + // Set version number to `0.0.0` + parsed_string.version = "0.0.0".to_string(); + // And store new string back in original variable + thunderstore_mod_string = Some(parsed_string.to_string()) + } + let ns_mod = NorthstarMod { name: parsed_mod_json.name, version: parsed_mod_json.version, From 9f9c5559cb9d29656e16a01082ad5617bb0a41e0 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Tue, 18 Jul 2023 17:50:41 +0200 Subject: [PATCH 07/25] feat: Support deleting older versions of package on update --- src-tauri/src/mod_management/mod.rs | 63 ++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index c9b7ae0c6..14411accb 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -407,8 +407,60 @@ async fn get_mod_dependencies(thunderstore_mod_string: &str) -> Result::new()) } +/// Deletes all versions of Thunderstore package except the specified one +fn delete_older_versions( + thunderstore_mod_string: &str, + game_install: &GameInstall, +) -> Result<(), String> { + let thunderstore_mod_string: ParsedThunderstoreModString = + thunderstore_mod_string.parse().unwrap(); + log::info!( + "Deleting other versions of {}", + thunderstore_mod_string.to_string() + ); + let packages_folder = format!("{}/R2Northstar/packages", game_install.game_path); + + // Get folders in packages dir + let paths = match std::fs::read_dir(&packages_folder) { + Ok(paths) => paths, + Err(_err) => return Err(format!("Failed to read directory {}", &packages_folder)), + }; + + let mut directories: Vec = Vec::new(); + + // Get list of folders in `mods` directory + for path in paths { + let my_path = path.unwrap().path(); + + let md = std::fs::metadata(my_path.clone()).unwrap(); + if md.is_dir() { + directories.push(my_path); + } + } + + for directory in directories { + let folder_name = directory.file_name().unwrap().to_str().unwrap(); + let ts_mod_string_from_folder: ParsedThunderstoreModString = match folder_name.parse() { + Ok(res) => res, + Err(err) => { + log::warn!("{err}"); + continue; + } + }; + // Check which match `AUTHOR-MOD` and do NOT match `AUTHOR-MOD-VERSION` + if ts_mod_string_from_folder.author_name == thunderstore_mod_string.author_name + && ts_mod_string_from_folder.mod_name == thunderstore_mod_string.mod_name + && ts_mod_string_from_folder.version != thunderstore_mod_string.version + { + delete_package_folder(&directory.display().to_string())?; + } + } + + Ok(()) +} + // Copied from `libtermite` source code and modified -// Should be replaced with a library call to libthermite in the future +// Should be replaced with a library call to >libthermite in the future /// Download and install mod to the specified target. #[async_recursion] pub async fn fc_download_mod_and_install( @@ -503,6 +555,15 @@ pub async fn fc_download_mod_and_install( } }; + // Succesful package install + match delete_older_versions(thunderstore_mod_string, game_install) { + Ok(()) => (), + Err(err) => { + log::warn!("Failed deleting older versions due to: {}", err); + todo!(); // should we do something on error or ignore? + } + } + Ok(()) } From 8a1c8d3f05a210353051a4d3c17f7852432326cd Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Tue, 18 Jul 2023 18:01:22 +0200 Subject: [PATCH 08/25] fix: Typo in comment --- src-tauri/src/mod_management/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index 14411accb..70f902e5a 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -555,7 +555,7 @@ pub async fn fc_download_mod_and_install( } }; - // Succesful package install + // Successful package install match delete_older_versions(thunderstore_mod_string, game_install) { Ok(()) => (), Err(err) => { From ea74685ab1f88ad16cef5e58450c28aa120852be Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Tue, 18 Jul 2023 18:02:07 +0200 Subject: [PATCH 09/25] fix: Add missing semi colon No clue how that even worked in the first place --- src-tauri/src/mod_management/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index 70f902e5a..a1a8cdf0f 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -562,7 +562,7 @@ pub async fn fc_download_mod_and_install( log::warn!("Failed deleting older versions due to: {}", err); todo!(); // should we do something on error or ignore? } - } + }; Ok(()) } From 695858088486a1a9d5fe9a74f79f1cad95a20b14 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Wed, 19 Jul 2023 01:09:17 +0200 Subject: [PATCH 10/25] feat: Delete packages installed in legacy mode on upgrade --- src-tauri/src/mod_management/legacy.rs | 36 ++++++++++++++++++++++++++ src-tauri/src/mod_management/mod.rs | 8 ++++++ 2 files changed, 44 insertions(+) diff --git a/src-tauri/src/mod_management/legacy.rs b/src-tauri/src/mod_management/legacy.rs index 568aadfc8..4e1d81ff2 100644 --- a/src-tauri/src/mod_management/legacy.rs +++ b/src-tauri/src/mod_management/legacy.rs @@ -126,6 +126,42 @@ pub fn parse_installed_mods( Ok(mods) } +/// Deletes all legacy packages that match in author and mod name +/// regardless of version +pub fn delete_legacy_package_install( + thunderstore_mod_string: &str, + game_install: &GameInstall, +) -> Result<(), String> { + let thunderstore_mod_string: ParsedThunderstoreModString = + thunderstore_mod_string.parse().unwrap(); + let found_installed_legacy_mods = match parse_installed_mods(&game_install) { + Ok(res) => res, + Err(err) => return Err(err.to_string()), + }; + + for legacy_mod in found_installed_legacy_mods { + if legacy_mod.thunderstore_mod_string.is_none() { + continue; // Not a thunderstore mod + } + + let current_mod_ts_string: ParsedThunderstoreModString = legacy_mod + .clone() + .thunderstore_mod_string + .unwrap() + .parse() + .unwrap(); + + if thunderstore_mod_string.author_name == current_mod_ts_string.author_name + && thunderstore_mod_string.mod_name == current_mod_ts_string.mod_name + { + // They match, delete + delete_mod_folder(&legacy_mod.directory)?; + } + } + + Ok(()) +} + /// Deletes all NorthstarMods related to a Thunderstore mod pub fn delete_thunderstore_mod( game_install: GameInstall, diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index a1a8cdf0f..e1939e088 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -556,6 +556,14 @@ pub async fn fc_download_mod_and_install( }; // Successful package install + match legacy::delete_legacy_package_install(thunderstore_mod_string, game_install) { + Ok(()) => (), + Err(err) => { + log::warn!("Failed deleting legacy versions due to: {}", err); + todo!(); // should we do something on error or ignore? + } + }; + match delete_older_versions(thunderstore_mod_string, game_install) { Ok(()) => (), Err(err) => { From 349a3cbb56b36c78788d007495341925711e6026 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Wed, 19 Jul 2023 01:46:22 +0200 Subject: [PATCH 11/25] fix: Remove unnecessary reference according to clippy --- src-tauri/src/mod_management/legacy.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/mod_management/legacy.rs b/src-tauri/src/mod_management/legacy.rs index 4e1d81ff2..cf535000e 100644 --- a/src-tauri/src/mod_management/legacy.rs +++ b/src-tauri/src/mod_management/legacy.rs @@ -134,7 +134,7 @@ pub fn delete_legacy_package_install( ) -> Result<(), String> { let thunderstore_mod_string: ParsedThunderstoreModString = thunderstore_mod_string.parse().unwrap(); - let found_installed_legacy_mods = match parse_installed_mods(&game_install) { + let found_installed_legacy_mods = match parse_installed_mods(game_install) { Ok(res) => res, Err(err) => return Err(err.to_string()), }; From 48bfce134d94f620ca2c704adbc6e342714014f1 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Wed, 19 Jul 2023 17:04:36 +0200 Subject: [PATCH 12/25] feat: Add ability to delete a Thunderstore package --- src-tauri/src/mod_management/mod.rs | 52 +++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index 2ac26ede4..d0ce34767 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -548,11 +548,63 @@ pub fn delete_northstar_mod(game_install: GameInstall, nsmod_name: String) -> Re Err(format!("Mod {nsmod_name} not found to be installed")) } +/// Deletes a given Thunderstore package +fn delete_package_folder(ts_package_directory: &str) -> Result<(), String> { + let ns_mod_dir_path = std::path::Path::new(&ts_package_directory); + + // Safety check: Check whether `manifest.json` exists and exit early if not + // If it does not exist, we might not be dealing with a Thunderstore package + let mod_json_path = ns_mod_dir_path.join("manifest.json"); + if !mod_json_path.exists() { + // If it doesn't exist, return an error + return Err(format!( + "manifest.json does not exist in {}", + ts_package_directory + )); + } + + match std::fs::remove_dir_all(ts_package_directory) { + Ok(()) => Ok(()), + Err(err) => Err(format!("Failed deleting package: {err}")), + } +} + /// Deletes all NorthstarMods related to a Thunderstore mod #[tauri::command] pub fn delete_thunderstore_mod( game_install: GameInstall, thunderstore_mod_string: String, ) -> Result<(), String> { + // Check packages + let packages_folder = format!("{}/R2Northstar/packages", game_install.game_path); + if std::path::Path::new(&packages_folder).exists() { + println!( + "Directory {} exists. Listing subdirectories...", + packages_folder + ); + for entry in fs::read_dir(packages_folder).unwrap() { + let entry = entry.unwrap(); + + // Check if it's a folder and skip if otherwise + if !entry.file_type().unwrap().is_dir() { + log::warn!("Skipping \"{}\", not a file", entry.path().display()); + continue; + } + + let entry_path = entry.path(); + let package_folder_ts_string = entry_path.file_name().unwrap().to_string_lossy(); + dbg!(package_folder_ts_string.clone()); + + if package_folder_ts_string != thunderstore_mod_string { + // Not the mod folder we are looking for, try the next one\ + continue; + } + + // All checks passed, this is the matching mod + return delete_package_folder(&entry.path().display().to_string()); + } + } + + // Try legacy mod installs as fallback legacy::delete_thunderstore_mod(game_install, thunderstore_mod_string) } From 0d06d88aaf59a9496fbaf9a8a94a17eccb836ed7 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Wed, 19 Jul 2023 22:18:14 +0200 Subject: [PATCH 13/25] fix: Remove debug prints --- src-tauri/src/mod_management/mod.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index d0ce34767..b28671c8d 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -578,10 +578,6 @@ pub fn delete_thunderstore_mod( // Check packages let packages_folder = format!("{}/R2Northstar/packages", game_install.game_path); if std::path::Path::new(&packages_folder).exists() { - println!( - "Directory {} exists. Listing subdirectories...", - packages_folder - ); for entry in fs::read_dir(packages_folder).unwrap() { let entry = entry.unwrap(); @@ -593,7 +589,6 @@ pub fn delete_thunderstore_mod( let entry_path = entry.path(); let package_folder_ts_string = entry_path.file_name().unwrap().to_string_lossy(); - dbg!(package_folder_ts_string.clone()); if package_folder_ts_string != thunderstore_mod_string { // Not the mod folder we are looking for, try the next one\ From e0aab46dc221ded90390609c80991a3665c8e452 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Thu, 20 Jul 2023 00:45:58 +0200 Subject: [PATCH 14/25] fix: Typo in comment --- src-tauri/src/mod_management/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index 6eb7da51b..a88bd6460 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -460,7 +460,7 @@ fn delete_older_versions( } // Copied from `libtermite` source code and modified -// Should be replaced with a library call to >libthermite in the future +// Should be replaced with a library call to libthermite in the future /// Download and install mod to the specified target. #[async_recursion] pub async fn fc_download_mod_and_install( From e3c68e1f322b8bbf8b39ecc3b39b46baf59f6ca7 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Thu, 20 Jul 2023 00:49:14 +0200 Subject: [PATCH 15/25] fix: Typo in Cargo.toml --- src-tauri/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1c758eb37..261e0b9d5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -33,7 +33,7 @@ steamlocate = "1.2" # Error messages anyhow = "1.0" # libthermite for Northstar/mod install handling -libthermite = { version = ""0.7.0-alpha", features = ["proton"] } +libthermite = { version = "0.7.0-alpha", features = ["proton"] } # zip stuff zip = "0.6.2" # Regex From 8ae71ef5f04cab43b19b2b17a26012eeffa62566 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Thu, 20 Jul 2023 01:04:26 +0200 Subject: [PATCH 16/25] feat: Delete old version of package on update also deletes old version of legacy package if installed --- src-tauri/src/mod_management/legacy.rs | 36 ++++++++++++++ src-tauri/src/mod_management/mod.rs | 69 ++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/src-tauri/src/mod_management/legacy.rs b/src-tauri/src/mod_management/legacy.rs index f24f44b63..3136a618e 100644 --- a/src-tauri/src/mod_management/legacy.rs +++ b/src-tauri/src/mod_management/legacy.rs @@ -115,6 +115,42 @@ pub fn parse_installed_mods( Ok(mods) } +/// Deletes all legacy packages that match in author and mod name +/// regardless of version +pub fn delete_legacy_package_install( + thunderstore_mod_string: &str, + game_install: &GameInstall, +) -> Result<(), String> { + let thunderstore_mod_string: ParsedThunderstoreModString = + thunderstore_mod_string.parse().unwrap(); + let found_installed_legacy_mods = match parse_installed_mods(game_install) { + Ok(res) => res, + Err(err) => return Err(err.to_string()), + }; + + for legacy_mod in found_installed_legacy_mods { + if legacy_mod.thunderstore_mod_string.is_none() { + continue; // Not a thunderstore mod + } + + let current_mod_ts_string: ParsedThunderstoreModString = legacy_mod + .clone() + .thunderstore_mod_string + .unwrap() + .parse() + .unwrap(); + + if thunderstore_mod_string.author_name == current_mod_ts_string.author_name + && thunderstore_mod_string.mod_name == current_mod_ts_string.mod_name + { + // They match, delete + delete_mod_folder(&legacy_mod.directory)?; + } + } + + Ok(()) +} + /// Deletes all NorthstarMods related to a Thunderstore mod pub fn delete_thunderstore_mod( game_install: GameInstall, diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index b11181c29..afed9692e 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -407,6 +407,58 @@ async fn get_mod_dependencies(thunderstore_mod_string: &str) -> Result::new()) } +/// Deletes all versions of Thunderstore package except the specified one +fn delete_older_versions( + thunderstore_mod_string: &str, + game_install: &GameInstall, +) -> Result<(), String> { + let thunderstore_mod_string: ParsedThunderstoreModString = + thunderstore_mod_string.parse().unwrap(); + log::info!( + "Deleting other versions of {}", + thunderstore_mod_string.to_string() + ); + let packages_folder = format!("{}/R2Northstar/packages", game_install.game_path); + + // Get folders in packages dir + let paths = match std::fs::read_dir(&packages_folder) { + Ok(paths) => paths, + Err(_err) => return Err(format!("Failed to read directory {}", &packages_folder)), + }; + + let mut directories: Vec = Vec::new(); + + // Get list of folders in `mods` directory + for path in paths { + let my_path = path.unwrap().path(); + + let md = std::fs::metadata(my_path.clone()).unwrap(); + if md.is_dir() { + directories.push(my_path); + } + } + + for directory in directories { + let folder_name = directory.file_name().unwrap().to_str().unwrap(); + let ts_mod_string_from_folder: ParsedThunderstoreModString = match folder_name.parse() { + Ok(res) => res, + Err(err) => { + log::warn!("{err}"); + continue; + } + }; + // Check which match `AUTHOR-MOD` and do NOT match `AUTHOR-MOD-VERSION` + if ts_mod_string_from_folder.author_name == thunderstore_mod_string.author_name + && ts_mod_string_from_folder.mod_name == thunderstore_mod_string.mod_name + && ts_mod_string_from_folder.version != thunderstore_mod_string.version + { + delete_package_folder(&directory.display().to_string())?; + } + } + + Ok(()) +} + // Copied from `libtermite` source code and modified // Should be replaced with a library call to libthermite in the future /// Download and install mod to the specified target. @@ -503,6 +555,23 @@ pub async fn fc_download_mod_and_install( } }; + // Successful package install + match legacy::delete_legacy_package_install(thunderstore_mod_string, game_install) { + Ok(()) => (), + Err(err) => { + // Catch error but ignore + log::warn!("Failed deleting legacy versions due to: {}", err); + } + }; + + match delete_older_versions(thunderstore_mod_string, game_install) { + Ok(()) => (), + Err(err) => { + // Catch error but ignore + log::warn!("Failed deleting older versions due to: {}", err); + } + }; + Ok(()) } From c16ff2e1718b9c8c13a173c5fd0607712da12085 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Thu, 20 Jul 2023 01:05:40 +0200 Subject: [PATCH 17/25] chore: Sync with other branch --- src-tauri/src/mod_management/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index a88bd6460..afed9692e 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -559,16 +559,16 @@ pub async fn fc_download_mod_and_install( match legacy::delete_legacy_package_install(thunderstore_mod_string, game_install) { Ok(()) => (), Err(err) => { + // Catch error but ignore log::warn!("Failed deleting legacy versions due to: {}", err); - todo!(); // should we do something on error or ignore? } }; match delete_older_versions(thunderstore_mod_string, game_install) { Ok(()) => (), Err(err) => { + // Catch error but ignore log::warn!("Failed deleting older versions due to: {}", err); - todo!(); // should we do something on error or ignore? } }; From d335e7483dfd1959945ee06038c02877a349ef66 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Thu, 20 Jul 2023 02:21:25 +0200 Subject: [PATCH 18/25] feat: Add sanity check for package install --- src-tauri/src/mod_management/mod.rs | 47 +++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index afed9692e..cef7ff714 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -2,6 +2,7 @@ use crate::constants::{BLACKLISTED_MODS, CORE_MODS}; use async_recursion::async_recursion; +use thermite::prelude::ThermiteError; use crate::NorthstarMod; use anyhow::{anyhow, Result}; @@ -459,6 +460,41 @@ fn delete_older_versions( Ok(()) } +/// Checks whether some mod is correctly formatted +/// Currently checks whether +/// - Some `mod.json` exists under `mods/*/mod.json` +fn fc_sanity_check(input: &&fs::File) -> bool { + let mut archive = match zip::read::ZipArchive::new(*input) { + Ok(archive) => archive, + Err(_) => return false, + }; + + let mut has_mods = false; + let mut mod_json_exists = false; + + // Checks for `mods/*/mod.json` + for i in 0..archive.len() { + let file = match archive.by_index(i) { + Ok(file) => file, + Err(_) => continue, + }; + let file_path = file.mangled_name(); + if file_path.starts_with("mods/") { + has_mods = true; + if let Some(name) = file_path.file_name() { + if name == "mod.json" { + let parent_path = file_path.parent().unwrap(); + if parent_path.parent().unwrap().to_str().unwrap() == "mods" { + mod_json_exists = true; + } + } + } + } + } + + has_mods && mod_json_exists +} + // Copied from `libtermite` source code and modified // Should be replaced with a library call to libthermite in the future /// Download and install mod to the specified target. @@ -544,14 +580,21 @@ pub async fn fc_download_mod_and_install( ); // Extract the mod to the mods directory - match thermite::core::manage::install_mod( + match thermite::core::manage::install_with_sanity( temp_file.file(), std::path::Path::new(&install_directory), + fc_sanity_check, ) { Ok(_) => (), Err(err) => { log::warn!("libthermite couldn't install mod {thunderstore_mod_string} due to {err:?}",); - return Err(err.to_string()); + return match err { + ThermiteError::SanityError => Err( + "Mod failed sanity check during install. It's probably not correctly formatted" + .to_string(), + ), + _ => Err(err.to_string()), + }; } }; From c5bffe6b02a5bd61cff4d973d49f5250d1fd738b Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Thu, 20 Jul 2023 02:32:26 +0200 Subject: [PATCH 19/25] fix: Remove accidentally duplicated code --- src-tauri/src/mod_management/mod.rs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index 00a4987bb..cef7ff714 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -615,23 +615,6 @@ pub async fn fc_download_mod_and_install( } }; - // Successful package install - match legacy::delete_legacy_package_install(thunderstore_mod_string, game_install) { - Ok(()) => (), - Err(err) => { - // Catch error but ignore - log::warn!("Failed deleting legacy versions due to: {}", err); - } - }; - - match delete_older_versions(thunderstore_mod_string, game_install) { - Ok(()) => (), - Err(err) => { - // Catch error but ignore - log::warn!("Failed deleting older versions due to: {}", err); - } - }; - Ok(()) } From 06cdb5d191897dcafd93dea9cf23e7a1a1708d8f Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Thu, 20 Jul 2023 13:09:44 +0200 Subject: [PATCH 20/25] Bump libthermite to 0.7.0-alpha.1 --- src-tauri/Cargo.lock | 5 +++-- src-tauri/Cargo.toml | 2 +- src-tauri/src/mod_management/mod.rs | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index d57c17524..e0d510c6b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1993,12 +1993,13 @@ checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libthermite" -version = "0.7.0-alpha" +version = "0.7.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3927ebe9945316ba6a70f4384045fba7da9261e23b44faa7fddf9238f8916fa" +checksum = "fccf09f4637fd1437d1c5bb05fe7949dfdbe276d0ea2985239101eecd7eca0f4" dependencies = [ "flate2", "json5", + "lazy_static", "regex", "serde", "serde_json", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 261e0b9d5..5c2e7b94b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -33,7 +33,7 @@ steamlocate = "1.2" # Error messages anyhow = "1.0" # libthermite for Northstar/mod install handling -libthermite = { version = "0.7.0-alpha", features = ["proton"] } +libthermite = { version = "0.7.0-alpha.1", features = ["proton"] } # zip stuff zip = "0.6.2" # Regex diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index cef7ff714..c8b0fde83 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -575,12 +575,13 @@ pub async fn fc_download_mod_and_install( // Get directory to install to made up of packages directory and Thunderstore mod string let install_directory = format!( - "{}/R2Northstar/packages/{}", - game_install.game_path, thunderstore_mod_string + "{}/R2Northstar/packages/", + game_install.game_path ); // Extract the mod to the mods directory match thermite::core::manage::install_with_sanity( + thunderstore_mod_string, temp_file.file(), std::path::Path::new(&install_directory), fc_sanity_check, From 68892a467ce10c358bffe8da3229a4ee18ad800a Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Thu, 20 Jul 2023 13:11:17 +0200 Subject: [PATCH 21/25] fix: Formatting --- src-tauri/src/mod_management/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index c8b0fde83..51115b167 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -574,10 +574,7 @@ pub async fn fc_download_mod_and_install( }; // Get directory to install to made up of packages directory and Thunderstore mod string - let install_directory = format!( - "{}/R2Northstar/packages/", - game_install.game_path - ); + let install_directory = format!("{}/R2Northstar/packages/", game_install.game_path); // Extract the mod to the mods directory match thermite::core::manage::install_with_sanity( From d7fdbf8889d51b1b6b256a3f7ffa0934874fcc2f Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Fri, 21 Jul 2023 12:09:35 +0200 Subject: [PATCH 22/25] fix: Bump libthermite to 0.7.0-beta The difference is simply the removed deprecation notice --- src-tauri/Cargo.lock | 4 ++-- src-tauri/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index e0d510c6b..f01d299b1 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1993,9 +1993,9 @@ checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libthermite" -version = "0.7.0-alpha.1" +version = "0.7.0-beta" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fccf09f4637fd1437d1c5bb05fe7949dfdbe276d0ea2985239101eecd7eca0f4" +checksum = "07d01e44ad3cd57ad026987a2d69a71d7a6d49e5ecdbbe64c2f940477b2a3a2d" dependencies = [ "flate2", "json5", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5c2e7b94b..bba82afc9 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -33,7 +33,7 @@ steamlocate = "1.2" # Error messages anyhow = "1.0" # libthermite for Northstar/mod install handling -libthermite = { version = "0.7.0-alpha.1", features = ["proton"] } +libthermite = { version = "0.7.0-beta", features = ["proton"] } # zip stuff zip = "0.6.2" # Regex From 448c6f343984b48b3ba7e1b9faaab54651b758f9 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Fri, 21 Jul 2023 12:14:56 +0200 Subject: [PATCH 23/25] docs: Add comment explaining "legacy package" --- src-tauri/src/mod_management/legacy.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src-tauri/src/mod_management/legacy.rs b/src-tauri/src/mod_management/legacy.rs index 3136a618e..8ca24269a 100644 --- a/src-tauri/src/mod_management/legacy.rs +++ b/src-tauri/src/mod_management/legacy.rs @@ -117,6 +117,10 @@ pub fn parse_installed_mods( /// Deletes all legacy packages that match in author and mod name /// regardless of version +/// +/// "legacy package" refers to a Thunderstore package installed into the `mods` folder +/// by extracting Northstar mods contained inside and then adding `manifest.json` and `thunderstore_author.txt` +/// to indicate which Thunderstore package they are part of pub fn delete_legacy_package_install( thunderstore_mod_string: &str, game_install: &GameInstall, From e4f995b1f8e25ed6cddae2672ea3e79da80e55ee Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Fri, 21 Jul 2023 12:15:29 +0200 Subject: [PATCH 24/25] docs: Add comment explaining why we skip a folder if parsing folder name to Thunderstore mod string failed. --- src-tauri/src/mod_management/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index 51115b167..c049fe07f 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -444,6 +444,10 @@ fn delete_older_versions( let ts_mod_string_from_folder: ParsedThunderstoreModString = match folder_name.parse() { Ok(res) => res, Err(err) => { + // Failed parsing folder name as Thunderstore mod string + // This means it doesn't follow the `AUTHOR-MOD-VERSION` naming structure + // This folder could've been manually created by the user or another application + // As parsing failed we cannot determine the Thunderstore package it is part of hence we skip it log::warn!("{err}"); continue; } From 5e988a6df608ba11956af54951b50cad2e32e3d9 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Fri, 21 Jul 2023 12:18:33 +0200 Subject: [PATCH 25/25] style: Remove trailing whitespace --- src-tauri/src/mod_management/legacy.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/mod_management/legacy.rs b/src-tauri/src/mod_management/legacy.rs index 8ca24269a..914632500 100644 --- a/src-tauri/src/mod_management/legacy.rs +++ b/src-tauri/src/mod_management/legacy.rs @@ -117,7 +117,7 @@ pub fn parse_installed_mods( /// Deletes all legacy packages that match in author and mod name /// regardless of version -/// +/// /// "legacy package" refers to a Thunderstore package installed into the `mods` folder /// by extracting Northstar mods contained inside and then adding `manifest.json` and `thunderstore_author.txt` /// to indicate which Thunderstore package they are part of