use std::fs;
use std::path;
use serde_json;
use errors::*;
use paths;
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct Config {
pub destinations: Vec<Destination>,
#[serde(default)]
pub exclude: Vec<String>,
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Destination {
pub repo: String,
#[serde(default)]
pub after_backup: Vec<String>,
#[serde(default)]
pub before_backup: Vec<String>,
}
impl Config {
pub fn load_user() -> Result<Self> {
Self::load(&paths::config_file()?)
}
pub fn load(p: &path::Path) -> Result<Self> {
serde_json::from_reader(fs::File::open(&p)?).chain_err(|| "cannot load configuration file")
}
}
#[cfg(test)]
mod tests {
use std::fs;
use std::io::Write;
use std::path;
use tempdir;
use super::*;
#[test]
fn test_missing_config() {
with_config(|config_path| {
assert!(Config::load(&config_path).is_err());
});
}
#[test]
fn test_invalid_config() {
with_config(|config_path| {
fs::File::create(&config_path)
.unwrap()
.write_all(
br#"{ "destinations": [ { "url": "file:///", "beforeBackup": "test" } ] }"#
)
.unwrap();
assert!(Config::load(&config_path).is_err());
});
}
#[test]
fn test_load_config() {
with_config(|config_path| {
fs::File::create(&config_path)
.unwrap()
.write_all(br#"{"destinations": []}"#)
.unwrap();
let expected = Config {
destinations: vec![],
exclude: vec![],
};
let obtained = Config::load(&config_path).unwrap();
assert_eq!(obtained, expected);
});
}
#[test]
fn test_load_config_destinations() {
macro_rules! vec_s {
($($x:expr), *) => (vec![$($x.to_string()), *]);
}
with_config(|config_path| {
fs::File::create(&config_path)
.unwrap()
.write_all(
br#"{
"destinations": [
{
"repo": "/"
},
{
"beforeBackup": ["test", "command"],
"repo": "/"
}
]
}"#,
)
.unwrap();
let expected = Config {
destinations: vec![
Destination {
after_backup: vec![],
before_backup: vec![],
repo: "/".to_string(),
},
Destination {
after_backup: vec![],
before_backup: vec_s!["test", "command"],
repo: "/".to_string(),
},
],
exclude: vec![],
};
let obtained = Config::load(&config_path).unwrap();
assert_eq!(obtained, expected);
});
}
fn with_config<F: FnOnce(&path::Path) -> ()>(block: F) {
let tmpdir = tempdir::TempDir::new("borg-hive").unwrap();
let tmpdir_path = tmpdir.path();
let test_config = tmpdir_path.join("borg-hive.json");
block(&test_config);
}
}