147 lines
3.6 KiB
Rust
147 lines
3.6 KiB
Rust
extern crate hyper;
|
|
|
|
use std::io;
|
|
use std::process::{Command, ExitStatus};
|
|
use std::path::PathBuf;
|
|
use std::ffi::OsStr;
|
|
|
|
/// Tests if a file is in a directory.
|
|
pub fn contains_file(path: &str, file: &str) -> bool {
|
|
let mut path = PathBuf::from(path);
|
|
path.push(file);
|
|
path.exists()
|
|
}
|
|
|
|
/// Tries to build a certain directory using the specified builders.
|
|
pub fn run_command(command: &str, path: &str) -> Result<ExitStatus, io::Error> {
|
|
let mut child = match Command::new(command)
|
|
.current_dir(path)
|
|
.spawn() {
|
|
Err(x) => return Err(x),
|
|
Ok(child) => child,
|
|
};
|
|
|
|
child.wait()
|
|
}
|
|
|
|
/// Run a build commands, and wait untils its finished, returning its result.
|
|
pub fn run_command_with_args<I, S>(command: &str, path: &str, args: I) -> Result<ExitStatus, io::Error> where
|
|
I: IntoIterator<Item=S>,
|
|
S: AsRef<OsStr> {
|
|
let mut child = match Command::new(command)
|
|
.current_dir(path)
|
|
.args(args)
|
|
.spawn() {
|
|
Err(x) => return Err(x),
|
|
Ok(child) => child,
|
|
};
|
|
|
|
child.wait()
|
|
}
|
|
|
|
/// Tries to build a certain directory using the specified builders.
|
|
pub fn build(path: &PathBuf, builders: &Vec<Builder>) -> Result<(), ()> {
|
|
|
|
let mut path = path.clone();
|
|
|
|
loop {
|
|
|
|
if path.to_str().unwrap() == "/" {
|
|
// Couldn't find a buildable directory
|
|
return Err(());
|
|
}
|
|
|
|
for builder in builders {
|
|
|
|
if builder.is_buildable(path.to_str().unwrap()) {
|
|
builder.build(path.to_str().unwrap())?;
|
|
return Ok(());
|
|
}
|
|
|
|
}
|
|
|
|
path.pop();
|
|
};
|
|
|
|
}
|
|
|
|
/// Destucture a Result to return a Result<(), ()>
|
|
pub fn destroy<T, E>(result: Result<T, E>) -> Result<(), ()> {
|
|
match result {
|
|
Err(_) => Err(()),
|
|
Ok(_) => Ok(()),
|
|
}
|
|
}
|
|
|
|
/// A general builders that contains many builders and can build any type of code.
|
|
#[derive(Clone)]
|
|
pub struct GeneralBuilder {
|
|
/// The builders contained.
|
|
builders: Vec<Builder>,
|
|
}
|
|
|
|
impl GeneralBuilder {
|
|
/// Creates a new general builder with the defaults builders.
|
|
pub fn new() -> GeneralBuilder {
|
|
GeneralBuilder {
|
|
builders: vec![
|
|
Builder::make(),
|
|
Builder::cargo(),
|
|
],
|
|
}
|
|
}
|
|
|
|
/// Triggers a build.
|
|
pub fn build(&self, path: &str) -> Result<(), ()> {
|
|
build(&PathBuf::from(path), &self.builders)
|
|
}
|
|
}
|
|
|
|
/// The builder that looks for makefiles.
|
|
#[derive(Clone)]
|
|
pub struct Builder {
|
|
/// The file to lookup to check build.
|
|
file: String,
|
|
|
|
/// The command to launch to build.
|
|
command: String,
|
|
|
|
/// The arguments to the command.
|
|
args: Vec<String>,
|
|
}
|
|
|
|
impl Builder {
|
|
/// Creates a new make builder.
|
|
pub fn make() -> Builder {
|
|
Builder {
|
|
file: "Makefile".to_string(),
|
|
command: "make".to_string(),
|
|
args: vec![],
|
|
}
|
|
}
|
|
|
|
/// Creates a new cargo builder.
|
|
pub fn cargo() -> Builder {
|
|
Builder {
|
|
file: "Cargo.toml".to_string(),
|
|
command: "cargo".to_string(),
|
|
args: vec!["build".to_string()],
|
|
}
|
|
}
|
|
|
|
/// Checks if a directory has corresponding files so it can build it.
|
|
/// e.g.: if there is a Makefile
|
|
fn is_buildable(&self, path: &str) -> bool {
|
|
contains_file(path, &self.file)
|
|
}
|
|
|
|
/// Trigger all the commands to build the project.
|
|
fn build(&self, path: &str) -> Result<(), ()> {
|
|
match run_command_with_args(&self.command, path, &self.args) {
|
|
Ok(_) => Ok(()),
|
|
Err(_) => Err(()),
|
|
}
|
|
}
|
|
}
|
|
|