| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- import { describe, expect, test } from "bun:test"
- import fs from "fs/promises"
- import path from "path"
- import { which } from "../../src/util/which"
- import { tmpdir } from "../fixture/fixture"
- async function cmd(dir: string, name: string, exec = true) {
- const ext = process.platform === "win32" ? ".cmd" : ""
- const file = path.join(dir, name + ext)
- const body = process.platform === "win32" ? "@echo off\r\n" : "#!/bin/sh\n"
- await fs.writeFile(file, body)
- if (process.platform !== "win32") {
- await fs.chmod(file, exec ? 0o755 : 0o644)
- }
- return file
- }
- function env(PATH: string): NodeJS.ProcessEnv {
- return {
- PATH,
- PATHEXT: process.env["PATHEXT"],
- }
- }
- function envPath(Path: string): NodeJS.ProcessEnv {
- return {
- Path,
- PathExt: process.env["PathExt"] ?? process.env["PATHEXT"],
- }
- }
- function same(a: string | null, b: string) {
- if (process.platform === "win32") {
- expect(a?.toLowerCase()).toBe(b.toLowerCase())
- return
- }
- expect(a).toBe(b)
- }
- describe("util.which", () => {
- test("returns null when command is missing", () => {
- expect(which("opencode-missing-command-for-test")).toBeNull()
- })
- test("finds a command from PATH override", async () => {
- await using tmp = await tmpdir()
- const bin = path.join(tmp.path, "bin")
- await fs.mkdir(bin)
- const file = await cmd(bin, "tool")
- same(which("tool", env(bin)), file)
- })
- test("uses first PATH match", async () => {
- await using tmp = await tmpdir()
- const a = path.join(tmp.path, "a")
- const b = path.join(tmp.path, "b")
- await fs.mkdir(a)
- await fs.mkdir(b)
- const first = await cmd(a, "dupe")
- await cmd(b, "dupe")
- same(which("dupe", env([a, b].join(path.delimiter))), first)
- })
- test("returns null for non-executable file on unix", async () => {
- if (process.platform === "win32") return
- await using tmp = await tmpdir()
- const bin = path.join(tmp.path, "bin")
- await fs.mkdir(bin)
- await cmd(bin, "noexec", false)
- expect(which("noexec", env(bin))).toBeNull()
- })
- test("uses PATHEXT on windows", async () => {
- if (process.platform !== "win32") return
- await using tmp = await tmpdir()
- const bin = path.join(tmp.path, "bin")
- await fs.mkdir(bin)
- const file = path.join(bin, "pathext.CMD")
- await fs.writeFile(file, "@echo off\r\n")
- expect(which("pathext", { PATH: bin, PATHEXT: ".CMD" })).toBe(file)
- })
- test("uses Windows Path casing fallback", async () => {
- if (process.platform !== "win32") return
- await using tmp = await tmpdir()
- const bin = path.join(tmp.path, "bin")
- await fs.mkdir(bin)
- const file = await cmd(bin, "mixed")
- same(which("mixed", envPath(bin)), file)
- })
- })
|