Skip to content

Commit

Permalink
Use activated environment by RVM (#1868)
Browse files Browse the repository at this point in the history
* Consider /usr/local/rvm as a possible installation path

* Use environment activated by RVM
  • Loading branch information
vinistock committed Apr 2, 2024
1 parent 049d0e6 commit 7395355
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 41 deletions.
65 changes: 41 additions & 24 deletions vscode/src/ruby/rvm.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable no-process-env */
import os from "os";
import path from "path";

import * as vscode from "vscode";

import { asyncExec } from "../common";

Expand All @@ -12,45 +13,61 @@ import { ActivationResult, VersionManager } from "./versionManager";
// - https://rvm.io
export class Rvm extends VersionManager {
async activate(): Promise<ActivationResult> {
const activationScript = [
"STDERR.print(",
"{yjit:!!defined?(RubyVM::YJIT),version:RUBY_VERSION,",
"home:Gem.user_dir,default:Gem.default_dir,ruby:RbConfig.ruby}",
".to_json)",
].join("");
const activationScript =
"STDERR.print({ env: ENV.to_h, yjit: !!defined?(RubyVM::YJIT), version: RUBY_VERSION }.to_json)";

const installationPath = await this.findRvmInstallation();

const result = await asyncExec(
`${path.join(os.homedir(), ".rvm", "bin", "rvm-auto-ruby")} -W0 -rjson -e '${activationScript}'`,
`${installationPath.fsPath} -W0 -rjson -e '${activationScript}'`,
{
cwd: this.bundleUri.fsPath,
},
);

const parsedResult = JSON.parse(result.stderr);

// Invoking `rvm-auto-ruby` doesn't actually inject anything into the environment, it just finds the right Ruby to
// execute. We need to build the environment from the variables we return in the activation script
const env = {
GEM_HOME: parsedResult.home,
GEM_PATH: `${parsedResult.home}${path.delimiter}${parsedResult.default}`,
PATH: [
path.join(parsedResult.home, "bin"),
path.join(parsedResult.default, "bin"),
path.dirname(parsedResult.ruby),
process.env.PATH,
].join(path.delimiter),
};

const activatedKeys = Object.entries(env)
const activatedKeys = Object.entries(parsedResult.env)
.map(([key, value]) => `${key}=${value}`)
.join(" ");

this.outputChannel.info(`Activated Ruby environment: ${activatedKeys}`);

return {
env: { ...process.env, ...env },
env: { ...process.env, ...parsedResult.env },
yjit: parsedResult.yjit,
version: parsedResult.version,
};
}

async findRvmInstallation(): Promise<vscode.Uri> {
const possiblePaths = [
vscode.Uri.joinPath(
vscode.Uri.file(os.homedir()),
".rvm",
"bin",
"rvm-auto-ruby",
),
vscode.Uri.joinPath(
vscode.Uri.file("/"),
"usr",
"local",
"rvm",
"bin",
"rvm-auto-ruby",
),
];

for (const uri of possiblePaths) {
try {
await vscode.workspace.fs.stat(uri);
return uri;
} catch (_error: any) {
// Continue to the next installation path
}
}

throw new Error(
`Cannot find RVM installation directory. Searched in ${possiblePaths.map((uri) => uri.fsPath).join(",")}`,
);
}
}
35 changes: 18 additions & 17 deletions vscode/src/test/suite/ruby/rvm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,28 @@ suite("RVM", () => {
const outputChannel = new WorkspaceChannel("fake", common.LOG_CHANNEL);
const rvm = new Rvm(workspaceFolder, outputChannel);

const activationScript = [
"STDERR.print(",
"{yjit:!!defined?(RubyVM::YJIT),version:RUBY_VERSION,",
"home:Gem.user_dir,default:Gem.default_dir,ruby:RbConfig.ruby}",
".to_json)",
].join("");
const activationScript =
"STDERR.print({ env: ENV.to_h, yjit: !!defined?(RubyVM::YJIT), version: RUBY_VERSION }.to_json)";

const installationPathStub = sinon
.stub(rvm, "findRvmInstallation")
.resolves(
vscode.Uri.joinPath(
vscode.Uri.file(os.homedir()),
".rvm",
"bin",
"rvm-auto-ruby",
),
);

const execStub = sinon.stub(common, "asyncExec").resolves({
stdout: "",
stderr: JSON.stringify({
env: {
ANY: "true",
},
yjit: true,
version: "3.0.0",
home: "/home/user/.rvm/gems/ruby/3.0.0",
default: "/usr/lib/ruby/gems/3.0.0",
ruby: "/home/user/.rvm/rubies/ruby-3.0.0/bin/ruby",
}),
});

Expand All @@ -56,15 +63,9 @@ suite("RVM", () => {

assert.strictEqual(version, "3.0.0");
assert.strictEqual(yjit, true);
assert.strictEqual(env.GEM_HOME, "/home/user/.rvm/gems/ruby/3.0.0");
assert.strictEqual(
env.GEM_PATH,
"/home/user/.rvm/gems/ruby/3.0.0:/usr/lib/ruby/gems/3.0.0",
);
assert.ok(env.PATH!.includes("/home/user/.rvm/gems/ruby/3.0.0/bin"));
assert.ok(env.PATH!.includes("/usr/lib/ruby/gems/3.0.0/bin"));
assert.ok(env.PATH!.includes("/home/user/.rvm/rubies/ruby-3.0.0/bin"));
assert.deepStrictEqual(env.ANY, "true");

execStub.restore();
installationPathStub.restore();
});
});

0 comments on commit 7395355

Please sign in to comment.