aboutsummaryrefslogtreecommitdiff
path: root/editors
diff options
context:
space:
mode:
authorVeetaha <[email protected]>2020-03-09 17:57:55 +0000
committerVeetaha <[email protected]>2020-03-14 00:01:46 +0000
commit1e73811fbe634efec90a3e009a84fd8dda9f5697 (patch)
treec87cff735a65fcc1c8d6c46d2dd8a9148f359c24 /editors
parent601fc9d1abf52c16356d49b6c540b31718e62b88 (diff)
vscode: amend server installation logic to account for nightlies
Diffstat (limited to 'editors')
-rw-r--r--editors/code/src/commands/server_version.ts3
-rw-r--r--editors/code/src/installation/server.ts97
-rw-r--r--editors/code/src/main.ts9
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 421301b42..c4d84b443 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';
5 5
6export function serverVersion(ctx: Ctx): Cmd { 6export function serverVersion(ctx: Ctx): Cmd {
7 return async () => { 7 return async () => {
8 const binaryPath = await ensureServerBinary(ctx.config.serverSource); 8 const binaryPath = await ensureServerBinary(ctx.config);
9 9
10 if (binaryPath == null) { 10 if (binaryPath == null) {
11 throw new Error( 11 throw new Error(
@@ -18,4 +18,3 @@ export function serverVersion(ctx: Ctx): Cmd {
18 vscode.window.showInformationMessage('rust-analyzer version : ' + version); 18 vscode.window.showInformationMessage('rust-analyzer version : ' + version);
19 }; 19 };
20} 20}
21
diff --git a/editors/code/src/installation/server.ts b/editors/code/src/installation/server.ts
index ef1c45ff6..345f30d47 100644
--- a/editors/code/src/installation/server.ts
+++ b/editors/code/src/installation/server.ts
@@ -1,14 +1,16 @@
1import * as vscode from "vscode"; 1import * as vscode from "vscode";
2import * as path from "path"; 2import * as path from "path";
3import { promises as dns } from "dns";
4import { spawnSync } from "child_process"; 3import { spawnSync } from "child_process";
5 4
6import { ArtifactSource } from "./interfaces"; 5import { ArtifactSource } from "./interfaces";
7import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info"; 6import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info";
8import { downloadArtifact } from "./download_artifact"; 7import { downloadArtifactWithProgressUi } from "./downloads";
9import { log, assert } from "../util"; 8import { log, assert } from "../util";
9import { Config, NIGHTLY_TAG } from "../config";
10
11export async function ensureServerBinary(config: Config): Promise<null | string> {
12 const source = config.serverSource;
10 13
11export async function ensureServerBinary(source: null | ArtifactSource): Promise<null | string> {
12 if (!source) { 14 if (!source) {
13 vscode.window.showErrorMessage( 15 vscode.window.showErrorMessage(
14 "Unfortunately we don't ship binaries for your platform yet. " + 16 "Unfortunately we don't ship binaries for your platform yet. " +
@@ -35,18 +37,11 @@ export async function ensureServerBinary(source: null | ArtifactSource): Promise
35 return null; 37 return null;
36 } 38 }
37 case ArtifactSource.Type.GithubRelease: { 39 case ArtifactSource.Type.GithubRelease: {
38 const prebuiltBinaryPath = path.join(source.dir, source.file); 40 if (!shouldDownloadServer(source, config)) {
39 41 return path.join(source.dir, source.file);
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;
47 } 42 }
48 43
49 if (source.askBeforeDownload) { 44 if (config.askBeforeDownload) {
50 const userResponse = await vscode.window.showInformationMessage( 45 const userResponse = await vscode.window.showInformationMessage(
51 `Language server version ${source.tag} for rust-analyzer is not installed. ` + 46 `Language server version ${source.tag} for rust-analyzer is not installed. ` +
52 "Do you want to download it now?", 47 "Do you want to download it now?",
@@ -55,38 +50,53 @@ export async function ensureServerBinary(source: null | ArtifactSource): Promise
55 if (userResponse !== "Download now") return null; 50 if (userResponse !== "Download now") return null;
56 } 51 }
57 52
58 if (!await downloadServer(source)) return null; 53 return await downloadServer(source, config);
59
60 return prebuiltBinaryPath;
61 } 54 }
62 } 55 }
63} 56}
64 57
65async function downloadServer(source: ArtifactSource.GithubRelease): Promise<boolean> { 58function 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
85async function downloadServer(
86 source: ArtifactSource.GithubRelease,
87 config: Config,
88): Promise<null | string> {
66 try { 89 try {
67 const releaseInfo = await fetchArtifactReleaseInfo(source.repo, source.file, source.tag); 90 const releaseInfo = await fetchArtifactReleaseInfo(source.repo, source.file, source.tag);
68 91
69 await downloadArtifact(releaseInfo, source.file, source.dir, "language server"); 92 await downloadArtifactWithProgressUi(releaseInfo, source.file, source.dir, "language server");
70 await setServerVersion(source.storage, releaseInfo.releaseName); 93 await Promise.all([
94 config.serverReleaseTag.set(releaseInfo.releaseName),
95 config.serverReleaseDate.set(releaseInfo.releaseDate)
96 ]);
71 } catch (err) { 97 } catch (err) {
72 vscode.window.showErrorMessage( 98 log.downloadError(err, "language server", source.repo.name);
73 `Failed to download language server from ${source.repo.name} ` + 99 return null;
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;
90 } 100 }
91 101
92 const binaryPath = path.join(source.dir, source.file); 102 const binaryPath = path.join(source.dir, source.file);
@@ -101,7 +111,7 @@ async function downloadServer(source: ArtifactSource.GithubRelease): Promise<boo
101 "Rust analyzer language server was successfully installed 🦀" 111 "Rust analyzer language server was successfully installed 🦀"
102 ); 112 );
103 113
104 return true; 114 return binaryPath;
105} 115}
106 116
107function isBinaryAvailable(binaryPath: string): boolean { 117function isBinaryAvailable(binaryPath: string): boolean {
@@ -115,14 +125,3 @@ function isBinaryAvailable(binaryPath: string): boolean {
115 125
116 return res.status === 0; 126 return res.status === 0;
117} 127}
118
119function 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
125async 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}
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index ecf53cf77..ee67c750c 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -8,6 +8,7 @@ import { activateHighlighting } from './highlighting';
8import { ensureServerBinary } from './installation/server'; 8import { ensureServerBinary } from './installation/server';
9import { Config } from './config'; 9import { Config } from './config';
10import { log } from './util'; 10import { log } from './util';
11import { ensureProperExtensionVersion } from './installation/extension';
11 12
12let ctx: Ctx | undefined; 13let ctx: Ctx | undefined;
13 14
@@ -34,7 +35,13 @@ export async function activate(context: vscode.ExtensionContext) {
34 35
35 const config = new Config(context); 36 const config = new Config(context);
36 37
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
38 if (serverPath == null) { 45 if (serverPath == null) {
39 throw new Error( 46 throw new Error(
40 "Rust Analyzer Language Server is not available. " + 47 "Rust Analyzer Language Server is not available. " +