diff options
author | fxqnlr <[email protected]> | 2024-09-14 18:59:23 +0200 |
---|---|---|
committer | fxqnlr <[email protected]> | 2024-09-14 18:59:23 +0200 |
commit | 0ed94b3f011a2d3c22bdc4affb502720be22c371 (patch) | |
tree | 9fb2cdbdccfa8c9cf5d9b8d3ccc48443fe6706a6 | |
parent | 1b99a4a1ed7772c9b68e59f46e493ea5b4715239 (diff) | |
download | arbs-0ed94b3f011a2d3c22bdc4affb502720be22c371.tar arbs-0ed94b3f011a2d3c22bdc4affb502720be22c371.tar.gz arbs-0ed94b3f011a2d3c22bdc4affb502720be22c371.zip |
add restoration of files and packages
-rw-r--r-- | src/backup.rs | 19 | ||||
-rw-r--r-- | src/cli.rs | 5 | ||||
-rw-r--r-- | src/error.rs | 26 | ||||
-rw-r--r-- | src/main.rs | 9 | ||||
-rw-r--r-- | src/pathinfo.rs | 44 |
5 files changed, 64 insertions, 39 deletions
diff --git a/src/backup.rs b/src/backup.rs index f9de139..3d07ace 100644 --- a/src/backup.rs +++ b/src/backup.rs | |||
@@ -45,9 +45,10 @@ impl Backup { | |||
45 | 45 | ||
46 | pub fn save(&self, config: &Config) -> Result<()> { | 46 | pub fn save(&self, config: &Config) -> Result<()> { |
47 | info!("Save Backup {:?}", self.get_location(config)); | 47 | info!("Save Backup {:?}", self.get_location(config)); |
48 | self.get_location(config).append_to_root(config)?; | 48 | let loc = self.get_location(config); |
49 | loc.append_to_root(config)?; | ||
49 | 50 | ||
50 | let backup_root = self.get_location(config).get_absolute_dir(config); | 51 | let backup_root = loc.get_absolute_dir(config); |
51 | create_dir_all(&backup_root).unwrap(); | 52 | create_dir_all(&backup_root).unwrap(); |
52 | let path = format!("{backup_root}/index.json"); | 53 | let path = format!("{backup_root}/index.json"); |
53 | let mut f = File::create(path).unwrap(); | 54 | let mut f = File::create(path).unwrap(); |
@@ -66,7 +67,7 @@ impl Backup { | |||
66 | let list: Vec<IndexEntry> = match Self::get_json_content(&backup_index_root) { | 67 | let list: Vec<IndexEntry> = match Self::get_json_content(&backup_index_root) { |
67 | Ok(list) => list, | 68 | Ok(list) => list, |
68 | Err(err) => { | 69 | Err(err) => { |
69 | if err.to_string() == "io: No such file or directory (os error 2)" { | 70 | if err.to_string() == "No such file or directory (os error 2)" { |
70 | return Ok(None); | 71 | return Ok(None); |
71 | }; | 72 | }; |
72 | return Err(err); | 73 | return Err(err); |
@@ -112,8 +113,16 @@ impl Backup { | |||
112 | format!("{loc}/{rel_location}") | 113 | format!("{loc}/{rel_location}") |
113 | } | 114 | } |
114 | 115 | ||
115 | pub fn restore(&self) { | 116 | pub fn restore(&self, config: &Config) -> Result<()> { |
116 | todo!() | 117 | info!(?self.id, ?self.timestamp, "Restore Backup"); |
118 | |||
119 | let backup_root = self.get_location(config).get_absolute_dir(config); | ||
120 | |||
121 | for path in &self.files { | ||
122 | path.restore(config, &backup_root)?; | ||
123 | } | ||
124 | |||
125 | Ok(()) | ||
117 | } | 126 | } |
118 | 127 | ||
119 | fn get_json_content<T: for<'a> Deserialize<'a>>(path: &str) -> Result<T> { | 128 | fn get_json_content<T: for<'a> Deserialize<'a>>(path: &str) -> Result<T> { |
@@ -20,6 +20,9 @@ pub enum Subcommands { | |||
20 | #[arg(short, long)] | 20 | #[arg(short, long)] |
21 | package_manager: Option<Manager>, | 21 | package_manager: Option<Manager>, |
22 | }, | 22 | }, |
23 | Restore, | 23 | Restore { |
24 | #[arg(short, long)] | ||
25 | package_install: bool | ||
26 | }, | ||
24 | } | 27 | } |
25 | 28 | ||
diff --git a/src/error.rs b/src/error.rs index e24c3b1..cb57e99 100644 --- a/src/error.rs +++ b/src/error.rs | |||
@@ -24,21 +24,13 @@ pub enum Error { | |||
24 | #[error("Unsupported os/distro")] | 24 | #[error("Unsupported os/distro")] |
25 | Unsupported, | 25 | Unsupported, |
26 | 26 | ||
27 | #[error("json: {source}")] | 27 | // Deps |
28 | SerdeJson { | 28 | #[error(transparent)] |
29 | #[from] | 29 | SerdeJson(#[from] serde_json::Error), |
30 | source: serde_json::Error, | 30 | |
31 | }, | 31 | #[error(transparent)] |
32 | 32 | TomlSerialize(#[from] toml::ser::Error), | |
33 | #[error("toml serializer: {source}")] | 33 | |
34 | TomlSerialize { | 34 | #[error(transparent)] |
35 | #[from] | 35 | Io(#[from] std::io::Error), |
36 | source: toml::ser::Error, | ||
37 | }, | ||
38 | |||
39 | #[error("io: {source}")] | ||
40 | Io { | ||
41 | #[from] | ||
42 | source: std::io::Error, | ||
43 | }, | ||
44 | } | 36 | } |
diff --git a/src/main.rs b/src/main.rs index 7393af9..487d095 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -46,13 +46,16 @@ fn main() -> color_eyre::Result<()> { | |||
46 | let backup = Backup::create(&config, package_manager)?; | 46 | let backup = Backup::create(&config, package_manager)?; |
47 | backup.save(&config)?; | 47 | backup.save(&config)?; |
48 | } | 48 | } |
49 | Subcommands::Restore => { | 49 | Subcommands::Restore { package_install } => { |
50 | let Some(last_backup) = Backup::get_last(&config)? else { | 50 | let Some(last_backup) = Backup::get_last(&config)? else { |
51 | return Err(Error::BackupNotFound)?; | 51 | return Err(Error::BackupNotFound)?; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | last_backup.packages.install()?; | 54 | if package_install { |
55 | last_backup.restore(); | 55 | last_backup.packages.install()?; |
56 | } | ||
57 | |||
58 | last_backup.restore(&config)?; | ||
56 | } | 59 | } |
57 | }; | 60 | }; |
58 | Ok(()) | 61 | Ok(()) |
diff --git a/src/pathinfo.rs b/src/pathinfo.rs index 03b8a6b..1231ff8 100644 --- a/src/pathinfo.rs +++ b/src/pathinfo.rs | |||
@@ -6,7 +6,7 @@ use std::{ | |||
6 | }; | 6 | }; |
7 | 7 | ||
8 | use serde::{Deserialize, Serialize}; | 8 | use serde::{Deserialize, Serialize}; |
9 | use tracing::info; | 9 | use tracing::{debug, info}; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | backup::{Backup, Id}, | 12 | backup::{Backup, Id}, |
@@ -186,6 +186,33 @@ impl PathInfo { | |||
186 | Ok(()) | 186 | Ok(()) |
187 | } | 187 | } |
188 | 188 | ||
189 | pub fn restore(&self, config: &Config, backup_root: &str) -> Result<()> { | ||
190 | if self.is_file { | ||
191 | info!(?self.rel_location, "Restore File"); | ||
192 | let backup_path = if let Some(last_modified) = self.last_modified.clone() { | ||
193 | let backup = Backup::from_index(config, &last_modified)?; | ||
194 | &backup.get_location(config).get_absolute_dir(config) | ||
195 | } else { | ||
196 | backup_root | ||
197 | }; | ||
198 | let backup_loc = format!("{}/{}", backup_path, self.rel_location); | ||
199 | let system_loc = self.get_absolute_path(); | ||
200 | debug!(?backup_loc, ?system_loc, "copy"); | ||
201 | |||
202 | if let Some(parents) = system_loc.parent() { | ||
203 | create_dir_all(parents)?; | ||
204 | } | ||
205 | |||
206 | std::fs::copy(backup_loc, system_loc)?; | ||
207 | } else { | ||
208 | for path in &self.children { | ||
209 | path.restore(config, backup_root)?; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | Ok(()) | ||
214 | } | ||
215 | |||
189 | fn get_abs_path(location_root: &str, rel_location: &str) -> PathBuf { | 216 | fn get_abs_path(location_root: &str, rel_location: &str) -> PathBuf { |
190 | let path = format!("{location_root}/{rel_location}"); | 217 | let path = format!("{location_root}/{rel_location}"); |
191 | PathBuf::from(path) | 218 | PathBuf::from(path) |
@@ -196,10 +223,7 @@ impl PathInfo { | |||
196 | return Err(Error::InvalidDirectory(value.to_string())); | 223 | return Err(Error::InvalidDirectory(value.to_string())); |
197 | }; | 224 | }; |
198 | if split.0.starts_with('~') { | 225 | if split.0.starts_with('~') { |
199 | return Ok(( | 226 | return Ok((split.1.to_string(), LocationRoot::User)); |
200 | split.1.to_string(), | ||
201 | LocationRoot::User, | ||
202 | )); | ||
203 | }; | 227 | }; |
204 | Ok(( | 228 | Ok(( |
205 | split.1.to_string(), | 229 | split.1.to_string(), |
@@ -330,17 +354,11 @@ mod tests { | |||
330 | let mut values_ok: Vec<(&str, (String, LocationRoot))> = Vec::new(); | 354 | let mut values_ok: Vec<(&str, (String, LocationRoot))> = Vec::new(); |
331 | values_ok.push(( | 355 | values_ok.push(( |
332 | "~/.config/nvim", | 356 | "~/.config/nvim", |
333 | ( | 357 | (".config/nvim".to_string(), LocationRoot::User), |
334 | ".config/nvim".to_string(), | ||
335 | LocationRoot::User, | ||
336 | ), | ||
337 | )); | 358 | )); |
338 | values_ok.push(( | 359 | values_ok.push(( |
339 | "u:test/.config/nvim", | 360 | "u:test/.config/nvim", |
340 | ( | 361 | (".config/nvim".to_string(), LocationRoot::User), |
341 | ".config/nvim".to_string(), | ||
342 | LocationRoot::User, | ||
343 | ), | ||
344 | )); | 362 | )); |
345 | values_ok.push(( | 363 | values_ok.push(( |
346 | "r:/.config/nvim", | 364 | "r:/.config/nvim", |