Skip to content
This repository was archived by the owner on Dec 8, 2020. It is now read-only.

Commit 9e15f1b

Browse files
authored
Use the nightly toolchain of rustup (#246)
1 parent 0e1fc2c commit 9e15f1b

File tree

2 files changed

+87
-60
lines changed

2 files changed

+87
-60
lines changed

src/components/configuration/Configuration.ts

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,16 @@ export class Configuration {
8181
* @param logger a logger to log messages
8282
*/
8383
public static async create(logger: ChildLogger): Promise<Configuration> {
84-
const rustcSysRoot: string | undefined = await this.loadRustcSysRoot();
85-
const createRustInstallationPromise = async () => {
86-
if (!rustcSysRoot) {
87-
return undefined;
88-
}
89-
if (Rustup.doesManageRustcSysRoot(rustcSysRoot)) {
90-
return await Rustup.create(logger.createChildLogger('Rustup: '), rustcSysRoot);
91-
} else {
92-
return new NotRustup(rustcSysRoot);
84+
const rustup: Rustup | undefined = await Rustup.create(logger.createChildLogger('Rustup: '));
85+
let rustInstallation: Rustup | NotRustup | undefined = undefined;
86+
if (rustup) {
87+
rustInstallation = rustup;
88+
} else {
89+
const rustcSysRoot: string | undefined = await this.loadRustcSysRoot();
90+
if (rustcSysRoot) {
91+
rustInstallation = new NotRustup(rustcSysRoot);
9392
}
94-
};
95-
const rustInstallation: Rustup | NotRustup | undefined = await createRustInstallationPromise();
93+
}
9694
const pathToRustSourceCodeSpecifiedByUser = await this.checkPathToRustSourceCodeSpecifiedByUser();
9795
const configuration = new Configuration(
9896
logger,
@@ -176,16 +174,13 @@ export class Configuration {
176174
if (this.rlsPathSpecifiedByUser) {
177175
return this.rlsPathSpecifiedByUser;
178176
}
179-
180-
if (this.rustInstallation instanceof Rustup) {
181-
const pathToRlsExecutable = this.rustInstallation.getPathToRlsExecutable();
182-
183-
if (pathToRlsExecutable) {
184-
return pathToRlsExecutable;
185-
}
177+
if (!(this.rustInstallation instanceof Rustup)) {
178+
return undefined;
186179
}
187-
188-
return undefined;
180+
if (!this.rustInstallation.isRlsInstalled()) {
181+
return undefined;
182+
}
183+
return 'rustup';
189184
}
190185

191186
/**
@@ -198,16 +193,21 @@ export class Configuration {
198193
const getRlsArgsSpecifiedByUser = () => {
199194
const rlsConfiguration: any = this.getRlsConfiguration();
200195
if (!rlsConfiguration) {
201-
return undefined;
196+
return [];
202197
}
203198
const rlsArgsSpecifiedByUser: any = rlsConfiguration.args;
204199
if (!rlsArgsSpecifiedByUser) {
205-
return undefined;
200+
return [];
206201
}
207202
return rlsArgsSpecifiedByUser;
208203
};
209-
const rlsArgs = getRlsArgsSpecifiedByUser() || [];
210-
return rlsArgs;
204+
if (!(this.rustInstallation instanceof Rustup)) {
205+
return getRlsArgsSpecifiedByUser();
206+
}
207+
if (!this.rustInstallation.isRlsInstalled()) {
208+
return getRlsArgsSpecifiedByUser();
209+
}
210+
return ['run', 'nightly', 'rls'].concat(getRlsArgsSpecifiedByUser());
211211
}
212212

213213
/**

src/components/configuration/Rustup.ts

Lines changed: 63 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,12 @@ export class Rustup {
6262
* The method is asynchronous because it tries to find Rust's source code
6363
* @param pathToRustcSysRoot A path to Rust's installation root
6464
*/
65-
public static async create(logger: ChildLogger, pathToRustcSysRoot: string): Promise<Rustup> {
66-
logger.createChildLogger('create: ').debug(`sysroot=${pathToRustcSysRoot}`);
67-
const rustup = new Rustup(logger, pathToRustcSysRoot, undefined, undefined);
65+
public static async create(logger: ChildLogger): Promise<Rustup | undefined> {
66+
const sysrootPath: string | undefined = await this.invokeGettingSysrootPath('nightly', logger);
67+
if (!sysrootPath) {
68+
return undefined;
69+
}
70+
const rustup = new Rustup(logger, sysrootPath, undefined, undefined);
6871
await rustup.updatePathToRustSourceCodePath();
6972
await rustup.updateComponents();
7073
await rustup.updatePathToRlsExecutable();
@@ -125,7 +128,7 @@ export class Rustup {
125128
*/
126129
public async updateComponents(): Promise<void> {
127130
const logger = this.logger.createChildLogger('updateComponents: ');
128-
const stdoutData: string | undefined = await this.invokeRustup(['component', 'list']);
131+
const stdoutData: string | undefined = await Rustup.invoke(['component', 'list', '--toolchain', 'nightly'], logger);
129132
if (!stdoutData) {
130133
logger.error(`stdoutData=${stdoutData}`);
131134
return undefined;
@@ -192,6 +195,14 @@ export class Rustup {
192195
return true;
193196
}
194197

198+
/**
199+
* Returns if RLS is installed
200+
* @return true if RLS is installed otherwise false
201+
*/
202+
public isRlsInstalled(): boolean {
203+
return this.isComponentInstalled(Rustup.getRlsComponentName());
204+
}
205+
195206
/**
196207
* Returns true if the component `rust-analysis` can be installed otherwise false.
197208
* If the component is already installed, the method returns false
@@ -233,6 +244,52 @@ export class Rustup {
233244
return ' (installed)';
234245
}
235246

247+
/**
248+
* Invokes rustup to get the path to the sysroot of the specified toolchain.
249+
* Checks if the invocation exited successfully and returns the output of the invocation
250+
* @param toolchain The toolchain to get the path to the sysroot for
251+
* @param logger The logger to log messages
252+
* @return The output of the invocation if the invocation exited successfully otherwise undefined
253+
*/
254+
private static async invokeGettingSysrootPath(toolchain: string, logger: ChildLogger): Promise<string | undefined> {
255+
const output: string | undefined = await this.invokeRun(toolchain, ['rustc', '--print', 'sysroot'], logger);
256+
if (!output) {
257+
return undefined;
258+
}
259+
return output.trim();
260+
}
261+
262+
/**
263+
* Invokes `rustup run...` with the specified toolchain and arguments, checks if it exited successfully and returns its output
264+
* @param toolchain The toolchain to invoke rustup with
265+
* @param args The arguments to invoke rustup with
266+
* @param logger The logger to log messages
267+
*/
268+
private static async invokeRun(toolchain: string, args: string[], logger: ChildLogger): Promise<string | undefined> {
269+
return await this.invoke(['run', toolchain, ...args], logger);
270+
}
271+
272+
/**
273+
* Invokes Rustup with specified arguments, checks if it exited successfully and returns its output
274+
* @param args Arguments to invoke Rustup with
275+
* @param logger The logger to log messages
276+
* @returns an output if invocation exited successfully otherwise undefined
277+
*/
278+
private static async invoke(args: string[], logger: ChildLogger): Promise<string | undefined> {
279+
const rustupExe = Rustup.getRustupExecutable();
280+
const functionLogger = logger.createChildLogger(`invoke: rustupExe=${rustupExe}, args=${JSON.stringify(args)}: `);
281+
const result = await OutputtingProcess.spawn(rustupExe, args, undefined);
282+
if (!result.success) {
283+
functionLogger.error('failed');
284+
return undefined;
285+
}
286+
if (result.exitCode !== 0) {
287+
functionLogger.error(`exited unexpectedly; exitCode=${result.exitCode}, stderrData=${result.stderrData}`);
288+
return undefined;
289+
}
290+
return result.stdoutData;
291+
}
292+
236293
/**
237294
* Constructs a new instance of the class.
238295
* The constructor is private because creating a new instance should be done via the method `create`
@@ -258,36 +315,6 @@ export class Rustup {
258315
this.components = [];
259316
}
260317

261-
/**
262-
* Invokes Rustup with specified arguments, checks it exited successfully and returns its output
263-
* @param args Arguments to invoke Rustup with
264-
* @returns an output if invokation Rustup exited successfully otherwise undefined
265-
*/
266-
private async invokeRustup(args: string[]): Promise<string | undefined> {
267-
const logger = this.logger.createChildLogger('invokeRustup: ');
268-
269-
const rustupExe = Rustup.getRustupExecutable();
270-
271-
// We assume that the executable of Rustup can be called since usually both `rustc` and `rustup` are placed in the same directory
272-
const result = await OutputtingProcess.spawn(rustupExe, args, undefined);
273-
274-
if (!result.success) {
275-
// It actually shouldn't happen.
276-
// If it happens, then there is some problem and we need to know about it
277-
logger.error(`failed to execute ${rustupExe}. This should not have happened`);
278-
279-
return undefined;
280-
}
281-
282-
if (result.exitCode !== 0) {
283-
logger.error(`${rustupExe} ${args.join(' ')} exited with code=${result.exitCode}, but zero is expected. This should not have happened. stderrData=${result.stderrData}`);
284-
285-
return undefined;
286-
}
287-
288-
return result.stdoutData;
289-
}
290-
291318
/**
292319
* Takes from the field `components` only installed components
293320
* @returns a list of installed components
@@ -317,8 +344,8 @@ export class Rustup {
317344
// We return true because the component is installed, but anyway it is an exceptional situation
318345
return true;
319346
}
320-
const args = ['component', 'add', componentName];
321-
const stdoutData: string | undefined = await this.invokeRustup(args);
347+
const args = ['component', 'add', componentName, '--toolchain', 'nightly'];
348+
const stdoutData: string | undefined = await Rustup.invoke(args, logger);
322349
// Some error occurred. It is already logged in the method invokeRustup.
323350
// So we just need to notify a caller that the installation failed
324351
if (stdoutData === undefined) {

0 commit comments

Comments
 (0)