Three small follow-ups to 1751603:
- BACKUP_SUFFIX was lost during the launchOptions refactor. apply_mod
references it on every non-skip path (new target, drifted bytes, or
replace mode), so the moment a deployment hit one of those, the
service would NameError at runtime. The bug was latent on yarn
because every dropped file's bytes already matched its source, so
every apply short-circuited at the byte-match check; an empirical
rm libxell.dll + systemctl start reproduced the NameError before
the fix and showed a successful recreate after.
- Mention launchOptions in the leading file docstring. The Example
block already covers file ops; the new option had no entry-level
doc.
- Normalize blank lines between top-level Python defs in the heredoc
(PEP-8 wants exactly two: we had four between apply_mod and
apply_launch_options, zero between apply_launch_options and main).
Three additions on top of the file-replacement scaffolding:
- mode = "init": create-on-first-apply, leave-alone-otherwise. For
files the application writes back to (configs edited in-game, save
files). Operator pushes a new template by deleting the target.
- chmod 644 after every copy. shutil.copy2 preserved the source's
/nix/store mode (0o444), which made dropped DLL configs read-only.
Apps that wrote back (OptiScaler "Save INI") got EACCES, which in
OptiScaler's case cascaded into CreateSwapChainForHwnd returning
E_FAIL and crashed FH5 on launch.
- launchOptions = listOf str. Multiple mods targeting the same
steamAppId have their lists concatenated (mod-name alphabetical),
joined with spaces, %command% appended once. Written into Steam's
per-app block in userdata/<id>/config/localconfig.vdf via vdf
parse + atomic os.replace. Idempotent.
- X-ConfigHash on the systemd unit so switch-to-configuration switch
re-runs apply when the manifest changes.