2020-04-03 12:19:55 +03:00
#![ allow(unused_imports) ]
2022-01-15 06:50:42 +02:00
use std ::path ::PathBuf ;
use std ::process ::Command ;
use std ::{ env , path ::Path } ;
use std ::{ fs , io ::Write } ;
2022-11-11 09:39:29 -05:00
use color_eyre ::eyre ::eyre ;
use color_eyre ::eyre ::Context ;
use color_eyre ::eyre ::Result ;
2022-01-15 06:50:42 +02:00
use tempfile ::tempfile_in ;
2023-01-29 19:19:27 +00:00
use tracing ::{ debug , error } ;
2022-01-15 06:50:42 +02:00
2022-11-08 05:54:35 -05:00
use crate ::command ::{ CommandExt , Utf8Output } ;
2020-02-08 22:13:56 +02:00
use crate ::execution_context ::ExecutionContext ;
2023-05-25 15:09:23 +08:00
use crate ::executor ::ExecutorOutput ;
2019-08-22 21:46:06 +03:00
use crate ::terminal ::{ print_separator , shell } ;
2023-06-23 17:02:58 +08:00
use crate ::utils ::{ self , check_is_python_2_or_shim , require , require_option , which , PathExt , REQUIRE_SUDO } ;
2023-04-17 16:19:59 +02:00
use crate ::Step ;
2023-05-01 00:02:13 +05:30
use crate ::HOME_DIR ;
2021-02-08 06:31:14 +02:00
use crate ::{
2023-01-29 19:19:27 +00:00
error ::{ SkipStep , StepFailed , TopgradeError } ,
2021-02-08 06:31:14 +02:00
terminal ::print_warning ,
} ;
2018-08-19 14:45:23 +03:00
2021-03-22 09:00:56 +02:00
pub fn run_cargo_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2021-05-05 13:52:12 +03:00
let cargo_dir = env ::var_os ( " CARGO_HOME " )
. map ( PathBuf ::from )
2023-05-01 00:02:13 +05:30
. unwrap_or_else ( | | HOME_DIR . join ( " .cargo " ) )
2021-05-05 13:52:12 +03:00
. require ( ) ? ;
2023-05-27 17:41:42 +08:00
require ( " cargo " ) . or_else ( | _ | {
2021-06-04 14:17:40 +03:00
require_option (
cargo_dir . join ( " bin/cargo " ) . if_exists ( ) ,
String ::from ( " No cargo detected " ) ,
)
} ) ? ;
2021-05-05 13:52:12 +03:00
let toml_file = cargo_dir . join ( " .crates.toml " ) . require ( ) ? ;
2021-03-22 09:00:56 +02:00
2021-05-05 13:52:12 +03:00
if fs ::metadata ( & toml_file ) ? . len ( ) = = 0 {
return Err ( SkipStep ( format! ( " {} exists but empty " , & toml_file . display ( ) ) ) . into ( ) ) ;
2021-03-22 09:00:56 +02:00
}
2021-02-13 06:39:06 +02:00
2019-01-13 23:20:32 +02:00
print_separator ( " Cargo " ) ;
2023-05-27 17:41:42 +08:00
let cargo_update = require ( " cargo-install-update " )
2021-06-04 14:17:40 +03:00
. ok ( )
. or_else ( | | cargo_dir . join ( " bin/cargo-install-update " ) . if_exists ( ) ) ;
let cargo_update = match cargo_update {
Some ( e ) = > e ,
None = > {
let message = String ::from ( " cargo-update isn't installed so Topgrade can't upgrade cargo packages. \n Install cargo-update by running `cargo install cargo-update` " ) ;
print_warning ( & message ) ;
return Err ( SkipStep ( message ) . into ( ) ) ;
2021-02-08 06:31:14 +02:00
}
} ;
2021-03-22 09:00:56 +02:00
ctx . run_type ( )
2019-01-13 23:20:32 +02:00
. execute ( cargo_update )
2022-10-23 11:34:30 +00:00
. args ( [ " install-update " , " --git " , " --all " ] )
2023-03-03 19:58:15 +08:00
. status_checked ( ) ? ;
if ctx . config ( ) . cleanup ( ) {
2023-05-27 17:41:42 +08:00
let cargo_cache = require ( " cargo-cache " )
2023-03-03 19:58:15 +08:00
. ok ( )
. or_else ( | | cargo_dir . join ( " bin/cargo-cache " ) . if_exists ( ) ) ;
match cargo_cache {
Some ( e ) = > {
ctx . run_type ( ) . execute ( e ) . args ( [ " -a " ] ) . status_checked ( ) ? ;
}
None = > {
let message = String ::from ( " cargo-cache isn't installed so Topgrade can't cleanup cargo packages. \n Install cargo-cache by running `cargo install cargo-cache` " ) ;
print_warning ( message ) ;
}
}
}
Ok ( ( ) )
2018-08-19 14:45:23 +03:00
}
2023-05-25 15:09:23 +08:00
pub fn run_flutter_upgrade ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let flutter = require ( " flutter " ) ? ;
2019-11-20 13:35:41 +02:00
2019-11-20 14:41:05 +02:00
print_separator ( " Flutter " ) ;
2023-05-25 15:09:23 +08:00
ctx . run_type ( ) . execute ( flutter ) . arg ( " upgrade " ) . status_checked ( )
2022-11-23 15:23:00 +00:00
}
2023-05-25 15:09:23 +08:00
pub fn run_gem ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let gem = require ( " gem " ) ? ;
2023-05-01 00:02:13 +05:30
HOME_DIR . join ( " .gem " ) . require ( ) ? ;
2018-09-06 16:46:49 +03:00
2022-11-24 20:21:03 +01:00
print_separator ( " Gems " ) ;
2018-09-06 16:46:49 +03:00
2023-05-25 15:09:23 +08:00
let mut command = ctx . run_type ( ) . execute ( gem ) ;
2020-08-01 15:13:04 +03:00
command . arg ( " update " ) ;
if env ::var_os ( " RBENV_SHELL " ) . is_none ( ) {
debug! ( " Detected rbenv. Avoiding --user-install " ) ;
command . arg ( " --user-install " ) ;
}
2022-11-08 05:54:35 -05:00
command . status_checked ( )
2018-09-06 16:46:49 +03:00
}
2023-01-29 19:19:27 +00:00
pub fn run_rubygems ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-01 00:02:13 +05:30
HOME_DIR . join ( " .gem " ) . require ( ) ? ;
2023-02-02 21:48:48 +00:00
let gem = require ( " gem " ) ? ;
2022-11-24 20:21:03 +01:00
print_separator ( " RubyGems " ) ;
2023-02-02 21:48:48 +00:00
let gem_path_str = gem . as_os_str ( ) ;
if gem_path_str . to_str ( ) . unwrap ( ) . contains ( " asdf " ) {
ctx . run_type ( )
. execute ( gem )
. args ( [ " update " , " --system " ] )
. status_checked ( ) ? ;
2023-06-13 22:15:57 +08:00
} else {
let sudo = require_option ( ctx . sudo ( ) . as_ref ( ) , REQUIRE_SUDO . to_string ( ) ) ? ;
2023-05-27 17:41:42 +08:00
if ! Path ::new ( " /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb " ) . exists ( ) {
2023-01-29 19:19:27 +00:00
ctx . run_type ( )
. execute ( sudo )
. arg ( " -EH " )
2023-02-02 21:48:48 +00:00
. arg ( gem )
2023-01-29 19:19:27 +00:00
. args ( [ " update " , " --system " ] )
. status_checked ( ) ? ;
}
2022-12-15 20:27:27 +00:00
}
2023-06-13 22:15:57 +08:00
2023-01-29 19:19:27 +00:00
Ok ( ( ) )
2022-11-24 20:21:03 +01:00
}
2021-10-25 12:54:27 -06:00
pub fn run_haxelib_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let haxelib = require ( " haxelib " ) ? ;
2021-10-25 12:54:27 -06:00
let haxelib_dir =
2022-11-08 05:54:35 -05:00
PathBuf ::from ( std ::str ::from_utf8 ( & Command ::new ( & haxelib ) . arg ( " config " ) . output_checked ( ) ? . stdout ) ? . trim ( ) )
. require ( ) ? ;
2021-10-25 12:54:27 -06:00
let directory_writable = tempfile_in ( & haxelib_dir ) . is_ok ( ) ;
debug! ( " {:?} writable: {} " , haxelib_dir , directory_writable ) ;
print_separator ( " haxelib " ) ;
let mut command = if directory_writable {
ctx . run_type ( ) . execute ( & haxelib )
} else {
2023-06-13 22:15:57 +08:00
let sudo = require_option ( ctx . sudo ( ) . as_ref ( ) , REQUIRE_SUDO . to_string ( ) ) ? ;
let mut c = ctx . run_type ( ) . execute ( sudo ) ;
2021-10-25 12:54:27 -06:00
c . arg ( & haxelib ) ;
c
} ;
2022-11-08 05:54:35 -05:00
command . arg ( " update " ) . status_checked ( )
2021-10-25 12:54:27 -06:00
}
2020-07-30 06:27:29 +03:00
pub fn run_sheldon ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let sheldon = require ( " sheldon " ) ? ;
2020-07-30 06:27:29 +03:00
print_separator ( " Sheldon " ) ;
2022-11-08 05:54:35 -05:00
ctx . run_type ( )
. execute ( sheldon )
. args ( [ " lock " , " --update " ] )
. status_checked ( )
2020-07-30 06:27:29 +03:00
}
2023-05-25 15:09:23 +08:00
pub fn run_fossil ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let fossil = require ( " fossil " ) ? ;
2021-02-17 16:46:29 +02:00
print_separator ( " Fossil " ) ;
2023-05-25 15:09:23 +08:00
ctx . run_type ( ) . execute ( fossil ) . args ( [ " all " , " sync " ] ) . status_checked ( )
2021-02-17 16:46:29 +02:00
}
2023-05-25 15:09:23 +08:00
pub fn run_micro ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let micro = require ( " micro " ) ? ;
2021-02-15 20:43:36 +01:00
print_separator ( " micro " ) ;
2023-05-25 15:09:23 +08:00
let stdout = ctx
. run_type ( )
2022-11-08 05:54:35 -05:00
. execute ( micro )
. args ( [ " -plugin " , " update " ] )
. output_checked_utf8 ( ) ?
. stdout ;
2021-09-02 07:27:09 +03:00
std ::io ::stdout ( ) . write_all ( stdout . as_bytes ( ) ) ? ;
2021-02-15 20:43:36 +01:00
if stdout . contains ( " Nothing to install / update " ) | | stdout . contains ( " One or more plugins installed " ) {
Ok ( ( ) )
} else {
2022-11-11 09:39:29 -05:00
Err ( eyre! ( " micro output does not indicate success: {} " , stdout ) )
2021-02-15 20:43:36 +01:00
}
}
2018-10-29 14:32:33 +02:00
#[ cfg(not(any(
target_os = " freebsd " ,
target_os = " openbsd " ,
target_os = " netbsd " ,
target_os = " dragonfly "
) ) ) ]
2023-05-25 15:09:23 +08:00
pub fn run_apm ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let apm = require ( " apm " ) ? ;
2018-08-19 14:45:23 +03:00
2019-01-13 23:20:32 +02:00
print_separator ( " Atom Package Manager " ) ;
2018-08-19 14:45:23 +03:00
2023-05-25 15:09:23 +08:00
ctx . run_type ( )
2022-11-08 05:54:35 -05:00
. execute ( apm )
. args ( [ " upgrade " , " --confirm=false " ] )
. status_checked ( )
2018-08-19 14:45:23 +03:00
}
2023-04-05 15:42:47 +03:00
pub fn run_rustup ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let rustup = require ( " rustup " ) ? ;
2018-08-19 14:45:23 +03:00
2019-01-13 23:20:32 +02:00
print_separator ( " rustup " ) ;
2023-04-05 15:42:47 +03:00
ctx . run_type ( ) . execute ( rustup ) . arg ( " update " ) . status_checked ( )
2018-08-19 14:45:23 +03:00
}
2023-05-25 15:09:23 +08:00
pub fn run_juliaup ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let juliaup = require ( " juliaup " ) ? ;
2022-11-24 14:17:58 -05:00
print_separator ( " juliaup " ) ;
2023-05-01 00:02:13 +05:30
if juliaup . canonicalize ( ) ? . is_descendant_of ( & HOME_DIR ) {
2023-05-25 15:09:23 +08:00
ctx . run_type ( )
. execute ( & juliaup )
. args ( [ " self " , " update " ] )
. status_checked ( ) ? ;
2022-11-24 14:17:58 -05:00
}
2023-05-25 15:09:23 +08:00
ctx . run_type ( ) . execute ( & juliaup ) . arg ( " update " ) . status_checked ( )
2022-11-24 14:17:58 -05:00
}
2020-08-28 16:16:23 +03:00
pub fn run_choosenim ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let choosenim = require ( " choosenim " ) ? ;
2020-08-28 16:16:23 +03:00
print_separator ( " choosenim " ) ;
let run_type = ctx . run_type ( ) ;
2022-11-08 05:54:35 -05:00
run_type . execute ( & choosenim ) . args ( [ " update " , " self " ] ) . status_checked ( ) ? ;
run_type . execute ( & choosenim ) . args ( [ " update " , " stable " ] ) . status_checked ( )
2020-08-28 16:16:23 +03:00
}
2023-05-25 15:09:23 +08:00
pub fn run_krew_upgrade ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let krew = require ( " kubectl-krew " ) ? ;
2020-06-29 05:13:31 +02:00
print_separator ( " Krew " ) ;
2023-05-25 15:09:23 +08:00
ctx . run_type ( ) . execute ( krew ) . args ( [ " upgrade " ] ) . status_checked ( )
2020-06-29 05:13:31 +02:00
}
2023-05-25 15:09:23 +08:00
pub fn run_gcloud_components_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let gcloud = require ( " gcloud " ) ? ;
2020-11-15 20:07:42 -08:00
2022-11-04 09:48:05 -04:00
if gcloud . starts_with ( " /snap " ) {
Ok ( ( ) )
} else {
print_separator ( " gcloud " ) ;
2020-11-15 20:07:42 -08:00
2023-05-25 15:09:23 +08:00
ctx . run_type ( )
2022-11-04 09:48:05 -04:00
. execute ( gcloud )
. args ( [ " components " , " update " , " --quiet " ] )
2022-11-08 05:54:35 -05:00
. status_checked ( )
2022-11-04 09:48:05 -04:00
}
2020-11-15 20:07:42 -08:00
}
2023-05-25 15:09:23 +08:00
pub fn run_jetpack ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let jetpack = require ( " jetpack " ) ? ;
2018-10-18 16:05:27 +03:00
2019-01-13 23:20:32 +02:00
print_separator ( " Jetpack " ) ;
2018-10-18 16:05:27 +03:00
2023-05-25 15:09:23 +08:00
ctx . run_type ( )
. execute ( jetpack )
. args ( [ " global " , " update " ] )
. status_checked ( )
2018-10-18 16:05:27 +03:00
}
2020-09-25 01:00:06 +08:00
pub fn run_rtcl ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let rupdate = require ( " rupdate " ) ? ;
2020-09-25 01:00:06 +08:00
print_separator ( " rtcl " ) ;
2022-11-08 05:54:35 -05:00
ctx . run_type ( ) . execute ( rupdate ) . status_checked ( )
2020-09-25 01:00:06 +08:00
}
2022-10-10 20:24:41 +00:00
pub fn run_opam_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let opam = require ( " opam " ) ? ;
2018-09-03 13:45:01 +02:00
2019-01-13 23:20:32 +02:00
print_separator ( " OCaml Package Manager " ) ;
2018-09-03 13:45:01 +02:00
2022-11-08 05:54:35 -05:00
ctx . run_type ( ) . execute ( & opam ) . arg ( " update " ) . status_checked ( ) ? ;
2023-10-10 02:08:46 +02:00
let mut command = ctx . run_type ( ) . execute ( & opam ) ;
command . arg ( " upgrade " ) ;
if ctx . config ( ) . yes ( Step ::Opam ) {
command . arg ( " --yes " ) ;
}
command . status_checked ( ) ? ;
2022-10-10 20:24:41 +00:00
if ctx . config ( ) . cleanup ( ) {
2022-11-08 05:54:35 -05:00
ctx . run_type ( ) . execute ( & opam ) . arg ( " clean " ) . status_checked ( ) ? ;
2022-10-10 20:24:41 +00:00
}
Ok ( ( ) )
2018-09-03 13:45:01 +02:00
}
2022-12-15 11:39:25 +00:00
pub fn run_vcpkg_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let vcpkg = require ( " vcpkg " ) ? ;
2019-01-13 23:20:32 +02:00
print_separator ( " vcpkg " ) ;
2018-11-10 20:22:26 +02:00
2022-12-15 11:39:25 +00:00
#[ cfg(unix) ]
let is_root_install = ! & vcpkg . starts_with ( " /home " ) ;
#[ cfg(not(unix)) ]
let is_root_install = false ;
let mut command = if is_root_install {
ctx . run_type ( ) . execute ( & vcpkg )
} else {
2023-06-13 22:15:57 +08:00
let sudo = require_option ( ctx . sudo ( ) . as_ref ( ) , REQUIRE_SUDO . to_string ( ) ) ? ;
let mut c = ctx . run_type ( ) . execute ( sudo ) ;
2022-12-15 11:39:25 +00:00
c . arg ( & vcpkg ) ;
c
} ;
command . args ( [ " upgrade " , " --no-dry-run " ] ) . status_checked ( )
2018-11-10 20:22:26 +02:00
}
2023-08-14 03:22:26 +02:00
pub fn run_vscode_extensions_upgrade ( ctx : & ExecutionContext ) -> Result < ( ) > {
let vscode = require ( " code " ) ? ;
print_separator ( " Visual Studio Code extensions " ) ;
// Vscode does not have CLI command to upgrade all extensions (see https://github.com/microsoft/vscode/issues/56578)
// Instead we get the list of installed extensions with `code --list-extensions` command (obtain a line-return separated list of installed extensions)
let extensions = Command ::new ( & vscode )
. arg ( " --list-extensions " )
. output_checked_utf8 ( ) ?
. stdout ;
// Then we construct the upgrade command: `code --force --install-extension [ext0] --install-extension [ext1] ... --install-extension [extN]`
if ! extensions . is_empty ( ) {
let mut command_args = vec! [ " --force " ] ;
for extension in extensions . split_whitespace ( ) {
command_args . extend ( [ " --install-extension " , extension ] ) ;
}
ctx . run_type ( ) . execute ( & vscode ) . args ( command_args ) . status_checked ( ) ? ;
}
Ok ( ( ) )
}
2023-05-25 15:09:23 +08:00
pub fn run_pipx_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let pipx = require ( " pipx " ) ? ;
2019-01-13 23:20:32 +02:00
print_separator ( " pipx " ) ;
2018-10-31 13:01:57 +02:00
2023-05-25 15:09:23 +08:00
ctx . run_type ( ) . execute ( pipx ) . arg ( " upgrade-all " ) . status_checked ( )
2018-10-31 13:01:57 +02:00
}
2022-01-15 06:50:42 +02:00
pub fn run_conda_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let conda = require ( " conda " ) ? ;
2022-01-24 22:05:52 +02:00
let output = Command ::new ( " conda " )
2022-10-23 11:34:30 +00:00
. args ( [ " config " , " --show " , " auto_activate_base " ] )
2022-11-08 05:54:35 -05:00
. output_checked_utf8 ( ) ? ;
debug! ( " Conda output: {} " , output . stdout ) ;
if output . stdout . contains ( " False " ) {
2022-01-24 22:05:52 +02:00
return Err ( SkipStep ( " auto_activate_base is set to False " . to_string ( ) ) . into ( ) ) ;
}
2022-01-15 06:50:42 +02:00
print_separator ( " Conda " ) ;
2023-04-17 16:19:59 +02:00
let mut command = ctx . run_type ( ) . execute ( conda ) ;
2023-07-14 17:11:18 +01:00
command . args ( [ " update " , " --all " , " -n " , " base " ] ) ;
2023-04-17 16:19:59 +02:00
if ctx . config ( ) . yes ( Step ::Conda ) {
command . arg ( " --yes " ) ;
}
command . status_checked ( )
}
pub fn run_mamba_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let mamba = require ( " mamba " ) ? ;
2023-04-17 16:19:59 +02:00
let output = Command ::new ( " mamba " )
. args ( [ " config " , " --show " , " auto_activate_base " ] )
. output_checked_utf8 ( ) ? ;
debug! ( " Mamba output: {} " , output . stdout ) ;
if output . stdout . contains ( " False " ) {
return Err ( SkipStep ( " auto_activate_base is set to False " . to_string ( ) ) . into ( ) ) ;
}
print_separator ( " Mamba " ) ;
let mut command = ctx . run_type ( ) . execute ( mamba ) ;
2023-07-14 17:11:18 +01:00
command . args ( [ " update " , " --all " , " -n " , " base " ] ) ;
2023-04-17 16:19:59 +02:00
if ctx . config ( ) . yes ( Step ::Mamba ) {
command . arg ( " --yes " ) ;
}
command . status_checked ( )
2022-01-15 06:50:42 +02:00
}
2023-08-13 04:05:07 +02:00
pub fn run_miktex_packages_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
let miktex = require ( " miktex " ) ? ;
print_separator ( " miktex " ) ;
ctx . run_type ( )
. execute ( miktex )
. args ( [ " packages " , " update " ] )
. status_checked ( )
}
2023-05-25 15:09:23 +08:00
pub fn run_pip3_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-06-23 17:02:58 +08:00
let py = require ( " python " ) . and_then ( check_is_python_2_or_shim ) ;
let py3 = require ( " python3 " ) . and_then ( check_is_python_2_or_shim ) ;
let python3 = match ( py , py3 ) {
// prefer `python` if it is available and is a valid Python 3.
( Ok ( py ) , _ ) = > py ,
( Err ( _ ) , Ok ( py3 ) ) = > py3 ,
( Err ( py_err ) , Err ( py3_err ) ) = > {
return Err ( SkipStep ( format! ( " Skip due to following reasons: {} {} " , py_err , py3_err ) ) . into ( ) ) ;
}
} ;
2022-05-01 20:47:14 +03:00
Command ::new ( & python3 )
2022-10-23 11:34:30 +00:00
. args ( [ " -m " , " pip " ] )
2022-11-08 05:54:35 -05:00
. output_checked_utf8 ( )
2023-09-17 03:40:04 -04:00
. map_err ( | _ | SkipStep ( " pip does not exist " . to_string ( ) ) ) ? ;
2022-05-01 20:47:14 +03:00
2023-02-23 14:01:26 -08:00
let check_externally_managed = " import sysconfig; from os import path; print('Y') if path.isfile(path.join(sysconfig.get_path('stdlib'), 'EXTERNALLY-MANAGED')) else print('N') " ;
Command ::new ( & python3 )
. args ( [ " -c " , check_externally_managed ] )
. output_checked_utf8 ( )
. map_err ( | _ | SkipStep ( " pip may be externally managed " . to_string ( ) ) )
. and_then ( | output | match output . stdout . trim ( ) {
" N " = > Ok ( ( ) ) ,
" Y " = > Err ( SkipStep ( " pip is externally managed " . to_string ( ) ) ) ,
_ = > {
print_warning ( " Unexpected output when checking EXTERNALLY-MANAGED " ) ;
print_warning ( output . stdout . trim ( ) ) ;
Err ( SkipStep ( " pip may be externally managed " . to_string ( ) ) )
}
} ) ? ;
2021-03-02 10:39:49 +01:00
print_separator ( " pip3 " ) ;
2023-05-27 17:41:42 +08:00
if env ::var ( " VIRTUAL_ENV " ) . is_ok ( ) {
2021-06-26 15:04:49 +03:00
print_warning ( " This step is will be skipped when running inside a virtual environment " ) ;
return Err ( SkipStep ( " Does not run inside a virtual environment " . to_string ( ) ) . into ( ) ) ;
}
2021-03-02 10:39:49 +01:00
2023-05-25 15:09:23 +08:00
ctx . run_type ( )
2022-05-01 20:47:14 +03:00
. execute ( & python3 )
2022-10-23 11:34:30 +00:00
. args ( [ " -m " , " pip " , " install " , " --upgrade " , " --user " , " pip " ] )
2022-11-08 05:54:35 -05:00
. status_checked ( )
2021-03-02 10:39:49 +01:00
}
2023-01-29 19:19:27 +00:00
pub fn run_pip_review_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
let pip_review = require ( " pip-review " ) ? ;
print_separator ( " pip-review " ) ;
if ! ctx . config ( ) . enable_pip_review ( ) {
print_warning (
" Pip-review is disabled by default. Enable it by setting enable_pip_review=true in the configuration. " ,
) ;
return Err ( SkipStep ( String ::from ( " Pip-review is disabled by default " ) ) . into ( ) ) ;
}
ctx . run_type ( )
. execute ( pip_review )
. arg ( " --auto " )
. status_checked_with_codes ( & [ 1 ] ) ? ;
Ok ( ( ) )
}
2023-05-20 23:03:59 +05:30
pub fn run_pip_review_local_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
let pip_review = require ( " pip-review " ) ? ;
print_separator ( " pip-review (local) " ) ;
if ! ctx . config ( ) . enable_pip_review_local ( ) {
print_warning (
" Pip-review (local) is disabled by default. Enable it by setting enable_pip_review_local=true in the configuration. " ,
) ;
return Err ( SkipStep ( String ::from ( " Pip-review (local) is disabled by default " ) ) . into ( ) ) ;
}
ctx . run_type ( )
. execute ( pip_review )
. arg ( " --local " )
. arg ( " --auto " )
. status_checked_with_codes ( & [ 1 ] ) ? ;
Ok ( ( ) )
}
2023-01-29 19:19:27 +00:00
pub fn run_pipupgrade_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
let pipupgrade = require ( " pipupgrade " ) ? ;
print_separator ( " Pipupgrade " ) ;
2023-05-30 03:04:23 -04:00
if ! ctx . config ( ) . enable_pipupgrade ( ) {
2023-01-29 19:19:27 +00:00
print_warning (
" Pipupgrade is disabled by default. Enable it by setting enable_pipupgrade=true in the configuration. " ,
) ;
return Err ( SkipStep ( String ::from ( " Pipupgrade is disabled by default " ) ) . into ( ) ) ;
}
2023-05-30 03:04:23 -04:00
ctx . run_type ( )
. execute ( pipupgrade )
. args ( ctx . config ( ) . pipupgrade_arguments ( ) . split_whitespace ( ) )
. status_checked ( ) ? ;
2023-01-29 19:19:27 +00:00
Ok ( ( ) )
}
2023-05-25 15:09:23 +08:00
pub fn run_stack_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
if require ( " ghcup " ) . is_ok ( ) {
2022-10-30 12:34:14 -04:00
// `ghcup` is present and probably(?) being used to install `stack`.
// Don't upgrade `stack`, let `ghcup` handle it. Per `ghcup install stack`:
// !!! Additionally, you should upgrade stack only through ghcup and not use 'stack upgrade' !!!
return Ok ( ( ) ) ;
}
2023-05-27 17:41:42 +08:00
let stack = require ( " stack " ) ? ;
2019-10-07 19:13:29 +02:00
print_separator ( " stack " ) ;
2023-05-25 15:09:23 +08:00
ctx . run_type ( ) . execute ( stack ) . arg ( " upgrade " ) . status_checked ( )
2019-10-07 19:13:29 +02:00
}
2023-05-25 15:09:23 +08:00
pub fn run_ghcup_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let ghcup = require ( " ghcup " ) ? ;
2022-10-30 12:34:14 -04:00
print_separator ( " ghcup " ) ;
2023-05-25 15:09:23 +08:00
ctx . run_type ( ) . execute ( ghcup ) . arg ( " upgrade " ) . status_checked ( )
2022-10-30 12:34:14 -04:00
}
2020-06-03 22:12:27 +03:00
pub fn run_tlmgr_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
cfg_if ::cfg_if! {
2022-04-23 01:50:17 +05:30
if #[ cfg(any(target_os = " linux " , target_os = " android " )) ] {
2020-06-03 22:12:27 +03:00
if ! ctx . config ( ) . enable_tlmgr_linux ( ) {
2022-04-23 01:50:17 +05:30
return Err ( SkipStep ( String ::from ( " tlmgr must be explicity enabled in the configuration to run in Android/Linux " ) ) . into ( ) ) ;
2020-06-03 22:12:27 +03:00
}
}
}
2023-05-27 17:41:42 +08:00
let tlmgr = require ( " tlmgr " ) ? ;
let kpsewhich = require ( " kpsewhich " ) ? ;
2019-12-12 20:24:22 +02:00
let tlmgr_directory = {
let mut d = PathBuf ::from (
2022-11-08 05:54:35 -05:00
& Command ::new ( kpsewhich )
. arg ( " -var-value=SELFAUTOPARENT " )
. output_checked_utf8 ( ) ?
. stdout
. trim ( ) ,
2019-12-12 20:24:22 +02:00
) ;
d . push ( " tlpkg " ) ;
d
}
. require ( ) ? ;
let directory_writable = tempfile_in ( & tlmgr_directory ) . is_ok ( ) ;
debug! ( " {:?} writable: {} " , tlmgr_directory , directory_writable ) ;
print_separator ( " TeX Live package manager " ) ;
let mut command = if directory_writable {
2020-06-03 22:12:27 +03:00
ctx . run_type ( ) . execute ( & tlmgr )
2019-12-12 20:24:22 +02:00
} else {
2023-06-13 22:15:57 +08:00
let sudo = require_option ( ctx . sudo ( ) . as_ref ( ) , REQUIRE_SUDO . to_string ( ) ) ? ;
let mut c = ctx . run_type ( ) . execute ( sudo ) ;
2019-12-12 20:24:22 +02:00
c . arg ( & tlmgr ) ;
c
} ;
2022-10-23 11:34:30 +00:00
command . args ( [ " update " , " --self " , " --all " ] ) ;
2019-12-12 20:24:22 +02:00
2022-11-08 05:54:35 -05:00
command . status_checked ( )
2019-12-12 20:24:22 +02:00
}
2023-05-25 15:09:23 +08:00
pub fn run_chezmoi_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let chezmoi = require ( " chezmoi " ) ? ;
2023-05-01 00:02:13 +05:30
HOME_DIR . join ( " .local/share/chezmoi " ) . require ( ) ? ;
2021-07-19 07:29:34 +02:00
print_separator ( " chezmoi " ) ;
2023-05-25 15:09:23 +08:00
ctx . run_type ( ) . execute ( chezmoi ) . arg ( " update " ) . status_checked ( )
2021-07-19 07:29:34 +02:00
}
2023-05-25 15:09:23 +08:00
pub fn run_myrepos_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let myrepos = require ( " mr " ) ? ;
2023-05-01 00:02:13 +05:30
HOME_DIR . join ( " .mrconfig " ) . require ( ) ? ;
2019-05-15 11:33:22 +02:00
print_separator ( " myrepos " ) ;
2023-05-25 15:09:23 +08:00
ctx . run_type ( )
2019-05-15 11:33:22 +02:00
. execute ( & myrepos )
. arg ( " --directory " )
2023-05-01 00:02:13 +05:30
. arg ( & * HOME_DIR )
2019-05-15 11:33:22 +02:00
. arg ( " checkout " )
2022-11-08 05:54:35 -05:00
. status_checked ( ) ? ;
2023-05-25 15:09:23 +08:00
ctx . run_type ( )
2019-05-15 11:33:22 +02:00
. execute ( & myrepos )
. arg ( " --directory " )
2023-05-01 00:02:13 +05:30
. arg ( & * HOME_DIR )
2019-05-15 11:33:22 +02:00
. arg ( " update " )
2022-11-08 05:54:35 -05:00
. status_checked ( )
2019-05-15 11:33:22 +02:00
}
2020-02-08 22:13:56 +02:00
pub fn run_custom_command ( name : & str , command : & str , ctx : & ExecutionContext ) -> Result < ( ) > {
2018-12-05 11:34:08 +02:00
print_separator ( name ) ;
2023-03-17 21:58:58 +05:30
let mut exec = ctx . run_type ( ) . execute ( shell ( ) ) ;
#[ cfg(unix) ]
let command = if let Some ( command ) = command . strip_prefix ( " -i " ) {
exec . arg ( " -i " ) ;
command
} else {
command
} ;
exec . arg ( " -c " ) . arg ( command ) . status_checked ( )
2018-08-19 14:45:23 +03:00
}
2018-10-02 13:45:29 +03:00
2020-03-08 21:38:25 +02:00
pub fn run_composer_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let composer = require ( " composer " ) ? ;
2019-01-13 23:20:32 +02:00
let composer_home = Command ::new ( & composer )
2022-10-23 11:34:30 +00:00
. args ( [ " global " , " config " , " --absolute " , " --quiet " , " home " ] )
2022-11-08 05:54:35 -05:00
. output_checked_utf8 ( )
2023-01-29 19:19:27 +00:00
. map_err ( | e | ( SkipStep ( format! ( " Error getting the composer directory: {e} " ) ) ) )
2022-11-08 05:54:35 -05:00
. map ( | s | PathBuf ::from ( s . stdout . trim ( ) ) ) ?
2019-12-11 23:05:38 +02:00
. require ( ) ? ;
2019-01-13 23:20:32 +02:00
2023-05-01 00:02:13 +05:30
if ! composer_home . is_descendant_of ( & HOME_DIR ) {
2020-08-21 23:04:36 +03:00
return Err ( SkipStep ( format! (
" Composer directory {} isn't a decandent of the user's home directory " ,
composer_home . display ( )
) )
. into ( ) ) ;
2019-01-13 23:20:32 +02:00
}
2018-12-17 10:53:05 +02:00
2019-01-13 23:20:32 +02:00
print_separator ( " Composer " ) ;
2018-12-17 10:53:05 +02:00
2020-03-08 21:38:25 +02:00
if ctx . config ( ) . composer_self_update ( ) {
cfg_if ::cfg_if! {
if #[ cfg(unix) ] {
// If self-update fails without sudo then there's probably an update
let has_update = match ctx . run_type ( ) . execute ( & composer ) . arg ( " self-update " ) . output ( ) ? {
ExecutorOutput ::Wet ( output ) = > ! output . status . success ( ) ,
_ = > false
} ;
if has_update {
2023-06-13 22:15:57 +08:00
let sudo = require_option ( ctx . sudo ( ) . as_ref ( ) , REQUIRE_SUDO . to_string ( ) ) ? ;
2020-03-08 21:38:25 +02:00
ctx . run_type ( )
2023-06-13 22:15:57 +08:00
. execute ( sudo )
2020-03-08 21:38:25 +02:00
. arg ( & composer )
. arg ( " self-update " )
2022-11-08 05:54:35 -05:00
. status_checked ( ) ? ;
2020-03-08 21:38:25 +02:00
}
} else {
2022-11-08 05:54:35 -05:00
ctx . run_type ( ) . execute ( & composer ) . arg ( " self-update " ) . status_checked ( ) ? ;
2020-03-08 21:38:25 +02:00
}
}
}
2022-11-08 05:54:35 -05:00
let output = ctx . run_type ( ) . execute ( & composer ) . args ( [ " global " , " update " ] ) . output ( ) ? ;
if let ExecutorOutput ::Wet ( output ) = output {
let output : Utf8Output = output . try_into ( ) ? ;
print! ( " {} \n {} " , output . stdout , output . stderr ) ;
if output . stdout . contains ( " valet " ) | | output . stderr . contains ( " valet " ) {
2023-05-27 17:41:42 +08:00
if let Some ( valet ) = which ( " valet " ) {
2022-11-08 05:54:35 -05:00
ctx . run_type ( ) . execute ( valet ) . arg ( " install " ) . status_checked ( ) ? ;
}
2020-02-10 21:10:06 +01:00
}
2018-10-02 13:45:29 +03:00
}
2019-01-13 23:20:32 +02:00
Ok ( ( ) )
2018-10-02 13:45:29 +03:00
}
2020-12-26 06:43:45 +02:00
pub fn run_dotnet_upgrade ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let dotnet = require ( " dotnet " ) ? ;
2020-12-26 06:43:45 +02:00
2023-05-25 15:24:53 +08:00
// Skip when the `dotnet tool list` subcommand fails.
// (This is expected when a dotnet runtime is installed but no SDK.)
2023-01-29 19:19:27 +00:00
let output = match ctx
. run_type ( )
. execute ( & dotnet )
. args ( [ " tool " , " list " , " --global " ] )
2023-10-12 14:37:52 +08:00
// dotnet will print a greeting message on its first run, from this question:
// https://stackoverflow.com/q/70493706/14092446
// Setting `DOTNET_NOLOGO` to `true` should disable it
. env ( " DOTNET_NOLOGO " , " true " )
2023-01-29 19:19:27 +00:00
. output_checked_utf8 ( )
{
Ok ( output ) = > output ,
Err ( _ ) = > {
return Err ( SkipStep ( String ::from (
" Error running `dotnet tool list`. This is expected when a dotnet runtime is installed but no SDK. " ,
) )
. into ( ) )
2022-12-18 14:12:36 +00:00
}
2023-01-29 19:19:27 +00:00
} ;
2020-12-26 06:43:45 +02:00
2023-05-25 15:24:53 +08:00
let mut packages = output
. stdout
. lines ( )
// Skip the header:
//
// Package Id Version Commands
// -------------------------------------
//
// One thing to note is that .NET SDK respect locale, which means this
// header can be printed in languages other than English, do NOT use it
// to do any check.
. skip ( 2 )
. filter ( | line | ! line . is_empty ( ) )
. peekable ( ) ;
2020-12-26 06:43:45 +02:00
2023-01-29 19:19:27 +00:00
if packages . peek ( ) . is_none ( ) {
return Err ( SkipStep ( String ::from ( " No dotnet global tools installed " ) ) . into ( ) ) ;
}
2020-12-26 06:43:45 +02:00
2023-01-29 19:19:27 +00:00
print_separator ( " .NET " ) ;
for package in packages {
let package_name = package . split_whitespace ( ) . next ( ) . unwrap ( ) ;
ctx . run_type ( )
. execute ( & dotnet )
. args ( [ " tool " , " update " , package_name , " --global " ] )
. status_checked ( )
. with_context ( | | format! ( " Failed to update .NET package {package_name} " ) ) ? ;
2022-12-18 14:12:36 +00:00
}
2023-01-29 19:19:27 +00:00
2020-12-26 06:43:45 +02:00
Ok ( ( ) )
}
2021-03-14 13:12:38 +03:00
2022-12-14 09:12:39 +01:00
pub fn run_helix_grammars ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
require ( " helix " ) ? ;
2022-12-14 09:12:39 +01:00
print_separator ( " Helix " ) ;
2023-06-13 22:15:57 +08:00
let sudo = require_option ( ctx . sudo ( ) . as_ref ( ) , REQUIRE_SUDO . to_string ( ) ) ? ;
2022-12-14 09:12:39 +01:00
ctx . run_type ( )
2023-06-13 22:15:57 +08:00
. execute ( sudo )
2022-12-14 09:12:39 +01:00
. args ( [ " helix " , " --grammar " , " fetch " ] )
. status_checked ( )
. with_context ( | | " Failed to download helix grammars! " ) ? ;
ctx . run_type ( )
2023-06-13 22:15:57 +08:00
. execute ( sudo )
2022-12-14 09:12:39 +01:00
. args ( [ " helix " , " --grammar " , " build " ] )
. status_checked ( )
. with_context ( | | " Failed to build helix grammars! " ) ? ;
Ok ( ( ) )
}
2023-05-25 15:09:23 +08:00
pub fn run_raco_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let raco = require ( " raco " ) ? ;
2021-03-14 13:12:38 +03:00
print_separator ( " Racket Package Manager " ) ;
2023-05-25 15:09:23 +08:00
ctx . run_type ( )
. execute ( raco )
. args ( [ " pkg " , " update " , " --all " ] )
. status_checked ( )
2021-03-14 13:12:38 +03:00
}
2021-05-29 01:59:27 -03:00
pub fn bin_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let bin = require ( " bin " ) ? ;
2021-05-29 01:59:27 -03:00
print_separator ( " Bin " ) ;
2022-11-08 05:54:35 -05:00
ctx . run_type ( ) . execute ( bin ) . arg ( " update " ) . status_checked ( )
2021-05-29 01:59:27 -03:00
}
2021-11-15 07:09:02 +01:00
pub fn spicetify_upgrade ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-07-14 21:44:06 +05:30
// As of 04-07-2023 NixOS packages Spicetify with the `spicetify-cli` binary name
let spicetify = require ( " spicetify " ) . or ( require ( " spicetify-cli " ) ) ? ;
2021-11-15 07:09:02 +01:00
print_separator ( " Spicetify " ) ;
2022-11-08 05:54:35 -05:00
ctx . run_type ( ) . execute ( spicetify ) . arg ( " upgrade " ) . status_checked ( )
2021-11-15 07:09:02 +01:00
}
2022-03-08 00:16:52 +01:00
pub fn run_ghcli_extensions_upgrade ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let gh = require ( " gh " ) ? ;
2022-11-08 05:54:35 -05:00
let result = Command ::new ( & gh ) . args ( [ " extensions " , " list " ] ) . output_checked_utf8 ( ) ;
2022-03-29 03:17:15 +03:00
if result . is_err ( ) {
debug! ( " GH result {:?} " , result ) ;
return Err ( SkipStep ( String ::from ( " GH failed " ) ) . into ( ) ) ;
}
2022-03-08 00:16:52 +01:00
print_separator ( " GitHub CLI Extensions " ) ;
ctx . run_type ( )
. execute ( & gh )
2022-10-23 11:34:30 +00:00
. args ( [ " extension " , " upgrade " , " --all " ] )
2022-11-08 05:54:35 -05:00
. status_checked ( )
2022-03-08 00:16:52 +01:00
}
2022-10-10 18:29:56 +00:00
pub fn update_julia_packages ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let julia = require ( " julia " ) ? ;
2022-10-10 18:29:56 +00:00
print_separator ( " Julia Packages " ) ;
ctx . run_type ( )
2022-11-03 04:26:20 +08:00
. execute ( julia )
2022-10-23 11:34:30 +00:00
. args ( [ " -e " , " using Pkg; Pkg.update() " ] )
2022-11-08 05:54:35 -05:00
. status_checked ( )
2022-10-10 18:29:56 +00:00
}
2022-12-08 22:47:57 +01:00
2023-05-25 15:09:23 +08:00
pub fn run_helm_repo_update ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-27 17:41:42 +08:00
let helm = require ( " helm " ) ? ;
2022-12-08 22:47:57 +01:00
print_separator ( " Helm " ) ;
2023-01-29 19:19:27 +00:00
let no_repo = " no repositories found " ;
let mut success = true ;
2023-05-25 15:09:23 +08:00
let mut exec = ctx . run_type ( ) . execute ( helm ) ;
2023-01-29 19:19:27 +00:00
if let Err ( e ) = exec . arg ( " repo " ) . arg ( " update " ) . status_checked ( ) {
error! ( " Updating repositories failed: {} " , e ) ;
success = match exec . output_checked_utf8 ( ) {
Ok ( s ) = > s . stdout . contains ( no_repo ) | | s . stderr . contains ( no_repo ) ,
Err ( e ) = > match e . downcast_ref ::< TopgradeError > ( ) {
Some ( TopgradeError ::ProcessFailedWithOutput ( _ , _ , stderr ) ) = > stderr . contains ( no_repo ) ,
_ = > false ,
} ,
} ;
}
if success {
Ok ( ( ) )
} else {
Err ( eyre! ( StepFailed ) )
}
2022-12-08 22:47:57 +01:00
}
2023-05-05 16:17:42 +08:00
2023-05-25 15:09:23 +08:00
pub fn run_stew ( ctx : & ExecutionContext ) -> Result < ( ) > {
2023-05-05 16:17:42 +08:00
let stew = require ( " stew " ) ? ;
print_separator ( " stew " ) ;
2023-05-25 15:09:23 +08:00
ctx . run_type ( ) . execute ( stew ) . args ( [ " upgrade " , " --all " ] ) . status_checked ( )
2023-05-05 16:17:42 +08:00
}
2023-06-23 17:03:57 +08:00
pub fn run_bob ( ctx : & ExecutionContext ) -> Result < ( ) > {
let bob = require ( " bob " ) ? ;
print_separator ( " Bob " ) ;
ctx . run_type ( ) . execute ( bob ) . args ( [ " update " , " --all " ] ) . status_checked ( )
}