Skip to content

Commit 90437cc

Browse files
authored
Move chruby activation script into a file (#3551)
1 parent f257fd7 commit 90437cc

File tree

7 files changed

+71
-78
lines changed

7 files changed

+71
-78
lines changed

test/integration_test.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,25 @@ def test_activation_script_succeeds_even_on_binary_encoding
5656
end
5757
end
5858

59+
def test_chruby_activation_script
60+
_stdout, stderr, status = Open3.capture3(
61+
"ruby",
62+
"-EUTF-8:UTF-8",
63+
File.join(__dir__, "..", "vscode", "chruby_activation.rb"),
64+
RUBY_VERSION,
65+
)
66+
67+
assert_equal(0, status.exitstatus, stderr)
68+
69+
default_gems, gem_home, yjit, version = stderr.split("RUBY_LSP_ACTIVATION_SEPARATOR")
70+
71+
assert_equal(RUBY_VERSION, version)
72+
# These may be switched in CI due to Bundler settings, so we use simpler assertions
73+
assert(yjit)
74+
assert(gem_home)
75+
assert(default_gems)
76+
end
77+
5978
def test_activation_script_succeeds_on_invalid_unicode
6079
ENV["LC_ALL"] = "C"
6180
ENV["LANG"] = "C"

vscode/chruby_activation.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# frozen_string_literal: true
2+
3+
# Typically, GEM_HOME points to $HOME/.gem/ruby/version_without_patch. For example, for Ruby 3.2.2, it would be
4+
# $HOME/.gem/ruby/3.2.0. However, chruby overrides GEM_HOME to use the patch part of the version, resulting in
5+
# $HOME/.gem/ruby/3.2.2. In our activation script, we check if a directory using the patch exists and then prefer
6+
# that over the default one.
7+
user_dir = Gem.user_dir
8+
paths = Gem.path
9+
default_dir = Gem.default_dir
10+
11+
if paths.length > 2
12+
paths.delete(default_dir)
13+
paths.delete(user_dir)
14+
first_path = paths[0]
15+
user_dir = first_path if first_path && Dir.exist?(first_path)
16+
end
17+
18+
newer_gem_home = File.join(File.dirname(user_dir), ARGV.first)
19+
gems = Dir.exist?(newer_gem_home) ? newer_gem_home : user_dir
20+
STDERR.print(
21+
[
22+
default_dir,
23+
gems,
24+
!!defined?(RubyVM::YJIT),
25+
RUBY_VERSION
26+
].join("RUBY_LSP_ACTIVATION_SEPARATOR")
27+
)

vscode/src/ruby/chruby.ts

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -180,27 +180,13 @@ export class Chruby extends VersionManager {
180180
yjit: boolean;
181181
version: string;
182182
}> {
183-
// Typically, GEM_HOME points to $HOME/.gem/ruby/version_without_patch. For example, for Ruby 3.2.2, it would be
184-
// $HOME/.gem/ruby/3.2.0. However, chruby overrides GEM_HOME to use the patch part of the version, resulting in
185-
// $HOME/.gem/ruby/3.2.2. In our activation script, we check if a directory using the patch exists and then prefer
186-
// that over the default one.
187-
const script = [
188-
"user_dir = Gem.user_dir",
189-
"paths = Gem.path",
190-
"if paths.length > 2",
191-
" paths.delete(Gem.default_dir)",
192-
" paths.delete(Gem.user_dir)",
193-
" if paths[0]",
194-
" user_dir = paths[0] if Dir.exist?(paths[0])",
195-
" end",
196-
"end",
197-
`newer_gem_home = File.join(File.dirname(user_dir), "${rubyVersion.version}")`,
198-
"gems = (Dir.exist?(newer_gem_home) ? newer_gem_home : user_dir)",
199-
`STDERR.print([Gem.default_dir, gems, !!defined?(RubyVM::YJIT), RUBY_VERSION].join("${ACTIVATION_SEPARATOR}"))`,
200-
].join(";");
183+
const activationUri = vscode.Uri.joinPath(
184+
this.context.extensionUri,
185+
"chruby_activation.rb",
186+
);
201187

202188
const result = await this.runScript(
203-
`${rubyExecutableUri.fsPath} -EUTF-8:UTF-8 -e '${script}'`,
189+
`${rubyExecutableUri.fsPath} -EUTF-8:UTF-8 '${activationUri.fsPath}' ${rubyVersion.version}`,
204190
);
205191

206192
const [defaultGems, gemHome, yjit, version] =

vscode/src/ruby/rubyInstaller.ts

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import os from "os";
33

44
import * as vscode from "vscode";
55

6-
import { asyncExec } from "../common";
7-
86
import { Chruby } from "./chruby";
97

108
interface RubyVersion {
@@ -77,21 +75,4 @@ export class RubyInstaller extends Chruby {
7775

7876
return activationResult;
7977
}
80-
81-
// Override the `runScript` method to ensure that we do not pass any `shell` to `asyncExec`. The activation script is
82-
// only compatible with `cmd.exe`, and not Powershell, due to escaping of quotes. We need to ensure to always run the
83-
// script on `cmd.exe`.
84-
protected runScript(command: string) {
85-
this.outputChannel.info(
86-
`Running command: \`${command}\` in ${this.bundleUri.fsPath}`,
87-
);
88-
this.outputChannel.debug(
89-
`Environment used for command: ${JSON.stringify(process.env)}`,
90-
);
91-
92-
return asyncExec(command, {
93-
cwd: this.bundleUri.fsPath,
94-
env: process.env,
95-
});
96-
}
9778
}

vscode/src/ruby/versionManager.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ export abstract class VersionManager {
2424
protected readonly workspaceFolder: vscode.WorkspaceFolder;
2525
protected readonly bundleUri: vscode.Uri;
2626
protected readonly manuallySelectRuby: () => Promise<void>;
27-
28-
private readonly context: vscode.ExtensionContext;
27+
protected readonly context: vscode.ExtensionContext;
2928
private readonly customBundleGemfile?: string;
3029

3130
constructor(

vscode/src/test/suite/ruby/chruby.test.ts

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { WorkspaceChannel } from "../../../workspaceChannel";
1313
import { LOG_CHANNEL } from "../../../common";
1414
import { RUBY_VERSION, MAJOR, MINOR, VERSION_REGEX } from "../../rubyVersion";
1515
import { ActivationResult } from "../../../ruby/versionManager";
16+
import { CONTEXT } from "../helpers";
1617

1718
// Create links to the real Ruby installations on CI and on our local machines
1819
function createRubySymlinks(destination: string) {
@@ -50,16 +51,6 @@ suite("Chruby", () => {
5051
return;
5152
}
5253

53-
const context = {
54-
extensionMode: vscode.ExtensionMode.Test,
55-
subscriptions: [],
56-
workspaceState: {
57-
get: (_name: string) => undefined,
58-
update: (_name: string, _value: any) => Promise.resolve(),
59-
},
60-
extensionUri: vscode.Uri.parse("file:///fake"),
61-
} as unknown as vscode.ExtensionContext;
62-
6354
let rootPath: string;
6455
let workspacePath: string;
6556
let workspaceFolder: vscode.WorkspaceFolder;
@@ -97,7 +88,7 @@ suite("Chruby", () => {
9788
const chruby = new Chruby(
9889
workspaceFolder,
9990
outputChannel,
100-
context,
91+
CONTEXT,
10192
async () => {},
10293
);
10394
chruby.rubyInstallationUris = [
@@ -114,7 +105,7 @@ suite("Chruby", () => {
114105
const chruby = new Chruby(
115106
workspaceFolder,
116107
outputChannel,
117-
context,
108+
CONTEXT,
118109
async () => {},
119110
);
120111
chruby.rubyInstallationUris = [
@@ -151,7 +142,7 @@ suite("Chruby", () => {
151142
const chruby = new Chruby(
152143
workspaceFolder,
153144
outputChannel,
154-
context,
145+
CONTEXT,
155146
async () => {},
156147
);
157148
chruby.rubyInstallationUris = [
@@ -201,7 +192,7 @@ suite("Chruby", () => {
201192
const chruby = new Chruby(
202193
workspaceFolder,
203194
outputChannel,
204-
context,
195+
CONTEXT,
205196
async () => {},
206197
);
207198
chruby.rubyInstallationUris = [
@@ -236,7 +227,7 @@ suite("Chruby", () => {
236227
const chruby = new Chruby(
237228
workspaceFolder,
238229
outputChannel,
239-
context,
230+
CONTEXT,
240231
async () => {},
241232
);
242233
chruby.rubyInstallationUris = [vscode.Uri.file(rubyHome)];
@@ -263,7 +254,7 @@ suite("Chruby", () => {
263254
const chruby = new Chruby(
264255
workspaceFolder,
265256
outputChannel,
266-
context,
257+
CONTEXT,
267258
async () => {},
268259
);
269260
configStub.restore();
@@ -288,7 +279,7 @@ suite("Chruby", () => {
288279
const chruby = new Chruby(
289280
workspaceFolder,
290281
outputChannel,
291-
context,
282+
CONTEXT,
292283
async () => {},
293284
);
294285
chruby.rubyInstallationUris = [
@@ -320,7 +311,7 @@ suite("Chruby", () => {
320311
const chruby = new Chruby(
321312
workspaceFolder,
322313
outputChannel,
323-
context,
314+
CONTEXT,
324315
async () => {},
325316
);
326317
chruby.rubyInstallationUris = [
@@ -336,7 +327,7 @@ suite("Chruby", () => {
336327
const chruby = new Chruby(
337328
workspaceFolder,
338329
outputChannel,
339-
context,
330+
CONTEXT,
340331
async () => {},
341332
);
342333
chruby.rubyInstallationUris = [
@@ -353,7 +344,7 @@ suite("Chruby", () => {
353344
const chruby = new Chruby(
354345
workspaceFolder,
355346
outputChannel,
356-
context,
347+
CONTEXT,
357348
async () => {},
358349
);
359350
chruby.rubyInstallationUris = [
@@ -371,7 +362,7 @@ suite("Chruby", () => {
371362
const chruby = new Chruby(
372363
workspaceFolder,
373364
outputChannel,
374-
context,
365+
CONTEXT,
375366
async () => {},
376367
);
377368
chruby.rubyInstallationUris = [
@@ -388,7 +379,7 @@ suite("Chruby", () => {
388379
const chruby = new Chruby(
389380
workspaceFolder,
390381
outputChannel,
391-
context,
382+
CONTEXT,
392383
async () => {},
393384
);
394385
chruby.rubyInstallationUris = [
@@ -408,7 +399,7 @@ suite("Chruby", () => {
408399
const chruby = new Chruby(
409400
workspaceFolder,
410401
outputChannel,
411-
context,
402+
CONTEXT,
412403
async () => {},
413404
);
414405
chruby.rubyInstallationUris = [

vscode/src/test/suite/ruby/rubyInstaller.test.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { WorkspaceChannel } from "../../../workspaceChannel";
1313
import { LOG_CHANNEL } from "../../../common";
1414
import { RUBY_VERSION, VERSION_REGEX } from "../../rubyVersion";
1515
import { ACTIVATION_SEPARATOR } from "../../../ruby/versionManager";
16-
import { createRubySymlinks } from "../helpers";
16+
import { createRubySymlinks, CONTEXT } from "../helpers";
1717

1818
suite("RubyInstaller", () => {
1919
if (os.platform() !== "win32") {
@@ -22,16 +22,6 @@ suite("RubyInstaller", () => {
2222
return;
2323
}
2424

25-
const context = {
26-
extensionMode: vscode.ExtensionMode.Test,
27-
subscriptions: [],
28-
workspaceState: {
29-
get: (_name: string) => undefined,
30-
update: (_name: string, _value: any) => Promise.resolve(),
31-
},
32-
extensionUri: vscode.Uri.parse("file:///fake"),
33-
} as unknown as vscode.ExtensionContext;
34-
3525
let rootPath: string;
3626
let workspacePath: string;
3727
let workspaceFolder: vscode.WorkspaceFolder;
@@ -68,7 +58,7 @@ suite("RubyInstaller", () => {
6858
const windows = new RubyInstaller(
6959
workspaceFolder,
7060
outputChannel,
71-
context,
61+
CONTEXT,
7262
async () => {},
7363
);
7464
const { env, version, yjit } = await windows.activate();
@@ -88,7 +78,7 @@ suite("RubyInstaller", () => {
8878
const windows = new RubyInstaller(
8979
workspaceFolder,
9080
outputChannel,
91-
context,
81+
CONTEXT,
9282
async () => {},
9383
);
9484
const { env, version, yjit } = await windows.activate();
@@ -108,7 +98,7 @@ suite("RubyInstaller", () => {
10898
const windows = new RubyInstaller(
10999
workspaceFolder,
110100
outputChannel,
111-
context,
101+
CONTEXT,
112102
async () => {},
113103
);
114104
const result = ["/fake/dir", "/other/fake/dir", true, RUBY_VERSION].join(
@@ -133,7 +123,7 @@ suite("RubyInstaller", () => {
133123
const windows = new RubyInstaller(
134124
workspaceFolder,
135125
outputChannel,
136-
context,
126+
CONTEXT,
137127
async () => {},
138128
);
139129
const result = [

0 commit comments

Comments
 (0)