From 1e73811fbe634efec90a3e009a84fd8dda9f5697 Mon Sep 17 00:00:00 2001 From: Veetaha Date: Mon, 9 Mar 2020 19:57:55 +0200 Subject: [PATCH] vscode: amend server installation logic to account for nightlies --- editors/code/src/commands/server_version.ts | 3 +- editors/code/src/installation/server.ts | 97 ++++++++++----------- editors/code/src/main.ts | 9 +- 3 files changed, 57 insertions(+), 52 deletions(-) diff --git a/editors/code/src/commands/server_version.ts b/editors/code/src/commands/server_version.ts index 421301b42c..c4d84b4439 100644 --- a/editors/code/src/commands/server_version.ts +++ b/editors/code/src/commands/server_version.ts @@ -5,7 +5,7 @@ import { spawnSync } from 'child_process'; export function serverVersion(ctx: Ctx): Cmd { return async () => { - const binaryPath = await ensureServerBinary(ctx.config.serverSource); + const binaryPath = await ensureServerBinary(ctx.config); if (binaryPath == null) { throw new Error( @@ -18,4 +18,3 @@ export function serverVersion(ctx: Ctx): Cmd { vscode.window.showInformationMessage('rust-analyzer version : ' + version); }; } - diff --git a/editors/code/src/installation/server.ts b/editors/code/src/installation/server.ts index ef1c45ff65..345f30d476 100644 --- a/editors/code/src/installation/server.ts +++ b/editors/code/src/installation/server.ts @@ -1,14 +1,16 @@ import * as vscode from "vscode"; import * as path from "path"; -import { promises as dns } from "dns"; import { spawnSync } from "child_process"; import { ArtifactSource } from "./interfaces"; import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info"; -import { downloadArtifact } from "./download_artifact"; +import { downloadArtifactWithProgressUi } from "./downloads"; import { log, assert } from "../util"; +import { Config, NIGHTLY_TAG } from "../config"; + +export async function ensureServerBinary(config: Config): Promise { + const source = config.serverSource; -export async function ensureServerBinary(source: null | ArtifactSource): Promise { if (!source) { vscode.window.showErrorMessage( "Unfortunately we don't ship binaries for your platform yet. " + @@ -35,18 +37,11 @@ export async function ensureServerBinary(source: null | ArtifactSource): Promise return null; } case ArtifactSource.Type.GithubRelease: { - const prebuiltBinaryPath = 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 (!shouldDownloadServer(source, config)) { + return path.join(source.dir, source.file); } - if (source.askBeforeDownload) { + if (config.askBeforeDownload) { const userResponse = await vscode.window.showInformationMessage( `Language server version ${source.tag} for rust-analyzer is not installed. ` + "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 (!await downloadServer(source)) return null; - - return prebuiltBinaryPath; + return await downloadServer(source, config); } } } -async function downloadServer(source: ArtifactSource.GithubRelease): Promise { +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 { try { const releaseInfo = await fetchArtifactReleaseInfo(source.repo, source.file, source.tag); - await downloadArtifact(releaseInfo, source.file, source.dir, "language server"); - await setServerVersion(source.storage, releaseInfo.releaseName); + await downloadArtifactWithProgressUi(releaseInfo, source.file, source.dir, "language server"); + await Promise.all([ + config.serverReleaseTag.set(releaseInfo.releaseName), + config.serverReleaseDate.set(releaseInfo.releaseDate) + ]); } catch (err) { - vscode.window.showErrorMessage( - `Failed to download language server from ${source.repo.name} ` + - `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; + log.downloadError(err, "language server", source.repo.name); + return null; } const binaryPath = path.join(source.dir, source.file); @@ -101,7 +111,7 @@ async function downloadServer(source: ArtifactSource.GithubRelease): Promise("server-version", null); - log.debug("Get server-version:", version); - return version; -} - -async function setServerVersion(storage: vscode.Memento, version: string): Promise { - log.debug("Set server-version:", version); - await storage.update("server-version", version.toString()); -} diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index ecf53cf775..ee67c750c1 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -8,6 +8,7 @@ import { activateHighlighting } from './highlighting'; import { ensureServerBinary } from './installation/server'; import { Config } from './config'; import { log } from './util'; +import { ensureProperExtensionVersion } from './installation/extension'; let ctx: Ctx | undefined; @@ -34,7 +35,13 @@ export async function activate(context: vscode.ExtensionContext) { 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) { throw new Error( "Rust Analyzer Language Server is not available. " +