Steam imports: read only the linked manifest, and leave staged ones alone

seed_install read the app's manifest from every library before checking
that it was the linked DroidDeck install, so a manifest in another library
that is not UTF-8 raised past the caller and stopped routing for later
games. It now returns before reading anything but the linked manifest.

An untouched manifest from an older version was migrated even while
steamapps/downloading/<appid> existed; that migration now waits until
Steam is not staging the app, like the rewrite of a queued import.
This commit is contained in:
K11MCH1 authored and Kurt Himebauch committed 2026-11-05 13:59:44 -05:00
1 parent 1ec1c20be1
commit fcbd45453f
2 files changed
+28 -5

No files matched your search

@@ -461,13 +461,15 @@ def seed_install(steam_root, game, appid):
for root in libraries(steam_root):
existing = root / "steamapps" / manifest.name
if existing.is_file():
if not (existing == manifest and source.is_dir() and target.is_symlink()
and os.readlink(target) == str(source)):
return True
text = existing.read_text()
linked = (existing == manifest and source.is_dir() and target.is_symlink()
and os.readlink(target) == str(source))
if linked and build is None and update_not_started(text, steamapps, appid, name):
staging = (steamapps / "downloading" / str(appid)).exists()
if build is None and update_not_started(text, steamapps, appid, name):
wanted = update_on_launch(text)
elif linked and (text in (minimal, bare, legacy, legacy.replace('"StateFlags" "4"', '"StateFlags" "2"'))
or (build is not None and update_not_started(text, steamapps, appid, name))):
elif ((text in (minimal, bare, legacy, legacy.replace('"StateFlags" "4"', '"StateFlags" "2"')) and not staging)
or (build is not None and update_not_started(text, steamapps, appid, name))):
wanted = content
else:
wanted = text
+21
View File
@@ -336,6 +336,27 @@ class ImportsTest(unittest.TestCase):
imports.route(self.steam, self.acct, [self.game])
self.assertEqual(before, path.read_text())
def test_an_untouched_import_is_left_alone_while_steam_stages_it(self):
self.snapshot()
imports.route(self.steam, self.acct, [self.game])
path = self.steam / 'steamapps/appmanifest_42.acf'
older = path.read_text().replace(' "AutoUpdateBehavior" "1"\n', '')
path.write_text(older)
(self.steam / 'steamapps/downloading/42').mkdir(parents=True)
imports.route(self.steam, self.acct, [self.game])
self.assertEqual(older, path.read_text())
def test_a_manifest_in_another_library_is_not_read(self):
other = self.root / 'Other'
(other / 'steamapps').mkdir(parents=True)
(other / 'steamapps/appmanifest_42.acf').write_bytes(b'"AppState"\n{\n "name" "\xff\xfe"\n}\n')
(self.steam / 'steamapps').mkdir(parents=True)
(self.steam / 'steamapps/libraryfolders.vdf').write_text('"libraryfolders"\n{\n\t"1"\n\t{\n\t\t"path"\t\t"%s"\n\t}\n}\n' % other)
self.snapshot()
games, routes = imports.route(self.steam, self.acct, [self.game])
self.assertEqual({str(self.game['appid']): 42}, routes)
self.assertEqual(b'"AppState"\n{\n "name" "\xff\xfe"\n}\n', (other / 'steamapps/appmanifest_42.acf').read_bytes())
def test_started_import_without_a_build_is_left_to_steam(self):
for extra, staging in [('\t"BytesDownloaded"\t\t"5"\n\t"AutoUpdateBehavior"\t\t"0"\n', False),
('\t"AutoUpdateBehavior"\t\t"0"\n', True)]: