Skip to content

Commit 3bc4ae0

Browse files
committed
Refactor binary path detection with new shell utility function
1 parent 32c5c86 commit 3bc4ae0

File tree

5 files changed

+49
-34
lines changed

5 files changed

+49
-34
lines changed

src/toolchain/swiftly.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import * as vscode from "vscode";
2020
import { Version } from "../utilities/version";
2121
import { z } from "zod/v4/mini";
2222
import { SwiftLogger } from "../logging/SwiftLogger";
23+
import { findBinaryPath } from "../utilities/shell";
2324

2425
const ListResult = z.object({
2526
toolchains: z.array(
@@ -241,8 +242,8 @@ export class Swiftly {
241242
return false;
242243
}
243244
try {
244-
const { stdout } = await execFile("which", ["swiftly"]);
245-
return stdout.trim().length > 0;
245+
await findBinaryPath("swiftly");
246+
return true;
246247
} catch (error) {
247248
return false;
248249
}

src/toolchain/toolchain.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { Sanitizer } from "./Sanitizer";
2626
import { lineBreakRegex } from "../utilities/tasks";
2727
import { Swiftly } from "./swiftly";
2828
import { SwiftLogger } from "../logging/SwiftLogger";
29+
import { findBinaryPath } from "../utilities/shell";
2930
/**
3031
* Contents of **Info.plist** on Windows.
3132
*/
@@ -550,18 +551,7 @@ export class SwiftToolchain {
550551
// use `type swift` to find `swift`. Run inside /bin/sh to ensure
551552
// we get consistent output as different shells output a different
552553
// format. Tried running with `-p` but that is not available in /bin/sh
553-
const { stdout, stderr } = await execFile("/bin/sh", [
554-
"-c",
555-
"LC_MESSAGES=C type swift",
556-
]);
557-
const swiftMatch = /^swift is (.*)$/.exec(stdout.trimEnd());
558-
if (swiftMatch) {
559-
swift = swiftMatch[1];
560-
} else {
561-
throw Error(
562-
`/bin/sh -c LC_MESSAGES=C type swift: stdout: ${stdout}, stderr: ${stderr}`
563-
);
564-
}
554+
swift = await findBinaryPath("swift");
565555
break;
566556
}
567557
}

src/utilities/shell.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { execFile } from "./utilities";
2+
3+
export async function findBinaryPath(binaryName: string): Promise<string> {
4+
const { stdout, stderr } = await execFile("/bin/sh", [
5+
"-c",
6+
`LC_MESSAGES=C type ${binaryName}`,
7+
]);
8+
const binaryNameMatch = new RegExp(`^${binaryName} is (.*)$`).exec(stdout.trimEnd());
9+
if (binaryNameMatch) {
10+
return binaryNameMatch[1];
11+
} else {
12+
throw Error(
13+
`/bin/sh -c LC_MESSAGES=C type ${binaryName}: stdout: ${stdout}, stderr: ${stderr}`
14+
);
15+
}
16+
}

test/unit-tests/toolchain/swiftly.test.ts

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
import { expect } from "chai";
1616
import { Swiftly } from "../../../src/toolchain/swiftly";
1717
import * as utilities from "../../../src/utilities/utilities";
18+
import * as shell from "../../../src/utilities/shell";
1819
import { mockGlobalModule, mockGlobalValue } from "../../MockUtils";
1920

2021
suite("Swiftly Unit Tests", () => {
2122
const mockUtilities = mockGlobalModule(utilities);
23+
const mockShell = mockGlobalModule(shell);
2224
const mockedPlatform = mockGlobalValue(process, "platform");
2325

2426
setup(() => {
@@ -105,36 +107,21 @@ suite("Swiftly Unit Tests", () => {
105107

106108
suite("isInstalled", () => {
107109
test("should return true when swiftly is found", async () => {
108-
mockUtilities.execFile.withArgs("which", ["swiftly"]).resolves({
109-
stdout: "/usr/local/bin/swiftly\n",
110-
stderr: "",
111-
});
110+
mockShell.findBinaryPath.withArgs("swiftly").resolves("/usr/local/bin/swiftly");
112111

113112
const result = await Swiftly.isInstalled();
114113

115114
expect(result).to.be.true;
116-
expect(mockUtilities.execFile).to.have.been.calledWith("which", ["swiftly"]);
115+
expect(mockShell.findBinaryPath).to.have.been.calledWith("swiftly");
117116
});
118117

119118
test("should return false when swiftly is not found", async () => {
120-
mockUtilities.execFile.withArgs("which", ["swiftly"]).rejects(new Error("not found"));
121-
122-
const result = await Swiftly.isInstalled();
123-
124-
expect(result).to.be.false;
125-
expect(mockUtilities.execFile).to.have.been.calledWith("which", ["swiftly"]);
126-
});
127-
128-
test("should return false when which returns empty output", async () => {
129-
mockUtilities.execFile.withArgs("which", ["swiftly"]).resolves({
130-
stdout: "",
131-
stderr: "",
132-
});
119+
mockShell.findBinaryPath.withArgs("swiftly").rejects(new Error("not found"));
133120

134121
const result = await Swiftly.isInstalled();
135122

136123
expect(result).to.be.false;
137-
expect(mockUtilities.execFile).to.have.been.calledWith("which", ["swiftly"]);
124+
expect(mockShell.findBinaryPath).to.have.been.calledWith("swiftly");
138125
});
139126

140127
test("should return false when platform is not supported", async () => {
@@ -143,7 +130,7 @@ suite("Swiftly Unit Tests", () => {
143130
const result = await Swiftly.isInstalled();
144131

145132
expect(result).to.be.false;
146-
expect(mockUtilities.execFile).not.to.have.been.called;
133+
expect(mockShell.findBinaryPath).not.to.have.been.called;
147134
});
148135
});
149136
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { expect } from "chai";
2+
import { findBinaryPath } from "../../../src/utilities/shell";
3+
4+
suite("Shell Unit Test Suite", () => {
5+
suite("findBinaryPath", () => {
6+
test("returns the path to a binary in the PATH", async () => {
7+
const binaryPath = await findBinaryPath("node");
8+
expect(binaryPath).to.be.a("string");
9+
expect(binaryPath).to.include("node");
10+
});
11+
12+
test("throws for a non-existent binary", async () => {
13+
try {
14+
await findBinaryPath("nonexistentbinary");
15+
expect.fail("Expected an error to be thrown for a non-existent binary");
16+
} catch (error) {
17+
expect(error).to.be.an("error");
18+
}
19+
});
20+
});
21+
});

0 commit comments

Comments
 (0)