Skip to content

fix(launcher): remove installation keeps the saves and trophies, and no rebuild can lose them - #119

Merged
utkuhalis merged 1 commit into
mainfrom
fix/keep-saves
Nov 11, 2026
Merged

utkuhalis merged 1 commit into
mainfrom
fix/keep-saves

Conversation

@utkuhalis

Copy link
Copy Markdown
Collaborator

Found while adding Delete game (#114): a game's saves and trophies live inside the installation the launcher builds (.AnyPS5/Data/<game>/game), so Remove Installation deleted them with it, without saying so. The same fix, rules and wording as on Windows and Linux (AnyTogether/AnyPS5-Desktop, branch fix/keep-saves).

Where saves were lost before

  • Remove Installation: AppModel.uninstall (AppModel.swift:1936) called Installer.setAside, which moves the whole data folder into Removing (Installer.swift:297-314), and Installer.remove then deleted it, saves included.
  • An unlock over files whose bundle is gone (the .app removed by hand, or an unlock the launcher was quit over after the old bundle went): Installer.place carried the saves over only through the old bundle's Contents/Resources/game link (Installer.swift:706) and then removed Data/<game>/game (Installer.swift:715), saves included.
  • An unlock that fails while the new bundle takes the old one's place: the saves had already moved into the .partial bundle (Installer.swift:706), and run removes that bundle when it throws (Installer.swift:503).
  • The launcher quit during that step: removing the old game's files (Installer.swift:715) can take a while, and all that time the saves sat in the .partial bundle, which the next start (removeLeftovers, Installer.swift:337-345) or the next unlock (Installer.swift:586) deleted.

The rebuilds themselves (after an engine change, the automatic rebuild of a stale copy from #116, Update from Git's Relink All, a game's own engine, the relinker options, an update added, Unlock Again) all go through AppModel.unlock to the one Installer.run, and place carried the saves over when it finished. That part was right and now has tests.

What changes

  • Remove Installation keeps what is the player's: the saves (_sd), the save memory (_sd_mem), the trophies (_trophy), the other profiles' parked saves (_profiles), the mark that says whose are in place, and now also the game's download data (download0 to download2, what the engine gives the game as /download0 and keeps between runs). They move to .AnyPS5/Saves/<game> in the games folder before anything is set aside, and the next unlock of the game takes them back. This is Delete game's code (Installer.keepSaves), now inside the new Installer.uninstall, which Remove Installation and Delete game both call.
  • The card says so: "Your saves and trophies are kept and come back when you unlock the game again." after the text it had.
  • Saves that cannot be moved keep the installation: nothing is set aside, the parts already moved go back, and the notice says "The installation could not be removed" with the system's reason.
  • Kept only when there is something to keep: an empty folder and a link are left behind, so a game never played leaves nothing in Saves.
  • place also carries over from the game's files themselves, so they give their saves to the new installation whether or not their bundle is there.
  • A place that throws moves the saves out of the half-made bundle into .AnyPS5/Saves/<game> before the bundle is removed.
  • A half-made bundle left by a quit gives its saves back before it is removed, at the next start and at the next unlock: into the game's files when they are still there, else into .AnyPS5/Saves/<game>. One they cannot be taken out of stays.

There was no way to delete a game's saves on purpose before this change other than Remove Installation doing it silently, so none is added. Deleting a profile still removes that profile's saves from the installed games, as before.

Release note

Remove Installation keeps your saves: a game's saves and trophies live inside the installation AnyPS5 builds, and Remove Installation used to delete them with it without saying so. It now keeps them, together with the game's download data, in the games folder under .AnyPS5/Saves, and they come back when you unlock the game again, the same way as after Delete game. The card says they are kept. Saves are also safe when an unlock is interrupted or fails just as the new installation takes the old one's place.

Tests

  • Tests/AnyPS5CoreTests/SavesKeptTests.swift, with a fake engine and the real Installer.run: Remove Installation keeps every part and the next unlock takes them back, saves that cannot be kept remove nothing, a part that cannot be moved puts the others back, a rebuild after an engine change, with another engine altogether, after the relinker options change, after an update is added, a rebuild that fails, the game's files without their bundle, a place that throws, a half-made bundle with the old game still there and with it gone, and removeLeftovers.
  • Tests/AnyPS5Tests/SavesSurviveModelTests.swift, the launcher's model with an engine folder of its own: the card's text, Remove Installation from the card then Unlock, the notice when saves cannot be kept, the stale copy rebuilt by Play, and Unlock Again from Game Settings.

Every test works in temporary folders.

Not run

Nothing was built or run on a Mac: no local swift build or swift test, CI only. The card was not looked at on a screen and no real game was removed or rebuilt. The model tests cover the stale copy's rebuild and Unlock Again. The other rebuilds (Update from Git, a game's own engine, the relinker options, an update added) are tested at the installer, which they all reach through the same unlock. All 28 language files have the two new texts. English and Turkish were written by hand, the other 26 are machine translations built from the words those files already use.

…no rebuild can lose them

A game's saves, trophies and download data live in the installation the launcher builds (its data folder), so Remove Installation deleted them with it. Uninstall now keeps them in the store first, as Delete game does (the same code), and the next unlock takes them back. The card says so. A rebuild that fails or is interrupted while the new bundle takes the old one's place leaves them in the game or in the store, never in the half-made bundle that is removed, and the game's files without their bundle still give their saves to the next unlock.
@utkuhalis
utkuhalis merged commit a21055e into main Nov 11, 2026
18 of 20 checks passed
@utkuhalis
utkuhalis deleted the fix/keep-saves branch November 11, 2026 22:17
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