From 889dc4f87b05d838b25428478a8c42dac454a5cf Mon Sep 17 00:00:00 2001 From: fxqnlr Date: Mon, 7 Nov 2022 22:29:35 +0100 Subject: finished rusqlite; added all db tests --- data.db | Bin 24576 -> 24576 bytes src/commands/download.rs | 4 +- src/commands/list.rs | 27 ++- src/commands/modification.rs | 2 +- src/commands/setup.rs | 17 +- src/commands/update.rs | 13 +- src/db.rs | 406 ++++++++++++++++++------------------------- src/lib.rs | 2 +- tests/db.rs | 248 ++++++++++++++++++++++++++ tests/db_integration.rs | 115 ------------ 10 files changed, 451 insertions(+), 383 deletions(-) create mode 100644 tests/db.rs delete mode 100644 tests/db_integration.rs diff --git a/data.db b/data.db index 07e57ad..5308bbc 100644 Binary files a/data.db and b/data.db differ diff --git a/src/commands/download.rs b/src/commands/download.rs index 05c54cb..993294b 100644 --- a/src/commands/download.rs +++ b/src/commands/download.rs @@ -4,12 +4,12 @@ use reqwest::Client; use futures_util::StreamExt; -use crate::{get_current_list, config::Cfg, db::get_dl_links}; +use crate::{get_current_list, config::Cfg, db::userlist_get_all_downloads}; pub async fn download(config: Cfg) -> Result<(), Box> { let list = get_current_list(config.clone())?; - let links = get_dl_links(config.clone(), list)?; + let links = userlist_get_all_downloads(config.clone(), list.id)?; download_links(config, links).await?; diff --git a/src/commands/list.rs b/src/commands/list.rs index ffa5926..6c80e4e 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs @@ -1,8 +1,8 @@ use std::io::{Error, ErrorKind}; -use crate::{db::{lists_insert, remove_list, change_list, get_lists, get_current_list_id, get_list}, Modloader, config::Cfg, input::Input}; +use crate::{db::{lists_insert, lists_remove, config_change_current_list, lists_get_all_ids, config_get_current_list, lists_get}, Modloader, config::Cfg, input::Input}; -#[derive(Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct List { pub id: String, pub mc_version: String, @@ -12,8 +12,8 @@ pub struct List { pub fn list(config: Cfg, args: Option>) -> Result<(), Box> { if args.is_none() { - let lists = get_lists(config.clone())?; - let current_list = get_current_list_id(config)?; + let lists = lists_get_all_ids(config.clone())?; + let current_list = config_get_current_list(config)?; println!("Your lists:\n{}\n-----\nCurrently selected list: \"{}\"", lists.join(",\n"), current_list); return Ok(()); } @@ -37,8 +37,8 @@ pub fn list(config: Cfg, args: Option>) -> Result<(), Box Result> { - let id = get_current_list_id(config.clone())?; - get_list(config, id) + let id = config_get_current_list(config.clone())?; + lists_get(config, id) } fn add(config: Cfg, args: Vec) -> Result<(), Box> { @@ -52,10 +52,7 @@ fn add(config: Cfg, args: Vec) -> Result<(), Box> "fabric" => Modloader::Fabric, _ => return Err(Box::new(Error::new(ErrorKind::InvalidInput, "UNKNOWN_MODLOADER"))) }; - match lists_insert(config, id, mc_version, mod_loader) { - Err(err) => { Err(Box::new(Error::new(ErrorKind::Other, "TBD"))) }, - Ok(()) => Ok(()), - } + lists_insert(config, id, mc_version, mod_loader) }, 5.. => Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_MANY_ARGUMENTS"))), _ => panic!("list arguments should never be zero or lower"), @@ -63,13 +60,13 @@ fn add(config: Cfg, args: Vec) -> Result<(), Box> } fn change(config: Cfg, args: Vec) -> Result<(), Box> { - let lists = get_lists(config.clone())?; + let lists = lists_get_all_ids(config.clone())?; match args.len() { 1 => { let list = String::from(&args[0]); if !lists.contains(&list) { return Err(Box::new(Error::new(ErrorKind::NotFound, "LIST_DOESNT_EXIST"))); }; - match change_list(config, list) { - Err(err) => { Err(Box::new(Error::new(ErrorKind::Other, "TBD"))) }, + match config_change_current_list(config, list) { + Err(..) => { Err(Box::new(Error::new(ErrorKind::Other, "72"))) }, Ok(()) => Ok(()), } }, @@ -81,8 +78,8 @@ fn change(config: Cfg, args: Vec) -> Result<(), Box) -> Result<(), Box> { match args.len() { 1 => { - match remove_list(config, String::from(&args[0])) { - Err(err) => { Err(Box::new(Error::new(ErrorKind::Other, "TBD"))) }, + match lists_remove(config, String::from(&args[0])) { + Err(..) => { Err(Box::new(Error::new(ErrorKind::Other, "85"))) }, Ok(()) => Ok(()), } }, diff --git a/src/commands/modification.rs b/src/commands/modification.rs index 7836735..595b677 100644 --- a/src/commands/modification.rs +++ b/src/commands/modification.rs @@ -22,7 +22,7 @@ pub async fn modification(config: Cfg, args: Option>) -> Result<(), } async fn add(config: Cfg, args: Vec) -> Result<(), Box> { - + //TODO! DO NOT PANIC IF MOD IS ALREADY IN MODS DB if args.is_empty() { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_FEW_ARGUMENTS"))); }; let current_list = get_current_list(config.clone())?; diff --git a/src/commands/setup.rs b/src/commands/setup.rs index 0940959..8c0fcfd 100644 --- a/src/commands/setup.rs +++ b/src/commands/setup.rs @@ -1,6 +1,6 @@ use std::{fs::File, path::Path, io::{Error, ErrorKind}}; -use crate::{config::Cfg, db::{db_setup, user_dbversion, create_dbversion, insert_column, get_lists, get_list, get_current_versions, insert_dl_link}, modrinth::get_raw_versions}; +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}, modrinth::get_raw_versions}; pub async fn setup(config: Cfg) -> Result<(), Box> { @@ -10,7 +10,7 @@ pub async fn setup(config: Cfg) -> Result<(), Box> { return create(config, db_file); } - match user_dbversion(config.clone()) { + match s_config_get_version(config.clone()) { Ok(ver) => { match ver.as_str() { _ => return Err(Box::new(Error::new(ErrorKind::Other, "UNKNOWN_VERSION"))) @@ -29,26 +29,25 @@ fn create(config: Cfg, db_file: String) -> Result<(), Box } async fn to_02(config: Cfg) -> Result<(), Box> { - let lists = get_lists(config.clone())?; + let lists = lists_get_all_ids(config.clone())?; for list in lists { println!("Updating {}", list); - insert_column(config.clone(), String::from(&list), String::from("current_download"), String::new())?; + s_insert_column(config.clone(), String::from(&list), String::from("current_download"), String::new())?; - let full_list = get_list(config.clone(), String::from(&list))?; + let full_list = lists_get(config.clone(), String::from(&list))?; - let versions = get_current_versions(config.clone(), full_list.clone())?; + 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(); - insert_dl_link(config.clone(), full_list.clone(), ver.project_id, file.url)?; + s_userlist_update_download(config.clone(), String::from(&full_list.id), ver.project_id, file.url)?; } }; - create_dbversion(config)?; - + s_config_create_version(config)?; Ok(()) } diff --git a/src/commands/update.rs b/src/commands/update.rs index d278a78..e383eae 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs @@ -4,7 +4,7 @@ use reqwest::Client; use futures_util::StreamExt; -use crate::{config::Cfg, modrinth::{projects, Project, versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, get_versions, get_list_version, change_list_versions}, List}; +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}, List}; pub async fn update(config: Cfg) -> Result<(), Box> { @@ -12,7 +12,7 @@ pub async fn update(config: Cfg) -> Result<(), Box> { let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?; - let mut versions = get_versions(config.clone(), mods.clone())?; + 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; @@ -54,12 +54,15 @@ async fn specific_update(config: Cfg, list: List, project: Project) -> Result = vec![]; - if versions.join("|") != get_list_version(config.clone(), list.clone(), String::from(&project.id))? { + if versions.join("|") != userlist_get_applicable_versions(config.clone(), String::from(&list.id), String::from(&project.id))? { //get new versions print!(" | getting new version"); let current_str = extract_current_version(applicable_versions.clone())?; - current.push(applicable_versions.into_iter().find(|ver| ver.id == current_str).unwrap()); - change_list_versions(config, list, current_str, versions, project.id)?; + let current_ver = applicable_versions.into_iter().find(|ver| ver.id == current_str).ok_or("")?; + current.push(current_ver.clone()); + + let link = current_ver.files.into_iter().find(|f| f.primary).ok_or("")?.url; + userlist_change_versions(config, list.id, current_str, versions.join("|"), link, project.id)?; } if current.is_empty() { return Err(Box::new(Error::new(ErrorKind::NotFound, "NO_UPDATE_AVAILABLE"))) }; diff --git a/src/db.rs b/src/db.rs index 86e697e..5d82271 100644 --- a/src/db.rs +++ b/src/db.rs @@ -2,9 +2,9 @@ use std::io::{Error, ErrorKind}; use rusqlite::Connection; -use crate::{Modloader, config::Cfg, List}; +use crate::{Modloader, config::Cfg, List, get_modloader}; -//MODS +//mods pub fn mods_insert(config: Cfg, id: String, name: String, versions: Vec) -> Result<(), Box> { println!("Inserting mod {}({}) into database", name, id); @@ -75,6 +75,43 @@ pub fn mods_remove(config: Cfg, id: String) -> Result<(), Box) -> Result, Box> { + let data = format!("{}/data.db", config.data); + let connection = Connection::open(data)?; + + if mods.is_empty() { return Err(Box::new(Error::new(ErrorKind::Other, "MODS_NO_INPUT"))); } + + let mut wherestr = String::from("WHERE"); + for (i, id) in mods.iter().enumerate() { + let mut or = " OR"; + if i == mods.len() - 1 { or = "" }; + wherestr = format!("{} id = '{}'{}", wherestr, id, or); + } + + let mut versionmaps: Vec = Vec::new(); + let mut stmt = connection.prepare(dbg!(format!("SELECT id, versions FROM mods {}", wherestr).as_str()))?; + let id_iter = stmt.query_map([], |row| { + Ok(vec![row.get::(0)?, row.get::(1)?]) + })?; + + for ver in id_iter { + let version = ver?; + println!("Found versions {} for mod {}", version[1], version[0]); + versionmaps.push(DBModlistVersions { mod_id: String::from(&version[0]), versions: String::from(&version[1]) }) + }; + + match versionmaps.is_empty() { + true => Err(Box::new(Error::new(ErrorKind::NotFound, "MODS_MODS_NOT_FOUND"))), + false => Ok(versionmaps), + } +} + //userlist pub fn userlist_insert(config: Cfg, list_id: String, mod_id: String, current_version: String, applicable_versions: Vec, current_link: String) -> Result<(), Box> { println!("Inserting {} into current list({})", mod_id, list_id); @@ -119,69 +156,74 @@ pub fn userlist_remove(config: Cfg, list_id: String, mod_id: String) -> Result<( } -#[derive(Debug, Clone)] -pub struct DBModlistVersions { - pub mod_id: String, - pub versions: String, -} - -pub fn get_versions(config: Cfg, mods: Vec) -> Result, Box> { - /* +pub fn userlist_get_applicable_versions(config: Cfg, list_id: String, mod_id: String) -> Result> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); + let connection = Connection::open(data).unwrap(); - let mut wherestr = String::from("WHERE"); - for (i, id) in mods.iter().enumerate() { - let mut or = " OR"; - if i == mods.len() - 1 { or = "" } - println!("Pushing {}({}) | OR: '{}'", id, i, or); - wherestr = format!("{} id = '{}'{}", wherestr, id, or); - } + let mut version: String = String::new(); + let mut stmt = connection.prepare(format!("SELECT applicable_versions FROM {} WHERE mod_id = ?", list_id).as_str())?; + let ver_iter = stmt.query_map([mod_id], |row| { + row.get::(0) + })?; - let sql = format!("SELECT id, versions FROM mods {}", wherestr); + for ver in ver_iter { + println!("Found id {:?}", ver); + version = ver?; + }; - dbg!(&sql); + match version.is_empty() { + true => Err(Box::new(Error::new(ErrorKind::NotFound, "MOD_NOT_FOUND"))), + false => Ok(version), + } +} - let mut versionmaps: Vec = Vec::new(); - //TODO catch sql errors better - let mut cursor = connection.prepare(sql).unwrap().into_cursor(); +pub fn userlist_get_all_current_version_ids(config: Cfg, list_id: String) -> Result, Box> { + let data = format!("{}/data.db", config.data); + let connection = Connection::open(data)?; - while let Some(Ok(row)) = cursor.next() { - println!("{}: {}", row.get::(0), row.get::(1)); - versionmaps.push(DBModlistVersions { mod_id: row.get::(0), versions: row.get::(1) }) + let mut versions: Vec = Vec::new(); + let mut stmt = connection.prepare(format!("SELECT current_version FROM {}", list_id).as_str())?; + let id_iter = stmt.query_map([], |row| { + row.get::(0) + })?; + + for id in id_iter { + versions.push(id?); }; - if versionmaps.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; + if versions.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; - Ok(versionmaps) - */ - Ok(vec![DBModlistVersions { mod_id: String::new(), versions: String::new() }]) + Ok(versions) } -pub fn get_list_version(config: Cfg, list: List, mod_id: String) -> Result> { - /* +pub fn userlist_change_versions(config: Cfg, list_id: String, current_version: String, versions: String, link: String, mod_id: String) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("SELECT applicable_versions FROM {} WHERE mod_id = '{}'", list.id, mod_id); - - //TODO catch sql errors better - let mut version: String = String::new(); - connection.iterate(sql, |ver| { - if ver.is_empty() { return false; }; - for &(_column, value) in ver.iter() { - version = String::from(value.unwrap()); - } - true - }).unwrap(); - - if version.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; + let connection = Connection::open(data)?; - Ok(version) - */ - Ok(String::new()) + connection.execute(format!("UPDATE {} SET current_version = ?1, applicable_versions = ?2, current_download = ?3 WHERE mod_id = ?4", list_id).as_str(), [current_version, versions, link, mod_id])?; + Ok(()) } +pub fn userlist_get_all_downloads(config: Cfg, list_id: String) -> Result, Box> { + let data = format!("{}/data.db", config.data); + let connection = Connection::open(data).unwrap(); + + let mut links: Vec = Vec::new(); + let mut stmt = connection.prepare(format!("SELECT current_download FROM {}", list_id).as_str())?; + let link_iter = stmt.query_map([], |row| { + row.get::(0) + })?; + + for link in link_iter { + let l = link?; + println!("Found link {}", String::from(&l)); + links.push(l) + }; + + if links.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; + + Ok(links) +} //lists pub fn lists_insert(config: Cfg, id: String, mc_version: String, mod_loader: Modloader) -> Result<(), Box> { @@ -196,222 +238,134 @@ pub fn lists_insert(config: Cfg, id: String, mc_version: String, mod_loader: Mod Ok(()) } -pub fn remove_list(config: Cfg, id: String) -> Result<(), Box> { - /* +pub fn lists_remove(config: Cfg, id: String) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql_list = format!("DELETE FROM lists WHERE id = '{}'", id); - let sql_table = format!("DROP TABLE '{}'", id); - let sql = format!("{};{};", sql_list, sql_table); + let connection = Connection::open(data)?; - connection.execute(sql) - */ + connection.execute("DELETE FROM lists WHERE id = ?", [&id])?; + connection.execute(format!("DROP TABLE {}", id).as_str(), [])?; Ok(()) } -pub fn get_lists(config: Cfg) -> Result, Box> { - /* +pub fn lists_get(config: Cfg, list_id: String) -> Result> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = "SELECT id FROM lists"; - - let mut list: Vec = Vec::new(); - //TODO catch sql errors better - connection.iterate(sql, |ids| { - if ids.is_empty() { return false; }; - for &(_column, value) in ids.iter() { - list.push(String::from(value.unwrap())); - } - true - }).unwrap(); - match list.is_empty() { - true => Err(Box::new(std::io::Error::new(ErrorKind::NotFound, "NO_LISTS"))), - false => Ok(list), - } - */ - Ok(vec![String::new()]) -} - -pub fn get_current_versions(config: Cfg, list: List) -> Result, Box> { - /* - let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("SELECT current_version FROM {}", list.id); + let connection = Connection::open(data).unwrap(); - dbg!(&sql); + let mut list = List { id: String::new(), mc_version: String::new(), modloader: Modloader::Fabric }; + let mut stmt = connection.prepare("SELECT mc_version, modloader FROM lists WHERE id = ?")?; - let mut versions: Vec = Vec::new(); - //TODO catch sql errors better - let mut cursor = connection.prepare(sql).unwrap().into_cursor(); + let list_iter = stmt.query_map([&list_id], |row| { + Ok(vec![row.get::(0)?, row.get::(1)?]) + })?; - while let Some(Ok(row)) = cursor.next() { - versions.push(row.get::(0)); + for l in list_iter { + let li = l?; + list = List { id: String::from(&list_id), mc_version: String::from(&li[0]), modloader: get_modloader(String::from(&li[1]))? }; }; - if versions.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; - - Ok(versions) - */ - Ok(vec![String::new()]) -} - -pub fn get_list(config: Cfg, id: String) -> Result> { - /* - let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("SELECT mc_version, modloader FROM lists WHERE id = '{}'", id); + if list.id.is_empty() { return Err(Box::new(Error::new(ErrorKind::Other, "LIST_NOT_FOUND"))); } - let mut list = vec![]; - //TODO catch sql errors better - connection.iterate(sql, |ids| { - if ids.is_empty() { return false; }; - for &(_column, value) in ids.iter() { - list.push(String::from(value.unwrap())); - } - true - }).unwrap(); - - if list.len() != 2 { return Err(Box::new(std::io::Error::new(ErrorKind::InvalidData, "LIST_MISSING_DATA"))) }; - - Ok(List { id, mc_version: String::from(&list[0]), modloader: get_modloader(String::from(&list[1]))? }) - */ - Ok(List { id: String::new(), mc_version: String::new(), modloader: Modloader::Fabric }) + Ok(list) } -pub fn change_list_versions(config: Cfg, list: List, current_version: String, versions: Vec, mod_id: String) -> Result<(), Box> { - /* +pub fn lists_get_all_ids(config: Cfg) -> Result, Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); + let connection = Connection::open(data).unwrap(); + + let mut list_ids: Vec = Vec::new(); + let mut stmt = connection.prepare("SELECT id FROM lists")?; + let id_iter = stmt.query_map([], |row| { + row.get::(0) + })?; - let sql = format!("UPDATE {} SET current_version = '{}', applicable_versions = '{}' WHERE mod_id = '{}'", list.id, current_version, versions.join("|"), mod_id); + for id in id_iter { + println!("Found id {:?}", id.as_ref().unwrap()); + list_ids.push(id?) + }; - connection.execute(sql) - */ - Ok(()) + match list_ids.is_empty() { + true => Err(Box::new(std::io::Error::new(ErrorKind::NotFound, "NO_LISTS"))), + false => Ok(list_ids), + } } -//DOWNLOAD - -pub fn insert_dl_link(config: Cfg, list: List, mod_id: String, link: String) -> Result<(), Box> { - /* +//config +pub fn config_change_current_list(config: Cfg, id: String) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("UPDATE {} SET current_download = '{}' WHERE mod_id = '{}'", list.id, link, mod_id); + let connection = Connection::open(data)?; - connection.execute(sql) - */ + connection.execute("UPDATE user_config SET value = ? WHERE id = 'current_list'", [id])?; Ok(()) } -pub fn get_dl_links(config: Cfg, list: List) -> Result, Box> { - /* +pub fn config_get_current_list(config: Cfg) -> Result> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("SELECT current_download FROM {}", list.id); - - dbg!(&sql); - - let mut links: Vec = Vec::new(); - //TODO catch sql errors better - let mut cursor = connection.prepare(sql).unwrap().into_cursor(); + let connection = Connection::open(data).unwrap(); + + let mut list_id = String::new(); + let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'current_list'")?; + let list_iter = stmt.query_map([], |row| { + row.get::(0) + })?; - while let Some(Ok(row)) = cursor.next() { - links.push(row.get::(0)); + for list in list_iter { + list_id = list?; }; - if links.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; - - Ok(links) - */ - Ok(vec![String::new()]) + if list_id.is_empty() { return Err(Box::new(Error::new(ErrorKind::Other, "NO_CURRENT_LIST"))); } + + Ok(list_id) } -//config -pub fn change_list(config: Cfg, id: String) -> Result<(), Box> { - /* +//SETUP(UPDATES) +pub fn s_userlist_update_download(config: Cfg, list_id: String, mod_id: String, link: String) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("UPDATE user_config SET value = '{}' WHERE id = 'current_list'", id); + let connection = Connection::open(data)?; - connection.execute(sql) - */ + connection.execute(format!("UPDATE {} SET current_download = ?1 WHERE mod_id = ?2", list_id).as_str(), [link, mod_id])?; Ok(()) } -pub fn get_current_list_id(config: Cfg) -> Result> { - /* +pub fn s_config_create_version(config: Cfg) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); + let connection = Connection::open(data)?; - let sql = "SELECT id FROM lists"; - - let mut list: String = String::new(); - //TODO catch sql errors better - connection.iterate(sql, |ids| { - if ids.is_empty() { return false; }; - for &(_column, value) in ids.iter() { - list = String::from(value.unwrap()); - } - true - }).unwrap(); - if list.is_empty() { - get_lists(config)?; - panic!("current list field should never be empty if there are other lists"); - }; - Ok(list) - */ - Ok(String::new()) + connection.execute("INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' )", ())?; + Ok(()) } -pub fn update_dbversion(config: Cfg, ver: String) -> Result<(), Box> { - /* +pub fn s_config_update_version(config: Cfg, ver: String) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("UPDATE user_config SET value = '{}' WHERE id = 'db_version'", ver); + let connection = Connection::open(data)?; - connection.execute(sql) - */ + connection.execute("UPDATE user_config SET value = ? WHERE id = 'db_version'", [ver])?; Ok(()) } -pub fn create_dbversion(config: Cfg) -> Result<(), Box> { - /* +pub fn s_config_get_version(config: Cfg) -> Result> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - let sql = "INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' );"; - connection.execute(sql) - */ - Ok(()) + let connection = Connection::open(data)?; + + let mut version: String = String::new(); + let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'db_version'")?; + let ver_iter = stmt.query_map([], |row| { + row.get::(0) + })?; + + for ver in ver_iter { + version = ver?; + }; + + if version.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_DBVERSION"))); }; + Ok(version) } -pub fn user_dbversion(config: Cfg) -> Result> { - /* +pub fn s_insert_column(config: Cfg, table: String, column: String, c_type: String) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); + let connection = Connection::open(data)?; - let sql = "SELECT db_version FROM user_config"; - - let mut ver: String = String::new(); - //TODO catch sql errors better - connection.iterate(sql, |ids| { - if ids.is_empty() { return false; }; - for &(_column, value) in ids.iter() { - ver = String::from(value.unwrap()); - } - true - })?; - if ver.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_DBVERSION"))); }; - Ok(ver) - */ - Ok(String::from("0.2")) + connection.execute(format!("ALTER TABLE {} ADD '{}' {}", table, column, c_type).as_str(), ())?; + Ok(()) } pub fn db_setup(config: Cfg) -> Result<(), Box> { @@ -432,21 +386,3 @@ pub fn db_setup(config: Cfg) -> Result<(), Box> { Ok(()) } -pub fn insert_column(config: Cfg, table: String, column: String, c_type: String) -> Result<(), Box> { - /* - let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let ct = match c_type { - sqlite::Type::Null => "NULL", - sqlite::Type::Float => "FLOAT", - sqlite::Type::Binary => "BINARY", - sqlite::Type::String => "TEXT", - sqlite::Type::Integer => "INT", - }; - - let sql = format!("ALTER TABLE {} ADD '{}' {}", table, column, ct); - connection.execute(sql) - */ - Ok(()) -} diff --git a/src/lib.rs b/src/lib.rs index e059293..1e7ebbf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ use std::io::{Error, ErrorKind}; pub use apis::*; pub use commands::*; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum Modloader { Fabric, Forge diff --git a/tests/db.rs b/tests/db.rs new file mode 100644 index 0000000..16061d0 --- /dev/null +++ b/tests/db.rs @@ -0,0 +1,248 @@ +use std::{fs::{File, create_dir_all}, path::Path, sync::Once}; + +use modlist::{config::{Cfg, Apis}, db::{mods_insert, db_setup, mods_get_all_ids, mods_get_id, mods_remove, userlist_insert, lists_insert, userlist_get_all_ids, userlist_remove, mods_get_versions, userlist_get_applicable_versions, lists_remove, lists_get, lists_get_all_ids, userlist_get_all_current_version_ids, userlist_change_versions, s_userlist_update_download, userlist_get_all_downloads, config_change_current_list, config_get_current_list, s_config_update_version, s_config_create_version, s_config_get_version}, Modloader, List}; + +static INIT: Once = Once::new(); + +fn setup() -> Cfg { + let db_pathstr = "./test_tmp/db"; + + let config = Cfg { data: String::from(db_pathstr), downloads: String::from("-"), clean_remove: false, apis: Apis { modrinth: String::from("-") } }; + + INIT.call_once(|| { + let db_path = Path::new(db_pathstr); + create_dir_all(db_path).unwrap(); + let db_filestr = format!("{}/data.db", db_pathstr); + File::create(db_filestr).unwrap(); + println!("INIT TEST DB"); + db_setup(config.clone()).unwrap(); + }); + config +} + +#[test] +fn test_mods_insert() { + let config = setup(); + + mods_insert(config.clone(), String::from("I"), String::from("INSERT_TEST"), vec![String::from("INSERT_VER1"), String::from("INSERT_VER2")]).unwrap(); + let ids = mods_get_all_ids(config).unwrap(); + + assert!(ids.contains(&String::from("I"))); +} + +#[test] +fn test_mods_get_all_ids() { + let config = setup(); + + mods_insert(config.clone(), String::from("GAI1"), String::from("GETALLIDS_TEST1"), vec![String::from("GAI1_VER1"), String::from("GAI1_VER2")]).unwrap(); + mods_insert(config.clone(), String::from("GAI2"), String::from("GETALLIDS_TEST2"), vec![String::from("GAI2_VER1"), String::from("GAI2_VER2")]).unwrap(); + let ids = mods_get_all_ids(config).unwrap(); + + assert!(ids.contains(&String::from("GAI1"))); + assert!(ids.contains(&String::from("GAI2"))); +} + +#[test] +fn test_mods_get_id() { + let config = setup(); + + mods_insert(config.clone(), String::from("GI"), String::from("GETID_TEST"), vec![String::from("GI_VER1"), String::from("GI_VER2")]).unwrap(); +} + +#[test] +fn test_mods_remove() { + let config = setup(); + + mods_insert(config.clone(), String::from("R"), String::from("REMOVE_TEST"), vec![String::from("R_VER1"), String::from("R_VER2")]).unwrap(); + let ids = mods_get_all_ids(config.clone()).unwrap(); + assert!(ids.contains(&String::from("R"))); + mods_remove(config.clone(), String::from("R")).unwrap(); + assert!(mods_get_id(config, String::from("REMOVE_TEST")).is_err()); +} + +#[test] +fn test_mods_get_versions() { + let config = setup(); + + mods_insert(config.clone(), String::from("M_GVs1"), String::from("M_GVs_TEST1"), vec![String::from("M_GVs1_VER1"), String::from("M_GVs1_VER2")]).unwrap(); + mods_insert(config.clone(), String::from("M_GVs2"), String::from("M_GVs_TEST2"), vec![String::from("M_GVs2_VER1"), String::from("M_GVs2_VER2")]).unwrap(); + let versions = mods_get_versions(config, vec![String::from("M_GVs1"), String::from("M_GVs2")]).unwrap(); + + assert!(versions.contains(&modlist::db::DBModlistVersions { mod_id: String::from("M_GVs1"), versions: String::from("M_GVs1_VER1|M_GVs1_VER2") })); + assert!(versions.contains(&modlist::db::DBModlistVersions { mod_id: String::from("M_GVs2"), versions: String::from("M_GVs2_VER1|M_GVs2_VER2") })); +} + +//user_list +#[test] +fn test_userlist_insert() { + let config = setup(); + + lists_insert(config.clone(), String::from("UL_I_LIST"), String::from("UL_I_MC"), Modloader::Fabric).unwrap(); + userlist_insert(config, String::from("UL_I_LIST"), String::from("UL_I"), String::from("UL_I_VER1"), vec![String::from("UL_I_VER1"), String::from("UL_I_VER2")], String::from("localhost:8080/dl/UL_I_VER1.test")).unwrap(); +} + +#[test] +fn test_userlist_get_all_ids() { + let config = setup(); + + lists_insert(config.clone(), String::from("UL_GAI_LIST"), String::from("UL_GAI_MC"), Modloader::Fabric).unwrap(); + userlist_insert(config.clone(), String::from("UL_GAI_LIST"), String::from("UL_GAI1"), String::from("UL_GAI1_VER1"), vec![String::from("UL_GAI2_VER1"), String::from("UL_GAI1_VER2")], String::from("localhost:8080/dl/UL_GAI1_VER1.test")).unwrap(); + userlist_insert(config.clone(), String::from("UL_GAI_LIST"), String::from("UL_GAI2"), String::from("UL_GAI2_VER1"), vec![String::from("UL_GAI2_VER1"), String::from("UL_GAI2_VER2")], String::from("localhost:8080/dl/UL_GAI2_VER1.test")).unwrap(); + let ids = userlist_get_all_ids(config, String::from("UL_GAI_LIST")).unwrap(); + + assert!(ids.contains(&String::from("UL_GAI1"))); + assert!(ids.contains(&String::from("UL_GAI2"))); +} + +#[test] +fn test_userlist_remove() { + let config = setup(); + + lists_insert(config.clone(), String::from("UL_R_LIST"), String::from("UL_R_MC"), Modloader::Fabric).unwrap(); + userlist_insert(config.clone(), String::from("UL_R_LIST"), String::from("UL_R"), String::from("UL_R_VER1"), vec![String::from("UL_R_VER1"), String::from("UL_R_VER2")], String::from("localhost:8080/dl/UL_R_VER1.test")).unwrap(); + let ids = userlist_get_all_ids(config.clone(), String::from("UL_R_LIST")).unwrap(); + assert!(ids.contains(&String::from("UL_R"))); + userlist_remove(config.clone(), String::from("UL_R_LIST"), String::from("UL_R")).unwrap(); + assert!(userlist_get_all_ids(config, String::from("UL_R_LIST")).is_err()) +} + +#[test] +fn test_userlist_get_applicable_versions() { + let config = setup(); + + lists_insert(config.clone(), String::from("UL_GAV_LIST"), String::from("UL_GAV_MC"), Modloader::Fabric).unwrap(); + userlist_insert(config.clone(), String::from("UL_GAV_LIST"), String::from("UL_GAV"), String::from("UL_GAV_VER1"), vec![String::from("UL_GAV_VER1"), String::from("UL_GAV_VER2")], String::from("localhost:8080/dl/UL_GAV_VER1.test")).unwrap(); + assert_eq!(userlist_get_applicable_versions(config, String::from("UL_GAV_LIST"), String::from("UL_GAV")).unwrap(), String::from("UL_GAV_VER1|UL_GAV_VER2")); +} + +#[test] +fn test_userlist_get_all_current_version_ids() { + let config = setup(); + + lists_insert(config.clone(), String::from("UL_GACVI_LIST"), String::from("UL_GACVI_MC"), Modloader::Fabric).unwrap(); + userlist_insert(config.clone(), String::from("UL_GACVI_LIST"), String::from("UL_GACVI1"), String::from("UL_GACVI1_VER1"), vec![String::from("UL_GACVI2_VER1"), String::from("UL_GACVI1_VER2")], String::from("localhost:8080/dl/UL_GACVI1_VER1.test")).unwrap(); + userlist_insert(config.clone(), String::from("UL_GACVI_LIST"), String::from("UL_GACVI2"), String::from("UL_GACVI2_VER1"), vec![String::from("UL_GACVI2_VER1"), String::from("UL_GACVI2_VER2")], String::from("localhost:8080/dl/UL_GACVI2_VER1.test")).unwrap(); + + let ids = userlist_get_all_current_version_ids(config, String::from("UL_GACVI_LIST")).unwrap(); + + assert!(ids.contains(&String::from("UL_GACVI1_VER1"))); + assert!(ids.contains(&String::from("UL_GACVI2_VER1"))); +} + +#[test] +fn test_userlist_change_versions() { + let config = setup(); + + lists_insert(config.clone(), String::from("UL_CV_LIST"), String::from("UL_CV_MC"), Modloader::Fabric).unwrap(); + userlist_insert(config.clone(), String::from("UL_CV_LIST"), String::from("UL_CV"), String::from("UL_CV_VER1"), vec![String::from("UL_CV_VER1"), String::from("UL_CV_VER2")], String::from("localhost:8080/dl/UL_CV_VER1.test")).unwrap(); + let versions = userlist_get_all_current_version_ids(config.clone(), String::from("UL_CV_LIST")).unwrap(); + assert!(versions.contains(&String::from("UL_CV_VER1"))); + + userlist_change_versions(config.clone(), String::from("UL_CV_LIST"), String::from("UL_CV_VER3"), String::from("UL_CV_VER1|UL_CV_VER2|UL_CV_VER3"), String::from("localhost:8080/dl/UL_CV_VER3.test"), String::from("UL_CV")).unwrap(); + let versions = userlist_get_all_current_version_ids(config, String::from("UL_CV_LIST")).unwrap(); + assert!(!versions.contains(&String::from("UL_CV_VER1"))); + assert!(versions.contains(&String::from("UL_CV_VER3"))); +} + +#[test] +fn test_userlist_get_all_downloads() { + let config = setup(); + + lists_insert(config.clone(), String::from("UL_GAD_LIST"), String::from("UL_GAD_MC"), Modloader::Fabric).unwrap(); + userlist_insert(config.clone(), String::from("UL_GAD_LIST"), String::from("UL_GAD1"), String::from("UL_GAD1_VER1"), vec![String::from("UL_GAD1_VER1"), String::from("UL_GAD1_VER1")], String::from("localhost:8080/dl/UL_GAD1_VER1.test")).unwrap(); + userlist_insert(config.clone(), String::from("UL_GAD_LIST"), String::from("UL_GAD2"), String::from("UL_GAD2_VER1"), vec![String::from("UL_GAD2_VER1"), String::from("UL_GAD2_VER1")], String::from("localhost:8080/dl/UL_GAD2_VER1.test")).unwrap(); + let links = userlist_get_all_downloads(config, String::from("UL_GAD_LIST")).unwrap(); + + assert!(links.contains(&String::from("localhost:8080/dl/UL_GAD1_VER1.test"))); + assert!(links.contains(&String::from("localhost:8080/dl/UL_GAD2_VER1.test"))); +} + + +//lists +#[test] +fn test_lists_insert() { + let config = setup(); + + lists_insert(config, String::from("L_I_LIST"), String::from("L_I_MC"), Modloader::Fabric).unwrap(); +} + +#[test] +fn test_lists_remove() { + let config = setup(); + + lists_insert(config.clone(), String::from("L_R_LIST"), String::from("L_R_MC"), Modloader::Fabric).unwrap(); + lists_remove(config, String::from("L_R_LIST")).unwrap(); +} + +#[test] +fn test_lists_get() { + let config = setup(); + + lists_insert(config.clone(), String::from("L_G_LIST"), String::from("L_G_MC"), Modloader::Fabric).unwrap(); + + assert_eq!(lists_get(config, String::from("L_G_LIST")).unwrap(), List { id: String::from("L_G_LIST"), mc_version: String::from("L_G_MC"), modloader: Modloader::Fabric }); +} + +#[test] +fn test_lists_get_all_ids() { + let config = setup(); + + lists_insert(config.clone(), String::from("L_GAI1_LIST"), String::from("L_GAI1_MC"), Modloader::Fabric).unwrap(); + lists_insert(config.clone(), String::from("L_GAI2_LIST"), String::from("L_GAI2_MC"), Modloader::Fabric).unwrap(); + let ids = lists_get_all_ids(config).unwrap(); + + assert!(ids.contains(&String::from("L_GAI1_LIST"))); + assert!(ids.contains(&String::from("L_GAI2_LIST"))); +} + +//config +#[test] +fn test_config_change_current_list() { + let config = setup(); + + config_change_current_list(config, String::from("C_CCL_LIST")).unwrap(); +} + +#[test] +fn test_config_get_current_list() { + let config = setup(); + + config_change_current_list(config.clone(), String::from("C_GCL_LIST")).unwrap(); + assert_eq!(config_get_current_list(config).unwrap(), String::from("C_GCL_LIST")); +} + +//setup +#[test] +fn test_s_userlist_update_download() { + let config = setup(); + + lists_insert(config.clone(), String::from("UL_UD_LIST"), String::from("UL_UD_MC"), Modloader::Fabric).unwrap(); + userlist_insert(config.clone(), String::from("UL_UD_LIST"), String::from("UL_UD"), String::from("UL_UD_VER1"), vec![String::from("UL_UD_VER1"), String::from("UL_UD_VER1")], String::from("localhost:8080/dl/UL_UD_VER1.test")).unwrap(); + s_userlist_update_download(config.clone(), String::from("UL_UD_LIST"), String::from("UL_UD"), String::from("localhost:8080/dl/UL_UD_VER1X.test")).unwrap(); + let links = userlist_get_all_downloads(config, String::from("UL_UD_LIST")).unwrap(); + + assert!(links.contains(&String::from("localhost:8080/dl/UL_UD_VER1X.test"))); + assert!(!links.contains(&String::from("localhost:8080/dl/UL_UD_VER1.test"))); +} + +#[test] +fn test_s_config_create_version() { + let config = setup(); + + s_config_create_version(config).unwrap(); +} + +#[test] +fn test_s_config_update_version() { + let config = setup(); + + s_config_update_version(config, String::from("S_C_UV")).unwrap(); +} + +#[test] +fn test_s_config_get_version() { + let config = setup(); + + s_config_update_version(config.clone(), String::from("S_C_GV")).unwrap(); + assert_eq!(s_config_get_version(config).unwrap(), String::from("S_C_GV")); +} diff --git a/tests/db_integration.rs b/tests/db_integration.rs deleted file mode 100644 index 8c3d194..0000000 --- a/tests/db_integration.rs +++ /dev/null @@ -1,115 +0,0 @@ -use std::{fs::{File, create_dir_all}, path::Path, sync::Once}; - -use modlist::{config::{Cfg, Apis}, db::{mods_insert, db_setup, user_dbversion, mods_get_all_ids, mods_get_id, mods_remove, userlist_insert, lists_insert, userlist_get_all_ids, userlist_remove}, Modloader}; - -static INIT: Once = Once::new(); - -fn setup() -> Cfg { - let db_pathstr = "./test_tmp/db"; - - let config = Cfg { data: String::from(db_pathstr), downloads: String::from("-"), clean_remove: false, apis: Apis { modrinth: String::from("-") } }; - - INIT.call_once(|| { - let db_path = Path::new(db_pathstr); - create_dir_all(db_path).unwrap(); - let db_filestr = format!("{}/data.db", db_pathstr); - File::create(db_filestr).unwrap(); - println!("INIT TEST DB"); - db_setup(config.clone()).unwrap(); - }); - config -} - -#[test] -fn test_user_dbversion() { - let config = setup(); - - assert_eq!(user_dbversion(config).unwrap(), "0.2"); -} - -#[test] -fn test_mods_insert() { - let config = setup(); - - mods_insert(config.clone(), String::from("I"), String::from("INSERT_TEST"), vec![String::from("INSERT_VER1"), String::from("INSERT_VER2")]).unwrap(); - let ids = mods_get_all_ids(config).unwrap(); - - assert!(ids.contains(&String::from("I"))); -} - -#[test] -fn test_mods_get_all_ids() { - let config = setup(); - - mods_insert(config.clone(), String::from("GAI1"), String::from("GETALLIDS_TEST1"), vec![String::from("GAI1_VER1"), String::from("GAI1_VER2")]).unwrap(); - mods_insert(config.clone(), String::from("GAI2"), String::from("GETALLIDS_TEST2"), vec![String::from("GAI2_VER1"), String::from("GAI2_VER2")]).unwrap(); - let ids = mods_get_all_ids(config).unwrap(); - - assert!(ids.contains(&String::from("GAI1"))); - assert!(ids.contains(&String::from("GAI2"))); -} - -#[test] -fn test_mods_get_id() { - let config = setup(); - - mods_insert(config.clone(), String::from("GI"), String::from("GETID_TEST"), vec![String::from("GI_VER1"), String::from("GI_VER2")]).unwrap(); - let id = mods_get_id(config, String::from("GETID_TEST")).unwrap(); - - assert_eq!(id, String::from("GI")); -} - -#[test] -fn test_mods_remove() { - let config = setup(); - - mods_insert(config.clone(), String::from("R"), String::from("REMOVE_TEST"), vec![String::from("R_VER1"), String::from("R_VER2")]).unwrap(); - let ids = mods_get_all_ids(config.clone()).unwrap(); - assert!(ids.contains(&String::from("R"))); - mods_remove(config.clone(), String::from("R")).unwrap(); - assert!(mods_get_id(config, String::from("REMOVE_TEST")).is_err()); -} - -//user_list -#[test] -fn test_userlist_insert() { - let config = setup(); - - lists_insert(config.clone(), String::from("UL_I_LIST"), String::from("UL_I_MC"), Modloader::Fabric).unwrap(); - userlist_insert(config, String::from("UL_I_LIST"), String::from("UL_I"), String::from("UL_I_VER1"), vec![String::from("UL_I_VER1"), String::from("UL_I_VER2")], String::from("localhost:8080/dl/UL_I_VER1.test")).unwrap(); - //let list = mods_get_all_ids(config).unwrap(); - - //assert!(ids.contains(&String::from("I"))); -} - -#[test] -fn test_userlist_get_all_ids() { - let config = setup(); - - lists_insert(config.clone(), String::from("UL_GAI_LIST"), String::from("UL_GAI_MC"), Modloader::Fabric).unwrap(); - userlist_insert(config.clone(), String::from("UL_GAI_LIST"), String::from("UL_GAI1"), String::from("UL_GAI1_VER1"), vec![String::from("UL_GAI2_VER1"), String::from("UL_GAI1_VER2")], String::from("localhost:8080/dl/UL_GAI1_VER1.test")).unwrap(); - userlist_insert(config.clone(), String::from("UL_GAI_LIST"), String::from("UL_GAI2"), String::from("UL_GAI2_VER1"), vec![String::from("UL_GAI2_VER1"), String::from("UL_GAI2_VER2")], String::from("localhost:8080/dl/UL_GAI2_VER1.test")).unwrap(); - let ids = userlist_get_all_ids(config, String::from("UL_GAI_LIST")).unwrap(); - - assert!(ids.contains(&String::from("UL_GAI1"))); - assert!(ids.contains(&String::from("UL_GAI2"))); -} - -#[test] -fn test_userlist_remove() { - let config = setup(); - - lists_insert(config.clone(), String::from("UL_R_LIST"), String::from("UL_R_MC"), Modloader::Fabric).unwrap(); - userlist_insert(config.clone(), String::from("UL_R_LIST"), String::from("UL_R"), String::from("UL_R_VER1"), vec![String::from("UL_R_VER1"), String::from("UL_R_VER2")], String::from("localhost:8080/dl/UL_R_VER1.test")).unwrap(); - let ids = userlist_get_all_ids(config.clone(), String::from("UL_R_LIST")).unwrap(); - assert!(ids.contains(&String::from("UL_R"))); - userlist_remove(config.clone(), String::from("UL_R_LIST"), String::from("UL_R")).unwrap(); - assert!(userlist_get_all_ids(config, String::from("UL_R_LIST")).is_err()) -} -//lists -#[test] -fn test_lists_insert() { - let config = setup(); - - lists_insert(config, String::from("TESTLIST"), String::from("L_I_LIST"), Modloader::Fabric).unwrap(); -} -- cgit v1.2.3