diff --git a/Cargo.toml b/Cargo.toml index e8d1c92..d8ce9de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rust_util" -version = "0.6.35" +version = "0.6.36" authors = ["Hatter Jiang "] edition = "2018" description = "Hatter's Rust Util" diff --git a/src/lib.rs b/src/lib.rs index 9fdd27b..b31296e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ pub mod util_git; #[cfg(feature = "use_clap")] pub mod util_clap; pub mod util_tlv; +pub mod util_runtime; /// iff!(condition, result_when_true, result_when_false) #[macro_export] macro_rules! iff { @@ -47,6 +48,7 @@ pub mod util_tlv; #[macro_export] macro_rules! failure_and_exit { ($($arg:tt)+) => ( { rust_util::util_msg::print_error(&format!($($arg)+)); + rsut_util::util_runtime::register_callback(); std::process::exit(-1); } ) } diff --git a/src/util_clap.rs b/src/util_clap.rs index 4674135..6f1ca37 100644 --- a/src/util_clap.rs +++ b/src/util_clap.rs @@ -16,6 +16,7 @@ pub trait DefaultCommand { } pub struct DefaultCommandImpl; + impl DefaultCommand for DefaultCommandImpl { fn process_command<'a>(&self, app: App<'a, 'a>) -> App<'a, 'a> { app.arg(Arg::with_name("verbose").long("verbose").short("v").multiple(true).help("Show verbose info")) @@ -40,7 +41,7 @@ impl CommandExecutor { } pub fn new(default_cmd: Option>) -> Self { - CommandExecutor{ + CommandExecutor { default_cmd, commands: Vec::new(), } @@ -60,8 +61,8 @@ impl CommandExecutor { pub fn run(&self) -> XResult<()> { let app = App::new(env!("CARGO_PKG_NAME")) - .version(env!("CARGO_PKG_VERSION")) - .about(env!("CARGO_PKG_DESCRIPTION")); + .version(env!("CARGO_PKG_VERSION")) + .about(env!("CARGO_PKG_DESCRIPTION")); self.run_with(app) } @@ -77,18 +78,25 @@ impl CommandExecutor { if let Some(sub_cmd_matches) = matches.subcommand_matches(command.name()) { match command.run(&matches, sub_cmd_matches)? { None => return Ok(()), - Some(code) => process::exit(code), + Some(code) => { + crate::util_runtime::invoke_callbacks(); + process::exit(code); + } } } } match &self.default_cmd { None => { util_msg::print_error("No default command, please try help (--help)"); + crate::util_runtime::invoke_callbacks(); process::exit(1); - }, + } Some(default_cmd) => match default_cmd.run(&matches)? { None => return Ok(()), - Some(code) => process::exit(code), + Some(code) => { + crate::util_runtime::invoke_callbacks(); + process::exit(code); + } }, } } diff --git a/src/util_cmd.rs b/src/util_cmd.rs index 289b771..0424fe2 100644 --- a/src/util_cmd.rs +++ b/src/util_cmd.rs @@ -1,6 +1,6 @@ use std::io::{self, Error, ErrorKind}; use std::process::{Command, ExitStatus, Output}; -use crate::util_msg::{print_debug, print_error, MessageType}; +use crate::util_msg::{print_debug, print_error, MessageType, print_message}; pub fn run_command_or_exit(cmd: &str, args: &[&str]) -> Output { let mut c = Command::new(cmd); @@ -12,23 +12,30 @@ pub fn run_command_or_exit(cmd: &str, args: &[&str]) -> Output { match output { Err(e) => { print_error(&format!("Run command: {:?}, failed: {}", c, e)); + crate::util_runtime::invoke_callbacks(); std::process::exit(-1); - }, + } Ok(output) => { if !output.status.success() { - print_error(&format!(r##"Run command failed, code: {:?} + print_output(MessageType::ERROR, &output); + } + output + } + } +} + +pub fn print_output(message_type: MessageType, output: &Output) { + crate::util_msg::when(message_type, || { + print_message(message_type, &format!(r##"Run command failed, code: {:?} -----std out--------------------------------------------------------------- {} -----std err--------------------------------------------------------------- {} ---------------------------------------------------------------------------"##, - output.status.code(), - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr))); - } - output - } - } + output.status.code(), + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr))); + }); } pub fn run_command_and_wait(cmd: &mut Command) -> io::Result { diff --git a/src/util_os.rs b/src/util_os.rs index 78544c9..9b2168b 100644 --- a/src/util_os.rs +++ b/src/util_os.rs @@ -1,3 +1,4 @@ +use std::path::PathBuf; pub fn is_macos() -> bool { cfg!(target_os = "macos") @@ -10,3 +11,9 @@ pub fn is_linux() -> bool { pub fn is_macos_or_linux() -> bool { is_macos() || is_linux() } + +pub fn get_full_work_dir() -> Option { + PathBuf::from(".").canonicalize().ok().map(|p| { + p.to_str().map(ToString::to_string) + }).flatten() +} \ No newline at end of file diff --git a/src/util_runtime.rs b/src/util_runtime.rs new file mode 100644 index 0000000..ac2a3d8 --- /dev/null +++ b/src/util_runtime.rs @@ -0,0 +1,24 @@ +use std::sync::Mutex; +use crate::util_msg::MessageType; + +lazy_static! { + static ref EXIT_CALLBACK: Mutex () + Send + 'static>>> = Mutex::new(vec![]); +} + +pub fn register_callback(f: F) where F: Fn() -> () + Send + 'static { + let mut exit_callbacks = EXIT_CALLBACK.lock().unwrap(); + exit_callbacks.push(Box::new(f)); +} + +pub fn invoke_callbacks() { + let mut exit_callbacks = EXIT_CALLBACK.lock().unwrap(); + let total = exit_callbacks.len(); + let mut index = 0; + while exit_callbacks.len() > 0 { + crate::util_msg::when(MessageType::DEBUG, || { + crate::util_msg::print_debug(&format!("Running exit callbacks: {} of {}", index, total)); + }); + exit_callbacks.remove(0)(); + index += 1; + } +} \ No newline at end of file