From ff23a11e632812b685f594324e6004c6da81cd4d Mon Sep 17 00:00:00 2001 From: fxqnlr Date: Sun, 5 Feb 2023 09:23:29 +0100 Subject: Fixed update shit not correctly updating --- src/commands/io.rs | 20 +++++----- src/commands/list.rs | 1 + src/commands/mod.rs | 4 +- src/commands/modification.rs | 73 +++++++++++++++++------------------ src/commands/setup.rs | 86 ++++++++++++++++++++++-------------------- src/commands/update.rs | 90 ++++++++++++++++++++------------------------ 6 files changed, 136 insertions(+), 138 deletions(-) (limited to 'src/commands') diff --git a/src/commands/io.rs b/src/commands/io.rs index 4835e3d..44604d1 100644 --- a/src/commands/io.rs +++ b/src/commands/io.rs @@ -2,7 +2,7 @@ use std::fs::File; use std::io::prelude::*; use serde::{Serialize, Deserialize}; -use crate::{input::{Input, IoOptions}, db::{lists_get, userlist_get_all_ids, lists_get_all_ids, lists_insert}, config::Cfg, Modloader, /*mod_add,*/ List, devdir, error::MLE}; +use crate::{input::{Input, IoOptions}, db::{lists_get, userlist_get_all_ids, lists_get_all_ids, lists_insert}, config::Cfg, Modloader, List, devdir, error::MLE, mods_add}; #[derive(Debug, Serialize, Deserialize)] struct Export { @@ -24,7 +24,7 @@ impl ExportList { let list = lists_get(config.clone(), String::from(&list_id))?; let mut dl_folder = None; - if download == true { dl_folder = Some(list.download_folder) }; + if download{ dl_folder = Some(list.download_folder) }; let mods = userlist_get_all_ids(config, list_id)?.join("|"); @@ -51,7 +51,7 @@ fn export(config: Cfg, input: Input) -> MLE<()> { } let mut lists: Vec = vec![]; for list_id in list_ids { - lists.push(ExportList::from(config.clone(), String::from(list_id), true)?); + lists.push(ExportList::from(config.clone(), list_id, true)?); } let toml = toml::to_string( &Export { lists } )?; @@ -59,7 +59,7 @@ fn export(config: Cfg, input: Input) -> MLE<()> { let filestr = dirs::home_dir().unwrap().join("mlexport.toml"); let mut file = File::create(devdir(filestr.into_os_string().into_string().unwrap().as_str()))?; - file.write_all(&toml.as_bytes())?; + file.write_all(toml.as_bytes())?; Ok(()) } @@ -67,8 +67,8 @@ fn export(config: Cfg, input: Input) -> MLE<()> { async fn import(config: Cfg, input: Input) -> MLE<()> { let filestr: String = match input.file { - Some(args) => String::from(args), - None => String::from(devdir(dirs::home_dir().unwrap().join("mlexport.toml").into_os_string().into_string().unwrap().as_str())), + Some(args) => args, + None => devdir(dirs::home_dir().unwrap().join("mlexport.toml").into_os_string().into_string().unwrap().as_str()), }; let mut file = File::open(filestr)?; @@ -76,17 +76,17 @@ async fn import(config: Cfg, input: Input) -> MLE<()> { file.read_to_string(&mut content)?; let export: Export = toml::from_str(&content)?; - println!("{:#?}", export); - for exportlist in export.lists { let list = List { id: exportlist.id, mc_version: exportlist.mc_version, modloader: Modloader::from(&exportlist.launcher)?, download_folder: exportlist.download_folder.ok_or("NO_DL").unwrap() }; lists_insert(config.clone(), list.id.clone(), list.mc_version.clone(), list.modloader.clone(), String::from(&list.download_folder))?; - let mods: Vec<&str> = exportlist.mods.split("|").collect(); + let mods: Vec<&str> = exportlist.mods.split('|').collect(); let mut mod_ids = vec![]; for mod_id in mods { mod_ids.push(String::from(mod_id)); }; - //mod_add(config.clone(), mod_ids, list.clone(), false).await?; + //TODO impl set_version and good direct download + //TODO impl all at once, dafuck + mods_add(config.clone(), mod_ids, list, input.direct_download, false).await?; } Ok(()) } diff --git a/src/commands/list.rs b/src/commands/list.rs index eaf6fa1..8e86973 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs @@ -49,6 +49,7 @@ fn remove(config: Cfg, input: Input) -> MLE<()> { } ///Changing the current lists version and updating it +/// /// #Arguments /// /// * `config` - The current config diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 38139f9..0d5bd00 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,13 +1,13 @@ pub mod modification; pub mod list; pub mod update; -//pub mod setup; +pub mod setup; pub mod download; pub mod io; pub use modification::*; pub use list::*; pub use update::*; -//pub use setup::*; +pub use setup::*; pub use download::*; pub use io::*; diff --git a/src/commands/modification.rs b/src/commands/modification.rs index c82d6b5..12a635f 100644 --- a/src/commands/modification.rs +++ b/src/commands/modification.rs @@ -1,4 +1,9 @@ -use crate::{modrinth::{project, versions, extract_current_version, Version, projects}, config::Cfg, db::{mods_insert, userlist_remove, mods_get_id, userlist_insert, mods_get_all_ids, userlist_get_all_ids, userlist_get_current_version, lists_get_all_ids, mods_remove}, input::{Input, ModOptions}, files::{delete_version, download_versions}, List, error::{MLE, ErrorType, MLError}}; +use crate::{modrinth::{project, versions, extract_current_version, Version, projects}, config::Cfg, db::{mods_insert, userlist_remove, mods_get_id, userlist_insert, userlist_get_all_ids, userlist_get_current_version, lists_get_all_ids, mods_remove}, input::{Input, ModOptions}, files::{delete_version, download_versions}, List, error::{MLE, ErrorType, MLError}}; + +//TODO DO IT +pub struct ModVer { + +} pub async fn modification(config: Cfg, input: Input) -> MLE<()> { match input.clone().mod_options.ok_or("").unwrap() { @@ -13,22 +18,26 @@ pub async fn modification(config: Cfg, input: Input) -> MLE<()> { async fn add(config: Cfg, input: Input) -> MLE<()> { - mod_add(config, vec![String::from(input.mod_id.unwrap())], input.list.unwrap(), input.direct_download).await?; + mods_add(config, vec![input.mod_id.unwrap()], input.list.unwrap(), input.direct_download, input.set_version).await?; Ok(()) } - -pub async fn mod_add(config: Cfg, mod_id: Vec, list: List, direct_download: bool) -> MLE<()> { +//TODO impl specific version +pub async fn mods_add(config: Cfg, mod_id: Vec, list: List, direct_download: bool, set_version: bool) -> MLE<()> { - //Fix printing (its horrible) - println!("Adding mod(s) {:?}", mod_id); + println!("Add mods to {}", list.id); + println!(" └Add mods:"); let projects = if mod_id.len() == 1 { vec![project(String::from(&config.apis.modrinth), &mod_id[0]).await] } else { projects(String::from(&config.apis.modrinth), mod_id).await }; + + let mut downloadstack: Vec = Vec::new(); for project in projects { + println!("\t└{}", project.title); + println!("\t └Get versions"); let available_versions = versions(String::from(&config.apis.modrinth), String::from(&project.id), list.clone()).await; let mut available_versions_vec: Vec = Vec::new(); @@ -37,64 +46,56 @@ pub async fn mod_add(config: Cfg, mod_id: Vec, list: List, direct_downlo let file: String; if !available_versions.is_empty() { let current_id = extract_current_version(available_versions.clone())?; + println!("\t └Current version: {}", current_id); current_version = Some(available_versions.clone().into_iter().find(|v| v.id == current_id).unwrap()); current_version_id = current_version.clone().unwrap().id; file = current_version.clone().ok_or("").unwrap().files.into_iter().find(|f| f.primary).unwrap().url; - for ver in available_versions { available_versions_vec.push(ver.id); }; } else { - println!("There's currently no mod version for your specified target"); + println!("\t └There's currently no mod version for your specified target"); current_version = None; current_version_id = String::from("NONE"); file = String::from("NONE"); available_versions_vec.push(String::from("NONE")); } - //add to current list and mod table - match userlist_get_all_ids(config.clone(), list.clone().id) { - Ok(mods) => { - if mods.contains(&project.id) { - return Err(MLError::new(ErrorType::ModError, "MOD_ALREADY_ON_LIST")); } - else { - userlist_insert(config.clone(), String::from(&list.id), String::from(&project.id), String::from(¤t_version_id), available_versions_vec, file)?; - } + match userlist_insert(config.clone(), &list.id, &project.id, ¤t_version_id, available_versions_vec, &file, set_version) { + Err(e) => { + let expected_err = format!("SQL: UNIQUE constraint failed: {}.mod_id", list.id); + if e.to_string() == expected_err { Err(MLError::new(ErrorType::ModError, "MOD_ALREADY_ON_SELECTED_LIST")) } else { Err(e) } }, - Err(..) => userlist_insert(config.clone(), String::from(&list.id), String::from(&project.id), String::from(¤t_version_id), available_versions_vec, file)?, - }; + Ok(..) => { Ok(..) }, + }?; - match mods_get_all_ids(config.clone()) { - Ok(mods) => { - if mods.contains(&project.id) { - //return Err(Box::new(Error::new(ErrorKind::Other, "MOD_ALREADY_IN_DATABASE"))) - } else { - mods_insert(config.clone(), String::from(&project.id), String::from(&project.title), project.versions)?; - } - }, - Err(..) => { - mods_insert(config.clone(), String::from(&project.id), String::from(&project.title), project.versions)?; + match mods_insert(config.clone(), &project.id, &project.slug, &project.title) { + Err(e) => { + if e.to_string() == "SQL: UNIQUE constraint failed: mods.id" { Ok(..) } else { Err(e) } }, - }; + Ok(..) => Ok(..), + }?; - if direct_download && current_version.is_some() { download_versions(list.clone(), config.clone(), vec![current_version.unwrap()]).await?; }; - - } + downloadstack.push(current_version.unwrap()); + }; + + //Download all the added mods + if direct_download { + download_versions(list.clone(), config.clone(), downloadstack).await?; + }; Ok(()) } fn remove(config: Cfg, input: Input) -> MLE<()> { - - //TODO inplement deletion by slug or title - let mod_id = mods_get_id(config.clone(), input.clone().mod_id.unwrap())?; + + let mod_id = mods_get_id(&config.data, input.mod_id.as_ref().unwrap())?; let version = userlist_get_current_version(config.clone(), input.clone().list.unwrap().id, String::from(&mod_id))?; - //TODO implement remove from modlist if not in any other lists && config clean is true userlist_remove(config.clone(), input.clone().list.unwrap().id, String::from(&mod_id))?; delete_version(input.list.unwrap(), version)?; diff --git a/src/commands/setup.rs b/src/commands/setup.rs index cc7472c..0161bd7 100644 --- a/src/commands/setup.rs +++ b/src/commands/setup.rs @@ -1,66 +1,72 @@ -use std::{fs::File, path::Path, io::{Error, ErrorKind}}; +use std::{fs::File, path::Path}; -use crate::{config::Cfg, db::{db_setup, s_config_get_version, s_config_create_version, s_insert_column, lists_get_all_ids, lists_get, userlist_get_all_current_version_ids, s_userlist_update_download, s_config_update_version}, modrinth::get_raw_versions, devdir}; +use crate::{config::Cfg, db::db_setup, error::MLE, devdir}; -pub async fn setup(config: Cfg) -> Result<(), Box> { +pub async fn setup(config: Cfg) -> MLE<()> { let db_file = devdir(format!("{}/data.db", config.data).as_str()); if !Path::new(&db_file).exists() { - return create(config, db_file); + create(config, db_file)?; } + /* match s_config_get_version(config.clone()) { Ok(ver) => { match ver.as_str() { "0.2" => to_03(config)?, "0.3" => to_04(config)?, - _ => return Err(Box::new(Error::new(ErrorKind::Other, "UNKNOWN_VERSION"))) + _ => return Err(MLError::new(ErrorType::Other, "UNKNOWN_VERSION")) } }, Err(..) => to_02(config).await? }; + */ Ok(()) } -fn create(config: Cfg, db_file: String) -> Result<(), Box> { - File::create(db_file)?; - db_setup(config)?; - Ok(()) -} - -async fn to_02(config: Cfg) -> Result<(), Box> { - let lists = lists_get_all_ids(config.clone())?; - - for list in lists { - println!("Updating {}", list); - s_insert_column(config.clone(), String::from(&list), String::from("current_download"), String::from("TEXT"), None)?; - - let full_list = lists_get(config.clone(), String::from(&list))?; +fn create(config: Cfg, db_file: String) -> MLE<()> { - let versions = userlist_get_all_current_version_ids(config.clone(), full_list.clone().id)?; - - let raw_versions = get_raw_versions(String::from(&config.apis.modrinth), versions).await; - - for ver in raw_versions { - println!("Adding link for {}", ver.project_id); - let file = ver.files.into_iter().find(|f| f.primary).unwrap(); - s_userlist_update_download(config.clone(), String::from(&full_list.id), ver.project_id, file.url)?; - } - }; - s_config_create_version(config)?; + println!("Create database"); + File::create(db_file)?; + db_setup(config)?; Ok(()) } -fn to_03(config: Cfg) -> Result<(), Box> { - s_insert_column(config.clone(), String::from("lists"), String::from("download_folder"), String::from("TEXT"), None)?; - s_config_update_version(config, String::from("0.3")) -} +//async fn to_02(config: Cfg) -> Result<(), Box> { +// let lists = lists_get_all_ids(config.clone())?; +// +// for list in lists { +// println!("Updating {}", list); +// s_insert_column(config.clone(), String::from(&list), String::from("current_download"), String::from("TEXT"), None)?; +// +// let full_list = lists_get(config.clone(), String::from(&list))?; +// +// let versions = userlist_get_all_current_version_ids(config.clone(), full_list.clone().id)?; +// +// let raw_versions = get_raw_versions(String::from(&config.apis.modrinth), versions).await; +// +// for ver in raw_versions { +// println!("Adding link for {}", ver.project_id); +// let file = ver.files.into_iter().find(|f| f.primary).unwrap(); +// s_userlist_update_download(config.clone(), String::from(&full_list.id), ver.project_id, file.url)?; +// } +// }; +// s_config_create_version(config)?; +// +// Ok(()) +//} +// +//fn to_03(config: Cfg) -> Result<(), Box> { +// s_insert_column(config.clone(), String::from("lists"), String::from("download_folder"), String::from("TEXT"), None)?; +// s_config_update_version(config, String::from("0.3")) +//} +// +//fn to_04(config: Cfg) -> Result<(), Box> { +// for list_id in lists_get_all_ids(config.clone())? { +// s_insert_column(config.clone(), list_id, String::from("disabled_versions"), String::from("TEXT"), Some(String::from("NONE")))?; +// } +// s_config_update_version(config, String::from("0.4")) +//} -fn to_04(config: Cfg) -> Result<(), Box> { - for list_id in lists_get_all_ids(config.clone())? { - s_insert_column(config.clone(), list_id, String::from("disabled_versions"), String::from("TEXT"), Some(String::from("NONE")))?; - } - s_config_update_version(config, String::from("0.4")) -} \ No newline at end of file diff --git a/src/commands/update.rs b/src/commands/update.rs index d400a24..bc5b316 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs @@ -1,4 +1,4 @@ -use crate::{config::Cfg, modrinth::{projects, Project, versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, mods_get_versions, userlist_get_applicable_versions, userlist_change_versions, lists_get_all_ids, lists_get, userlist_get_current_version, mods_change_versions}, List, input::Input, files::{delete_version, download_versions, disable_version, clean_list_dir}, error::{MLE, MLError, ErrorType}}; +use crate::{config::Cfg, modrinth::{versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, userlist_get_applicable_versions, userlist_change_versions, lists_get_all_ids, lists_get, userlist_get_current_version, mods_get_title, userlist_get_set_version}, List, input::Input, files::{delete_version, download_versions, disable_version, clean_list_dir}, error::{MLE, MLError, ErrorType}}; pub async fn update(config: Cfg, input: Input) -> MLE<()> { let mut liststack: Vec = vec![]; @@ -9,7 +9,7 @@ pub async fn update(config: Cfg, input: Input) -> MLE<()> { } } else { let current = get_current_list(config.clone())?; - println!("Check for updates of mods in list {}", current.id); + println!("Update list {}:", current.id); liststack.push(current) } cmd_update(config, liststack, input.clean, input.direct_download, input.delete_old).await @@ -20,59 +20,41 @@ pub async fn cmd_update(config: Cfg, liststack: Vec, clean: bool, direct_d let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?; let mut current_versions: Vec<(String, String)> = vec![]; + + println!(" └Update mods:"); + let mut updatestack: Vec = vec![]; + + for id in mods { + let title = mods_get_title(config.clone(), &id)?; + println!("\t└{}", title); - let mut versions = mods_get_versions(config.clone(), mods.clone())?; - versions.sort_by_key(|ver| ver.mod_id.clone()); - - let mut projects = projects(String::from(&config.apis.modrinth), mods).await; - projects.sort_by_key(|pro| pro.id.clone()); + if userlist_get_set_version(config.clone(), ¤t_list.id, &id)? { + println!("\t └Set version, skipping update"); + continue; + } - println!("Comparing mod versions:"); - let mut updatestack: Vec = vec![]; - for (index, project) in projects.into_iter().enumerate() { - //Get versions for project and check if they match up - let current_version = &versions[index]; - let p_id = String::from(&project.id); - let v_id = ¤t_version.mod_id; - if &p_id != v_id { return Err(MLError::new(ErrorType::Other, "SORTING_ERROR")) }; - - println!("\t({}) Check for update", project.title); - //Getting current installed version for disable or delete - let disable_version = userlist_get_current_version(config.clone(), String::from(¤t_list.id), String::from(&project.id))?; - - let version_db_string = project.versions.join("|"); + let disable_version = userlist_get_current_version(config.clone(), String::from(¤t_list.id), String::from(&id))?; - //Adding to stack if not the same versions in the list OR if clean == true - if clean || (version_db_string != current_version.versions) { - updatestack.push(match specific_update(config.clone(), clean, current_list.clone(), project.clone()).await { + updatestack.push( + match specific_update(config.clone(), clean, current_list.clone(), String::from(&id)).await { Ok(ver) => { - current_versions.push((disable_version, p_id)); + current_versions.push((disable_version, id)); ver }, Err(e) => { - //Catch no update available if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { - mods_change_versions(config.clone(), version_db_string, project.id)?; - println!("\t └No new version found for the specified minecraft version"); + println!("\t └No new version found for the specified minecraft version"); } else { return Err(e); }; continue; - }, - }); - } else { - println!("\t └No new version found"); - }; + } + } + ) }; - - //Linebreak readability - println!(""); - if clean { clean_list_dir(¤t_list)? }; - - //Linebreak readability - println!(""); + if clean { clean_list_dir(¤t_list)?; }; if direct_download && !updatestack.is_empty() { download_versions(current_list.clone(), config.clone(), updatestack).await?; @@ -81,10 +63,10 @@ pub async fn cmd_update(config: Cfg, liststack: Vec, clean: bool, direct_d if !clean { for ver in current_versions { if delete_old { - println!("Deleting version {} for mod {}", ver.0, ver.1); + println!("\t └Delete version {}", ver.0); delete_version(current_list.clone(), ver.0)?; } else if ver.0 != "NONE" { - println!("Disabling version {} for mod {}", ver.0, ver.1); + println!("\t └Disable version {}", ver.0); disable_version(config.clone(), current_list.clone(), ver.0, ver.1)?; }; } @@ -95,8 +77,8 @@ pub async fn cmd_update(config: Cfg, liststack: Vec, clean: bool, direct_d Ok(()) } -async fn specific_update(config: Cfg, clean: bool, list: List, project: Project) -> MLE { - let applicable_versions = versions(String::from(&config.apis.modrinth), String::from(&project.id), list.clone()).await; +async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> MLE { + let applicable_versions = versions(String::from(&config.apis.modrinth), String::from(&id), list.clone()).await; let mut versions: Vec = vec![]; @@ -108,12 +90,20 @@ async fn specific_update(config: Cfg, clean: bool, list: List, project: Project) versions.push(String::from("NONE")); } - let mut current: Vec = vec![]; - if clean || (versions.join("|") != userlist_get_applicable_versions(config.clone(), String::from(&list.id), String::from(&project.id))?) { - //get new versions - println!("\t └Get versions for specified minecraft versions"); + //TODO Split clean and no match + if clean || (versions.join("|") != userlist_get_applicable_versions(config.clone(), String::from(&list.id), String::from(&id))?) { + let current_str = extract_current_version(applicable_versions.clone())?; + + if clean { + println!("\t └Add version to downloadstack"); + } else { + println!("\t └Get versions for specified minecraft versions"); + println!("\t └New current version: {}", current_str); + }; + + //get new versions let current_ver = match applicable_versions.into_iter().find(|ver| ver.id == current_str).ok_or("!no current version in applicable_versions") { Ok(v) => Ok(v), Err(e) => Err(MLError::new(ErrorType::Other, e)), @@ -124,7 +114,7 @@ async fn specific_update(config: Cfg, clean: bool, list: List, project: Project) Ok(p) => Ok(p), Err(e) => Err(MLError::new(ErrorType::Other, e)), }?.url; - userlist_change_versions(config, list.id, current_str, versions.join("|"), link, project.id)?; + userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id)?; } if current.is_empty() { return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")) }; @@ -139,7 +129,7 @@ async fn download_updates_test() { use crate::{modrinth::{Version, VersionFile, Hash, VersionType}, Modloader, List}; let config = Cfg::init("modlist.toml").unwrap(); - let current_list = List { id: String::from("..."), mc_version: String::from("..."), modloader: Modloader::Forge, download_folder: String::from("./dl") }; + 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(), -- cgit v1.2.3