diff options
Diffstat (limited to 'src/commands')
-rw-r--r-- | src/commands/download.rs | 93 | ||||
-rw-r--r-- | src/commands/io.rs | 72 | ||||
-rw-r--r-- | src/commands/list.rs | 85 | ||||
-rw-r--r-- | src/commands/modification.rs | 204 | ||||
-rw-r--r-- | src/commands/update.rs | 222 |
5 files changed, 430 insertions, 246 deletions
diff --git a/src/commands/download.rs b/src/commands/download.rs index ebfb4eb..a7cf744 100644 --- a/src/commands/download.rs +++ b/src/commands/download.rs | |||
@@ -1,26 +1,48 @@ | |||
1 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; | ||
2 | |||
1 | use crate::{config::Cfg, List}; | 3 | use crate::{config::Cfg, List}; |
2 | use crate::{ | 4 | use crate::{ |
3 | db::userlist_get_all_current_versions_with_mods, | 5 | db::userlist_get_all_current_versions_with_mods, |
4 | error::{ErrorType, MLError, MLE}, | 6 | error::{ErrorType, MLError, MLE}, |
5 | files::{ | 7 | files::{ |
6 | clean_list_dir, delete_version, disable_version, download_versions, get_downloaded_versions, | 8 | clean_list_dir, delete_version, disable_version, download_versions, |
9 | get_downloaded_versions, | ||
7 | }, | 10 | }, |
8 | modrinth::get_raw_versions, | 11 | modrinth::get_raw_versions, |
9 | }; | 12 | }; |
13 | use crate::{PROGRESS_CHARS, STYLE_BAR_POS}; | ||
10 | 14 | ||
11 | pub async fn download(config: Cfg, liststack: Vec<List>, clean: bool, delete_old: bool) -> MLE<()> { | 15 | pub async fn download( |
16 | config: &Cfg, | ||
17 | liststack: Vec<List>, | ||
18 | clean: bool, | ||
19 | delete_old: bool, | ||
20 | ) -> MLE<()> { | ||
21 | let mp = MultiProgress::new(); | ||
22 | let download_p = | ||
23 | mp.add(ProgressBar::new(liststack.len().try_into().unwrap())); | ||
24 | download_p.set_style( | ||
25 | ProgressStyle::with_template(STYLE_BAR_POS) | ||
26 | .unwrap() | ||
27 | .progress_chars(PROGRESS_CHARS), | ||
28 | ); | ||
12 | 29 | ||
13 | for current_list in liststack { | 30 | for current_list in liststack { |
14 | println!("Downloading current versions of mods in {}", current_list.id); | 31 | download_p.set_message(format!("Download in {}", current_list.id)); |
15 | let downloaded_versions = get_downloaded_versions(current_list.clone())?; | 32 | |
16 | // println!("To download: {:#?}", downloaded_versions); | 33 | let downloaded_versions = |
17 | let current_version_ids = match userlist_get_all_current_versions_with_mods( | 34 | get_downloaded_versions(current_list.clone())?; |
18 | config.clone(), | 35 | let current_version_ids = |
19 | String::from(¤t_list.id), | 36 | match userlist_get_all_current_versions_with_mods( |
20 | ) { | 37 | config, |
21 | Ok(i) => Ok(i), | 38 | String::from(¤t_list.id), |
22 | Err(e) => Err(MLError::new(ErrorType::DBError, e.to_string().as_str())), | 39 | ) { |
23 | }?; | 40 | Ok(i) => Ok(i), |
41 | Err(e) => Err(MLError::new( | ||
42 | ErrorType::DBError, | ||
43 | e.to_string().as_str(), | ||
44 | )), | ||
45 | }?; | ||
24 | 46 | ||
25 | let mut to_download: Vec<String> = vec![]; | 47 | let mut to_download: Vec<String> = vec![]; |
26 | //(mod_id, version_id) | 48 | //(mod_id, version_id) |
@@ -39,7 +61,10 @@ pub async fn download(config: Cfg, liststack: Vec<List>, clean: bool, delete_old | |||
39 | .ok_or("SOMETHING_HAS_REALLY_GONE_WRONG") | 61 | .ok_or("SOMETHING_HAS_REALLY_GONE_WRONG") |
40 | .unwrap(); | 62 | .unwrap(); |
41 | if ¤t_version != downloaded_version { | 63 | if ¤t_version != downloaded_version { |
42 | to_disable.push((mod_id.clone(), String::from(downloaded_version))); | 64 | to_disable.push(( |
65 | mod_id.clone(), | ||
66 | String::from(downloaded_version), | ||
67 | )); | ||
43 | to_download.push(current_version); | 68 | to_download.push(current_version); |
44 | } | 69 | } |
45 | } | 70 | } |
@@ -54,23 +79,57 @@ pub async fn download(config: Cfg, liststack: Vec<List>, clean: bool, delete_old | |||
54 | current_list.clone(), | 79 | current_list.clone(), |
55 | config.clone(), | 80 | config.clone(), |
56 | get_raw_versions(&config.apis.modrinth, to_download).await, | 81 | get_raw_versions(&config.apis.modrinth, to_download).await, |
82 | &mp, | ||
83 | &download_p, | ||
57 | ) | 84 | ) |
58 | .await?; | 85 | .await?; |
59 | } else { | 86 | } else { |
60 | println!("There are no new versions to download"); | 87 | download_p.println(format!( |
88 | "There are no new versions to download for {}", | ||
89 | current_list.id | ||
90 | )); | ||
61 | } | 91 | } |
62 | 92 | ||
63 | if !to_disable.is_empty() { | 93 | if !to_disable.is_empty() { |
94 | let d_p = mp.insert_before( | ||
95 | &download_p, | ||
96 | ProgressBar::new(to_disable.len().try_into().unwrap()), | ||
97 | ); | ||
98 | d_p.set_style( | ||
99 | ProgressStyle::with_template(STYLE_BAR_POS) | ||
100 | .unwrap() | ||
101 | .progress_chars(PROGRESS_CHARS), | ||
102 | ); | ||
64 | for ver in to_disable { | 103 | for ver in to_disable { |
65 | if delete_old { | 104 | if delete_old { |
66 | println!("Deleting version {} for mod {}", ver.1, ver.0); | 105 | d_p.set_message(format!("Delete version {}", ver.1)); |
67 | delete_version(current_list.clone(), ver.1)?; | 106 | d_p.inc(1); |
107 | delete_version(¤t_list, ver.1)?; | ||
68 | } else { | 108 | } else { |
69 | disable_version(config.clone(), current_list.clone(), ver.1, ver.0)?; | 109 | d_p.set_message(format!("Disable version {}", ver.1)); |
110 | d_p.inc(1); | ||
111 | disable_version( | ||
112 | config, | ||
113 | current_list.clone(), | ||
114 | ver.1, | ||
115 | ver.0, | ||
116 | )?; | ||
70 | }; | 117 | }; |
71 | } | 118 | } |
119 | |||
120 | let del_msg = if delete_old { | ||
121 | "Deleted all old versions" | ||
122 | } else { | ||
123 | "Disabled all old versions" | ||
124 | }; | ||
125 | |||
126 | d_p.finish_with_message(del_msg); | ||
72 | } | 127 | } |
128 | |||
129 | download_p.inc(1); | ||
73 | } | 130 | } |
74 | 131 | ||
132 | download_p.finish_with_message("Downloaded all lists"); | ||
133 | |||
75 | Ok(()) | 134 | Ok(()) |
76 | } | 135 | } |
diff --git a/src/commands/io.rs b/src/commands/io.rs index dd294bc..8e44b2b 100644 --- a/src/commands/io.rs +++ b/src/commands/io.rs | |||
@@ -1,12 +1,16 @@ | |||
1 | use indicatif::{ProgressBar, ProgressStyle}; | ||
1 | use serde::{Deserialize, Serialize}; | 2 | use serde::{Deserialize, Serialize}; |
2 | use std::fs::File; | 3 | use std::fs::File; |
3 | use std::io::prelude::*; | 4 | use std::io::prelude::*; |
4 | 5 | ||
5 | use crate::{ | 6 | use crate::{ |
6 | config::Cfg, | 7 | config::Cfg, |
7 | db::{lists_get, lists_get_all_ids, lists_insert, userlist_get_set_version, userlist_get_all_ids, userlist_get_current_version}, | 8 | db::{ |
9 | lists_get, lists_get_all_ids, lists_insert, userlist_get_all_ids, | ||
10 | userlist_get_current_version, userlist_get_set_version, | ||
11 | }, | ||
8 | error::MLE, | 12 | error::MLE, |
9 | mod_add, IDSelector, List, Modloader, AddMod, | 13 | mod_add, AddMod, IDSelector, List, Modloader, STYLE_OPERATION, |
10 | }; | 14 | }; |
11 | 15 | ||
12 | #[derive(Debug, Serialize, Deserialize)] | 16 | #[derive(Debug, Serialize, Deserialize)] |
@@ -17,14 +21,14 @@ struct Export { | |||
17 | #[derive(Debug, Serialize, Deserialize)] | 21 | #[derive(Debug, Serialize, Deserialize)] |
18 | struct ExportVersion { | 22 | struct ExportVersion { |
19 | version: String, | 23 | version: String, |
20 | set: bool | 24 | set: bool, |
21 | } | 25 | } |
22 | 26 | ||
23 | impl ExportVersion { | 27 | impl ExportVersion { |
24 | fn from(config: Cfg, list_id: &str, mod_id: &str) -> MLE<Self> { | 28 | fn from(config: &Cfg, list_id: &str, mod_id: &str) -> MLE<Self> { |
25 | Ok(Self { | 29 | Ok(Self { |
26 | version: userlist_get_current_version(config.clone(), list_id, mod_id)?, | 30 | version: userlist_get_current_version(config, list_id, mod_id)?, |
27 | set: userlist_get_set_version(config.clone(), list_id, mod_id)? | 31 | set: userlist_get_set_version(config, list_id, mod_id)?, |
28 | }) | 32 | }) |
29 | } | 33 | } |
30 | } | 34 | } |
@@ -39,18 +43,18 @@ struct ExportList { | |||
39 | } | 43 | } |
40 | 44 | ||
41 | impl ExportList { | 45 | impl ExportList { |
42 | pub fn from(config: Cfg, list_id: String, download: bool) -> MLE<Self> { | 46 | pub fn from(config: &Cfg, list_id: &str, download: bool) -> MLE<Self> { |
43 | let list = lists_get(config.clone(), String::from(&list_id))?; | 47 | let list = lists_get(config, list_id)?; |
44 | 48 | ||
45 | let mut dl_folder = None; | 49 | let mut dl_folder = None; |
46 | if download { | 50 | if download { |
47 | dl_folder = Some(list.download_folder) | 51 | dl_folder = Some(list.download_folder) |
48 | }; | 52 | }; |
49 | 53 | ||
50 | let mods = userlist_get_all_ids(config.clone(), &list_id)?; | 54 | let mods = userlist_get_all_ids(config, list_id)?; |
51 | let mut versions = vec![]; | 55 | let mut versions = vec![]; |
52 | for m in mods { | 56 | for m in mods { |
53 | versions.push(ExportVersion::from(config.clone(), &list_id, &m)?) | 57 | versions.push(ExportVersion::from(config, list_id, &m)?) |
54 | } | 58 | } |
55 | 59 | ||
56 | Ok(Self { | 60 | Ok(Self { |
@@ -63,29 +67,46 @@ impl ExportList { | |||
63 | } | 67 | } |
64 | } | 68 | } |
65 | 69 | ||
66 | pub fn export(config: Cfg, list: Option<String>) -> MLE<()> { | 70 | pub fn export(config: &Cfg, list: Option<String>) -> MLE<()> { |
71 | let progress = ProgressBar::new_spinner(); | ||
72 | progress.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | ||
73 | |||
67 | let mut list_ids: Vec<String> = vec![]; | 74 | let mut list_ids: Vec<String> = vec![]; |
68 | if list.is_none() { | 75 | if list.is_none() { |
69 | list_ids = lists_get_all_ids(config.clone())?; | 76 | list_ids = lists_get_all_ids(config)?; |
70 | } else { | 77 | } else { |
71 | list_ids.push(lists_get(config.clone(), list.unwrap())?.id); | 78 | list_ids.push(lists_get(config, &list.unwrap())?.id); |
72 | } | 79 | } |
80 | |||
73 | let mut lists: Vec<ExportList> = vec![]; | 81 | let mut lists: Vec<ExportList> = vec![]; |
74 | for list_id in list_ids { | 82 | for list_id in list_ids { |
75 | lists.push(ExportList::from(config.clone(), list_id, true)?); | 83 | progress.set_message(format!("Export {}", list_id)); |
84 | //TODO download option/ new download on import | ||
85 | lists.push(ExportList::from(config, &list_id, true)?); | ||
76 | } | 86 | } |
77 | 87 | ||
78 | let toml = toml::to_string(&Export { lists })?; | 88 | let toml = toml::to_string(&Export { lists })?; |
79 | 89 | ||
80 | let filestr = dirs::home_dir().unwrap().join("mlexport.toml"); | 90 | let filestr = dirs::home_dir() |
91 | .unwrap() | ||
92 | .join("mlexport.toml") | ||
93 | .into_os_string() | ||
94 | .into_string() | ||
95 | .unwrap(); | ||
81 | 96 | ||
82 | let mut file = File::create(filestr.into_os_string().into_string().unwrap().as_str())?; | 97 | progress.set_message("Create file"); |
98 | let mut file = File::create(&filestr)?; | ||
83 | file.write_all(toml.as_bytes())?; | 99 | file.write_all(toml.as_bytes())?; |
100 | progress.finish_with_message(format!("Exported to {}", filestr)); | ||
84 | 101 | ||
85 | Ok(()) | 102 | Ok(()) |
86 | } | 103 | } |
87 | 104 | ||
88 | pub async fn import(config: Cfg, file_str: String, direct_download: bool) -> MLE<()> { | 105 | pub async fn import( |
106 | config: &Cfg, | ||
107 | file_str: &str, | ||
108 | direct_download: bool, | ||
109 | ) -> MLE<()> { | ||
89 | let mut file = File::open(file_str)?; | 110 | let mut file = File::open(file_str)?; |
90 | let mut content = String::new(); | 111 | let mut content = String::new(); |
91 | file.read_to_string(&mut content)?; | 112 | file.read_to_string(&mut content)?; |
@@ -99,18 +120,21 @@ pub async fn import(config: Cfg, file_str: String, direct_download: bool) -> MLE | |||
99 | download_folder: exportlist.download_folder.ok_or("NO_DL").unwrap(), | 120 | download_folder: exportlist.download_folder.ok_or("NO_DL").unwrap(), |
100 | }; | 121 | }; |
101 | lists_insert( | 122 | lists_insert( |
102 | config.clone(), | 123 | config, |
103 | list.id.clone(), | 124 | &list.id, |
104 | list.mc_version.clone(), | 125 | &list.mc_version, |
105 | list.modloader.clone(), | 126 | &list.modloader, |
106 | String::from(&list.download_folder), | 127 | &list.download_folder, |
107 | )?; | 128 | )?; |
108 | 129 | ||
109 | let mut ver_ids = vec![]; | 130 | let mut ver_ids = vec![]; |
110 | for id in exportlist.versions { | 131 | for id in exportlist.versions { |
111 | ver_ids.push(AddMod { id: IDSelector::VersionID(id.version), set_version: id.set} ); | 132 | ver_ids.push(AddMod { |
133 | id: IDSelector::VersionID(id.version), | ||
134 | set_version: id.set, | ||
135 | }); | ||
112 | } | 136 | } |
113 | mod_add(config.clone(), ver_ids, list, direct_download).await?; | 137 | mod_add(config, ver_ids, list, direct_download).await?; |
114 | } | 138 | } |
115 | Ok(()) | 139 | Ok(()) |
116 | } | 140 | } |
diff --git a/src/commands/list.rs b/src/commands/list.rs index 4aa4306..3665446 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs | |||
@@ -1,11 +1,13 @@ | |||
1 | use indicatif::{ProgressBar, ProgressStyle}; | ||
2 | |||
1 | use crate::{ | 3 | use crate::{ |
2 | config::Cfg, | 4 | config::Cfg, |
3 | db::{ | 5 | db::{ |
4 | config_change_current_list, config_get_current_list, lists_get, lists_insert, lists_remove, | 6 | config_change_current_list, config_get_current_list, lists_get, |
5 | lists_version, lists_get_all_ids, | 7 | lists_get_all_ids, lists_insert, lists_remove, lists_version, |
6 | }, | 8 | }, |
7 | error::{MLE, MLError, ErrorType}, | 9 | error::{ErrorType, MLError, MLE}, |
8 | update, Modloader, | 10 | update, Modloader, STYLE_OPERATION, |
9 | }; | 11 | }; |
10 | 12 | ||
11 | #[derive(Debug, Clone, PartialEq, Eq)] | 13 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -16,31 +18,47 @@ pub struct List { | |||
16 | pub download_folder: String, | 18 | pub download_folder: String, |
17 | } | 19 | } |
18 | 20 | ||
19 | pub fn get_current_list(config: Cfg) -> MLE<List> { | 21 | pub fn get_current_list(config: &Cfg) -> MLE<List> { |
20 | let id = config_get_current_list(config.clone())?; | 22 | let id = config_get_current_list(config)?; |
21 | lists_get(config, id) | 23 | lists_get(config, &id) |
22 | } | 24 | } |
23 | 25 | ||
24 | pub fn list_add( | 26 | pub fn list_add( |
25 | config: Cfg, | 27 | config: &Cfg, |
26 | id: String, | 28 | id: &str, |
27 | mc_version: String, | 29 | mc_version: &str, |
28 | modloader: Modloader, | 30 | modloader: &Modloader, |
29 | directory: String, | 31 | directory: &str, |
30 | ) -> MLE<()> { | 32 | ) -> MLE<()> { |
31 | lists_insert(config, id, mc_version, modloader, directory) | 33 | let p = ProgressBar::new_spinner(); |
34 | p.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | ||
35 | p.set_message(format!("Create {}", id)); | ||
36 | lists_insert(config, id, mc_version, modloader, directory)?; | ||
37 | p.finish_with_message(format!("Created {}", id)); | ||
38 | Ok(()) | ||
32 | } | 39 | } |
33 | 40 | ||
34 | pub fn list_change(config: Cfg, id: String) -> MLE<()> { | 41 | pub fn list_change(config: &Cfg, id: &str) -> MLE<()> { |
35 | if lists_get_all_ids(config.clone())?.into_iter().find(|l| l == &id).is_none() { | 42 | let p = ProgressBar::new_spinner(); |
43 | p.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | ||
44 | p.set_message(format!("Change default list to {}", id)); | ||
45 | |||
46 | if !lists_get_all_ids(config)?.into_iter().any(|l| l == id) { | ||
36 | return Err(MLError::new(ErrorType::ArgumentError, "List not found")); | 47 | return Err(MLError::new(ErrorType::ArgumentError, "List not found")); |
37 | }; | 48 | }; |
38 | println!("Change default list to: {}", id); | 49 | config_change_current_list(config, id)?; |
39 | config_change_current_list(config, id) | 50 | |
51 | p.finish_with_message(format!("Changed default list to {}", id)); | ||
52 | Ok(()) | ||
40 | } | 53 | } |
41 | 54 | ||
42 | pub fn list_remove(config: Cfg, id: String) -> MLE<()> { | 55 | pub fn list_remove(config: &Cfg, id: &str) -> MLE<()> { |
43 | lists_remove(config, id) | 56 | let p = ProgressBar::new_spinner(); |
57 | p.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | ||
58 | p.set_message(format!("Remove {}", id)); | ||
59 | lists_remove(config, id)?; | ||
60 | p.finish_with_message(format!("Removed {}", id)); | ||
61 | Ok(()) | ||
44 | } | 62 | } |
45 | 63 | ||
46 | ///Changing the current lists version and updating it | 64 | ///Changing the current lists version and updating it |
@@ -50,31 +68,34 @@ pub fn list_remove(config: Cfg, id: String) -> MLE<()> { | |||
50 | /// * `config` - The current config | 68 | /// * `config` - The current config |
51 | /// * `args` - All args, to extract the new version | 69 | /// * `args` - All args, to extract the new version |
52 | pub async fn list_version( | 70 | pub async fn list_version( |
53 | config: Cfg, | 71 | config: &Cfg, |
54 | id: String, | 72 | id: &str, |
55 | mc_version: String, | 73 | mc_version: String, |
56 | download: bool, | 74 | download: bool, |
57 | delete: bool, | 75 | delete: bool, |
58 | ) -> MLE<()> { | 76 | ) -> MLE<()> { |
59 | println!( | 77 | let p = ProgressBar::new_spinner(); |
78 | p.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | ||
79 | p.set_message(format!( | ||
60 | "Change version for list {} to minecraft version: {}", | 80 | "Change version for list {} to minecraft version: {}", |
61 | id, mc_version | 81 | id, mc_version |
62 | ); | 82 | )); |
63 | 83 | ||
64 | lists_version(config.clone(), &id, &mc_version)?; | 84 | lists_version(config, id, &mc_version)?; |
85 | |||
86 | p.finish_with_message(format!( | ||
87 | "Changed version for list {} to minecraft version: {}", | ||
88 | id, mc_version | ||
89 | )); | ||
65 | 90 | ||
66 | println!( | 91 | let list = lists_get(config, id)?; |
67 | "\nCheck for updates for new minecraft version in list {}", | ||
68 | id | ||
69 | ); | ||
70 | let list = lists_get(config.clone(), id)?; | ||
71 | update(config, vec![list], true, download, delete).await | 92 | update(config, vec![list], true, download, delete).await |
72 | } | 93 | } |
73 | 94 | ||
74 | pub fn list_list(config: Cfg) -> MLE<()> { | 95 | pub fn list_list(config: &Cfg) -> MLE<()> { |
75 | let lists = lists_get_all_ids(config.clone())?; | 96 | let lists = lists_get_all_ids(config)?; |
76 | for list in lists { | 97 | for list in lists { |
77 | let l = lists_get(config.clone(), list)?; | 98 | let l = lists_get(config, &list)?; |
78 | println!("{}: | {} | {}", l.id, l.mc_version, l.modloader) | 99 | println!("{}: | {} | {}", l.id, l.mc_version, l.modloader) |
79 | } | 100 | } |
80 | Ok(()) | 101 | Ok(()) |
diff --git a/src/commands/modification.rs b/src/commands/modification.rs index 9a1a651..4488b70 100644 --- a/src/commands/modification.rs +++ b/src/commands/modification.rs | |||
@@ -1,24 +1,30 @@ | |||
1 | use std::{io::Write, collections::HashMap}; | 1 | use std::collections::HashMap; |
2 | |||
3 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; | ||
2 | 4 | ||
3 | use crate::{ | 5 | use crate::{ |
4 | config::Cfg, | 6 | config::Cfg, |
5 | db::{ | 7 | db::{ |
6 | lists_get_all_ids, mods_get_id, mods_insert, mods_remove, userlist_get_all_ids, | 8 | lists_get_all_ids, mods_get_id, mods_get_info, mods_insert, |
7 | userlist_get_current_version, userlist_insert, userlist_remove, mods_get_info, | 9 | mods_remove, userlist_get_all_ids, userlist_get_current_version, |
10 | userlist_insert, userlist_remove, | ||
8 | }, | 11 | }, |
9 | error::{ErrorType, MLError, MLE}, | 12 | error::{ErrorType, MLError, MLE}, |
10 | files::{delete_version, download_versions}, | 13 | files::{delete_version, download_versions}, |
11 | modrinth::{extract_current_version, get_raw_versions, project, projects, versions, Version}, | 14 | modrinth::{ |
12 | List, | 15 | extract_current_version, get_raw_versions, project, projects, versions, |
16 | Version, | ||
17 | }, | ||
18 | List, PROGRESS_CHARS, STYLE_BAR_POS, STYLE_OPERATION, | ||
13 | }; | 19 | }; |
14 | 20 | ||
15 | #[derive(Debug, Clone)] | 21 | #[derive(Debug)] |
16 | pub struct AddMod { | 22 | pub struct AddMod { |
17 | pub id: IDSelector, | 23 | pub id: IDSelector, |
18 | pub set_version: bool | 24 | pub set_version: bool, |
19 | } | 25 | } |
20 | 26 | ||
21 | #[derive(Debug, Clone, PartialEq, Eq)] | 27 | #[derive(Debug, PartialEq, Eq)] |
22 | pub enum IDSelector { | 28 | pub enum IDSelector { |
23 | ModificationID(String), | 29 | ModificationID(String), |
24 | VersionID(String), | 30 | VersionID(String), |
@@ -36,54 +42,76 @@ pub struct ProjectInfo { | |||
36 | } | 42 | } |
37 | 43 | ||
38 | pub async fn mod_add( | 44 | pub async fn mod_add( |
39 | config: Cfg, | 45 | config: &Cfg, |
40 | mods: Vec<AddMod>, | 46 | mods: Vec<AddMod>, |
41 | list: List, | 47 | list: List, |
42 | direct_download: bool, | 48 | direct_download: bool, |
43 | ) -> MLE<()> { | 49 | ) -> MLE<()> { |
44 | println!("Add mods to {}", list.id); | 50 | let mp = MultiProgress::new(); |
45 | println!(" └Add mods:"); | ||
46 | 51 | ||
47 | let mut mod_ids: Vec<(String, bool)> = Vec::new(); | 52 | let mut mod_ids: Vec<(String, bool)> = Vec::new(); |
48 | let mut ver_ids: Vec<(String, bool)> = Vec::new(); | 53 | let mut ver_ids: Vec<(String, bool)> = Vec::new(); |
49 | 54 | ||
55 | let add_p = mp.add(ProgressBar::new(mods.len().try_into().unwrap())); | ||
56 | add_p.set_style( | ||
57 | ProgressStyle::with_template(STYLE_BAR_POS) | ||
58 | .unwrap() | ||
59 | .progress_chars(PROGRESS_CHARS), | ||
60 | ); | ||
61 | add_p.set_message("Sort ids"); | ||
62 | |||
50 | //"Sort" project ids from version ids to be able to handle them differently but in a batch | 63 | //"Sort" project ids from version ids to be able to handle them differently but in a batch |
51 | for m in mods { | 64 | for m in mods { |
65 | add_p.inc(1); | ||
52 | match m.id { | 66 | match m.id { |
53 | IDSelector::ModificationID(pid) => mod_ids.push((pid, m.set_version)), | 67 | IDSelector::ModificationID(pid) => { |
68 | mod_ids.push((pid, m.set_version)) | ||
69 | } | ||
54 | IDSelector::VersionID(vid) => ver_ids.push((vid, m.set_version)), | 70 | IDSelector::VersionID(vid) => ver_ids.push((vid, m.set_version)), |
55 | } | 71 | } |
56 | } | 72 | } |
57 | 73 | ||
74 | add_p.set_message("Get infos"); | ||
75 | |||
58 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); | 76 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); |
59 | if !mod_ids.is_empty() { | 77 | if !mod_ids.is_empty() { |
60 | projectinfo.append(&mut get_mod_infos(config.clone(), mod_ids, list.clone()).await?) | 78 | projectinfo |
79 | .append(&mut get_mod_infos(config, mod_ids, list.clone()).await?); | ||
61 | }; | 80 | }; |
62 | if !ver_ids.is_empty() { | 81 | if !ver_ids.is_empty() { |
63 | projectinfo.append(&mut get_ver_info(config.clone(), ver_ids).await?) | 82 | projectinfo.append(&mut get_ver_info(config, ver_ids).await?); |
64 | }; | 83 | }; |
65 | 84 | ||
66 | if projectinfo.is_empty() { | 85 | if projectinfo.is_empty() { |
67 | return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")); | 86 | return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")); |
68 | }; | 87 | }; |
69 | 88 | ||
89 | add_p.set_message("Add mods to database"); | ||
90 | |||
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 project_p = mp.insert_before( |
74 | println!(" └Insert mod in list {} and save infos", list.id); | 95 | &add_p, |
75 | } else { | 96 | ProgressBar::new(projectinfo.len().try_into().unwrap()), |
76 | println!(" └Insert mods in list {} and save infos", list.id); | 97 | ); |
77 | } | 98 | project_p.set_style( |
99 | ProgressStyle::with_template(STYLE_BAR_POS) | ||
100 | .unwrap() | ||
101 | .progress_chars(PROGRESS_CHARS), | ||
102 | ); | ||
78 | 103 | ||
79 | for project in projectinfo { | 104 | for project in projectinfo { |
105 | project_p.set_message(format!("Add {}", project.title)); | ||
106 | |||
80 | let current_version_id = if project.current_version.is_none() { | 107 | let current_version_id = if project.current_version.is_none() { |
81 | String::from("NONE") | 108 | String::from("NONE") |
82 | } else { | 109 | } else { |
83 | project.current_version.clone().unwrap().id | 110 | project.current_version.clone().unwrap().id |
84 | }; | 111 | }; |
112 | |||
85 | match userlist_insert( | 113 | match userlist_insert( |
86 | config.clone(), | 114 | config, |
87 | &list.id, | 115 | &list.id, |
88 | &project.mod_id, | 116 | &project.mod_id, |
89 | ¤t_version_id, | 117 | ¤t_version_id, |
@@ -92,7 +120,10 @@ pub async fn mod_add( | |||
92 | project.set_version, | 120 | project.set_version, |
93 | ) { | 121 | ) { |
94 | Err(e) => { | 122 | Err(e) => { |
95 | let expected_err = format!("SQL: UNIQUE constraint failed: {}.mod_id", list.id); | 123 | let expected_err = format!( |
124 | "SQL: UNIQUE constraint failed: {}.mod_id", | ||
125 | list.id | ||
126 | ); | ||
96 | if e.to_string() == expected_err { | 127 | if e.to_string() == expected_err { |
97 | Err(MLError::new( | 128 | Err(MLError::new( |
98 | ErrorType::ModError, | 129 | ErrorType::ModError, |
@@ -106,7 +137,7 @@ pub async fn mod_add( | |||
106 | }?; | 137 | }?; |
107 | 138 | ||
108 | match mods_insert( | 139 | match mods_insert( |
109 | config.clone(), | 140 | config, |
110 | &project.mod_id, | 141 | &project.mod_id, |
111 | &project.slug, | 142 | &project.slug, |
112 | &project.title, | 143 | &project.title, |
@@ -124,18 +155,35 @@ pub async fn mod_add( | |||
124 | if project.current_version.is_some() { | 155 | if project.current_version.is_some() { |
125 | downloadstack.push(project.current_version.unwrap()) | 156 | downloadstack.push(project.current_version.unwrap()) |
126 | }; | 157 | }; |
158 | |||
159 | project_p.inc(1); | ||
127 | } | 160 | } |
128 | 161 | ||
162 | project_p.finish_with_message("Added all mods to the database"); | ||
163 | |||
129 | //Download all the added mods | 164 | //Download all the added mods |
130 | if direct_download { | 165 | if direct_download { |
131 | download_versions(list.clone(), config.clone(), downloadstack).await?; | 166 | add_p.set_message("Download mods"); |
167 | download_versions( | ||
168 | list.clone(), | ||
169 | config.clone(), | ||
170 | downloadstack, | ||
171 | &mp, | ||
172 | &add_p, | ||
173 | ) | ||
174 | .await?; | ||
132 | }; | 175 | }; |
133 | 176 | ||
177 | add_p.finish_with_message("Added all mods"); | ||
178 | |||
134 | Ok(()) | 179 | Ok(()) |
135 | } | 180 | } |
136 | 181 | ||
137 | async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> MLE<Vec<ProjectInfo>> { | 182 | async fn get_mod_infos( |
138 | 183 | config: &Cfg, | |
184 | mod_ids: Vec<(String, bool)>, | ||
185 | list: List, | ||
186 | ) -> MLE<Vec<ProjectInfo>> { | ||
139 | let mut setmap: HashMap<String, bool> = HashMap::new(); | 187 | let mut setmap: HashMap<String, bool> = HashMap::new(); |
140 | 188 | ||
141 | let mut ids = vec![]; | 189 | let mut ids = vec![]; |
@@ -154,8 +202,6 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> | |||
154 | _ => panic!("PANIC"), | 202 | _ => panic!("PANIC"), |
155 | }; | 203 | }; |
156 | for project in m_projects { | 204 | for project in m_projects { |
157 | println!("\t└{}", project.title); | ||
158 | println!("\t └Get versions"); | ||
159 | let available_versions = versions( | 205 | let available_versions = versions( |
160 | &config.apis.modrinth, | 206 | &config.apis.modrinth, |
161 | String::from(&project.id), | 207 | String::from(&project.id), |
@@ -167,8 +213,8 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> | |||
167 | let current_version: Option<Version>; | 213 | let current_version: Option<Version>; |
168 | let file: String; | 214 | let file: String; |
169 | if !available_versions.is_empty() { | 215 | if !available_versions.is_empty() { |
170 | let current_id = extract_current_version(available_versions.clone())?; | 216 | let current_id = |
171 | println!("\t └Current version: {}", current_id); | 217 | extract_current_version(available_versions.clone())?; |
172 | 218 | ||
173 | current_version = Some( | 219 | current_version = Some( |
174 | available_versions | 220 | available_versions |
@@ -177,19 +223,15 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> | |||
177 | .find(|v| v.id == current_id) | 223 | .find(|v| v.id == current_id) |
178 | .unwrap(), | 224 | .unwrap(), |
179 | ); | 225 | ); |
180 | 226 | ||
181 | // match primary, if none? | 227 | // match primary, if none? |
182 | let files = current_version | 228 | let files = current_version.clone().ok_or("").unwrap().files; |
183 | .clone() | ||
184 | .ok_or("") | ||
185 | .unwrap() | ||
186 | .files; | ||
187 | 229 | ||
188 | file = match files.clone().into_iter().find(|f| f.primary) { | 230 | file = match files.clone().into_iter().find(|f| f.primary) { |
189 | Some(f) => f, | 231 | Some(f) => f, |
190 | None => { files[0].clone() } | 232 | None => files[0].clone(), |
191 | } | 233 | } |
192 | .url; | 234 | .url; |
193 | 235 | ||
194 | for ver in available_versions { | 236 | for ver in available_versions { |
195 | available_versions_vec.push(ver.id); | 237 | available_versions_vec.push(ver.id); |
@@ -197,15 +239,14 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> | |||
197 | 239 | ||
198 | projectinfo.push(ProjectInfo { | 240 | projectinfo.push(ProjectInfo { |
199 | mod_id: String::from(&project.id), | 241 | mod_id: String::from(&project.id), |
200 | slug: project.slug, | 242 | slug: project.slug.clone(), |
201 | title: project.title, | 243 | title: project.title, |
202 | current_version, | 244 | current_version, |
203 | applicable_versions: available_versions_vec, | 245 | applicable_versions: available_versions_vec, |
204 | download_link: file, | 246 | download_link: file, |
205 | set_version: setmap.get(&project.id).unwrap().clone(), | 247 | set_version: *setmap.get(&project.slug).unwrap(), |
206 | }) | 248 | }) |
207 | } else { | 249 | } else { |
208 | println!("\t └There's currently no mod version for your specified target"); | ||
209 | current_version = None; | 250 | current_version = None; |
210 | file = String::from("NONE"); | 251 | file = String::from("NONE"); |
211 | available_versions_vec.push(String::from("NONE")); | 252 | available_versions_vec.push(String::from("NONE")); |
@@ -216,7 +257,7 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> | |||
216 | current_version, | 257 | current_version, |
217 | applicable_versions: available_versions_vec, | 258 | applicable_versions: available_versions_vec, |
218 | download_link: file, | 259 | download_link: file, |
219 | set_version: setmap.get(&project.id).unwrap().clone(), | 260 | set_version: *setmap.get(&project.id).unwrap(), |
220 | }) | 261 | }) |
221 | } | 262 | } |
222 | } | 263 | } |
@@ -224,8 +265,10 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) -> | |||
224 | Ok(projectinfo) | 265 | Ok(projectinfo) |
225 | } | 266 | } |
226 | 267 | ||
227 | async fn get_ver_info(config: Cfg, ver_ids: Vec<(String, bool)>) -> MLE<Vec<ProjectInfo>> { | 268 | async fn get_ver_info( |
228 | 269 | config: &Cfg, | |
270 | ver_ids: Vec<(String, bool)>, | ||
271 | ) -> MLE<Vec<ProjectInfo>> { | ||
229 | let mut setmap: HashMap<String, bool> = HashMap::new(); | 272 | let mut setmap: HashMap<String, bool> = HashMap::new(); |
230 | 273 | ||
231 | let mut ids = vec![]; | 274 | let mut ids = vec![]; |
@@ -248,14 +291,15 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<(String, bool)>) -> MLE<Vec<Proj | |||
248 | 291 | ||
249 | for (i, project) in v_projects.into_iter().enumerate() { | 292 | for (i, project) in v_projects.into_iter().enumerate() { |
250 | let version = &v_versions[i]; | 293 | let version = &v_versions[i]; |
251 | println!("\t└{}({})", project.title, version.id); | 294 | |
252 | let file = version | 295 | let files = version.clone().files; |
253 | .clone() | 296 | |
254 | .files | 297 | let file = match files.clone().into_iter().find(|f| f.primary) { |
255 | .into_iter() | 298 | Some(f) => f, |
256 | .find(|f| f.primary) | 299 | None => files[0].clone(), |
257 | .unwrap() | 300 | } |
258 | .url; | 301 | .url; |
302 | |||
259 | projectinfo.push(ProjectInfo { | 303 | projectinfo.push(ProjectInfo { |
260 | mod_id: String::from(&project.id), | 304 | mod_id: String::from(&project.id), |
261 | slug: project.slug, | 305 | slug: project.slug, |
@@ -263,7 +307,7 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<(String, bool)>) -> MLE<Vec<Proj | |||
263 | current_version: Some(version.clone()), | 307 | current_version: Some(version.clone()), |
264 | applicable_versions: vec![String::from(&version.id)], | 308 | applicable_versions: vec![String::from(&version.id)], |
265 | download_link: file, | 309 | download_link: file, |
266 | set_version: setmap.get(&version.id).unwrap().clone(), | 310 | set_version: *setmap.get(&version.id).unwrap(), |
267 | }) | 311 | }) |
268 | } | 312 | } |
269 | Ok(projectinfo) | 313 | Ok(projectinfo) |
@@ -275,48 +319,45 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<(String, bool)>) -> MLE<Vec<Proj | |||
275 | /// * `config` - config struct | 319 | /// * `config` - config struct |
276 | /// * `id` - name, slug or id of the mod | 320 | /// * `id` - name, slug or id of the mod |
277 | /// * `list` - List struct | 321 | /// * `list` - List struct |
278 | pub fn mod_remove(config: Cfg, id: &str, list: List) -> MLE<()> { | 322 | pub fn mod_remove(config: &Cfg, id: &str, list: &List) -> MLE<()> { |
323 | let progress = ProgressBar::new_spinner(); | ||
324 | progress.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | ||
325 | |||
279 | let mod_id = mods_get_id(&config.data, id)?; | 326 | let mod_id = mods_get_id(&config.data, id)?; |
280 | 327 | ||
281 | println!("Remove mod {} from {}", mods_get_info(config.clone(), &mod_id)?.title, list.id); | 328 | let info = mods_get_info(config, &mod_id)?; |
282 | let version = userlist_get_current_version(config.clone(), &list.id, &mod_id)?; | ||
283 | 329 | ||
284 | print!(" └Remove from list"); | 330 | progress.set_message(format!("Remove {} from {}", info.title, list.id)); |
285 | //Force flush of stdout, else print! doesn't print instantly | ||
286 | std::io::stdout().flush()?; | ||
287 | userlist_remove(config.clone(), &list.id, &mod_id)?; | ||
288 | println!(" ✓"); | ||
289 | 331 | ||
290 | print!(" └Delete file"); | 332 | let version = userlist_get_current_version(config, &list.id, &mod_id)?; |
291 | //Force flush of stdout, else print! doesn't print instantly | 333 | |
292 | std::io::stdout().flush()?; | 334 | userlist_remove(config, &list.id, &mod_id)?; |
335 | |||
336 | progress.set_message("Delete file"); | ||
293 | match delete_version(list, version) { | 337 | match delete_version(list, version) { |
294 | Ok(_) => (), | 338 | Ok(_) => (), |
295 | Err(err) => { | 339 | Err(err) => { |
296 | if err.to_string() != "User input not accepted: VERSION_NOT_FOUND_IN_FILES" { | 340 | if err.to_string() |
341 | != "User input not accepted: VERSION_NOT_FOUND_IN_FILES" | ||
342 | { | ||
297 | return Err(err); | 343 | return Err(err); |
298 | }; | 344 | }; |
299 | () | 345 | } |
300 | }, | ||
301 | }; | 346 | }; |
302 | println!(" ✓"); | ||
303 | 347 | ||
304 | print!(" └Clean main db table"); | 348 | progress.set_message("Check main list"); |
305 | //Force flush of stdout, else print! doesn't print instantly | 349 | let list_ids = lists_get_all_ids(config)?; |
306 | std::io::stdout().flush()?; | ||
307 | let list_ids = lists_get_all_ids(config.clone())?; | ||
308 | 350 | ||
309 | // Remove mod from main list if not used elsewhere | 351 | // Remove mod from main list if not used elsewhere |
310 | let mut mod_used = false; | 352 | let mut mod_used = false; |
311 | for id in list_ids { | 353 | for id in list_ids { |
312 | let mods = match userlist_get_all_ids(config.clone(), &id) { | 354 | let mods = match userlist_get_all_ids(config, &id) { |
313 | Ok(m) => m, | 355 | Ok(m) => m, |
314 | Err(err) => { | 356 | Err(err) => { |
315 | if err.to_string() == "Database: NO_MODS_USERLIST" { | 357 | if err.to_string() == "Database: NO_MODS_USERLIST" { |
316 | println!(" ✓"); | ||
317 | return Ok(()); | 358 | return Ok(()); |
318 | }; | 359 | }; |
319 | return Err(err) | 360 | return Err(err); |
320 | } | 361 | } |
321 | }; | 362 | }; |
322 | if mods.contains(&mod_id) { | 363 | if mods.contains(&mod_id) { |
@@ -326,9 +367,14 @@ pub fn mod_remove(config: Cfg, id: &str, list: List) -> MLE<()> { | |||
326 | } | 367 | } |
327 | 368 | ||
328 | if !mod_used { | 369 | if !mod_used { |
329 | mods_remove(config, mod_id)?; | 370 | progress.set_message("Remove from main list"); |
371 | mods_remove(config, &mod_id)?; | ||
330 | }; | 372 | }; |
331 | println!(" ✓"); | 373 | |
374 | progress.finish_with_message(format!( | ||
375 | "Removed {} from {}", | ||
376 | info.title, list.id | ||
377 | )); | ||
332 | 378 | ||
333 | Ok(()) | 379 | Ok(()) |
334 | } | 380 | } |
diff --git a/src/commands/update.rs b/src/commands/update.rs index d3a282b..c19c02c 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs | |||
@@ -1,49 +1,81 @@ | |||
1 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; | ||
2 | |||
1 | use crate::{ | 3 | use crate::{ |
2 | config::Cfg, | 4 | config::Cfg, |
3 | db::{ | 5 | db::{ |
4 | mods_get_info, userlist_change_versions, userlist_get_all_ids, | 6 | mods_get_info, userlist_change_versions, userlist_get_all_ids, |
5 | userlist_get_applicable_versions, userlist_get_current_version, userlist_get_set_version, | 7 | userlist_get_applicable_versions, userlist_get_current_version, |
8 | userlist_get_set_version, | ||
6 | }, | 9 | }, |
7 | error::{ErrorType, MLError, MLE}, | 10 | error::{ErrorType, MLError, MLE}, |
8 | files::{clean_list_dir, delete_version, disable_version, download_versions}, | 11 | files::{ |
12 | clean_list_dir, delete_version, disable_version, download_versions, | ||
13 | }, | ||
9 | modrinth::{extract_current_version, versions, Version}, | 14 | modrinth::{extract_current_version, versions, Version}, |
10 | List, | 15 | List, PROGRESS_CHARS, STYLE_BAR_POS, STYLE_OPERATION, |
11 | }; | 16 | }; |
12 | 17 | ||
13 | pub async fn update( | 18 | pub async fn update( |
14 | config: Cfg, | 19 | config: &Cfg, |
15 | liststack: Vec<List>, | 20 | liststack: Vec<List>, |
16 | clean: bool, | 21 | clean: bool, |
17 | direct_download: bool, | 22 | direct_download: bool, |
18 | delete_old: bool, | 23 | delete_old: bool, |
19 | ) -> MLE<()> { | 24 | ) -> MLE<()> { |
25 | let mp = MultiProgress::new(); | ||
26 | |||
27 | let update_p = | ||
28 | mp.add(ProgressBar::new(liststack.len().try_into().unwrap())); | ||
29 | update_p.set_style( | ||
30 | ProgressStyle::with_template(STYLE_BAR_POS) | ||
31 | .unwrap() | ||
32 | .progress_chars(PROGRESS_CHARS), | ||
33 | ); | ||
34 | |||
20 | for current_list in liststack { | 35 | for current_list in liststack { |
21 | println!("Update mods in {}", current_list.id); | 36 | update_p.set_message(format!("Update {}", current_list.id)); |
22 | let mods = userlist_get_all_ids(config.clone(), ¤t_list.id)?; | ||
23 | 37 | ||
24 | let mut current_versions: Vec<(String, String)> = vec![]; | 38 | let list_p = mp.insert_before(&update_p, ProgressBar::new(2)); |
39 | list_p | ||
40 | .set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); | ||
41 | list_p.set_message("Update mods"); | ||
42 | |||
43 | let mods = userlist_get_all_ids(config, ¤t_list.id)?; | ||
44 | |||
45 | let list_u_p = mp.insert_before( | ||
46 | &list_p, | ||
47 | ProgressBar::new(mods.len().try_into().unwrap()), | ||
48 | ); | ||
49 | list_u_p.set_style( | ||
50 | ProgressStyle::with_template(STYLE_BAR_POS) | ||
51 | .unwrap() | ||
52 | .progress_chars(PROGRESS_CHARS), | ||
53 | ); | ||
25 | 54 | ||
55 | let mut current_versions: Vec<(String, String)> = vec![]; | ||
26 | let mut updatestack: Vec<Version> = vec![]; | 56 | let mut updatestack: Vec<Version> = vec![]; |
27 | 57 | ||
28 | for id in mods { | 58 | for id in mods { |
29 | let info = mods_get_info(config.clone(), &id)?; | 59 | let info = mods_get_info(config, &id)?; |
30 | println!(" ├{}", info.title); | 60 | list_u_p.set_message(format!("Update {}", info.title)); |
31 | 61 | ||
32 | if userlist_get_set_version(config.clone(), ¤t_list.id, &id)? { | 62 | //Skip check if version is set |
33 | println!(" │ └Set version, skipping update"); | 63 | if userlist_get_set_version(config, ¤t_list.id, &id)? { |
64 | list_u_p.inc(1); | ||
34 | continue; | 65 | continue; |
35 | } | 66 | } |
36 | 67 | ||
37 | //Getting current installed version for disable or delete | 68 | //Getting current installed version for disable or delete |
38 | let disable_version = | 69 | let disable_version = |
39 | userlist_get_current_version(config.clone(), ¤t_list.id, &id)?; | 70 | userlist_get_current_version(config, ¤t_list.id, &id)?; |
40 | 71 | ||
41 | updatestack.push( | 72 | updatestack.push( |
42 | match specific_update( | 73 | match specific_update( |
43 | config.clone(), | 74 | config, |
44 | clean, | 75 | clean, |
45 | current_list.clone(), | 76 | current_list.clone(), |
46 | String::from(&id), | 77 | &id, |
78 | &list_u_p, | ||
47 | ) | 79 | ) |
48 | .await | 80 | .await |
49 | { | 81 | { |
@@ -53,46 +85,94 @@ pub async fn update( | |||
53 | } | 85 | } |
54 | Err(e) => { | 86 | Err(e) => { |
55 | if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { | 87 | if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { |
56 | println!( | ||
57 | " │ └No new version found for the specified minecraft version" | ||
58 | ); | ||
59 | } else { | 88 | } else { |
60 | return Err(e); | 89 | return Err(e); |
61 | }; | 90 | }; |
91 | list_u_p.inc(1); | ||
62 | continue; | 92 | continue; |
63 | } | 93 | } |
64 | }, | 94 | }, |
65 | ) | 95 | ); |
96 | list_u_p.inc(1); | ||
66 | } | 97 | } |
67 | 98 | ||
99 | list_u_p.finish_with_message(format!( | ||
100 | "Updated mods in {}", | ||
101 | current_list.id | ||
102 | )); | ||
103 | |||
68 | if clean { | 104 | if clean { |
105 | list_p.set_message("Cleaning"); | ||
69 | clean_list_dir(¤t_list)?; | 106 | clean_list_dir(¤t_list)?; |
70 | }; | 107 | }; |
71 | 108 | ||
72 | if direct_download && !updatestack.is_empty() { | 109 | if direct_download && !updatestack.is_empty() { |
73 | download_versions(current_list.clone(), config.clone(), updatestack).await?; | 110 | download_versions( |
111 | current_list.clone(), | ||
112 | config.clone(), | ||
113 | updatestack, | ||
114 | &mp, | ||
115 | &list_p, | ||
116 | ) | ||
117 | .await?; | ||
74 | 118 | ||
75 | //Disable old versions | 119 | //Disable old versions |
76 | if !clean { | 120 | if !clean { |
121 | let d_p = mp.insert_before( | ||
122 | &list_p, | ||
123 | ProgressBar::new( | ||
124 | current_versions.len().try_into().unwrap(), | ||
125 | ), | ||
126 | ); | ||
127 | d_p.set_style( | ||
128 | ProgressStyle::with_template(STYLE_BAR_POS) | ||
129 | .unwrap() | ||
130 | .progress_chars(PROGRESS_CHARS), | ||
131 | ); | ||
77 | for ver in current_versions { | 132 | for ver in current_versions { |
78 | if delete_old { | 133 | if delete_old { |
79 | println!(" └Delete version {}", ver.0); | 134 | d_p.set_message(format!("Delete version {}", ver.0)); |
80 | delete_version(current_list.clone(), ver.0)?; | 135 | d_p.inc(1); |
136 | delete_version(¤t_list, ver.0)?; | ||
81 | } else if ver.0 != "NONE" { | 137 | } else if ver.0 != "NONE" { |
82 | println!(" └Disable version {}", ver.0); | 138 | d_p.set_message(format!("Disable version {}", ver.0)); |
83 | disable_version(config.clone(), current_list.clone(), ver.0, ver.1)?; | 139 | d_p.inc(1); |
140 | disable_version( | ||
141 | config, | ||
142 | current_list.clone(), | ||
143 | ver.0, | ||
144 | ver.1, | ||
145 | )?; | ||
84 | }; | 146 | }; |
85 | } | 147 | } |
148 | |||
149 | let del_msg = if delete_old { | ||
150 | "Deleted all old versions" | ||
151 | } else { | ||
152 | "Disabled all old versions" | ||
153 | }; | ||
154 | |||
155 | d_p.finish_with_message(del_msg); | ||
86 | } | 156 | } |
87 | }; | 157 | }; |
158 | list_p.finish_with_message(format!("Updated {}", current_list.id)); | ||
159 | update_p.inc(1); | ||
88 | } | 160 | } |
89 | 161 | ||
162 | update_p.finish_with_message("Updated all lists"); | ||
163 | |||
90 | Ok(()) | 164 | Ok(()) |
91 | } | 165 | } |
92 | 166 | ||
93 | async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> MLE<Version> { | 167 | async fn specific_update( |
168 | config: &Cfg, | ||
169 | clean: bool, | ||
170 | list: List, | ||
171 | id: &str, | ||
172 | progress: &ProgressBar, | ||
173 | ) -> MLE<Version> { | ||
94 | let applicable_versions = | 174 | let applicable_versions = |
95 | versions(&config.apis.modrinth, String::from(&id), list.clone()).await; | 175 | versions(&config.apis.modrinth, String::from(id), list.clone()).await; |
96 | 176 | ||
97 | let mut versions: Vec<String> = vec![]; | 177 | let mut versions: Vec<String> = vec![]; |
98 | 178 | ||
@@ -108,19 +188,19 @@ async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> ML | |||
108 | if clean | 188 | if clean |
109 | || (versions.join("|") | 189 | || (versions.join("|") |
110 | != userlist_get_applicable_versions( | 190 | != userlist_get_applicable_versions( |
111 | config.clone(), | 191 | config, |
112 | String::from(&list.id), | 192 | String::from(&list.id), |
113 | String::from(&id), | 193 | String::from(id), |
114 | )?) | 194 | )?) |
115 | { | 195 | { |
116 | let current_str = extract_current_version(applicable_versions.clone())?; | 196 | let current_str = extract_current_version(applicable_versions.clone())?; |
117 | 197 | ||
118 | if clean { | 198 | if !clean { |
119 | println!("\t └Add version to downloadstack"); | 199 | progress.println(format!( |
120 | } else { | 200 | "Found new version for {}", |
121 | println!("\t └Get versions for specified minecraft versions"); | 201 | mods_get_info(config, id).unwrap().title |
122 | println!("\t └New current version: {}", current_str); | 202 | )); |
123 | }; | 203 | } |
124 | 204 | ||
125 | //get new versions | 205 | //get new versions |
126 | let current_ver = match applicable_versions | 206 | let current_ver = match applicable_versions |
@@ -133,73 +213,27 @@ async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> ML | |||
133 | }?; | 213 | }?; |
134 | current.push(current_ver.clone()); | 214 | current.push(current_ver.clone()); |
135 | 215 | ||
136 | let link = match current_ver | 216 | let files = ¤t_ver.files; |
137 | .files | 217 | |
138 | .into_iter() | 218 | let link = match files.clone().into_iter().find(|f| f.primary) { |
139 | .find(|f| f.primary) | 219 | Some(f) => f, |
140 | .ok_or("!no primary in links") | 220 | None => files[0].clone(), |
141 | { | 221 | } |
142 | Ok(p) => Ok(p), | ||
143 | Err(e) => Err(MLError::new(ErrorType::Other, e)), | ||
144 | }? | ||
145 | .url; | 222 | .url; |
146 | userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id)?; | 223 | |
224 | userlist_change_versions( | ||
225 | config, | ||
226 | list.id, | ||
227 | current_str, | ||
228 | versions.join("|"), | ||
229 | link, | ||
230 | id.to_string(), | ||
231 | )?; | ||
147 | } | 232 | } |
148 | 233 | ||
149 | if current.is_empty() { | 234 | if current.is_empty() { |
150 | return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")); | 235 | return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")); |
151 | }; | 236 | }; |
152 | 237 | ||
153 | //println!(" └✔️"); | ||
154 | Ok(current[0].clone()) | 238 | Ok(current[0].clone()) |
155 | } | 239 | } |
156 | |||
157 | // #[tokio::test] | ||
158 | // async fn download_updates_test() { | ||
159 | // use crate::{ | ||
160 | // modrinth::{Hash, Version, VersionFile, VersionType}, | ||
161 | // List, Modloader, | ||
162 | // }; | ||
163 | // | ||
164 | // let config = Cfg::init().unwrap(); | ||
165 | // let current_list = List { | ||
166 | // id: String::from("..."), | ||
167 | // mc_version: String::from("..."), | ||
168 | // modloader: Modloader::Fabric, | ||
169 | // download_folder: String::from("./dev/tests/dl"), | ||
170 | // }; | ||
171 | // | ||
172 | // let versions = vec![Version { | ||
173 | // id: "dEqtGnT9".to_string(), | ||
174 | // project_id: "kYuIpRLv".to_string(), | ||
175 | // author_id: "Qnt13hO8".to_string(), | ||
176 | // featured: true, | ||
177 | // name: "1.2.2-1.19 - Fabric".to_string(), | ||
178 | // version_number: "1.2.2-1.19".to_string(), | ||
179 | // changelog: None, | ||
180 | // date_published: "2022-11-02T17:41:43.072267Z".to_string(), | ||
181 | // downloads: 58, | ||
182 | // version_type: VersionType::release, | ||
183 | // files: vec![VersionFile { | ||
184 | // hashes: Hash { | ||
185 | // sha1: "fdc6dc39427fc92cc1d7ad8b275b5b83325e712b".to_string(), | ||
186 | // sha512: "5b372f00d6e5d6a5ef225c3897826b9f6a2be5506905f7f71b9e939779765b41be6f2a9b029cfc752ad0751d0d2d5f8bb4544408df1363eebdde15641e99a849".to_string() | ||
187 | // }, | ||
188 | // url: "https://cdn.modrinth.com/data/kYuIpRLv/versions/dEqtGnT9/waveycapes-fabric-1.2.2-mc1.19.2.jar".to_string(), | ||
189 | // filename: "waveycapes-fabric-1.2.2-mc1.19.2.jar".to_string(), | ||
190 | // primary: true, | ||
191 | // size: 323176 | ||
192 | // }], | ||
193 | // game_versions: vec![ | ||
194 | // "1.19".to_string(), | ||
195 | // "1.19.1".to_string(), | ||
196 | // "1.19.2".to_string() | ||
197 | // ], | ||
198 | // loaders: vec![ | ||
199 | // "fabric".to_string() | ||
200 | // ] | ||
201 | // }]; | ||
202 | // assert!(download_versions(current_list, config, versions) | ||
203 | // .await | ||
204 | // .is_ok()) | ||
205 | // } | ||