refractr/src/config.rs
2025-03-02 14:39:12 -07:00

155 lines
4.1 KiB
Rust

use crate::common;
use core::fmt;
use std::io::Read;
use std::path::PathBuf;
use std::fs;
use std::env;
use std::fs::{File, Metadata};
use toml;
use serde_derive::Deserialize;
pub struct ConfigFile {
pub path: String,
pub file: Metadata,
pub config: Config
}
impl fmt::Display for ConfigFile {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let branches_list = match &self.config.branches {
None => String::from("All branches"),
Some(vec) => {
let mut out = String::from("[");
for i in 0..vec.len() {
out = format!("{}{}", out, vec[i]);
if i < vec.len() - 1 {
out.push_str(", ");
}
}
out.push(']');
out
}
};
let mut to_list = String::from("[");
for i in 0..self.config.to.len() {
to_list.push_str(&self.config.to[i]);
if i < self.config.to.len() - 1 {
to_list.push_str(", ");
}
};
to_list.push(']');
let work_dir_path = match &self.config.work_dir {
None => {
if cfg!(windows) {
format!("Using default \"{}\\refractr\"", match env::var("TEMP") {
Ok(val) => val,
Err(_) => format!("This shouldn't happen!")
})
} else {
format!("Using default: /tmp/refractr")
}
},
Some(path) => format!("{}", path)
};
let schedule_interval = match self.config.schedule.interval {
None => {
if !self.config.schedule.enabled {
String::from("")
} else {
String::from("This shouldn't happen!\n")
}
},
Some(int) => format!("\n Scheduled interval in seconds: {}", int.to_string())
};
write!(f, "Config file: \"{}\"\n \
Is a file: {}\n \
Read only: {}\n \
Configuration:\n \
Git repo to clone: {}\n \
Git repos to push clone to: {}\n \
Branches of clone to push: {}\n \
Working directory: {}\n \
SSH key for pushing clone: {}\n \
Schedule enabled: {}\
{}"
, self.path, self.file.is_file(), self.file.permissions().readonly(), self.config.from
, to_list, branches_list, work_dir_path, self.config.git.ssh_identity_file, self.config.schedule.enabled
, schedule_interval)
}
}
#[derive(Deserialize)]
pub struct Config {
from: String,
to: Vec<String>,
branches: Option<Vec<String>>,
work_dir: Option<String>,
git: Git,
schedule: Schedule
}
#[derive(Deserialize)]
struct Git {
ssh_identity_file: String,
}
#[derive(Deserialize)]
struct Schedule {
enabled: bool,
interval: Option<i32>,
}
pub fn read_config(paths: Vec<PathBuf>, refractr: &common::Refractr) -> Vec<ConfigFile> {
let mut config_files: Vec<ConfigFile> = vec![];
for path in paths {
common::verbose(refractr.verbose, 1, format!("Reading config file: \"{}\"", String::from(path.to_string_lossy())));
let mut data = String::new();
let mut file = match File::open(path.as_path()) {
Err(e) => panic!("refractr: unable to open {}: {}", path.as_path().display(), e),
Ok(file) => file
};
if let Err(e) = file.read_to_string(&mut data) {
panic!("refractr: unable to read {}: {}", path.as_path().display(), e)
}
let config_file = ConfigFile {
path: String::from(path.to_string_lossy()),
file: match fs::metadata(&path) {
Err(_) => panic!("refractr: cannot obtain metadata: {}", path.as_path().display()),
Ok(metadata) => metadata
},
config: verify_config(toml::from_str(&data).unwrap())
};
config_files.push(config_file);
}
return config_files;
}
fn verify_config(config: Config) -> Config {
if config.schedule.enabled {
assert_ne!(config.schedule.interval, None);
}
assert_ne!("", match &config.work_dir {
Some(path) => format!("{}", path),
None => {
if cfg!(windows) {
match env::var("TEMP") {
Ok(val) => val,
Err(_) => format!("")
}
} else {
format!("/tmp/refractr")
}
},
});
return config;
}