diff --git a/src/emacs.el b/src/emacs.el new file mode 100644 index 00000000..a507af43 --- /dev/null +++ b/src/emacs.el @@ -0,0 +1,7 @@ +(progn + (let ((package-menu-async nil)) + (package-list-packages)) + (package-menu-mark-upgrades) + (condition-case nil + (package-menu-execute 'noquery) + (user-error nil))) \ No newline at end of file diff --git a/src/git.rs b/src/git.rs index af26f32b..99d9c72b 100644 --- a/src/git.rs +++ b/src/git.rs @@ -38,7 +38,7 @@ impl Git { None } - pub fn pull>(&self, path: P) -> Result<(), Error> { + pub fn pull>(&self, path: P) -> Result, Error> { if let Some(git) = &self.git { if let Ok(mut command) = Command::new(&git) .arg("pull") @@ -47,10 +47,10 @@ impl Git { .current_dir(path) .spawn() { - command.wait()?; + return Ok(Some(command.wait()?.success())); } } - Ok(()) + Ok(None) } } diff --git a/src/main.rs b/src/main.rs index e5ef14ce..910da3b8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,11 +6,13 @@ extern crate failure_derive; extern crate termion; mod git; +mod report; mod terminal; use failure::Error; use git::Git; use os_type::OSType; +use report::{Report, Reporter}; use std::collections::HashSet; use std::env::home_dir; use std::path::PathBuf; @@ -36,10 +38,7 @@ impl Check for ExitStatus { } } -const EMACS_UPGRADE: &str = "(progn (let ((package-menu-async nil)) - (package-list-packages)) - (package-menu-mark-upgrades) - (package-menu-execute 'noquery))"; +const EMACS_UPGRADE: &str = include_str!("emacs.el"); fn home_path(p: &str) -> PathBuf { let mut path = home_dir().unwrap(); @@ -62,6 +61,7 @@ fn main() -> Result<(), Error> { let git = Git::new(); let mut git_repos: HashSet = HashSet::new(); let terminal = Terminal::new(); + let mut reports = Report::new(); { let mut collect_repo = |path| { @@ -81,7 +81,9 @@ fn main() -> Result<(), Error> { for repo in git_repos { terminal.print_separator(format!("Pulling {}", repo)); - git.pull(repo)?; + if let Some(success) = git.pull(&repo)? { + success.report(format!("git: {}", repo), &mut reports); + } } if cfg!(unix) { @@ -91,13 +93,18 @@ fn main() -> Result<(), Error> { Command::new(&zsh) .args(&["-c", "source ~/.zshrc && zplug update"]) .spawn()? - .wait()?; + .wait()? + .report("zplug", &mut reports); } } if let Some(tpm) = tpm() { terminal.print_separator("tmux plugins"); - Command::new(&tpm).arg("all").spawn()?.wait()?; + Command::new(&tpm) + .arg("all") + .spawn()? + .wait()? + .report("tmux", &mut reports); } } @@ -107,7 +114,8 @@ fn main() -> Result<(), Error> { Command::new(&cargo_upgrade) .args(&["install-update", "--all"]) .spawn()? - .wait()?; + .wait()? + .report("Cargo", &mut reports); } if let Ok(emacs) = which("emacs") { @@ -122,7 +130,8 @@ fn main() -> Result<(), Error> { EMACS_UPGRADE, ]) .spawn()? - .wait()?; + .wait()? + .report("Emacs", &mut reports); } } @@ -133,13 +142,17 @@ fn main() -> Result<(), Error> { match os_type::current_platform().os_type { OSType::Arch => { if let Ok(yay) = which("yay") { - Command::new(yay).spawn()?.wait()?; + Command::new(yay) + .spawn()? + .wait()? + .report("System upgrade", &mut reports); } else { if let Ok(sudo) = &sudo { Command::new(&sudo) .args(&["pacman", "-Syu"]) .spawn()? - .wait()?; + .wait()? + .report("System upgrade", &mut reports); } else { terminal.print_warning("No sudo or yay detected. Skipping system upgrade"); } @@ -151,7 +164,8 @@ fn main() -> Result<(), Error> { Command::new(&sudo) .args(&["yum", "upgrade"]) .spawn()? - .wait()?; + .wait()? + .report("System upgrade", &mut reports);; } } @@ -168,7 +182,8 @@ fn main() -> Result<(), Error> { .spawn()? .wait() .map_err(Error::from) - })?; + })? + .report("System upgrade", &mut reports);; } } @@ -194,13 +209,18 @@ fn main() -> Result<(), Error> { .spawn()? .wait() .map_err(Error::from) - })?; + })? + .report("Firmware upgrade", &mut reports); } if let Ok(sudo) = &sudo { if let Ok(needrestart) = which("needrestart") { terminal.print_separator("Check for needed restarts"); - Command::new(&sudo).arg(&needrestart).spawn()?.wait()?; + Command::new(&sudo) + .arg(&needrestart) + .spawn()? + .wait()? + .report("Restarts", &mut reports); } } } @@ -219,14 +239,27 @@ fn main() -> Result<(), Error> { .spawn()? .wait() .map_err(Error::from) - })?; + })? + .report("Homebrew", &mut reports); } terminal.print_separator("System update"); Command::new("softwareupdate") .args(&["--install", "--all"]) .spawn()? - .wait()?; + .wait()? + .report("System upgrade", &mut reports);; + } + + let mut reports: Vec<_> = reports.into_iter().collect(); + reports.sort(); + + if !reports.is_empty() { + terminal.print_separator("Summary"); + + for (key, succeeded) in reports { + terminal.print_result(key, succeeded); + } } Ok(()) diff --git a/src/report.rs b/src/report.rs new file mode 100644 index 00000000..b386246b --- /dev/null +++ b/src/report.rs @@ -0,0 +1,21 @@ +use std::borrow::Cow; +use std::collections::HashMap; +use std::process::ExitStatus; + +pub type Report = HashMap; + +pub trait Reporter { + fn report<'a, M: Into>>(&self, key: M, report: &mut Report); +} + +impl Reporter for ExitStatus { + fn report<'a, M: Into>>(&self, key: M, report: &mut Report) { + report.insert(key.into().into_owned(), self.success()); + } +} + +impl Reporter for bool { + fn report<'a, M: Into>>(&self, key: M, report: &mut Report) { + report.insert(key.into().into_owned(), *self); + } +} diff --git a/src/terminal.rs b/src/terminal.rs index bb23c11b..da0d47e3 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -47,4 +47,31 @@ impl Terminal { } } } + + pub fn print_result>(&self, key: P, succeeded: bool) { + let key = key.as_ref(); + + match self.width { + Some(_) => { + if succeeded { + println!( + "{}: {}OK{}", + key, + color::Fg(color::LightGreen), + color::Fg(color::Reset) + ); + } else { + println!( + "{}: {}FAILED{}", + key, + color::Fg(color::LightRed), + color::Fg(color::Reset) + ); + } + } + None => { + println!("{}: {}", key, if succeeded { "OK" } else { "FAILED" }); + } + } + } }