Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit 64a004c

Browse files
authored
Write the Ruby environment information into a temporary file (#918)
Some shell plugins take the stderr pipe over completely and prevent the NodeJS process from properly writing to the stderr in the shell. To avoid being susceptible to this issue, we can write the results into a temporary file we control
1 parent d0136c5 commit 64a004c

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

src/ruby.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import path from "path";
22
import fs from "fs/promises";
3+
import os from "os";
34

45
import * as vscode from "vscode";
56

@@ -170,11 +171,19 @@ export class Ruby {
170171
private async activate(ruby: string) {
171172
let command = this.shell ? `${this.shell} -ic '` : "";
172173

174+
// Certain shell plugins take over standard pipes like `stderr` and cause activation issues. To get around tools
175+
// that do that, we use a temporary file to write the environment information from Ruby and then read it in NodeJS
176+
// to apply the right environment variables
177+
const tmpFilePath = path.join(
178+
os.tmpdir(),
179+
`ruby_lsp_${path.basename(this.workingFolderPath)}`,
180+
);
181+
173182
// The Ruby activation script is intentionally written as an array that gets joined into a one liner because some
174183
// terminals cannot handle line breaks. Do not switch this to a multiline string or that will break activation for
175184
// those terminals
176185
const script = [
177-
"STDERR.printf(%{RUBY_ENV_ACTIVATE%sRUBY_ENV_ACTIVATE}, ",
186+
`File.write(\\"${tmpFilePath}\\", `,
178187
"JSON.dump({ env: ENV.to_h, ruby_version: RUBY_VERSION, yjit: defined?(RubyVM::YJIT) }))",
179188
].join("");
180189

@@ -188,16 +197,19 @@ export class Ruby {
188197
`Trying to activate Ruby environment with command: ${command} inside directory: ${this.cwd}`,
189198
);
190199

191-
const result = await asyncExec(command, { cwd: this.cwd });
192-
const rubyInfoJson = /RUBY_ENV_ACTIVATE(.*)RUBY_ENV_ACTIVATE/.exec(
193-
result.stderr,
194-
)![1];
195-
196-
const rubyInfo = JSON.parse(rubyInfoJson);
200+
try {
201+
await asyncExec(command, { cwd: this.cwd });
202+
const envJson = await fs.readFile(tmpFilePath, "utf8");
203+
const rubyInfo = JSON.parse(envJson);
197204

198-
this._env = rubyInfo.env;
199-
this.rubyVersion = rubyInfo.ruby_version;
200-
this.yjitEnabled = rubyInfo.yjit === "constant";
205+
this._env = rubyInfo.env;
206+
this.rubyVersion = rubyInfo.ruby_version;
207+
this.yjitEnabled = rubyInfo.yjit === "constant";
208+
} catch (error: any) {
209+
// Ensure we cleanup the temp file even if we failed to activate
210+
await fs.rm(tmpFilePath);
211+
throw error;
212+
}
201213
}
202214

203215
// Fetch information related to the Ruby version. This can only be invoked after activation, so that `rubyVersion` is

0 commit comments

Comments
 (0)