Fix cargo not found on macos bug at vscode extension side

This commit is contained in:
veetaha 2020-05-06 01:42:04 +03:00 committed by Craig Disselkoen
parent a78dd06951
commit c9b395be2b
3 changed files with 48 additions and 7 deletions

View file

@ -1,6 +1,9 @@
import * as cp from 'child_process'; import * as cp from 'child_process';
import * as os from 'os';
import * as path from 'path';
import * as readline from 'readline'; import * as readline from 'readline';
import { OutputChannel } from 'vscode'; import { OutputChannel } from 'vscode';
import { isValidExecutable } from './util';
interface CompilationArtifact { interface CompilationArtifact {
fileName: string; fileName: string;
@ -63,7 +66,14 @@ export class Cargo {
onStderrString: (data: string) => void onStderrString: (data: string) => void
): Promise<number> { ): Promise<number> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const cargo = cp.spawn('cargo', cargoArgs, { let cargoPath;
try {
cargoPath = getCargoPathOrFail();
} catch (err) {
return reject(err);
}
const cargo = cp.spawn(cargoPath, cargoArgs, {
stdio: ['ignore', 'pipe', 'pipe'], stdio: ['ignore', 'pipe', 'pipe'],
cwd: this.rootFolder cwd: this.rootFolder
}); });
@ -87,3 +97,27 @@ export class Cargo {
}); });
} }
} }
// Mirrors `ra_env::get_path_for_executable` implementation
function getCargoPathOrFail(): string {
const envVar = process.env.CARGO;
const executableName = "cargo";
if (envVar) {
if (isValidExecutable(envVar)) return envVar;
throw new Error(`\`${envVar}\` environment variable points to something that's not a valid executable`);
}
if (isValidExecutable(executableName)) return executableName;
const standardLocation = path.join(os.homedir(), '.cargo', 'bin', executableName);
if (isValidExecutable(standardLocation)) return standardLocation;
throw new Error(
`Failed to find \`${executableName}\` executable. ` +
`Make sure \`${executableName}\` is in \`$PATH\`, ` +
`or set \`${envVar}\` to point to a valid executable.`
);
}

View file

@ -8,10 +8,9 @@ import { activateInlayHints } from './inlay_hints';
import { activateStatusDisplay } from './status_display'; import { activateStatusDisplay } from './status_display';
import { Ctx } from './ctx'; import { Ctx } from './ctx';
import { Config, NIGHTLY_TAG } from './config'; import { Config, NIGHTLY_TAG } from './config';
import { log, assert } from './util'; import { log, assert, isValidExecutable } from './util';
import { PersistentState } from './persistent_state'; import { PersistentState } from './persistent_state';
import { fetchRelease, download } from './net'; import { fetchRelease, download } from './net';
import { spawnSync } from 'child_process';
import { activateTaskProvider } from './tasks'; import { activateTaskProvider } from './tasks';
let ctx: Ctx | undefined; let ctx: Ctx | undefined;
@ -179,10 +178,7 @@ async function bootstrapServer(config: Config, state: PersistentState): Promise<
log.debug("Using server binary at", path); log.debug("Using server binary at", path);
const res = spawnSync(path, ["--version"], { encoding: 'utf8' }); if (!isValidExecutable(path)) {
log.debug("Checked binary availability via --version", res);
log.debug(res, "--version output:", res.output);
if (res.status !== 0) {
throw new Error(`Failed to execute ${path} --version`); throw new Error(`Failed to execute ${path} --version`);
} }

View file

@ -1,6 +1,7 @@
import * as lc from "vscode-languageclient"; import * as lc from "vscode-languageclient";
import * as vscode from "vscode"; import * as vscode from "vscode";
import { strict as nativeAssert } from "assert"; import { strict as nativeAssert } from "assert";
import { spawnSync } from "child_process";
export function assert(condition: boolean, explanation: string): asserts condition { export function assert(condition: boolean, explanation: string): asserts condition {
try { try {
@ -82,3 +83,13 @@ export function isRustDocument(document: vscode.TextDocument): document is RustD
export function isRustEditor(editor: vscode.TextEditor): editor is RustEditor { export function isRustEditor(editor: vscode.TextEditor): editor is RustEditor {
return isRustDocument(editor.document); return isRustDocument(editor.document);
} }
export function isValidExecutable(path: string): boolean {
log.debug("Checking availability of a binary at", path);
const res = spawnSync(path, ["--version"], { encoding: 'utf8' });
log.debug(res, "--version output:", res.output);
return res.status === 0;
}