cleanCandidates
uses node:path
Take away what verifies built and left behind in dist: each branch's candidate (dist/candidates/branches and it was built in
the last maxAge (a day: a failed one is kept a while, to run its tcm again); and dist/candidate, where every
verify built before each had its own, unless a verify of that kind holds dist/verify.lock. Says what it took.
import { candidateDir, lockHeld } from "#codebase/tcmts/dev"; import fs from "node:fs"; import path from "node:path"; export function cleanCandidates(dist: string, branches: string[], maxAge = 86_400_000): string[] { const removed: string[] = []; const live = new Set(branches.map((b) => path.basename(candidateDir(dist, b)))); const under = path.join(dist, "candidates"); for (const name of fs.existsSync(under) ? fs.readdirSync(under) : []) { const dir = path.join(under, name); if (lockHeld(path.join(dir, "verify.lock"))) continue; let age = Infinity; try { age = Date.now() - fs.statSync(dir).mtimeMs; } catch {} if (live.has(name) && age < maxAge) continue; fs.rmSync(dir, { recursive: true, force: true }); removed.push(path.relative(dist, dir)); } const old = path.join(dist, "candidate"); if (fs.existsSync(old) && !lockHeld(path.join(dist, "verify.lock"))) { fs.rmSync(old, { recursive: true, force: true }); removed.push("candidate"); } return removed; }