Remove managed data from the Setup screen - #79
Merged
Merged
Conversation
Uninstalling MuMDIA left everything the application had downloaded or built behind, with nothing in the interface that could remove it: 8.9 GB on one development machine, of which 4.7 GB was the managed Python environment and 4.3 GB the predicted-library cache. An MSI removes exactly what it placed under Program Files, and all of this is written at runtime under %LOCALAPPDATA%\MuMDIA (or ~/.local/share/MuMDIA). Deliberately not a WiX uninstall custom action. An upgrade reinstalls over the same data directory and reuses that download and that cache, an MSI uninstall also runs during some upgrade paths, and a spectral library is hours of prediction rather than a download, so a silent delete there would destroy real work as a side effect of a version change. The Setup screen gains a "Managed data" card instead. `components::inventory` lists what exists item by item with the bytes it occupies, each row names the exact paths, and removal takes two clicks. The six items are primary, ms2pip, thermo, diann, libraries and settings; every directory name now comes from a constant exported by the module that writes there, so a rename cannot leave something behind that nothing offers to remove. Checked against a real installation: every file present is covered by an item. Two safety properties, both tested. `remove_in` resolves the real PARENT directory and refuses anything resolving outside the data directory, and refuses a symbolic link outright, because this is a recursive delete driven by a string from the frontend; canonicalising the item itself would follow a link and delete its target. `components_remove` refuses entirely while a search, an installation or a library build is running, since those hold the files it would delete, and a poisoned lock counts as busy. The install trackers keep a terminal `done` on purpose so a caller polling for it cannot miss the transition, so each of them gains a `forget`; without it a removed component went on reporting itself installed until the application restarted. Sizing the folder walks every file in a Python environment, so the card refreshes when the Setup screen is opened, after a removal, and once when an installation finishes, never on the 900 ms installation poll. Desktop tests 83 -> 87, and two concurrent `cargo test` runs both pass, which is the check the earlier shared-temp-dir flakes need. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uninstalling MuMDIA left everything the application had downloaded or built behind, with nothing in the interface that could remove it. Measured on one development machine: 8.9 GB.
python\libraries\configs\,diann.json,console-*.txtAn MSI removes exactly what it placed under Program Files. All of the above is written at runtime under
%LOCALAPPDATA%\MuMDIA(or~/.local/share/MuMDIA), so the installer has no record of it.Why not an uninstaller action
Leaving the files is the right default; having no way to remove them was the bug.
What this adds
A Managed data card at the bottom of the Setup screen.
components::inventorylists what exists, item by item, with the bytes each occupies; each row names the exact paths and takes two clicks. Six items:primary,ms2pip,thermo,diann,libraries,settings.Every directory name now comes from a constant exported by the module that writes there (
components::THERMO_DIR_NAME,diann::MANAGED_DIR_NAME,diann::LIBRARY_CACHE_NAME,diann::STATE_FILE_NAME,settings::CONFIG_DIR_NAME), so a rename cannot leave something behind that nothing offers to remove.Safety
This is a recursive delete driven by a string from the frontend, so:
remove_inresolves the real parent directory and refuses anything resolving outside the data directory. Canonicalising the item itself would follow a link and delete its target, which is why the check is on the parent;components_removerefuses entirely while a search, an installation or a library build is running, because those hold the files it would delete. A poisoned lock counts as busy.Each install tracker gains a
forget. Their terminaldoneis sticky on purpose so a caller polling for it cannot miss the transition; withoutforget, a removed component went on reporting itself installed until the application restarted.Sizing the folder walks every file in a Python environment, so the card refreshes when the Setup screen is opened, after a removal, and once when an installation finishes. Never on the 900 ms installation poll, and not at startup.
Validation
cargo fmt --check,cargo clippy --all-targets -D warnings,cargo test --lib: 87 passed (83 before; four new tests cover listing, removal, the refusal of unknown ids and the absent-path size).cargo testruns in separate target directories, both 87 passed, which is the check the earlier shared-temp-dir flakes need.ci/check_desktop_ui.py: 114 element ids, 32 commands, both directions agree.ci/check_doc_refs.pyclean.node --check desktop/ui/app.js.Not exercised: the card has no browser-level test, so the rendering and the two-click flow want one manual pass in a rehearsal build. Nothing was deleted from the development machine during this work.
🤖 Generated with Claude Code