From 4e2d7f2550b05e410735f51beac76ed040178cf4 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 1 Apr 2022 23:42:37 -0400 Subject: make mod file paths case-insensitive in all SMAPI APIs --- src/SMAPI/Framework/ContentPack.cs | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) (limited to 'src/SMAPI/Framework/ContentPack.cs') diff --git a/src/SMAPI/Framework/ContentPack.cs b/src/SMAPI/Framework/ContentPack.cs index 3920354e..e02ef88b 100644 --- a/src/SMAPI/Framework/ContentPack.cs +++ b/src/SMAPI/Framework/ContentPack.cs @@ -1,9 +1,8 @@ using System; -using System.Collections.Generic; using System.IO; using StardewModdingAPI.Framework.ModHelpers; using StardewModdingAPI.Toolkit.Serialization; -using StardewModdingAPI.Toolkit.Utilities; +using StardewModdingAPI.Utilities; namespace StardewModdingAPI.Framework { @@ -16,8 +15,8 @@ namespace StardewModdingAPI.Framework /// Encapsulates SMAPI's JSON file parsing. private readonly JsonHelper JsonHelper; - /// A cache of case-insensitive => exact relative paths within the content pack, for case-insensitive file lookups on Linux/macOS. - private readonly IDictionary RelativePaths = new Dictionary(StringComparer.OrdinalIgnoreCase); + /// A case-insensitive lookup of relative paths within the . + private readonly CaseInsensitivePathCache RelativePathCache; /********* @@ -48,19 +47,15 @@ namespace StardewModdingAPI.Framework /// Provides an API for loading content assets from the content pack's folder. /// Provides translations stored in the content pack's i18n folder. /// Encapsulates SMAPI's JSON file parsing. - public ContentPack(string directoryPath, IManifest manifest, IModContentHelper content, TranslationHelper translation, JsonHelper jsonHelper) + /// A case-insensitive lookup of relative paths within the . + public ContentPack(string directoryPath, IManifest manifest, IModContentHelper content, TranslationHelper translation, JsonHelper jsonHelper, CaseInsensitivePathCache relativePathCache) { this.DirectoryPath = directoryPath; this.Manifest = manifest; this.ModContent = content; this.TranslationImpl = translation; this.JsonHelper = jsonHelper; - - foreach (string path in Directory.EnumerateFiles(this.DirectoryPath, "*", SearchOption.AllDirectories)) - { - string relativePath = path.Substring(this.DirectoryPath.Length + 1); - this.RelativePaths[relativePath] = relativePath; - } + this.RelativePathCache = relativePathCache; } /// @@ -90,8 +85,7 @@ namespace StardewModdingAPI.Framework FileInfo file = this.GetFile(path, out path); this.JsonHelper.WriteJsonFile(file.FullName, data); - if (!this.RelativePaths.ContainsKey(path)) - this.RelativePaths[path] = path; + this.RelativePathCache.Add(path); } /// @@ -112,18 +106,6 @@ namespace StardewModdingAPI.Framework /********* ** Private methods *********/ - /// Get the real relative path from a case-insensitive path. - /// The normalized relative path. - private string GetCaseInsensitiveRelativePath(string relativePath) - { - if (!PathUtilities.IsSafeRelativePath(relativePath)) - throw new InvalidOperationException($"You must call {nameof(IContentPack)} methods with a relative path."); - - return !string.IsNullOrWhiteSpace(relativePath) && this.RelativePaths.TryGetValue(relativePath, out string caseInsensitivePath) - ? caseInsensitivePath - : relativePath; - } - /// Get the underlying file info. /// The normalized file path relative to the content pack directory. private FileInfo GetFile(string relativePath) @@ -136,7 +118,11 @@ namespace StardewModdingAPI.Framework /// The relative path after case-insensitive matching. private FileInfo GetFile(string relativePath, out string actualRelativePath) { - actualRelativePath = this.GetCaseInsensitiveRelativePath(relativePath); + if (!PathUtilities.IsSafeRelativePath(relativePath)) + throw new InvalidOperationException($"You must call {nameof(IContentPack)} methods with a relative path."); + + actualRelativePath = this.RelativePathCache.GetFilePath(relativePath); + return new FileInfo(Path.Combine(this.DirectoryPath, actualRelativePath)); } } -- cgit