mirror of
https://github.com/morluto/rea.git
synced 2026-11-08 15:56:35 +00:00
`rea doctor`, documented as strictly read-only, ran `brew --prefix --cask hopper-disassembler` when Hopper was not in a standard location. Current Homebrew rejects that option combination, but any brew command naming a cask first fetches the cask API, so each doctor run wrote about 600 files (36 MB) into the user's Homebrew cache. Ask brew only for its Caskroom, which brew answers without loading the cask API, and read the application directory Homebrew recorded in the Hopper cask's install receipt. Fixes #1165 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
109 lines
3.5 KiB
TypeScript
109 lines
3.5 KiB
TypeScript
import { mkdir, writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
|
|
import { expect, it } from "vitest";
|
|
|
|
import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js";
|
|
import { systemDoctorHost } from "./Doctor.js";
|
|
|
|
it("threads the selected host and environment into system diagnostics", async () => {
|
|
const environment = {
|
|
HOME: "/selected/home",
|
|
HOPPER_LAUNCHER_PATH: "/selected/bin/hopper",
|
|
PATH: "/selected/bin",
|
|
};
|
|
const calls: Array<{
|
|
command: string;
|
|
arguments: readonly string[];
|
|
environment: NodeJS.ProcessEnv | undefined;
|
|
}> = [];
|
|
const host = systemDoctorHost({
|
|
platform: "linux",
|
|
architecture: "x64",
|
|
environment,
|
|
execFileOutput: async (command, arguments_, options) => {
|
|
calls.push({ command, arguments: arguments_, environment: options?.env });
|
|
if (command === "sw_vers") return { stdout: "15.0\n", stderr: "" };
|
|
if (command === "ldd") return { stdout: "linux-vdso.so.1", stderr: "" };
|
|
return { stdout: "/selected/bin/rea\n", stderr: "" };
|
|
},
|
|
});
|
|
|
|
expect(host.homeDirectory).toBe("/selected/home");
|
|
expect(host.platform).toBe("linux");
|
|
expect(host.architecture).toBe("x64");
|
|
await host.installationPaths?.();
|
|
await host.macosVersion();
|
|
await host.executable(process.execPath);
|
|
|
|
expect(calls.map(({ command }) => command)).toEqual([
|
|
"which",
|
|
"sw_vers",
|
|
"ldd",
|
|
]);
|
|
expect(
|
|
calls.every(({ environment: observed }) => observed === environment),
|
|
).toBe(true);
|
|
});
|
|
|
|
it.each([
|
|
[{ default: { appdir: "/Applications" } }, "/Applications"],
|
|
[
|
|
{
|
|
default: { appdir: "/Applications" },
|
|
env: { appdir: "/Env Apps" },
|
|
explicit: { appdir: "~/Tools" },
|
|
},
|
|
"HOME/Tools",
|
|
],
|
|
[
|
|
{ default: { appdir: "/Applications" }, env: { appdir: "/Env Apps" } },
|
|
"/Env Apps",
|
|
],
|
|
])(
|
|
"locates the Hopper cask from its Caskroom receipt without a cask command (%j)",
|
|
async (config, expectedAppdir) => {
|
|
const root = await createTestTempDirectory("rea-doctor-caskroom-");
|
|
const caskroom = join(root, "Caskroom");
|
|
const metadata = join(caskroom, "hopper-disassembler", ".metadata");
|
|
await mkdir(metadata, { recursive: true });
|
|
await writeFile(join(metadata, "config.json"), JSON.stringify(config));
|
|
const calls: (readonly string[])[] = [];
|
|
const host = systemDoctorHost({
|
|
platform: "darwin",
|
|
environment: { HOME: join(root, "home") },
|
|
execFileOutput: async (_command, arguments_) => {
|
|
calls.push(arguments_);
|
|
return { stdout: `${caskroom}\n`, stderr: "" };
|
|
},
|
|
});
|
|
|
|
expect(await host.brewHopperPath()).toBe(
|
|
join(
|
|
expectedAppdir.replace("HOME", join(root, "home")),
|
|
"Hopper Disassembler.app/Contents/MacOS/hopper",
|
|
),
|
|
);
|
|
// A cask argument makes Homebrew fetch and cache its API data.
|
|
expect(calls).toEqual([["--caskroom"]]);
|
|
},
|
|
);
|
|
|
|
it("reports no Homebrew Hopper when the cask has no receipt", async () => {
|
|
const caskroom = await createTestTempDirectory("rea-doctor-caskroom-");
|
|
const calls: (readonly string[])[] = [];
|
|
const host = systemDoctorHost({
|
|
platform: "darwin",
|
|
environment: { HOME: caskroom },
|
|
execFileOutput: async (_command, arguments_) => {
|
|
calls.push(arguments_);
|
|
return { stdout: `${caskroom}\n`, stderr: "" };
|
|
},
|
|
});
|
|
|
|
expect(await host.brewHopperPath()).toBeUndefined();
|
|
expect(
|
|
calls.every((arguments_) => arguments_.join(" ") === "--caskroom"),
|
|
).toBe(true);
|
|
});
|