fix(update): on Linux "Skip this version" is kept, and no longer costs the game its saves #2283

Merged
jarynclouatre merged 1 commit from fix/linux-update-skip-saves into main 2026-11-11 16:58:55 +00:00
jarynclouatre commented 2026-11-11 13:27:26 +00:00 (Migrated from github.com)

On Linux, choosing "Skip this version" in the game's own update question at two starts leaves the game showing no saves: it runs on an empty user/ folder beside the game from then on, while the real saves sit in ~/.local/share/hookshot.

This is the question bin/hookshot asks when the player starts it themselves (a terminal, a Steam or Lutris shortcut to it), with curl and zenity installed. The folder's launcher and the builder ask in their own windows and are not affected.

What happens

hos_update_check writes hookshot_update_skip.txt to user/ beside the game, as on Windows. Linux keeps its saves in $XDG_DATA_HOME/hookshot since 7eeb91a, and right after the question the same start moves a user/ folder beside the game there, as saves from an earlier build (saves_dir):

  1. First skip: the file is moved to the data folder with nothing else, saves-moved.txt is written though no save moved, and the next start asks again, because the check reads the file beside the game.
  2. Second skip: the file is now in both places. The move reads that as saves it cannot move and keeps the old place: hos_user_dir becomes the user/ beside the game, which holds only the skip file. No saves are shown, and new ones are written there.

The change

  • The skip is kept with the saves, where they are: the data folder, or --user's folder.
  • main asks about the update once that place is known (the call moves below the lines that set it; the Windows order of effects is the same, its check does not use the saves' place).

A skip that an earlier start already moved to the data folder is read again. One in a user/ folder from an earlier build moves with the saves and is read too.

A player already in the second state keeps running beside the game after this change, since both places then hold a save folder and the move rightly does not pick one. Their earlier saves are in ~/.local/share/hookshot/save; removing the user folder beside the game (if nothing was saved since) brings them back.

Tested

tests/test_linux_update_skip.py (new) builds the game's start as hos_main.c has it (the part of main that finds the folder, asks about an update and picks the saves' place, with saves_dir), with hos_update.c and host/posix/win32_posix.c, puts it in a game folder of its own as bin/hookshot, and starts it with a curl that names a release and a zenity that answers "Skip this version":

  • On this change: asked once for a release and never again, every start uses the data folder, no user/ or saves-moved.txt appears beside the game, a newer release is asked about again; a user/ from an earlier build with saves and a skip moves once and is not asked.
  • On main: fails at the second start, "the game uses …/Games/Hookshot/user for its saves".
  • python -I -B tests/run_all.py: nothing new fails.

Not tested in a built game or with the real zenity and GitHub: the functions are the source's own, the two tools are stand-ins.

