2018-06-08 18:19:07 +03:00
|
|
|
extern crate directories;
|
2018-06-04 22:33:39 +03:00
|
|
|
extern crate failure;
|
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-06-08 18:19:07 +03:00
|
|
|
extern crate toml;
|
|
|
|
|
#[macro_use]
|
|
|
|
|
extern crate serde_derive;
|
|
|
|
|
extern crate serde;
|
2018-05-29 23:48:30 +03:00
|
|
|
|
2018-06-08 18:19:07 +03:00
|
|
|
mod config;
|
2018-05-30 07:53:19 +03:00
|
|
|
mod git;
|
2018-06-07 16:19:11 +03:00
|
|
|
mod linux;
|
2018-06-09 20:39:13 +03:00
|
|
|
mod npm;
|
2018-06-03 18:04:58 +03:00
|
|
|
mod report;
|
2018-06-06 15:32:38 +03:00
|
|
|
mod steps;
|
2018-05-31 16:00:01 +03:00
|
|
|
mod terminal;
|
2018-06-07 08:51:16 +03:00
|
|
|
mod vim;
|
2018-05-30 07:53:19 +03:00
|
|
|
|
2018-06-08 18:19:07 +03:00
|
|
|
use config::Config;
|
2018-06-04 22:33:39 +03:00
|
|
|
use failure::Error;
|
2018-06-11 08:21:39 +03:00
|
|
|
use git::{Git, Repositories};
|
2018-06-03 18:04:58 +03:00
|
|
|
use report::{Report, Reporter};
|
2018-05-29 23:48:30 +03:00
|
|
|
use std::env::home_dir;
|
2018-06-09 20:39:13 +03:00
|
|
|
use std::path::{Path, PathBuf};
|
2018-06-06 15:32:38 +03:00
|
|
|
use std::process::ExitStatus;
|
|
|
|
|
use steps::*;
|
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-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
|
|
|
}
|
|
|
|
|
|
2018-06-09 20:39:13 +03:00
|
|
|
fn is_ancestor(ancestor: &Path, path: &Path) -> bool {
|
|
|
|
|
let mut p = path;
|
|
|
|
|
while let Some(parent) = p.parent() {
|
|
|
|
|
if parent == ancestor {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p = parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
|
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();
|
2018-06-11 08:21:39 +03:00
|
|
|
let mut git_repos = Repositories::new(&git);
|
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-06-08 18:19:07 +03:00
|
|
|
let config = Config::read()?;
|
2018-05-30 07:53:19 +03:00
|
|
|
|
2018-06-11 08:29:40 +03:00
|
|
|
let sudo = if cfg!(target_os = "linux") {
|
|
|
|
|
which("sudo").ok()
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if cfg!(target_os = "linux") {
|
|
|
|
|
terminal.print_separator("System update");
|
|
|
|
|
match linux::Distribution::detect() {
|
|
|
|
|
Ok(distribution) => {
|
|
|
|
|
match distribution {
|
|
|
|
|
linux::Distribution::Arch => upgrade_arch_linux(&sudo, &terminal),
|
|
|
|
|
linux::Distribution::CentOS => upgrade_redhat(&sudo, &terminal),
|
|
|
|
|
linux::Distribution::Fedora => upgrade_fedora(&sudo, &terminal),
|
|
|
|
|
linux::Distribution::Ubuntu | linux::Distribution::Debian => {
|
|
|
|
|
upgrade_debian(&sudo, &terminal)
|
|
|
|
|
}
|
|
|
|
|
}.report("System upgrade", &mut reports);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Err(e) => {
|
|
|
|
|
println!("Error detecting current distribution: {}", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if cfg!(target_os = "macos") {
|
|
|
|
|
if let Ok(brew) = which("brew") {
|
|
|
|
|
terminal.print_separator("Homebrew");
|
|
|
|
|
run_homebrew(&brew).report("Homebrew", &mut reports);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-11 08:21:39 +03:00
|
|
|
git_repos.insert(home_path(".emacs.d"));
|
2018-05-30 07:53:19 +03:00
|
|
|
|
2018-06-08 18:19:07 +03:00
|
|
|
if cfg!(unix) {
|
2018-06-11 08:21:39 +03:00
|
|
|
git_repos.insert(home_path(".zshrc"));
|
|
|
|
|
git_repos.insert(home_path(".oh-my-zsh"));
|
|
|
|
|
git_repos.insert(home_path(".tmux"));
|
2018-06-08 18:19:07 +03:00
|
|
|
}
|
2018-05-30 07:53:19 +03:00
|
|
|
|
2018-06-08 18:19:07 +03:00
|
|
|
if let Some(custom_git_repos) = config.git_repos() {
|
|
|
|
|
for git_repo in custom_git_repos {
|
2018-06-11 08:21:39 +03:00
|
|
|
git_repos.insert(git_repo);
|
2018-05-30 07:53:19 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-11 08:21:39 +03:00
|
|
|
for repo in git_repos.repositories() {
|
2018-05-31 16:00:01 +03:00
|
|
|
terminal.print_separator(format!("Pulling {}", repo));
|
2018-06-09 22:55:31 +03:00
|
|
|
if let Some(success) = git.pull(&repo).ok().and_then(|i| i) {
|
2018-06-03 18:04:58 +03:00
|
|
|
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-30 07:53:19 +03:00
|
|
|
if home_path(".zplug").exists() {
|
2018-06-06 15:32:38 +03:00
|
|
|
terminal.print_separator("zplug");
|
|
|
|
|
run_zplug(&zsh).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-06 15:32:38 +03:00
|
|
|
run_tpm(&tpm).report("tmux", &mut reports);
|
2018-05-29 23:48:30 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-07 22:36:32 +03:00
|
|
|
if let Ok(rustup) = which("rustup") {
|
|
|
|
|
terminal.print_separator("rustup");
|
|
|
|
|
run_rustup(&rustup).report("rustup", &mut reports);
|
|
|
|
|
}
|
|
|
|
|
|
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");
|
2018-06-06 15:32:38 +03:00
|
|
|
run_cargo_update(&cargo_upgrade).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") {
|
2018-06-06 15:32:38 +03:00
|
|
|
let init_file = home_path(".emacs.d/init.el");
|
|
|
|
|
if init_file.exists() {
|
2018-06-01 14:46:33 +03:00
|
|
|
terminal.print_separator("Emacs");
|
2018-06-07 08:51:16 +03:00
|
|
|
run_emacs(&emacs, &init_file).report("Emacs", &mut reports);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-07 09:21:44 +03:00
|
|
|
if let Ok(vim) = which("vim") {
|
|
|
|
|
if let Some(vimrc) = vim::vimrc() {
|
2018-06-07 08:51:16 +03:00
|
|
|
if let Some(plugin_framework) = vim::PluginFramework::detect(&vimrc) {
|
|
|
|
|
terminal.print_separator(&format!("vim ({:?})", plugin_framework));
|
|
|
|
|
run_vim(&vim, &vimrc, plugin_framework.upgrade_command())
|
|
|
|
|
.report("Vim", &mut reports);
|
|
|
|
|
}
|
2018-05-31 16:17:28 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-09 20:39:13 +03:00
|
|
|
if let Ok(npm) = which("npm").map(npm::NPM::new) {
|
|
|
|
|
if let Ok(npm_root) = npm.root() {
|
|
|
|
|
if is_ancestor(&home_dir().unwrap(), &npm_root) {
|
|
|
|
|
terminal.print_separator("Node Package Manager");
|
|
|
|
|
npm.upgrade().report("Node Package Manager", &mut reports);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-06 11:27:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Ok(apm) = which("apm") {
|
|
|
|
|
terminal.print_separator("Atom Package Manager");
|
2018-06-06 15:32:38 +03:00
|
|
|
run_apm(&apm).report("Atom Package Manager", &mut reports);
|
2018-06-06 11:27:43 +03:00
|
|
|
}
|
|
|
|
|
|
2018-05-31 09:19:27 +03:00
|
|
|
if cfg!(target_os = "linux") {
|
2018-06-03 16:12:16 +03:00
|
|
|
if let Ok(fwupdmgr) = which("fwupdmgr") {
|
|
|
|
|
terminal.print_separator("Firmware upgrades");
|
2018-06-06 15:32:38 +03:00
|
|
|
run_fwupdmgr(&fwupdmgr).report("Firmware upgrade", &mut reports);
|
2018-06-03 16:12:16 +03:00
|
|
|
}
|
|
|
|
|
|
2018-06-11 08:29:40 +03:00
|
|
|
if let Some(sudo) = &sudo {
|
2018-06-06 15:32:38 +03:00
|
|
|
if let Ok(_) = which("needrestart") {
|
2018-05-31 16:00:01 +03:00
|
|
|
terminal.print_separator("Check for needed restarts");
|
2018-06-06 15:32:38 +03:00
|
|
|
run_needrestart(&sudo).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") {
|
2018-06-11 08:29:40 +03:00
|
|
|
terminal.print_separator("App Store");
|
|
|
|
|
upgrade_macos().report("App Store", &mut reports);;
|
2018-06-03 18:04:58 +03:00
|
|
|
}
|
|
|
|
|
|
2018-06-08 18:19:07 +03:00
|
|
|
if let Some(commands) = config.commands() {
|
|
|
|
|
for (name, command) in commands {
|
|
|
|
|
terminal.print_separator(name);
|
|
|
|
|
run_custom_command(&command).report(name.as_ref(), &mut reports);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-03 18:04:58 +03:00
|
|
|
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(())
|
|
|
|
|
}
|