diff options
-rw-r--r-- | src/apis/modrinth.rs | 2 | ||||
-rw-r--r-- | src/cache.rs | 1 | ||||
-rw-r--r-- | src/commands/download.rs | 4 | ||||
-rw-r--r-- | src/commands/io.rs | 2 | ||||
-rw-r--r-- | src/commands/list.rs | 2 | ||||
-rw-r--r-- | src/commands/modification.rs | 70 | ||||
-rw-r--r-- | src/commands/update.rs | 79 | ||||
-rw-r--r-- | src/config.rs | 4 | ||||
-rw-r--r-- | src/db.rs | 2 | ||||
-rw-r--r-- | src/files.rs | 61 | ||||
-rw-r--r-- | src/lib.rs | 6 |
11 files changed, 145 insertions, 88 deletions
diff --git a/src/apis/modrinth.rs b/src/apis/modrinth.rs index 525cc0d..14ff266 100644 --- a/src/apis/modrinth.rs +++ b/src/apis/modrinth.rs | |||
@@ -170,7 +170,7 @@ pub async fn projects(api: &str, ids: Vec<String>) -> Vec<Project> { | |||
170 | pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { | 170 | pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { |
171 | let url = format!( | 171 | let url = format!( |
172 | r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, | 172 | r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, |
173 | id, list.modloader.to_string(), list.mc_version | 173 | id, list.modloader, list.mc_version |
174 | ); | 174 | ); |
175 | 175 | ||
176 | let data = get(api, &url).await.unwrap(); | 176 | let data = get(api, &url).await.unwrap(); |
diff --git a/src/cache.rs b/src/cache.rs index c928670..1e22091 100644 --- a/src/cache.rs +++ b/src/cache.rs | |||
@@ -32,6 +32,5 @@ pub fn get_cached_versions(path: &str) -> HashMap<String, String> { | |||
32 | pub fn copy_cached_version(version_path: &str, download_path: &str) { | 32 | pub fn copy_cached_version(version_path: &str, download_path: &str) { |
33 | let versplit: Vec<&str> = version_path.split('/').collect(); | 33 | let versplit: Vec<&str> = version_path.split('/').collect(); |
34 | let download = format!("{}/{}", download_path, versplit[versplit.len() - 1]); | 34 | let download = format!("{}/{}", download_path, versplit[versplit.len() - 1]); |
35 | // println!("{:#?}", download); | ||
36 | copy(version_path, download).unwrap(); | 35 | copy(version_path, download).unwrap(); |
37 | } | 36 | } |
diff --git a/src/commands/download.rs b/src/commands/download.rs index ebfb4eb..6831714 100644 --- a/src/commands/download.rs +++ b/src/commands/download.rs | |||
@@ -1,3 +1,4 @@ | |||
1 | |||
1 | use crate::{config::Cfg, List}; | 2 | use crate::{config::Cfg, List}; |
2 | use crate::{ | 3 | use crate::{ |
3 | db::userlist_get_all_current_versions_with_mods, | 4 | db::userlist_get_all_current_versions_with_mods, |
@@ -9,7 +10,6 @@ use crate::{ | |||
9 | }; | 10 | }; |
10 | 11 | ||
11 | pub async fn download(config: Cfg, liststack: Vec<List>, clean: bool, delete_old: bool) -> MLE<()> { | 12 | pub async fn download(config: Cfg, liststack: Vec<List>, clean: bool, delete_old: bool) -> MLE<()> { |
12 | |||
13 | for current_list in liststack { | 13 | for current_list in liststack { |
14 | println!("Downloading current versions of mods in {}", current_list.id); | 14 | println!("Downloading current versions of mods in {}", current_list.id); |
15 | let downloaded_versions = get_downloaded_versions(current_list.clone())?; | 15 | let downloaded_versions = get_downloaded_versions(current_list.clone())?; |
@@ -63,7 +63,7 @@ pub async fn download(config: Cfg, liststack: Vec<List>, clean: bool, delete_old | |||
63 | if !to_disable.is_empty() { | 63 | if !to_disable.is_empty() { |
64 | for ver in to_disable { | 64 | for ver in to_disable { |
65 | if delete_old { | 65 | if delete_old { |
66 | println!("Deleting version {} for mod {}", ver.1, ver.0); | 66 | // println!("Deleting version {} for mod {}", ver.1, ver.0); |
67 | delete_version(current_list.clone(), ver.1)?; | 67 | delete_version(current_list.clone(), ver.1)?; |
68 | } else { | 68 | } else { |
69 | disable_version(config.clone(), current_list.clone(), ver.1, ver.0)?; | 69 | disable_version(config.clone(), current_list.clone(), ver.1, ver.0)?; |
diff --git a/src/commands/io.rs b/src/commands/io.rs index dd294bc..2a26f1d 100644 --- a/src/commands/io.rs +++ b/src/commands/io.rs | |||
@@ -24,7 +24,7 @@ impl ExportVersion { | |||
24 | fn from(config: Cfg, list_id: &str, mod_id: &str) -> MLE<Self> { | 24 | fn from(config: Cfg, list_id: &str, mod_id: &str) -> MLE<Self> { |
25 | Ok(Self { | 25 | Ok(Self { |
26 | version: userlist_get_current_version(config.clone(), list_id, mod_id)?, | 26 | version: userlist_get_current_version(config.clone(), list_id, mod_id)?, |
27 | set: userlist_get_set_version(config.clone(), list_id, mod_id)? | 27 | set: userlist_get_set_version(config, list_id, mod_id)? |
28 | }) | 28 | }) |
29 | } | 29 | } |
30 | } | 30 | } |
diff --git a/src/commands/list.rs b/src/commands/list.rs index 4aa4306..c07823b 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs | |||
@@ -32,7 +32,7 @@ pub fn list_add( | |||
32 | } | 32 | } |
33 | 33 | ||
34 | pub fn list_change(config: Cfg, id: String) -> MLE<()> { | 34 | pub fn list_change(config: Cfg, id: String) -> MLE<()> { |
35 | if lists_get_all_ids(config.clone())?.into_iter().find(|l| l == &id).is_none() { | 35 | if !lists_get_all_ids(config.clone())?.into_iter().any(|l| l == id) { |
36 | return Err(MLError::new(ErrorType::ArgumentError, "List not found")); | 36 | return Err(MLError::new(ErrorType::ArgumentError, "List not found")); |
37 | }; | 37 | }; |
38 | println!("Change default list to: {}", id); | 38 | println!("Change default list to: {}", id); |
diff --git a/src/commands/modification.rs b/src/commands/modification.rs index d4c49d6..730583d 100644 --- a/src/commands/modification.rs +++ b/src/commands/modification.rs | |||
@@ -1,5 +1,7 @@ | |||
1 | use std::{io::Write, collections::HashMap}; | 1 | use std::{io::Write, collections::HashMap}; |
2 | 2 | ||
3 | use indicatif::{ProgressBar, ProgressStyle}; | ||
4 | |||
3 | use crate::{ | 5 | use crate::{ |
4 | config::Cfg, | 6 | config::Cfg, |
5 | db::{ | 7 | db::{ |
@@ -12,6 +14,8 @@ use crate::{ | |||
12 | List, | 14 | List, |
13 | }; | 15 | }; |
14 | 16 | ||
17 | const PROGRESS_CHARS: &str = "#>-"; | ||
18 | |||
15 | #[derive(Debug, Clone)] | 19 | #[derive(Debug, Clone)] |
16 | pub struct AddMod { | 20 | pub struct AddMod { |
17 | pub id: IDSelector, | 21 | pub id: IDSelector, |
@@ -41,28 +45,45 @@ pub async fn mod_add( | |||
41 | list: List, | 45 | list: List, |
42 | direct_download: bool, | 46 | direct_download: bool, |
43 | ) -> MLE<()> { | 47 | ) -> MLE<()> { |
44 | println!("Add mods to {}", list.id); | 48 | let spinner_style = ProgressStyle::with_template("{spinner:.green}{msg}").unwrap(); |
45 | println!(" └Add mods:"); | 49 | let bar_style = ProgressStyle::with_template("{spinner:.green}{wide_msg}{pos}/{len} [{bar:.green/lime}]").unwrap().progress_chars(PROGRESS_CHARS); |
50 | |||
51 | // println!("Add mods to {}", list.id); | ||
52 | // println!(" └Add mods:"); | ||
46 | 53 | ||
47 | let mut mod_ids: Vec<(String, bool)> = Vec::new(); | 54 | let mut mod_ids: Vec<(String, bool)> = Vec::new(); |
48 | let mut ver_ids: Vec<(String, bool)> = Vec::new(); | 55 | let mut ver_ids: Vec<(String, bool)> = Vec::new(); |
49 | 56 | ||
57 | let p = ProgressBar::new(mods.len().try_into().unwrap()); | ||
58 | p.set_style(spinner_style.clone()); | ||
59 | p.set_message("Sort ids"); | ||
60 | |||
50 | //"Sort" project ids from version ids to be able to handle them differently but in a batch | 61 | //"Sort" project ids from version ids to be able to handle them differently but in a batch |
51 | for m in mods { | 62 | for m in mods { |
63 | p.inc(1); | ||
52 | match m.id { | 64 | match m.id { |
53 | IDSelector::ModificationID(pid) => mod_ids.push((pid, m.set_version)), | 65 | IDSelector::ModificationID(pid) => mod_ids.push((pid, m.set_version)), |
54 | IDSelector::VersionID(vid) => ver_ids.push((vid, m.set_version)), | 66 | IDSelector::VersionID(vid) => ver_ids.push((vid, m.set_version)), |
55 | } | 67 | } |
56 | } | 68 | } |
57 | 69 | ||
70 | p.finish_with_message("Sort ids done"); | ||
71 | |||
72 | let info_p = ProgressBar::new(2); | ||
73 | info_p.set_message("Get infos"); | ||
74 | info_p.set_style(bar_style.clone()); | ||
58 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); | 75 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); |
59 | if !mod_ids.is_empty() { | 76 | if !mod_ids.is_empty() { |
60 | projectinfo.append(&mut get_mod_infos(config.clone(), mod_ids, list.clone()).await?) | 77 | projectinfo.append(&mut get_mod_infos(config.clone(), mod_ids, list.clone()).await?); |
78 | info_p.inc(1); | ||
61 | }; | 79 | }; |
62 | if !ver_ids.is_empty() { | 80 | if !ver_ids.is_empty() { |
63 | projectinfo.append(&mut get_ver_info(config.clone(), ver_ids).await?) | 81 | projectinfo.append(&mut get_ver_info(config.clone(), ver_ids).await?); |
82 | info_p.inc(1); | ||
64 | }; | 83 | }; |
65 | 84 | ||
85 | info_p.finish_with_message("Get infos done"); | ||
86 | |||
66 | if projectinfo.is_empty() { | 87 | if projectinfo.is_empty() { |
67 | return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")); | 88 | return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")); |
68 | }; | 89 | }; |
@@ -70,18 +91,19 @@ pub async fn mod_add( | |||
70 | let mut downloadstack: Vec<Version> = Vec::new(); | 91 | let mut downloadstack: Vec<Version> = Vec::new(); |
71 | 92 | ||
72 | //Adding each mod to the lists and downloadstack | 93 | //Adding each mod to the lists and downloadstack |
73 | if projectinfo.len() == 1 { | 94 | let add_p = ProgressBar::new(projectinfo.len().try_into().unwrap()); |
74 | println!(" └Insert mod in list {} and save infos", list.id); | 95 | add_p.set_style(bar_style); |
75 | } else { | ||
76 | println!(" └Insert mods in list {} and save infos", list.id); | ||
77 | } | ||
78 | 96 | ||
79 | for project in projectinfo { | 97 | for project in projectinfo { |
98 | |||
99 | add_p.set_message(format!("Add {}", project.title)); | ||
100 | |||
80 | let current_version_id = if project.current_version.is_none() { | 101 | let current_version_id = if project.current_version.is_none() { |
81 | String::from("NONE") | 102 | String::from("NONE") |
82 | } else { | 103 | } else { |
83 | project.current_version.clone().unwrap().id | 104 | project.current_version.clone().unwrap().id |
84 | }; | 105 | }; |
106 | |||
85 | match userlist_insert( | 107 | match userlist_insert( |
86 | config.clone(), | 108 | config.clone(), |
87 | &list.id, | 109 | &list.id, |
@@ -124,8 +146,13 @@ pub async fn mod_add( | |||
124 | if project.current_version.is_some() { | 146 | if project.current_version.is_some() { |
125 | downloadstack.push(project.current_version.unwrap()) | 147 | downloadstack.push(project.current_version.unwrap()) |
126 | }; | 148 | }; |
149 | |||
150 | // add_p.println(format!("Added {}", project.title)); | ||
151 | add_p.inc(1); | ||
127 | } | 152 | } |
128 | 153 | ||
154 | add_p.finish_with_message("Added all mods"); | ||
155 | |||
129 | //Download all the added mods | 156 | //Download all the added mods |
130 | if direct_download { | 157 | if direct_download { |
131 | download_versions(list.clone(), config.clone(), downloadstack).await?; | 158 | download_versions(list.clone(), config.clone(), downloadstack).await?; |
@@ -140,7 +167,7 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> | |||
140 | 167 | ||
141 | let mut ids = vec![]; | 168 | let mut ids = vec![]; |
142 | 169 | ||
143 | println!("{:?}", mod_ids); | 170 | // println!("{:?}", mod_ids); |
144 | 171 | ||
145 | for id in mod_ids { | 172 | for id in mod_ids { |
146 | setmap.insert(id.0.to_string(), id.1); | 173 | setmap.insert(id.0.to_string(), id.1); |
@@ -156,8 +183,8 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> | |||
156 | _ => panic!("PANIC"), | 183 | _ => panic!("PANIC"), |
157 | }; | 184 | }; |
158 | for project in m_projects { | 185 | for project in m_projects { |
159 | println!("\t└{}", project.title); | 186 | // println!("\t└{}", project.title); |
160 | println!("\t └Get versions"); | 187 | // println!("\t └Get versions"); |
161 | let available_versions = versions( | 188 | let available_versions = versions( |
162 | &config.apis.modrinth, | 189 | &config.apis.modrinth, |
163 | String::from(&project.id), | 190 | String::from(&project.id), |
@@ -170,7 +197,7 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> | |||
170 | let file: String; | 197 | let file: String; |
171 | if !available_versions.is_empty() { | 198 | if !available_versions.is_empty() { |
172 | let current_id = extract_current_version(available_versions.clone())?; | 199 | let current_id = extract_current_version(available_versions.clone())?; |
173 | println!("\t └Current version: {}", current_id); | 200 | // println!("\t └Current version: {}", current_id); |
174 | 201 | ||
175 | current_version = Some( | 202 | current_version = Some( |
176 | available_versions | 203 | available_versions |
@@ -197,7 +224,7 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> | |||
197 | available_versions_vec.push(ver.id); | 224 | available_versions_vec.push(ver.id); |
198 | } | 225 | } |
199 | 226 | ||
200 | println!("{:?}", setmap); | 227 | // println!("{:?}", setmap); |
201 | 228 | ||
202 | projectinfo.push(ProjectInfo { | 229 | projectinfo.push(ProjectInfo { |
203 | mod_id: String::from(&project.id), | 230 | mod_id: String::from(&project.id), |
@@ -206,10 +233,10 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> | |||
206 | current_version, | 233 | current_version, |
207 | applicable_versions: available_versions_vec, | 234 | applicable_versions: available_versions_vec, |
208 | download_link: file, | 235 | download_link: file, |
209 | set_version: setmap.get(&project.slug).unwrap().clone(), | 236 | set_version: *setmap.get(&project.slug).unwrap(), |
210 | }) | 237 | }) |
211 | } else { | 238 | } else { |
212 | println!("\t └There's currently no mod version for your specified target"); | 239 | // println!("\t └There's currently no mod version for your specified target"); |
213 | current_version = None; | 240 | current_version = None; |
214 | file = String::from("NONE"); | 241 | file = String::from("NONE"); |
215 | available_versions_vec.push(String::from("NONE")); | 242 | available_versions_vec.push(String::from("NONE")); |
@@ -220,7 +247,7 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> | |||
220 | current_version, | 247 | current_version, |
221 | applicable_versions: available_versions_vec, | 248 | applicable_versions: available_versions_vec, |
222 | download_link: file, | 249 | download_link: file, |
223 | set_version: setmap.get(&project.id).unwrap().clone(), | 250 | set_version: *setmap.get(&project.id).unwrap(), |
224 | }) | 251 | }) |
225 | } | 252 | } |
226 | } | 253 | } |
@@ -252,7 +279,7 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<(String, bool)>) -> MLE<Vec<Proj | |||
252 | 279 | ||
253 | for (i, project) in v_projects.into_iter().enumerate() { | 280 | for (i, project) in v_projects.into_iter().enumerate() { |
254 | let version = &v_versions[i]; | 281 | let version = &v_versions[i]; |
255 | println!("\t└{}({})", project.title, version.id); | 282 | // println!("\t└{}({})", project.title, version.id); |
256 | let file = version | 283 | let file = version |
257 | .clone() | 284 | .clone() |
258 | .files | 285 | .files |
@@ -267,7 +294,7 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<(String, bool)>) -> MLE<Vec<Proj | |||
267 | current_version: Some(version.clone()), | 294 | current_version: Some(version.clone()), |
268 | applicable_versions: vec![String::from(&version.id)], | 295 | applicable_versions: vec![String::from(&version.id)], |
269 | download_link: file, | 296 | download_link: file, |
270 | set_version: setmap.get(&version.id).unwrap().clone(), | 297 | set_version: *setmap.get(&version.id).unwrap(), |
271 | }) | 298 | }) |
272 | } | 299 | } |
273 | Ok(projectinfo) | 300 | Ok(projectinfo) |
@@ -282,7 +309,7 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<(String, bool)>) -> MLE<Vec<Proj | |||
282 | pub fn mod_remove(config: Cfg, id: &str, list: List) -> MLE<()> { | 309 | pub fn mod_remove(config: Cfg, id: &str, list: List) -> MLE<()> { |
283 | let mod_id = mods_get_id(&config.data, id)?; | 310 | let mod_id = mods_get_id(&config.data, id)?; |
284 | 311 | ||
285 | println!("Remove mod {} from {}", mods_get_info(config.clone(), &mod_id)?.title, list.id); | 312 | println!("Remove mod {} from {}", mods_get_info(&config, &mod_id)?.title, list.id); |
286 | let version = userlist_get_current_version(config.clone(), &list.id, &mod_id)?; | 313 | let version = userlist_get_current_version(config.clone(), &list.id, &mod_id)?; |
287 | 314 | ||
288 | print!(" └Remove from list"); | 315 | print!(" └Remove from list"); |
@@ -300,7 +327,6 @@ pub fn mod_remove(config: Cfg, id: &str, list: List) -> MLE<()> { | |||
300 | if err.to_string() != "User input not accepted: VERSION_NOT_FOUND_IN_FILES" { | 327 | if err.to_string() != "User input not accepted: VERSION_NOT_FOUND_IN_FILES" { |
301 | return Err(err); | 328 | return Err(err); |
302 | }; | 329 | }; |
303 | () | ||
304 | }, | 330 | }, |
305 | }; | 331 | }; |
306 | println!(" ✓"); | 332 | println!(" ✓"); |
diff --git a/src/commands/update.rs b/src/commands/update.rs index d3a282b..2de13f3 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | use indicatif::{ProgressBar, ProgressStyle, MultiProgress}; | ||
2 | |||
1 | use crate::{ | 3 | use crate::{ |
2 | config::Cfg, | 4 | config::Cfg, |
3 | db::{ | 5 | db::{ |
@@ -10,6 +12,8 @@ use crate::{ | |||
10 | List, | 12 | List, |
11 | }; | 13 | }; |
12 | 14 | ||
15 | const PROGRESS_CHARS: &str = "#>-"; | ||
16 | |||
13 | pub async fn update( | 17 | pub async fn update( |
14 | config: Cfg, | 18 | config: Cfg, |
15 | liststack: Vec<List>, | 19 | liststack: Vec<List>, |
@@ -17,20 +21,39 @@ pub async fn update( | |||
17 | direct_download: bool, | 21 | direct_download: bool, |
18 | delete_old: bool, | 22 | delete_old: bool, |
19 | ) -> MLE<()> { | 23 | ) -> MLE<()> { |
24 | |||
25 | let mp = MultiProgress::new(); | ||
26 | |||
27 | let update_p = mp.add(ProgressBar::new(liststack.len().try_into().unwrap())); | ||
28 | let bar_style = ProgressStyle::with_template("{spinner:.green}{wide_msg}{pos}/{len} [{bar:.green/lime}]").unwrap().progress_chars(PROGRESS_CHARS); | ||
29 | let spinner_style = ProgressStyle::with_template("{spinner:.green}{msg}").unwrap(); | ||
30 | update_p.set_style(bar_style.clone()); | ||
31 | update_p.set_message("Update"); | ||
32 | |||
20 | for current_list in liststack { | 33 | for current_list in liststack { |
21 | println!("Update mods in {}", current_list.id); | 34 | |
35 | // println!("Update mods in {}", current_list.id); | ||
22 | let mods = userlist_get_all_ids(config.clone(), ¤t_list.id)?; | 36 | let mods = userlist_get_all_ids(config.clone(), ¤t_list.id)?; |
23 | 37 | ||
38 | let list_p = mp.insert_before(&update_p, ProgressBar::new(mods.len().try_into().unwrap())); | ||
39 | list_p.set_style(bar_style.clone()); | ||
40 | list_p.set_message(format!("Update {}", current_list.id)); | ||
41 | |||
24 | let mut current_versions: Vec<(String, String)> = vec![]; | 42 | let mut current_versions: Vec<(String, String)> = vec![]; |
25 | 43 | ||
26 | let mut updatestack: Vec<Version> = vec![]; | 44 | let mut updatestack: Vec<Version> = vec![]; |
27 | 45 | ||
28 | for id in mods { | 46 | for id in mods { |
29 | let info = mods_get_info(config.clone(), &id)?; | 47 | let mod_p = mp.insert_before(&list_p, ProgressBar::new(1)); |
30 | println!(" ├{}", info.title); | 48 | mod_p.set_style(spinner_style.clone()); |
49 | |||
50 | let info = mods_get_info(&config, &id)?; | ||
51 | mod_p.set_message(format!("Update {}", info.title)); | ||
52 | // println!(" ├{}", info.title); | ||
31 | 53 | ||
32 | if userlist_get_set_version(config.clone(), ¤t_list.id, &id)? { | 54 | if userlist_get_set_version(config.clone(), ¤t_list.id, &id)? { |
33 | println!(" │ └Set version, skipping update"); | 55 | // println!(" │ └Set version, skipping update"); |
56 | list_p.inc(1); | ||
34 | continue; | 57 | continue; |
35 | } | 58 | } |
36 | 59 | ||
@@ -38,12 +61,15 @@ pub async fn update( | |||
38 | let disable_version = | 61 | let disable_version = |
39 | userlist_get_current_version(config.clone(), ¤t_list.id, &id)?; | 62 | userlist_get_current_version(config.clone(), ¤t_list.id, &id)?; |
40 | 63 | ||
64 | mod_p.inc(1); | ||
65 | |||
41 | updatestack.push( | 66 | updatestack.push( |
42 | match specific_update( | 67 | match specific_update( |
43 | config.clone(), | 68 | config.clone(), |
44 | clean, | 69 | clean, |
45 | current_list.clone(), | 70 | current_list.clone(), |
46 | String::from(&id), | 71 | String::from(&id), |
72 | &mod_p | ||
47 | ) | 73 | ) |
48 | .await | 74 | .await |
49 | { | 75 | { |
@@ -53,19 +79,25 @@ pub async fn update( | |||
53 | } | 79 | } |
54 | Err(e) => { | 80 | Err(e) => { |
55 | if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { | 81 | if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { |
56 | println!( | 82 | // println!( |
57 | " │ └No new version found for the specified minecraft version" | 83 | // " │ └No new version found for the specified minecraft version" |
58 | ); | 84 | // ); |
59 | } else { | 85 | } else { |
60 | return Err(e); | 86 | return Err(e); |
61 | }; | 87 | }; |
88 | list_p.inc(1); | ||
62 | continue; | 89 | continue; |
63 | } | 90 | } |
64 | }, | 91 | }, |
65 | ) | 92 | ); |
93 | list_p.inc(1); | ||
66 | } | 94 | } |
67 | 95 | ||
96 | list_p.finish_with_message(format!("Updated {}", current_list.id)); | ||
97 | |||
68 | if clean { | 98 | if clean { |
99 | update_p.set_message("Cleaning"); | ||
100 | update_p.inc(1); | ||
69 | clean_list_dir(¤t_list)?; | 101 | clean_list_dir(¤t_list)?; |
70 | }; | 102 | }; |
71 | 103 | ||
@@ -85,12 +117,16 @@ pub async fn update( | |||
85 | } | 117 | } |
86 | } | 118 | } |
87 | }; | 119 | }; |
120 | update_p.inc(1); | ||
88 | } | 121 | } |
89 | 122 | ||
123 | update_p.finish_with_message("Updated all lists"); | ||
124 | |||
125 | |||
90 | Ok(()) | 126 | Ok(()) |
91 | } | 127 | } |
92 | 128 | ||
93 | async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> MLE<Version> { | 129 | async fn specific_update(config: Cfg, clean: bool, list: List, id: String, progress: &ProgressBar) -> MLE<Version> { |
94 | let applicable_versions = | 130 | let applicable_versions = |
95 | versions(&config.apis.modrinth, String::from(&id), list.clone()).await; | 131 | versions(&config.apis.modrinth, String::from(&id), list.clone()).await; |
96 | 132 | ||
@@ -116,10 +152,11 @@ async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> ML | |||
116 | let current_str = extract_current_version(applicable_versions.clone())?; | 152 | let current_str = extract_current_version(applicable_versions.clone())?; |
117 | 153 | ||
118 | if clean { | 154 | if clean { |
119 | println!("\t └Add version to downloadstack"); | 155 | // println!("\t └Add version to downloadstack"); |
120 | } else { | 156 | } else { |
121 | println!("\t └Get versions for specified minecraft versions"); | 157 | progress.println(format!("Found new version for {}", mods_get_info(&config, &id).unwrap().title)); |
122 | println!("\t └New current version: {}", current_str); | 158 | // println!("\t └Get versions for specified minecraft versions"); |
159 | // println!("\t └New current version: {}", current_str); | ||
123 | }; | 160 | }; |
124 | 161 | ||
125 | //get new versions | 162 | //get new versions |
@@ -133,16 +170,14 @@ async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> ML | |||
133 | }?; | 170 | }?; |
134 | current.push(current_ver.clone()); | 171 | current.push(current_ver.clone()); |
135 | 172 | ||
136 | let link = match current_ver | 173 | let files = ¤t_ver.files; |
137 | .files | 174 | |
138 | .into_iter() | 175 | let link = match files.clone().into_iter().find(|f| f.primary) { |
139 | .find(|f| f.primary) | 176 | Some(f) => f, |
140 | .ok_or("!no primary in links") | 177 | None => { files[0].clone() } |
141 | { | 178 | } |
142 | Ok(p) => Ok(p), | 179 | .url; |
143 | Err(e) => Err(MLError::new(ErrorType::Other, e)), | 180 | |
144 | }? | ||
145 | .url; | ||
146 | userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id)?; | 181 | userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id)?; |
147 | } | 182 | } |
148 | 183 | ||
diff --git a/src/config.rs b/src/config.rs index e1049d1..0cb1891 100644 --- a/src/config.rs +++ b/src/config.rs | |||
@@ -31,7 +31,7 @@ pub struct Defaults { | |||
31 | impl Cfg { | 31 | impl Cfg { |
32 | pub async fn init(path: Option<String>) -> MLE<Self> { | 32 | pub async fn init(path: Option<String>) -> MLE<Self> { |
33 | let configfile = match path.clone() { | 33 | let configfile = match path.clone() { |
34 | Some(p) => String::from(p), | 34 | Some(p) => p, |
35 | None => dirs::config_dir() | 35 | None => dirs::config_dir() |
36 | .unwrap() | 36 | .unwrap() |
37 | .join("modlist") | 37 | .join("modlist") |
@@ -89,7 +89,7 @@ fn create_config(path: &str) -> MLE<()> { | |||
89 | let default_cfg = Cfg { | 89 | let default_cfg = Cfg { |
90 | data: cache_dir.clone(), | 90 | data: cache_dir.clone(), |
91 | cache: format!("{}/cache", cache_dir), | 91 | cache: format!("{}/cache", cache_dir), |
92 | versions: cache_dir.clone(), | 92 | versions: cache_dir, |
93 | defaults: Defaults { | 93 | defaults: Defaults { |
94 | modloader: Modloader::Fabric, | 94 | modloader: Modloader::Fabric, |
95 | version: VersionLevel::Release | 95 | version: VersionLevel::Release |
@@ -93,7 +93,7 @@ pub struct ModInfo { | |||
93 | pub title: String, | 93 | pub title: String, |
94 | } | 94 | } |
95 | 95 | ||
96 | pub fn mods_get_info(config: Cfg, id: &str) -> MLE<ModInfo> { | 96 | pub fn mods_get_info(config: &Cfg, id: &str) -> MLE<ModInfo> { |
97 | let data = format!("{}/data.db", config.data); | 97 | let data = format!("{}/data.db", config.data); |
98 | let connection = Connection::open(data)?; | 98 | let connection = Connection::open(data)?; |
99 | 99 | ||
diff --git a/src/files.rs b/src/files.rs index a4a1d3b..04b00f0 100644 --- a/src/files.rs +++ b/src/files.rs | |||
@@ -17,55 +17,50 @@ use crate::{ | |||
17 | List, | 17 | List, |
18 | }; | 18 | }; |
19 | 19 | ||
20 | const PROGRESS_CHARS: &str = "#>-"; | ||
21 | |||
20 | pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<()> { | 22 | pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<()> { |
21 | let cached = get_cached_versions(&config.cache); | 23 | let cached = get_cached_versions(&config.cache); |
22 | 24 | ||
23 | // println!("{:#?}", cached); | ||
24 | |||
25 | // println!(" └Download mods to {}", dl_path); | ||
26 | |||
27 | let mp = MultiProgress::new(); | 25 | let mp = MultiProgress::new(); |
28 | 26 | ||
29 | let mut js = JoinSet::new(); | 27 | let mut js = JoinSet::new(); |
30 | let style = ProgressStyle::with_template("{spinner:.green}{msg}\t[{bar:.green/lime}] {bytes}/{total_bytes}") | ||
31 | .unwrap() | ||
32 | .progress_chars("#>-"); | ||
33 | 28 | ||
29 | let style_spinner = ProgressStyle::with_template("{spinner:.green}{wide_msg}").unwrap(); | ||
30 | |||
31 | let all = mp.add(ProgressBar::new(versions.len().try_into().unwrap())); | ||
32 | all.set_style(ProgressStyle::with_template("{wide_msg}{pos}/{len} [{bar:.green/lime}]").unwrap().progress_chars(PROGRESS_CHARS)); | ||
33 | all.set_message("Downloading"); | ||
34 | |||
34 | for ver in versions { | 35 | for ver in versions { |
35 | let p = mp.add(ProgressBar::new(1)); | 36 | let p = mp.insert_before(&all, ProgressBar::new(1)); |
36 | p.set_style(style.clone()); | 37 | p.set_style(style_spinner.clone()); |
37 | js.spawn(download_version(config.clone(), list.clone(), ver, cached.clone(), p)); | 38 | js.spawn(download_version(config.clone(), list.clone(), ver, cached.clone(), p)); |
39 | // std::thread::sleep(std::time::Duration::from_millis(200)); | ||
38 | } | 40 | } |
39 | 41 | ||
40 | mp.clear().unwrap(); | 42 | while js.join_next().await.is_some() { all.inc(1) } |
43 | |||
44 | all.finish(); | ||
41 | 45 | ||
42 | while js.join_next().await.is_some() {} | 46 | // mp.clear().unwrap(); |
43 | 47 | ||
44 | Ok(()) | 48 | Ok(()) |
45 | } | 49 | } |
46 | 50 | ||
47 | async fn download_version(config: Cfg, list: List, version: Version, mut cached: HashMap<String, String>, progress: ProgressBar) -> MLE<()> { | 51 | async fn download_version(config: Cfg, list: List, version: Version, mut cached: HashMap<String, String>, progress: ProgressBar) -> MLE<()> { |
48 | let project_info = mods_get_info(config.clone(), &version.project_id)?; | 52 | let project_info = mods_get_info(&config, &version.project_id)?; |
49 | 53 | ||
50 | let dl_path = String::from(&list.download_folder); | 54 | let dl_path = String::from(&list.download_folder); |
51 | 55 | ||
52 | progress.set_message(String::from(&version.id)); | 56 | progress.set_message(format!("{} - {}", project_info.title, version.id)); |
53 | 57 | ||
54 | //Check cache if already downloaded | 58 | //Check cache if already downloaded |
55 | let c = cached.remove(&version.id); | 59 | let c = cached.remove(&version.id); |
56 | if c.is_some() { | 60 | if c.is_some() { |
57 | print!( | 61 | progress.set_message(format!("Get {} from cache", version.id)); |
58 | "\t└({})Get version {} from cache", | ||
59 | project_info.title, version.id | ||
60 | ); | ||
61 | //Force flush of stdout, else print! doesn't print instantly | ||
62 | std::io::stdout().flush()?; | ||
63 | copy_cached_version(&c.unwrap(), &dl_path); | 62 | copy_cached_version(&c.unwrap(), &dl_path); |
64 | println!(" ✓"); | ||
65 | } else { | 63 | } else { |
66 | // print!("\t└({})Download version {}", project_info.title, version.id); | ||
67 | //Force flush of stdout, else print! doesn't print instantly | ||
68 | std::io::stdout().flush().unwrap(); | ||
69 | let files = version.files; | 64 | let files = version.files; |
70 | let file = match files.clone().into_iter().find(|f| f.primary) { | 65 | let file = match files.clone().into_iter().find(|f| f.primary) { |
71 | Some(f) => f, | 66 | Some(f) => f, |
@@ -91,19 +86,15 @@ async fn download_version(config: Cfg, list: List, version: Version, mut cached: | |||
91 | &progress | 86 | &progress |
92 | ) | 87 | ) |
93 | .await?; | 88 | .await?; |
94 | // println!(" ✓"); | 89 | |
95 | //Copy file to cache | 90 | progress.set_message(format!("Copy {} to cache", version.id)); |
96 | // print!("\t └Copy to cache"); | ||
97 | //Force flush of stdout, else print! doesn't print instantly | ||
98 | std::io::stdout().flush().unwrap(); | ||
99 | let dl_path_file = format!("{}/{}", list.download_folder, filename); | 91 | let dl_path_file = format!("{}/{}", list.download_folder, filename); |
100 | let cache_path = format!("{}/{}", &config.clone().cache, filename); | 92 | let cache_path = format!("{}/{}", &config.clone().cache, filename); |
101 | // println!("{}:{}", dl_path_file, cache_path); | 93 | |
102 | copy(dl_path_file, cache_path)?; | 94 | copy(dl_path_file, cache_path)?; |
103 | // println!(" ✓"); | ||
104 | } | 95 | } |
105 | 96 | ||
106 | progress.finish_with_message(format!("✓{}", version.id)); | 97 | progress.finish_with_message(format!("✓{} - {}", project_info.title, version.id)); |
107 | 98 | ||
108 | Ok(()) | 99 | Ok(()) |
109 | } | 100 | } |
@@ -114,8 +105,12 @@ async fn download_file(url: &str, path: &str, name: &str, progress: &ProgressBar | |||
114 | 105 | ||
115 | let size = res.content_length().expect("Couldn't get content length"); | 106 | let size = res.content_length().expect("Couldn't get content length"); |
116 | 107 | ||
108 | let style_bar_byte = ProgressStyle::with_template("{spinner:.green}{wide_msg}{bytes}/{total_bytes} [{bar:.green/lime}]") | ||
109 | .unwrap() | ||
110 | .progress_chars(PROGRESS_CHARS); | ||
111 | |||
117 | progress.set_length(size); | 112 | progress.set_length(size); |
118 | // progress.set_style(ProgressStyle::with_template("{spinner:.green}{msg}\t[{wide_bar:.green/lime}] {bytes}/{total_bytes}").unwrap().progress_chars("#>-")); | 113 | progress.set_style(style_bar_byte); |
119 | 114 | ||
120 | // download chunks | 115 | // download chunks |
121 | let mut file = File::create(&dl_path_file)?; | 116 | let mut file = File::create(&dl_path_file)?; |
@@ -124,7 +119,7 @@ async fn download_file(url: &str, path: &str, name: &str, progress: &ProgressBar | |||
124 | let mut downloaded: u64 = 0; | 119 | let mut downloaded: u64 = 0; |
125 | 120 | ||
126 | while let Some(item) = stream.next().await { | 121 | while let Some(item) = stream.next().await { |
127 | progress.inc(1); | 122 | // progress.inc(1); |
128 | let chunk = item?; | 123 | let chunk = item?; |
129 | file.write_all(&chunk)?; | 124 | file.write_all(&chunk)?; |
130 | 125 | ||
@@ -14,6 +14,8 @@ pub use commands::*; | |||
14 | use error::{ErrorType, MLError, MLE}; | 14 | use error::{ErrorType, MLError, MLE}; |
15 | use serde::{Deserialize, Serialize}; | 15 | use serde::{Deserialize, Serialize}; |
16 | 16 | ||
17 | pub static TICK_CHARS: &str = "#>-"; | ||
18 | |||
17 | #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] | 19 | #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] |
18 | pub enum Modloader { | 20 | pub enum Modloader { |
19 | #[serde(rename(serialize = "fabric", deserialize = "fabric"))] | 21 | #[serde(rename(serialize = "fabric", deserialize = "fabric"))] |
@@ -64,7 +66,7 @@ pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> { | |||
64 | let versions = get_game_versions().await; | 66 | let versions = get_game_versions().await; |
65 | remove_file(path)?; | 67 | remove_file(path)?; |
66 | let mut file = File::create(path)?; | 68 | let mut file = File::create(path)?; |
67 | file.write_all(&serde_json::to_string_pretty(&versions)?.as_bytes())?; | 69 | file.write_all(serde_json::to_string_pretty(&versions)?.as_bytes())?; |
68 | println!(" ✓"); | 70 | println!(" ✓"); |
69 | Ok(()) | 71 | Ok(()) |
70 | } | 72 | } |
@@ -105,7 +107,7 @@ impl VersionLevel { | |||
105 | Ok(snapshot.version) | 107 | Ok(snapshot.version) |
106 | }, | 108 | }, |
107 | VersionLevel::Version(v) => { | 109 | VersionLevel::Version(v) => { |
108 | if versions.find(|ver| ver.version == v).is_some() { | 110 | if versions.any(|ver| ver.version == v) { |
109 | Ok(v) | 111 | Ok(v) |
110 | } else { | 112 | } else { |
111 | Err(MLError::new(ErrorType::ConfigError, "unknown minecraft version")) | 113 | Err(MLError::new(ErrorType::ConfigError, "unknown minecraft version")) |