diff options
author | fxqnlr <[email protected]> | 2024-09-04 17:32:19 +0200 |
---|---|---|
committer | fxqnlr <[email protected]> | 2024-09-04 17:32:19 +0200 |
commit | ecc4743fdec43eb578e9c35bb008c68909f1517e (patch) | |
tree | 73916114bc2bff8c72f759f5aae11a95d4dede22 | |
parent | 11e64fc7560de3cd0def718edf68c31e3dc8be72 (diff) | |
download | modlist-refactor.tar modlist-refactor.tar.gz modlist-refactor.zip |
better error handlingrefactor
-rw-r--r-- | Cargo.lock | 9 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/apis/modrinth.rs | 51 | ||||
-rw-r--r-- | src/cache.rs | 12 | ||||
-rw-r--r-- | src/commands/download.rs | 44 | ||||
-rw-r--r-- | src/commands/io.rs | 29 | ||||
-rw-r--r-- | src/commands/list.rs | 38 | ||||
-rw-r--r-- | src/commands/modification.rs | 63 | ||||
-rw-r--r-- | src/commands/update.rs | 160 | ||||
-rw-r--r-- | src/config.rs | 26 | ||||
-rw-r--r-- | src/data.rs | 2 | ||||
-rw-r--r-- | src/data/gameversion.rs | 33 | ||||
-rw-r--r-- | src/data/list.rs | 4 | ||||
-rw-r--r-- | src/data/modloader.rs | 14 | ||||
-rw-r--r-- | src/data/projectinfo.rs (renamed from src/data/project.rs) | 0 | ||||
-rw-r--r-- | src/db.rs | 151 | ||||
-rw-r--r-- | src/error.rs | 129 | ||||
-rw-r--r-- | src/errors.rs | 132 | ||||
-rw-r--r-- | src/files.rs | 54 | ||||
-rw-r--r-- | src/main.rs | 6 |
20 files changed, 457 insertions, 501 deletions
@@ -957,6 +957,7 @@ dependencies = [ | |||
957 | "rusqlite", | 957 | "rusqlite", |
958 | "serde", | 958 | "serde", |
959 | "serde_json", | 959 | "serde_json", |
960 | "thiserror", | ||
960 | "tokio", | 961 | "tokio", |
961 | "toml 0.7.4", | 962 | "toml 0.7.4", |
962 | ] | 963 | ] |
@@ -1527,18 +1528,18 @@ dependencies = [ | |||
1527 | 1528 | ||
1528 | [[package]] | 1529 | [[package]] |
1529 | name = "thiserror" | 1530 | name = "thiserror" |
1530 | version = "1.0.40" | 1531 | version = "1.0.63" |
1531 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1532 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1532 | checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" | 1533 | checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" |
1533 | dependencies = [ | 1534 | dependencies = [ |
1534 | "thiserror-impl", | 1535 | "thiserror-impl", |
1535 | ] | 1536 | ] |
1536 | 1537 | ||
1537 | [[package]] | 1538 | [[package]] |
1538 | name = "thiserror-impl" | 1539 | name = "thiserror-impl" |
1539 | version = "1.0.40" | 1540 | version = "1.0.63" |
1540 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1541 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1541 | checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" | 1542 | checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" |
1542 | dependencies = [ | 1543 | dependencies = [ |
1543 | "proc-macro2", | 1544 | "proc-macro2", |
1544 | "quote", | 1545 | "quote", |
@@ -20,3 +20,4 @@ clap = { version = "4.2.1", features = ["derive"] } | |||
20 | clap_complete = "4.2.0" | 20 | clap_complete = "4.2.0" |
21 | indicatif = "0.17.3" | 21 | indicatif = "0.17.3" |
22 | config = "0.14.0" | 22 | config = "0.14.0" |
23 | thiserror = "1.0.63" | ||
diff --git a/src/apis/modrinth.rs b/src/apis/modrinth.rs index 7f1fb52..afd7b69 100644 --- a/src/apis/modrinth.rs +++ b/src/apis/modrinth.rs | |||
@@ -3,7 +3,7 @@ use reqwest::Client; | |||
3 | use serde::{Deserialize, Serialize}; | 3 | use serde::{Deserialize, Serialize}; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | error::{EType, MLErr, MLE}, | 6 | errors::{Error, MLE}, |
7 | List, | 7 | List, |
8 | }; | 8 | }; |
9 | 9 | ||
@@ -131,10 +131,7 @@ pub enum GameVersionType { | |||
131 | } | 131 | } |
132 | 132 | ||
133 | /// # Errors | 133 | /// # Errors |
134 | async fn get( | 134 | async fn get(api: &str, path: &str) -> Result<Vec<u8>, Error> { |
135 | api: &str, | ||
136 | path: &str, | ||
137 | ) -> Result<Option<Vec<u8>>, Box<dyn std::error::Error>> { | ||
138 | let url = format!(r#"{api}{path}"#); | 135 | let url = format!(r#"{api}{path}"#); |
139 | 136 | ||
140 | let client = Client::builder() | 137 | let client = Client::builder() |
@@ -145,23 +142,19 @@ async fn get( | |||
145 | .build()?; | 142 | .build()?; |
146 | let res = client.get(url).send().await?; | 143 | let res = client.get(url).send().await?; |
147 | 144 | ||
148 | let mut data: Option<Vec<u8>> = None; | 145 | if res.status() != 200 { |
149 | 146 | return Err(Error::RequestNotOK(res.status())); | |
150 | if res.status() == 200 { | ||
151 | data = Some(res.bytes().await?.to_vec()); | ||
152 | } | 147 | } |
153 | 148 | ||
154 | Ok(data) | 149 | Ok(res.bytes().await?.to_vec()) |
155 | } | 150 | } |
156 | 151 | ||
157 | /// # Errors | 152 | /// # Errors |
158 | pub async fn project(api: &str, name: &str) -> MLE<Project> { | 153 | pub async fn project(api: &str, name: &str) -> MLE<Project> { |
159 | let url = format!("project/{name}"); | 154 | let url = format!("project/{name}"); |
160 | let data = get(api, &url).await | 155 | let data = get(api, &url).await?; |
161 | .map_err(|_| MLErr::new(EType::Other, "geterr"))? | ||
162 | .ok_or(MLErr::new(EType::Other, "geterr2"))?; | ||
163 | 156 | ||
164 | serde_json::from_slice(&data).map_err(|_| MLErr::new(EType::LibJson, "from project")) | 157 | Ok(serde_json::from_slice(&data)?) |
165 | } | 158 | } |
166 | 159 | ||
167 | /// # Errors | 160 | /// # Errors |
@@ -169,11 +162,9 @@ pub async fn projects(api: &str, ids: Vec<String>) -> MLE<Vec<Project>> { | |||
169 | let all = ids.join(r#"",""#); | 162 | let all = ids.join(r#"",""#); |
170 | let url = format!(r#"projects?ids=["{all}"]"#); | 163 | let url = format!(r#"projects?ids=["{all}"]"#); |
171 | 164 | ||
172 | let data = get(api, &url).await | 165 | let data = get(api, &url).await?; |
173 | .map_err(|_| MLErr::new(EType::Other, "geterr"))? | ||
174 | .ok_or(MLErr::new(EType::Other, "geterr2"))?; | ||
175 | 166 | ||
176 | serde_json::from_slice(&data).map_err(|_| MLErr::new(EType::LibJson, "from projects")) | 167 | Ok(serde_json::from_slice(&data)?) |
177 | } | 168 | } |
178 | 169 | ||
179 | ///Get applicable versions from `mod_id` with list context | 170 | ///Get applicable versions from `mod_id` with list context |
@@ -184,12 +175,12 @@ pub async fn versions(api: &str, id: String, list: List) -> MLE<Vec<Version>> { | |||
184 | id, list.modloader, list.mc_version | 175 | id, list.modloader, list.mc_version |
185 | ); | 176 | ); |
186 | 177 | ||
187 | let data = get(api, &url).await | 178 | let data = get(api, &url).await?; |
188 | .map_err(|_| MLErr::new(EType::Other, "geterr"))?; | ||
189 | 179 | ||
190 | Ok(match data { | 180 | Ok(if data.is_empty() { |
191 | Some(data) => serde_json::from_slice(&data).map_err(|_| MLErr::new(EType::LibJson, "from version"))?, | 181 | Vec::new() |
192 | None => Vec::new(), | 182 | } else { |
183 | serde_json::from_slice(&data)? | ||
193 | }) | 184 | }) |
194 | } | 185 | } |
195 | 186 | ||
@@ -201,17 +192,15 @@ pub async fn get_raw_versions( | |||
201 | ) -> MLE<Vec<Version>> { | 192 | ) -> MLE<Vec<Version>> { |
202 | let url = format!(r#"versions?ids=["{}"]"#, versions.join(r#"",""#)); | 193 | let url = format!(r#"versions?ids=["{}"]"#, versions.join(r#"",""#)); |
203 | 194 | ||
204 | let data = get(api, &url).await | 195 | let data = get(api, &url).await?; |
205 | .map_err(|_| MLErr::new(EType::Other, "geterr"))? | ||
206 | .ok_or(MLErr::new(EType::Other, "geterr2"))?; | ||
207 | 196 | ||
208 | serde_json::from_slice(&data).map_err(|_| MLErr::new(EType::LibJson, "from raw version")) | 197 | Ok(serde_json::from_slice(&data)?) |
209 | } | 198 | } |
210 | 199 | ||
211 | /// # Errors | 200 | /// # Errors |
212 | pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> { | 201 | pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> { |
213 | match versions.len() { | 202 | match versions.len() { |
214 | 0 => Err(MLErr::new(EType::ModError, "NO_VERSIONS_AVAILABLE")), | 203 | 0 => Err(Error::ModError("NO_VERSIONS_AVAILABLE".to_string())), |
215 | 1.. => { | 204 | 1.. => { |
216 | let mut times: Vec<(String, DateTime<FixedOffset>)> = vec![]; | 205 | let mut times: Vec<(String, DateTime<FixedOffset>)> = vec![]; |
217 | for ver in versions { | 206 | for ver in versions { |
@@ -228,9 +217,7 @@ pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> { | |||
228 | /// # Errors | 217 | /// # Errors |
229 | pub async fn get_game_versions() -> MLE<Vec<GameVersion>> { | 218 | pub async fn get_game_versions() -> MLE<Vec<GameVersion>> { |
230 | let data = get("https://api.modrinth.com/v2/", "tag/game_version") | 219 | let data = get("https://api.modrinth.com/v2/", "tag/game_version") |
231 | .await | 220 | .await?; |
232 | .map_err(|_| MLErr::new(EType::Other, "geterr"))? | ||
233 | .ok_or(MLErr::new(EType::Other, "geterr2"))?; | ||
234 | 221 | ||
235 | serde_json::from_slice(&data).map_err(|_| MLErr::new(EType::LibJson, "from game version")) | 222 | Ok(serde_json::from_slice(&data)?) |
236 | } | 223 | } |
diff --git a/src/cache.rs b/src/cache.rs index 6ffeb52..199a440 100644 --- a/src/cache.rs +++ b/src/cache.rs | |||
@@ -3,15 +3,15 @@ use std::{ | |||
3 | fs::{copy, read_dir}, | 3 | fs::{copy, read_dir}, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use crate::error::{EType, MLErr, MLE}; | 6 | use crate::errors::{ConversionError, Error, MLE}; |
7 | 7 | ||
8 | /// # Errors | 8 | /// # Errors |
9 | pub fn get_cached_versions(path: &str) -> MLE<HashMap<String, String>> { | 9 | pub fn get_cached_versions(path: &str) -> MLE<HashMap<String, String>> { |
10 | let mut versions: HashMap<String, String> = HashMap::new(); | 10 | let mut versions: HashMap<String, String> = HashMap::new(); |
11 | for file in read_dir(path).map_err(|_| MLErr::new(EType::IoError, "readdir"))? { | 11 | for file in read_dir(path)? { |
12 | let path = file.map_err(|_| MLErr::new(EType::IoError, "file"))?.path(); | 12 | let path = file?.path(); |
13 | if path.is_file() && path.extension().ok_or(MLErr::new(EType::IoError, "ext"))? == "jar" { | 13 | if path.is_file() && path.extension().ok_or(Error::NoFileExtension)? == "jar" { |
14 | let pathstr = path.to_str().ok_or(MLErr::new(EType::IoError, "path"))?; | 14 | let pathstr = path.to_str().ok_or(ConversionError::InvalidPath)?; |
15 | let namesplit: Vec<&str> = pathstr.split('.').collect(); | 15 | let namesplit: Vec<&str> = pathstr.split('.').collect(); |
16 | versions.insert( | 16 | versions.insert( |
17 | String::from(namesplit[namesplit.len() - 2]), | 17 | String::from(namesplit[namesplit.len() - 2]), |
@@ -27,6 +27,6 @@ pub fn copy_cached_version(version_path: &str, download_path: &str) -> MLE<()> { | |||
27 | let versplit: Vec<&str> = version_path.split('/').collect(); | 27 | let versplit: Vec<&str> = version_path.split('/').collect(); |
28 | let download = | 28 | let download = |
29 | format!("{}/{}", download_path, versplit[versplit.len() - 1]); | 29 | format!("{}/{}", download_path, versplit[versplit.len() - 1]); |
30 | copy(version_path, download).map_err(|err| MLErr::new(EType::IoError, &err.to_string()))?; | 30 | copy(version_path, download)?; |
31 | Ok(()) | 31 | Ok(()) |
32 | } | 32 | } |
diff --git a/src/commands/download.rs b/src/commands/download.rs index 269d5d3..bb946b0 100644 --- a/src/commands/download.rs +++ b/src/commands/download.rs | |||
@@ -1,10 +1,11 @@ | |||
1 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; | 1 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; |
2 | 2 | ||
3 | use crate::apis::modrinth::get_raw_versions; | 3 | use crate::apis::modrinth::get_raw_versions; |
4 | use crate::errors::Error; | ||
4 | use crate::{config::Cfg, List}; | 5 | use crate::{config::Cfg, List}; |
5 | use crate::{ | 6 | use crate::{ |
6 | db::userlist_get_all_current_versions_with_mods, | 7 | db::userlist_get_all_current_versions_with_mods, |
7 | error::{EType, MLErr, MLE}, | 8 | errors::MLE, |
8 | files::{ | 9 | files::{ |
9 | clean_list_dir, delete_version, disable_version, download_versions, | 10 | clean_list_dir, delete_version, disable_version, download_versions, |
10 | get_downloaded_versions, | 11 | get_downloaded_versions, |
@@ -20,20 +21,22 @@ pub async fn download( | |||
20 | delete_old: bool, | 21 | delete_old: bool, |
21 | ) -> MLE<()> { | 22 | ) -> MLE<()> { |
22 | let mp = MultiProgress::new(); | 23 | let mp = MultiProgress::new(); |
23 | let download_p = mp.add(ProgressBar::new( | 24 | let download_p = mp.add(ProgressBar::new(liststack.len().try_into()?)); |
24 | liststack | ||
25 | .len() | ||
26 | .try_into() | ||
27 | .map_err(|_| MLErr::new(EType::Other, "ListStackLen"))?, | ||
28 | )); | ||
29 | download_p.set_style( | 25 | download_p.set_style( |
30 | ProgressStyle::with_template(STYLE_BAR_POS) | 26 | ProgressStyle::with_template(STYLE_BAR_POS)? |
31 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))? | ||
32 | .progress_chars(PROGRESS_CHARS), | 27 | .progress_chars(PROGRESS_CHARS), |
33 | ); | 28 | ); |
34 | 29 | ||
35 | for current_list in liststack { | 30 | for current_list in liststack { |
36 | download_list(config, mp.clone(), download_p.clone(), current_list, clean, delete_old).await?; | 31 | download_list( |
32 | config, | ||
33 | mp.clone(), | ||
34 | download_p.clone(), | ||
35 | current_list, | ||
36 | clean, | ||
37 | delete_old, | ||
38 | ) | ||
39 | .await?; | ||
37 | } | 40 | } |
38 | 41 | ||
39 | download_p.finish_with_message("Downloaded all lists"); | 42 | download_p.finish_with_message("Downloaded all lists"); |
@@ -52,13 +55,8 @@ async fn download_list( | |||
52 | download_p.set_message(format!("Download in {}", current_list.id)); | 55 | download_p.set_message(format!("Download in {}", current_list.id)); |
53 | 56 | ||
54 | let downloaded_versions = get_downloaded_versions(¤t_list)?; | 57 | let downloaded_versions = get_downloaded_versions(¤t_list)?; |
55 | let current_version_ids = match userlist_get_all_current_versions_with_mods( | 58 | let current_version_ids = |
56 | config, | 59 | userlist_get_all_current_versions_with_mods(config, ¤t_list.id)?; |
57 | ¤t_list.id, | ||
58 | ) { | ||
59 | Ok(i) => Ok(i), | ||
60 | Err(e) => Err(MLErr::new(EType::DBError, e.to_string().as_str())), | ||
61 | }?; | ||
62 | 60 | ||
63 | let mut to_download: Vec<String> = vec![]; | 61 | let mut to_download: Vec<String> = vec![]; |
64 | //(mod_id, version_id) | 62 | //(mod_id, version_id) |
@@ -74,7 +72,7 @@ async fn download_list( | |||
74 | to_download.push(current_version); | 72 | to_download.push(current_version); |
75 | } else { | 73 | } else { |
76 | let downloaded_version = | 74 | let downloaded_version = |
77 | current_download.ok_or(MLErr::new(EType::Other, "IDK, WTF"))?; | 75 | current_download.ok_or(Error::NoDownload)?; |
78 | if ¤t_version != downloaded_version { | 76 | if ¤t_version != downloaded_version { |
79 | to_disable | 77 | to_disable |
80 | .push((mod_id.clone(), String::from(downloaded_version))); | 78 | .push((mod_id.clone(), String::from(downloaded_version))); |
@@ -106,16 +104,10 @@ async fn download_list( | |||
106 | if !to_disable.is_empty() { | 104 | if !to_disable.is_empty() { |
107 | let d_p = mp.insert_before( | 105 | let d_p = mp.insert_before( |
108 | &download_p, | 106 | &download_p, |
109 | ProgressBar::new( | 107 | ProgressBar::new(to_disable.len().try_into()?), |
110 | to_disable | ||
111 | .len() | ||
112 | .try_into() | ||
113 | .map_err(|_| MLErr::new(EType::Other, "ListStackLen"))?, | ||
114 | ), | ||
115 | ); | 108 | ); |
116 | d_p.set_style( | 109 | d_p.set_style( |
117 | ProgressStyle::with_template(STYLE_BAR_POS) | 110 | ProgressStyle::with_template(STYLE_BAR_POS)? |
118 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))? | ||
119 | .progress_chars(PROGRESS_CHARS), | 111 | .progress_chars(PROGRESS_CHARS), |
120 | ); | 112 | ); |
121 | for ver in to_disable { | 113 | for ver in to_disable { |
diff --git a/src/commands/io.rs b/src/commands/io.rs index dea0d84..80bc7d6 100644 --- a/src/commands/io.rs +++ b/src/commands/io.rs | |||
@@ -4,10 +4,14 @@ use std::fs::File; | |||
4 | use std::io::prelude::*; | 4 | use std::io::prelude::*; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | config::Cfg, data::modification::{AddMod, IDSelector}, db::{ | 7 | config::Cfg, |
8 | data::modification::{AddMod, IDSelector}, | ||
9 | db::{ | ||
8 | lists_get, lists_get_all_ids, lists_insert, userlist_get_all_ids, | 10 | lists_get, lists_get_all_ids, lists_insert, userlist_get_all_ids, |
9 | userlist_get_current_version, userlist_get_set_version, | 11 | userlist_get_current_version, userlist_get_set_version, |
10 | }, error::{EType, MLErr, MLE}, mod_add, List, Modloader, STYLE_OPERATION | 12 | }, |
13 | errors::{ConversionError, Error, MLE}, | ||
14 | mod_add, List, Modloader, STYLE_OPERATION, | ||
11 | }; | 15 | }; |
12 | 16 | ||
13 | #[derive(Debug, Serialize, Deserialize)] | 17 | #[derive(Debug, Serialize, Deserialize)] |
@@ -67,22 +71,13 @@ impl ExportList { | |||
67 | /// # Errors | 71 | /// # Errors |
68 | pub fn export(config: &Cfg, list: Option<String>) -> MLE<()> { | 72 | pub fn export(config: &Cfg, list: Option<String>) -> MLE<()> { |
69 | let progress = ProgressBar::new_spinner(); | 73 | let progress = ProgressBar::new_spinner(); |
70 | progress.set_style( | 74 | progress.set_style(ProgressStyle::with_template(STYLE_OPERATION)?); |
71 | ProgressStyle::with_template(STYLE_OPERATION) | ||
72 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?, | ||
73 | ); | ||
74 | 75 | ||
75 | let mut list_ids: Vec<String> = vec![]; | 76 | let mut list_ids: Vec<String> = vec![]; |
76 | if list.is_none() { | 77 | if list.is_none() { |
77 | list_ids = lists_get_all_ids(config)?; | 78 | list_ids = lists_get_all_ids(config)?; |
78 | } else { | 79 | } else { |
79 | list_ids.push( | 80 | list_ids.push(lists_get(config, &list.ok_or(Error::ListNotFound)?)?.id); |
80 | lists_get( | ||
81 | config, | ||
82 | &list.ok_or(MLErr::new(EType::Other, "nolist"))?, | ||
83 | )? | ||
84 | .id, | ||
85 | ); | ||
86 | } | 81 | } |
87 | 82 | ||
88 | let mut lists: Vec<ExportList> = vec![]; | 83 | let mut lists: Vec<ExportList> = vec![]; |
@@ -95,11 +90,11 @@ pub fn export(config: &Cfg, list: Option<String>) -> MLE<()> { | |||
95 | let toml = toml::to_string(&Export { lists })?; | 90 | let toml = toml::to_string(&Export { lists })?; |
96 | 91 | ||
97 | let filestr = dirs::home_dir() | 92 | let filestr = dirs::home_dir() |
98 | .ok_or(MLErr::new(EType::Other, "no home"))? | 93 | .ok_or(Error::SysDirNotFound("home".to_string()))? |
99 | .join("mlexport.toml") | 94 | .join("mlexport.toml") |
100 | .into_os_string() | 95 | .into_os_string() |
101 | .into_string() | 96 | .into_string() |
102 | .map_err(|_| MLErr::new(EType::IoError, "No String"))?; | 97 | .map_err(|_| ConversionError::InvalidPath)?; |
103 | 98 | ||
104 | progress.set_message("Create file"); | 99 | progress.set_message("Create file"); |
105 | let mut file = File::create(&filestr)?; | 100 | let mut file = File::create(&filestr)?; |
@@ -124,10 +119,10 @@ pub async fn import( | |||
124 | let list = List { | 119 | let list = List { |
125 | id: exportlist.id, | 120 | id: exportlist.id, |
126 | mc_version: exportlist.mc_version, | 121 | mc_version: exportlist.mc_version, |
127 | modloader: Modloader::from(&exportlist.launcher)?, | 122 | modloader: Modloader::try_from(exportlist.launcher.as_str())?, |
128 | download_folder: exportlist | 123 | download_folder: exportlist |
129 | .download_folder | 124 | .download_folder |
130 | .ok_or(MLErr::new(EType::Other, "NO_DL"))?, | 125 | .ok_or(Error::NoDownloadFolder)?, |
131 | }; | 126 | }; |
132 | lists_insert( | 127 | lists_insert( |
133 | config, | 128 | config, |
diff --git a/src/commands/list.rs b/src/commands/list.rs index 23a9f0f..db8a831 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs | |||
@@ -1,10 +1,14 @@ | |||
1 | use indicatif::{ProgressBar, ProgressStyle}; | 1 | use indicatif::{ProgressBar, ProgressStyle}; |
2 | 2 | ||
3 | use crate::{ | 3 | use crate::{ |
4 | config::Cfg, data::modloader::Modloader, db::{ | 4 | config::Cfg, |
5 | config_change_current_list, lists_get, | 5 | data::modloader::Modloader, |
6 | lists_get_all_ids, lists_insert, lists_remove, lists_version, | 6 | db::{ |
7 | }, error::{EType, MLErr, MLE}, update, STYLE_OPERATION | 7 | config_change_current_list, lists_get, lists_get_all_ids, lists_insert, |
8 | lists_remove, lists_version, | ||
9 | }, | ||
10 | errors::{Error, MLE}, | ||
11 | update, STYLE_OPERATION, | ||
8 | }; | 12 | }; |
9 | 13 | ||
10 | /// # Errors | 14 | /// # Errors |
@@ -16,11 +20,7 @@ pub fn add( | |||
16 | directory: &str, | 20 | directory: &str, |
17 | ) -> MLE<()> { | 21 | ) -> MLE<()> { |
18 | let p = ProgressBar::new_spinner(); | 22 | let p = ProgressBar::new_spinner(); |
19 | p.set_style( | 23 | p.set_style(ProgressStyle::with_template(STYLE_OPERATION)?); |
20 | ProgressStyle::with_template(STYLE_OPERATION).map_err(|_| { | ||
21 | MLErr::new(EType::LibIndicatif, "template error") | ||
22 | })?, | ||
23 | ); | ||
24 | p.set_message(format!("Create {id}")); | 24 | p.set_message(format!("Create {id}")); |
25 | lists_insert(config, id, mc_version, modloader, directory)?; | 25 | lists_insert(config, id, mc_version, modloader, directory)?; |
26 | p.finish_with_message(format!("Created {id}")); | 26 | p.finish_with_message(format!("Created {id}")); |
@@ -30,15 +30,11 @@ pub fn add( | |||
30 | /// # Errors | 30 | /// # Errors |
31 | pub fn change(config: &Cfg, id: &str) -> MLE<()> { | 31 | pub fn change(config: &Cfg, id: &str) -> MLE<()> { |
32 | let p = ProgressBar::new_spinner(); | 32 | let p = ProgressBar::new_spinner(); |
33 | p.set_style( | 33 | p.set_style(ProgressStyle::with_template(STYLE_OPERATION)?); |
34 | ProgressStyle::with_template(STYLE_OPERATION).map_err(|_| { | ||
35 | MLErr::new(EType::LibIndicatif, "template error") | ||
36 | })?, | ||
37 | ); | ||
38 | p.set_message(format!("Change default list to {id}")); | 34 | p.set_message(format!("Change default list to {id}")); |
39 | 35 | ||
40 | if !lists_get_all_ids(config)?.into_iter().any(|l| l == id) { | 36 | if !lists_get_all_ids(config)?.into_iter().any(|l| l == id) { |
41 | return Err(MLErr::new(EType::ArgumentError, "List not found")); | 37 | return Err(Error::ListNotFound); |
42 | }; | 38 | }; |
43 | config_change_current_list(config, id)?; | 39 | config_change_current_list(config, id)?; |
44 | 40 | ||
@@ -49,11 +45,7 @@ pub fn change(config: &Cfg, id: &str) -> MLE<()> { | |||
49 | /// # Errors | 45 | /// # Errors |
50 | pub fn remove(config: &Cfg, id: &str) -> MLE<()> { | 46 | pub fn remove(config: &Cfg, id: &str) -> MLE<()> { |
51 | let p = ProgressBar::new_spinner(); | 47 | let p = ProgressBar::new_spinner(); |
52 | p.set_style( | 48 | p.set_style(ProgressStyle::with_template(STYLE_OPERATION)?); |
53 | ProgressStyle::with_template(STYLE_OPERATION).map_err(|_| { | ||
54 | MLErr::new(EType::LibIndicatif, "template error") | ||
55 | })?, | ||
56 | ); | ||
57 | p.set_message(format!("Remove {id}")); | 49 | p.set_message(format!("Remove {id}")); |
58 | lists_remove(config, id)?; | 50 | lists_remove(config, id)?; |
59 | p.finish_with_message(format!("Removed {id}")); | 51 | p.finish_with_message(format!("Removed {id}")); |
@@ -75,11 +67,7 @@ pub async fn version( | |||
75 | delete: bool, | 67 | delete: bool, |
76 | ) -> MLE<()> { | 68 | ) -> MLE<()> { |
77 | let p = ProgressBar::new_spinner(); | 69 | let p = ProgressBar::new_spinner(); |
78 | p.set_style( | 70 | p.set_style(ProgressStyle::with_template(STYLE_OPERATION)?); |
79 | ProgressStyle::with_template(STYLE_OPERATION).map_err(|_| { | ||
80 | MLErr::new(EType::LibIndicatif, "template error") | ||
81 | })?, | ||
82 | ); | ||
83 | p.set_message(format!( | 71 | p.set_message(format!( |
84 | "Change version for list {id} to minecraft version: {mc_version}" | 72 | "Change version for list {id} to minecraft version: {mc_version}" |
85 | )); | 73 | )); |
diff --git a/src/commands/modification.rs b/src/commands/modification.rs index d20f575..27ba098 100644 --- a/src/commands/modification.rs +++ b/src/commands/modification.rs | |||
@@ -3,11 +3,23 @@ use std::collections::HashMap; | |||
3 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; | 3 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | apis::modrinth::{extract_current_version, get_raw_versions, project, projects, versions, Version}, config::Cfg, data::{modification::{AddMod, IDSelector}, project::ProjectInfo}, db::{ | 6 | apis::modrinth::{ |
7 | extract_current_version, get_raw_versions, project, projects, versions, | ||
8 | Version, | ||
9 | }, | ||
10 | config::Cfg, | ||
11 | data::{ | ||
12 | modification::{AddMod, IDSelector}, | ||
13 | projectinfo::ProjectInfo, | ||
14 | }, | ||
15 | db::{ | ||
7 | lists_get_all_ids, mods_get_id, mods_get_info, mods_insert, | 16 | lists_get_all_ids, mods_get_id, mods_get_info, mods_insert, |
8 | mods_remove, userlist_get_all_ids, userlist_get_current_version, | 17 | mods_remove, userlist_get_all_ids, userlist_get_current_version, |
9 | userlist_insert, userlist_remove, | 18 | userlist_insert, userlist_remove, |
10 | }, error::{EType, MLErr, MLE}, files::{delete_version, download_versions}, List, PROGRESS_CHARS, STYLE_BAR_POS, STYLE_OPERATION | 19 | }, |
20 | errors::{Error, MLE}, | ||
21 | files::{delete_version, download_versions}, | ||
22 | List, PROGRESS_CHARS, STYLE_BAR_POS, STYLE_OPERATION, | ||
11 | }; | 23 | }; |
12 | 24 | ||
13 | /// # Errors | 25 | /// # Errors |
@@ -22,14 +34,9 @@ pub async fn mod_add( | |||
22 | let mut mod_ids: Vec<(String, bool)> = Vec::new(); | 34 | let mut mod_ids: Vec<(String, bool)> = Vec::new(); |
23 | let mut ver_ids: Vec<(String, bool)> = Vec::new(); | 35 | let mut ver_ids: Vec<(String, bool)> = Vec::new(); |
24 | 36 | ||
25 | let add_p = mp.add(ProgressBar::new( | 37 | let add_p = mp.add(ProgressBar::new(mods.len().try_into()?)); |
26 | mods.len() | ||
27 | .try_into() | ||
28 | .map_err(|_| MLErr::new(EType::Other, "MODSLENTRY"))?, | ||
29 | )); | ||
30 | add_p.set_style( | 38 | add_p.set_style( |
31 | ProgressStyle::with_template(STYLE_BAR_POS) | 39 | ProgressStyle::with_template(STYLE_BAR_POS)? |
32 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))? | ||
33 | .progress_chars(PROGRESS_CHARS), | 40 | .progress_chars(PROGRESS_CHARS), |
34 | ); | 41 | ); |
35 | add_p.set_message("Sort ids"); | 42 | add_p.set_message("Sort ids"); |
@@ -57,7 +64,7 @@ pub async fn mod_add( | |||
57 | }; | 64 | }; |
58 | 65 | ||
59 | if projectinfo.is_empty() { | 66 | if projectinfo.is_empty() { |
60 | return Err(MLErr::new(EType::ArgumentError, "NO_IDS?")); | 67 | return Err(Error::NoProjectInfo); |
61 | }; | 68 | }; |
62 | 69 | ||
63 | add_p.set_message("Add mods to database"); | 70 | add_p.set_message("Add mods to database"); |
@@ -65,29 +72,18 @@ pub async fn mod_add( | |||
65 | let mut downloadstack: Vec<Version> = Vec::new(); | 72 | let mut downloadstack: Vec<Version> = Vec::new(); |
66 | 73 | ||
67 | //Adding each mod to the lists and downloadstack | 74 | //Adding each mod to the lists and downloadstack |
68 | let project_p = mp.insert_before( | 75 | let project_p = mp |
69 | &add_p, | 76 | .insert_before(&add_p, ProgressBar::new(projectinfo.len().try_into()?)); |
70 | ProgressBar::new( | ||
71 | projectinfo | ||
72 | .len() | ||
73 | .try_into() | ||
74 | .map_err(|_| MLErr::new(EType::Other, "infolen"))?, | ||
75 | ), | ||
76 | ); | ||
77 | project_p.set_style( | 77 | project_p.set_style( |
78 | ProgressStyle::with_template(STYLE_BAR_POS) | 78 | ProgressStyle::with_template(STYLE_BAR_POS)? |
79 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))? | ||
80 | .progress_chars(PROGRESS_CHARS), | 79 | .progress_chars(PROGRESS_CHARS), |
81 | ); | 80 | ); |
82 | 81 | ||
83 | for project in projectinfo { | 82 | for project in projectinfo { |
84 | add_project(config, &project_p, &project, &list)?; | 83 | add_project(config, &project_p, &project, &list)?; |
85 | if project.current_version.is_some() { | 84 | if project.current_version.is_some() { |
86 | downloadstack.push( | 85 | downloadstack |
87 | project | 86 | .push(project.current_version.ok_or(Error::NoCurrentVersion)?); |
88 | .current_version | ||
89 | .ok_or(MLErr::new(EType::Other, "cur_ver"))?, | ||
90 | ); | ||
91 | }; | 87 | }; |
92 | } | 88 | } |
93 | 89 | ||
@@ -125,7 +121,7 @@ fn add_project( | |||
125 | project | 121 | project |
126 | .current_version | 122 | .current_version |
127 | .clone() | 123 | .clone() |
128 | .ok_or(MLErr::new(EType::Other, "cur_ver"))? | 124 | .ok_or(Error::NoCurrentVersion)? |
129 | .id | 125 | .id |
130 | }; | 126 | }; |
131 | 127 | ||
@@ -142,9 +138,9 @@ fn add_project( | |||
142 | let expected_err = | 138 | let expected_err = |
143 | format!("SQL: UNIQUE constraint failed: {}.mod_id", list.id); | 139 | format!("SQL: UNIQUE constraint failed: {}.mod_id", list.id); |
144 | if e.to_string() == expected_err { | 140 | if e.to_string() == expected_err { |
145 | Err(MLErr::new(EType::ModError, "MOD_ALREADY_ON_SELECTED_LIST")) | 141 | Err(Error::ModAlreadyOnList) |
146 | } else { | 142 | } else { |
147 | Err(e) | 143 | Err(e)? |
148 | } | 144 | } |
149 | } | 145 | } |
150 | Ok(..) => Ok(..), | 146 | Ok(..) => Ok(..), |
@@ -212,7 +208,7 @@ async fn get_mod_infos( | |||
212 | download_link: file, | 208 | download_link: file, |
213 | set_version: *setmap | 209 | set_version: *setmap |
214 | .get(&project.id) | 210 | .get(&project.id) |
215 | .ok_or(MLErr::new(EType::Other, "not in setmap"))?, | 211 | .ok_or(Error::VersionSetNotSet)?, |
216 | }); | 212 | }); |
217 | } else { | 213 | } else { |
218 | let current_id = | 214 | let current_id = |
@@ -312,10 +308,7 @@ async fn get_ver_info( | |||
312 | /// # Errors | 308 | /// # Errors |
313 | pub fn mod_remove(config: &Cfg, id: &str, list: &List) -> MLE<()> { | 309 | pub fn mod_remove(config: &Cfg, id: &str, list: &List) -> MLE<()> { |
314 | let progress = ProgressBar::new_spinner(); | 310 | let progress = ProgressBar::new_spinner(); |
315 | progress.set_style( | 311 | progress.set_style(ProgressStyle::with_template(STYLE_OPERATION)?); |
316 | ProgressStyle::with_template(STYLE_OPERATION) | ||
317 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?, | ||
318 | ); | ||
319 | 312 | ||
320 | let mod_id = mods_get_id(&config.data, id)?; | 313 | let mod_id = mods_get_id(&config.data, id)?; |
321 | 314 | ||
@@ -351,7 +344,7 @@ pub fn mod_remove(config: &Cfg, id: &str, list: &List) -> MLE<()> { | |||
351 | if err.to_string() == "Database: NO_MODS_USERLIST" { | 344 | if err.to_string() == "Database: NO_MODS_USERLIST" { |
352 | return Ok(()); | 345 | return Ok(()); |
353 | }; | 346 | }; |
354 | return Err(err); | 347 | return Err(err)?; |
355 | } | 348 | } |
356 | }; | 349 | }; |
357 | if mods.contains(&mod_id) { | 350 | if mods.contains(&mod_id) { |
diff --git a/src/commands/update.rs b/src/commands/update.rs index 721ced5..92ea9d6 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs | |||
@@ -1,13 +1,19 @@ | |||
1 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; | 1 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; |
2 | 2 | ||
3 | use crate::{ | 3 | use crate::{ |
4 | apis::modrinth::{extract_current_version, versions, Version}, config::Cfg, data::list::List, db::{ | 4 | apis::modrinth::{extract_current_version, versions, Version}, |
5 | config::Cfg, | ||
6 | data::list::List, | ||
7 | db::{ | ||
5 | mods_get_info, userlist_change_versions, userlist_get_all_ids, | 8 | mods_get_info, userlist_change_versions, userlist_get_all_ids, |
6 | userlist_get_applicable_versions, userlist_get_current_version, | 9 | userlist_get_applicable_versions, userlist_get_current_version, |
7 | userlist_get_set_version, | 10 | userlist_get_set_version, |
8 | }, error::{EType, MLErr, MLE}, files::{ | 11 | }, |
12 | errors::{Error, MLE}, | ||
13 | files::{ | ||
9 | clean_list_dir, delete_version, disable_version, download_versions, | 14 | clean_list_dir, delete_version, disable_version, download_versions, |
10 | }, PROGRESS_CHARS, STYLE_BAR_POS, STYLE_OPERATION | 15 | }, |
16 | PROGRESS_CHARS, STYLE_BAR_POS, STYLE_OPERATION, | ||
11 | }; | 17 | }; |
12 | 18 | ||
13 | /// # Errors | 19 | /// # Errors |
@@ -20,15 +26,9 @@ pub async fn update( | |||
20 | ) -> MLE<()> { | 26 | ) -> MLE<()> { |
21 | let mp = MultiProgress::new(); | 27 | let mp = MultiProgress::new(); |
22 | 28 | ||
23 | let update_p = mp.add(ProgressBar::new( | 29 | let update_p = mp.add(ProgressBar::new(liststack.len().try_into()?)); |
24 | liststack | ||
25 | .len() | ||
26 | .try_into() | ||
27 | .map_err(|_| MLErr::new(EType::Other, "ListStackLen"))?, | ||
28 | )); | ||
29 | update_p.set_style( | 30 | update_p.set_style( |
30 | ProgressStyle::with_template(STYLE_BAR_POS) | 31 | ProgressStyle::with_template(STYLE_BAR_POS)? |
31 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))? | ||
32 | .progress_chars(PROGRESS_CHARS), | 32 | .progress_chars(PROGRESS_CHARS), |
33 | ); | 33 | ); |
34 | 34 | ||
@@ -36,26 +36,15 @@ pub async fn update( | |||
36 | update_p.set_message(format!("Update {}", current_list.id)); | 36 | update_p.set_message(format!("Update {}", current_list.id)); |
37 | 37 | ||
38 | let list_p = mp.insert_before(&update_p, ProgressBar::new(2)); | 38 | let list_p = mp.insert_before(&update_p, ProgressBar::new(2)); |
39 | list_p.set_style( | 39 | list_p.set_style(ProgressStyle::with_template(STYLE_OPERATION)?); |
40 | ProgressStyle::with_template(STYLE_OPERATION).map_err(|_| { | ||
41 | MLErr::new(EType::LibIndicatif, "template error") | ||
42 | })?, | ||
43 | ); | ||
44 | list_p.set_message("Update mods"); | 40 | list_p.set_message("Update mods"); |
45 | 41 | ||
46 | let mods = userlist_get_all_ids(config, ¤t_list.id)?; | 42 | let mods = userlist_get_all_ids(config, ¤t_list.id)?; |
47 | 43 | ||
48 | let list_u_p = mp.insert_before( | 44 | let list_u_p = |
49 | &list_p, | 45 | mp.insert_before(&list_p, ProgressBar::new(mods.len().try_into()?)); |
50 | ProgressBar::new( | ||
51 | mods.len() | ||
52 | .try_into() | ||
53 | .map_err(|_| MLErr::new(EType::Other, "ListStackLen"))?, | ||
54 | ), | ||
55 | ); | ||
56 | list_u_p.set_style( | 46 | list_u_p.set_style( |
57 | ProgressStyle::with_template(STYLE_BAR_POS) | 47 | ProgressStyle::with_template(STYLE_BAR_POS)? |
58 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))? | ||
59 | .progress_chars(PROGRESS_CHARS), | 48 | .progress_chars(PROGRESS_CHARS), |
60 | ); | 49 | ); |
61 | 50 | ||
@@ -63,7 +52,16 @@ pub async fn update( | |||
63 | let mut updatestack: Vec<Version> = vec![]; | 52 | let mut updatestack: Vec<Version> = vec![]; |
64 | 53 | ||
65 | for id in mods { | 54 | for id in mods { |
66 | update_mod(config, id, list_u_p.clone(), ¤t_list, &mut updatestack, &mut current_versions, clean).await?; | 55 | update_mod( |
56 | config, | ||
57 | id, | ||
58 | list_u_p.clone(), | ||
59 | ¤t_list, | ||
60 | &mut updatestack, | ||
61 | &mut current_versions, | ||
62 | clean, | ||
63 | ) | ||
64 | .await?; | ||
67 | } | 65 | } |
68 | 66 | ||
69 | list_u_p.finish_with_message(format!( | 67 | list_u_p.finish_with_message(format!( |
@@ -91,12 +89,11 @@ pub async fn update( | |||
91 | let d_p = mp.insert_before( | 89 | let d_p = mp.insert_before( |
92 | &list_p, | 90 | &list_p, |
93 | ProgressBar::new( | 91 | ProgressBar::new( |
94 | current_versions.len().try_into().map_err(|_| MLErr::new(EType::Other, "ListStackLen"))?, | 92 | current_versions.len().try_into()?, |
95 | ), | 93 | ), |
96 | ); | 94 | ); |
97 | d_p.set_style( | 95 | d_p.set_style( |
98 | ProgressStyle::with_template(STYLE_BAR_POS) | 96 | ProgressStyle::with_template(STYLE_BAR_POS)? |
99 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))? | ||
100 | .progress_chars(PROGRESS_CHARS), | 97 | .progress_chars(PROGRESS_CHARS), |
101 | ); | 98 | ); |
102 | for ver in current_versions { | 99 | for ver in current_versions { |
@@ -129,45 +126,40 @@ pub async fn update( | |||
129 | Ok(()) | 126 | Ok(()) |
130 | } | 127 | } |
131 | 128 | ||
132 | async fn update_mod(config: &Cfg, id: String, list_u_p: ProgressBar, current_list: &List, updatestack: &mut Vec<Version>, current_versions: &mut Vec<(String, String)>, clean: bool) -> MLE<()> { | 129 | async fn update_mod( |
133 | let info = mods_get_info(config, &id)?; | 130 | config: &Cfg, |
134 | list_u_p.set_message(format!("Update {}", info.title)); | 131 | id: String, |
132 | list_u_p: ProgressBar, | ||
133 | current_list: &List, | ||
134 | updatestack: &mut Vec<Version>, | ||
135 | current_versions: &mut Vec<(String, String)>, | ||
136 | clean: bool, | ||
137 | ) -> MLE<()> { | ||
138 | let info = mods_get_info(config, &id)?; | ||
139 | list_u_p.set_message(format!("Update {}", info.title)); | ||
135 | 140 | ||
136 | //Skip check if version is set | 141 | //Skip check if version is set |
137 | if userlist_get_set_version(config, ¤t_list.id, &id)? { | 142 | if userlist_get_set_version(config, ¤t_list.id, &id)? { |
138 | list_u_p.inc(1); | 143 | list_u_p.inc(1); |
139 | return Ok(()); | 144 | return Ok(()); |
140 | } | 145 | } |
141 | 146 | ||
142 | //Getting current installed version for disable or delete | 147 | //Getting current installed version for disable or delete |
143 | let disable_version = | 148 | let disable_version = |
144 | userlist_get_current_version(config, ¤t_list.id, &id)?; | 149 | userlist_get_current_version(config, ¤t_list.id, &id)?; |
145 | 150 | ||
146 | updatestack.push( | 151 | let version = specific_update( |
147 | match specific_update( | 152 | config, |
148 | config, | 153 | clean, |
149 | clean, | 154 | current_list.clone(), |
150 | current_list.clone(), | 155 | &id, |
151 | &id, | 156 | &list_u_p, |
152 | &list_u_p, | 157 | ).await?; |
153 | ) | 158 | if let Some(v) = version { |
154 | .await | 159 | updatestack.push(v); |
155 | { | 160 | current_versions.push((disable_version, id.to_string())); |
156 | Ok(ver) => { | 161 | } |
157 | current_versions.push((disable_version, id.to_string())); | 162 | list_u_p.inc(1); |
158 | ver | ||
159 | } | ||
160 | Err(e) => { | ||
161 | if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { | ||
162 | } else { | ||
163 | return Err(e); | ||
164 | }; | ||
165 | list_u_p.inc(1); | ||
166 | return Ok(()); | ||
167 | } | ||
168 | }, | ||
169 | ); | ||
170 | list_u_p.inc(1); | ||
171 | 163 | ||
172 | Ok(()) | 164 | Ok(()) |
173 | } | 165 | } |
@@ -178,7 +170,7 @@ async fn specific_update( | |||
178 | list: List, | 170 | list: List, |
179 | id: &str, | 171 | id: &str, |
180 | progress: &ProgressBar, | 172 | progress: &ProgressBar, |
181 | ) -> MLE<Version> { | 173 | ) -> MLE<Option<Version>> { |
182 | let applicable_versions = | 174 | let applicable_versions = |
183 | versions(&config.apis.modrinth, String::from(id), list.clone()).await?; | 175 | versions(&config.apis.modrinth, String::from(id), list.clone()).await?; |
184 | 176 | ||
@@ -192,14 +184,12 @@ async fn specific_update( | |||
192 | } | 184 | } |
193 | } | 185 | } |
194 | 186 | ||
195 | let mut current: Vec<Version> = vec![]; | 187 | let mut current: Option<Version> = None; |
196 | if clean | 188 | if clean || (versions.join("|") != userlist_get_applicable_versions( |
197 | || (versions.join("|") | ||
198 | != userlist_get_applicable_versions( | ||
199 | config, | 189 | config, |
200 | &list.id, | 190 | &list.id, |
201 | String::from(id), | 191 | String::from(id), |
202 | )?) | 192 | )?) |
203 | { | 193 | { |
204 | let current_str = extract_current_version(applicable_versions.clone())?; | 194 | let current_str = extract_current_version(applicable_versions.clone())?; |
205 | 195 | ||
@@ -211,15 +201,10 @@ async fn specific_update( | |||
211 | } | 201 | } |
212 | 202 | ||
213 | //get new versions | 203 | //get new versions |
214 | let current_ver = match applicable_versions | 204 | let Some(current_ver) = applicable_versions.into_iter().find(|ver| ver.id == current_str) else { |
215 | .into_iter() | 205 | return Err(Error::NoCurrentVersion); |
216 | .find(|ver| ver.id == current_str) | 206 | }; |
217 | .ok_or("!no current version in applicable_versions") | 207 | current = Some(current_ver.clone()); |
218 | { | ||
219 | Ok(v) => Ok(v), | ||
220 | Err(e) => Err(MLErr::new(EType::Other, e)), | ||
221 | }?; | ||
222 | current.push(current_ver.clone()); | ||
223 | 208 | ||
224 | let files = ¤t_ver.files; | 209 | let files = ¤t_ver.files; |
225 | 210 | ||
@@ -237,11 +222,12 @@ async fn specific_update( | |||
237 | link, | 222 | link, |
238 | id.to_string(), | 223 | id.to_string(), |
239 | )?; | 224 | )?; |
240 | } | ||
241 | |||
242 | if current.is_empty() { | ||
243 | return Err(MLErr::new(EType::ModError, "NO_UPDATE_AVAILABLE")); | ||
244 | }; | 225 | }; |
245 | 226 | ||
246 | Ok(current[0].clone()) | 227 | if current.is_none() { |
228 | // No Update Available | ||
229 | Ok(None) | ||
230 | } else { | ||
231 | Ok(current) | ||
232 | } | ||
247 | } | 233 | } |
diff --git a/src/config.rs b/src/config.rs index 8312d15..f361deb 100644 --- a/src/config.rs +++ b/src/config.rs | |||
@@ -7,7 +7,12 @@ use std::{ | |||
7 | use serde::{Deserialize, Serialize}; | 7 | use serde::{Deserialize, Serialize}; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | data::{gameversion::{check_game_versions, VersionLevel}, modloader::Modloader}, db::setup, error::{EType, MLErr, MLE} | 10 | data::{ |
11 | gameversion::{check_game_versions, VersionLevel}, | ||
12 | modloader::Modloader, | ||
13 | }, | ||
14 | db::setup, | ||
15 | errors::{Error, MLE}, | ||
11 | }; | 16 | }; |
12 | 17 | ||
13 | #[derive(Debug, Clone, Serialize, Deserialize)] | 18 | #[derive(Debug, Clone, Serialize, Deserialize)] |
@@ -55,14 +60,17 @@ pub struct Defaults { | |||
55 | impl Cfg { | 60 | impl Cfg { |
56 | /// # Errors | 61 | /// # Errors |
57 | pub async fn init(path: Option<String>) -> MLE<Self> { | 62 | pub async fn init(path: Option<String>) -> MLE<Self> { |
58 | let configfile = match path.clone() { | 63 | let configfile = if let Some(cf) = path.clone() { |
59 | Some(p) => p, | 64 | cf |
60 | None => dirs::config_dir() | 65 | } else { |
61 | .ok_or(MLErr::new(EType::Other, "config_dir"))? | 66 | let Some(config_dir) = dirs::config_dir() else { |
67 | return Err(Error::SysDirNotFound("config".to_string())); | ||
68 | }; | ||
69 | config_dir | ||
62 | .join("modlist") | 70 | .join("modlist") |
63 | .join("config.toml") | 71 | .join("config.toml") |
64 | .to_string_lossy() | 72 | .to_string_lossy() |
65 | .to_string(), | 73 | .to_string() |
66 | }; | 74 | }; |
67 | 75 | ||
68 | if let Some(err) = File::open(&configfile).err() { | 76 | if let Some(err) = File::open(&configfile).err() { |
@@ -78,10 +86,8 @@ impl Cfg { | |||
78 | .add_source( | 86 | .add_source( |
79 | config::Environment::with_prefix("MODLIST").separator("_"), | 87 | config::Environment::with_prefix("MODLIST").separator("_"), |
80 | ) | 88 | ) |
81 | .build() | 89 | .build()? |
82 | .unwrap() | 90 | .try_deserialize()?; |
83 | .try_deserialize() | ||
84 | .unwrap(); | ||
85 | 91 | ||
86 | //Check cache | 92 | //Check cache |
87 | if !Path::new(&config.cache).exists() { | 93 | if !Path::new(&config.cache).exists() { |
diff --git a/src/data.rs b/src/data.rs index cff0f47..f72fbcf 100644 --- a/src/data.rs +++ b/src/data.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | pub mod list; | 1 | pub mod list; |
2 | pub mod gameversion; | 2 | pub mod gameversion; |
3 | pub mod modloader; | 3 | pub mod modloader; |
4 | pub mod project; | 4 | pub mod projectinfo; |
5 | pub mod modification; | 5 | pub mod modification; |
6 | 6 | ||
7 | pub static STYLE_BAR_BYTE: &str = | 7 | pub static STYLE_BAR_BYTE: &str = |
diff --git a/src/data/gameversion.rs b/src/data/gameversion.rs index 3868502..1bda755 100644 --- a/src/data/gameversion.rs +++ b/src/data/gameversion.rs | |||
@@ -5,11 +5,15 @@ use std::{ | |||
5 | }; | 5 | }; |
6 | 6 | ||
7 | use apis::modrinth::{get_game_versions, GameVersion, GameVersionType}; | 7 | use apis::modrinth::{get_game_versions, GameVersion, GameVersionType}; |
8 | use error::{EType, MLErr, MLE}; | 8 | use errors::MLE; |
9 | use indicatif::{ProgressBar, ProgressStyle}; | 9 | use indicatif::{ProgressBar, ProgressStyle}; |
10 | use serde::{Deserialize, Serialize}; | 10 | use serde::{Deserialize, Serialize}; |
11 | 11 | ||
12 | use crate::{apis, error, STYLE_MESSAGE}; | 12 | use crate::{ |
13 | apis, | ||
14 | errors::{self, Error}, | ||
15 | STYLE_MESSAGE, | ||
16 | }; | ||
13 | 17 | ||
14 | #[derive(Debug, Clone, Deserialize, Serialize)] | 18 | #[derive(Debug, Clone, Deserialize, Serialize)] |
15 | pub enum VersionLevel { | 19 | pub enum VersionLevel { |
@@ -25,15 +29,11 @@ pub enum VersionLevel { | |||
25 | /// # Errors | 29 | /// # Errors |
26 | pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> { | 30 | pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> { |
27 | let p = ProgressBar::new(1); | 31 | let p = ProgressBar::new(1); |
28 | p.set_style(ProgressStyle::with_template(STYLE_MESSAGE).map_err(|_| { | 32 | p.set_style(ProgressStyle::with_template(STYLE_MESSAGE)?); |
29 | MLErr::new(EType::LibIndicatif, "template error") | ||
30 | })?); | ||
31 | p.set_message("Update minecraft versions"); | 33 | p.set_message("Update minecraft versions"); |
32 | 34 | ||
33 | let creation_time = fs::metadata(path)?.created()?; | 35 | let creation_time = fs::metadata(path)?.created()?; |
34 | if !force | 36 | if !force && creation_time.elapsed()? < Duration::from_secs(60 * 60 * 24) { |
35 | && creation_time.elapsed().map_err(|_| MLErr::new(EType::LibIndicatif, "SystemTimeError"))? < Duration::from_secs(60 * 60 * 24) | ||
36 | { | ||
37 | return Ok(()); | 37 | return Ok(()); |
38 | } | 38 | } |
39 | 39 | ||
@@ -57,7 +57,7 @@ pub fn load_game_versions(path: &str) -> MLE<Vec<GameVersion>> { | |||
57 | } | 57 | } |
58 | 58 | ||
59 | impl VersionLevel { | 59 | impl VersionLevel { |
60 | pub fn from(str: &str) -> Self { | 60 | #[must_use] pub fn from(str: &str) -> Self { |
61 | match str { | 61 | match str { |
62 | "release" => VersionLevel::Release, | 62 | "release" => VersionLevel::Release, |
63 | "snapshot" => VersionLevel::Snapshot, | 63 | "snapshot" => VersionLevel::Snapshot, |
@@ -85,10 +85,7 @@ impl VersionLevel { | |||
85 | { | 85 | { |
86 | Ok(release.version) | 86 | Ok(release.version) |
87 | } else { | 87 | } else { |
88 | Err(MLErr::new( | 88 | Err(Error::MinecraftVersionNotFound) |
89 | EType::Other, | ||
90 | "no minecraft release version found", | ||
91 | )) | ||
92 | } | 89 | } |
93 | } | 90 | } |
94 | VersionLevel::Snapshot => { | 91 | VersionLevel::Snapshot => { |
@@ -97,20 +94,14 @@ impl VersionLevel { | |||
97 | { | 94 | { |
98 | Ok(snapshot.version) | 95 | Ok(snapshot.version) |
99 | } else { | 96 | } else { |
100 | Err(MLErr::new( | 97 | Err(Error::MinecraftVersionNotFound) |
101 | EType::Other, | ||
102 | "no minecraft snapshot version found", | ||
103 | )) | ||
104 | } | 98 | } |
105 | } | 99 | } |
106 | VersionLevel::Version(v) => { | 100 | VersionLevel::Version(v) => { |
107 | if versions.any(|ver| ver.version == v) { | 101 | if versions.any(|ver| ver.version == v) { |
108 | Ok(v) | 102 | Ok(v) |
109 | } else { | 103 | } else { |
110 | Err(MLErr::new( | 104 | Err(Error::MinecraftVersionNotFound) |
111 | EType::ConfigError, | ||
112 | "unknown minecraft version", | ||
113 | )) | ||
114 | } | 105 | } |
115 | } | 106 | } |
116 | } | 107 | } |
diff --git a/src/data/list.rs b/src/data/list.rs index 0045b7a..b886af1 100644 --- a/src/data/list.rs +++ b/src/data/list.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use crate::{config::Cfg, db::{config_get_current_list, lists_get}, error::MLE}; | 1 | use crate::{config::Cfg, db::{config_get_current_list, lists_get}, errors::MLE}; |
2 | 2 | ||
3 | use super::modloader::Modloader; | 3 | use super::modloader::Modloader; |
4 | 4 | ||
@@ -14,6 +14,6 @@ impl List { | |||
14 | /// # Errors | 14 | /// # Errors |
15 | pub fn get_current_list(config: &Cfg) -> MLE<List> { | 15 | pub fn get_current_list(config: &Cfg) -> MLE<List> { |
16 | let id = config_get_current_list(config)?; | 16 | let id = config_get_current_list(config)?; |
17 | lists_get(config, &id) | 17 | Ok(lists_get(config, &id)?) |
18 | } | 18 | } |
19 | } | 19 | } |
diff --git a/src/data/modloader.rs b/src/data/modloader.rs index 050213f..ef2611b 100644 --- a/src/data/modloader.rs +++ b/src/data/modloader.rs | |||
@@ -2,7 +2,7 @@ use std::fmt::Display; | |||
2 | 2 | ||
3 | use serde::{Deserialize, Serialize}; | 3 | use serde::{Deserialize, Serialize}; |
4 | 4 | ||
5 | use crate::error::{EType, MLErr, MLE}; | 5 | use crate::errors::ConversionError; |
6 | 6 | ||
7 | #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] | 7 | #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] |
8 | pub enum Modloader { | 8 | pub enum Modloader { |
@@ -14,16 +14,14 @@ pub enum Modloader { | |||
14 | Quilt, | 14 | Quilt, |
15 | } | 15 | } |
16 | 16 | ||
17 | impl Modloader { | 17 | impl TryFrom<&str> for Modloader { |
18 | /// # Errors | 18 | type Error = ConversionError; |
19 | pub fn from(string: &str) -> MLE<Modloader> { | 19 | fn try_from(value: &str) -> Result<Self, Self::Error> { |
20 | match string { | 20 | match value { |
21 | "forge" => Ok(Modloader::Forge), | 21 | "forge" => Ok(Modloader::Forge), |
22 | "fabric" => Ok(Modloader::Fabric), | 22 | "fabric" => Ok(Modloader::Fabric), |
23 | "quilt" => Ok(Modloader::Quilt), | 23 | "quilt" => Ok(Modloader::Quilt), |
24 | _ => { | 24 | _ => Err(ConversionError::Modloader(value.to_string())) |
25 | Err(MLErr::new(EType::ArgumentError, "UNKNOWN_MODLOADER")) | ||
26 | } | ||
27 | } | 25 | } |
28 | } | 26 | } |
29 | } | 27 | } |
diff --git a/src/data/project.rs b/src/data/projectinfo.rs index 9807867..9807867 100644 --- a/src/data/project.rs +++ b/src/data/projectinfo.rs | |||
@@ -1,16 +1,39 @@ | |||
1 | use std::io::{Error, ErrorKind}; | ||
2 | |||
3 | use rusqlite::Connection; | 1 | use rusqlite::Connection; |
4 | 2 | ||
5 | use crate::{ | 3 | use crate::{ |
6 | config::Cfg, | 4 | config::Cfg, |
7 | data::{list::List, modloader::Modloader}, | 5 | data::{list::List, modloader::Modloader}, |
8 | error::{EType, MLErr, MLE}, | ||
9 | }; | 6 | }; |
10 | 7 | ||
8 | type DbE<T> = Result<T, DBError>; | ||
9 | |||
10 | #[derive(Debug, thiserror::Error)] | ||
11 | pub enum DBError { | ||
12 | #[error("sqlite: {source}")] | ||
13 | Sqlite { | ||
14 | #[from] | ||
15 | source: rusqlite::Error, | ||
16 | }, | ||
17 | |||
18 | #[error("conversion: {source}")] | ||
19 | Conversion { | ||
20 | #[from] | ||
21 | source: crate::errors::ConversionError, | ||
22 | }, | ||
23 | |||
24 | #[error("not enough arguments")] | ||
25 | NotEnoughArguments, | ||
26 | |||
27 | #[error("couldn't find requested mod/version")] | ||
28 | NotFound, | ||
29 | |||
30 | #[error("no mods/versions are available in the requested scope")] | ||
31 | NotAvailable, | ||
32 | } | ||
33 | |||
11 | //MODS | 34 | //MODS |
12 | /// # Errors | 35 | /// # Errors |
13 | pub fn mods_insert(config: &Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { | 36 | pub fn mods_insert(config: &Cfg, id: &str, slug: &str, name: &str) -> DbE<()> { |
14 | let data = format!("{}/data.db", config.data); | 37 | let data = format!("{}/data.db", config.data); |
15 | let connection = Connection::open(data)?; | 38 | let connection = Connection::open(data)?; |
16 | 39 | ||
@@ -23,9 +46,7 @@ pub fn mods_insert(config: &Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { | |||
23 | } | 46 | } |
24 | 47 | ||
25 | /// # Errors | 48 | /// # Errors |
26 | pub fn mods_get_all_ids( | 49 | pub fn mods_get_all_ids(config: &Cfg) -> DbE<Vec<String>> { |
27 | config: &Cfg, | ||
28 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { | ||
29 | let data = format!("{}/data.db", config.data); | 50 | let data = format!("{}/data.db", config.data); |
30 | let connection = Connection::open(data)?; | 51 | let connection = Connection::open(data)?; |
31 | 52 | ||
@@ -39,7 +60,7 @@ pub fn mods_get_all_ids( | |||
39 | } | 60 | } |
40 | 61 | ||
41 | if mods.is_empty() { | 62 | if mods.is_empty() { |
42 | Err(Box::new(Error::new(ErrorKind::NotFound, "NO_MODS_ALL"))) | 63 | Err(DBError::NotFound) |
43 | } else { | 64 | } else { |
44 | Ok(mods) | 65 | Ok(mods) |
45 | } | 66 | } |
@@ -53,8 +74,8 @@ pub fn mods_get_all_ids( | |||
53 | /// | 74 | /// |
54 | /// # Errors | 75 | /// # Errors |
55 | /// | 76 | /// |
56 | /// Will return `MLError` when no mod id is found | 77 | /// Will return `DBError` when no mod id is found |
57 | pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { | 78 | pub fn mods_get_id(data: &str, slug: &str) -> DbE<String> { |
58 | let data = format!("{data}/data.db"); | 79 | let data = format!("{data}/data.db"); |
59 | let connection = Connection::open(data)?; | 80 | let connection = Connection::open(data)?; |
60 | 81 | ||
@@ -91,7 +112,7 @@ pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { | |||
91 | } | 112 | } |
92 | 113 | ||
93 | if mod_id.is_empty() { | 114 | if mod_id.is_empty() { |
94 | return Err(MLErr::new(EType::DBError, "GI_MOD_NOT_FOUND")); | 115 | Err(DBError::NotFound)?; |
95 | }; | 116 | }; |
96 | 117 | ||
97 | Ok(mod_id) | 118 | Ok(mod_id) |
@@ -103,7 +124,7 @@ pub struct ModInfo { | |||
103 | } | 124 | } |
104 | 125 | ||
105 | /// # Errors | 126 | /// # Errors |
106 | pub fn mods_get_info(config: &Cfg, id: &str) -> MLE<ModInfo> { | 127 | pub fn mods_get_info(config: &Cfg, id: &str) -> DbE<ModInfo> { |
107 | let data = format!("{}/data.db", config.data); | 128 | let data = format!("{}/data.db", config.data); |
108 | let connection = Connection::open(data)?; | 129 | let connection = Connection::open(data)?; |
109 | 130 | ||
@@ -125,15 +146,15 @@ pub fn mods_get_info(config: &Cfg, id: &str) -> MLE<ModInfo> { | |||
125 | }); | 146 | }); |
126 | } | 147 | } |
127 | 148 | ||
128 | if mod_info.is_none() { | 149 | if let Some(mi) = mod_info { |
129 | Err(MLErr::new(EType::DBError, "GN_MOD_NOT_FOUND")) | 150 | Ok(mi) |
130 | } else { | 151 | } else { |
131 | Ok(mod_info.ok_or(MLErr::new(EType::Other, "mod_info"))?) | 152 | Err(DBError::NotFound)? |
132 | } | 153 | } |
133 | } | 154 | } |
134 | 155 | ||
135 | /// # Errors | 156 | /// # Errors |
136 | pub fn mods_remove(config: &Cfg, id: &str) -> MLE<()> { | 157 | pub fn mods_remove(config: &Cfg, id: &str) -> DbE<()> { |
137 | let data = format!("{}/data.db", config.data); | 158 | let data = format!("{}/data.db", config.data); |
138 | let connection = Connection::open(data)?; | 159 | let connection = Connection::open(data)?; |
139 | 160 | ||
@@ -152,12 +173,12 @@ pub struct DBModlistVersions { | |||
152 | pub fn mods_get_versions( | 173 | pub fn mods_get_versions( |
153 | config: &Cfg, | 174 | config: &Cfg, |
154 | mods: &[String], | 175 | mods: &[String], |
155 | ) -> MLE<Vec<DBModlistVersions>> { | 176 | ) -> DbE<Vec<DBModlistVersions>> { |
156 | let data = format!("{}/data.db", config.data); | 177 | let data = format!("{}/data.db", config.data); |
157 | let connection = Connection::open(data)?; | 178 | let connection = Connection::open(data)?; |
158 | 179 | ||
159 | if mods.is_empty() { | 180 | if mods.is_empty() { |
160 | return Err(MLErr::new(EType::ArgumentError, "MODS_NO_INPUT")); | 181 | Err(DBError::NotEnoughArguments)?; |
161 | } | 182 | } |
162 | 183 | ||
163 | let mut wherestr = String::from("WHERE"); | 184 | let mut wherestr = String::from("WHERE"); |
@@ -190,7 +211,7 @@ pub fn mods_get_versions( | |||
190 | } | 211 | } |
191 | 212 | ||
192 | if versionmaps.is_empty() { | 213 | if versionmaps.is_empty() { |
193 | Err(MLErr::new(EType::DBError, "MODS_MODS_NOT_FOUND")) | 214 | Err(DBError::NotFound) |
194 | } else { | 215 | } else { |
195 | Ok(versionmaps) | 216 | Ok(versionmaps) |
196 | } | 217 | } |
@@ -206,7 +227,7 @@ pub fn userlist_insert( | |||
206 | applicable_versions: &[String], | 227 | applicable_versions: &[String], |
207 | current_link: &str, | 228 | current_link: &str, |
208 | set_version: bool, | 229 | set_version: bool, |
209 | ) -> MLE<()> { | 230 | ) -> DbE<()> { |
210 | let data = format!("{}/data.db", config.data); | 231 | let data = format!("{}/data.db", config.data); |
211 | let connection = Connection::open(data)?; | 232 | let connection = Connection::open(data)?; |
212 | 233 | ||
@@ -228,7 +249,7 @@ pub fn userlist_insert( | |||
228 | } | 249 | } |
229 | 250 | ||
230 | /// # Errors | 251 | /// # Errors |
231 | pub fn userlist_get_all_ids(config: &Cfg, list_id: &str) -> MLE<Vec<String>> { | 252 | pub fn userlist_get_all_ids(config: &Cfg, list_id: &str) -> DbE<Vec<String>> { |
232 | let data = format!("{}/data.db", config.data); | 253 | let data = format!("{}/data.db", config.data); |
233 | let connection = Connection::open(data)?; | 254 | let connection = Connection::open(data)?; |
234 | 255 | ||
@@ -242,17 +263,14 @@ pub fn userlist_get_all_ids(config: &Cfg, list_id: &str) -> MLE<Vec<String>> { | |||
242 | } | 263 | } |
243 | 264 | ||
244 | if mod_ids.is_empty() { | 265 | if mod_ids.is_empty() { |
245 | Err(MLErr::new( | 266 | Err(DBError::NotAvailable) |
246 | EType::DBError, | ||
247 | &format!("NO_MODS_USERLIST{list_id}"), | ||
248 | )) | ||
249 | } else { | 267 | } else { |
250 | Ok(mod_ids) | 268 | Ok(mod_ids) |
251 | } | 269 | } |
252 | } | 270 | } |
253 | 271 | ||
254 | /// # Errors | 272 | /// # Errors |
255 | pub fn userlist_remove(config: &Cfg, list_id: &str, mod_id: &str) -> MLE<()> { | 273 | pub fn userlist_remove(config: &Cfg, list_id: &str, mod_id: &str) -> DbE<()> { |
256 | let data = format!("{}/data.db", config.data); | 274 | let data = format!("{}/data.db", config.data); |
257 | let connection = Connection::open(data)?; | 275 | let connection = Connection::open(data)?; |
258 | 276 | ||
@@ -268,7 +286,7 @@ pub fn userlist_get_applicable_versions( | |||
268 | config: &Cfg, | 286 | config: &Cfg, |
269 | list_id: &str, | 287 | list_id: &str, |
270 | mod_id: String, | 288 | mod_id: String, |
271 | ) -> MLE<String> { | 289 | ) -> DbE<String> { |
272 | let data = format!("{}/data.db", config.data); | 290 | let data = format!("{}/data.db", config.data); |
273 | let connection = Connection::open(data)?; | 291 | let connection = Connection::open(data)?; |
274 | 292 | ||
@@ -285,7 +303,7 @@ pub fn userlist_get_applicable_versions( | |||
285 | } | 303 | } |
286 | 304 | ||
287 | if version.is_empty() { | 305 | if version.is_empty() { |
288 | Err(MLErr::new(EType::DBError, "GAV_MOD_NOT_FOUND")) | 306 | Err(DBError::NotFound) |
289 | } else { | 307 | } else { |
290 | Ok(version) | 308 | Ok(version) |
291 | } | 309 | } |
@@ -295,7 +313,7 @@ pub fn userlist_get_applicable_versions( | |||
295 | pub fn userlist_get_all_applicable_versions_with_mods( | 313 | pub fn userlist_get_all_applicable_versions_with_mods( |
296 | config: &Cfg, | 314 | config: &Cfg, |
297 | list_id: &str, | 315 | list_id: &str, |
298 | ) -> MLE<Vec<(String, String)>> { | 316 | ) -> DbE<Vec<(String, String)>> { |
299 | let data = format!("{}/data.db", config.data); | 317 | let data = format!("{}/data.db", config.data); |
300 | let connection = Connection::open(data)?; | 318 | let connection = Connection::open(data)?; |
301 | 319 | ||
@@ -316,7 +334,7 @@ pub fn userlist_get_all_applicable_versions_with_mods( | |||
316 | } | 334 | } |
317 | 335 | ||
318 | if versions.is_empty() { | 336 | if versions.is_empty() { |
319 | return Err(MLErr::new(EType::DBError, "NO_MODS_ON_LIST")); | 337 | return Err(DBError::NotAvailable); |
320 | }; | 338 | }; |
321 | 339 | ||
322 | Ok(versions) | 340 | Ok(versions) |
@@ -327,7 +345,7 @@ pub fn userlist_get_current_version( | |||
327 | config: &Cfg, | 345 | config: &Cfg, |
328 | list_id: &str, | 346 | list_id: &str, |
329 | mod_id: &str, | 347 | mod_id: &str, |
330 | ) -> MLE<String> { | 348 | ) -> DbE<String> { |
331 | let data = format!("{}/data.db", config.data); | 349 | let data = format!("{}/data.db", config.data); |
332 | let connection = Connection::open(data)?; | 350 | let connection = Connection::open(data)?; |
333 | 351 | ||
@@ -344,7 +362,7 @@ pub fn userlist_get_current_version( | |||
344 | } | 362 | } |
345 | 363 | ||
346 | if version.is_empty() { | 364 | if version.is_empty() { |
347 | Err(MLErr::new(EType::DBError, "GCV_MOD_NOT_FOUND")) | 365 | Err(DBError::NotFound) |
348 | } else { | 366 | } else { |
349 | Ok(version) | 367 | Ok(version) |
350 | } | 368 | } |
@@ -354,7 +372,7 @@ pub fn userlist_get_current_version( | |||
354 | pub fn userlist_get_all_current_version_ids( | 372 | pub fn userlist_get_all_current_version_ids( |
355 | config: &Cfg, | 373 | config: &Cfg, |
356 | list_id: &str, | 374 | list_id: &str, |
357 | ) -> MLE<Vec<String>> { | 375 | ) -> DbE<Vec<String>> { |
358 | let data = format!("{}/data.db", config.data); | 376 | let data = format!("{}/data.db", config.data); |
359 | let connection = Connection::open(data)?; | 377 | let connection = Connection::open(data)?; |
360 | 378 | ||
@@ -368,7 +386,7 @@ pub fn userlist_get_all_current_version_ids( | |||
368 | } | 386 | } |
369 | 387 | ||
370 | if versions.is_empty() { | 388 | if versions.is_empty() { |
371 | return Err(MLErr::new(EType::DBError, "NO_MODS_ON_LIST")); | 389 | return Err(DBError::NotAvailable); |
372 | }; | 390 | }; |
373 | 391 | ||
374 | Ok(versions) | 392 | Ok(versions) |
@@ -378,7 +396,7 @@ pub fn userlist_get_all_current_version_ids( | |||
378 | pub fn userlist_get_all_current_versions_with_mods( | 396 | pub fn userlist_get_all_current_versions_with_mods( |
379 | config: &Cfg, | 397 | config: &Cfg, |
380 | list_id: &str, | 398 | list_id: &str, |
381 | ) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> { | 399 | ) -> DbE<Vec<(String, String)>> { |
382 | let data = format!("{}/data.db", config.data); | 400 | let data = format!("{}/data.db", config.data); |
383 | let connection = Connection::open(data)?; | 401 | let connection = Connection::open(data)?; |
384 | 402 | ||
@@ -399,10 +417,7 @@ pub fn userlist_get_all_current_versions_with_mods( | |||
399 | } | 417 | } |
400 | 418 | ||
401 | if versions.is_empty() { | 419 | if versions.is_empty() { |
402 | return Err(Box::new(std::io::Error::new( | 420 | return Err(DBError::NotAvailable); |
403 | ErrorKind::Other, | ||
404 | "NO_MODS_ON_LIST", | ||
405 | ))); | ||
406 | }; | 421 | }; |
407 | 422 | ||
408 | Ok(versions) | 423 | Ok(versions) |
@@ -413,7 +428,7 @@ pub fn userlist_get_set_version( | |||
413 | config: &Cfg, | 428 | config: &Cfg, |
414 | list_id: &str, | 429 | list_id: &str, |
415 | mod_id: &str, | 430 | mod_id: &str, |
416 | ) -> MLE<bool> { | 431 | ) -> DbE<bool> { |
417 | let data = format!("{}/data.db", config.data); | 432 | let data = format!("{}/data.db", config.data); |
418 | let connection = Connection::open(data)?; | 433 | let connection = Connection::open(data)?; |
419 | 434 | ||
@@ -439,7 +454,7 @@ pub fn userlist_change_versions( | |||
439 | versions: String, | 454 | versions: String, |
440 | link: String, | 455 | link: String, |
441 | mod_id: String, | 456 | mod_id: String, |
442 | ) -> MLE<()> { | 457 | ) -> DbE<()> { |
443 | let data = format!("{}/data.db", config.data); | 458 | let data = format!("{}/data.db", config.data); |
444 | let connection = Connection::open(data)?; | 459 | let connection = Connection::open(data)?; |
445 | 460 | ||
@@ -453,7 +468,7 @@ pub fn userlist_add_disabled_versions( | |||
453 | list_id: &str, | 468 | list_id: &str, |
454 | disabled_version: String, | 469 | disabled_version: String, |
455 | mod_id: String, | 470 | mod_id: String, |
456 | ) -> MLE<()> { | 471 | ) -> DbE<()> { |
457 | let data = format!("{}/data.db", config.data); | 472 | let data = format!("{}/data.db", config.data); |
458 | let connection = Connection::open(data)?; | 473 | let connection = Connection::open(data)?; |
459 | 474 | ||
@@ -480,7 +495,7 @@ pub fn userlist_get_disabled_versions( | |||
480 | config: &Cfg, | 495 | config: &Cfg, |
481 | list_id: &str, | 496 | list_id: &str, |
482 | mod_id: String, | 497 | mod_id: String, |
483 | ) -> MLE<String> { | 498 | ) -> DbE<String> { |
484 | let data = format!("{}/data.db", config.data); | 499 | let data = format!("{}/data.db", config.data); |
485 | let connection = Connection::open(data)?; | 500 | let connection = Connection::open(data)?; |
486 | 501 | ||
@@ -497,7 +512,7 @@ pub fn userlist_get_disabled_versions( | |||
497 | } | 512 | } |
498 | 513 | ||
499 | if version.is_empty() { | 514 | if version.is_empty() { |
500 | Err(MLErr::new(EType::DBError, "GDV_MOD_NOT_FOUND")) | 515 | Err(DBError::NotFound) |
501 | } else { | 516 | } else { |
502 | Ok(version) | 517 | Ok(version) |
503 | } | 518 | } |
@@ -507,7 +522,7 @@ pub fn userlist_get_disabled_versions( | |||
507 | pub fn userlist_get_all_downloads( | 522 | pub fn userlist_get_all_downloads( |
508 | config: &Cfg, | 523 | config: &Cfg, |
509 | list_id: &str, | 524 | list_id: &str, |
510 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { | 525 | ) -> DbE<Vec<String>> { |
511 | let data = format!("{}/data.db", config.data); | 526 | let data = format!("{}/data.db", config.data); |
512 | let connection = Connection::open(data)?; | 527 | let connection = Connection::open(data)?; |
513 | 528 | ||
@@ -522,10 +537,7 @@ pub fn userlist_get_all_downloads( | |||
522 | } | 537 | } |
523 | 538 | ||
524 | if links.is_empty() { | 539 | if links.is_empty() { |
525 | return Err(Box::new(std::io::Error::new( | 540 | return Err(DBError::NotAvailable); |
526 | ErrorKind::Other, | ||
527 | "NO_MODS_ON_LIST", | ||
528 | ))); | ||
529 | }; | 541 | }; |
530 | 542 | ||
531 | Ok(links) | 543 | Ok(links) |
@@ -540,7 +552,7 @@ pub fn lists_insert( | |||
540 | mc_version: &str, | 552 | mc_version: &str, |
541 | mod_loader: &Modloader, | 553 | mod_loader: &Modloader, |
542 | download_folder: &str, | 554 | download_folder: &str, |
543 | ) -> MLE<()> { | 555 | ) -> DbE<()> { |
544 | let data = format!("{}/data.db", config.data); | 556 | let data = format!("{}/data.db", config.data); |
545 | let connection = Connection::open(data)?; | 557 | let connection = Connection::open(data)?; |
546 | 558 | ||
@@ -554,7 +566,7 @@ pub fn lists_insert( | |||
554 | } | 566 | } |
555 | 567 | ||
556 | /// # Errors | 568 | /// # Errors |
557 | pub fn lists_remove(config: &Cfg, id: &str) -> MLE<()> { | 569 | pub fn lists_remove(config: &Cfg, id: &str) -> DbE<()> { |
558 | let data = format!("{}/data.db", config.data); | 570 | let data = format!("{}/data.db", config.data); |
559 | let connection = Connection::open(data)?; | 571 | let connection = Connection::open(data)?; |
560 | 572 | ||
@@ -564,7 +576,7 @@ pub fn lists_remove(config: &Cfg, id: &str) -> MLE<()> { | |||
564 | } | 576 | } |
565 | 577 | ||
566 | /// # Errors | 578 | /// # Errors |
567 | pub fn lists_get(config: &Cfg, list_id: &str) -> MLE<List> { | 579 | pub fn lists_get(config: &Cfg, list_id: &str) -> DbE<List> { |
568 | let data = format!("{}/data.db", config.data); | 580 | let data = format!("{}/data.db", config.data); |
569 | let connection = Connection::open(data)?; | 581 | let connection = Connection::open(data)?; |
570 | 582 | ||
@@ -591,20 +603,20 @@ pub fn lists_get(config: &Cfg, list_id: &str) -> MLE<List> { | |||
591 | list = List { | 603 | list = List { |
592 | id: list_id.to_string(), | 604 | id: list_id.to_string(), |
593 | mc_version: String::from(&li[0]), | 605 | mc_version: String::from(&li[0]), |
594 | modloader: Modloader::from(&li[1])?, | 606 | modloader: Modloader::try_from(li[1].as_str())?, |
595 | download_folder: String::from(&li[2]), | 607 | download_folder: String::from(&li[2]), |
596 | }; | 608 | }; |
597 | } | 609 | } |
598 | 610 | ||
599 | if list.id.is_empty() { | 611 | if list.id.is_empty() { |
600 | return Err(MLErr::new(EType::DBError, "LIST_NOT_FOUND")); | 612 | Err(DBError::NotFound)?; |
601 | } | 613 | } |
602 | 614 | ||
603 | Ok(list) | 615 | Ok(list) |
604 | } | 616 | } |
605 | 617 | ||
606 | /// # Errors | 618 | /// # Errors |
607 | pub fn lists_version(config: &Cfg, list_id: &str, version: &str) -> MLE<()> { | 619 | pub fn lists_version(config: &Cfg, list_id: &str, version: &str) -> DbE<()> { |
608 | let data = format!("{}/data.db", config.data); | 620 | let data = format!("{}/data.db", config.data); |
609 | let connection = Connection::open(data)?; | 621 | let connection = Connection::open(data)?; |
610 | 622 | ||
@@ -616,7 +628,7 @@ pub fn lists_version(config: &Cfg, list_id: &str, version: &str) -> MLE<()> { | |||
616 | } | 628 | } |
617 | 629 | ||
618 | /// # Errors | 630 | /// # Errors |
619 | pub fn lists_get_all_ids(config: &Cfg) -> MLE<Vec<String>> { | 631 | pub fn lists_get_all_ids(config: &Cfg) -> DbE<Vec<String>> { |
620 | let data = format!("{}/data.db", config.data); | 632 | let data = format!("{}/data.db", config.data); |
621 | let connection = Connection::open(data)?; | 633 | let connection = Connection::open(data)?; |
622 | 634 | ||
@@ -629,7 +641,7 @@ pub fn lists_get_all_ids(config: &Cfg) -> MLE<Vec<String>> { | |||
629 | } | 641 | } |
630 | 642 | ||
631 | if list_ids.is_empty() { | 643 | if list_ids.is_empty() { |
632 | Err(MLErr::new(EType::DBError, "NO_LISTS")) | 644 | Err(DBError::NotAvailable) |
633 | } else { | 645 | } else { |
634 | Ok(list_ids) | 646 | Ok(list_ids) |
635 | } | 647 | } |
@@ -637,7 +649,7 @@ pub fn lists_get_all_ids(config: &Cfg) -> MLE<Vec<String>> { | |||
637 | 649 | ||
638 | //config | 650 | //config |
639 | /// # Errors | 651 | /// # Errors |
640 | pub fn config_change_current_list(config: &Cfg, id: &str) -> MLE<()> { | 652 | pub fn config_change_current_list(config: &Cfg, id: &str) -> DbE<()> { |
641 | let data = format!("{}/data.db", config.data); | 653 | let data = format!("{}/data.db", config.data); |
642 | let connection = Connection::open(data)?; | 654 | let connection = Connection::open(data)?; |
643 | 655 | ||
@@ -649,7 +661,7 @@ pub fn config_change_current_list(config: &Cfg, id: &str) -> MLE<()> { | |||
649 | } | 661 | } |
650 | 662 | ||
651 | /// # Errors | 663 | /// # Errors |
652 | pub fn config_get_current_list(config: &Cfg) -> MLE<String> { | 664 | pub fn config_get_current_list(config: &Cfg) -> DbE<String> { |
653 | let data = format!("{}/data.db", config.data); | 665 | let data = format!("{}/data.db", config.data); |
654 | let connection = Connection::open(data)?; | 666 | let connection = Connection::open(data)?; |
655 | 667 | ||
@@ -663,7 +675,7 @@ pub fn config_get_current_list(config: &Cfg) -> MLE<String> { | |||
663 | } | 675 | } |
664 | 676 | ||
665 | if list_id.is_empty() { | 677 | if list_id.is_empty() { |
666 | return Err(MLErr::new(EType::DBError, "NO_CURRENT_LIST")); | 678 | return Err(DBError::NotAvailable); |
667 | } | 679 | } |
668 | 680 | ||
669 | Ok(list_id) | 681 | Ok(list_id) |
@@ -720,7 +732,7 @@ pub fn s_config_update_version( | |||
720 | /// # Errors | 732 | /// # Errors |
721 | pub fn s_config_get_version( | 733 | pub fn s_config_get_version( |
722 | config: &Cfg, | 734 | config: &Cfg, |
723 | ) -> Result<String, Box<dyn std::error::Error>> { | 735 | ) -> DbE<String> { |
724 | let data = format!("{}/data.db", config.data); | 736 | let data = format!("{}/data.db", config.data); |
725 | let connection = Connection::open(data)?; | 737 | let connection = Connection::open(data)?; |
726 | 738 | ||
@@ -734,10 +746,7 @@ pub fn s_config_get_version( | |||
734 | } | 746 | } |
735 | 747 | ||
736 | if version.is_empty() { | 748 | if version.is_empty() { |
737 | return Err(Box::new(std::io::Error::new( | 749 | return Err(DBError::NotAvailable); |
738 | ErrorKind::Other, | ||
739 | "NO_DBVERSION", | ||
740 | ))); | ||
741 | }; | 750 | }; |
742 | Ok(version) | 751 | Ok(version) |
743 | } | 752 | } |
@@ -749,18 +758,14 @@ pub fn s_insert_column( | |||
749 | column: &str, | 758 | column: &str, |
750 | c_type: &str, | 759 | c_type: &str, |
751 | default: Option<String>, | 760 | default: Option<String>, |
752 | ) -> Result<(), Box<dyn std::error::Error>> { | 761 | ) -> DbE<()> { |
753 | let data = format!("{}/data.db", config.data); | 762 | let data = format!("{}/data.db", config.data); |
754 | let connection = Connection::open(data)?; | 763 | let connection = Connection::open(data)?; |
755 | 764 | ||
756 | let mut sql = format!("ALTER TABLE {table} ADD '{column}' {c_type}"); | 765 | let mut sql = format!("ALTER TABLE {table} ADD '{column}' {c_type}"); |
757 | 766 | ||
758 | if default.is_some() { | 767 | if let Some(def) = default { |
759 | sql = format!( | 768 | sql = format!("{sql} DEFAULT {def}"); |
760 | "{} DEFAULT {}", | ||
761 | sql, | ||
762 | default.ok_or(MLErr::new(EType::Other, "errornous default"))? | ||
763 | ); | ||
764 | } | 769 | } |
765 | 770 | ||
766 | connection.execute(sql.as_str(), ())?; | 771 | connection.execute(sql.as_str(), ())?; |
@@ -768,7 +773,7 @@ pub fn s_insert_column( | |||
768 | } | 773 | } |
769 | 774 | ||
770 | /// # Errors | 775 | /// # Errors |
771 | pub fn setup(path: &str) -> MLE<()> { | 776 | pub fn setup(path: &str) -> DbE<()> { |
772 | let connection = Connection::open(path)?; | 777 | let connection = Connection::open(path)?; |
773 | 778 | ||
774 | connection.execute_batch( | 779 | connection.execute_batch( |
diff --git a/src/error.rs b/src/error.rs deleted file mode 100644 index 652fa0c..0000000 --- a/src/error.rs +++ /dev/null | |||
@@ -1,129 +0,0 @@ | |||
1 | use core::fmt; | ||
2 | use serde::Deserialize; | ||
3 | |||
4 | pub type MLE<T> = Result<T, MLErr>; | ||
5 | |||
6 | #[derive(Debug, Deserialize)] | ||
7 | pub struct MLErr { | ||
8 | etype: EType, | ||
9 | message: String, | ||
10 | } | ||
11 | |||
12 | #[derive(Debug, Deserialize)] | ||
13 | pub enum EType { | ||
14 | ArgumentError, | ||
15 | ArgumentCountError, | ||
16 | ConfigError, | ||
17 | DBError, | ||
18 | ModError, | ||
19 | LibToml, | ||
20 | LibSql, | ||
21 | LibReq, | ||
22 | LibChrono, | ||
23 | LibJson, | ||
24 | LibIndicatif, | ||
25 | IoError, | ||
26 | Other, | ||
27 | } | ||
28 | |||
29 | impl std::error::Error for MLErr { | ||
30 | fn description(&self) -> &str { | ||
31 | &self.message | ||
32 | } | ||
33 | } | ||
34 | |||
35 | impl fmt::Display for MLErr { | ||
36 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
37 | match self.etype { | ||
38 | EType::ArgumentError => { | ||
39 | write!(f, "User input not accepted: {}", self.message) | ||
40 | } | ||
41 | EType::ArgumentCountError => { | ||
42 | write!(f, "Too many/too few arguments") | ||
43 | } | ||
44 | EType::ConfigError => write!(f, "CONFIG"), | ||
45 | EType::DBError => write!(f, "Database: {}", self.message), | ||
46 | EType::ModError => write!(f, "Mod: {}", self.message), | ||
47 | EType::LibToml => write!(f, "TOML"), | ||
48 | EType::LibSql => write!(f, "SQL: {}", self.message), | ||
49 | EType::LibReq => write!(f, "REQWEST"), | ||
50 | EType::LibChrono => write!(f, "Chrono error: {}", self.message), | ||
51 | EType::LibJson => write!(f, "JSON: {}", self.message), | ||
52 | EType::LibIndicatif => write!(f, "Indicativ: {}", self.message), | ||
53 | EType::IoError => write!(f, "IO"), | ||
54 | EType::Other => write!(f, "OTHER"), | ||
55 | } | ||
56 | } | ||
57 | } | ||
58 | |||
59 | impl From<reqwest::Error> for MLErr { | ||
60 | fn from(error: reqwest::Error) -> Self { | ||
61 | Self { | ||
62 | etype: EType::LibReq, | ||
63 | message: error.to_string(), | ||
64 | } | ||
65 | } | ||
66 | } | ||
67 | |||
68 | impl From<toml::de::Error> for MLErr { | ||
69 | fn from(error: toml::de::Error) -> Self { | ||
70 | Self { | ||
71 | etype: EType::LibToml, | ||
72 | message: error.to_string(), | ||
73 | } | ||
74 | } | ||
75 | } | ||
76 | |||
77 | impl From<rusqlite::Error> for MLErr { | ||
78 | fn from(error: rusqlite::Error) -> Self { | ||
79 | Self { | ||
80 | etype: EType::LibSql, | ||
81 | message: error.to_string(), | ||
82 | } | ||
83 | } | ||
84 | } | ||
85 | |||
86 | impl From<toml::ser::Error> for MLErr { | ||
87 | fn from(error: toml::ser::Error) -> Self { | ||
88 | Self { | ||
89 | etype: EType::LibToml, | ||
90 | message: error.to_string(), | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | impl From<chrono::ParseError> for MLErr { | ||
96 | fn from(error: chrono::ParseError) -> Self { | ||
97 | Self { | ||
98 | etype: EType::LibChrono, | ||
99 | message: error.to_string(), | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | |||
104 | impl From<std::io::Error> for MLErr { | ||
105 | fn from(error: std::io::Error) -> Self { | ||
106 | Self { | ||
107 | etype: EType::IoError, | ||
108 | message: error.to_string(), | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | |||
113 | impl From<serde_json::error::Error> for MLErr { | ||
114 | fn from(value: serde_json::error::Error) -> Self { | ||
115 | Self { | ||
116 | etype: EType::LibJson, | ||
117 | message: value.to_string(), | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | |||
122 | impl MLErr { | ||
123 | #[must_use] pub fn new(etype: EType, message: &str) -> Self { | ||
124 | Self { | ||
125 | etype, | ||
126 | message: String::from(message), | ||
127 | } | ||
128 | } | ||
129 | } | ||
diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..be2ca3c --- /dev/null +++ b/src/errors.rs | |||
@@ -0,0 +1,132 @@ | |||
1 | use std::{io, num::TryFromIntError, time::SystemTimeError}; | ||
2 | |||
3 | use chrono::ParseError; | ||
4 | use indicatif::style::TemplateError; | ||
5 | use reqwest::StatusCode; | ||
6 | |||
7 | use crate::db::DBError; | ||
8 | |||
9 | pub type MLE<T> = Result<T, Error>; | ||
10 | |||
11 | #[derive(Debug, thiserror::Error)] | ||
12 | pub enum Error { | ||
13 | #[error("io: {source}")] | ||
14 | Io { | ||
15 | #[from] | ||
16 | source: io::Error, | ||
17 | }, | ||
18 | |||
19 | #[error("tryfromint: {source}")] | ||
20 | TryFromInt { | ||
21 | #[from] | ||
22 | source: TryFromIntError, | ||
23 | }, | ||
24 | |||
25 | #[error("serde_json: {source}")] | ||
26 | Json { | ||
27 | #[from] | ||
28 | source: serde_json::Error, | ||
29 | }, | ||
30 | |||
31 | #[error("reqwest: {source}")] | ||
32 | Reqwest { | ||
33 | #[from] | ||
34 | source: reqwest::Error, | ||
35 | }, | ||
36 | |||
37 | #[error("chrono parse error: {source}")] | ||
38 | ChronoParse { | ||
39 | #[from] | ||
40 | source: ParseError, | ||
41 | }, | ||
42 | |||
43 | #[error("config: {source}")] | ||
44 | Config { | ||
45 | #[from] | ||
46 | source: config::ConfigError, | ||
47 | }, | ||
48 | |||
49 | #[error("indicatif template: {source}")] | ||
50 | IndicatifTemplate { | ||
51 | #[from] | ||
52 | source: TemplateError, | ||
53 | }, | ||
54 | |||
55 | #[error("toml: {source}")] | ||
56 | TomlSer { | ||
57 | #[from] | ||
58 | source: toml::ser::Error, | ||
59 | }, | ||
60 | |||
61 | #[error("toml: {source}")] | ||
62 | TomlDeser { | ||
63 | #[from] | ||
64 | source: toml::de::Error, | ||
65 | }, | ||
66 | |||
67 | #[error("systemtime: {source}")] | ||
68 | Systemtime { | ||
69 | #[from] | ||
70 | source: SystemTimeError, | ||
71 | }, | ||
72 | |||
73 | #[error("conversion: {source}")] | ||
74 | Conversion { | ||
75 | #[from] | ||
76 | source: ConversionError, | ||
77 | }, | ||
78 | |||
79 | #[error("Request didn't return 200 OK ({0})")] | ||
80 | RequestNotOK(StatusCode), | ||
81 | |||
82 | #[error("ModError ({0})")] | ||
83 | ModError(String), | ||
84 | |||
85 | #[error("No file extension where one should be")] | ||
86 | NoFileExtension, | ||
87 | |||
88 | #[error("Desired path not found")] | ||
89 | PathNotFound, | ||
90 | |||
91 | #[error("Desired system directory {0} not found")] | ||
92 | SysDirNotFound(String), | ||
93 | |||
94 | #[error("No requested Minecraft version found")] | ||
95 | MinecraftVersionNotFound, | ||
96 | |||
97 | #[error("Mod already added")] | ||
98 | ModAlreadyOnList, | ||
99 | |||
100 | #[error("No versions are applicable for the current scope")] | ||
101 | NoCurrentVersion, | ||
102 | |||
103 | #[error("The version does not know if it's locked or not")] | ||
104 | VersionSetNotSet, | ||
105 | |||
106 | #[error("No download for the current id found")] | ||
107 | NoDownload, | ||
108 | |||
109 | #[error("No ProjectInfo found / no id given")] | ||
110 | NoProjectInfo, | ||
111 | |||
112 | #[error("The requested List was not found")] | ||
113 | ListNotFound, | ||
114 | |||
115 | #[error("No download folder given")] | ||
116 | NoDownloadFolder, | ||
117 | |||
118 | #[error("db: {source}")] | ||
119 | DB { | ||
120 | #[from] | ||
121 | source: DBError, | ||
122 | }, | ||
123 | } | ||
124 | |||
125 | #[derive(Debug, thiserror::Error)] | ||
126 | pub enum ConversionError { | ||
127 | #[error("couldn't convert to Modloader from: {0}")] | ||
128 | Modloader(String), | ||
129 | |||
130 | #[error("Path couldn't be converted to string")] | ||
131 | InvalidPath, | ||
132 | } | ||
diff --git a/src/files.rs b/src/files.rs index 98785fd..2a6e949 100644 --- a/src/files.rs +++ b/src/files.rs | |||
@@ -10,7 +10,13 @@ use std::{ | |||
10 | use tokio::task::JoinSet; | 10 | use tokio::task::JoinSet; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | apis::modrinth::Version, cache::{copy_cached_version, get_cached_versions}, config::Cfg, data::list::List, db::{mods_get_info, userlist_add_disabled_versions}, error::{EType, MLErr, MLE}, PROGRESS_CHARS, STYLE_BAR_BYTE, STYLE_BAR_POS, STYLE_SPINNER | 13 | apis::modrinth::Version, |
14 | cache::{copy_cached_version, get_cached_versions}, | ||
15 | config::Cfg, | ||
16 | data::list::List, | ||
17 | db::{mods_get_info, userlist_add_disabled_versions}, | ||
18 | errors::{ConversionError, Error, MLE}, | ||
19 | PROGRESS_CHARS, STYLE_BAR_BYTE, STYLE_BAR_POS, STYLE_SPINNER, | ||
14 | }; | 20 | }; |
15 | 21 | ||
16 | /// # Errors | 22 | /// # Errors |
@@ -25,15 +31,14 @@ pub async fn download_versions( | |||
25 | 31 | ||
26 | let mut js = JoinSet::new(); | 32 | let mut js = JoinSet::new(); |
27 | 33 | ||
28 | let style_spinner = ProgressStyle::with_template(STYLE_SPINNER).map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?; | 34 | let style_spinner = ProgressStyle::with_template(STYLE_SPINNER)?; |
29 | 35 | ||
30 | let all = progress.insert_before( | 36 | let all = progress.insert_before( |
31 | progress_before, | 37 | progress_before, |
32 | ProgressBar::new(versions.len().try_into().map_err(|_| MLErr::new(EType::Other, "ListStackLen"))?), | 38 | ProgressBar::new(versions.len().try_into()?), |
33 | ); | 39 | ); |
34 | all.set_style( | 40 | all.set_style( |
35 | ProgressStyle::with_template(STYLE_BAR_POS) | 41 | ProgressStyle::with_template(STYLE_BAR_POS)? |
36 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))? | ||
37 | .progress_chars(PROGRESS_CHARS), | 42 | .progress_chars(PROGRESS_CHARS), |
38 | ); | 43 | ); |
39 | all.set_message(format!("✓Downloading {}", list.id)); | 44 | all.set_message(format!("✓Downloading {}", list.id)); |
@@ -87,8 +92,8 @@ async fn download_version( | |||
87 | None => files[0].clone(), | 92 | None => files[0].clone(), |
88 | }; | 93 | }; |
89 | let mut splitname: Vec<&str> = file.filename.split('.').collect(); | 94 | let mut splitname: Vec<&str> = file.filename.split('.').collect(); |
90 | let Ok(extension) = splitname.pop().ok_or("") else { | 95 | let Some(extension) = splitname.pop() else { |
91 | return Err(MLErr::new(EType::Other, "NO_FILE_EXTENSION")) | 96 | return Err(Error::NoFileExtension); |
92 | }; | 97 | }; |
93 | let filename = format!( | 98 | let filename = format!( |
94 | "{}.mr.{}.{}.{}", | 99 | "{}.mr.{}.{}.{}", |
@@ -169,7 +174,12 @@ pub fn disable_version( | |||
169 | 174 | ||
170 | rename(file, disabled)?; | 175 | rename(file, disabled)?; |
171 | 176 | ||
172 | userlist_add_disabled_versions(config, ¤t_list.id, versionid, mod_id)?; | 177 | userlist_add_disabled_versions( |
178 | config, | ||
179 | ¤t_list.id, | ||
180 | versionid, | ||
181 | mod_id, | ||
182 | )?; | ||
173 | 183 | ||
174 | Ok(()) | 184 | Ok(()) |
175 | } | 185 | } |
@@ -189,8 +199,8 @@ pub fn get_file_path(list: &List, versionid: &str) -> MLE<String> { | |||
189 | for file in read_dir(&list.download_folder)? { | 199 | for file in read_dir(&list.download_folder)? { |
190 | let path = file?.path(); | 200 | let path = file?.path(); |
191 | if path.is_file() { | 201 | if path.is_file() { |
192 | let Ok(pathstr) = path.to_str().ok_or("") else { | 202 | let Some(pathstr) = path.to_str() else { |
193 | return Err(MLErr::new(EType::Other, "INVALID_PATH")) | 203 | return Err(Error::PathNotFound); |
194 | }; | 204 | }; |
195 | let namesplit: Vec<&str> = pathstr.split('.').collect(); | 205 | let namesplit: Vec<&str> = pathstr.split('.').collect(); |
196 | let ver_id = namesplit[namesplit.len() - 2]; | 206 | let ver_id = namesplit[namesplit.len() - 2]; |
@@ -198,11 +208,8 @@ pub fn get_file_path(list: &List, versionid: &str) -> MLE<String> { | |||
198 | } | 208 | } |
199 | } | 209 | } |
200 | 210 | ||
201 | let Ok(filename) = names.get(versionid).ok_or("") else { | 211 | let Some(filename) = names.get(versionid) else { |
202 | return Err(MLErr::new( | 212 | return Err(Error::PathNotFound); |
203 | EType::ArgumentError, | ||
204 | "VERSION_NOT_FOUND_IN_FILES", | ||
205 | )) | ||
206 | }; | 213 | }; |
207 | 214 | ||
208 | Ok(filename.to_owned()) | 215 | Ok(filename.to_owned()) |
@@ -213,13 +220,16 @@ pub fn get_downloaded_versions(list: &List) -> MLE<HashMap<String, String>> { | |||
213 | let mut versions: HashMap<String, String> = HashMap::new(); | 220 | let mut versions: HashMap<String, String> = HashMap::new(); |
214 | for file in read_dir(&list.download_folder)? { | 221 | for file in read_dir(&list.download_folder)? { |
215 | let path = file?.path(); | 222 | let path = file?.path(); |
216 | if path.is_file() | 223 | if path.is_file() { |
217 | && path | 224 | let Some(extension) = path.extension() else { |
218 | .extension() | 225 | return Err(Error::NoFileExtension); |
219 | .ok_or(MLErr::new(EType::IoError, "extension"))? | 226 | }; |
220 | == "jar" | 227 | if extension != "jar" { |
221 | { | 228 | continue; |
222 | let pathstr = path.to_str().ok_or(MLErr::new(EType::IoError, "path_to_str"))?; | 229 | } |
230 | let Some(pathstr) = path.to_str() else { | ||
231 | return Err(ConversionError::InvalidPath)?; | ||
232 | }; | ||
223 | let namesplit: Vec<&str> = pathstr.split('.').collect(); | 233 | let namesplit: Vec<&str> = pathstr.split('.').collect(); |
224 | versions.insert( | 234 | versions.insert( |
225 | String::from(namesplit[namesplit.len() - 3]), | 235 | String::from(namesplit[namesplit.len() - 3]), |
diff --git a/src/main.rs b/src/main.rs index 038e2f4..1b8f041 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -5,7 +5,7 @@ pub mod cache; | |||
5 | pub mod commands; | 5 | pub mod commands; |
6 | pub mod config; | 6 | pub mod config; |
7 | pub mod db; | 7 | pub mod db; |
8 | pub mod error; | 8 | pub mod errors; |
9 | pub mod files; | 9 | pub mod files; |
10 | pub mod data; | 10 | pub mod data; |
11 | 11 | ||
@@ -14,7 +14,7 @@ use config::Cfg; | |||
14 | use data::{gameversion::VersionLevel, list::List, modification::{AddMod, IDSelector}, modloader::Modloader}; | 14 | use data::{gameversion::VersionLevel, list::List, modification::{AddMod, IDSelector}, modloader::Modloader}; |
15 | pub use data::{STYLE_BAR_POS, STYLE_MESSAGE, STYLE_SPINNER, STYLE_BAR_BYTE, STYLE_OPERATION, PROGRESS_CHARS}; | 15 | pub use data::{STYLE_BAR_POS, STYLE_MESSAGE, STYLE_SPINNER, STYLE_BAR_BYTE, STYLE_OPERATION, PROGRESS_CHARS}; |
16 | use db::{config_get_current_list, lists_get, lists_get_all_ids}; | 16 | use db::{config_get_current_list, lists_get, lists_get_all_ids}; |
17 | use error::MLE; | 17 | use errors::MLE; |
18 | 18 | ||
19 | #[derive(Parser)] | 19 | #[derive(Parser)] |
20 | #[command(author, version, about)] | 20 | #[command(author, version, about)] |
@@ -297,7 +297,7 @@ async fn handle_list( | |||
297 | version, | 297 | version, |
298 | } => { | 298 | } => { |
299 | let ml = match modloader { | 299 | let ml = match modloader { |
300 | Some(ml) => Modloader::from(&ml).unwrap(), | 300 | Some(ml) => Modloader::try_from(ml.as_str())?, |
301 | None => config.defaults.modloader.clone(), | 301 | None => config.defaults.modloader.clone(), |
302 | }; | 302 | }; |
303 | 303 | ||