diff options
-rw-r--r-- | Cargo.lock | 633 | ||||
-rw-r--r-- | Cargo.toml | 8 | ||||
-rw-r--r-- | src/apis/modrinth.rs | 56 | ||||
-rw-r--r-- | src/commands/download.rs | 46 | ||||
-rw-r--r-- | src/commands/io.rs | 78 | ||||
-rw-r--r-- | src/commands/list.rs | 81 | ||||
-rw-r--r-- | src/commands/mod.rs | 16 | ||||
-rw-r--r-- | src/commands/modification.rs | 223 | ||||
-rw-r--r-- | src/commands/setup.rs | 12 | ||||
-rw-r--r-- | src/commands/update.rs | 132 | ||||
-rw-r--r-- | src/config.rs | 18 | ||||
-rw-r--r-- | src/db.rs | 431 | ||||
-rw-r--r-- | src/error.rs | 37 | ||||
-rw-r--r-- | src/files.rs | 59 | ||||
-rw-r--r-- | src/input.rs | 344 | ||||
-rw-r--r-- | src/lib.rs | 29 | ||||
-rw-r--r-- | src/main.rs | 312 |
17 files changed, 1522 insertions, 993 deletions
@@ -38,6 +38,55 @@ dependencies = [ | |||
38 | ] | 38 | ] |
39 | 39 | ||
40 | [[package]] | 40 | [[package]] |
41 | name = "anstream" | ||
42 | version = "0.3.0" | ||
43 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
44 | checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371" | ||
45 | dependencies = [ | ||
46 | "anstyle", | ||
47 | "anstyle-parse", | ||
48 | "anstyle-query", | ||
49 | "anstyle-wincon", | ||
50 | "colorchoice", | ||
51 | "is-terminal", | ||
52 | "utf8parse", | ||
53 | ] | ||
54 | |||
55 | [[package]] | ||
56 | name = "anstyle" | ||
57 | version = "1.0.0" | ||
58 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
59 | checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" | ||
60 | |||
61 | [[package]] | ||
62 | name = "anstyle-parse" | ||
63 | version = "0.2.0" | ||
64 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
65 | checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" | ||
66 | dependencies = [ | ||
67 | "utf8parse", | ||
68 | ] | ||
69 | |||
70 | [[package]] | ||
71 | name = "anstyle-query" | ||
72 | version = "1.0.0" | ||
73 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
74 | checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" | ||
75 | dependencies = [ | ||
76 | "windows-sys 0.48.0", | ||
77 | ] | ||
78 | |||
79 | [[package]] | ||
80 | name = "anstyle-wincon" | ||
81 | version = "1.0.0" | ||
82 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
83 | checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd" | ||
84 | dependencies = [ | ||
85 | "anstyle", | ||
86 | "windows-sys 0.48.0", | ||
87 | ] | ||
88 | |||
89 | [[package]] | ||
41 | name = "autocfg" | 90 | name = "autocfg" |
42 | version = "1.1.0" | 91 | version = "1.1.0" |
43 | source = "registry+https://github.com/rust-lang/crates.io-index" | 92 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -71,6 +120,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
71 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | 120 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" |
72 | 121 | ||
73 | [[package]] | 122 | [[package]] |
123 | name = "bitflags" | ||
124 | version = "2.0.2" | ||
125 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
126 | checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1" | ||
127 | |||
128 | [[package]] | ||
74 | name = "bumpalo" | 129 | name = "bumpalo" |
75 | version = "3.12.0" | 130 | version = "3.12.0" |
76 | source = "registry+https://github.com/rust-lang/crates.io-index" | 131 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -96,9 +151,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | |||
96 | 151 | ||
97 | [[package]] | 152 | [[package]] |
98 | name = "chrono" | 153 | name = "chrono" |
99 | version = "0.4.23" | 154 | version = "0.4.24" |
100 | source = "registry+https://github.com/rust-lang/crates.io-index" | 155 | source = "registry+https://github.com/rust-lang/crates.io-index" |
101 | checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" | 156 | checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" |
102 | dependencies = [ | 157 | dependencies = [ |
103 | "iana-time-zone", | 158 | "iana-time-zone", |
104 | "js-sys", | 159 | "js-sys", |
@@ -110,6 +165,57 @@ dependencies = [ | |||
110 | ] | 165 | ] |
111 | 166 | ||
112 | [[package]] | 167 | [[package]] |
168 | name = "clap" | ||
169 | version = "4.2.2" | ||
170 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
171 | checksum = "9b802d85aaf3a1cdb02b224ba472ebdea62014fccfcb269b95a4d76443b5ee5a" | ||
172 | dependencies = [ | ||
173 | "clap_builder", | ||
174 | "clap_derive", | ||
175 | "once_cell", | ||
176 | ] | ||
177 | |||
178 | [[package]] | ||
179 | name = "clap_builder" | ||
180 | version = "4.2.2" | ||
181 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
182 | checksum = "14a1a858f532119338887a4b8e1af9c60de8249cd7bafd68036a489e261e37b6" | ||
183 | dependencies = [ | ||
184 | "anstream", | ||
185 | "anstyle", | ||
186 | "bitflags 1.3.2", | ||
187 | "clap_lex", | ||
188 | "strsim", | ||
189 | ] | ||
190 | |||
191 | [[package]] | ||
192 | name = "clap_complete" | ||
193 | version = "4.2.0" | ||
194 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
195 | checksum = "01c22dcfb410883764b29953103d9ef7bb8fe21b3fa1158bc99986c2067294bd" | ||
196 | dependencies = [ | ||
197 | "clap", | ||
198 | ] | ||
199 | |||
200 | [[package]] | ||
201 | name = "clap_derive" | ||
202 | version = "4.2.0" | ||
203 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
204 | checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" | ||
205 | dependencies = [ | ||
206 | "heck", | ||
207 | "proc-macro2", | ||
208 | "quote", | ||
209 | "syn 2.0.13", | ||
210 | ] | ||
211 | |||
212 | [[package]] | ||
213 | name = "clap_lex" | ||
214 | version = "0.4.1" | ||
215 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
216 | checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" | ||
217 | |||
218 | [[package]] | ||
113 | name = "codespan-reporting" | 219 | name = "codespan-reporting" |
114 | version = "0.11.1" | 220 | version = "0.11.1" |
115 | source = "registry+https://github.com/rust-lang/crates.io-index" | 221 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -120,6 +226,12 @@ dependencies = [ | |||
120 | ] | 226 | ] |
121 | 227 | ||
122 | [[package]] | 228 | [[package]] |
229 | name = "colorchoice" | ||
230 | version = "1.0.0" | ||
231 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
232 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" | ||
233 | |||
234 | [[package]] | ||
123 | name = "core-foundation" | 235 | name = "core-foundation" |
124 | version = "0.9.3" | 236 | version = "0.9.3" |
125 | source = "registry+https://github.com/rust-lang/crates.io-index" | 237 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -131,15 +243,15 @@ dependencies = [ | |||
131 | 243 | ||
132 | [[package]] | 244 | [[package]] |
133 | name = "core-foundation-sys" | 245 | name = "core-foundation-sys" |
134 | version = "0.8.3" | 246 | version = "0.8.4" |
135 | source = "registry+https://github.com/rust-lang/crates.io-index" | 247 | source = "registry+https://github.com/rust-lang/crates.io-index" |
136 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" | 248 | checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" |
137 | 249 | ||
138 | [[package]] | 250 | [[package]] |
139 | name = "cxx" | 251 | name = "cxx" |
140 | version = "1.0.91" | 252 | version = "1.0.94" |
141 | source = "registry+https://github.com/rust-lang/crates.io-index" | 253 | source = "registry+https://github.com/rust-lang/crates.io-index" |
142 | checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" | 254 | checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" |
143 | dependencies = [ | 255 | dependencies = [ |
144 | "cc", | 256 | "cc", |
145 | "cxxbridge-flags", | 257 | "cxxbridge-flags", |
@@ -149,9 +261,9 @@ dependencies = [ | |||
149 | 261 | ||
150 | [[package]] | 262 | [[package]] |
151 | name = "cxx-build" | 263 | name = "cxx-build" |
152 | version = "1.0.91" | 264 | version = "1.0.94" |
153 | source = "registry+https://github.com/rust-lang/crates.io-index" | 265 | source = "registry+https://github.com/rust-lang/crates.io-index" |
154 | checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" | 266 | checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" |
155 | dependencies = [ | 267 | dependencies = [ |
156 | "cc", | 268 | "cc", |
157 | "codespan-reporting", | 269 | "codespan-reporting", |
@@ -159,44 +271,44 @@ dependencies = [ | |||
159 | "proc-macro2", | 271 | "proc-macro2", |
160 | "quote", | 272 | "quote", |
161 | "scratch", | 273 | "scratch", |
162 | "syn", | 274 | "syn 2.0.13", |
163 | ] | 275 | ] |
164 | 276 | ||
165 | [[package]] | 277 | [[package]] |
166 | name = "cxxbridge-flags" | 278 | name = "cxxbridge-flags" |
167 | version = "1.0.91" | 279 | version = "1.0.94" |
168 | source = "registry+https://github.com/rust-lang/crates.io-index" | 280 | source = "registry+https://github.com/rust-lang/crates.io-index" |
169 | checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" | 281 | checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" |
170 | 282 | ||
171 | [[package]] | 283 | [[package]] |
172 | name = "cxxbridge-macro" | 284 | name = "cxxbridge-macro" |
173 | version = "1.0.91" | 285 | version = "1.0.94" |
174 | source = "registry+https://github.com/rust-lang/crates.io-index" | 286 | source = "registry+https://github.com/rust-lang/crates.io-index" |
175 | checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" | 287 | checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" |
176 | dependencies = [ | 288 | dependencies = [ |
177 | "proc-macro2", | 289 | "proc-macro2", |
178 | "quote", | 290 | "quote", |
179 | "syn", | 291 | "syn 2.0.13", |
180 | ] | 292 | ] |
181 | 293 | ||
182 | [[package]] | 294 | [[package]] |
183 | name = "dirs" | 295 | name = "dirs" |
184 | version = "4.0.0" | 296 | version = "5.0.0" |
185 | source = "registry+https://github.com/rust-lang/crates.io-index" | 297 | source = "registry+https://github.com/rust-lang/crates.io-index" |
186 | checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" | 298 | checksum = "dece029acd3353e3a58ac2e3eb3c8d6c35827a892edc6cc4138ef9c33df46ecd" |
187 | dependencies = [ | 299 | dependencies = [ |
188 | "dirs-sys", | 300 | "dirs-sys", |
189 | ] | 301 | ] |
190 | 302 | ||
191 | [[package]] | 303 | [[package]] |
192 | name = "dirs-sys" | 304 | name = "dirs-sys" |
193 | version = "0.3.7" | 305 | version = "0.4.0" |
194 | source = "registry+https://github.com/rust-lang/crates.io-index" | 306 | source = "registry+https://github.com/rust-lang/crates.io-index" |
195 | checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" | 307 | checksum = "04414300db88f70d74c5ff54e50f9e1d1737d9a5b90f53fcf2e95ca2a9ab554b" |
196 | dependencies = [ | 308 | dependencies = [ |
197 | "libc", | 309 | "libc", |
198 | "redox_users", | 310 | "redox_users", |
199 | "winapi", | 311 | "windows-sys 0.45.0", |
200 | ] | 312 | ] |
201 | 313 | ||
202 | [[package]] | 314 | [[package]] |
@@ -209,6 +321,27 @@ dependencies = [ | |||
209 | ] | 321 | ] |
210 | 322 | ||
211 | [[package]] | 323 | [[package]] |
324 | name = "errno" | ||
325 | version = "0.3.0" | ||
326 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
327 | checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" | ||
328 | dependencies = [ | ||
329 | "errno-dragonfly", | ||
330 | "libc", | ||
331 | "windows-sys 0.45.0", | ||
332 | ] | ||
333 | |||
334 | [[package]] | ||
335 | name = "errno-dragonfly" | ||
336 | version = "0.1.2" | ||
337 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
338 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" | ||
339 | dependencies = [ | ||
340 | "cc", | ||
341 | "libc", | ||
342 | ] | ||
343 | |||
344 | [[package]] | ||
212 | name = "error-chain" | 345 | name = "error-chain" |
213 | version = "0.12.4" | 346 | version = "0.12.4" |
214 | source = "registry+https://github.com/rust-lang/crates.io-index" | 347 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -271,53 +404,53 @@ dependencies = [ | |||
271 | 404 | ||
272 | [[package]] | 405 | [[package]] |
273 | name = "futures-channel" | 406 | name = "futures-channel" |
274 | version = "0.3.26" | 407 | version = "0.3.28" |
275 | source = "registry+https://github.com/rust-lang/crates.io-index" | 408 | source = "registry+https://github.com/rust-lang/crates.io-index" |
276 | checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" | 409 | checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" |
277 | dependencies = [ | 410 | dependencies = [ |
278 | "futures-core", | 411 | "futures-core", |
279 | ] | 412 | ] |
280 | 413 | ||
281 | [[package]] | 414 | [[package]] |
282 | name = "futures-core" | 415 | name = "futures-core" |
283 | version = "0.3.26" | 416 | version = "0.3.28" |
284 | source = "registry+https://github.com/rust-lang/crates.io-index" | 417 | source = "registry+https://github.com/rust-lang/crates.io-index" |
285 | checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" | 418 | checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" |
286 | 419 | ||
287 | [[package]] | 420 | [[package]] |
288 | name = "futures-io" | 421 | name = "futures-io" |
289 | version = "0.3.26" | 422 | version = "0.3.28" |
290 | source = "registry+https://github.com/rust-lang/crates.io-index" | 423 | source = "registry+https://github.com/rust-lang/crates.io-index" |
291 | checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" | 424 | checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" |
292 | 425 | ||
293 | [[package]] | 426 | [[package]] |
294 | name = "futures-macro" | 427 | name = "futures-macro" |
295 | version = "0.3.26" | 428 | version = "0.3.28" |
296 | source = "registry+https://github.com/rust-lang/crates.io-index" | 429 | source = "registry+https://github.com/rust-lang/crates.io-index" |
297 | checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" | 430 | checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" |
298 | dependencies = [ | 431 | dependencies = [ |
299 | "proc-macro2", | 432 | "proc-macro2", |
300 | "quote", | 433 | "quote", |
301 | "syn", | 434 | "syn 2.0.13", |
302 | ] | 435 | ] |
303 | 436 | ||
304 | [[package]] | 437 | [[package]] |
305 | name = "futures-sink" | 438 | name = "futures-sink" |
306 | version = "0.3.26" | 439 | version = "0.3.28" |
307 | source = "registry+https://github.com/rust-lang/crates.io-index" | 440 | source = "registry+https://github.com/rust-lang/crates.io-index" |
308 | checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" | 441 | checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" |
309 | 442 | ||
310 | [[package]] | 443 | [[package]] |
311 | name = "futures-task" | 444 | name = "futures-task" |
312 | version = "0.3.26" | 445 | version = "0.3.28" |
313 | source = "registry+https://github.com/rust-lang/crates.io-index" | 446 | source = "registry+https://github.com/rust-lang/crates.io-index" |
314 | checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" | 447 | checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" |
315 | 448 | ||
316 | [[package]] | 449 | [[package]] |
317 | name = "futures-util" | 450 | name = "futures-util" |
318 | version = "0.3.26" | 451 | version = "0.3.28" |
319 | source = "registry+https://github.com/rust-lang/crates.io-index" | 452 | source = "registry+https://github.com/rust-lang/crates.io-index" |
320 | checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" | 453 | checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" |
321 | dependencies = [ | 454 | dependencies = [ |
322 | "futures-core", | 455 | "futures-core", |
323 | "futures-io", | 456 | "futures-io", |
@@ -349,9 +482,9 @@ checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" | |||
349 | 482 | ||
350 | [[package]] | 483 | [[package]] |
351 | name = "h2" | 484 | name = "h2" |
352 | version = "0.3.15" | 485 | version = "0.3.16" |
353 | source = "registry+https://github.com/rust-lang/crates.io-index" | 486 | source = "registry+https://github.com/rust-lang/crates.io-index" |
354 | checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" | 487 | checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" |
355 | dependencies = [ | 488 | dependencies = [ |
356 | "bytes", | 489 | "bytes", |
357 | "fnv", | 490 | "fnv", |
@@ -385,6 +518,12 @@ dependencies = [ | |||
385 | ] | 518 | ] |
386 | 519 | ||
387 | [[package]] | 520 | [[package]] |
521 | name = "heck" | ||
522 | version = "0.4.1" | ||
523 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
524 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" | ||
525 | |||
526 | [[package]] | ||
388 | name = "hermit-abi" | 527 | name = "hermit-abi" |
389 | version = "0.2.6" | 528 | version = "0.2.6" |
390 | source = "registry+https://github.com/rust-lang/crates.io-index" | 529 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -394,6 +533,12 @@ dependencies = [ | |||
394 | ] | 533 | ] |
395 | 534 | ||
396 | [[package]] | 535 | [[package]] |
536 | name = "hermit-abi" | ||
537 | version = "0.3.1" | ||
538 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
539 | checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" | ||
540 | |||
541 | [[package]] | ||
397 | name = "http" | 542 | name = "http" |
398 | version = "0.2.9" | 543 | version = "0.2.9" |
399 | source = "registry+https://github.com/rust-lang/crates.io-index" | 544 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -429,9 +574,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" | |||
429 | 574 | ||
430 | [[package]] | 575 | [[package]] |
431 | name = "hyper" | 576 | name = "hyper" |
432 | version = "0.14.24" | 577 | version = "0.14.25" |
433 | source = "registry+https://github.com/rust-lang/crates.io-index" | 578 | source = "registry+https://github.com/rust-lang/crates.io-index" |
434 | checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" | 579 | checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" |
435 | dependencies = [ | 580 | dependencies = [ |
436 | "bytes", | 581 | "bytes", |
437 | "futures-channel", | 582 | "futures-channel", |
@@ -466,16 +611,16 @@ dependencies = [ | |||
466 | 611 | ||
467 | [[package]] | 612 | [[package]] |
468 | name = "iana-time-zone" | 613 | name = "iana-time-zone" |
469 | version = "0.1.53" | 614 | version = "0.1.56" |
470 | source = "registry+https://github.com/rust-lang/crates.io-index" | 615 | source = "registry+https://github.com/rust-lang/crates.io-index" |
471 | checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" | 616 | checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" |
472 | dependencies = [ | 617 | dependencies = [ |
473 | "android_system_properties", | 618 | "android_system_properties", |
474 | "core-foundation-sys", | 619 | "core-foundation-sys", |
475 | "iana-time-zone-haiku", | 620 | "iana-time-zone-haiku", |
476 | "js-sys", | 621 | "js-sys", |
477 | "wasm-bindgen", | 622 | "wasm-bindgen", |
478 | "winapi", | 623 | "windows", |
479 | ] | 624 | ] |
480 | 625 | ||
481 | [[package]] | 626 | [[package]] |
@@ -500,9 +645,9 @@ dependencies = [ | |||
500 | 645 | ||
501 | [[package]] | 646 | [[package]] |
502 | name = "indexmap" | 647 | name = "indexmap" |
503 | version = "1.9.2" | 648 | version = "1.9.3" |
504 | source = "registry+https://github.com/rust-lang/crates.io-index" | 649 | source = "registry+https://github.com/rust-lang/crates.io-index" |
505 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" | 650 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" |
506 | dependencies = [ | 651 | dependencies = [ |
507 | "autocfg", | 652 | "autocfg", |
508 | "hashbrown", | 653 | "hashbrown", |
@@ -518,16 +663,39 @@ dependencies = [ | |||
518 | ] | 663 | ] |
519 | 664 | ||
520 | [[package]] | 665 | [[package]] |
666 | name = "io-lifetimes" | ||
667 | version = "1.0.9" | ||
668 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
669 | checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" | ||
670 | dependencies = [ | ||
671 | "hermit-abi 0.3.1", | ||
672 | "libc", | ||
673 | "windows-sys 0.45.0", | ||
674 | ] | ||
675 | |||
676 | [[package]] | ||
521 | name = "ipnet" | 677 | name = "ipnet" |
522 | version = "2.7.1" | 678 | version = "2.7.2" |
679 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
680 | checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" | ||
681 | |||
682 | [[package]] | ||
683 | name = "is-terminal" | ||
684 | version = "0.4.6" | ||
523 | source = "registry+https://github.com/rust-lang/crates.io-index" | 685 | source = "registry+https://github.com/rust-lang/crates.io-index" |
524 | checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" | 686 | checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" |
687 | dependencies = [ | ||
688 | "hermit-abi 0.3.1", | ||
689 | "io-lifetimes", | ||
690 | "rustix", | ||
691 | "windows-sys 0.45.0", | ||
692 | ] | ||
525 | 693 | ||
526 | [[package]] | 694 | [[package]] |
527 | name = "itoa" | 695 | name = "itoa" |
528 | version = "1.0.5" | 696 | version = "1.0.6" |
529 | source = "registry+https://github.com/rust-lang/crates.io-index" | 697 | source = "registry+https://github.com/rust-lang/crates.io-index" |
530 | checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" | 698 | checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" |
531 | 699 | ||
532 | [[package]] | 700 | [[package]] |
533 | name = "js-sys" | 701 | name = "js-sys" |
@@ -546,15 +714,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | |||
546 | 714 | ||
547 | [[package]] | 715 | [[package]] |
548 | name = "libc" | 716 | name = "libc" |
549 | version = "0.2.139" | 717 | version = "0.2.141" |
550 | source = "registry+https://github.com/rust-lang/crates.io-index" | 718 | source = "registry+https://github.com/rust-lang/crates.io-index" |
551 | checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" | 719 | checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" |
552 | 720 | ||
553 | [[package]] | 721 | [[package]] |
554 | name = "libsqlite3-sys" | 722 | name = "libsqlite3-sys" |
555 | version = "0.25.2" | 723 | version = "0.26.0" |
556 | source = "registry+https://github.com/rust-lang/crates.io-index" | 724 | source = "registry+https://github.com/rust-lang/crates.io-index" |
557 | checksum = "29f835d03d717946d28b1d1ed632eb6f0e24a299388ee623d0c23118d3e8a7fa" | 725 | checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" |
558 | dependencies = [ | 726 | dependencies = [ |
559 | "cc", | 727 | "cc", |
560 | "pkg-config", | 728 | "pkg-config", |
@@ -571,6 +739,12 @@ dependencies = [ | |||
571 | ] | 739 | ] |
572 | 740 | ||
573 | [[package]] | 741 | [[package]] |
742 | name = "linux-raw-sys" | ||
743 | version = "0.3.1" | ||
744 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
745 | checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" | ||
746 | |||
747 | [[package]] | ||
574 | name = "lock_api" | 748 | name = "lock_api" |
575 | version = "0.4.9" | 749 | version = "0.4.9" |
576 | source = "registry+https://github.com/rust-lang/crates.io-index" | 750 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -597,9 +771,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" | |||
597 | 771 | ||
598 | [[package]] | 772 | [[package]] |
599 | name = "mime" | 773 | name = "mime" |
600 | version = "0.3.16" | 774 | version = "0.3.17" |
601 | source = "registry+https://github.com/rust-lang/crates.io-index" | 775 | source = "registry+https://github.com/rust-lang/crates.io-index" |
602 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" | 776 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" |
603 | 777 | ||
604 | [[package]] | 778 | [[package]] |
605 | name = "miniz_oxide" | 779 | name = "miniz_oxide" |
@@ -624,9 +798,11 @@ dependencies = [ | |||
624 | 798 | ||
625 | [[package]] | 799 | [[package]] |
626 | name = "modlist" | 800 | name = "modlist" |
627 | version = "0.11.0" | 801 | version = "0.12.0" |
628 | dependencies = [ | 802 | dependencies = [ |
629 | "chrono", | 803 | "chrono", |
804 | "clap", | ||
805 | "clap_complete", | ||
630 | "dirs", | 806 | "dirs", |
631 | "error-chain", | 807 | "error-chain", |
632 | "futures-util", | 808 | "futures-util", |
@@ -657,15 +833,6 @@ dependencies = [ | |||
657 | ] | 833 | ] |
658 | 834 | ||
659 | [[package]] | 835 | [[package]] |
660 | name = "nom8" | ||
661 | version = "0.2.0" | ||
662 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
663 | checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" | ||
664 | dependencies = [ | ||
665 | "memchr", | ||
666 | ] | ||
667 | |||
668 | [[package]] | ||
669 | name = "num-integer" | 836 | name = "num-integer" |
670 | version = "0.1.45" | 837 | version = "0.1.45" |
671 | source = "registry+https://github.com/rust-lang/crates.io-index" | 838 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -690,7 +857,7 @@ version = "1.15.0" | |||
690 | source = "registry+https://github.com/rust-lang/crates.io-index" | 857 | source = "registry+https://github.com/rust-lang/crates.io-index" |
691 | checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" | 858 | checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" |
692 | dependencies = [ | 859 | dependencies = [ |
693 | "hermit-abi", | 860 | "hermit-abi 0.2.6", |
694 | "libc", | 861 | "libc", |
695 | ] | 862 | ] |
696 | 863 | ||
@@ -711,11 +878,11 @@ checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" | |||
711 | 878 | ||
712 | [[package]] | 879 | [[package]] |
713 | name = "openssl" | 880 | name = "openssl" |
714 | version = "0.10.45" | 881 | version = "0.10.49" |
715 | source = "registry+https://github.com/rust-lang/crates.io-index" | 882 | source = "registry+https://github.com/rust-lang/crates.io-index" |
716 | checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" | 883 | checksum = "4d2f106ab837a24e03672c59b1239669a0596406ff657c3c0835b6b7f0f35a33" |
717 | dependencies = [ | 884 | dependencies = [ |
718 | "bitflags", | 885 | "bitflags 1.3.2", |
719 | "cfg-if", | 886 | "cfg-if", |
720 | "foreign-types", | 887 | "foreign-types", |
721 | "libc", | 888 | "libc", |
@@ -726,13 +893,13 @@ dependencies = [ | |||
726 | 893 | ||
727 | [[package]] | 894 | [[package]] |
728 | name = "openssl-macros" | 895 | name = "openssl-macros" |
729 | version = "0.1.0" | 896 | version = "0.1.1" |
730 | source = "registry+https://github.com/rust-lang/crates.io-index" | 897 | source = "registry+https://github.com/rust-lang/crates.io-index" |
731 | checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" | 898 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" |
732 | dependencies = [ | 899 | dependencies = [ |
733 | "proc-macro2", | 900 | "proc-macro2", |
734 | "quote", | 901 | "quote", |
735 | "syn", | 902 | "syn 2.0.13", |
736 | ] | 903 | ] |
737 | 904 | ||
738 | [[package]] | 905 | [[package]] |
@@ -743,11 +910,10 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" | |||
743 | 910 | ||
744 | [[package]] | 911 | [[package]] |
745 | name = "openssl-sys" | 912 | name = "openssl-sys" |
746 | version = "0.9.80" | 913 | version = "0.9.84" |
747 | source = "registry+https://github.com/rust-lang/crates.io-index" | 914 | source = "registry+https://github.com/rust-lang/crates.io-index" |
748 | checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" | 915 | checksum = "3a20eace9dc2d82904039cb76dcf50fb1a0bba071cfd1629720b5d6f1ddba0fa" |
749 | dependencies = [ | 916 | dependencies = [ |
750 | "autocfg", | ||
751 | "cc", | 917 | "cc", |
752 | "libc", | 918 | "libc", |
753 | "pkg-config", | 919 | "pkg-config", |
@@ -772,7 +938,7 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" | |||
772 | dependencies = [ | 938 | dependencies = [ |
773 | "cfg-if", | 939 | "cfg-if", |
774 | "libc", | 940 | "libc", |
775 | "redox_syscall", | 941 | "redox_syscall 0.2.16", |
776 | "smallvec", | 942 | "smallvec", |
777 | "windows-sys 0.45.0", | 943 | "windows-sys 0.45.0", |
778 | ] | 944 | ] |
@@ -803,18 +969,18 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" | |||
803 | 969 | ||
804 | [[package]] | 970 | [[package]] |
805 | name = "proc-macro2" | 971 | name = "proc-macro2" |
806 | version = "1.0.51" | 972 | version = "1.0.56" |
807 | source = "registry+https://github.com/rust-lang/crates.io-index" | 973 | source = "registry+https://github.com/rust-lang/crates.io-index" |
808 | checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" | 974 | checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" |
809 | dependencies = [ | 975 | dependencies = [ |
810 | "unicode-ident", | 976 | "unicode-ident", |
811 | ] | 977 | ] |
812 | 978 | ||
813 | [[package]] | 979 | [[package]] |
814 | name = "quote" | 980 | name = "quote" |
815 | version = "1.0.23" | 981 | version = "1.0.26" |
816 | source = "registry+https://github.com/rust-lang/crates.io-index" | 982 | source = "registry+https://github.com/rust-lang/crates.io-index" |
817 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" | 983 | checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" |
818 | dependencies = [ | 984 | dependencies = [ |
819 | "proc-macro2", | 985 | "proc-macro2", |
820 | ] | 986 | ] |
@@ -825,34 +991,34 @@ version = "0.2.16" | |||
825 | source = "registry+https://github.com/rust-lang/crates.io-index" | 991 | source = "registry+https://github.com/rust-lang/crates.io-index" |
826 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" | 992 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" |
827 | dependencies = [ | 993 | dependencies = [ |
828 | "bitflags", | 994 | "bitflags 1.3.2", |
829 | ] | 995 | ] |
830 | 996 | ||
831 | [[package]] | 997 | [[package]] |
832 | name = "redox_users" | 998 | name = "redox_syscall" |
833 | version = "0.4.3" | 999 | version = "0.3.5" |
834 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1000 | source = "registry+https://github.com/rust-lang/crates.io-index" |
835 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" | 1001 | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" |
836 | dependencies = [ | 1002 | dependencies = [ |
837 | "getrandom", | 1003 | "bitflags 1.3.2", |
838 | "redox_syscall", | ||
839 | "thiserror", | ||
840 | ] | 1004 | ] |
841 | 1005 | ||
842 | [[package]] | 1006 | [[package]] |
843 | name = "remove_dir_all" | 1007 | name = "redox_users" |
844 | version = "0.5.3" | 1008 | version = "0.4.3" |
845 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1009 | source = "registry+https://github.com/rust-lang/crates.io-index" |
846 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" | 1010 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" |
847 | dependencies = [ | 1011 | dependencies = [ |
848 | "winapi", | 1012 | "getrandom", |
1013 | "redox_syscall 0.2.16", | ||
1014 | "thiserror", | ||
849 | ] | 1015 | ] |
850 | 1016 | ||
851 | [[package]] | 1017 | [[package]] |
852 | name = "reqwest" | 1018 | name = "reqwest" |
853 | version = "0.11.14" | 1019 | version = "0.11.16" |
854 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1020 | source = "registry+https://github.com/rust-lang/crates.io-index" |
855 | checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" | 1021 | checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" |
856 | dependencies = [ | 1022 | dependencies = [ |
857 | "base64", | 1023 | "base64", |
858 | "bytes", | 1024 | "bytes", |
@@ -889,11 +1055,11 @@ dependencies = [ | |||
889 | 1055 | ||
890 | [[package]] | 1056 | [[package]] |
891 | name = "rusqlite" | 1057 | name = "rusqlite" |
892 | version = "0.28.0" | 1058 | version = "0.29.0" |
893 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1059 | source = "registry+https://github.com/rust-lang/crates.io-index" |
894 | checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a" | 1060 | checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" |
895 | dependencies = [ | 1061 | dependencies = [ |
896 | "bitflags", | 1062 | "bitflags 2.0.2", |
897 | "fallible-iterator", | 1063 | "fallible-iterator", |
898 | "fallible-streaming-iterator", | 1064 | "fallible-streaming-iterator", |
899 | "hashlink", | 1065 | "hashlink", |
@@ -903,15 +1069,29 @@ dependencies = [ | |||
903 | 1069 | ||
904 | [[package]] | 1070 | [[package]] |
905 | name = "rustc-demangle" | 1071 | name = "rustc-demangle" |
906 | version = "0.1.21" | 1072 | version = "0.1.22" |
1073 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1074 | checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b" | ||
1075 | |||
1076 | [[package]] | ||
1077 | name = "rustix" | ||
1078 | version = "0.37.7" | ||
907 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1079 | source = "registry+https://github.com/rust-lang/crates.io-index" |
908 | checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" | 1080 | checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d" |
1081 | dependencies = [ | ||
1082 | "bitflags 1.3.2", | ||
1083 | "errno", | ||
1084 | "io-lifetimes", | ||
1085 | "libc", | ||
1086 | "linux-raw-sys", | ||
1087 | "windows-sys 0.45.0", | ||
1088 | ] | ||
909 | 1089 | ||
910 | [[package]] | 1090 | [[package]] |
911 | name = "ryu" | 1091 | name = "ryu" |
912 | version = "1.0.12" | 1092 | version = "1.0.13" |
913 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1093 | source = "registry+https://github.com/rust-lang/crates.io-index" |
914 | checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" | 1094 | checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" |
915 | 1095 | ||
916 | [[package]] | 1096 | [[package]] |
917 | name = "schannel" | 1097 | name = "schannel" |
@@ -930,9 +1110,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" | |||
930 | 1110 | ||
931 | [[package]] | 1111 | [[package]] |
932 | name = "scratch" | 1112 | name = "scratch" |
933 | version = "1.0.3" | 1113 | version = "1.0.5" |
934 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1114 | source = "registry+https://github.com/rust-lang/crates.io-index" |
935 | checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" | 1115 | checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" |
936 | 1116 | ||
937 | [[package]] | 1117 | [[package]] |
938 | name = "security-framework" | 1118 | name = "security-framework" |
@@ -940,7 +1120,7 @@ version = "2.8.2" | |||
940 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1120 | source = "registry+https://github.com/rust-lang/crates.io-index" |
941 | checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" | 1121 | checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" |
942 | dependencies = [ | 1122 | dependencies = [ |
943 | "bitflags", | 1123 | "bitflags 1.3.2", |
944 | "core-foundation", | 1124 | "core-foundation", |
945 | "core-foundation-sys", | 1125 | "core-foundation-sys", |
946 | "libc", | 1126 | "libc", |
@@ -959,29 +1139,29 @@ dependencies = [ | |||
959 | 1139 | ||
960 | [[package]] | 1140 | [[package]] |
961 | name = "serde" | 1141 | name = "serde" |
962 | version = "1.0.152" | 1142 | version = "1.0.159" |
963 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1143 | source = "registry+https://github.com/rust-lang/crates.io-index" |
964 | checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" | 1144 | checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" |
965 | dependencies = [ | 1145 | dependencies = [ |
966 | "serde_derive", | 1146 | "serde_derive", |
967 | ] | 1147 | ] |
968 | 1148 | ||
969 | [[package]] | 1149 | [[package]] |
970 | name = "serde_derive" | 1150 | name = "serde_derive" |
971 | version = "1.0.152" | 1151 | version = "1.0.159" |
972 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1152 | source = "registry+https://github.com/rust-lang/crates.io-index" |
973 | checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" | 1153 | checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" |
974 | dependencies = [ | 1154 | dependencies = [ |
975 | "proc-macro2", | 1155 | "proc-macro2", |
976 | "quote", | 1156 | "quote", |
977 | "syn", | 1157 | "syn 2.0.13", |
978 | ] | 1158 | ] |
979 | 1159 | ||
980 | [[package]] | 1160 | [[package]] |
981 | name = "serde_json" | 1161 | name = "serde_json" |
982 | version = "1.0.93" | 1162 | version = "1.0.95" |
983 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1163 | source = "registry+https://github.com/rust-lang/crates.io-index" |
984 | checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" | 1164 | checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" |
985 | dependencies = [ | 1165 | dependencies = [ |
986 | "itoa", | 1166 | "itoa", |
987 | "ryu", | 1167 | "ryu", |
@@ -1020,9 +1200,9 @@ dependencies = [ | |||
1020 | 1200 | ||
1021 | [[package]] | 1201 | [[package]] |
1022 | name = "slab" | 1202 | name = "slab" |
1023 | version = "0.4.7" | 1203 | version = "0.4.8" |
1024 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1204 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1025 | checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" | 1205 | checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" |
1026 | dependencies = [ | 1206 | dependencies = [ |
1027 | "autocfg", | 1207 | "autocfg", |
1028 | ] | 1208 | ] |
@@ -1035,19 +1215,36 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" | |||
1035 | 1215 | ||
1036 | [[package]] | 1216 | [[package]] |
1037 | name = "socket2" | 1217 | name = "socket2" |
1038 | version = "0.4.7" | 1218 | version = "0.4.9" |
1039 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1219 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1040 | checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" | 1220 | checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" |
1041 | dependencies = [ | 1221 | dependencies = [ |
1042 | "libc", | 1222 | "libc", |
1043 | "winapi", | 1223 | "winapi", |
1044 | ] | 1224 | ] |
1045 | 1225 | ||
1046 | [[package]] | 1226 | [[package]] |
1227 | name = "strsim" | ||
1228 | version = "0.10.0" | ||
1229 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1230 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" | ||
1231 | |||
1232 | [[package]] | ||
1233 | name = "syn" | ||
1234 | version = "1.0.109" | ||
1235 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1236 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" | ||
1237 | dependencies = [ | ||
1238 | "proc-macro2", | ||
1239 | "quote", | ||
1240 | "unicode-ident", | ||
1241 | ] | ||
1242 | |||
1243 | [[package]] | ||
1047 | name = "syn" | 1244 | name = "syn" |
1048 | version = "1.0.107" | 1245 | version = "2.0.13" |
1049 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1246 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1050 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" | 1247 | checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" |
1051 | dependencies = [ | 1248 | dependencies = [ |
1052 | "proc-macro2", | 1249 | "proc-macro2", |
1053 | "quote", | 1250 | "quote", |
@@ -1056,16 +1253,15 @@ dependencies = [ | |||
1056 | 1253 | ||
1057 | [[package]] | 1254 | [[package]] |
1058 | name = "tempfile" | 1255 | name = "tempfile" |
1059 | version = "3.3.0" | 1256 | version = "3.5.0" |
1060 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1257 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1061 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" | 1258 | checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" |
1062 | dependencies = [ | 1259 | dependencies = [ |
1063 | "cfg-if", | 1260 | "cfg-if", |
1064 | "fastrand", | 1261 | "fastrand", |
1065 | "libc", | 1262 | "redox_syscall 0.3.5", |
1066 | "redox_syscall", | 1263 | "rustix", |
1067 | "remove_dir_all", | 1264 | "windows-sys 0.45.0", |
1068 | "winapi", | ||
1069 | ] | 1265 | ] |
1070 | 1266 | ||
1071 | [[package]] | 1267 | [[package]] |
@@ -1079,22 +1275,22 @@ dependencies = [ | |||
1079 | 1275 | ||
1080 | [[package]] | 1276 | [[package]] |
1081 | name = "thiserror" | 1277 | name = "thiserror" |
1082 | version = "1.0.38" | 1278 | version = "1.0.40" |
1083 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1279 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1084 | checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" | 1280 | checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" |
1085 | dependencies = [ | 1281 | dependencies = [ |
1086 | "thiserror-impl", | 1282 | "thiserror-impl", |
1087 | ] | 1283 | ] |
1088 | 1284 | ||
1089 | [[package]] | 1285 | [[package]] |
1090 | name = "thiserror-impl" | 1286 | name = "thiserror-impl" |
1091 | version = "1.0.38" | 1287 | version = "1.0.40" |
1092 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1093 | checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" | 1289 | checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" |
1094 | dependencies = [ | 1290 | dependencies = [ |
1095 | "proc-macro2", | 1291 | "proc-macro2", |
1096 | "quote", | 1292 | "quote", |
1097 | "syn", | 1293 | "syn 2.0.13", |
1098 | ] | 1294 | ] |
1099 | 1295 | ||
1100 | [[package]] | 1296 | [[package]] |
@@ -1125,14 +1321,13 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" | |||
1125 | 1321 | ||
1126 | [[package]] | 1322 | [[package]] |
1127 | name = "tokio" | 1323 | name = "tokio" |
1128 | version = "1.25.0" | 1324 | version = "1.27.0" |
1129 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1325 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1130 | checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" | 1326 | checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" |
1131 | dependencies = [ | 1327 | dependencies = [ |
1132 | "autocfg", | 1328 | "autocfg", |
1133 | "bytes", | 1329 | "bytes", |
1134 | "libc", | 1330 | "libc", |
1135 | "memchr", | ||
1136 | "mio", | 1331 | "mio", |
1137 | "num_cpus", | 1332 | "num_cpus", |
1138 | "parking_lot", | 1333 | "parking_lot", |
@@ -1140,18 +1335,18 @@ dependencies = [ | |||
1140 | "signal-hook-registry", | 1335 | "signal-hook-registry", |
1141 | "socket2", | 1336 | "socket2", |
1142 | "tokio-macros", | 1337 | "tokio-macros", |
1143 | "windows-sys 0.42.0", | 1338 | "windows-sys 0.45.0", |
1144 | ] | 1339 | ] |
1145 | 1340 | ||
1146 | [[package]] | 1341 | [[package]] |
1147 | name = "tokio-macros" | 1342 | name = "tokio-macros" |
1148 | version = "1.8.2" | 1343 | version = "2.0.0" |
1149 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1344 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1150 | checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" | 1345 | checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" |
1151 | dependencies = [ | 1346 | dependencies = [ |
1152 | "proc-macro2", | 1347 | "proc-macro2", |
1153 | "quote", | 1348 | "quote", |
1154 | "syn", | 1349 | "syn 2.0.13", |
1155 | ] | 1350 | ] |
1156 | 1351 | ||
1157 | [[package]] | 1352 | [[package]] |
@@ -1180,9 +1375,9 @@ dependencies = [ | |||
1180 | 1375 | ||
1181 | [[package]] | 1376 | [[package]] |
1182 | name = "toml" | 1377 | name = "toml" |
1183 | version = "0.7.2" | 1378 | version = "0.7.3" |
1184 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1379 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1185 | checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6" | 1380 | checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" |
1186 | dependencies = [ | 1381 | dependencies = [ |
1187 | "serde", | 1382 | "serde", |
1188 | "serde_spanned", | 1383 | "serde_spanned", |
@@ -1201,15 +1396,15 @@ dependencies = [ | |||
1201 | 1396 | ||
1202 | [[package]] | 1397 | [[package]] |
1203 | name = "toml_edit" | 1398 | name = "toml_edit" |
1204 | version = "0.19.3" | 1399 | version = "0.19.8" |
1205 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1400 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1206 | checksum = "5e6a7712b49e1775fb9a7b998de6635b299237f48b404dde71704f2e0e7f37e5" | 1401 | checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" |
1207 | dependencies = [ | 1402 | dependencies = [ |
1208 | "indexmap", | 1403 | "indexmap", |
1209 | "nom8", | ||
1210 | "serde", | 1404 | "serde", |
1211 | "serde_spanned", | 1405 | "serde_spanned", |
1212 | "toml_datetime", | 1406 | "toml_datetime", |
1407 | "winnow", | ||
1213 | ] | 1408 | ] |
1214 | 1409 | ||
1215 | [[package]] | 1410 | [[package]] |
@@ -1246,15 +1441,15 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" | |||
1246 | 1441 | ||
1247 | [[package]] | 1442 | [[package]] |
1248 | name = "unicode-bidi" | 1443 | name = "unicode-bidi" |
1249 | version = "0.3.10" | 1444 | version = "0.3.13" |
1250 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1445 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1251 | checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" | 1446 | checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" |
1252 | 1447 | ||
1253 | [[package]] | 1448 | [[package]] |
1254 | name = "unicode-ident" | 1449 | name = "unicode-ident" |
1255 | version = "1.0.6" | 1450 | version = "1.0.8" |
1256 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1451 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1257 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" | 1452 | checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" |
1258 | 1453 | ||
1259 | [[package]] | 1454 | [[package]] |
1260 | name = "unicode-normalization" | 1455 | name = "unicode-normalization" |
@@ -1283,6 +1478,12 @@ dependencies = [ | |||
1283 | ] | 1478 | ] |
1284 | 1479 | ||
1285 | [[package]] | 1480 | [[package]] |
1481 | name = "utf8parse" | ||
1482 | version = "0.2.1" | ||
1483 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1484 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" | ||
1485 | |||
1486 | [[package]] | ||
1286 | name = "vcpkg" | 1487 | name = "vcpkg" |
1287 | version = "0.2.15" | 1488 | version = "0.2.15" |
1288 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1489 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1337,7 +1538,7 @@ dependencies = [ | |||
1337 | "once_cell", | 1538 | "once_cell", |
1338 | "proc-macro2", | 1539 | "proc-macro2", |
1339 | "quote", | 1540 | "quote", |
1340 | "syn", | 1541 | "syn 1.0.109", |
1341 | "wasm-bindgen-shared", | 1542 | "wasm-bindgen-shared", |
1342 | ] | 1543 | ] |
1343 | 1544 | ||
@@ -1371,7 +1572,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" | |||
1371 | dependencies = [ | 1572 | dependencies = [ |
1372 | "proc-macro2", | 1573 | "proc-macro2", |
1373 | "quote", | 1574 | "quote", |
1374 | "syn", | 1575 | "syn 1.0.109", |
1375 | "wasm-bindgen-backend", | 1576 | "wasm-bindgen-backend", |
1376 | "wasm-bindgen-shared", | 1577 | "wasm-bindgen-shared", |
1377 | ] | 1578 | ] |
@@ -1437,18 +1638,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1437 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | 1638 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" |
1438 | 1639 | ||
1439 | [[package]] | 1640 | [[package]] |
1641 | name = "windows" | ||
1642 | version = "0.48.0" | ||
1643 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1644 | checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" | ||
1645 | dependencies = [ | ||
1646 | "windows-targets 0.48.0", | ||
1647 | ] | ||
1648 | |||
1649 | [[package]] | ||
1440 | name = "windows-sys" | 1650 | name = "windows-sys" |
1441 | version = "0.42.0" | 1651 | version = "0.42.0" |
1442 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1652 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1443 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" | 1653 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" |
1444 | dependencies = [ | 1654 | dependencies = [ |
1445 | "windows_aarch64_gnullvm", | 1655 | "windows_aarch64_gnullvm 0.42.2", |
1446 | "windows_aarch64_msvc", | 1656 | "windows_aarch64_msvc 0.42.2", |
1447 | "windows_i686_gnu", | 1657 | "windows_i686_gnu 0.42.2", |
1448 | "windows_i686_msvc", | 1658 | "windows_i686_msvc 0.42.2", |
1449 | "windows_x86_64_gnu", | 1659 | "windows_x86_64_gnu 0.42.2", |
1450 | "windows_x86_64_gnullvm", | 1660 | "windows_x86_64_gnullvm 0.42.2", |
1451 | "windows_x86_64_msvc", | 1661 | "windows_x86_64_msvc 0.42.2", |
1452 | ] | 1662 | ] |
1453 | 1663 | ||
1454 | [[package]] | 1664 | [[package]] |
@@ -1457,65 +1667,140 @@ version = "0.45.0" | |||
1457 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1667 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1458 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" | 1668 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" |
1459 | dependencies = [ | 1669 | dependencies = [ |
1460 | "windows-targets", | 1670 | "windows-targets 0.42.2", |
1671 | ] | ||
1672 | |||
1673 | [[package]] | ||
1674 | name = "windows-sys" | ||
1675 | version = "0.48.0" | ||
1676 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1677 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" | ||
1678 | dependencies = [ | ||
1679 | "windows-targets 0.48.0", | ||
1680 | ] | ||
1681 | |||
1682 | [[package]] | ||
1683 | name = "windows-targets" | ||
1684 | version = "0.42.2" | ||
1685 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1686 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" | ||
1687 | dependencies = [ | ||
1688 | "windows_aarch64_gnullvm 0.42.2", | ||
1689 | "windows_aarch64_msvc 0.42.2", | ||
1690 | "windows_i686_gnu 0.42.2", | ||
1691 | "windows_i686_msvc 0.42.2", | ||
1692 | "windows_x86_64_gnu 0.42.2", | ||
1693 | "windows_x86_64_gnullvm 0.42.2", | ||
1694 | "windows_x86_64_msvc 0.42.2", | ||
1461 | ] | 1695 | ] |
1462 | 1696 | ||
1463 | [[package]] | 1697 | [[package]] |
1464 | name = "windows-targets" | 1698 | name = "windows-targets" |
1465 | version = "0.42.1" | 1699 | version = "0.48.0" |
1466 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1700 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1467 | checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" | 1701 | checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" |
1468 | dependencies = [ | 1702 | dependencies = [ |
1469 | "windows_aarch64_gnullvm", | 1703 | "windows_aarch64_gnullvm 0.48.0", |
1470 | "windows_aarch64_msvc", | 1704 | "windows_aarch64_msvc 0.48.0", |
1471 | "windows_i686_gnu", | 1705 | "windows_i686_gnu 0.48.0", |
1472 | "windows_i686_msvc", | 1706 | "windows_i686_msvc 0.48.0", |
1473 | "windows_x86_64_gnu", | 1707 | "windows_x86_64_gnu 0.48.0", |
1474 | "windows_x86_64_gnullvm", | 1708 | "windows_x86_64_gnullvm 0.48.0", |
1475 | "windows_x86_64_msvc", | 1709 | "windows_x86_64_msvc 0.48.0", |
1476 | ] | 1710 | ] |
1477 | 1711 | ||
1478 | [[package]] | 1712 | [[package]] |
1479 | name = "windows_aarch64_gnullvm" | 1713 | name = "windows_aarch64_gnullvm" |
1480 | version = "0.42.1" | 1714 | version = "0.42.2" |
1715 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1716 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" | ||
1717 | |||
1718 | [[package]] | ||
1719 | name = "windows_aarch64_gnullvm" | ||
1720 | version = "0.48.0" | ||
1721 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1722 | checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" | ||
1723 | |||
1724 | [[package]] | ||
1725 | name = "windows_aarch64_msvc" | ||
1726 | version = "0.42.2" | ||
1481 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1727 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1482 | checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" | 1728 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" |
1483 | 1729 | ||
1484 | [[package]] | 1730 | [[package]] |
1485 | name = "windows_aarch64_msvc" | 1731 | name = "windows_aarch64_msvc" |
1486 | version = "0.42.1" | 1732 | version = "0.48.0" |
1487 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1733 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1488 | checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" | 1734 | checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" |
1489 | 1735 | ||
1490 | [[package]] | 1736 | [[package]] |
1491 | name = "windows_i686_gnu" | 1737 | name = "windows_i686_gnu" |
1492 | version = "0.42.1" | 1738 | version = "0.42.2" |
1739 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1740 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" | ||
1741 | |||
1742 | [[package]] | ||
1743 | name = "windows_i686_gnu" | ||
1744 | version = "0.48.0" | ||
1745 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1746 | checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" | ||
1747 | |||
1748 | [[package]] | ||
1749 | name = "windows_i686_msvc" | ||
1750 | version = "0.42.2" | ||
1493 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1751 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1494 | checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" | 1752 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" |
1495 | 1753 | ||
1496 | [[package]] | 1754 | [[package]] |
1497 | name = "windows_i686_msvc" | 1755 | name = "windows_i686_msvc" |
1498 | version = "0.42.1" | 1756 | version = "0.48.0" |
1757 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1758 | checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" | ||
1759 | |||
1760 | [[package]] | ||
1761 | name = "windows_x86_64_gnu" | ||
1762 | version = "0.42.2" | ||
1499 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1763 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1500 | checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" | 1764 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" |
1501 | 1765 | ||
1502 | [[package]] | 1766 | [[package]] |
1503 | name = "windows_x86_64_gnu" | 1767 | name = "windows_x86_64_gnu" |
1504 | version = "0.42.1" | 1768 | version = "0.48.0" |
1505 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1769 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1506 | checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" | 1770 | checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" |
1507 | 1771 | ||
1508 | [[package]] | 1772 | [[package]] |
1509 | name = "windows_x86_64_gnullvm" | 1773 | name = "windows_x86_64_gnullvm" |
1510 | version = "0.42.1" | 1774 | version = "0.42.2" |
1511 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1775 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1512 | checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" | 1776 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" |
1777 | |||
1778 | [[package]] | ||
1779 | name = "windows_x86_64_gnullvm" | ||
1780 | version = "0.48.0" | ||
1781 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1782 | checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" | ||
1783 | |||
1784 | [[package]] | ||
1785 | name = "windows_x86_64_msvc" | ||
1786 | version = "0.42.2" | ||
1787 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1788 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" | ||
1513 | 1789 | ||
1514 | [[package]] | 1790 | [[package]] |
1515 | name = "windows_x86_64_msvc" | 1791 | name = "windows_x86_64_msvc" |
1516 | version = "0.42.1" | 1792 | version = "0.48.0" |
1793 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1794 | checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" | ||
1795 | |||
1796 | [[package]] | ||
1797 | name = "winnow" | ||
1798 | version = "0.4.1" | ||
1517 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1799 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1518 | checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" | 1800 | checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" |
1801 | dependencies = [ | ||
1802 | "memchr", | ||
1803 | ] | ||
1519 | 1804 | ||
1520 | [[package]] | 1805 | [[package]] |
1521 | name = "winreg" | 1806 | name = "winreg" |
@@ -1,6 +1,6 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "modlist" | 2 | name = "modlist" |
3 | version = "0.11.1" | 3 | version = "0.12.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 |
@@ -10,9 +10,11 @@ reqwest = { version = "0.11", features = ["json", "stream"] } | |||
10 | tokio = { version = "1", features = ["full"] } | 10 | tokio = { version = "1", features = ["full"] } |
11 | serde = { version = "1.0", features = ["derive"] } | 11 | serde = { version = "1.0", features = ["derive"] } |
12 | serde_json = "1.0.87" | 12 | serde_json = "1.0.87" |
13 | rusqlite = { version = "0.28.0", features = ["bundled"] } | 13 | rusqlite = { version = "0.29.0", features = ["bundled"] } |
14 | futures-util = "0.3.14" | 14 | futures-util = "0.3.14" |
15 | chrono = "0.4.22" | 15 | chrono = "0.4.22" |
16 | toml = "0.7.2" | 16 | toml = "0.7.2" |
17 | error-chain = "0.12.4" | 17 | error-chain = "0.12.4" |
18 | dirs = "4.0.0" | 18 | dirs = "5.0.0" |
19 | clap = { version = "4.2.1", features = ["derive"] } | ||
20 | clap_complete = "4.2.0" | ||
diff --git a/src/apis/modrinth.rs b/src/apis/modrinth.rs index bb5ee19..9afe7f3 100644 --- a/src/apis/modrinth.rs +++ b/src/apis/modrinth.rs | |||
@@ -2,7 +2,10 @@ use chrono::{DateTime, FixedOffset}; | |||
2 | use reqwest::Client; | 2 | use reqwest::Client; |
3 | use serde::Deserialize; | 3 | use serde::Deserialize; |
4 | 4 | ||
5 | use crate::{Modloader, List, error::{MLE, MLError, ErrorType}}; | 5 | use crate::{ |
6 | error::{ErrorType, MLError, MLE}, | ||
7 | List, Modloader, | ||
8 | }; | ||
6 | 9 | ||
7 | #[derive(Debug, Deserialize, Clone)] | 10 | #[derive(Debug, Deserialize, Clone)] |
8 | pub struct Project { | 11 | pub struct Project { |
@@ -47,7 +50,7 @@ pub struct ModeratorMessage { | |||
47 | pub enum Side { | 50 | pub enum Side { |
48 | required, | 51 | required, |
49 | optional, | 52 | optional, |
50 | unsupported | 53 | unsupported, |
51 | } | 54 | } |
52 | 55 | ||
53 | #[allow(non_camel_case_types)] | 56 | #[allow(non_camel_case_types)] |
@@ -55,7 +58,7 @@ pub enum Side { | |||
55 | pub enum Type { | 58 | pub enum Type { |
56 | r#mod, | 59 | r#mod, |
57 | modpack, | 60 | modpack, |
58 | recourcepack | 61 | recourcepack, |
59 | } | 62 | } |
60 | 63 | ||
61 | #[allow(non_camel_case_types)] | 64 | #[allow(non_camel_case_types)] |
@@ -63,9 +66,11 @@ pub enum Type { | |||
63 | pub enum Status { | 66 | pub enum Status { |
64 | approved, | 67 | approved, |
65 | rejected, | 68 | rejected, |
66 | draft, unlisted, archived, | 69 | draft, |
70 | unlisted, | ||
71 | archived, | ||
67 | processing, | 72 | processing, |
68 | unknown | 73 | unknown, |
69 | } | 74 | } |
70 | 75 | ||
71 | #[derive(Debug, Clone, Deserialize)] | 76 | #[derive(Debug, Clone, Deserialize)] |
@@ -90,7 +95,7 @@ pub struct Version { | |||
90 | pub enum VersionType { | 95 | pub enum VersionType { |
91 | release, | 96 | release, |
92 | beta, | 97 | beta, |
93 | alpha | 98 | alpha, |
94 | } | 99 | } |
95 | 100 | ||
96 | #[derive(Debug, Clone, Deserialize)] | 101 | #[derive(Debug, Clone, Deserialize)] |
@@ -110,22 +115,19 @@ pub struct Hash { | |||
110 | 115 | ||
111 | async fn get(api: &str, path: String) -> Result<Option<Vec<u8>>, Box<dyn std::error::Error>> { | 116 | async fn get(api: &str, path: String) -> Result<Option<Vec<u8>>, Box<dyn std::error::Error>> { |
112 | let url = format!(r#"{}{}"#, api, path); | 117 | let url = format!(r#"{}{}"#, api, path); |
113 | 118 | ||
114 | let client = Client::builder() | 119 | let client = Client::builder() |
115 | .user_agent(format!("fxqnlr/modlistcli/{} ([email protected])", env!("CARGO_PKG_VERSION"))) | 120 | .user_agent(format!( |
121 | "fxqnlr/modlistcli/{} ([email protected])", | ||
122 | env!("CARGO_PKG_VERSION") | ||
123 | )) | ||
116 | .build()?; | 124 | .build()?; |
117 | let res = client.get(url) | 125 | let res = client.get(url).send().await?; |
118 | .send() | 126 | |
119 | .await?; | ||
120 | |||
121 | let mut data: Option<Vec<u8>> = None; | 127 | let mut data: Option<Vec<u8>> = None; |
122 | 128 | ||
123 | if res.status() == 200 { | 129 | if res.status() == 200 { |
124 | data = Some(res | 130 | data = Some(res.bytes().await?.to_vec()); |
125 | .bytes() | ||
126 | .await? | ||
127 | .to_vec() | ||
128 | ); | ||
129 | } | 131 | } |
130 | 132 | ||
131 | Ok(data) | 133 | Ok(data) |
@@ -143,7 +145,7 @@ pub async fn projects(api: &str, ids: Vec<String>) -> Vec<Project> { | |||
143 | let url = format!(r#"projects?ids=["{}"]"#, all); | 145 | let url = format!(r#"projects?ids=["{}"]"#, all); |
144 | 146 | ||
145 | let data = get(api, url).await.unwrap().unwrap(); | 147 | let data = get(api, url).await.unwrap().unwrap(); |
146 | 148 | ||
147 | serde_json::from_slice(&data).unwrap() | 149 | serde_json::from_slice(&data).unwrap() |
148 | } | 150 | } |
149 | 151 | ||
@@ -154,7 +156,10 @@ pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { | |||
154 | Modloader::Fabric => String::from("fabric"), | 156 | Modloader::Fabric => String::from("fabric"), |
155 | }; | 157 | }; |
156 | 158 | ||
157 | let url = format!(r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, id, loaderstr, list.mc_version); | 159 | let url = format!( |
160 | r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, | ||
161 | id, loaderstr, list.mc_version | ||
162 | ); | ||
158 | 163 | ||
159 | let data = get(api, url).await.unwrap(); | 164 | let data = get(api, url).await.unwrap(); |
160 | 165 | ||
@@ -185,7 +190,7 @@ pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> { | |||
185 | times.sort_by_key(|t| t.1); | 190 | times.sort_by_key(|t| t.1); |
186 | times.reverse(); | 191 | times.reverse(); |
187 | Ok(times[0].0.to_string()) | 192 | Ok(times[0].0.to_string()) |
188 | }, | 193 | } |
189 | _ => panic!("available_versions should never be negative"), | 194 | _ => panic!("available_versions should never be negative"), |
190 | } | 195 | } |
191 | } | 196 | } |
@@ -205,16 +210,19 @@ pub struct MCVersion { | |||
205 | } | 210 | } |
206 | 211 | ||
207 | pub async fn get_minecraft_version(api: &str, version: MCVersionType) -> String { | 212 | pub async fn get_minecraft_version(api: &str, version: MCVersionType) -> String { |
208 | let data = get(api, String::from("tag/game_version")).await.unwrap().unwrap(); | 213 | let data = get(api, String::from("tag/game_version")) |
214 | .await | ||
215 | .unwrap() | ||
216 | .unwrap(); | ||
209 | let mc_versions: Vec<MCVersion> = serde_json::from_slice(&data).unwrap(); | 217 | let mc_versions: Vec<MCVersion> = serde_json::from_slice(&data).unwrap(); |
210 | let ver = match version { | 218 | let ver = match version { |
211 | MCVersionType::Release => { | 219 | MCVersionType::Release => { |
212 | let mut i = 0; | 220 | let mut i = 0; |
213 | while !mc_versions[i].major { | 221 | while !mc_versions[i].major { |
214 | i += 1; | 222 | i += 1; |
215 | }; | 223 | } |
216 | &mc_versions[i] | 224 | &mc_versions[i] |
217 | }, | 225 | } |
218 | MCVersionType::Latest => &mc_versions[0], | 226 | MCVersionType::Latest => &mc_versions[0], |
219 | MCVersionType::Specific => { | 227 | MCVersionType::Specific => { |
220 | println!("Not inplemented"); | 228 | println!("Not inplemented"); |
diff --git a/src/commands/download.rs b/src/commands/download.rs index 2714630..9434591 100644 --- a/src/commands/download.rs +++ b/src/commands/download.rs | |||
@@ -1,10 +1,16 @@ | |||
1 | use crate::{files::{get_downloaded_versions, download_versions, delete_version, disable_version, clean_list_dir}, db::{userlist_get_all_current_versions_with_mods, lists_get_all_ids, lists_get}, modrinth::get_raw_versions, error::{MLE, ErrorType, MLError}}; | 1 | use crate::{config::Cfg, get_current_list, List}; |
2 | use crate::{List, get_current_list, config::Cfg, input::Input}; | 2 | use crate::{ |
3 | 3 | db::{lists_get, lists_get_all_ids, userlist_get_all_current_versions_with_mods}, | |
4 | pub async fn download(config: Cfg, input: Input) -> MLE<()> { | 4 | error::{ErrorType, MLError, MLE}, |
5 | files::{ | ||
6 | clean_list_dir, delete_version, disable_version, download_versions, get_downloaded_versions, | ||
7 | }, | ||
8 | modrinth::get_raw_versions, | ||
9 | }; | ||
5 | 10 | ||
11 | pub async fn download(config: Cfg, all_lists: bool, clean: bool, delete_old: bool) -> MLE<()> { | ||
6 | let mut liststack: Vec<List> = vec![]; | 12 | let mut liststack: Vec<List> = vec![]; |
7 | if input.all_lists { | 13 | if all_lists { |
8 | let list_ids = lists_get_all_ids(config.clone())?; | 14 | let list_ids = lists_get_all_ids(config.clone())?; |
9 | for id in list_ids { | 15 | for id in list_ids { |
10 | liststack.push(lists_get(config.clone(), id)?); | 16 | liststack.push(lists_get(config.clone(), id)?); |
@@ -18,7 +24,10 @@ pub async fn download(config: Cfg, input: Input) -> MLE<()> { | |||
18 | for current_list in liststack { | 24 | for current_list in liststack { |
19 | let downloaded_versions = get_downloaded_versions(current_list.clone())?; | 25 | let downloaded_versions = get_downloaded_versions(current_list.clone())?; |
20 | println!("To download: {:#?}", downloaded_versions); | 26 | println!("To download: {:#?}", downloaded_versions); |
21 | let current_version_ids = match userlist_get_all_current_versions_with_mods(config.clone(), String::from(¤t_list.id)) { | 27 | let current_version_ids = match userlist_get_all_current_versions_with_mods( |
28 | config.clone(), | ||
29 | String::from(¤t_list.id), | ||
30 | ) { | ||
22 | Ok(i) => Ok(i), | 31 | Ok(i) => Ok(i), |
23 | Err(e) => Err(MLError::new(ErrorType::DBError, e.to_string().as_str())), | 32 | Err(e) => Err(MLError::new(ErrorType::DBError, e.to_string().as_str())), |
24 | }?; | 33 | }?; |
@@ -33,31 +42,40 @@ pub async fn download(config: Cfg, input: Input) -> MLE<()> { | |||
33 | 42 | ||
34 | let current_download = downloaded_versions.get(&mod_id); | 43 | let current_download = downloaded_versions.get(&mod_id); |
35 | 44 | ||
36 | if current_download.is_none() || input.clean { | 45 | if current_download.is_none() || clean { |
37 | to_download.push(current_version); | 46 | to_download.push(current_version); |
38 | } else { | 47 | } else { |
39 | let downloaded_version = current_download.ok_or("SOMETHING_HAS_REALLY_GONE_WRONG").unwrap(); | 48 | let downloaded_version = current_download |
49 | .ok_or("SOMETHING_HAS_REALLY_GONE_WRONG") | ||
50 | .unwrap(); | ||
40 | if ¤t_version != downloaded_version { | 51 | if ¤t_version != downloaded_version { |
41 | to_disable.push((mod_id.clone(), String::from(downloaded_version))); | 52 | to_disable.push((mod_id.clone(), String::from(downloaded_version))); |
42 | to_download.push(current_version); | 53 | to_download.push(current_version); |
43 | } | 54 | } |
44 | } | 55 | } |
45 | } | 56 | } |
46 | 57 | ||
47 | if input.clean { clean_list_dir(¤t_list)? }; | 58 | if clean { |
59 | clean_list_dir(¤t_list)? | ||
60 | }; | ||
48 | 61 | ||
49 | if !to_download.is_empty() { | 62 | if !to_download.is_empty() { |
50 | download_versions(current_list.clone(), config.clone(), get_raw_versions(&config.apis.modrinth, to_download).await).await?; | 63 | download_versions( |
64 | current_list.clone(), | ||
65 | config.clone(), | ||
66 | get_raw_versions(&config.apis.modrinth, to_download).await, | ||
67 | ) | ||
68 | .await?; | ||
51 | } else { | 69 | } else { |
52 | println!("There are no new versions to download"); | 70 | println!("There are no new versions to download"); |
53 | } | 71 | } |
54 | 72 | ||
55 | if !to_disable.is_empty() { | 73 | if !to_disable.is_empty() { |
56 | for ver in to_disable { | 74 | for ver in to_disable { |
57 | if input.delete_old { | 75 | if delete_old { |
58 | println!("Deleting version {} for mod {}", ver.1, ver.0); | 76 | println!("Deleting version {} for mod {}", ver.1, ver.0); |
59 | delete_version(current_list.clone(), ver.1)?; | 77 | delete_version(current_list.clone(), ver.1)?; |
60 | } else { | 78 | } else { |
61 | disable_version(config.clone(), current_list.clone(), ver.1, ver.0)?; | 79 | disable_version(config.clone(), current_list.clone(), ver.1, ver.0)?; |
62 | }; | 80 | }; |
63 | } | 81 | } |
diff --git a/src/commands/io.rs b/src/commands/io.rs index a3d056f..7f03eec 100644 --- a/src/commands/io.rs +++ b/src/commands/io.rs | |||
@@ -1,12 +1,18 @@ | |||
1 | use serde::{Deserialize, Serialize}; | ||
1 | use std::fs::File; | 2 | use std::fs::File; |
2 | use std::io::prelude::*; | 3 | use std::io::prelude::*; |
3 | use serde::{Serialize, Deserialize}; | ||
4 | 4 | ||
5 | use crate::{input::{Input, IoOptions}, db::{lists_get, userlist_get_all_ids, lists_get_all_ids, lists_insert}, config::Cfg, Modloader, List, devdir, error::MLE, mods_add, IDSelector}; | 5 | use crate::{ |
6 | config::Cfg, | ||
7 | db::{lists_get, lists_get_all_ids, lists_insert, userlist_get_all_ids}, | ||
8 | devdir, | ||
9 | error::MLE, | ||
10 | mod_add, IDSelector, List, Modloader, | ||
11 | }; | ||
6 | 12 | ||
7 | #[derive(Debug, Serialize, Deserialize)] | 13 | #[derive(Debug, Serialize, Deserialize)] |
8 | struct Export { | 14 | struct Export { |
9 | lists: Vec<ExportList> | 15 | lists: Vec<ExportList>, |
10 | } | 16 | } |
11 | 17 | ||
12 | #[derive(Debug, Serialize, Deserialize)] | 18 | #[derive(Debug, Serialize, Deserialize)] |
@@ -20,73 +26,77 @@ struct ExportList { | |||
20 | 26 | ||
21 | impl ExportList { | 27 | impl ExportList { |
22 | pub fn from(config: Cfg, list_id: String, download: bool) -> MLE<Self> { | 28 | pub fn from(config: Cfg, list_id: String, download: bool) -> MLE<Self> { |
23 | |||
24 | let list = lists_get(config.clone(), String::from(&list_id))?; | 29 | let list = lists_get(config.clone(), String::from(&list_id))?; |
25 | 30 | ||
26 | let mut dl_folder = None; | 31 | let mut dl_folder = None; |
27 | if download{ dl_folder = Some(list.download_folder) }; | 32 | if download { |
33 | dl_folder = Some(list.download_folder) | ||
34 | }; | ||
28 | 35 | ||
29 | let mods = userlist_get_all_ids(config, list_id)?.join("|"); | 36 | let mods = userlist_get_all_ids(config, list_id)?.join("|"); |
30 | 37 | ||
31 | Ok(Self { id: list.id, mods, launcher: list.modloader.to_string(), mc_version: list.mc_version, download_folder: dl_folder }) | 38 | Ok(Self { |
39 | id: list.id, | ||
40 | mods, | ||
41 | launcher: list.modloader.to_string(), | ||
42 | mc_version: list.mc_version, | ||
43 | download_folder: dl_folder, | ||
44 | }) | ||
32 | } | 45 | } |
33 | } | 46 | } |
34 | 47 | ||
35 | pub async fn io(config: Cfg, input: Input) -> MLE<()> { | 48 | pub fn export(config: Cfg, list: Option<String>) -> MLE<()> { |
36 | |||
37 | match input.clone().io_options.unwrap() { | ||
38 | IoOptions::Export => { export(config, input)? }, | ||
39 | IoOptions::Import => { import(config, input).await? }, | ||
40 | } | ||
41 | |||
42 | Ok(()) | ||
43 | } | ||
44 | |||
45 | fn export(config: Cfg, input: Input) -> MLE<()> { | ||
46 | let mut list_ids: Vec<String> = vec![]; | 49 | let mut list_ids: Vec<String> = vec![]; |
47 | if input.all_lists { | 50 | if list.is_none() { |
48 | list_ids = lists_get_all_ids(config.clone())?; | 51 | list_ids = lists_get_all_ids(config.clone())?; |
49 | } else { | 52 | } else { |
50 | list_ids.push(lists_get(config.clone(), input.list.unwrap().id)?.id); | 53 | list_ids.push(lists_get(config.clone(), list.unwrap())?.id); |
51 | } | 54 | } |
52 | let mut lists: Vec<ExportList> = vec![]; | 55 | let mut lists: Vec<ExportList> = vec![]; |
53 | for list_id in list_ids { | 56 | for list_id in list_ids { |
54 | lists.push(ExportList::from(config.clone(), list_id, true)?); | 57 | lists.push(ExportList::from(config.clone(), list_id, true)?); |
55 | } | 58 | } |
56 | 59 | ||
57 | let toml = toml::to_string( &Export { lists } )?; | 60 | let toml = toml::to_string(&Export { lists })?; |
58 | 61 | ||
59 | let filestr = dirs::home_dir().unwrap().join("mlexport.toml"); | 62 | let filestr = dirs::home_dir().unwrap().join("mlexport.toml"); |
60 | 63 | ||
61 | let mut file = File::create(devdir(filestr.into_os_string().into_string().unwrap().as_str()))?; | 64 | let mut file = File::create(devdir( |
65 | filestr.into_os_string().into_string().unwrap().as_str(), | ||
66 | ))?; | ||
62 | file.write_all(toml.as_bytes())?; | 67 | file.write_all(toml.as_bytes())?; |
63 | 68 | ||
64 | Ok(()) | 69 | Ok(()) |
65 | } | 70 | } |
66 | 71 | ||
67 | async fn import(config: Cfg, input: Input) -> MLE<()> { | 72 | pub async fn import(config: Cfg, file_str: String, direct_download: bool) -> MLE<()> { |
68 | 73 | let mut file = File::open(file_str)?; | |
69 | let filestr: String = match input.file { | ||
70 | Some(args) => args, | ||
71 | None => devdir(dirs::home_dir().unwrap().join("mlexport.toml").into_os_string().into_string().unwrap().as_str()), | ||
72 | }; | ||
73 | |||
74 | let mut file = File::open(filestr)?; | ||
75 | let mut content = String::new(); | 74 | let mut content = String::new(); |
76 | file.read_to_string(&mut content)?; | 75 | file.read_to_string(&mut content)?; |
77 | let export: Export = toml::from_str(&content)?; | 76 | let export: Export = toml::from_str(&content)?; |
78 | 77 | ||
79 | for exportlist in export.lists { | 78 | for exportlist in export.lists { |
80 | let list = List { id: exportlist.id, mc_version: exportlist.mc_version, modloader: Modloader::from(&exportlist.launcher)?, download_folder: exportlist.download_folder.ok_or("NO_DL").unwrap() }; | 79 | let list = List { |
81 | lists_insert(config.clone(), list.id.clone(), list.mc_version.clone(), list.modloader.clone(), String::from(&list.download_folder))?; | 80 | id: exportlist.id, |
81 | mc_version: exportlist.mc_version, | ||
82 | modloader: Modloader::from(&exportlist.launcher)?, | ||
83 | download_folder: exportlist.download_folder.ok_or("NO_DL").unwrap(), | ||
84 | }; | ||
85 | lists_insert( | ||
86 | config.clone(), | ||
87 | list.id.clone(), | ||
88 | list.mc_version.clone(), | ||
89 | list.modloader.clone(), | ||
90 | String::from(&list.download_folder), | ||
91 | )?; | ||
82 | let mods: Vec<&str> = exportlist.mods.split('|').collect(); | 92 | let mods: Vec<&str> = exportlist.mods.split('|').collect(); |
83 | let mut mod_ids = vec![]; | 93 | let mut mod_ids = vec![]; |
84 | for mod_id in mods { | 94 | for mod_id in mods { |
85 | mod_ids.push(IDSelector::ModificationID(String::from(mod_id))); | 95 | mod_ids.push(IDSelector::ModificationID(String::from(mod_id))); |
86 | }; | 96 | } |
87 | //TODO impl set_version and good direct download | 97 | //TODO impl set_version and good direct download |
88 | //TODO impl all at once, dafuck | 98 | //TODO impl all at once, dafuck |
89 | mods_add(config.clone(), mod_ids, list, input.direct_download, false).await?; | 99 | mod_add(config.clone(), mod_ids, list, direct_download, false).await?; |
90 | } | 100 | } |
91 | Ok(()) | 101 | Ok(()) |
92 | } | 102 | } |
diff --git a/src/commands/list.rs b/src/commands/list.rs index 8e86973..13176f4 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs | |||
@@ -1,4 +1,12 @@ | |||
1 | use crate::{db::{lists_insert, lists_remove, config_change_current_list, config_get_current_list, lists_get, lists_version}, Modloader, config::Cfg, input::{Input, ListOptions}, cmd_update, error::MLE}; | 1 | use crate::{ |
2 | config::Cfg, | ||
3 | db::{ | ||
4 | config_change_current_list, config_get_current_list, lists_get, lists_insert, lists_remove, | ||
5 | lists_version, | ||
6 | }, | ||
7 | error::MLE, | ||
8 | update, Modloader, | ||
9 | }; | ||
2 | 10 | ||
3 | #[derive(Debug, Clone, PartialEq, Eq)] | 11 | #[derive(Debug, Clone, PartialEq, Eq)] |
4 | pub struct List { | 12 | pub struct List { |
@@ -8,60 +16,55 @@ pub struct List { | |||
8 | pub download_folder: String, | 16 | pub download_folder: String, |
9 | } | 17 | } |
10 | 18 | ||
11 | pub async fn list(config: Cfg, input: Input) -> MLE<()> { | ||
12 | |||
13 | match input.clone().list_options.unwrap() { | ||
14 | ListOptions::Add => { | ||
15 | add(config, input) | ||
16 | }, | ||
17 | ListOptions::Change => { | ||
18 | change(config, input) | ||
19 | }, | ||
20 | ListOptions::Remove => { | ||
21 | remove(config, input) | ||
22 | }, | ||
23 | ListOptions::Version => { | ||
24 | version(config, input).await | ||
25 | } | ||
26 | } | ||
27 | } | ||
28 | |||
29 | pub fn get_current_list(config: Cfg) -> MLE<List> { | 19 | pub fn get_current_list(config: Cfg) -> MLE<List> { |
30 | let id = config_get_current_list(config.clone())?; | 20 | let id = config_get_current_list(config.clone())?; |
31 | lists_get(config, id) | 21 | lists_get(config, id) |
32 | } | 22 | } |
33 | 23 | ||
34 | fn add(config: Cfg, input: Input) -> MLE<()> { | 24 | pub fn list_add( |
35 | let id = input.list_id.unwrap(); | 25 | config: Cfg, |
36 | let mc_version = input.list_mcversion.unwrap(); | 26 | id: String, |
37 | let mod_loader = input.modloader.unwrap(); | 27 | mc_version: String, |
38 | let download_folder = input.directory.unwrap(); | 28 | modloader: Modloader, |
39 | lists_insert(config, id, mc_version, mod_loader, download_folder) | 29 | directory: String, |
30 | ) -> MLE<()> { | ||
31 | lists_insert(config, id, mc_version, modloader, directory) | ||
40 | } | 32 | } |
41 | 33 | ||
42 | fn change(config: Cfg, input: Input) -> MLE<()> { | 34 | pub fn list_change(config: Cfg, id: String) -> MLE<()> { |
43 | println!("Change default list to: {}", input.clone().list.unwrap().id); | 35 | //TODO check if list exists |
44 | config_change_current_list(config, input.list.unwrap().id) | 36 | println!("Change default list to: {}", id); |
37 | config_change_current_list(config, id) | ||
45 | } | 38 | } |
46 | 39 | ||
47 | fn remove(config: Cfg, input: Input) -> MLE<()> { | 40 | pub fn list_remove(config: Cfg, id: String) -> MLE<()> { |
48 | lists_remove(config, input.list.unwrap().id) | 41 | lists_remove(config, id) |
49 | } | 42 | } |
50 | 43 | ||
51 | ///Changing the current lists version and updating it | 44 | ///Changing the current lists version and updating it |
52 | /// | 45 | /// |
53 | /// #Arguments | 46 | /// #Arguments |
54 | /// | 47 | /// |
55 | /// * `config` - The current config | 48 | /// * `config` - The current config |
56 | /// * `args` - All args, to extract the new version | 49 | /// * `args` - All args, to extract the new version |
57 | async fn version(config: Cfg, input: Input) -> MLE<()> { | 50 | pub async fn list_version( |
58 | println!("Change version for list {} to minecraft version: {}", input.clone().list.unwrap().id, input.clone().list_mcversion.unwrap()); | 51 | config: Cfg, |
52 | id: String, | ||
53 | mc_version: String, | ||
54 | download: bool, | ||
55 | delete: bool, | ||
56 | ) -> MLE<()> { | ||
57 | println!( | ||
58 | "Change version for list {} to minecraft version: {}", | ||
59 | id, mc_version | ||
60 | ); | ||
59 | 61 | ||
60 | lists_version(config.clone(), input.clone().list.ok_or("").unwrap().id, input.clone().list_mcversion.ok_or("").unwrap())?; | 62 | lists_version(config.clone(), &id, &mc_version)?; |
61 | |||
62 | //Linebreak readability | ||
63 | println!(""); | ||
64 | 63 | ||
65 | println!("Check for updates for new minecraft version in list {}", input.clone().list.unwrap().id); | 64 | println!( |
66 | cmd_update(config, vec![input.list.ok_or("").unwrap()], true, input.direct_download, input.delete_old).await | 65 | "\nCheck for updates for new minecraft version in list {}", |
66 | id | ||
67 | ); | ||
68 | let list = lists_get(config.clone(), id)?; | ||
69 | update(config, vec![list], true, download, delete).await | ||
67 | } | 70 | } |
diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 0d5bd00..1c7c012 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs | |||
@@ -1,13 +1,13 @@ | |||
1 | pub mod modification; | ||
2 | pub mod list; | ||
3 | pub mod update; | ||
4 | pub mod setup; | ||
5 | pub mod download; | 1 | pub mod download; |
6 | pub mod io; | 2 | pub mod io; |
3 | pub mod list; | ||
4 | pub mod modification; | ||
5 | pub mod setup; | ||
6 | pub mod update; | ||
7 | 7 | ||
8 | pub use modification::*; | ||
9 | pub use list::*; | ||
10 | pub use update::*; | ||
11 | pub use setup::*; | ||
12 | pub use download::*; | 8 | pub use download::*; |
13 | pub use io::*; | 9 | pub use io::*; |
10 | pub use list::*; | ||
11 | pub use modification::*; | ||
12 | pub use setup::*; | ||
13 | pub use update::*; | ||
diff --git a/src/commands/modification.rs b/src/commands/modification.rs index 31e50af..ffc4e10 100644 --- a/src/commands/modification.rs +++ b/src/commands/modification.rs | |||
@@ -1,27 +1,19 @@ | |||
1 | use crate::{modrinth::{versions, extract_current_version, Version, projects, get_raw_versions, project}, config::Cfg, db::{mods_insert, userlist_remove, mods_get_id, userlist_insert, userlist_get_all_ids, userlist_get_current_version, lists_get_all_ids, mods_remove}, input::{Input, ModOptions}, files::{delete_version, download_versions}, List, error::{MLE, ErrorType, MLError}}; | 1 | use crate::{ |
2 | config::Cfg, | ||
3 | db::{ | ||
4 | lists_get_all_ids, mods_get_id, mods_insert, mods_remove, userlist_get_all_ids, | ||
5 | userlist_get_current_version, userlist_insert, userlist_remove, | ||
6 | }, | ||
7 | error::{ErrorType, MLError, MLE}, | ||
8 | files::{delete_version, download_versions}, | ||
9 | modrinth::{extract_current_version, get_raw_versions, project, projects, versions, Version}, | ||
10 | List, | ||
11 | }; | ||
2 | 12 | ||
3 | #[derive(Debug, Clone, PartialEq, Eq)] | 13 | #[derive(Debug, Clone, PartialEq, Eq)] |
4 | pub enum IDSelector { | 14 | pub enum IDSelector { |
5 | ModificationID(String), | 15 | ModificationID(String), |
6 | VersionID(String) | 16 | VersionID(String), |
7 | } | ||
8 | |||
9 | pub async fn modification(config: Cfg, input: Input) -> MLE<()> { | ||
10 | match input.clone().mod_options.ok_or("").unwrap() { | ||
11 | ModOptions::Add => { | ||
12 | add(config, input).await | ||
13 | }, | ||
14 | ModOptions::Remove => { | ||
15 | remove(config, input) | ||
16 | }, | ||
17 | } | ||
18 | } | ||
19 | |||
20 | async fn add(config: Cfg, input: Input) -> MLE<()> { | ||
21 | |||
22 | mods_add(config, vec![input.mod_id.unwrap()], input.list.unwrap(), input.direct_download, input.set_version).await?; | ||
23 | |||
24 | Ok(()) | ||
25 | } | 17 | } |
26 | 18 | ||
27 | #[derive(Debug, Clone)] | 19 | #[derive(Debug, Clone)] |
@@ -34,10 +26,16 @@ pub struct ProjectInfo { | |||
34 | pub download_link: String, | 26 | pub download_link: String, |
35 | } | 27 | } |
36 | 28 | ||
37 | pub async fn mods_add(config: Cfg, ids: Vec<IDSelector>, list: List, direct_download: bool, set_version: bool) -> MLE<()> { | 29 | pub async fn mod_add( |
30 | config: Cfg, | ||
31 | ids: Vec<IDSelector>, | ||
32 | list: List, | ||
33 | direct_download: bool, | ||
34 | set_version: bool, | ||
35 | ) -> MLE<()> { | ||
38 | println!("Add mods to {}", list.id); | 36 | println!("Add mods to {}", list.id); |
39 | println!(" └Add mods:"); | 37 | println!(" └Add mods:"); |
40 | 38 | ||
41 | let mut mod_ids: Vec<String> = Vec::new(); | 39 | let mut mod_ids: Vec<String> = Vec::new(); |
42 | let mut ver_ids: Vec<String> = Vec::new(); | 40 | let mut ver_ids: Vec<String> = Vec::new(); |
43 | 41 | ||
@@ -50,11 +48,17 @@ pub async fn mods_add(config: Cfg, ids: Vec<IDSelector>, list: List, direct_down | |||
50 | } | 48 | } |
51 | 49 | ||
52 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); | 50 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); |
53 | if !mod_ids.is_empty() { projectinfo.append(&mut get_mod_infos(config.clone(), mod_ids, list.clone()).await?) }; | 51 | if !mod_ids.is_empty() { |
54 | if !ver_ids.is_empty() { projectinfo.append(&mut get_ver_info(config.clone(), ver_ids).await?) }; | 52 | projectinfo.append(&mut get_mod_infos(config.clone(), mod_ids, list.clone()).await?) |
53 | }; | ||
54 | if !ver_ids.is_empty() { | ||
55 | projectinfo.append(&mut get_ver_info(config.clone(), ver_ids).await?) | ||
56 | }; | ||
57 | |||
58 | if projectinfo.is_empty() { | ||
59 | return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")); | ||
60 | }; | ||
55 | 61 | ||
56 | if projectinfo.is_empty() { return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")) }; | ||
57 | |||
58 | let mut downloadstack: Vec<Version> = Vec::new(); | 62 | let mut downloadstack: Vec<Version> = Vec::new(); |
59 | 63 | ||
60 | //Adding each mod to the lists and downloadstack | 64 | //Adding each mod to the lists and downloadstack |
@@ -63,29 +67,59 @@ pub async fn mods_add(config: Cfg, ids: Vec<IDSelector>, list: List, direct_down | |||
63 | } else { | 67 | } else { |
64 | println!(" └Insert mods in list {} and save infos", list.id); | 68 | println!(" └Insert mods in list {} and save infos", list.id); |
65 | } | 69 | } |
66 | 70 | ||
67 | for project in projectinfo { | 71 | for project in projectinfo { |
68 | let current_version_id = if project.current_version.is_none() { String::from("NONE") } else { project.current_version.clone().unwrap().id }; | 72 | let current_version_id = if project.current_version.is_none() { |
69 | match userlist_insert(config.clone(), &list.id, &project.mod_id, ¤t_version_id, project.clone().applicable_versions, &project.download_link, set_version) { | 73 | String::from("NONE") |
74 | } else { | ||
75 | project.current_version.clone().unwrap().id | ||
76 | }; | ||
77 | match userlist_insert( | ||
78 | config.clone(), | ||
79 | &list.id, | ||
80 | &project.mod_id, | ||
81 | ¤t_version_id, | ||
82 | project.clone().applicable_versions, | ||
83 | &project.download_link, | ||
84 | set_version, | ||
85 | ) { | ||
70 | Err(e) => { | 86 | Err(e) => { |
71 | let expected_err = format!("SQL: UNIQUE constraint failed: {}.mod_id", list.id); | 87 | let expected_err = format!("SQL: UNIQUE constraint failed: {}.mod_id", list.id); |
72 | if e.to_string() == expected_err { Err(MLError::new(ErrorType::ModError, "MOD_ALREADY_ON_SELECTED_LIST")) } else { Err(e) } | 88 | if e.to_string() == expected_err { |
73 | }, | 89 | Err(MLError::new( |
74 | Ok(..) => { Ok(..) }, | 90 | ErrorType::ModError, |
91 | "MOD_ALREADY_ON_SELECTED_LIST", | ||
92 | )) | ||
93 | } else { | ||
94 | Err(e) | ||
95 | } | ||
96 | } | ||
97 | Ok(..) => Ok(..), | ||
75 | }?; | 98 | }?; |
76 | 99 | ||
77 | match mods_insert(config.clone(), &project.mod_id, &project.slug, &project.title) { | 100 | match mods_insert( |
101 | config.clone(), | ||
102 | &project.mod_id, | ||
103 | &project.slug, | ||
104 | &project.title, | ||
105 | ) { | ||
78 | Err(e) => { | 106 | Err(e) => { |
79 | if e.to_string() == "SQL: UNIQUE constraint failed: mods.id" { Ok(..) } else { Err(e) } | 107 | if e.to_string() == "SQL: UNIQUE constraint failed: mods.id" { |
80 | }, | 108 | Ok(..) |
109 | } else { | ||
110 | Err(e) | ||
111 | } | ||
112 | } | ||
81 | Ok(..) => Ok(..), | 113 | Ok(..) => Ok(..), |
82 | }?; | 114 | }?; |
83 | 115 | ||
84 | if project.current_version.is_some() { downloadstack.push(project.current_version.unwrap()) }; | 116 | if project.current_version.is_some() { |
117 | downloadstack.push(project.current_version.unwrap()) | ||
118 | }; | ||
85 | } | 119 | } |
86 | 120 | ||
87 | //Download all the added mods | 121 | //Download all the added mods |
88 | if direct_download { | 122 | if direct_download { |
89 | download_versions(list.clone(), config.clone(), downloadstack).await?; | 123 | download_versions(list.clone(), config.clone(), downloadstack).await?; |
90 | }; | 124 | }; |
91 | 125 | ||
@@ -104,7 +138,12 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<String>, list: List) -> MLE<Vec | |||
104 | for project in m_projects { | 138 | for project in m_projects { |
105 | println!("\t└{}", project.title); | 139 | println!("\t└{}", project.title); |
106 | println!("\t └Get versions"); | 140 | println!("\t └Get versions"); |
107 | let available_versions = versions(&config.apis.modrinth, String::from(&project.id), list.clone()).await; | 141 | let available_versions = versions( |
142 | &config.apis.modrinth, | ||
143 | String::from(&project.id), | ||
144 | list.clone(), | ||
145 | ) | ||
146 | .await; | ||
108 | 147 | ||
109 | let mut available_versions_vec: Vec<String> = Vec::new(); | 148 | let mut available_versions_vec: Vec<String> = Vec::new(); |
110 | let current_version: Option<Version>; | 149 | let current_version: Option<Version>; |
@@ -113,36 +152,63 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<String>, list: List) -> MLE<Vec | |||
113 | let current_id = extract_current_version(available_versions.clone())?; | 152 | let current_id = extract_current_version(available_versions.clone())?; |
114 | println!("\t └Current version: {}", current_id); | 153 | println!("\t └Current version: {}", current_id); |
115 | 154 | ||
116 | current_version = Some(available_versions.clone().into_iter().find(|v| v.id == current_id).unwrap()); | 155 | current_version = Some( |
156 | available_versions | ||
157 | .clone() | ||
158 | .into_iter() | ||
159 | .find(|v| v.id == current_id) | ||
160 | .unwrap(), | ||
161 | ); | ||
117 | 162 | ||
118 | file = current_version.clone().ok_or("").unwrap().files.into_iter().find(|f| f.primary).unwrap().url; | 163 | file = current_version |
164 | .clone() | ||
165 | .ok_or("") | ||
166 | .unwrap() | ||
167 | .files | ||
168 | .into_iter() | ||
169 | .find(|f| f.primary) | ||
170 | .unwrap() | ||
171 | .url; | ||
119 | for ver in available_versions { | 172 | for ver in available_versions { |
120 | available_versions_vec.push(ver.id); | 173 | available_versions_vec.push(ver.id); |
121 | }; | 174 | } |
122 | |||
123 | projectinfo.push(ProjectInfo { mod_id: project.id, slug: project.slug, title: project.title, current_version, applicable_versions: available_versions_vec, download_link: file }) | ||
124 | 175 | ||
176 | projectinfo.push(ProjectInfo { | ||
177 | mod_id: project.id, | ||
178 | slug: project.slug, | ||
179 | title: project.title, | ||
180 | current_version, | ||
181 | applicable_versions: available_versions_vec, | ||
182 | download_link: file, | ||
183 | }) | ||
125 | } else { | 184 | } else { |
126 | println!("\t └There's currently no mod version for your specified target"); | 185 | println!("\t └There's currently no mod version for your specified target"); |
127 | current_version = None; | 186 | current_version = None; |
128 | file = String::from("NONE"); | 187 | file = String::from("NONE"); |
129 | available_versions_vec.push(String::from("NONE")); | 188 | available_versions_vec.push(String::from("NONE")); |
130 | projectinfo.push(ProjectInfo { mod_id: project.id, slug: project.slug, title: project.title, current_version, applicable_versions: available_versions_vec, download_link: file }) | 189 | projectinfo.push(ProjectInfo { |
190 | mod_id: project.id, | ||
191 | slug: project.slug, | ||
192 | title: project.title, | ||
193 | current_version, | ||
194 | applicable_versions: available_versions_vec, | ||
195 | download_link: file, | ||
196 | }) | ||
131 | } | 197 | } |
132 | }; | 198 | } |
133 | 199 | ||
134 | Ok(projectinfo) | 200 | Ok(projectinfo) |
135 | } | 201 | } |
136 | 202 | ||
137 | async fn get_ver_info(config: Cfg, ver_ids: Vec<String>) -> MLE<Vec<ProjectInfo>> { | 203 | async fn get_ver_info(config: Cfg, ver_ids: Vec<String>) -> MLE<Vec<ProjectInfo>> { |
138 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); | 204 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); |
139 | 205 | ||
140 | //Get required information from ver_ids | 206 | //Get required information from ver_ids |
141 | let mut v_versions = get_raw_versions(&config.apis.modrinth, ver_ids).await; | 207 | let mut v_versions = get_raw_versions(&config.apis.modrinth, ver_ids).await; |
142 | let mut v_mod_ids: Vec<String> = Vec::new(); | 208 | let mut v_mod_ids: Vec<String> = Vec::new(); |
143 | for ver in v_versions.clone() { | 209 | for ver in v_versions.clone() { |
144 | v_mod_ids.push(ver.project_id); | 210 | v_mod_ids.push(ver.project_id); |
145 | }; | 211 | } |
146 | let mut v_projects = projects(&config.apis.modrinth, v_mod_ids).await; | 212 | let mut v_projects = projects(&config.apis.modrinth, v_mod_ids).await; |
147 | v_versions.sort_by(|a, b| a.project_id.cmp(&b.project_id)); | 213 | v_versions.sort_by(|a, b| a.project_id.cmp(&b.project_id)); |
148 | v_projects.sort_by(|a, b| a.id.cmp(&b.id)); | 214 | v_projects.sort_by(|a, b| a.id.cmp(&b.id)); |
@@ -150,35 +216,54 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<String>) -> MLE<Vec<ProjectInfo> | |||
150 | for (i, project) in v_projects.into_iter().enumerate() { | 216 | for (i, project) in v_projects.into_iter().enumerate() { |
151 | let version = &v_versions[i]; | 217 | let version = &v_versions[i]; |
152 | println!("\t└{}({})", project.title, version.id); | 218 | println!("\t└{}({})", project.title, version.id); |
153 | let file = version.clone().files.into_iter().find(|f| f.primary).unwrap().url; | 219 | let file = version |
154 | projectinfo.push(ProjectInfo { mod_id: project.id, slug: project.slug, title: project.title, current_version: Some(version.clone()), applicable_versions: vec![String::from(&version.id)], download_link: file }) | 220 | .clone() |
155 | }; | 221 | .files |
222 | .into_iter() | ||
223 | .find(|f| f.primary) | ||
224 | .unwrap() | ||
225 | .url; | ||
226 | projectinfo.push(ProjectInfo { | ||
227 | mod_id: project.id, | ||
228 | slug: project.slug, | ||
229 | title: project.title, | ||
230 | current_version: Some(version.clone()), | ||
231 | applicable_versions: vec![String::from(&version.id)], | ||
232 | download_link: file, | ||
233 | }) | ||
234 | } | ||
156 | Ok(projectinfo) | 235 | Ok(projectinfo) |
157 | } | 236 | } |
158 | 237 | ||
159 | fn remove(config: Cfg, input: Input) -> MLE<()> { | 238 | /// Remove mod from a list |
160 | 239 | /// # Arguments | |
161 | let id = match input.clone().mod_id.unwrap() { | 240 | /// |
162 | IDSelector::ModificationID(id) => id, | 241 | /// * `config` - config struct |
163 | IDSelector::VersionID(..) => return Err(MLError::new(ErrorType::ArgumentError, "NO_MOD_ID")), | 242 | /// * `id` - name, slug or id of the mod |
164 | }; | 243 | /// * `list` - List struct |
165 | 244 | pub fn mod_remove(config: Cfg, id: &str, list: List) -> MLE<()> { | |
166 | let mod_id = mods_get_id(&config.data, &id)?; | 245 | let mod_id = mods_get_id(&config.data, id)?; |
167 | 246 | ||
168 | let version = userlist_get_current_version(config.clone(), input.clone().list.unwrap().id, String::from(&mod_id))?; | 247 | let version = userlist_get_current_version(config.clone(), &list.id, &mod_id)?; |
169 | 248 | ||
170 | userlist_remove(config.clone(), input.clone().list.unwrap().id, String::from(&mod_id))?; | 249 | userlist_remove(config.clone(), &list.id, &mod_id)?; |
171 | delete_version(input.list.unwrap(), version)?; | 250 | delete_version(list, version)?; |
172 | 251 | ||
173 | let list_ids = lists_get_all_ids(config.clone())?; | 252 | let list_ids = lists_get_all_ids(config.clone())?; |
174 | 253 | ||
254 | // Remove mod from main list if not used elsewhere | ||
175 | let mut mod_used = false; | 255 | let mut mod_used = false; |
176 | for id in list_ids { | 256 | for id in list_ids { |
177 | let mods = userlist_get_all_ids(config.clone(), id)?; | 257 | let mods = userlist_get_all_ids(config.clone(), id)?; |
178 | if mods.contains(&mod_id) { mod_used = true; break; }; | 258 | if mods.contains(&mod_id) { |
179 | }; | 259 | mod_used = true; |
260 | break; | ||
261 | }; | ||
262 | } | ||
180 | 263 | ||
181 | if !mod_used { mods_remove(config, mod_id)?; }; | 264 | if !mod_used { |
265 | mods_remove(config, mod_id)?; | ||
266 | }; | ||
182 | 267 | ||
183 | Ok(()) | 268 | Ok(()) |
184 | } | 269 | } |
diff --git a/src/commands/setup.rs b/src/commands/setup.rs index 0161bd7..40e8c0a 100644 --- a/src/commands/setup.rs +++ b/src/commands/setup.rs | |||
@@ -1,14 +1,14 @@ | |||
1 | use std::{fs::File, path::Path}; | 1 | use std::{fs::File, path::Path}; |
2 | 2 | ||
3 | use crate::{config::Cfg, db::db_setup, error::MLE, devdir}; | 3 | use crate::{config::Cfg, db::db_setup, devdir, error::MLE}; |
4 | 4 | ||
5 | pub async fn setup(config: Cfg) -> MLE<()> { | 5 | pub async fn setup(config: Cfg) -> MLE<()> { |
6 | let db_file = devdir(format!("{}/data.db", config.data).as_str()); | 6 | let db_file = devdir(format!("{}/data.db", config.data).as_str()); |
7 | 7 | ||
8 | if !Path::new(&db_file).exists() { | 8 | if !Path::new(&db_file).exists() { |
9 | create(config, db_file)?; | 9 | create(config, db_file)?; |
10 | } | 10 | } |
11 | 11 | ||
12 | /* | 12 | /* |
13 | match s_config_get_version(config.clone()) { | 13 | match s_config_get_version(config.clone()) { |
14 | Ok(ver) => { | 14 | Ok(ver) => { |
@@ -21,12 +21,11 @@ pub async fn setup(config: Cfg) -> MLE<()> { | |||
21 | Err(..) => to_02(config).await? | 21 | Err(..) => to_02(config).await? |
22 | }; | 22 | }; |
23 | */ | 23 | */ |
24 | 24 | ||
25 | Ok(()) | 25 | Ok(()) |
26 | } | 26 | } |
27 | 27 | ||
28 | fn create(config: Cfg, db_file: String) -> MLE<()> { | 28 | fn create(config: Cfg, db_file: String) -> MLE<()> { |
29 | |||
30 | println!("Create database"); | 29 | println!("Create database"); |
31 | 30 | ||
32 | File::create(db_file)?; | 31 | File::create(db_file)?; |
@@ -44,7 +43,7 @@ fn create(config: Cfg, db_file: String) -> MLE<()> { | |||
44 | // let full_list = lists_get(config.clone(), String::from(&list))?; | 43 | // let full_list = lists_get(config.clone(), String::from(&list))?; |
45 | // | 44 | // |
46 | // let versions = userlist_get_all_current_version_ids(config.clone(), full_list.clone().id)?; | 45 | // let versions = userlist_get_all_current_version_ids(config.clone(), full_list.clone().id)?; |
47 | // | 46 | // |
48 | // let raw_versions = get_raw_versions(String::from(&config.apis.modrinth), versions).await; | 47 | // let raw_versions = get_raw_versions(String::from(&config.apis.modrinth), versions).await; |
49 | // | 48 | // |
50 | // for ver in raw_versions { | 49 | // for ver in raw_versions { |
@@ -69,4 +68,3 @@ fn create(config: Cfg, db_file: String) -> MLE<()> { | |||
69 | // } | 68 | // } |
70 | // s_config_update_version(config, String::from("0.4")) | 69 | // s_config_update_version(config, String::from("0.4")) |
71 | //} | 70 | //} |
72 | |||
diff --git a/src/commands/update.rs b/src/commands/update.rs index 75bee39..3d9578b 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs | |||
@@ -1,29 +1,30 @@ | |||
1 | use crate::{config::Cfg, modrinth::{versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, userlist_get_applicable_versions, userlist_change_versions, lists_get_all_ids, lists_get, userlist_get_current_version, userlist_get_set_version, mods_get_info}, List, input::Input, files::{delete_version, download_versions, disable_version, clean_list_dir}, error::{MLE, MLError, ErrorType}}; | 1 | use crate::{ |
2 | 2 | config::Cfg, | |
3 | pub async fn update(config: Cfg, input: Input) -> MLE<()> { | 3 | db::{ |
4 | let mut liststack: Vec<List> = vec![]; | 4 | mods_get_info, userlist_change_versions, userlist_get_all_ids, |
5 | if input.all_lists { | 5 | userlist_get_applicable_versions, userlist_get_current_version, userlist_get_set_version, |
6 | let list_ids = lists_get_all_ids(config.clone())?; | 6 | }, |
7 | for id in list_ids { | 7 | error::{ErrorType, MLError, MLE}, |
8 | liststack.push(lists_get(config.clone(), id)?); | 8 | files::{clean_list_dir, delete_version, disable_version, download_versions}, |
9 | } | 9 | modrinth::{extract_current_version, versions, Version}, |
10 | } else { | 10 | List, |
11 | let current = get_current_list(config.clone())?; | 11 | }; |
12 | println!("Update list {}:", current.id); | 12 | |
13 | liststack.push(current) | 13 | pub async fn update( |
14 | } | 14 | config: Cfg, |
15 | cmd_update(config, liststack, input.clean, input.direct_download, input.delete_old).await | 15 | liststack: Vec<List>, |
16 | } | 16 | clean: bool, |
17 | 17 | direct_download: bool, | |
18 | pub async fn cmd_update(config: Cfg, liststack: Vec<List>, clean: bool, direct_download: bool, delete_old: bool) -> MLE<()> { | 18 | delete_old: bool, |
19 | ) -> MLE<()> { | ||
19 | for current_list in liststack { | 20 | for current_list in liststack { |
20 | let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?; | 21 | let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?; |
21 | 22 | ||
22 | let mut current_versions: Vec<(String, String)> = vec![]; | 23 | let mut current_versions: Vec<(String, String)> = vec![]; |
23 | 24 | ||
24 | println!(" └Update mods:"); | 25 | println!(" └Update mods:"); |
25 | let mut updatestack: Vec<Version> = vec![]; | 26 | let mut updatestack: Vec<Version> = vec![]; |
26 | 27 | ||
27 | for id in mods { | 28 | for id in mods { |
28 | let info = mods_get_info(config.clone(), &id)?; | 29 | let info = mods_get_info(config.clone(), &id)?; |
29 | println!("\t└{}", info.title); | 30 | println!("\t└{}", info.title); |
@@ -34,27 +35,39 @@ pub async fn cmd_update(config: Cfg, liststack: Vec<List>, clean: bool, direct_d | |||
34 | } | 35 | } |
35 | 36 | ||
36 | //Getting current installed version for disable or delete | 37 | //Getting current installed version for disable or delete |
37 | let disable_version = userlist_get_current_version(config.clone(), String::from(¤t_list.id), String::from(&id))?; | 38 | let disable_version = |
39 | userlist_get_current_version(config.clone(), ¤t_list.id, &id)?; | ||
38 | 40 | ||
39 | updatestack.push( | 41 | updatestack.push( |
40 | match specific_update(config.clone(), clean, current_list.clone(), String::from(&id)).await { | 42 | match specific_update( |
43 | config.clone(), | ||
44 | clean, | ||
45 | current_list.clone(), | ||
46 | String::from(&id), | ||
47 | ) | ||
48 | .await | ||
49 | { | ||
41 | Ok(ver) => { | 50 | Ok(ver) => { |
42 | current_versions.push((disable_version, id)); | 51 | current_versions.push((disable_version, id)); |
43 | ver | 52 | ver |
44 | }, | 53 | } |
45 | Err(e) => { | 54 | Err(e) => { |
46 | if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { | 55 | if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { |
47 | println!("\t └No new version found for the specified minecraft version"); | 56 | println!( |
57 | "\t └No new version found for the specified minecraft version" | ||
58 | ); | ||
48 | } else { | 59 | } else { |
49 | return Err(e); | 60 | return Err(e); |
50 | }; | 61 | }; |
51 | continue; | 62 | continue; |
52 | } | 63 | } |
53 | } | 64 | }, |
54 | ) | 65 | ) |
55 | }; | 66 | } |
56 | 67 | ||
57 | if clean { clean_list_dir(¤t_list)?; }; | 68 | if clean { |
69 | clean_list_dir(¤t_list)?; | ||
70 | }; | ||
58 | 71 | ||
59 | if direct_download && !updatestack.is_empty() { | 72 | if direct_download && !updatestack.is_empty() { |
60 | download_versions(current_list.clone(), config.clone(), updatestack).await?; | 73 | download_versions(current_list.clone(), config.clone(), updatestack).await?; |
@@ -65,7 +78,7 @@ pub async fn cmd_update(config: Cfg, liststack: Vec<List>, clean: bool, direct_d | |||
65 | if delete_old { | 78 | if delete_old { |
66 | println!("\t └Delete version {}", ver.0); | 79 | println!("\t └Delete version {}", ver.0); |
67 | delete_version(current_list.clone(), ver.0)?; | 80 | delete_version(current_list.clone(), ver.0)?; |
68 | } else if ver.0 != "NONE" { | 81 | } else if ver.0 != "NONE" { |
69 | println!("\t └Disable version {}", ver.0); | 82 | println!("\t └Disable version {}", ver.0); |
70 | disable_version(config.clone(), current_list.clone(), ver.0, ver.1)?; | 83 | disable_version(config.clone(), current_list.clone(), ver.0, ver.1)?; |
71 | }; | 84 | }; |
@@ -78,10 +91,11 @@ pub async fn cmd_update(config: Cfg, liststack: Vec<List>, clean: bool, direct_d | |||
78 | } | 91 | } |
79 | 92 | ||
80 | async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> MLE<Version> { | 93 | async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> MLE<Version> { |
81 | let applicable_versions = versions(&config.apis.modrinth, String::from(&id), list.clone()).await; | 94 | let applicable_versions = |
82 | 95 | versions(&config.apis.modrinth, String::from(&id), list.clone()).await; | |
96 | |||
83 | let mut versions: Vec<String> = vec![]; | 97 | let mut versions: Vec<String> = vec![]; |
84 | 98 | ||
85 | if !applicable_versions.is_empty() { | 99 | if !applicable_versions.is_empty() { |
86 | for ver in &applicable_versions { | 100 | for ver in &applicable_versions { |
87 | versions.push(String::from(&ver.id)); | 101 | versions.push(String::from(&ver.id)); |
@@ -92,8 +106,14 @@ async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> ML | |||
92 | 106 | ||
93 | let mut current: Vec<Version> = vec![]; | 107 | let mut current: Vec<Version> = vec![]; |
94 | //TODO Split clean and no match | 108 | //TODO Split clean and no match |
95 | if clean || (versions.join("|") != userlist_get_applicable_versions(config.clone(), String::from(&list.id), String::from(&id))?) { | 109 | if clean |
96 | 110 | || (versions.join("|") | |
111 | != userlist_get_applicable_versions( | ||
112 | config.clone(), | ||
113 | String::from(&list.id), | ||
114 | String::from(&id), | ||
115 | )?) | ||
116 | { | ||
97 | let current_str = extract_current_version(applicable_versions.clone())?; | 117 | let current_str = extract_current_version(applicable_versions.clone())?; |
98 | 118 | ||
99 | if clean { | 119 | if clean { |
@@ -104,34 +124,54 @@ async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> ML | |||
104 | }; | 124 | }; |
105 | 125 | ||
106 | //get new versions | 126 | //get new versions |
107 | let current_ver = match applicable_versions.into_iter().find(|ver| ver.id == current_str).ok_or("!no current version in applicable_versions") { | 127 | let current_ver = match applicable_versions |
128 | .into_iter() | ||
129 | .find(|ver| ver.id == current_str) | ||
130 | .ok_or("!no current version in applicable_versions") | ||
131 | { | ||
108 | Ok(v) => Ok(v), | 132 | Ok(v) => Ok(v), |
109 | Err(e) => Err(MLError::new(ErrorType::Other, e)), | 133 | Err(e) => Err(MLError::new(ErrorType::Other, e)), |
110 | }?; | 134 | }?; |
111 | current.push(current_ver.clone()); | 135 | current.push(current_ver.clone()); |
112 | 136 | ||
113 | let link = match current_ver.files.into_iter().find(|f| f.primary).ok_or("!no primary in links") { | 137 | //TODO implement version selection if no primary |
138 | let link = match current_ver | ||
139 | .files | ||
140 | .into_iter() | ||
141 | .find(|f| f.primary) | ||
142 | .ok_or("!no primary in links") | ||
143 | { | ||
114 | Ok(p) => Ok(p), | 144 | Ok(p) => Ok(p), |
115 | Err(e) => Err(MLError::new(ErrorType::Other, e)), | 145 | Err(e) => Err(MLError::new(ErrorType::Other, e)), |
116 | }?.url; | 146 | }? |
147 | .url; | ||
117 | userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id)?; | 148 | userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id)?; |
118 | } | 149 | } |
119 | 150 | ||
120 | if current.is_empty() { return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")) }; | 151 | if current.is_empty() { |
121 | 152 | return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")); | |
153 | }; | ||
154 | |||
122 | //println!(" └✔️"); | 155 | //println!(" └✔️"); |
123 | Ok(current[0].clone()) | 156 | Ok(current[0].clone()) |
124 | } | 157 | } |
125 | 158 | ||
126 | #[tokio::test] | 159 | #[tokio::test] |
127 | async fn download_updates_test() { | 160 | async fn download_updates_test() { |
161 | use crate::{ | ||
162 | modrinth::{Hash, Version, VersionFile, VersionType}, | ||
163 | List, Modloader, | ||
164 | }; | ||
128 | 165 | ||
129 | use crate::{modrinth::{Version, VersionFile, Hash, VersionType}, Modloader, List}; | ||
130 | |||
131 | let config = Cfg::init("modlist.toml").unwrap(); | 166 | let config = Cfg::init("modlist.toml").unwrap(); |
132 | let current_list = List { id: String::from("..."), mc_version: String::from("..."), modloader: Modloader::Fabric, download_folder: String::from("./dev/tests/dl") }; | 167 | let current_list = List { |
133 | 168 | id: String::from("..."), | |
134 | let versions = vec![Version { | 169 | mc_version: String::from("..."), |
170 | modloader: Modloader::Fabric, | ||
171 | download_folder: String::from("./dev/tests/dl"), | ||
172 | }; | ||
173 | |||
174 | let versions = vec![Version { | ||
135 | id: "dEqtGnT9".to_string(), | 175 | id: "dEqtGnT9".to_string(), |
136 | project_id: "kYuIpRLv".to_string(), | 176 | project_id: "kYuIpRLv".to_string(), |
137 | author_id: "Qnt13hO8".to_string(), | 177 | author_id: "Qnt13hO8".to_string(), |
@@ -161,5 +201,7 @@ async fn download_updates_test() { | |||
161 | "fabric".to_string() | 201 | "fabric".to_string() |
162 | ] | 202 | ] |
163 | }]; | 203 | }]; |
164 | assert!(download_versions(current_list, config, versions).await.is_ok()) | 204 | assert!(download_versions(current_list, config, versions) |
205 | .await | ||
206 | .is_ok()) | ||
165 | } | 207 | } |
diff --git a/src/config.rs b/src/config.rs index ded0062..1b54d5f 100644 --- a/src/config.rs +++ b/src/config.rs | |||
@@ -1,8 +1,11 @@ | |||
1 | use std::{fs::File, io::{Read, Write}}; | 1 | use std::{ |
2 | fs::File, | ||
3 | io::{Read, Write}, | ||
4 | }; | ||
2 | 5 | ||
3 | use serde::{Serialize, Deserialize}; | 6 | use serde::{Deserialize, Serialize}; |
4 | 7 | ||
5 | use crate::{error::MLE, devdir}; | 8 | use crate::{devdir, error::MLE}; |
6 | 9 | ||
7 | #[derive(Debug, Clone, Serialize, Deserialize)] | 10 | #[derive(Debug, Clone, Serialize, Deserialize)] |
8 | pub struct Cfg { | 11 | pub struct Cfg { |
@@ -24,10 +27,15 @@ impl Cfg { | |||
24 | Err(err) => { | 27 | Err(err) => { |
25 | if err.kind() == std::io::ErrorKind::NotFound { | 28 | if err.kind() == std::io::ErrorKind::NotFound { |
26 | println!("No config file found, creating one"); | 29 | println!("No config file found, creating one"); |
27 | let default_cfg = Cfg { data: String::from("./"), apis: Apis { modrinth: String::from("https://api.modrinth.com/v2/") } }; | 30 | let default_cfg = Cfg { |
31 | data: String::from("./"), | ||
32 | apis: Apis { | ||
33 | modrinth: String::from("https://api.modrinth.com/v2/"), | ||
34 | }, | ||
35 | }; | ||
28 | let mut file = File::create(devdir(configfile.to_str().unwrap()))?; | 36 | let mut file = File::create(devdir(configfile.to_str().unwrap()))?; |
29 | println!("Created config file"); | 37 | println!("Created config file"); |
30 | file.write_all(&toml::to_string(&default_cfg)?.as_bytes())?; | 38 | file.write_all(toml::to_string(&default_cfg)?.as_bytes())?; |
31 | File::open(devdir(configfile.to_str().unwrap()))? | 39 | File::open(devdir(configfile.to_str().unwrap()))? |
32 | } else { | 40 | } else { |
33 | return Err(err.into()); | 41 | return Err(err.into()); |
@@ -2,17 +2,21 @@ use std::io::{Error, ErrorKind}; | |||
2 | 2 | ||
3 | use rusqlite::Connection; | 3 | use rusqlite::Connection; |
4 | 4 | ||
5 | use crate::{Modloader, config::Cfg, List, devdir, error::{MLE, MLError, ErrorType}}; | 5 | use crate::{ |
6 | config::Cfg, | ||
7 | devdir, | ||
8 | error::{ErrorType, MLError, MLE}, | ||
9 | List, Modloader, | ||
10 | }; | ||
6 | 11 | ||
7 | //MODS | 12 | //MODS |
8 | pub fn mods_insert(config: Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { | 13 | pub fn mods_insert(config: Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { |
9 | |||
10 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 14 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
11 | let connection = Connection::open(data)?; | 15 | let connection = Connection::open(data)?; |
12 | 16 | ||
13 | connection.execute( | 17 | connection.execute( |
14 | "INSERT INTO mods (id, slug, title) VALUES (?1, ?2, ?3)", | 18 | "INSERT INTO mods (id, slug, title) VALUES (?1, ?2, ?3)", |
15 | [id, slug, name.replace('\'', "").as_str()] | 19 | [id, slug, name.replace('\'', "").as_str()], |
16 | )?; | 20 | )?; |
17 | 21 | ||
18 | Ok(()) | 22 | Ok(()) |
@@ -21,13 +25,11 @@ pub fn mods_insert(config: Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { | |||
21 | pub fn mods_get_all_ids(config: Cfg) -> Result<Vec<String>, Box<dyn std::error::Error>> { | 25 | pub fn mods_get_all_ids(config: Cfg) -> Result<Vec<String>, Box<dyn std::error::Error>> { |
22 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 26 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
23 | let connection = Connection::open(data).unwrap(); | 27 | let connection = Connection::open(data).unwrap(); |
24 | 28 | ||
25 | let mut mods: Vec<String> = Vec::new(); | 29 | let mut mods: Vec<String> = Vec::new(); |
26 | 30 | ||
27 | let mut stmt = connection.prepare("SELECT id FROM mods")?; | 31 | let mut stmt = connection.prepare("SELECT id FROM mods")?; |
28 | let id_iter = stmt.query_map([], |row| { | 32 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
29 | row.get::<usize, String>(0) | ||
30 | })?; | ||
31 | 33 | ||
32 | for id in id_iter { | 34 | for id in id_iter { |
33 | mods.push(id?); | 35 | mods.push(id?); |
@@ -49,33 +51,33 @@ pub fn mods_get_all_ids(config: Cfg) -> Result<Vec<String>, Box<dyn std::error:: | |||
49 | /// | 51 | /// |
50 | ///Will return `MLError` when no mod id is found | 52 | ///Will return `MLError` when no mod id is found |
51 | pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { | 53 | pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { |
54 | //TODO check if "slug" is id | ||
55 | |||
52 | let data = devdir(format!("{}/data.db", data).as_str()); | 56 | let data = devdir(format!("{}/data.db", data).as_str()); |
53 | let connection = Connection::open(data)?; | 57 | let connection = Connection::open(data)?; |
54 | 58 | ||
55 | let mut mod_id = String::new(); | 59 | let mut mod_id = String::new(); |
56 | 60 | ||
57 | //get from slug | 61 | //get from slug |
58 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE slug = ?")?; | 62 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE slug = ?")?; |
59 | let id_iter = stmt.query_map([slug], |row| { | 63 | let id_iter = stmt.query_map([slug], |row| row.get::<usize, String>(0))?; |
60 | row.get::<usize, String>(0) | ||
61 | })?; | ||
62 | 64 | ||
63 | for id in id_iter { | 65 | for id in id_iter { |
64 | mod_id = id?; | 66 | mod_id = id?; |
65 | }; | 67 | } |
66 | //get from title if no id found from slug | 68 | //get from title if no id found from slug |
67 | if mod_id.is_empty() { | 69 | if mod_id.is_empty() { |
68 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE title = ?")?; | 70 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE title = ?")?; |
69 | let id_iter = stmt.query_map([slug], |row| { | 71 | let id_iter = stmt.query_map([slug], |row| row.get::<usize, String>(0))?; |
70 | row.get::<usize, String>(0) | ||
71 | })?; | ||
72 | 72 | ||
73 | for id in id_iter { | 73 | for id in id_iter { |
74 | mod_id = id?; | 74 | mod_id = id?; |
75 | }; | 75 | } |
76 | } | 76 | } |
77 | 77 | ||
78 | if mod_id.is_empty() { return Err(MLError::new(ErrorType::DBError, "GI_MOD_NOT_FOUND")) }; | 78 | if mod_id.is_empty() { |
79 | return Err(MLError::new(ErrorType::DBError, "GI_MOD_NOT_FOUND")); | ||
80 | }; | ||
79 | 81 | ||
80 | Ok(mod_id) | 82 | Ok(mod_id) |
81 | } | 83 | } |
@@ -88,17 +90,23 @@ pub struct ModInfo { | |||
88 | pub fn mods_get_info(config: Cfg, id: &str) -> MLE<ModInfo> { | 90 | pub fn mods_get_info(config: Cfg, id: &str) -> MLE<ModInfo> { |
89 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 91 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
90 | let connection = Connection::open(data)?; | 92 | let connection = Connection::open(data)?; |
91 | 93 | ||
92 | let mut mod_info: Option<ModInfo> = None; | 94 | let mut mod_info: Option<ModInfo> = None; |
93 | let mut stmt = connection.prepare("SELECT title, slug FROM mods WHERE id = ?")?; | 95 | let mut stmt = connection.prepare("SELECT title, slug FROM mods WHERE id = ?")?; |
94 | let name_iter = stmt.query_map([id], |row| { | 96 | let name_iter = stmt.query_map([id], |row| { |
95 | Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?]) | 97 | Ok(vec![ |
98 | row.get::<usize, String>(0)?, | ||
99 | row.get::<usize, String>(1)?, | ||
100 | ]) | ||
96 | })?; | 101 | })?; |
97 | 102 | ||
98 | for info in name_iter { | 103 | for info in name_iter { |
99 | let i = info?; | 104 | let i = info?; |
100 | mod_info = Some(ModInfo { title: String::from(&i[0]), slug: String::from(&i[1]) }); | 105 | mod_info = Some(ModInfo { |
101 | }; | 106 | title: String::from(&i[0]), |
107 | slug: String::from(&i[1]), | ||
108 | }); | ||
109 | } | ||
102 | 110 | ||
103 | match mod_info.is_none() { | 111 | match mod_info.is_none() { |
104 | true => Err(MLError::new(ErrorType::DBError, "GN_MOD_NOT_FOUND")), | 112 | true => Err(MLError::new(ErrorType::DBError, "GN_MOD_NOT_FOUND")), |
@@ -107,7 +115,6 @@ pub fn mods_get_info(config: Cfg, id: &str) -> MLE<ModInfo> { | |||
107 | } | 115 | } |
108 | 116 | ||
109 | pub fn mods_remove(config: Cfg, id: String) -> MLE<()> { | 117 | pub fn mods_remove(config: Cfg, id: String) -> MLE<()> { |
110 | |||
111 | println!("Removing mod {} from database", id); | 118 | println!("Removing mod {} from database", id); |
112 | 119 | ||
113 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 120 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
@@ -128,27 +135,42 @@ pub fn mods_get_versions(config: Cfg, mods: Vec<String>) -> MLE<Vec<DBModlistVer | |||
128 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 135 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
129 | let connection = Connection::open(data)?; | 136 | let connection = Connection::open(data)?; |
130 | 137 | ||
131 | if mods.is_empty() { return Err(MLError::new(ErrorType::ArgumentError, "MODS_NO_INPUT")); } | 138 | if mods.is_empty() { |
139 | return Err(MLError::new(ErrorType::ArgumentError, "MODS_NO_INPUT")); | ||
140 | } | ||
132 | 141 | ||
133 | let mut wherestr = String::from("WHERE"); | 142 | let mut wherestr = String::from("WHERE"); |
134 | for (i, id) in mods.iter().enumerate() { | 143 | for (i, id) in mods.iter().enumerate() { |
135 | let mut or = " OR"; | 144 | let mut or = " OR"; |
136 | if i == mods.len() - 1 { or = "" }; | 145 | if i == mods.len() - 1 { |
146 | or = "" | ||
147 | }; | ||
137 | wherestr = format!("{} id = '{}'{}", wherestr, id, or); | 148 | wherestr = format!("{} id = '{}'{}", wherestr, id, or); |
138 | } | 149 | } |
139 | 150 | ||
140 | let mut versionmaps: Vec<DBModlistVersions> = Vec::new(); | 151 | let mut versionmaps: Vec<DBModlistVersions> = Vec::new(); |
141 | let mut stmt = connection.prepare(format!("SELECT id, versions, title FROM mods {}", wherestr).as_str())?; | 152 | let mut stmt = connection |
153 | .prepare(format!("SELECT id, versions, title FROM mods {}", wherestr).as_str())?; | ||
142 | let id_iter = stmt.query_map([], |row| { | 154 | let id_iter = stmt.query_map([], |row| { |
143 | Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?, row.get::<usize, String>(2)?]) | 155 | Ok(vec![ |
156 | row.get::<usize, String>(0)?, | ||
157 | row.get::<usize, String>(1)?, | ||
158 | row.get::<usize, String>(2)?, | ||
159 | ]) | ||
144 | })?; | 160 | })?; |
145 | 161 | ||
146 | for ver in id_iter { | 162 | for ver in id_iter { |
147 | let version = ver?; | 163 | let version = ver?; |
148 | println!("\t({}) Get versions from the database", String::from(&version[2])); | 164 | println!( |
165 | "\t({}) Get versions from the database", | ||
166 | String::from(&version[2]) | ||
167 | ); | ||
149 | //println!("Found versions {} for mod {}", version[1], version[0]); | 168 | //println!("Found versions {} for mod {}", version[1], version[0]); |
150 | versionmaps.push(DBModlistVersions { mod_id: String::from(&version[0]), versions: String::from(&version[1]) }) | 169 | versionmaps.push(DBModlistVersions { |
151 | }; | 170 | mod_id: String::from(&version[0]), |
171 | versions: String::from(&version[1]), | ||
172 | }) | ||
173 | } | ||
152 | 174 | ||
153 | match versionmaps.is_empty() { | 175 | match versionmaps.is_empty() { |
154 | true => Err(MLError::new(ErrorType::DBError, "MODS_MODS_NOT_FOUND")), | 176 | true => Err(MLError::new(ErrorType::DBError, "MODS_MODS_NOT_FOUND")), |
@@ -157,16 +179,37 @@ pub fn mods_get_versions(config: Cfg, mods: Vec<String>) -> MLE<Vec<DBModlistVer | |||
157 | } | 179 | } |
158 | 180 | ||
159 | //userlist | 181 | //userlist |
160 | pub fn userlist_insert(config: Cfg, list_id: &str, mod_id: &str, current_version: &str, applicable_versions: Vec<String>, current_link: &str, set_version: bool) -> MLE<()> { | 182 | pub fn userlist_insert( |
183 | config: Cfg, | ||
184 | list_id: &str, | ||
185 | mod_id: &str, | ||
186 | current_version: &str, | ||
187 | applicable_versions: Vec<String>, | ||
188 | current_link: &str, | ||
189 | set_version: bool, | ||
190 | ) -> MLE<()> { | ||
161 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 191 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
162 | let connection = Connection::open(data)?; | 192 | let connection = Connection::open(data)?; |
163 | 193 | ||
164 | let sv = match set_version { | 194 | let sv = match set_version { |
165 | true => "1", | 195 | true => "1", |
166 | false => "0", | 196 | false => "0", |
167 | }; | 197 | }; |
168 | 198 | ||
169 | connection.execute(format!("INSERT INTO {} VALUES (?1, ?2, ?3, ?4, 'NONE', ?5)", list_id).as_str(), [mod_id, current_version, applicable_versions.join("|").as_str(), current_link, sv])?; | 199 | connection.execute( |
200 | format!( | ||
201 | "INSERT INTO {} VALUES (?1, ?2, ?3, ?4, 'NONE', ?5)", | ||
202 | list_id | ||
203 | ) | ||
204 | .as_str(), | ||
205 | [ | ||
206 | mod_id, | ||
207 | current_version, | ||
208 | applicable_versions.join("|").as_str(), | ||
209 | current_link, | ||
210 | sv, | ||
211 | ], | ||
212 | )?; | ||
170 | 213 | ||
171 | Ok(()) | 214 | Ok(()) |
172 | } | 215 | } |
@@ -177,14 +220,12 @@ pub fn userlist_get_all_ids(config: Cfg, list_id: String) -> MLE<Vec<String>> { | |||
177 | 220 | ||
178 | let mut mod_ids: Vec<String> = Vec::new(); | 221 | let mut mod_ids: Vec<String> = Vec::new(); |
179 | let mut stmt = connection.prepare(format!("SELECT mod_id FROM {}", list_id).as_str())?; | 222 | let mut stmt = connection.prepare(format!("SELECT mod_id FROM {}", list_id).as_str())?; |
180 | let id_iter = stmt.query_map([], |row| { | 223 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
181 | row.get::<usize, String>(0) | ||
182 | })?; | ||
183 | 224 | ||
184 | for id in id_iter { | 225 | for id in id_iter { |
185 | //println!("Found id {:?}", id.as_ref().unwrap()); | 226 | //println!("Found id {:?}", id.as_ref().unwrap()); |
186 | mod_ids.push(id?) | 227 | mod_ids.push(id?) |
187 | }; | 228 | } |
188 | 229 | ||
189 | match mod_ids.is_empty() { | 230 | match mod_ids.is_empty() { |
190 | true => Err(MLError::new(ErrorType::DBError, "NO_MODS")), | 231 | true => Err(MLError::new(ErrorType::DBError, "NO_MODS")), |
@@ -192,29 +233,38 @@ pub fn userlist_get_all_ids(config: Cfg, list_id: String) -> MLE<Vec<String>> { | |||
192 | } | 233 | } |
193 | } | 234 | } |
194 | 235 | ||
195 | 236 | pub fn userlist_remove(config: Cfg, list_id: &str, mod_id: &str) -> MLE<()> { | |
196 | pub fn userlist_remove(config: Cfg, list_id: String, mod_id: String) -> MLE<()> { | ||
197 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 237 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
198 | let connection = Connection::open(data)?; | 238 | let connection = Connection::open(data)?; |
199 | 239 | ||
200 | connection.execute(format!("DELETE FROM {} WHERE mod_id = ?", list_id).as_str(), [mod_id])?; | 240 | connection.execute( |
241 | format!("DELETE FROM {} WHERE mod_id = ?", list_id).as_str(), | ||
242 | [mod_id], | ||
243 | )?; | ||
201 | Ok(()) | 244 | Ok(()) |
202 | } | 245 | } |
203 | 246 | ||
204 | 247 | pub fn userlist_get_applicable_versions( | |
205 | pub fn userlist_get_applicable_versions(config: Cfg, list_id: String, mod_id: String) -> MLE<String> { | 248 | config: Cfg, |
249 | list_id: String, | ||
250 | mod_id: String, | ||
251 | ) -> MLE<String> { | ||
206 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 252 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
207 | let connection = Connection::open(data).unwrap(); | 253 | let connection = Connection::open(data).unwrap(); |
208 | 254 | ||
209 | let mut version: String = String::new(); | 255 | let mut version: String = String::new(); |
210 | let mut stmt = connection.prepare(format!("SELECT applicable_versions FROM {} WHERE mod_id = ?", list_id).as_str())?; | 256 | let mut stmt = connection.prepare( |
211 | let ver_iter = stmt.query_map([mod_id], |row| { | 257 | format!( |
212 | row.get::<usize, String>(0) | 258 | "SELECT applicable_versions FROM {} WHERE mod_id = ?", |
213 | })?; | 259 | list_id |
260 | ) | ||
261 | .as_str(), | ||
262 | )?; | ||
263 | let ver_iter = stmt.query_map([mod_id], |row| row.get::<usize, String>(0))?; | ||
214 | 264 | ||
215 | for ver in ver_iter { | 265 | for ver in ver_iter { |
216 | version = ver?; | 266 | version = ver?; |
217 | }; | 267 | } |
218 | 268 | ||
219 | match version.is_empty() { | 269 | match version.is_empty() { |
220 | true => Err(MLError::new(ErrorType::DBError, "GAV_MOD_NOT_FOUND")), | 270 | true => Err(MLError::new(ErrorType::DBError, "GAV_MOD_NOT_FOUND")), |
@@ -222,39 +272,47 @@ pub fn userlist_get_applicable_versions(config: Cfg, list_id: String, mod_id: St | |||
222 | } | 272 | } |
223 | } | 273 | } |
224 | 274 | ||
225 | pub fn userlist_get_all_applicable_versions_with_mods(config: Cfg, list_id: String) -> MLE<Vec<(String, String)>> { | 275 | pub fn userlist_get_all_applicable_versions_with_mods( |
276 | config: Cfg, | ||
277 | list_id: String, | ||
278 | ) -> MLE<Vec<(String, String)>> { | ||
226 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 279 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
227 | let connection = Connection::open(data)?; | 280 | let connection = Connection::open(data)?; |
228 | 281 | ||
229 | let mut versions: Vec<(String, String)> = Vec::new(); | 282 | let mut versions: Vec<(String, String)> = Vec::new(); |
230 | let mut stmt = connection.prepare(format!("SELECT mod_id, applicable_versions FROM {}", list_id).as_str())?; | 283 | let mut stmt = connection |
284 | .prepare(format!("SELECT mod_id, applicable_versions FROM {}", list_id).as_str())?; | ||
231 | let id_iter = stmt.query_map([], |row| { | 285 | let id_iter = stmt.query_map([], |row| { |
232 | Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?]) | 286 | Ok(vec![ |
287 | row.get::<usize, String>(0)?, | ||
288 | row.get::<usize, String>(1)?, | ||
289 | ]) | ||
233 | })?; | 290 | })?; |
234 | 291 | ||
235 | for ver in id_iter { | 292 | for ver in id_iter { |
236 | let out = ver?; | 293 | let out = ver?; |
237 | versions.push((out[0].to_owned(), out[1].to_owned())); | 294 | versions.push((out[0].to_owned(), out[1].to_owned())); |
238 | }; | 295 | } |
239 | 296 | ||
240 | if versions.is_empty() { return Err(MLError::new(ErrorType::DBError, "NO_MODS_ON_LIST")); }; | 297 | if versions.is_empty() { |
298 | return Err(MLError::new(ErrorType::DBError, "NO_MODS_ON_LIST")); | ||
299 | }; | ||
241 | 300 | ||
242 | Ok(versions) | 301 | Ok(versions) |
243 | } | 302 | } |
244 | 303 | ||
245 | pub fn userlist_get_current_version(config: Cfg, list_id: String, mod_id: String) -> MLE<String> { | 304 | pub fn userlist_get_current_version(config: Cfg, list_id: &str, mod_id: &str) -> MLE<String> { |
246 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 305 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
247 | let connection = Connection::open(data).unwrap(); | 306 | let connection = Connection::open(data).unwrap(); |
248 | 307 | ||
249 | let mut version: String = String::new(); | 308 | let mut version: String = String::new(); |
250 | let mut stmt = connection.prepare(format!("SELECT current_version FROM {} WHERE mod_id = ?", list_id).as_str())?; | 309 | let mut stmt = connection |
251 | let ver_iter = stmt.query_map([&mod_id], |row| { | 310 | .prepare(format!("SELECT current_version FROM {} WHERE mod_id = ?", list_id).as_str())?; |
252 | row.get::<usize, String>(0) | 311 | let ver_iter = stmt.query_map([&mod_id], |row| row.get::<usize, String>(0))?; |
253 | })?; | ||
254 | 312 | ||
255 | for ver in ver_iter { | 313 | for ver in ver_iter { |
256 | version = ver?; | 314 | version = ver?; |
257 | }; | 315 | } |
258 | 316 | ||
259 | match version.is_empty() { | 317 | match version.is_empty() { |
260 | true => Err(MLError::new(ErrorType::DBError, "GCV_MOD_NOT_FOUND")), | 318 | true => Err(MLError::new(ErrorType::DBError, "GCV_MOD_NOT_FOUND")), |
@@ -262,63 +320,88 @@ pub fn userlist_get_current_version(config: Cfg, list_id: String, mod_id: String | |||
262 | } | 320 | } |
263 | } | 321 | } |
264 | 322 | ||
265 | pub fn userlist_get_all_current_version_ids(config: Cfg, list_id: String) -> Result<Vec<String>, Box<dyn std::error::Error>> { | 323 | pub fn userlist_get_all_current_version_ids( |
324 | config: Cfg, | ||
325 | list_id: String, | ||
326 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { | ||
266 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 327 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
267 | let connection = Connection::open(data)?; | 328 | let connection = Connection::open(data)?; |
268 | 329 | ||
269 | let mut versions: Vec<String> = Vec::new(); | 330 | let mut versions: Vec<String> = Vec::new(); |
270 | let mut stmt = connection.prepare(format!("SELECT current_version FROM {}", list_id).as_str())?; | 331 | let mut stmt = |
271 | let id_iter = stmt.query_map([], |row| { | 332 | connection.prepare(format!("SELECT current_version FROM {}", list_id).as_str())?; |
272 | row.get::<usize, String>(0) | 333 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
273 | })?; | ||
274 | 334 | ||
275 | for id in id_iter { | 335 | for id in id_iter { |
276 | versions.push(id?); | 336 | versions.push(id?); |
277 | }; | 337 | } |
278 | 338 | ||
279 | if versions.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; | 339 | if versions.is_empty() { |
340 | return Err(Box::new(std::io::Error::new( | ||
341 | ErrorKind::Other, | ||
342 | "NO_MODS_ON_LIST", | ||
343 | ))); | ||
344 | }; | ||
280 | 345 | ||
281 | Ok(versions) | 346 | Ok(versions) |
282 | } | 347 | } |
283 | 348 | ||
284 | pub fn userlist_get_all_current_versions_with_mods(config: Cfg, list_id: String) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> { | 349 | pub fn userlist_get_all_current_versions_with_mods( |
350 | config: Cfg, | ||
351 | list_id: String, | ||
352 | ) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> { | ||
285 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 353 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
286 | let connection = Connection::open(data)?; | 354 | let connection = Connection::open(data)?; |
287 | 355 | ||
288 | let mut versions: Vec<(String, String)> = Vec::new(); | 356 | let mut versions: Vec<(String, String)> = Vec::new(); |
289 | let mut stmt = connection.prepare(format!("SELECT mod_id, current_version FROM {}", list_id).as_str())?; | 357 | let mut stmt = |
358 | connection.prepare(format!("SELECT mod_id, current_version FROM {}", list_id).as_str())?; | ||
290 | let id_iter = stmt.query_map([], |row| { | 359 | let id_iter = stmt.query_map([], |row| { |
291 | Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?]) | 360 | Ok(vec![ |
361 | row.get::<usize, String>(0)?, | ||
362 | row.get::<usize, String>(1)?, | ||
363 | ]) | ||
292 | })?; | 364 | })?; |
293 | 365 | ||
294 | for ver in id_iter { | 366 | for ver in id_iter { |
295 | let out = ver?; | 367 | let out = ver?; |
296 | versions.push((out[0].to_owned(), out[1].to_owned())); | 368 | versions.push((out[0].to_owned(), out[1].to_owned())); |
297 | }; | 369 | } |
298 | 370 | ||
299 | if versions.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; | 371 | if versions.is_empty() { |
372 | return Err(Box::new(std::io::Error::new( | ||
373 | ErrorKind::Other, | ||
374 | "NO_MODS_ON_LIST", | ||
375 | ))); | ||
376 | }; | ||
300 | 377 | ||
301 | Ok(versions) | 378 | Ok(versions) |
302 | } | 379 | } |
303 | 380 | ||
304 | pub fn userlist_get_set_version(config:Cfg, list_id: &str, mod_id: &str) -> MLE<bool> { | 381 | pub fn userlist_get_set_version(config: Cfg, list_id: &str, mod_id: &str) -> MLE<bool> { |
305 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 382 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
306 | let connection = Connection::open(data).unwrap(); | 383 | let connection = Connection::open(data).unwrap(); |
307 | 384 | ||
308 | let mut set_version: bool = false; | 385 | let mut set_version: bool = false; |
309 | let mut stmt = connection.prepare(format!("SELECT set_version FROM {} WHERE mod_id = ?", list_id).as_str())?; | 386 | let mut stmt = connection |
310 | let ver_iter = stmt.query_map([&mod_id], |row| { | 387 | .prepare(format!("SELECT set_version FROM {} WHERE mod_id = ?", list_id).as_str())?; |
311 | row.get::<usize, bool>(0) | 388 | let ver_iter = stmt.query_map([&mod_id], |row| row.get::<usize, bool>(0))?; |
312 | })?; | ||
313 | 389 | ||
314 | for ver in ver_iter { | 390 | for ver in ver_iter { |
315 | set_version = ver?; | 391 | set_version = ver?; |
316 | }; | 392 | } |
317 | 393 | ||
318 | Ok(set_version) | 394 | Ok(set_version) |
319 | } | 395 | } |
320 | 396 | ||
321 | pub fn userlist_change_versions(config: Cfg, list_id: String, current_version: String, versions: String, link: String, mod_id: String) -> MLE<()> { | 397 | pub fn userlist_change_versions( |
398 | config: Cfg, | ||
399 | list_id: String, | ||
400 | current_version: String, | ||
401 | versions: String, | ||
402 | link: String, | ||
403 | mod_id: String, | ||
404 | ) -> MLE<()> { | ||
322 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 405 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
323 | let connection = Connection::open(data)?; | 406 | let connection = Connection::open(data)?; |
324 | 407 | ||
@@ -326,33 +409,45 @@ pub fn userlist_change_versions(config: Cfg, list_id: String, current_version: S | |||
326 | Ok(()) | 409 | Ok(()) |
327 | } | 410 | } |
328 | 411 | ||
329 | pub fn userlist_add_disabled_versions(config: Cfg, list_id: String, disabled_version: String, mod_id: String) -> MLE<()> { | 412 | pub fn userlist_add_disabled_versions( |
413 | config: Cfg, | ||
414 | list_id: String, | ||
415 | disabled_version: String, | ||
416 | mod_id: String, | ||
417 | ) -> MLE<()> { | ||
330 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 418 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
331 | let connection = Connection::open(data)?; | 419 | let connection = Connection::open(data)?; |
332 | 420 | ||
333 | let currently_disabled_versions = userlist_get_disabled_versions(config, String::from(&list_id), String::from(&mod_id))?; | 421 | let currently_disabled_versions = |
334 | let disabled_versions = match currently_disabled_versions == "NONE" { | 422 | userlist_get_disabled_versions(config, String::from(&list_id), String::from(&mod_id))?; |
423 | let disabled_versions = match currently_disabled_versions == "NONE" { | ||
335 | true => disabled_version, | 424 | true => disabled_version, |
336 | false => format!("{}|{}", currently_disabled_versions, disabled_version), | 425 | false => format!("{}|{}", currently_disabled_versions, disabled_version), |
337 | }; | 426 | }; |
338 | 427 | ||
339 | connection.execute(format!("UPDATE {} SET disabled_versions = ?1 WHERE mod_id = ?2", list_id).as_str(), [disabled_versions, mod_id])?; | 428 | connection.execute( |
429 | format!( | ||
430 | "UPDATE {} SET disabled_versions = ?1 WHERE mod_id = ?2", | ||
431 | list_id | ||
432 | ) | ||
433 | .as_str(), | ||
434 | [disabled_versions, mod_id], | ||
435 | )?; | ||
340 | Ok(()) | 436 | Ok(()) |
341 | } | 437 | } |
342 | 438 | ||
343 | pub fn userlist_get_disabled_versions(config:Cfg, list_id: String, mod_id: String) -> MLE<String> { | 439 | pub fn userlist_get_disabled_versions(config: Cfg, list_id: String, mod_id: String) -> MLE<String> { |
344 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 440 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
345 | let connection = Connection::open(data).unwrap(); | 441 | let connection = Connection::open(data).unwrap(); |
346 | 442 | ||
347 | let mut version: String = String::new(); | 443 | let mut version: String = String::new(); |
348 | let mut stmt = connection.prepare(format!("SELECT disabled_versions FROM {} WHERE mod_id = ?", list_id).as_str())?; | 444 | let mut stmt = connection |
349 | let ver_iter = stmt.query_map([mod_id], |row| { | 445 | .prepare(format!("SELECT disabled_versions FROM {} WHERE mod_id = ?", list_id).as_str())?; |
350 | row.get::<usize, String>(0) | 446 | let ver_iter = stmt.query_map([mod_id], |row| row.get::<usize, String>(0))?; |
351 | })?; | ||
352 | 447 | ||
353 | for ver in ver_iter { | 448 | for ver in ver_iter { |
354 | version = ver?; | 449 | version = ver?; |
355 | }; | 450 | } |
356 | 451 | ||
357 | match version.is_empty() { | 452 | match version.is_empty() { |
358 | true => Err(MLError::new(ErrorType::DBError, "GDV_MOD_NOT_FOUND")), | 453 | true => Err(MLError::new(ErrorType::DBError, "GDV_MOD_NOT_FOUND")), |
@@ -360,36 +455,57 @@ pub fn userlist_get_disabled_versions(config:Cfg, list_id: String, mod_id: Strin | |||
360 | } | 455 | } |
361 | } | 456 | } |
362 | 457 | ||
363 | pub fn userlist_get_all_downloads(config: Cfg, list_id: String) -> Result<Vec<String>, Box<dyn std::error::Error>> { | 458 | pub fn userlist_get_all_downloads( |
459 | config: Cfg, | ||
460 | list_id: String, | ||
461 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { | ||
364 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 462 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
365 | let connection = Connection::open(data).unwrap(); | 463 | let connection = Connection::open(data).unwrap(); |
366 | 464 | ||
367 | let mut links: Vec<String> = Vec::new(); | 465 | let mut links: Vec<String> = Vec::new(); |
368 | let mut stmt = connection.prepare(format!("SELECT current_download FROM {}", list_id).as_str())?; | 466 | let mut stmt = |
369 | let link_iter = stmt.query_map([], |row| { | 467 | connection.prepare(format!("SELECT current_download FROM {}", list_id).as_str())?; |
370 | row.get::<usize, String>(0) | 468 | let link_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
371 | })?; | ||
372 | 469 | ||
373 | for link in link_iter { | 470 | for link in link_iter { |
374 | let l = link?; | 471 | let l = link?; |
375 | println!("Found link {}", String::from(&l)); | 472 | println!("Found link {}", String::from(&l)); |
376 | links.push(l) | 473 | links.push(l) |
377 | }; | 474 | } |
378 | 475 | ||
379 | if links.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; | 476 | if links.is_empty() { |
477 | return Err(Box::new(std::io::Error::new( | ||
478 | ErrorKind::Other, | ||
479 | "NO_MODS_ON_LIST", | ||
480 | ))); | ||
481 | }; | ||
380 | 482 | ||
381 | Ok(links) | 483 | Ok(links) |
382 | } | 484 | } |
383 | 485 | ||
384 | //lists | 486 | //lists |
385 | ///Inserts into lists table and creates new table | 487 | ///Inserts into lists table and creates new table |
386 | pub fn lists_insert(config: Cfg, id: String, mc_version: String, mod_loader: Modloader, download_folder: String) -> MLE<()> { | 488 | pub fn lists_insert( |
489 | config: Cfg, | ||
490 | id: String, | ||
491 | mc_version: String, | ||
492 | mod_loader: Modloader, | ||
493 | download_folder: String, | ||
494 | ) -> MLE<()> { | ||
387 | println!("Creating list {}", id); | 495 | println!("Creating list {}", id); |
388 | 496 | ||
389 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 497 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
390 | let connection = Connection::open(data)?; | 498 | let connection = Connection::open(data)?; |
391 | 499 | ||
392 | connection.execute("INSERT INTO lists VALUES (?1, ?2, ?3, ?4)", [id.clone(), mc_version, mod_loader.to_string(), download_folder])?; | 500 | connection.execute( |
501 | "INSERT INTO lists VALUES (?1, ?2, ?3, ?4)", | ||
502 | [ | ||
503 | id.clone(), | ||
504 | mc_version, | ||
505 | mod_loader.to_string(), | ||
506 | download_folder, | ||
507 | ], | ||
508 | )?; | ||
393 | 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(), [])?; | 509 | 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(), [])?; |
394 | 510 | ||
395 | Ok(()) | 511 | Ok(()) |
@@ -408,44 +524,62 @@ pub fn lists_get(config: Cfg, list_id: String) -> MLE<List> { | |||
408 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 524 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
409 | let connection = Connection::open(data).unwrap(); | 525 | let connection = Connection::open(data).unwrap(); |
410 | 526 | ||
411 | let mut list = List { id: String::new(), mc_version: String::new(), modloader: Modloader::Fabric, download_folder: String::new() }; | 527 | let mut list = List { |
412 | let mut stmt = connection.prepare("SELECT mc_version, modloader, download_folder FROM lists WHERE id = ?")?; | 528 | id: String::new(), |
529 | mc_version: String::new(), | ||
530 | modloader: Modloader::Fabric, | ||
531 | download_folder: String::new(), | ||
532 | }; | ||
533 | let mut stmt = connection | ||
534 | .prepare("SELECT mc_version, modloader, download_folder FROM lists WHERE id = ?")?; | ||
413 | 535 | ||
414 | let list_iter = stmt.query_map([&list_id], |row| { | 536 | let list_iter = stmt.query_map([&list_id], |row| { |
415 | Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?, row.get::<usize, String>(2)?]) | 537 | Ok(vec![ |
538 | row.get::<usize, String>(0)?, | ||
539 | row.get::<usize, String>(1)?, | ||
540 | row.get::<usize, String>(2)?, | ||
541 | ]) | ||
416 | })?; | 542 | })?; |
417 | 543 | ||
418 | for l in list_iter { | 544 | for l in list_iter { |
419 | let li = l?; | 545 | let li = l?; |
420 | list = List { id: String::from(&list_id), mc_version: String::from(&li[0]), modloader: Modloader::from(&li[1])?, download_folder: String::from(&li[2]) }; | 546 | list = List { |
421 | }; | 547 | id: String::from(&list_id), |
548 | mc_version: String::from(&li[0]), | ||
549 | modloader: Modloader::from(&li[1])?, | ||
550 | download_folder: String::from(&li[2]), | ||
551 | }; | ||
552 | } | ||
553 | |||
554 | if list.id.is_empty() { | ||
555 | return Err(MLError::new(ErrorType::DBError, "LIST_NOT_FOUND")); | ||
556 | } | ||
422 | 557 | ||
423 | if list.id.is_empty() { return Err(MLError::new(ErrorType::DBError, "LIST_NOT_FOUND")); } | ||
424 | |||
425 | Ok(list) | 558 | Ok(list) |
426 | } | 559 | } |
427 | 560 | ||
428 | pub fn lists_version(config: Cfg, list_id: String, version: String) -> MLE<()> { | 561 | pub fn lists_version(config: Cfg, list_id: &str, version: &str) -> MLE<()> { |
429 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 562 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
430 | let connection = Connection::open(data).unwrap(); | 563 | let connection = Connection::open(data).unwrap(); |
431 | 564 | ||
432 | connection.execute("UPDATE lists SET mc_version = ? WHERE id = ?", [version, list_id])?; | 565 | connection.execute( |
566 | "UPDATE lists SET mc_version = ? WHERE id = ?", | ||
567 | [version, list_id], | ||
568 | )?; | ||
433 | Ok(()) | 569 | Ok(()) |
434 | } | 570 | } |
435 | 571 | ||
436 | pub fn lists_get_all_ids(config: Cfg) -> MLE<Vec<String>> { | 572 | pub fn lists_get_all_ids(config: Cfg) -> MLE<Vec<String>> { |
437 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 573 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
438 | let connection = Connection::open(data).unwrap(); | 574 | let connection = Connection::open(data).unwrap(); |
439 | 575 | ||
440 | let mut list_ids: Vec<String> = Vec::new(); | 576 | let mut list_ids: Vec<String> = Vec::new(); |
441 | let mut stmt = connection.prepare("SELECT id FROM lists")?; | 577 | let mut stmt = connection.prepare("SELECT id FROM lists")?; |
442 | let id_iter = stmt.query_map([], |row| { | 578 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
443 | row.get::<usize, String>(0) | ||
444 | })?; | ||
445 | 579 | ||
446 | for id in id_iter { | 580 | for id in id_iter { |
447 | list_ids.push(id?) | 581 | list_ids.push(id?) |
448 | }; | 582 | } |
449 | 583 | ||
450 | match list_ids.is_empty() { | 584 | match list_ids.is_empty() { |
451 | true => Err(MLError::new(ErrorType::DBError, "NO_LISTS")), | 585 | true => Err(MLError::new(ErrorType::DBError, "NO_LISTS")), |
@@ -458,35 +592,50 @@ pub fn config_change_current_list(config: Cfg, id: String) -> MLE<()> { | |||
458 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 592 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
459 | let connection = Connection::open(data)?; | 593 | let connection = Connection::open(data)?; |
460 | 594 | ||
461 | connection.execute("UPDATE user_config SET value = ? WHERE id = 'current_list'", [id])?; | 595 | connection.execute( |
596 | "UPDATE user_config SET value = ? WHERE id = 'current_list'", | ||
597 | [id], | ||
598 | )?; | ||
462 | Ok(()) | 599 | Ok(()) |
463 | } | 600 | } |
464 | 601 | ||
465 | pub fn config_get_current_list(config: Cfg) -> MLE<String> { | 602 | pub fn config_get_current_list(config: Cfg) -> MLE<String> { |
466 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 603 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
467 | let connection = Connection::open(data).unwrap(); | 604 | let connection = Connection::open(data).unwrap(); |
468 | 605 | ||
469 | let mut list_id = String::new(); | 606 | let mut list_id = String::new(); |
470 | let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'current_list'")?; | 607 | let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'current_list'")?; |
471 | let list_iter = stmt.query_map([], |row| { | 608 | let list_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
472 | row.get::<usize, String>(0) | ||
473 | })?; | ||
474 | 609 | ||
475 | for list in list_iter { | 610 | for list in list_iter { |
476 | list_id = list?; | 611 | list_id = list?; |
477 | }; | 612 | } |
613 | |||
614 | if list_id.is_empty() { | ||
615 | return Err(MLError::new(ErrorType::DBError, "NO_CURRENT_LIST")); | ||
616 | } | ||
478 | 617 | ||
479 | if list_id.is_empty() { return Err(MLError::new(ErrorType::DBError, "NO_CURRENT_LIST")); } | ||
480 | |||
481 | Ok(list_id) | 618 | Ok(list_id) |
482 | } | 619 | } |
483 | 620 | ||
484 | //SETUP(UPDATES) | 621 | //SETUP(UPDATES) |
485 | pub fn s_userlist_update_download(config: Cfg, list_id: String, mod_id: String, link: String) -> Result<(), Box<dyn std::error::Error>> { | 622 | pub fn s_userlist_update_download( |
623 | config: Cfg, | ||
624 | list_id: String, | ||
625 | mod_id: String, | ||
626 | link: String, | ||
627 | ) -> Result<(), Box<dyn std::error::Error>> { | ||
486 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 628 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
487 | let connection = Connection::open(data)?; | 629 | let connection = Connection::open(data)?; |
488 | 630 | ||
489 | connection.execute(format!("UPDATE {} SET current_download = ?1 WHERE mod_id = ?2", list_id).as_str(), [link, mod_id])?; | 631 | connection.execute( |
632 | format!( | ||
633 | "UPDATE {} SET current_download = ?1 WHERE mod_id = ?2", | ||
634 | list_id | ||
635 | ) | ||
636 | .as_str(), | ||
637 | [link, mod_id], | ||
638 | )?; | ||
490 | Ok(()) | 639 | Ok(()) |
491 | } | 640 | } |
492 | 641 | ||
@@ -494,7 +643,10 @@ pub fn s_config_create_version(config: Cfg) -> Result<(), Box<dyn std::error::Er | |||
494 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 643 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
495 | let connection = Connection::open(data)?; | 644 | let connection = Connection::open(data)?; |
496 | 645 | ||
497 | connection.execute("INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' )", ())?; | 646 | connection.execute( |
647 | "INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' )", | ||
648 | (), | ||
649 | )?; | ||
498 | Ok(()) | 650 | Ok(()) |
499 | } | 651 | } |
500 | 652 | ||
@@ -502,34 +654,46 @@ pub fn s_config_update_version(config: Cfg, ver: String) -> Result<(), Box<dyn s | |||
502 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 654 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
503 | let connection = Connection::open(data)?; | 655 | let connection = Connection::open(data)?; |
504 | 656 | ||
505 | connection.execute("UPDATE user_config SET value = ? WHERE id = 'db_version'", [ver])?; | 657 | connection.execute( |
658 | "UPDATE user_config SET value = ? WHERE id = 'db_version'", | ||
659 | [ver], | ||
660 | )?; | ||
506 | Ok(()) | 661 | Ok(()) |
507 | } | 662 | } |
508 | 663 | ||
509 | pub fn s_config_get_version(config: Cfg) -> Result<String, Box<dyn std::error::Error>> { | 664 | pub fn s_config_get_version(config: Cfg) -> Result<String, Box<dyn std::error::Error>> { |
510 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 665 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
511 | let connection = Connection::open(data)?; | 666 | let connection = Connection::open(data)?; |
512 | 667 | ||
513 | let mut version: String = String::new(); | 668 | let mut version: String = String::new(); |
514 | let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'db_version'")?; | 669 | let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'db_version'")?; |
515 | let ver_iter = stmt.query_map([], |row| { | 670 | let ver_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
516 | row.get::<usize, String>(0) | ||
517 | })?; | ||
518 | 671 | ||
519 | for ver in ver_iter { | 672 | for ver in ver_iter { |
520 | version = ver?; | 673 | version = ver?; |
521 | }; | 674 | } |
522 | 675 | ||
523 | if version.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_DBVERSION"))); }; | 676 | if version.is_empty() { |
677 | return Err(Box::new(std::io::Error::new( | ||
678 | ErrorKind::Other, | ||
679 | "NO_DBVERSION", | ||
680 | ))); | ||
681 | }; | ||
524 | Ok(version) | 682 | Ok(version) |
525 | } | 683 | } |
526 | 684 | ||
527 | pub fn s_insert_column(config: Cfg, table: String, column: String, c_type: String, default: Option<String>) -> Result<(), Box<dyn std::error::Error>> { | 685 | pub fn s_insert_column( |
686 | config: Cfg, | ||
687 | table: String, | ||
688 | column: String, | ||
689 | c_type: String, | ||
690 | default: Option<String>, | ||
691 | ) -> Result<(), Box<dyn std::error::Error>> { | ||
528 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 692 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
529 | let connection = Connection::open(data)?; | 693 | let connection = Connection::open(data)?; |
530 | 694 | ||
531 | let mut sql = format!("ALTER TABLE {} ADD '{}' {}", table, column, c_type); | 695 | let mut sql = format!("ALTER TABLE {} ADD '{}' {}", table, column, c_type); |
532 | 696 | ||
533 | if default.is_some() { | 697 | if default.is_some() { |
534 | sql = format!("{} DEFAULT {}", sql, default.unwrap()); | 698 | sql = format!("{} DEFAULT {}", sql, default.unwrap()); |
535 | } | 699 | } |
@@ -539,7 +703,6 @@ pub fn s_insert_column(config: Cfg, table: String, column: String, c_type: Strin | |||
539 | } | 703 | } |
540 | 704 | ||
541 | pub fn db_setup(config: Cfg) -> MLE<()> { | 705 | pub fn db_setup(config: Cfg) -> MLE<()> { |
542 | |||
543 | println!("Initiating database"); | 706 | println!("Initiating database"); |
544 | 707 | ||
545 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 708 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
@@ -552,6 +715,6 @@ pub fn db_setup(config: Cfg) -> MLE<()> { | |||
552 | INSERT INTO 'user_config' VALUES ( 'db_version', '0.5' ); | 715 | INSERT INTO 'user_config' VALUES ( 'db_version', '0.5' ); |
553 | INSERT INTO 'user_config' VALUES ( 'current_list', '...' )", | 716 | INSERT INTO 'user_config' VALUES ( 'current_list', '...' )", |
554 | )?; | 717 | )?; |
555 | 718 | ||
556 | Ok(()) | 719 | Ok(()) |
557 | } | 720 | } |
diff --git a/src/error.rs b/src/error.rs index 794a919..bd6e3da 100644 --- a/src/error.rs +++ b/src/error.rs | |||
@@ -43,49 +43,70 @@ impl fmt::Display for MLError { | |||
43 | ErrorType::LibReq => write!(f, "REQWEST"), | 43 | ErrorType::LibReq => write!(f, "REQWEST"), |
44 | ErrorType::LibChrono => write!(f, "Chrono error: {}", self.message), | 44 | ErrorType::LibChrono => write!(f, "Chrono error: {}", self.message), |
45 | ErrorType::IoError => write!(f, "IO"), | 45 | ErrorType::IoError => write!(f, "IO"), |
46 | ErrorType::Other => write!(f, "OTHER") | 46 | ErrorType::Other => write!(f, "OTHER"), |
47 | } | 47 | } |
48 | } | 48 | } |
49 | } | 49 | } |
50 | 50 | ||
51 | impl From<reqwest::Error> for MLError { | 51 | impl From<reqwest::Error> for MLError { |
52 | fn from(error: reqwest::Error) -> Self { | 52 | fn from(error: reqwest::Error) -> Self { |
53 | Self { etype: ErrorType::LibReq, message: error.to_string() } | 53 | Self { |
54 | etype: ErrorType::LibReq, | ||
55 | message: error.to_string(), | ||
56 | } | ||
54 | } | 57 | } |
55 | } | 58 | } |
56 | 59 | ||
57 | impl From<toml::de::Error> for MLError { | 60 | impl From<toml::de::Error> for MLError { |
58 | fn from(error: toml::de::Error) -> Self { | 61 | fn from(error: toml::de::Error) -> Self { |
59 | Self { etype: ErrorType::LibToml, message: error.to_string() } | 62 | Self { |
63 | etype: ErrorType::LibToml, | ||
64 | message: error.to_string(), | ||
65 | } | ||
60 | } | 66 | } |
61 | } | 67 | } |
62 | 68 | ||
63 | impl From<rusqlite::Error> for MLError { | 69 | impl From<rusqlite::Error> for MLError { |
64 | fn from(error: rusqlite::Error) -> Self { | 70 | fn from(error: rusqlite::Error) -> Self { |
65 | Self { etype: ErrorType::LibSql, message: error.to_string() } | 71 | Self { |
72 | etype: ErrorType::LibSql, | ||
73 | message: error.to_string(), | ||
74 | } | ||
66 | } | 75 | } |
67 | } | 76 | } |
68 | 77 | ||
69 | impl From<toml::ser::Error> for MLError { | 78 | impl From<toml::ser::Error> for MLError { |
70 | fn from(error: toml::ser::Error) -> Self { | 79 | fn from(error: toml::ser::Error) -> Self { |
71 | Self { etype: ErrorType::LibToml, message: error.to_string() } | 80 | Self { |
81 | etype: ErrorType::LibToml, | ||
82 | message: error.to_string(), | ||
83 | } | ||
72 | } | 84 | } |
73 | } | 85 | } |
74 | 86 | ||
75 | impl From<chrono::ParseError> for MLError { | 87 | impl From<chrono::ParseError> for MLError { |
76 | fn from(error: chrono::ParseError) -> Self { | 88 | fn from(error: chrono::ParseError) -> Self { |
77 | Self { etype: ErrorType::LibChrono, message: error.to_string() } | 89 | Self { |
90 | etype: ErrorType::LibChrono, | ||
91 | message: error.to_string(), | ||
92 | } | ||
78 | } | 93 | } |
79 | } | 94 | } |
80 | 95 | ||
81 | impl From<std::io::Error> for MLError { | 96 | impl From<std::io::Error> for MLError { |
82 | fn from(error: std::io::Error) -> Self { | 97 | fn from(error: std::io::Error) -> Self { |
83 | Self { etype: ErrorType::IoError, message: error.to_string() } | 98 | Self { |
99 | etype: ErrorType::IoError, | ||
100 | message: error.to_string(), | ||
101 | } | ||
84 | } | 102 | } |
85 | } | 103 | } |
86 | 104 | ||
87 | impl MLError { | 105 | impl MLError { |
88 | pub fn new(etype: ErrorType, message: &str) -> Self { | 106 | pub fn new(etype: ErrorType, message: &str) -> Self { |
89 | Self { etype, message: String::from(message) } | 107 | Self { |
108 | etype, | ||
109 | message: String::from(message), | ||
110 | } | ||
90 | } | 111 | } |
91 | } | 112 | } |
diff --git a/src/files.rs b/src/files.rs index 6519c6a..6160cb4 100644 --- a/src/files.rs +++ b/src/files.rs | |||
@@ -1,11 +1,20 @@ | |||
1 | use std::{fs::{File, read_dir, remove_file, rename}, io::Write, collections::HashMap}; | ||
2 | use futures_util::StreamExt; | 1 | use futures_util::StreamExt; |
3 | use reqwest::Client; | 2 | use reqwest::Client; |
4 | 3 | use std::{ | |
5 | use crate::{List, modrinth::Version, db::{userlist_add_disabled_versions, mods_get_info}, config::Cfg, error::{MLE, MLError, ErrorType}}; | 4 | collections::HashMap, |
5 | fs::{read_dir, remove_file, rename, File}, | ||
6 | io::Write, | ||
7 | }; | ||
8 | |||
9 | use crate::{ | ||
10 | config::Cfg, | ||
11 | db::{mods_get_info, userlist_add_disabled_versions}, | ||
12 | error::{ErrorType, MLError, MLE}, | ||
13 | modrinth::Version, | ||
14 | List, | ||
15 | }; | ||
6 | 16 | ||
7 | pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<String> { | 17 | pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<String> { |
8 | |||
9 | let dl_path = String::from(&list.download_folder); | 18 | let dl_path = String::from(&list.download_folder); |
10 | 19 | ||
11 | println!(" └Download mods to {}", dl_path); | 20 | println!(" └Download mods to {}", dl_path); |
@@ -21,7 +30,13 @@ pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) | |||
21 | Ok(e) => e, | 30 | Ok(e) => e, |
22 | Err(..) => return Err(MLError::new(ErrorType::Other, "NO_FILE_EXTENSION")), | 31 | Err(..) => return Err(MLError::new(ErrorType::Other, "NO_FILE_EXTENSION")), |
23 | }; | 32 | }; |
24 | let filename = format!("{}.mr.{}.{}.{}", splitname.join("."), ver.project_id, ver.id, extension); | 33 | let filename = format!( |
34 | "{}.mr.{}.{}.{}", | ||
35 | splitname.join("."), | ||
36 | ver.project_id, | ||
37 | ver.id, | ||
38 | extension | ||
39 | ); | ||
25 | download_file(primary_file.url, list.clone().download_folder, filename).await?; | 40 | download_file(primary_file.url, list.clone().download_folder, filename).await?; |
26 | //tokio::time::sleep(std::time::Duration::new(3, 0)).await; | 41 | //tokio::time::sleep(std::time::Duration::new(3, 0)).await; |
27 | println!(" ✓"); | 42 | println!(" ✓"); |
@@ -32,10 +47,7 @@ pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) | |||
32 | 47 | ||
33 | async fn download_file(url: String, path: String, name: String) -> MLE<()> { | 48 | async fn download_file(url: String, path: String, name: String) -> MLE<()> { |
34 | let dl_path_file = format!("{}/{}", path, name); | 49 | let dl_path_file = format!("{}/{}", path, name); |
35 | let res = Client::new() | 50 | let res = Client::new().get(String::from(&url)).send().await?; |
36 | .get(String::from(&url)) | ||
37 | .send() | ||
38 | .await?; | ||
39 | 51 | ||
40 | // download chunks | 52 | // download chunks |
41 | let mut file = File::create(&dl_path_file)?; | 53 | let mut file = File::create(&dl_path_file)?; |
@@ -49,7 +61,12 @@ async fn download_file(url: String, path: String, name: String) -> MLE<()> { | |||
49 | Ok(()) | 61 | Ok(()) |
50 | } | 62 | } |
51 | 63 | ||
52 | pub fn disable_version(config: Cfg, current_list: List, versionid: String, mod_id: String) -> MLE<()> { | 64 | pub fn disable_version( |
65 | config: Cfg, | ||
66 | current_list: List, | ||
67 | versionid: String, | ||
68 | mod_id: String, | ||
69 | ) -> MLE<()> { | ||
53 | //println!("Disabling version {} for mod {}", versionid, mod_id); | 70 | //println!("Disabling version {} for mod {}", versionid, mod_id); |
54 | let file = get_file_path(current_list.clone(), String::from(&versionid))?; | 71 | let file = get_file_path(current_list.clone(), String::from(&versionid))?; |
55 | let disabled = format!("{}.disabled", file); | 72 | let disabled = format!("{}.disabled", file); |
@@ -63,7 +80,7 @@ pub fn disable_version(config: Cfg, current_list: List, versionid: String, mod_i | |||
63 | 80 | ||
64 | pub fn delete_version(list: List, version: String) -> MLE<()> { | 81 | pub fn delete_version(list: List, version: String) -> MLE<()> { |
65 | let file = get_file_path(list, version)?; | 82 | let file = get_file_path(list, version)?; |
66 | 83 | ||
67 | remove_file(file)?; | 84 | remove_file(file)?; |
68 | 85 | ||
69 | Ok(()) | 86 | Ok(()) |
@@ -76,19 +93,24 @@ pub fn get_file_path(list: List, versionid: String) -> MLE<String> { | |||
76 | if path.is_file() { | 93 | if path.is_file() { |
77 | let pathstr = match path.to_str().ok_or("") { | 94 | let pathstr = match path.to_str().ok_or("") { |
78 | Ok(s) => s, | 95 | Ok(s) => s, |
79 | Err(..) => return Err(MLError::new(ErrorType::Other, "INVALID_PATH")) | 96 | Err(..) => return Err(MLError::new(ErrorType::Other, "INVALID_PATH")), |
80 | }; | 97 | }; |
81 | let namesplit: Vec<&str> = pathstr.split('.').collect(); | 98 | let namesplit: Vec<&str> = pathstr.split('.').collect(); |
82 | let ver_id = namesplit[namesplit.len() - 2]; | 99 | let ver_id = namesplit[namesplit.len() - 2]; |
83 | names.insert(String::from(ver_id), String::from(pathstr)); | 100 | names.insert(String::from(ver_id), String::from(pathstr)); |
84 | } | 101 | } |
85 | }; | 102 | } |
86 | 103 | ||
87 | let filename = match names.get(&versionid).ok_or("") { | 104 | let filename = match names.get(&versionid).ok_or("") { |
88 | Ok(n) => n, | 105 | Ok(n) => n, |
89 | Err(..) => return Err(MLError::new(ErrorType::ArgumentError, "VERSION_NOT_FOUND_IN_FILES")) | 106 | Err(..) => { |
107 | return Err(MLError::new( | ||
108 | ErrorType::ArgumentError, | ||
109 | "VERSION_NOT_FOUND_IN_FILES", | ||
110 | )) | ||
111 | } | ||
90 | }; | 112 | }; |
91 | 113 | ||
92 | Ok(filename.to_owned()) | 114 | Ok(filename.to_owned()) |
93 | } | 115 | } |
94 | 116 | ||
@@ -99,7 +121,10 @@ pub fn get_downloaded_versions(list: List) -> MLE<HashMap<String, String>> { | |||
99 | if path.is_file() && path.extension().ok_or("BAH").unwrap() == "jar" { | 121 | if path.is_file() && path.extension().ok_or("BAH").unwrap() == "jar" { |
100 | let pathstr = path.to_str().ok_or("BAH").unwrap(); | 122 | let pathstr = path.to_str().ok_or("BAH").unwrap(); |
101 | let namesplit: Vec<&str> = pathstr.split('.').collect(); | 123 | let namesplit: Vec<&str> = pathstr.split('.').collect(); |
102 | versions.insert(String::from(namesplit[namesplit.len() - 3]), String::from(namesplit[namesplit.len() - 2])); | 124 | versions.insert( |
125 | String::from(namesplit[namesplit.len() - 3]), | ||
126 | String::from(namesplit[namesplit.len() - 2]), | ||
127 | ); | ||
103 | } | 128 | } |
104 | } | 129 | } |
105 | Ok(versions) | 130 | Ok(versions) |
@@ -111,6 +136,6 @@ pub fn clean_list_dir(list: &List) -> MLE<()> { | |||
111 | for entry in std::fs::read_dir(dl_path)? { | 136 | for entry in std::fs::read_dir(dl_path)? { |
112 | let entry = entry?; | 137 | let entry = entry?; |
113 | std::fs::remove_file(entry.path())?; | 138 | std::fs::remove_file(entry.path())?; |
114 | }; | 139 | } |
115 | Ok(()) | 140 | Ok(()) |
116 | } | 141 | } |
diff --git a/src/input.rs b/src/input.rs deleted file mode 100644 index 6c62ab7..0000000 --- a/src/input.rs +++ /dev/null | |||
@@ -1,344 +0,0 @@ | |||
1 | use crate::{error::{MLE, MLError, ErrorType}, Modloader, config::Cfg, db::lists_get, get_current_list, List, modrinth::{get_minecraft_version, MCVersionType}, IDSelector}; | ||
2 | |||
3 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
4 | pub struct Input { | ||
5 | pub command: Option<Cmd>, | ||
6 | pub mod_options: Option<ModOptions>, | ||
7 | pub mod_id: Option<IDSelector>, | ||
8 | pub set_version: bool, | ||
9 | pub all_lists: bool, | ||
10 | pub clean: bool, | ||
11 | pub direct_download: bool, | ||
12 | pub delete_old: bool, | ||
13 | pub list: Option<List>, | ||
14 | pub list_options: Option<ListOptions>, | ||
15 | pub list_id: Option<String>, | ||
16 | pub list_mcversion: Option<String>, | ||
17 | pub modloader: Option<Modloader>, | ||
18 | pub directory: Option<String>, | ||
19 | pub io_options: Option<IoOptions>, | ||
20 | pub file: Option<String>, | ||
21 | } | ||
22 | |||
23 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
24 | pub enum Cmd { | ||
25 | Mod, | ||
26 | List, | ||
27 | Update, | ||
28 | Download, | ||
29 | Io, | ||
30 | Version, | ||
31 | Setup, | ||
32 | } | ||
33 | |||
34 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
35 | pub enum ModOptions { | ||
36 | Add, | ||
37 | Remove | ||
38 | } | ||
39 | |||
40 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
41 | pub enum ListOptions { | ||
42 | Add, | ||
43 | Remove, | ||
44 | Change, | ||
45 | Version, | ||
46 | } | ||
47 | |||
48 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
49 | pub enum IoOptions { | ||
50 | Export, | ||
51 | Import | ||
52 | } | ||
53 | |||
54 | impl Input { | ||
55 | fn from(config: Cfg, input: Vec<String>) -> MLE<Self> { | ||
56 | let input_string = input.join(" "); | ||
57 | let mut args: Vec<&str> = input_string.split(" -").collect(); | ||
58 | args[0] = args[0].split_at(1).1; | ||
59 | |||
60 | let mut command: Option<Cmd> = None; | ||
61 | |||
62 | let mut mod_options: Option<ModOptions> = None; | ||
63 | let mut mod_id: Option<IDSelector> = None; | ||
64 | let mut set_version = false; | ||
65 | let mut all_lists = false; | ||
66 | let mut clean = false; | ||
67 | let mut direct_download = true; | ||
68 | let mut delete_old = false; | ||
69 | let mut list: Option<List> = None; | ||
70 | let mut list_options: Option<ListOptions> = None; | ||
71 | let mut list_id: Option<String> = None; | ||
72 | let mut list_mcversion: Option<String> = None; | ||
73 | let mut modloader: Option<Modloader> = None; | ||
74 | let mut directory: Option<String> = None; | ||
75 | let mut io_options: Option<IoOptions> = None; | ||
76 | let mut file: Option<String> = None; | ||
77 | |||
78 | for arg in args { | ||
79 | let arg_split: Vec<&str> = arg.trim().split(' ').collect(); | ||
80 | match arg_split[0] { | ||
81 | "v" | "version" => { | ||
82 | command = Some(Cmd::Version); | ||
83 | }, | ||
84 | "d" | "download" => { | ||
85 | command = Some(Cmd::Download); | ||
86 | }, | ||
87 | "u" | "update" => { | ||
88 | command = Some(Cmd::Update); | ||
89 | }, | ||
90 | "ma" => { | ||
91 | command = Some(Cmd::Mod); | ||
92 | mod_options = Some(ModOptions::Add); | ||
93 | if arg_split.len() == 2 { | ||
94 | mod_id = Some(IDSelector::ModificationID(String::from(arg_split[1]))); | ||
95 | } else { | ||
96 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a list mod slug or id")); | ||
97 | } | ||
98 | }, | ||
99 | //TODO impl this | ||
100 | "mv" => { | ||
101 | command = Some(Cmd::Mod); | ||
102 | mod_options = Some(ModOptions::Add); | ||
103 | if arg_split.len() == 2 { | ||
104 | mod_id = Some(IDSelector::VersionID(String::from(arg_split[1]))); | ||
105 | } else { | ||
106 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a version id")); | ||
107 | }; | ||
108 | }, | ||
109 | "mr" => { | ||
110 | command = Some(Cmd::Mod); | ||
111 | mod_options = Some(ModOptions::Remove); | ||
112 | if arg_split.len() == 2 { | ||
113 | mod_id = Some(IDSelector::ModificationID(String::from(arg_split[1]))); | ||
114 | } else { | ||
115 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a mod id")); | ||
116 | }; | ||
117 | }, | ||
118 | "set_version" => { | ||
119 | set_version = true; | ||
120 | }, | ||
121 | "all_lists" => { | ||
122 | all_lists = true; | ||
123 | }, | ||
124 | "clean" => { | ||
125 | clean = true; | ||
126 | }, | ||
127 | "no_download" => { | ||
128 | direct_download = false; | ||
129 | }, | ||
130 | "delete_old" => { | ||
131 | delete_old = true; | ||
132 | }, | ||
133 | "l" => { | ||
134 | if arg_split.len() == 2 { | ||
135 | list = Some(lists_get(config.clone(), String::from(arg_split[1]))?); | ||
136 | } else { | ||
137 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a list via it's id")); | ||
138 | } | ||
139 | } | ||
140 | "la" => { | ||
141 | command = Some(Cmd::List); | ||
142 | list_options = Some(ListOptions::Add); | ||
143 | if arg_split.len() == 2 { | ||
144 | list_id = Some(String::from(arg_split[1])); | ||
145 | } else { | ||
146 | return Err(MLError::new(ErrorType::ArgumentError, "Please give the new list an id")); | ||
147 | } | ||
148 | }, | ||
149 | "lr" => { | ||
150 | command = Some(Cmd::List); | ||
151 | list_options = Some(ListOptions::Remove); | ||
152 | }, | ||
153 | "lc" => { | ||
154 | command = Some(Cmd::List); | ||
155 | list_options = Some(ListOptions::Change); | ||
156 | }, | ||
157 | "lv" => { | ||
158 | command = Some(Cmd::List); | ||
159 | list_options = Some(ListOptions::Version); | ||
160 | if arg_split.len() == 2 { | ||
161 | list_mcversion = Some(String::from(arg_split[1])); | ||
162 | } else { | ||
163 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a minecraft version")); | ||
164 | } | ||
165 | }, | ||
166 | "mcv" => { | ||
167 | if arg_split.len() == 2 { | ||
168 | list_mcversion = Some(String::from(arg_split[1])); | ||
169 | } else { | ||
170 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a minecraft version")); | ||
171 | } | ||
172 | }, | ||
173 | "ml" => { | ||
174 | if arg_split.len() == 2 { | ||
175 | modloader = Some(Modloader::from(arg_split[1])?); | ||
176 | } else { | ||
177 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a modloader")); | ||
178 | } | ||
179 | }, | ||
180 | "dir" => { | ||
181 | if arg_split.len() == 2 { | ||
182 | directory = Some(String::from(arg_split[1])); | ||
183 | } else { | ||
184 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a directory")); | ||
185 | } | ||
186 | }, | ||
187 | "export" => { | ||
188 | command = Some(Cmd::Io); | ||
189 | io_options = Some(IoOptions::Export); | ||
190 | }, | ||
191 | "import" => { | ||
192 | command = Some(Cmd::Io); | ||
193 | io_options = Some(IoOptions::Import); | ||
194 | }, | ||
195 | "f" => { | ||
196 | file = Some(String::from(arg_split[1])); | ||
197 | }, | ||
198 | "setup" => { | ||
199 | command = Some(Cmd::Setup); | ||
200 | } | ||
201 | _ => return Err(MLError::new(ErrorType::ArgumentError, format!("Unknown Argument ({})", arg_split[0]).as_str())), | ||
202 | } | ||
203 | } | ||
204 | |||
205 | Ok(Self { | ||
206 | command, | ||
207 | mod_options, | ||
208 | mod_id, | ||
209 | set_version, | ||
210 | all_lists, | ||
211 | clean, | ||
212 | direct_download, | ||
213 | delete_old, | ||
214 | list, | ||
215 | list_options, | ||
216 | list_id, | ||
217 | list_mcversion, | ||
218 | modloader, | ||
219 | directory, | ||
220 | io_options, | ||
221 | file | ||
222 | }) | ||
223 | } | ||
224 | } | ||
225 | |||
226 | pub async fn get_input(config: Cfg, args: Vec<String>) -> MLE<Input> { | ||
227 | let input = Input::from(config.clone(), args)?; | ||
228 | |||
229 | if input.command.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "No command specified")); }; | ||
230 | |||
231 | match input.clone().command.unwrap() { | ||
232 | Cmd::Mod => check_mod(input, config), | ||
233 | Cmd::List => check_list(input, config).await, | ||
234 | _ => Ok(input), | ||
235 | } | ||
236 | } | ||
237 | |||
238 | fn check_mod(mut input: Input, config: Cfg) -> MLE<Input> { | ||
239 | if input.mod_options.is_none() { | ||
240 | return Err(MLError::new(ErrorType::ArgumentError, "No mod option")); | ||
241 | }; | ||
242 | match input.clone().mod_options.unwrap() { | ||
243 | ModOptions::Add => { | ||
244 | if input.mod_id.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "No mod id/slug or version id")); }; | ||
245 | if input.list_id.is_none() { input.list = Some(get_current_list(config)?); }; | ||
246 | Ok(input) | ||
247 | }, | ||
248 | ModOptions::Remove => { | ||
249 | if input.mod_id.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "MODS_NO_MODID")); }; | ||
250 | if input.list_id.is_none() { input.list = Some(get_current_list(config)?); }; | ||
251 | Ok(input) | ||
252 | }, | ||
253 | } | ||
254 | } | ||
255 | |||
256 | async fn check_list(mut input: Input, config: Cfg) -> MLE<Input> { | ||
257 | if input.list_options.is_none() { | ||
258 | return Err(MLError::new(ErrorType::ArgumentError, "NO_LIST_ARGUMENT")); | ||
259 | }; | ||
260 | match input.clone().list_options.unwrap() { | ||
261 | ListOptions::Add => { | ||
262 | if input.list_id.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "no list id specified")); }; | ||
263 | if input.list_mcversion.is_none() { | ||
264 | println!("No Minecraft Version specified, defaulting to latest release"); | ||
265 | input.list_mcversion = Some(get_minecraft_version(&config.apis.modrinth, MCVersionType::Release).await); | ||
266 | }; | ||
267 | if input.directory.is_none() { | ||
268 | let id = input.clone().list_id.unwrap(); | ||
269 | println!("No download directory specified, defaulting to ./downloads/{}", id); | ||
270 | input.directory = Some(format!("./downloads/{}", id)) | ||
271 | }; | ||
272 | if input.modloader.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "no modloader specified")); }; | ||
273 | Ok(input) | ||
274 | }, | ||
275 | ListOptions::Remove => { | ||
276 | if input.list.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "NO_LIST_SPECIFIED")); }; | ||
277 | Ok(input) | ||
278 | }, | ||
279 | ListOptions::Change => { | ||
280 | if input.list.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "NO_LIST_SPECIFIED")); }; | ||
281 | Ok(input) | ||
282 | }, | ||
283 | ListOptions::Version => { | ||
284 | if input.list.is_none() { | ||
285 | println!("No list specified, using default"); | ||
286 | input.list = Some(get_current_list(config)?); | ||
287 | }; | ||
288 | Ok(input) | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | |||
293 | #[test] | ||
294 | fn input_from() { | ||
295 | let config = Cfg::init("modlist.toml").unwrap(); | ||
296 | assert_eq!( | ||
297 | Input::from(config, vec![String::from("-la test -lv 1.19.3")]).unwrap(), | ||
298 | Input { | ||
299 | command: Some(Cmd::List), | ||
300 | mod_options: None, | ||
301 | mod_id: None, | ||
302 | set_version: false, | ||
303 | all_lists: false, | ||
304 | clean: false, | ||
305 | direct_download: false, | ||
306 | delete_old: false, | ||
307 | list: None, | ||
308 | list_options: Some(ListOptions::Add), | ||
309 | list_id: Some(String::from("test")), | ||
310 | list_mcversion: Some(String::from("1.19.3")), | ||
311 | modloader: None, | ||
312 | directory: None, | ||
313 | io_options: None, | ||
314 | file: None, | ||
315 | } | ||
316 | ); | ||
317 | |||
318 | } | ||
319 | |||
320 | #[tokio::test] | ||
321 | async fn get_input_test() { | ||
322 | let config = Cfg::init("modlist.toml").unwrap(); | ||
323 | assert_eq!( | ||
324 | get_input(config.clone(), vec![String::from("-ma test")]).await.unwrap(), | ||
325 | Input { | ||
326 | command: Some(Cmd::Mod), | ||
327 | mod_options: Some(ModOptions::Add), | ||
328 | mod_id: Some(IDSelector::ModificationID(String::from("test"))), | ||
329 | set_version: false, | ||
330 | all_lists: false, | ||
331 | clean: false, | ||
332 | direct_download: false, | ||
333 | delete_old: false, | ||
334 | list: Some(lists_get(config.clone(), String::from("one")).unwrap()), | ||
335 | list_options: None, | ||
336 | list_id: None, | ||
337 | list_mcversion: None, | ||
338 | modloader: None, | ||
339 | directory: None, | ||
340 | io_options: None, | ||
341 | file: None | ||
342 | } | ||
343 | ) | ||
344 | } | ||
@@ -1,36 +1,37 @@ | |||
1 | pub mod apis; | 1 | pub mod apis; |
2 | pub mod config; | ||
3 | pub mod commands; | 2 | pub mod commands; |
4 | pub mod input; | 3 | pub mod config; |
5 | pub mod db; | 4 | pub mod db; |
6 | pub mod error; | 5 | pub mod error; |
7 | pub mod files; | 6 | pub mod files; |
8 | 7 | ||
9 | use std::path::Path; | 8 | use std::{fmt::Display, path::Path}; |
10 | 9 | ||
11 | pub use apis::*; | 10 | pub use apis::*; |
12 | pub use commands::*; | 11 | pub use commands::*; |
13 | use error::{MLE, ErrorType, MLError}; | 12 | use error::{ErrorType, MLError, MLE}; |
14 | 13 | ||
15 | #[derive(Debug, Clone, PartialEq, Eq)] | 14 | #[derive(Debug, Clone, PartialEq, Eq)] |
16 | pub enum Modloader { | 15 | pub enum Modloader { |
17 | Fabric, | 16 | Fabric, |
18 | Forge | 17 | Forge, |
19 | } | 18 | } |
20 | 19 | ||
21 | impl Modloader { | 20 | impl Modloader { |
22 | fn to_string(&self) -> String { | 21 | pub fn from(string: &str) -> MLE<Modloader> { |
23 | match self { | ||
24 | Modloader::Fabric => String::from("fabric"), | ||
25 | Modloader::Forge => String::from("forge"), | ||
26 | } | ||
27 | } | ||
28 | |||
29 | fn from(string: &str) -> MLE<Modloader> { | ||
30 | match string { | 22 | match string { |
31 | "forge" => Ok(Modloader::Forge), | 23 | "forge" => Ok(Modloader::Forge), |
32 | "fabric" => Ok(Modloader::Fabric), | 24 | "fabric" => Ok(Modloader::Fabric), |
33 | _ => Err(MLError::new(ErrorType::ArgumentError, "UNKNOWN_MODLOADER")) | 25 | _ => Err(MLError::new(ErrorType::ArgumentError, "UNKNOWN_MODLOADER")), |
26 | } | ||
27 | } | ||
28 | } | ||
29 | |||
30 | impl Display for Modloader { | ||
31 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
32 | match self { | ||
33 | Modloader::Fabric => write!(f, "fabric"), | ||
34 | Modloader::Forge => write!(f, "forge"), | ||
34 | } | 35 | } |
35 | } | 36 | } |
36 | } | 37 | } |
diff --git a/src/main.rs b/src/main.rs index 32727c7..2006856 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -1,65 +1,269 @@ | |||
1 | use std::{env, process}; | 1 | use clap::{Parser, Subcommand}; |
2 | use modlist::{ | ||
3 | config::Cfg, | ||
4 | db::{config_get_current_list, lists_get, lists_get_all_ids}, | ||
5 | devdir, download, export, get_current_list, import, list_add, list_change, list_remove, | ||
6 | list_version, mod_add, mod_remove, update, IDSelector, List, Modloader, | ||
7 | }; | ||
2 | 8 | ||
3 | use modlist::{config::Cfg, input::{get_input, Cmd}, update, download, list, io, modification, setup}; | 9 | //TODO implement remote sql db |
10 | |||
11 | //TODO make default list optional | ||
12 | #[derive(Parser)] | ||
13 | #[command(author, version, about)] | ||
14 | struct Cli { | ||
15 | #[command(subcommand)] | ||
16 | command: Commands, | ||
17 | } | ||
18 | |||
19 | #[derive(Subcommand)] | ||
20 | enum Commands { | ||
21 | r#Mod { | ||
22 | #[command(subcommand)] | ||
23 | command: ModCommands, | ||
24 | }, | ||
25 | List { | ||
26 | #[command(subcommand)] | ||
27 | command: ListCommands, | ||
28 | }, | ||
29 | Download { | ||
30 | /// download all lists | ||
31 | #[arg(short, long)] | ||
32 | all: bool, | ||
33 | |||
34 | /// clean all mods before downloading them | ||
35 | #[arg(short, long)] | ||
36 | clean: bool, | ||
37 | |||
38 | /// remove disabled versions | ||
39 | #[arg(short, long)] | ||
40 | remove: bool, | ||
41 | }, | ||
42 | Update { | ||
43 | /// download all lists | ||
44 | #[arg(short, long)] | ||
45 | all: bool, | ||
46 | |||
47 | /// directly download updated mods | ||
48 | #[arg(short, long)] | ||
49 | download: bool, | ||
50 | |||
51 | /// clean all mods before downloading them | ||
52 | #[arg(short, long)] | ||
53 | clean: bool, | ||
54 | |||
55 | /// delete disabled versions | ||
56 | #[arg(short, long)] | ||
57 | remove: bool, | ||
58 | }, | ||
59 | Import { | ||
60 | #[arg(short, long)] | ||
61 | file: Option<String>, | ||
62 | |||
63 | /// directly download imported mods | ||
64 | #[arg(short, long)] | ||
65 | download: bool, | ||
66 | }, | ||
67 | Export { | ||
68 | /// the list you want to export | ||
69 | list: Option<String>, | ||
70 | }, | ||
71 | } | ||
72 | |||
73 | #[derive(Subcommand)] | ||
74 | enum ModCommands { | ||
75 | Add { | ||
76 | /// id of the mod/version | ||
77 | id: String, | ||
78 | |||
79 | /// set id mode to version | ||
80 | #[arg(short, long)] | ||
81 | version: bool, | ||
82 | |||
83 | /// directly download the mod | ||
84 | #[arg(short, long)] | ||
85 | download: bool, | ||
86 | |||
87 | /// lock the version added | ||
88 | #[arg(/* short , */long)] | ||
89 | lock: bool, | ||
90 | |||
91 | /// optional List selection, else default list will be used | ||
92 | #[arg(short, long)] | ||
93 | list: Option<String>, | ||
94 | }, | ||
95 | Remove { | ||
96 | /// id, name or title of the mod | ||
97 | id: String, | ||
98 | |||
99 | /// optional List selection, else default list will be used | ||
100 | #[arg(short, long)] | ||
101 | list: Option<String>, | ||
102 | }, | ||
103 | } | ||
104 | |||
105 | #[derive(Subcommand)] | ||
106 | enum ListCommands { | ||
107 | Add { | ||
108 | /// list id | ||
109 | id: String, | ||
110 | |||
111 | directory: String, | ||
112 | |||
113 | modloader: Option<String>, | ||
114 | |||
115 | version: Option<String>, | ||
116 | }, | ||
117 | Remove { | ||
118 | /// id, name or title of the list | ||
119 | id: String, | ||
120 | }, | ||
121 | List, | ||
122 | Change { | ||
123 | /// id of the list to change to | ||
124 | id: String, | ||
125 | }, | ||
126 | Version { | ||
127 | /// list id | ||
128 | id: String, | ||
129 | /// desired minecraft version | ||
130 | version: String, | ||
131 | |||
132 | /// directly download updated mods | ||
133 | #[arg(long, short)] | ||
134 | download: bool, | ||
135 | |||
136 | /// delete disabled versions | ||
137 | #[arg(short, long)] | ||
138 | remove: bool, | ||
139 | }, | ||
140 | } | ||
4 | 141 | ||
5 | #[tokio::main] | 142 | #[tokio::main] |
6 | async fn main() { | 143 | async fn main() { |
144 | let cli = Cli::parse(); | ||
145 | |||
7 | let config = Cfg::init("modlist.toml").unwrap(); | 146 | let config = Cfg::init("modlist.toml").unwrap(); |
8 | 147 | println!("{:?}", config); | |
9 | let mut args: Vec<String> = env::args().collect(); | 148 | |
10 | args.reverse(); | 149 | //TODO setup? maybe setup on install |
11 | args.pop(); | 150 | match cli.command { |
12 | args.reverse(); | 151 | Commands::Mod { command } => { |
13 | 152 | match command { | |
14 | if args.is_empty() { | 153 | #[allow(unused_variables)] |
15 | println!("Please enter an argument"); | 154 | ModCommands::Add { |
16 | process::exit(1); | 155 | id, |
17 | }; | 156 | version, |
18 | 157 | list, | |
19 | let input = match get_input(config.clone(), args).await { | 158 | download, |
20 | Ok(i) => i, | 159 | lock, |
21 | Err(e) => { | 160 | } => { |
22 | println!("{}", e); | 161 | let listf = match list { |
23 | process::exit(1); | 162 | Some(list) => lists_get(config.clone(), list).unwrap(), |
163 | None => lists_get( | ||
164 | config.clone(), | ||
165 | config_get_current_list(config.clone()).unwrap(), | ||
166 | ) | ||
167 | .unwrap(), | ||
168 | }; | ||
169 | |||
170 | let marked_id = match version { | ||
171 | true => IDSelector::VersionID(id), | ||
172 | false => IDSelector::ModificationID(id), | ||
173 | }; | ||
174 | |||
175 | mod_add(config, vec![marked_id], listf, download, lock).await | ||
176 | } | ||
177 | ModCommands::Remove { id, list } => { | ||
178 | //TODO add output | ||
179 | //TODO add success even if no file found | ||
180 | let listf = match list { | ||
181 | Some(list) => lists_get(config.clone(), list).unwrap(), | ||
182 | None => lists_get( | ||
183 | config.clone(), | ||
184 | config_get_current_list(config.clone()).unwrap(), | ||
185 | ) | ||
186 | .unwrap(), | ||
187 | }; | ||
188 | mod_remove(config, &id, listf) | ||
189 | } | ||
190 | } | ||
24 | } | 191 | } |
25 | }; | 192 | Commands::List { command } => { |
26 | 193 | match command { | |
27 | match input.clone().command.unwrap() { | 194 | ListCommands::Add { |
28 | Cmd::Mod => { | 195 | id, |
29 | modification(config, input).await | 196 | directory, |
30 | }, | 197 | modloader, |
31 | Cmd::List => { | 198 | version, |
32 | list(config, input).await | 199 | } => { |
33 | }, | 200 | let ml = match modloader { |
34 | Cmd::Update => { | 201 | Some(ml) => Modloader::from(&ml).unwrap(), |
35 | update(config, input).await | 202 | //TODO add default modloader to config |
36 | }, | 203 | None => Modloader::Fabric, |
37 | Cmd::Download => { | 204 | }; |
38 | download(config, input).await | ||
39 | }, | ||
40 | Cmd::Io => { | ||
41 | io(config, input).await | ||
42 | }, | ||
43 | Cmd::Version => { | ||
44 | show_version(); | ||
45 | Ok(()) | ||
46 | }, | ||
47 | Cmd::Setup => { | ||
48 | setup(config).await | ||
49 | }, | ||
50 | }.unwrap() | ||
51 | } | ||
52 | 205 | ||
53 | fn show_version() { | 206 | let ver = match version { |
54 | match std::env::var("DEV") { | 207 | Some(ver) => ver, |
55 | Ok(dev) => { | 208 | //TODO get latest version |
56 | let devint = dev.parse::<i32>().unwrap(); | 209 | //TODO impl config for specific version or latest or latest snap |
57 | if devint >= 1 { | 210 | None => "1.19.4".to_string(), |
58 | println!("Modlist by FxQnLr v{} (DEV)", env!("CARGO_PKG_VERSION")); | 211 | }; |
212 | |||
213 | list_add(config, id, ver, ml, directory) | ||
214 | } | ||
215 | ListCommands::Remove { id } => list_remove(config, id), | ||
216 | ListCommands::List => { | ||
217 | todo!() | ||
218 | } | ||
219 | ListCommands::Change { id } => list_change(config, id), | ||
220 | ListCommands::Version { | ||
221 | id, | ||
222 | version, | ||
223 | download, | ||
224 | remove, | ||
225 | } => list_version(config, id, version, download, remove).await, | ||
226 | } | ||
227 | } | ||
228 | //TODO a add specific list | ||
229 | Commands::Update { | ||
230 | all, | ||
231 | download, | ||
232 | clean, | ||
233 | remove, | ||
234 | } => { | ||
235 | let mut liststack: Vec<List> = vec![]; | ||
236 | if all { | ||
237 | let list_ids = lists_get_all_ids(config.clone()).unwrap(); | ||
238 | for id in list_ids { | ||
239 | liststack.push(lists_get(config.clone(), id).unwrap()); | ||
240 | } | ||
59 | } else { | 241 | } else { |
60 | println!("Modlist by FxQnLr v{}", env!("CARGO_PKG_VERSION")); | 242 | let current = get_current_list(config.clone()).unwrap(); |
243 | println!("Update list {}:", current.id); | ||
244 | liststack.push(current) | ||
61 | } | 245 | } |
62 | }, | 246 | update(config, liststack, clean, download, remove).await |
63 | Err(..) => println!("Modlist by FxQnLr v{}", env!("CARGO_PKG_VERSION")), | 247 | } |
248 | //TODO add specific list | ||
249 | Commands::Download { all, clean, remove } => download(config, all, clean, remove).await, | ||
250 | Commands::Import { file, download } => { | ||
251 | let filestr: String = match file { | ||
252 | Some(args) => args, | ||
253 | None => devdir( | ||
254 | dirs::home_dir() | ||
255 | .unwrap() | ||
256 | .join("mlexport.toml") | ||
257 | .into_os_string() | ||
258 | .into_string() | ||
259 | .unwrap() | ||
260 | .as_str(), | ||
261 | ), | ||
262 | }; | ||
263 | |||
264 | import(config, filestr, download).await | ||
265 | } | ||
266 | Commands::Export { list } => export(config, list), | ||
64 | } | 267 | } |
268 | .unwrap(); | ||
65 | } | 269 | } |