diff options
-rw-r--r-- | .rustfmt.toml | 1 | ||||
-rw-r--r-- | Cargo.lock | 376 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | src/apis/modrinth.rs | 19 | ||||
-rw-r--r-- | src/cache.rs | 4 | ||||
-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 | ||||
-rw-r--r-- | src/config.rs | 51 | ||||
-rw-r--r-- | src/db.rs | 216 | ||||
-rw-r--r-- | src/error.rs | 14 | ||||
-rw-r--r-- | src/files.rs | 199 | ||||
-rw-r--r-- | src/lib.rs | 72 | ||||
-rw-r--r-- | src/main.rs | 206 |
16 files changed, 1080 insertions, 757 deletions
diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..df99c69 --- /dev/null +++ b/.rustfmt.toml | |||
@@ -0,0 +1 @@ | |||
max_width = 80 | |||
@@ -19,11 +19,11 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" | |||
19 | 19 | ||
20 | [[package]] | 20 | [[package]] |
21 | name = "ahash" | 21 | name = "ahash" |
22 | version = "0.7.6" | 22 | version = "0.8.3" |
23 | source = "registry+https://github.com/rust-lang/crates.io-index" | 23 | source = "registry+https://github.com/rust-lang/crates.io-index" |
24 | checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" | 24 | checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" |
25 | dependencies = [ | 25 | dependencies = [ |
26 | "getrandom", | 26 | "cfg-if", |
27 | "once_cell", | 27 | "once_cell", |
28 | "version_check", | 28 | "version_check", |
29 | ] | 29 | ] |
@@ -39,9 +39,9 @@ dependencies = [ | |||
39 | 39 | ||
40 | [[package]] | 40 | [[package]] |
41 | name = "anstream" | 41 | name = "anstream" |
42 | version = "0.3.1" | 42 | version = "0.3.2" |
43 | source = "registry+https://github.com/rust-lang/crates.io-index" | 43 | source = "registry+https://github.com/rust-lang/crates.io-index" |
44 | checksum = "6342bd4f5a1205d7f41e94a41a901f5647c938cdfa96036338e8533c9d6c2450" | 44 | checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" |
45 | dependencies = [ | 45 | dependencies = [ |
46 | "anstyle", | 46 | "anstyle", |
47 | "anstyle-parse", | 47 | "anstyle-parse", |
@@ -109,9 +109,9 @@ dependencies = [ | |||
109 | 109 | ||
110 | [[package]] | 110 | [[package]] |
111 | name = "base64" | 111 | name = "base64" |
112 | version = "0.21.0" | 112 | version = "0.21.2" |
113 | source = "registry+https://github.com/rust-lang/crates.io-index" | 113 | source = "registry+https://github.com/rust-lang/crates.io-index" |
114 | checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" | 114 | checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" |
115 | 115 | ||
116 | [[package]] | 116 | [[package]] |
117 | name = "bitflags" | 117 | name = "bitflags" |
@@ -121,15 +121,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | |||
121 | 121 | ||
122 | [[package]] | 122 | [[package]] |
123 | name = "bitflags" | 123 | name = "bitflags" |
124 | version = "2.2.1" | 124 | version = "2.3.1" |
125 | source = "registry+https://github.com/rust-lang/crates.io-index" | 125 | source = "registry+https://github.com/rust-lang/crates.io-index" |
126 | checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813" | 126 | checksum = "6776fc96284a0bb647b615056fc496d1fe1644a7ab01829818a6d91cae888b84" |
127 | 127 | ||
128 | [[package]] | 128 | [[package]] |
129 | name = "bumpalo" | 129 | name = "bumpalo" |
130 | version = "3.12.1" | 130 | version = "3.13.0" |
131 | source = "registry+https://github.com/rust-lang/crates.io-index" | 131 | source = "registry+https://github.com/rust-lang/crates.io-index" |
132 | checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" | 132 | checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" |
133 | 133 | ||
134 | [[package]] | 134 | [[package]] |
135 | name = "bytes" | 135 | name = "bytes" |
@@ -166,9 +166,9 @@ dependencies = [ | |||
166 | 166 | ||
167 | [[package]] | 167 | [[package]] |
168 | name = "clap" | 168 | name = "clap" |
169 | version = "4.2.4" | 169 | version = "4.3.0" |
170 | source = "registry+https://github.com/rust-lang/crates.io-index" | 170 | source = "registry+https://github.com/rust-lang/crates.io-index" |
171 | checksum = "956ac1f6381d8d82ab4684768f89c0ea3afe66925ceadb4eeb3fc452ffc55d62" | 171 | checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc" |
172 | dependencies = [ | 172 | dependencies = [ |
173 | "clap_builder", | 173 | "clap_builder", |
174 | "clap_derive", | 174 | "clap_derive", |
@@ -177,9 +177,9 @@ dependencies = [ | |||
177 | 177 | ||
178 | [[package]] | 178 | [[package]] |
179 | name = "clap_builder" | 179 | name = "clap_builder" |
180 | version = "4.2.4" | 180 | version = "4.3.0" |
181 | source = "registry+https://github.com/rust-lang/crates.io-index" | 181 | source = "registry+https://github.com/rust-lang/crates.io-index" |
182 | checksum = "84080e799e54cff944f4b4a4b0e71630b0e0443b25b985175c7dddc1a859b749" | 182 | checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990" |
183 | dependencies = [ | 183 | dependencies = [ |
184 | "anstream", | 184 | "anstream", |
185 | "anstyle", | 185 | "anstyle", |
@@ -190,40 +190,30 @@ dependencies = [ | |||
190 | 190 | ||
191 | [[package]] | 191 | [[package]] |
192 | name = "clap_complete" | 192 | name = "clap_complete" |
193 | version = "4.2.1" | 193 | version = "4.3.0" |
194 | source = "registry+https://github.com/rust-lang/crates.io-index" | 194 | source = "registry+https://github.com/rust-lang/crates.io-index" |
195 | checksum = "1a19591b2ab0e3c04b588a0e04ddde7b9eaa423646d1b4a8092879216bf47473" | 195 | checksum = "a04ddfaacc3bc9e6ea67d024575fafc2a813027cf374b8f24f7bc233c6b6be12" |
196 | dependencies = [ | 196 | dependencies = [ |
197 | "clap", | 197 | "clap", |
198 | ] | 198 | ] |
199 | 199 | ||
200 | [[package]] | 200 | [[package]] |
201 | name = "clap_derive" | 201 | name = "clap_derive" |
202 | version = "4.2.0" | 202 | version = "4.3.0" |
203 | source = "registry+https://github.com/rust-lang/crates.io-index" | 203 | source = "registry+https://github.com/rust-lang/crates.io-index" |
204 | checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" | 204 | checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b" |
205 | dependencies = [ | 205 | dependencies = [ |
206 | "heck", | 206 | "heck", |
207 | "proc-macro2", | 207 | "proc-macro2", |
208 | "quote", | 208 | "quote", |
209 | "syn 2.0.15", | 209 | "syn", |
210 | ] | 210 | ] |
211 | 211 | ||
212 | [[package]] | 212 | [[package]] |
213 | name = "clap_lex" | 213 | name = "clap_lex" |
214 | version = "0.4.1" | 214 | version = "0.5.0" |
215 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
216 | checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" | ||
217 | |||
218 | [[package]] | ||
219 | name = "codespan-reporting" | ||
220 | version = "0.11.1" | ||
221 | source = "registry+https://github.com/rust-lang/crates.io-index" | 215 | source = "registry+https://github.com/rust-lang/crates.io-index" |
222 | checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" | 216 | checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" |
223 | dependencies = [ | ||
224 | "termcolor", | ||
225 | "unicode-width", | ||
226 | ] | ||
227 | 217 | ||
228 | [[package]] | 218 | [[package]] |
229 | name = "colorchoice" | 219 | name = "colorchoice" |
@@ -232,6 +222,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
232 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" | 222 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" |
233 | 223 | ||
234 | [[package]] | 224 | [[package]] |
225 | name = "console" | ||
226 | version = "0.15.7" | ||
227 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
228 | checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" | ||
229 | dependencies = [ | ||
230 | "encode_unicode", | ||
231 | "lazy_static", | ||
232 | "libc", | ||
233 | "unicode-width", | ||
234 | "windows-sys 0.45.0", | ||
235 | ] | ||
236 | |||
237 | [[package]] | ||
235 | name = "core-foundation" | 238 | name = "core-foundation" |
236 | version = "0.9.3" | 239 | version = "0.9.3" |
237 | source = "registry+https://github.com/rust-lang/crates.io-index" | 240 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -248,70 +251,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
248 | checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" | 251 | checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" |
249 | 252 | ||
250 | [[package]] | 253 | [[package]] |
251 | name = "cxx" | ||
252 | version = "1.0.94" | ||
253 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
254 | checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" | ||
255 | dependencies = [ | ||
256 | "cc", | ||
257 | "cxxbridge-flags", | ||
258 | "cxxbridge-macro", | ||
259 | "link-cplusplus", | ||
260 | ] | ||
261 | |||
262 | [[package]] | ||
263 | name = "cxx-build" | ||
264 | version = "1.0.94" | ||
265 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
266 | checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" | ||
267 | dependencies = [ | ||
268 | "cc", | ||
269 | "codespan-reporting", | ||
270 | "once_cell", | ||
271 | "proc-macro2", | ||
272 | "quote", | ||
273 | "scratch", | ||
274 | "syn 2.0.15", | ||
275 | ] | ||
276 | |||
277 | [[package]] | ||
278 | name = "cxxbridge-flags" | ||
279 | version = "1.0.94" | ||
280 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
281 | checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" | ||
282 | |||
283 | [[package]] | ||
284 | name = "cxxbridge-macro" | ||
285 | version = "1.0.94" | ||
286 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
287 | checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" | ||
288 | dependencies = [ | ||
289 | "proc-macro2", | ||
290 | "quote", | ||
291 | "syn 2.0.15", | ||
292 | ] | ||
293 | |||
294 | [[package]] | ||
295 | name = "dirs" | 254 | name = "dirs" |
296 | version = "5.0.0" | 255 | version = "5.0.1" |
297 | source = "registry+https://github.com/rust-lang/crates.io-index" | 256 | source = "registry+https://github.com/rust-lang/crates.io-index" |
298 | checksum = "dece029acd3353e3a58ac2e3eb3c8d6c35827a892edc6cc4138ef9c33df46ecd" | 257 | checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" |
299 | dependencies = [ | 258 | dependencies = [ |
300 | "dirs-sys", | 259 | "dirs-sys", |
301 | ] | 260 | ] |
302 | 261 | ||
303 | [[package]] | 262 | [[package]] |
304 | name = "dirs-sys" | 263 | name = "dirs-sys" |
305 | version = "0.4.0" | 264 | version = "0.4.1" |
306 | source = "registry+https://github.com/rust-lang/crates.io-index" | 265 | source = "registry+https://github.com/rust-lang/crates.io-index" |
307 | checksum = "04414300db88f70d74c5ff54e50f9e1d1737d9a5b90f53fcf2e95ca2a9ab554b" | 266 | checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" |
308 | dependencies = [ | 267 | dependencies = [ |
309 | "libc", | 268 | "libc", |
269 | "option-ext", | ||
310 | "redox_users", | 270 | "redox_users", |
311 | "windows-sys 0.45.0", | 271 | "windows-sys 0.48.0", |
312 | ] | 272 | ] |
313 | 273 | ||
314 | [[package]] | 274 | [[package]] |
275 | name = "encode_unicode" | ||
276 | version = "0.3.6" | ||
277 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
278 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" | ||
279 | |||
280 | [[package]] | ||
315 | name = "encoding_rs" | 281 | name = "encoding_rs" |
316 | version = "0.8.32" | 282 | version = "0.8.32" |
317 | source = "registry+https://github.com/rust-lang/crates.io-index" | 283 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -431,7 +397,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" | |||
431 | dependencies = [ | 397 | dependencies = [ |
432 | "proc-macro2", | 398 | "proc-macro2", |
433 | "quote", | 399 | "quote", |
434 | "syn 2.0.15", | 400 | "syn", |
435 | ] | 401 | ] |
436 | 402 | ||
437 | [[package]] | 403 | [[package]] |
@@ -482,9 +448,9 @@ checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" | |||
482 | 448 | ||
483 | [[package]] | 449 | [[package]] |
484 | name = "h2" | 450 | name = "h2" |
485 | version = "0.3.18" | 451 | version = "0.3.19" |
486 | source = "registry+https://github.com/rust-lang/crates.io-index" | 452 | source = "registry+https://github.com/rust-lang/crates.io-index" |
487 | checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21" | 453 | checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" |
488 | dependencies = [ | 454 | dependencies = [ |
489 | "bytes", | 455 | "bytes", |
490 | "fnv", | 456 | "fnv", |
@@ -504,17 +470,23 @@ name = "hashbrown" | |||
504 | version = "0.12.3" | 470 | version = "0.12.3" |
505 | source = "registry+https://github.com/rust-lang/crates.io-index" | 471 | source = "registry+https://github.com/rust-lang/crates.io-index" |
506 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" | 472 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" |
473 | |||
474 | [[package]] | ||
475 | name = "hashbrown" | ||
476 | version = "0.13.2" | ||
477 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
478 | checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" | ||
507 | dependencies = [ | 479 | dependencies = [ |
508 | "ahash", | 480 | "ahash", |
509 | ] | 481 | ] |
510 | 482 | ||
511 | [[package]] | 483 | [[package]] |
512 | name = "hashlink" | 484 | name = "hashlink" |
513 | version = "0.8.1" | 485 | version = "0.8.2" |
514 | source = "registry+https://github.com/rust-lang/crates.io-index" | 486 | source = "registry+https://github.com/rust-lang/crates.io-index" |
515 | checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" | 487 | checksum = "0761a1b9491c4f2e3d66aa0f62d0fba0af9a0e2852e4d48ea506632a4b56e6aa" |
516 | dependencies = [ | 488 | dependencies = [ |
517 | "hashbrown", | 489 | "hashbrown 0.13.2", |
518 | ] | 490 | ] |
519 | 491 | ||
520 | [[package]] | 492 | [[package]] |
@@ -625,12 +597,11 @@ dependencies = [ | |||
625 | 597 | ||
626 | [[package]] | 598 | [[package]] |
627 | name = "iana-time-zone-haiku" | 599 | name = "iana-time-zone-haiku" |
628 | version = "0.1.1" | 600 | version = "0.1.2" |
629 | source = "registry+https://github.com/rust-lang/crates.io-index" | 601 | source = "registry+https://github.com/rust-lang/crates.io-index" |
630 | checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" | 602 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" |
631 | dependencies = [ | 603 | dependencies = [ |
632 | "cxx", | 604 | "cc", |
633 | "cxx-build", | ||
634 | ] | 605 | ] |
635 | 606 | ||
636 | [[package]] | 607 | [[package]] |
@@ -650,7 +621,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
650 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" | 621 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" |
651 | dependencies = [ | 622 | dependencies = [ |
652 | "autocfg", | 623 | "autocfg", |
653 | "hashbrown", | 624 | "hashbrown 0.12.3", |
625 | ] | ||
626 | |||
627 | [[package]] | ||
628 | name = "indicatif" | ||
629 | version = "0.17.3" | ||
630 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
631 | checksum = "cef509aa9bc73864d6756f0d34d35504af3cf0844373afe9b8669a5b8005a729" | ||
632 | dependencies = [ | ||
633 | "console", | ||
634 | "number_prefix", | ||
635 | "portable-atomic 0.3.20", | ||
636 | "unicode-width", | ||
654 | ] | 637 | ] |
655 | 638 | ||
656 | [[package]] | 639 | [[package]] |
@@ -664,9 +647,9 @@ dependencies = [ | |||
664 | 647 | ||
665 | [[package]] | 648 | [[package]] |
666 | name = "io-lifetimes" | 649 | name = "io-lifetimes" |
667 | version = "1.0.10" | 650 | version = "1.0.11" |
668 | source = "registry+https://github.com/rust-lang/crates.io-index" | 651 | source = "registry+https://github.com/rust-lang/crates.io-index" |
669 | checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" | 652 | checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" |
670 | dependencies = [ | 653 | dependencies = [ |
671 | "hermit-abi 0.3.1", | 654 | "hermit-abi 0.3.1", |
672 | "libc", | 655 | "libc", |
@@ -699,9 +682,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" | |||
699 | 682 | ||
700 | [[package]] | 683 | [[package]] |
701 | name = "js-sys" | 684 | name = "js-sys" |
702 | version = "0.3.61" | 685 | version = "0.3.63" |
703 | source = "registry+https://github.com/rust-lang/crates.io-index" | 686 | source = "registry+https://github.com/rust-lang/crates.io-index" |
704 | checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" | 687 | checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" |
705 | dependencies = [ | 688 | dependencies = [ |
706 | "wasm-bindgen", | 689 | "wasm-bindgen", |
707 | ] | 690 | ] |
@@ -714,9 +697,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | |||
714 | 697 | ||
715 | [[package]] | 698 | [[package]] |
716 | name = "libc" | 699 | name = "libc" |
717 | version = "0.2.142" | 700 | version = "0.2.144" |
718 | source = "registry+https://github.com/rust-lang/crates.io-index" | 701 | source = "registry+https://github.com/rust-lang/crates.io-index" |
719 | checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" | 702 | checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" |
720 | 703 | ||
721 | [[package]] | 704 | [[package]] |
722 | name = "libsqlite3-sys" | 705 | name = "libsqlite3-sys" |
@@ -730,19 +713,10 @@ dependencies = [ | |||
730 | ] | 713 | ] |
731 | 714 | ||
732 | [[package]] | 715 | [[package]] |
733 | name = "link-cplusplus" | ||
734 | version = "1.0.8" | ||
735 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
736 | checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" | ||
737 | dependencies = [ | ||
738 | "cc", | ||
739 | ] | ||
740 | |||
741 | [[package]] | ||
742 | name = "linux-raw-sys" | 716 | name = "linux-raw-sys" |
743 | version = "0.3.4" | 717 | version = "0.3.8" |
744 | source = "registry+https://github.com/rust-lang/crates.io-index" | 718 | source = "registry+https://github.com/rust-lang/crates.io-index" |
745 | checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf" | 719 | checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" |
746 | 720 | ||
747 | [[package]] | 721 | [[package]] |
748 | name = "lock_api" | 722 | name = "lock_api" |
@@ -798,7 +772,7 @@ dependencies = [ | |||
798 | 772 | ||
799 | [[package]] | 773 | [[package]] |
800 | name = "modlist" | 774 | name = "modlist" |
801 | version = "0.14.2" | 775 | version = "0.15.0" |
802 | dependencies = [ | 776 | dependencies = [ |
803 | "chrono", | 777 | "chrono", |
804 | "clap", | 778 | "clap", |
@@ -806,6 +780,7 @@ dependencies = [ | |||
806 | "dirs", | 780 | "dirs", |
807 | "error-chain", | 781 | "error-chain", |
808 | "futures-util", | 782 | "futures-util", |
783 | "indicatif", | ||
809 | "reqwest", | 784 | "reqwest", |
810 | "rusqlite", | 785 | "rusqlite", |
811 | "serde", | 786 | "serde", |
@@ -862,6 +837,12 @@ dependencies = [ | |||
862 | ] | 837 | ] |
863 | 838 | ||
864 | [[package]] | 839 | [[package]] |
840 | name = "number_prefix" | ||
841 | version = "0.4.0" | ||
842 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
843 | checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" | ||
844 | |||
845 | [[package]] | ||
865 | name = "object" | 846 | name = "object" |
866 | version = "0.30.3" | 847 | version = "0.30.3" |
867 | source = "registry+https://github.com/rust-lang/crates.io-index" | 848 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -899,7 +880,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" | |||
899 | dependencies = [ | 880 | dependencies = [ |
900 | "proc-macro2", | 881 | "proc-macro2", |
901 | "quote", | 882 | "quote", |
902 | "syn 2.0.15", | 883 | "syn", |
903 | ] | 884 | ] |
904 | 885 | ||
905 | [[package]] | 886 | [[package]] |
@@ -921,6 +902,12 @@ dependencies = [ | |||
921 | ] | 902 | ] |
922 | 903 | ||
923 | [[package]] | 904 | [[package]] |
905 | name = "option-ext" | ||
906 | version = "0.2.0" | ||
907 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
908 | checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" | ||
909 | |||
910 | [[package]] | ||
924 | name = "parking_lot" | 911 | name = "parking_lot" |
925 | version = "0.12.1" | 912 | version = "0.12.1" |
926 | source = "registry+https://github.com/rust-lang/crates.io-index" | 913 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -963,24 +950,39 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" | |||
963 | 950 | ||
964 | [[package]] | 951 | [[package]] |
965 | name = "pkg-config" | 952 | name = "pkg-config" |
966 | version = "0.3.26" | 953 | version = "0.3.27" |
967 | source = "registry+https://github.com/rust-lang/crates.io-index" | 954 | source = "registry+https://github.com/rust-lang/crates.io-index" |
968 | checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" | 955 | checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" |
956 | |||
957 | [[package]] | ||
958 | name = "portable-atomic" | ||
959 | version = "0.3.20" | ||
960 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
961 | checksum = "e30165d31df606f5726b090ec7592c308a0eaf61721ff64c9a3018e344a8753e" | ||
962 | dependencies = [ | ||
963 | "portable-atomic 1.3.2", | ||
964 | ] | ||
965 | |||
966 | [[package]] | ||
967 | name = "portable-atomic" | ||
968 | version = "1.3.2" | ||
969 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
970 | checksum = "dc59d1bcc64fc5d021d67521f818db868368028108d37f0e98d74e33f68297b5" | ||
969 | 971 | ||
970 | [[package]] | 972 | [[package]] |
971 | name = "proc-macro2" | 973 | name = "proc-macro2" |
972 | version = "1.0.56" | 974 | version = "1.0.59" |
973 | source = "registry+https://github.com/rust-lang/crates.io-index" | 975 | source = "registry+https://github.com/rust-lang/crates.io-index" |
974 | checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" | 976 | checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" |
975 | dependencies = [ | 977 | dependencies = [ |
976 | "unicode-ident", | 978 | "unicode-ident", |
977 | ] | 979 | ] |
978 | 980 | ||
979 | [[package]] | 981 | [[package]] |
980 | name = "quote" | 982 | name = "quote" |
981 | version = "1.0.26" | 983 | version = "1.0.28" |
982 | source = "registry+https://github.com/rust-lang/crates.io-index" | 984 | source = "registry+https://github.com/rust-lang/crates.io-index" |
983 | checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" | 985 | checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" |
984 | dependencies = [ | 986 | dependencies = [ |
985 | "proc-macro2", | 987 | "proc-macro2", |
986 | ] | 988 | ] |
@@ -1016,9 +1018,9 @@ dependencies = [ | |||
1016 | 1018 | ||
1017 | [[package]] | 1019 | [[package]] |
1018 | name = "reqwest" | 1020 | name = "reqwest" |
1019 | version = "0.11.16" | 1021 | version = "0.11.18" |
1020 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1021 | checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" | 1023 | checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" |
1022 | dependencies = [ | 1024 | dependencies = [ |
1023 | "base64", | 1025 | "base64", |
1024 | "bytes", | 1026 | "bytes", |
@@ -1059,7 +1061,7 @@ version = "0.29.0" | |||
1059 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1061 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1060 | checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" | 1062 | checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" |
1061 | dependencies = [ | 1063 | dependencies = [ |
1062 | "bitflags 2.2.1", | 1064 | "bitflags 2.3.1", |
1063 | "fallible-iterator", | 1065 | "fallible-iterator", |
1064 | "fallible-streaming-iterator", | 1066 | "fallible-streaming-iterator", |
1065 | "hashlink", | 1067 | "hashlink", |
@@ -1075,9 +1077,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" | |||
1075 | 1077 | ||
1076 | [[package]] | 1078 | [[package]] |
1077 | name = "rustix" | 1079 | name = "rustix" |
1078 | version = "0.37.15" | 1080 | version = "0.37.19" |
1079 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1080 | checksum = "a0661814f891c57c930a610266415528da53c4933e6dea5fb350cbfe048a9ece" | 1082 | checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" |
1081 | dependencies = [ | 1083 | dependencies = [ |
1082 | "bitflags 1.3.2", | 1084 | "bitflags 1.3.2", |
1083 | "errno", | 1085 | "errno", |
@@ -1109,16 +1111,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1109 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" | 1111 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" |
1110 | 1112 | ||
1111 | [[package]] | 1113 | [[package]] |
1112 | name = "scratch" | ||
1113 | version = "1.0.5" | ||
1114 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1115 | checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" | ||
1116 | |||
1117 | [[package]] | ||
1118 | name = "security-framework" | 1114 | name = "security-framework" |
1119 | version = "2.8.2" | 1115 | version = "2.9.1" |
1120 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1116 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1121 | checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" | 1117 | checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" |
1122 | dependencies = [ | 1118 | dependencies = [ |
1123 | "bitflags 1.3.2", | 1119 | "bitflags 1.3.2", |
1124 | "core-foundation", | 1120 | "core-foundation", |
@@ -1129,9 +1125,9 @@ dependencies = [ | |||
1129 | 1125 | ||
1130 | [[package]] | 1126 | [[package]] |
1131 | name = "security-framework-sys" | 1127 | name = "security-framework-sys" |
1132 | version = "2.8.0" | 1128 | version = "2.9.0" |
1133 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1129 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1134 | checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" | 1130 | checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" |
1135 | dependencies = [ | 1131 | dependencies = [ |
1136 | "core-foundation-sys", | 1132 | "core-foundation-sys", |
1137 | "libc", | 1133 | "libc", |
@@ -1139,22 +1135,22 @@ dependencies = [ | |||
1139 | 1135 | ||
1140 | [[package]] | 1136 | [[package]] |
1141 | name = "serde" | 1137 | name = "serde" |
1142 | version = "1.0.160" | 1138 | version = "1.0.163" |
1143 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1139 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1144 | checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" | 1140 | checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" |
1145 | dependencies = [ | 1141 | dependencies = [ |
1146 | "serde_derive", | 1142 | "serde_derive", |
1147 | ] | 1143 | ] |
1148 | 1144 | ||
1149 | [[package]] | 1145 | [[package]] |
1150 | name = "serde_derive" | 1146 | name = "serde_derive" |
1151 | version = "1.0.160" | 1147 | version = "1.0.163" |
1152 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1148 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1153 | checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" | 1149 | checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" |
1154 | dependencies = [ | 1150 | dependencies = [ |
1155 | "proc-macro2", | 1151 | "proc-macro2", |
1156 | "quote", | 1152 | "quote", |
1157 | "syn 2.0.15", | 1153 | "syn", |
1158 | ] | 1154 | ] |
1159 | 1155 | ||
1160 | [[package]] | 1156 | [[package]] |
@@ -1170,9 +1166,9 @@ dependencies = [ | |||
1170 | 1166 | ||
1171 | [[package]] | 1167 | [[package]] |
1172 | name = "serde_spanned" | 1168 | name = "serde_spanned" |
1173 | version = "0.6.1" | 1169 | version = "0.6.2" |
1174 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1170 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1175 | checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" | 1171 | checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d" |
1176 | dependencies = [ | 1172 | dependencies = [ |
1177 | "serde", | 1173 | "serde", |
1178 | ] | 1174 | ] |
@@ -1231,20 +1227,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" | |||
1231 | 1227 | ||
1232 | [[package]] | 1228 | [[package]] |
1233 | name = "syn" | 1229 | name = "syn" |
1234 | version = "1.0.109" | 1230 | version = "2.0.17" |
1235 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1231 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1236 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" | 1232 | checksum = "45b6ddbb36c5b969c182aec3c4a0bce7df3fbad4b77114706a49aacc80567388" |
1237 | dependencies = [ | ||
1238 | "proc-macro2", | ||
1239 | "quote", | ||
1240 | "unicode-ident", | ||
1241 | ] | ||
1242 | |||
1243 | [[package]] | ||
1244 | name = "syn" | ||
1245 | version = "2.0.15" | ||
1246 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1247 | checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" | ||
1248 | dependencies = [ | 1233 | dependencies = [ |
1249 | "proc-macro2", | 1234 | "proc-macro2", |
1250 | "quote", | 1235 | "quote", |
@@ -1265,15 +1250,6 @@ dependencies = [ | |||
1265 | ] | 1250 | ] |
1266 | 1251 | ||
1267 | [[package]] | 1252 | [[package]] |
1268 | name = "termcolor" | ||
1269 | version = "1.2.0" | ||
1270 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1271 | checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" | ||
1272 | dependencies = [ | ||
1273 | "winapi-util", | ||
1274 | ] | ||
1275 | |||
1276 | [[package]] | ||
1277 | name = "thiserror" | 1253 | name = "thiserror" |
1278 | version = "1.0.40" | 1254 | version = "1.0.40" |
1279 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1255 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1290,7 +1266,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" | |||
1290 | dependencies = [ | 1266 | dependencies = [ |
1291 | "proc-macro2", | 1267 | "proc-macro2", |
1292 | "quote", | 1268 | "quote", |
1293 | "syn 2.0.15", | 1269 | "syn", |
1294 | ] | 1270 | ] |
1295 | 1271 | ||
1296 | [[package]] | 1272 | [[package]] |
@@ -1321,9 +1297,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" | |||
1321 | 1297 | ||
1322 | [[package]] | 1298 | [[package]] |
1323 | name = "tokio" | 1299 | name = "tokio" |
1324 | version = "1.28.0" | 1300 | version = "1.28.1" |
1325 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1301 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1326 | checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f" | 1302 | checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" |
1327 | dependencies = [ | 1303 | dependencies = [ |
1328 | "autocfg", | 1304 | "autocfg", |
1329 | "bytes", | 1305 | "bytes", |
@@ -1346,7 +1322,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" | |||
1346 | dependencies = [ | 1322 | dependencies = [ |
1347 | "proc-macro2", | 1323 | "proc-macro2", |
1348 | "quote", | 1324 | "quote", |
1349 | "syn 2.0.15", | 1325 | "syn", |
1350 | ] | 1326 | ] |
1351 | 1327 | ||
1352 | [[package]] | 1328 | [[package]] |
@@ -1375,9 +1351,9 @@ dependencies = [ | |||
1375 | 1351 | ||
1376 | [[package]] | 1352 | [[package]] |
1377 | name = "toml" | 1353 | name = "toml" |
1378 | version = "0.7.3" | 1354 | version = "0.7.4" |
1379 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1355 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1380 | checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" | 1356 | checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec" |
1381 | dependencies = [ | 1357 | dependencies = [ |
1382 | "serde", | 1358 | "serde", |
1383 | "serde_spanned", | 1359 | "serde_spanned", |
@@ -1387,18 +1363,18 @@ dependencies = [ | |||
1387 | 1363 | ||
1388 | [[package]] | 1364 | [[package]] |
1389 | name = "toml_datetime" | 1365 | name = "toml_datetime" |
1390 | version = "0.6.1" | 1366 | version = "0.6.2" |
1391 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1367 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1392 | checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" | 1368 | checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" |
1393 | dependencies = [ | 1369 | dependencies = [ |
1394 | "serde", | 1370 | "serde", |
1395 | ] | 1371 | ] |
1396 | 1372 | ||
1397 | [[package]] | 1373 | [[package]] |
1398 | name = "toml_edit" | 1374 | name = "toml_edit" |
1399 | version = "0.19.8" | 1375 | version = "0.19.10" |
1400 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1376 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1401 | checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" | 1377 | checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" |
1402 | dependencies = [ | 1378 | dependencies = [ |
1403 | "indexmap", | 1379 | "indexmap", |
1404 | "serde", | 1380 | "serde", |
@@ -1415,19 +1391,20 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" | |||
1415 | 1391 | ||
1416 | [[package]] | 1392 | [[package]] |
1417 | name = "tracing" | 1393 | name = "tracing" |
1418 | version = "0.1.38" | 1394 | version = "0.1.37" |
1419 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1395 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1420 | checksum = "cf9cf6a813d3f40c88b0b6b6f29a5c95c6cdbf97c1f9cc53fb820200f5ad814d" | 1396 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" |
1421 | dependencies = [ | 1397 | dependencies = [ |
1398 | "cfg-if", | ||
1422 | "pin-project-lite", | 1399 | "pin-project-lite", |
1423 | "tracing-core", | 1400 | "tracing-core", |
1424 | ] | 1401 | ] |
1425 | 1402 | ||
1426 | [[package]] | 1403 | [[package]] |
1427 | name = "tracing-core" | 1404 | name = "tracing-core" |
1428 | version = "0.1.30" | 1405 | version = "0.1.31" |
1429 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1406 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1430 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" | 1407 | checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" |
1431 | dependencies = [ | 1408 | dependencies = [ |
1432 | "once_cell", | 1409 | "once_cell", |
1433 | ] | 1410 | ] |
@@ -1446,9 +1423,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" | |||
1446 | 1423 | ||
1447 | [[package]] | 1424 | [[package]] |
1448 | name = "unicode-ident" | 1425 | name = "unicode-ident" |
1449 | version = "1.0.8" | 1426 | version = "1.0.9" |
1450 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1427 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1451 | checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" | 1428 | checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" |
1452 | 1429 | ||
1453 | [[package]] | 1430 | [[package]] |
1454 | name = "unicode-normalization" | 1431 | name = "unicode-normalization" |
@@ -1518,9 +1495,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" | |||
1518 | 1495 | ||
1519 | [[package]] | 1496 | [[package]] |
1520 | name = "wasm-bindgen" | 1497 | name = "wasm-bindgen" |
1521 | version = "0.2.84" | 1498 | version = "0.2.86" |
1522 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1499 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1523 | checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" | 1500 | checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" |
1524 | dependencies = [ | 1501 | dependencies = [ |
1525 | "cfg-if", | 1502 | "cfg-if", |
1526 | "wasm-bindgen-macro", | 1503 | "wasm-bindgen-macro", |
@@ -1528,24 +1505,24 @@ dependencies = [ | |||
1528 | 1505 | ||
1529 | [[package]] | 1506 | [[package]] |
1530 | name = "wasm-bindgen-backend" | 1507 | name = "wasm-bindgen-backend" |
1531 | version = "0.2.84" | 1508 | version = "0.2.86" |
1532 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1509 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1533 | checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" | 1510 | checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" |
1534 | dependencies = [ | 1511 | dependencies = [ |
1535 | "bumpalo", | 1512 | "bumpalo", |
1536 | "log", | 1513 | "log", |
1537 | "once_cell", | 1514 | "once_cell", |
1538 | "proc-macro2", | 1515 | "proc-macro2", |
1539 | "quote", | 1516 | "quote", |
1540 | "syn 1.0.109", | 1517 | "syn", |
1541 | "wasm-bindgen-shared", | 1518 | "wasm-bindgen-shared", |
1542 | ] | 1519 | ] |
1543 | 1520 | ||
1544 | [[package]] | 1521 | [[package]] |
1545 | name = "wasm-bindgen-futures" | 1522 | name = "wasm-bindgen-futures" |
1546 | version = "0.4.34" | 1523 | version = "0.4.36" |
1547 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1524 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1548 | checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" | 1525 | checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" |
1549 | dependencies = [ | 1526 | dependencies = [ |
1550 | "cfg-if", | 1527 | "cfg-if", |
1551 | "js-sys", | 1528 | "js-sys", |
@@ -1555,9 +1532,9 @@ dependencies = [ | |||
1555 | 1532 | ||
1556 | [[package]] | 1533 | [[package]] |
1557 | name = "wasm-bindgen-macro" | 1534 | name = "wasm-bindgen-macro" |
1558 | version = "0.2.84" | 1535 | version = "0.2.86" |
1559 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1536 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1560 | checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" | 1537 | checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" |
1561 | dependencies = [ | 1538 | dependencies = [ |
1562 | "quote", | 1539 | "quote", |
1563 | "wasm-bindgen-macro-support", | 1540 | "wasm-bindgen-macro-support", |
@@ -1565,22 +1542,22 @@ dependencies = [ | |||
1565 | 1542 | ||
1566 | [[package]] | 1543 | [[package]] |
1567 | name = "wasm-bindgen-macro-support" | 1544 | name = "wasm-bindgen-macro-support" |
1568 | version = "0.2.84" | 1545 | version = "0.2.86" |
1569 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1546 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1570 | checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" | 1547 | checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" |
1571 | dependencies = [ | 1548 | dependencies = [ |
1572 | "proc-macro2", | 1549 | "proc-macro2", |
1573 | "quote", | 1550 | "quote", |
1574 | "syn 1.0.109", | 1551 | "syn", |
1575 | "wasm-bindgen-backend", | 1552 | "wasm-bindgen-backend", |
1576 | "wasm-bindgen-shared", | 1553 | "wasm-bindgen-shared", |
1577 | ] | 1554 | ] |
1578 | 1555 | ||
1579 | [[package]] | 1556 | [[package]] |
1580 | name = "wasm-bindgen-shared" | 1557 | name = "wasm-bindgen-shared" |
1581 | version = "0.2.84" | 1558 | version = "0.2.86" |
1582 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1559 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1583 | checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" | 1560 | checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" |
1584 | 1561 | ||
1585 | [[package]] | 1562 | [[package]] |
1586 | name = "wasm-streams" | 1563 | name = "wasm-streams" |
@@ -1597,9 +1574,9 @@ dependencies = [ | |||
1597 | 1574 | ||
1598 | [[package]] | 1575 | [[package]] |
1599 | name = "web-sys" | 1576 | name = "web-sys" |
1600 | version = "0.3.61" | 1577 | version = "0.3.63" |
1601 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1578 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1602 | checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" | 1579 | checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" |
1603 | dependencies = [ | 1580 | dependencies = [ |
1604 | "js-sys", | 1581 | "js-sys", |
1605 | "wasm-bindgen", | 1582 | "wasm-bindgen", |
@@ -1622,15 +1599,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1622 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | 1599 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" |
1623 | 1600 | ||
1624 | [[package]] | 1601 | [[package]] |
1625 | name = "winapi-util" | ||
1626 | version = "0.1.5" | ||
1627 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1628 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" | ||
1629 | dependencies = [ | ||
1630 | "winapi", | ||
1631 | ] | ||
1632 | |||
1633 | [[package]] | ||
1634 | name = "winapi-x86_64-pc-windows-gnu" | 1602 | name = "winapi-x86_64-pc-windows-gnu" |
1635 | version = "0.4.0" | 1603 | version = "0.4.0" |
1636 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1604 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1794,9 +1762,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" | |||
1794 | 1762 | ||
1795 | [[package]] | 1763 | [[package]] |
1796 | name = "winnow" | 1764 | name = "winnow" |
1797 | version = "0.4.1" | 1765 | version = "0.4.6" |
1798 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1766 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1799 | checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" | 1767 | checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" |
1800 | dependencies = [ | 1768 | dependencies = [ |
1801 | "memchr", | 1769 | "memchr", |
1802 | ] | 1770 | ] |
@@ -1,6 +1,6 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "modlist" | 2 | name = "modlist" |
3 | version = "0.14.2" | 3 | version = "0.15.0" |
4 | edition = "2021" | 4 | edition = "2021" |
5 | 5 | ||
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
@@ -18,3 +18,4 @@ error-chain = "0.12.4" | |||
18 | dirs = "5.0.0" | 18 | dirs = "5.0.0" |
19 | clap = { version = "4.2.1", features = ["derive"] } | 19 | clap = { version = "4.2.1", features = ["derive"] } |
20 | clap_complete = "4.2.0" | 20 | clap_complete = "4.2.0" |
21 | indicatif = "0.17.3" | ||
diff --git a/src/apis/modrinth.rs b/src/apis/modrinth.rs index 525cc0d..9a22633 100644 --- a/src/apis/modrinth.rs +++ b/src/apis/modrinth.rs | |||
@@ -127,10 +127,13 @@ pub enum GameVersionType { | |||
127 | release, | 127 | release, |
128 | snapshot, | 128 | snapshot, |
129 | alpha, | 129 | alpha, |
130 | beta | 130 | beta, |
131 | } | 131 | } |
132 | 132 | ||
133 | async fn get(api: &str, path: &str) -> Result<Option<Vec<u8>>, Box<dyn std::error::Error>> { | 133 | async fn get( |
134 | api: &str, | ||
135 | path: &str, | ||
136 | ) -> Result<Option<Vec<u8>>, Box<dyn std::error::Error>> { | ||
134 | let url = format!(r#"{}{}"#, api, path); | 137 | let url = format!(r#"{}{}"#, api, path); |
135 | 138 | ||
136 | let client = Client::builder() | 139 | let client = Client::builder() |
@@ -170,7 +173,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> { | 173 | pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { |
171 | let url = format!( | 174 | let url = format!( |
172 | r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, | 175 | r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, |
173 | id, list.modloader.to_string(), list.mc_version | 176 | id, list.modloader, list.mc_version |
174 | ); | 177 | ); |
175 | 178 | ||
176 | let data = get(api, &url).await.unwrap(); | 179 | let data = get(api, &url).await.unwrap(); |
@@ -182,7 +185,10 @@ pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { | |||
182 | } | 185 | } |
183 | 186 | ||
184 | ///Get version with the version ids | 187 | ///Get version with the version ids |
185 | pub async fn get_raw_versions(api: &str, versions: Vec<String>) -> Vec<Version> { | 188 | pub async fn get_raw_versions( |
189 | api: &str, | ||
190 | versions: Vec<String>, | ||
191 | ) -> Vec<Version> { | ||
186 | let url = format!(r#"versions?ids=["{}"]"#, versions.join(r#"",""#)); | 192 | let url = format!(r#"versions?ids=["{}"]"#, versions.join(r#"",""#)); |
187 | 193 | ||
188 | let data = get(api, &url).await.unwrap().unwrap(); | 194 | let data = get(api, &url).await.unwrap().unwrap(); |
@@ -208,7 +214,10 @@ pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> { | |||
208 | } | 214 | } |
209 | 215 | ||
210 | pub async fn get_game_versions() -> Vec<GameVersion> { | 216 | pub async fn get_game_versions() -> Vec<GameVersion> { |
211 | let data = get("https://api.modrinth.com/v2/", "tag/game_version").await.unwrap().unwrap(); | 217 | let data = get("https://api.modrinth.com/v2/", "tag/game_version") |
218 | .await | ||
219 | .unwrap() | ||
220 | .unwrap(); | ||
212 | 221 | ||
213 | serde_json::from_slice(&data).unwrap() | 222 | serde_json::from_slice(&data).unwrap() |
214 | } | 223 | } |
diff --git a/src/cache.rs b/src/cache.rs index c928670..8df4d2f 100644 --- a/src/cache.rs +++ b/src/cache.rs | |||
@@ -31,7 +31,7 @@ pub fn get_cached_versions(path: &str) -> HashMap<String, String> { | |||
31 | /// Panics if . | 31 | /// Panics if . |
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 = |
35 | // println!("{:#?}", download); | 35 | format!("{}/{}", download_path, versplit[versplit.len() - 1]); |
36 | copy(version_path, download).unwrap(); | 36 | copy(version_path, download).unwrap(); |
37 | } | 37 | } |
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 | // } | ||
diff --git a/src/config.rs b/src/config.rs index e1049d1..f0eb8f7 100644 --- a/src/config.rs +++ b/src/config.rs | |||
@@ -4,9 +4,12 @@ use std::{ | |||
4 | path::Path, | 4 | path::Path, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use indicatif::{ProgressBar, ProgressStyle}; | ||
7 | use serde::{Deserialize, Serialize}; | 8 | use serde::{Deserialize, Serialize}; |
8 | 9 | ||
9 | use crate::{db::db_setup, error::MLE, Modloader, VersionLevel, check_game_versions}; | 10 | use crate::{ |
11 | check_game_versions, db::db_setup, error::MLE, Modloader, VersionLevel, | ||
12 | }; | ||
10 | 13 | ||
11 | #[derive(Debug, Clone, Serialize, Deserialize)] | 14 | #[derive(Debug, Clone, Serialize, Deserialize)] |
12 | pub struct Cfg { | 15 | pub struct Cfg { |
@@ -31,7 +34,7 @@ pub struct Defaults { | |||
31 | impl Cfg { | 34 | impl Cfg { |
32 | pub async fn init(path: Option<String>) -> MLE<Self> { | 35 | pub async fn init(path: Option<String>) -> MLE<Self> { |
33 | let configfile = match path.clone() { | 36 | let configfile = match path.clone() { |
34 | Some(p) => String::from(p), | 37 | Some(p) => p, |
35 | None => dirs::config_dir() | 38 | None => dirs::config_dir() |
36 | .unwrap() | 39 | .unwrap() |
37 | .join("modlist") | 40 | .join("modlist") |
@@ -43,7 +46,8 @@ impl Cfg { | |||
43 | let mut file = match File::open(&configfile) { | 46 | let mut file = match File::open(&configfile) { |
44 | Ok(file) => file, | 47 | Ok(file) => file, |
45 | Err(err) => { | 48 | Err(err) => { |
46 | if err.kind() == std::io::ErrorKind::NotFound && path.is_none() { | 49 | if err.kind() == std::io::ErrorKind::NotFound && path.is_none() |
50 | { | ||
47 | create_config(&configfile)?; | 51 | create_config(&configfile)?; |
48 | File::open(&configfile)? | 52 | File::open(&configfile)? |
49 | } else { | 53 | } else { |
@@ -71,16 +75,18 @@ impl Cfg { | |||
71 | Err(..) => { | 75 | Err(..) => { |
72 | create_versions_dummy(&versionfile).await?; | 76 | create_versions_dummy(&versionfile).await?; |
73 | check_game_versions(&versionfile, true).await?; | 77 | check_game_versions(&versionfile, true).await?; |
74 | }, | 78 | } |
75 | } | 79 | } |
80 | |||
76 | Ok(config) | 81 | Ok(config) |
77 | } | 82 | } |
78 | } | 83 | } |
79 | 84 | ||
80 | fn create_config(path: &str) -> MLE<()> { | 85 | fn create_config(path: &str) -> MLE<()> { |
81 | print!("No config file found, create default"); | 86 | let p = ProgressBar::new(1); |
82 | //Force flush of stdout, else print! doesn't print instantly | 87 | p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); |
83 | std::io::stdout().flush()?; | 88 | p.set_message("Create default config"); |
89 | |||
84 | let cache_dir = dirs::cache_dir() | 90 | let cache_dir = dirs::cache_dir() |
85 | .unwrap() | 91 | .unwrap() |
86 | .join("modlist") | 92 | .join("modlist") |
@@ -89,10 +95,10 @@ fn create_config(path: &str) -> MLE<()> { | |||
89 | let default_cfg = Cfg { | 95 | let default_cfg = Cfg { |
90 | data: cache_dir.clone(), | 96 | data: cache_dir.clone(), |
91 | cache: format!("{}/cache", cache_dir), | 97 | cache: format!("{}/cache", cache_dir), |
92 | versions: cache_dir.clone(), | 98 | versions: cache_dir, |
93 | defaults: Defaults { | 99 | defaults: Defaults { |
94 | modloader: Modloader::Fabric, | 100 | modloader: Modloader::Fabric, |
95 | version: VersionLevel::Release | 101 | version: VersionLevel::Release, |
96 | }, | 102 | }, |
97 | apis: Apis { | 103 | apis: Apis { |
98 | modrinth: String::from("https://api.modrinth.com/v2/"), | 104 | modrinth: String::from("https://api.modrinth.com/v2/"), |
@@ -101,37 +107,36 @@ fn create_config(path: &str) -> MLE<()> { | |||
101 | create_dir_all(path.split("config.toml").collect::<Vec<&str>>()[0])?; | 107 | create_dir_all(path.split("config.toml").collect::<Vec<&str>>()[0])?; |
102 | let mut file = File::create(path)?; | 108 | let mut file = File::create(path)?; |
103 | file.write_all(toml::to_string(&default_cfg)?.as_bytes())?; | 109 | file.write_all(toml::to_string(&default_cfg)?.as_bytes())?; |
104 | println!(" ✓"); | 110 | p.finish_with_message(format!("Created default config ({})", path)); |
105 | Ok(()) | 111 | Ok(()) |
106 | } | 112 | } |
107 | 113 | ||
108 | fn create_database(path: &str) -> MLE<()> { | 114 | fn create_database(path: &str) -> MLE<()> { |
109 | print!("No database found, create base"); | 115 | let p = ProgressBar::new(1); |
110 | //Force flush of stdout, else print! doesn't print instantly | 116 | p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); |
111 | std::io::stdout().flush()?; | 117 | p.set_message("Create database"); |
112 | 118 | ||
113 | File::create(path)?; | 119 | File::create(path)?; |
114 | db_setup(path)?; | 120 | db_setup(path)?; |
115 | println!(" ✓"); | 121 | p.finish_with_message(format!("Created database ({})", path)); |
116 | Ok(()) | 122 | Ok(()) |
117 | } | 123 | } |
118 | 124 | ||
119 | fn create_cache(path: &str) -> MLE<()> { | 125 | fn create_cache(path: &str) -> MLE<()> { |
120 | print!("No cache direcory found, create one"); | 126 | let p = ProgressBar::new(1); |
121 | //Force flush of stdout, else print! doesn't print instantly | 127 | p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); |
122 | std::io::stdout().flush()?; | 128 | p.set_message("Create cache"); |
123 | 129 | ||
124 | create_dir_all(path)?; | 130 | create_dir_all(path)?; |
125 | println!(" ✓"); | 131 | p.finish_with_message(format!("Created cache ({})", path)); |
126 | Ok(()) | 132 | Ok(()) |
127 | } | 133 | } |
128 | 134 | ||
129 | async fn create_versions_dummy(path: &str) -> MLE<()> { | 135 | async fn create_versions_dummy(path: &str) -> MLE<()> { |
130 | print!("No version file found, create dummy"); | 136 | let p = ProgressBar::new(1); |
131 | //Force flush of stdout, else print! doesn't print instantly | 137 | p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); |
132 | std::io::stdout().flush()?; | 138 | p.set_message("Create version file"); |
133 | |||
134 | File::create(path)?; | 139 | File::create(path)?; |
135 | println!(" ✓"); | 140 | p.finish_with_message(format!("Created version file ({})", path)); |
136 | Ok(()) | 141 | Ok(()) |
137 | } | 142 | } |
@@ -9,7 +9,7 @@ use crate::{ | |||
9 | }; | 9 | }; |
10 | 10 | ||
11 | //MODS | 11 | //MODS |
12 | pub fn mods_insert(config: Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { | 12 | pub fn mods_insert(config: &Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { |
13 | let data = format!("{}/data.db", config.data); | 13 | let data = format!("{}/data.db", config.data); |
14 | let connection = Connection::open(data)?; | 14 | let connection = Connection::open(data)?; |
15 | 15 | ||
@@ -21,7 +21,9 @@ pub fn mods_insert(config: Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { | |||
21 | Ok(()) | 21 | Ok(()) |
22 | } | 22 | } |
23 | 23 | ||
24 | pub fn mods_get_all_ids(config: Cfg) -> Result<Vec<String>, Box<dyn std::error::Error>> { | 24 | pub fn mods_get_all_ids( |
25 | config: &Cfg, | ||
26 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { | ||
25 | let data = format!("{}/data.db", config.data); | 27 | let data = format!("{}/data.db", config.data); |
26 | let connection = Connection::open(data).unwrap(); | 28 | let connection = Connection::open(data).unwrap(); |
27 | 29 | ||
@@ -64,8 +66,10 @@ pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { | |||
64 | } | 66 | } |
65 | //get from id if no slug found | 67 | //get from id if no slug found |
66 | if mod_id.is_empty() { | 68 | if mod_id.is_empty() { |
67 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE id = ?")?; | 69 | let mut stmt = |
68 | let id_iter = stmt.query_map([slug], |row| row.get::<usize, String>(0))?; | 70 | connection.prepare("SELECT id FROM mods WHERE id = ?")?; |
71 | let id_iter = | ||
72 | stmt.query_map([slug], |row| row.get::<usize, String>(0))?; | ||
69 | 73 | ||
70 | for id in id_iter { | 74 | for id in id_iter { |
71 | mod_id = id?; | 75 | mod_id = id?; |
@@ -73,8 +77,10 @@ pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { | |||
73 | } | 77 | } |
74 | //get from title if no id found from slug | 78 | //get from title if no id found from slug |
75 | if mod_id.is_empty() { | 79 | if mod_id.is_empty() { |
76 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE title = ?")?; | 80 | let mut stmt = |
77 | let id_iter = stmt.query_map([slug], |row| row.get::<usize, String>(0))?; | 81 | connection.prepare("SELECT id FROM mods WHERE title = ?")?; |
82 | let id_iter = | ||
83 | stmt.query_map([slug], |row| row.get::<usize, String>(0))?; | ||
78 | 84 | ||
79 | for id in id_iter { | 85 | for id in id_iter { |
80 | mod_id = id?; | 86 | mod_id = id?; |
@@ -93,12 +99,13 @@ pub struct ModInfo { | |||
93 | pub title: String, | 99 | pub title: String, |
94 | } | 100 | } |
95 | 101 | ||
96 | pub fn mods_get_info(config: Cfg, id: &str) -> MLE<ModInfo> { | 102 | pub fn mods_get_info(config: &Cfg, id: &str) -> MLE<ModInfo> { |
97 | let data = format!("{}/data.db", config.data); | 103 | let data = format!("{}/data.db", config.data); |
98 | let connection = Connection::open(data)?; | 104 | let connection = Connection::open(data)?; |
99 | 105 | ||
100 | let mut mod_info: Option<ModInfo> = None; | 106 | let mut mod_info: Option<ModInfo> = None; |
101 | let mut stmt = connection.prepare("SELECT title, slug FROM mods WHERE id = ?")?; | 107 | let mut stmt = |
108 | connection.prepare("SELECT title, slug FROM mods WHERE id = ?")?; | ||
102 | let name_iter = stmt.query_map([id], |row| { | 109 | let name_iter = stmt.query_map([id], |row| { |
103 | Ok(vec![ | 110 | Ok(vec![ |
104 | row.get::<usize, String>(0)?, | 111 | row.get::<usize, String>(0)?, |
@@ -120,9 +127,7 @@ pub fn mods_get_info(config: Cfg, id: &str) -> MLE<ModInfo> { | |||
120 | } | 127 | } |
121 | } | 128 | } |
122 | 129 | ||
123 | pub fn mods_remove(config: Cfg, id: String) -> MLE<()> { | 130 | pub fn mods_remove(config: &Cfg, id: &str) -> MLE<()> { |
124 | println!("Removing mod {} from database", id); | ||
125 | |||
126 | let data = format!("{}/data.db", config.data); | 131 | let data = format!("{}/data.db", config.data); |
127 | let connection = Connection::open(data)?; | 132 | let connection = Connection::open(data)?; |
128 | 133 | ||
@@ -137,7 +142,10 @@ pub struct DBModlistVersions { | |||
137 | pub versions: String, | 142 | pub versions: String, |
138 | } | 143 | } |
139 | 144 | ||
140 | pub fn mods_get_versions(config: Cfg, mods: Vec<String>) -> MLE<Vec<DBModlistVersions>> { | 145 | pub fn mods_get_versions( |
146 | config: &Cfg, | ||
147 | mods: Vec<String>, | ||
148 | ) -> MLE<Vec<DBModlistVersions>> { | ||
141 | let data = format!("{}/data.db", config.data); | 149 | let data = format!("{}/data.db", config.data); |
142 | let connection = Connection::open(data)?; | 150 | let connection = Connection::open(data)?; |
143 | 151 | ||
@@ -155,8 +163,9 @@ pub fn mods_get_versions(config: Cfg, mods: Vec<String>) -> MLE<Vec<DBModlistVer | |||
155 | } | 163 | } |
156 | 164 | ||
157 | let mut versionmaps: Vec<DBModlistVersions> = Vec::new(); | 165 | let mut versionmaps: Vec<DBModlistVersions> = Vec::new(); |
158 | let mut stmt = connection | 166 | let mut stmt = connection.prepare( |
159 | .prepare(format!("SELECT id, versions, title FROM mods {}", wherestr).as_str())?; | 167 | format!("SELECT id, versions, title FROM mods {}", wherestr).as_str(), |
168 | )?; | ||
160 | let id_iter = stmt.query_map([], |row| { | 169 | let id_iter = stmt.query_map([], |row| { |
161 | Ok(vec![ | 170 | Ok(vec![ |
162 | row.get::<usize, String>(0)?, | 171 | row.get::<usize, String>(0)?, |
@@ -167,11 +176,6 @@ pub fn mods_get_versions(config: Cfg, mods: Vec<String>) -> MLE<Vec<DBModlistVer | |||
167 | 176 | ||
168 | for ver in id_iter { | 177 | for ver in id_iter { |
169 | let version = ver?; | 178 | let version = ver?; |
170 | println!( | ||
171 | "\t({}) Get versions from the database", | ||
172 | String::from(&version[2]) | ||
173 | ); | ||
174 | //println!("Found versions {} for mod {}", version[1], version[0]); | ||
175 | versionmaps.push(DBModlistVersions { | 179 | versionmaps.push(DBModlistVersions { |
176 | mod_id: String::from(&version[0]), | 180 | mod_id: String::from(&version[0]), |
177 | versions: String::from(&version[1]), | 181 | versions: String::from(&version[1]), |
@@ -186,7 +190,7 @@ pub fn mods_get_versions(config: Cfg, mods: Vec<String>) -> MLE<Vec<DBModlistVer | |||
186 | 190 | ||
187 | //userlist | 191 | //userlist |
188 | pub fn userlist_insert( | 192 | pub fn userlist_insert( |
189 | config: Cfg, | 193 | config: &Cfg, |
190 | list_id: &str, | 194 | list_id: &str, |
191 | mod_id: &str, | 195 | mod_id: &str, |
192 | current_version: &str, | 196 | current_version: &str, |
@@ -220,26 +224,29 @@ pub fn userlist_insert( | |||
220 | Ok(()) | 224 | Ok(()) |
221 | } | 225 | } |
222 | 226 | ||
223 | pub fn userlist_get_all_ids(config: Cfg, list_id: &str) -> MLE<Vec<String>> { | 227 | pub fn userlist_get_all_ids(config: &Cfg, list_id: &str) -> MLE<Vec<String>> { |
224 | let data = format!("{}/data.db", config.data); | 228 | let data = format!("{}/data.db", config.data); |
225 | let connection = Connection::open(data).unwrap(); | 229 | let connection = Connection::open(data).unwrap(); |
226 | 230 | ||
227 | let mut mod_ids: Vec<String> = Vec::new(); | 231 | let mut mod_ids: Vec<String> = Vec::new(); |
228 | let mut stmt = connection.prepare(format!("SELECT mod_id FROM {}", list_id).as_str())?; | 232 | let mut stmt = connection |
233 | .prepare(format!("SELECT mod_id FROM {}", list_id).as_str())?; | ||
229 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; | 234 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
230 | 235 | ||
231 | for id in id_iter { | 236 | for id in id_iter { |
232 | //println!("Found id {:?}", id.as_ref().unwrap()); | ||
233 | mod_ids.push(id?) | 237 | mod_ids.push(id?) |
234 | } | 238 | } |
235 | 239 | ||
236 | match mod_ids.is_empty() { | 240 | match mod_ids.is_empty() { |
237 | true => Err(MLError::new(ErrorType::DBError, "NO_MODS_USERLIST")), | 241 | true => Err(MLError::new( |
242 | ErrorType::DBError, | ||
243 | &format!("NO_MODS_USERLIST{}", list_id), | ||
244 | )), | ||
238 | false => Ok(mod_ids), | 245 | false => Ok(mod_ids), |
239 | } | 246 | } |
240 | } | 247 | } |
241 | 248 | ||
242 | pub fn userlist_remove(config: Cfg, list_id: &str, mod_id: &str) -> MLE<()> { | 249 | pub fn userlist_remove(config: &Cfg, list_id: &str, mod_id: &str) -> MLE<()> { |
243 | let data = format!("{}/data.db", config.data); | 250 | let data = format!("{}/data.db", config.data); |
244 | let connection = Connection::open(data)?; | 251 | let connection = Connection::open(data)?; |
245 | 252 | ||
@@ -251,7 +258,7 @@ pub fn userlist_remove(config: Cfg, list_id: &str, mod_id: &str) -> MLE<()> { | |||
251 | } | 258 | } |
252 | 259 | ||
253 | pub fn userlist_get_applicable_versions( | 260 | pub fn userlist_get_applicable_versions( |
254 | config: Cfg, | 261 | config: &Cfg, |
255 | list_id: String, | 262 | list_id: String, |
256 | mod_id: String, | 263 | mod_id: String, |
257 | ) -> MLE<String> { | 264 | ) -> MLE<String> { |
@@ -266,7 +273,8 @@ pub fn userlist_get_applicable_versions( | |||
266 | ) | 273 | ) |
267 | .as_str(), | 274 | .as_str(), |
268 | )?; | 275 | )?; |
269 | let ver_iter = stmt.query_map([mod_id], |row| row.get::<usize, String>(0))?; | 276 | let ver_iter = |
277 | stmt.query_map([mod_id], |row| row.get::<usize, String>(0))?; | ||
270 | 278 | ||
271 | for ver in ver_iter { | 279 | for ver in ver_iter { |
272 | version = ver?; | 280 | version = ver?; |
@@ -279,15 +287,16 @@ pub fn userlist_get_applicable_versions( | |||
279 | } | 287 | } |
280 | 288 | ||
281 | pub fn userlist_get_all_applicable_versions_with_mods( | 289 | pub fn userlist_get_all_applicable_versions_with_mods( |
282 | config: Cfg, | 290 | config: &Cfg, |
283 | list_id: String, | 291 | list_id: String, |
284 | ) -> MLE<Vec<(String, String)>> { | 292 | ) -> MLE<Vec<(String, String)>> { |
285 | let data = format!("{}/data.db", config.data); | 293 | let data = format!("{}/data.db", config.data); |
286 | let connection = Connection::open(data)?; | 294 | let connection = Connection::open(data)?; |
287 | 295 | ||
288 | let mut versions: Vec<(String, String)> = Vec::new(); | 296 | let mut versions: Vec<(String, String)> = Vec::new(); |
289 | let mut stmt = connection | 297 | let mut stmt = connection.prepare( |
290 | .prepare(format!("SELECT mod_id, applicable_versions FROM {}", list_id).as_str())?; | 298 | format!("SELECT mod_id, applicable_versions FROM {}", list_id).as_str(), |
299 | )?; | ||
291 | let id_iter = stmt.query_map([], |row| { | 300 | let id_iter = stmt.query_map([], |row| { |
292 | Ok(vec![ | 301 | Ok(vec![ |
293 | row.get::<usize, String>(0)?, | 302 | row.get::<usize, String>(0)?, |
@@ -307,14 +316,21 @@ pub fn userlist_get_all_applicable_versions_with_mods( | |||
307 | Ok(versions) | 316 | Ok(versions) |
308 | } | 317 | } |
309 | 318 | ||
310 | pub fn userlist_get_current_version(config: Cfg, list_id: &str, mod_id: &str) -> MLE<String> { | 319 | pub fn userlist_get_current_version( |
320 | config: &Cfg, | ||
321 | list_id: &str, | ||
322 | mod_id: &str, | ||
323 | ) -> MLE<String> { | ||
311 | let data = format!("{}/data.db", config.data); | 324 | let data = format!("{}/data.db", config.data); |
312 | let connection = Connection::open(data).unwrap(); | 325 | let connection = Connection::open(data).unwrap(); |
313 | 326 | ||
314 | let mut version: String = String::new(); | 327 | let mut version: String = String::new(); |
315 | let mut stmt = connection | 328 | let mut stmt = connection.prepare( |
316 | .prepare(format!("SELECT current_version FROM {} WHERE mod_id = ?", list_id).as_str())?; | 329 | format!("SELECT current_version FROM {} WHERE mod_id = ?", list_id) |
317 | let ver_iter = stmt.query_map([&mod_id], |row| row.get::<usize, String>(0))?; | 330 | .as_str(), |
331 | )?; | ||
332 | let ver_iter = | ||
333 | stmt.query_map([&mod_id], |row| row.get::<usize, String>(0))?; | ||
318 | 334 | ||
319 | for ver in ver_iter { | 335 | for ver in ver_iter { |
320 | version = ver?; | 336 | version = ver?; |
@@ -327,15 +343,15 @@ pub fn userlist_get_current_version(config: Cfg, list_id: &str, mod_id: &str) -> | |||
327 | } | 343 | } |
328 | 344 | ||
329 | pub fn userlist_get_all_current_version_ids( | 345 | pub fn userlist_get_all_current_version_ids( |
330 | config: Cfg, | 346 | config: &Cfg, |
331 | list_id: String, | 347 | list_id: String, |
332 | ) -> MLE<Vec<String>> { | 348 | ) -> MLE<Vec<String>> { |
333 | let data = format!("{}/data.db", config.data); | 349 | let data = format!("{}/data.db", config.data); |
334 | let connection = Connection::open(data)?; | 350 | let connection = Connection::open(data)?; |
335 | 351 | ||
336 | let mut versions: Vec<String> = Vec::new(); | 352 | let mut versions: Vec<String> = Vec::new(); |
337 | let mut stmt = | 353 | let mut stmt = connection |
338 | connection.prepare(format!("SELECT current_version FROM {}", list_id).as_str())?; | 354 | .prepare(format!("SELECT current_version FROM {}", list_id).as_str())?; |
339 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; | 355 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
340 | 356 | ||
341 | for id in id_iter { | 357 | for id in id_iter { |
@@ -343,25 +359,23 @@ pub fn userlist_get_all_current_version_ids( | |||
343 | } | 359 | } |
344 | 360 | ||
345 | if versions.is_empty() { | 361 | if versions.is_empty() { |
346 | return Err(MLError::new( | 362 | return Err(MLError::new(ErrorType::DBError, "NO_MODS_ON_LIST")); |
347 | ErrorType::DBError, | ||
348 | "NO_MODS_ON_LIST", | ||
349 | )); | ||
350 | }; | 363 | }; |
351 | 364 | ||
352 | Ok(versions) | 365 | Ok(versions) |
353 | } | 366 | } |
354 | 367 | ||
355 | pub fn userlist_get_all_current_versions_with_mods( | 368 | pub fn userlist_get_all_current_versions_with_mods( |
356 | config: Cfg, | 369 | config: &Cfg, |
357 | list_id: String, | 370 | list_id: String, |
358 | ) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> { | 371 | ) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> { |
359 | let data = format!("{}/data.db", config.data); | 372 | let data = format!("{}/data.db", config.data); |
360 | let connection = Connection::open(data)?; | 373 | let connection = Connection::open(data)?; |
361 | 374 | ||
362 | let mut versions: Vec<(String, String)> = Vec::new(); | 375 | let mut versions: Vec<(String, String)> = Vec::new(); |
363 | let mut stmt = | 376 | let mut stmt = connection.prepare( |
364 | connection.prepare(format!("SELECT mod_id, current_version FROM {}", list_id).as_str())?; | 377 | format!("SELECT mod_id, current_version FROM {}", list_id).as_str(), |
378 | )?; | ||
365 | let id_iter = stmt.query_map([], |row| { | 379 | let id_iter = stmt.query_map([], |row| { |
366 | Ok(vec![ | 380 | Ok(vec![ |
367 | row.get::<usize, String>(0)?, | 381 | row.get::<usize, String>(0)?, |
@@ -384,14 +398,21 @@ pub fn userlist_get_all_current_versions_with_mods( | |||
384 | Ok(versions) | 398 | Ok(versions) |
385 | } | 399 | } |
386 | 400 | ||
387 | pub fn userlist_get_set_version(config: Cfg, list_id: &str, mod_id: &str) -> MLE<bool> { | 401 | pub fn userlist_get_set_version( |
402 | config: &Cfg, | ||
403 | list_id: &str, | ||
404 | mod_id: &str, | ||
405 | ) -> MLE<bool> { | ||
388 | let data = format!("{}/data.db", config.data); | 406 | let data = format!("{}/data.db", config.data); |
389 | let connection = Connection::open(data).unwrap(); | 407 | let connection = Connection::open(data).unwrap(); |
390 | 408 | ||
391 | let mut set_version: bool = false; | 409 | let mut set_version: bool = false; |
392 | let mut stmt = connection | 410 | let mut stmt = connection.prepare( |
393 | .prepare(format!("SELECT set_version FROM {} WHERE mod_id = ?", list_id).as_str())?; | 411 | format!("SELECT set_version FROM {} WHERE mod_id = ?", list_id) |
394 | let ver_iter = stmt.query_map([&mod_id], |row| row.get::<usize, bool>(0))?; | 412 | .as_str(), |
413 | )?; | ||
414 | let ver_iter = | ||
415 | stmt.query_map([&mod_id], |row| row.get::<usize, bool>(0))?; | ||
395 | 416 | ||
396 | for ver in ver_iter { | 417 | for ver in ver_iter { |
397 | set_version = ver?; | 418 | set_version = ver?; |
@@ -401,7 +422,7 @@ pub fn userlist_get_set_version(config: Cfg, list_id: &str, mod_id: &str) -> MLE | |||
401 | } | 422 | } |
402 | 423 | ||
403 | pub fn userlist_change_versions( | 424 | pub fn userlist_change_versions( |
404 | config: Cfg, | 425 | config: &Cfg, |
405 | list_id: String, | 426 | list_id: String, |
406 | current_version: String, | 427 | current_version: String, |
407 | versions: String, | 428 | versions: String, |
@@ -416,7 +437,7 @@ pub fn userlist_change_versions( | |||
416 | } | 437 | } |
417 | 438 | ||
418 | pub fn userlist_add_disabled_versions( | 439 | pub fn userlist_add_disabled_versions( |
419 | config: Cfg, | 440 | config: &Cfg, |
420 | list_id: String, | 441 | list_id: String, |
421 | disabled_version: String, | 442 | disabled_version: String, |
422 | mod_id: String, | 443 | mod_id: String, |
@@ -424,11 +445,16 @@ pub fn userlist_add_disabled_versions( | |||
424 | let data = format!("{}/data.db", config.data); | 445 | let data = format!("{}/data.db", config.data); |
425 | let connection = Connection::open(data)?; | 446 | let connection = Connection::open(data)?; |
426 | 447 | ||
427 | let currently_disabled_versions = | 448 | let currently_disabled_versions = userlist_get_disabled_versions( |
428 | userlist_get_disabled_versions(config, String::from(&list_id), String::from(&mod_id))?; | 449 | config, |
450 | String::from(&list_id), | ||
451 | String::from(&mod_id), | ||
452 | )?; | ||
429 | let disabled_versions = match currently_disabled_versions == "NONE" { | 453 | let disabled_versions = match currently_disabled_versions == "NONE" { |
430 | true => disabled_version, | 454 | true => disabled_version, |
431 | false => format!("{}|{}", currently_disabled_versions, disabled_version), | 455 | false => { |
456 | format!("{}|{}", currently_disabled_versions, disabled_version) | ||
457 | } | ||
432 | }; | 458 | }; |
433 | 459 | ||
434 | connection.execute( | 460 | connection.execute( |
@@ -442,14 +468,21 @@ pub fn userlist_add_disabled_versions( | |||
442 | Ok(()) | 468 | Ok(()) |
443 | } | 469 | } |
444 | 470 | ||
445 | pub fn userlist_get_disabled_versions(config: Cfg, list_id: String, mod_id: String) -> MLE<String> { | 471 | pub fn userlist_get_disabled_versions( |
472 | config: &Cfg, | ||
473 | list_id: String, | ||
474 | mod_id: String, | ||
475 | ) -> MLE<String> { | ||
446 | let data = format!("{}/data.db", config.data); | 476 | let data = format!("{}/data.db", config.data); |
447 | let connection = Connection::open(data).unwrap(); | 477 | let connection = Connection::open(data).unwrap(); |
448 | 478 | ||
449 | let mut version: String = String::new(); | 479 | let mut version: String = String::new(); |
450 | let mut stmt = connection | 480 | let mut stmt = connection.prepare( |
451 | .prepare(format!("SELECT disabled_versions FROM {} WHERE mod_id = ?", list_id).as_str())?; | 481 | format!("SELECT disabled_versions FROM {} WHERE mod_id = ?", list_id) |
452 | let ver_iter = stmt.query_map([mod_id], |row| row.get::<usize, String>(0))?; | 482 | .as_str(), |
483 | )?; | ||
484 | let ver_iter = | ||
485 | stmt.query_map([mod_id], |row| row.get::<usize, String>(0))?; | ||
453 | 486 | ||
454 | for ver in ver_iter { | 487 | for ver in ver_iter { |
455 | version = ver?; | 488 | version = ver?; |
@@ -462,20 +495,20 @@ pub fn userlist_get_disabled_versions(config: Cfg, list_id: String, mod_id: Stri | |||
462 | } | 495 | } |
463 | 496 | ||
464 | pub fn userlist_get_all_downloads( | 497 | pub fn userlist_get_all_downloads( |
465 | config: Cfg, | 498 | config: &Cfg, |
466 | list_id: String, | 499 | list_id: String, |
467 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { | 500 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { |
468 | let data = format!("{}/data.db", config.data); | 501 | let data = format!("{}/data.db", config.data); |
469 | let connection = Connection::open(data).unwrap(); | 502 | let connection = Connection::open(data).unwrap(); |
470 | 503 | ||
471 | let mut links: Vec<String> = Vec::new(); | 504 | let mut links: Vec<String> = Vec::new(); |
472 | let mut stmt = | 505 | let mut stmt = connection.prepare( |
473 | connection.prepare(format!("SELECT current_download FROM {}", list_id).as_str())?; | 506 | format!("SELECT current_download FROM {}", list_id).as_str(), |
507 | )?; | ||
474 | let link_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; | 508 | let link_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
475 | 509 | ||
476 | for link in link_iter { | 510 | for link in link_iter { |
477 | let l = link?; | 511 | let l = link?; |
478 | println!("Found link {}", String::from(&l)); | ||
479 | links.push(l) | 512 | links.push(l) |
480 | } | 513 | } |
481 | 514 | ||
@@ -492,32 +525,25 @@ pub fn userlist_get_all_downloads( | |||
492 | //lists | 525 | //lists |
493 | ///Inserts into lists table and creates new table | 526 | ///Inserts into lists table and creates new table |
494 | pub fn lists_insert( | 527 | pub fn lists_insert( |
495 | config: Cfg, | 528 | config: &Cfg, |
496 | id: String, | 529 | id: &str, |
497 | mc_version: String, | 530 | mc_version: &str, |
498 | mod_loader: Modloader, | 531 | mod_loader: &Modloader, |
499 | download_folder: String, | 532 | download_folder: &str, |
500 | ) -> MLE<()> { | 533 | ) -> MLE<()> { |
501 | println!("Creating list {}", id); | ||
502 | |||
503 | let data = format!("{}/data.db", config.data); | 534 | let data = format!("{}/data.db", config.data); |
504 | let connection = Connection::open(data)?; | 535 | let connection = Connection::open(data)?; |
505 | 536 | ||
506 | connection.execute( | 537 | connection.execute( |
507 | "INSERT INTO lists VALUES (?1, ?2, ?3, ?4)", | 538 | "INSERT INTO lists VALUES (?1, ?2, ?3, ?4)", |
508 | [ | 539 | [id, mc_version, &mod_loader.to_string(), download_folder], |
509 | id.clone(), | ||
510 | mc_version, | ||
511 | mod_loader.to_string(), | ||
512 | download_folder, | ||
513 | ], | ||
514 | )?; | 540 | )?; |
515 | connection.execute(format!("CREATE TABLE {}( 'mod_id' TEXT, 'current_version' TEXT, 'applicable_versions' BLOB, 'current_download' TEXT, 'disabled_versions' TEXT DEFAULT 'NONE', 'set_version' INTEGER, CONSTRAINT {}_PK PRIMARY KEY (mod_id) )", id, id).as_str(), [])?; | 541 | connection.execute(format!("CREATE TABLE {}( 'mod_id' TEXT, 'current_version' TEXT, 'applicable_versions' BLOB, 'current_download' TEXT, 'disabled_versions' TEXT DEFAULT 'NONE', 'set_version' INTEGER, CONSTRAINT {}_PK PRIMARY KEY (mod_id) )", id, id).as_str(), [])?; |
516 | 542 | ||
517 | Ok(()) | 543 | Ok(()) |
518 | } | 544 | } |
519 | 545 | ||
520 | pub fn lists_remove(config: Cfg, id: String) -> MLE<()> { | 546 | pub fn lists_remove(config: &Cfg, id: &str) -> MLE<()> { |
521 | let data = format!("{}/data.db", config.data); | 547 | let data = format!("{}/data.db", config.data); |
522 | let connection = Connection::open(data)?; | 548 | let connection = Connection::open(data)?; |
523 | 549 | ||
@@ -526,7 +552,7 @@ pub fn lists_remove(config: Cfg, id: String) -> MLE<()> { | |||
526 | Ok(()) | 552 | Ok(()) |
527 | } | 553 | } |
528 | 554 | ||
529 | pub fn lists_get(config: Cfg, list_id: String) -> MLE<List> { | 555 | pub fn lists_get(config: &Cfg, list_id: &str) -> MLE<List> { |
530 | let data = format!("{}/data.db", config.data); | 556 | let data = format!("{}/data.db", config.data); |
531 | let connection = Connection::open(data).unwrap(); | 557 | let connection = Connection::open(data).unwrap(); |
532 | 558 | ||
@@ -536,8 +562,9 @@ pub fn lists_get(config: Cfg, list_id: String) -> MLE<List> { | |||
536 | modloader: Modloader::Fabric, | 562 | modloader: Modloader::Fabric, |
537 | download_folder: String::new(), | 563 | download_folder: String::new(), |
538 | }; | 564 | }; |
539 | let mut stmt = connection | 565 | let mut stmt = connection.prepare( |
540 | .prepare("SELECT mc_version, modloader, download_folder FROM lists WHERE id = ?")?; | 566 | "SELECT mc_version, modloader, download_folder FROM lists WHERE id = ?", |
567 | )?; | ||
541 | 568 | ||
542 | let list_iter = stmt.query_map([&list_id], |row| { | 569 | let list_iter = stmt.query_map([&list_id], |row| { |
543 | Ok(vec![ | 570 | Ok(vec![ |
@@ -550,7 +577,7 @@ pub fn lists_get(config: Cfg, list_id: String) -> MLE<List> { | |||
550 | for l in list_iter { | 577 | for l in list_iter { |
551 | let li = l?; | 578 | let li = l?; |
552 | list = List { | 579 | list = List { |
553 | id: String::from(&list_id), | 580 | id: list_id.to_string(), |
554 | mc_version: String::from(&li[0]), | 581 | mc_version: String::from(&li[0]), |
555 | modloader: Modloader::from(&li[1])?, | 582 | modloader: Modloader::from(&li[1])?, |
556 | download_folder: String::from(&li[2]), | 583 | download_folder: String::from(&li[2]), |
@@ -564,7 +591,7 @@ pub fn lists_get(config: Cfg, list_id: String) -> MLE<List> { | |||
564 | Ok(list) | 591 | Ok(list) |
565 | } | 592 | } |
566 | 593 | ||
567 | pub fn lists_version(config: Cfg, list_id: &str, version: &str) -> MLE<()> { | 594 | pub fn lists_version(config: &Cfg, list_id: &str, version: &str) -> MLE<()> { |
568 | let data = format!("{}/data.db", config.data); | 595 | let data = format!("{}/data.db", config.data); |
569 | let connection = Connection::open(data).unwrap(); | 596 | let connection = Connection::open(data).unwrap(); |
570 | 597 | ||
@@ -575,7 +602,7 @@ pub fn lists_version(config: Cfg, list_id: &str, version: &str) -> MLE<()> { | |||
575 | Ok(()) | 602 | Ok(()) |
576 | } | 603 | } |
577 | 604 | ||
578 | pub fn lists_get_all_ids(config: Cfg) -> MLE<Vec<String>> { | 605 | pub fn lists_get_all_ids(config: &Cfg) -> MLE<Vec<String>> { |
579 | let data = format!("{}/data.db", config.data); | 606 | let data = format!("{}/data.db", config.data); |
580 | let connection = Connection::open(data).unwrap(); | 607 | let connection = Connection::open(data).unwrap(); |
581 | 608 | ||
@@ -594,7 +621,7 @@ pub fn lists_get_all_ids(config: Cfg) -> MLE<Vec<String>> { | |||
594 | } | 621 | } |
595 | 622 | ||
596 | //config | 623 | //config |
597 | pub fn config_change_current_list(config: Cfg, id: String) -> MLE<()> { | 624 | pub fn config_change_current_list(config: &Cfg, id: &str) -> MLE<()> { |
598 | let data = format!("{}/data.db", config.data); | 625 | let data = format!("{}/data.db", config.data); |
599 | let connection = Connection::open(data)?; | 626 | let connection = Connection::open(data)?; |
600 | 627 | ||
@@ -605,12 +632,13 @@ pub fn config_change_current_list(config: Cfg, id: String) -> MLE<()> { | |||
605 | Ok(()) | 632 | Ok(()) |
606 | } | 633 | } |
607 | 634 | ||
608 | pub fn config_get_current_list(config: Cfg) -> MLE<String> { | 635 | pub fn config_get_current_list(config: &Cfg) -> MLE<String> { |
609 | let data = format!("{}/data.db", config.data); | 636 | let data = format!("{}/data.db", config.data); |
610 | let connection = Connection::open(data).unwrap(); | 637 | let connection = Connection::open(data).unwrap(); |
611 | 638 | ||
612 | let mut list_id = String::new(); | 639 | let mut list_id = String::new(); |
613 | let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'current_list'")?; | 640 | let mut stmt = connection |
641 | .prepare("SELECT value FROM user_config WHERE id = 'current_list'")?; | ||
614 | let list_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; | 642 | let list_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
615 | 643 | ||
616 | for list in list_iter { | 644 | for list in list_iter { |
@@ -626,7 +654,7 @@ pub fn config_get_current_list(config: Cfg) -> MLE<String> { | |||
626 | 654 | ||
627 | //SETUP(UPDATES) | 655 | //SETUP(UPDATES) |
628 | pub fn s_userlist_update_download( | 656 | pub fn s_userlist_update_download( |
629 | config: Cfg, | 657 | config: &Cfg, |
630 | list_id: String, | 658 | list_id: String, |
631 | mod_id: String, | 659 | mod_id: String, |
632 | link: String, | 660 | link: String, |
@@ -645,7 +673,9 @@ pub fn s_userlist_update_download( | |||
645 | Ok(()) | 673 | Ok(()) |
646 | } | 674 | } |
647 | 675 | ||
648 | pub fn s_config_create_version(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { | 676 | pub fn s_config_create_version( |
677 | config: &Cfg, | ||
678 | ) -> Result<(), Box<dyn std::error::Error>> { | ||
649 | let data = format!("{}/data.db", config.data); | 679 | let data = format!("{}/data.db", config.data); |
650 | let connection = Connection::open(data)?; | 680 | let connection = Connection::open(data)?; |
651 | 681 | ||
@@ -656,7 +686,10 @@ pub fn s_config_create_version(config: Cfg) -> Result<(), Box<dyn std::error::Er | |||
656 | Ok(()) | 686 | Ok(()) |
657 | } | 687 | } |
658 | 688 | ||
659 | pub fn s_config_update_version(config: Cfg, ver: String) -> Result<(), Box<dyn std::error::Error>> { | 689 | pub fn s_config_update_version( |
690 | config: &Cfg, | ||
691 | ver: String, | ||
692 | ) -> Result<(), Box<dyn std::error::Error>> { | ||
660 | let data = format!("{}/data.db", config.data); | 693 | let data = format!("{}/data.db", config.data); |
661 | let connection = Connection::open(data)?; | 694 | let connection = Connection::open(data)?; |
662 | 695 | ||
@@ -667,12 +700,15 @@ pub fn s_config_update_version(config: Cfg, ver: String) -> Result<(), Box<dyn s | |||
667 | Ok(()) | 700 | Ok(()) |
668 | } | 701 | } |
669 | 702 | ||
670 | pub fn s_config_get_version(config: Cfg) -> Result<String, Box<dyn std::error::Error>> { | 703 | pub fn s_config_get_version( |
704 | config: &Cfg, | ||
705 | ) -> Result<String, Box<dyn std::error::Error>> { | ||
671 | let data = format!("{}/data.db", config.data); | 706 | let data = format!("{}/data.db", config.data); |
672 | let connection = Connection::open(data)?; | 707 | let connection = Connection::open(data)?; |
673 | 708 | ||
674 | let mut version: String = String::new(); | 709 | let mut version: String = String::new(); |
675 | let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'db_version'")?; | 710 | let mut stmt = connection |
711 | .prepare("SELECT value FROM user_config WHERE id = 'db_version'")?; | ||
676 | let ver_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; | 712 | let ver_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
677 | 713 | ||
678 | for ver in ver_iter { | 714 | for ver in ver_iter { |
@@ -689,7 +725,7 @@ pub fn s_config_get_version(config: Cfg) -> Result<String, Box<dyn std::error::E | |||
689 | } | 725 | } |
690 | 726 | ||
691 | pub fn s_insert_column( | 727 | pub fn s_insert_column( |
692 | config: Cfg, | 728 | config: &Cfg, |
693 | table: String, | 729 | table: String, |
694 | column: String, | 730 | column: String, |
695 | c_type: String, | 731 | c_type: String, |
diff --git a/src/error.rs b/src/error.rs index e6afeaa..a2b37a8 100644 --- a/src/error.rs +++ b/src/error.rs | |||
@@ -34,8 +34,12 @@ impl std::error::Error for MLError { | |||
34 | impl fmt::Display for MLError { | 34 | impl fmt::Display for MLError { |
35 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 35 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
36 | match self.etype { | 36 | match self.etype { |
37 | ErrorType::ArgumentError => write!(f, "User input not accepted: {}", self.message), | 37 | ErrorType::ArgumentError => { |
38 | ErrorType::ArgumentCountError => write!(f, "Too many/too few arguments"), | 38 | write!(f, "User input not accepted: {}", self.message) |
39 | } | ||
40 | ErrorType::ArgumentCountError => { | ||
41 | write!(f, "Too many/too few arguments") | ||
42 | } | ||
39 | ErrorType::ConfigError => write!(f, "CONFIG"), | 43 | ErrorType::ConfigError => write!(f, "CONFIG"), |
40 | ErrorType::DBError => write!(f, "Database: {}", self.message), | 44 | ErrorType::DBError => write!(f, "Database: {}", self.message), |
41 | ErrorType::ModError => write!(f, "Mod: {}", self.message), | 45 | ErrorType::ModError => write!(f, "Mod: {}", self.message), |
@@ -106,9 +110,11 @@ impl From<std::io::Error> for MLError { | |||
106 | 110 | ||
107 | impl From<serde_json::error::Error> for MLError { | 111 | impl From<serde_json::error::Error> for MLError { |
108 | fn from(value: serde_json::error::Error) -> Self { | 112 | fn from(value: serde_json::error::Error) -> Self { |
109 | Self { etype: ErrorType::LibJson, message: value.to_string() } | 113 | Self { |
114 | etype: ErrorType::LibJson, | ||
115 | message: value.to_string(), | ||
116 | } | ||
110 | } | 117 | } |
111 | |||
112 | } | 118 | } |
113 | 119 | ||
114 | impl MLError { | 120 | impl MLError { |
diff --git a/src/files.rs b/src/files.rs index a4c128e..3a16c62 100644 --- a/src/files.rs +++ b/src/files.rs | |||
@@ -1,10 +1,13 @@ | |||
1 | use futures_util::StreamExt; | 1 | use futures_util::StreamExt; |
2 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; | ||
2 | use reqwest::Client; | 3 | use reqwest::Client; |
3 | use std::{ | 4 | use std::{ |
5 | cmp::min, | ||
4 | collections::HashMap, | 6 | collections::HashMap, |
5 | fs::{copy, read_dir, remove_file, rename, File}, | 7 | fs::{copy, read_dir, remove_file, rename, File}, |
6 | io::Write, | 8 | io::Write, |
7 | }; | 9 | }; |
10 | use tokio::task::JoinSet; | ||
8 | 11 | ||
9 | use crate::{ | 12 | use crate::{ |
10 | cache::{copy_cached_version, get_cached_versions}, | 13 | cache::{copy_cached_version, get_cached_versions}, |
@@ -12,99 +15,160 @@ use crate::{ | |||
12 | db::{mods_get_info, userlist_add_disabled_versions}, | 15 | db::{mods_get_info, userlist_add_disabled_versions}, |
13 | error::{ErrorType, MLError, MLE}, | 16 | error::{ErrorType, MLError, MLE}, |
14 | modrinth::Version, | 17 | modrinth::Version, |
15 | List, | 18 | List, PROGRESS_CHARS, STYLE_BAR_BYTE, STYLE_BAR_POS, STYLE_SPINNER, |
16 | }; | 19 | }; |
17 | 20 | ||
18 | pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<String> { | 21 | pub async fn download_versions( |
19 | let mut cached = get_cached_versions(&config.cache); | 22 | list: List, |
23 | config: Cfg, | ||
24 | versions: Vec<Version>, | ||
25 | progress: &MultiProgress, | ||
26 | progress_before: &ProgressBar, | ||
27 | ) -> MLE<()> { | ||
28 | let cached = get_cached_versions(&config.cache); | ||
20 | 29 | ||
21 | // println!("{:#?}", cached); | 30 | let mut js = JoinSet::new(); |
22 | 31 | ||
23 | let dl_path = String::from(&list.download_folder); | 32 | let style_spinner = ProgressStyle::with_template(STYLE_SPINNER).unwrap(); |
24 | 33 | ||
25 | println!(" └Download mods to {}", dl_path); | 34 | let all = progress.insert_before( |
35 | progress_before, | ||
36 | ProgressBar::new(versions.len().try_into().unwrap()), | ||
37 | ); | ||
38 | all.set_style( | ||
39 | ProgressStyle::with_template(STYLE_BAR_POS) | ||
40 | .unwrap() | ||
41 | .progress_chars(PROGRESS_CHARS), | ||
42 | ); | ||
43 | all.set_message(format!("✓Downloading {}", list.id)); | ||
26 | 44 | ||
27 | for ver in versions { | 45 | for ver in versions { |
28 | let project_info = mods_get_info(config.clone(), &ver.project_id)?; | 46 | let p = progress.insert_before(&all, ProgressBar::new(1)); |
29 | 47 | p.set_style(style_spinner.clone()); | |
30 | //Check cache if already downloaded | 48 | js.spawn(download_version( |
31 | let c = cached.remove(&ver.id); | 49 | config.clone(), |
32 | if c.is_some() { | 50 | list.clone(), |
33 | print!( | 51 | ver, |
34 | "\t└({})Get version {} from cache", | 52 | cached.clone(), |
35 | project_info.title, ver.id | 53 | p, |
36 | ); | 54 | )); |
37 | //Force flush of stdout, else print! doesn't print instantly | 55 | } |
38 | std::io::stdout().flush()?; | 56 | |
39 | copy_cached_version(&c.unwrap(), &dl_path); | 57 | while js.join_next().await.is_some() { |
40 | println!(" ✓"); | 58 | all.inc(1) |
41 | } else { | 59 | } |
42 | print!("\t└({})Download version {}", project_info.title, ver.id); | 60 | |
43 | //Force flush of stdout, else print! doesn't print instantly | 61 | all.finish_with_message(format!("✓Downloading {}", list.id)); |
44 | std::io::stdout().flush().unwrap(); | 62 | |
45 | let files = ver.files; | 63 | Ok(()) |
46 | let file = match files.clone().into_iter().find(|f| f.primary) { | 64 | } |
47 | Some(f) => f, | 65 | |
48 | None => files[0].clone() | 66 | async fn download_version( |
49 | }; | 67 | config: Cfg, |
50 | let mut splitname: Vec<&str> = file.filename.split('.').collect(); | 68 | list: List, |
51 | let extension = match splitname.pop().ok_or("") { | 69 | version: Version, |
52 | Ok(e) => e, | 70 | mut cached: HashMap<String, String>, |
53 | Err(..) => return Err(MLError::new(ErrorType::Other, "NO_FILE_EXTENSION")), | 71 | progress: ProgressBar, |
54 | }; | 72 | ) -> MLE<()> { |
55 | let filename = format!( | 73 | let project_info = mods_get_info(&config, &version.project_id)?; |
56 | "{}.mr.{}.{}.{}", | 74 | |
57 | splitname.join("."), | 75 | let dl_path = String::from(&list.download_folder); |
58 | ver.project_id, | 76 | |
59 | ver.id, | 77 | progress.set_message(format!("{} - {}", project_info.title, version.id)); |
60 | extension | 78 | |
61 | ); | 79 | let mut cache_msg = ""; |
62 | download_file( | 80 | //Check cache if already downloaded |
63 | file.url, | 81 | let c = cached.remove(&version.id); |
64 | list.clone().download_folder, | 82 | if c.is_some() { |
65 | filename.clone(), | 83 | progress.set_message(format!("Get {} from cache", version.id)); |
66 | ) | 84 | cache_msg = " (cached)"; |
85 | copy_cached_version(&c.unwrap(), &dl_path); | ||
86 | } else { | ||
87 | let files = version.files; | ||
88 | let file = match files.clone().into_iter().find(|f| f.primary) { | ||
89 | Some(f) => f, | ||
90 | None => files[0].clone(), | ||
91 | }; | ||
92 | let mut splitname: Vec<&str> = file.filename.split('.').collect(); | ||
93 | let extension = match splitname.pop().ok_or("") { | ||
94 | Ok(e) => e, | ||
95 | Err(..) => { | ||
96 | return Err(MLError::new(ErrorType::Other, "NO_FILE_EXTENSION")) | ||
97 | } | ||
98 | }; | ||
99 | let filename = format!( | ||
100 | "{}.mr.{}.{}.{}", | ||
101 | splitname.join("."), | ||
102 | version.project_id, | ||
103 | version.id, | ||
104 | extension | ||
105 | ); | ||
106 | |||
107 | download_file(&file.url, &list.download_folder, &filename, &progress) | ||
67 | .await?; | 108 | .await?; |
68 | println!(" ✓"); | 109 | |
69 | //Copy file to cache | 110 | progress.set_message(format!("Copy {} to cache", version.id)); |
70 | print!("\t └Copy to cache"); | 111 | let dl_path_file = format!("{}/{}", list.download_folder, filename); |
71 | //Force flush of stdout, else print! doesn't print instantly | 112 | let cache_path = format!("{}/{}", &config.cache, filename); |
72 | std::io::stdout().flush().unwrap(); | 113 | |
73 | let dl_path_file = format!("{}/{}", list.download_folder, filename); | 114 | copy(dl_path_file, cache_path)?; |
74 | let cache_path = format!("{}/{}", &config.clone().cache, filename); | ||
75 | // println!("{}:{}", dl_path_file, cache_path); | ||
76 | copy(dl_path_file, cache_path)?; | ||
77 | println!(" ✓"); | ||
78 | } | ||
79 | } | 115 | } |
80 | 116 | ||
81 | Ok(dl_path) | 117 | progress.finish_with_message(format!( |
118 | "✓{} - {}{}", | ||
119 | project_info.title, version.id, cache_msg | ||
120 | )); | ||
121 | |||
122 | Ok(()) | ||
82 | } | 123 | } |
83 | 124 | ||
84 | async fn download_file(url: String, path: String, name: String) -> MLE<()> { | 125 | async fn download_file( |
126 | url: &str, | ||
127 | path: &str, | ||
128 | name: &str, | ||
129 | progress: &ProgressBar, | ||
130 | ) -> MLE<()> { | ||
85 | let dl_path_file = format!("{}/{}", path, name); | 131 | let dl_path_file = format!("{}/{}", path, name); |
86 | let res = Client::new().get(String::from(&url)).send().await?; | 132 | let res = Client::new().get(url).send().await?; |
133 | |||
134 | let size = res.content_length().expect("Couldn't get content length"); | ||
135 | |||
136 | let style_bar_byte = ProgressStyle::with_template(STYLE_BAR_BYTE) | ||
137 | .unwrap() | ||
138 | .progress_chars(PROGRESS_CHARS); | ||
139 | |||
140 | progress.set_length(size); | ||
141 | progress.set_style(style_bar_byte); | ||
87 | 142 | ||
88 | // download chunks | 143 | // download chunks |
89 | let mut file = File::create(&dl_path_file)?; | 144 | let mut file = File::create(&dl_path_file)?; |
90 | let mut stream = res.bytes_stream(); | 145 | let mut stream = res.bytes_stream(); |
91 | 146 | ||
147 | let mut downloaded: u64 = 0; | ||
148 | |||
92 | while let Some(item) = stream.next().await { | 149 | while let Some(item) = stream.next().await { |
150 | // progress.inc(1); | ||
93 | let chunk = item?; | 151 | let chunk = item?; |
94 | file.write_all(&chunk)?; | 152 | file.write_all(&chunk)?; |
153 | |||
154 | // Progress bar | ||
155 | let new = min(downloaded + (chunk.len() as u64), size); | ||
156 | downloaded = new; | ||
157 | progress.set_position(new); | ||
158 | |||
159 | // std::thread::sleep(std::time::Duration::from_millis(100)); | ||
95 | } | 160 | } |
96 | 161 | ||
97 | Ok(()) | 162 | Ok(()) |
98 | } | 163 | } |
99 | 164 | ||
100 | pub fn disable_version( | 165 | pub fn disable_version( |
101 | config: Cfg, | 166 | config: &Cfg, |
102 | current_list: List, | 167 | current_list: List, |
103 | versionid: String, | 168 | versionid: String, |
104 | mod_id: String, | 169 | mod_id: String, |
105 | ) -> MLE<()> { | 170 | ) -> MLE<()> { |
106 | //println!("Disabling version {} for mod {}", versionid, mod_id); | 171 | let file = get_file_path(¤t_list, String::from(&versionid))?; |
107 | let file = get_file_path(current_list.clone(), String::from(&versionid))?; | ||
108 | let disabled = format!("{}.disabled", file); | 172 | let disabled = format!("{}.disabled", file); |
109 | 173 | ||
110 | rename(file, disabled)?; | 174 | rename(file, disabled)?; |
@@ -114,7 +178,7 @@ pub fn disable_version( | |||
114 | Ok(()) | 178 | Ok(()) |
115 | } | 179 | } |
116 | 180 | ||
117 | pub fn delete_version(list: List, version: String) -> MLE<()> { | 181 | pub fn delete_version(list: &List, version: String) -> MLE<()> { |
118 | let file = get_file_path(list, version)?; | 182 | let file = get_file_path(list, version)?; |
119 | 183 | ||
120 | remove_file(file)?; | 184 | remove_file(file)?; |
@@ -122,14 +186,16 @@ pub fn delete_version(list: List, version: String) -> MLE<()> { | |||
122 | Ok(()) | 186 | Ok(()) |
123 | } | 187 | } |
124 | 188 | ||
125 | pub fn get_file_path(list: List, versionid: String) -> MLE<String> { | 189 | pub fn get_file_path(list: &List, versionid: String) -> MLE<String> { |
126 | let mut names: HashMap<String, String> = HashMap::new(); | 190 | let mut names: HashMap<String, String> = HashMap::new(); |
127 | for file in read_dir(list.download_folder)? { | 191 | for file in read_dir(&list.download_folder)? { |
128 | let path = file?.path(); | 192 | let path = file?.path(); |
129 | if path.is_file() { | 193 | if path.is_file() { |
130 | let pathstr = match path.to_str().ok_or("") { | 194 | let pathstr = match path.to_str().ok_or("") { |
131 | Ok(s) => s, | 195 | Ok(s) => s, |
132 | Err(..) => return Err(MLError::new(ErrorType::Other, "INVALID_PATH")), | 196 | Err(..) => { |
197 | return Err(MLError::new(ErrorType::Other, "INVALID_PATH")) | ||
198 | } | ||
133 | }; | 199 | }; |
134 | let namesplit: Vec<&str> = pathstr.split('.').collect(); | 200 | let namesplit: Vec<&str> = pathstr.split('.').collect(); |
135 | let ver_id = namesplit[namesplit.len() - 2]; | 201 | let ver_id = namesplit[namesplit.len() - 2]; |
@@ -168,7 +234,6 @@ pub fn get_downloaded_versions(list: List) -> MLE<HashMap<String, String>> { | |||
168 | 234 | ||
169 | pub fn clean_list_dir(list: &List) -> MLE<()> { | 235 | pub fn clean_list_dir(list: &List) -> MLE<()> { |
170 | let dl_path = &list.download_folder; | 236 | let dl_path = &list.download_folder; |
171 | println!(" └Clean directory for: {}", list.id); | ||
172 | for entry in std::fs::read_dir(dl_path)? { | 237 | for entry in std::fs::read_dir(dl_path)? { |
173 | let entry = entry?; | 238 | let entry = entry?; |
174 | std::fs::remove_file(entry.path())?; | 239 | std::fs::remove_file(entry.path())?; |
@@ -6,14 +6,28 @@ pub mod db; | |||
6 | pub mod error; | 6 | pub mod error; |
7 | pub mod files; | 7 | pub mod files; |
8 | 8 | ||
9 | use std::{fmt::Display, fs::{File, remove_file, self}, io::{Write, Read}, time::Duration}; | 9 | use std::{ |
10 | fmt::Display, | ||
11 | fs::{self, remove_file, File}, | ||
12 | io::{Read, Write}, | ||
13 | time::Duration, | ||
14 | }; | ||
10 | 15 | ||
11 | pub use apis::*; | ||
12 | use apis::modrinth::{get_game_versions, GameVersion, GameVersionType}; | 16 | use apis::modrinth::{get_game_versions, GameVersion, GameVersionType}; |
17 | pub use apis::*; | ||
13 | pub use commands::*; | 18 | pub use commands::*; |
14 | use error::{ErrorType, MLError, MLE}; | 19 | use error::{ErrorType, MLError, MLE}; |
20 | use indicatif::{ProgressBar, ProgressStyle}; | ||
15 | use serde::{Deserialize, Serialize}; | 21 | use serde::{Deserialize, Serialize}; |
16 | 22 | ||
23 | pub static STYLE_BAR_BYTE: &str = | ||
24 | "{spinner:.green}{wide_msg}{bytes}/{total_bytes} [{bar:.green/lime}]"; | ||
25 | pub static STYLE_BAR_POS: &str = " {wide_msg}{pos}/{len} [{bar:.green/lime}]"; | ||
26 | pub static STYLE_SPINNER: &str = "{spinner:.green}{wide_msg}"; | ||
27 | pub static STYLE_OPERATION: &str = " {wide_msg}"; | ||
28 | pub static STYLE_MESSAGE: &str = "{wide_msg}"; | ||
29 | pub static PROGRESS_CHARS: &str = "#>-"; | ||
30 | |||
17 | #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] | 31 | #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] |
18 | pub enum Modloader { | 32 | pub enum Modloader { |
19 | #[serde(rename(serialize = "fabric", deserialize = "fabric"))] | 33 | #[serde(rename(serialize = "fabric", deserialize = "fabric"))] |
@@ -30,7 +44,9 @@ impl Modloader { | |||
30 | "forge" => Ok(Modloader::Forge), | 44 | "forge" => Ok(Modloader::Forge), |
31 | "fabric" => Ok(Modloader::Fabric), | 45 | "fabric" => Ok(Modloader::Fabric), |
32 | "quilt" => Ok(Modloader::Quilt), | 46 | "quilt" => Ok(Modloader::Quilt), |
33 | _ => Err(MLError::new(ErrorType::ArgumentError, "UNKNOWN_MODLOADER")), | 47 | _ => { |
48 | Err(MLError::new(ErrorType::ArgumentError, "UNKNOWN_MODLOADER")) | ||
49 | } | ||
34 | } | 50 | } |
35 | } | 51 | } |
36 | } | 52 | } |
@@ -51,21 +67,29 @@ pub enum VersionLevel { | |||
51 | Release, | 67 | Release, |
52 | #[serde(rename(serialize = "snapshot", deserialize = "snapshot"))] | 68 | #[serde(rename(serialize = "snapshot", deserialize = "snapshot"))] |
53 | Snapshot, | 69 | Snapshot, |
54 | Version(String) | 70 | Version(String), |
55 | } | 71 | } |
56 | 72 | ||
57 | /// Checks if update needed (time) | 73 | /// Checks if update needed (time) |
58 | /// if yes: get versions, update | 74 | /// if yes: get versions, update |
59 | pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> { | 75 | pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> { |
76 | let p = ProgressBar::new(1); | ||
77 | p.set_style(ProgressStyle::with_template(STYLE_MESSAGE).unwrap()); | ||
78 | p.set_message("Update minecraft versions"); | ||
79 | |||
60 | let creation_time = fs::metadata(path)?.created()?; | 80 | let creation_time = fs::metadata(path)?.created()?; |
61 | if !force && creation_time.elapsed().unwrap() < Duration::from_secs(60 * 60 * 24) { return Ok(()); } | 81 | if !force |
62 | print!("Update minecraft versions"); | 82 | && creation_time.elapsed().unwrap() < Duration::from_secs(60 * 60 * 24) |
63 | std::io::stdout().flush()?; | 83 | { |
84 | return Ok(()); | ||
85 | } | ||
86 | |||
64 | let versions = get_game_versions().await; | 87 | let versions = get_game_versions().await; |
65 | remove_file(path)?; | 88 | remove_file(path)?; |
66 | let mut file = File::create(path)?; | 89 | let mut file = File::create(path)?; |
67 | file.write_all(&serde_json::to_string_pretty(&versions)?.as_bytes())?; | 90 | file.write_all(serde_json::to_string_pretty(&versions)?.as_bytes())?; |
68 | println!(" ✓"); | 91 | |
92 | p.finish_with_message("Updated minecraft versions"); | ||
69 | Ok(()) | 93 | Ok(()) |
70 | } | 94 | } |
71 | 95 | ||
@@ -79,7 +103,6 @@ pub fn load_game_versions(path: &str) -> MLE<Vec<GameVersion>> { | |||
79 | } | 103 | } |
80 | 104 | ||
81 | impl VersionLevel { | 105 | impl VersionLevel { |
82 | |||
83 | pub fn from(str: &str) -> Self { | 106 | pub fn from(str: &str) -> Self { |
84 | match str { | 107 | match str { |
85 | "release" => VersionLevel::Release, | 108 | "release" => VersionLevel::Release, |
@@ -88,29 +111,38 @@ impl VersionLevel { | |||
88 | } | 111 | } |
89 | } | 112 | } |
90 | 113 | ||
91 | pub async fn get(self, versions_path: &str, force_update: bool) -> MLE<String> { | 114 | pub async fn get( |
115 | self, | ||
116 | versions_path: &str, | ||
117 | force_update: bool, | ||
118 | ) -> MLE<String> { | ||
92 | let path = format!("{}/versions.json", versions_path); | 119 | let path = format!("{}/versions.json", versions_path); |
93 | check_game_versions(&path, force_update).await?; | 120 | check_game_versions(&path, force_update).await?; |
94 | let mut versions = load_game_versions(&path)?.into_iter(); | 121 | let mut versions = load_game_versions(&path)?.into_iter(); |
95 | 122 | ||
96 | match self { | 123 | match self { |
97 | VersionLevel::Release => { | 124 | VersionLevel::Release => { |
98 | let release = versions.find(|ver| ver.version_type == GameVersionType::release).unwrap(); | 125 | let release = versions |
99 | println!("{:?}", release); | 126 | .find(|ver| ver.version_type == GameVersionType::release) |
127 | .unwrap(); | ||
100 | Ok(release.version) | 128 | Ok(release.version) |
101 | }, | 129 | } |
102 | VersionLevel::Snapshot => { | 130 | VersionLevel::Snapshot => { |
103 | let snapshot = versions.find(|ver| ver.version_type == GameVersionType::snapshot).unwrap(); | 131 | let snapshot = versions |
104 | println!("{:?}", snapshot); | 132 | .find(|ver| ver.version_type == GameVersionType::snapshot) |
133 | .unwrap(); | ||
105 | Ok(snapshot.version) | 134 | Ok(snapshot.version) |
106 | }, | 135 | } |
107 | VersionLevel::Version(v) => { | 136 | VersionLevel::Version(v) => { |
108 | if versions.find(|ver| ver.version == v).is_some() { | 137 | if versions.any(|ver| ver.version == v) { |
109 | Ok(v) | 138 | Ok(v) |
110 | } else { | 139 | } else { |
111 | Err(MLError::new(ErrorType::ConfigError, "unknown minecraft version")) | 140 | Err(MLError::new( |
141 | ErrorType::ConfigError, | ||
142 | "unknown minecraft version", | ||
143 | )) | ||
112 | } | 144 | } |
113 | }, | 145 | } |
114 | } | 146 | } |
115 | } | 147 | } |
116 | } | 148 | } |
diff --git a/src/main.rs b/src/main.rs index 31a320b..5d60a17 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -2,8 +2,9 @@ use clap::{Parser, Subcommand}; | |||
2 | use modlist::{ | 2 | use modlist::{ |
3 | config::Cfg, | 3 | config::Cfg, |
4 | db::{config_get_current_list, lists_get, lists_get_all_ids}, | 4 | db::{config_get_current_list, lists_get, lists_get_all_ids}, |
5 | download, export, get_current_list, import, list_add, list_change, list_remove, list_version, | 5 | download, export, get_current_list, import, list_add, list_change, |
6 | mod_add, mod_remove, update, IDSelector, List, Modloader, VersionLevel, list_list, AddMod, | 6 | list_list, list_remove, list_version, mod_add, mod_remove, update, AddMod, |
7 | IDSelector, List, Modloader, VersionLevel, | ||
7 | }; | 8 | }; |
8 | 9 | ||
9 | #[derive(Parser)] | 10 | #[derive(Parser)] |
@@ -15,10 +16,6 @@ struct Cli { | |||
15 | /// config file path | 16 | /// config file path |
16 | #[arg(short, long)] | 17 | #[arg(short, long)] |
17 | config: Option<String>, | 18 | config: Option<String>, |
18 | |||
19 | /// Force GameVersion update | ||
20 | #[arg(long)] | ||
21 | force_gameupdate: bool, | ||
22 | } | 19 | } |
23 | 20 | ||
24 | #[derive(Subcommand)] | 21 | #[derive(Subcommand)] |
@@ -30,6 +27,10 @@ enum Commands { | |||
30 | List { | 27 | List { |
31 | #[command(subcommand)] | 28 | #[command(subcommand)] |
32 | command: ListCommands, | 29 | command: ListCommands, |
30 | |||
31 | /// Force GameVersion update | ||
32 | #[arg(long)] | ||
33 | force_gameupdate: bool, | ||
33 | }, | 34 | }, |
34 | Download { | 35 | Download { |
35 | /// download all lists | 36 | /// download all lists |
@@ -43,7 +44,7 @@ enum Commands { | |||
43 | /// remove disabled versions | 44 | /// remove disabled versions |
44 | #[arg(short, long)] | 45 | #[arg(short, long)] |
45 | remove: bool, | 46 | remove: bool, |
46 | 47 | ||
47 | /// optional List selection, else default list will be used | 48 | /// optional List selection, else default list will be used |
48 | #[arg(short, long)] | 49 | #[arg(short, long)] |
49 | list: Option<String>, | 50 | list: Option<String>, |
@@ -81,7 +82,7 @@ enum Commands { | |||
81 | /// the list you want to export | 82 | /// the list you want to export |
82 | list: Option<String>, | 83 | list: Option<String>, |
83 | }, | 84 | }, |
84 | Test | 85 | Test, |
85 | } | 86 | } |
86 | 87 | ||
87 | #[derive(Subcommand)] | 88 | #[derive(Subcommand)] |
@@ -160,119 +161,134 @@ async fn main() { | |||
160 | let config = Cfg::init(cli.config).await.unwrap(); | 161 | let config = Cfg::init(cli.config).await.unwrap(); |
161 | 162 | ||
162 | match cli.command { | 163 | match cli.command { |
163 | Commands::Mod { command } => { | 164 | Commands::Mod { command } => match command { |
164 | match command { | 165 | ModCommands::Add { |
165 | #[allow(unused_variables)] | 166 | id, |
166 | ModCommands::Add { | 167 | version, |
167 | id, | 168 | list, |
168 | version, | 169 | download, |
169 | list, | 170 | lock, |
170 | download, | 171 | } => { |
171 | lock, | 172 | let listf = match list { |
172 | } => { | 173 | Some(list) => lists_get(&config, &list).unwrap(), |
173 | let listf = match list { | 174 | None => lists_get( |
174 | Some(list) => lists_get(config.clone(), list).unwrap(), | 175 | &config, |
175 | None => lists_get( | 176 | &config_get_current_list(&config).unwrap(), |
176 | config.clone(), | 177 | ) |
177 | config_get_current_list(config.clone()).unwrap(), | 178 | .unwrap(), |
178 | ) | 179 | }; |
179 | .unwrap(), | ||
180 | }; | ||
181 | 180 | ||
182 | let marked_id = match version { | 181 | let marked_id = match version { |
183 | true => IDSelector::VersionID(id), | 182 | true => IDSelector::VersionID(id), |
184 | false => IDSelector::ModificationID(id), | 183 | false => IDSelector::ModificationID(id), |
185 | }; | 184 | }; |
186 | 185 | ||
187 | let add_id = AddMod { id: marked_id, set_version: lock }; | 186 | let add_id = AddMod { |
187 | id: marked_id, | ||
188 | set_version: lock, | ||
189 | }; | ||
188 | 190 | ||
189 | mod_add(config, vec![add_id], listf, download).await | 191 | mod_add(&config, vec![add_id], listf, download).await |
190 | } | ||
191 | ModCommands::Remove { id, list } => { | ||
192 | let listf = match list { | ||
193 | Some(list) => lists_get(config.clone(), list).unwrap(), | ||
194 | None => lists_get( | ||
195 | config.clone(), | ||
196 | config_get_current_list(config.clone()).unwrap(), | ||
197 | ) | ||
198 | .unwrap(), | ||
199 | }; | ||
200 | mod_remove(config, &id, listf) | ||
201 | } | ||
202 | } | 192 | } |
203 | } | 193 | ModCommands::Remove { id, list } => { |
204 | Commands::List { command } => { | 194 | let listf = match list { |
205 | match command { | 195 | Some(list) => lists_get(&config, &list).unwrap(), |
206 | ListCommands::Add { | 196 | None => lists_get( |
207 | id, | 197 | &config, |
208 | directory, | 198 | &config_get_current_list(&config).unwrap(), |
209 | modloader, | 199 | ) |
210 | version, | 200 | .unwrap(), |
211 | } => { | 201 | }; |
212 | let ml = match modloader { | 202 | mod_remove(&config, &id, &listf) |
213 | Some(ml) => Modloader::from(&ml).unwrap(), | ||
214 | None => config.clone().defaults.modloader, | ||
215 | }; | ||
216 | |||
217 | let versions_path = &config.versions; | ||
218 | let ver = match version { | ||
219 | Some(ver) => VersionLevel::from(&ver).get(versions_path, cli.force_gameupdate).await.unwrap(), | ||
220 | None => config.clone().defaults.version.get(versions_path, cli.force_gameupdate).await.unwrap(), | ||
221 | }; | ||
222 | |||
223 | list_add(config, id, ver, ml, directory) | ||
224 | } | ||
225 | ListCommands::Remove { id } => list_remove(config, id), | ||
226 | ListCommands::List => { | ||
227 | list_list(config) | ||
228 | } | ||
229 | ListCommands::Change { id } => list_change(config, id), | ||
230 | ListCommands::Version { | ||
231 | id, | ||
232 | version, | ||
233 | download, | ||
234 | remove, | ||
235 | } => list_version(config, id, version, download, remove).await, | ||
236 | } | 203 | } |
237 | } | 204 | }, |
205 | Commands::List { | ||
206 | command, | ||
207 | force_gameupdate, | ||
208 | } => match command { | ||
209 | ListCommands::Add { | ||
210 | id, | ||
211 | directory, | ||
212 | modloader, | ||
213 | version, | ||
214 | } => { | ||
215 | let ml = match modloader { | ||
216 | Some(ml) => Modloader::from(&ml).unwrap(), | ||
217 | None => config.defaults.modloader.clone(), | ||
218 | }; | ||
219 | |||
220 | let versions_path = &config.versions; | ||
221 | let ver = match version { | ||
222 | Some(ver) => VersionLevel::from(&ver) | ||
223 | .get(versions_path, force_gameupdate) | ||
224 | .await | ||
225 | .unwrap(), | ||
226 | None => config | ||
227 | .defaults | ||
228 | .version | ||
229 | .clone() | ||
230 | .get(versions_path, force_gameupdate) | ||
231 | .await | ||
232 | .unwrap(), | ||
233 | }; | ||
234 | |||
235 | list_add(&config, &id, &ver, &ml, &directory) | ||
236 | } | ||
237 | ListCommands::Remove { id } => list_remove(&config, &id), | ||
238 | ListCommands::List => list_list(&config), | ||
239 | ListCommands::Change { id } => list_change(&config, &id), | ||
240 | ListCommands::Version { | ||
241 | id, | ||
242 | version, | ||
243 | download, | ||
244 | remove, | ||
245 | } => list_version(&config, &id, version, download, remove).await, | ||
246 | }, | ||
238 | Commands::Update { | 247 | Commands::Update { |
239 | all, | 248 | all, |
240 | download, | 249 | download, |
241 | clean, | 250 | clean, |
242 | remove, | 251 | remove, |
243 | list | 252 | list, |
244 | } => { | 253 | } => { |
245 | let mut liststack: Vec<List> = vec![]; | 254 | let mut liststack: Vec<List> = vec![]; |
246 | if all { | 255 | if all { |
247 | let list_ids = lists_get_all_ids(config.clone()).unwrap(); | 256 | let list_ids = lists_get_all_ids(&config).unwrap(); |
248 | for id in list_ids { | 257 | for id in list_ids { |
249 | liststack.push(lists_get(config.clone(), id).unwrap()); | 258 | liststack.push(lists_get(&config, &id).unwrap()); |
250 | } | 259 | } |
251 | } else { | 260 | } else { |
252 | let current = match list { | 261 | let current = match list { |
253 | Some(l) => lists_get(config.clone(), l).unwrap(), | 262 | Some(l) => lists_get(&config, &l).unwrap(), |
254 | None => get_current_list(config.clone()).unwrap(), | 263 | None => get_current_list(&config).unwrap(), |
255 | }; | 264 | }; |
256 | liststack.push(current) | 265 | liststack.push(current) |
257 | } | 266 | } |
258 | update(config, liststack, clean, download, remove).await | 267 | |
268 | update(&config, liststack, clean, download, remove).await | ||
259 | } | 269 | } |
260 | Commands::Download { all, clean, remove, list } => { | 270 | Commands::Download { |
271 | all, | ||
272 | clean, | ||
273 | remove, | ||
274 | list, | ||
275 | } => { | ||
261 | let mut liststack: Vec<List> = vec![]; | 276 | let mut liststack: Vec<List> = vec![]; |
262 | if all { | 277 | if all { |
263 | let list_ids = lists_get_all_ids(config.clone()).unwrap(); | 278 | let list_ids = lists_get_all_ids(&config).unwrap(); |
264 | for id in list_ids { | 279 | for id in list_ids { |
265 | liststack.push(lists_get(config.clone(), id).unwrap()); | 280 | liststack.push(lists_get(&config, &id).unwrap()); |
266 | } | 281 | } |
267 | } else { | 282 | } else { |
268 | let current = match list { | 283 | let current = match list { |
269 | Some(l) => lists_get(config.clone(), l).unwrap(), | 284 | Some(l) => lists_get(&config, &l).unwrap(), |
270 | None => get_current_list(config.clone()).unwrap(), | 285 | None => get_current_list(&config).unwrap(), |
271 | }; | 286 | }; |
272 | liststack.push(current) | 287 | liststack.push(current) |
273 | } | 288 | } |
274 | download(config, liststack, clean, remove).await | 289 | |
275 | }, | 290 | download(&config, liststack, clean, remove).await |
291 | } | ||
276 | Commands::Import { file, download } => { | 292 | Commands::Import { file, download } => { |
277 | let filestr: String = match file { | 293 | let filestr: String = match file { |
278 | Some(args) => args, | 294 | Some(args) => args, |
@@ -284,9 +300,9 @@ async fn main() { | |||
284 | .unwrap(), | 300 | .unwrap(), |
285 | }; | 301 | }; |
286 | 302 | ||
287 | import(config, filestr, download).await | 303 | import(&config, &filestr, download).await |
288 | } | 304 | } |
289 | Commands::Export { list } => export(config, list), | 305 | Commands::Export { list } => export(&config, list), |
290 | Commands::Test => Ok(()), | 306 | Commands::Test => Ok(()), |
291 | } | 307 | } |
292 | .unwrap(); | 308 | .unwrap(); |