switch: Never delete a real Mods folder when picking a profile #46
Labels
No labels
Kind/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
blocked
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
s1d3sw1ped/SwipedModSwitcher!46
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "ash/safe-switch-45"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #45
Why
Picking a profile ran
os.RemoveAllon the game mods path and ignored the error. The first time someone used the switcher, their real Mods folder (full of mods) was wiped with no prompt or backup, and a half-deleted folder looked like a clean switch.What changed
switcher(no fyne import, so it's testable) withSwitch(profile, modsPath). It Lstats the mods path first:os.Remove) and makes the new one. If the new link fails, the old link is put back.ErrRealModsFolder, nothing touched. I picked refuse over move-and-confirm because it's simpler and can't lose anything. The dialog tells the user to move the contents into a new folder under the profiles dir and then remove or rename the Mods folder.dialog.NewError(real error text), instead of the generic "not admin" message.Test on windowsstep (go test ./switcher/...) to the windows job in pull-request-ci and push-ci. The Linux test job already runsgo test -race ./....Tests
switcher/switch_test.go, 4 tests, all passing locally (go test -race -count=1 -v ./switcher/):ErrRealModsFolder, folder and nested file untouchedRisk / rollback
Users whose Mods path is a real folder now get a refusal instead of a wipe; that's intended. Rollback: revert this commit.
GO from me on
7391559.This fixes the real problem in #45: a real Mods folder is never deleted now.
SwitchLstats first, only ever removes a symlink, refuses a real folder or file withErrRealModsFolder, and puts the old link back if the new one fails. The dialog now shows the actual error instead of the "not admin" guess. Refusing instead of moving is the right call for a first fix, since it can't lose anything. Head is on the current develop tip.One small thing, not blocking:
TestSwitchLinkFailureLeavesOldLinklinks a different path (missing/Mods), so it never goes through the remove-then-relink branch and the restore code isn't actually tested. If you want real coverage there, a follow-up could make the new link fail on the same path (for example a profile path that's unusable on that OS). Fine to leave for later.The CI change only adds a
go test ./switcher/...step on Windows, with no secrets and no new triggers. Because it touches workflows I'm adding Blake. Linus merges once Blake says GO and CI is green.Update at
7391559: the Windows runner account can't create symlinks (A required privilege is not held by the client, run 166). The three link tests now skip there and give that error as the reason. The real-folder test, which is the no-data-loss guarantee, runs and passes on Windows (run 167). All four tests run on Linux. To get full link coverage on Windows, the win-runner service account needs Developer Mode or SeCreateSymbolicLinkPrivilege. That's an ops follow-up, not part of this PR.Blake security review: APPROVE at
7391559d8a.go test ./switcher/...) to the existing windows job in pull-request-ci.yaml and push-ci.yaml. Triggers unchanged, nopermissions:change, no secrets or env secrets used.@mainin this workflow.windowslabel. Tests write only under t.TempDir and skip when the account can't make symlinks, so they run fine as the non-admin runner user and touch no locked toolchain dirs.