aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/installation/server.ts
diff options
context:
space:
mode:
Diffstat (limited to 'editors/code/src/installation/server.ts')
-rw-r--r--editors/code/src/installation/server.ts131
1 files changed, 0 insertions, 131 deletions
diff --git a/editors/code/src/installation/server.ts b/editors/code/src/installation/server.ts
deleted file mode 100644
index 05d326131..000000000
--- a/editors/code/src/installation/server.ts
+++ /dev/null
@@ -1,131 +0,0 @@
1import * as vscode from "vscode";
2import * as path from "path";
3import { spawnSync } from "child_process";
4
5import { ArtifactSource } from "./interfaces";
6import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info";
7import { downloadArtifactWithProgressUi } from "./downloads";
8import { log, assert, notReentrant } from "../util";
9import { Config, NIGHTLY_TAG } from "../config";
10import { PersistentState } from "../persistent_state";
11
12export async function ensureServerBinary(config: Config, state: PersistentState): Promise<null | string> {
13 const source = config.serverSource;
14
15 if (!source) {
16 vscode.window.showErrorMessage(
17 "Unfortunately we don't ship binaries for your platform yet. " +
18 "You need to manually clone rust-analyzer repository and " +
19 "run `cargo xtask install --server` to build the language server from sources. " +
20 "If you feel that your platform should be supported, please create an issue " +
21 "about that [here](https://github.com/rust-analyzer/rust-analyzer/issues) and we " +
22 "will consider it."
23 );
24 return null;
25 }
26
27 switch (source.type) {
28 case ArtifactSource.Type.ExplicitPath: {
29 if (isBinaryAvailable(source.path)) {
30 return source.path;
31 }
32
33 vscode.window.showErrorMessage(
34 `Unable to run ${source.path} binary. ` +
35 `To use the pre-built language server, set "rust-analyzer.serverPath" ` +
36 "value to `null` or remove it from the settings to use it by default."
37 );
38 return null;
39 }
40 case ArtifactSource.Type.GithubRelease: {
41 if (!shouldDownloadServer(state, source)) {
42 return path.join(source.dir, source.file);
43 }
44
45 if (config.askBeforeDownload) {
46 const userResponse = await vscode.window.showInformationMessage(
47 `Language server version ${source.tag} for rust-analyzer is not installed. ` +
48 "Do you want to download it now?",
49 "Download now", "Cancel"
50 );
51 if (userResponse !== "Download now") return null;
52 }
53
54 return await downloadServer(state, source);
55 }
56 }
57}
58
59function shouldDownloadServer(
60 state: PersistentState,
61 source: ArtifactSource.GithubRelease,
62): boolean {
63 if (!isBinaryAvailable(path.join(source.dir, source.file))) return true;
64
65 const installed = {
66 tag: state.serverReleaseTag.get(),
67 date: state.serverReleaseDate.get()
68 };
69 const required = {
70 tag: source.tag,
71 date: state.installedNightlyExtensionReleaseDate.get()
72 };
73
74 log.debug("Installed server:", installed, "required:", required);
75
76 if (required.tag !== NIGHTLY_TAG || installed.tag !== NIGHTLY_TAG) {
77 return required.tag !== installed.tag;
78 }
79
80 assert(required.date !== null, "Extension release date should have been saved during its installation");
81 assert(installed.date !== null, "Server release date should have been saved during its installation");
82
83 return installed.date.getTime() !== required.date.getTime();
84}
85
86/**
87 * Enforcing no reentrancy for this is best-effort.
88 */
89const downloadServer = notReentrant(async (
90 state: PersistentState,
91 source: ArtifactSource.GithubRelease,
92): Promise<null | string> => {
93 try {
94 const releaseInfo = await fetchArtifactReleaseInfo(source.repo, source.file, source.tag);
95
96 await downloadArtifactWithProgressUi(releaseInfo, source.file, source.dir, "language server");
97 await Promise.all([
98 state.serverReleaseTag.set(releaseInfo.releaseName),
99 state.serverReleaseDate.set(releaseInfo.releaseDate)
100 ]);
101 } catch (err) {
102 log.downloadError(err, "language server", source.repo.name);
103 return null;
104 }
105
106 const binaryPath = path.join(source.dir, source.file);
107
108 assert(isBinaryAvailable(binaryPath),
109 `Downloaded language server binary is not functional.` +
110 `Downloaded from GitHub repo ${source.repo.owner}/${source.repo.name} ` +
111 `to ${binaryPath}`
112 );
113
114 vscode.window.showInformationMessage(
115 "Rust analyzer language server was successfully installed 🦀"
116 );
117
118 return binaryPath;
119});
120
121function isBinaryAvailable(binaryPath: string): boolean {
122 const res = spawnSync(binaryPath, ["--version"]);
123
124 // ACHTUNG! `res` type declaration is inherently wrong, see
125 // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/42221
126
127 log.debug("Checked binary availablity via --version", res);
128 log.debug(binaryPath, "--version output:", res.output?.map(String));
129
130 return res.status === 0;
131}