Honor the exit code from the child in the parent
This commit is contained in:
parent
07e29916be
commit
32fa7cbda8
@ -2,6 +2,7 @@ use std::env;
|
|||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
#[cfg(target_family = "windows")]
|
#[cfg(target_family = "windows")]
|
||||||
const PATH_SEPARATOR: char = ';';
|
const PATH_SEPARATOR: char = ';';
|
||||||
@ -9,23 +10,31 @@ const PATH_SEPARATOR: char = ';';
|
|||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
const PATH_SEPARATOR: char = ':';
|
const PATH_SEPARATOR: char = ':';
|
||||||
|
|
||||||
pub fn execute(path: &Path, prog: &str) {
|
pub fn execute(target: &Path) -> io::Result<i32> {
|
||||||
let path_str = path.as_os_str().to_os_string().into_string().unwrap();
|
let target_dir = target.parent()
|
||||||
let path_env = match env::var("PATH") {
|
.and_then(|dir| dir.to_str())
|
||||||
Ok(p) => format!("{}{}{}", &path_str, PATH_SEPARATOR, &p),
|
.expect("Unable to construct target directory");
|
||||||
_ => path_str
|
let target_file_name = target.file_name()
|
||||||
};
|
.and_then(|file_name| file_name.to_str())
|
||||||
|
.expect("Unable to identify target file name");
|
||||||
|
trace!("target={:?}", target);
|
||||||
|
trace!("target_dir={:?}", target_dir);
|
||||||
|
trace!("target_file_name={:?}", target_file_name);
|
||||||
|
|
||||||
|
let current_path_env = env::var("PATH").unwrap_or(String::new());
|
||||||
|
let path_env = format!("{}{}{}", target_dir, PATH_SEPARATOR, current_path_env);
|
||||||
|
trace!("path_env={:?}", path_env);
|
||||||
|
|
||||||
let args: Vec<String> = env::args().skip(1).collect();
|
let args: Vec<String> = env::args().skip(1).collect();
|
||||||
trace!("PATH={:?} prog={:?} args={:?}", path_env, prog, args);
|
trace!("args={:?}", args);
|
||||||
Command::new(prog)
|
|
||||||
|
Ok(Command::new(target_file_name)
|
||||||
.env("PATH", path_env)
|
.env("PATH", path_env)
|
||||||
.args(args)
|
.args(args)
|
||||||
.stdin(Stdio::inherit())
|
.stdin(Stdio::inherit())
|
||||||
.stdout(Stdio::inherit())
|
.stdout(Stdio::inherit())
|
||||||
.stderr(Stdio::inherit())
|
.stderr(Stdio::inherit())
|
||||||
.spawn()
|
.spawn()?
|
||||||
.unwrap_or_else(|_| panic!("{} failed to start", prog))
|
.wait()?
|
||||||
.wait()
|
.code().unwrap_or(1))
|
||||||
.unwrap_or_else(|_| panic!("{} failed to wait", prog));
|
|
||||||
}
|
}
|
||||||
|
@ -1,40 +1,40 @@
|
|||||||
extern crate dirs;
|
extern crate dirs;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate simple_logger;
|
extern crate simple_logger;
|
||||||
|
|
||||||
|
use log::Level;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::ffi::*;
|
use std::ffi::*;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::*;
|
use std::path::*;
|
||||||
use log::Level;
|
use std::process;
|
||||||
|
|
||||||
mod extractor;
|
mod extractor;
|
||||||
mod executor;
|
mod executor;
|
||||||
|
|
||||||
static PROG_BUF: &'static [u8] = b"tVQhhsFFlGGD3oWV4lEPST8I8FEPP54IM0q7daes4E1y3p2U2wlJRYmWmjPYfkhZ0PlT14Ls0j8fdDkoj33f2BlRJavLj3mWGibJsGt5uLAtrCDtvxikZ8UX2mQDCrgE\0";
|
static TARGET_FILE_NAME_BUF: &'static [u8] = b"tVQhhsFFlGGD3oWV4lEPST8I8FEPP54IM0q7daes4E1y3p2U2wlJRYmWmjPYfkhZ0PlT14Ls0j8fdDkoj33f2BlRJavLj3mWGibJsGt5uLAtrCDtvxikZ8UX2mQDCrgE\0";
|
||||||
|
|
||||||
fn prog() -> &'static str {
|
fn target_file_name() -> &'static str {
|
||||||
let nul_pos = PROG_BUF.iter()
|
let nul_pos = TARGET_FILE_NAME_BUF.iter()
|
||||||
.position(|elem| *elem == b'\0')
|
.position(|elem| *elem == b'\0')
|
||||||
.expect("PROG_BUF has no NUL terminator");
|
.expect("TARGET_FILE_NAME_BUF has no NUL terminator");
|
||||||
|
|
||||||
let slice = &PROG_BUF[..(nul_pos + 1)];
|
let slice = &TARGET_FILE_NAME_BUF[..(nul_pos + 1)];
|
||||||
CStr::from_bytes_with_nul(slice)
|
CStr::from_bytes_with_nul(slice)
|
||||||
.expect("Can't convert PROG_BUF slice to CStr")
|
.expect("Can't convert TARGET_FILE_NAME_BUF slice to CStr")
|
||||||
.to_str()
|
.to_str()
|
||||||
.expect("Can't convert PROG_BUF CStr to str")
|
.expect("Can't convert TARGET_FILE_NAME_BUF CStr to str")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cache_path(prog: &str) -> PathBuf {
|
fn cache_path(target: &str) -> PathBuf {
|
||||||
dirs::data_local_dir()
|
dirs::data_local_dir()
|
||||||
.expect("No data local dir found")
|
.expect("No data local dir found")
|
||||||
.join("warp")
|
.join("warp")
|
||||||
.join("packages")
|
.join("packages")
|
||||||
.join(prog)
|
.join(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract(exe_path: &Path, cache_path: &Path) -> io::Result<()> {
|
fn extract(exe_path: &Path, cache_path: &Path) -> io::Result<()> {
|
||||||
@ -48,26 +48,35 @@ fn main() -> Result<(), Box<Error>> {
|
|||||||
simple_logger::init_with_level(Level::Trace)?;
|
simple_logger::init_with_level(Level::Trace)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let prog = prog();
|
let self_path = env::current_exe()?;
|
||||||
let cache_path = cache_path(prog);
|
let self_file_name = self_path.file_name().unwrap();
|
||||||
let exe_path = env::current_exe()?;
|
let cache_path = cache_path(&self_file_name.to_string_lossy());
|
||||||
trace!("prog={:?}, cache_path={:?}, exe_path={:?}", prog, cache_path, exe_path);
|
|
||||||
|
trace!("self_path={:?}", self_path);
|
||||||
|
trace!("self_file_name={:?}", self_file_name);
|
||||||
|
trace!("cache_path={:?}", cache_path);
|
||||||
|
|
||||||
|
let target_file_name = target_file_name();
|
||||||
|
let target_path = cache_path.join(target_file_name);
|
||||||
|
|
||||||
|
trace!("target_exec={:?}", target_file_name);
|
||||||
|
trace!("target_path={:?}", target_path);
|
||||||
|
|
||||||
match fs::metadata(&cache_path) {
|
match fs::metadata(&cache_path) {
|
||||||
Ok(cache) => {
|
Ok(cache) => {
|
||||||
if cache.modified()? >= fs::metadata(&exe_path)?.modified()? {
|
if cache.modified()? >= fs::metadata(&self_path)?.modified()? {
|
||||||
trace!("cache is up-to-date");
|
trace!("cache is up-to-date");
|
||||||
} else {
|
} else {
|
||||||
trace!("cache is outdated");
|
trace!("cache is outdated");
|
||||||
extract(&exe_path, &cache_path)?;
|
extract(&self_path, &cache_path)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
trace!("cache not found");
|
trace!("cache not found");
|
||||||
extract(&exe_path, &cache_path)?;
|
extract(&self_path, &cache_path)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
executor::execute(&cache_path, &prog);
|
let exit_code = executor::execute(&target_path)?;
|
||||||
Ok(())
|
process::exit(exit_code);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user