mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
vscode: amend server installation logic to account for nightlies
This commit is contained in:
parent
601fc9d1ab
commit
1e73811fbe
3 changed files with 57 additions and 52 deletions
|
@ -5,7 +5,7 @@ import { spawnSync } from 'child_process';
|
||||||
|
|
||||||
export function serverVersion(ctx: Ctx): Cmd {
|
export function serverVersion(ctx: Ctx): Cmd {
|
||||||
return async () => {
|
return async () => {
|
||||||
const binaryPath = await ensureServerBinary(ctx.config.serverSource);
|
const binaryPath = await ensureServerBinary(ctx.config);
|
||||||
|
|
||||||
if (binaryPath == null) {
|
if (binaryPath == null) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -18,4 +18,3 @@ export function serverVersion(ctx: Ctx): Cmd {
|
||||||
vscode.window.showInformationMessage('rust-analyzer version : ' + version);
|
vscode.window.showInformationMessage('rust-analyzer version : ' + version);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import { promises as dns } from "dns";
|
|
||||||
import { spawnSync } from "child_process";
|
import { spawnSync } from "child_process";
|
||||||
|
|
||||||
import { ArtifactSource } from "./interfaces";
|
import { ArtifactSource } from "./interfaces";
|
||||||
import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info";
|
import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info";
|
||||||
import { downloadArtifact } from "./download_artifact";
|
import { downloadArtifactWithProgressUi } from "./downloads";
|
||||||
import { log, assert } from "../util";
|
import { log, assert } from "../util";
|
||||||
|
import { Config, NIGHTLY_TAG } from "../config";
|
||||||
|
|
||||||
|
export async function ensureServerBinary(config: Config): Promise<null | string> {
|
||||||
|
const source = config.serverSource;
|
||||||
|
|
||||||
export async function ensureServerBinary(source: null | ArtifactSource): Promise<null | string> {
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
vscode.window.showErrorMessage(
|
vscode.window.showErrorMessage(
|
||||||
"Unfortunately we don't ship binaries for your platform yet. " +
|
"Unfortunately we don't ship binaries for your platform yet. " +
|
||||||
|
@ -35,18 +37,11 @@ export async function ensureServerBinary(source: null | ArtifactSource): Promise
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
case ArtifactSource.Type.GithubRelease: {
|
case ArtifactSource.Type.GithubRelease: {
|
||||||
const prebuiltBinaryPath = path.join(source.dir, source.file);
|
if (!shouldDownloadServer(source, config)) {
|
||||||
|
return path.join(source.dir, source.file);
|
||||||
const installedVersion: null | string = getServerVersion(source.storage);
|
|
||||||
const requiredVersion: string = source.tag;
|
|
||||||
|
|
||||||
log.debug("Installed version:", installedVersion, "required:", requiredVersion);
|
|
||||||
|
|
||||||
if (isBinaryAvailable(prebuiltBinaryPath) && installedVersion === requiredVersion) {
|
|
||||||
return prebuiltBinaryPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source.askBeforeDownload) {
|
if (config.askBeforeDownload) {
|
||||||
const userResponse = await vscode.window.showInformationMessage(
|
const userResponse = await vscode.window.showInformationMessage(
|
||||||
`Language server version ${source.tag} for rust-analyzer is not installed. ` +
|
`Language server version ${source.tag} for rust-analyzer is not installed. ` +
|
||||||
"Do you want to download it now?",
|
"Do you want to download it now?",
|
||||||
|
@ -55,38 +50,53 @@ export async function ensureServerBinary(source: null | ArtifactSource): Promise
|
||||||
if (userResponse !== "Download now") return null;
|
if (userResponse !== "Download now") return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!await downloadServer(source)) return null;
|
return await downloadServer(source, config);
|
||||||
|
|
||||||
return prebuiltBinaryPath;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadServer(source: ArtifactSource.GithubRelease): Promise<boolean> {
|
function shouldDownloadServer(
|
||||||
|
source: ArtifactSource.GithubRelease,
|
||||||
|
config: Config
|
||||||
|
): boolean {
|
||||||
|
if (!isBinaryAvailable(path.join(source.dir, source.file))) return true;
|
||||||
|
|
||||||
|
const installed = {
|
||||||
|
tag: config.serverReleaseTag.get(),
|
||||||
|
date: config.serverReleaseDate.get()
|
||||||
|
};
|
||||||
|
const required = {
|
||||||
|
tag: source.tag,
|
||||||
|
date: config.installedNightlyExtensionReleaseDate.get()
|
||||||
|
};
|
||||||
|
|
||||||
|
log.debug("Installed server:", installed, "required:", required);
|
||||||
|
|
||||||
|
if (required.tag !== NIGHTLY_TAG || installed.tag !== NIGHTLY_TAG) {
|
||||||
|
return required.tag !== installed.tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(required.date !== null, "Extension release date should have been saved during its installation");
|
||||||
|
assert(installed.date !== null, "Server release date should have been saved during its installation");
|
||||||
|
|
||||||
|
return installed.date.getTime() !== required.date.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadServer(
|
||||||
|
source: ArtifactSource.GithubRelease,
|
||||||
|
config: Config,
|
||||||
|
): Promise<null | string> {
|
||||||
try {
|
try {
|
||||||
const releaseInfo = await fetchArtifactReleaseInfo(source.repo, source.file, source.tag);
|
const releaseInfo = await fetchArtifactReleaseInfo(source.repo, source.file, source.tag);
|
||||||
|
|
||||||
await downloadArtifact(releaseInfo, source.file, source.dir, "language server");
|
await downloadArtifactWithProgressUi(releaseInfo, source.file, source.dir, "language server");
|
||||||
await setServerVersion(source.storage, releaseInfo.releaseName);
|
await Promise.all([
|
||||||
|
config.serverReleaseTag.set(releaseInfo.releaseName),
|
||||||
|
config.serverReleaseDate.set(releaseInfo.releaseDate)
|
||||||
|
]);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
vscode.window.showErrorMessage(
|
log.downloadError(err, "language server", source.repo.name);
|
||||||
`Failed to download language server from ${source.repo.name} ` +
|
return null;
|
||||||
`GitHub repository: ${err.message}`
|
|
||||||
);
|
|
||||||
|
|
||||||
log.error(err);
|
|
||||||
|
|
||||||
dns.resolve('example.com').then(
|
|
||||||
addrs => log.debug("DNS resolution for example.com was successful", addrs),
|
|
||||||
err => {
|
|
||||||
log.error(
|
|
||||||
"DNS resolution for example.com failed, " +
|
|
||||||
"there might be an issue with Internet availability"
|
|
||||||
);
|
|
||||||
log.error(err);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const binaryPath = path.join(source.dir, source.file);
|
const binaryPath = path.join(source.dir, source.file);
|
||||||
|
@ -101,7 +111,7 @@ async function downloadServer(source: ArtifactSource.GithubRelease): Promise<boo
|
||||||
"Rust analyzer language server was successfully installed 🦀"
|
"Rust analyzer language server was successfully installed 🦀"
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return binaryPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isBinaryAvailable(binaryPath: string): boolean {
|
function isBinaryAvailable(binaryPath: string): boolean {
|
||||||
|
@ -115,14 +125,3 @@ function isBinaryAvailable(binaryPath: string): boolean {
|
||||||
|
|
||||||
return res.status === 0;
|
return res.status === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getServerVersion(storage: vscode.Memento): null | string {
|
|
||||||
const version = storage.get<null | string>("server-version", null);
|
|
||||||
log.debug("Get server-version:", version);
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setServerVersion(storage: vscode.Memento, version: string): Promise<void> {
|
|
||||||
log.debug("Set server-version:", version);
|
|
||||||
await storage.update("server-version", version.toString());
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { activateHighlighting } from './highlighting';
|
||||||
import { ensureServerBinary } from './installation/server';
|
import { ensureServerBinary } from './installation/server';
|
||||||
import { Config } from './config';
|
import { Config } from './config';
|
||||||
import { log } from './util';
|
import { log } from './util';
|
||||||
|
import { ensureProperExtensionVersion } from './installation/extension';
|
||||||
|
|
||||||
let ctx: Ctx | undefined;
|
let ctx: Ctx | undefined;
|
||||||
|
|
||||||
|
@ -34,7 +35,13 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||||
|
|
||||||
const config = new Config(context);
|
const config = new Config(context);
|
||||||
|
|
||||||
const serverPath = await ensureServerBinary(config.serverSource);
|
vscode.workspace.onDidChangeConfiguration(() => ensureProperExtensionVersion(config));
|
||||||
|
|
||||||
|
// Don't await the user response here, otherwise we will block the lsp server bootstrap
|
||||||
|
void ensureProperExtensionVersion(config);
|
||||||
|
|
||||||
|
const serverPath = await ensureServerBinary(config);
|
||||||
|
|
||||||
if (serverPath == null) {
|
if (serverPath == null) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Rust Analyzer Language Server is not available. " +
|
"Rust Analyzer Language Server is not available. " +
|
||||||
|
|
Loading…
Reference in a new issue