import type { Stats } from 'node:fs'; import type { LinkManifest } from './fan-out.manifest.js'; /** What a leftover scan found, and whether it could look at all. */ export interface LeftoverScan { /** Hidden folders beside the destination that an interrupted operation left. */ folders: string[]; /** * Set when the parent folder could not be listed. Round 24 (cross-model * review): returning an empty list then reports "could not look" as "nothing * is there", and the accepted residual's promise is that a displaced entry * gets reported. */ unreadable?: string; } export declare const BACKUP_TAG = ".skillsmith-backup-"; export declare const STAGING_TAG = ".skillsmith-staging-"; export declare function escapeRegExp(s: string): string; /** Hidden sibling name prefix for `dest`, e.g. `.foo.skillsmith-backup-`. */ export declare function siblingPrefix(dest: string, tag: string): string; /** Exact match for a `mkdtemp` folder made from `siblingPrefix(dest, tag)` (6-char suffix). */ export declare function siblingPattern(dest: string, tag: string): RegExp; export declare function lstatOrNull(p: string): Promise; /** Whether the link manifest records `dest` as a copy Skillsmith made. */ export declare function isRecordedCopy(dest: string, manifest: LinkManifest): boolean; /** * Housekeeping under the destination lock, before any write: * - remove an empty backup folder (a crash before anything was moved in); * - restore a backup stranded by a crash between the rename-aside and the * swap: the destination is missing, this is the only backup whose * `original` is a real directory, and the manifest still records the * destination as a copy. Backups are only ever made of recorded copies, * so an unrecorded one has been uninstalled since, and restoring it would * bring back a stale, untracked copy. With two or more, nothing says which * is newest (a name can sort anywhere), so none is restored (round 9). * * Any other backup is left in place for `listLeftoverBackups` to report, and * so is a staging folder left by a crashed write: round 14 (cross-model * review) stopped deleting those here, since neither a folder's name nor its * contents proves who owns it now. Returns the backup folders restored from. */ export declare function recoverDestination(dest: string, manifest: LinkManifest): Promise<{ restored: string[]; unreadable?: string; }>; /** * Backup folders for `dest` that are still present: copies an interrupted * refresh left behind (after the swap, or unrestorable). Round 7: these are * reported to the user rather than kept silently or deleted. Round 8: an * empty one holds nothing to report and is removed. Round 9: on a volume * that ignores case, a backup made under another spelling of the name * (`.Foo.` for `foo`) belongs to this destination too, so it is reported; * it is never removed or restored, since on a case-sensitive volume the * same name belongs to a different destination. Round 14: a staging folder * left by a crashed write is reported the same way. Round 15: so is what a * crashed or failed removal left under a parked name. Call under the lock. */ export declare function listLeftoverBackups(dest: string): Promise; /** User-facing warning for a leftover backup, staging folder or parked entry. */ export declare function leftoverBackupWarning(folder: string): string; //# sourceMappingURL=fan-out.leftovers.d.ts.map