Result of committing one staged action. Carries the path of the
.pre-import.bak we parked the previous target at (if any) so we
can either roll it back on a later failure or unlink it on
finalize.
RAII guard that flips Scheduler::import_in_progress on construction
and restores it on drop, including on panic. The run loop checks the
flag once per tick and short-circuits while itโs set.
Per-file action staged for the commit phase. Writes land in
.<name>.import.tmp alongside the final path so the rename is
across a single directory entry (atomic on every filesystem we
support). Removes have no temp โ theyโre just deferred unlinks.
Only the settings window invokes backup IPC. Overlays never need
it; gate at the command boundary so a future renderer bug that
leaks the IPC handle to an overlay canโt initiate a destructive
import or exfiltrate state.
Hard cap on the on-disk size of a bundle file weโll deserialize.
Realistic worst case: ~300 B per logged event ร ~50 events/day ร
a decade โ 55 MB. 64 MiB gives a generous multiple of that while
keeping the peak allocation (read into String, then parse) low
enough not to stress a 4 GB tray-app footprint. Larger files
short-circuit before parse so an accidentally-picked 10 GiB blob
canโt OOM the deserializer.
Sibling path where the existing target is parked for the duration
of the commit. If a later stageโs commit fails we rename this back
into place; if every stage succeeds we delete it during finalize.
Apply one staged action, parking the existing target at
.pre-import.bak first so a later commit failure can be rolled
back. A pre-existing .bak (residue from a previously-failed
import) is unlinked first so the parking rename succeeds on
Windows, which doesnโt overwrite a present destination.
Happy-path cleanup after every stage committed successfully.
Unlinks the .pre-import.bak files we parked during commit so
they donโt linger as confusing sibling files.
Single-line breadcrumb the import flow drops into the log file
on success. Pulled out of the log::info! call so the format
arguments are exercised by a unit test even when no logger is
installed in the test binary (the log crate short-circuits
argument evaluation when log_enabled!(Info) is false).
Reverse-restore every committed stage from its .pre-import.bak.
Best-effort: each step swallows errors because a) weโre already in
a failure path and b) a failed individual rollback shouldnโt
abort the rest. Stale .bak files left by a catastrophic rollback
failure are picked up by the next importโs commit_stage (it
unlinks the stale .bak before parking).
Events are checked leniently: a line we canโt parse โ e.g. an event
type written by a newer Entracte โ must not brick the whole import.
The events file is written verbatim and the stats reader
(crate::stats::read_all) already drops lines it canโt parse, so
unknown events are preserved on disk and simply ignored when computing
stats. We only count and warn so the drop isnโt silent โ matching the
runtime readerโs tolerance rather than the old all-or-nothing reject.