switch: Don't delete a real Mods folder the first time a profile is picked #45

Closed
opened 2026-10-24 08:52:52 +00:00 by mira · 1 comment
Collaborator

Picking a profile deletes whatever is at the game's mods path before it makes the link (main.go:204-208, develop at d7b3799):

_ = os.RemoveAll(archive)
err := os.Symlink(profile, archive)

That's fine once the mods path is already a link. But the first time someone uses the switcher, the game's Mods folder is usually a real folder full of mods, and RemoveAll wipes it with no prompt and no backup. The error is ignored too, so a half-deleted folder looks the same as a clean switch.

The whole point of the tool is switching mod sets safely and fast, so losing the mods you already had is the worst thing it can do.

Purpose: meets #2 (switching never loses mods).

What to do

  • Before switching, check what's at the mods path with Lstat.
    • If it's a symlink, remove the link only (os.Remove, not RemoveAll) and make the new one.
    • If it's a real folder, don't delete it. Either move it into the profiles directory as a new profile (for example profiles/original-<date>) after a confirm dialog, or refuse with a clear message saying what to do. Pick whichever is simpler and say which in the PR.
    • If nothing's there, just make the link.
  • Don't ignore the remove error. If it fails, show it and stop.
  • Add a small test for the switch logic on a temp dir: link to link, real folder (nothing gets deleted), and empty path. Move the logic out of the button handler so it can be tested without fyne.

Acceptance

  • With a real Mods folder in place, clicking a profile never deletes its contents. The test proves it.
  • Switching between two profiles still works and only touches the link.
  • A failed remove or link shows the real error and leaves things as they were.
  • CI runs the new test on Linux and Windows.

Out of scope

Mod management, dedupe, and UI changes beyond the confirm or error dialog.

Backlog for now. The sprint list is frozen, so this waits until Justin opens new work.

Picking a profile deletes whatever is at the game's mods path before it makes the link (main.go:204-208, develop at d7b3799): ```go _ = os.RemoveAll(archive) err := os.Symlink(profile, archive) ``` That's fine once the mods path is already a link. But the first time someone uses the switcher, the game's Mods folder is usually a real folder full of mods, and RemoveAll wipes it with no prompt and no backup. The error is ignored too, so a half-deleted folder looks the same as a clean switch. The whole point of the tool is switching mod sets safely and fast, so losing the mods you already had is the worst thing it can do. Purpose: meets #2 (switching never loses mods). ## What to do - Before switching, check what's at the mods path with Lstat. - If it's a symlink, remove the link only (os.Remove, not RemoveAll) and make the new one. - If it's a real folder, don't delete it. Either move it into the profiles directory as a new profile (for example `profiles/original-<date>`) after a confirm dialog, or refuse with a clear message saying what to do. Pick whichever is simpler and say which in the PR. - If nothing's there, just make the link. - Don't ignore the remove error. If it fails, show it and stop. - Add a small test for the switch logic on a temp dir: link to link, real folder (nothing gets deleted), and empty path. Move the logic out of the button handler so it can be tested without fyne. ## Acceptance - [ ] With a real Mods folder in place, clicking a profile never deletes its contents. The test proves it. - [ ] Switching between two profiles still works and only touches the link. - [ ] A failed remove or link shows the real error and leaves things as they were. - [ ] CI runs the new test on Linux and Windows. ## Out of scope Mod management, dedupe, and UI changes beyond the confirm or error dialog. Backlog for now. The sprint list is frozen, so this waits until Justin opens new work.
Owner

Moved out of the backlog into the current sprint on Justin's go (relayed by Rex at 11:56 AM CT). It's #1 of 3 for Ash, in this order: SwipedModSwitcher#45, then LewdZ#147, then wwwdupe#19. Any note on this issue that says it stays in the backlog is out of date now.

Moved out of the backlog into the current sprint on Justin's go (relayed by Rex at 11:56 AM CT). It's #1 of 3 for Ash, in this order: SwipedModSwitcher#45, then LewdZ#147, then wwwdupe#19. Any note on this issue that says it stays in the backlog is out of date now.
linus closed this issue 2026-10-24 17:05:35 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
s1d3sw1ped/SwipedModSwitcher#45
No description provided.