From 7f1a262999d7a8b7f12a97daf4b6722638dc62a1 Mon Sep 17 00:00:00 2001 From: fxqnlr Date: Thu, 25 May 2023 21:06:40 +0200 Subject: more progress instead of print, more references --- src/commands/download.rs | 8 ++- src/commands/modification.rs | 18 +++---- src/commands/update.rs | 123 +++++++++++++------------------------------ src/config.rs | 35 ++++++------ src/db.rs | 17 +++--- src/files.rs | 22 ++++---- src/lib.rs | 13 ++++- src/main.rs | 15 +++--- 8 files changed, 109 insertions(+), 142 deletions(-) (limited to 'src') diff --git a/src/commands/download.rs b/src/commands/download.rs index fea3f34..e9a96b5 100644 --- a/src/commands/download.rs +++ b/src/commands/download.rs @@ -1,4 +1,6 @@ +use indicatif::MultiProgress; + use crate::{config::Cfg, List}; use crate::{ db::userlist_get_all_current_versions_with_mods, @@ -10,10 +12,12 @@ use crate::{ }; pub async fn download(config: &Cfg, liststack: Vec, clean: bool, delete_old: bool) -> MLE<()> { + + let mp = MultiProgress::new(); + for current_list in liststack { println!("Downloading current versions of mods in {}", current_list.id); let downloaded_versions = get_downloaded_versions(current_list.clone())?; - // println!("To download: {:#?}", downloaded_versions); let current_version_ids = match userlist_get_all_current_versions_with_mods( config, String::from(¤t_list.id), @@ -54,6 +58,8 @@ pub async fn download(config: &Cfg, liststack: Vec, clean: bool, delete_ol current_list.clone(), config.clone(), get_raw_versions(&config.apis.modrinth, to_download).await, + &mp, + None ) .await?; } else { diff --git a/src/commands/modification.rs b/src/commands/modification.rs index 31931f8..d369c4b 100644 --- a/src/commands/modification.rs +++ b/src/commands/modification.rs @@ -1,6 +1,6 @@ use std::{io::Write, collections::HashMap}; -use indicatif::{ProgressBar, ProgressStyle}; +use indicatif::{ProgressBar, ProgressStyle, MultiProgress}; use crate::{ config::Cfg, @@ -11,16 +11,16 @@ use crate::{ error::{ErrorType, MLError, MLE}, files::{delete_version, download_versions}, modrinth::{extract_current_version, get_raw_versions, project, projects, versions, Version}, - List, PROGRESS_CHARS, + List, PROGRESS_CHARS, STYLE_BAR_POS, STYLE_SPINNER, }; -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct AddMod { pub id: IDSelector, pub set_version: bool } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq)] pub enum IDSelector { ModificationID(String), VersionID(String), @@ -43,12 +43,11 @@ pub async fn mod_add( list: List, direct_download: bool, ) -> MLE<()> { - let spinner_style = ProgressStyle::with_template("{spinner:.green}{msg}").unwrap(); - let bar_style = ProgressStyle::with_template("{spinner:.green}{wide_msg}{pos}/{len} [{bar:.green/lime}]").unwrap().progress_chars(PROGRESS_CHARS); - // println!("Add mods to {}", list.id); - // println!(" └Add mods:"); + //TODO MultiProgress + let spinner_style = ProgressStyle::with_template(STYLE_SPINNER).unwrap(); + let bar_style = ProgressStyle::with_template(STYLE_BAR_POS).unwrap().progress_chars(PROGRESS_CHARS); let mut mod_ids: Vec<(String, bool)> = Vec::new(); let mut ver_ids: Vec<(String, bool)> = Vec::new(); @@ -153,7 +152,8 @@ pub async fn mod_add( //Download all the added mods if direct_download { - download_versions(list.clone(), config.clone(), downloadstack).await?; + let mp = MultiProgress::new(); + download_versions(list.clone(), config.clone(), downloadstack, &mp, None).await?; }; Ok(()) diff --git a/src/commands/update.rs b/src/commands/update.rs index 7482e43..bde6896 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs @@ -9,7 +9,7 @@ use crate::{ error::{ErrorType, MLError, MLE}, files::{clean_list_dir, delete_version, disable_version, download_versions}, modrinth::{extract_current_version, versions, Version}, - List, PROGRESS_CHARS, + List, PROGRESS_CHARS, STYLE_BAR_POS, }; pub async fn update( @@ -23,35 +23,32 @@ pub async fn update( let mp = MultiProgress::new(); let update_p = mp.add(ProgressBar::new(liststack.len().try_into().unwrap())); - let bar_style = ProgressStyle::with_template("{spinner:.green}{wide_msg}{pos}/{len} [{bar:.green/lime}]").unwrap().progress_chars(PROGRESS_CHARS); - let spinner_style = ProgressStyle::with_template("{spinner:.green}{msg}").unwrap(); + let bar_style = ProgressStyle::with_template(STYLE_BAR_POS).unwrap().progress_chars(PROGRESS_CHARS); update_p.set_style(bar_style.clone()); update_p.set_message("Update"); for current_list in liststack { + let list_p = mp.insert_before(&update_p, ProgressBar::new(2)); + list_p.set_style(ProgressStyle::with_template(STYLE_BAR_POS).unwrap().progress_chars(PROGRESS_CHARS)); + list_p.set_message(format!("Update {}", current_list.id)); - // println!("Update mods in {}", current_list.id); let mods = userlist_get_all_ids(config, ¤t_list.id)?; - let list_p = mp.insert_before(&update_p, ProgressBar::new(mods.len().try_into().unwrap())); - list_p.set_style(bar_style.clone()); - list_p.set_message(format!("Update {}", current_list.id)); + let list_u_p = mp.insert_before(&list_p, ProgressBar::new(mods.len().try_into().unwrap())); + list_u_p.set_style(bar_style.clone()); + list_u_p.set_message(format!("Update {}", current_list.id)); let mut current_versions: Vec<(String, String)> = vec![]; let mut updatestack: Vec = vec![]; for id in mods { - let mod_p = mp.insert_before(&list_p, ProgressBar::new(1)); - mod_p.set_style(spinner_style.clone()); - let info = mods_get_info(config, &id)?; - mod_p.set_message(format!("Update {}", info.title)); - // println!(" ├{}", info.title); - + list_u_p.set_message(format!("Update {}", info.title)); + + //Skip check if version is set if userlist_get_set_version(config, ¤t_list.id, &id)? { - // println!(" │ └Set version, skipping update"); - list_p.inc(1); + list_u_p.inc(1); continue; } @@ -59,15 +56,13 @@ pub async fn update( let disable_version = userlist_get_current_version(config, ¤t_list.id, &id)?; - mod_p.inc(1); - updatestack.push( match specific_update( config, clean, current_list.clone(), &id, - &mod_p + &list_u_p ) .await { @@ -77,44 +72,55 @@ pub async fn update( } Err(e) => { if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { - // println!( - // " │ └No new version found for the specified minecraft version" - // ); } else { return Err(e); }; - list_p.inc(1); + list_u_p.inc(1); continue; } }, ); - list_p.inc(1); + list_u_p.inc(1); } - list_p.finish_with_message(format!("Updated {}", current_list.id)); + list_u_p.finish_with_message(format!("Updated mods in {}", current_list.id)); + list_p.inc(1); if clean { - update_p.set_message("Cleaning"); - update_p.inc(1); + list_p.set_message("Cleaning"); clean_list_dir(¤t_list)?; }; if direct_download && !updatestack.is_empty() { - download_versions(current_list.clone(), config.clone(), updatestack).await?; + download_versions(current_list.clone(), config.clone(), updatestack, &mp, Some(&list_p)).await?; //Disable old versions if !clean { + let d_p = mp.insert_before(&list_p, ProgressBar::new(current_versions.len().try_into().unwrap())); + d_p.set_style(bar_style.clone()); for ver in current_versions { if delete_old { - println!(" └Delete version {}", ver.0); + d_p.set_message(format!("Delete version {}", ver.0)); + d_p.inc(1); delete_version(current_list.clone(), ver.0)?; } else if ver.0 != "NONE" { - println!(" └Disable version {}", ver.0); + d_p.set_message(format!("Disable version {}", ver.0)); + d_p.inc(1); disable_version(config, current_list.clone(), ver.0, ver.1)?; }; } + + let del_msg = if delete_old { + "Deleted all old versions" + } else { + "Disabled all old versions" + }; + + d_p.finish_with_message(del_msg); } }; + list_p.inc(1); + list_p.finish_with_message(format!("Updated {}", current_list.id)); update_p.inc(1); } @@ -149,13 +155,7 @@ async fn specific_update(config: &Cfg, clean: bool, list: List, id: &str, progre { let current_str = extract_current_version(applicable_versions.clone())?; - if clean { - // println!("\t └Add version to downloadstack"); - } else { - progress.println(format!("Found new version for {}", mods_get_info(config, id).unwrap().title)); - // println!("\t └Get versions for specified minecraft versions"); - // println!("\t └New current version: {}", current_str); - }; + if !clean { progress.println(format!("Found new version for {}", mods_get_info(config, id).unwrap().title)); } //get new versions let current_ver = match applicable_versions @@ -183,56 +183,5 @@ async fn specific_update(config: &Cfg, clean: bool, list: List, id: &str, progre return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")); }; - //println!(" └✔️"); Ok(current[0].clone()) } - -// #[tokio::test] -// async fn download_updates_test() { -// use crate::{ -// modrinth::{Hash, Version, VersionFile, VersionType}, -// List, Modloader, -// }; -// -// let config = Cfg::init().unwrap(); -// let current_list = List { -// id: String::from("..."), -// mc_version: String::from("..."), -// modloader: Modloader::Fabric, -// download_folder: String::from("./dev/tests/dl"), -// }; -// -// let versions = vec![Version { -// id: "dEqtGnT9".to_string(), -// project_id: "kYuIpRLv".to_string(), -// author_id: "Qnt13hO8".to_string(), -// featured: true, -// name: "1.2.2-1.19 - Fabric".to_string(), -// version_number: "1.2.2-1.19".to_string(), -// changelog: None, -// date_published: "2022-11-02T17:41:43.072267Z".to_string(), -// downloads: 58, -// version_type: VersionType::release, -// files: vec![VersionFile { -// hashes: Hash { -// sha1: "fdc6dc39427fc92cc1d7ad8b275b5b83325e712b".to_string(), -// sha512: "5b372f00d6e5d6a5ef225c3897826b9f6a2be5506905f7f71b9e939779765b41be6f2a9b029cfc752ad0751d0d2d5f8bb4544408df1363eebdde15641e99a849".to_string() -// }, -// url: "https://cdn.modrinth.com/data/kYuIpRLv/versions/dEqtGnT9/waveycapes-fabric-1.2.2-mc1.19.2.jar".to_string(), -// filename: "waveycapes-fabric-1.2.2-mc1.19.2.jar".to_string(), -// primary: true, -// size: 323176 -// }], -// game_versions: vec![ -// "1.19".to_string(), -// "1.19.1".to_string(), -// "1.19.2".to_string() -// ], -// loaders: vec![ -// "fabric".to_string() -// ] -// }]; -// assert!(download_versions(current_list, config, versions) -// .await -// .is_ok()) -// } diff --git a/src/config.rs b/src/config.rs index a952d40..54cf768 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,6 +4,7 @@ use std::{ path::Path, }; +use indicatif::{ProgressBar, ProgressStyle}; use serde::{Deserialize, Serialize}; use crate::{db::db_setup, error::MLE, Modloader, VersionLevel, check_game_versions}; @@ -79,9 +80,10 @@ impl Cfg { } fn create_config(path: &str) -> MLE<()> { - print!("No config file found, create default"); - //Force flush of stdout, else print! doesn't print instantly - std::io::stdout().flush()?; + let p = ProgressBar::new(1); + p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); + p.set_message("Create default config"); + let cache_dir = dirs::cache_dir() .unwrap() .join("modlist") @@ -102,37 +104,36 @@ fn create_config(path: &str) -> MLE<()> { create_dir_all(path.split("config.toml").collect::>()[0])?; let mut file = File::create(path)?; file.write_all(toml::to_string(&default_cfg)?.as_bytes())?; - println!(" ✓"); + p.finish_with_message(format!("Created default config ({})", path)); Ok(()) } fn create_database(path: &str) -> MLE<()> { - print!("No database found, create base"); - //Force flush of stdout, else print! doesn't print instantly - std::io::stdout().flush()?; + let p = ProgressBar::new(1); + p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); + p.set_message("Create database"); File::create(path)?; db_setup(path)?; - println!(" ✓"); + p.finish_with_message(format!("Created database ({})", path)); Ok(()) } fn create_cache(path: &str) -> MLE<()> { - print!("No cache direcory found, create one"); - //Force flush of stdout, else print! doesn't print instantly - std::io::stdout().flush()?; + let p = ProgressBar::new(1); + p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); + p.set_message("Create cache"); create_dir_all(path)?; - println!(" ✓"); + p.finish_with_message(format!("Created cache ({})", path)); Ok(()) } async fn create_versions_dummy(path: &str) -> MLE<()> { - print!("No version file found, create dummy"); - //Force flush of stdout, else print! doesn't print instantly - std::io::stdout().flush()?; - + let p = ProgressBar::new(1); + p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); + p.set_message("Create version file"); File::create(path)?; - println!(" ✓"); + p.finish_with_message(format!("Created version file ({})", path)); Ok(()) } diff --git a/src/db.rs b/src/db.rs index 3409298..22085a5 100644 --- a/src/db.rs +++ b/src/db.rs @@ -121,7 +121,7 @@ pub fn mods_get_info(config: &Cfg, id: &str) -> MLE { } pub fn mods_remove(config: &Cfg, id: String) -> MLE<()> { - println!("Removing mod {} from database", id); + // println!("Removing mod {} from database", id); let data = format!("{}/data.db", config.data); let connection = Connection::open(data)?; @@ -167,10 +167,10 @@ pub fn mods_get_versions(config: &Cfg, mods: Vec) -> MLE MLE> { let id_iter = stmt.query_map([], |row| row.get::(0))?; for id in id_iter { - //println!("Found id {:?}", id.as_ref().unwrap()); mod_ids.push(id?) } match mod_ids.is_empty() { - true => Err(MLError::new(ErrorType::DBError, "NO_MODS_USERLIST")), + true => Err(MLError::new(ErrorType::DBError, &format!("NO_MODS_USERLIST{}", list_id))), false => Ok(mod_ids), } } @@ -475,7 +474,7 @@ pub fn userlist_get_all_downloads( for link in link_iter { let l = link?; - println!("Found link {}", String::from(&l)); + // println!("Found link {}", String::from(&l)); links.push(l) } @@ -498,7 +497,7 @@ pub fn lists_insert( mod_loader: &Modloader, download_folder: &str, ) -> MLE<()> { - println!("Creating list {}", id); + // println!("Creating list {}", id); let data = format!("{}/data.db", config.data); let connection = Connection::open(data)?; diff --git a/src/files.rs b/src/files.rs index 565d2b6..2830a5f 100644 --- a/src/files.rs +++ b/src/files.rs @@ -14,24 +14,27 @@ use crate::{ db::{mods_get_info, userlist_add_disabled_versions}, error::{ErrorType, MLError, MLE}, modrinth::Version, - List, PROGRESS_CHARS, + List, PROGRESS_CHARS, STYLE_BAR_POS, STYLE_SPINNER, STYLE_BAR_BYTE, }; -pub async fn download_versions(list: List, config: Cfg, versions: Vec) -> MLE<()> { +pub async fn download_versions(list: List, config: Cfg, versions: Vec, progress: &MultiProgress, progress_before: Option<&ProgressBar>) -> MLE<()> { let cached = get_cached_versions(&config.cache); - let mp = MultiProgress::new(); - let mut js = JoinSet::new(); - let style_spinner = ProgressStyle::with_template("{spinner:.green}{wide_msg}").unwrap(); + let style_spinner = ProgressStyle::with_template(STYLE_SPINNER).unwrap(); + + let all = match progress_before { + Some(p) => progress.insert_before(p, ProgressBar::new(versions.len().try_into().unwrap())), + None => progress.add(ProgressBar::new(versions.len().try_into().unwrap())), - let all = mp.add(ProgressBar::new(versions.len().try_into().unwrap())); - all.set_style(ProgressStyle::with_template("{wide_msg}{pos}/{len} [{bar:.green/lime}]").unwrap().progress_chars(PROGRESS_CHARS)); + + }; + all.set_style(ProgressStyle::with_template(STYLE_BAR_POS).unwrap().progress_chars(PROGRESS_CHARS)); all.set_message("Downloading"); for ver in versions { - let p = mp.insert_before(&all, ProgressBar::new(1)); + let p = progress.insert_before(&all, ProgressBar::new(1)); p.set_style(style_spinner.clone()); js.spawn(download_version(config.clone(), list.clone(), ver, cached.clone(), p)); // std::thread::sleep(std::time::Duration::from_millis(200)); @@ -103,7 +106,7 @@ async fn download_file(url: &str, path: &str, name: &str, progress: &ProgressBar let size = res.content_length().expect("Couldn't get content length"); - let style_bar_byte = ProgressStyle::with_template("{spinner:.green}{wide_msg}{bytes}/{total_bytes} [{bar:.green/lime}]") + let style_bar_byte = ProgressStyle::with_template(STYLE_BAR_BYTE) .unwrap() .progress_chars(PROGRESS_CHARS); @@ -203,7 +206,6 @@ pub fn get_downloaded_versions(list: List) -> MLE> { pub fn clean_list_dir(list: &List) -> MLE<()> { let dl_path = &list.download_folder; - println!(" └Clean directory for: {}", list.id); for entry in std::fs::read_dir(dl_path)? { let entry = entry?; std::fs::remove_file(entry.path())?; diff --git a/src/lib.rs b/src/lib.rs index 69cc650..a7a34ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,8 +12,13 @@ pub use apis::*; use apis::modrinth::{get_game_versions, GameVersion, GameVersionType}; pub use commands::*; use error::{ErrorType, MLError, MLE}; +use indicatif::{ProgressStyle, ProgressBar}; use serde::{Deserialize, Serialize}; +pub static STYLE_BAR_POS: &str = "{spinner:.green}{wide_msg}{pos}/{len} [{bar:.green/lime}]"; +pub static STYLE_BAR_BYTE: &str = "{spinner:.green}{wide_msg}{bytes}/{total_bytes} [{bar:.green/lime}]"; +pub static STYLE_SPINNER: &str = "{spinner:.green}{wide_msg}"; +pub static STYLE_MESSAGE: &str = "{wide_msg}"; pub static PROGRESS_CHARS: &str = "#>-"; #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] @@ -59,15 +64,19 @@ pub enum VersionLevel { /// Checks if update needed (time) /// if yes: get versions, update pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> { + let p = ProgressBar::new(1); + p.set_style(ProgressStyle::with_template(STYLE_MESSAGE).unwrap()); + p.set_message("Update minecraft versions"); + let creation_time = fs::metadata(path)?.created()?; if !force && creation_time.elapsed().unwrap() < Duration::from_secs(60 * 60 * 24) { return Ok(()); } - print!("Update minecraft versions"); std::io::stdout().flush()?; let versions = get_game_versions().await; remove_file(path)?; let mut file = File::create(path)?; file.write_all(serde_json::to_string_pretty(&versions)?.as_bytes())?; - println!(" ✓"); + + p.finish_with_message("Updated minecraft versions"); Ok(()) } diff --git a/src/main.rs b/src/main.rs index 0e040b6..7e00368 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,10 +15,6 @@ struct Cli { /// config file path #[arg(short, long)] config: Option, - - /// Force GameVersion update - #[arg(long)] - force_gameupdate: bool, } #[derive(Subcommand)] @@ -30,6 +26,10 @@ enum Commands { List { #[command(subcommand)] command: ListCommands, + + /// Force GameVersion update + #[arg(long)] + force_gameupdate: bool, }, Download { /// download all lists @@ -200,7 +200,7 @@ async fn main() { } } } - Commands::List { command } => { + Commands::List { command, force_gameupdate } => { match command { ListCommands::Add { id, @@ -215,8 +215,8 @@ async fn main() { let versions_path = &config.versions; let ver = match version { - Some(ver) => VersionLevel::from(&ver).get(versions_path, cli.force_gameupdate).await.unwrap(), - None => config.defaults.version.clone().get(versions_path, cli.force_gameupdate).await.unwrap(), + Some(ver) => VersionLevel::from(&ver).get(versions_path, force_gameupdate).await.unwrap(), + None => config.defaults.version.clone().get(versions_path, force_gameupdate).await.unwrap(), }; list_add(&config, &id, &ver, &ml, &directory) @@ -254,6 +254,7 @@ async fn main() { }; liststack.push(current) } + update(&config, liststack, clean, download, remove).await } Commands::Download { all, clean, remove, list } => { -- cgit v1.2.3