32
32
33
33
use std:: borrow:: Cow ;
34
34
use std:: env:: { self , consts:: EXE_SUFFIX } ;
35
- use std :: fmt ;
36
- use std:: fs ;
35
+ # [ cfg ( not ( windows ) ) ]
36
+ use std:: io ;
37
37
use std:: io:: Write ;
38
38
use std:: path:: { Component , MAIN_SEPARATOR , Path , PathBuf } ;
39
39
use std:: process:: Command ;
40
40
use std:: str:: FromStr ;
41
+ use std:: { fmt, fs} ;
41
42
42
43
use anyhow:: { Context , Result , anyhow} ;
43
44
use cfg_if:: cfg_if;
@@ -1071,6 +1072,67 @@ pub(crate) fn uninstall(no_prompt: bool, process: &Process) -> Result<utils::Exi
1071
1072
Ok ( utils:: ExitCode ( 0 ) )
1072
1073
}
1073
1074
1075
+ #[ derive( Clone , Copy , Debug ) ]
1076
+ pub ( crate ) enum SelfUpdatePermission {
1077
+ HardFail ,
1078
+ #[ cfg( not( windows) ) ]
1079
+ Skip ,
1080
+ Permit ,
1081
+ }
1082
+
1083
+ #[ cfg( windows) ]
1084
+ pub ( crate ) fn self_update_permitted ( _explicit : bool ) -> Result < SelfUpdatePermission > {
1085
+ Ok ( SelfUpdatePermission :: Permit )
1086
+ }
1087
+
1088
+ #[ cfg( not( windows) ) ]
1089
+ pub ( crate ) fn self_update_permitted ( explicit : bool ) -> Result < SelfUpdatePermission > {
1090
+ // Detect if rustup is not meant to self-update
1091
+ let current_exe = env:: current_exe ( ) ?;
1092
+ let current_exe_dir = current_exe. parent ( ) . expect ( "Rustup isn't in a directory‽" ) ;
1093
+ if let Err ( e) = tempfile:: Builder :: new ( )
1094
+ . prefix ( "updtest" )
1095
+ . tempdir_in ( current_exe_dir)
1096
+ {
1097
+ match e. kind ( ) {
1098
+ io:: ErrorKind :: PermissionDenied => {
1099
+ trace ! ( "Skipping self-update because we cannot write to the rustup dir" ) ;
1100
+ if explicit {
1101
+ return Ok ( SelfUpdatePermission :: HardFail ) ;
1102
+ } else {
1103
+ return Ok ( SelfUpdatePermission :: Skip ) ;
1104
+ }
1105
+ }
1106
+ _ => return Err ( e. into ( ) ) ,
1107
+ }
1108
+ }
1109
+ Ok ( SelfUpdatePermission :: Permit )
1110
+ }
1111
+
1112
+ /// Performs all of a self-update: check policy, download, apply and exit.
1113
+ pub ( crate ) async fn self_update ( process : & Process ) -> Result < utils:: ExitCode > {
1114
+ match self_update_permitted ( false ) ? {
1115
+ SelfUpdatePermission :: HardFail => {
1116
+ error ! ( "Unable to self-update. STOP" ) ;
1117
+ return Ok ( utils:: ExitCode ( 1 ) ) ;
1118
+ }
1119
+ #[ cfg( not( windows) ) ]
1120
+ SelfUpdatePermission :: Skip => return Ok ( utils:: ExitCode ( 0 ) ) ,
1121
+ SelfUpdatePermission :: Permit => { }
1122
+ }
1123
+
1124
+ let setup_path = prepare_update ( process) . await ?;
1125
+
1126
+ if let Some ( setup_path) = & setup_path {
1127
+ return run_update ( setup_path) ;
1128
+ } else {
1129
+ // Try again in case we emitted "tool `{}` is already installed" last time.
1130
+ install_proxies ( process) ?;
1131
+ }
1132
+
1133
+ Ok ( utils:: ExitCode ( 0 ) )
1134
+ }
1135
+
1074
1136
/// Self update downloads rustup-init to `CARGO_HOME`/bin/rustup-init
1075
1137
/// and runs it.
1076
1138
///
@@ -1089,11 +1151,11 @@ pub(crate) fn uninstall(no_prompt: bool, process: &Process) -> Result<utils::Exi
1089
1151
pub ( crate ) async fn update ( cfg : & Cfg < ' _ > ) -> Result < utils:: ExitCode > {
1090
1152
common:: warn_if_host_is_emulated ( cfg. process ) ;
1091
1153
1092
- use common :: SelfUpdatePermission :: * ;
1154
+ use SelfUpdatePermission :: * ;
1093
1155
let update_permitted = if cfg ! ( feature = "no-self-update" ) {
1094
1156
HardFail
1095
1157
} else {
1096
- common :: self_update_permitted ( true ) ?
1158
+ self_update_permitted ( true ) ?
1097
1159
} ;
1098
1160
match update_permitted {
1099
1161
HardFail => {
0 commit comments