From e2a7871fca664305a284cef31a36a693b05d23b6 Mon Sep 17 00:00:00 2001 From: Janne Pulkkinen Date: Tue, 16 Jan 2024 18:37:35 +0200 Subject: [PATCH] Fix parsing incomplete appmanifest files Incomplete appmanifest files can apparently be left over from old installations. Ignore such files and print a warning. Fixes #273 --- CHANGELOG.md | 1 + src/protontricks/steam.py | 12 ++++++++++-- tests/test_steam.py | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 547efb7..9487b4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### Fixed - Fix Protontricks crash when custom Proton has an empty `compatibilitytool.vdf` manifest + - Fix Protontricks crash when an incomplete appmanifest file is parsed ## [1.11.0] - 2023-12-30 ### Added diff --git a/src/protontricks/steam.py b/src/protontricks/steam.py index 403ef39..9e49e58 100644 --- a/src/protontricks/steam.py +++ b/src/protontricks/steam.py @@ -241,8 +241,16 @@ def from_appmanifest(cls, path, steam_lib_paths, steam_path=None): try: name = app_state["name"] except KeyError: - # Older app installations also use `userconfig/name` - name = app_state["userconfig"]["name"] + try: + # Older app installations also use `userconfig/name` + name = app_state["userconfig"]["name"] + except KeyError: + logger.warning( + "Incomplete appmanifest found at %s. This might be a " + "leftover file from an old installation. Skipping...", + path + ) + return None # Proton prefix may exist on a different library prefix_path = find_appid_proton_prefix( diff --git a/tests/test_steam.py b/tests/test_steam.py index f990334..861884a 100644 --- a/tests/test_steam.py +++ b/tests/test_steam.py @@ -84,6 +84,40 @@ def test_steam_app_from_appmanifest_empty(self, steam_app_factory): """ steam_app = steam_app_factory(name="Fake game", appid=10) + appmanifest_path = \ + Path(steam_app.install_path).parent.parent / "appmanifest_10.acf" + appmanifest_path.write_text( + vdf.dumps({ + "AppState": { + "appid": "10", + "Universe": "1", + "installdir": "Fake game", + # Use the same StateFlags mentioned in the #273 issue. + # Two flags set here are `StateUpdateRequired` and + # `StateUpdateStarted`, which might indicate the file + # is not properly tracked by Steam itself, since the + # installation directory was gone at this point. + "StateFlags": "1026" + } + }) + ) + + # Incomplete appmanifest file is ignored + assert not SteamApp.from_appmanifest( + path=appmanifest_path, + steam_lib_paths=[] + ) + + def test_steam_app_from_appmanifest_incomplete(self, steam_app_factory): + """ + Try to deserialize from an incomplete appmanifest and check that no + SteamApp is returned. + + Incomplete appmanifests can supposedly be created when moving app + installations + """ + steam_app = steam_app_factory(name="Fake game", appid=10) + appmanifest_path = \ Path(steam_app.install_path).parent.parent / "appmanifest_10.acf" appmanifest_path.write_text("")