diff options
-rw-r--r-- | editors/code/src/commands/server_version.ts | 3 | ||||
-rw-r--r-- | editors/code/src/installation/server.ts | 97 | ||||
-rw-r--r-- | 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 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 | ||
6 | export function serverVersion(ctx: Ctx): Cmd { | 6 | export 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 @@ | |||
1 | import * as vscode from "vscode"; | 1 | import * as vscode from "vscode"; |
2 | import * as path from "path"; | 2 | import * as path from "path"; |
3 | import { promises as dns } from "dns"; | ||
4 | import { spawnSync } from "child_process"; | 3 | import { spawnSync } from "child_process"; |
5 | 4 | ||
6 | import { ArtifactSource } from "./interfaces"; | 5 | import { ArtifactSource } from "./interfaces"; |
7 | import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info"; | 6 | import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info"; |
8 | import { downloadArtifact } from "./download_artifact"; | 7 | import { downloadArtifactWithProgressUi } from "./downloads"; |
9 | import { log, assert } from "../util"; | 8 | 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; | ||
10 | 13 | ||
11 | export 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 | ||
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> { | ||
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 | ||
107 | function isBinaryAvailable(binaryPath: string): boolean { | 117 | function 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 | |||
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 | } | ||
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'; | |||
8 | import { ensureServerBinary } from './installation/server'; | 8 | import { ensureServerBinary } from './installation/server'; |
9 | import { Config } from './config'; | 9 | import { Config } from './config'; |
10 | import { log } from './util'; | 10 | import { log } from './util'; |
11 | import { ensureProperExtensionVersion } from './installation/extension'; | ||
11 | 12 | ||
12 | let ctx: Ctx | undefined; | 13 | let 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. " + |