Skip to content

Commit 1e73811

Browse files
author
Veetaha
committed
vscode: amend server installation logic to account for nightlies
1 parent 601fc9d commit 1e73811

File tree

3 files changed

+57
-52
lines changed

3 files changed

+57
-52
lines changed

editors/code/src/commands/server_version.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { spawnSync } from 'child_process';
55

66
export function serverVersion(ctx: Ctx): Cmd {
77
return async () => {
8-
const binaryPath = await ensureServerBinary(ctx.config.serverSource);
8+
const binaryPath = await ensureServerBinary(ctx.config);
99

1010
if (binaryPath == null) {
1111
throw new Error(
@@ -18,4 +18,3 @@ export function serverVersion(ctx: Ctx): Cmd {
1818
vscode.window.showInformationMessage('rust-analyzer version : ' + version);
1919
};
2020
}
21-
Lines changed: 48 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import * as vscode from "vscode";
22
import * as path from "path";
3-
import { promises as dns } from "dns";
43
import { spawnSync } from "child_process";
54

65
import { ArtifactSource } from "./interfaces";
76
import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info";
8-
import { downloadArtifact } from "./download_artifact";
7+
import { downloadArtifactWithProgressUi } from "./downloads";
98
import { log, assert } from "../util";
9+
import { Config, NIGHTLY_TAG } from "../config";
10+
11+
export async function ensureServerBinary(config: Config): Promise<null | string> {
12+
const source = config.serverSource;
1013

11-
export async function ensureServerBinary(source: null | ArtifactSource): Promise<null | string> {
1214
if (!source) {
1315
vscode.window.showErrorMessage(
1416
"Unfortunately we don't ship binaries for your platform yet. " +
@@ -35,18 +37,11 @@ export async function ensureServerBinary(source: null | ArtifactSource): Promise
3537
return null;
3638
}
3739
case ArtifactSource.Type.GithubRelease: {
38-
const prebuiltBinaryPath = path.join(source.dir, source.file);
39-
40-
const installedVersion: null | string = getServerVersion(source.storage);
41-
const requiredVersion: string = source.tag;
42-
43-
log.debug("Installed version:", installedVersion, "required:", requiredVersion);
44-
45-
if (isBinaryAvailable(prebuiltBinaryPath) && installedVersion === requiredVersion) {
46-
return prebuiltBinaryPath;
40+
if (!shouldDownloadServer(source, config)) {
41+
return path.join(source.dir, source.file);
4742
}
4843

49-
if (source.askBeforeDownload) {
44+
if (config.askBeforeDownload) {
5045
const userResponse = await vscode.window.showInformationMessage(
5146
`Language server version ${source.tag} for rust-analyzer is not installed. ` +
5247
"Do you want to download it now?",
@@ -55,38 +50,53 @@ export async function ensureServerBinary(source: null | ArtifactSource): Promise
5550
if (userResponse !== "Download now") return null;
5651
}
5752

58-
if (!await downloadServer(source)) return null;
59-
60-
return prebuiltBinaryPath;
53+
return await downloadServer(source, config);
6154
}
6255
}
6356
}
6457

65-
async function downloadServer(source: ArtifactSource.GithubRelease): Promise<boolean> {
58+
function shouldDownloadServer(
59+
source: ArtifactSource.GithubRelease,
60+
config: Config
61+
): boolean {
62+
if (!isBinaryAvailable(path.join(source.dir, source.file))) return true;
63+
64+
const installed = {
65+
tag: config.serverReleaseTag.get(),
66+
date: config.serverReleaseDate.get()
67+
};
68+
const required = {
69+
tag: source.tag,
70+
date: config.installedNightlyExtensionReleaseDate.get()
71+
};
72+
73+
log.debug("Installed server:", installed, "required:", required);
74+
75+
if (required.tag !== NIGHTLY_TAG || installed.tag !== NIGHTLY_TAG) {
76+
return required.tag !== installed.tag;
77+
}
78+
79+
assert(required.date !== null, "Extension release date should have been saved during its installation");
80+
assert(installed.date !== null, "Server release date should have been saved during its installation");
81+
82+
return installed.date.getTime() !== required.date.getTime();
83+
}
84+
85+
async function downloadServer(
86+
source: ArtifactSource.GithubRelease,
87+
config: Config,
88+
): Promise<null | string> {
6689
try {
6790
const releaseInfo = await fetchArtifactReleaseInfo(source.repo, source.file, source.tag);
6891

69-
await downloadArtifact(releaseInfo, source.file, source.dir, "language server");
70-
await setServerVersion(source.storage, releaseInfo.releaseName);
92+
await downloadArtifactWithProgressUi(releaseInfo, source.file, source.dir, "language server");
93+
await Promise.all([
94+
config.serverReleaseTag.set(releaseInfo.releaseName),
95+
config.serverReleaseDate.set(releaseInfo.releaseDate)
96+
]);
7197
} catch (err) {
72-
vscode.window.showErrorMessage(
73-
`Failed to download language server from ${source.repo.name} ` +
74-
`GitHub repository: ${err.message}`
75-
);
76-
77-
log.error(err);
78-
79-
dns.resolve('example.com').then(
80-
addrs => log.debug("DNS resolution for example.com was successful", addrs),
81-
err => {
82-
log.error(
83-
"DNS resolution for example.com failed, " +
84-
"there might be an issue with Internet availability"
85-
);
86-
log.error(err);
87-
}
88-
);
89-
return false;
98+
log.downloadError(err, "language server", source.repo.name);
99+
return null;
90100
}
91101

92102
const binaryPath = path.join(source.dir, source.file);
@@ -101,7 +111,7 @@ async function downloadServer(source: ArtifactSource.GithubRelease): Promise<boo
101111
"Rust analyzer language server was successfully installed 🦀"
102112
);
103113

104-
return true;
114+
return binaryPath;
105115
}
106116

107117
function isBinaryAvailable(binaryPath: string): boolean {
@@ -115,14 +125,3 @@ function isBinaryAvailable(binaryPath: string): boolean {
115125

116126
return res.status === 0;
117127
}
118-
119-
function getServerVersion(storage: vscode.Memento): null | string {
120-
const version = storage.get<null | string>("server-version", null);
121-
log.debug("Get server-version:", version);
122-
return version;
123-
}
124-
125-
async function setServerVersion(storage: vscode.Memento, version: string): Promise<void> {
126-
log.debug("Set server-version:", version);
127-
await storage.update("server-version", version.toString());
128-
}

editors/code/src/main.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { activateHighlighting } from './highlighting';
88
import { ensureServerBinary } from './installation/server';
99
import { Config } from './config';
1010
import { log } from './util';
11+
import { ensureProperExtensionVersion } from './installation/extension';
1112

1213
let ctx: Ctx | undefined;
1314

@@ -34,7 +35,13 @@ export async function activate(context: vscode.ExtensionContext) {
3435

3536
const config = new Config(context);
3637

37-
const serverPath = await ensureServerBinary(config.serverSource);
38+
vscode.workspace.onDidChangeConfiguration(() => ensureProperExtensionVersion(config));
39+
40+
// Don't await the user response here, otherwise we will block the lsp server bootstrap
41+
void ensureProperExtensionVersion(config);
42+
43+
const serverPath = await ensureServerBinary(config);
44+
3845
if (serverPath == null) {
3946
throw new Error(
4047
"Rust Analyzer Language Server is not available. " +

0 commit comments

Comments
 (0)