@@ -17,16 +17,17 @@ function isInstalledRegex(componentName: string): RegExp {
17
17
export interface RustupConfig {
18
18
channel : string ;
19
19
path : string ;
20
+ pathQuotes : string ;
20
21
useWSL : boolean ;
21
22
}
22
23
23
24
export async function rustupUpdate ( config : RustupConfig ) {
24
25
startSpinner ( 'RLS' , 'Updating…' ) ;
25
26
26
27
try {
27
- const { stdout } = await withWsl ( config . useWSL ) . exec (
28
- ` ${ config . path } update` ,
29
- ) ;
28
+ const { stdout } = await withWsl ( config . useWSL ) . execFile ( config . path , [
29
+ ' update' ,
30
+ ] ) ;
30
31
31
32
// This test is imperfect because if the user has multiple toolchains installed, they
32
33
// might have one updated and one unchanged. But I don't want to go too far down the
@@ -65,13 +66,38 @@ export async function ensureToolchain(config: RustupConfig) {
65
66
* Checks for required RLS components and prompts the user to install if it's
66
67
* not already.
67
68
*/
69
+
68
70
export async function checkForRls ( config : RustupConfig ) {
69
71
if ( await hasRlsComponents ( config ) ) {
70
72
return ;
71
73
}
72
74
75
+ // Format an easier to understand component install prompt
76
+ const componentsNeededUserOutput = REQUIRED_COMPONENTS . map ( ( component , i ) => {
77
+ if (
78
+ REQUIRED_COMPONENTS . length > 1 &&
79
+ i === REQUIRED_COMPONENTS . length - 1
80
+ ) {
81
+ return ' and `' + component + '`' ;
82
+ } else if (
83
+ i !== 0 &&
84
+ i !== REQUIRED_COMPONENTS . length - 1 &&
85
+ REQUIRED_COMPONENTS . length > 2
86
+ ) {
87
+ return ', `' + component + '`' ;
88
+ } else {
89
+ return '`' + component + '`' ;
90
+ }
91
+ } ) ;
73
92
const clicked = await Promise . resolve (
74
- window . showInformationMessage ( 'RLS not installed. Install?' , 'Yes' ) ,
93
+ window . showInformationMessage (
94
+ `
95
+ Rustup
96
+ ${
97
+ componentsNeededUserOutput . length > 1 ? 'components' : 'component'
98
+ } ${ componentsNeededUserOutput . join ( '' ) } not installed. Install?`,
99
+ 'Yes' ,
100
+ ) ,
75
101
) ;
76
102
if ( clicked ) {
77
103
await installRlsComponents ( config ) ;
@@ -83,9 +109,10 @@ export async function checkForRls(config: RustupConfig) {
83
109
84
110
async function hasToolchain ( config : RustupConfig ) : Promise < boolean > {
85
111
try {
86
- const { stdout } = await withWsl ( config . useWSL ) . exec (
87
- `${ config . path } toolchain list` ,
88
- ) ;
112
+ const { stdout } = await withWsl ( config . useWSL ) . execFile ( config . path , [
113
+ 'toolchain' ,
114
+ 'list' ,
115
+ ] ) ;
89
116
return stdout . includes ( config . channel ) ;
90
117
} catch ( e ) {
91
118
console . log ( e ) ;
@@ -129,7 +156,7 @@ async function tryToInstallToolchain(config: RustupConfig) {
129
156
*/
130
157
async function listComponents ( config : RustupConfig ) : Promise < string [ ] > {
131
158
return withWsl ( config . useWSL )
132
- . exec ( ` ${ config . path } component list --toolchain ${ config . channel } ` )
159
+ . execFile ( config . path , [ ' component' , ' list' , ' --toolchain' , config . channel ] )
133
160
. then ( ( { stdout } ) =>
134
161
stdout
135
162
. toString ( )
@@ -142,9 +169,20 @@ async function hasRlsComponents(config: RustupConfig): Promise<boolean> {
142
169
try {
143
170
const components = await listComponents ( config ) ;
144
171
145
- return REQUIRED_COMPONENTS . map ( isInstalledRegex ) . every ( isInstalledRegex =>
146
- components . some ( c => isInstalledRegex . test ( c ) ) ,
147
- ) ;
172
+ // Splice the components that are installed from the REQUIRED_COMPONENTS array
173
+ for ( let i = REQUIRED_COMPONENTS . length ; i >= 0 ; -- i ) {
174
+ const installedRegex = isInstalledRegex ( REQUIRED_COMPONENTS [ i ] ) ;
175
+ components . forEach ( component => {
176
+ if ( installedRegex . test ( component ) ) {
177
+ REQUIRED_COMPONENTS . splice ( i , 1 ) ;
178
+ }
179
+ } ) ;
180
+ }
181
+ if ( REQUIRED_COMPONENTS . length === 0 ) {
182
+ return true ;
183
+ } else {
184
+ return false ;
185
+ }
148
186
} catch ( e ) {
149
187
console . log ( e ) ;
150
188
window . showErrorMessage ( `Can't detect RLS components: ${ e . message } ` ) ;
@@ -153,7 +191,7 @@ async function hasRlsComponents(config: RustupConfig): Promise<boolean> {
153
191
}
154
192
}
155
193
156
- async function installRlsComponents ( config : RustupConfig ) {
194
+ export async function installRlsComponents ( config : RustupConfig ) {
157
195
startSpinner ( 'RLS' , 'Installing components…' ) ;
158
196
159
197
for ( const component of REQUIRED_COMPONENTS ) {
@@ -226,7 +264,9 @@ export function parseActiveToolchain(rustupOutput: string): string {
226
264
export async function getVersion ( config : RustupConfig ) : Promise < string > {
227
265
const versionRegex = / r u s t u p ( [ 0 - 9 ] + \. [ 0 - 9 ] + \. [ 0 - 9 ] + ) / ;
228
266
229
- const output = await withWsl ( config . useWSL ) . exec ( `${ config . path } --version` ) ;
267
+ const output = await withWsl ( config . useWSL ) . execFile ( config . path , [
268
+ '--version' ,
269
+ ] ) ;
230
270
const versionMatch = output . stdout . toString ( ) . match ( versionRegex ) ;
231
271
if ( versionMatch && versionMatch . length >= 2 ) {
232
272
return versionMatch [ 1 ] ;
@@ -257,7 +297,7 @@ export function getActiveChannel(wsPath: string, config: RustupConfig): string {
257
297
try {
258
298
// `rustup show active-toolchain` is available since rustup 1.12.0
259
299
activeChannel = withWsl ( config . useWSL )
260
- . execSync ( `${ config . path } show active-toolchain` , { cwd : wsPath } )
300
+ . execSync ( `${ config . pathQuotes } show active-toolchain` , { cwd : wsPath } )
261
301
. toString ( )
262
302
. trim ( ) ;
263
303
// Since rustup 1.17.0 if the active toolchain is the default, we're told
@@ -268,7 +308,7 @@ export function getActiveChannel(wsPath: string, config: RustupConfig): string {
268
308
} catch ( e ) {
269
309
// Possibly an old rustup version, so try rustup show
270
310
const showOutput = withWsl ( config . useWSL )
271
- . execSync ( `${ config . path } show` , { cwd : wsPath } )
311
+ . execSync ( `${ config . pathQuotes } show` , { cwd : wsPath } )
272
312
. toString ( ) ;
273
313
activeChannel = parseActiveToolchain ( showOutput ) ;
274
314
}
0 commit comments