diff options
-rw-r--r-- | Cargo.lock | 267 | ||||
-rw-r--r-- | Cargo.toml | 33 | ||||
-rw-r--r-- | src/backup.rs | 17 | ||||
-rw-r--r-- | src/cli.rs | 25 | ||||
-rw-r--r-- | src/config.rs | 30 | ||||
-rw-r--r-- | src/error.rs | 12 | ||||
-rw-r--r-- | src/main.rs | 42 | ||||
-rw-r--r-- | src/packages.rs | 85 | ||||
-rw-r--r-- | src/packages/pacman.rs | 13 | ||||
-rw-r--r-- | src/packages/portage.rs | 4 | ||||
-rw-r--r-- | src/pathinfo.rs | 41 |
11 files changed, 479 insertions, 90 deletions
@@ -27,6 +27,55 @@ dependencies = [ | |||
27 | ] | 27 | ] |
28 | 28 | ||
29 | [[package]] | 29 | [[package]] |
30 | name = "anstream" | ||
31 | version = "0.6.15" | ||
32 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
33 | checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" | ||
34 | dependencies = [ | ||
35 | "anstyle", | ||
36 | "anstyle-parse", | ||
37 | "anstyle-query", | ||
38 | "anstyle-wincon", | ||
39 | "colorchoice", | ||
40 | "is_terminal_polyfill", | ||
41 | "utf8parse", | ||
42 | ] | ||
43 | |||
44 | [[package]] | ||
45 | name = "anstyle" | ||
46 | version = "1.0.8" | ||
47 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
48 | checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" | ||
49 | |||
50 | [[package]] | ||
51 | name = "anstyle-parse" | ||
52 | version = "0.2.5" | ||
53 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
54 | checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" | ||
55 | dependencies = [ | ||
56 | "utf8parse", | ||
57 | ] | ||
58 | |||
59 | [[package]] | ||
60 | name = "anstyle-query" | ||
61 | version = "1.1.1" | ||
62 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
63 | checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" | ||
64 | dependencies = [ | ||
65 | "windows-sys 0.52.0", | ||
66 | ] | ||
67 | |||
68 | [[package]] | ||
69 | name = "anstyle-wincon" | ||
70 | version = "3.0.4" | ||
71 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
72 | checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" | ||
73 | dependencies = [ | ||
74 | "anstyle", | ||
75 | "windows-sys 0.52.0", | ||
76 | ] | ||
77 | |||
78 | [[package]] | ||
30 | name = "anyhow" | 79 | name = "anyhow" |
31 | version = "1.0.86" | 80 | version = "1.0.86" |
32 | source = "registry+https://github.com/rust-lang/crates.io-index" | 81 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -37,8 +86,10 @@ name = "arbs" | |||
37 | version = "0.1.0" | 86 | version = "0.1.0" |
38 | dependencies = [ | 87 | dependencies = [ |
39 | "anyhow", | 88 | "anyhow", |
89 | "clap", | ||
40 | "color-eyre", | 90 | "color-eyre", |
41 | "config", | 91 | "config", |
92 | "dirs", | ||
42 | "gethostname", | 93 | "gethostname", |
43 | "serde", | 94 | "serde", |
44 | "serde_json", | 95 | "serde_json", |
@@ -116,6 +167,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
116 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | 167 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" |
117 | 168 | ||
118 | [[package]] | 169 | [[package]] |
170 | name = "clap" | ||
171 | version = "4.5.17" | ||
172 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
173 | checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" | ||
174 | dependencies = [ | ||
175 | "clap_builder", | ||
176 | "clap_derive", | ||
177 | ] | ||
178 | |||
179 | [[package]] | ||
180 | name = "clap_builder" | ||
181 | version = "4.5.17" | ||
182 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
183 | checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" | ||
184 | dependencies = [ | ||
185 | "anstream", | ||
186 | "anstyle", | ||
187 | "clap_lex", | ||
188 | "strsim", | ||
189 | ] | ||
190 | |||
191 | [[package]] | ||
192 | name = "clap_derive" | ||
193 | version = "4.5.13" | ||
194 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
195 | checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" | ||
196 | dependencies = [ | ||
197 | "heck", | ||
198 | "proc-macro2", | ||
199 | "quote", | ||
200 | "syn", | ||
201 | ] | ||
202 | |||
203 | [[package]] | ||
204 | name = "clap_lex" | ||
205 | version = "0.7.2" | ||
206 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
207 | checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" | ||
208 | |||
209 | [[package]] | ||
119 | name = "color-eyre" | 210 | name = "color-eyre" |
120 | version = "0.6.3" | 211 | version = "0.6.3" |
121 | source = "registry+https://github.com/rust-lang/crates.io-index" | 212 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -143,6 +234,12 @@ dependencies = [ | |||
143 | ] | 234 | ] |
144 | 235 | ||
145 | [[package]] | 236 | [[package]] |
237 | name = "colorchoice" | ||
238 | version = "1.0.2" | ||
239 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
240 | checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" | ||
241 | |||
242 | [[package]] | ||
146 | name = "config" | 243 | name = "config" |
147 | version = "0.14.0" | 244 | version = "0.14.0" |
148 | source = "registry+https://github.com/rust-lang/crates.io-index" | 245 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -159,7 +256,6 @@ dependencies = [ | |||
159 | "serde", | 256 | "serde", |
160 | "serde_json", | 257 | "serde_json", |
161 | "toml", | 258 | "toml", |
162 | "yaml-rust", | ||
163 | ] | 259 | ] |
164 | 260 | ||
165 | [[package]] | 261 | [[package]] |
@@ -251,6 +347,27 @@ dependencies = [ | |||
251 | ] | 347 | ] |
252 | 348 | ||
253 | [[package]] | 349 | [[package]] |
350 | name = "dirs" | ||
351 | version = "5.0.1" | ||
352 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
353 | checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" | ||
354 | dependencies = [ | ||
355 | "dirs-sys", | ||
356 | ] | ||
357 | |||
358 | [[package]] | ||
359 | name = "dirs-sys" | ||
360 | version = "0.4.1" | ||
361 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
362 | checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" | ||
363 | dependencies = [ | ||
364 | "libc", | ||
365 | "option-ext", | ||
366 | "redox_users", | ||
367 | "windows-sys 0.48.0", | ||
368 | ] | ||
369 | |||
370 | [[package]] | ||
254 | name = "dlv-list" | 371 | name = "dlv-list" |
255 | version = "0.5.2" | 372 | version = "0.5.2" |
256 | source = "registry+https://github.com/rust-lang/crates.io-index" | 373 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -272,7 +389,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
272 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" | 389 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" |
273 | dependencies = [ | 390 | dependencies = [ |
274 | "libc", | 391 | "libc", |
275 | "windows-sys", | 392 | "windows-sys 0.52.0", |
276 | ] | 393 | ] |
277 | 394 | ||
278 | [[package]] | 395 | [[package]] |
@@ -302,7 +419,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
302 | checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30" | 419 | checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30" |
303 | dependencies = [ | 420 | dependencies = [ |
304 | "rustix", | 421 | "rustix", |
305 | "windows-targets", | 422 | "windows-targets 0.52.6", |
306 | ] | 423 | ] |
307 | 424 | ||
308 | [[package]] | 425 | [[package]] |
@@ -335,6 +452,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
335 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" | 452 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" |
336 | 453 | ||
337 | [[package]] | 454 | [[package]] |
455 | name = "heck" | ||
456 | version = "0.5.0" | ||
457 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
458 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" | ||
459 | |||
460 | [[package]] | ||
338 | name = "indenter" | 461 | name = "indenter" |
339 | version = "0.3.3" | 462 | version = "0.3.3" |
340 | source = "registry+https://github.com/rust-lang/crates.io-index" | 463 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -351,6 +474,12 @@ dependencies = [ | |||
351 | ] | 474 | ] |
352 | 475 | ||
353 | [[package]] | 476 | [[package]] |
477 | name = "is_terminal_polyfill" | ||
478 | version = "1.70.1" | ||
479 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
480 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" | ||
481 | |||
482 | [[package]] | ||
354 | name = "itoa" | 483 | name = "itoa" |
355 | version = "1.0.11" | 484 | version = "1.0.11" |
356 | source = "registry+https://github.com/rust-lang/crates.io-index" | 485 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -380,10 +509,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
380 | checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" | 509 | checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" |
381 | 510 | ||
382 | [[package]] | 511 | [[package]] |
383 | name = "linked-hash-map" | 512 | name = "libredox" |
384 | version = "0.5.6" | 513 | version = "0.1.3" |
385 | source = "registry+https://github.com/rust-lang/crates.io-index" | 514 | source = "registry+https://github.com/rust-lang/crates.io-index" |
386 | checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" | 515 | checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" |
516 | dependencies = [ | ||
517 | "bitflags", | ||
518 | "libc", | ||
519 | ] | ||
387 | 520 | ||
388 | [[package]] | 521 | [[package]] |
389 | name = "linux-raw-sys" | 522 | name = "linux-raw-sys" |
@@ -469,6 +602,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
469 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" | 602 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" |
470 | 603 | ||
471 | [[package]] | 604 | [[package]] |
605 | name = "option-ext" | ||
606 | version = "0.2.0" | ||
607 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
608 | checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" | ||
609 | |||
610 | [[package]] | ||
472 | name = "ordered-multimap" | 611 | name = "ordered-multimap" |
473 | version = "0.6.0" | 612 | version = "0.6.0" |
474 | source = "registry+https://github.com/rust-lang/crates.io-index" | 613 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -572,6 +711,17 @@ dependencies = [ | |||
572 | ] | 711 | ] |
573 | 712 | ||
574 | [[package]] | 713 | [[package]] |
714 | name = "redox_users" | ||
715 | version = "0.4.6" | ||
716 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
717 | checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" | ||
718 | dependencies = [ | ||
719 | "getrandom", | ||
720 | "libredox", | ||
721 | "thiserror", | ||
722 | ] | ||
723 | |||
724 | [[package]] | ||
575 | name = "regex" | 725 | name = "regex" |
576 | version = "1.10.6" | 726 | version = "1.10.6" |
577 | source = "registry+https://github.com/rust-lang/crates.io-index" | 727 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -653,7 +803,7 @@ dependencies = [ | |||
653 | "errno", | 803 | "errno", |
654 | "libc", | 804 | "libc", |
655 | "linux-raw-sys", | 805 | "linux-raw-sys", |
656 | "windows-sys", | 806 | "windows-sys 0.52.0", |
657 | ] | 807 | ] |
658 | 808 | ||
659 | [[package]] | 809 | [[package]] |
@@ -736,6 +886,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
736 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" | 886 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" |
737 | 887 | ||
738 | [[package]] | 888 | [[package]] |
889 | name = "strsim" | ||
890 | version = "0.11.1" | ||
891 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
892 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" | ||
893 | |||
894 | [[package]] | ||
739 | name = "syn" | 895 | name = "syn" |
740 | version = "2.0.77" | 896 | version = "2.0.77" |
741 | source = "registry+https://github.com/rust-lang/crates.io-index" | 897 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -958,6 +1114,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
958 | checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" | 1114 | checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" |
959 | 1115 | ||
960 | [[package]] | 1116 | [[package]] |
1117 | name = "utf8parse" | ||
1118 | version = "0.2.2" | ||
1119 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1120 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" | ||
1121 | |||
1122 | [[package]] | ||
961 | name = "uuid" | 1123 | name = "uuid" |
962 | version = "1.10.0" | 1124 | version = "1.10.0" |
963 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1125 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1008,11 +1170,35 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | |||
1008 | 1170 | ||
1009 | [[package]] | 1171 | [[package]] |
1010 | name = "windows-sys" | 1172 | name = "windows-sys" |
1173 | version = "0.48.0" | ||
1174 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1175 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" | ||
1176 | dependencies = [ | ||
1177 | "windows-targets 0.48.5", | ||
1178 | ] | ||
1179 | |||
1180 | [[package]] | ||
1181 | name = "windows-sys" | ||
1011 | version = "0.52.0" | 1182 | version = "0.52.0" |
1012 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1183 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1013 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" | 1184 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" |
1014 | dependencies = [ | 1185 | dependencies = [ |
1015 | "windows-targets", | 1186 | "windows-targets 0.52.6", |
1187 | ] | ||
1188 | |||
1189 | [[package]] | ||
1190 | name = "windows-targets" | ||
1191 | version = "0.48.5" | ||
1192 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1193 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" | ||
1194 | dependencies = [ | ||
1195 | "windows_aarch64_gnullvm 0.48.5", | ||
1196 | "windows_aarch64_msvc 0.48.5", | ||
1197 | "windows_i686_gnu 0.48.5", | ||
1198 | "windows_i686_msvc 0.48.5", | ||
1199 | "windows_x86_64_gnu 0.48.5", | ||
1200 | "windows_x86_64_gnullvm 0.48.5", | ||
1201 | "windows_x86_64_msvc 0.48.5", | ||
1016 | ] | 1202 | ] |
1017 | 1203 | ||
1018 | [[package]] | 1204 | [[package]] |
@@ -1021,30 +1207,48 @@ version = "0.52.6" | |||
1021 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1207 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1022 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" | 1208 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" |
1023 | dependencies = [ | 1209 | dependencies = [ |
1024 | "windows_aarch64_gnullvm", | 1210 | "windows_aarch64_gnullvm 0.52.6", |
1025 | "windows_aarch64_msvc", | 1211 | "windows_aarch64_msvc 0.52.6", |
1026 | "windows_i686_gnu", | 1212 | "windows_i686_gnu 0.52.6", |
1027 | "windows_i686_gnullvm", | 1213 | "windows_i686_gnullvm", |
1028 | "windows_i686_msvc", | 1214 | "windows_i686_msvc 0.52.6", |
1029 | "windows_x86_64_gnu", | 1215 | "windows_x86_64_gnu 0.52.6", |
1030 | "windows_x86_64_gnullvm", | 1216 | "windows_x86_64_gnullvm 0.52.6", |
1031 | "windows_x86_64_msvc", | 1217 | "windows_x86_64_msvc 0.52.6", |
1032 | ] | 1218 | ] |
1033 | 1219 | ||
1034 | [[package]] | 1220 | [[package]] |
1035 | name = "windows_aarch64_gnullvm" | 1221 | name = "windows_aarch64_gnullvm" |
1222 | version = "0.48.5" | ||
1223 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1224 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" | ||
1225 | |||
1226 | [[package]] | ||
1227 | name = "windows_aarch64_gnullvm" | ||
1036 | version = "0.52.6" | 1228 | version = "0.52.6" |
1037 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1229 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1038 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" | 1230 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" |
1039 | 1231 | ||
1040 | [[package]] | 1232 | [[package]] |
1041 | name = "windows_aarch64_msvc" | 1233 | name = "windows_aarch64_msvc" |
1234 | version = "0.48.5" | ||
1235 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1236 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" | ||
1237 | |||
1238 | [[package]] | ||
1239 | name = "windows_aarch64_msvc" | ||
1042 | version = "0.52.6" | 1240 | version = "0.52.6" |
1043 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1241 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1044 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" | 1242 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" |
1045 | 1243 | ||
1046 | [[package]] | 1244 | [[package]] |
1047 | name = "windows_i686_gnu" | 1245 | name = "windows_i686_gnu" |
1246 | version = "0.48.5" | ||
1247 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1248 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" | ||
1249 | |||
1250 | [[package]] | ||
1251 | name = "windows_i686_gnu" | ||
1048 | version = "0.52.6" | 1252 | version = "0.52.6" |
1049 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1253 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1050 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" | 1254 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" |
@@ -1057,24 +1261,48 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" | |||
1057 | 1261 | ||
1058 | [[package]] | 1262 | [[package]] |
1059 | name = "windows_i686_msvc" | 1263 | name = "windows_i686_msvc" |
1264 | version = "0.48.5" | ||
1265 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1266 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" | ||
1267 | |||
1268 | [[package]] | ||
1269 | name = "windows_i686_msvc" | ||
1060 | version = "0.52.6" | 1270 | version = "0.52.6" |
1061 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1271 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1062 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" | 1272 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" |
1063 | 1273 | ||
1064 | [[package]] | 1274 | [[package]] |
1065 | name = "windows_x86_64_gnu" | 1275 | name = "windows_x86_64_gnu" |
1276 | version = "0.48.5" | ||
1277 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1278 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" | ||
1279 | |||
1280 | [[package]] | ||
1281 | name = "windows_x86_64_gnu" | ||
1066 | version = "0.52.6" | 1282 | version = "0.52.6" |
1067 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1283 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1068 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" | 1284 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" |
1069 | 1285 | ||
1070 | [[package]] | 1286 | [[package]] |
1071 | name = "windows_x86_64_gnullvm" | 1287 | name = "windows_x86_64_gnullvm" |
1288 | version = "0.48.5" | ||
1289 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1290 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" | ||
1291 | |||
1292 | [[package]] | ||
1293 | name = "windows_x86_64_gnullvm" | ||
1072 | version = "0.52.6" | 1294 | version = "0.52.6" |
1073 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1295 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1074 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" | 1296 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" |
1075 | 1297 | ||
1076 | [[package]] | 1298 | [[package]] |
1077 | name = "windows_x86_64_msvc" | 1299 | name = "windows_x86_64_msvc" |
1300 | version = "0.48.5" | ||
1301 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1302 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" | ||
1303 | |||
1304 | [[package]] | ||
1305 | name = "windows_x86_64_msvc" | ||
1078 | version = "0.52.6" | 1306 | version = "0.52.6" |
1079 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1307 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1080 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" | 1308 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" |
@@ -1087,12 +1315,3 @@ checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" | |||
1087 | dependencies = [ | 1315 | dependencies = [ |
1088 | "memchr", | 1316 | "memchr", |
1089 | ] | 1317 | ] |
1090 | |||
1091 | [[package]] | ||
1092 | name = "yaml-rust" | ||
1093 | version = "0.4.5" | ||
1094 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1095 | checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" | ||
1096 | dependencies = [ | ||
1097 | "linked-hash-map", | ||
1098 | ] | ||
@@ -1,18 +1,41 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "arbs" | 2 | name = "arbs" |
3 | version = "0.1.0" | ||
4 | edition = "2021" | 3 | edition = "2021" |
4 | version = "0.1.0" | ||
5 | 5 | ||
6 | [dependencies] | 6 | [dependencies] |
7 | anyhow = "1.0.86" | 7 | anyhow = "1.0.86" |
8 | color-eyre = "0.6.3" | 8 | color-eyre = "0.6.3" |
9 | config = "0.14.0" | 9 | dirs = "5.0.1" |
10 | gethostname = "0.5.0" | 10 | gethostname = "0.5.0" |
11 | serde = { version = "1.0.209", features = ["derive"] } | ||
12 | serde_json = "1.0.128" | 11 | serde_json = "1.0.128" |
13 | thiserror = "1.0.63" | 12 | thiserror = "1.0.63" |
14 | toml = "0.8.19" | 13 | toml = "0.8.19" |
15 | tracing = "0.1.40" | 14 | tracing = "0.1.40" |
16 | tracing-appender = "0.2.3" | 15 | tracing-appender = "0.2.3" |
17 | tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } | 16 | |
18 | uuid = { version = "1.10.0", features = ["v4"] } | 17 | [dependencies.clap] |
18 | version = "4.5.17" | ||
19 | features = ["derive"] | ||
20 | |||
21 | [dependencies.config] | ||
22 | version = "0.14.0" | ||
23 | features = ["ini", "toml", "json5", "ron", "json", "convert-case", "async"] | ||
24 | default-features = false | ||
25 | |||
26 | [dependencies.serde] | ||
27 | version = "1.0.209" | ||
28 | features = ["derive"] | ||
29 | |||
30 | [dependencies.tracing-subscriber] | ||
31 | version = "0.3.18" | ||
32 | features = ["env-filter"] | ||
33 | |||
34 | [dependencies.uuid] | ||
35 | version = "1.10.0" | ||
36 | features = ["v4"] | ||
37 | |||
38 | [features] | ||
39 | default = ["pacman", "portage"] | ||
40 | pacman = [] | ||
41 | portage = [] | ||
diff --git a/src/backup.rs b/src/backup.rs index e463593..f9de139 100644 --- a/src/backup.rs +++ b/src/backup.rs | |||
@@ -12,7 +12,7 @@ use uuid::Uuid; | |||
12 | use crate::{ | 12 | use crate::{ |
13 | config::Config, | 13 | config::Config, |
14 | error::{Error, Result}, | 14 | error::{Error, Result}, |
15 | packages::Package, | 15 | packages::{Manager, PackageList}, |
16 | pathinfo::PathInfo, | 16 | pathinfo::PathInfo, |
17 | }; | 17 | }; |
18 | 18 | ||
@@ -22,13 +22,13 @@ pub type Id = String; | |||
22 | pub struct Backup { | 22 | pub struct Backup { |
23 | pub id: String, | 23 | pub id: String, |
24 | pub timestamp: u64, | 24 | pub timestamp: u64, |
25 | packages: Vec<Package>, | 25 | pub packages: PackageList, |
26 | pub files: Vec<PathInfo>, | 26 | pub files: Vec<PathInfo>, |
27 | device: String, | 27 | pub device: String, |
28 | } | 28 | } |
29 | 29 | ||
30 | impl Backup { | 30 | impl Backup { |
31 | pub fn create(config: &Config, packages: Vec<Package>) -> Result<Self> { | 31 | pub fn create(config: &Config, manager: Option<Manager>) -> Result<Self> { |
32 | let mut files: Vec<PathInfo> = Vec::new(); | 32 | let mut files: Vec<PathInfo> = Vec::new(); |
33 | for dir in &config.directories { | 33 | for dir in &config.directories { |
34 | files.push(PathInfo::from_path(config, dir)?); | 34 | files.push(PathInfo::from_path(config, dir)?); |
@@ -37,7 +37,7 @@ impl Backup { | |||
37 | // TODO: UUID not really needed, maybe a shorter hash | 37 | // TODO: UUID not really needed, maybe a shorter hash |
38 | id: Uuid::new_v4().to_string(), | 38 | id: Uuid::new_v4().to_string(), |
39 | timestamp: Self::get_timestamp(), | 39 | timestamp: Self::get_timestamp(), |
40 | packages, | 40 | packages: Manager::get_manager(manager)?.get_installed()?, |
41 | files, | 41 | files, |
42 | device: config.device.clone(), | 42 | device: config.device.clone(), |
43 | }) | 43 | }) |
@@ -62,6 +62,7 @@ impl Backup { | |||
62 | 62 | ||
63 | pub fn get_last(config: &Config) -> Result<Option<Self>> { | 63 | pub fn get_last(config: &Config) -> Result<Option<Self>> { |
64 | let backup_index_root = format!("{}/index.json", config.root); | 64 | let backup_index_root = format!("{}/index.json", config.root); |
65 | info!(?backup_index_root, "backup index location:"); | ||
65 | let list: Vec<IndexEntry> = match Self::get_json_content(&backup_index_root) { | 66 | let list: Vec<IndexEntry> = match Self::get_json_content(&backup_index_root) { |
66 | Ok(list) => list, | 67 | Ok(list) => list, |
67 | Err(err) => { | 68 | Err(err) => { |
@@ -72,6 +73,8 @@ impl Backup { | |||
72 | } | 73 | } |
73 | }; | 74 | }; |
74 | 75 | ||
76 | info!(?list, "backup index:"); | ||
77 | |||
75 | Ok(Some(Self::from_index( | 78 | Ok(Some(Self::from_index( |
76 | config, | 79 | config, |
77 | &list.last().ok_or(Error::BackupNotFound)?.id, | 80 | &list.last().ok_or(Error::BackupNotFound)?.id, |
@@ -109,6 +112,10 @@ impl Backup { | |||
109 | format!("{loc}/{rel_location}") | 112 | format!("{loc}/{rel_location}") |
110 | } | 113 | } |
111 | 114 | ||
115 | pub fn restore(&self) { | ||
116 | todo!() | ||
117 | } | ||
118 | |||
112 | fn get_json_content<T: for<'a> Deserialize<'a>>(path: &str) -> Result<T> { | 119 | fn get_json_content<T: for<'a> Deserialize<'a>>(path: &str) -> Result<T> { |
113 | let mut file = File::open(path)?; | 120 | let mut file = File::open(path)?; |
114 | let mut content = String::new(); | 121 | let mut content = String::new(); |
diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..6ffe03f --- /dev/null +++ b/src/cli.rs | |||
@@ -0,0 +1,25 @@ | |||
1 | use std::path::PathBuf; | ||
2 | |||
3 | use clap::{Parser, Subcommand}; | ||
4 | |||
5 | use crate::packages::Manager; | ||
6 | |||
7 | #[derive(Parser)] | ||
8 | pub struct Cli { | ||
9 | #[arg(short, long)] | ||
10 | pub config: Option<PathBuf>, | ||
11 | |||
12 | #[command(subcommand)] | ||
13 | pub subcommand: Subcommands, | ||
14 | } | ||
15 | |||
16 | #[derive(Subcommand)] | ||
17 | pub enum Subcommands { | ||
18 | GenerateConfig, | ||
19 | Save { | ||
20 | #[arg(short, long)] | ||
21 | package_manager: Option<Manager>, | ||
22 | }, | ||
23 | Restore, | ||
24 | } | ||
25 | |||
diff --git a/src/config.rs b/src/config.rs index 13dd0e4..46d2204 100644 --- a/src/config.rs +++ b/src/config.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | use std::{fs::create_dir_all, io::Write, path::PathBuf}; | ||
2 | |||
1 | use config::{File, Map}; | 3 | use config::{File, Map}; |
2 | use serde::{Deserialize, Serialize}; | 4 | use serde::{Deserialize, Serialize}; |
3 | use tracing::{debug, trace}; | 5 | use tracing::{debug, trace}; |
@@ -6,7 +8,6 @@ use tracing::{debug, trace}; | |||
6 | #[serde(default)] | 8 | #[serde(default)] |
7 | pub struct Config { | 9 | pub struct Config { |
8 | pub root: String, | 10 | pub root: String, |
9 | pub user: Vec<String>, | ||
10 | pub directories: Vec<String>, | 11 | pub directories: Vec<String>, |
11 | pub custom_directories: Map<String, String>, | 12 | pub custom_directories: Map<String, String>, |
12 | pub device: String, | 13 | pub device: String, |
@@ -16,7 +17,6 @@ impl Default for Config { | |||
16 | fn default() -> Self { | 17 | fn default() -> Self { |
17 | Self { | 18 | Self { |
18 | root: "/mnt/backup".to_string(), | 19 | root: "/mnt/backup".to_string(), |
19 | user: vec![], | ||
20 | directories: vec![], | 20 | directories: vec![], |
21 | custom_directories: Map::new(), | 21 | custom_directories: Map::new(), |
22 | device: gethostname::gethostname() | 22 | device: gethostname::gethostname() |
@@ -27,10 +27,16 @@ impl Default for Config { | |||
27 | } | 27 | } |
28 | 28 | ||
29 | impl Config { | 29 | impl Config { |
30 | pub fn load() -> Result<Self, config::ConfigError> { | 30 | pub fn load(path: Option<PathBuf>) -> core::result::Result<Self, config::ConfigError> { |
31 | debug!("load config"); | 31 | debug!("load config"); |
32 | let source = if let Some(source) = path { | ||
33 | source | ||
34 | } else { | ||
35 | Self::get_location() | ||
36 | }; | ||
37 | |||
32 | let config = config::Config::builder() | 38 | let config = config::Config::builder() |
33 | .add_source(File::with_name("config.toml").required(false)) | 39 | .add_source(File::with_name(&source.to_string_lossy()).required(false)) |
34 | .add_source(config::Environment::with_prefix("FXBAUP").separator("_")) | 40 | .add_source(config::Environment::with_prefix("FXBAUP").separator("_")) |
35 | .build()?; | 41 | .build()?; |
36 | 42 | ||
@@ -39,4 +45,20 @@ impl Config { | |||
39 | 45 | ||
40 | cfg | 46 | cfg |
41 | } | 47 | } |
48 | |||
49 | pub fn generate() -> crate::error::Result<()> { | ||
50 | let loc = Self::get_location(); | ||
51 | create_dir_all(loc.parent().unwrap())?; | ||
52 | let mut f = std::fs::File::create(loc)?; | ||
53 | f.write_all(toml::to_string(&Self::default())?.as_bytes())?; | ||
54 | |||
55 | Ok(()) | ||
56 | } | ||
57 | |||
58 | fn get_location() -> PathBuf { | ||
59 | let mut conf_dir = dirs::config_local_dir().unwrap(); | ||
60 | conf_dir.push("arbs"); | ||
61 | conf_dir.push("config.toml"); | ||
62 | conf_dir | ||
63 | } | ||
42 | } | 64 | } |
diff --git a/src/error.rs b/src/error.rs index 0cf4dca..e24c3b1 100644 --- a/src/error.rs +++ b/src/error.rs | |||
@@ -14,9 +14,6 @@ pub enum Error { | |||
14 | #[error("invalid directory '{0}'")] | 14 | #[error("invalid directory '{0}'")] |
15 | InvalidDirectory(String), | 15 | InvalidDirectory(String), |
16 | 16 | ||
17 | #[error("Only exactly one user allowed in config")] | ||
18 | MultiUser, | ||
19 | |||
20 | #[error("Requested backup not found")] | 17 | #[error("Requested backup not found")] |
21 | BackupNotFound, | 18 | BackupNotFound, |
22 | 19 | ||
@@ -24,12 +21,21 @@ pub enum Error { | |||
24 | #[error("Unknown Package Manger Output")] | 21 | #[error("Unknown Package Manger Output")] |
25 | UnknownOutput, | 22 | UnknownOutput, |
26 | 23 | ||
24 | #[error("Unsupported os/distro")] | ||
25 | Unsupported, | ||
26 | |||
27 | #[error("json: {source}")] | 27 | #[error("json: {source}")] |
28 | SerdeJson { | 28 | SerdeJson { |
29 | #[from] | 29 | #[from] |
30 | source: serde_json::Error, | 30 | source: serde_json::Error, |
31 | }, | 31 | }, |
32 | 32 | ||
33 | #[error("toml serializer: {source}")] | ||
34 | TomlSerialize { | ||
35 | #[from] | ||
36 | source: toml::ser::Error, | ||
37 | }, | ||
38 | |||
33 | #[error("io: {source}")] | 39 | #[error("io: {source}")] |
34 | Io { | 40 | Io { |
35 | #[from] | 41 | #[from] |
diff --git a/src/main.rs b/src/main.rs index 1284e0c..7393af9 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -1,10 +1,13 @@ | |||
1 | use backup::Backup; | 1 | use backup::Backup; |
2 | use clap::Parser; | ||
3 | use cli::Subcommands; | ||
2 | use config::Config; | 4 | use config::Config; |
3 | use packages::{pacman::Pacman, PackageManager}; | 5 | use error::Error; |
4 | use tracing::{debug, info, level_filters::LevelFilter}; | 6 | use tracing::{debug, level_filters::LevelFilter}; |
5 | use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; | 7 | use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; |
6 | 8 | ||
7 | mod backup; | 9 | mod backup; |
10 | mod cli; | ||
8 | mod config; | 11 | mod config; |
9 | mod error; | 12 | mod error; |
10 | mod packages; | 13 | mod packages; |
@@ -13,7 +16,7 @@ mod pathinfo; | |||
13 | fn main() -> color_eyre::Result<()> { | 16 | fn main() -> color_eyre::Result<()> { |
14 | color_eyre::install()?; | 17 | color_eyre::install()?; |
15 | 18 | ||
16 | let file_appender = tracing_appender::rolling::never("./", "arps.log"); | 19 | let file_appender = tracing_appender::rolling::never("./", "arbs.log"); |
17 | let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender); | 20 | let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender); |
18 | 21 | ||
19 | tracing_subscriber::registry() | 22 | tracing_subscriber::registry() |
@@ -33,19 +36,24 @@ fn main() -> color_eyre::Result<()> { | |||
33 | .init(); | 36 | .init(); |
34 | debug!("logging initialized"); | 37 | debug!("logging initialized"); |
35 | 38 | ||
36 | let mut cfg = Config::load()?; | 39 | let cli = cli::Cli::parse(); |
37 | cfg.user.push("fx".to_string()); | 40 | |
38 | cfg.directories.push("~/.config/nvim".to_string()); | 41 | let config = Config::load(cli.config)?; |
39 | cfg.root = "./backup".to_string(); | 42 | |
40 | 43 | match cli.subcommand { | |
41 | let pacman = Pacman; | 44 | Subcommands::GenerateConfig => Config::generate()?, |
42 | let pkgs = pacman.get_installed()?; | 45 | Subcommands::Save { package_manager } => { |
43 | let backup = Backup::create(&cfg, pkgs); | 46 | let backup = Backup::create(&config, package_manager)?; |
44 | // info!(?backup); | 47 | backup.save(&config)?; |
45 | // pacman.install(vec![Package { | 48 | } |
46 | // id: "lapce".to_string(), | 49 | Subcommands::Restore => { |
47 | // version: "0.4.2-1".to_string(), | 50 | let Some(last_backup) = Backup::get_last(&config)? else { |
48 | // explicit: true, | 51 | return Err(Error::BackupNotFound)?; |
49 | // }])?; | 52 | }; |
53 | |||
54 | last_backup.packages.install()?; | ||
55 | last_backup.restore(); | ||
56 | } | ||
57 | }; | ||
50 | Ok(()) | 58 | Ok(()) |
51 | } | 59 | } |
diff --git a/src/packages.rs b/src/packages.rs index 5ee5664..2eadcfc 100644 --- a/src/packages.rs +++ b/src/packages.rs | |||
@@ -1,19 +1,96 @@ | |||
1 | use std::{fs::File, io::Read}; | ||
2 | |||
3 | use pacman::Pacman; | ||
4 | use portage::Portage; | ||
1 | use serde::{Deserialize, Serialize}; | 5 | use serde::{Deserialize, Serialize}; |
2 | 6 | ||
3 | use crate::error::Result; | 7 | use crate::error::{Error, Result}; |
4 | 8 | ||
5 | pub mod pacman; | 9 | #[cfg(feature = "pacman")] |
6 | pub mod portage; | 10 | mod pacman; |
11 | #[cfg(feature = "portage")] | ||
12 | mod portage; | ||
7 | 13 | ||
8 | #[derive(Debug, Serialize, Deserialize)] | 14 | #[derive(Debug, Serialize, Deserialize)] |
15 | pub struct PackageList { | ||
16 | packages: Vec<Package>, | ||
17 | manager: Manager, | ||
18 | } | ||
19 | |||
20 | impl PackageList { | ||
21 | pub fn install(&self) -> Result<()> { | ||
22 | self.manager.to_package_manager().install(self.packages.clone()) | ||
23 | } | ||
24 | } | ||
25 | |||
26 | #[derive(Debug, Clone, Serialize, Deserialize)] | ||
9 | pub struct Package { | 27 | pub struct Package { |
10 | pub id: String, | 28 | pub id: String, |
11 | pub version: String, | 29 | pub version: String, |
12 | pub explicit: bool, | 30 | pub explicit: bool, |
13 | } | 31 | } |
14 | 32 | ||
33 | #[derive(Debug, Clone, clap::ValueEnum, Serialize, Deserialize)] | ||
34 | pub enum Manager { | ||
35 | #[cfg(feature = "pacman")] | ||
36 | Pacman, | ||
37 | #[cfg(feature = "portage")] | ||
38 | Portage, | ||
39 | } | ||
40 | |||
41 | |||
42 | impl Manager { | ||
43 | pub fn get_manager(manager: Option<Manager>) -> Result<Box<dyn PackageManager>> { | ||
44 | #[cfg(not(target_os = "linux"))] | ||
45 | { | ||
46 | return Err(Error::Unsupported); | ||
47 | } | ||
48 | |||
49 | #[cfg(target_os = "linux")] | ||
50 | { | ||
51 | if let Some(man) = manager { | ||
52 | return Ok(man.to_package_manager()); | ||
53 | } | ||
54 | let mut os_release = File::open("/etc/os-release")?; | ||
55 | let mut content = String::new(); | ||
56 | os_release.read_to_string(&mut content)?; | ||
57 | |||
58 | let lines: Vec<&str> = content.split('\n').collect(); | ||
59 | for line in lines { | ||
60 | let Some((key, value)) = line.split_once('=') else { | ||
61 | continue; | ||
62 | }; | ||
63 | if key == "ID" { | ||
64 | return Self::from_str(value); | ||
65 | } | ||
66 | } | ||
67 | Err(Error::Unsupported) | ||
68 | } | ||
69 | } | ||
70 | |||
71 | fn from_str(value: &str) -> Result<Box<dyn PackageManager>> { | ||
72 | Ok(match value { | ||
73 | #[cfg(feature = "pacman")] | ||
74 | "arch" => Box::new(Pacman), | ||
75 | #[cfg(feature = "portage")] | ||
76 | "gentoo" => Box::new(Portage), | ||
77 | _ => return Err(Error::Unsupported), | ||
78 | }) | ||
79 | } | ||
80 | |||
81 | fn to_package_manager(&self) -> Box<dyn PackageManager> { | ||
82 | match self { | ||
83 | #[cfg(feature = "pacman")] | ||
84 | Self::Pacman => Box::new(Pacman), | ||
85 | #[cfg(feature = "portage")] | ||
86 | Self::Portage => Box::new(Portage), | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | |||
91 | |||
15 | pub trait PackageManager { | 92 | pub trait PackageManager { |
16 | fn get_installed(&self) -> Result<Vec<Package>>; | 93 | fn get_installed(&self) -> Result<PackageList>; |
17 | 94 | ||
18 | fn install(&self, pkgs: Vec<Package>) -> Result<()>; | 95 | fn install(&self, pkgs: Vec<Package>) -> Result<()>; |
19 | } | 96 | } |
diff --git a/src/packages/pacman.rs b/src/packages/pacman.rs index e10c6fb..0ad463b 100644 --- a/src/packages/pacman.rs +++ b/src/packages/pacman.rs | |||
@@ -1,13 +1,13 @@ | |||
1 | use std::process::{Command, Stdio}; | 1 | use std::process::{Command, Stdio}; |
2 | 2 | ||
3 | use super::{Package, PackageManager}; | 3 | use super::{Package, PackageList, PackageManager}; |
4 | 4 | ||
5 | use crate::error::{Error, Result}; | 5 | use crate::error::{Error, Result}; |
6 | 6 | ||
7 | pub struct Pacman; | 7 | pub struct Pacman; |
8 | 8 | ||
9 | impl PackageManager for Pacman { | 9 | impl PackageManager for Pacman { |
10 | fn get_installed(&self) -> Result<Vec<super::Package>> { | 10 | fn get_installed(&self) -> Result<PackageList> { |
11 | let pm_pkgs = Command::new("pacman").args(["-Q"]).output().unwrap(); | 11 | let pm_pkgs = Command::new("pacman").args(["-Q"]).output().unwrap(); |
12 | let pm_e_pkgs = Command::new("pacman") | 12 | let pm_e_pkgs = Command::new("pacman") |
13 | .args(["-Q", "--explicit"]) | 13 | .args(["-Q", "--explicit"]) |
@@ -37,16 +37,19 @@ impl PackageManager for Pacman { | |||
37 | }); | 37 | }); |
38 | } | 38 | } |
39 | 39 | ||
40 | Ok(pkgs) | 40 | Ok(PackageList { |
41 | packages: pkgs, | ||
42 | manager: super::Manager::Pacman, | ||
43 | }) | ||
41 | } | 44 | } |
42 | 45 | ||
43 | fn install(&self, pkgs: Vec<super::Package>) -> Result<()> { | 46 | fn install(&self, pkgs: Vec<super::Package>) -> Result<()> { |
44 | let mut args = vec!["--noconfirm".to_string(), "-S".to_string()]; | 47 | let mut args = vec!["pacman".to_string(), "--noconfirm".to_string(), "-S".to_string()]; |
45 | 48 | ||
46 | for pkg in pkgs { | 49 | for pkg in pkgs { |
47 | args.push(pkg.id); | 50 | args.push(pkg.id); |
48 | } | 51 | } |
49 | Command::new("pacman") | 52 | Command::new("doas") |
50 | .stdout(Stdio::inherit()) | 53 | .stdout(Stdio::inherit()) |
51 | .args(args) | 54 | .args(args) |
52 | .spawn()? | 55 | .spawn()? |
diff --git a/src/packages/portage.rs b/src/packages/portage.rs index f9a760b..7fa09a8 100644 --- a/src/packages/portage.rs +++ b/src/packages/portage.rs | |||
@@ -1,11 +1,11 @@ | |||
1 | use tracing::error; | 1 | use tracing::error; |
2 | 2 | ||
3 | use super::PackageManager; | 3 | use super::{PackageList, PackageManager}; |
4 | 4 | ||
5 | pub struct Portage; | 5 | pub struct Portage; |
6 | 6 | ||
7 | impl PackageManager for Portage { | 7 | impl PackageManager for Portage { |
8 | fn get_installed(&self) -> crate::error::Result<Vec<super::Package>> { | 8 | fn get_installed(&self) -> crate::error::Result<PackageList> { |
9 | todo!() | 9 | todo!() |
10 | } | 10 | } |
11 | 11 | ||
diff --git a/src/pathinfo.rs b/src/pathinfo.rs index 8b1ca2f..03b8a6b 100644 --- a/src/pathinfo.rs +++ b/src/pathinfo.rs | |||
@@ -120,7 +120,8 @@ impl PathInfo { | |||
120 | let old_path = modified_backup.get_absolute_file_location(config, &last_file.rel_location); | 120 | let old_path = modified_backup.get_absolute_file_location(config, &last_file.rel_location); |
121 | let new_path = format!("{location_root}/{rel_location}"); | 121 | let new_path = format!("{location_root}/{rel_location}"); |
122 | 122 | ||
123 | let mut old = File::open(old_path)?; let mut new = File::open(new_path)?; | 123 | let mut old = File::open(old_path)?; |
124 | let mut new = File::open(new_path)?; | ||
124 | 125 | ||
125 | let old_len = old.metadata()?.len(); | 126 | let old_len = old.metadata()?.len(); |
126 | let new_len = new.metadata()?.len(); | 127 | let new_len = new.metadata()?.len(); |
@@ -195,12 +196,9 @@ impl PathInfo { | |||
195 | return Err(Error::InvalidDirectory(value.to_string())); | 196 | return Err(Error::InvalidDirectory(value.to_string())); |
196 | }; | 197 | }; |
197 | if split.0.starts_with('~') { | 198 | if split.0.starts_with('~') { |
198 | if config.user.len() != 1 { | ||
199 | return Err(Error::MultiUser); | ||
200 | } | ||
201 | return Ok(( | 199 | return Ok(( |
202 | split.1.to_string(), | 200 | split.1.to_string(), |
203 | LocationRoot::User(config.user[0].clone()), | 201 | LocationRoot::User, |
204 | )); | 202 | )); |
205 | }; | 203 | }; |
206 | Ok(( | 204 | Ok(( |
@@ -212,18 +210,22 @@ impl PathInfo { | |||
212 | 210 | ||
213 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] | 211 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] |
214 | pub enum LocationRoot { | 212 | pub enum LocationRoot { |
215 | User(String), | 213 | User, |
216 | Custom(String), | 214 | Custom(String), |
217 | SystemSettings, | 215 | SystemConfig, |
216 | UserConfig, | ||
218 | Root, | 217 | Root, |
219 | } | 218 | } |
220 | 219 | ||
221 | impl Display for LocationRoot { | 220 | impl Display for LocationRoot { |
222 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 221 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
223 | match self { | 222 | match self { |
224 | LocationRoot::User(user) => write!(f, "/home/{user}"), | 223 | LocationRoot::User => write!(f, "{}", dirs::home_dir().unwrap().to_string_lossy()), |
225 | LocationRoot::Custom(loc) => write!(f, "{loc}"), | 224 | LocationRoot::Custom(loc) => write!(f, "{loc}"), |
226 | LocationRoot::SystemSettings => write!(f, "/etc"), | 225 | LocationRoot::SystemConfig => write!(f, "/etc"), |
226 | LocationRoot::UserConfig => { | ||
227 | write!(f, "{}", dirs::config_local_dir().unwrap().to_string_lossy()) | ||
228 | } | ||
227 | LocationRoot::Root => write!(f, "/"), | 229 | LocationRoot::Root => write!(f, "/"), |
228 | } | 230 | } |
229 | } | 231 | } |
@@ -236,8 +238,9 @@ impl LocationRoot { | |||
236 | return Err(Error::NoIndex); | 238 | return Err(Error::NoIndex); |
237 | }; | 239 | }; |
238 | match split_op.0 { | 240 | match split_op.0 { |
239 | "u" => Ok(Self::User(split_op.1.to_string())), | 241 | "u" => Ok(Self::User), |
240 | "s" => Ok(Self::SystemSettings), | 242 | "s" => Ok(Self::SystemConfig), |
243 | "d" => Ok(Self::UserConfig), | ||
241 | "r" => Ok(Self::Root), | 244 | "r" => Ok(Self::Root), |
242 | "c" => Ok(Self::Custom( | 245 | "c" => Ok(Self::Custom( |
243 | config | 246 | config |
@@ -262,7 +265,6 @@ mod tests { | |||
262 | backup::Backup, | 265 | backup::Backup, |
263 | config::Config, | 266 | config::Config, |
264 | error::{Error, Result}, | 267 | error::{Error, Result}, |
265 | packages::{pacman::Pacman, PackageManager}, | ||
266 | }; | 268 | }; |
267 | 269 | ||
268 | use super::LocationRoot; | 270 | use super::LocationRoot; |
@@ -276,8 +278,8 @@ mod tests { | |||
276 | .insert("test".to_string(), "/usr/local/test".to_string()); | 278 | .insert("test".to_string(), "/usr/local/test".to_string()); |
277 | 279 | ||
278 | let mut values_ok: Vec<(&str, LocationRoot)> = Vec::new(); | 280 | let mut values_ok: Vec<(&str, LocationRoot)> = Vec::new(); |
279 | values_ok.push(("u:test", LocationRoot::User("test".to_string()))); | 281 | values_ok.push(("u:test", LocationRoot::User)); |
280 | values_ok.push(("s:", LocationRoot::SystemSettings)); | 282 | values_ok.push(("s:", LocationRoot::SystemConfig)); |
281 | values_ok.push(("r:", LocationRoot::Root)); | 283 | values_ok.push(("r:", LocationRoot::Root)); |
282 | values_ok.push(( | 284 | values_ok.push(( |
283 | "c:test", | 285 | "c:test", |
@@ -321,7 +323,6 @@ mod tests { | |||
321 | #[test] | 323 | #[test] |
322 | fn parse_location() -> Result<()> { | 324 | fn parse_location() -> Result<()> { |
323 | let mut config = Config::default(); | 325 | let mut config = Config::default(); |
324 | config.user.push("test".to_string()); | ||
325 | config | 326 | config |
326 | .custom_directories | 327 | .custom_directories |
327 | .insert("test".to_string(), "/usr/local/test".to_string()); | 328 | .insert("test".to_string(), "/usr/local/test".to_string()); |
@@ -331,14 +332,14 @@ mod tests { | |||
331 | "~/.config/nvim", | 332 | "~/.config/nvim", |
332 | ( | 333 | ( |
333 | ".config/nvim".to_string(), | 334 | ".config/nvim".to_string(), |
334 | LocationRoot::User("test".to_string()), | 335 | LocationRoot::User, |
335 | ), | 336 | ), |
336 | )); | 337 | )); |
337 | values_ok.push(( | 338 | values_ok.push(( |
338 | "u:test/.config/nvim", | 339 | "u:test/.config/nvim", |
339 | ( | 340 | ( |
340 | ".config/nvim".to_string(), | 341 | ".config/nvim".to_string(), |
341 | LocationRoot::User("test".to_string()), | 342 | LocationRoot::User, |
342 | ), | 343 | ), |
343 | )); | 344 | )); |
344 | values_ok.push(( | 345 | values_ok.push(( |
@@ -351,7 +352,7 @@ mod tests { | |||
351 | )); | 352 | )); |
352 | values_ok.push(( | 353 | values_ok.push(( |
353 | "s:/.config/nvim", | 354 | "s:/.config/nvim", |
354 | (".config/nvim".to_string(), LocationRoot::SystemSettings), | 355 | (".config/nvim".to_string(), LocationRoot::SystemConfig), |
355 | )); | 356 | )); |
356 | values_ok.push(( | 357 | values_ok.push(( |
357 | "c:test/.config/nvim", | 358 | "c:test/.config/nvim", |
@@ -385,9 +386,7 @@ mod tests { | |||
385 | let mut f = File::create("./backup-test-dir/nothing.txt")?; | 386 | let mut f = File::create("./backup-test-dir/nothing.txt")?; |
386 | f.write_all("unmodified".as_bytes())?; | 387 | f.write_all("unmodified".as_bytes())?; |
387 | 388 | ||
388 | let pacman = Pacman; | 389 | let backup = Backup::create(&config, None)?; |
389 | let pkgs = pacman.get_installed()?; | ||
390 | let backup = Backup::create(&config, pkgs)?; | ||
391 | backup.save(&config)?; | 390 | backup.save(&config)?; |
392 | 391 | ||
393 | let mut f = File::create("./backup-test-dir/size.txt")?; | 392 | let mut f = File::create("./backup-test-dir/size.txt")?; |