a moved file relocates its ladder instead of rebuilding it, and orphans go
Moving a file into a folder made the sync look at a new path, find nothing, and convert it again — minutes of work to produce bytes that already existed a directory away — while the old folder stayed behind forever, because nothing ever deleted one. A move preserves size and mtime, and both are already in the manifest and in the stat. So the sync indexes what is already derived on that pair, and a file that has moved has its ladder RENAMED across. An ambiguous match is refused rather than guessed. Two originals can share a size and an mtime — a camera dump can write a whole card in one second — and rebuilding is merely slow where attaching the wrong photographs to a name is wrong. Orphans are removed afterwards, and only on a WHOLE-TREE sync. A scoped run knows about one folder, so everything outside it looks abandoned; deleting on that basis would take out the library the first time somebody re-synced a subfolder. Safe otherwise because derived/ is reproducible by definition, which is what its name has meant since these two folders stopped being called `user` and `treated`. Both are counted, recorded in the ledger and shown only when they happened, so an ordinary run stays one short line. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,10 @@ type SyncState = {
|
||||
done: number;
|
||||
built: number;
|
||||
skipped: number;
|
||||
/** Ladders renamed into place because their original moved, rather than rebuilt. */
|
||||
moved: number;
|
||||
/** Derived folders removed because their original is gone. Whole-tree syncs only. */
|
||||
pruned: number;
|
||||
errors: SyncError[];
|
||||
current: string[];
|
||||
startedAt: string | null;
|
||||
@@ -61,6 +65,8 @@ type Run = {
|
||||
total: number;
|
||||
built: number;
|
||||
skipped: number;
|
||||
moved: number;
|
||||
pruned: number;
|
||||
errors: SyncError[];
|
||||
fatal: string | null;
|
||||
};
|
||||
@@ -251,6 +257,9 @@ export const MediaSync = ({ onSettled }: { onSettled?: (settled: boolean) => voi
|
||||
{run.scope ? `${run.scope} · ` : ''}
|
||||
{run.built} built
|
||||
{run.skipped ? `, ${run.skipped} current` : ''}
|
||||
{/* Only when they happened, so an ordinary run stays one short line. */}
|
||||
{run.moved ? `, ${run.moved} moved` : ''}
|
||||
{run.pruned ? `, ${run.pruned} orphans removed` : ''}
|
||||
{run.errors.length ? `, ${run.errors.length} failed` : ''}
|
||||
{run.fatal ? ` — ${run.fatal}` : ''}
|
||||
{run.trigger === 'watcher' ? ' · on upload' : ''}
|
||||
|
||||
Reference in New Issue
Block a user