From ab7f99e061e54924899b778e929dd2e17c8792d9 Mon Sep 17 00:00:00 2001 From: fxqnlr Date: Fri, 6 Sep 2024 13:47:47 +0200 Subject: add root index and directory creation --- src/backup.rs | 89 ++++++++++++++++++++++++--- src/error.rs | 17 ++++- src/main.rs | 13 ++-- src/pathinfo.rs | 188 ++++++++++++++++++++++++++++---------------------------- src/storage.rs | 8 --- 5 files changed, 197 insertions(+), 118 deletions(-) delete mode 100644 src/storage.rs (limited to 'src') diff --git a/src/backup.rs b/src/backup.rs index 4e74c97..69bc2ea 100644 --- a/src/backup.rs +++ b/src/backup.rs @@ -1,9 +1,20 @@ -use std::time::{SystemTime, UNIX_EPOCH}; +use std::{ + fs::{create_dir_all, File, OpenOptions}, + io::{ErrorKind, Read, Write}, + path::PathBuf, + time::{SystemTime, UNIX_EPOCH}, +}; +use gethostname::gethostname; use serde::{Deserialize, Serialize}; use uuid::Uuid; -use crate::{config::Config, pathinfo::PathInfo, packages::Package, error::Result}; +use crate::{ + config::Config, + error::{Error, Result}, + packages::Package, + pathinfo::PathInfo, +}; pub type BackupId = String; @@ -24,21 +35,81 @@ impl Backup { Ok(Self { // UUID not really needed, maybe a shorter hash id: Uuid::new_v4().to_string(), - timestamp: SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_secs(), + timestamp: Self::get_timestamp(), packages, files, }) } - + pub fn save(&self, config: &Config) -> Result<()> { + let rel_location = format!( + "bu_{}_{}", + gethostname() + .into_string() + .map_err(|_| Error::InvalidOsString)?, + Self::get_timestamp() + ); + + let bl = BackupLocation { + id: self.id.to_string(), + rel_location, + }; + + Self::append_to_root_index(config, bl.clone())?; + + let backup_root = format!("{}/{}", config.root, bl.rel_location); + create_dir_all(&backup_root).unwrap(); + let path = format!("{}/index.json", backup_root); + let mut f = File::create(path).unwrap(); + f.write_all(&serde_json::to_vec(self).unwrap()).unwrap(); + + Ok(()) + } + + pub fn get(config: &Config, _id: Option) -> Result<()> { + let backup_index_root = format!("{}/index.json", config.root); + let mut file = File::open(backup_index_root)?; + let mut content = String::new(); + file.read_to_string(&mut content)?; + let list: Vec = serde_json::from_str(&content)?; + println!("{list:#?}"); + + todo!(); + + Ok(()) + } + + fn append_to_root_index(config: &Config, new_backup: BackupLocation) -> Result<()> { + let backup_index_root = format!("{}/index.json", config.root); + let path = PathBuf::from(&backup_index_root); + if path.exists() { + let mut f = File::open(&path)?; + let mut content = String::new(); + f.read_to_string(&mut content)?; + let mut loc: Vec = serde_json::from_str(&content)?; + + let mut f = File::create(path)?; + loc.push(new_backup); + + f.write_all(&serde_json::to_vec(&loc)?)?; + } else { + let mut f = File::create(backup_index_root)?; + f.write_all(&serde_json::to_vec(&vec![new_backup])?)?; + }; + + Ok(()) + } + + fn get_timestamp() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + } } +#[derive(Debug, Clone, Serialize, Deserialize)] struct BackupLocation { id: BackupId, rel_location: String, } - -type BackupList = Vec; diff --git a/src/error.rs b/src/error.rs index 77eab69..dc132f4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,6 @@ pub type Result = std::result::Result; -#[derive(Debug, PartialEq, Eq, thiserror::Error)] +#[derive(Debug, thiserror::Error)] pub enum Error { #[error("unknown custom directory '{0}'")] CustomDirectory(String), @@ -16,4 +16,19 @@ pub enum Error { #[error("Only exactly one user allowed in config")] MultiUser, + + #[error("OsString couldn't be converted to string")] + InvalidOsString, + + #[error("json: {source}")] + SerdeJson { + #[from] + source: serde_json::Error, + }, + + #[error("io: {source}")] + Io { + #[from] + source: std::io::Error, + } } diff --git a/src/main.rs b/src/main.rs index 1fdcebf..e0b3758 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,21 @@ use backup::Backup; use config::Config; use packages::{pacman::Pacman, PackageManager}; -use storage::save_index; mod backup; mod config; mod error; mod pathinfo; mod packages; -mod storage; -fn main() -> anyhow::Result<()> { +fn main() -> color_eyre::Result<()> { + color_eyre::install()?; + let mut cfg = Config::load()?; cfg.user.push("fx".to_string()); cfg.directories.push("~/.config/nvim".to_string()); cfg.directories.push("~/.config/hypr".to_string()); - let toml = toml::to_string(&cfg)?; - println!("{toml}"); + cfg.root = "./backup".to_string(); let pacman = Pacman; let pkgs = pacman.get_installed(); @@ -24,7 +23,9 @@ fn main() -> anyhow::Result<()> { let backup = Backup::create(&cfg, pkgs)?; // println!("{backup:#?}"); - save_index(backup); + backup.save(&cfg)?; + + Backup::get(&cfg, None)?; // let fi = FileInfo::new("~/.config/nvim", &cfg)?; // println!("{:?}", fi.get_absolute_path()); diff --git a/src/pathinfo.rs b/src/pathinfo.rs index b0c3be4..be43b6e 100644 --- a/src/pathinfo.rs +++ b/src/pathinfo.rs @@ -150,97 +150,97 @@ impl LocationRoot { } } -#[cfg(test)] -mod tests { - use crate::{ - config::Config, - error::{Error, Result}, - pathinfo::PathInfo, - }; - - use super::LocationRoot; - - #[test] - fn from_op_str() -> Result<()> { - let mut config = Config::default(); - config - .custom_directories - .insert("test".to_string(), "/usr/local/test".to_string()); - - let mut values: Vec<(&str, Result)> = Vec::new(); - values.push(("u:test", Ok(LocationRoot::User("test".to_string())))); - values.push(("s:", Ok(LocationRoot::SystemSettings))); - values.push(("r:", Ok(LocationRoot::Root))); - values.push(( - "c:test", - Ok(LocationRoot::Custom("/usr/local/test".to_string())), - )); - values.push(("c:rest", Err(Error::CustomDirectory("rest".to_string())))); - values.push(("t:test/", Err(Error::InvalidIndex("t".to_string())))); - values.push(( - "test:test/usr", - Err(Error::InvalidIndex("test".to_string())), - )); - values.push(("/usr/local/test", Err(Error::NoIndex))); - values.push(("c/usr/local/test", Err(Error::NoIndex))); - - for value in values { - print!("Testing {value:?}"); - assert_eq!(LocationRoot::from_op_str(value.0, &config), value.1); - println!("\rTesting {value:?} ✓"); - } - - Ok(()) - } - - #[test] - fn parse_location() -> Result<()> { - let mut config = Config::default(); - config.user.push("test".to_string()); - config - .custom_directories - .insert("test".to_string(), "/usr/local/test".to_string()); - - let mut values: Vec<(&str, Result<(String, LocationRoot)>)> = Vec::new(); - values.push(( - "~/.config/nvim", - Ok(( - ".config/nvim".to_string(), - LocationRoot::User("test".to_string()), - )), - )); - values.push(( - "u:test/.config/nvim", - Ok(( - ".config/nvim".to_string(), - LocationRoot::User("test".to_string()), - )), - )); - values.push(( - "r:/.config/nvim", - Ok((".config/nvim".to_string(), LocationRoot::Root)), - )); - values.push(( - "r:/.config/nvim", - Ok((".config/nvim".to_string(), LocationRoot::Root)), - )); - values.push(( - "s:/.config/nvim", - Ok((".config/nvim".to_string(), LocationRoot::SystemSettings)), - )); - values.push(( - "c:test/.config/nvim", - Ok(( - ".config/nvim".to_string(), - LocationRoot::Custom("/usr/local/test".to_string()), - )), - )); - - for value in values { - print!("Testing {value:?}"); - assert_eq!(PathInfo::parse_location(&value.0, &config), value.1); - println!("\rTesting {value:?} ✓"); - } - Ok(()) - } -} +// #[cfg(test)] +// mod tests { +// use crate::{ +// config::Config, +// error::{Error, Result}, +// pathinfo::PathInfo, +// }; +// +// use super::LocationRoot; +// +// #[test] +// fn from_op_str() -> Result<()> { +// let mut config = Config::default(); +// config +// .custom_directories +// .insert("test".to_string(), "/usr/local/test".to_string()); +// +// let mut values: Vec<(&str, Result)> = Vec::new(); +// values.push(("u:test", Ok(LocationRoot::User("test".to_string())))); +// values.push(("s:", Ok(LocationRoot::SystemSettings))); +// values.push(("r:", Ok(LocationRoot::Root))); +// values.push(( +// "c:test", +// Ok(LocationRoot::Custom("/usr/local/test".to_string())), +// )); +// values.push(("c:rest", Err(Error::CustomDirectory("rest".to_string())))); +// values.push(("t:test/", Err(Error::InvalidIndex("t".to_string())))); +// values.push(( +// "test:test/usr", +// Err(Error::InvalidIndex("test".to_string())), +// )); +// values.push(("/usr/local/test", Err(Error::NoIndex))); +// values.push(("c/usr/local/test", Err(Error::NoIndex))); +// +// for value in values { +// print!("Testing {value:?}"); +// assert_eq!(LocationRoot::from_op_str(value.0, &config), value.1); +// println!("\rTesting {value:?} ✓"); +// } +// +// Ok(()) +// } +// +// #[test] +// fn parse_location() -> Result<()> { +// let mut config = Config::default(); +// config.user.push("test".to_string()); +// config +// .custom_directories +// .insert("test".to_string(), "/usr/local/test".to_string()); +// +// let mut values: Vec<(&str, Result<(String, LocationRoot)>)> = Vec::new(); +// values.push(( +// "~/.config/nvim", +// Ok(( +// ".config/nvim".to_string(), +// LocationRoot::User("test".to_string()), +// )), +// )); +// values.push(( +// "u:test/.config/nvim", +// Ok(( +// ".config/nvim".to_string(), +// LocationRoot::User("test".to_string()), +// )), +// )); +// values.push(( +// "r:/.config/nvim", +// Ok((".config/nvim".to_string(), LocationRoot::Root)), +// )); +// values.push(( +// "r:/.config/nvim", +// Ok((".config/nvim".to_string(), LocationRoot::Root)), +// )); +// values.push(( +// "s:/.config/nvim", +// Ok((".config/nvim".to_string(), LocationRoot::SystemSettings)), +// )); +// values.push(( +// "c:test/.config/nvim", +// Ok(( +// ".config/nvim".to_string(), +// LocationRoot::Custom("/usr/local/test".to_string()), +// )), +// )); +// +// for value in values { +// print!("Testing {value:?}"); +// assert_eq!(PathInfo::parse_location(&value.0, &config), value.1); +// println!("\rTesting {value:?} ✓"); +// } +// Ok(()) +// } +// } diff --git a/src/storage.rs b/src/storage.rs deleted file mode 100644 index b9e8de9..0000000 --- a/src/storage.rs +++ /dev/null @@ -1,8 +0,0 @@ -use std::{fs::File, io::Write}; - -use crate::backup::Backup; - -pub fn save_index(backup: Backup) { - let mut f = File::create("./index.json").unwrap(); - f.write_all(&serde_json::to_vec(&backup).unwrap()).unwrap(); -} -- cgit v1.2.3