init: initial code

This commit is contained in:
Xory 2024-09-08 15:50:34 +03:00
commit 7cf6adc479
11 changed files with 142 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
/Cargo.lock

8
Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "cynewave"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { version = "1.0.210", features = [ "derive" ] }
toml = "0.8.19"

2
README.md Normal file
View file

@ -0,0 +1,2 @@
# Cynewave
Cynewave is a WIP fast and configurable backup system written in Rust.

0
log.txt Normal file
View file

81
src/lib.rs Normal file
View file

@ -0,0 +1,81 @@
use serde::Deserialize;
use toml;
use std::{fs, io, path::Path};
mod logger;
use logger::{log, LogLevel};
#[derive(Deserialize, Debug, PartialEq)]
pub struct StageConfig {
pub src_files: Vec<String>,
pub target_dir: String,
pub recursive: bool
}
#[derive(Deserialize, Debug, PartialEq)]
pub struct Config {
pub stage_1: StageConfig
}
impl Config {
pub fn new(config_toml: String) -> Config {
toml::from_str(&config_toml).expect("Invalid Config")
}
}
pub fn stage1(config: &Config) -> io::Result<()> {
for file in &config.stage_1.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_1.target_dir);
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)?;
};
} else if Path::new(file).is_dir() && config.stage_1.recursive {
if let Err(err) = fs::create_dir(target_path) {
log("./log.txt".to_string(), err.to_string(), LogLevel::Error)?;
}
for entry in fs::read_dir(file)? {
let target_dir = format!("{}/{}", &config.stage_1.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)?;
};
}
} 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::*;
#[test]
fn config_parser_test() {
let toml_config = "[stage_1]
src_files = [ './testfiles/src/file1.txt', './testfiles/src/file2.txt', './testfiles/src/a' ]
target_dir = './testfiles/dir'
recursive = true";
let parsed_config = Config::new(toml_config.to_string());
assert_eq!(
Config {
stage_1: StageConfig {
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
}
},
parsed_config
);
}
}

29
src/logger.rs Normal file
View file

@ -0,0 +1,29 @@
use std::io::{Result, Write};
use std::fs::OpenOptions;
pub enum LogLevel {
Error,
Warning,
Info
}
pub fn log(logfile: String, text: String, level: LogLevel) -> Result<()> {
let prefix = match level {
LogLevel::Error => "E".to_string(),
LogLevel::Warning => "W".to_string(),
LogLevel::Info => "I".to_string()
};
let msg = format!("{prefix}: {text}");
println!("{msg}");
let mut logfile = OpenOptions::new()
.read(false)
.write(false)
.append(true)
.open(logfile)?;
logfile.write(msg.as_bytes())?;
logfile.write(b"
")?;
Ok(())
}

13
src/main.rs Normal file
View file

@ -0,0 +1,13 @@
use cynewave::{Config, stage1};
mod logger;
use logger::{log, LogLevel};
use std::fs;
fn main() {
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();
}

5
testconfig.toml Normal file
View file

@ -0,0 +1,5 @@
[stage_1]
src_files = [ "./testfiles/src/file1.txt", "./testfiles/src/file2.txt", "./testfiles/src/a" ]
target_dir = "./testfiles/dir"
recursive = false

View file

1
testfiles/src/file1.txt Normal file
View file

@ -0,0 +1 @@
a

1
testfiles/src/file2.txt Normal file
View file

@ -0,0 +1 @@
b