diff --git a/Cargo.toml b/Cargo.toml index 13f0779c..2f5aefdf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,10 +22,10 @@ env_logger = "0.5.13" walkdir = "2.2.6" console = "0.6.2" self_update = { version = "0.5.0", optional = true } +lazy_static = "1.1.0" [target.'cfg(unix)'.dependencies] nix = "0.11.0" -lazy_static = "1.1.0" [profile.release] lto = true diff --git a/src/freebsd.rs b/src/freebsd.rs index 086dcb4f..cabfe5de 100644 --- a/src/freebsd.rs +++ b/src/freebsd.rs @@ -1,13 +1,13 @@ use super::executor::Executor; -use super::terminal::Terminal; +use super::terminal::{print_separator, print_warning}; use super::utils::Check; use failure; use std::path::PathBuf; use std::process::Command; #[must_use] -pub fn upgrade_freebsd(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - terminal.print_separator("FreeBSD Update"); +pub fn upgrade_freebsd(sudo: &Option, dry_run: bool) -> Option<(&'static str, bool)> { + print_separator("FreeBSD Update"); if let Some(sudo) = sudo { let success = || -> Result<(), failure::Error> { @@ -21,18 +21,14 @@ pub fn upgrade_freebsd(sudo: &Option, terminal: &mut Terminal, dry_run: Some(("FreeBSD Update", success)) } else { - terminal.print_warning("No sudo or yay detected. Skipping system upgrade"); + print_warning("No sudo or yay detected. Skipping system upgrade"); None } } #[must_use] -pub fn upgrade_packages( - sudo: &Option, - terminal: &mut Terminal, - dry_run: bool, -) -> Option<(&'static str, bool)> { - terminal.print_separator("FreeBSD Packages"); +pub fn upgrade_packages(sudo: &Option, dry_run: bool) -> Option<(&'static str, bool)> { + print_separator("FreeBSD Packages"); if let Some(sudo) = sudo { let success = || -> Result<(), failure::Error> { @@ -46,7 +42,7 @@ pub fn upgrade_packages( Some(("FreeBSD Packages", success)) } else { - terminal.print_warning("No sudo or yay detected. Skipping package upgrade"); + print_warning("No sudo or yay detected. Skipping package upgrade"); None } } diff --git a/src/generic.rs b/src/generic.rs index 9cbd1b7e..3a08104a 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -1,5 +1,5 @@ use super::executor::Executor; -use super::terminal::Terminal; +use super::terminal::print_separator; use super::utils::{self, Check, PathExt}; use directories::BaseDirs; use failure::Error; @@ -9,9 +9,9 @@ use std::process::Command; const EMACS_UPGRADE: &str = include_str!("emacs.el"); #[must_use] -pub fn run_cargo_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_cargo_update(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(cargo_update) = utils::which("cargo-install-update") { - terminal.print_separator("Cargo"); + print_separator("Cargo"); let success = || -> Result<(), Error> { Executor::new(cargo_update, dry_run) @@ -30,10 +30,10 @@ pub fn run_cargo_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'sta } #[must_use] -pub fn run_gem(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_gem(base_dirs: &BaseDirs, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(gem) = utils::which("gem") { if base_dirs.home_dir().join(".gem").exists() { - terminal.print_separator("RubyGems"); + print_separator("RubyGems"); let success = || -> Result<(), Error> { Executor::new(&gem, dry_run) @@ -52,10 +52,10 @@ pub fn run_gem(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> } #[must_use] -pub fn run_emacs(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_emacs(base_dirs: &BaseDirs, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(emacs) = utils::which("emacs") { if let Some(init_file) = base_dirs.home_dir().join(".emacs.d/init.el").if_exists() { - terminal.print_separator("Emacs"); + print_separator("Emacs"); let success = || -> Result<(), Error> { Executor::new(&emacs, dry_run) @@ -80,9 +80,9 @@ pub fn run_emacs(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) - target_os = "netbsd", target_os = "dragonfly" )))] -pub fn run_apm(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_apm(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(apm) = utils::which("apm") { - terminal.print_separator("Atom Package Manager"); + print_separator("Atom Package Manager"); let success = || -> Result<(), Error> { Executor::new(&apm, dry_run) @@ -101,9 +101,9 @@ pub fn run_apm(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, } #[must_use] -pub fn run_rustup(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_rustup(base_dirs: &BaseDirs, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(rustup) = utils::which("rustup") { - terminal.print_separator("rustup"); + print_separator("rustup"); let success = || -> Result<(), Error> { if rustup.is_descendant_of(base_dirs.home_dir()) { @@ -125,9 +125,9 @@ pub fn run_rustup(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) } #[must_use] -pub fn run_jetpack(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_jetpack(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(jetpack) = utils::which("jetpack") { - terminal.print_separator("Jetpack"); + print_separator("Jetpack"); let success = || -> Result<(), Error> { Executor::new(&jetpack, dry_run) @@ -145,9 +145,9 @@ pub fn run_jetpack(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static s } #[must_use] -pub fn run_opam_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_opam_update(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(opam) = utils::which("opam") { - terminal.print_separator("OCaml Package Manager"); + print_separator("OCaml Package Manager"); let success = || -> Result<(), Error> { Executor::new(&opam, dry_run).arg("update").spawn()?.wait()?.check()?; @@ -162,12 +162,16 @@ pub fn run_opam_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'stat } #[must_use] -pub fn run_vcpkg_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_vcpkg_update(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(vcpkg) = utils::which("vcpkg") { - terminal.print_separator("vcpkg"); + print_separator("vcpkg"); let success = || -> Result<(), Error> { - Executor::new(&vcpkg, dry_run).args(&["upgrade", "--no-dry-run"]).spawn()?.wait()?.check()?; + Executor::new(&vcpkg, dry_run) + .args(&["upgrade", "--no-dry-run"]) + .spawn()? + .wait()? + .check()?; Ok(()) }().is_ok(); @@ -178,9 +182,9 @@ pub fn run_vcpkg_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'sta } #[must_use] -pub fn run_pipx_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_pipx_update(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(pipx) = utils::which("pipx") { - terminal.print_separator("pipx"); + print_separator("pipx"); let success = || -> Result<(), Error> { Executor::new(&pipx, dry_run) @@ -198,8 +202,8 @@ pub fn run_pipx_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'stat } #[must_use] -pub fn run_custom_command(name: &str, command: &str, terminal: &mut Terminal, dry_run: bool) -> Result<(), Error> { - terminal.print_separator(name); +pub fn run_custom_command(name: &str, command: &str, dry_run: bool) -> Result<(), Error> { + print_separator(name); Executor::new("sh", dry_run) .arg("-c") .arg(command) @@ -211,11 +215,7 @@ pub fn run_custom_command(name: &str, command: &str, terminal: &mut Terminal, dr } #[must_use] -pub fn run_composer_update( - base_dirs: &BaseDirs, - terminal: &mut Terminal, - dry_run: bool, -) -> Option<(&'static str, bool)> { +pub fn run_composer_update(base_dirs: &BaseDirs, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(composer) = utils::which("composer") { let composer_home = || -> Result { let output = Command::new(&composer) @@ -227,7 +227,7 @@ pub fn run_composer_update( if let Ok(composer_home) = composer_home { if composer_home.is_descendant_of(base_dirs.home_dir()) { - terminal.print_separator("Composer"); + print_separator("Composer"); let success = || -> Result<(), Error> { Executor::new(&composer, dry_run) diff --git a/src/git.rs b/src/git.rs index 08de3b1e..a167ad28 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,5 +1,5 @@ use super::executor::Executor; -use super::terminal::Terminal; +use super::terminal::print_separator; use super::utils::{which, Check}; use failure::Error; use log::{debug, error}; @@ -58,10 +58,10 @@ impl Git { None } - pub fn pull>(&self, path: P, terminal: &mut Terminal, dry_run: bool) -> Option<(String, bool)> { + pub fn pull>(&self, path: P, dry_run: bool) -> Option<(String, bool)> { let path = path.as_ref(); - terminal.print_separator(format!("Pulling {}", path.display())); + print_separator(format!("Pulling {}", path.display())); let git = self.git.as_ref().unwrap(); diff --git a/src/linux.rs b/src/linux.rs index ebe93aa1..204b150a 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -1,5 +1,5 @@ use super::executor::Executor; -use super::terminal::Terminal; +use super::terminal::{print_separator, print_warning}; use super::utils::{which, Check}; use failure; use failure_derive::Fail; @@ -67,22 +67,17 @@ impl Distribution { } #[must_use] - pub fn upgrade( - self, - sudo: &Option, - terminal: &mut Terminal, - dry_run: bool, - ) -> Option<(&'static str, bool)> { - terminal.print_separator("System update"); + pub fn upgrade(self, sudo: &Option, dry_run: bool) -> Option<(&'static str, bool)> { + print_separator("System update"); let success = match self { - Distribution::Arch => upgrade_arch_linux(&sudo, terminal, dry_run), - Distribution::CentOS => upgrade_redhat(&sudo, terminal, dry_run), - Distribution::Fedora => upgrade_fedora(&sudo, terminal, dry_run), - Distribution::Ubuntu | Distribution::Debian => upgrade_debian(&sudo, terminal, dry_run), - Distribution::Gentoo => upgrade_gentoo(&sudo, terminal, dry_run), - Distribution::OpenSuse => upgrade_opensuse(&sudo, terminal, dry_run), - Distribution::Void => upgrade_void(&sudo, terminal, dry_run), + Distribution::Arch => upgrade_arch_linux(&sudo, dry_run), + Distribution::CentOS => upgrade_redhat(&sudo, dry_run), + Distribution::Fedora => upgrade_fedora(&sudo, dry_run), + Distribution::Ubuntu | Distribution::Debian => upgrade_debian(&sudo, dry_run), + Distribution::Gentoo => upgrade_gentoo(&sudo, dry_run), + Distribution::OpenSuse => upgrade_opensuse(&sudo, dry_run), + Distribution::Void => upgrade_void(&sudo, dry_run), }; Some(("System update", success.is_ok())) @@ -115,11 +110,11 @@ pub fn show_pacnew() { } } -fn upgrade_arch_linux(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_arch_linux(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { if let Some(yay) = which("yay") { if let Some(python) = which("python") { if python != PathBuf::from("/usr/bin/python") { - terminal.print_warning(format!( + print_warning(format!( "Python detected at {:?}, which is probably not the system Python. It's dangerous to run yay since Python based AUR packages will be installed in the wrong location", python @@ -136,13 +131,13 @@ It's dangerous to run yay since Python based AUR packages will be installed in t .wait()? .check()?; } else { - terminal.print_warning("No sudo or yay detected. Skipping system upgrade"); + print_warning("No sudo or yay detected. Skipping system upgrade"); } Ok(()) } -fn upgrade_redhat(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_redhat(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { if let Some(sudo) = &sudo { Executor::new(&sudo, dry_run) .args(&["/usr/bin/yum", "upgrade"]) @@ -150,13 +145,13 @@ fn upgrade_redhat(sudo: &Option, terminal: &mut Terminal, dry_run: bool .wait()? .check()?; } else { - terminal.print_warning("No sudo detected. Skipping system upgrade"); + print_warning("No sudo detected. Skipping system upgrade"); } Ok(()) } -fn upgrade_opensuse(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_opensuse(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { if let Some(sudo) = &sudo { Executor::new(&sudo, dry_run) .args(&["/usr/bin/zypper", "refresh"]) @@ -170,13 +165,13 @@ fn upgrade_opensuse(sudo: &Option, terminal: &mut Terminal, dry_run: bo .wait()? .check()?; } else { - terminal.print_warning("No sudo detected. Skipping system upgrade"); + print_warning("No sudo detected. Skipping system upgrade"); } Ok(()) } -fn upgrade_void(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_void(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { if let Some(sudo) = &sudo { Executor::new(&sudo, dry_run) .args(&["/usr/bin/xbps-install", "-Su"]) @@ -184,13 +179,13 @@ fn upgrade_void(sudo: &Option, terminal: &mut Terminal, dry_run: bool) .wait()? .check()?; } else { - terminal.print_warning("No sudo detected. Skipping system upgrade"); + print_warning("No sudo detected. Skipping system upgrade"); } Ok(()) } -fn upgrade_fedora(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_fedora(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { if let Some(sudo) = &sudo { Executor::new(&sudo, dry_run) .args(&["/usr/bin/dnf", "upgrade"]) @@ -198,13 +193,13 @@ fn upgrade_fedora(sudo: &Option, terminal: &mut Terminal, dry_run: bool .wait()? .check()?; } else { - terminal.print_warning("No sudo detected. Skipping system upgrade"); + print_warning("No sudo detected. Skipping system upgrade"); } Ok(()) } -fn upgrade_gentoo(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_gentoo(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { if let Some(sudo) = &sudo { if let Some(layman) = which("layman") { Executor::new(&sudo, dry_run) @@ -234,13 +229,13 @@ fn upgrade_gentoo(sudo: &Option, terminal: &mut Terminal, dry_run: bool .wait()? .check()?; } else { - terminal.print_warning("No sudo detected. Skipping system upgrade"); + print_warning("No sudo detected. Skipping system upgrade"); } Ok(()) } -fn upgrade_debian(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Result<(), failure::Error> { +fn upgrade_debian(sudo: &Option, dry_run: bool) -> Result<(), failure::Error> { if let Some(sudo) = &sudo { Executor::new(&sudo, dry_run) .args(&["/usr/bin/apt", "update"]) @@ -254,17 +249,17 @@ fn upgrade_debian(sudo: &Option, terminal: &mut Terminal, dry_run: bool .wait()? .check()?; } else { - terminal.print_warning("No sudo detected. Skipping system upgrade"); + print_warning("No sudo detected. Skipping system upgrade"); } Ok(()) } #[must_use] -pub fn run_needrestart(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_needrestart(sudo: &Option, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(sudo) = sudo { if let Some(needrestart) = which("needrestart") { - terminal.print_separator("Check for needed restarts"); + print_separator("Check for needed restarts"); let success = || -> Result<(), failure::Error> { Executor::new(&sudo, dry_run) @@ -284,9 +279,9 @@ pub fn run_needrestart(sudo: &Option, terminal: &mut Terminal, dry_run: } #[must_use] -pub fn run_fwupdmgr(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_fwupdmgr(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(fwupdmgr) = which("fwupdmgr") { - terminal.print_separator("Firmware upgrades"); + print_separator("Firmware upgrades"); let success = || -> Result<(), failure::Error> { Executor::new(&fwupdmgr, dry_run) @@ -309,9 +304,9 @@ pub fn run_fwupdmgr(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static } #[must_use] -pub fn flatpak_user_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn flatpak_user_update(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(flatpak) = which("flatpak") { - terminal.print_separator("Flatpak User Packages"); + print_separator("Flatpak User Packages"); let success = || -> Result<(), failure::Error> { Executor::new(&flatpak, dry_run) @@ -329,14 +324,10 @@ pub fn flatpak_user_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&' } #[must_use] -pub fn flatpak_global_update( - sudo: &Option, - terminal: &mut Terminal, - dry_run: bool, -) -> Option<(&'static str, bool)> { +pub fn flatpak_global_update(sudo: &Option, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(sudo) = sudo { if let Some(flatpak) = which("flatpak") { - terminal.print_separator("Flatpak Global Packages"); + print_separator("Flatpak Global Packages"); let success = || -> Result<(), failure::Error> { Executor::new(&sudo, dry_run) @@ -355,11 +346,11 @@ pub fn flatpak_global_update( } #[must_use] -pub fn run_snap(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_snap(sudo: &Option, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(sudo) = sudo { if let Some(snap) = which("snap") { if PathBuf::from("/var/snapd.socket").exists() { - terminal.print_separator("snap"); + print_separator("snap"); let success = || -> Result<(), failure::Error> { Executor::new(&sudo, dry_run) @@ -380,10 +371,10 @@ pub fn run_snap(sudo: &Option, terminal: &mut Terminal, dry_run: bool) } #[must_use] -pub fn run_etc_update(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_etc_update(sudo: &Option, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(sudo) = sudo { if let Some(etc_update) = which("etc-update") { - terminal.print_separator("etc-update"); + print_separator("etc-update"); let success = || -> Result<(), failure::Error> { Executor::new(&sudo, dry_run) diff --git a/src/macos.rs b/src/macos.rs index f30f017b..fbffd517 100644 --- a/src/macos.rs +++ b/src/macos.rs @@ -1,11 +1,11 @@ use super::executor::Executor; -use super::terminal::Terminal; +use super::terminal::print_separator; use super::utils::Check; use failure; #[must_use] -pub fn upgrade_macos(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - terminal.print_separator("App Store"); +pub fn upgrade_macos(dry_run: bool) -> Option<(&'static str, bool)> { + print_separator("App Store"); let success = || -> Result<(), failure::Error> { Executor::new("softwareupdate", dry_run) diff --git a/src/main.rs b/src/main.rs index 86c8a85e..1c319878 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,6 @@ extern crate directories; extern crate env_logger; extern crate failure; extern crate failure_derive; -#[cfg(unix)] extern crate lazy_static; extern crate log; #[cfg(unix)] @@ -47,7 +46,6 @@ mod vim; use self::config::Config; use self::git::{Git, Repositories}; use self::report::Report; -use self::terminal::Terminal; use failure::Error; use failure_derive::Fail; use std::borrow::Cow; @@ -55,6 +53,7 @@ use std::env; use std::io::ErrorKind; use std::process::exit; use structopt::StructOpt; +use terminal::*; #[derive(Fail, Debug)] #[fail(display = "A step failed")] @@ -68,16 +67,12 @@ struct NoBaseDirectories; #[fail(display = "Process Interrupted")] pub struct Interrupted; -struct ExecutionContext { - terminal: Terminal, -} - -fn execute<'a, F, M>(func: F, execution_context: &mut ExecutionContext) -> Result, Error> +fn execute<'a, F, M>(func: F) -> Result, Error> where M: Into>, - F: Fn(&mut Terminal) -> Option<(M, bool)>, + F: Fn() -> Option<(M, bool)>, { - while let Some((key, success)) = func(&mut execution_context.terminal) { + while let Some((key, success)) = func() { if success { return Ok(Some((key, success))); } @@ -87,7 +82,7 @@ where ctrlc::set_running(true); } - let should_retry = execution_context.terminal.should_retry(running).map_err(|e| { + let should_retry = should_retry(running).map_err(|e| { if e.kind() == ErrorKind::Interrupted { Error::from(Interrupted) } else { @@ -117,10 +112,6 @@ fn run() -> Result<(), Error> { env_logger::init(); - let mut execution_context = ExecutionContext { - terminal: Terminal::new(), - }; - let base_dirs = directories::BaseDirs::new().ok_or(NoBaseDirectories)?; let git = Git::new(); let mut git_repos = Repositories::new(&git); @@ -134,17 +125,15 @@ fn run() -> Result<(), Error> { #[cfg(feature = "self-update")] { if !opt.dry_run { - if let Err(e) = self_update::self_update(&mut execution_context.terminal) { - execution_context - .terminal - .print_warning(format!("Self update error: {}", e)); + if let Err(e) = self_update::self_update() { + print_warning(format!("Self update error: {}", e)); } } } if let Some(commands) = config.pre_commands() { for (name, command) in commands { - generic::run_custom_command(&name, &command, &mut execution_context.terminal, opt.dry_run)?; + generic::run_custom_command(&name, &command, opt.dry_run)?; } } @@ -152,10 +141,7 @@ fn run() -> Result<(), Error> { let powershell = windows::Powershell::new(); #[cfg(windows)] - report.push_result(execute( - |terminal| powershell.update_modules(terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| powershell.update_modules(opt.dry_run))?); #[cfg(target_os = "linux")] let distribution = linux::Distribution::detect(); @@ -165,49 +151,28 @@ fn run() -> Result<(), Error> { if !opt.no_system { match &distribution { Ok(distribution) => { - report.push_result(execute( - |terminal| distribution.upgrade(&sudo, terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| distribution.upgrade(&sudo, opt.dry_run))?); } Err(e) => { println!("Error detecting current distribution: {}", e); } } - report.push_result(execute( - |terminal| linux::run_etc_update(&sudo, terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| linux::run_etc_update(&sudo, opt.dry_run))?); } } #[cfg(windows)] - report.push_result(execute( - |terminal| windows::run_chocolatey(terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| windows::run_chocolatey(opt.dry_run))?); #[cfg(windows)] - report.push_result(execute( - |terminal| windows::run_scoop(terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| windows::run_scoop(opt.dry_run))?); #[cfg(unix)] - report.push_result(execute( - |terminal| unix::run_homebrew(terminal, opt.cleanup, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| unix::run_homebrew(opt.cleanup, opt.dry_run))?); #[cfg(target_os = "freebsd")] - report.push_result(execute( - |terminal| freebsd::upgrade_packages(&sudo, terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| freebsd::upgrade_packages(&sudo, opt.dry_run))?); #[cfg(unix)] - report.push_result(execute( - |terminal| unix::run_nix(terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| unix::run_nix(opt.dry_run))?); if !opt.no_emacs { git_repos.insert(base_dirs.home_dir().join(".emacs.d")); @@ -240,80 +205,32 @@ fn run() -> Result<(), Error> { } } for repo in git_repos.repositories() { - report.push_result(execute( - |terminal| git.pull(&repo, terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| git.pull(&repo, opt.dry_run))?); } #[cfg(unix)] { - report.push_result(execute( - |terminal| unix::run_zplug(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| unix::run_fisher(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| tmux::run_tpm(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| unix::run_zplug(&base_dirs, opt.dry_run))?); + report.push_result(execute(|| unix::run_fisher(&base_dirs, opt.dry_run))?); + report.push_result(execute(|| tmux::run_tpm(&base_dirs, opt.dry_run))?); } - report.push_result(execute( - |terminal| generic::run_rustup(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| generic::run_cargo_update(terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| generic::run_rustup(&base_dirs, opt.dry_run))?); + report.push_result(execute(|| generic::run_cargo_update(opt.dry_run))?); if !opt.no_emacs { - report.push_result(execute( - |terminal| generic::run_emacs(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| generic::run_emacs(&base_dirs, opt.dry_run))?); } - report.push_result(execute( - |terminal| generic::run_opam_update(terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| generic::run_vcpkg_update(terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| generic::run_pipx_update(terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| generic::run_jetpack(terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| vim::upgrade_vim(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| vim::upgrade_neovim(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| node::run_npm_upgrade(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| generic::run_composer_update(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| node::yarn_global_update(terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| generic::run_opam_update(opt.dry_run))?); + report.push_result(execute(|| generic::run_vcpkg_update(opt.dry_run))?); + report.push_result(execute(|| generic::run_pipx_update(opt.dry_run))?); + report.push_result(execute(|| generic::run_jetpack(opt.dry_run))?); + report.push_result(execute(|| vim::upgrade_vim(&base_dirs, opt.dry_run))?); + report.push_result(execute(|| vim::upgrade_neovim(&base_dirs, opt.dry_run))?); + report.push_result(execute(|| node::run_npm_upgrade(&base_dirs, opt.dry_run))?); + report.push_result(execute(|| generic::run_composer_update(&base_dirs, opt.dry_run))?); + report.push_result(execute(|| node::yarn_global_update(opt.dry_run))?); #[cfg(not(any( target_os = "freebsd", @@ -321,92 +238,56 @@ fn run() -> Result<(), Error> { target_os = "netbsd", target_os = "dragonfly" )))] - report.push_result(execute( - |terminal| generic::run_apm(terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| generic::run_gem(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| generic::run_apm(opt.dry_run))?); + report.push_result(execute(|| generic::run_gem(&base_dirs, opt.dry_run))?); #[cfg(target_os = "linux")] { - report.push_result(execute( - |terminal| linux::flatpak_user_update(terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| linux::flatpak_global_update(&sudo, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| linux::run_snap(&sudo, terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| linux::flatpak_user_update(opt.dry_run))?); + report.push_result(execute(|| linux::flatpak_global_update(&sudo, opt.dry_run))?); + report.push_result(execute(|| linux::run_snap(&sudo, opt.dry_run))?); } if let Some(commands) = config.commands() { for (name, command) in commands { - report.push_result(execute( - |terminal| { - Some(( - name, - generic::run_custom_command(&name, &command, terminal, opt.dry_run).is_ok(), - )) - }, - &mut execution_context, - )?); + report.push_result(execute(|| { + Some((name, generic::run_custom_command(&name, &command, opt.dry_run).is_ok())) + })?); } } #[cfg(target_os = "linux")] { - report.push_result(execute( - |terminal| linux::run_fwupdmgr(terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| linux::run_needrestart(&sudo, terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| linux::run_fwupdmgr(opt.dry_run))?); + report.push_result(execute(|| linux::run_needrestart(&sudo, opt.dry_run))?); } #[cfg(target_os = "macos")] { if !opt.no_system { - report.push_result(execute( - |terminal| macos::upgrade_macos(terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| macos::upgrade_macos(opt.dry_run))?); } } #[cfg(target_os = "freebsd")] { if !opt.no_system { - report.push_result(execute( - |terminal| freebsd::upgrade_freebsd(&sudo, terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| freebsd::upgrade_freebsd(&sudo, opt.dry_run))?); } } #[cfg(windows)] { if !opt.no_system { - report.push_result(execute( - |terminal| powershell.windows_update(terminal, opt.dry_run), - &mut execution_context, - )?); + report.push_result(execute(|| powershell.windows_update(opt.dry_run))?); } } if !report.data().is_empty() { - execution_context.terminal.print_separator("Summary"); + print_separator("Summary"); for (key, succeeded) in report.data() { - execution_context.terminal.print_result(key, *succeeded); + print_result(key, *succeeded); } #[cfg(target_os = "linux")] diff --git a/src/node.rs b/src/node.rs index 7fe58613..b1e9910b 100644 --- a/src/node.rs +++ b/src/node.rs @@ -1,5 +1,5 @@ use super::executor::Executor; -use super::terminal::Terminal; +use super::terminal::print_separator; use super::utils::{which, Check, PathExt}; use directories::BaseDirs; use failure; @@ -35,11 +35,11 @@ impl NPM { } #[must_use] -pub fn run_npm_upgrade(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_npm_upgrade(base_dirs: &BaseDirs, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(npm) = which("npm").map(NPM::new) { if let Ok(npm_root) = npm.root() { if npm_root.is_descendant_of(base_dirs.home_dir()) { - terminal.print_separator("Node Package Manager"); + print_separator("Node Package Manager"); let success = npm.upgrade(dry_run).is_ok(); return Some(("NPM", success)); } @@ -49,9 +49,9 @@ pub fn run_npm_upgrade(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: b } #[must_use] -pub fn yarn_global_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn yarn_global_update(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(yarn) = which("yarn") { - terminal.print_separator("Yarn"); + print_separator("Yarn"); let success = || -> Result<(), failure::Error> { Executor::new(&yarn, dry_run) diff --git a/src/self_update.rs b/src/self_update.rs index db706ce8..ec9f71f5 100644 --- a/src/self_update.rs +++ b/src/self_update.rs @@ -1,4 +1,4 @@ -use super::terminal::Terminal; +use super::terminal::*; use failure::Error; use self_update_crate; #[cfg(unix)] @@ -8,8 +8,8 @@ use std::os::unix::process::CommandExt; #[cfg(unix)] use std::process::Command; -pub fn self_update(terminal: &mut Terminal) -> Result<(), Error> { - terminal.print_separator("Self update"); +pub fn self_update() -> Result<(), Error> { + print_separator("Self update"); #[cfg(unix)] let current_exe = env::current_exe(); @@ -35,7 +35,7 @@ pub fn self_update(terminal: &mut Terminal) -> Result<(), Error> { #[cfg(unix)] { if result.updated() { - terminal.print_warning("Respawning..."); + print_warning("Respawning..."); let err = Command::new(current_exe?).args(env::args().skip(1)).exec(); Err(err)? } diff --git a/src/terminal.rs b/src/terminal.rs index c5d33ef9..b3cc31cd 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -1,14 +1,20 @@ use console::{style, Term}; +use lazy_static::lazy_static; use std::cmp::{max, min}; use std::io::{self, Write}; +use std::sync::Mutex; -pub struct Terminal { +lazy_static! { + static ref TERMINAL: Mutex = Mutex::new(Terminal::new()); +} + +struct Terminal { width: Option, term: Term, } impl Terminal { - pub fn new() -> Self { + fn new() -> Self { let term = Term::stdout(); Self { width: term.size_checked().map(|(_, w)| w), @@ -16,56 +22,59 @@ impl Terminal { } } - pub fn print_separator>(&mut self, message: P) { + fn print_separator>(&mut self, message: P) { let message = message.as_ref(); match self.width { Some(width) => { - println!( - "{}", - style(format!( - "\n―― {} {:―^border$}", - message, - "", - border = max(2, min(80, width as usize) - 3 - message.len()) - )).bold() - .white() - ); + self.term + .write_fmt(format_args!( + "{}\n", + style(format_args!( + "\n―― {} {:―^border$}", + message, + "", + border = max(2, min(80, width as usize) - 3 - message.len()) + )).bold() + .white() + )).ok(); } None => { - println!("―― {} ――", message); + self.term.write_fmt(format_args!("―― {} ――\n", message)).ok(); } } } #[allow(dead_code)] - pub fn print_warning>(&mut self, message: P) { + fn print_warning>(&mut self, message: P) { let message = message.as_ref(); - println!("{}", style(message).yellow().bold()); + self.term + .write_fmt(format_args!("{}\n", style(message).yellow().bold())) + .ok(); } - pub fn print_result>(&mut self, key: P, succeeded: bool) { + fn print_result>(&mut self, key: P, succeeded: bool) { let key = key.as_ref(); - println!( - "{}: {}", - key, - if succeeded { - style("OK").bold().green() - } else { - style("FAILED").bold().red() - } - ); + self.term + .write_fmt(format_args!( + "{}: {}\n", + key, + if succeeded { + style("OK").bold().green() + } else { + style("FAILED").bold().red() + } + )).ok(); } - pub fn should_retry(&mut self, running: bool) -> Result { + fn should_retry(&mut self, running: bool) -> Result { if self.width.is_none() { return Ok(false); } - println!(); self.term .write_fmt(format_args!( - "{}", + "\n{}", style(format!( "Retry? [y/N] {}", if !running { @@ -85,7 +94,8 @@ impl Terminal { } }; - println!(); + self.term.write_str("\n").ok(); + answer } } @@ -95,3 +105,19 @@ impl Default for Terminal { Self::new() } } + +pub fn should_retry(running: bool) -> Result { + TERMINAL.lock().unwrap().should_retry(running) +} + +pub fn print_separator>(message: P) { + TERMINAL.lock().unwrap().print_separator(message) +} + +pub fn print_warning>(message: P) { + TERMINAL.lock().unwrap().print_warning(message) +} + +pub fn print_result>(key: P, succeeded: bool) { + TERMINAL.lock().unwrap().print_result(key, succeeded) +} diff --git a/src/tmux.rs b/src/tmux.rs index e1286cf1..e7b07cc7 100644 --- a/src/tmux.rs +++ b/src/tmux.rs @@ -1,5 +1,5 @@ use super::executor::Executor; -use super::terminal::Terminal; +use super::terminal::print_separator; use super::utils::which; use super::utils::{Check, PathExt}; use directories::BaseDirs; @@ -10,13 +10,13 @@ use std::os::unix::process::CommandExt; use std::path::Path; use std::process::Command; -pub fn run_tpm(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_tpm(base_dirs: &BaseDirs, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(tpm) = base_dirs .home_dir() .join(".tmux/plugins/tpm/bin/update_plugins") .if_exists() { - terminal.print_separator("tmux plugins"); + print_separator("tmux plugins"); let success = || -> Result<(), Error> { Executor::new(&tpm, dry_run).arg("all").spawn()?.wait()?.check()?; diff --git a/src/unix.rs b/src/unix.rs index e1754049..572a4a21 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -1,13 +1,13 @@ use super::executor::Executor; -use super::terminal::Terminal; +use super::terminal::print_separator; use super::utils::{which, Check}; use directories::BaseDirs; use failure::Error; -pub fn run_zplug(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_zplug(base_dirs: &BaseDirs, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(zsh) = which("zsh") { if base_dirs.home_dir().join(".zplug").exists() { - terminal.print_separator("zplug"); + print_separator("zplug"); let success = || -> Result<(), Error> { Executor::new(zsh, dry_run) @@ -25,10 +25,10 @@ pub fn run_zplug(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) - None } -pub fn run_fisher(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_fisher(base_dirs: &BaseDirs, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(fish) = which("fish") { if base_dirs.home_dir().join(".config/fish/functions/fisher.fish").exists() { - terminal.print_separator("fisher"); + print_separator("fisher"); let success = || -> Result<(), Error> { Executor::new(&fish, dry_run) @@ -52,9 +52,9 @@ pub fn run_fisher(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) } #[must_use] -pub fn run_homebrew(terminal: &mut Terminal, cleanup: bool, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_homebrew(cleanup: bool, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(brew) = which("brew") { - terminal.print_separator("Brew"); + print_separator("Brew"); let inner = || -> Result<(), Error> { Executor::new(&brew, dry_run).arg("update").spawn()?.wait()?.check()?; @@ -72,10 +72,10 @@ pub fn run_homebrew(terminal: &mut Terminal, cleanup: bool, dry_run: bool) -> Op } #[must_use] -pub fn run_nix(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_nix(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(nix) = which("nix") { if let Some(nix_env) = which("nix-env") { - terminal.print_separator("Nix"); + print_separator("Nix"); let inner = || -> Result<(), Error> { Executor::new(&nix, dry_run) diff --git a/src/vim.rs b/src/vim.rs index 500f9f86..4e63c811 100644 --- a/src/vim.rs +++ b/src/vim.rs @@ -1,5 +1,5 @@ use super::executor::Executor; -use super::terminal::Terminal; +use super::terminal::print_separator; use super::utils::{which, Check, PathExt}; use directories::BaseDirs; use failure; @@ -82,11 +82,11 @@ fn upgrade( } #[must_use] -pub fn upgrade_vim(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn upgrade_vim(base_dirs: &BaseDirs, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(vim) = which("vim") { if let Some(vimrc) = vimrc(&base_dirs) { if let Some(plugin_framework) = PluginFramework::detect(&vimrc) { - terminal.print_separator(&format!("Vim ({:?})", plugin_framework)); + print_separator(&format!("Vim ({:?})", plugin_framework)); let success = upgrade(&vim, &vimrc, plugin_framework, dry_run).is_ok(); return Some(("vim", success)); } @@ -97,11 +97,11 @@ pub fn upgrade_vim(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) } #[must_use] -pub fn upgrade_neovim(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn upgrade_neovim(base_dirs: &BaseDirs, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(nvim) = which("nvim") { if let Some(nvimrc) = nvimrc(&base_dirs) { if let Some(plugin_framework) = PluginFramework::detect(&nvimrc) { - terminal.print_separator(&format!("Neovim ({:?})", plugin_framework)); + print_separator(&format!("Neovim ({:?})", plugin_framework)); let success = upgrade(&nvim, &nvimrc, plugin_framework, dry_run).is_ok(); return Some(("Neovim", success)); } diff --git a/src/windows.rs b/src/windows.rs index d1d2bbbc..c5338fb3 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -1,5 +1,5 @@ use super::executor::Executor; -use super::terminal::Terminal; +use super::terminal::print_separator; use super::utils::{self, which, Check}; use failure; use log::error; @@ -7,9 +7,9 @@ use std::path::PathBuf; use std::process::Command; #[must_use] -pub fn run_chocolatey(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_chocolatey(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(choco) = utils::which("choco") { - terminal.print_separator("Chocolatey"); + print_separator("Chocolatey"); let success = || -> Result<(), failure::Error> { Executor::new(&choco, dry_run) @@ -27,9 +27,9 @@ pub fn run_chocolatey(terminal: &mut Terminal, dry_run: bool) -> Option<(&'stati } #[must_use] -pub fn run_scoop(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { +pub fn run_scoop(dry_run: bool) -> Option<(&'static str, bool)> { if let Some(scoop) = utils::which("scoop") { - terminal.print_separator("Scoop"); + print_separator("Scoop"); let success = || -> Result<(), failure::Error> { Executor::new(&scoop, dry_run) @@ -91,9 +91,9 @@ impl Powershell { } #[must_use] - pub fn update_modules(&self, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { + pub fn update_modules(&self, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(powershell) = &self.path { - terminal.print_separator("Powershell Modules Update"); + print_separator("Powershell Modules Update"); let success = || -> Result<(), failure::Error> { Executor::new(&powershell, dry_run) @@ -111,10 +111,10 @@ impl Powershell { } #[must_use] - pub fn windows_update(&self, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { + pub fn windows_update(&self, dry_run: bool) -> Option<(&'static str, bool)> { if let Some(powershell) = &self.path { if Self::has_command(&powershell, "Install-WindowsUpdate") { - terminal.print_separator("Windows Update"); + print_separator("Windows Update"); let success = || -> Result<(), failure::Error> { Executor::new(&powershell, dry_run)