| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- import { $ } from "bun"
- import * as fs from "fs/promises"
- import os from "os"
- import path from "path"
- import type { Config } from "../../src/config/config"
- // Strip null bytes from paths (defensive fix for CI environment issues)
- function sanitizePath(p: string): string {
- return p.replace(/\0/g, "")
- }
- function exists(dir: string) {
- return fs
- .stat(dir)
- .then(() => true)
- .catch(() => false)
- }
- function clean(dir: string) {
- return fs.rm(dir, {
- recursive: true,
- force: true,
- maxRetries: 5,
- retryDelay: 100,
- })
- }
- async function stop(dir: string) {
- if (!(await exists(dir))) return
- await $`git fsmonitor--daemon stop`.cwd(dir).quiet().nothrow()
- }
- type TmpDirOptions<T> = {
- git?: boolean
- config?: Partial<Config.Info>
- init?: (dir: string) => Promise<T>
- dispose?: (dir: string) => Promise<T>
- }
- export async function tmpdir<T>(options?: TmpDirOptions<T>) {
- const dirpath = sanitizePath(path.join(os.tmpdir(), "opencode-test-" + Math.random().toString(36).slice(2)))
- await fs.mkdir(dirpath, { recursive: true })
- if (options?.git) {
- await $`git init`.cwd(dirpath).quiet()
- await $`git config core.fsmonitor false`.cwd(dirpath).quiet()
- await $`git commit --allow-empty -m "root commit ${dirpath}"`.cwd(dirpath).quiet()
- }
- if (options?.config) {
- await Bun.write(
- path.join(dirpath, "opencode.json"),
- JSON.stringify({
- $schema: "https://opencode.ai/config.json",
- ...options.config,
- }),
- )
- }
- const realpath = sanitizePath(await fs.realpath(dirpath))
- const extra = await options?.init?.(realpath)
- const result = {
- [Symbol.asyncDispose]: async () => {
- try {
- await options?.dispose?.(realpath)
- } finally {
- if (options?.git) await stop(realpath).catch(() => undefined)
- await clean(realpath).catch(() => undefined)
- }
- },
- path: realpath,
- extra: extra as T,
- }
- return result
- }
|