extern crate std;
extern crate getopts;
use compiler;
use cmd;
use config;
use fetcher;
const PROLOG: &'static str =
"Usage:
subcomponent fetch [options] [components]
";
pub struct CmdFetch {
dry_run: bool,
force: bool,
components: Vec<String>,
}
impl CmdFetch {
fn fetch_new_component(&self, component: &config::Component) -> Result<(), fetcher::Error> {
info!("Fetching new component {} ...", component.id_get());
for method in component.fetch_methods_get() {
debug!("Trying method `{}`...", method.name_get());
let result = method.fetch_new(component);
if result.is_ok() {
return result;
}
}
Err(fetcher::Error::EverythingFailed)
}
fn get_used_fetch_method(&self, component: &config::Component) -> Option<String> {
for method in component.fetch_methods_get() {
if method.is_fetchable(component) {
return Some(method.name_get().to_string());
}
}
None
}
fn fetch_update_component(&self, component: &config::Component) -> Result<(), fetcher::Error> {
info!("Updating component \"{}\" ...", component.id_get());
if let Some(name) = self.get_used_fetch_method(component) {
let method = component.fetch_method_get(name.as_str());
method.fetch_update(component, self.force)
} else {
Ok(())
}
}
fn fetch_component(&self, component: &config::Component) -> Result<(), fetcher::Error> {
let path = std::path::Path::new(component.path_get());
if path.exists() {
self.fetch_update_component(component)
} else {
self.fetch_new_component(component)
}
}
}
impl cmd::Cmd for CmdFetch {
fn help(&self, opts: &getopts::Options) {
println!("{}", opts.usage(PROLOG));
}
fn getopts_set(&self, opts: &mut getopts::Options) {
opts.optflag("n", "dry-run", "Don't fetch anything");
opts.optflag("f", "force",
"Force updating. This discards potential user changes!");
}
fn getopts_matches_use(&mut self, matches: &getopts::Matches) {
if matches.opt_present("dry-run") {
self.dry_run = true;
}
if matches.opt_present("force") {
self.force = true;
}
for component in &matches.free {
self.components.push(component.clone());
}
}
fn run(&self, parser_arg: &Option<compiler::parser::Parser>) -> Result<(), cmd::Error> {
if let Some(ref parser) = *parser_arg {
if ! self.dry_run {
let components = parser.components_get();
if ! self.components.is_empty() {
for comp_id in &self.components {
let mut comp_found = false;
for component in components.iter() {
let borrowed = component.borrow();
if borrowed.id_get() == comp_id {
comp_found = true;
self.fetch_component(&borrowed)?;
break;
}
}
if ! comp_found {
error!("Failed to find component '{}'", comp_id);
return Err(cmd::Error::InvalidComponentName);
}
}
} else {
for component in components.iter() {
let borrowed = component.borrow();
self.fetch_component(&borrowed)?;
}
}
}
Ok(())
} else {
error!("The 'fetch' command requires a valid subcomponent file");
Err(cmd::Error::NoSubcomponentFile)
}
}
}
pub fn new() -> CmdFetch {
CmdFetch {
dry_run: false,
force: false,
components: Vec::new(),
}
}