Files
topgrade/src/main.rs

294 lines
8.3 KiB
Rust
Raw Normal View History

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"));
collect_repo(home_path(".oh-my-zsh"));
2018-05-30 07:53:19 +03:00
collect_repo(home_path(".tmux"));
}
}
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-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)
.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)
.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)
.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-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)
.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)
.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)
.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)
.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
}
}
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-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)
.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")
.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);;
}
if let Ok(npm) = which("npm") {
terminal.print_separator("Node Package Manager");
Command::new(&npm)
.args(&["install", "npm"])
.spawn()?
.wait()?
.check()
.and_then(|()| {
Command::new(&npm)
.args(&["update", "-g"])
.spawn()?
.wait()
.map_err(Error::from)
})?
.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-06-03 18:04:58 +03:00
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(())
}