diff --git a/src/generic.rs b/src/generic.rs new file mode 100644 index 00000000..7c7a424c --- /dev/null +++ b/src/generic.rs @@ -0,0 +1,104 @@ +use super::terminal::Terminal; +use super::utils; +use super::utils::{Check, PathExt}; +use directories::BaseDirs; +use failure::Error; +use std::process::Command; + +const EMACS_UPGRADE: &str = include_str!("emacs.el"); + +#[must_use] +pub fn run_cargo_update(base_dirs: &BaseDirs, terminal: &mut Terminal) -> Option<(&'static str, bool)> { + if let Some(cargo_update) = base_dirs.home_dir().join(".cargo/bin/cargo-install-update").if_exists() { + terminal.print_separator("Cargo"); + + let success = || -> Result<(), Error> { + Command::new(cargo_update) + .args(&["install-update", "--git", "--all"]) + .spawn()? + .wait()? + .check()?; + + Ok(()) + }().is_ok(); + + return Some(("Cargo", success)); + } + + None +} + +#[must_use] +pub fn run_emacs(base_dirs: &BaseDirs, terminal: &mut Terminal) -> 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"); + + let success = || -> Result<(), Error> { + Command::new(&emacs) + .args(&["--batch", "-l", init_file.to_str().unwrap(), "--eval", EMACS_UPGRADE]) + .spawn()? + .wait()? + .check()?; + + Ok(()) + }().is_ok(); + + return Some(("Emacs", success)); + } + } + None +} + +#[must_use] +pub fn run_apm(terminal: &mut Terminal) -> Option<(&'static str, bool)> { + if let Some(apm) = utils::which("apm") { + terminal.print_separator("Atom Package Manager"); + + let success = || -> Result<(), Error> { + Command::new(&apm) + .args(&["upgrade", "--confirm=false"]) + .spawn()? + .wait()? + .check()?; + + Ok(()) + }().is_ok(); + + return Some(("apm", success)); + } + + None +} + +#[must_use] +pub fn run_rustup(base_dirs: &BaseDirs, terminal: &mut Terminal) -> Option<(&'static str, bool)> { + if let Some(rustup) = utils::which("rustup") { + terminal.print_separator("rustup"); + + let success = || -> Result<(), Error> { + if rustup.is_descendant_of(base_dirs.home_dir()) { + Command::new(&rustup) + .args(&["self", "update"]) + .spawn()? + .wait()? + .check()?; + } + + Command::new(&rustup).arg("update").spawn()?.wait()?.check()?; + Ok(()) + }().is_ok(); + + return Some(("rustup", success)); + } + + None +} + +#[must_use] +pub fn run_custom_command(name: &str, command: &str, terminal: &mut Terminal) -> Result<(), Error> { + terminal.print_separator(name); + Command::new("sh").arg("-c").arg(command).spawn()?.wait()?.check()?; + + Ok(()) +} diff --git a/src/git.rs b/src/git.rs index b1ba21e5..e222e440 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,3 +1,4 @@ +use super::terminal::Terminal; use super::utils::{which, Check}; use failure::Error; use std::collections::HashSet; @@ -56,9 +57,15 @@ impl Git { None } - pub fn pull>(&self, path: P) -> Result, Error> { - if let Some(git) = &self.git { - Command::new(&git) + pub fn pull>(&self, path: P, terminal: &mut Terminal) -> Option<(String, bool)> { + let path = path.as_ref(); + + terminal.print_separator(format!("Pulling {}", path.display())); + + let git = self.git.as_ref().unwrap(); + + let success = || -> Result<(), Error> { + Command::new(git) .arg("pull") .arg("--rebase") .arg("--autostash") @@ -67,7 +74,7 @@ impl Git { .wait()? .check()?; - Command::new(&git) + Command::new(git) .arg("submodule") .arg("update") .arg("--init") @@ -77,10 +84,10 @@ impl Git { .wait()? .check()?; - return Ok(Some(())); - } + Ok(()) + }().is_ok(); - Ok(None) + Some((format!("git: {}", path.display()), success)) } } diff --git a/src/linux.rs b/src/linux.rs index b1c504d4..6f49dbda 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -50,7 +50,7 @@ impl Distribution { } } -pub fn upgrade_arch_linux(sudo: &Option, terminal: &mut Terminal) -> Result<(), failure::Error> { +fn upgrade_arch_linux(sudo: &Option, terminal: &mut Terminal) -> Result<(), failure::Error> { if let Some(yay) = which("yay") { if let Some(python) = which("python") { if python != PathBuf::from("/usr/bin/python") { @@ -77,7 +77,7 @@ It's dangerous to run yay since Python based AUR packages will be installed in t Ok(()) } -pub fn upgrade_redhat(sudo: &Option, terminal: &mut Terminal) -> Result<(), failure::Error> { +fn upgrade_redhat(sudo: &Option, terminal: &mut Terminal) -> Result<(), failure::Error> { if let Some(sudo) = &sudo { Command::new(&sudo) .args(&["/usr/bin/yum", "upgrade"]) @@ -91,7 +91,7 @@ pub fn upgrade_redhat(sudo: &Option, terminal: &mut Terminal) -> Result Ok(()) } -pub fn upgrade_fedora(sudo: &Option, terminal: &mut Terminal) -> Result<(), failure::Error> { +fn upgrade_fedora(sudo: &Option, terminal: &mut Terminal) -> Result<(), failure::Error> { if let Some(sudo) = &sudo { Command::new(&sudo) .args(&["/usr/bin/dnf", "upgrade"]) @@ -105,7 +105,7 @@ pub fn upgrade_fedora(sudo: &Option, terminal: &mut Terminal) -> Result Ok(()) } -pub fn upgrade_debian(sudo: &Option, terminal: &mut Terminal) -> Result<(), failure::Error> { +fn upgrade_debian(sudo: &Option, terminal: &mut Terminal) -> Result<(), failure::Error> { if let Some(sudo) = &sudo { Command::new(&sudo) .args(&["/usr/bin/apt", "update"]) @@ -125,32 +125,97 @@ pub fn upgrade_debian(sudo: &Option, terminal: &mut Terminal) -> Result Ok(()) } -pub fn run_needrestart(sudo: &PathBuf, needrestart: &PathBuf) -> Result<(), failure::Error> { - Command::new(&sudo).arg(needrestart).spawn()?.wait()?.check()?; +#[must_use] +pub fn upgrade(sudo: &Option, terminal: &mut Terminal) -> Option<(&'static str, bool)> { + terminal.print_separator("System update"); - Ok(()) + let success = match Distribution::detect() { + Ok(distribution) => match distribution { + Distribution::Arch => upgrade_arch_linux(&sudo, terminal), + Distribution::CentOS => upgrade_redhat(&sudo, terminal), + Distribution::Fedora => upgrade_fedora(&sudo, terminal), + Distribution::Ubuntu | Distribution::Debian => upgrade_debian(&sudo, terminal), + }.is_ok(), + Err(e) => { + println!("Error detecting current distribution: {}", e); + false + } + }; + + Some(("System update", success)) } -pub fn run_fwupdmgr(fwupdmgr: &PathBuf) -> Result<(), failure::Error> { - Command::new(&fwupdmgr).arg("refresh").spawn()?.wait()?.check()?; +#[must_use] +pub fn run_needrestart(sudo: &Option, terminal: &mut Terminal) -> Option<(&'static str, bool)> { + if let Some(sudo) = sudo { + if let Some(needrestart) = which("needrestart") { + terminal.print_separator("Check for needed restarts"); - Command::new(&fwupdmgr).arg("get-updates").spawn()?.wait()?.check()?; + let success = || -> Result<(), failure::Error> { + Command::new(&sudo).arg(needrestart).spawn()?.wait()?.check()?; - Ok(()) + Ok(()) + }().is_ok(); + + return Some(("Restarts", success)); + } + } + + None } -pub fn run_flatpak(flatpak: &PathBuf) -> Result<(), failure::Error> { - Command::new(&flatpak).args(&["update", "-y"]).spawn()?.wait()?.check()?; +#[must_use] +pub fn run_fwupdmgr(terminal: &mut Terminal) -> Option<(&'static str, bool)> { + if let Some(fwupdmgr) = which("fwupdmgr") { + terminal.print_separator("Firmware upgrades"); - Ok(()) + let success = || -> Result<(), failure::Error> { + Command::new(&fwupdmgr).arg("refresh").spawn()?.wait()?.check()?; + Command::new(&fwupdmgr).arg("get-updates").spawn()?.wait()?.check()?; + Ok(()) + }().is_ok(); + + return Some(("Firmware upgrade", success)); + } + + None } -pub fn run_snap(sudo: &PathBuf, snap: &PathBuf) -> Result<(), failure::Error> { - Command::new(&sudo) - .args(&[snap.to_str().unwrap(), "refresh"]) - .spawn()? - .wait()? - .check()?; +#[must_use] +pub fn run_flatpak(terminal: &mut Terminal) -> Option<(&'static str, bool)> { + if let Some(flatpak) = which("flatpak") { + terminal.print_separator("Flatpak"); - Ok(()) + let success = || -> Result<(), failure::Error> { + Command::new(&flatpak).args(&["update", "-y"]).spawn()?.wait()?.check()?; + Ok(()) + }().is_ok(); + + return Some(("Flatpak", success)); + } + + None +} + +#[must_use] +pub fn run_snap(sudo: &Option, terminal: &mut Terminal) -> Option<(&'static str, bool)> { + if let Some(sudo) = sudo { + if let Some(snap) = which("snap") { + terminal.print_separator("snap"); + + let success = || -> Result<(), failure::Error> { + Command::new(&sudo) + .args(&[snap.to_str().unwrap(), "refresh"]) + .spawn()? + .wait()? + .check()?; + + Ok(()) + }().is_ok(); + + return Some(("snap", success)); + } + } + + None } diff --git a/src/macos.rs b/src/macos.rs index 87bda353..464cc913 100644 --- a/src/macos.rs +++ b/src/macos.rs @@ -1,8 +1,12 @@ +use super::terminal::Terminal; use super::utils::Check; use failure; use std::process::Command; -pub fn upgrade_macos() -> Result<(), failure::Error> { +#[must_use] +pub fn upgrade_macos(terminal: &mut Terminal) -> Result<(), failure::Error> { + terminal.print_separator("App Store"); + Command::new("softwareupdate") .args(&["--install", "--all"]) .spawn()? diff --git a/src/main.rs b/src/main.rs index e866b586..2ed4ffc3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,20 +26,18 @@ mod unix; mod windows; mod config; +mod generic; mod git; -mod npm; +mod node; mod report; -mod steps; mod terminal; mod utils; mod vim; use self::config::Config; use self::git::{Git, Repositories}; -use self::report::{Report, Reporter}; -use self::steps::*; +use self::report::{report, Report}; use self::terminal::Terminal; -use self::utils::PathExt; use clap::{App, Arg}; use failure::Error; use std::env; @@ -53,7 +51,6 @@ struct StepFailed; #[fail(display = "Cannot find the user base directories")] struct NoBaseDirectories; -#[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))] fn run() -> Result<(), Error> { let matches = App::new("Topgrade") .version(crate_version!()) @@ -91,47 +88,21 @@ fn run() -> Result<(), Error> { if let Some(commands) = config.pre_commands() { for (name, command) in commands { - terminal.print_separator(name); - run_custom_command(&command)?; + generic::run_custom_command(&name, &command, &mut terminal)?; } } if !(matches.is_present("no_system")) { #[cfg(target_os = "linux")] - { - terminal.print_separator("System update"); - match linux::Distribution::detect() { - Ok(distribution) => { - match distribution { - linux::Distribution::Arch => linux::upgrade_arch_linux(&sudo, &mut terminal), - linux::Distribution::CentOS => linux::upgrade_redhat(&sudo, &mut terminal), - linux::Distribution::Fedora => linux::upgrade_fedora(&sudo, &mut terminal), - linux::Distribution::Ubuntu | linux::Distribution::Debian => { - linux::upgrade_debian(&sudo, &mut terminal) - } - }.report("System upgrade", &mut reports); - } - - Err(e) => { - println!("Error detecting current distribution: {}", e); - } - } - } - - if let Some(brew) = utils::which("brew") { - terminal.print_separator("Brew"); - run_homebrew(&brew).report("Brew", &mut reports); - } + report(&mut reports, linux::upgrade(&sudo, &mut terminal)); #[cfg(windows)] - { - if let Some(choco) = utils::which("choco") { - terminal.print_separator("Chocolatey"); - windows::run_chocolatey(&choco).report("Chocolatey", &mut reports); - } - } + report(&mut reports, windows::run_chocolatey(&mut terminal)); } + #[cfg(unix)] + report(&mut reports, unix::run_homebrew(&mut terminal)); + git_repos.insert(base_dirs.home_dir().join(".emacs.d")); git_repos.insert(base_dirs.home_dir().join(".vim")); git_repos.insert(base_dirs.home_dir().join(".config/nvim")); @@ -151,128 +122,53 @@ fn run() -> Result<(), Error> { } for repo in git_repos.repositories() { - terminal.print_separator(format!("Pulling {}", repo)); - git.pull(&repo).report(format!("git: {}", repo), &mut reports); + report(&mut reports, git.pull(&repo, &mut terminal)); } #[cfg(unix)] { - if let Some(zsh) = utils::which("zsh") { - if base_dirs.home_dir().join(".zplug").exists() { - terminal.print_separator("zplug"); - unix::run_zplug(&zsh).report("zplug", &mut reports); - } - } - - if let Some(fish) = utils::which("fish") { - if base_dirs.home_dir().join(".config/fish/functions/fisher.fish").exists() { - terminal.print_separator("fisherman"); - unix::run_fisherman(&fish).report("fisherman", &mut reports); - } - } - - if let Some(tpm) = unix::tpm_path(&base_dirs) { - terminal.print_separator("tmux plugins"); - unix::run_tpm(&tpm).report("tmux", &mut reports); - } + report(&mut reports, unix::run_zplug(&base_dirs, &mut terminal)); + report(&mut reports, unix::run_fisherman(&base_dirs, &mut terminal)); + report(&mut reports, unix::run_tpm(&base_dirs, &mut terminal)); } - if let Some(rustup) = utils::which("rustup") { - terminal.print_separator("rustup"); - run_rustup(&rustup, &base_dirs).report("rustup", &mut reports); - } - - if let Some(cargo_upgrade) = base_dirs.home_dir().join(".cargo/bin/cargo-install-update").if_exists() { - terminal.print_separator("Cargo"); - run_cargo_update(&cargo_upgrade).report("Cargo", &mut reports); - } - - 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"); - run_emacs(&emacs, &init_file).report("Emacs", &mut reports); - } - } - - if let Some(vim) = utils::which("vim") { - if let Some(vimrc) = vim::vimrc(&base_dirs) { - if let Some(plugin_framework) = vim::PluginFramework::detect(&vimrc) { - terminal.print_separator(&format!("Vim ({:?})", plugin_framework)); - vim::upgrade(&vim, &vimrc, &plugin_framework).report("Vim", &mut reports); - } - } - } - - if let Some(nvim) = utils::which("nvim") { - if let Some(nvimrc) = vim::nvimrc(&base_dirs) { - if let Some(plugin_framework) = vim::PluginFramework::detect(&nvimrc) { - terminal.print_separator(&format!("Neovim ({:?})", plugin_framework)); - vim::upgrade(&nvim, &nvimrc, &plugin_framework).report("Neovim", &mut reports); - } - } - } - - if let Some(npm) = utils::which("npm").map(npm::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"); - npm.upgrade().report("Node Package Manager", &mut reports); - } - } - } - - if let Some(yarn) = utils::which("yarn") { - terminal.print_separator("Yarn"); - yarn_global_update(&yarn).report("Yarn", &mut reports); - } - - if let Some(apm) = utils::which("apm") { - terminal.print_separator("Atom Package Manager"); - run_apm(&apm).report("Atom Package Manager", &mut reports); - } + report(&mut reports, generic::run_rustup(&base_dirs, &mut terminal)); + report(&mut reports, generic::run_cargo_update(&base_dirs, &mut terminal)); + report(&mut reports, generic::run_emacs(&base_dirs, &mut terminal)); + report(&mut reports, vim::upgrade_vim(&base_dirs, &mut terminal)); + report(&mut reports, vim::upgrade_neovim(&base_dirs, &mut terminal)); + report(&mut reports, node::run_npm_upgrade(&base_dirs, &mut terminal)); + report(&mut reports, node::yarn_global_update(&mut terminal)); + report(&mut reports, generic::run_apm(&mut terminal)); #[cfg(target_os = "linux")] { - if let Some(flatpak) = utils::which("flatpak") { - terminal.print_separator("Flatpak"); - linux::run_flatpak(&flatpak).report("Flatpak", &mut reports); - } - - if let Some(sudo) = &sudo { - if let Some(snap) = utils::which("snap") { - terminal.print_separator("snap"); - linux::run_snap(&sudo, &snap).report("snap", &mut reports); - } - } + report(&mut reports, linux::run_flatpak(&mut terminal)); + report(&mut reports, linux::run_snap(&sudo, &mut terminal)); } if let Some(commands) = config.commands() { for (name, command) in commands { - terminal.print_separator(name); - run_custom_command(&command).report(name.as_str(), &mut reports); + report( + &mut reports, + Some(( + name, + generic::run_custom_command(&name, &command, &mut terminal).is_ok(), + )), + ); } } #[cfg(target_os = "linux")] { - if let Some(fwupdmgr) = utils::which("fwupdmgr") { - terminal.print_separator("Firmware upgrades"); - linux::run_fwupdmgr(&fwupdmgr).report("Firmware upgrade", &mut reports); - } - - if let Some(sudo) = &sudo { - if let Some(needrestart) = utils::which("needrestart") { - terminal.print_separator("Check for needed restarts"); - linux::run_needrestart(&sudo, &needrestart).report("Restarts", &mut reports); - } - } + report(&mut reports, linux::run_fwupdmgr(&mut terminal)); + report(&mut reports, linux::run_needrestart(&sudo, &mut terminal)); } #[cfg(target_os = "macos")] { if !(matches.is_present("no_system")) { - terminal.print_separator("App Store"); - macos::upgrade_macos().report("App Store", &mut reports); + macos::upgrade_macos(&mut terminal).report("App Store", &mut reports); } } diff --git a/src/node.rs b/src/node.rs new file mode 100644 index 00000000..634884ac --- /dev/null +++ b/src/node.rs @@ -0,0 +1,68 @@ +use super::terminal::Terminal; +use super::utils::{which, Check, PathExt}; +use directories::BaseDirs; +use failure; +use std::path::PathBuf; +use std::process::Command; + +struct NPM { + command: PathBuf, +} + +impl NPM { + fn new(command: PathBuf) -> Self { + Self { command } + } + + fn root(&self) -> Result { + let output = Command::new(&self.command).args(&["root", "-g"]).output()?; + + output.status.check()?; + + Ok(PathBuf::from(&String::from_utf8(output.stdout)?)) + } + + fn upgrade(&self) -> Result<(), failure::Error> { + Command::new(&self.command) + .args(&["update", "-g"]) + .spawn()? + .wait()? + .check()?; + + Ok(()) + } +} + +#[must_use] +pub fn run_npm_upgrade(base_dirs: &BaseDirs, terminal: &mut Terminal) -> 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"); + let success = npm.upgrade().is_ok(); + return Some(("NPM", success)); + } + } + } + None +} + +#[must_use] +pub fn yarn_global_update(terminal: &mut Terminal) -> Option<(&'static str, bool)> { + if let Some(yarn) = which("yarn") { + terminal.print_separator("Yarn"); + + let success = || -> Result<(), failure::Error> { + Command::new(&yarn) + .args(&["global", "upgrade", "-s"]) + .spawn()? + .wait()? + .check()?; + Ok(()) + }().is_ok(); + + return Some(("yarn", success)); + } + + None +} diff --git a/src/npm.rs b/src/npm.rs deleted file mode 100644 index 2f775f33..00000000 --- a/src/npm.rs +++ /dev/null @@ -1,32 +0,0 @@ -use super::utils::Check; -use failure; -use std::path::PathBuf; -use std::process::Command; - -pub struct NPM { - command: PathBuf, -} - -impl NPM { - pub fn new(command: PathBuf) -> Self { - Self { command } - } - - pub fn root(&self) -> Result { - let output = Command::new(&self.command).args(&["root", "-g"]).output()?; - - output.status.check()?; - - Ok(PathBuf::from(&String::from_utf8(output.stdout)?)) - } - - pub fn upgrade(&self) -> Result<(), failure::Error> { - Command::new(&self.command) - .args(&["update", "-g"]) - .spawn()? - .wait()? - .check()?; - - Ok(()) - } -} diff --git a/src/report.rs b/src/report.rs index fda8d8b3..de6921b3 100644 --- a/src/report.rs +++ b/src/report.rs @@ -3,45 +3,11 @@ use std::borrow::Cow; type CowString<'a> = Cow<'a, str>; pub type Report<'a> = Vec<(CowString<'a>, bool)>; -pub trait Reporter { - fn report<'a, M: Into>>(&self, key: M, report: &mut Report<'a>); -} +pub fn report<'a, M: Into>>(report: &mut Report<'a>, result: Option<(M, bool)>) { + if let Some((key, success)) = result { + let key = key.into(); -impl Reporter for Result -where - T: Reporter, -{ - fn report<'a, M: Into>>(&self, key: M, report: &mut Report<'a>) { - match self { - Err(_) => { - report.push((key.into(), false)); - } - Ok(item) => { - item.report(key, report); - } - } - } -} - -impl Reporter for Option -where - T: Reporter, -{ - fn report<'a, M: Into>>(&self, key: M, report: &mut Report<'a>) { - if let Some(item) = self { - item.report(key, report); - } - } -} - -impl Reporter for bool { - fn report<'a, M: Into>>(&self, key: M, report: &mut Report<'a>) { - report.push((key.into(), *self)); - } -} - -impl Reporter for () { - fn report<'a, M: Into>>(&self, key: M, report: &mut Report<'a>) { - report.push((key.into(), true)); + debug_assert!(!report.iter().any(|(k, _)| k == &key), "{} already reported", key); + report.push((key, success)); } } diff --git a/src/steps.rs b/src/steps.rs deleted file mode 100644 index a6c2528b..00000000 --- a/src/steps.rs +++ /dev/null @@ -1,71 +0,0 @@ -use super::utils::{Check, PathExt}; -use directories::BaseDirs; -use failure; -use std::path::PathBuf; -use std::process::Command; - -const EMACS_UPGRADE: &str = include_str!("emacs.el"); - -pub fn run_cargo_update(cargo_update: &PathBuf) -> Result<(), failure::Error> { - Command::new(&cargo_update) - .args(&["install-update", "--git", "--all"]) - .spawn()? - .wait()? - .check()?; - - Ok(()) -} - -pub fn run_emacs(emacs: &PathBuf, init: &PathBuf) -> Result<(), failure::Error> { - Command::new(&emacs) - .args(&["--batch", "-l", init.to_str().unwrap(), "--eval", EMACS_UPGRADE]) - .spawn()? - .wait()? - .check()?; - - Ok(()) -} - -pub fn yarn_global_update(yarn: &PathBuf) -> Result<(), failure::Error> { - Command::new(&yarn) - .args(&["global", "upgrade", "-s"]) - .spawn()? - .wait()? - .check()?; - - Ok(()) -} - -pub fn run_apm(apm: &PathBuf) -> Result<(), failure::Error> { - Command::new(&apm) - .args(&["upgrade", "--confirm=false"]) - .spawn()? - .wait()? - .check()?; - - Ok(()) -} - -pub fn run_rustup(rustup: &PathBuf, base_dirs: &BaseDirs) -> Result<(), failure::Error> { - if rustup.is_descendant_of(base_dirs.home_dir()) { - Command::new(rustup).args(&["self", "update"]).spawn()?.wait()?.check()?; - } - - Command::new(rustup).arg("update").spawn()?.wait()?.check()?; - - Ok(()) -} - -pub fn run_homebrew(homebrew: &PathBuf) -> Result<(), failure::Error> { - Command::new(&homebrew).arg("update").spawn()?.wait()?.check()?; - - Command::new(&homebrew).arg("upgrade").spawn()?.wait()?.check()?; - - Ok(()) -} - -pub fn run_custom_command(command: &str) -> Result<(), failure::Error> { - Command::new("sh").arg("-c").arg(command).spawn()?.wait()?.check()?; - - Ok(()) -} diff --git a/src/unix.rs b/src/unix.rs index 963748ec..5423803d 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -1,42 +1,70 @@ +use super::terminal::Terminal; use super::utils::{which, Check, PathExt}; use directories::BaseDirs; -use failure; +use failure::Error; use std::env; use std::os::unix::process::CommandExt; -use std::path::PathBuf; use std::process::Command; -pub fn run_zplug(zsh: &PathBuf) -> Result<(), failure::Error> { - Command::new(zsh) - .args(&["-c", "source ~/.zshrc && zplug update"]) - .spawn()? - .wait()? - .check()?; +pub fn run_zplug(base_dirs: &BaseDirs, terminal: &mut Terminal) -> Option<(&'static str, bool)> { + if let Some(zsh) = which("zsh") { + if base_dirs.home_dir().join(".zplug").exists() { + terminal.print_separator("zplug"); - Ok(()) + let success = || -> Result<(), Error> { + Command::new(zsh) + .args(&["-c", "source ~/.zshrc && zplug update"]) + .spawn()? + .wait()? + .check()?; + Ok(()) + }().is_ok(); + + return Some(("zplug", success)); + } + } + + None } -pub fn run_fisherman(fish: &PathBuf) -> Result<(), failure::Error> { - Command::new(fish) - .args(&["-c", "fisher update"]) - .spawn()? - .wait()? - .check()?; +pub fn run_fisherman(base_dirs: &BaseDirs, terminal: &mut Terminal) -> Option<(&'static str, bool)> { + if let Some(fish) = which("fisherman") { + if base_dirs.home_dir().join(".config/fish/functions/fisher.fish").exists() { + terminal.print_separator("fisherman"); - Ok(()) + let success = || -> Result<(), Error> { + Command::new(fish) + .args(&["-c", "fisher update"]) + .spawn()? + .wait()? + .check()?; + Ok(()) + }().is_ok(); + + return Some(("fisherman", success)); + } + } + + None } -pub fn run_tpm(tpm: &PathBuf) -> Result<(), failure::Error> { - Command::new(&tpm).arg("all").spawn()?.wait()?.check()?; - - Ok(()) -} - -pub fn tpm_path(base_dirs: &BaseDirs) -> Option { - base_dirs +pub fn run_tpm(base_dirs: &BaseDirs, terminal: &mut Terminal) -> 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"); + + let success = || -> Result<(), Error> { + Command::new(&tpm).arg("all").spawn()?.wait()?.check()?; + Ok(()) + }().is_ok(); + + return Some(("tmux", success)); + } + + None } pub fn run_in_tmux() -> ! { @@ -57,3 +85,20 @@ pub fn run_in_tmux() -> ! { .exec(); panic!("{:?}", err); } + +#[must_use] +pub fn run_homebrew(terminal: &mut Terminal) -> Option<(&'static str, bool)> { + if let Some(brew) = which("brew") { + terminal.print_separator("Brew"); + + let inner = || -> Result<(), Error> { + Command::new(&brew).arg("update").spawn()?.wait()?.check()?; + Command::new(&brew).arg("upgrade").spawn()?.wait()?.check()?; + Ok(()) + }; + + return Some(("Brew", inner().is_ok())); + } + + None +} diff --git a/src/vim.rs b/src/vim.rs index b74cdb81..e0abb1b0 100644 --- a/src/vim.rs +++ b/src/vim.rs @@ -1,4 +1,5 @@ -use super::utils::{Check, PathExt}; +use super::terminal::Terminal; +use super::utils::{which, Check, PathExt}; use directories::BaseDirs; use failure; use std::fs; @@ -44,7 +45,7 @@ pub fn vimrc(base_dirs: &BaseDirs) -> Option { .or_else(|| base_dirs.home_dir().join(".vim/vimrc").if_exists()) } -pub fn nvimrc(base_dirs: &BaseDirs) -> Option { +fn nvimrc(base_dirs: &BaseDirs) -> Option { #[cfg(unix)] return base_dirs.config_dir().join("nvim/init.vim").if_exists(); @@ -52,7 +53,8 @@ pub fn nvimrc(base_dirs: &BaseDirs) -> Option { return base_dirs.cache_dir().join("nvim/init.vim").if_exists(); } -pub fn upgrade(vim: &PathBuf, vimrc: &PathBuf, plugin_framework: &PluginFramework) -> Result<(), failure::Error> { +#[must_use] +fn upgrade(vim: &PathBuf, vimrc: &PathBuf, plugin_framework: PluginFramework) -> Result<(), failure::Error> { Command::new(&vim) .args(&[ "-N", @@ -74,3 +76,33 @@ pub fn upgrade(vim: &PathBuf, vimrc: &PathBuf, plugin_framework: &PluginFramewor Ok(()) } + +#[must_use] +pub fn upgrade_vim(base_dirs: &BaseDirs, terminal: &mut Terminal) -> 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)); + let success = upgrade(&vim, &vimrc, plugin_framework).is_ok(); + return Some(("vim", success)); + } + } + } + + None +} + +#[must_use] +pub fn upgrade_neovim(base_dirs: &BaseDirs, terminal: &mut Terminal) -> 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)); + let success = upgrade(&nvim, &nvimrc, plugin_framework).is_ok(); + return Some(("Neovim", success)); + } + } + } + + None +} diff --git a/src/windows.rs b/src/windows.rs index e3b371c1..ca966696 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -1,10 +1,20 @@ -use super::utils::Check; +use super::terminal::Terminal; +use super::utils::{self, Check}; use failure; -use std::path::PathBuf; use std::process::Command; -pub fn run_chocolatey(choco: &PathBuf) -> Result<(), failure::Error> { - Command::new(&choco).args(&["upgrade", "all"]).spawn()?.wait()?.check()?; +#[must_use] +pub fn run_chocolatey(terminal: &mut Terminal) -> Option<(&'static str, bool)> { + if let Some(choco) = utils::which("choco") { + terminal.print_separator("Chocolatey"); - Ok(()) + let success = || -> Result<(), failure::Error> { + Command::new(&choco).args(&["upgrade", "all"]).spawn()?.wait()?.check()?; + Ok(()) + }().is_ok(); + + return Some(("Chocolatey", success)); + } + + None }