summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock254
-rw-r--r--Cargo.toml5
-rw-r--r--src/backup.rs28
-rw-r--r--src/config.rs7
-rw-r--r--src/main.rs47
-rw-r--r--src/packages.rs2
-rw-r--r--src/packages/pacman.rs18
-rw-r--r--src/packages/portage.rs5
-rw-r--r--src/pathinfo.rs32
10 files changed, 324 insertions, 75 deletions
diff --git a/.gitignore b/.gitignore
index 57e4770..a2956f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
1/target 1/target
2/backup* 2/backup*
3tags 3tags
4*.log
diff --git a/Cargo.lock b/Cargo.lock
index 09c9843..e72016e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -18,12 +18,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
18checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 18checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
19 19
20[[package]] 20[[package]]
21name = "aho-corasick"
22version = "1.1.3"
23source = "registry+https://github.com/rust-lang/crates.io-index"
24checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
25dependencies = [
26 "memchr",
27]
28
29[[package]]
21name = "anyhow" 30name = "anyhow"
22version = "1.0.86" 31version = "1.0.86"
23source = "registry+https://github.com/rust-lang/crates.io-index" 32source = "registry+https://github.com/rust-lang/crates.io-index"
24checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" 33checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
25 34
26[[package]] 35[[package]]
36name = "arps"
37version = "0.1.0"
38dependencies = [
39 "anyhow",
40 "color-eyre",
41 "config",
42 "gethostname",
43 "serde",
44 "serde_json",
45 "thiserror",
46 "toml",
47 "tracing",
48 "tracing-appender",
49 "tracing-subscriber",
50 "uuid",
51]
52
53[[package]]
27name = "async-trait" 54name = "async-trait"
28version = "0.1.82" 55version = "0.1.82"
29source = "registry+https://github.com/rust-lang/crates.io-index" 56source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -174,6 +201,21 @@ dependencies = [
174] 201]
175 202
176[[package]] 203[[package]]
204name = "crossbeam-channel"
205version = "0.5.13"
206source = "registry+https://github.com/rust-lang/crates.io-index"
207checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
208dependencies = [
209 "crossbeam-utils",
210]
211
212[[package]]
213name = "crossbeam-utils"
214version = "0.8.20"
215source = "registry+https://github.com/rust-lang/crates.io-index"
216checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
217
218[[package]]
177name = "crunchy" 219name = "crunchy"
178version = "0.2.2" 220version = "0.2.2"
179source = "registry+https://github.com/rust-lang/crates.io-index" 221source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -190,6 +232,15 @@ dependencies = [
190] 232]
191 233
192[[package]] 234[[package]]
235name = "deranged"
236version = "0.3.11"
237source = "registry+https://github.com/rust-lang/crates.io-index"
238checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
239dependencies = [
240 "powerfmt",
241]
242
243[[package]]
193name = "digest" 244name = "digest"
194version = "0.10.7" 245version = "0.10.7"
195source = "registry+https://github.com/rust-lang/crates.io-index" 246source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -235,21 +286,6 @@ dependencies = [
235] 286]
236 287
237[[package]] 288[[package]]
238name = "fxbaup"
239version = "0.1.0"
240dependencies = [
241 "anyhow",
242 "color-eyre",
243 "config",
244 "gethostname",
245 "serde",
246 "serde_json",
247 "thiserror",
248 "toml",
249 "uuid",
250]
251
252[[package]]
253name = "generic-array" 289name = "generic-array"
254version = "0.14.7" 290version = "0.14.7"
255source = "registry+https://github.com/rust-lang/crates.io-index" 291source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -356,6 +392,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
356checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 392checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
357 393
358[[package]] 394[[package]]
395name = "log"
396version = "0.4.22"
397source = "registry+https://github.com/rust-lang/crates.io-index"
398checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
399
400[[package]]
401name = "matchers"
402version = "0.1.0"
403source = "registry+https://github.com/rust-lang/crates.io-index"
404checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
405dependencies = [
406 "regex-automata 0.1.10",
407]
408
409[[package]]
359name = "memchr" 410name = "memchr"
360version = "2.7.4" 411version = "2.7.4"
361source = "registry+https://github.com/rust-lang/crates.io-index" 412source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -387,6 +438,22 @@ dependencies = [
387] 438]
388 439
389[[package]] 440[[package]]
441name = "nu-ansi-term"
442version = "0.46.0"
443source = "registry+https://github.com/rust-lang/crates.io-index"
444checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
445dependencies = [
446 "overload",
447 "winapi",
448]
449
450[[package]]
451name = "num-conv"
452version = "0.1.0"
453source = "registry+https://github.com/rust-lang/crates.io-index"
454checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
455
456[[package]]
390name = "object" 457name = "object"
391version = "0.32.2" 458version = "0.32.2"
392source = "registry+https://github.com/rust-lang/crates.io-index" 459source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -412,6 +479,12 @@ dependencies = [
412] 479]
413 480
414[[package]] 481[[package]]
482name = "overload"
483version = "0.1.1"
484source = "registry+https://github.com/rust-lang/crates.io-index"
485checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
486
487[[package]]
415name = "owo-colors" 488name = "owo-colors"
416version = "3.5.0" 489version = "3.5.0"
417source = "registry+https://github.com/rust-lang/crates.io-index" 490source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -475,6 +548,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
475checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 548checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
476 549
477[[package]] 550[[package]]
551name = "powerfmt"
552version = "0.2.0"
553source = "registry+https://github.com/rust-lang/crates.io-index"
554checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
555
556[[package]]
478name = "proc-macro2" 557name = "proc-macro2"
479version = "1.0.86" 558version = "1.0.86"
480source = "registry+https://github.com/rust-lang/crates.io-index" 559source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -493,6 +572,50 @@ dependencies = [
493] 572]
494 573
495[[package]] 574[[package]]
575name = "regex"
576version = "1.10.6"
577source = "registry+https://github.com/rust-lang/crates.io-index"
578checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
579dependencies = [
580 "aho-corasick",
581 "memchr",
582 "regex-automata 0.4.7",
583 "regex-syntax 0.8.4",
584]
585
586[[package]]
587name = "regex-automata"
588version = "0.1.10"
589source = "registry+https://github.com/rust-lang/crates.io-index"
590checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
591dependencies = [
592 "regex-syntax 0.6.29",
593]
594
595[[package]]
596name = "regex-automata"
597version = "0.4.7"
598source = "registry+https://github.com/rust-lang/crates.io-index"
599checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
600dependencies = [
601 "aho-corasick",
602 "memchr",
603 "regex-syntax 0.8.4",
604]
605
606[[package]]
607name = "regex-syntax"
608version = "0.6.29"
609source = "registry+https://github.com/rust-lang/crates.io-index"
610checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
611
612[[package]]
613name = "regex-syntax"
614version = "0.8.4"
615source = "registry+https://github.com/rust-lang/crates.io-index"
616checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
617
618[[package]]
496name = "ron" 619name = "ron"
497version = "0.8.1" 620version = "0.8.1"
498source = "registry+https://github.com/rust-lang/crates.io-index" 621source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -607,6 +730,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
607checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 730checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
608 731
609[[package]] 732[[package]]
733name = "smallvec"
734version = "1.13.2"
735source = "registry+https://github.com/rust-lang/crates.io-index"
736checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
737
738[[package]]
610name = "syn" 739name = "syn"
611version = "2.0.77" 740version = "2.0.77"
612source = "registry+https://github.com/rust-lang/crates.io-index" 741source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -648,6 +777,37 @@ dependencies = [
648] 777]
649 778
650[[package]] 779[[package]]
780name = "time"
781version = "0.3.36"
782source = "registry+https://github.com/rust-lang/crates.io-index"
783checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
784dependencies = [
785 "deranged",
786 "itoa",
787 "num-conv",
788 "powerfmt",
789 "serde",
790 "time-core",
791 "time-macros",
792]
793
794[[package]]
795name = "time-core"
796version = "0.1.2"
797source = "registry+https://github.com/rust-lang/crates.io-index"
798checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
799
800[[package]]
801name = "time-macros"
802version = "0.2.18"
803source = "registry+https://github.com/rust-lang/crates.io-index"
804checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
805dependencies = [
806 "num-conv",
807 "time-core",
808]
809
810[[package]]
651name = "tiny-keccak" 811name = "tiny-keccak"
652version = "2.0.2" 812version = "2.0.2"
653source = "registry+https://github.com/rust-lang/crates.io-index" 813source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -697,10 +857,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
697checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 857checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
698dependencies = [ 858dependencies = [
699 "pin-project-lite", 859 "pin-project-lite",
860 "tracing-attributes",
700 "tracing-core", 861 "tracing-core",
701] 862]
702 863
703[[package]] 864[[package]]
865name = "tracing-appender"
866version = "0.2.3"
867source = "registry+https://github.com/rust-lang/crates.io-index"
868checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf"
869dependencies = [
870 "crossbeam-channel",
871 "thiserror",
872 "time",
873 "tracing-subscriber",
874]
875
876[[package]]
877name = "tracing-attributes"
878version = "0.1.27"
879source = "registry+https://github.com/rust-lang/crates.io-index"
880checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
881dependencies = [
882 "proc-macro2",
883 "quote",
884 "syn",
885]
886
887[[package]]
704name = "tracing-core" 888name = "tracing-core"
705version = "0.1.32" 889version = "0.1.32"
706source = "registry+https://github.com/rust-lang/crates.io-index" 890source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -721,14 +905,32 @@ dependencies = [
721] 905]
722 906
723[[package]] 907[[package]]
908name = "tracing-log"
909version = "0.2.0"
910source = "registry+https://github.com/rust-lang/crates.io-index"
911checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
912dependencies = [
913 "log",
914 "once_cell",
915 "tracing-core",
916]
917
918[[package]]
724name = "tracing-subscriber" 919name = "tracing-subscriber"
725version = "0.3.18" 920version = "0.3.18"
726source = "registry+https://github.com/rust-lang/crates.io-index" 921source = "registry+https://github.com/rust-lang/crates.io-index"
727checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" 922checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
728dependencies = [ 923dependencies = [
924 "matchers",
925 "nu-ansi-term",
926 "once_cell",
927 "regex",
729 "sharded-slab", 928 "sharded-slab",
929 "smallvec",
730 "thread_local", 930 "thread_local",
931 "tracing",
731 "tracing-core", 932 "tracing-core",
933 "tracing-log",
732] 934]
733 935
734[[package]] 936[[package]]
@@ -783,6 +985,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
783checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 985checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
784 986
785[[package]] 987[[package]]
988name = "winapi"
989version = "0.3.9"
990source = "registry+https://github.com/rust-lang/crates.io-index"
991checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
992dependencies = [
993 "winapi-i686-pc-windows-gnu",
994 "winapi-x86_64-pc-windows-gnu",
995]
996
997[[package]]
998name = "winapi-i686-pc-windows-gnu"
999version = "0.4.0"
1000source = "registry+https://github.com/rust-lang/crates.io-index"
1001checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1002
1003[[package]]
1004name = "winapi-x86_64-pc-windows-gnu"
1005version = "0.4.0"
1006source = "registry+https://github.com/rust-lang/crates.io-index"
1007checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1008
1009[[package]]
786name = "windows-sys" 1010name = "windows-sys"
787version = "0.52.0" 1011version = "0.52.0"
788source = "registry+https://github.com/rust-lang/crates.io-index" 1012source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 62a91a7..9fc7b01 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2name = "fxbaup" 2name = "arps"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2021"
5 5
@@ -12,4 +12,7 @@ serde = { version = "1.0.209", features = ["derive"] }
12serde_json = "1.0.128" 12serde_json = "1.0.128"
13thiserror = "1.0.63" 13thiserror = "1.0.63"
14toml = "0.8.19" 14toml = "0.8.19"
15tracing = "0.1.40"
16tracing-appender = "0.2.3"
17tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
15uuid = { version = "1.10.0", features = ["v4"] } 18uuid = { version = "1.10.0", features = ["v4"] }
diff --git a/src/backup.rs b/src/backup.rs
index 675f020..e463593 100644
--- a/src/backup.rs
+++ b/src/backup.rs
@@ -6,6 +6,7 @@ use std::{
6}; 6};
7 7
8use serde::{Deserialize, Serialize}; 8use serde::{Deserialize, Serialize};
9use tracing::info;
9use uuid::Uuid; 10use uuid::Uuid;
10 11
11use crate::{ 12use crate::{
@@ -15,7 +16,7 @@ use crate::{
15 pathinfo::PathInfo, 16 pathinfo::PathInfo,
16}; 17};
17 18
18pub type BackupId = String; 19pub type Id = String;
19 20
20#[derive(Debug, Serialize, Deserialize)] 21#[derive(Debug, Serialize, Deserialize)]
21pub struct Backup { 22pub struct Backup {
@@ -43,13 +44,12 @@ impl Backup {
43 } 44 }
44 45
45 pub fn save(&self, config: &Config) -> Result<()> { 46 pub fn save(&self, config: &Config) -> Result<()> {
46 println!("Save Backup {:?}", self.get_location(config)); 47 info!("Save Backup {:?}", self.get_location(config));
47 // println!("{self:#?}");
48 self.get_location(config).append_to_root(config)?; 48 self.get_location(config).append_to_root(config)?;
49 49
50 let backup_root = self.get_location(config).get_absolute_dir(config); 50 let backup_root = self.get_location(config).get_absolute_dir(config);
51 create_dir_all(&backup_root).unwrap(); 51 create_dir_all(&backup_root).unwrap();
52 let path = format!("{}/index.json", backup_root); 52 let path = format!("{backup_root}/index.json");
53 let mut f = File::create(path).unwrap(); 53 let mut f = File::create(path).unwrap();
54 f.write_all(&serde_json::to_vec(self).unwrap()).unwrap(); 54 f.write_all(&serde_json::to_vec(self).unwrap()).unwrap();
55 55
@@ -62,7 +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 let list: Vec<BackupLocation> = match Self::get_json_content(&backup_index_root) { 65 let list: Vec<IndexEntry> = match Self::get_json_content(&backup_index_root) {
66 Ok(list) => list, 66 Ok(list) => list,
67 Err(err) => { 67 Err(err) => {
68 if err.to_string() == "io: No such file or directory (os error 2)" { 68 if err.to_string() == "io: No such file or directory (os error 2)" {
@@ -78,9 +78,9 @@ impl Backup {
78 )?)) 78 )?))
79 } 79 }
80 80
81 pub fn from_index(config: &Config, id: &BackupId) -> Result<Self> { 81 pub fn from_index(config: &Config, id: &Id) -> Result<Self> {
82 let backup_index_root = format!("{}/index.json", config.root); 82 let backup_index_root = format!("{}/index.json", config.root);
83 let list: Vec<BackupLocation> = Self::get_json_content(&backup_index_root)?; 83 let list: Vec<IndexEntry> = Self::get_json_content(&backup_index_root)?;
84 let index_loc = list 84 let index_loc = list
85 .iter() 85 .iter()
86 .find(|bl| &bl.id == id) 86 .find(|bl| &bl.id == id)
@@ -94,10 +94,10 @@ impl Backup {
94 Ok(index_file) 94 Ok(index_file)
95 } 95 }
96 96
97 pub fn get_location(&self, config: &Config) -> BackupLocation { 97 pub fn get_location(&self, config: &Config) -> IndexEntry {
98 let rel_location = format!("{}_{}", config.device, self.timestamp); 98 let rel_location = format!("{}_{}", config.device, self.timestamp);
99 99
100 BackupLocation { 100 IndexEntry {
101 id: self.id.to_string(), 101 id: self.id.to_string(),
102 rel_location, 102 rel_location,
103 } 103 }
@@ -106,7 +106,7 @@ impl Backup {
106 pub fn get_absolute_file_location(&self, config: &Config, rel_location: &str) -> String { 106 pub fn get_absolute_file_location(&self, config: &Config, rel_location: &str) -> String {
107 let loc = self.get_location(config).get_absolute_dir(config); 107 let loc = self.get_location(config).get_absolute_dir(config);
108 108
109 format!("{}/{}", loc, rel_location) 109 format!("{loc}/{rel_location}")
110 } 110 }
111 111
112 fn get_json_content<T: for<'a> Deserialize<'a>>(path: &str) -> Result<T> { 112 fn get_json_content<T: for<'a> Deserialize<'a>>(path: &str) -> Result<T> {
@@ -125,12 +125,12 @@ impl Backup {
125} 125}
126 126
127#[derive(Debug, Clone, Serialize, Deserialize)] 127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct BackupLocation { 128pub struct IndexEntry {
129 id: BackupId, 129 id: Id,
130 rel_location: String, 130 rel_location: String,
131} 131}
132 132
133impl BackupLocation { 133impl IndexEntry {
134 pub fn get_absolute_dir(&self, config: &Config) -> String { 134 pub fn get_absolute_dir(&self, config: &Config) -> String {
135 format!("{}/{}", config.root, self.rel_location) 135 format!("{}/{}", config.root, self.rel_location)
136 } 136 }
@@ -142,7 +142,7 @@ impl BackupLocation {
142 let mut f = File::open(&path)?; 142 let mut f = File::open(&path)?;
143 let mut content = String::new(); 143 let mut content = String::new();
144 f.read_to_string(&mut content)?; 144 f.read_to_string(&mut content)?;
145 let mut loc: Vec<BackupLocation> = serde_json::from_str(&content)?; 145 let mut loc: Vec<IndexEntry> = serde_json::from_str(&content)?;
146 146
147 let mut f = File::create(path)?; 147 let mut f = File::create(path)?;
148 loc.push(self.clone()); 148 loc.push(self.clone());
diff --git a/src/config.rs b/src/config.rs
index 439c17c..13dd0e4 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,5 +1,6 @@
1use config::{File, Map}; 1use config::{File, Map};
2use serde::{Deserialize, Serialize}; 2use serde::{Deserialize, Serialize};
3use tracing::{debug, trace};
3 4
4#[derive(Debug, Serialize, Deserialize)] 5#[derive(Debug, Serialize, Deserialize)]
5#[serde(default)] 6#[serde(default)]
@@ -27,11 +28,15 @@ impl Default for Config {
27 28
28impl Config { 29impl Config {
29 pub fn load() -> Result<Self, config::ConfigError> { 30 pub fn load() -> Result<Self, config::ConfigError> {
31 debug!("load config");
30 let config = config::Config::builder() 32 let config = config::Config::builder()
31 .add_source(File::with_name("config.toml").required(false)) 33 .add_source(File::with_name("config.toml").required(false))
32 .add_source(config::Environment::with_prefix("FXBAUP").separator("_")) 34 .add_source(config::Environment::with_prefix("FXBAUP").separator("_"))
33 .build()?; 35 .build()?;
34 36
35 config.try_deserialize() 37 let cfg = config.try_deserialize();
38 trace!(?cfg, "loaded config");
39
40 cfg
36 } 41 }
37} 42}
diff --git a/src/main.rs b/src/main.rs
index e67e535..1284e0c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,8 @@
1use backup::Backup; 1use backup::Backup;
2use config::Config; 2use config::Config;
3use packages::{pacman::Pacman, PackageManager}; 3use packages::{pacman::Pacman, PackageManager};
4use tracing::{debug, info, level_filters::LevelFilter};
5use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
4 6
5mod backup; 7mod backup;
6mod config; 8mod config;
@@ -11,30 +13,39 @@ mod pathinfo;
11fn main() -> color_eyre::Result<()> { 13fn main() -> color_eyre::Result<()> {
12 color_eyre::install()?; 14 color_eyre::install()?;
13 15
16 let file_appender = tracing_appender::rolling::never("./", "arps.log");
17 let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
18
19 tracing_subscriber::registry()
20 .with(
21 fmt::layer()
22 .with_writer(non_blocking)
23 .with_file(false)
24 .with_ansi(false)
25 .without_time(),
26 )
27 .with(fmt::layer().with_file(false).without_time())
28 .with(
29 EnvFilter::builder()
30 .with_default_directive(LevelFilter::INFO.into())
31 .from_env_lossy(),
32 )
33 .init();
34 debug!("logging initialized");
35
14 let mut cfg = Config::load()?; 36 let mut cfg = Config::load()?;
15 cfg.user.push("fx".to_string()); 37 cfg.user.push("fx".to_string());
16 cfg.directories.push("~/.config/nvim".to_string()); 38 cfg.directories.push("~/.config/nvim".to_string());
17 // cfg.directories.push("~/.config/hypr".to_string());
18 cfg.root = "./backup".to_string(); 39 cfg.root = "./backup".to_string();
19 // cfg.root = "./backup-test".to_string();
20 // cfg.directories.push("u:/code/proj/fxbaup/backup-test-dir".to_string());
21 40
22 let pacman = Pacman; 41 let pacman = Pacman;
23 let pkgs = pacman.get_installed()?; 42 let pkgs = pacman.get_installed()?;
24 43 let backup = Backup::create(&cfg, pkgs);
25 let backup = Backup::create(&cfg, pkgs)?; 44 // info!(?backup);
26 // println!("{backup:#?}"); 45 // pacman.install(vec![Package {
27 46 // id: "lapce".to_string(),
28 backup.save(&cfg)?; 47 // version: "0.4.2-1".to_string(),
29 48 // explicit: true,
30 // PathInfo::compare_to_last_modified(&cfg, &LocationRoot::User("fx".to_string()), "code/proj/fxbaub/backup-test-dir/size.txt")?; 49 // }])?;
31 // PathInfo::compare_to_last_modified(&cfg, &LocationRoot::User("fx".to_string()), "code/proj/fxbaub/backup-test-dir/content.txt")?;
32
33 // let index = Backup::get_index(&cfg, None)?;
34
35 // println!("{index:#?}");
36
37 // let fi = FileInfo::new("~/.config/nvim", &cfg)?;
38 // println!("{:?}", fi.get_absolute_path());
39 Ok(()) 50 Ok(())
40} 51}
diff --git a/src/packages.rs b/src/packages.rs
index e7b4c3d..5ee5664 100644
--- a/src/packages.rs
+++ b/src/packages.rs
@@ -15,5 +15,5 @@ pub struct Package {
15pub trait PackageManager { 15pub trait PackageManager {
16 fn get_installed(&self) -> Result<Vec<Package>>; 16 fn get_installed(&self) -> Result<Vec<Package>>;
17 17
18 fn install(&self, pkgs: Vec<Package>); 18 fn install(&self, pkgs: Vec<Package>) -> Result<()>;
19} 19}
diff --git a/src/packages/pacman.rs b/src/packages/pacman.rs
index b5be4c0..e10c6fb 100644
--- a/src/packages/pacman.rs
+++ b/src/packages/pacman.rs
@@ -1,4 +1,4 @@
1use std::process::Command; 1use std::process::{Command, Stdio};
2 2
3use super::{Package, PackageManager}; 3use super::{Package, PackageManager};
4 4
@@ -34,13 +34,23 @@ impl PackageManager for Pacman {
34 id: split[0].to_string(), 34 id: split[0].to_string(),
35 version: split[1].to_string(), 35 version: split[1].to_string(),
36 explicit, 36 explicit,
37 }) 37 });
38 } 38 }
39 39
40 Ok(pkgs) 40 Ok(pkgs)
41 } 41 }
42 42
43 fn install(&self, _pkgs: Vec<super::Package>) { 43 fn install(&self, pkgs: Vec<super::Package>) -> Result<()> {
44 todo!(); 44 let mut args = vec!["--noconfirm".to_string(), "-S".to_string()];
45
46 for pkg in pkgs {
47 args.push(pkg.id);
48 }
49 Command::new("pacman")
50 .stdout(Stdio::inherit())
51 .args(args)
52 .spawn()?
53 .wait_with_output()?;
54 Ok(())
45 } 55 }
46} 56}
diff --git a/src/packages/portage.rs b/src/packages/portage.rs
index 6b9e508..f9a760b 100644
--- a/src/packages/portage.rs
+++ b/src/packages/portage.rs
@@ -1,3 +1,5 @@
1use tracing::error;
2
1use super::PackageManager; 3use super::PackageManager;
2 4
3pub struct Portage; 5pub struct Portage;
@@ -7,7 +9,8 @@ impl PackageManager for Portage {
7 todo!() 9 todo!()
8 } 10 }
9 11
10 fn install(&self, pkgs: Vec<super::Package>) { 12 fn install(&self, pkgs: Vec<super::Package>) -> crate::error::Result<()> {
13 error!("Install {pkgs:?}");
11 todo!() 14 todo!()
12 } 15 }
13} 16}
diff --git a/src/pathinfo.rs b/src/pathinfo.rs
index 212dd2a..5b9aa21 100644
--- a/src/pathinfo.rs
+++ b/src/pathinfo.rs
@@ -6,9 +6,10 @@ use std::{
6}; 6};
7 7
8use serde::{Deserialize, Serialize}; 8use serde::{Deserialize, Serialize};
9use tracing::info;
9 10
10use crate::{ 11use crate::{
11 backup::{Backup, BackupId}, 12 backup::{Backup, Id},
12 config::Config, 13 config::Config,
13 error::{Error, Result}, 14 error::{Error, Result},
14}; 15};
@@ -18,7 +19,7 @@ pub struct PathInfo {
18 is_file: bool, 19 is_file: bool,
19 rel_location: String, 20 rel_location: String,
20 location_root: LocationRoot, 21 location_root: LocationRoot,
21 last_modified: Option<BackupId>, 22 last_modified: Option<Id>,
22 children: Vec<PathInfo>, 23 children: Vec<PathInfo>,
23} 24}
24 25
@@ -34,7 +35,7 @@ impl PathInfo {
34 rel_location: &str, 35 rel_location: &str,
35 location_root: &LocationRoot, 36 location_root: &LocationRoot,
36 ) -> Result<Self> { 37 ) -> Result<Self> {
37 println!("Handling {rel_location}"); 38 info!("Handling {rel_location}");
38 let path = Self::get_abs_path(&location_root.to_string(), rel_location); 39 let path = Self::get_abs_path(&location_root.to_string(), rel_location);
39 Ok(if path.is_dir() { 40 Ok(if path.is_dir() {
40 let mut last_modified = Some(String::new()); 41 let mut last_modified = Some(String::new());
@@ -51,7 +52,7 @@ impl PathInfo {
51 }; 52 };
52 let handle = Self::handle_dir(config, rl.1, location_root)?; 53 let handle = Self::handle_dir(config, rl.1, location_root)?;
53 if let Some(lm) = handle.last_modified.clone() { 54 if let Some(lm) = handle.last_modified.clone() {
54 if last_modified != None { 55 if last_modified.is_some() {
55 let ts = Backup::from_index(config, &lm)?.timestamp; 56 let ts = Backup::from_index(config, &lm)?.timestamp;
56 if ts > last_modified_timestamp { 57 if ts > last_modified_timestamp {
57 last_modified_timestamp = ts; 58 last_modified_timestamp = ts;
@@ -82,7 +83,7 @@ impl PathInfo {
82 ) -> Result<Self> { 83 ) -> Result<Self> {
83 let last_modified = Self::compare_to_last_modified(config, location_root, rel_location)?; 84 let last_modified = Self::compare_to_last_modified(config, location_root, rel_location)?;
84 85
85 println!("From file {rel_location} ({:?})", last_modified); 86 info!("From file {rel_location} ({last_modified:?})");
86 87
87 Ok(Self { 88 Ok(Self {
88 rel_location: rel_location.to_string(), 89 rel_location: rel_location.to_string(),
@@ -107,7 +108,6 @@ impl PathInfo {
107 let last_file_opt = Self::find_last_modified(files, rel_location, location_root); 108 let last_file_opt = Self::find_last_modified(files, rel_location, location_root);
108 let Some(last_file) = last_file_opt else { 109 let Some(last_file) = last_file_opt else {
109 // File didn't exist last Backup 110 // File didn't exist last Backup
110 println!("File didn't exist last Backup");
111 return Ok(None); 111 return Ok(None);
112 }; 112 };
113 113
@@ -120,8 +120,7 @@ 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)?; 123 let mut old = File::open(old_path)?; let mut new = File::open(new_path)?;
124 let mut new = File::open(new_path)?;
125 124
126 let old_len = old.metadata()?.len(); 125 let old_len = old.metadata()?.len();
127 let new_len = new.metadata()?.len(); 126 let new_len = new.metadata()?.len();
@@ -147,15 +146,10 @@ impl PathInfo {
147 ) -> Option<PathInfo> { 146 ) -> Option<PathInfo> {
148 for path in files { 147 for path in files {
149 if path.is_file { 148 if path.is_file {
150 println!("Checking {}", path.rel_location);
151 println!("File rel: {} ?= {}", path.rel_location, rel_location);
152 println!("File rot: {} ?= {}", path.location_root, location_root);
153 if path.rel_location == rel_location && path.location_root == *location_root { 149 if path.rel_location == rel_location && path.location_root == *location_root {
154 println!("Return Some");
155 return Some(path); 150 return Some(path);
156 }; 151 };
157 } else { 152 } else {
158 println!("Checking all in {path:?}");
159 let is_modified = 153 let is_modified =
160 PathInfo::find_last_modified(path.children, rel_location, location_root); 154 PathInfo::find_last_modified(path.children, rel_location, location_root);
161 if is_modified.is_some() { 155 if is_modified.is_some() {
@@ -174,11 +168,9 @@ impl PathInfo {
174 if self.last_modified.is_some() { 168 if self.last_modified.is_some() {
175 return Ok(()); 169 return Ok(());
176 } 170 }
177 println!("Save File {:?}", self.rel_location); 171 info!("Save File {:?}", self.rel_location);
178 if self.is_file { 172 if self.is_file {
179 let new_path = format!("{}/{}", backup_root, self.rel_location); 173 let new_path = format!("{}/{}", backup_root, self.rel_location);
180 // println!("New Path: {new_path}");
181 // println!("Old Path: {:?}", self.get_absolute_path());
182 let np = Path::new(&new_path); 174 let np = Path::new(&new_path);
183 if let Some(parent) = np.parent() { 175 if let Some(parent) = np.parent() {
184 create_dir_all(parent)?; 176 create_dir_all(parent)?;
@@ -194,7 +186,7 @@ impl PathInfo {
194 } 186 }
195 187
196 fn get_abs_path(location_root: &str, rel_location: &str) -> PathBuf { 188 fn get_abs_path(location_root: &str, rel_location: &str) -> PathBuf {
197 let path = format!("{}/{}", location_root, rel_location); 189 let path = format!("{location_root}/{rel_location}");
198 PathBuf::from(path) 190 PathBuf::from(path)
199 } 191 }
200 192
@@ -383,7 +375,7 @@ mod tests {
383 config.root = "./backup-test".to_string(); 375 config.root = "./backup-test".to_string();
384 config 376 config
385 .directories 377 .directories
386 .push("u:fx/code/proj/fxbaup/backup-test-dir".to_string()); 378 .push("u:fx/code/proj/arps/backup-test-dir".to_string());
387 379
388 create_dir_all("./backup-test-dir")?; 380 create_dir_all("./backup-test-dir")?;
389 let mut f = File::create("./backup-test-dir/size.txt")?; 381 let mut f = File::create("./backup-test-dir/size.txt")?;
@@ -403,12 +395,12 @@ mod tests {
403 let mut f = File::create("./backup-test-dir/content.txt")?; 395 let mut f = File::create("./backup-test-dir/content.txt")?;
404 f.write_all("unmodefied".as_bytes())?; 396 f.write_all("unmodefied".as_bytes())?;
405 397
406 let pi = PathInfo::from_path(&config, "u:fx/code/proj/fxbaup/backup-test-dir")?; 398 let pi = PathInfo::from_path(&config, "u:fx/code/proj/arps/backup-test-dir")?;
407 399
408 let last_backup = Backup::get_last(&config)?.unwrap(); 400 let last_backup = Backup::get_last(&config)?.unwrap();
409 for file in pi.children { 401 for file in pi.children {
410 println!("test rel: {}", file.rel_location); 402 println!("test rel: {}", file.rel_location);
411 let res = if file.rel_location == "code/proj/fxbaup/backup-test-dir/nothing.txt" { 403 let res = if file.rel_location == "code/proj/arps/backup-test-dir/nothing.txt" {
412 Some(last_backup.id.clone()) 404 Some(last_backup.id.clone())
413 } else { 405 } else {
414 None 406 None