From 416f4dc383ff5a1194da3a5532a8e159a4a1dac0 Mon Sep 17 00:00:00 2001 From: fxqnlr Date: Sun, 23 Apr 2023 18:24:32 +0200 Subject: added caching, better data location --- Cargo.toml | 2 +- cache | Bin 0 -> 435482 bytes src/cache.rs | 36 +++++++++++++++++++++++++++++++ src/config.rs | 4 +++- src/files.rs | 67 ++++++++++++++++++++++++++++++++++++++++------------------ src/lib.rs | 1 + 6 files changed, 87 insertions(+), 23 deletions(-) create mode 100644 cache create mode 100644 src/cache.rs diff --git a/Cargo.toml b/Cargo.toml index 51652f3..732f38b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "modlist" -version = "0.12.0" +version = "0.13.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/cache b/cache new file mode 100644 index 0000000..22c613c Binary files /dev/null and b/cache differ diff --git a/src/cache.rs b/src/cache.rs new file mode 100644 index 0000000..30c9f09 --- /dev/null +++ b/src/cache.rs @@ -0,0 +1,36 @@ +use std::{collections::HashMap, fs::{read_dir, copy}}; + +use crate::devdir; + +/// . +/// +/// # Panics +/// +/// Panics if . +pub fn get_cached_versions(path: &str) -> HashMap { + let mut versions: HashMap = HashMap::new(); + for file in read_dir(devdir(path)).unwrap() { + let path = file.unwrap().path(); + if path.is_file() && path.extension().ok_or("BAH").unwrap() == "jar" { + let pathstr = path.to_str().ok_or("BAH").unwrap(); + let namesplit: Vec<&str> = pathstr.split('.').collect(); + versions.insert( + String::from(namesplit[namesplit.len() - 2]), + String::from(pathstr), + ); + } + } + versions +} + +/// . +/// +/// # Panics +/// +/// Panics if . +pub fn copy_cached_version(version_path: &str, download_path: &str) { + let versplit: Vec<&str> = version_path.split('/').collect(); + let download = format!("{}{}", download_path, versplit[versplit.len() - 1]); + // println!("{:#?}", download); + copy(version_path, download).unwrap(); +} diff --git a/src/config.rs b/src/config.rs index 1b54d5f..a9a937e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,6 +10,7 @@ use crate::{devdir, error::MLE}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Cfg { pub data: String, + pub cache: String, pub apis: Apis, } @@ -28,7 +29,8 @@ impl Cfg { if err.kind() == std::io::ErrorKind::NotFound { println!("No config file found, creating one"); let default_cfg = Cfg { - data: String::from("./"), + data: String::from("~/.cache/modlist/"), + cache: String::from("~/.cache/modlist/cache"), apis: Apis { modrinth: String::from("https://api.modrinth.com/v2/"), }, diff --git a/src/files.rs b/src/files.rs index 6160cb4..ecf9b52 100644 --- a/src/files.rs +++ b/src/files.rs @@ -2,7 +2,7 @@ use futures_util::StreamExt; use reqwest::Client; use std::{ collections::HashMap, - fs::{read_dir, remove_file, rename, File}, + fs::{read_dir, remove_file, rename, File, copy}, io::Write, }; @@ -11,35 +11,60 @@ use crate::{ db::{mods_get_info, userlist_add_disabled_versions}, error::{ErrorType, MLError, MLE}, modrinth::Version, - List, + List, cache::{get_cached_versions, copy_cached_version}, devdir, }; pub async fn download_versions(list: List, config: Cfg, versions: Vec) -> MLE { + + let mut cached = get_cached_versions(&devdir(&config.cache)); + + println!("{:#?}", cached); + let dl_path = String::from(&list.download_folder); println!(" └Download mods to {}", dl_path); for ver in versions { let project_info = mods_get_info(config.clone(), &ver.project_id)?; - print!("\t└({})Download version {}", project_info.title, ver.id); - //Force flush of stdout, else print! doesn't print instantly - std::io::stdout().flush().unwrap(); - let primary_file = ver.files.into_iter().find(|file| file.primary).unwrap(); - let mut splitname: Vec<&str> = primary_file.filename.split('.').collect(); - let extension = match splitname.pop().ok_or("") { - Ok(e) => e, - Err(..) => return Err(MLError::new(ErrorType::Other, "NO_FILE_EXTENSION")), - }; - let filename = format!( - "{}.mr.{}.{}.{}", - splitname.join("."), - ver.project_id, - ver.id, - extension - ); - download_file(primary_file.url, list.clone().download_folder, filename).await?; - //tokio::time::sleep(std::time::Duration::new(3, 0)).await; - println!(" ✓"); + + //Check cache if already downloaded + let c = cached.remove(&ver.id); + if c.is_some() { + print!("\t└({})Get version {} from cache", project_info.title, ver.id); + //Force flush of stdout, else print! doesn't print instantly + std::io::stdout().flush().unwrap(); + copy_cached_version(&c.unwrap(), &dl_path); + println!(" ✓"); + } else { + print!("\t└({})Download version {}", project_info.title, ver.id); + //Force flush of stdout, else print! doesn't print instantly + std::io::stdout().flush().unwrap(); + let primary_file = ver.files.into_iter().find(|file| file.primary).unwrap(); + let mut splitname: Vec<&str> = primary_file.filename.split('.').collect(); + let extension = match splitname.pop().ok_or("") { + Ok(e) => e, + Err(..) => return Err(MLError::new(ErrorType::Other, "NO_FILE_EXTENSION")), + }; + let filename = format!( + "{}.mr.{}.{}.{}", + splitname.join("."), + ver.project_id, + ver.id, + extension + ); + download_file(primary_file.url, list.clone().download_folder, filename.clone()).await?; + println!(" ✓"); + //Copy file to cache + print!("\t └Copy to cache"); + //Force flush of stdout, else print! doesn't print instantly + std::io::stdout().flush().unwrap(); + let dl_path_file = format!("{}/{}", list.download_folder, filename); + let cache_path = format!("{}/{}", devdir(&config.clone().cache), filename); + // println!("{}:{}", dl_path_file, cache_path); + copy(dl_path_file, cache_path)?; + println!(" ✓"); + } + } Ok(dl_path) diff --git a/src/lib.rs b/src/lib.rs index 43f0fe7..390696c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ pub mod config; pub mod db; pub mod error; pub mod files; +pub mod cache; use std::{fmt::Display, path::Path}; -- cgit v1.2.3