| 120 | |
| 121 | /** Effectful scoped tmpdir. Cleaned up when the scope closes. Make sure these stay in sync */ |
| 122 | export function tmpdirScoped<E = never, R = never>(options?: { |
| 123 | git?: boolean |
| 124 | config?: Partial<ConfigV1.Info> | (() => Partial<ConfigV1.Info>) |
| 125 | init?: (directory: string) => Effect.Effect<void, E, R> |
| 126 | }) { |
| 127 | return Effect.gen(function* () { |
| 128 | const spawner = yield* ChildProcessSpawner.ChildProcessSpawner |
| 129 | const dirpath = sanitizePath(path.join(os.tmpdir(), "opencode-test-" + Math.random().toString(36).slice(2))) |
| 130 | yield* Effect.promise(() => fs.mkdir(dirpath, { recursive: true })) |
| 131 | const dir = sanitizePath(yield* Effect.promise(() => fs.realpath(dirpath))) |
| 132 | |
| 133 | yield* Effect.addFinalizer(() => |
| 134 | Effect.promise(async () => { |
| 135 | if (options?.git) await stop(dir).catch(() => undefined) |
| 136 | await clean(dir).catch(() => undefined) |
| 137 | }), |
| 138 | ) |
| 139 | |
| 140 | const git = (...args: string[]) => |
| 141 | spawner.spawn(ChildProcess.make("git", args, { cwd: dir })).pipe(Effect.flatMap((handle) => handle.exitCode)) |
| 142 | |
| 143 | if (options?.git) { |
| 144 | yield* git("init") |
| 145 | yield* git("config", "core.fsmonitor", "false") |
| 146 | yield* git("config", "commit.gpgsign", "false") |
| 147 | yield* git("config", "user.email", "test@opencode.test") |
| 148 | yield* git("config", "user.name", "Test") |
| 149 | yield* git("commit", "--allow-empty", "-m", `root commit ${dir}`) |
| 150 | } |
| 151 | |
| 152 | if (options?.config) { |
| 153 | const resolved = typeof options.config === "function" ? options.config() : options.config |
| 154 | yield* Effect.promise(() => |
| 155 | fs.writeFile( |
| 156 | path.join(dir, "opencode.json"), |
| 157 | JSON.stringify({ $schema: "https://opencode.ai/config.json", ...resolved }), |
| 158 | ), |
| 159 | ) |
| 160 | } |
| 161 | |
| 162 | if (options?.init) yield* options.init(dir) |
| 163 | |
| 164 | return dir |
| 165 | }) |
| 166 | } |
| 167 | |
| 168 | export const provideInstance = |
| 169 | (directory: string) => |