/** * Temporary copies: where they go, and when they are removed. * * Both the remote editor and the drag-out keep local copies of remote files. * Until now they were only removed when the SFTP panel was destroyed, so * anything left by a crash, a `taskkill` or a plain window close stayed on disk * for good. * * Two mechanisms, deliberately unequal: * * - **On startup**, anything older than this process is deleted. This is the * one that matters: it is the only one that catches a run which ended * without executing a single line of our code. * - **On `beforeunload`**, this window's own directory goes. Not on * `windowCloseRequest$`, which fires *before* the close is confirmed — a * cancelled close would have deleted the copy of a file still open in the * user's editor. * * Per-window directories keep one window's copies apart from another's, and the * purge decides what to delete by asking whether the process that owns a * directory is **still running** — its pid is right there in the name. * * That question replaced a boot-time cutoff, which was wrong as soon as a second * window existed: `process.uptime()` is the age of the *current renderer*, not * of the application, so a window opened at 10:30 treated the 10:00 window's * directory as predating "boot" and deleted it — including a file being edited * right then, after which the watcher had nothing left to send and every save * went silently nowhere. * * A pid can be recycled by an unrelated process, which would make us keep a * directory one run too long. That is the harmless side of the trade: this * class exists to avoid leaving copies behind, never to risk deleting one that * is in use. */ export declare class SidebarPlusTempFilesService { private sessionDir; private counter; constructor(); /** A fresh, empty directory for one file. */ makeDir(kind: 'drag' | 'edit'): Promise; /** Drops a directory handed out by `makeDir()`; missing is not an error. */ remove(dir: string): Promise; /** * Removes what runs that are over left behind. * * A directory is fair game only when the process named in it is gone. Our * own is skipped explicitly rather than relying on it looking alive: it is * the one case where being wrong would delete the copies of the window * doing the deleting. */ private purgeStale; /** * Whether a pid still belongs to a running process. * * Signal 0 performs the permission and existence checks without delivering * anything. `EPERM` means the process is there but out of reach — alive for * our purposes, and the answer that errs towards keeping a directory. */ private static isProcessAlive; /** * Synchronous on purpose: `beforeunload` does not wait for a promise, so an * async removal would simply not happen. A copy still held open by an * external editor raises EBUSY on Windows — ignored, the startup purge will * get it next time. */ private purgeSession; }