aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editors/code/src/main.ts49
1 files changed, 48 insertions, 1 deletions
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index ac3bb365e..0a234cb84 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -1,7 +1,7 @@
1import * as vscode from 'vscode'; 1import * as vscode from 'vscode';
2import * as path from "path"; 2import * as path from "path";
3import * as os from "os"; 3import * as os from "os";
4import { promises as fs } from "fs"; 4import { promises as fs, PathLike } from "fs";
5 5
6import * as commands from './commands'; 6import * as commands from './commands';
7import { activateInlayHints } from './inlay_hints'; 7import { activateInlayHints } from './inlay_hints';
@@ -12,6 +12,7 @@ import { log, assert, isValidExecutable } from './util';
12import { PersistentState } from './persistent_state'; 12import { PersistentState } from './persistent_state';
13import { fetchRelease, download } from './net'; 13import { fetchRelease, download } from './net';
14import { activateTaskProvider } from './tasks'; 14import { activateTaskProvider } from './tasks';
15import { exec } from 'child_process';
15 16
16let ctx: Ctx | undefined; 17let ctx: Ctx | undefined;
17 18
@@ -188,6 +189,46 @@ async function bootstrapServer(config: Config, state: PersistentState): Promise<
188 return path; 189 return path;
189} 190}
190 191
192async function patchelf(dest: PathLike): Promise<void> {
193 await vscode.window.withProgress(
194 {
195 location: vscode.ProgressLocation.Notification,
196 title: "Patching rust-analysis for NixOS"
197 },
198 async (progress, _) => {
199 let patch_path = path.join(os.tmpdir(), "patch-ra.nix")
200 progress.report({message: "Writing nix file", increment: 5})
201 await fs.writeFile(patch_path, `
202 {src, pkgs ? import <nixpkgs> {}}:
203 pkgs.stdenv.mkDerivation {
204 name = "rust-analyzer";
205 inherit src;
206 phases = [ "installPhase" "fixupPhase" ];
207 installPhase = "cp $src $out";
208 fixupPhase = ''
209 chmod 755 $out
210 patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" $out
211 '';
212 }
213 `)
214 let orig_file = dest + "-orig"
215 await fs.rename(dest, orig_file)
216 progress.report({message: "Patching executable", increment: 20})
217 await new Promise((resolve, reject) => {
218 exec(`nix-build ${patch_path} --arg src '${orig_file}' -o ${dest}`,
219 (err, stdout, stderr) => {
220 if (err != null) {
221 reject(Error(stderr))
222 } else {
223 resolve(stdout)
224 }
225 })
226 })
227 // await fs.unlink(orig_file)
228 }
229 )
230}
231
191async function getServer(config: Config, state: PersistentState): Promise<string | undefined> { 232async function getServer(config: Config, state: PersistentState): Promise<string | undefined> {
192 const explicitPath = process.env.__RA_LSP_SERVER_DEBUG ?? config.serverPath; 233 const explicitPath = process.env.__RA_LSP_SERVER_DEBUG ?? config.serverPath;
193 if (explicitPath) { 234 if (explicitPath) {
@@ -237,6 +278,12 @@ async function getServer(config: Config, state: PersistentState): Promise<string
237 assert(!!artifact, `Bad release: ${JSON.stringify(release)}`); 278 assert(!!artifact, `Bad release: ${JSON.stringify(release)}`);
238 279
239 await download(artifact.browser_download_url, dest, "Downloading rust-analyzer server", { mode: 0o755 }); 280 await download(artifact.browser_download_url, dest, "Downloading rust-analyzer server", { mode: 0o755 });
281
282 // Patching executable if that's NixOS.
283 if (fs.stat("/etc/nixos").then(_ => true).catch(_ => false)) {
284 await patchelf(dest)
285 }
286
240 await state.updateServerVersion(config.package.version); 287 await state.updateServerVersion(config.package.version);
241 return dest; 288 return dest;
242} 289}