diff options
| author | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-05-14 16:34:13 -0500 |
|---|---|---|
| committer | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-05-14 16:34:13 -0500 |
| commit | 95a7f6bc85ec5695388def1ccfd785a631d3958b (patch) | |
| tree | c57c68c77f0a32672e9ac5ca31614fed0f94ad1d | |
| parent | 7133cf6308fb5c1c156bae9f182a1dafcb11f715 (diff) | |
bg3: publish only top-level overwrite mappings to avoid self-symlinks
After the first launch, doc/Stats -> overwrite/Stats (and siblings) are
deployed as directory symlinks. The next mappings() pass rglob'd
overwrite/ and emitted a Mapping for every nested entry — destinations
resolved back through the parent symlink to the source, so both
create_mapping's unlink+symlink_to and fuseconnector's
create_directory_symlink ended up operating on a path that physically
*was* the source, producing self-pointing symlinks and wiping the
directory contents on the next launch.
Emit one directory mapping per redirected top-level subdir instead. The
parent symlink covers everything underneath via normal path resolution,
so no nested mapping is generated and the alias condition can't arise.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| -rw-r--r-- | libs/basic_games/games/baldursgate3/bg3_file_mapper.py | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/libs/basic_games/games/baldursgate3/bg3_file_mapper.py b/libs/basic_games/games/baldursgate3/bg3_file_mapper.py index cb6dd21..8719057 100644 --- a/libs/basic_games/games/baldursgate3/bg3_file_mapper.py +++ b/libs/basic_games/games/baldursgate3/bg3_file_mapper.py @@ -13,6 +13,21 @@ from . import bg3_utils _IS_LINUX = platform.system() != "Windows" +# Top-level subdirectories of MO2's overwrite that should be redirected into +# the game's Documents folder. Each is published as a single directory +# mapping so the parent symlink covers everything underneath — recursing +# into overwrite/ produces nested mappings whose destinations resolve back +# through the parent symlink to the source, corrupting the tree into +# self-pointing symlinks on the next launch. +_OVERWRITE_REDIRECTED_DIRS = ( + "Script Extender", + "Stats", + "Temp", + "LevelCache", + "Mods", + "GMCampaigns", +) + class BG3FileMapper(mobase.IPluginFileMapper): current_mappings: list[mobase.Mapping] = [] @@ -51,16 +66,17 @@ class BG3FileMapper(mobase.IPluginFileMapper): if progress.wasCanceled(): qWarning("mapping canceled by user") return self.current_mappings - (self._utils.overwrite_path / "Script Extender").mkdir( - parents=True, exist_ok=True - ) - (self._utils.overwrite_path / "Stats").mkdir(parents=True, exist_ok=True) - (self._utils.overwrite_path / "Temp").mkdir(parents=True, exist_ok=True) - (self._utils.overwrite_path / "LevelCache").mkdir(parents=True, exist_ok=True) - (self._utils.overwrite_path / "Stats").mkdir(parents=True, exist_ok=True) - (self._utils.overwrite_path / "Mods").mkdir(parents=True, exist_ok=True) - (self._utils.overwrite_path / "GMCampaigns").mkdir(parents=True, exist_ok=True) - self.map_files(self._utils.overwrite_path) + for name in _OVERWRITE_REDIRECTED_DIRS: + src = self._utils.overwrite_path / name + src.mkdir(parents=True, exist_ok=True) + self.current_mappings.append( + mobase.Mapping( + source=str(src), + destination=str(self.doc_path / name), + is_directory=True, + create_target=True, + ) + ) self.create_mapping( self._utils.modsettings_path, self.doc_path |
