use anyhow::Context;
use std::{fs::File, io::Read, path::Path};
use crate::{
atry,
errors::{Error, Result},
};
mod syntax {
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SerializedConfiguration {
pub repo: RepoConfiguration,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct RepoConfiguration {
pub upstream_urls: Vec<String>,
pub rc_name: Option<String>,
pub release_name: Option<String>,
pub release_tag_name_format: Option<String>,
}
}
pub use syntax::RepoConfiguration;
#[derive(Clone, Debug)]
pub struct ConfigurationFile {
pub repo: RepoConfiguration,
}
impl Default for ConfigurationFile {
fn default() -> Self {
let repo = RepoConfiguration::default();
ConfigurationFile { repo }
}
}
impl ConfigurationFile {
pub fn get<P: AsRef<Path>>(path: P) -> Result<Self> {
let mut f = match File::open(&path) {
Ok(f) => f,
Err(e) => {
return if e.kind() == std::io::ErrorKind::NotFound {
Ok(Self::default())
} else {
Err(Error::new(e).context(format!(
"failed to open config file `{}`",
path.as_ref().display()
)))
}
}
};
let mut text = String::new();
f.read_to_string(&mut text)
.with_context(|| format!("failed to read config file `{}`", path.as_ref().display()))?;
let sercfg: syntax::SerializedConfiguration = toml::from_str(&text).with_context(|| {
format!(
"could not parse config file `{}` as TOML",
path.as_ref().display()
)
})?;
Ok(ConfigurationFile { repo: sercfg.repo })
}
pub fn into_toml(self) -> Result<String> {
let syn_cfg = syntax::SerializedConfiguration { repo: self.repo };
Ok(atry!(
toml::to_string_pretty(&syn_cfg);
["could not serialize configuration into TOML format"]
))
}
}