Skip to content

Commit ae9bc52

Browse files
Match SerializedFile names case-sensitively (#106)
The serialized-file id provider keyed names by their lowercased form, so cross-file reference resolution, scene-bundle keying and ContentLayout linkage were all case-insensitive. Record and match names using the case found on the file system / inside the archive instead: drop the ToLowerInvariant() at every serialized-file name key site (a file's own name, external reference paths, scene .sharedAssets names, m_SceneHashes scene files, and ContentLayout .cf hashes). This also makes dangling-ref stub names preserve the referenced case rather than lowercasing them. No schema change (serialized_files.name already stored the actual relative path). Full test suite green, confirming the test data has no case mismatch between references and the files they target.
1 parent fb41219 commit ae9bc52

4 files changed

Lines changed: 17 additions & 16 deletions

File tree

Analyzer/SQLite/Handlers/AssetBundleHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public void Process(Context ctx, long objectId, RandomAccessReader reader, out s
9898
// Scriptable Build Pipeline / Addressables: key the scene on its SerializedFile
9999
// (from m_SceneHashes) and create the synthetic Scene object here, since the writer
100100
// cannot recognise a "CAB-<hash>" scene file by name.
101-
var sceneFileId = ctx.SerializedFileIdProvider.GetId(sceneFile.ToLowerInvariant());
101+
var sceneFileId = ctx.SerializedFileIdProvider.GetId(sceneFile);
102102
var objId = ctx.ObjectIdProvider.GetId((sceneFileId, 0));
103103

104104
// The synthetic Scene object is inserted once (objects.id is a primary key), but the

Analyzer/SQLite/Writers/ContentLayoutSQLWriter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,11 @@ private void PopulateContentFileDependencies(ContentLayout layout)
203203

204204
var resolved = (file.SerializedFileDependencies ?? [])
205205
.Select(i => hashByIndex.TryGetValue(i, out var hash) && !string.IsNullOrEmpty(hash)
206-
? (hash + ".cf").ToLowerInvariant()
206+
? hash + ".cf"
207207
: null)
208208
.ToArray();
209209

210-
m_ContentFileDependencies.Add((file.ContentHash + ".cf").ToLowerInvariant(), resolved);
210+
m_ContentFileDependencies.Add(file.ContentHash + ".cf", resolved);
211211
}
212212
}
213213

@@ -246,7 +246,7 @@ public void LinkSerializedFiles()
246246
{
247247
foreach (var file in m_ImportedFiles)
248248
{
249-
var fileName = (file.ContentHash + ".cf").ToLowerInvariant();
249+
var fileName = file.ContentHash + ".cf";
250250
var id = m_SerializedFileIdProvider.GetId(fileName);
251251

252252
update.Parameters["@id"].Value = id;

Analyzer/SQLite/Writers/SerializedFileSQLiteWriter.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ public void WriteSerializedFile(string relativePath, string fullPath, string con
185185
using var sf = UnityFileSystem.OpenSerializedFile(fullPath);
186186
using var reader = new UnityFileReader(fullPath, 64 * 1024 * 1024);
187187
using var pptrReader = new PPtrAndCrcProcessor(sf, reader, containingFolder, m_SkipCrc, AddReference);
188-
int serializedFileId = m_SerializedFileIdProvider.GetId(Path.GetFileName(fullPath).ToLowerInvariant());
188+
int serializedFileId = m_SerializedFileIdProvider.GetId(Path.GetFileName(fullPath));
189189
int sceneId = -1;
190190

191191
// Two SerializedFiles with the same name map to the same id (the provider deduplicates by
@@ -244,7 +244,7 @@ public void WriteSerializedFile(string relativePath, string fullPath, string con
244244
// path -> file mapping from the AssetBundle object's m_SceneHashes.
245245
var fileName = Path.GetFileName(fullPath);
246246
var sceneFileName = fileName.Substring(0, fileName.Length - ".sharedAssets".Length);
247-
var sceneFileId = m_SerializedFileIdProvider.GetId(sceneFileName.ToLowerInvariant());
247+
var sceneFileId = m_SerializedFileIdProvider.GetId(sceneFileName);
248248
sceneId = m_ObjectIdProvider.GetId((sceneFileId, 0));
249249
}
250250

@@ -272,12 +272,13 @@ public void WriteSerializedFile(string relativePath, string fullPath, string con
272272

273273
// Local file id 0 is always this file itself; ids 1..N follow the order of the
274274
// external reference table. Resolve each external reference to its global file id
275-
// by (lowercased) file name. For ContentDirectory files the external table holds
276-
// symbolic placeholders, so when an imported ContentLayout covers this file the
277-
// actual target comes from its dependency list, matched by position; built-in
278-
// dependencies (null entries) keep the external table path.
275+
// by file name (matched case-sensitively, as it appears on disk / in the archive).
276+
// For ContentDirectory files the external table holds symbolic placeholders, so when
277+
// an imported ContentLayout covers this file the actual target comes from its
278+
// dependency list, matched by position; built-in dependencies (null entries) keep the
279+
// external table path.
279280
var resolvedDependencies = m_ContentFileDependencies.GetDependencies(
280-
Path.GetFileName(fullPath).ToLowerInvariant());
281+
Path.GetFileName(fullPath));
281282

282283
if (resolvedDependencies != null && resolvedDependencies.Length != sf.ExternalReferences.Count)
283284
{
@@ -292,7 +293,7 @@ public void WriteSerializedFile(string relativePath, string fullPath, string con
292293
foreach (var extRef in sf.ExternalReferences)
293294
{
294295
var name = resolvedDependencies?[localId - 1]
295-
?? extRef.Path.Substring(extRef.Path.LastIndexOf('/') + 1).ToLowerInvariant();
296+
?? extRef.Path.Substring(extRef.Path.LastIndexOf('/') + 1);
296297
m_LocalToDbFileId.Add(localId++, m_SerializedFileIdProvider.GetId(name));
297298
}
298299

Analyzer/Util/ContentFileDependencyMap.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ namespace UnityDataTools.Analyzer.Util;
66
// In ContentDirectory builds the external reference table inside a SerializedFile holds symbolic
77
// .cfid placeholders instead of real filenames; the actual target of a reference is determined
88
// positionally through the layout's dependency list (see Documentation/contentdirectory-format.md).
9-
// This map holds, for each content file (keyed by its lowercased "<contenthash>.cf" filename),
10-
// the resolved dependency filenames in external-reference-table order. An entry is null where the
9+
// This map holds, for each content file (keyed by its "<contenthash>.cf" filename), the resolved
10+
// dependency filenames in external-reference-table order. An entry is null where the
1111
// dependency is a built-in file (which has no content hash); such references fall back to the
1212
// path from the external reference table.
1313
public class ContentFileDependencyMap
@@ -19,8 +19,8 @@ public void Add(string fileName, string[] resolvedDependencies)
1919
m_Dependencies[fileName] = resolvedDependencies;
2020
}
2121

22-
// Returns the resolved dependency filenames for the given (lowercased) filename, or null if
23-
// the file is not covered by an imported ContentLayout.
22+
// Returns the resolved dependency filenames for the given filename, or null if the file is
23+
// not covered by an imported ContentLayout.
2424
public string[] GetDependencies(string fileName)
2525
{
2626
return m_Dependencies.TryGetValue(fileName, out var dependencies) ? dependencies : null;

0 commit comments

Comments
 (0)