(options: CleanupOptions)
| 295 | * (never throw — this is fire-and-forget background work). |
| 296 | */ |
| 297 | export function cleanupStaleNativeCache(options: CleanupOptions): CleanupResult { |
| 298 | const { cacheBase, version, target, currentRoot } = options; |
| 299 | const targetDir = join(cacheBase, 'native', version, target); |
| 300 | const result: CleanupResult = { kept: [], removed: [], errors: [] }; |
| 301 | |
| 302 | let entries: string[]; |
| 303 | try { |
| 304 | entries = readdirSync(targetDir); |
| 305 | } catch { |
| 306 | return result; |
| 307 | } |
| 308 | |
| 309 | const siblings: Array<{ path: string; mtimeMs: number }> = []; |
| 310 | for (const name of entries) { |
| 311 | const path = join(targetDir, name); |
| 312 | try { |
| 313 | const st = statSync(path); |
| 314 | if (!st.isDirectory()) continue; |
| 315 | siblings.push({ path, mtimeMs: st.mtimeMs }); |
| 316 | } catch (error) { |
| 317 | (result.errors as Array<{ path: string; error: unknown }>).push({ path, error }); |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | if (siblings.length === 0) return result; |
| 322 | |
| 323 | // sort newest first |
| 324 | siblings.sort((a, b) => b.mtimeMs - a.mtimeMs); |
| 325 | // Defensive: keep the most recently modified sibling that is not currentRoot |
| 326 | // so a previously-written cache survives in case currentRoot calc changed. |
| 327 | const mostRecentOther = siblings.find((entry) => entry.path !== currentRoot)?.path; |
| 328 | const keepSet = new Set<string>( |
| 329 | mostRecentOther === undefined ? [currentRoot] : [currentRoot, mostRecentOther], |
| 330 | ); |
| 331 | |
| 332 | for (const { path } of siblings) { |
| 333 | if (keepSet.has(path)) { |
| 334 | result.kept.push(path); |
| 335 | continue; |
| 336 | } |
| 337 | try { |
| 338 | rmSync(path, { recursive: true, force: true }); |
| 339 | result.removed.push(path); |
| 340 | } catch (error) { |
| 341 | (result.errors as Array<{ path: string; error: unknown }>).push({ path, error }); |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | return result; |
| 346 | } |
| 347 | |
| 348 | /** |
| 349 | * Convenience: discover currentRoot from embedded manifest + run cleanup. |
no test coverage detected