Expand description
One idempotent pass that makes a directory tree match another, in process.
What:
Make one directory tree match another, in process: copy what is missing or changed (cloning file data where the
filesystem can), optionally delete what the source no longer has, or only add what is newer in the source.
Why:
This is the work cp --archive --reflink=always, rsync --archive --delete and rsync --archive --update did in
the migration script, without starting those programs. One idempotent function serves all three passes, so a
pass interrupted at any point is repeated safely: an entry already equal (same type, size, modification time and
permission bits) is left alone. The walk uses a work stack, not recursion, so a deep tree cannot overflow the stack;
a directory’s own attributes are applied after its children, because adding a child changes its modification time.
Files this user may not read (for example root-owned mode 600 logs) are left where they are and listed; any other
failure, and a directory this user cannot list, stops the run (the rule of the 2026-11-01 real run: copying around
an unreadable directory with deletion on would erase its subtree from the copy).
Every entry is written under a temporary name in its directory and renamed over its name when complete, so a kill
never leaves a half-written file at a name a later pass would take for a newer one. The destination is reached
through open directory descriptors (subvolume_anchor.rs), so a directory replaced by a link during the pass
redirects nothing. An update-only pass never removes a destination entry that may hold newer work: a directory, or
an entry of another type that is not older than the source, is kept and listed.
In TS you’d write (pseudocode):
const stats = await syncTree({ platform, source, destination, delete: true, updateOnly: false, excluded: ['.git/index.lock'] });Structs§
- Sync
Options - What:
What one pass may do.
&'a [PathBuf]borrows the list of excluded paths for the pass. Why: The excluded paths (relative to the tree roots) are neither copied nor deleted: the lock files the migration itself holds are the use. - Sync
Stats - What: What one pass did. Why: The report prints the counts, and the unreadable and skipped lists are the loud part of it.
Functions§
- sync_
tree - What:
Run one pass from
sourcetodestination(both existing directories). Why: See the module description; the work stack replaces recursion.