2
2
3
3
use anyhow:: Context as _;
4
4
use crossterm:: tty:: IsTty as _;
5
+ use rustc_codegen_spirv_cache:: toolchain:: {
6
+ ensure_toolchain_installation, HaltToolchainInstallation , REQUIRED_TOOLCHAIN_COMPONENTS ,
7
+ } ;
5
8
6
- /// Use `rustup` to install the toolchain and components, if not already installed.
7
- ///
8
- /// Pretty much runs:
9
- ///
10
- /// * rustup toolchain add nightly-2024-04-24
11
- /// * rustup component add --toolchain nightly-2024-04-24 rust-src rustc-dev llvm-tools
9
+ use crate :: user_output;
10
+
11
+ /// Uses `rustup` to install the toolchain and all the [required components](REQUIRED_TOOLCHAIN_COMPONENTS),
12
+ /// if not already installed, while additionally asking for the user consent.
12
13
pub fn ensure_toolchain_and_components_exist (
13
14
channel : & str ,
14
15
skip_toolchain_install_consent : bool ,
15
16
) -> anyhow:: Result < ( ) > {
16
- // Check for the required toolchain
17
- let output_toolchain_list = std:: process:: Command :: new ( "rustup" )
18
- . args ( [ "toolchain" , "list" ] )
19
- . output ( )
20
- . context ( "running rustup command" ) ?;
21
- anyhow:: ensure!(
22
- output_toolchain_list. status. success( ) ,
23
- "could not list installed toolchains"
24
- ) ;
25
- let string_toolchain_list = String :: from_utf8_lossy ( & output_toolchain_list. stdout ) ;
26
- if string_toolchain_list
27
- . split_whitespace ( )
28
- . any ( |toolchain| toolchain. starts_with ( channel) )
29
- {
30
- log:: debug!( "toolchain {channel} is already installed" ) ;
31
- } else {
17
+ let on_toolchain_install = || {
32
18
let message = format ! ( "Rust {channel} with `rustup`" ) ;
33
19
get_consent_for_toolchain_install (
34
20
format ! ( "Install {message}" ) . as_ref ( ) ,
35
21
skip_toolchain_install_consent,
36
22
) ?;
37
- crate :: user_output!( "Installing {message}\n " ) ?;
38
-
39
- let output_toolchain_add = std:: process:: Command :: new ( "rustup" )
40
- . args ( [ "toolchain" , "add" ] )
41
- . arg ( channel)
42
- . stdout ( std:: process:: Stdio :: inherit ( ) )
43
- . stderr ( std:: process:: Stdio :: inherit ( ) )
44
- . output ( )
45
- . context ( "adding toolchain" ) ?;
46
- anyhow:: ensure!(
47
- output_toolchain_add. status. success( ) ,
48
- "could not install required toolchain"
23
+ log:: debug!( "installing toolchain {channel}" ) ;
24
+ user_output ! ( "Installing {message}\n " ) ?;
25
+ Ok ( ( ) )
26
+ } ;
27
+ let on_components_install = || {
28
+ let message = format ! (
29
+ "components {REQUIRED_TOOLCHAIN_COMPONENTS:?} for toolchain {channel} with `rustup`"
49
30
) ;
50
- }
51
-
52
- // Check for the required components
53
- let output_component_list = std:: process:: Command :: new ( "rustup" )
54
- . args ( [ "component" , "list" , "--toolchain" ] )
55
- . arg ( channel)
56
- . output ( )
57
- . context ( "getting toolchain list" ) ?;
58
- anyhow:: ensure!(
59
- output_component_list. status. success( ) ,
60
- "could not list installed components"
61
- ) ;
62
- let string_component_list = String :: from_utf8_lossy ( & output_component_list. stdout ) ;
63
- let required_components = [ "rust-src" , "rustc-dev" , "llvm-tools" ] ;
64
- let installed_components = string_component_list. lines ( ) . collect :: < Vec < _ > > ( ) ;
65
- let all_components_installed = required_components. iter ( ) . all ( |component| {
66
- installed_components. iter ( ) . any ( |installed_component| {
67
- let is_component = installed_component. starts_with ( component) ;
68
- let is_installed = installed_component. ends_with ( "(installed)" ) ;
69
- is_component && is_installed
70
- } )
71
- } ) ;
72
- if all_components_installed {
73
- log:: debug!( "all required components are installed" ) ;
74
- } else {
75
- let message = "toolchain components [rust-src, rustc-dev, llvm-tools] with `rustup`" ;
76
31
get_consent_for_toolchain_install (
77
32
format ! ( "Install {message}" ) . as_ref ( ) ,
78
33
skip_toolchain_install_consent,
79
34
) ?;
80
- crate :: user_output!( "Installing {message}\n " ) ?;
81
-
82
- let output_component_add = std:: process:: Command :: new ( "rustup" )
83
- . args ( [ "component" , "add" , "--toolchain" ] )
84
- . arg ( channel)
85
- . args ( [ "rust-src" , "rustc-dev" , "llvm-tools" ] )
86
- . stdout ( std:: process:: Stdio :: inherit ( ) )
87
- . stderr ( std:: process:: Stdio :: inherit ( ) )
88
- . output ( )
89
- . context ( "adding rustup component" ) ?;
90
- anyhow:: ensure!(
91
- output_component_add. status. success( ) ,
92
- "could not install required components"
93
- ) ;
94
- }
35
+ log:: debug!( "installing required components of toolchain {channel}" ) ;
36
+ user_output ! ( "Installing {message}\n " ) ?;
37
+ Ok ( ( ) )
38
+ } ;
95
39
96
- Ok ( ( ) )
40
+ let halt_installation = HaltToolchainInstallation {
41
+ on_toolchain_install,
42
+ on_components_install,
43
+ } ;
44
+ ensure_toolchain_installation ( channel, halt_installation)
97
45
}
98
46
99
47
/// Prompt user if they want to install a new Rust toolchain.
@@ -106,13 +54,13 @@ fn get_consent_for_toolchain_install(
106
54
}
107
55
108
56
if !std:: io:: stdout ( ) . is_tty ( ) {
109
- log:: error!( "Attempted to ask for consent when there's no TTY" ) ;
57
+ log:: error!( "attempted to ask for consent when there's no TTY" ) ;
110
58
anyhow:: bail!( "no TTY detected, so can't ask for consent to install Rust toolchain" )
111
59
}
112
60
113
61
log:: debug!( "asking for consent to install the required toolchain" ) ;
114
62
crossterm:: terminal:: enable_raw_mode ( ) . context ( "enabling raw mode" ) ?;
115
- crate :: user_output!( "{prompt} [y/n]: " ) ?;
63
+ user_output ! ( "{prompt} [y/n]: " ) ?;
116
64
let mut input = crossterm:: event:: read ( ) . context ( "reading crossterm event" ) ?;
117
65
118
66
if let crossterm:: event:: Event :: Key ( crossterm:: event:: KeyEvent {
0 commit comments