diff --git a/src/executor.rs b/src/executor.rs index 2807eae5..0540c038 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -176,3 +176,20 @@ impl Check for ExecutorExitStatus { } } } + +/// Extension methods for `std::process::Command` +pub trait CommandExt { + /// Run the command, wait for it to complete, check the return code and decode the output as UTF-8. + fn check_output(&mut self) -> Result; +} + +impl CommandExt for Command { + fn check_output(&mut self) -> Result { + let output = self.output().context(ErrorKind::ProcessExecution)?; + let status = output.status; + if !status.success() { + Err(ErrorKind::ProcessFailed(status))? + } + Ok(String::from_utf8(output.stdout).context(ErrorKind::ProcessExecution)?) + } +} diff --git a/src/steps/generic.rs b/src/steps/generic.rs index c43eeedd..eaf19882 100644 --- a/src/steps/generic.rs +++ b/src/steps/generic.rs @@ -1,9 +1,8 @@ -use crate::error::{Error, ErrorKind}; -use crate::executor::RunType; +use crate::error::Error; +use crate::executor::{CommandExt, RunType}; use crate::terminal::print_separator; -use crate::utils::{self, Check, PathExt}; +use crate::utils::{self, PathExt}; use directories::BaseDirs; -use failure::ResultExt; use std::path::PathBuf; use std::process::Command; @@ -202,16 +201,10 @@ pub fn run_custom_command(name: &str, command: &str, run_type: RunType) -> Resul #[must_use] pub fn run_composer_update(base_dirs: &BaseDirs, run_type: RunType) -> Option<(&'static str, bool)> { if let Some(composer) = utils::which("composer") { - let composer_home = || -> Result { - let output = Command::new(&composer) - .args(&["global", "config", "--absolute", "home"]) - .output() - .context(ErrorKind::ProcessExecution)?; - output.status.check()?; - Ok(PathBuf::from( - &String::from_utf8(output.stdout).context(ErrorKind::ProcessExecution)?, - )) - }(); + let composer_home = Command::new(&composer) + .args(&["global", "config", "--absolute", "home"]) + .check_output() + .map(PathBuf::from); if let Ok(composer_home) = composer_home { if composer_home.is_descendant_of(base_dirs.home_dir()) { diff --git a/src/steps/git.rs b/src/steps/git.rs index bd08adac..badf113b 100644 --- a/src/steps/git.rs +++ b/src/steps/git.rs @@ -1,5 +1,5 @@ use crate::error::Error; -use crate::executor::RunType; +use crate::executor::{CommandExt, RunType}; use crate::terminal::print_separator; use crate::utils::which; use log::{debug, error}; @@ -38,15 +38,10 @@ impl Git { let output = Command::new(&git) .args(&["rev-parse", "--show-toplevel"]) .current_dir(path) - .output(); - - if let Ok(output) = output { - if !output.status.success() { - return None; - } - - return Some(String::from_utf8_lossy(&output.stdout).trim().to_string()); - } + .check_output() + .ok() + .map(|output| output.trim().to_string()); + return output; } } Err(e) => match e.kind() { diff --git a/src/steps/node.rs b/src/steps/node.rs index be98b559..b2f6e702 100644 --- a/src/steps/node.rs +++ b/src/steps/node.rs @@ -1,9 +1,8 @@ -use crate::error::{Error, ErrorKind}; -use crate::executor::RunType; +use crate::error::Error; +use crate::executor::{CommandExt, RunType}; use crate::terminal::print_separator; -use crate::utils::{which, Check, PathExt}; +use crate::utils::{which, PathExt}; use directories::BaseDirs; -use failure::ResultExt; use std::path::PathBuf; use std::process::Command; @@ -17,16 +16,10 @@ impl NPM { } fn root(&self) -> Result { - let output = Command::new(&self.command) + Command::new(&self.command) .args(&["root", "-g"]) - .output() - .context(ErrorKind::ProcessExecution)?; - - output.status.check()?; - - Ok(PathBuf::from( - &String::from_utf8(output.stdout).context(ErrorKind::ProcessExecution)?, - )) + .check_output() + .map(PathBuf::from) } fn upgrade(&self, run_type: RunType) -> Result<(), Error> { diff --git a/src/steps/os/windows.rs b/src/steps/os/windows.rs index 6a209656..d45f92ed 100644 --- a/src/steps/os/windows.rs +++ b/src/steps/os/windows.rs @@ -1,8 +1,7 @@ -use crate::error::{Error, ErrorKind}; -use crate::executor::RunType; +use crate::error::Error; +use crate::executor::{CommandExt, RunType}; use crate::terminal::print_separator; -use crate::utils::{self, which, Check}; -use failure::ResultExt; +use crate::utils::{self, which}; use log::error; use std::path::PathBuf; use std::process::Command; @@ -57,9 +56,7 @@ impl Powershell { || -> Result<(), Error> { Command::new(&powershell) .args(&["-Command", &format!("Get-Command {}", command)]) - .output() - .context(ErrorKind::ProcessExecution)? - .check()?; + .check_output()?; Ok(()) }() .is_ok() @@ -67,16 +64,10 @@ impl Powershell { pub fn profile(&self) -> Option { if let Some(powershell) = &self.path { - let result = || -> Result { - let output = Command::new(powershell) - .args(&["-Command", "echo $profile"]) - .output() - .context(ErrorKind::ProcessExecution)?; - output.status.check()?; - Ok(PathBuf::from( - String::from_utf8_lossy(&output.stdout).trim().to_string(), - )) - }(); + let result = Command::new(powershell) + .args(&["-Command", "echo $profile"]) + .check_output() + .map(PathBuf::from); match result { Err(e) => error!("Error getting Powershell profile: {}", e),