diff --git a/Cargo.lock b/Cargo.lock index f4fd669..f8ffd6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,6 +41,7 @@ dependencies = [ "steamlocate", "strip-ansi-escapes", "tokio", + "walkdir", "winresource", ] @@ -1383,6 +1384,15 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scc" version = "2.1.16" @@ -1996,6 +2006,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -2147,6 +2167,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 738e711..20e9175 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ futures-util = "0.3.31" indicatif = "0.17.11" tokio = { version="1.43.0", features = ["rt-multi-thread", "macros"] } simple-log = "2.1.1" +walkdir = "2.5" [target.'cfg(unix)'.dependencies] openssl = { version = "0.10.71", default-features = false, features = ["vendored"] } diff --git a/src/main.rs b/src/main.rs index 9411c5a..6aa8d3b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,7 +26,7 @@ use mslnk::ShellLink; use simple_log::LogConfigBuilder; use std::{ borrow::Cow, - collections::HashMap, + collections::{HashMap, HashSet}, env, fs, path::{Path, PathBuf}, }; @@ -388,56 +388,44 @@ async fn update( if game.engine == "iw4" { iw4x::update(dir, &mut cache, prerelease).await; - let iw4x_dirs = vec!["iw4x", "zone/patch"]; - for d in &iw4x_dirs { - if let Ok(dir_iter) = dir.join(d).read_dir() { - 'outer: for file in dir_iter.filter_map(|entry| entry.ok()) { - let file_path = file.path(); + let scan_dirs = ["iw4x", "zone/patch"]; + let valid_files: HashSet<_> = cdn_info + .iter() + .filter_map(|cdn_file| { + if cdn_file.name.starts_with("iw4/") || cdn_file.name.starts_with("iw4-dlc/") { + Some(Path::new(&cdn_file.name).to_path_buf()) + } else { + None + } + }) + .collect(); - if file_path.is_dir() { - continue; - } + for scan_dir in scan_dirs.iter() { + let full_scan_dir = dir.join(scan_dir); + if !full_scan_dir.exists() || !full_scan_dir.is_dir() { + continue; + } - let file_path_rel = match file_path.strip_prefix(dir) { - Ok(rel) => rel.to_path_buf(), - Err(_) => continue, - }; + for entry in walkdir::WalkDir::new(&full_scan_dir) + .into_iter() + .filter_map(Result::ok) + .filter(|e| e.file_type().is_file()) + { + let rel_path = entry.path().strip_prefix(dir).unwrap_or(entry.path()); + let cdn_path = if rel_path.starts_with("iw4-dlc") { + rel_path.to_path_buf() + } else { + Path::new("iw4").join(rel_path) + }; - if iw4x_dirs - .iter() - .any(|prefix| file_path_rel.starts_with(Path::new(prefix))) - { - if !cdn_info - .iter() - .any(|cdn_file| cdn_file.name.starts_with("iw4")) - { - continue; - } - - let should_continue = cdn_info.iter().any(|cdn_file| { - let path_rem = Path::new(&cdn_file.name) - .strip_prefix(Path::new("iw4")) - .unwrap_or_else(|_| Path::new(&cdn_file.name)); - path_rem == file_path_rel - }); - - if should_continue { - continue 'outer; - } - - crate::println_info!( - "{}{}", - misc::prefix("removed"), - file_path.cute_path() + if !valid_files.contains(&cdn_path) { + crate::println_info!("{}{}", misc::prefix("removed"), entry.path().cute_path()); + if std::fs::remove_file(entry.path()).is_err() { + crate::println_error!( + "{}Couldn't delete {}", + misc::prefix("error"), + entry.path().cute_path() ); - - if fs::remove_file(&file_path).is_err() { - crate::println_error!( - "{}Couldn't delete {}", - misc::prefix("error"), - file_path.cute_path() - ); - } } } }