diff --git a/dist/index.js b/dist/index.js index bb5ba60..869accc 100644 --- a/dist/index.js +++ b/dist/index.js @@ -562,21 +562,16 @@ function parseStackYaml(contents) { exports.parseStackYaml = parseStackYaml; async function getStackDirectories(stackYaml, stack, workingDirectory) { const cwd = workingDirectory ?? process.cwd(); - const stackRoot = (await stack.read(["path", "--stack-root"])).trim(); - const stackPrograms = stackYaml["local-programs-path"] ?? defaultLocalProgramsPath(stackRoot); + const output = await stack.read(["path", "--stack-root", "--programs"]); + const stackPath = yaml.load(output); const stackWorks = packagesStackWorks(stackYaml, cwd); - return { stackRoot, stackPrograms, stackWorks }; + return { + stackRoot: stackPath["stack-root"], + stackPrograms: stackPath.programs, + stackWorks, + }; } exports.getStackDirectories = getStackDirectories; -function defaultLocalProgramsPath(stackRoot) { - if (process.platform === "win32") { - const localAppData = process.env.LOCALAPPDATA; - if (localAppData) { - return (0, path_1.join)(localAppData, "Programs", "stack"); - } - } - return (0, path_1.join)(stackRoot, "programs"); -} function packagesStackWorks(stackYaml, cwd) { const packageStackWorks = (stackYaml.packages ?? []) .filter((p) => p !== ".") diff --git a/src/stack-yaml.test.ts b/src/stack-yaml.test.ts index b9c9f00..56779c6 100644 --- a/src/stack-yaml.test.ts +++ b/src/stack-yaml.test.ts @@ -1,24 +1,30 @@ import { parseStackYaml, getStackDirectories } from "./stack-yaml"; import { StackCLI } from "./stack-cli"; -function mockStackCLI(stackRoot: string = "/home/me/.stack"): StackCLI { +const testStackRoot = "/home/me/.stack"; +const testPrograms = `${testStackRoot}/programs/x86_64-linux`; +const testStackPathYaml = ` +stack-root: ${testStackRoot} +programs: ${testPrograms} +`; + +function mockStackCLI(): StackCLI { const stack = new StackCLI([]); jest .spyOn(stack, "read") .mockImplementation((args: string[]): Promise => { - if (args[0] !== "path") { - throw new Error("StackCLI.read() is only mocked for path"); + // Stringify to avoid array-comparison pitfalls + const expected = ["path", "--stack-root", "--programs"].toString(); + const given = args.toString(); + + if (given !== expected) { + throw new Error( + `StackCLI.read() is only mocked for ${expected}, saw ${given}`, + ); } - switch (args[1]) { - case "--stack-root": - return Promise.resolve(stackRoot); - default: - throw new Error( - "StackCLI.read(path) is only mocked for --stack-root", - ); - } + return Promise.resolve(testStackPathYaml); }); return stack; @@ -27,12 +33,12 @@ function mockStackCLI(stackRoot: string = "/home/me/.stack"): StackCLI { describe("getStackDirectories", () => { test("stackRoot, stackPrograms", async () => { const stackYaml = parseStackYaml("resolver: lts-22\n"); - const stack = mockStackCLI("/home/me/.stack"); + const stack = mockStackCLI(); const stackDirectories = await getStackDirectories(stackYaml, stack, ""); - expect(stackDirectories.stackRoot).toEqual("/home/me/.stack"); - expect(stackDirectories.stackPrograms).toEqual("/home/me/.stack/programs"); + expect(stackDirectories.stackRoot).toEqual(testStackRoot); + expect(stackDirectories.stackPrograms).toEqual(testPrograms); }); describe("stackWorks", () => { diff --git a/src/stack-yaml.ts b/src/stack-yaml.ts index 9866014..708c68c 100644 --- a/src/stack-yaml.ts +++ b/src/stack-yaml.ts @@ -25,6 +25,12 @@ export type StackDirectories = { stackWorks: string[]; }; +// Internal type for parsing Yaml output from `stack path` +type StackPath = { + "stack-root": string; + programs: string; +}; + export async function getStackDirectories( stackYaml: StackYaml, stack: StackCLI, @@ -32,32 +38,18 @@ export async function getStackDirectories( ): Promise { const cwd = workingDirectory ?? process.cwd(); - // Only use --stack-root, which (as of stack v2.15) won't load the environment - // and install GHC, etc. It's the only option currently safe to make use of - // outside of caching. - const stackRoot = (await stack.read(["path", "--stack-root"])).trim(); - - // Avoid `stack path --programs` until - // https://github.com/commercialhaskell/stack/issues/6484 is fixed. - const stackPrograms = - stackYaml["local-programs-path"] ?? defaultLocalProgramsPath(stackRoot); - + // Only use --stack-root and --programs, which (as of stack v2.15.3) won't + // load the environment and install GHC, etc. These are the only options + // currently safe to make use of outside of caching. + const output = await stack.read(["path", "--stack-root", "--programs"]); + const stackPath = yaml.load(output) as StackPath; const stackWorks = packagesStackWorks(stackYaml, cwd); - return { stackRoot, stackPrograms, stackWorks }; -} - -// https://docs.haskellstack.org/en/stable/yaml_configuration/#local-programs-path -function defaultLocalProgramsPath(stackRoot: string): string { - if (process.platform === "win32") { - const localAppData = process.env.LOCALAPPDATA; - - if (localAppData) { - return pathJoin(localAppData, "Programs", "stack"); - } - } - - return pathJoin(stackRoot, "programs"); + return { + stackRoot: stackPath["stack-root"], + stackPrograms: stackPath.programs, + stackWorks, + }; } function packagesStackWorks(stackYaml: StackYaml, cwd: string): string[] {