Skip to content

Commit 289ec62

Browse files
sparrK0lb3
andauthored
Handle relative and case insensitive file paths (#191)
* Handle relative and case insensitive file paths * improve find_sensitive_path (no recursion) * environment.py - look in self.path instead of cwd * fix files.File import error for type hinting * Update environment.py --------- Co-authored-by: Rudolf Kolbe <[email protected]>
1 parent 63bfcc3 commit 289ec62

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

UnityPy/environment.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,16 @@ def load_file(
107107
file = b"".join(file)
108108
else:
109109
name = file
110+
if not os.path.exists(file):
111+
# relative paths are in the asset directory, not the cwd
112+
if not os.path.isabs(file):
113+
file = os.path.join(self.path, file)
114+
# Unity paths are case insensitive, so we need to find "Resources/Foo.asset" when the record says "resources/foo.asset"
115+
if not os.path.exists(file):
116+
file = ImportHelper.find_sensitive_path(self.path, file)
117+
# nonexistent files might be packaging errors or references to Unity's global Library/
118+
if file is None:
119+
return
110120
file = self.fs.open(file, "rb")
111121

112122
typ, reader = ImportHelper.check_file_type(file)
@@ -155,7 +165,7 @@ def save(self, pack="none", out_path="output"):
155165
for fname, fitem in self.files.items():
156166
if getattr(fitem, "is_changed", False):
157167
with open(
158-
self.fs.sep.join([out_path, ntpath.basename(f)]), "wb"
168+
self.fs.sep.join([out_path, ntpath.basename(fname)]), "wb"
159169
) as out:
160170
out.write(fitem.save(packer=pack))
161171

UnityPy/helpers/ImportHelper.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import os
1+
from __future__ import annotations
2+
import os
23
from typing import Union, List
34
from .CompressionHelper import BROTLI_MAGIC, GZIP_MAGIC
45
from ..enums import FileType
@@ -127,7 +128,7 @@ def parse_file(
127128
name: str,
128129
typ: FileType = None,
129130
is_dependency=False,
130-
):
131+
) -> Union[files.File, EndianBinaryReader]:
131132
if typ is None:
132133
typ, _ = check_file_type(reader)
133134
if typ == FileType.AssetsFile and not name.endswith(
@@ -141,3 +142,20 @@ def parse_file(
141142
else:
142143
f = reader
143144
return f
145+
146+
147+
def find_sensitive_path(dir: str, insensitive_path: str) -> Union[str, None]:
148+
parts = os.path.split(insensitive_path.strip(os.path.sep))
149+
150+
senstive_path = dir
151+
for part in parts:
152+
part_lower = part.lower()
153+
part = next(
154+
(name for name in os.listdir(senstive_path) if name.lower() == part_lower),
155+
None,
156+
)
157+
if next is None:
158+
return None
159+
senstive_path = os.path.join(senstive_path, part)
160+
161+
return senstive_path

0 commit comments

Comments
 (0)