refractr/src/config.rs

176 lines
4.8 KiB
Rust
Raw Normal View History

2025-03-02 11:47:29 -07:00
use crate::common;
use core::fmt;
2025-02-15 22:11:08 -07:00
use std::io::Read;
use std::path::PathBuf;
2025-03-02 11:47:29 -07:00
use std::fs;
2025-03-02 14:39:12 -07:00
use std::env;
2025-03-02 11:47:29 -07:00
use std::fs::{File, Metadata};
2025-02-15 22:11:08 -07:00
use toml;
use serde_derive::Deserialize;
2025-03-02 11:47:29 -07:00
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(']');
2025-03-02 14:39:12 -07:00
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: {}\
2025-03-02 11:47:29 -07:00
{}"
, self.path, self.file.is_file(), self.file.permissions().readonly(), self.config.from
2025-03-02 14:39:12 -07:00
, to_list, branches_list, work_dir_path, self.config.git.ssh_identity_file, self.config.schedule.enabled
, schedule_interval)
2025-03-02 11:47:29 -07:00
}
}
#[derive(PartialEq)]
2025-02-15 22:11:08 -07:00
#[derive(Deserialize)]
2025-03-02 14:39:12 -07:00
pub struct Config {
2025-03-02 18:33:33 -07:00
pub from: String,
pub to: Vec<String>,
pub branches: Option<Vec<String>>,
pub work_dir: Option<String>,
pub git: Git,
pub schedule: Schedule
2025-02-15 22:11:08 -07:00
}
#[derive(PartialEq)]
2025-02-15 22:11:08 -07:00
#[derive(Deserialize)]
2025-03-03 21:10:31 -07:00
pub struct Git {
pub ssh_identity_file: String,
2025-02-15 22:11:08 -07:00
}
#[derive(PartialEq)]
2025-02-15 22:11:08 -07:00
#[derive(Deserialize)]
2025-03-03 21:10:31 -07:00
pub struct Schedule {
pub enabled: bool,
pub interval: Option<i32>,
2025-02-15 22:11:08 -07:00
}
2025-03-02 11:47:29 -07:00
pub fn read_config(paths: Vec<PathBuf>, refractr: &common::Refractr) -> Vec<ConfigFile> {
let mut config_files: Vec<ConfigFile> = vec![];
for path in paths {
2025-03-02 14:39:12 -07:00
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()) {
2025-03-02 11:47:29 -07:00
Err(e) => panic!("refractr: unable to open {}: {}", path.as_path().display(), e),
Ok(file) => file
};
2025-02-15 22:11:08 -07:00
if let Err(e) = file.read_to_string(&mut data) {
2025-03-02 11:47:29 -07:00
panic!("refractr: unable to read {}: {}", path.as_path().display(), e)
}
2025-03-02 11:47:29 -07:00
let config_file = ConfigFile {
path: match fs::canonicalize(&path) {
Err(_) => panic!("refractr: cannot get absolute path of config file: {}", path.as_path().display()),
Ok(abs) => abs.to_string_lossy().to_string()
},
2025-03-02 11:47:29 -07:00
file: match fs::metadata(&path) {
Err(_) => panic!("refractr: cannot obtain metadata for config file: {}", path.as_path().display()),
2025-03-02 11:47:29 -07:00
Ok(metadata) => metadata
},
config: verify_config(toml::from_str(&data).unwrap())
};
2025-03-02 14:39:12 -07:00
let mut dup = false;
for i in &config_files {
if i.path == config_file.path {
eprintln!("refractr: warning: skipping config file \"{}\" as it was already read", path.as_path().display());
dup = true;
break;
} else if i.config == config_file.config {
eprintln!("refractr: warning: config files \"{}\" and \"{}\" appear to have the same config", i.path, config_file.path);
}
}
if !dup {
config_files.push(config_file);
}
2025-02-15 22:11:08 -07:00
}
2025-03-02 11:47:29 -07:00
return config_files;
}
fn verify_config(config: Config) -> Config {
2025-03-02 11:47:29 -07:00
if config.schedule.enabled {
assert_ne!(config.schedule.interval, None);
assert!(config.schedule.interval.unwrap() >= 15);
2025-03-02 11:47:29 -07:00
}
2025-03-02 14:39:12 -07:00
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")
}
},
});
2025-02-15 22:11:08 -07:00
return config;
2025-03-02 11:47:29 -07:00
}