import { promises as fs } from "node:fs"; import * as os from "node:os"; import * as path from "node:path"; import type { ScopedInstruction } from "./instructions.ts"; import type { PullRequestSnapshot } from "./types.ts"; export interface SnapshotFiles { directory: string; manifestPath: string; dispose(): Promise; } export async function writeSnapshot( snapshot: PullRequestSnapshot, instructions: ScopedInstruction[], ): Promise { const directory = await fs.mkdtemp(path.join(os.tmpdir(), "pi-code-review-")); await fs.chmod(directory, 0o700); const metadataPath = path.join(directory, "pull-request.json"); const diffPath = path.join(directory, "changes.diff"); const instructionsPath = path.join(directory, "instructions.json"); const manifestPath = path.join(directory, "manifest.json"); const writePrivate = async (filePath: string, content: string) => { await fs.writeFile(filePath, content, { encoding: "utf8", mode: 0o600 }); }; await writePrivate( metadataPath, JSON.stringify({ ...snapshot, diff: undefined }, null, 2), ); await writePrivate(diffPath, snapshot.diff); await writePrivate(instructionsPath, JSON.stringify(instructions, null, 2)); await writePrivate( manifestPath, JSON.stringify( { metadata: metadataPath, diff: diffPath, instructions: instructionsPath, changedFiles: snapshot.files.map((file) => file.path), }, null, 2, ), ); let disposed = false; return { directory, manifestPath, async dispose() { if (disposed) return; disposed = true; await fs.rm(directory, { recursive: true, force: true }); }, }; }