#[macro_use] extern crate log;
extern crate getopts;
extern crate crypto;
mod logger;
mod utils;
mod common;
mod config;
mod cmd;
mod hook;
#[macro_use] mod compiler;
mod fetcher;
mod unpacker;
mod subprocess;
use cmd::Errno;
const PROLOG: &'static str = "Usage:
subcomponent [options]
subcomponent <command> [options]
Commands:
fetch Fetch locally the requested components
status Tell the status of the components
template Create a subcomponent template
";
fn usage(opts: &getopts::Options, exit: i32) -> ! {
println!("{}", opts.usage(PROLOG));
std::process::exit(exit);
}
fn main() {
let args: Vec<String> = std::env::args().collect();
let mut opts = getopts::Options::new();
let mut loglevel = log::LogLevelFilter::Info;
opts.parsing_style(getopts::ParsingStyle::StopAtFirstFree);
opts.optflag("h", "help", "Display this message");
opts.optflag("", "debug", "Increase log verbosity for debug");
opts.optopt("C", "", "Execute subcomponent at path PATH", "PATH");
opts.optopt("f", "file", "Use FILE instead of the default one", "FILE");
let matches = match opts.parse(&args[1..]) {
Ok(m) => { m },
Err(err) => {
logger::init(log::LogLevelFilter::Error);
error!("Options parsing failed: {}", err);
usage(&opts, 1);
}
};
if matches.opt_present("debug") {
loglevel = log::LogLevelFilter::Trace;
}
logger::init(loglevel);
if matches.opt_present("help") {
usage(&opts, 0);
}
if matches.free.is_empty() {
error!("A command name is required");
std::process::exit(1);
}
if let Some(path_opt) = matches.opt_str("C") {
let path = std::path::Path::new(&path_opt);
if let Err(err) = std::env::set_current_dir(&path) {
error!("Failed to change directory to \"{}\". {}",
path.display(), err);
let errcode = match err.raw_os_error() {
Some(code) => code,
None => 127
};
std::process::exit(errcode);
} else {
debug!("Working directory is now {:?}", path);
}
}
let mut entry = std::path::PathBuf::new();
match matches.opt_str("f") {
None => {
entry.push(common::sub_dir_get());
entry.push(common::sub_file_get());
},
Some(file_opt) => {
entry.push(file_opt);
}
}
let parser_opt = if entry.exists() {
match compiler::compile(&entry) {
Ok(parser) => Some(parser),
Err(err) => {
error!("Compilation of {} failed: {}", entry.display(), err);
std::process::exit(127);
}
}
} else {
None
};
let cmds_opt = match cmd::getopts(&matches.free, &parser_opt) {
Ok(c) => c,
Err(err) => {
error!("Command failed: {}", err);
std::process::exit(127);
}
};
let mut return_code = -1;
if let Some(cmds) = cmds_opt {
for cmd in cmds {
if let Err(ret) = cmd.run(&parser_opt) {
error!("Command failed: {}", ret);
if let Some(os_err) = ret.errno() {
return_code = os_err;
}
std::process::exit(return_code);
}
}
}
std::process::exit(0);
}