#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
#![cfg_attr(coverage_nightly, coverage(off))]
#[cfg(windows)]
use std::env;
#[cfg(windows)]
use std::io::{self, Write};
#[cfg(windows)]
use std::process::{self, ExitCode};
#[cfg(windows)]
use dure::{Cli, Outcome, run};
#[cfg(all(windows, not(miri)))]
#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
#[cfg(not(windows))]
#[cfg_attr(test, mutants::skip)]
fn main() -> std::process::ExitCode {
eprintln!("Error: dure runs only on Windows.");
std::process::ExitCode::FAILURE
}
#[cfg(windows)]
#[cfg_attr(test, mutants::skip)]
fn main() -> ExitCode {
let Some(env_args) = env::args_os()
.map(|arg| arg.into_string().ok())
.collect::<Option<Vec<String>>>()
else {
write_line(
&mut io::stderr(),
"Error: every argument must be valid Unicode.",
);
return ExitCode::FAILURE;
};
let str_args: Vec<&str> = env_args.iter().map(String::as_str).collect();
let program_name = str_args.first().map_or("dure", |name| *name);
let cli = match Cli::from_args(&[program_name], str_args.get(1..).unwrap_or(&[])) {
Ok(cli) => cli,
Err(early_exit) => {
return match early_exit.status {
Ok(()) => {
write_line(&mut io::stdout(), &early_exit.output);
ExitCode::SUCCESS
}
Err(()) => {
write_line(&mut io::stderr(), &early_exit.output);
ExitCode::FAILURE
}
};
}
};
let invocation = match cli.into_invocation() {
Ok(invocation) => invocation,
Err(early_exit) => {
write_line(&mut io::stderr(), &early_exit.output);
return ExitCode::FAILURE;
}
};
match run(&invocation) {
Ok(Outcome::Success) => ExitCode::SUCCESS,
Ok(Outcome::AppExit(status)) => {
if status == 0 {
ExitCode::SUCCESS
} else if let Ok(code) = u8::try_from(status) {
ExitCode::from(code)
} else {
process::exit(status);
}
}
Err(error) => {
write_line(&mut io::stderr(), &format!("Error: {error}"));
ExitCode::FAILURE
}
}
}
#[cfg(windows)]
fn write_line(stream: &mut impl Write, message: &str) {
_ = writeln!(stream, "{message}");
_ = stream.flush();
}