usvfs-workaround: fix paths
Closed this issue · 9 comments
Due to the very nature of *nix being case-sensitive the resulting gamedata folder contains non-merged folders with different capitalization. The picture demonstrates this very well. This happens throughout the gamedata-folder, resulting in in-game glitches and bugs (Noticeably the sound -> TOZ-34 for example).
Wine, as of now, does not seem to handle this:
https://wiki.winehq.org/Case_Insensitive_Filenames
Possible solution
Rewrite paths to be lowercase before copying.
For this another library must be used or a function needs to be written from scratch
Alternatively the function distutils.dir_util.copy_tree(..) can be replaced with a modified version via monkey patching.
I don't know though where to find said function's source code. There is also a probability that it was written in C.
Another way is to write a function that will be executed on the target mod directory after copy_tree which renames the folders to their lowercase counterpart.
It's not possible with folder filtering
I was planning on lowering everything just before but ... It's not a solution since some installation directives contain capital letters.
Still looking for a smart idea to do that. Actually, the only mod with capital letters is: 122- Zone Tales in Loading Screens - Oni, so issue is really minor.
I may need to search for gamedata dirs in decompressed archive and force them to lowercase.
It's not possible with folder filtering
I was planning on lowering everything just before but ... It's not a solution since some installation directives contain capital letters. Still looking for a smart idea to do that. Actually, the only mod with capital letters is: 122- Zone Tales in Loading Screens - Oni, so issue is really minor.
I may need to search for gamedata dirs in decompressed archive and force them to lowercase.
I got a little bit acquainted with python and wrote a recursive function that does what we need. The initial folder will not be renamed (The mod folder).
import os.path
import shutil
# renames all tree subdirectories to lowercase
def tree_lower_subdirectories(directory, modify_root = False):
if not os.path.lexists(directory): return False
if modify_root and any(map(str.isupper, os.path.basename(directory))):
ps = os.path.split(directory)
directory_lower=os.path.join(ps[0], ps[1].lower())
if os.path.isdir(directory_lower): # already exists
shutil.copytree(directory, directory_lower, dirs_exist_ok=True)
shutil.rmtree(directory)
else:
os.rename(directory, directory_lower)
directory = directory_lower
for dir_ in os.listdir(directory):
if os.path.isdir(os.path.join(directory, dir_)):
tree_lower_subdirectories(
os.path.join(directory, dir_),
not modify_root and not modify_root or modify_root
)
I used it separately in the mods folder. Works as intended :)
The game glitches I observed are solved
PR should fix the issue, you can check that by verifying the content of mod 122
And content installation folder if you use usvfs-workaround
PR should fix the issue, you can check that by verifying the content of mod 122
Great you made that. Why do you not use or at least adapt my code, though? Not that I mind, but I'd like to know.
It has less dependencies, as you are already using shutil.
I prefer to avoid recursive function and using pathlib
instead of os
since it is used everywhere in this code
Okay, fair enough.