2020-12-01 08:59:59 +02:00
#![ allow(clippy::cognitive_complexity) ]
2021-12-18 20:39:57 +02:00
use std ::env ;
use std ::io ;
2023-05-01 00:02:13 +05:30
use std ::path ::PathBuf ;
2021-12-18 20:39:57 +02:00
use std ::process ::exit ;
2023-01-29 19:19:27 +00:00
use std ::time ::Duration ;
2021-12-18 20:39:57 +02:00
2022-11-26 20:42:35 +01:00
use clap ::CommandFactory ;
2022-04-23 12:35:06 +02:00
use clap ::{ crate_version , Parser } ;
2022-11-11 09:39:29 -05:00
use color_eyre ::eyre ::Context ;
2023-05-01 00:02:13 +05:30
use color_eyre ::eyre ::Result ;
2021-12-18 20:39:57 +02:00
use console ::Key ;
2023-05-01 00:02:13 +05:30
#[ cfg(windows) ]
use etcetera ::base_strategy ::Windows ;
use etcetera ::base_strategy ::{ BaseStrategy , Xdg } ;
use once_cell ::sync ::Lazy ;
2022-11-16 13:43:57 -05:00
use tracing ::debug ;
2021-12-18 20:39:57 +02:00
use self ::config ::{ CommandLineArgs , Config , Step } ;
use self ::error ::StepFailed ;
#[ cfg(all(windows, feature = " self-update " )) ]
use self ::error ::Upgraded ;
use self ::steps ::{ remote ::* , * } ;
use self ::terminal ::* ;
2022-11-08 05:54:35 -05:00
mod command ;
2018-06-28 12:16:54 +03:00
mod config ;
2018-10-17 14:07:58 +03:00
mod ctrlc ;
2018-12-11 16:43:26 +02:00
mod error ;
2020-02-08 22:13:56 +02:00
mod execution_context ;
2018-08-26 16:12:59 +03:00
mod executor ;
2018-06-03 18:04:58 +03:00
mod report ;
2020-02-09 13:41:55 +02:00
mod runner ;
2020-07-01 21:03:19 +03:00
#[ cfg(windows) ]
mod self_renamer ;
2018-11-26 14:27:19 +02:00
#[ cfg(feature = " self-update " ) ]
mod self_update ;
2018-12-15 21:52:21 +02:00
mod steps ;
2022-11-24 14:15:43 -05:00
mod sudo ;
2018-05-31 16:00:01 +03:00
mod terminal ;
2018-06-17 11:43:25 +03:00
mod utils ;
2018-05-30 07:53:19 +03:00
2023-05-01 00:02:13 +05:30
pub static HOME_DIR : Lazy < PathBuf > = Lazy ::new ( | | home ::home_dir ( ) . expect ( " No home directory " ) ) ;
pub static XDG_DIRS : Lazy < Xdg > = Lazy ::new ( | | Xdg ::new ( ) . expect ( " No home directory " ) ) ;
#[ cfg(windows) ]
pub static WINDOWS_DIRS : Lazy < Windows > = Lazy ::new ( | | Windows ::new ( ) . expect ( " No home directory " ) ) ;
2019-12-11 23:05:38 +02:00
fn run ( ) -> Result < ( ) > {
2022-11-11 09:39:29 -05:00
color_eyre ::install ( ) ? ;
2018-10-17 14:07:58 +03:00
ctrlc ::set_handler ( ) ;
2022-04-23 12:35:06 +02:00
let opt = CommandLineArgs ::parse ( ) ;
2022-05-07 08:11:53 +03:00
2022-11-26 20:42:35 +01:00
if let Some ( shell ) = opt . gen_completion {
let cmd = & mut CommandLineArgs ::command ( ) ;
clap_complete ::generate ( shell , cmd , clap ::crate_name! ( ) , & mut std ::io ::stdout ( ) ) ;
return Ok ( ( ) ) ;
}
if opt . gen_manpage {
let man = clap_mangen ::Man ::new ( CommandLineArgs ::command ( ) ) ;
man . render ( & mut std ::io ::stdout ( ) ) ? ;
return Ok ( ( ) ) ;
}
2022-11-16 13:43:57 -05:00
install_tracing ( & opt . tracing_filter_directives ( ) ) ? ;
2022-05-07 08:11:53 +03:00
for env in opt . env_variables ( ) {
let mut splitted = env . split ( '=' ) ;
let var = splitted . next ( ) . unwrap ( ) ;
let value = splitted . next ( ) . unwrap ( ) ;
env ::set_var ( var , value ) ;
}
2019-11-04 22:55:06 +02:00
if opt . edit_config ( ) {
2023-05-01 00:02:13 +05:30
Config ::edit ( ) ? ;
2019-08-22 22:29:31 +03:00
return Ok ( ( ) ) ;
} ;
2020-06-30 10:01:22 +03:00
if opt . show_config_reference ( ) {
print! ( " {} " , crate ::config ::EXAMPLE_CONFIG ) ;
return Ok ( ( ) ) ;
}
2023-05-01 00:02:13 +05:30
let config = Config ::load ( opt ) ? ;
2019-11-04 22:55:06 +02:00
terminal ::set_title ( config . set_title ( ) ) ;
2022-03-29 03:42:47 +03:00
terminal ::display_time ( config . display_time ( ) ) ;
2020-02-27 13:30:55 +02:00
terminal ::set_desktop_notifications ( config . notify_each_step ( ) ) ;
2019-11-04 22:55:06 +02:00
2020-02-26 12:27:58 +02:00
debug! ( " Version: {} " , crate_version! ( ) ) ;
debug! ( " OS: {} " , env! ( " TARGET " ) ) ;
debug! ( " {:?} " , std ::env ::args ( ) ) ;
debug! ( " Binary path: {:?} " , std ::env ::current_exe ( ) ) ;
debug! ( " Self Update: {:?} " , cfg! ( feature = " self-update " ) ) ;
2023-02-07 12:21:15 -05:00
#[ cfg(target_os = " linux " ) ]
2023-03-03 11:58:58 +00:00
{
2023-04-05 15:34:47 +03:00
if config . display_preamble ( ) & & terminal ::supports_notify_send ( ) & & ! config . skip_notify ( ) {
2023-03-03 11:58:58 +00:00
print_warning ( " Due to a design issue with notify-send it could be that topgrade hangs when it's finished.
2023-01-29 19:19:27 +00:00
If this is the case on your system add the - - skip - notify flag to the topgrade command or set skip_notify = true in the config file .
If you don ' t want this message to appear any longer set display_preamble = false in the config file .
For more information about this issue see https ://askubuntu.com/questions/110969/notify-send-ignores-timeout and https://github.com/topgrade-rs/topgrade/issues/288.");
2023-03-03 11:58:58 +00:00
}
2023-01-29 19:19:27 +00:00
}
2019-06-13 09:21:39 +03:00
if config . run_in_tmux ( ) & & env ::var ( " TOPGRADE_INSIDE_TMUX " ) . is_err ( ) {
2018-06-27 23:04:39 +03:00
#[ cfg(unix) ]
{
2022-11-15 10:30:26 -05:00
tmux ::run_in_tmux ( config . tmux_arguments ( ) ? ) ? ;
return Ok ( ( ) ) ;
2018-06-20 21:05:49 +03:00
}
}
2018-12-15 21:52:21 +02:00
let git = git ::Git ::new ( ) ;
let mut git_repos = git ::Repositories ::new ( & git ) ;
2018-11-07 14:31:44 +02:00
2023-03-13 19:23:37 +00:00
let sudo = config . sudo_command ( ) . map_or_else ( sudo ::Sudo ::detect , sudo ::Sudo ::new ) ;
2019-01-22 22:37:32 +02:00
let run_type = executor ::RunType ::new ( config . dry_run ( ) ) ;
2018-06-11 08:29:40 +03:00
2023-05-01 00:02:13 +05:30
let ctx = execution_context ::ExecutionContext ::new ( run_type , sudo , & git , & config ) ;
2020-02-08 22:13:56 +02:00
2020-02-09 13:41:55 +02:00
let mut runner = runner ::Runner ::new ( & ctx ) ;
2018-11-12 21:27:49 +02:00
#[ cfg(feature = " self-update " ) ]
{
2023-03-22 22:05:21 +01:00
let config_self_upgrade = env ::var ( " TOPGRADE_NO_SELF_UPGRADE " ) . is_err ( ) & & ! config . no_self_update ( ) ;
if ! run_type . dry ( ) & & config_self_upgrade {
2019-06-03 09:41:25 +03:00
let result = self_update ::self_update ( ) ;
2019-12-11 23:05:38 +02:00
if let Err ( e ) = & result {
#[ cfg(windows) ]
{
if e . downcast_ref ::< Upgraded > ( ) . is_some ( ) {
return result ;
}
2019-06-03 09:41:25 +03:00
}
2023-01-29 19:31:37 +00:00
print_warning ( format! ( " Self update error: {e} " ) ) ;
2018-11-12 21:27:49 +02:00
}
}
}
2018-11-07 14:31:44 +02:00
2020-07-01 21:03:19 +03:00
#[ cfg(windows) ]
let _self_rename = if config . self_rename ( ) {
Some ( crate ::self_renamer ::SelfRenamer ::create ( ) ? )
} else {
None
} ;
2018-06-20 20:26:08 +03:00
if let Some ( commands ) = config . pre_commands ( ) {
for ( name , command ) in commands {
2021-09-02 06:18:01 +03:00
generic ::run_custom_command ( name , command , & ctx ) ? ;
2018-06-20 20:26:08 +03:00
}
}
2022-11-24 14:15:43 -05:00
if config . pre_sudo ( ) {
2022-11-25 17:19:32 -05:00
if let Some ( sudo ) = ctx . sudo ( ) {
sudo . elevate ( & ctx ) ? ;
}
2022-11-24 14:15:43 -05:00
}
2019-08-14 21:36:57 +03:00
let powershell = powershell ::Powershell ::new ( ) ;
2020-07-02 11:15:56 +03:00
let should_run_powershell = powershell . profile ( ) . is_some ( ) & & config . should_run ( Step ::Powershell ) ;
2019-02-27 09:47:20 +02:00
2019-06-04 09:35:29 +03:00
#[ cfg(windows) ]
2020-08-21 21:10:54 +03:00
runner . execute ( Step ::Wsl , " WSL " , | | windows ::run_wsl_topgrade ( & ctx ) ) ? ;
2019-06-04 09:35:29 +03:00
2023-01-29 19:19:27 +00:00
#[ cfg(windows) ]
runner . execute ( Step ::WslUpdate , " WSL " , | | windows ::update_wsl ( & ctx ) ) ? ;
2019-06-05 14:15:45 +03:00
if let Some ( topgrades ) = config . remote_topgrades ( ) {
2020-08-02 06:29:16 +03:00
for remote_topgrade in topgrades . iter ( ) . filter ( | t | config . should_execute_remote ( t ) ) {
2023-01-29 19:19:27 +00:00
runner . execute ( Step ::Remotes , format! ( " Remote ( {remote_topgrade} ) " ) , | | {
2020-08-22 14:46:17 +03:00
remote ::ssh ::ssh_step ( & ctx , remote_topgrade )
2020-07-02 11:15:56 +03:00
} ) ? ;
2019-06-05 14:15:45 +03:00
}
}
2023-05-05 14:31:24 +05:30
#[ cfg(target_os = " linux " ) ]
// NOTE: Due to breaking `nu` updates, `packer.nu` needs to be updated before `nu` get updated
// by other package managers.
runner . execute ( Step ::Shell , " packer.nu " , | | linux ::run_packer_nu ( & ctx ) ) ? ;
2018-10-02 10:46:38 +03:00
#[ cfg(target_os = " linux " ) ]
let distribution = linux ::Distribution ::detect ( ) ;
2022-10-23 11:34:30 +00:00
#[ cfg(target_os = r# " linux " #) ]
2018-08-22 22:18:48 +03:00
{
2020-07-02 11:15:56 +03:00
match & distribution {
Ok ( distribution ) = > {
runner . execute ( Step ::System , " System update " , | | distribution . upgrade ( & ctx ) ) ? ;
}
Err ( e ) = > {
2023-01-29 19:19:27 +00:00
println! ( " Error detecting current distribution: {e} " ) ;
2018-10-02 10:46:38 +03:00
}
2018-08-22 22:18:48 +03:00
}
2022-01-26 22:52:52 +02:00
runner . execute ( Step ::ConfigUpdate , " config-update " , | | linux ::run_config_update ( & ctx ) ) ? ;
2020-12-16 13:43:38 +02:00
2020-12-30 10:35:50 +02:00
runner . execute ( Step ::BrewFormula , " Brew " , | | {
2022-05-13 20:59:13 +03:00
unix ::run_brew_formula ( & ctx , unix ::BrewVariant ::Path )
2020-12-30 10:35:50 +02:00
} ) ? ;
2018-06-28 07:47:51 +03:00
}
2018-08-22 22:18:48 +03:00
#[ cfg(windows) ]
2019-09-28 14:49:24 +03:00
{
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Chocolatey , " Chocolatey " , | | windows ::run_chocolatey ( & ctx ) ) ? ;
runner . execute ( Step ::Scoop , " Scoop " , | | windows ::run_scoop ( config . cleanup ( ) , run_type ) ) ? ;
2021-06-03 13:08:17 +03:00
runner . execute ( Step ::Winget , " Winget " , | | windows ::run_winget ( & ctx ) ) ? ;
2019-09-28 14:49:24 +03:00
}
2018-10-17 13:57:30 +03:00
2020-12-16 13:43:38 +02:00
#[ cfg(target_os = " macos " ) ]
2019-09-28 14:49:24 +03:00
{
2020-12-30 10:35:50 +02:00
runner . execute ( Step ::BrewFormula , " Brew (ARM) " , | | {
unix ::run_brew_formula ( & ctx , unix ::BrewVariant ::MacArm )
} ) ? ;
runner . execute ( Step ::BrewFormula , " Brew (Intel) " , | | {
unix ::run_brew_formula ( & ctx , unix ::BrewVariant ::MacIntel )
} ) ? ;
2022-05-13 20:59:13 +03:00
runner . execute ( Step ::BrewFormula , " Brew " , | | {
unix ::run_brew_formula ( & ctx , unix ::BrewVariant ::Path )
} ) ? ;
2020-12-30 10:35:50 +02:00
runner . execute ( Step ::BrewCask , " Brew Cask (ARM) " , | | {
unix ::run_brew_cask ( & ctx , unix ::BrewVariant ::MacArm )
2020-12-16 13:43:38 +02:00
} ) ? ;
2020-12-30 10:35:50 +02:00
runner . execute ( Step ::BrewCask , " Brew Cask (Intel) " , | | {
unix ::run_brew_cask ( & ctx , unix ::BrewVariant ::MacIntel )
2020-12-16 13:43:38 +02:00
} ) ? ;
2022-05-13 20:59:13 +03:00
runner . execute ( Step ::BrewCask , " Brew Cask " , | | {
unix ::run_brew_cask ( & ctx , unix ::BrewVariant ::Path )
} ) ? ;
2021-05-04 11:27:19 +03:00
runner . execute ( Step ::Macports , " MacPorts " , | | macos ::run_macports ( & ctx ) ) ? ;
2020-12-16 13:43:38 +02:00
}
2020-06-24 14:30:24 +03:00
2020-12-16 13:43:38 +02:00
#[ cfg(unix) ]
{
2020-07-11 08:00:35 +03:00
runner . execute ( Step ::Yadm , " yadm " , | | unix ::run_yadm ( & ctx ) ) ? ;
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Nix , " nix " , | | unix ::run_nix ( & ctx ) ) ? ;
2022-10-10 18:03:34 +00:00
runner . execute ( Step ::Guix , " guix " , | | unix ::run_guix ( & ctx ) ) ? ;
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::HomeManager , " home-manager " , | | unix ::run_home_manager ( run_type ) ) ? ;
runner . execute ( Step ::Asdf , " asdf " , | | unix ::run_asdf ( run_type ) ) ? ;
2021-09-02 06:14:56 +03:00
runner . execute ( Step ::Pkgin , " pkgin " , | | unix ::run_pkgin ( & ctx ) ) ? ;
2022-10-10 20:16:13 +00:00
runner . execute ( Step ::Bun , " bun " , | | unix ::run_bun ( & ctx ) ) ? ;
2019-09-28 14:49:24 +03:00
}
2019-06-25 22:47:36 -07:00
#[ cfg(target_os = " dragonfly " ) ]
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Pkg , " DragonFly BSD Packages " , | | {
2022-11-25 17:19:32 -05:00
dragonfly ::upgrade_packages ( ctx . sudo ( ) . as_ref ( ) , run_type )
2020-07-02 11:15:56 +03:00
} ) ? ;
2019-09-28 14:49:24 +03:00
2018-11-12 11:13:43 +02:00
#[ cfg(target_os = " freebsd " ) ]
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Pkg , " FreeBSD Packages " , | | {
2022-11-25 17:19:32 -05:00
freebsd ::upgrade_packages ( & ctx , ctx . sudo ( ) . as_ref ( ) , run_type )
2020-07-02 11:15:56 +03:00
} ) ? ;
2018-08-19 14:45:23 +03:00
2022-11-02 11:00:10 +01:00
#[ cfg(target_os = " openbsd " ) ]
runner . execute ( Step ::Pkg , " OpenBSD Packages " , | | {
2022-11-25 17:19:32 -05:00
openbsd ::upgrade_packages ( ctx . sudo ( ) . as_ref ( ) , run_type )
2022-11-02 11:00:10 +01:00
} ) ? ;
2021-09-02 16:54:31 +00:00
#[ cfg(target_os = " android " ) ]
runner . execute ( Step ::Pkg , " Termux Packages " , | | android ::upgrade_packages ( & ctx ) ) ? ;
2023-05-01 00:02:13 +05:30
let emacs = emacs ::Emacs ::new ( ) ;
2020-01-28 21:06:33 +02:00
if config . use_predefined_git_repos ( ) {
2020-01-28 21:04:59 +02:00
if config . should_run ( Step ::Emacs ) {
2020-01-29 21:31:14 +02:00
if ! emacs . is_doom ( ) {
if let Some ( directory ) = emacs . directory ( ) {
2020-03-04 10:32:58 +02:00
git_repos . insert_if_repo ( directory ) ;
2020-01-29 21:31:14 +02:00
}
2020-01-28 21:04:59 +02:00
}
2023-05-01 00:02:13 +05:30
git_repos . insert_if_repo ( HOME_DIR . join ( " .doom.d " ) ) ;
2019-01-27 20:04:46 +02:00
}
2018-09-05 11:17:15 +03:00
2020-01-28 21:04:59 +02:00
if config . should_run ( Step ::Vim ) {
2023-05-01 00:02:13 +05:30
git_repos . insert_if_repo ( HOME_DIR . join ( " .vim " ) ) ;
git_repos . insert_if_repo ( HOME_DIR . join ( " .config/nvim " ) ) ;
2020-01-28 21:04:59 +02:00
}
2018-05-30 07:53:19 +03:00
2023-05-01 00:02:13 +05:30
git_repos . insert_if_repo ( HOME_DIR . join ( " .ideavimrc " ) ) ;
git_repos . insert_if_repo ( HOME_DIR . join ( " .intellimacs " ) ) ;
2021-05-30 15:50:21 +03:00
2022-10-31 02:05:12 -04:00
if config . should_run ( Step ::Rcm ) {
2023-05-01 00:02:13 +05:30
git_repos . insert_if_repo ( HOME_DIR . join ( " .dotfiles " ) ) ;
2022-10-31 02:05:12 -04:00
}
2020-01-28 21:04:59 +02:00
#[ cfg(unix) ]
{
2023-05-01 00:02:13 +05:30
git_repos . insert_if_repo ( zsh ::zshrc ( ) ) ;
2020-05-12 08:51:42 +03:00
if config . should_run ( Step ::Tmux ) {
2023-05-01 00:02:13 +05:30
git_repos . insert_if_repo ( HOME_DIR . join ( " .tmux " ) ) ;
2020-05-12 08:51:42 +03:00
}
2023-05-01 00:02:13 +05:30
git_repos . insert_if_repo ( HOME_DIR . join ( " .config/fish " ) ) ;
git_repos . insert_if_repo ( XDG_DIRS . config_dir ( ) . join ( " openbox " ) ) ;
git_repos . insert_if_repo ( XDG_DIRS . config_dir ( ) . join ( " bspwm " ) ) ;
git_repos . insert_if_repo ( XDG_DIRS . config_dir ( ) . join ( " i3 " ) ) ;
git_repos . insert_if_repo ( XDG_DIRS . config_dir ( ) . join ( " sway " ) ) ;
2020-01-28 21:04:59 +02:00
}
2018-05-30 07:53:19 +03:00
2020-01-28 21:04:59 +02:00
#[ cfg(windows) ]
2020-03-04 10:32:58 +02:00
git_repos . insert_if_repo (
2023-05-01 00:02:13 +05:30
WINDOWS_DIRS
. cache_dir ( )
2020-01-28 21:04:59 +02:00
. join ( " Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState " ) ,
) ;
2021-02-02 22:28:22 +02:00
#[ cfg(windows) ]
2023-05-01 00:02:13 +05:30
windows ::insert_startup_scripts ( & mut git_repos ) . ok ( ) ;
2021-02-02 22:28:22 +02:00
2020-01-28 21:04:59 +02:00
if let Some ( profile ) = powershell . profile ( ) {
2020-03-04 10:32:58 +02:00
git_repos . insert_if_repo ( profile ) ;
2020-01-28 21:04:59 +02:00
}
2018-08-23 22:08:04 +03:00
}
2019-01-22 22:37:32 +02:00
if config . should_run ( Step ::GitRepos ) {
2018-09-03 11:51:09 -04:00
if let Some ( custom_git_repos ) = config . git_repos ( ) {
for git_repo in custom_git_repos {
2019-08-11 12:41:09 +03:00
git_repos . glob_insert ( git_repo ) ;
2018-09-03 11:51:09 -04:00
}
2018-05-30 07:53:19 +03:00
}
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::GitRepos , " Git repositories " , | | {
git . multi_pull_step ( & git_repos , & ctx )
} ) ? ;
2018-05-30 07:53:19 +03:00
}
2018-05-31 15:59:45 +03:00
2019-08-14 21:36:57 +03:00
if should_run_powershell {
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Powershell , " Powershell Modules Update " , | | {
2020-07-15 08:47:15 +03:00
powershell . update_modules ( & ctx )
2020-07-02 11:15:56 +03:00
} ) ? ;
2019-11-04 23:04:35 +02:00
}
2019-02-19 08:47:01 +02:00
#[ cfg(unix) ]
2019-11-04 23:04:35 +02:00
{
2023-05-01 00:02:13 +05:30
runner . execute ( Step ::Shell , " zr " , | | zsh ::run_zr ( run_type ) ) ? ;
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Shell , " antibody " , | | zsh ::run_antibody ( run_type ) ) ? ;
2023-02-26 23:45:43 +02:00
runner . execute ( Step ::Shell , " antidote " , | | zsh ::run_antidote ( & ctx ) ) ? ;
2023-05-01 00:02:13 +05:30
runner . execute ( Step ::Shell , " antigen " , | | zsh ::run_antigen ( run_type ) ) ? ;
runner . execute ( Step ::Shell , " zgenom " , | | zsh ::run_zgenom ( run_type ) ) ? ;
runner . execute ( Step ::Shell , " zplug " , | | zsh ::run_zplug ( run_type ) ) ? ;
runner . execute ( Step ::Shell , " zinit " , | | zsh ::run_zinit ( run_type ) ) ? ;
runner . execute ( Step ::Shell , " zi " , | | zsh ::run_zi ( run_type ) ) ? ;
runner . execute ( Step ::Shell , " zim " , | | zsh ::run_zim ( run_type ) ) ? ;
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Shell , " oh-my-zsh " , | | zsh ::run_oh_my_zsh ( & ctx ) ) ? ;
2023-05-18 01:17:37 +08:00
runner . execute ( Step ::Shell , " oh-my-bash " , | | unix ::run_oh_my_bash ( & ctx ) ) ? ;
2022-11-14 02:49:46 -05:00
runner . execute ( Step ::Shell , " fisher " , | | unix ::run_fisher ( run_type ) ) ? ;
2021-02-10 08:58:03 +02:00
runner . execute ( Step ::Shell , " bash-it " , | | unix ::run_bashit ( & ctx ) ) ? ;
2020-09-03 09:32:45 +03:00
runner . execute ( Step ::Shell , " oh-my-fish " , | | unix ::run_oh_my_fish ( & ctx ) ) ? ;
2021-04-12 04:14:14 -05:00
runner . execute ( Step ::Shell , " fish-plug " , | | unix ::run_fish_plug ( & ctx ) ) ? ;
2022-10-31 02:05:43 -04:00
runner . execute ( Step ::Shell , " fundle " , | | unix ::run_fundle ( & ctx ) ) ? ;
2023-05-01 00:02:13 +05:30
runner . execute ( Step ::Tmux , " tmux " , | | tmux ::run_tpm ( run_type ) ) ? ;
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Tldr , " TLDR " , | | unix ::run_tldr ( run_type ) ) ? ;
runner . execute ( Step ::Pearl , " pearl " , | | unix ::run_pearl ( run_type ) ) ? ;
2022-04-23 01:50:17 +05:30
#[ cfg(not(any(target_os = " macos " , target_os = " android " ))) ]
2021-10-25 21:31:13 +03:00
runner . execute ( Step ::GnomeShellExtensions , " Gnome Shell Extensions " , | | {
unix ::upgrade_gnome_extensions ( & ctx )
} ) ? ;
2023-05-01 00:02:13 +05:30
runner . execute ( Step ::Sdkman , " SDKMAN! " , | | unix ::run_sdkman ( config . cleanup ( ) , run_type ) ) ? ;
2022-10-31 02:05:12 -04:00
runner . execute ( Step ::Rcm , " rcm " , | | unix ::run_rcm ( & ctx ) ) ? ;
2023-05-18 01:18:03 +08:00
runner . execute ( Step ::Maza , " maza " , | | unix ::run_maza ( & ctx ) ) ? ;
2020-06-29 05:13:31 +02:00
}
2018-10-29 14:32:33 +02:00
#[ cfg(not(any(
target_os = " freebsd " ,
target_os = " openbsd " ,
target_os = " netbsd " ,
target_os = " dragonfly "
) ) ) ]
2021-02-17 19:41:52 +02:00
runner . execute ( Step ::Atom , " apm " , | | generic ::run_apm ( run_type ) ) ? ;
2021-02-17 16:46:29 +02:00
runner . execute ( Step ::Fossil , " fossil " , | | generic ::run_fossil ( run_type ) ) ? ;
2023-04-05 15:42:47 +03:00
runner . execute ( Step ::Rustup , " rustup " , | | generic ::run_rustup ( & ctx ) ) ? ;
2023-05-01 00:02:13 +05:30
runner . execute ( Step ::Juliaup , " juliaup " , | | generic ::run_juliaup ( run_type ) ) ? ;
2020-12-26 09:21:14 +02:00
runner . execute ( Step ::Dotnet , " .NET " , | | generic ::run_dotnet_upgrade ( & ctx ) ) ? ;
2020-08-28 16:16:23 +03:00
runner . execute ( Step ::Choosenim , " choosenim " , | | generic ::run_choosenim ( & ctx ) ) ? ;
2021-03-22 09:00:56 +02:00
runner . execute ( Step ::Cargo , " cargo " , | | generic ::run_cargo_update ( & ctx ) ) ? ;
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Flutter , " Flutter " , | | generic ::run_flutter_upgrade ( run_type ) ) ? ;
2022-11-19 19:04:33 -05:00
runner . execute ( Step ::Go , " go-global-update " , | | go ::run_go_global_update ( run_type ) ) ? ;
runner . execute ( Step ::Go , " gup " , | | go ::run_go_gup ( run_type ) ) ? ;
2021-11-18 20:45:34 +02:00
runner . execute ( Step ::Emacs , " Emacs " , | | emacs . upgrade ( & ctx ) ) ? ;
2022-10-10 20:24:41 +00:00
runner . execute ( Step ::Opam , " opam " , | | generic ::run_opam_update ( & ctx ) ) ? ;
2022-12-15 11:39:25 +00:00
runner . execute ( Step ::Vcpkg , " vcpkg " , | | generic ::run_vcpkg_update ( & ctx ) ) ? ;
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Pipx , " pipx " , | | generic ::run_pipx_update ( run_type ) ) ? ;
2022-01-15 06:50:42 +02:00
runner . execute ( Step ::Conda , " conda " , | | generic ::run_conda_update ( & ctx ) ) ? ;
2023-04-17 16:19:59 +02:00
runner . execute ( Step ::Mamba , " mamba " , | | generic ::run_mamba_update ( & ctx ) ) ? ;
2021-04-12 11:04:51 +03:00
runner . execute ( Step ::Pip3 , " pip3 " , | | generic ::run_pip3_update ( run_type ) ) ? ;
2023-01-29 19:19:27 +00:00
runner . execute ( Step ::PipReview , " pip-review " , | | generic ::run_pip_review_update ( & ctx ) ) ? ;
2023-05-20 23:03:59 +05:30
runner . execute ( Step ::PipReviewLocal , " pip-review (local) " , | | {
generic ::run_pip_review_local_update ( & ctx )
} ) ? ;
2023-01-29 19:19:27 +00:00
runner . execute ( Step ::Pipupgrade , " pipupgrade " , | | generic ::run_pipupgrade_update ( & ctx ) ) ? ;
2022-10-30 12:34:14 -04:00
runner . execute ( Step ::Ghcup , " ghcup " , | | generic ::run_ghcup_update ( run_type ) ) ? ;
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Stack , " stack " , | | generic ::run_stack_update ( run_type ) ) ? ;
runner . execute ( Step ::Tlmgr , " tlmgr " , | | generic ::run_tlmgr_update ( & ctx ) ) ? ;
2023-05-01 00:02:13 +05:30
runner . execute ( Step ::Myrepos , " myrepos " , | | generic ::run_myrepos_update ( run_type ) ) ? ;
runner . execute ( Step ::Chezmoi , " chezmoi " , | | generic ::run_chezmoi_update ( run_type ) ) ? ;
2020-09-23 18:31:11 +08:00
runner . execute ( Step ::Jetpack , " jetpack " , | | generic ::run_jetpack ( run_type ) ) ? ;
2023-05-01 00:02:13 +05:30
runner . execute ( Step ::Vim , " vim " , | | vim ::upgrade_vim ( & ctx ) ) ? ;
runner . execute ( Step ::Vim , " Neovim " , | | vim ::upgrade_neovim ( & ctx ) ) ? ;
2022-04-23 15:39:58 +03:00
runner . execute ( Step ::Vim , " The Ultimate vimrc " , | | vim ::upgrade_ultimate_vimrc ( & ctx ) ) ? ;
2023-05-01 00:02:13 +05:30
runner . execute ( Step ::Vim , " voom " , | | vim ::run_voom ( run_type ) ) ? ;
2022-02-06 18:48:06 -03:00
runner . execute ( Step ::Kakoune , " Kakoune " , | | kakoune ::upgrade_kak_plug ( & ctx ) ) ? ;
2022-12-14 09:12:39 +01:00
runner . execute ( Step ::Helix , " helix " , | | generic ::run_helix_grammars ( & ctx ) ) ? ;
2021-06-09 10:52:48 +03:00
runner . execute ( Step ::Node , " npm " , | | node ::run_npm_upgrade ( & ctx ) ) ? ;
2022-12-15 00:42:48 +03:00
runner . execute ( Step ::Yarn , " yarn " , | | node ::run_yarn_upgrade ( & ctx ) ) ? ;
runner . execute ( Step ::Pnpm , " pnpm " , | | node ::run_pnpm_upgrade ( & ctx ) ) ? ;
2022-03-05 20:59:19 +01:00
runner . execute ( Step ::Containers , " Containers " , | | containers ::run_containers ( & ctx ) ) ? ;
2020-10-01 15:59:06 -04:00
runner . execute ( Step ::Deno , " deno " , | | node ::deno_upgrade ( & ctx ) ) ? ;
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Composer , " composer " , | | generic ::run_composer_update ( & ctx ) ) ? ;
runner . execute ( Step ::Krew , " krew " , | | generic ::run_krew_upgrade ( run_type ) ) ? ;
2022-12-08 22:47:57 +01:00
runner . execute ( Step ::Helm , " helm " , | | generic ::run_helm_repo_update ( run_type ) ) ? ;
2023-05-01 00:02:13 +05:30
runner . execute ( Step ::Gem , " gem " , | | generic ::run_gem ( run_type ) ) ? ;
2023-01-29 19:19:27 +00:00
runner . execute ( Step ::RubyGems , " rubygems " , | | generic ::run_rubygems ( & ctx ) ) ? ;
2022-10-10 18:29:56 +00:00
runner . execute ( Step ::Julia , " julia " , | | generic ::update_julia_packages ( & ctx ) ) ? ;
2021-10-25 12:54:27 -06:00
runner . execute ( Step ::Haxelib , " haxelib " , | | generic ::run_haxelib_update ( & ctx ) ) ? ;
2020-07-30 06:27:29 +03:00
runner . execute ( Step ::Sheldon , " sheldon " , | | generic ::run_sheldon ( & ctx ) ) ? ;
2023-05-05 16:17:42 +08:00
runner . execute ( Step ::Stew , " stew " , | | generic ::run_stew ( run_type ) ) ? ;
2020-09-25 01:00:06 +08:00
runner . execute ( Step ::Rtcl , " rtcl " , | | generic ::run_rtcl ( & ctx ) ) ? ;
2021-05-29 01:59:27 -03:00
runner . execute ( Step ::Bin , " bin " , | | generic ::bin_update ( & ctx ) ) ? ;
2020-11-15 20:07:42 -08:00
runner . execute ( Step ::Gcloud , " gcloud " , | | {
generic ::run_gcloud_components_update ( run_type )
} ) ? ;
2021-02-15 20:43:36 +01:00
runner . execute ( Step ::Micro , " micro " , | | generic ::run_micro ( run_type ) ) ? ;
2021-03-14 13:12:38 +03:00
runner . execute ( Step ::Raco , " raco " , | | generic ::run_raco_update ( run_type ) ) ? ;
2021-11-15 07:09:02 +01:00
runner . execute ( Step ::Spicetify , " spicetify " , | | generic ::spicetify_upgrade ( & ctx ) ) ? ;
2022-04-03 17:25:07 -04:00
runner . execute ( Step ::GithubCliExtensions , " GitHub CLI Extensions " , | | {
2022-03-08 00:16:52 +01:00
generic ::run_ghcli_extensions_upgrade ( & ctx )
} ) ? ;
2018-06-06 11:27:43 +03:00
2018-06-27 23:04:39 +03:00
#[ cfg(target_os = " linux " ) ]
{
2023-01-29 19:19:27 +00:00
runner . execute ( Step ::AM , " am " , | | linux ::update_am ( & ctx ) ) ? ;
2023-05-09 14:03:06 +08:00
runner . execute ( Step ::AppMan , " appman " , | | linux ::run_appman ( & ctx ) ) ? ;
2022-05-07 09:14:20 +03:00
runner . execute ( Step ::DebGet , " deb-get " , | | linux ::run_deb_get ( & ctx ) ) ? ;
2022-01-24 11:10:21 +01:00
runner . execute ( Step ::Toolbx , " toolbx " , | | toolbx ::run_toolbx ( & ctx ) ) ? ;
2021-06-30 12:37:41 +02:00
runner . execute ( Step ::Flatpak , " Flatpak " , | | linux ::flatpak_update ( & ctx ) ) ? ;
2022-11-25 17:19:32 -05:00
runner . execute ( Step ::Snap , " snap " , | | linux ::run_snap ( ctx . sudo ( ) . as_ref ( ) , run_type ) ) ? ;
2021-10-25 21:33:58 +03:00
runner . execute ( Step ::Pacstall , " pacstall " , | | linux ::run_pacstall ( & ctx ) ) ? ;
2022-10-10 20:09:24 +00:00
runner . execute ( Step ::Pacdef , " pacdef " , | | linux ::run_pacdef ( & ctx ) ) ? ;
2022-10-14 16:46:21 +02:00
runner . execute ( Step ::Protonup , " protonup " , | | linux ::run_protonup_update ( & ctx ) ) ? ;
2022-10-27 00:12:38 +02:00
runner . execute ( Step ::Distrobox , " distrobox " , | | linux ::run_distrobox_update ( & ctx ) ) ? ;
2023-01-29 19:19:27 +00:00
runner . execute ( Step ::DkpPacman , " dkp-pacman " , | | linux ::run_dkp_pacman_update ( & ctx ) ) ? ;
2018-06-14 13:24:52 +03:00
}
2018-06-11 08:38:29 +03:00
if let Some ( commands ) = config . commands ( ) {
for ( name , command ) in commands {
2022-05-07 15:25:51 +03:00
if config . should_run_custom_command ( name ) {
runner . execute ( Step ::CustomCommands , name , | | {
generic ::run_custom_command ( name , command , & ctx )
} ) ? ;
}
2018-06-11 08:38:29 +03:00
}
}
2018-06-27 23:04:39 +03:00
#[ cfg(target_os = " linux " ) ]
{
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::System , " pihole " , | | {
2022-11-25 17:19:32 -05:00
linux ::run_pihole_update ( ctx . sudo ( ) . as_ref ( ) , run_type )
2020-07-02 11:15:56 +03:00
} ) ? ;
2021-03-23 06:33:30 +02:00
runner . execute ( Step ::Firmware , " Firmware upgrades " , | | linux ::run_fwupdmgr ( & ctx ) ) ? ;
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Restarts , " Restarts " , | | {
2022-11-25 17:19:32 -05:00
linux ::run_needrestart ( ctx . sudo ( ) . as_ref ( ) , run_type )
2020-07-02 11:15:56 +03:00
} ) ? ;
2018-05-31 09:19:27 +03:00
}
2018-06-27 23:04:39 +03:00
#[ cfg(target_os = " macos " ) ]
{
2022-06-17 11:10:21 +03:00
runner . execute ( Step ::Sparkle , " Sparkle " , | | macos ::run_sparkle ( & ctx ) ) ? ;
2021-04-06 09:52:55 +03:00
runner . execute ( Step ::Mas , " App Store " , | | macos ::run_mas ( run_type ) ) ? ;
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::System , " System upgrade " , | | macos ::upgrade_macos ( & ctx ) ) ? ;
2018-06-03 18:04:58 +03:00
}
2018-11-12 11:13:43 +02:00
#[ cfg(target_os = " freebsd " ) ]
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::System , " FreeBSD Upgrade " , | | {
2022-11-25 17:19:32 -05:00
freebsd ::upgrade_freebsd ( ctx . sudo ( ) . as_ref ( ) , run_type )
2020-07-02 11:15:56 +03:00
} ) ? ;
2018-11-12 11:13:43 +02:00
2022-11-02 11:00:10 +01:00
#[ cfg(target_os = " openbsd " ) ]
runner . execute ( Step ::System , " OpenBSD Upgrade " , | | {
2022-11-25 17:19:32 -05:00
openbsd ::upgrade_openbsd ( ctx . sudo ( ) . as_ref ( ) , run_type )
2022-11-02 11:00:10 +01:00
} ) ? ;
2018-08-22 22:18:48 +03:00
#[ cfg(windows) ]
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::System , " Windows update " , | | windows ::windows_update ( & ctx ) ) ? ;
2019-06-13 12:19:47 +02:00
2020-06-10 11:51:52 +03:00
if config . should_run ( Step ::Vagrant ) {
2020-06-16 21:02:50 +03:00
if let Ok ( boxes ) = vagrant ::collect_boxes ( & ctx ) {
for vagrant_box in boxes {
2020-07-02 11:15:56 +03:00
runner . execute ( Step ::Vagrant , format! ( " Vagrant ( {} ) " , vagrant_box . smart_name ( ) ) , | | {
2020-06-16 21:02:50 +03:00
vagrant ::topgrade_vagrant_box ( & ctx , & vagrant_box )
} ) ? ;
}
}
2020-06-10 11:51:52 +03:00
}
2022-04-23 15:09:54 +03:00
runner . execute ( Step ::Vagrant , " Vagrant boxes " , | | vagrant ::upgrade_vagrant_boxes ( & ctx ) ) ? ;
2020-06-10 11:51:52 +03:00
2020-02-09 13:41:55 +02:00
if ! runner . report ( ) . data ( ) . is_empty ( ) {
2018-12-05 11:34:08 +02:00
print_separator ( " Summary " ) ;
2018-06-03 18:04:58 +03:00
2020-07-02 11:15:56 +03:00
for ( key , result ) in runner . report ( ) . data ( ) {
2020-08-21 23:04:36 +03:00
print_result ( key , result ) ;
2018-06-03 18:04:58 +03:00
}
2018-10-02 11:36:10 +03:00
#[ cfg(target_os = " linux " ) ]
{
if let Ok ( distribution ) = & distribution {
distribution . show_summary ( ) ;
}
}
2018-11-15 11:37:08 +02:00
#[ cfg(target_os = " freebsd " ) ]
2022-11-25 17:19:32 -05:00
freebsd ::audit_packages ( ctx . sudo ( ) . as_ref ( ) ) . ok ( ) ;
2019-06-25 22:47:36 -07:00
#[ cfg(target_os = " dragonfly " ) ]
2022-11-25 17:19:32 -05:00
dragonfly ::audit_packages ( ctx . sudo ( ) . as_ref ( ) ) . ok ( ) ;
2018-05-29 23:48:30 +03:00
}
2020-08-30 07:40:06 +03:00
let mut post_command_failed = false ;
if let Some ( commands ) = config . post_commands ( ) {
for ( name , command ) in commands {
2021-09-02 06:18:01 +03:00
if generic ::run_custom_command ( name , command , & ctx ) . is_err ( ) {
2020-08-30 07:40:06 +03:00
post_command_failed = true ;
}
}
}
2019-06-16 09:09:05 +03:00
if config . keep_at_end ( ) {
2019-08-04 09:25:35 +03:00
print_info ( " \n (R)eboot \n (S)hell \n (Q)uit " ) ;
loop {
2021-02-13 06:26:50 +02:00
match get_key ( ) {
2021-10-28 22:05:35 +03:00
Ok ( Key ::Char ( 's' ) ) | Ok ( Key ::Char ( 'S' ) ) = > {
2022-11-08 05:54:35 -05:00
run_shell ( ) . context ( " Failed to execute shell " ) ? ;
2021-10-28 22:05:35 +03:00
}
Ok ( Key ::Char ( 'r' ) ) | Ok ( Key ::Char ( 'R' ) ) = > {
2022-11-08 05:54:35 -05:00
reboot ( ) . context ( " Failed to reboot " ) ? ;
2021-10-28 22:05:35 +03:00
}
Ok ( Key ::Char ( 'q' ) ) | Ok ( Key ::Char ( 'Q' ) ) = > ( ) ,
_ = > {
continue ;
}
2019-06-13 22:05:18 +03:00
}
2019-08-04 09:25:35 +03:00
break ;
2019-06-13 22:05:18 +03:00
}
2019-06-13 09:21:39 +03:00
}
2020-11-04 11:31:09 +02:00
let failed = post_command_failed | | runner . report ( ) . data ( ) . iter ( ) . any ( | ( _ , result ) | result . failed ( ) ) ;
2022-10-10 20:21:20 +00:00
if ! config . skip_notify ( ) {
terminal ::notify_desktop (
format! (
" Topgrade finished {} " ,
if failed { " with errors " } else { " successfully " }
) ,
2023-01-29 19:19:27 +00:00
Some ( Duration ::from_secs ( 10 ) ) ,
)
2022-10-10 20:21:20 +00:00
}
2020-11-04 11:31:09 +02:00
if failed {
2019-12-11 23:05:38 +02:00
Err ( StepFailed . into ( ) )
2020-07-02 11:15:56 +03:00
} else {
Ok ( ( ) )
2018-06-11 08:57:55 +03:00
}
}
fn main ( ) {
match run ( ) {
Ok ( ( ) ) = > {
exit ( 0 ) ;
}
Err ( error ) = > {
2019-06-03 09:41:25 +03:00
#[ cfg(all(windows, feature = " self-update " )) ]
{
2019-12-11 23:05:38 +02:00
if let Some ( Upgraded ( status ) ) = error . downcast_ref ::< Upgraded > ( ) {
2019-06-03 09:41:25 +03:00
exit ( status . code ( ) . unwrap ( ) ) ;
}
}
2019-12-11 23:05:38 +02:00
let skip_print = ( error . downcast_ref ::< StepFailed > ( ) . is_some ( ) )
| | ( error
. downcast_ref ::< io ::Error > ( )
2018-12-11 16:43:26 +02:00
. filter ( | io_error | io_error . kind ( ) = = io ::ErrorKind ::Interrupted )
2019-12-11 23:05:38 +02:00
. is_some ( ) ) ;
2018-12-11 16:43:26 +02:00
2019-12-11 23:05:38 +02:00
if ! skip_print {
2022-11-11 09:39:29 -05:00
// The `Debug` implementation of `eyre::Result` prints a multi-line
2022-11-03 12:46:43 -04:00
// error message that includes all the 'causes' added with
// `.with_context(...)` calls.
2023-01-29 19:19:27 +00:00
println! ( " Error: {error:?} " ) ;
2018-10-17 14:07:58 +03:00
}
2018-06-11 08:57:55 +03:00
exit ( 1 ) ;
}
}
2018-05-29 23:48:30 +03:00
}
2022-11-16 13:43:57 -05:00
pub fn install_tracing ( filter_directives : & str ) -> Result < ( ) > {
use tracing_subscriber ::fmt ;
use tracing_subscriber ::fmt ::format ::FmtSpan ;
use tracing_subscriber ::layer ::SubscriberExt ;
use tracing_subscriber ::util ::SubscriberInitExt ;
use tracing_subscriber ::EnvFilter ;
let env_filter = EnvFilter ::try_new ( filter_directives )
. or_else ( | _ | EnvFilter ::try_from_default_env ( ) )
. or_else ( | _ | EnvFilter ::try_new ( " info " ) ) ? ;
let fmt_layer = fmt ::layer ( )
. with_target ( false )
. with_span_events ( FmtSpan ::NEW | FmtSpan ::CLOSE )
. without_time ( ) ;
let registry = tracing_subscriber ::registry ( ) ;
registry . with ( env_filter ) . with ( fmt_layer ) . init ( ) ;
Ok ( ( ) )
}