181 lines
5.5 KiB
Rust
181 lines
5.5 KiB
Rust
//! Handle config
|
|
|
|
pub use ini::Ini;
|
|
use std::collections::HashMap;
|
|
use std::path::PathBuf;
|
|
|
|
use crate::error::{Config as ConfigError, ConfigFormat as ConfigFormatError};
|
|
|
|
pub static RELATIVE_CONFIG_FILE: &str = "mia.ini";
|
|
|
|
/// List all sections of the config
|
|
pub struct Config {
|
|
pub general: General,
|
|
pub schema: Schema,
|
|
}
|
|
|
|
/// List all options of the 'General' section
|
|
pub struct General {
|
|
pub import_branch_prefix: String,
|
|
pub import_branch_schema: String,
|
|
pub main_branch: String,
|
|
}
|
|
|
|
/// List all options of the 'Schema' section
|
|
pub struct Schema {
|
|
pub default: String,
|
|
pub custom: HashMap<String, String>,
|
|
}
|
|
|
|
impl Config {
|
|
/// Initialize `Config` by reading it from a valid Ini config file at `config_path`.
|
|
pub fn from_file(config_path: &PathBuf) -> Result<Self, ConfigError> {
|
|
let ini_conf = Ini::load_from_file(&config_path).map_err(|source| match source {
|
|
ini::Error::Io(e) => ConfigError::ReadFile { source: e },
|
|
ini::Error::Parse(e) => ConfigError::from(e),
|
|
})?;
|
|
Config::from_ini(ini_conf)
|
|
}
|
|
|
|
/// Initialize `Config` from valid ini string `dump`.
|
|
pub fn from_string(dump: &str) -> Result<Self, ConfigError> {
|
|
let ini_conf = Ini::load_from_str(dump)?;
|
|
Config::from_ini(ini_conf)
|
|
}
|
|
|
|
/// Initialize `Config` from a `Ini` config.
|
|
fn from_ini(ini_conf: Ini) -> Result<Self, ConfigError> {
|
|
let mut schemas = HashMap::from_iter(Self::read_section(&ini_conf, "Schema")?);
|
|
let schema_default = schemas.remove("Default").ok_or(ConfigError::InvalidFormat(
|
|
ConfigFormatError::Custom {
|
|
message: format!("Field 'Default' is missing in section 'Schema'"),
|
|
},
|
|
))?;
|
|
|
|
Ok(Self {
|
|
general: General {
|
|
import_branch_prefix: Self::read_property(
|
|
&ini_conf,
|
|
"General",
|
|
"ImportBranchPrefix",
|
|
)?,
|
|
import_branch_schema: Self::read_property(
|
|
&ini_conf,
|
|
"General",
|
|
"ImportBranchSchema",
|
|
)?,
|
|
main_branch: Self::read_property(&ini_conf, "General", "MainBranch")?,
|
|
},
|
|
schema: Schema {
|
|
default: schema_default,
|
|
custom: schemas,
|
|
},
|
|
})
|
|
}
|
|
|
|
/// Dumps the default config to `file`.
|
|
/// `file` must not exists.
|
|
pub fn dump_default(file: &PathBuf) -> Result<(), ConfigError> {
|
|
assert!(file.is_absolute());
|
|
|
|
// TODO: Add flag to overwrite config in case it exists
|
|
if file.exists() {
|
|
return Err(ConfigError::WriteFile {
|
|
source: std::io::Error::new(
|
|
std::io::ErrorKind::Other,
|
|
format!(": File {} already exists", file.display()),
|
|
),
|
|
});
|
|
}
|
|
|
|
let def_config = Config::default();
|
|
|
|
let mut conf = Ini::new();
|
|
conf.with_section(Some("General"))
|
|
.set(
|
|
"ImportBranchPrefix",
|
|
def_config.general.import_branch_prefix,
|
|
)
|
|
.set(
|
|
"ImportBranchSchema",
|
|
def_config.general.import_branch_schema,
|
|
)
|
|
.set("MainBranch", def_config.general.main_branch);
|
|
|
|
conf.with_section(Some("Schema"))
|
|
.set("Default", def_config.schema.default)
|
|
.set(
|
|
"Event",
|
|
def_config
|
|
.schema
|
|
.custom
|
|
.get("Event")
|
|
.expect("Default trait is supposed to add an 'Event' schema"),
|
|
);
|
|
|
|
conf.write_to_file(file)
|
|
.map_err(|source| ConfigError::WriteFile { source })?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Return value of key within section
|
|
fn read_property(file: &Ini, section: &str, key: &str) -> Result<String, ConfigFormatError> {
|
|
Ok(file
|
|
.section(Some(section))
|
|
.ok_or(ConfigFormatError::Custom {
|
|
message: format!("Section '{}' is missing", section),
|
|
})?
|
|
.get(key)
|
|
.ok_or(ConfigFormatError::Custom {
|
|
message: format!("Field '{}' is missing in section '{}'", key, section),
|
|
})?
|
|
.to_string())
|
|
}
|
|
|
|
/// Return (key, value) pair for given section
|
|
fn read_section(file: &Ini, section: &str) -> Result<Vec<(String, String)>, ConfigFormatError> {
|
|
Ok(file
|
|
.section(Some(section))
|
|
.ok_or(ConfigFormatError::Custom {
|
|
message: format!("Section '{}' is missing", section),
|
|
})?
|
|
.iter()
|
|
.map(|(s, k)| (s.to_string(), k.to_string()))
|
|
.collect())
|
|
}
|
|
}
|
|
|
|
impl Default for Config {
|
|
fn default() -> Self {
|
|
Self {
|
|
general: General::default(),
|
|
schema: Schema::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for General {
|
|
fn default() -> Self {
|
|
Self {
|
|
import_branch_prefix: String::from("import/"),
|
|
import_branch_schema: String::from("*Sy*Sm*i*c"),
|
|
main_branch: String::from("main"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for Schema {
|
|
fn default() -> Self {
|
|
let mut schema = HashMap::new();
|
|
schema.insert(
|
|
String::from("Event"),
|
|
String::from("%Y/*Sy*Sm*Sd-*Ey*Em*Ed*i/%y%m%d/%y%m%d_%H%M%S*c.*x"),
|
|
);
|
|
Self {
|
|
default: String::from("%Y/%y%m%d*i/%y%m%d_%H%M%S*c.*x"),
|
|
custom: schema,
|
|
}
|
|
}
|
|
}
|