Skip to content

Commit 4a6d31a

Browse files
authored
Merge pull request #4109 from knu/detect-mise-via-shell-path
vscode: Detect mise via shell PATH like other version managers
2 parents 5e72408 + 1813e47 commit 4a6d31a

3 files changed

Lines changed: 35 additions & 73 deletions

File tree

vscode/src/ruby.ts

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,6 @@ import { Custom } from "./ruby/custom";
1717
import { Asdf } from "./ruby/asdf";
1818
import { Rv } from "./ruby/rv";
1919

20-
async function detectMise() {
21-
const possiblePaths = [
22-
vscode.Uri.joinPath(vscode.Uri.file(os.homedir()), ".local", "bin", "mise"),
23-
vscode.Uri.joinPath(vscode.Uri.file("/"), "opt", "homebrew", "bin", "mise"),
24-
vscode.Uri.joinPath(vscode.Uri.file("/"), "usr", "bin", "mise"),
25-
];
26-
27-
for (const possiblePath of possiblePaths) {
28-
try {
29-
await vscode.workspace.fs.stat(possiblePath);
30-
return true;
31-
} catch (_error: any) {
32-
// Continue looking
33-
}
34-
}
35-
36-
return false;
37-
}
38-
3920
export enum ManagerIdentifier {
4021
Asdf = "asdf",
4122
Auto = "auto",
@@ -374,6 +355,7 @@ export class Ruby implements RubyInterface {
374355
ManagerIdentifier.Rvm,
375356
ManagerIdentifier.Asdf,
376357
ManagerIdentifier.Rv,
358+
ManagerIdentifier.Mise,
377359
];
378360

379361
for (const tool of managers) {
@@ -385,11 +367,6 @@ export class Ruby implements RubyInterface {
385367
}
386368
}
387369

388-
if (await detectMise()) {
389-
this.versionManager = ManagerIdentifier.Mise;
390-
return;
391-
}
392-
393370
if (os.platform() === "win32") {
394371
this.versionManager = ManagerIdentifier.RubyInstaller;
395372
return;

vscode/src/ruby/mise.ts

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import { VersionManager, ActivationResult, NonReportableError } from "./versionM
99
// Learn more: https://github.com/jdx/mise
1010
export class Mise extends VersionManager {
1111
async activate(): Promise<ActivationResult> {
12-
const miseUri = await this.findMiseUri();
12+
const miseExec = await this.findMise();
1313

1414
// The exec command in Mise is called `x`
15-
const parsedResult = await this.runEnvActivationScript(`${miseUri.fsPath} x -- ruby`);
15+
const parsedResult = await this.runEnvActivationScript(`${miseExec} x -- ruby`);
1616

1717
return {
1818
env: { ...process.env, ...parsedResult.env },
@@ -22,46 +22,37 @@ export class Mise extends VersionManager {
2222
};
2323
}
2424

25-
async findMiseUri(): Promise<vscode.Uri> {
25+
async findMise(): Promise<string> {
2626
const config = vscode.workspace.getConfiguration("rubyLsp");
27-
const misePath = config.get<string | undefined>("rubyVersionManager.miseExecutablePath");
27+
const configuredMisePath = config.get<string | undefined>("rubyVersionManager.miseExecutablePath");
2828

29-
if (misePath) {
30-
const configuredPath = vscode.Uri.file(misePath);
31-
32-
try {
33-
await vscode.workspace.fs.stat(configuredPath);
34-
return configuredPath;
35-
} catch (_error: any) {
36-
throw new NonReportableError(
37-
`Mise executable configured as ${configuredPath.fsPath}, but that file doesn't exist`,
38-
);
39-
}
29+
if (configuredMisePath) {
30+
return this.ensureMiseExistsAt(configuredMisePath);
4031
}
4132

42-
// Possible mise installation paths
33+
// Possible mise installation directories. If none match, fall back to the PATH.
4334
//
4435
// 1. Installation from curl | sh (per mise.jdx.dev Getting Started)
4536
// 2. Homebrew M series
46-
// 3. Installation from `apt install mise`
37+
// 3. Homebrew Intel / Linuxbrew
38+
// 4. Linuxbrew (legacy)
39+
// 5. Installation from `apt install mise`
4740
const possiblePaths = [
48-
vscode.Uri.joinPath(vscode.Uri.file(os.homedir()), ".local", "bin", "mise"),
49-
vscode.Uri.joinPath(vscode.Uri.file("/"), "opt", "homebrew", "bin", "mise"),
50-
vscode.Uri.joinPath(vscode.Uri.file("/"), "usr", "bin", "mise"),
41+
vscode.Uri.joinPath(vscode.Uri.file(os.homedir()), ".local", "bin"),
42+
vscode.Uri.joinPath(vscode.Uri.file("/"), "opt", "homebrew", "bin"),
43+
vscode.Uri.joinPath(vscode.Uri.file("/"), "usr", "local", "bin"),
44+
vscode.Uri.joinPath(vscode.Uri.file("/"), "home", "linuxbrew", ".linuxbrew", "bin"),
45+
vscode.Uri.joinPath(vscode.Uri.file("/"), "usr", "bin"),
5146
];
47+
return this.findExec(possiblePaths, "mise");
48+
}
5249

53-
for (const possiblePath of possiblePaths) {
54-
try {
55-
await vscode.workspace.fs.stat(possiblePath);
56-
return possiblePath;
57-
} catch (_error: any) {
58-
// Continue looking
59-
}
50+
private async ensureMiseExistsAt(path: string): Promise<string> {
51+
try {
52+
await vscode.workspace.fs.stat(vscode.Uri.file(path));
53+
return path;
54+
} catch (_error: any) {
55+
throw new NonReportableError(`The Ruby LSP version manager is configured to be Mise, but ${path} does not exist`);
6056
}
61-
62-
throw new NonReportableError(
63-
`The Ruby LSP version manager is configured to be Mise, but could not find Mise installation. Searched in
64-
${possiblePaths.join(", ")}`,
65-
);
6657
}
6758
}

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

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ suite("Mise", () => {
3535
context.dispose();
3636
});
3737

38-
test("Finds Ruby only binary path is appended to PATH", async () => {
38+
test("Activates with auto-detected mise", async () => {
3939
const workspacePath = process.env.PWD!;
4040
const workspaceFolder = {
4141
uri: vscode.Uri.from({ scheme: "file", path: workspacePath }),
@@ -51,31 +51,25 @@ suite("Mise", () => {
5151
stdout: "",
5252
stderr: `${ACTIVATION_SEPARATOR}${envStub}${ACTIVATION_SEPARATOR}`,
5353
});
54-
const findStub = sandbox
55-
.stub(mise, "findMiseUri")
56-
.resolves(vscode.Uri.joinPath(vscode.Uri.file(os.homedir()), ".local", "bin", "mise"));
54+
55+
// Stub findMise to return the executable name, simulating PATH fallback
56+
sandbox.stub(mise, "findMise" as any).resolves("mise");
5757

5858
const { env, version, yjit } = await mise.activate();
5959

6060
assert.ok(
61-
execStub.calledOnceWithExactly(
62-
`${os.homedir()}/.local/bin/mise x -- ruby -EUTF-8:UTF-8 '${activationPath.fsPath}'`,
63-
{
64-
cwd: workspacePath,
65-
shell: vscode.env.shell,
66-
67-
env: process.env,
68-
encoding: "utf-8",
69-
},
70-
),
61+
execStub.calledOnceWithExactly(`mise x -- ruby -EUTF-8:UTF-8 '${activationPath.fsPath}'`, {
62+
cwd: workspacePath,
63+
shell: vscode.env.shell,
64+
65+
env: process.env,
66+
encoding: "utf-8",
67+
}),
7168
);
7269

7370
assert.strictEqual(version, "3.0.0");
7471
assert.strictEqual(yjit, true);
7572
assert.deepStrictEqual(env.ANY, "true");
76-
77-
execStub.restore();
78-
findStub.restore();
7973
});
8074

8175
test("Allows configuring where Mise is installed", async () => {

0 commit comments

Comments
 (0)