use std::collections::HashMap;
use toml_edit::{self, Document};
use failure::Error;
use errors::*;
const REGISTRIES_ENTRY: &str = "registries";
pub type Registries = HashMap<String, String>;
#[derive(Debug)]
pub struct Config {
data: Document,
}
impl Config {
pub fn new(data: String) -> Result<Config, Error> {
match data.parse() {
Ok(data) => Ok(Config { data }),
Err(_) => Err(RegistryError::BrokenConfig.into())
}
}
pub fn data(&self) -> String {
self.data.to_string()
}
pub fn add(&mut self, name: &str, url: &str) -> Result<(), Error> {
match self.check_table() {
Ok(_) => {
if !self.data[REGISTRIES_ENTRY][name].is_none() {
return Err(RegistryError::AlreadyExist { name: name.into() }.into());
}
},
Err(_) => { self.data[REGISTRIES_ENTRY] = toml_edit::table(); }
}
self.data[REGISTRIES_ENTRY][name] = toml_edit::value(url);
Ok(())
}
pub fn remove(&mut self, name: &str) -> Result<String, Error> {
self.check_table()?;
let registries = &mut self.data[REGISTRIES_ENTRY];
if registries[name].is_none() {
return Err(RegistryError::NoSuchRegistry { name: name.into() }.into());
}
let url = registries[name].as_str().unwrap().to_string();
registries[name] = toml_edit::Item::None;
if registries.as_table_like().unwrap().is_empty() {
*registries = toml_edit::Item::None;
}
Ok(url)
}
pub fn rename(&mut self, old: &str, new: &str) -> Result<(), Error> {
let url = self.get(old)?;
self.add(new, &url)?;
let _ = self.remove(old)?;
Ok(())
}
pub fn get(&self, name: &str) -> Result<String, Error> {
self.check_table()?;
let registry = &self.data[REGISTRIES_ENTRY][name];
if registry.is_none() {
return Err(RegistryError::NoSuchRegistry { name: name.into() }.into());
}
Ok(registry.as_str().unwrap().to_string())
}
pub fn set(&mut self, name: &str, url: &str) -> Result<String, Error> {
self.check_table()?;
let registry = &mut self.data[REGISTRIES_ENTRY][name];
if registry.is_none() {
return Err(RegistryError::NoSuchRegistry { name: name.into() }.into());
}
let old = registry.as_str().unwrap().to_string();
*registry = toml_edit::value(url);
Ok(old)
}
pub fn list(&self) -> Result<Registries, Error> {
let mut result = HashMap::new();
let registries = match &self.data[REGISTRIES_ENTRY].as_table() {
&Some(r) => r,
&None => return Ok(result),
};
for (s, v) in registries.iter() {
if let Some(v) = v.as_str() {
result.insert(s.to_string(), v.to_string());
}
}
Ok(result)
}
fn check_table(&self) -> Result<(), Error> {
let reg = &self.data[REGISTRIES_ENTRY];
if !reg.is_table_like() {
return Err(RegistryError::TableAbsent.into());
}
Ok(())
}
}