refractr/src/config.rs

170 lines
4.8 KiB
Rust

use crate::common;
use crate::refractr::Refractr;
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 mut branches_list = String::from("[");
for i in 0..self.config.branches.len() {
branches_list = format!("{}{}", branches_list, &self.config.branches[i]);
if i < self.config.branches.len() - 1 {
branches_list.push_str(", ");
}
}
branches_list.push(']');
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(PartialEq)]
#[derive(Deserialize)]
pub struct Config {
pub from: String,
pub to: Vec<String>,
pub branches: Vec<String>,
pub work_dir: Option<String>,
pub git: Git,
pub schedule: Schedule
}
#[derive(PartialEq)]
#[derive(Deserialize)]
pub struct Git {
pub ssh_identity_file: String,
}
#[derive(PartialEq)]
#[derive(Deserialize)]
pub struct Schedule {
pub enabled: bool,
pub interval: Option<i32>,
}
pub fn read_config(paths: Vec<PathBuf>, refractr: &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: 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()
},
file: match fs::metadata(&path) {
Err(_) => panic!("refractr: cannot obtain metadata for config file: {}", path.as_path().display()),
Ok(metadata) => metadata
},
config: verify_config(toml::from_str(&data).unwrap())
};
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);
}
}
return config_files;
}
fn verify_config(config: Config) -> Config {
if config.schedule.enabled {
assert_ne!(config.schedule.interval, None);
assert!(config.schedule.interval.unwrap() >= 15);
}
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;
}