@@ -17,16 +17,17 @@ function isInstalledRegex(componentName: string): RegExp {
1717export interface RustupConfig {
1818 channel : string ;
1919 path : string ;
20+ pathQuotes : string ;
2021 useWSL : boolean ;
2122}
2223
2324export async function rustupUpdate ( config : RustupConfig ) {
2425 startSpinner ( 'RLS' , 'Updating…' ) ;
2526
2627 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+ ] ) ;
3031
3132 // This test is imperfect because if the user has multiple toolchains installed, they
3233 // 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) {
6566 * Checks for required RLS components and prompts the user to install if it's
6667 * not already.
6768 */
69+
6870export async function checkForRls ( config : RustupConfig ) {
6971 if ( await hasRlsComponents ( config ) ) {
7072 return ;
7173 }
7274
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+ } ) ;
7392 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+ ) ,
75101 ) ;
76102 if ( clicked ) {
77103 await installRlsComponents ( config ) ;
@@ -83,9 +109,10 @@ export async function checkForRls(config: RustupConfig) {
83109
84110async function hasToolchain ( config : RustupConfig ) : Promise < boolean > {
85111 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+ ] ) ;
89116 return stdout . includes ( config . channel ) ;
90117 } catch ( e ) {
91118 console . log ( e ) ;
@@ -129,7 +156,7 @@ async function tryToInstallToolchain(config: RustupConfig) {
129156 */
130157async function listComponents ( config : RustupConfig ) : Promise < string [ ] > {
131158 return withWsl ( config . useWSL )
132- . exec ( ` ${ config . path } component list --toolchain ${ config . channel } ` )
159+ . execFile ( config . path , [ ' component' , ' list' , ' --toolchain' , config . channel ] )
133160 . then ( ( { stdout } ) =>
134161 stdout
135162 . toString ( )
@@ -142,9 +169,20 @@ async function hasRlsComponents(config: RustupConfig): Promise<boolean> {
142169 try {
143170 const components = await listComponents ( config ) ;
144171
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+ }
148186 } catch ( e ) {
149187 console . log ( e ) ;
150188 window . showErrorMessage ( `Can't detect RLS components: ${ e . message } ` ) ;
@@ -153,7 +191,7 @@ async function hasRlsComponents(config: RustupConfig): Promise<boolean> {
153191 }
154192}
155193
156- async function installRlsComponents ( config : RustupConfig ) {
194+ export async function installRlsComponents ( config : RustupConfig ) {
157195 startSpinner ( 'RLS' , 'Installing components…' ) ;
158196
159197 for ( const component of REQUIRED_COMPONENTS ) {
@@ -226,7 +264,9 @@ export function parseActiveToolchain(rustupOutput: string): string {
226264export async function getVersion ( config : RustupConfig ) : Promise < string > {
227265 const versionRegex = / r u s t u p ( [ 0 - 9 ] + \. [ 0 - 9 ] + \. [ 0 - 9 ] + ) / ;
228266
229- const output = await withWsl ( config . useWSL ) . exec ( `${ config . path } --version` ) ;
267+ const output = await withWsl ( config . useWSL ) . execFile ( config . path , [
268+ '--version' ,
269+ ] ) ;
230270 const versionMatch = output . stdout . toString ( ) . match ( versionRegex ) ;
231271 if ( versionMatch && versionMatch . length >= 2 ) {
232272 return versionMatch [ 1 ] ;
@@ -257,7 +297,7 @@ export function getActiveChannel(wsPath: string, config: RustupConfig): string {
257297 try {
258298 // `rustup show active-toolchain` is available since rustup 1.12.0
259299 activeChannel = withWsl ( config . useWSL )
260- . execSync ( `${ config . path } show active-toolchain` , { cwd : wsPath } )
300+ . execSync ( `${ config . pathQuotes } show active-toolchain` , { cwd : wsPath } )
261301 . toString ( )
262302 . trim ( ) ;
263303 // 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 {
268308 } catch ( e ) {
269309 // Possibly an old rustup version, so try rustup show
270310 const showOutput = withWsl ( config . useWSL )
271- . execSync ( `${ config . path } show` , { cwd : wsPath } )
311+ . execSync ( `${ config . pathQuotes } show` , { cwd : wsPath } )
272312 . toString ( ) ;
273313 activeChannel = parseActiveToolchain ( showOutput ) ;
274314 }
0 commit comments