From 28f0988f5fd65983a8e8f71248becae8889498ea Mon Sep 17 00:00:00 2001 From: Xory Date: Tue, 10 Sep 2024 11:02:19 +0300 Subject: [PATCH] feat: add stage 2 --- log.txt | 4 +++ resetenv.sh | 4 +++ src/lib.rs | 64 ++++++++++++++++++++++++++++++++++++--- src/main.rs | 15 ++++++--- testconfig.toml | 8 ++++- testfiles/dir/a/file3.txt | 0 testfiles/dir/file1.txt | 1 + testfiles/dir/file2.txt | 1 + 8 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 resetenv.sh create mode 100644 testfiles/dir/a/file3.txt create mode 100644 testfiles/dir/file1.txt create mode 100644 testfiles/dir/file2.txt diff --git a/log.txt b/log.txt index e69de29..85d8832 100644 --- a/log.txt +++ b/log.txt @@ -0,0 +1,4 @@ + +I: Begin backup log - 1725955295 +I: Beginning stage 1 backup. +I: Beginning stage 2 backup. diff --git a/resetenv.sh b/resetenv.sh new file mode 100644 index 0000000..6835b85 --- /dev/null +++ b/resetenv.sh @@ -0,0 +1,4 @@ +#! /bin/bash +rm -r testfiles/dir/* +echo "" > log.txt +rm -r /run/media/xory/Ventoy/backup/* diff --git a/src/lib.rs b/src/lib.rs index b3d604f..74e6f58 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,12 +15,20 @@ pub struct StageConfig { #[derive(Deserialize, Debug, PartialEq)] pub struct Config { - pub stage_1: StageConfig + pub stage_1: StageConfig, + pub stage_2: StageConfig } impl Config { pub fn new(config_toml: String) -> Config { - toml::from_str(&config_toml).expect("Invalid Config") + let config = match toml::from_str(&config_toml) { + Ok(config) => config, + Err(err) => { + let _ = log("./log.txt".to_string(), format!("Failed to parse config, got error {err}"), LogLevel::Error); + std::process::exit(1); + } + }; + config } } @@ -55,6 +63,44 @@ pub fn stage1(config: &Config) -> io::Result<()> { Ok(()) } +pub fn stage2(config: &Config) -> io::Result<()> { + for file in &config.stage_2.src_files { + let filename = match file.split('/').last() { + Some(filename) => filename, + None => { eprintln!("E: Failed to derive filename from {file}"); break } + }; + + let target_path = format!("{}/{filename}", &config.stage_2.target_dir); + if !Path::new(&config.stage_2.target_dir).exists() { + log(".log.txt".to_string(), "External drive missing or not mounted, please insert and/or mount the drive and try again.".to_string(), LogLevel::Error)?; + break + } + + if Path::new(file).is_file() { + if let Err(err) = fs::copy(file, target_path) { + log("./log.txt".to_string(), err.to_string(), LogLevel::Error)?; + break + }; + } else if Path::new(file).is_dir() && config.stage_2.recursive { + if let Err(err) = fs::create_dir(target_path) { + log("./log.txt".to_string(), err.to_string(), LogLevel::Error)?; + break + } + for entry in fs::read_dir(file)? { + let target_dir = format!("{}/{}", &config.stage_2.target_dir, filename); + let file = entry?; + if let Err(err) = fs::copy(Path::new(&file.path()), format!("{}/{}", target_dir, file.file_name().to_str().unwrap())) { + log("./log.txt".to_string(), err.to_string(), LogLevel::Error)?; + break + }; + } + } else { + log("./log.txt".to_string(), "Copy conditions not matched for file {file}, skipping.".to_string(), LogLevel::Warning)?; + } + } + Ok(()) +} + #[cfg(test)] mod tests { use super::*; @@ -64,7 +110,12 @@ mod tests { let toml_config = "[stage_1] src_files = [ './testfiles/src/file1.txt', './testfiles/src/file2.txt', './testfiles/src/a' ] target_dir = './testfiles/dir' - recursive = true"; + recursive = true + [stage_2] + src_files = [ './testfiles/src/file1.txt', './testfiles/src/file2.txt', './testfiles/src/a' ] + target_dir = '/run/media/xory/Ventoy/backup' + recursive = true + "; let parsed_config = Config::new(toml_config.to_string()); assert_eq!( @@ -73,7 +124,12 @@ mod tests { src_files: vec![ "./testfiles/src/file1.txt".to_string(), "./testfiles/src/file2.txt".to_string(), "./testfiles/src/a".to_string() ], target_dir: "./testfiles/dir".to_string(), recursive: true - } + }, + stage_2: StageConfig { + src_files: vec![ "./testfiles/src/file1.txt".to_string(), "./testfiles/src/file2.txt".to_string(), "./testfiles/src/a".to_string() ], + target_dir: "/run/media/xory/Ventoy/backup".to_string(), + recursive: true + } }, parsed_config ); diff --git a/src/main.rs b/src/main.rs index 58864b9..851f168 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,18 @@ -use cynewave::{Config, stage1}; +use cynewave::{Config, stage1, stage2}; mod logger; use logger::{log, LogLevel}; use std::fs; +use std::time::{UNIX_EPOCH, SystemTime}; -fn main() { +fn main() -> Result<(), Box> { + let current_epoch = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs(); + log("./log.txt".to_string(), format!("Begin backup log - {current_epoch}"), LogLevel::Info)?; let config_file: String = fs::read_to_string("./testconfig.toml").expect("Failed to read config"); let config: Config = Config::new(config_file); dbg!(&config); - log("./log.txt".to_string(), "Beginning stage 1 backup.".to_string(), LogLevel::Info).unwrap(); - stage1(&config).unwrap(); - + log("./log.txt".to_string(), "Beginning stage 1 backup.".to_string(), LogLevel::Info)?; + stage1(&config)?; + log("./log.txt".to_string(), "Beginning stage 2 backup.".to_string(), LogLevel::Info)?; + stage2(&config)?; + Ok(()) } diff --git a/testconfig.toml b/testconfig.toml index b2e6aa0..cece4bf 100644 --- a/testconfig.toml +++ b/testconfig.toml @@ -1,5 +1,11 @@ [stage_1] src_files = [ "./testfiles/src/file1.txt", "./testfiles/src/file2.txt", "./testfiles/src/a" ] target_dir = "./testfiles/dir" -recursive = false +recursive = true + +[stage_2] +src_files = [ "./testfiles/src/file1.txt", "./testfiles/src/file2.txt", "./testfiles/src/a" ] +target_dir = "/run/media/xory/Ventoy/backup" +recursive = true + diff --git a/testfiles/dir/a/file3.txt b/testfiles/dir/a/file3.txt new file mode 100644 index 0000000..e69de29 diff --git a/testfiles/dir/file1.txt b/testfiles/dir/file1.txt new file mode 100644 index 0000000..7898192 --- /dev/null +++ b/testfiles/dir/file1.txt @@ -0,0 +1 @@ +a diff --git a/testfiles/dir/file2.txt b/testfiles/dir/file2.txt new file mode 100644 index 0000000..6178079 --- /dev/null +++ b/testfiles/dir/file2.txt @@ -0,0 +1 @@ +b