diff options
Diffstat (limited to 'editors/code/src/installation/server.ts')
-rw-r--r-- | editors/code/src/installation/server.ts | 131 |
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 @@ | |||
1 | import * as vscode from "vscode"; | ||
2 | import * as path from "path"; | ||
3 | import { spawnSync } from "child_process"; | ||
4 | |||
5 | import { ArtifactSource } from "./interfaces"; | ||
6 | import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info"; | ||
7 | import { downloadArtifactWithProgressUi } from "./downloads"; | ||
8 | import { log, assert, notReentrant } from "../util"; | ||
9 | import { Config, NIGHTLY_TAG } from "../config"; | ||
10 | import { PersistentState } from "../persistent_state"; | ||
11 | |||
12 | export 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 | |||
59 | function 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 | */ | ||
89 | const 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 | |||
121 | function 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 | } | ||