2016-09-27 22:49:17 -07:00
|
|
|
#[macro_use]
|
|
|
|
extern crate brev;
|
2016-06-16 17:13:43 -07:00
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
#[derive(PartialEq, Clone, Copy)]
|
|
|
|
enum Make {
|
|
|
|
GNU, // GNU Make installed as `gmake`
|
|
|
|
GNUStealthy, // GNU Make installed as `make`
|
|
|
|
Other, // Another make installed as `make`
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
impl Make {
|
|
|
|
fn command(self) -> &'static str {
|
|
|
|
if self == Make::GNU {
|
|
|
|
"gmake"
|
|
|
|
} else {
|
|
|
|
"make"
|
|
|
|
}
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
fn gnu(self) -> bool {
|
|
|
|
self != Make::Other
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
fn status(command: &mut std::process::Command) -> std::io::Result<std::process::ExitStatus> {
|
|
|
|
command
|
|
|
|
.stdin(std::process::Stdio::null())
|
|
|
|
.stdout(std::process::Stdio::null())
|
|
|
|
.stderr(std::process::Stdio::null())
|
|
|
|
.status()
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
fn which_make() -> Option<Make> {
|
|
|
|
// check `gmake`
|
|
|
|
let result = status(std::process::Command::new("gmake").arg("-v"));
|
|
|
|
|
|
|
|
if let Ok(exit_status) = result {
|
|
|
|
if exit_status.success() {
|
|
|
|
return Some(Make::GNU);
|
|
|
|
}
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
2016-09-27 22:49:17 -07:00
|
|
|
|
|
|
|
// check `make`. pass gmake specific flags to see if it's actually gmake
|
|
|
|
let result = status(std::process::Command::new("make").arg("-v").arg("--always-make"));
|
|
|
|
|
|
|
|
if let Ok(exit_status) = result {
|
|
|
|
return if exit_status.success() {
|
|
|
|
Some(Make::GNUStealthy)
|
|
|
|
} else {
|
|
|
|
Some(Make::Other)
|
|
|
|
};
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
return None;
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
2016-09-27 22:49:17 -07:00
|
|
|
let make = match which_make() {
|
|
|
|
None => die!("Could not execute `make` or `gmake`."),
|
|
|
|
Some(make) => make,
|
|
|
|
};
|
2016-06-16 17:13:43 -07:00
|
|
|
|
|
|
|
loop {
|
2016-09-27 22:49:17 -07:00
|
|
|
match std::fs::metadata("justfile") {
|
|
|
|
Ok(metadata) => if metadata.is_file() { break; },
|
|
|
|
Err(error) => die!("Error fetching justfile metadata: {}", error),
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
2016-09-27 22:49:17 -07:00
|
|
|
|
|
|
|
match std::env::current_dir() {
|
|
|
|
Ok(pathbuf) => if pathbuf.as_os_str() == "/" { die!("No justfile found"); },
|
|
|
|
Err(error) => die!("Error getting current dir: {}", error),
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
if let Err(error) = std::env::set_current_dir("..") {
|
|
|
|
die!("Error changing directory: {}", error);
|
|
|
|
}
|
|
|
|
}
|
2016-06-16 17:13:43 -07:00
|
|
|
|
|
|
|
let recipes: Vec<String> = std::env::args().skip(1).take_while(|arg| arg != "--").collect();
|
|
|
|
let arguments: Vec<String> = std::env::args().skip(1 + recipes.len() + 1).collect();
|
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
for (i, argument) in arguments.into_iter().enumerate() {
|
|
|
|
std::env::set_var(format!("ARG{}", i), argument);
|
|
|
|
}
|
2016-06-16 17:13:43 -07:00
|
|
|
|
2016-09-27 22:49:17 -07:00
|
|
|
let mut command = std::process::Command::new(make.command());
|
|
|
|
|
|
|
|
command.arg("MAKEFLAGS=");
|
|
|
|
|
|
|
|
if make.gnu() {
|
|
|
|
command.arg("--always-make").arg("--no-print-directory");
|
|
|
|
}
|
|
|
|
|
|
|
|
command.arg("-f").arg("justfile");
|
|
|
|
|
|
|
|
for recipe in recipes {
|
|
|
|
command.arg(recipe);
|
|
|
|
}
|
|
|
|
|
|
|
|
match command.status() {
|
|
|
|
Err(error) => die!("Failed to execute `{:?}`: {}", command, error),
|
|
|
|
Ok(exit_status) => match exit_status.code() {
|
|
|
|
Some(code) => std::process::exit(code),
|
|
|
|
None => std::process::exit(-1),
|
|
|
|
}
|
|
|
|
}
|
2016-06-16 17:13:43 -07:00
|
|
|
}
|