From 44b9da666020fa05920c8a6786428eea77666d14 Mon Sep 17 00:00:00 2001 From: dark0dave Date: Sun, 8 Oct 2023 09:08:48 +0100 Subject: [PATCH] fix(walk): Fixed walked depth and add skip option Signed-off-by: dark0dave --- README.md | 10 ++++++---- src/args.rs | 10 +++++++++- src/main.rs | 31 ++++++++++++++++++++++++++++--- src/utils.rs | 19 ++++++++++++------- src/weidu.rs | 2 +- 5 files changed, 56 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 85dedaf..ea91ea2 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,13 @@ Usage: mod_installer [OPTIONS] --log-file \ --mod-directories Options: - --log-file Full path to target log [env: LOG_FILE=] - -g, --game-directory Full path to game directory [env: GAME_DIRECTORY=] - -w, --weidu-binary Full Path to weidu binary [env: WEIDU_BINARY=] - -m, --mod-directories Full Path to mod directories [env: MOD_DIRECTORIES=] + --log-file Full path to target log [env: LOG_FILE] + -g, --game-directory Full path to game directory [env: GAME_DIRECTORY] + -w, --weidu-binary Full Path to weidu binary [env: WEIDU_BINARY] + -m, --mod-directories Full Path to mod directories [env: MOD_DIRECTORIES] -l, --language Game Language [default: en_US] + -d, --depth Depth to walk folder structure [default: 3] + -s, --skip-installed Compare against installed weidu log, note this is best effort -h, --help Print help -V, --version Print version ``` diff --git a/src/args.rs b/src/args.rs index ecb8590..216c4ae 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use clap::Parser; +use clap::{ArgAction, Parser}; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] @@ -32,6 +32,14 @@ pub struct Args { /// Game Language #[clap(short, long, default_value = "en_US")] pub language: String, + + /// Depth to walk folder structure + #[clap(long, short, default_value = "3")] + pub depth: usize, + + /// Compare against installed weidu log, note this is best effort + #[clap(long, short, action=ArgAction::SetFalse)] + pub skip_installed: bool, } fn parse_absolute_path(arg: &str) -> Result { diff --git a/src/main.rs b/src/main.rs index 1238f56..b93b686 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,13 +30,38 @@ fn main() { ); let args = Args::parse(); - create_weidu_log_if_not_exists(&args.game_directory); + let installed_log_path = create_weidu_log_if_not_exists(&args.game_directory); + + let mods = parse_weidu_log(args.log_file); + let number_of_mods_found = mods.len(); + let mods_to_be_installed = if args.skip_installed { + let installed_mods = parse_weidu_log(installed_log_path); + mods.iter() + .filter_map(|weidu_mod| { + if !installed_mods.contains(weidu_mod) { + Some(weidu_mod.clone()) + } else { + None + } + }) + .collect() + } else { + mods + }; + + log::debug!( + "Number of mods found: {}, Number of mods to be installed: {}", + number_of_mods_found, + mods_to_be_installed.len() + ); let mut mod_folder_cache = HashMap::new(); - for weidu_mod in parse_weidu_log(args.log_file) { + for weidu_mod in mods_to_be_installed { let mod_folder = mod_folder_cache .entry(weidu_mod.tp_file.clone()) - .or_insert_with(|| search_mod_folders(&args.mod_directories, &weidu_mod.clone())); + .or_insert_with(|| { + search_mod_folders(&args.mod_directories, &weidu_mod.clone(), args.depth) + }); log::debug!("Found mod folder {:?}, for mod {:?}", mod_folder, weidu_mod); diff --git a/src/utils.rs b/src/utils.rs index 04f9250..c621fa1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -7,11 +7,12 @@ use walkdir::WalkDir; use crate::mod_component::ModComponent; -pub fn create_weidu_log_if_not_exists(game_directory: &Path) { +pub fn create_weidu_log_if_not_exists(game_directory: &Path) -> PathBuf { let weidu_log_file = game_directory.join("weidu").with_extension("log"); if !weidu_log_file.exists() { - File::create(weidu_log_file).unwrap(); + File::create(weidu_log_file.clone()).unwrap(); } + weidu_log_file } pub fn mod_folder_present_in_game_directory(game_directory: &Path, mod_name: &str) -> bool { @@ -28,10 +29,14 @@ pub fn copy_mod_folder(game_directory: &Path, mod_folder: &Path) { } } -pub fn search_mod_folders(folder_directories: &[PathBuf], weidu_mod: &ModComponent) -> PathBuf { +pub fn search_mod_folders( + folder_directories: &[PathBuf], + weidu_mod: &ModComponent, + depth: usize, +) -> PathBuf { let mod_folder_locations = folder_directories .iter() - .find_map(|mod_folder| find_mod_folder(weidu_mod, mod_folder)); + .find_map(|mod_folder| find_mod_folder(weidu_mod, mod_folder, depth)); if let Some(mod_folder) = mod_folder_locations { mod_folder @@ -41,10 +46,10 @@ pub fn search_mod_folders(folder_directories: &[PathBuf], weidu_mod: &ModCompone } } -fn find_mod_folder(mod_component: &ModComponent, mod_dir: &Path) -> Option { +fn find_mod_folder(mod_component: &ModComponent, mod_dir: &Path, depth: usize) -> Option { WalkDir::new(mod_dir) .follow_links(true) - .max_depth(4) + .max_depth(depth) .into_iter() .find_map(|entry| match entry { Ok(entry) @@ -77,7 +82,7 @@ mod tests { lang: "0".to_string(), component: "0".to_string(), }; - let mod_folder = find_mod_folder(&mod_component, Path::new("fixtures/mods")); + let mod_folder = find_mod_folder(&mod_component, Path::new("fixtures/mods"), 3); let expected = Path::new(&format!("fixtures/mods/mod_a/{}", mod_component.name)).to_path_buf(); diff --git a/src/weidu.rs b/src/weidu.rs index 266c609..92480a8 100644 --- a/src/weidu.rs +++ b/src/weidu.rs @@ -16,7 +16,7 @@ pub fn get_user_input() -> String { } fn generate_args(weidu_mod: &ModComponent, language: &str) -> Vec { - format!("{mod_name}/{mod_tp_file} --quick-log --yes --ask-only {component} --use-lang {game_lang} --language {mod_lang}", mod_name = weidu_mod.name, mod_tp_file = weidu_mod.tp_file, component = weidu_mod.component, mod_lang = weidu_mod.lang, game_lang = language).split(' ').map(|x|x.to_string()).collect() + format!("{mod_name}/{mod_tp_file} --yes --ask-only {component} --use-lang {game_lang} --language {mod_lang}", mod_name = weidu_mod.name, mod_tp_file = weidu_mod.tp_file, component = weidu_mod.component, mod_lang = weidu_mod.lang, game_lang = language).split(' ').map(|x|x.to_string()).collect() } pub fn install(