Files
topgrade/src/main.rs

287 lines
8.2 KiB
Rust
Raw Normal View History

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;
extern crate toml;
#[macro_use]
extern crate serde_derive;
2018-06-12 11:30:03 +03:00
#[macro_use]
extern crate clap;
extern crate serde;
extern crate shellexpand;
2018-06-17 14:17:36 +03:00
#[macro_use]
extern crate log;
extern crate env_logger;
2018-05-29 23:48:30 +03:00
mod config;
2018-05-30 07:53:19 +03:00
mod git;
mod linux;
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-17 11:43:25 +03:00
mod utils;
2018-06-07 08:51:16 +03:00
mod vim;
2018-05-30 07:53:19 +03:00
2018-06-20 21:05:49 +03:00
use clap::{App, Arg};
use config::Config;
2018-06-04 22:33:39 +03:00
use failure::Error;
use git::{Git, Repositories};
2018-06-03 18:04:58 +03:00
use report::{Report, Reporter};
2018-06-20 21:05:49 +03:00
use std::env;
2018-05-29 23:48:30 +03:00
use std::env::home_dir;
2018-06-20 21:05:49 +03:00
#[cfg(unix)]
use std::os::unix::process::CommandExt;
2018-06-17 11:43:25 +03:00
use std::path::PathBuf;
use std::process::exit;
2018-06-20 21:05:49 +03:00
use std::process::Command;
2018-06-06 15:32:38 +03:00
use steps::*;
2018-05-31 16:00:01 +03:00
use terminal::Terminal;
2018-06-17 11:43:25 +03:00
use utils::{home_path, is_ancestor};
2018-05-29 23:48:30 +03:00
#[derive(Fail, Debug)]
#[fail(display = "A step failed")]
struct StepFailed;
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
}
}
fn run() -> Result<(), Error> {
2018-06-20 21:05:49 +03:00
let matches = App::new("Topgrade")
2018-06-12 11:30:03 +03:00
.version(crate_version!())
.about("Upgrade all the things")
2018-06-20 21:05:49 +03:00
.arg(
Arg::with_name("tmux")
.help("Invoke inside tmux")
.short("t")
.long("tmux"),
)
2018-06-12 11:30:03 +03:00
.get_matches();
2018-06-20 21:05:49 +03:00
if matches.is_present("tmux") && !env::var("TMUX").is_ok() {
if cfg!(unix) {
let tmux = utils::which("tmux").expect("Could not find tmux");
let err = Command::new(tmux)
.args(&[
"new-session",
"-s",
"topgrade",
"-n",
"topgrade",
&env::args().collect::<Vec<String>>().join(" "),
";",
"set",
"remain-on-exit",
"on",
])
.exec();
panic!("{:?}", err);
} else {
panic!("This flag is only implemented in Unix systems");
}
}
2018-06-17 14:17:36 +03:00
env_logger::init();
2018-05-30 07:53:19 +03:00
let git = Git::new();
let mut git_repos = Repositories::new(&git);
2018-05-31 16:00:01 +03:00
let terminal = Terminal::new();
let config = Config::read()?;
2018-06-27 18:06:24 +03:00
let mut reports = Report::new();
2018-05-30 07:53:19 +03:00
let sudo = if cfg!(target_os = "linux") {
2018-06-17 14:17:36 +03:00
utils::which("sudo")
} else {
None
};
2018-06-20 20:26:08 +03:00
if let Some(commands) = config.pre_commands() {
for (name, command) in commands {
terminal.print_separator(name);
run_custom_command(&command)?;
}
}
if cfg!(target_os = "linux") {
terminal.print_separator("System update");
match linux::Distribution::detect() {
Ok(distribution) => {
match distribution {
2018-06-12 21:28:32 +03:00
linux::Distribution::Arch => linux::upgrade_arch_linux(&sudo, &terminal),
linux::Distribution::CentOS => linux::upgrade_redhat(&sudo, &terminal),
linux::Distribution::Fedora => linux::upgrade_fedora(&sudo, &terminal),
linux::Distribution::Ubuntu | linux::Distribution::Debian => {
2018-06-12 21:28:32 +03:00
linux::upgrade_debian(&sudo, &terminal)
}
}.report("System upgrade", &mut reports);
}
Err(e) => {
println!("Error detecting current distribution: {}", e);
}
}
}
2018-06-25 22:29:51 +03:00
if let Some(brew) = utils::which("brew") {
terminal.print_separator("Brew");
run_homebrew(&brew).report("Brew", &mut reports);
}
git_repos.insert(home_path(".emacs.d"));
2018-05-30 07:53:19 +03:00
if cfg!(unix) {
git_repos.insert(home_path(".zshrc"));
git_repos.insert(home_path(".oh-my-zsh"));
git_repos.insert(home_path(".tmux"));
2018-06-11 11:38:25 +03:00
git_repos.insert(home_path(".config/fish/config.fish"));
}
2018-05-30 07:53:19 +03:00
if let Some(custom_git_repos) = config.git_repos() {
for git_repo in custom_git_repos {
git_repos.insert(git_repo);
2018-05-30 07:53:19 +03:00
}
}
for repo in git_repos.repositories() {
2018-05-31 16:00:01 +03:00
terminal.print_separator(format!("Pulling {}", repo));
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-29 23:48:30 +03:00
if cfg!(unix) {
2018-06-17 14:17:36 +03:00
if let Some(zsh) = utils::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-17 14:17:36 +03:00
if let Some(rustup) = utils::which("rustup") {
2018-06-07 22:36:32 +03:00
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-06-17 14:17:36 +03:00
if let Some(emacs) = utils::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-17 14:17:36 +03:00
if let Some(vim) = utils::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-17 14:17:36 +03:00
if let Some(npm) = utils::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-17 14:17:36 +03:00
if let Some(apm) = utils::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-14 13:24:52 +03:00
if cfg!(target_os = "linux") {
2018-06-17 14:17:36 +03:00
if let Some(flatpak) = utils::which("flatpak") {
2018-06-14 13:24:52 +03:00
terminal.print_separator("Flatpak");
run_flatpak(&flatpak).report("Flatpak", &mut reports);
}
if let Some(sudo) = &sudo {
2018-06-17 14:17:36 +03:00
if let Some(snap) = utils::which("snap") {
2018-06-14 13:24:52 +03:00
terminal.print_separator("snap");
run_snap(&sudo, &snap).report("snap", &mut reports);
}
}
}
if let Some(commands) = config.commands() {
for (name, command) in commands {
terminal.print_separator(name);
2018-06-27 18:06:24 +03:00
run_custom_command(&command).report(name.as_str(), &mut reports);
}
}
2018-05-31 09:19:27 +03:00
if cfg!(target_os = "linux") {
2018-06-17 14:17:36 +03:00
if let Some(fwupdmgr) = utils::which("fwupdmgr") {
2018-06-03 16:12:16 +03:00
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
}
if let Some(sudo) = &sudo {
2018-06-17 14:17:36 +03:00
if let Some(_) = utils::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") {
terminal.print_separator("App Store");
upgrade_macos().report("App Store", &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-06-03 18:04:58 +03:00
}
2018-05-29 23:48:30 +03:00
}
if reports.iter().all(|(_, succeeded)| *succeeded) {
Ok(())
} else {
Err(StepFailed.into())
}
}
fn main() {
match run() {
Ok(()) => {
exit(0);
}
Err(error) => {
match error.downcast::<StepFailed>() {
Ok(_) => (),
Err(error) => println!("ERROR: {}", error),
};
exit(1);
}
}
2018-05-29 23:48:30 +03:00
}