diff options
-rw-r--r-- | src/apis/modrinth.rs | 18 | ||||
-rw-r--r-- | src/commands/download.rs | 30 | ||||
-rw-r--r-- | src/commands/io.rs | 24 | ||||
-rw-r--r-- | src/commands/list.rs | 33 | ||||
-rw-r--r-- | src/commands/modification.rs | 57 | ||||
-rw-r--r-- | src/commands/update.rs | 39 | ||||
-rw-r--r-- | src/config.rs | 13 | ||||
-rw-r--r-- | src/db.rs | 222 | ||||
-rw-r--r-- | src/error.rs | 70 | ||||
-rw-r--r-- | src/files.rs | 66 | ||||
-rw-r--r-- | src/lib.rs | 52 | ||||
-rw-r--r-- | src/main.rs | 13 |
12 files changed, 385 insertions, 252 deletions
diff --git a/src/apis/modrinth.rs b/src/apis/modrinth.rs index 5366f3d..75e65e6 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::{ErrorType, MLError, MLE}, | 6 | error::{EType, MLErr, MLE}, |
7 | List, | 7 | List, |
8 | }; | 8 | }; |
9 | 9 | ||
@@ -130,6 +130,8 @@ pub enum GameVersionType { | |||
130 | beta, | 130 | beta, |
131 | } | 131 | } |
132 | 132 | ||
133 | /// # Errors | ||
134 | /// # Panics | ||
133 | async fn get( | 135 | async fn get( |
134 | api: &str, | 136 | api: &str, |
135 | path: &str, | 137 | path: &str, |
@@ -153,6 +155,8 @@ async fn get( | |||
153 | Ok(data) | 155 | Ok(data) |
154 | } | 156 | } |
155 | 157 | ||
158 | /// # Errors | ||
159 | /// # Panics | ||
156 | pub async fn project(api: &str, name: &str) -> Project { | 160 | pub async fn project(api: &str, name: &str) -> Project { |
157 | let url = format!("project/{name}"); | 161 | let url = format!("project/{name}"); |
158 | let data = get(api, &url).await.unwrap().unwrap(); | 162 | let data = get(api, &url).await.unwrap().unwrap(); |
@@ -160,6 +164,8 @@ pub async fn project(api: &str, name: &str) -> Project { | |||
160 | serde_json::from_slice(&data).unwrap() | 164 | serde_json::from_slice(&data).unwrap() |
161 | } | 165 | } |
162 | 166 | ||
167 | /// # Errors | ||
168 | /// # Panics | ||
163 | pub async fn projects(api: &str, ids: Vec<String>) -> Vec<Project> { | 169 | pub async fn projects(api: &str, ids: Vec<String>) -> Vec<Project> { |
164 | let all = ids.join(r#"",""#); | 170 | let all = ids.join(r#"",""#); |
165 | let url = format!(r#"projects?ids=["{all}"]"#); | 171 | let url = format!(r#"projects?ids=["{all}"]"#); |
@@ -170,6 +176,8 @@ pub async fn projects(api: &str, ids: Vec<String>) -> Vec<Project> { | |||
170 | } | 176 | } |
171 | 177 | ||
172 | ///Get applicable versions from `mod_id` with list context | 178 | ///Get applicable versions from `mod_id` with list context |
179 | /// # Errors | ||
180 | /// # Panics | ||
173 | pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { | 181 | pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { |
174 | let url = format!( | 182 | let url = format!( |
175 | r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, | 183 | r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, |
@@ -185,6 +193,8 @@ pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { | |||
185 | } | 193 | } |
186 | 194 | ||
187 | ///Get version with the version ids | 195 | ///Get version with the version ids |
196 | /// # Errors | ||
197 | /// # Panics | ||
188 | pub async fn get_raw_versions( | 198 | pub async fn get_raw_versions( |
189 | api: &str, | 199 | api: &str, |
190 | versions: Vec<String>, | 200 | versions: Vec<String>, |
@@ -196,9 +206,10 @@ pub async fn get_raw_versions( | |||
196 | serde_json::from_slice(&data).unwrap() | 206 | serde_json::from_slice(&data).unwrap() |
197 | } | 207 | } |
198 | 208 | ||
209 | /// # Errors | ||
199 | pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> { | 210 | pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> { |
200 | match versions.len() { | 211 | match versions.len() { |
201 | 0 => Err(MLError::new(ErrorType::ModError, "NO_VERSIONS_AVAILABLE")), | 212 | 0 => Err(MLErr::new(EType::ModError, "NO_VERSIONS_AVAILABLE")), |
202 | 1.. => { | 213 | 1.. => { |
203 | let mut times: Vec<(String, DateTime<FixedOffset>)> = vec![]; | 214 | let mut times: Vec<(String, DateTime<FixedOffset>)> = vec![]; |
204 | for ver in versions { | 215 | for ver in versions { |
@@ -209,10 +220,11 @@ pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> { | |||
209 | times.reverse(); | 220 | times.reverse(); |
210 | Ok(times[0].0.to_string()) | 221 | Ok(times[0].0.to_string()) |
211 | } | 222 | } |
212 | _ => panic!("available_versions should never be negative"), | ||
213 | } | 223 | } |
214 | } | 224 | } |
215 | 225 | ||
226 | /// # Errors | ||
227 | /// # Panics | ||
216 | pub async fn get_game_versions() -> Vec<GameVersion> { | 228 | pub async fn get_game_versions() -> Vec<GameVersion> { |
217 | let data = get("https://api.modrinth.com/v2/", "tag/game_version") | 229 | let data = get("https://api.modrinth.com/v2/", "tag/game_version") |
218 | .await | 230 | .await |
diff --git a/src/commands/download.rs b/src/commands/download.rs index 3e50c87..7321832 100644 --- a/src/commands/download.rs +++ b/src/commands/download.rs | |||
@@ -1,9 +1,11 @@ | |||
1 | #![allow(clippy::too_many_lines)] | ||
2 | |||
1 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; | 3 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; |
2 | 4 | ||
3 | use crate::{config::Cfg, List}; | 5 | use crate::{config::Cfg, List}; |
4 | use crate::{ | 6 | use crate::{ |
5 | db::userlist_get_all_current_versions_with_mods, | 7 | db::userlist_get_all_current_versions_with_mods, |
6 | error::{ErrorType, MLError, MLE}, | 8 | error::{EType, MLErr, MLE}, |
7 | files::{ | 9 | files::{ |
8 | clean_list_dir, delete_version, disable_version, download_versions, | 10 | clean_list_dir, delete_version, disable_version, download_versions, |
9 | get_downloaded_versions, | 11 | get_downloaded_versions, |
@@ -12,6 +14,8 @@ use crate::{ | |||
12 | }; | 14 | }; |
13 | use crate::{PROGRESS_CHARS, STYLE_BAR_POS}; | 15 | use crate::{PROGRESS_CHARS, STYLE_BAR_POS}; |
14 | 16 | ||
17 | /// # Errors | ||
18 | /// # Panics | ||
15 | pub async fn download( | 19 | pub async fn download( |
16 | config: &Cfg, | 20 | config: &Cfg, |
17 | liststack: Vec<List>, | 21 | liststack: Vec<List>, |
@@ -31,15 +35,15 @@ pub async fn download( | |||
31 | download_p.set_message(format!("Download in {}", current_list.id)); | 35 | download_p.set_message(format!("Download in {}", current_list.id)); |
32 | 36 | ||
33 | let downloaded_versions = | 37 | let downloaded_versions = |
34 | get_downloaded_versions(current_list.clone())?; | 38 | get_downloaded_versions(¤t_list)?; |
35 | let current_version_ids = | 39 | let current_version_ids = |
36 | match userlist_get_all_current_versions_with_mods( | 40 | match userlist_get_all_current_versions_with_mods( |
37 | config, | 41 | config, |
38 | String::from(¤t_list.id), | 42 | ¤t_list.id, |
39 | ) { | 43 | ) { |
40 | Ok(i) => Ok(i), | 44 | Ok(i) => Ok(i), |
41 | Err(e) => Err(MLError::new( | 45 | Err(e) => Err(MLErr::new( |
42 | ErrorType::DBError, | 46 | EType::DBError, |
43 | e.to_string().as_str(), | 47 | e.to_string().as_str(), |
44 | )), | 48 | )), |
45 | }?; | 49 | }?; |
@@ -74,7 +78,12 @@ pub async fn download( | |||
74 | clean_list_dir(¤t_list)?; | 78 | clean_list_dir(¤t_list)?; |
75 | }; | 79 | }; |
76 | 80 | ||
77 | if !to_download.is_empty() { | 81 | if to_download.is_empty() { |
82 | download_p.println(format!( | ||
83 | "There are no new versions to download for {}", | ||
84 | current_list.id | ||
85 | )); | ||
86 | } else { | ||
78 | download_versions( | 87 | download_versions( |
79 | current_list.clone(), | 88 | current_list.clone(), |
80 | config.clone(), | 89 | config.clone(), |
@@ -83,11 +92,6 @@ pub async fn download( | |||
83 | &download_p, | 92 | &download_p, |
84 | ) | 93 | ) |
85 | .await?; | 94 | .await?; |
86 | } else { | ||
87 | download_p.println(format!( | ||
88 | "There are no new versions to download for {}", | ||
89 | current_list.id | ||
90 | )); | ||
91 | } | 95 | } |
92 | 96 | ||
93 | if !to_disable.is_empty() { | 97 | if !to_disable.is_empty() { |
@@ -104,13 +108,13 @@ pub async fn download( | |||
104 | if delete_old { | 108 | if delete_old { |
105 | d_p.set_message(format!("Delete version {}", ver.1)); | 109 | d_p.set_message(format!("Delete version {}", ver.1)); |
106 | d_p.inc(1); | 110 | d_p.inc(1); |
107 | delete_version(¤t_list, ver.1)?; | 111 | delete_version(¤t_list, &ver.1)?; |
108 | } else { | 112 | } else { |
109 | d_p.set_message(format!("Disable version {}", ver.1)); | 113 | d_p.set_message(format!("Disable version {}", ver.1)); |
110 | d_p.inc(1); | 114 | d_p.inc(1); |
111 | disable_version( | 115 | disable_version( |
112 | config, | 116 | config, |
113 | current_list.clone(), | 117 | ¤t_list, |
114 | ver.1, | 118 | ver.1, |
115 | ver.0, | 119 | ver.0, |
116 | )?; | 120 | )?; |
diff --git a/src/commands/io.rs b/src/commands/io.rs index 1d17f7c..c9691c4 100644 --- a/src/commands/io.rs +++ b/src/commands/io.rs | |||
@@ -9,7 +9,7 @@ use crate::{ | |||
9 | lists_get, lists_get_all_ids, lists_insert, userlist_get_all_ids, | 9 | lists_get, lists_get_all_ids, lists_insert, userlist_get_all_ids, |
10 | userlist_get_current_version, userlist_get_set_version, | 10 | userlist_get_current_version, userlist_get_set_version, |
11 | }, | 11 | }, |
12 | error::MLE, | 12 | error::{EType, MLErr, MLE}, |
13 | mod_add, AddMod, IDSelector, List, Modloader, STYLE_OPERATION, | 13 | mod_add, AddMod, IDSelector, List, Modloader, STYLE_OPERATION, |
14 | }; | 14 | }; |
15 | 15 | ||
@@ -67,15 +67,26 @@ impl ExportList { | |||
67 | } | 67 | } |
68 | } | 68 | } |
69 | 69 | ||
70 | /// # Errors | ||
71 | /// # Panics | ||
70 | pub fn export(config: &Cfg, list: Option<String>) -> MLE<()> { | 72 | pub fn export(config: &Cfg, list: Option<String>) -> MLE<()> { |
71 | let progress = ProgressBar::new_spinner(); | 73 | let progress = ProgressBar::new_spinner(); |
72 | progress.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | 74 | progress.set_style( |
75 | ProgressStyle::with_template(STYLE_OPERATION) | ||
76 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?, | ||
77 | ); | ||
73 | 78 | ||
74 | let mut list_ids: Vec<String> = vec![]; | 79 | let mut list_ids: Vec<String> = vec![]; |
75 | if list.is_none() { | 80 | if list.is_none() { |
76 | list_ids = lists_get_all_ids(config)?; | 81 | list_ids = lists_get_all_ids(config)?; |
77 | } else { | 82 | } else { |
78 | list_ids.push(lists_get(config, &list.unwrap())?.id); | 83 | list_ids.push( |
84 | lists_get( | ||
85 | config, | ||
86 | &list.ok_or(MLErr::new(EType::Other, "nolist"))?, | ||
87 | )? | ||
88 | .id, | ||
89 | ); | ||
79 | } | 90 | } |
80 | 91 | ||
81 | let mut lists: Vec<ExportList> = vec![]; | 92 | let mut lists: Vec<ExportList> = vec![]; |
@@ -88,7 +99,7 @@ pub fn export(config: &Cfg, list: Option<String>) -> MLE<()> { | |||
88 | let toml = toml::to_string(&Export { lists })?; | 99 | let toml = toml::to_string(&Export { lists })?; |
89 | 100 | ||
90 | let filestr = dirs::home_dir() | 101 | let filestr = dirs::home_dir() |
91 | .unwrap() | 102 | .ok_or(MLErr::new(EType::Other, "no home"))? |
92 | .join("mlexport.toml") | 103 | .join("mlexport.toml") |
93 | .into_os_string() | 104 | .into_os_string() |
94 | .into_string() | 105 | .into_string() |
@@ -102,6 +113,7 @@ pub fn export(config: &Cfg, list: Option<String>) -> MLE<()> { | |||
102 | Ok(()) | 113 | Ok(()) |
103 | } | 114 | } |
104 | 115 | ||
116 | /// # Errors | ||
105 | pub async fn import( | 117 | pub async fn import( |
106 | config: &Cfg, | 118 | config: &Cfg, |
107 | file_str: &str, | 119 | file_str: &str, |
@@ -117,7 +129,9 @@ pub async fn import( | |||
117 | id: exportlist.id, | 129 | id: exportlist.id, |
118 | mc_version: exportlist.mc_version, | 130 | mc_version: exportlist.mc_version, |
119 | modloader: Modloader::from(&exportlist.launcher)?, | 131 | modloader: Modloader::from(&exportlist.launcher)?, |
120 | download_folder: exportlist.download_folder.ok_or("NO_DL").unwrap(), | 132 | download_folder: exportlist |
133 | .download_folder | ||
134 | .ok_or(MLErr::new(EType::Other, "NO_DL"))?, | ||
121 | }; | 135 | }; |
122 | lists_insert( | 136 | lists_insert( |
123 | config, | 137 | config, |
diff --git a/src/commands/list.rs b/src/commands/list.rs index 63105cf..47c1dc6 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs | |||
@@ -1,3 +1,4 @@ | |||
1 | #![allow(clippy::module_name_repetitions)] | ||
1 | use indicatif::{ProgressBar, ProgressStyle}; | 2 | use indicatif::{ProgressBar, ProgressStyle}; |
2 | 3 | ||
3 | use crate::{ | 4 | use crate::{ |
@@ -6,7 +7,7 @@ use crate::{ | |||
6 | config_change_current_list, config_get_current_list, lists_get, | 7 | config_change_current_list, config_get_current_list, lists_get, |
7 | lists_get_all_ids, lists_insert, lists_remove, lists_version, | 8 | lists_get_all_ids, lists_insert, lists_remove, lists_version, |
8 | }, | 9 | }, |
9 | error::{ErrorType, MLError, MLE}, | 10 | error::{EType, MLErr, MLE}, |
10 | update, Modloader, STYLE_OPERATION, | 11 | update, Modloader, STYLE_OPERATION, |
11 | }; | 12 | }; |
12 | 13 | ||
@@ -18,11 +19,13 @@ pub struct List { | |||
18 | pub download_folder: String, | 19 | pub download_folder: String, |
19 | } | 20 | } |
20 | 21 | ||
22 | /// # Errors | ||
21 | pub fn get_current_list(config: &Cfg) -> MLE<List> { | 23 | pub fn get_current_list(config: &Cfg) -> MLE<List> { |
22 | let id = config_get_current_list(config)?; | 24 | let id = config_get_current_list(config)?; |
23 | lists_get(config, &id) | 25 | lists_get(config, &id) |
24 | } | 26 | } |
25 | 27 | ||
28 | /// # Errors | ||
26 | pub fn list_add( | 29 | pub fn list_add( |
27 | config: &Cfg, | 30 | config: &Cfg, |
28 | id: &str, | 31 | id: &str, |
@@ -31,20 +34,27 @@ pub fn list_add( | |||
31 | directory: &str, | 34 | directory: &str, |
32 | ) -> MLE<()> { | 35 | ) -> MLE<()> { |
33 | let p = ProgressBar::new_spinner(); | 36 | let p = ProgressBar::new_spinner(); |
34 | p.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | 37 | p.set_style( |
38 | ProgressStyle::with_template(STYLE_OPERATION) | ||
39 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?, | ||
40 | ); | ||
35 | p.set_message(format!("Create {id}")); | 41 | p.set_message(format!("Create {id}")); |
36 | lists_insert(config, id, mc_version, modloader, directory)?; | 42 | lists_insert(config, id, mc_version, modloader, directory)?; |
37 | p.finish_with_message(format!("Created {id}")); | 43 | p.finish_with_message(format!("Created {id}")); |
38 | Ok(()) | 44 | Ok(()) |
39 | } | 45 | } |
40 | 46 | ||
47 | /// # Errors | ||
41 | pub fn list_change(config: &Cfg, id: &str) -> MLE<()> { | 48 | pub fn list_change(config: &Cfg, id: &str) -> MLE<()> { |
42 | let p = ProgressBar::new_spinner(); | 49 | let p = ProgressBar::new_spinner(); |
43 | p.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | 50 | p.set_style( |
51 | ProgressStyle::with_template(STYLE_OPERATION) | ||
52 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?, | ||
53 | ); | ||
44 | p.set_message(format!("Change default list to {id}")); | 54 | p.set_message(format!("Change default list to {id}")); |
45 | 55 | ||
46 | if !lists_get_all_ids(config)?.into_iter().any(|l| l == id) { | 56 | if !lists_get_all_ids(config)?.into_iter().any(|l| l == id) { |
47 | return Err(MLError::new(ErrorType::ArgumentError, "List not found")); | 57 | return Err(MLErr::new(EType::ArgumentError, "List not found")); |
48 | }; | 58 | }; |
49 | config_change_current_list(config, id)?; | 59 | config_change_current_list(config, id)?; |
50 | 60 | ||
@@ -52,9 +62,13 @@ pub fn list_change(config: &Cfg, id: &str) -> MLE<()> { | |||
52 | Ok(()) | 62 | Ok(()) |
53 | } | 63 | } |
54 | 64 | ||
65 | /// # Errors | ||
55 | pub fn list_remove(config: &Cfg, id: &str) -> MLE<()> { | 66 | pub fn list_remove(config: &Cfg, id: &str) -> MLE<()> { |
56 | let p = ProgressBar::new_spinner(); | 67 | let p = ProgressBar::new_spinner(); |
57 | p.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | 68 | p.set_style( |
69 | ProgressStyle::with_template(STYLE_OPERATION) | ||
70 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?, | ||
71 | ); | ||
58 | p.set_message(format!("Remove {id}")); | 72 | p.set_message(format!("Remove {id}")); |
59 | lists_remove(config, id)?; | 73 | lists_remove(config, id)?; |
60 | p.finish_with_message(format!("Removed {id}")); | 74 | p.finish_with_message(format!("Removed {id}")); |
@@ -67,6 +81,7 @@ pub fn list_remove(config: &Cfg, id: &str) -> MLE<()> { | |||
67 | /// | 81 | /// |
68 | /// * `config` - The current config | 82 | /// * `config` - The current config |
69 | /// * `args` - All args, to extract the new version | 83 | /// * `args` - All args, to extract the new version |
84 | /// # Errors | ||
70 | pub async fn list_version( | 85 | pub async fn list_version( |
71 | config: &Cfg, | 86 | config: &Cfg, |
72 | id: &str, | 87 | id: &str, |
@@ -75,7 +90,10 @@ pub async fn list_version( | |||
75 | delete: bool, | 90 | delete: bool, |
76 | ) -> MLE<()> { | 91 | ) -> MLE<()> { |
77 | let p = ProgressBar::new_spinner(); | 92 | let p = ProgressBar::new_spinner(); |
78 | p.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | 93 | p.set_style( |
94 | ProgressStyle::with_template(STYLE_OPERATION) | ||
95 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?, | ||
96 | ); | ||
79 | p.set_message(format!( | 97 | p.set_message(format!( |
80 | "Change version for list {id} to minecraft version: {mc_version}" | 98 | "Change version for list {id} to minecraft version: {mc_version}" |
81 | )); | 99 | )); |
@@ -90,7 +108,8 @@ pub async fn list_version( | |||
90 | update(config, vec![list], true, download, delete).await | 108 | update(config, vec![list], true, download, delete).await |
91 | } | 109 | } |
92 | 110 | ||
93 | pub fn list_list(config: &Cfg) -> MLE<()> { | 111 | /// # Errors |
112 | pub fn list_lists(config: &Cfg) -> MLE<()> { | ||
94 | let lists = lists_get_all_ids(config)?; | 113 | let lists = lists_get_all_ids(config)?; |
95 | for list in lists { | 114 | for list in lists { |
96 | let l = lists_get(config, &list)?; | 115 | let l = lists_get(config, &list)?; |
diff --git a/src/commands/modification.rs b/src/commands/modification.rs index e0e54b2..6e6213f 100644 --- a/src/commands/modification.rs +++ b/src/commands/modification.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | #![allow(clippy::too_many_lines)] | ||
2 | |||
1 | use std::collections::HashMap; | 3 | use std::collections::HashMap; |
2 | 4 | ||
3 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; | 5 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; |
@@ -9,7 +11,7 @@ use crate::{ | |||
9 | mods_remove, userlist_get_all_ids, userlist_get_current_version, | 11 | mods_remove, userlist_get_all_ids, userlist_get_current_version, |
10 | userlist_insert, userlist_remove, | 12 | userlist_insert, userlist_remove, |
11 | }, | 13 | }, |
12 | error::{ErrorType, MLError, MLE}, | 14 | error::{EType, MLErr, MLE}, |
13 | files::{delete_version, download_versions}, | 15 | files::{delete_version, download_versions}, |
14 | modrinth::{ | 16 | modrinth::{ |
15 | extract_current_version, get_raw_versions, project, projects, versions, | 17 | extract_current_version, get_raw_versions, project, projects, versions, |
@@ -41,6 +43,8 @@ pub struct ProjectInfo { | |||
41 | pub set_version: bool, | 43 | pub set_version: bool, |
42 | } | 44 | } |
43 | 45 | ||
46 | /// # Errors | ||
47 | /// # Panics | ||
44 | pub async fn mod_add( | 48 | pub async fn mod_add( |
45 | config: &Cfg, | 49 | config: &Cfg, |
46 | mods: Vec<AddMod>, | 50 | mods: Vec<AddMod>, |
@@ -52,10 +56,11 @@ pub async fn mod_add( | |||
52 | let mut mod_ids: Vec<(String, bool)> = Vec::new(); | 56 | let mut mod_ids: Vec<(String, bool)> = Vec::new(); |
53 | let mut ver_ids: Vec<(String, bool)> = Vec::new(); | 57 | let mut ver_ids: Vec<(String, bool)> = Vec::new(); |
54 | 58 | ||
55 | let add_p = mp.add(ProgressBar::new(mods.len().try_into().unwrap())); | 59 | let add_p = mp.add(ProgressBar::new(mods.len().try_into().map_err(|_| MLErr::new(EType::Other, "MODSLENTRY"))?)); |
56 | add_p.set_style( | 60 | add_p.set_style( |
57 | ProgressStyle::with_template(STYLE_BAR_POS) | 61 | ProgressStyle::with_template(STYLE_BAR_POS).map_err(|_| { |
58 | .unwrap() | 62 | MLErr::new(EType::LibIndicatif, "template error") |
63 | })? | ||
59 | .progress_chars(PROGRESS_CHARS), | 64 | .progress_chars(PROGRESS_CHARS), |
60 | ); | 65 | ); |
61 | add_p.set_message("Sort ids"); | 66 | add_p.set_message("Sort ids"); |
@@ -83,7 +88,7 @@ pub async fn mod_add( | |||
83 | }; | 88 | }; |
84 | 89 | ||
85 | if projectinfo.is_empty() { | 90 | if projectinfo.is_empty() { |
86 | return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")); | 91 | return Err(MLErr::new(EType::ArgumentError, "NO_IDS?")); |
87 | }; | 92 | }; |
88 | 93 | ||
89 | add_p.set_message("Add mods to database"); | 94 | add_p.set_message("Add mods to database"); |
@@ -115,7 +120,7 @@ pub async fn mod_add( | |||
115 | &list.id, | 120 | &list.id, |
116 | &project.mod_id, | 121 | &project.mod_id, |
117 | ¤t_version_id, | 122 | ¤t_version_id, |
118 | project.clone().applicable_versions, | 123 | &project.applicable_versions, |
119 | &project.download_link, | 124 | &project.download_link, |
120 | project.set_version, | 125 | project.set_version, |
121 | ) { | 126 | ) { |
@@ -125,8 +130,8 @@ pub async fn mod_add( | |||
125 | list.id | 130 | list.id |
126 | ); | 131 | ); |
127 | if e.to_string() == expected_err { | 132 | if e.to_string() == expected_err { |
128 | Err(MLError::new( | 133 | Err(MLErr::new( |
129 | ErrorType::ModError, | 134 | EType::ModError, |
130 | "MOD_ALREADY_ON_SELECTED_LIST", | 135 | "MOD_ALREADY_ON_SELECTED_LIST", |
131 | )) | 136 | )) |
132 | } else { | 137 | } else { |
@@ -212,7 +217,20 @@ async fn get_mod_infos( | |||
212 | let mut available_versions_vec: Vec<String> = Vec::new(); | 217 | let mut available_versions_vec: Vec<String> = Vec::new(); |
213 | let current_version: Option<Version>; | 218 | let current_version: Option<Version>; |
214 | let file: String; | 219 | let file: String; |
215 | if !available_versions.is_empty() { | 220 | if available_versions.is_empty() { |
221 | current_version = None; | ||
222 | file = String::from("NONE"); | ||
223 | available_versions_vec.push(String::from("NONE")); | ||
224 | projectinfo.push(ProjectInfo { | ||
225 | mod_id: String::from(&project.id), | ||
226 | slug: project.slug, | ||
227 | title: project.title, | ||
228 | current_version, | ||
229 | applicable_versions: available_versions_vec, | ||
230 | download_link: file, | ||
231 | set_version: *setmap.get(&project.id).unwrap(), | ||
232 | }); | ||
233 | } else { | ||
216 | let current_id = | 234 | let current_id = |
217 | extract_current_version(available_versions.clone())?; | 235 | extract_current_version(available_versions.clone())?; |
218 | 236 | ||
@@ -246,19 +264,6 @@ async fn get_mod_infos( | |||
246 | download_link: file, | 264 | download_link: file, |
247 | set_version: *setmap.get(&project.slug).unwrap(), | 265 | set_version: *setmap.get(&project.slug).unwrap(), |
248 | }); | 266 | }); |
249 | } else { | ||
250 | current_version = None; | ||
251 | file = String::from("NONE"); | ||
252 | available_versions_vec.push(String::from("NONE")); | ||
253 | projectinfo.push(ProjectInfo { | ||
254 | mod_id: String::from(&project.id), | ||
255 | slug: project.slug, | ||
256 | title: project.title, | ||
257 | current_version, | ||
258 | applicable_versions: available_versions_vec, | ||
259 | download_link: file, | ||
260 | set_version: *setmap.get(&project.id).unwrap(), | ||
261 | }); | ||
262 | } | 267 | } |
263 | } | 268 | } |
264 | 269 | ||
@@ -319,9 +324,13 @@ async fn get_ver_info( | |||
319 | /// * `config` - config struct | 324 | /// * `config` - config struct |
320 | /// * `id` - name, slug or id of the mod | 325 | /// * `id` - name, slug or id of the mod |
321 | /// * `list` - List struct | 326 | /// * `list` - List struct |
327 | /// | ||
328 | /// # Errors | ||
322 | pub fn mod_remove(config: &Cfg, id: &str, list: &List) -> MLE<()> { | 329 | pub fn mod_remove(config: &Cfg, id: &str, list: &List) -> MLE<()> { |
323 | let progress = ProgressBar::new_spinner(); | 330 | let progress = ProgressBar::new_spinner(); |
324 | progress.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | 331 | progress.set_style(ProgressStyle::with_template(STYLE_OPERATION).map_err(|_| { |
332 | MLErr::new(EType::LibIndicatif, "template error") | ||
333 | })?); | ||
325 | 334 | ||
326 | let mod_id = mods_get_id(&config.data, id)?; | 335 | let mod_id = mods_get_id(&config.data, id)?; |
327 | 336 | ||
@@ -334,7 +343,7 @@ pub fn mod_remove(config: &Cfg, id: &str, list: &List) -> MLE<()> { | |||
334 | userlist_remove(config, &list.id, &mod_id)?; | 343 | userlist_remove(config, &list.id, &mod_id)?; |
335 | 344 | ||
336 | progress.set_message("Delete file"); | 345 | progress.set_message("Delete file"); |
337 | match delete_version(list, version) { | 346 | match delete_version(list, &version) { |
338 | Ok(()) => (), | 347 | Ok(()) => (), |
339 | Err(err) => { | 348 | Err(err) => { |
340 | if err.to_string() | 349 | if err.to_string() |
diff --git a/src/commands/update.rs b/src/commands/update.rs index c19c02c..d0b930d 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | #![allow(clippy::too_many_lines)] | ||
2 | |||
1 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; | 3 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; |
2 | 4 | ||
3 | use crate::{ | 5 | use crate::{ |
@@ -7,7 +9,7 @@ use crate::{ | |||
7 | userlist_get_applicable_versions, userlist_get_current_version, | 9 | userlist_get_applicable_versions, userlist_get_current_version, |
8 | userlist_get_set_version, | 10 | userlist_get_set_version, |
9 | }, | 11 | }, |
10 | error::{ErrorType, MLError, MLE}, | 12 | error::{EType, MLErr, MLE}, |
11 | files::{ | 13 | files::{ |
12 | clean_list_dir, delete_version, disable_version, download_versions, | 14 | clean_list_dir, delete_version, disable_version, download_versions, |
13 | }, | 15 | }, |
@@ -15,6 +17,8 @@ use crate::{ | |||
15 | List, PROGRESS_CHARS, STYLE_BAR_POS, STYLE_OPERATION, | 17 | List, PROGRESS_CHARS, STYLE_BAR_POS, STYLE_OPERATION, |
16 | }; | 18 | }; |
17 | 19 | ||
20 | /// # Errors | ||
21 | /// # Panics | ||
18 | pub async fn update( | 22 | pub async fn update( |
19 | config: &Cfg, | 23 | config: &Cfg, |
20 | liststack: Vec<List>, | 24 | liststack: Vec<List>, |
@@ -24,11 +28,15 @@ pub async fn update( | |||
24 | ) -> MLE<()> { | 28 | ) -> MLE<()> { |
25 | let mp = MultiProgress::new(); | 29 | let mp = MultiProgress::new(); |
26 | 30 | ||
27 | let update_p = | 31 | let update_p = mp.add(ProgressBar::new( |
28 | mp.add(ProgressBar::new(liststack.len().try_into().unwrap())); | 32 | liststack |
33 | .len() | ||
34 | .try_into() | ||
35 | .map_err(|_| MLErr::new(EType::Other, "ListStackLen"))?, | ||
36 | )); | ||
29 | update_p.set_style( | 37 | update_p.set_style( |
30 | ProgressStyle::with_template(STYLE_BAR_POS) | 38 | ProgressStyle::with_template(STYLE_BAR_POS) |
31 | .unwrap() | 39 | .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))? |
32 | .progress_chars(PROGRESS_CHARS), | 40 | .progress_chars(PROGRESS_CHARS), |
33 | ); | 41 | ); |
34 | 42 | ||
@@ -133,16 +141,11 @@ pub async fn update( | |||
133 | if delete_old { | 141 | if delete_old { |
134 | d_p.set_message(format!("Delete version {}", ver.0)); | 142 | d_p.set_message(format!("Delete version {}", ver.0)); |
135 | d_p.inc(1); | 143 | d_p.inc(1); |
136 | delete_version(¤t_list, ver.0)?; | 144 | delete_version(¤t_list, &ver.0)?; |
137 | } else if ver.0 != "NONE" { | 145 | } else if ver.0 != "NONE" { |
138 | d_p.set_message(format!("Disable version {}", ver.0)); | 146 | d_p.set_message(format!("Disable version {}", ver.0)); |
139 | d_p.inc(1); | 147 | d_p.inc(1); |
140 | disable_version( | 148 | disable_version(config, ¤t_list, ver.0, ver.1)?; |
141 | config, | ||
142 | current_list.clone(), | ||
143 | ver.0, | ||
144 | ver.1, | ||
145 | )?; | ||
146 | }; | 149 | }; |
147 | } | 150 | } |
148 | 151 | ||
@@ -176,12 +179,12 @@ async fn specific_update( | |||
176 | 179 | ||
177 | let mut versions: Vec<String> = vec![]; | 180 | let mut versions: Vec<String> = vec![]; |
178 | 181 | ||
179 | if !applicable_versions.is_empty() { | 182 | if applicable_versions.is_empty() { |
183 | versions.push(String::from("NONE")); | ||
184 | } else { | ||
180 | for ver in &applicable_versions { | 185 | for ver in &applicable_versions { |
181 | versions.push(String::from(&ver.id)); | 186 | versions.push(String::from(&ver.id)); |
182 | } | 187 | } |
183 | } else { | ||
184 | versions.push(String::from("NONE")); | ||
185 | } | 188 | } |
186 | 189 | ||
187 | let mut current: Vec<Version> = vec![]; | 190 | let mut current: Vec<Version> = vec![]; |
@@ -189,7 +192,7 @@ async fn specific_update( | |||
189 | || (versions.join("|") | 192 | || (versions.join("|") |
190 | != userlist_get_applicable_versions( | 193 | != userlist_get_applicable_versions( |
191 | config, | 194 | config, |
192 | String::from(&list.id), | 195 | &list.id, |
193 | String::from(id), | 196 | String::from(id), |
194 | )?) | 197 | )?) |
195 | { | 198 | { |
@@ -209,7 +212,7 @@ async fn specific_update( | |||
209 | .ok_or("!no current version in applicable_versions") | 212 | .ok_or("!no current version in applicable_versions") |
210 | { | 213 | { |
211 | Ok(v) => Ok(v), | 214 | Ok(v) => Ok(v), |
212 | Err(e) => Err(MLError::new(ErrorType::Other, e)), | 215 | Err(e) => Err(MLErr::new(EType::Other, e)), |
213 | }?; | 216 | }?; |
214 | current.push(current_ver.clone()); | 217 | current.push(current_ver.clone()); |
215 | 218 | ||
@@ -223,7 +226,7 @@ async fn specific_update( | |||
223 | 226 | ||
224 | userlist_change_versions( | 227 | userlist_change_versions( |
225 | config, | 228 | config, |
226 | list.id, | 229 | &list.id, |
227 | current_str, | 230 | current_str, |
228 | versions.join("|"), | 231 | versions.join("|"), |
229 | link, | 232 | link, |
@@ -232,7 +235,7 @@ async fn specific_update( | |||
232 | } | 235 | } |
233 | 236 | ||
234 | if current.is_empty() { | 237 | if current.is_empty() { |
235 | return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")); | 238 | return Err(MLErr::new(EType::ModError, "NO_UPDATE_AVAILABLE")); |
236 | }; | 239 | }; |
237 | 240 | ||
238 | Ok(current[0].clone()) | 241 | Ok(current[0].clone()) |
diff --git a/src/config.rs b/src/config.rs index 3538a69..6280932 100644 --- a/src/config.rs +++ b/src/config.rs | |||
@@ -8,7 +8,7 @@ use indicatif::{ProgressBar, ProgressStyle}; | |||
8 | use serde::{Deserialize, Serialize}; | 8 | use serde::{Deserialize, Serialize}; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | check_game_versions, db::db_setup, error::MLE, Modloader, VersionLevel, | 11 | check_game_versions, db::setup, error::{EType, MLErr, MLE}, Modloader, VersionLevel, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | #[derive(Debug, Clone, Serialize, Deserialize)] | 14 | #[derive(Debug, Clone, Serialize, Deserialize)] |
@@ -32,11 +32,12 @@ pub struct Defaults { | |||
32 | } | 32 | } |
33 | 33 | ||
34 | impl Cfg { | 34 | impl Cfg { |
35 | /// # Errors | ||
35 | pub async fn init(path: Option<String>) -> MLE<Self> { | 36 | pub async fn init(path: Option<String>) -> MLE<Self> { |
36 | let configfile = match path.clone() { | 37 | let configfile = match path.clone() { |
37 | Some(p) => p, | 38 | Some(p) => p, |
38 | None => dirs::config_dir() | 39 | None => dirs::config_dir() |
39 | .unwrap() | 40 | .ok_or(MLErr::new(EType::Other, "config_dir"))? |
40 | .join("modlist") | 41 | .join("modlist") |
41 | .join("config.toml") | 42 | .join("config.toml") |
42 | .to_string_lossy() | 43 | .to_string_lossy() |
@@ -70,8 +71,8 @@ impl Cfg { | |||
70 | }; | 71 | }; |
71 | //Check versions | 72 | //Check versions |
72 | let versionfile = format!("{}/versions.json", config.versions); | 73 | let versionfile = format!("{}/versions.json", config.versions); |
73 | if let Ok(..) = File::open(&versionfile) { } else { | 74 | if File::open(&versionfile).is_err() { |
74 | create_versions_dummy(&versionfile).await?; | 75 | create_versions_dummy(&versionfile)?; |
75 | check_game_versions(&versionfile, true).await?; | 76 | check_game_versions(&versionfile, true).await?; |
76 | } | 77 | } |
77 | 78 | ||
@@ -114,7 +115,7 @@ fn create_database(path: &str) -> MLE<()> { | |||
114 | p.set_message("Create database"); | 115 | p.set_message("Create database"); |
115 | 116 | ||
116 | File::create(path)?; | 117 | File::create(path)?; |
117 | db_setup(path)?; | 118 | setup(path)?; |
118 | p.finish_with_message(format!("Created database ({path})")); | 119 | p.finish_with_message(format!("Created database ({path})")); |
119 | Ok(()) | 120 | Ok(()) |
120 | } | 121 | } |
@@ -129,7 +130,7 @@ fn create_cache(path: &str) -> MLE<()> { | |||
129 | Ok(()) | 130 | Ok(()) |
130 | } | 131 | } |
131 | 132 | ||
132 | async fn create_versions_dummy(path: &str) -> MLE<()> { | 133 | fn create_versions_dummy(path: &str) -> MLE<()> { |
133 | let p = ProgressBar::new(1); | 134 | let p = ProgressBar::new(1); |
134 | p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); | 135 | p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); |
135 | p.set_message("Create version file"); | 136 | p.set_message("Create version file"); |
@@ -4,11 +4,12 @@ use rusqlite::Connection; | |||
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | config::Cfg, | 6 | config::Cfg, |
7 | error::{ErrorType, MLError, MLE}, | 7 | error::{EType, MLErr, MLE}, |
8 | List, Modloader, | 8 | List, Modloader, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | //MODS | 11 | //MODS |
12 | /// # Errors | ||
12 | pub fn mods_insert(config: &Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { | 13 | pub fn mods_insert(config: &Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { |
13 | let data = format!("{}/data.db", config.data); | 14 | let data = format!("{}/data.db", config.data); |
14 | let connection = Connection::open(data)?; | 15 | let connection = Connection::open(data)?; |
@@ -21,11 +22,12 @@ pub fn mods_insert(config: &Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { | |||
21 | Ok(()) | 22 | Ok(()) |
22 | } | 23 | } |
23 | 24 | ||
25 | /// # Errors | ||
24 | pub fn mods_get_all_ids( | 26 | pub fn mods_get_all_ids( |
25 | config: &Cfg, | 27 | config: &Cfg, |
26 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { | 28 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { |
27 | let data = format!("{}/data.db", config.data); | 29 | let data = format!("{}/data.db", config.data); |
28 | let connection = Connection::open(data).unwrap(); | 30 | let connection = Connection::open(data)?; |
29 | 31 | ||
30 | let mut mods: Vec<String> = Vec::new(); | 32 | let mut mods: Vec<String> = Vec::new(); |
31 | 33 | ||
@@ -36,21 +38,22 @@ pub fn mods_get_all_ids( | |||
36 | mods.push(id?); | 38 | mods.push(id?); |
37 | } | 39 | } |
38 | 40 | ||
39 | match mods.is_empty() { | 41 | if mods.is_empty() { |
40 | true => Err(Box::new(Error::new(ErrorKind::NotFound, "NO_MODS_ALL"))), | 42 | Err(Box::new(Error::new(ErrorKind::NotFound, "NO_MODS_ALL"))) |
41 | false => Ok(mods), | 43 | } else { |
44 | Ok(mods) | ||
42 | } | 45 | } |
43 | } | 46 | } |
44 | 47 | ||
45 | ///Get mod id based on the slug or name | 48 | /// Get mod id based on the slug or name |
46 | ///# Arguments | 49 | /// # Arguments |
47 | /// | 50 | /// |
48 | ///* `data` - file directory of the database | 51 | ///* `data` - file directory of the database |
49 | ///* `slug` - Slug or Name of a mod | 52 | ///* `slug` - Slug or Name of a mod |
50 | /// | 53 | /// |
51 | ///# Failure | 54 | /// # Errors |
52 | /// | 55 | /// |
53 | ///Will return `MLError` when no mod id is found | 56 | /// Will return `MLError` when no mod id is found |
54 | pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { | 57 | pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { |
55 | let data = format!("{data}/data.db"); | 58 | let data = format!("{data}/data.db"); |
56 | let connection = Connection::open(data)?; | 59 | let connection = Connection::open(data)?; |
@@ -88,7 +91,7 @@ pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { | |||
88 | } | 91 | } |
89 | 92 | ||
90 | if mod_id.is_empty() { | 93 | if mod_id.is_empty() { |
91 | return Err(MLError::new(ErrorType::DBError, "GI_MOD_NOT_FOUND")); | 94 | return Err(MLErr::new(EType::DBError, "GI_MOD_NOT_FOUND")); |
92 | }; | 95 | }; |
93 | 96 | ||
94 | Ok(mod_id) | 97 | Ok(mod_id) |
@@ -99,6 +102,7 @@ pub struct ModInfo { | |||
99 | pub title: String, | 102 | pub title: String, |
100 | } | 103 | } |
101 | 104 | ||
105 | /// # Errors | ||
102 | pub fn mods_get_info(config: &Cfg, id: &str) -> MLE<ModInfo> { | 106 | pub fn mods_get_info(config: &Cfg, id: &str) -> MLE<ModInfo> { |
103 | let data = format!("{}/data.db", config.data); | 107 | let data = format!("{}/data.db", config.data); |
104 | let connection = Connection::open(data)?; | 108 | let connection = Connection::open(data)?; |
@@ -121,12 +125,14 @@ pub fn mods_get_info(config: &Cfg, id: &str) -> MLE<ModInfo> { | |||
121 | }); | 125 | }); |
122 | } | 126 | } |
123 | 127 | ||
124 | match mod_info.is_none() { | 128 | if mod_info.is_none() { |
125 | true => Err(MLError::new(ErrorType::DBError, "GN_MOD_NOT_FOUND")), | 129 | Err(MLErr::new(EType::DBError, "GN_MOD_NOT_FOUND")) |
126 | false => Ok(mod_info.unwrap()), | 130 | } else { |
131 | Ok(mod_info.ok_or(MLErr::new(EType::Other, "mod_info"))?) | ||
127 | } | 132 | } |
128 | } | 133 | } |
129 | 134 | ||
135 | /// # Errors | ||
130 | pub fn mods_remove(config: &Cfg, id: &str) -> MLE<()> { | 136 | pub fn mods_remove(config: &Cfg, id: &str) -> MLE<()> { |
131 | let data = format!("{}/data.db", config.data); | 137 | let data = format!("{}/data.db", config.data); |
132 | let connection = Connection::open(data)?; | 138 | let connection = Connection::open(data)?; |
@@ -142,15 +148,16 @@ pub struct DBModlistVersions { | |||
142 | pub versions: String, | 148 | pub versions: String, |
143 | } | 149 | } |
144 | 150 | ||
151 | /// # Errors | ||
145 | pub fn mods_get_versions( | 152 | pub fn mods_get_versions( |
146 | config: &Cfg, | 153 | config: &Cfg, |
147 | mods: Vec<String>, | 154 | mods: &[String], |
148 | ) -> MLE<Vec<DBModlistVersions>> { | 155 | ) -> MLE<Vec<DBModlistVersions>> { |
149 | let data = format!("{}/data.db", config.data); | 156 | let data = format!("{}/data.db", config.data); |
150 | let connection = Connection::open(data)?; | 157 | let connection = Connection::open(data)?; |
151 | 158 | ||
152 | if mods.is_empty() { | 159 | if mods.is_empty() { |
153 | return Err(MLError::new(ErrorType::ArgumentError, "MODS_NO_INPUT")); | 160 | return Err(MLErr::new(EType::ArgumentError, "MODS_NO_INPUT")); |
154 | } | 161 | } |
155 | 162 | ||
156 | let mut wherestr = String::from("WHERE"); | 163 | let mut wherestr = String::from("WHERE"); |
@@ -182,35 +189,32 @@ pub fn mods_get_versions( | |||
182 | }); | 189 | }); |
183 | } | 190 | } |
184 | 191 | ||
185 | match versionmaps.is_empty() { | 192 | if versionmaps.is_empty() { |
186 | true => Err(MLError::new(ErrorType::DBError, "MODS_MODS_NOT_FOUND")), | 193 | Err(MLErr::new(EType::DBError, "MODS_MODS_NOT_FOUND")) |
187 | false => Ok(versionmaps), | 194 | } else { |
195 | Ok(versionmaps) | ||
188 | } | 196 | } |
189 | } | 197 | } |
190 | 198 | ||
191 | //userlist | 199 | //userlist |
200 | /// # Errors | ||
192 | pub fn userlist_insert( | 201 | pub fn userlist_insert( |
193 | config: &Cfg, | 202 | config: &Cfg, |
194 | list_id: &str, | 203 | list_id: &str, |
195 | mod_id: &str, | 204 | mod_id: &str, |
196 | current_version: &str, | 205 | current_version: &str, |
197 | applicable_versions: Vec<String>, | 206 | applicable_versions: &[String], |
198 | current_link: &str, | 207 | current_link: &str, |
199 | set_version: bool, | 208 | set_version: bool, |
200 | ) -> MLE<()> { | 209 | ) -> MLE<()> { |
201 | let data = format!("{}/data.db", config.data); | 210 | let data = format!("{}/data.db", config.data); |
202 | let connection = Connection::open(data)?; | 211 | let connection = Connection::open(data)?; |
203 | 212 | ||
204 | let sv = match set_version { | 213 | let sv = if set_version { "1" } else { "0" }; |
205 | true => "1", | ||
206 | false => "0", | ||
207 | }; | ||
208 | 214 | ||
209 | connection.execute( | 215 | connection.execute( |
210 | format!( | 216 | format!("INSERT INTO {list_id} VALUES (?1, ?2, ?3, ?4, 'NONE', ?5)") |
211 | "INSERT INTO {list_id} VALUES (?1, ?2, ?3, ?4, 'NONE', ?5)" | 217 | .as_str(), |
212 | ) | ||
213 | .as_str(), | ||
214 | [ | 218 | [ |
215 | mod_id, | 219 | mod_id, |
216 | current_version, | 220 | current_version, |
@@ -223,28 +227,31 @@ pub fn userlist_insert( | |||
223 | Ok(()) | 227 | Ok(()) |
224 | } | 228 | } |
225 | 229 | ||
230 | /// # Errors | ||
226 | pub fn userlist_get_all_ids(config: &Cfg, list_id: &str) -> MLE<Vec<String>> { | 231 | pub fn userlist_get_all_ids(config: &Cfg, list_id: &str) -> MLE<Vec<String>> { |
227 | let data = format!("{}/data.db", config.data); | 232 | let data = format!("{}/data.db", config.data); |
228 | let connection = Connection::open(data).unwrap(); | 233 | let connection = Connection::open(data)?; |
229 | 234 | ||
230 | let mut mod_ids: Vec<String> = Vec::new(); | 235 | let mut mod_ids: Vec<String> = Vec::new(); |
231 | let mut stmt = connection | 236 | let mut stmt = |
232 | .prepare(format!("SELECT mod_id FROM {list_id}").as_str())?; | 237 | connection.prepare(format!("SELECT mod_id FROM {list_id}").as_str())?; |
233 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; | 238 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
234 | 239 | ||
235 | for id in id_iter { | 240 | for id in id_iter { |
236 | mod_ids.push(id?); | 241 | mod_ids.push(id?); |
237 | } | 242 | } |
238 | 243 | ||
239 | match mod_ids.is_empty() { | 244 | if mod_ids.is_empty() { |
240 | true => Err(MLError::new( | 245 | Err(MLErr::new( |
241 | ErrorType::DBError, | 246 | EType::DBError, |
242 | &format!("NO_MODS_USERLIST{list_id}"), | 247 | &format!("NO_MODS_USERLIST{list_id}"), |
243 | )), | 248 | )) |
244 | false => Ok(mod_ids), | 249 | } else { |
250 | Ok(mod_ids) | ||
245 | } | 251 | } |
246 | } | 252 | } |
247 | 253 | ||
254 | /// # Errors | ||
248 | pub fn userlist_remove(config: &Cfg, list_id: &str, mod_id: &str) -> MLE<()> { | 255 | pub fn userlist_remove(config: &Cfg, list_id: &str, mod_id: &str) -> MLE<()> { |
249 | let data = format!("{}/data.db", config.data); | 256 | let data = format!("{}/data.db", config.data); |
250 | let connection = Connection::open(data)?; | 257 | let connection = Connection::open(data)?; |
@@ -256,20 +263,19 @@ pub fn userlist_remove(config: &Cfg, list_id: &str, mod_id: &str) -> MLE<()> { | |||
256 | Ok(()) | 263 | Ok(()) |
257 | } | 264 | } |
258 | 265 | ||
266 | /// # Errors | ||
259 | pub fn userlist_get_applicable_versions( | 267 | pub fn userlist_get_applicable_versions( |
260 | config: &Cfg, | 268 | config: &Cfg, |
261 | list_id: String, | 269 | list_id: &str, |
262 | mod_id: String, | 270 | mod_id: String, |
263 | ) -> MLE<String> { | 271 | ) -> MLE<String> { |
264 | let data = format!("{}/data.db", config.data); | 272 | let data = format!("{}/data.db", config.data); |
265 | let connection = Connection::open(data).unwrap(); | 273 | let connection = Connection::open(data)?; |
266 | 274 | ||
267 | let mut version: String = String::new(); | 275 | let mut version: String = String::new(); |
268 | let mut stmt = connection.prepare( | 276 | let mut stmt = connection.prepare( |
269 | format!( | 277 | format!("SELECT applicable_versions FROM {list_id} WHERE mod_id = ?") |
270 | "SELECT applicable_versions FROM {list_id} WHERE mod_id = ?" | 278 | .as_str(), |
271 | ) | ||
272 | .as_str(), | ||
273 | )?; | 279 | )?; |
274 | let ver_iter = | 280 | let ver_iter = |
275 | stmt.query_map([mod_id], |row| row.get::<usize, String>(0))?; | 281 | stmt.query_map([mod_id], |row| row.get::<usize, String>(0))?; |
@@ -278,15 +284,17 @@ pub fn userlist_get_applicable_versions( | |||
278 | version = ver?; | 284 | version = ver?; |
279 | } | 285 | } |
280 | 286 | ||
281 | match version.is_empty() { | 287 | if version.is_empty() { |
282 | true => Err(MLError::new(ErrorType::DBError, "GAV_MOD_NOT_FOUND")), | 288 | Err(MLErr::new(EType::DBError, "GAV_MOD_NOT_FOUND")) |
283 | false => Ok(version), | 289 | } else { |
290 | Ok(version) | ||
284 | } | 291 | } |
285 | } | 292 | } |
286 | 293 | ||
294 | /// # Errors | ||
287 | pub fn userlist_get_all_applicable_versions_with_mods( | 295 | pub fn userlist_get_all_applicable_versions_with_mods( |
288 | config: &Cfg, | 296 | config: &Cfg, |
289 | list_id: String, | 297 | list_id: &str, |
290 | ) -> MLE<Vec<(String, String)>> { | 298 | ) -> MLE<Vec<(String, String)>> { |
291 | let data = format!("{}/data.db", config.data); | 299 | let data = format!("{}/data.db", config.data); |
292 | let connection = Connection::open(data)?; | 300 | let connection = Connection::open(data)?; |
@@ -308,19 +316,20 @@ pub fn userlist_get_all_applicable_versions_with_mods( | |||
308 | } | 316 | } |
309 | 317 | ||
310 | if versions.is_empty() { | 318 | if versions.is_empty() { |
311 | return Err(MLError::new(ErrorType::DBError, "NO_MODS_ON_LIST")); | 319 | return Err(MLErr::new(EType::DBError, "NO_MODS_ON_LIST")); |
312 | }; | 320 | }; |
313 | 321 | ||
314 | Ok(versions) | 322 | Ok(versions) |
315 | } | 323 | } |
316 | 324 | ||
325 | /// # Errors | ||
317 | pub fn userlist_get_current_version( | 326 | pub fn userlist_get_current_version( |
318 | config: &Cfg, | 327 | config: &Cfg, |
319 | list_id: &str, | 328 | list_id: &str, |
320 | mod_id: &str, | 329 | mod_id: &str, |
321 | ) -> MLE<String> { | 330 | ) -> MLE<String> { |
322 | let data = format!("{}/data.db", config.data); | 331 | let data = format!("{}/data.db", config.data); |
323 | let connection = Connection::open(data).unwrap(); | 332 | let connection = Connection::open(data)?; |
324 | 333 | ||
325 | let mut version: String = String::new(); | 334 | let mut version: String = String::new(); |
326 | let mut stmt = connection.prepare( | 335 | let mut stmt = connection.prepare( |
@@ -334,15 +343,17 @@ pub fn userlist_get_current_version( | |||
334 | version = ver?; | 343 | version = ver?; |
335 | } | 344 | } |
336 | 345 | ||
337 | match version.is_empty() { | 346 | if version.is_empty() { |
338 | true => Err(MLError::new(ErrorType::DBError, "GCV_MOD_NOT_FOUND")), | 347 | Err(MLErr::new(EType::DBError, "GCV_MOD_NOT_FOUND")) |
339 | false => Ok(version), | 348 | } else { |
349 | Ok(version) | ||
340 | } | 350 | } |
341 | } | 351 | } |
342 | 352 | ||
353 | /// # Errors | ||
343 | pub fn userlist_get_all_current_version_ids( | 354 | pub fn userlist_get_all_current_version_ids( |
344 | config: &Cfg, | 355 | config: &Cfg, |
345 | list_id: String, | 356 | list_id: &str, |
346 | ) -> MLE<Vec<String>> { | 357 | ) -> MLE<Vec<String>> { |
347 | let data = format!("{}/data.db", config.data); | 358 | let data = format!("{}/data.db", config.data); |
348 | let connection = Connection::open(data)?; | 359 | let connection = Connection::open(data)?; |
@@ -357,15 +368,16 @@ pub fn userlist_get_all_current_version_ids( | |||
357 | } | 368 | } |
358 | 369 | ||
359 | if versions.is_empty() { | 370 | if versions.is_empty() { |
360 | return Err(MLError::new(ErrorType::DBError, "NO_MODS_ON_LIST")); | 371 | return Err(MLErr::new(EType::DBError, "NO_MODS_ON_LIST")); |
361 | }; | 372 | }; |
362 | 373 | ||
363 | Ok(versions) | 374 | Ok(versions) |
364 | } | 375 | } |
365 | 376 | ||
377 | /// # Errors | ||
366 | pub fn userlist_get_all_current_versions_with_mods( | 378 | pub fn userlist_get_all_current_versions_with_mods( |
367 | config: &Cfg, | 379 | config: &Cfg, |
368 | list_id: String, | 380 | list_id: &str, |
369 | ) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> { | 381 | ) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> { |
370 | let data = format!("{}/data.db", config.data); | 382 | let data = format!("{}/data.db", config.data); |
371 | let connection = Connection::open(data)?; | 383 | let connection = Connection::open(data)?; |
@@ -396,18 +408,18 @@ pub fn userlist_get_all_current_versions_with_mods( | |||
396 | Ok(versions) | 408 | Ok(versions) |
397 | } | 409 | } |
398 | 410 | ||
411 | /// # Errors | ||
399 | pub fn userlist_get_set_version( | 412 | pub fn userlist_get_set_version( |
400 | config: &Cfg, | 413 | config: &Cfg, |
401 | list_id: &str, | 414 | list_id: &str, |
402 | mod_id: &str, | 415 | mod_id: &str, |
403 | ) -> MLE<bool> { | 416 | ) -> MLE<bool> { |
404 | let data = format!("{}/data.db", config.data); | 417 | let data = format!("{}/data.db", config.data); |
405 | let connection = Connection::open(data).unwrap(); | 418 | let connection = Connection::open(data)?; |
406 | 419 | ||
407 | let mut set_version: bool = false; | 420 | let mut set_version: bool = false; |
408 | let mut stmt = connection.prepare( | 421 | let mut stmt = connection.prepare( |
409 | format!("SELECT set_version FROM {list_id} WHERE mod_id = ?") | 422 | format!("SELECT set_version FROM {list_id} WHERE mod_id = ?").as_str(), |
410 | .as_str(), | ||
411 | )?; | 423 | )?; |
412 | let ver_iter = | 424 | let ver_iter = |
413 | stmt.query_map([&mod_id], |row| row.get::<usize, bool>(0))?; | 425 | stmt.query_map([&mod_id], |row| row.get::<usize, bool>(0))?; |
@@ -419,9 +431,10 @@ pub fn userlist_get_set_version( | |||
419 | Ok(set_version) | 431 | Ok(set_version) |
420 | } | 432 | } |
421 | 433 | ||
434 | /// # Errors | ||
422 | pub fn userlist_change_versions( | 435 | pub fn userlist_change_versions( |
423 | config: &Cfg, | 436 | config: &Cfg, |
424 | list_id: String, | 437 | list_id: &str, |
425 | current_version: String, | 438 | current_version: String, |
426 | versions: String, | 439 | versions: String, |
427 | link: String, | 440 | link: String, |
@@ -434,25 +447,22 @@ pub fn userlist_change_versions( | |||
434 | Ok(()) | 447 | Ok(()) |
435 | } | 448 | } |
436 | 449 | ||
450 | /// # Errors | ||
437 | pub fn userlist_add_disabled_versions( | 451 | pub fn userlist_add_disabled_versions( |
438 | config: &Cfg, | 452 | config: &Cfg, |
439 | list_id: String, | 453 | list_id: &str, |
440 | disabled_version: String, | 454 | disabled_version: String, |
441 | mod_id: String, | 455 | mod_id: String, |
442 | ) -> MLE<()> { | 456 | ) -> MLE<()> { |
443 | let data = format!("{}/data.db", config.data); | 457 | let data = format!("{}/data.db", config.data); |
444 | let connection = Connection::open(data)?; | 458 | let connection = Connection::open(data)?; |
445 | 459 | ||
446 | let currently_disabled_versions = userlist_get_disabled_versions( | 460 | let currently_disabled_versions = |
447 | config, | 461 | userlist_get_disabled_versions(config, list_id, String::from(&mod_id))?; |
448 | String::from(&list_id), | 462 | let disabled_versions = if currently_disabled_versions == "NONE" { |
449 | String::from(&mod_id), | 463 | disabled_version |
450 | )?; | 464 | } else { |
451 | let disabled_versions = match currently_disabled_versions == "NONE" { | 465 | format!("{currently_disabled_versions}|{disabled_version}") |
452 | true => disabled_version, | ||
453 | false => { | ||
454 | format!("{currently_disabled_versions}|{disabled_version}") | ||
455 | } | ||
456 | }; | 466 | }; |
457 | 467 | ||
458 | connection.execute( | 468 | connection.execute( |
@@ -465,13 +475,14 @@ pub fn userlist_add_disabled_versions( | |||
465 | Ok(()) | 475 | Ok(()) |
466 | } | 476 | } |
467 | 477 | ||
478 | /// # Errors | ||
468 | pub fn userlist_get_disabled_versions( | 479 | pub fn userlist_get_disabled_versions( |
469 | config: &Cfg, | 480 | config: &Cfg, |
470 | list_id: String, | 481 | list_id: &str, |
471 | mod_id: String, | 482 | mod_id: String, |
472 | ) -> MLE<String> { | 483 | ) -> MLE<String> { |
473 | let data = format!("{}/data.db", config.data); | 484 | let data = format!("{}/data.db", config.data); |
474 | let connection = Connection::open(data).unwrap(); | 485 | let connection = Connection::open(data)?; |
475 | 486 | ||
476 | let mut version: String = String::new(); | 487 | let mut version: String = String::new(); |
477 | let mut stmt = connection.prepare( | 488 | let mut stmt = connection.prepare( |
@@ -485,23 +496,24 @@ pub fn userlist_get_disabled_versions( | |||
485 | version = ver?; | 496 | version = ver?; |
486 | } | 497 | } |
487 | 498 | ||
488 | match version.is_empty() { | 499 | if version.is_empty() { |
489 | true => Err(MLError::new(ErrorType::DBError, "GDV_MOD_NOT_FOUND")), | 500 | Err(MLErr::new(EType::DBError, "GDV_MOD_NOT_FOUND")) |
490 | false => Ok(version), | 501 | } else { |
502 | Ok(version) | ||
491 | } | 503 | } |
492 | } | 504 | } |
493 | 505 | ||
506 | /// # Errors | ||
494 | pub fn userlist_get_all_downloads( | 507 | pub fn userlist_get_all_downloads( |
495 | config: &Cfg, | 508 | config: &Cfg, |
496 | list_id: String, | 509 | list_id: &str, |
497 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { | 510 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { |
498 | let data = format!("{}/data.db", config.data); | 511 | let data = format!("{}/data.db", config.data); |
499 | let connection = Connection::open(data).unwrap(); | 512 | let connection = Connection::open(data)?; |
500 | 513 | ||
501 | let mut links: Vec<String> = Vec::new(); | 514 | let mut links: Vec<String> = Vec::new(); |
502 | let mut stmt = connection.prepare( | 515 | let mut stmt = connection |
503 | format!("SELECT current_download FROM {list_id}").as_str(), | 516 | .prepare(format!("SELECT current_download FROM {list_id}").as_str())?; |
504 | )?; | ||
505 | let link_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; | 517 | let link_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
506 | 518 | ||
507 | for link in link_iter { | 519 | for link in link_iter { |
@@ -521,6 +533,7 @@ pub fn userlist_get_all_downloads( | |||
521 | 533 | ||
522 | //lists | 534 | //lists |
523 | ///Inserts into lists table and creates new table | 535 | ///Inserts into lists table and creates new table |
536 | /// # Errors | ||
524 | pub fn lists_insert( | 537 | pub fn lists_insert( |
525 | config: &Cfg, | 538 | config: &Cfg, |
526 | id: &str, | 539 | id: &str, |
@@ -540,6 +553,7 @@ pub fn lists_insert( | |||
540 | Ok(()) | 553 | Ok(()) |
541 | } | 554 | } |
542 | 555 | ||
556 | /// # Errors | ||
543 | pub fn lists_remove(config: &Cfg, id: &str) -> MLE<()> { | 557 | pub fn lists_remove(config: &Cfg, id: &str) -> MLE<()> { |
544 | let data = format!("{}/data.db", config.data); | 558 | let data = format!("{}/data.db", config.data); |
545 | let connection = Connection::open(data)?; | 559 | let connection = Connection::open(data)?; |
@@ -549,9 +563,10 @@ pub fn lists_remove(config: &Cfg, id: &str) -> MLE<()> { | |||
549 | Ok(()) | 563 | Ok(()) |
550 | } | 564 | } |
551 | 565 | ||
566 | /// # Errors | ||
552 | pub fn lists_get(config: &Cfg, list_id: &str) -> MLE<List> { | 567 | pub fn lists_get(config: &Cfg, list_id: &str) -> MLE<List> { |
553 | let data = format!("{}/data.db", config.data); | 568 | let data = format!("{}/data.db", config.data); |
554 | let connection = Connection::open(data).unwrap(); | 569 | let connection = Connection::open(data)?; |
555 | 570 | ||
556 | let mut list = List { | 571 | let mut list = List { |
557 | id: String::new(), | 572 | id: String::new(), |
@@ -582,15 +597,16 @@ pub fn lists_get(config: &Cfg, list_id: &str) -> MLE<List> { | |||
582 | } | 597 | } |
583 | 598 | ||
584 | if list.id.is_empty() { | 599 | if list.id.is_empty() { |
585 | return Err(MLError::new(ErrorType::DBError, "LIST_NOT_FOUND")); | 600 | return Err(MLErr::new(EType::DBError, "LIST_NOT_FOUND")); |
586 | } | 601 | } |
587 | 602 | ||
588 | Ok(list) | 603 | Ok(list) |
589 | } | 604 | } |
590 | 605 | ||
606 | /// # Errors | ||
591 | pub fn lists_version(config: &Cfg, list_id: &str, version: &str) -> MLE<()> { | 607 | pub fn lists_version(config: &Cfg, list_id: &str, version: &str) -> MLE<()> { |
592 | let data = format!("{}/data.db", config.data); | 608 | let data = format!("{}/data.db", config.data); |
593 | let connection = Connection::open(data).unwrap(); | 609 | let connection = Connection::open(data)?; |
594 | 610 | ||
595 | connection.execute( | 611 | connection.execute( |
596 | "UPDATE lists SET mc_version = ? WHERE id = ?", | 612 | "UPDATE lists SET mc_version = ? WHERE id = ?", |
@@ -599,9 +615,10 @@ pub fn lists_version(config: &Cfg, list_id: &str, version: &str) -> MLE<()> { | |||
599 | Ok(()) | 615 | Ok(()) |
600 | } | 616 | } |
601 | 617 | ||
618 | /// # Errors | ||
602 | pub fn lists_get_all_ids(config: &Cfg) -> MLE<Vec<String>> { | 619 | pub fn lists_get_all_ids(config: &Cfg) -> MLE<Vec<String>> { |
603 | let data = format!("{}/data.db", config.data); | 620 | let data = format!("{}/data.db", config.data); |
604 | let connection = Connection::open(data).unwrap(); | 621 | let connection = Connection::open(data)?; |
605 | 622 | ||
606 | let mut list_ids: Vec<String> = Vec::new(); | 623 | let mut list_ids: Vec<String> = Vec::new(); |
607 | let mut stmt = connection.prepare("SELECT id FROM lists")?; | 624 | let mut stmt = connection.prepare("SELECT id FROM lists")?; |
@@ -611,13 +628,15 @@ pub fn lists_get_all_ids(config: &Cfg) -> MLE<Vec<String>> { | |||
611 | list_ids.push(id?); | 628 | list_ids.push(id?); |
612 | } | 629 | } |
613 | 630 | ||
614 | match list_ids.is_empty() { | 631 | if list_ids.is_empty() { |
615 | true => Err(MLError::new(ErrorType::DBError, "NO_LISTS")), | 632 | Err(MLErr::new(EType::DBError, "NO_LISTS")) |
616 | false => Ok(list_ids), | 633 | } else { |
634 | Ok(list_ids) | ||
617 | } | 635 | } |
618 | } | 636 | } |
619 | 637 | ||
620 | //config | 638 | //config |
639 | /// # Errors | ||
621 | pub fn config_change_current_list(config: &Cfg, id: &str) -> MLE<()> { | 640 | pub fn config_change_current_list(config: &Cfg, id: &str) -> MLE<()> { |
622 | let data = format!("{}/data.db", config.data); | 641 | let data = format!("{}/data.db", config.data); |
623 | let connection = Connection::open(data)?; | 642 | let connection = Connection::open(data)?; |
@@ -629,9 +648,10 @@ pub fn config_change_current_list(config: &Cfg, id: &str) -> MLE<()> { | |||
629 | Ok(()) | 648 | Ok(()) |
630 | } | 649 | } |
631 | 650 | ||
651 | /// # Errors | ||
632 | pub fn config_get_current_list(config: &Cfg) -> MLE<String> { | 652 | pub fn config_get_current_list(config: &Cfg) -> MLE<String> { |
633 | let data = format!("{}/data.db", config.data); | 653 | let data = format!("{}/data.db", config.data); |
634 | let connection = Connection::open(data).unwrap(); | 654 | let connection = Connection::open(data)?; |
635 | 655 | ||
636 | let mut list_id = String::new(); | 656 | let mut list_id = String::new(); |
637 | let mut stmt = connection | 657 | let mut stmt = connection |
@@ -643,16 +663,17 @@ pub fn config_get_current_list(config: &Cfg) -> MLE<String> { | |||
643 | } | 663 | } |
644 | 664 | ||
645 | if list_id.is_empty() { | 665 | if list_id.is_empty() { |
646 | return Err(MLError::new(ErrorType::DBError, "NO_CURRENT_LIST")); | 666 | return Err(MLErr::new(EType::DBError, "NO_CURRENT_LIST")); |
647 | } | 667 | } |
648 | 668 | ||
649 | Ok(list_id) | 669 | Ok(list_id) |
650 | } | 670 | } |
651 | 671 | ||
652 | //SETUP(UPDATES) | 672 | //SETUP(UPDATES) |
673 | /// # Errors | ||
653 | pub fn s_userlist_update_download( | 674 | pub fn s_userlist_update_download( |
654 | config: &Cfg, | 675 | config: &Cfg, |
655 | list_id: String, | 676 | list_id: &str, |
656 | mod_id: String, | 677 | mod_id: String, |
657 | link: String, | 678 | link: String, |
658 | ) -> Result<(), Box<dyn std::error::Error>> { | 679 | ) -> Result<(), Box<dyn std::error::Error>> { |
@@ -660,15 +681,14 @@ pub fn s_userlist_update_download( | |||
660 | let connection = Connection::open(data)?; | 681 | let connection = Connection::open(data)?; |
661 | 682 | ||
662 | connection.execute( | 683 | connection.execute( |
663 | format!( | 684 | format!("UPDATE {list_id} SET current_download = ?1 WHERE mod_id = ?2") |
664 | "UPDATE {list_id} SET current_download = ?1 WHERE mod_id = ?2" | 685 | .as_str(), |
665 | ) | ||
666 | .as_str(), | ||
667 | [link, mod_id], | 686 | [link, mod_id], |
668 | )?; | 687 | )?; |
669 | Ok(()) | 688 | Ok(()) |
670 | } | 689 | } |
671 | 690 | ||
691 | /// # Errors | ||
672 | pub fn s_config_create_version( | 692 | pub fn s_config_create_version( |
673 | config: &Cfg, | 693 | config: &Cfg, |
674 | ) -> Result<(), Box<dyn std::error::Error>> { | 694 | ) -> Result<(), Box<dyn std::error::Error>> { |
@@ -682,6 +702,7 @@ pub fn s_config_create_version( | |||
682 | Ok(()) | 702 | Ok(()) |
683 | } | 703 | } |
684 | 704 | ||
705 | /// # Errors | ||
685 | pub fn s_config_update_version( | 706 | pub fn s_config_update_version( |
686 | config: &Cfg, | 707 | config: &Cfg, |
687 | ver: String, | 708 | ver: String, |
@@ -696,6 +717,7 @@ pub fn s_config_update_version( | |||
696 | Ok(()) | 717 | Ok(()) |
697 | } | 718 | } |
698 | 719 | ||
720 | /// # Errors | ||
699 | pub fn s_config_get_version( | 721 | pub fn s_config_get_version( |
700 | config: &Cfg, | 722 | config: &Cfg, |
701 | ) -> Result<String, Box<dyn std::error::Error>> { | 723 | ) -> Result<String, Box<dyn std::error::Error>> { |
@@ -720,11 +742,12 @@ pub fn s_config_get_version( | |||
720 | Ok(version) | 742 | Ok(version) |
721 | } | 743 | } |
722 | 744 | ||
745 | /// # Errors | ||
723 | pub fn s_insert_column( | 746 | pub fn s_insert_column( |
724 | config: &Cfg, | 747 | config: &Cfg, |
725 | table: String, | 748 | table: &str, |
726 | column: String, | 749 | column: &str, |
727 | c_type: String, | 750 | c_type: &str, |
728 | default: Option<String>, | 751 | default: Option<String>, |
729 | ) -> Result<(), Box<dyn std::error::Error>> { | 752 | ) -> Result<(), Box<dyn std::error::Error>> { |
730 | let data = format!("{}/data.db", config.data); | 753 | let data = format!("{}/data.db", config.data); |
@@ -733,14 +756,19 @@ pub fn s_insert_column( | |||
733 | let mut sql = format!("ALTER TABLE {table} ADD '{column}' {c_type}"); | 756 | let mut sql = format!("ALTER TABLE {table} ADD '{column}' {c_type}"); |
734 | 757 | ||
735 | if default.is_some() { | 758 | if default.is_some() { |
736 | sql = format!("{} DEFAULT {}", sql, default.unwrap()); | 759 | sql = format!( |
760 | "{} DEFAULT {}", | ||
761 | sql, | ||
762 | default.ok_or(MLErr::new(EType::Other, "errornous default"))? | ||
763 | ); | ||
737 | } | 764 | } |
738 | 765 | ||
739 | connection.execute(sql.as_str(), ())?; | 766 | connection.execute(sql.as_str(), ())?; |
740 | Ok(()) | 767 | Ok(()) |
741 | } | 768 | } |
742 | 769 | ||
743 | pub fn db_setup(path: &str) -> MLE<()> { | 770 | /// # Errors |
771 | pub fn setup(path: &str) -> MLE<()> { | ||
744 | let connection = Connection::open(path)?; | 772 | let connection = Connection::open(path)?; |
745 | 773 | ||
746 | connection.execute_batch( | 774 | connection.execute_batch( |
diff --git a/src/error.rs b/src/error.rs index b4cc444..652fa0c 100644 --- a/src/error.rs +++ b/src/error.rs | |||
@@ -1,16 +1,16 @@ | |||
1 | use core::fmt; | 1 | use core::fmt; |
2 | use serde::Deserialize; | 2 | use serde::Deserialize; |
3 | 3 | ||
4 | pub type MLE<T> = Result<T, MLError>; | 4 | pub type MLE<T> = Result<T, MLErr>; |
5 | 5 | ||
6 | #[derive(Debug, Deserialize)] | 6 | #[derive(Debug, Deserialize)] |
7 | pub struct MLError { | 7 | pub struct MLErr { |
8 | etype: ErrorType, | 8 | etype: EType, |
9 | message: String, | 9 | message: String, |
10 | } | 10 | } |
11 | 11 | ||
12 | #[derive(Debug, Deserialize)] | 12 | #[derive(Debug, Deserialize)] |
13 | pub enum ErrorType { | 13 | pub enum EType { |
14 | ArgumentError, | 14 | ArgumentError, |
15 | ArgumentCountError, | 15 | ArgumentCountError, |
16 | ConfigError, | 16 | ConfigError, |
@@ -21,104 +21,106 @@ pub enum ErrorType { | |||
21 | LibReq, | 21 | LibReq, |
22 | LibChrono, | 22 | LibChrono, |
23 | LibJson, | 23 | LibJson, |
24 | LibIndicatif, | ||
24 | IoError, | 25 | IoError, |
25 | Other, | 26 | Other, |
26 | } | 27 | } |
27 | 28 | ||
28 | impl std::error::Error for MLError { | 29 | impl std::error::Error for MLErr { |
29 | fn description(&self) -> &str { | 30 | fn description(&self) -> &str { |
30 | &self.message | 31 | &self.message |
31 | } | 32 | } |
32 | } | 33 | } |
33 | 34 | ||
34 | impl fmt::Display for MLError { | 35 | impl fmt::Display for MLErr { |
35 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 36 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
36 | match self.etype { | 37 | match self.etype { |
37 | ErrorType::ArgumentError => { | 38 | EType::ArgumentError => { |
38 | write!(f, "User input not accepted: {}", self.message) | 39 | write!(f, "User input not accepted: {}", self.message) |
39 | } | 40 | } |
40 | ErrorType::ArgumentCountError => { | 41 | EType::ArgumentCountError => { |
41 | write!(f, "Too many/too few arguments") | 42 | write!(f, "Too many/too few arguments") |
42 | } | 43 | } |
43 | ErrorType::ConfigError => write!(f, "CONFIG"), | 44 | EType::ConfigError => write!(f, "CONFIG"), |
44 | ErrorType::DBError => write!(f, "Database: {}", self.message), | 45 | EType::DBError => write!(f, "Database: {}", self.message), |
45 | ErrorType::ModError => write!(f, "Mod: {}", self.message), | 46 | EType::ModError => write!(f, "Mod: {}", self.message), |
46 | ErrorType::LibToml => write!(f, "TOML"), | 47 | EType::LibToml => write!(f, "TOML"), |
47 | ErrorType::LibSql => write!(f, "SQL: {}", self.message), | 48 | EType::LibSql => write!(f, "SQL: {}", self.message), |
48 | ErrorType::LibReq => write!(f, "REQWEST"), | 49 | EType::LibReq => write!(f, "REQWEST"), |
49 | ErrorType::LibChrono => write!(f, "Chrono error: {}", self.message), | 50 | EType::LibChrono => write!(f, "Chrono error: {}", self.message), |
50 | ErrorType::LibJson => write!(f, "JSON: {}", self.message), | 51 | EType::LibJson => write!(f, "JSON: {}", self.message), |
51 | ErrorType::IoError => write!(f, "IO"), | 52 | EType::LibIndicatif => write!(f, "Indicativ: {}", self.message), |
52 | ErrorType::Other => write!(f, "OTHER"), | 53 | EType::IoError => write!(f, "IO"), |
54 | EType::Other => write!(f, "OTHER"), | ||
53 | } | 55 | } |
54 | } | 56 | } |
55 | } | 57 | } |
56 | 58 | ||
57 | impl From<reqwest::Error> for MLError { | 59 | impl From<reqwest::Error> for MLErr { |
58 | fn from(error: reqwest::Error) -> Self { | 60 | fn from(error: reqwest::Error) -> Self { |
59 | Self { | 61 | Self { |
60 | etype: ErrorType::LibReq, | 62 | etype: EType::LibReq, |
61 | message: error.to_string(), | 63 | message: error.to_string(), |
62 | } | 64 | } |
63 | } | 65 | } |
64 | } | 66 | } |
65 | 67 | ||
66 | impl From<toml::de::Error> for MLError { | 68 | impl From<toml::de::Error> for MLErr { |
67 | fn from(error: toml::de::Error) -> Self { | 69 | fn from(error: toml::de::Error) -> Self { |
68 | Self { | 70 | Self { |
69 | etype: ErrorType::LibToml, | 71 | etype: EType::LibToml, |
70 | message: error.to_string(), | 72 | message: error.to_string(), |
71 | } | 73 | } |
72 | } | 74 | } |
73 | } | 75 | } |
74 | 76 | ||
75 | impl From<rusqlite::Error> for MLError { | 77 | impl From<rusqlite::Error> for MLErr { |
76 | fn from(error: rusqlite::Error) -> Self { | 78 | fn from(error: rusqlite::Error) -> Self { |
77 | Self { | 79 | Self { |
78 | etype: ErrorType::LibSql, | 80 | etype: EType::LibSql, |
79 | message: error.to_string(), | 81 | message: error.to_string(), |
80 | } | 82 | } |
81 | } | 83 | } |
82 | } | 84 | } |
83 | 85 | ||
84 | impl From<toml::ser::Error> for MLError { | 86 | impl From<toml::ser::Error> for MLErr { |
85 | fn from(error: toml::ser::Error) -> Self { | 87 | fn from(error: toml::ser::Error) -> Self { |
86 | Self { | 88 | Self { |
87 | etype: ErrorType::LibToml, | 89 | etype: EType::LibToml, |
88 | message: error.to_string(), | 90 | message: error.to_string(), |
89 | } | 91 | } |
90 | } | 92 | } |
91 | } | 93 | } |
92 | 94 | ||
93 | impl From<chrono::ParseError> for MLError { | 95 | impl From<chrono::ParseError> for MLErr { |
94 | fn from(error: chrono::ParseError) -> Self { | 96 | fn from(error: chrono::ParseError) -> Self { |
95 | Self { | 97 | Self { |
96 | etype: ErrorType::LibChrono, | 98 | etype: EType::LibChrono, |
97 | message: error.to_string(), | 99 | message: error.to_string(), |
98 | } | 100 | } |
99 | } | 101 | } |
100 | } | 102 | } |
101 | 103 | ||
102 | impl From<std::io::Error> for MLError { | 104 | impl From<std::io::Error> for MLErr { |
103 | fn from(error: std::io::Error) -> Self { | 105 | fn from(error: std::io::Error) -> Self { |
104 | Self { | 106 | Self { |
105 | etype: ErrorType::IoError, | 107 | etype: EType::IoError, |
106 | message: error.to_string(), | 108 | message: error.to_string(), |
107 | } | 109 | } |
108 | } | 110 | } |
109 | } | 111 | } |
110 | 112 | ||
111 | impl From<serde_json::error::Error> for MLError { | 113 | impl From<serde_json::error::Error> for MLErr { |
112 | fn from(value: serde_json::error::Error) -> Self { | 114 | fn from(value: serde_json::error::Error) -> Self { |
113 | Self { | 115 | Self { |
114 | etype: ErrorType::LibJson, | 116 | etype: EType::LibJson, |
115 | message: value.to_string(), | 117 | message: value.to_string(), |
116 | } | 118 | } |
117 | } | 119 | } |
118 | } | 120 | } |
119 | 121 | ||
120 | impl MLError { | 122 | impl MLErr { |
121 | #[must_use] pub fn new(etype: ErrorType, message: &str) -> Self { | 123 | #[must_use] pub fn new(etype: EType, message: &str) -> Self { |
122 | Self { | 124 | Self { |
123 | etype, | 125 | etype, |
124 | message: String::from(message), | 126 | message: String::from(message), |
diff --git a/src/files.rs b/src/files.rs index bf5a0a0..59f9ed1 100644 --- a/src/files.rs +++ b/src/files.rs | |||
@@ -13,11 +13,13 @@ use crate::{ | |||
13 | cache::{copy_cached_version, get_cached_versions}, | 13 | cache::{copy_cached_version, get_cached_versions}, |
14 | config::Cfg, | 14 | config::Cfg, |
15 | db::{mods_get_info, userlist_add_disabled_versions}, | 15 | db::{mods_get_info, userlist_add_disabled_versions}, |
16 | error::{ErrorType, MLError, MLE}, | 16 | error::{EType, MLErr, MLE}, |
17 | modrinth::Version, | 17 | modrinth::Version, |
18 | List, PROGRESS_CHARS, STYLE_BAR_BYTE, STYLE_BAR_POS, STYLE_SPINNER, | 18 | List, PROGRESS_CHARS, STYLE_BAR_BYTE, STYLE_BAR_POS, STYLE_SPINNER, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | /// # Errors | ||
22 | /// # Panics | ||
21 | pub async fn download_versions( | 23 | pub async fn download_versions( |
22 | list: List, | 24 | list: List, |
23 | config: Cfg, | 25 | config: Cfg, |
@@ -63,6 +65,8 @@ pub async fn download_versions( | |||
63 | Ok(()) | 65 | Ok(()) |
64 | } | 66 | } |
65 | 67 | ||
68 | /// # Errors | ||
69 | /// # Panics | ||
66 | async fn download_version( | 70 | async fn download_version( |
67 | config: Cfg, | 71 | config: Cfg, |
68 | list: List, | 72 | list: List, |
@@ -90,11 +94,8 @@ async fn download_version( | |||
90 | None => files[0].clone(), | 94 | None => files[0].clone(), |
91 | }; | 95 | }; |
92 | let mut splitname: Vec<&str> = file.filename.split('.').collect(); | 96 | let mut splitname: Vec<&str> = file.filename.split('.').collect(); |
93 | let extension = match splitname.pop().ok_or("") { | 97 | let Ok(extension) = splitname.pop().ok_or("") else { |
94 | Ok(e) => e, | 98 | return Err(MLErr::new(EType::Other, "NO_FILE_EXTENSION")) |
95 | Err(..) => { | ||
96 | return Err(MLError::new(ErrorType::Other, "NO_FILE_EXTENSION")) | ||
97 | } | ||
98 | }; | 99 | }; |
99 | let filename = format!( | 100 | let filename = format!( |
100 | "{}.mr.{}.{}.{}", | 101 | "{}.mr.{}.{}.{}", |
@@ -122,6 +123,8 @@ async fn download_version( | |||
122 | Ok(()) | 123 | Ok(()) |
123 | } | 124 | } |
124 | 125 | ||
126 | /// # Errors | ||
127 | /// # Panics | ||
125 | async fn download_file( | 128 | async fn download_file( |
126 | url: &str, | 129 | url: &str, |
127 | path: &str, | 130 | path: &str, |
@@ -162,23 +165,27 @@ async fn download_file( | |||
162 | Ok(()) | 165 | Ok(()) |
163 | } | 166 | } |
164 | 167 | ||
168 | /// # Errors | ||
169 | /// # Panics | ||
165 | pub fn disable_version( | 170 | pub fn disable_version( |
166 | config: &Cfg, | 171 | config: &Cfg, |
167 | current_list: List, | 172 | current_list: &List, |
168 | versionid: String, | 173 | versionid: String, |
169 | mod_id: String, | 174 | mod_id: String, |
170 | ) -> MLE<()> { | 175 | ) -> MLE<()> { |
171 | let file = get_file_path(¤t_list, String::from(&versionid))?; | 176 | let file = get_file_path(current_list, &versionid)?; |
172 | let disabled = format!("{file}.disabled"); | 177 | let disabled = format!("{file}.disabled"); |
173 | 178 | ||
174 | rename(file, disabled)?; | 179 | rename(file, disabled)?; |
175 | 180 | ||
176 | userlist_add_disabled_versions(config, current_list.id, versionid, mod_id)?; | 181 | userlist_add_disabled_versions(config, ¤t_list.id, versionid, mod_id)?; |
177 | 182 | ||
178 | Ok(()) | 183 | Ok(()) |
179 | } | 184 | } |
180 | 185 | ||
181 | pub fn delete_version(list: &List, version: String) -> MLE<()> { | 186 | /// # Errors |
187 | /// # Panics | ||
188 | pub fn delete_version(list: &List, version: &str) -> MLE<()> { | ||
182 | let file = get_file_path(list, version)?; | 189 | let file = get_file_path(list, version)?; |
183 | 190 | ||
184 | remove_file(file)?; | 191 | remove_file(file)?; |
@@ -186,16 +193,15 @@ pub fn delete_version(list: &List, version: String) -> MLE<()> { | |||
186 | Ok(()) | 193 | Ok(()) |
187 | } | 194 | } |
188 | 195 | ||
189 | pub fn get_file_path(list: &List, versionid: String) -> MLE<String> { | 196 | /// # Errors |
197 | /// # Panics | ||
198 | pub fn get_file_path(list: &List, versionid: &str) -> MLE<String> { | ||
190 | let mut names: HashMap<String, String> = HashMap::new(); | 199 | let mut names: HashMap<String, String> = HashMap::new(); |
191 | for file in read_dir(&list.download_folder)? { | 200 | for file in read_dir(&list.download_folder)? { |
192 | let path = file?.path(); | 201 | let path = file?.path(); |
193 | if path.is_file() { | 202 | if path.is_file() { |
194 | let pathstr = match path.to_str().ok_or("") { | 203 | let Ok(pathstr) = path.to_str().ok_or("") else { |
195 | Ok(s) => s, | 204 | return Err(MLErr::new(EType::Other, "INVALID_PATH")) |
196 | Err(..) => { | ||
197 | return Err(MLError::new(ErrorType::Other, "INVALID_PATH")) | ||
198 | } | ||
199 | }; | 205 | }; |
200 | let namesplit: Vec<&str> = pathstr.split('.').collect(); | 206 | let namesplit: Vec<&str> = pathstr.split('.').collect(); |
201 | let ver_id = namesplit[namesplit.len() - 2]; | 207 | let ver_id = namesplit[namesplit.len() - 2]; |
@@ -203,25 +209,29 @@ pub fn get_file_path(list: &List, versionid: String) -> MLE<String> { | |||
203 | } | 209 | } |
204 | } | 210 | } |
205 | 211 | ||
206 | let filename = match names.get(&versionid).ok_or("") { | 212 | let Ok(filename) = names.get(versionid).ok_or("") else { |
207 | Ok(n) => n, | 213 | return Err(MLErr::new( |
208 | Err(..) => { | 214 | EType::ArgumentError, |
209 | return Err(MLError::new( | 215 | "VERSION_NOT_FOUND_IN_FILES", |
210 | ErrorType::ArgumentError, | 216 | )) |
211 | "VERSION_NOT_FOUND_IN_FILES", | ||
212 | )) | ||
213 | } | ||
214 | }; | 217 | }; |
215 | 218 | ||
216 | Ok(filename.to_owned()) | 219 | Ok(filename.to_owned()) |
217 | } | 220 | } |
218 | 221 | ||
219 | pub fn get_downloaded_versions(list: List) -> MLE<HashMap<String, String>> { | 222 | /// # Errors |
223 | /// # Panics | ||
224 | pub fn get_downloaded_versions(list: &List) -> MLE<HashMap<String, String>> { | ||
220 | let mut versions: HashMap<String, String> = HashMap::new(); | 225 | let mut versions: HashMap<String, String> = HashMap::new(); |
221 | for file in read_dir(&list.download_folder)? { | 226 | for file in read_dir(&list.download_folder)? { |
222 | let path = file?.path(); | 227 | let path = file?.path(); |
223 | if path.is_file() && path.extension().ok_or("BAH").unwrap() == "jar" { | 228 | if path.is_file() |
224 | let pathstr = path.to_str().ok_or("BAH").unwrap(); | 229 | && path |
230 | .extension() | ||
231 | .ok_or(MLErr::new(EType::IoError, "extension"))? | ||
232 | == "jar" | ||
233 | { | ||
234 | let pathstr = path.to_str().ok_or(MLErr::new(EType::IoError, "path_to_str"))?; | ||
225 | let namesplit: Vec<&str> = pathstr.split('.').collect(); | 235 | let namesplit: Vec<&str> = pathstr.split('.').collect(); |
226 | versions.insert( | 236 | versions.insert( |
227 | String::from(namesplit[namesplit.len() - 3]), | 237 | String::from(namesplit[namesplit.len() - 3]), |
@@ -232,6 +242,8 @@ pub fn get_downloaded_versions(list: List) -> MLE<HashMap<String, String>> { | |||
232 | Ok(versions) | 242 | Ok(versions) |
233 | } | 243 | } |
234 | 244 | ||
245 | /// # Errors | ||
246 | /// # Panics | ||
235 | pub fn clean_list_dir(list: &List) -> MLE<()> { | 247 | pub fn clean_list_dir(list: &List) -> MLE<()> { |
236 | let dl_path = &list.download_folder; | 248 | let dl_path = &list.download_folder; |
237 | for entry in std::fs::read_dir(dl_path)? { | 249 | for entry in std::fs::read_dir(dl_path)? { |
@@ -16,7 +16,7 @@ use std::{ | |||
16 | use apis::modrinth::{get_game_versions, GameVersion, GameVersionType}; | 16 | use apis::modrinth::{get_game_versions, GameVersion, GameVersionType}; |
17 | pub use apis::*; | 17 | pub use apis::*; |
18 | pub use commands::*; | 18 | pub use commands::*; |
19 | use error::{ErrorType, MLError, MLE}; | 19 | use error::{EType, MLErr, MLE}; |
20 | use indicatif::{ProgressBar, ProgressStyle}; | 20 | use indicatif::{ProgressBar, ProgressStyle}; |
21 | use serde::{Deserialize, Serialize}; | 21 | use serde::{Deserialize, Serialize}; |
22 | 22 | ||
@@ -39,13 +39,15 @@ pub enum Modloader { | |||
39 | } | 39 | } |
40 | 40 | ||
41 | impl Modloader { | 41 | impl Modloader { |
42 | /// # Errors | ||
43 | /// # Panics | ||
42 | pub fn from(string: &str) -> MLE<Modloader> { | 44 | pub fn from(string: &str) -> MLE<Modloader> { |
43 | match string { | 45 | match string { |
44 | "forge" => Ok(Modloader::Forge), | 46 | "forge" => Ok(Modloader::Forge), |
45 | "fabric" => Ok(Modloader::Fabric), | 47 | "fabric" => Ok(Modloader::Fabric), |
46 | "quilt" => Ok(Modloader::Quilt), | 48 | "quilt" => Ok(Modloader::Quilt), |
47 | _ => { | 49 | _ => { |
48 | Err(MLError::new(ErrorType::ArgumentError, "UNKNOWN_MODLOADER")) | 50 | Err(MLErr::new(EType::ArgumentError, "UNKNOWN_MODLOADER")) |
49 | } | 51 | } |
50 | } | 52 | } |
51 | } | 53 | } |
@@ -72,14 +74,18 @@ pub enum VersionLevel { | |||
72 | 74 | ||
73 | /// Checks if update needed (time) | 75 | /// Checks if update needed (time) |
74 | /// if yes: get versions, update | 76 | /// if yes: get versions, update |
77 | /// # Errors | ||
78 | /// # Panics | ||
75 | pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> { | 79 | pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> { |
76 | let p = ProgressBar::new(1); | 80 | let p = ProgressBar::new(1); |
77 | p.set_style(ProgressStyle::with_template(STYLE_MESSAGE).unwrap()); | 81 | p.set_style(ProgressStyle::with_template(STYLE_MESSAGE).map_err(|_| { |
82 | MLErr::new(EType::LibIndicatif, "template error") | ||
83 | })?); | ||
78 | p.set_message("Update minecraft versions"); | 84 | p.set_message("Update minecraft versions"); |
79 | 85 | ||
80 | let creation_time = fs::metadata(path)?.created()?; | 86 | let creation_time = fs::metadata(path)?.created()?; |
81 | if !force | 87 | if !force |
82 | && creation_time.elapsed().unwrap() < Duration::from_secs(60 * 60 * 24) | 88 | && creation_time.elapsed().map_err(|_| MLErr::new(EType::LibIndicatif, "SystemTimeError"))? < Duration::from_secs(60 * 60 * 24) |
83 | { | 89 | { |
84 | return Ok(()); | 90 | return Ok(()); |
85 | } | 91 | } |
@@ -94,6 +100,7 @@ pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> { | |||
94 | } | 100 | } |
95 | 101 | ||
96 | /// Loads game versions from file | 102 | /// Loads game versions from file |
103 | /// # Errors | ||
97 | pub fn load_game_versions(path: &str) -> MLE<Vec<GameVersion>> { | 104 | pub fn load_game_versions(path: &str) -> MLE<Vec<GameVersion>> { |
98 | let mut file = File::open(path)?; | 105 | let mut file = File::open(path)?; |
99 | let mut data = String::new(); | 106 | let mut data = String::new(); |
@@ -103,7 +110,8 @@ pub fn load_game_versions(path: &str) -> MLE<Vec<GameVersion>> { | |||
103 | } | 110 | } |
104 | 111 | ||
105 | impl VersionLevel { | 112 | impl VersionLevel { |
106 | #[must_use] pub fn from(str: &str) -> Self { | 113 | #[must_use] |
114 | pub fn from(str: &str) -> Self { | ||
107 | match str { | 115 | match str { |
108 | "release" => VersionLevel::Release, | 116 | "release" => VersionLevel::Release, |
109 | "snapshot" => VersionLevel::Snapshot, | 117 | "snapshot" => VersionLevel::Snapshot, |
@@ -111,6 +119,12 @@ impl VersionLevel { | |||
111 | } | 119 | } |
112 | } | 120 | } |
113 | 121 | ||
122 | /// . | ||
123 | /// | ||
124 | /// # Panics | ||
125 | /// | ||
126 | /// Panics if . | ||
127 | /// # Errors | ||
114 | pub async fn get( | 128 | pub async fn get( |
115 | self, | 129 | self, |
116 | versions_path: &str, | 130 | versions_path: &str, |
@@ -122,23 +136,35 @@ impl VersionLevel { | |||
122 | 136 | ||
123 | match self { | 137 | match self { |
124 | VersionLevel::Release => { | 138 | VersionLevel::Release => { |
125 | let release = versions | 139 | if let Some(release) = versions |
126 | .find(|ver| ver.version_type == GameVersionType::release) | 140 | .find(|ver| ver.version_type == GameVersionType::release) |
127 | .unwrap(); | 141 | { |
128 | Ok(release.version) | 142 | Ok(release.version) |
143 | } else { | ||
144 | Err(MLErr::new( | ||
145 | EType::Other, | ||
146 | "no minecraft release version found", | ||
147 | )) | ||
148 | } | ||
129 | } | 149 | } |
130 | VersionLevel::Snapshot => { | 150 | VersionLevel::Snapshot => { |
131 | let snapshot = versions | 151 | if let Some(snapshot) = versions |
132 | .find(|ver| ver.version_type == GameVersionType::snapshot) | 152 | .find(|ver| ver.version_type == GameVersionType::snapshot) |
133 | .unwrap(); | 153 | { |
134 | Ok(snapshot.version) | 154 | Ok(snapshot.version) |
155 | } else { | ||
156 | Err(MLErr::new( | ||
157 | EType::Other, | ||
158 | "no minecraft snapshot version found", | ||
159 | )) | ||
160 | } | ||
135 | } | 161 | } |
136 | VersionLevel::Version(v) => { | 162 | VersionLevel::Version(v) => { |
137 | if versions.any(|ver| ver.version == v) { | 163 | if versions.any(|ver| ver.version == v) { |
138 | Ok(v) | 164 | Ok(v) |
139 | } else { | 165 | } else { |
140 | Err(MLError::new( | 166 | Err(MLErr::new( |
141 | ErrorType::ConfigError, | 167 | EType::ConfigError, |
142 | "unknown minecraft version", | 168 | "unknown minecraft version", |
143 | )) | 169 | )) |
144 | } | 170 | } |
diff --git a/src/main.rs b/src/main.rs index 21f2a30..a478ec7 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -1,9 +1,11 @@ | |||
1 | #![allow(clippy::too_many_lines)] | ||
2 | |||
1 | use clap::{Parser, Subcommand}; | 3 | use clap::{Parser, Subcommand}; |
2 | use modlist::{ | 4 | use modlist::{ |
3 | config::Cfg, | 5 | config::Cfg, |
4 | db::{config_get_current_list, lists_get, lists_get_all_ids}, | 6 | db::{config_get_current_list, lists_get, lists_get_all_ids}, |
5 | download, export, get_current_list, import, list_add, list_change, | 7 | download, export, get_current_list, import, list_add, list_change, |
6 | list_list, list_remove, list_version, mod_add, mod_remove, update, AddMod, | 8 | list_lists, list_remove, list_version, mod_add, mod_remove, update, AddMod, |
7 | IDSelector, List, Modloader, VersionLevel, | 9 | IDSelector, List, Modloader, VersionLevel, |
8 | }; | 10 | }; |
9 | 11 | ||
@@ -178,9 +180,10 @@ async fn main() { | |||
178 | .unwrap(), | 180 | .unwrap(), |
179 | }; | 181 | }; |
180 | 182 | ||
181 | let marked_id = match version { | 183 | let marked_id = if version { |
182 | true => IDSelector::VersionID(id), | 184 | IDSelector::VersionID(id) |
183 | false => IDSelector::ModificationID(id), | 185 | } else { |
186 | IDSelector::ModificationID(id) | ||
184 | }; | 187 | }; |
185 | 188 | ||
186 | let add_id = AddMod { | 189 | let add_id = AddMod { |
@@ -235,7 +238,7 @@ async fn main() { | |||
235 | list_add(&config, &id, &ver, &ml, &directory) | 238 | list_add(&config, &id, &ver, &ml, &directory) |
236 | } | 239 | } |
237 | ListCommands::Remove { id } => list_remove(&config, &id), | 240 | ListCommands::Remove { id } => list_remove(&config, &id), |
238 | ListCommands::List => list_list(&config), | 241 | ListCommands::List => list_lists(&config), |
239 | ListCommands::Change { id } => list_change(&config, &id), | 242 | ListCommands::Change { id } => list_change(&config, &id), |
240 | ListCommands::Version { | 243 | ListCommands::Version { |
241 | id, | 244 | id, |