mars/src/server.rs

160 lines
4.3 KiB
Rust

#[macro_use]
extern crate log;
use std::process::exit;
use std::sync::{mpsc, Arc, Mutex};
use std::{env, thread};
use colored::*;
use percent_encoding::percent_decode;
use hyper::rt::Future;
use hyper::service::service_fn_ok;
use hyper::{Body, Response, Server};
use mars::{builder_arguments_from_string, watch, GeneralBuilder};
fn main() {
beautylog::init(log::LevelFilter::Info).ok();
let mut args = env::args()
.skip(1)
.collect::<Vec<_>>()
.into_iter()
.peekable();
let mut watching = None;
let mut command = None;
let mut ignore = vec![];
let exit_code = loop {
let arg = args.next();
let arg = arg.as_deref();
let next = args.peek();
let next = next.as_deref();
let watch_is_some = watching.is_some();
let command_is_some = command.is_some();
match (arg, next, watch_is_some, command_is_some) {
(None, _, _, _) => {
break None;
}
(Some("-w") | Some("--watch"), Some(value), false, _) => {
watching = Some(value.to_string());
}
(Some("-w") | Some("--watch"), Some(_), true, _) => {
error!("argument watch present multiple times");
break Some(1);
}
(Some("-w") | Some("--watch"), None, _, _) => {
error!("argument watch without value");
break Some(1);
}
(Some("-i") | Some("--ignore"), Some(value), _, _) => {
ignore.push(value.to_string());
}
(Some("-i") | Some("--ignore"), None, _, _) => {
error!("argument ignore without value");
break Some(1);
}
(Some("-c") | Some("--command"), Some(value), _, false) => {
command = Some(value.to_string());
}
(Some("-c") | Some("--command"), Some(_), _, true) => {
error!("argument command present multiple times");
break Some(1);
}
(Some("-c") | Some("--command"), None, _, _) => {
error!("argument command without value");
break Some(1);
}
(Some(value), _, _, _) => {
error!("argument \"{}\" unknown", value);
break Some(1);
}
}
args.next();
};
if let Some(exit_code) = exit_code {
exit(exit_code);
}
if let Some(watching) = watching {
if let Err(e) = watch(&watching, ignore, command) {
error!("{}", e);
exit(1);
}
}
let (tx, rx) = mpsc::channel();
let tasks = Arc::new(Mutex::new(vec![]));
let clone = tasks.clone();
thread::spawn(move || {
let addr = ([127, 0, 0, 1], 1500).into();
let server = Server::bind(&addr)
.serve(move || {
let clone = clone.clone();
let tx_clone = tx.clone();
let r = service_fn_ok(move |r| {
clone.lock().unwrap().push(r.uri().clone());
tx_clone.send(()).unwrap();
Response::new(Body::from("Ok"))
});
r
})
.map_err(|e| error!("server error: {}", e));
info!("mars server listening on {}...", addr);
hyper::rt::run(server);
});
let mut builder = GeneralBuilder::new();
for _ in rx {
let uri = {
let mut tasks = tasks.lock().unwrap();
tasks.pop()
};
if let Some(uri) = uri {
let uri = percent_decode(uri.path().as_bytes()).decode_utf8().unwrap();
let (path, args) = builder_arguments_from_string(&*uri);
let path_string = path.to_str().unwrap();
let start_string = format!(
"---- STARTING BUILD ---- from {} {}",
path_string,
args.join(" ")
);
println!("{}", start_string.bold().green());
match builder.build(&path, &args) {
Err(_) => {
println!("{}", "--------- FAIL ---------".bold().red());
}
Ok(_) => {
println!("{}", "----- SUCCESSFUL -----".bold().green());
}
};
println!();
}
}
}