On Linux, choosing "Skip this version" in the game's own update question at two starts leaves the game showing no saves: it runs on an empty `user/` folder beside the game from then on, while the real saves sit in `~/.local/share/hookshot`. This is the question `bin/hookshot` asks when the player starts it themselves (a terminal, a Steam or Lutris shortcut to it), with `curl` and `zenity` installed. The folder's launcher and the builder ask in their own windows and are not affected. ## What happens `hos_update_check` writes `hookshot_update_skip.txt` to `user/` beside the game, as on Windows. Linux keeps its saves in `$XDG_DATA_HOME/hookshot` since 7eeb91a, and right after the question the same start moves a `user/` folder beside the game there, as saves from an earlier build (`saves_dir`): 1. First skip: the file is moved to the data folder with nothing else, `saves-moved.txt` is written though no save moved, and the next start asks again, because the check reads the file beside the game. 2. Second skip: the file is now in both places. The move reads that as saves it cannot move and keeps the old place: `hos_user_dir` becomes the `user/` beside the game, which holds only the skip file. No saves are shown, and new ones are written there. ## The change - The skip is kept with the saves, where they are: the data folder, or `--user`'s folder. - `main` asks about the update once that place is known (the call moves below the lines that set it; the Windows order of effects is the same, its check does not use the saves' place). A skip that an earlier start already moved to the data folder is read again. One in a `user/` folder from an earlier build moves with the saves and is read too. A player already in the second state keeps running beside the game after this change, since both places then hold a `save` folder and the move rightly does not pick one. Their earlier saves are in `~/.local/share/hookshot/save`; removing the `user` folder beside the game (if nothing was saved since) brings them back. ## Tested `tests/test_linux_update_skip.py` (new) builds the game's start as `hos_main.c` has it (the part of `main` that finds the folder, asks about an update and picks the saves' place, with `saves_dir`), with `hos_update.c` and `host/posix/win32_posix.c`, puts it in a game folder of its own as `bin/hookshot`, and starts it with a `curl` that names a release and a `zenity` that answers "Skip this version": - On this change: asked once for a release and never again, every start uses the data folder, no `user/` or `saves-moved.txt` appears beside the game, a newer release is asked about again; a `user/` from an earlier build with saves and a skip moves once and is not asked. - On `main`: fails at the second start, "the game uses …/Games/Hookshot/user for its saves". - `python -I -B tests/run_all.py`: nothing new fails. Not tested in a built game or with the real `zenity` and GitHub: the functions are the source's own, the two tools are stand-ins.
hckrman101 (Migrated from github.com) approved these changes 2026-11-11 16:49:29 +00:00
hckrman101 (Migrated from github.com) left a comment

Looks good. The diagnosis is clear and the fix is small.

Checked:

  • Linux: hos_update_check now runs after hos_user_dir is set (--user, or saves_dir(beside_user)), so the skip file is read and written in the saves' place. hos_user_dir is never NULL at that call, so the new snprintf/mkdir are safe. The old-user/ case still works: the move runs first, then the skip is read from the new place.
  • Windows: hos_update_check there is the separate #ifdef _WIN32 implementation, which doesn't use hos_user_dir, and the extern and the new path sit in the Linux section. Only the call moves, after image/hos_romfs_dir/hos_user_dir are set, so nothing changes for it. The non-Linux stub is untouched.
  • The new test is picked up by run_all.py discovery, skips cleanly on Windows/macOS, and needs no game.

Nits, none blocking: mkdir(hos_user_dir) isn't recursive, so with a nested --user path that doesn't exist yet the skip just isn't saved (the question is asked again, no harm). Also the extra mkdir creates the data folder before saves_dir ever sees a later start, which is fine since it only runs after saves_dir.

CI: all green except appimage, which fails the same way on main's latest Linux AppImage run, so it isn't from this PR.

Looks good. The diagnosis is clear and the fix is small. Checked: - Linux: `hos_update_check` now runs after `hos_user_dir` is set (`--user`, or `saves_dir(beside_user)`), so the skip file is read and written in the saves' place. `hos_user_dir` is never NULL at that call, so the new `snprintf`/`mkdir` are safe. The old-`user/` case still works: the move runs first, then the skip is read from the new place. - Windows: `hos_update_check` there is the separate `#ifdef _WIN32` implementation, which doesn't use `hos_user_dir`, and the `extern` and the new path sit in the Linux section. Only the call moves, after `image`/`hos_romfs_dir`/`hos_user_dir` are set, so nothing changes for it. The non-Linux stub is untouched. - The new test is picked up by `run_all.py` discovery, skips cleanly on Windows/macOS, and needs no game. Nits, none blocking: `mkdir(hos_user_dir)` isn't recursive, so with a nested `--user` path that doesn't exist yet the skip just isn't saved (the question is asked again, no harm). Also the extra `mkdir` creates the data folder before `saves_dir` ever sees a later start, which is fine since it only runs after `saves_dir`. CI: all green except `appimage`, which fails the same way on main's latest Linux AppImage run, so it isn't from this PR.
Commenting is not possible because the repository is archived.
No description provided.