From 270fb56f2b0b833f7224ee38693f2b0ac0be36a8 Mon Sep 17 00:00:00 2001 From: Vinicius Stock Date: Thu, 11 Apr 2024 09:41:56 -0400 Subject: [PATCH] Allow configuring Mise executable path --- vscode/package.json | 4 ++ vscode/src/ruby/mise.ts | 17 +++++--- vscode/src/test/suite/ruby/mise.test.ts | 56 +++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/vscode/package.json b/vscode/package.json index 94cf7e3ca..4a91358b1 100644 --- a/vscode/package.json +++ b/vscode/package.json @@ -249,6 +249,10 @@ "custom" ], "default": "auto" + }, + "miseExecutablePath": { + "description": "The path to the Mise executable, if not installed in ~/.local/bin/mise", + "type": "string" } }, "default": { diff --git a/vscode/src/ruby/mise.ts b/vscode/src/ruby/mise.ts index 8ce56e8a3..9059098d6 100644 --- a/vscode/src/ruby/mise.ts +++ b/vscode/src/ruby/mise.ts @@ -34,15 +34,22 @@ export class Mise extends VersionManager { } async findMiseUri(): Promise { - const miseUri = vscode.Uri.joinPath( - vscode.Uri.file(os.homedir()), - ".local", - "bin", - "mise", + const config = vscode.workspace.getConfiguration("rubyLsp"); + const misePath = config.get( + "rubyVersionManager.miseExecutablePath", ); + const miseUri = misePath + ? vscode.Uri.file(misePath) + : vscode.Uri.joinPath( + vscode.Uri.file(os.homedir()), + ".local", + "bin", + "mise", + ); try { await vscode.workspace.fs.stat(miseUri); + return miseUri; } catch (error: any) { // Couldn't find it } diff --git a/vscode/src/test/suite/ruby/mise.test.ts b/vscode/src/test/suite/ruby/mise.test.ts index 7f04ebd55..0283c0f8a 100644 --- a/vscode/src/test/suite/ruby/mise.test.ts +++ b/vscode/src/test/suite/ruby/mise.test.ts @@ -1,6 +1,7 @@ import assert from "assert"; import path from "path"; import os from "os"; +import fs from "fs"; import * as vscode from "vscode"; import sinon from "sinon"; @@ -65,4 +66,59 @@ suite("Mise", () => { execStub.restore(); findStub.restore(); }); + + test("Allows configuring where Mise is installed", async () => { + const workspacePath = fs.mkdtempSync( + path.join(os.tmpdir(), "ruby-lsp-test-"), + ); + const workspaceFolder = { + uri: vscode.Uri.from({ scheme: "file", path: workspacePath }), + name: path.basename(workspacePath), + index: 0, + }; + const outputChannel = new WorkspaceChannel("fake", common.LOG_CHANNEL); + const mise = new Mise(workspaceFolder, outputChannel); + + const activationScript = + "STDERR.print({ env: ENV.to_h, yjit: !!defined?(RubyVM::YJIT), version: RUBY_VERSION }.to_json)"; + + const execStub = sinon.stub(common, "asyncExec").resolves({ + stdout: "", + stderr: JSON.stringify({ + env: { ANY: "true" }, + yjit: true, + version: "3.0.0", + }), + }); + const misePath = path.join(workspacePath, "mise"); + fs.writeFileSync(misePath, "fakeMiseBinary"); + + const configStub = sinon + .stub(vscode.workspace, "getConfiguration") + .returns({ + get: (name: string) => { + if (name === "rubyVersionManager.miseExecutablePath") { + return misePath; + } + return ""; + }, + } as any); + + const { env, version, yjit } = await mise.activate(); + + assert.ok( + execStub.calledOnceWithExactly( + `${misePath} x -- ruby -W0 -rjson -e '${activationScript}'`, + { cwd: workspacePath }, + ), + ); + + assert.strictEqual(version, "3.0.0"); + assert.strictEqual(yjit, true); + assert.deepStrictEqual(env.ANY, "true"); + + execStub.restore(); + configStub.restore(); + fs.rmSync(workspacePath, { recursive: true, force: true }); + }); });