Skip to content

Fix: a new install no longer resets settings the user changed - #427

Merged
thcp merged 2 commits into
mainfrom
fix/preserve-settings-across-installs
Aug 24, 2026
Merged

Fix: a new install no longer resets settings the user changed#427
thcp merged 2 commits into
mainfrom
fix/preserve-settings-across-installs

Conversation

@thcp

@thcp thcp commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Confirmed, reproduced, fixed

Reproduced against the published 0.14.0 package, not a local build:

OLD install: user relocates the stems folder
    before : C:\Users\thale\Documents\StemDeck\jobs
    after  : ...\repro\MyStems
    settings.json jobs_dir -> ...\repro\MyStems

NEW install (fresh extract of the SAME release):
    reports: C:\Users\thale\Documents\StemDeck\jobs
    new install has settings.json: False

The library looks empty even though every stem is still on disk where the user put it.

Cause

Portable packages keep their data in <app>/data (#399), so settings.json lives inside the install directory. A new install is a new folder, so it starts with an empty data/ and loses everything the user set — not just the stems location, but the port, compute device, separation quality and language too.

The restore half was already in the working tree: migrate_persisted_files plus an ensure_workspace step that seeds a freshly extracted portable package from a per-user copy. What was missing was anything writing that copy. Nothing had, since #399 moved the data directory out of %LOCALAPPDATA% and no writer took over the old location — so the restore was reading a path that never existed. On this machine %LOCALAPPDATA%\StemDeck did not exist at all.

The write half

  • shared_settings_dir() names the per-user location once, for all three platforms. Deliberately the OS-standard data dir — exactly what local_data_dir() returns for a non-portable install — so both layouts share one location and an install that switches between them keeps its settings.
  • start_backend passes it as STEMDECK_SETTINGS_MIRROR, so the writer and ensure_workspace's reader cannot drift apart.
  • settings._save() mirrors there after each successful write. Best-effort by construction: it is a redundant copy and must never fail the setting the user just changed. Written via temp-file-and-replace, because a torn write would be restored verbatim into the next install.

Verified

End to end against the source backend — same scenario that reproduced the bug:

==> per-user copy written? True
    jobs_dir in copy: ...\verifyfix\MyStems
==> shell seeds the fresh install (what ensure_workspace does)
==> NEW install, started clean
    reports: ...\verifyfix\MyStems
RESULT: PASS - the new install kept the user's stems folder

Five tests cover the write half, including that a mirror which cannot be written still saves the setting, and that the mirror tracks later changes (a stale copy would hand back a setting the user had already changed — the same class of bug as losing it).

Windows Linux
clippy clean clean
rust tests 45 46
rustfmt clean

Python: ruff clean, and no new failures — identical 14 pre-existing Windows-environment failures on main and this branch.

Also included

The clippy cleanups already sitting in the working tree (derivable Default, match to if let, redundant trim, unneeded return, unused binding) — audit item F12. Mechanical, and both platforms compile with zero warnings.

Note on scope

This fixes the manual upgrade path, which is what was reported. The in-app updater added in #423 never had this problem: it replaces backend/ and the executable while leaving data/ untouched, so settings already survive that route.

Thales added 2 commits August 24, 2026 09:36
Reproduced against the published 0.14.0 package: relocate the stems folder in
Settings, extract the same release into a fresh folder, and the new install
reports the default folder again. The library looks empty even though every
stem is still on disk where the user put it.

Cause: portable packages keep their data in <app>/data (#399), so settings.json
lives INSIDE the install directory. A new install is a new folder, so it starts
with an empty data/ and loses everything the user set -- not just the stems
location but the port, compute device, separation quality and language too.

The restore half of the fix was already in the working tree: migrate_persisted_files
plus an ensure_workspace step that seeds a freshly extracted portable package
from a per-user copy. What was missing was anything writing that copy. Nothing
had, since #399 moved the data directory out of %LOCALAPPDATA% and no writer
took over the old location, so the restore read a path that never existed.

This adds the write half:

- shared_settings_dir() names the per-user location once, for all three
  platforms. Deliberately the OS-standard data dir -- exactly what
  local_data_dir() returns for a NON-portable install -- so both layouts share
  one location and an install that switches between them keeps its settings.
- start_backend passes it as STEMDECK_SETTINGS_MIRROR, so the writer and
  ensure_workspace's reader cannot drift apart.
- settings._save() mirrors there after each successful write. Best-effort by
  construction: it is a redundant copy and must never fail the setting the user
  just changed. Written via a temp file and replace, because a torn write would
  be restored verbatim into the next install.

Verified end to end against the source backend: relocate the folder in install
A, seed install B the way ensure_workspace does, and B reports the user's
folder rather than the default. Five tests cover the write half, including that
a mirror which cannot be written still saves the setting.

Also carries the clippy cleanups already sitting in the tree (derivable Default,
match to if let, redundant trim, unneeded return, unused binding) -- audit item
F12. Both platforms compile with no warnings; 45 Rust tests on Windows, 46 on
Linux, and the Python suite has no new failures against main.
Mirroring only on save left out the people most likely to be bitten:
someone who relocated their stems folder in an earlier release and never
opens Settings again never triggers a save, so no per-user copy is ever
written and their next fresh extract still starts from defaults.

Seed the copy on first load instead, from settings that are already on
disk. Guarded so an empty state (a genuine first run) can never overwrite
a good copy, which would destroy the very thing being preserved.

Also pins the Unraid template at 0.14.1.
@thcp
thcp merged commit 1e248ac into main Aug 24, 2026
12 checks passed
@thcp
thcp deleted the fix/preserve-settings-across-installs branch August 24, 2026 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant