diff --git a/src/config.rs b/src/config.rs index 8d9043d4..ff1bcd25 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,6 @@ +use super::error::{Error, ErrorKind}; use directories::BaseDirs; -use failure; +use failure::ResultExt; use serde_derive::Deserialize; use shellexpand; use std::collections::BTreeMap; @@ -17,13 +18,14 @@ pub struct Config { } impl Config { - pub fn read(base_dirs: &BaseDirs) -> Result { + pub fn read(base_dirs: &BaseDirs) -> Result { let config_path = base_dirs.config_dir().join("topgrade.toml"); if !config_path.exists() { return Ok(Default::default()); } - let mut result: Self = toml::from_str(&fs::read_to_string(config_path)?)?; + let mut result: Self = toml::from_str(&fs::read_to_string(config_path).context(ErrorKind::Configuration)?) + .context(ErrorKind::Configuration)?; if let Some(ref mut paths) = &mut result.git_repos { for path in paths.iter_mut() { diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 00000000..d97d0b02 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,80 @@ +use failure::{Backtrace, Context, Fail}; +use std::fmt::{self, Display}; +use std::process::ExitStatus; + +#[derive(Debug)] +pub struct Error { + inner: Context, +} + +#[derive(Copy, Clone, Eq, PartialEq, Debug, Fail)] +pub enum ErrorKind { + #[fail(display = "Error asking the user for retry")] + Retry, + + #[fail(display = "Cannot find the user base directories")] + NoBaseDirectories, + + #[fail(display = "A step failed")] + StepFailed, + + #[fail(display = "Error reading the configuration")] + Configuration, + + #[fail(display = "A custom pre-command failed")] + PreCommand, + + #[fail(display = "{}", _0)] + ProcessFailed(ExitStatus), + + #[fail(display = "Unknown Linux Distribution")] + #[cfg(target_os = "linux")] + UnknownLinuxDistribution, + + #[fail(display = "Detected Python is not the system Python")] + #[cfg(target_os = "linux")] + NotSystemPython, + + #[fail(display = "Process execution failure")] + ProcessExecution, + + #[fail(display = "Self-update failure")] + #[cfg(feature = "self-update")] + SelfUpdate, +} + +impl Fail for Error { + fn cause(&self) -> Option<&Fail> { + self.inner.cause() + } + + fn backtrace(&self) -> Option<&Backtrace> { + self.inner.backtrace() + } +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.inner, f) + } +} + +impl Error { + pub fn kind(&self) -> ErrorKind { + *self.inner.get_context() + } +} + +impl From for Error { + fn from(kind: ErrorKind) -> Error { + Error { + inner: Context::new(kind), + } + } +} + +impl From> for Error { + fn from(inner: Context) -> Error { + Error { inner } + } +} diff --git a/src/executor.rs b/src/executor.rs index 9f76af2b..1e0f10c7 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -1,7 +1,7 @@ +use super::error::{Error, ErrorKind}; use super::utils::Check; -use failure; +use failure::ResultExt; use std::ffi::{OsStr, OsString}; -use std::io; use std::path::Path; use std::process::{Child, Command, ExitStatus}; @@ -63,9 +63,9 @@ impl Executor { self } - pub fn spawn(&mut self) -> Result { - match self { - Executor::Wet(c) => c.spawn().map(ExecutorChild::Wet), + pub fn spawn(&mut self) -> Result { + let result = match self { + Executor::Wet(c) => c.spawn().context(ErrorKind::ProcessExecution).map(ExecutorChild::Wet)?, Executor::Dry(c) => { print!( "Dry running: {} {}", @@ -80,9 +80,11 @@ impl Executor { Some(dir) => println!(" in {}", dir.to_string_lossy()), None => println!(), }; - Ok(ExecutorChild::Dry) + ExecutorChild::Dry } - } + }; + + Ok(result) } } @@ -99,11 +101,16 @@ pub enum ExecutorChild { } impl ExecutorChild { - pub fn wait(&mut self) -> Result { - match self { - ExecutorChild::Wet(c) => c.wait().map(ExecutorExitStatus::Wet), - ExecutorChild::Dry => Ok(ExecutorExitStatus::Dry), - } + pub fn wait(&mut self) -> Result { + let result = match self { + ExecutorChild::Wet(c) => c + .wait() + .context(ErrorKind::ProcessExecution) + .map(ExecutorExitStatus::Wet)?, + ExecutorChild::Dry => ExecutorExitStatus::Dry, + }; + + Ok(result) } } @@ -113,7 +120,7 @@ pub enum ExecutorExitStatus { } impl Check for ExecutorExitStatus { - fn check(self) -> Result<(), failure::Error> { + fn check(self) -> Result<(), Error> { match self { ExecutorExitStatus::Wet(e) => e.check(), ExecutorExitStatus::Dry => Ok(()), diff --git a/src/freebsd.rs b/src/freebsd.rs index fa2660e1..b4817ee2 100644 --- a/src/freebsd.rs +++ b/src/freebsd.rs @@ -1,7 +1,8 @@ +use super::error::{Error, ErrorKind}; use super::executor::Executor; use super::terminal::{print_separator, print_warning}; use super::utils::Check; -use failure; +use failure::ResultExt; use std::path::PathBuf; use std::process::Command; @@ -10,7 +11,7 @@ pub fn upgrade_freebsd(sudo: &Option, dry_run: bool) -> Option<(&'stati print_separator("FreeBSD Update"); if let Some(sudo) = sudo { - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(sudo, dry_run) .args(&["/usr/sbin/freebsd-update", "fetch", "install"]) .spawn()? @@ -32,7 +33,7 @@ pub fn upgrade_packages(sudo: &Option, dry_run: bool) -> Option<(&'stat print_separator("FreeBSD Packages"); if let Some(sudo) = sudo { - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(sudo, dry_run) .args(&["/usr/sbin/pkg", "upgrade"]) .spawn()? @@ -49,13 +50,15 @@ pub fn upgrade_packages(sudo: &Option, dry_run: bool) -> Option<(&'stat } } -pub fn audit_packages(sudo: &Option) -> Result<(), failure::Error> { +pub fn audit_packages(sudo: &Option) -> Result<(), Error> { if let Some(sudo) = sudo { println!(); Command::new(sudo) .args(&["/usr/sbin/pkg", "audit", "-Fr"]) - .spawn()? - .wait()?; + .spawn() + .context(ErrorKind::ProcessExecution)? + .wait() + .context(ErrorKind::ProcessExecution)?; } Ok(()) } diff --git a/src/generic.rs b/src/generic.rs index 47173e29..df6b7260 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -1,8 +1,9 @@ +use super::error::{Error, ErrorKind}; use super::executor::Executor; use super::terminal::print_separator; use super::utils::{self, Check, PathExt}; use directories::BaseDirs; -use failure::Error; +use failure::ResultExt; use std::path::PathBuf; use std::process::Command; @@ -229,9 +230,12 @@ pub fn run_composer_update(base_dirs: &BaseDirs, dry_run: bool) -> Option<(&'sta let composer_home = || -> Result { let output = Command::new(&composer) .args(&["global", "config", "--absolute", "home"]) - .output()?; + .output() + .context(ErrorKind::ProcessExecution)?; output.status.check()?; - Ok(PathBuf::from(&String::from_utf8(output.stdout)?)) + Ok(PathBuf::from( + &String::from_utf8(output.stdout).context(ErrorKind::ProcessExecution)?, + )) }(); if let Ok(composer_home) = composer_home { diff --git a/src/git.rs b/src/git.rs index 40d8132d..1d3485b8 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,7 +1,7 @@ +use super::error::Error; use super::executor::Executor; use super::terminal::print_separator; use super::utils::{which, Check}; -use failure::Error; use log::{debug, error}; use std::collections::HashSet; use std::io; diff --git a/src/linux.rs b/src/linux.rs index bd2a265c..6fccefd1 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -1,8 +1,8 @@ +use super::error::{Error, ErrorKind}; use super::executor::Executor; use super::terminal::{print_separator, print_warning}; use super::utils::{which, Check}; -use failure; -use failure_derive::Fail; +use failure::ResultExt; use std::fs; use std::path::PathBuf; use walkdir::WalkDir; @@ -19,17 +19,9 @@ pub enum Distribution { Void, } -#[derive(Debug, Fail)] -#[fail(display = "Unknown Linux Distribution")] -struct UnknownLinuxDistribution; - -#[derive(Debug, Fail)] -#[fail(display = "Detected Python is not the system Python")] -struct NotSystemPython; - impl Distribution { - pub fn detect() -> Result { - let content = fs::read_to_string("/etc/os-release")?; + pub fn detect() -> Result { + let content = fs::read_to_string("/etc/os-release").context(ErrorKind::UnknownLinuxDistribution)?; if content.contains("Arch") | content.contains("Manjaro") | content.contains("Antergos") { return Ok(Distribution::Arch); @@ -63,7 +55,7 @@ impl Distribution { return Ok(Distribution::Gentoo); } - Err(UnknownLinuxDistribution.into()) + Err(ErrorKind::UnknownLinuxDistribution)? } #[must_use] @@ -111,7 +103,7 @@ pub fn show_pacnew() { } } -fn upgrade_arch_linux(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_arch_linux(sudo: &Option, dry_run: bool) -> Result<(), Error> { if let Some(yay) = which("yay") { if let Some(python) = which("python") { if python != PathBuf::from("/usr/bin/python") { @@ -120,7 +112,7 @@ fn upgrade_arch_linux(sudo: &Option, dry_run: bool) -> Result<(), failu It's dangerous to run yay since Python based AUR packages will be installed in the wrong location", python )); - return Err(NotSystemPython.into()); + return Err(ErrorKind::NotSystemPython)?; } } @@ -138,7 +130,7 @@ It's dangerous to run yay since Python based AUR packages will be installed in t Ok(()) } -fn upgrade_redhat(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_redhat(sudo: &Option, dry_run: bool) -> Result<(), Error> { if let Some(sudo) = &sudo { Executor::new(&sudo, dry_run) .args(&["/usr/bin/yum", "upgrade"]) @@ -152,7 +144,7 @@ fn upgrade_redhat(sudo: &Option, dry_run: bool) -> Result<(), failure:: Ok(()) } -fn upgrade_opensuse(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_opensuse(sudo: &Option, dry_run: bool) -> Result<(), Error> { if let Some(sudo) = &sudo { Executor::new(&sudo, dry_run) .args(&["/usr/bin/zypper", "refresh"]) @@ -172,7 +164,7 @@ fn upgrade_opensuse(sudo: &Option, dry_run: bool) -> Result<(), failure Ok(()) } -fn upgrade_void(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_void(sudo: &Option, dry_run: bool) -> Result<(), Error> { if let Some(sudo) = &sudo { Executor::new(&sudo, dry_run) .args(&["/usr/bin/xbps-install", "-Su"]) @@ -186,7 +178,7 @@ fn upgrade_void(sudo: &Option, dry_run: bool) -> Result<(), failure::Er Ok(()) } -fn upgrade_fedora(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_fedora(sudo: &Option, dry_run: bool) -> Result<(), Error> { if let Some(sudo) = &sudo { Executor::new(&sudo, dry_run) .args(&["/usr/bin/dnf", "upgrade"]) @@ -200,7 +192,7 @@ fn upgrade_fedora(sudo: &Option, dry_run: bool) -> Result<(), failure:: Ok(()) } -fn upgrade_gentoo(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_gentoo(sudo: &Option, dry_run: bool) -> Result<(), Error> { if let Some(sudo) = &sudo { if let Some(layman) = which("layman") { Executor::new(&sudo, dry_run) @@ -236,7 +228,7 @@ fn upgrade_gentoo(sudo: &Option, dry_run: bool) -> Result<(), failure:: Ok(()) } -fn upgrade_debian(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_debian(sudo: &Option, dry_run: bool) -> Result<(), Error> { if let Some(sudo) = &sudo { Executor::new(&sudo, dry_run) .args(&["/usr/bin/apt", "update"]) @@ -262,7 +254,7 @@ pub fn run_needrestart(sudo: &Option, dry_run: bool) -> Option<(&'stati if let Some(needrestart) = which("needrestart") { print_separator("Check for needed restarts"); - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(&sudo, dry_run) .arg(needrestart) .spawn()? @@ -285,7 +277,7 @@ pub fn run_fwupdmgr(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(fwupdmgr) = which("fwupdmgr") { print_separator("Firmware upgrades"); - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(&fwupdmgr, dry_run) .arg("refresh") .spawn()? @@ -311,7 +303,7 @@ pub fn flatpak_user_update(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(flatpak) = which("flatpak") { print_separator("Flatpak User Packages"); - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(&flatpak, dry_run) .args(&["update", "--user", "-y"]) .spawn()? @@ -333,7 +325,7 @@ pub fn flatpak_global_update(sudo: &Option, dry_run: bool) -> Option<(& if let Some(flatpak) = which("flatpak") { print_separator("Flatpak Global Packages"); - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(&sudo, dry_run) .args(&[flatpak.to_str().unwrap(), "update", "-y"]) .spawn()? @@ -357,7 +349,7 @@ pub fn run_snap(sudo: &Option, dry_run: bool) -> Option<(&'static str, if PathBuf::from("/var/snapd.socket").exists() { print_separator("snap"); - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(&sudo, dry_run) .args(&[snap.to_str().unwrap(), "refresh"]) .spawn()? @@ -382,7 +374,7 @@ pub fn run_etc_update(sudo: &Option, dry_run: bool) -> Option<(&'static if let Some(etc_update) = which("etc-update") { print_separator("etc-update"); - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(&sudo, dry_run) .arg(&etc_update.to_str().unwrap()) .spawn()? diff --git a/src/macos.rs b/src/macos.rs index ef782771..b4f8a912 100644 --- a/src/macos.rs +++ b/src/macos.rs @@ -1,13 +1,13 @@ +use super::error::Error; use super::executor::Executor; use super::terminal::print_separator; use super::utils::Check; -use failure; #[must_use] pub fn upgrade_macos(dry_run: bool) -> Option<(&'static str, bool)> { print_separator("App Store"); - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new("softwareupdate", dry_run) .args(&["--install", "--all"]) .spawn()? diff --git a/src/main.rs b/src/main.rs index f8ff3508..e28ecb93 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,6 +32,7 @@ mod windows; mod config; mod ctrlc; +mod error; mod executor; mod generic; mod git; @@ -44,29 +45,17 @@ mod utils; mod vim; use self::config::Config; +use self::error::{Error, ErrorKind}; use self::git::{Git, Repositories}; use self::report::Report; -use failure::Error; -use failure_derive::Fail; +use failure::{Fail, ResultExt}; use std::borrow::Cow; use std::env; -use std::io::ErrorKind; +use std::io; use std::process::exit; use structopt::StructOpt; use terminal::*; -#[derive(Fail, Debug)] -#[fail(display = "A step failed")] -struct StepFailed; - -#[derive(Fail, Debug)] -#[fail(display = "Cannot find the user base directories")] -struct NoBaseDirectories; - -#[derive(Fail, Debug)] -#[fail(display = "Process Interrupted")] -pub struct Interrupted; - fn execute<'a, F, M>(func: F, no_retry: bool) -> Result, Error> where M: Into>, @@ -83,14 +72,7 @@ where } let should_ask = !running || !no_retry; - let should_retry = should_ask - && should_retry(running).map_err(|e| { - if e.kind() == ErrorKind::Interrupted { - Error::from(Interrupted) - } else { - Error::from(e) - } - })?; + let should_retry = should_ask && should_retry(running).context(ErrorKind::Retry)?; if !should_retry { return Ok(Some((key, success))); @@ -114,7 +96,7 @@ fn run() -> Result<(), Error> { env_logger::init(); - let base_dirs = directories::BaseDirs::new().ok_or(NoBaseDirectories)?; + let base_dirs = directories::BaseDirs::new().ok_or(ErrorKind::NoBaseDirectories)?; let git = Git::new(); let mut git_repos = Repositories::new(&git); @@ -135,7 +117,7 @@ fn run() -> Result<(), Error> { if let Some(commands) = config.pre_commands() { for (name, command) in commands { - generic::run_custom_command(&name, &command, opt.dry_run)?; + generic::run_custom_command(&name, &command, opt.dry_run).context(ErrorKind::PreCommand)?; } } @@ -322,7 +304,7 @@ fn run() -> Result<(), Error> { if report.data().iter().all(|(_, succeeded)| *succeeded) { Ok(()) } else { - Err(StepFailed.into()) + Err(ErrorKind::StepFailed)? } } @@ -332,9 +314,21 @@ fn main() { exit(0); } Err(error) => { - if (error.downcast_ref::().is_some()) || (error.downcast_ref::().is_some()) { - } else { - println!("ERROR: {}", error) + let should_print = match error.kind() { + ErrorKind::StepFailed => false, + ErrorKind::Retry => error + .cause() + .and_then(|cause| cause.downcast_ref::()) + .filter(|io_error| io_error.kind() == io::ErrorKind::Interrupted) + .is_none(), + _ => true, + }; + + if should_print { + println!("Error: {}", error); + if let Some(cause) = error.cause() { + println!("Caused by: {}", cause); + } } exit(1); } diff --git a/src/node.rs b/src/node.rs index e2ed2ee9..4e1e50c2 100644 --- a/src/node.rs +++ b/src/node.rs @@ -1,8 +1,9 @@ +use super::error::{Error, ErrorKind}; use super::executor::Executor; use super::terminal::print_separator; use super::utils::{which, Check, PathExt}; use directories::BaseDirs; -use failure; +use failure::ResultExt; use std::path::PathBuf; use std::process::Command; @@ -15,15 +16,20 @@ impl NPM { Self { command } } - fn root(&self) -> Result { - let output = Command::new(&self.command).args(&["root", "-g"]).output()?; + fn root(&self) -> Result { + let output = Command::new(&self.command) + .args(&["root", "-g"]) + .output() + .context(ErrorKind::ProcessExecution)?; output.status.check()?; - Ok(PathBuf::from(&String::from_utf8(output.stdout)?)) + Ok(PathBuf::from( + &String::from_utf8(output.stdout).context(ErrorKind::ProcessExecution)?, + )) } - fn upgrade(&self, dry_run: bool) -> Result<(), failure::Error> { + fn upgrade(&self, dry_run: bool) -> Result<(), Error> { Executor::new(&self.command, dry_run) .args(&["update", "-g"]) .spawn()? @@ -53,7 +59,7 @@ pub fn yarn_global_update(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(yarn) = which("yarn") { print_separator("Yarn"); - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(&yarn, dry_run) .args(&["global", "upgrade", "-s"]) .spawn()? diff --git a/src/self_update.rs b/src/self_update.rs index ec9f71f5..fe5a6ade 100644 --- a/src/self_update.rs +++ b/src/self_update.rs @@ -1,5 +1,6 @@ +use super::error::{Error, ErrorKind}; use super::terminal::*; -use failure::Error; +use failure::ResultExt; use self_update_crate; #[cfg(unix)] use std::env; @@ -13,8 +14,9 @@ pub fn self_update() -> Result<(), Error> { #[cfg(unix)] let current_exe = env::current_exe(); - let target = self_update_crate::get_target()?; - let result = self_update_crate::backends::github::Update::configure()? + let target = self_update_crate::get_target().context(ErrorKind::SelfUpdate)?; + let result = self_update_crate::backends::github::Update::configure() + .context(ErrorKind::SelfUpdate)? .repo_owner("r-darwish") .repo_name("topgrade") .target(&target) @@ -23,8 +25,10 @@ pub fn self_update() -> Result<(), Error> { .show_download_progress(true) .current_version(self_update_crate::cargo_crate_version!()) .no_confirm(true) - .build()? - .update()?; + .build() + .context(ErrorKind::SelfUpdate)? + .update() + .context(ErrorKind::SelfUpdate)?; if let self_update_crate::Status::Updated(version) = &result { println!("\nTopgrade upgraded to {}", version); @@ -36,8 +40,10 @@ pub fn self_update() -> Result<(), Error> { { if result.updated() { print_warning("Respawning..."); - let err = Command::new(current_exe?).args(env::args().skip(1)).exec(); - Err(err)? + let err = Command::new(current_exe.context(ErrorKind::SelfUpdate)?) + .args(env::args().skip(1)) + .exec(); + Err(err).context(ErrorKind::SelfUpdate)? } } diff --git a/src/tmux.rs b/src/tmux.rs index bf95f3f4..cae45dd7 100644 --- a/src/tmux.rs +++ b/src/tmux.rs @@ -1,9 +1,10 @@ +use super::error::{Error, ErrorKind}; use super::executor::Executor; use super::terminal::print_separator; use super::utils::which; use super::utils::{Check, PathExt}; use directories::BaseDirs; -use failure::Error; +use failure::ResultExt; use std::env; use std::io; use std::os::unix::process::CommandExt; @@ -41,8 +42,10 @@ fn has_session(tmux: &Path, session_name: &str) -> Result { fn run_in_session(tmux: &Path, command: &str) -> Result<(), Error> { Command::new(tmux) .args(&["new-window", "-a", "-t", "topgrade:1", command]) - .spawn()? - .wait()? + .spawn() + .context(ErrorKind::ProcessExecution)? + .wait() + .context(ErrorKind::ProcessExecution)? .check()?; Ok(()) diff --git a/src/unix.rs b/src/unix.rs index 501a15b5..4d05a79c 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -2,7 +2,7 @@ use super::executor::Executor; use super::terminal::print_separator; use super::utils::{which, Check}; use directories::BaseDirs; -use failure::Error; +use Error; pub fn run_zplug(base_dirs: &BaseDirs, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(zsh) = which("zsh") { diff --git a/src/utils.rs b/src/utils.rs index d01cc515..37af057f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,4 @@ -use failure::Error; -use failure_derive::Fail; +use super::error::{Error, ErrorKind}; use log::{debug, error}; use std::ffi::OsStr; use std::fmt::Debug; @@ -7,10 +6,6 @@ use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output}; use which as which_mod; -#[derive(Fail, Debug)] -#[fail(display = "Process failed")] -pub struct ProcessFailed; - pub trait Check { fn check(self) -> Result<(), Error>; } @@ -20,7 +15,7 @@ impl Check for ExitStatus { if self.success() { Ok(()) } else { - Err(Error::from(ProcessFailed {})) + Err(ErrorKind::ProcessFailed(self))? } } } diff --git a/src/vim.rs b/src/vim.rs index da0d4e6b..73701caa 100644 --- a/src/vim.rs +++ b/src/vim.rs @@ -1,8 +1,8 @@ +use super::error::Error; use super::executor::Executor; use super::terminal::print_separator; use super::utils::{which, Check, PathExt}; use directories::BaseDirs; -use failure; use std::fs; use std::path::PathBuf; @@ -54,12 +54,7 @@ fn nvimrc(base_dirs: &BaseDirs) -> Option { } #[must_use] -fn upgrade( - vim: &PathBuf, - vimrc: &PathBuf, - plugin_framework: PluginFramework, - dry_run: bool, -) -> Result<(), failure::Error> { +fn upgrade(vim: &PathBuf, vimrc: &PathBuf, plugin_framework: PluginFramework, dry_run: bool) -> Result<(), Error> { Executor::new(&vim, dry_run) .args(&[ "-N", diff --git a/src/windows.rs b/src/windows.rs index 946dba33..4efbda20 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -1,7 +1,8 @@ +use super::error::{Error, ErrorKind}; use super::executor::Executor; use super::terminal::print_separator; use super::utils::{self, which, Check}; -use failure; +use failure::ResultExt; use log::error; use std::path::PathBuf; use std::process::Command; @@ -11,7 +12,7 @@ pub fn run_chocolatey(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(choco) = utils::which("choco") { print_separator("Chocolatey"); - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(&choco, dry_run) .args(&["upgrade", "all"]) .spawn()? @@ -32,7 +33,7 @@ pub fn run_scoop(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(scoop) = utils::which("scoop") { print_separator("Scoop"); - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(&scoop, dry_run) .args(&["update"]) .spawn()? @@ -65,10 +66,11 @@ impl Powershell { } pub fn has_command(powershell: &PathBuf, command: &str) -> bool { - || -> Result<(), failure::Error> { + || -> Result<(), Error> { Command::new(&powershell) .args(&["-Command", &format!("Get-Command {}", command)]) - .output()? + .output() + .context(ErrorKind::ProcessExecution)? .check()?; Ok(()) }() @@ -77,8 +79,11 @@ 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()?; + 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(), @@ -98,7 +103,7 @@ impl Powershell { if let Some(powershell) = &self.path { print_separator("Powershell Modules Update"); - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(&powershell, dry_run) .arg("Update-Module") .spawn()? @@ -120,7 +125,7 @@ impl Powershell { if Self::has_command(&powershell, "Install-WindowsUpdate") { print_separator("Windows Update"); - let success = || -> Result<(), failure::Error> { + let success = || -> Result<(), Error> { Executor::new(&powershell, dry_run) .args(&["-Command", "Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose"]) .spawn()?