2018-06-04 22:33:39 +03:00
|
|
|
extern crate failure;
|
2018-05-31 09:19:27 +03:00
|
|
|
extern crate os_type;
|
2018-05-29 23:48:30 +03:00
|
|
|
extern crate which;
|
|
|
|
|
#[macro_use]
|
2018-06-04 22:33:39 +03:00
|
|
|
extern crate failure_derive;
|
2018-05-31 16:00:01 +03:00
|
|
|
extern crate termion;
|
2018-05-29 23:48:30 +03:00
|
|
|
|
2018-05-30 07:53:19 +03:00
|
|
|
mod git;
|
2018-06-03 18:04:58 +03:00
|
|
|
mod report;
|
2018-05-31 16:00:01 +03:00
|
|
|
mod terminal;
|
2018-05-30 07:53:19 +03:00
|
|
|
|
2018-06-04 22:33:39 +03:00
|
|
|
use failure::Error;
|
2018-05-30 07:53:19 +03:00
|
|
|
use git::Git;
|
2018-05-31 09:19:27 +03:00
|
|
|
use os_type::OSType;
|
2018-06-03 18:04:58 +03:00
|
|
|
use report::{Report, Reporter};
|
2018-05-30 07:53:19 +03:00
|
|
|
use std::collections::HashSet;
|
2018-05-29 23:48:30 +03:00
|
|
|
use std::env::home_dir;
|
|
|
|
|
use std::path::PathBuf;
|
|
|
|
|
use std::process::{Command, ExitStatus};
|
2018-05-31 16:00:01 +03:00
|
|
|
use terminal::Terminal;
|
2018-05-29 23:48:30 +03:00
|
|
|
use which::which;
|
|
|
|
|
|
2018-06-04 22:33:39 +03:00
|
|
|
#[derive(Fail, Debug)]
|
|
|
|
|
#[fail(display = "Process failed")]
|
|
|
|
|
struct ProcessFailed;
|
|
|
|
|
|
2018-06-03 16:44:19 +03:00
|
|
|
trait Check {
|
2018-06-04 22:33:39 +03:00
|
|
|
fn check(self) -> Result<(), Error>;
|
2018-05-29 23:48:30 +03:00
|
|
|
}
|
|
|
|
|
|
2018-06-03 16:44:19 +03:00
|
|
|
impl Check for ExitStatus {
|
2018-06-04 22:33:39 +03:00
|
|
|
fn check(self) -> Result<(), Error> {
|
2018-06-03 16:44:19 +03:00
|
|
|
if self.success() {
|
|
|
|
|
Ok(())
|
2018-05-29 23:48:30 +03:00
|
|
|
} else {
|
2018-06-04 22:33:39 +03:00
|
|
|
Err(Error::from(ProcessFailed {}))
|
2018-05-29 23:48:30 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-03 18:04:58 +03:00
|
|
|
const EMACS_UPGRADE: &str = include_str!("emacs.el");
|
2018-05-31 16:17:28 +03:00
|
|
|
|
2018-05-30 07:53:19 +03:00
|
|
|
fn home_path(p: &str) -> PathBuf {
|
2018-05-29 23:48:30 +03:00
|
|
|
let mut path = home_dir().unwrap();
|
2018-05-30 07:53:19 +03:00
|
|
|
path.push(p);
|
|
|
|
|
path
|
2018-05-29 23:48:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(unix)]
|
|
|
|
|
fn tpm() -> Option<PathBuf> {
|
|
|
|
|
let mut path = home_dir().unwrap();
|
|
|
|
|
path.push(".tmux/plugins/tpm/bin/update_plugins");
|
|
|
|
|
if path.exists() {
|
|
|
|
|
Some(path)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-04 22:33:39 +03:00
|
|
|
fn main() -> Result<(), Error> {
|
2018-05-30 07:53:19 +03:00
|
|
|
let git = Git::new();
|
|
|
|
|
let mut git_repos: HashSet<String> = HashSet::new();
|
2018-05-31 16:00:01 +03:00
|
|
|
let terminal = Terminal::new();
|
2018-06-03 18:04:58 +03:00
|
|
|
let mut reports = Report::new();
|
2018-05-30 07:53:19 +03:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
let mut collect_repo = |path| {
|
|
|
|
|
if let Some(repo) = git.get_repo_root(path) {
|
|
|
|
|
git_repos.insert(repo);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
collect_repo(home_path(".emacs.d"));
|
|
|
|
|
|
|
|
|
|
if cfg!(unix) {
|
|
|
|
|
collect_repo(home_path(".zshrc"));
|
2018-05-31 15:59:45 +03:00
|
|
|
collect_repo(home_path(".oh-my-zsh"));
|
2018-05-30 07:53:19 +03:00
|
|
|
collect_repo(home_path(".tmux"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 15:59:45 +03:00
|
|
|
for repo in git_repos {
|
2018-05-31 16:00:01 +03:00
|
|
|
terminal.print_separator(format!("Pulling {}", repo));
|
2018-06-03 18:04:58 +03:00
|
|
|
if let Some(success) = git.pull(&repo)? {
|
|
|
|
|
success.report(format!("git: {}", repo), &mut reports);
|
|
|
|
|
}
|
2018-05-31 15:59:45 +03:00
|
|
|
}
|
|
|
|
|
|
2018-05-29 23:48:30 +03:00
|
|
|
if cfg!(unix) {
|
|
|
|
|
if let Ok(zsh) = which("zsh") {
|
2018-05-31 16:00:01 +03:00
|
|
|
terminal.print_separator("zplug");
|
2018-05-30 07:53:19 +03:00
|
|
|
if home_path(".zplug").exists() {
|
2018-05-29 23:48:30 +03:00
|
|
|
Command::new(&zsh)
|
2018-06-03 17:16:54 +03:00
|
|
|
.args(&["-c", "source ~/.zshrc && zplug update"])
|
2018-05-29 23:48:30 +03:00
|
|
|
.spawn()?
|
2018-06-03 18:04:58 +03:00
|
|
|
.wait()?
|
|
|
|
|
.report("zplug", &mut reports);
|
2018-05-29 23:48:30 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some(tpm) = tpm() {
|
2018-05-31 16:00:01 +03:00
|
|
|
terminal.print_separator("tmux plugins");
|
2018-06-03 18:04:58 +03:00
|
|
|
Command::new(&tpm)
|
|
|
|
|
.arg("all")
|
|
|
|
|
.spawn()?
|
|
|
|
|
.wait()?
|
|
|
|
|
.report("tmux", &mut reports);
|
2018-05-29 23:48:30 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 16:17:22 +03:00
|
|
|
let cargo_upgrade = home_path(".cargo/bin/cargo-install-update");
|
|
|
|
|
if cargo_upgrade.exists() {
|
|
|
|
|
terminal.print_separator("Cargo");
|
|
|
|
|
Command::new(&cargo_upgrade)
|
2018-06-03 17:16:54 +03:00
|
|
|
.args(&["install-update", "--all"])
|
2018-05-31 16:17:22 +03:00
|
|
|
.spawn()?
|
2018-06-03 18:04:58 +03:00
|
|
|
.wait()?
|
|
|
|
|
.report("Cargo", &mut reports);
|
2018-05-31 16:17:22 +03:00
|
|
|
}
|
|
|
|
|
|
2018-05-31 16:17:28 +03:00
|
|
|
if let Ok(emacs) = which("emacs") {
|
|
|
|
|
if home_path(".emacs.d").exists() {
|
2018-06-01 14:46:33 +03:00
|
|
|
terminal.print_separator("Emacs");
|
2018-05-31 16:17:28 +03:00
|
|
|
Command::new(&emacs)
|
2018-06-03 17:16:54 +03:00
|
|
|
.args(&[
|
|
|
|
|
"--batch",
|
|
|
|
|
"-l",
|
|
|
|
|
home_path(".emacs.d/init.el").to_str().unwrap(),
|
|
|
|
|
"--eval",
|
|
|
|
|
EMACS_UPGRADE,
|
|
|
|
|
])
|
2018-05-31 16:17:28 +03:00
|
|
|
.spawn()?
|
2018-06-03 18:04:58 +03:00
|
|
|
.wait()?
|
|
|
|
|
.report("Emacs", &mut reports);
|
2018-05-31 16:17:28 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-06 11:47:51 +03:00
|
|
|
if let Ok(gem) = which("gem") {
|
|
|
|
|
terminal.print_separator("RubyGems");
|
|
|
|
|
Command::new(&gem)
|
|
|
|
|
.args(&["update"])
|
|
|
|
|
.spawn()?
|
|
|
|
|
.wait()?
|
|
|
|
|
.report("RubyGems", &mut reports);
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-06 11:27:43 +03:00
|
|
|
if let Ok(npm) = which("npm") {
|
|
|
|
|
terminal.print_separator("Node Package Manager");
|
|
|
|
|
Command::new(&npm)
|
|
|
|
|
.args(&["update", "-g"])
|
|
|
|
|
.spawn()?
|
|
|
|
|
.wait()?
|
|
|
|
|
.report("Node Package Manager", &mut reports);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Ok(apm) = which("apm") {
|
|
|
|
|
terminal.print_separator("Atom Package Manager");
|
|
|
|
|
Command::new(&apm)
|
|
|
|
|
.args(&["upgrade", "--confirm=false"])
|
|
|
|
|
.spawn()?
|
|
|
|
|
.wait()
|
|
|
|
|
.map_err(Error::from)?
|
|
|
|
|
.report("Atom Package Manager", &mut reports);
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 09:19:27 +03:00
|
|
|
if cfg!(target_os = "linux") {
|
|
|
|
|
let sudo = which("sudo");
|
|
|
|
|
|
2018-06-03 16:43:53 +03:00
|
|
|
terminal.print_separator("System update");
|
2018-05-31 09:19:27 +03:00
|
|
|
match os_type::current_platform().os_type {
|
|
|
|
|
OSType::Arch => {
|
|
|
|
|
if let Ok(yay) = which("yay") {
|
2018-06-03 18:04:58 +03:00
|
|
|
Command::new(yay)
|
|
|
|
|
.spawn()?
|
|
|
|
|
.wait()?
|
|
|
|
|
.report("System upgrade", &mut reports);
|
2018-05-31 09:19:27 +03:00
|
|
|
} else {
|
|
|
|
|
if let Ok(sudo) = &sudo {
|
|
|
|
|
Command::new(&sudo)
|
2018-06-03 17:16:54 +03:00
|
|
|
.args(&["pacman", "-Syu"])
|
2018-05-31 09:19:27 +03:00
|
|
|
.spawn()?
|
2018-06-03 18:04:58 +03:00
|
|
|
.wait()?
|
|
|
|
|
.report("System upgrade", &mut reports);
|
2018-06-03 16:43:53 +03:00
|
|
|
} else {
|
|
|
|
|
terminal.print_warning("No sudo or yay detected. Skipping system upgrade");
|
2018-05-31 09:19:27 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-01 14:43:16 +03:00
|
|
|
|
|
|
|
|
OSType::CentOS | OSType::Redhat => {
|
|
|
|
|
if let Ok(sudo) = &sudo {
|
|
|
|
|
Command::new(&sudo)
|
2018-06-03 17:16:54 +03:00
|
|
|
.args(&["yum", "upgrade"])
|
2018-06-01 14:43:16 +03:00
|
|
|
.spawn()?
|
2018-06-03 18:04:58 +03:00
|
|
|
.wait()?
|
|
|
|
|
.report("System upgrade", &mut reports);;
|
2018-06-01 14:43:16 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OSType::Ubuntu | OSType::Debian => {
|
|
|
|
|
if let Ok(sudo) = &sudo {
|
|
|
|
|
Command::new(&sudo)
|
2018-06-03 17:16:54 +03:00
|
|
|
.args(&["apt", "update"])
|
2018-06-01 14:43:16 +03:00
|
|
|
.spawn()?
|
|
|
|
|
.wait()?
|
2018-06-03 16:44:19 +03:00
|
|
|
.check()
|
|
|
|
|
.and_then(|()| {
|
2018-06-01 14:43:16 +03:00
|
|
|
Command::new(&sudo)
|
2018-06-03 17:16:54 +03:00
|
|
|
.args(&["apt", "dist-upgrade"])
|
2018-06-01 14:43:16 +03:00
|
|
|
.spawn()?
|
|
|
|
|
.wait()
|
2018-06-04 22:33:39 +03:00
|
|
|
.map_err(Error::from)
|
2018-06-03 18:04:58 +03:00
|
|
|
})?
|
|
|
|
|
.report("System upgrade", &mut reports);;
|
2018-06-01 14:43:16 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-01 14:54:04 +03:00
|
|
|
OSType::Unknown => {
|
2018-06-03 16:43:53 +03:00
|
|
|
terminal.print_warning(
|
|
|
|
|
"Could not detect your Linux distribution. Do you have lsb-release installed?",
|
2018-06-01 14:54:04 +03:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 09:19:27 +03:00
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-03 16:12:16 +03:00
|
|
|
if let Ok(fwupdmgr) = which("fwupdmgr") {
|
|
|
|
|
terminal.print_separator("Firmware upgrades");
|
|
|
|
|
Command::new(&fwupdmgr)
|
|
|
|
|
.arg("refresh")
|
|
|
|
|
.spawn()?
|
|
|
|
|
.wait()?
|
2018-06-03 16:44:19 +03:00
|
|
|
.check()
|
|
|
|
|
.and_then(|()| {
|
|
|
|
|
Command::new(&fwupdmgr)
|
|
|
|
|
.arg("get-updates")
|
|
|
|
|
.spawn()?
|
|
|
|
|
.wait()
|
2018-06-04 22:33:39 +03:00
|
|
|
.map_err(Error::from)
|
2018-06-03 18:04:58 +03:00
|
|
|
})?
|
|
|
|
|
.report("Firmware upgrade", &mut reports);
|
2018-06-03 16:12:16 +03:00
|
|
|
}
|
|
|
|
|
|
2018-05-31 09:19:27 +03:00
|
|
|
if let Ok(sudo) = &sudo {
|
|
|
|
|
if let Ok(needrestart) = which("needrestart") {
|
2018-05-31 16:00:01 +03:00
|
|
|
terminal.print_separator("Check for needed restarts");
|
2018-06-03 18:04:58 +03:00
|
|
|
Command::new(&sudo)
|
|
|
|
|
.arg(&needrestart)
|
|
|
|
|
.spawn()?
|
|
|
|
|
.wait()?
|
|
|
|
|
.report("Restarts", &mut reports);
|
2018-05-31 09:19:27 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-29 23:48:30 +03:00
|
|
|
if cfg!(target_os = "macos") {
|
|
|
|
|
if let Ok(brew) = which("brew") {
|
2018-05-31 16:00:01 +03:00
|
|
|
terminal.print_separator("Homebrew");
|
2018-05-29 23:48:30 +03:00
|
|
|
Command::new(&brew)
|
|
|
|
|
.arg("update")
|
|
|
|
|
.spawn()?
|
|
|
|
|
.wait()?
|
2018-06-03 16:44:19 +03:00
|
|
|
.check()
|
|
|
|
|
.and_then(|()| {
|
2018-05-29 23:48:30 +03:00
|
|
|
Command::new(&brew)
|
2018-06-03 17:16:54 +03:00
|
|
|
.arg("upgrade")
|
2018-05-29 23:48:30 +03:00
|
|
|
.spawn()?
|
|
|
|
|
.wait()
|
2018-06-04 22:33:39 +03:00
|
|
|
.map_err(Error::from)
|
2018-06-03 18:04:58 +03:00
|
|
|
})?
|
|
|
|
|
.report("Homebrew", &mut reports);
|
2018-05-29 23:48:30 +03:00
|
|
|
}
|
|
|
|
|
|
2018-05-31 16:00:01 +03:00
|
|
|
terminal.print_separator("System update");
|
2018-05-29 23:48:30 +03:00
|
|
|
Command::new("softwareupdate")
|
2018-06-03 17:16:54 +03:00
|
|
|
.args(&["--install", "--all"])
|
2018-05-29 23:48:30 +03:00
|
|
|
.spawn()?
|
2018-06-03 18:04:58 +03:00
|
|
|
.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);
|
|
|
|
|
}
|
2018-05-29 23:48:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|