-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dev: Packages #429
base: main
Are you sure you want to change the base?
dev: Packages #429
Changes from 32 commits
9c0e479
008e31e
babb502
58b8dce
7e301bd
0fc68de
0cd98b6
6d0d813
24090dd
7df3de9
fb8cfbf
5fc6669
9f9c555
8a1c8d3
ea74685
6958580
349a3cb
a2b80ef
f8d321a
794817d
48bfce1
0d06d88
28c2627
56ac4a1
e0aab46
5f3dcde
e3c68e1
8ae71ef
c16ff2e
d335e74
ef088ee
c5bffe6
06cdb5d
68892a4
d7fdbf8
448c6f3
e4f995b
17d6282
5e988a6
4fbb3e2
09f8834
6b49af5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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, | ||
|
@@ -115,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)?; | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
Ok(()) | ||
} | ||
|
||
/// Deletes all NorthstarMods related to a Thunderstore mod | ||
pub fn delete_thunderstore_mod( | ||
game_install: GameInstall, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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}; | ||
|
@@ -407,6 +408,93 @@ async fn get_mod_dependencies(thunderstore_mod_string: &str) -> Result<Vec<Strin | |
Ok(Vec::<String>::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<PathBuf> = 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); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for loop found, use a iterator instead in this case. ( I hate for loops ). |
||
|
||
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())?; | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a iterator would also be better here although you can probably keep it and just move all these if cases into filters. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah so I kinda merged #426 before seeing your comments on here. Will do some refactoring to change update to your feedback though ^^ |
||
|
||
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; | ||
} | ||
} | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is literately the perfect use for a iterator. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uh, I'm dumb, can I have an example? ^^ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. smth like this it might not compile but it shouldn't be hard to fix stuff in it I think. |
||
} | ||
|
||
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. | ||
|
@@ -421,7 +509,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() { | ||
|
@@ -486,19 +573,45 @@ 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, | ||
match thermite::core::manage::install_with_sanity( | ||
temp_file.file(), | ||
std::path::Path::new(&mods_directory), | ||
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()), | ||
}; | ||
} | ||
}; | ||
|
||
// Successful package install | ||
match legacy::delete_legacy_package_install(thunderstore_mod_string, game_install) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider using a |
||
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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and here |
||
Ok(()) => (), | ||
Err(err) => { | ||
// Catch error but ignore | ||
log::warn!("Failed deleting older versions due to: {}", err); | ||
} | ||
}; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps just move this into the match case above ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't I have to duplicate the code then? Cause the
match
matches for like two casesmods.json
manifest.json
and athunderstore_author.txt