extern crate std;
use std::error::Error as FmtError;
use config;
use compiler::parser;
use std::ops::Deref;
use subprocess;
use unpacker;
use self::Error::*;
macro_rules! foreach_fetch {
($mac:ident) => {
$mac!(git);
$mac!(artifact);
}
}
macro_rules! declare_mod {
($name:ident) => { pub mod $name; }
}
foreach_fetch!(declare_mod);
#[derive(Debug)]
pub enum Error {
ProcessError(subprocess::Error),
EverythingFailed,
InvalidReference,
Dirty,
UnpackError(unpacker::Error),
ComponentPathNotCreated,
}
impl std::error::Error for Error {
fn description(&self) -> &str {
match *self {
ProcessError(ref err) => err.description(),
EverythingFailed => "All fetchers failed",
InvalidReference => "Reference could not be resolved",
Dirty => "Component is dirty",
UnpackError(ref err) => err.description(),
ComponentPathNotCreated => "The component path has not been created",
}
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.description())
}
}
impl From<subprocess::Error> for Error {
fn from(error: subprocess::Error) -> Self {
ProcessError(error)
}
}
impl From<unpacker::Error> for Error {
fn from(error: unpacker::Error) -> Self {
UnpackError(error)
}
}
impl From<std::io::Error> for Error {
fn from(error: std::io::Error) -> Self {
let err = subprocess::Error::IOError(error);
ProcessError(err)
}
}
pub trait Method {
fn fetch_new(&self, component: &config::Component) -> Result<(), Error>;
fn fetch_update(&self, component: &config::Component, force: bool) -> Result<(), Error>;
fn is_fetchable(&self, component: &config::Component) -> bool;
fn name_get(&self) -> &str;
}
pub fn parse_url(component: &str, method: &str, cfg: &config::Config) -> Result<Vec<String>, parser::Error> {
let key = format!("/subcomponents/{}/fetch/{}/url", component, method);
if let Some(prop) = cfg.get(&key) {
match prop.deref().value_get() {
parser::PropertyValue::StringValue(val) => {
return Ok(vec![val.clone()]);
},
parser::PropertyValue::StringListValue(val) => {
return Ok(val.clone());
},
_ => {
return Err(parser::Error::InvalidPropertyType);
}
}
}
Err(parser::Error::MissingRequiredProperty)
}
pub fn parse(parser: &mut parser::Parser) -> Result<(), parser::Error> { let cfg = parser.config_get();
let components = parser.components_get();
for component in components.iter() {
let mut methods_count = 0;
let id = {
let borrowed = component.borrow();
borrowed.id_get().clone()
};
macro_rules! verify_method {
($name:ident) => {
let key = format!("/subcomponents/{}/fetch/{}/",
id, stringify!($name));
if cfg.get(&key).is_some() {
let method = try!($name::parse(&id, cfg));
methods_count += 1;
let mut mut_component = component.borrow_mut();
mut_component.fetch_method_add(method);
}
}
}
foreach_fetch!(verify_method);
if methods_count <= 0 {
return Err(parser::Error::NoFetchMethod)
}
}
Ok(())
}