From f8d3bc99ba25dbb5ca4a8e8a6931e30fde63179d Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Thu, 29 Jan 2026 10:43:32 -0800 Subject: [PATCH] Use case insensitive compares for paths during harvesting Fixes 9213 --- .../HarvestFilesAndPayloadsCommand.cs | 9 ++++--- .../HarvestFilesFixture.cs | 27 +++++++++++++++++++ .../CaseInsensitiveExcludeSubdir.wxs | 11 ++++++++ .../CaseInsensitiveIncludeExclude.wxs | 11 ++++++++ 4 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/HarvestFiles/CaseInsensitiveExcludeSubdir.wxs create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/HarvestFiles/CaseInsensitiveIncludeExclude.wxs diff --git a/src/wix/WixToolset.Core/HarvestFilesAndPayloadsCommand.cs b/src/wix/WixToolset.Core/HarvestFilesAndPayloadsCommand.cs index b8265bc15..3746f8647 100644 --- a/src/wix/WixToolset.Core/HarvestFilesAndPayloadsCommand.cs +++ b/src/wix/WixToolset.Core/HarvestFilesAndPayloadsCommand.cs @@ -14,6 +14,7 @@ namespace WixToolset.Core internal class HarvestFilesAndPayloadsCommand { private const string BindPathOpenString = "!(bindpath."; + private static readonly char[] SplitSemicolons = { ';' }; public HarvestFilesAndPayloadsCommand(IOptimizeContext context) { @@ -54,8 +55,8 @@ private void HarvestFiles(HarvestFilesSymbol harvestFile, IntermediateSection se { var unusedSectionCachedInlinedDirectoryIds = new Dictionary(); - var inclusions = harvestFile.Inclusions.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - var exclusions = harvestFile.Exclusions.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + var inclusions = harvestFile.Inclusions.Split(SplitSemicolons, StringSplitOptions.RemoveEmptyEntries); + var exclusions = harvestFile.Exclusions.Split(SplitSemicolons, StringSplitOptions.RemoveEmptyEntries); var comparer = new WildcardFileComparer(); @@ -312,12 +313,12 @@ private class WildcardFileComparer : IEqualityComparer { public bool Equals(WildcardFile x, WildcardFile y) { - return x?.Path == y?.Path; + return StringComparer.OrdinalIgnoreCase.Equals(x?.Path, y?.Path); } public int GetHashCode(WildcardFile obj) { - return obj?.Path?.GetHashCode() ?? 0; + return obj?.Path is null ? 0 : StringComparer.OrdinalIgnoreCase.GetHashCode(obj.Path); } } } diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/HarvestFilesFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/HarvestFilesFixture.cs index 4d7253b8d..9efae1155 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/HarvestFilesFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/HarvestFilesFixture.cs @@ -142,6 +142,33 @@ public void CanHarvestFilesInDirectory() Build("Directory.wxs", (msiPath, _) => AssertFileIdsAndTargetPaths(msiPath, expected)); } + [Fact] + public void CanHarvestFilesWithCaseInsensitiveExcludeSubdirectory() + { + var expected = new[] + { + @"flsYgiwrDUkZnBEK6iUMkxxaJlD8yQ=PFiles\MsiPackage\test1.txt", + @"flslrDWblm4pE.4i4jR58_XyYMmR8I=PFiles\MsiPackage\files1_sub1\files1_sub2\test120.txt", + @"flsj.cb0sFWqIPHPFSKJSEEaPDuAQ4=PFiles\MsiPackage\test2.txt", + }; + + Build("CaseInsensitiveExcludeSubdir.wxs", (msiPath, _) => AssertFileIdsAndTargetPaths(msiPath, expected)); + } + + [Fact] + public void CanHarvestFilesWithCaseInsensitiveIncludeExclude() + { + var expected = new[] + { + @"flsaFu0CvigRX6Psea0ic6ZWevzLmI=PFiles\MsiPackage\test3.txt", + @"flsJBy_HKCNejalUyud4HisGqhd72E=PFiles\MsiPackage\test4.txt", + @"fls05.yw49T0FVAq3Wvq2ihNp3KWfI=PFiles\MsiPackage\files2_sub2\test20.txt", + @"flsf0falU_gCTJjtbSCNiFpJQ1d8EM=PFiles\MsiPackage\files2_sub2\test21.txt", + }; + + Build("CaseInsensitiveIncludeExclude.wxs", (msiPath, _) => AssertFileIdsAndTargetPaths(msiPath, expected)); + } + [Fact] public void CanHarvestFilesInDirectoryRef() { diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/HarvestFiles/CaseInsensitiveExcludeSubdir.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/HarvestFiles/CaseInsensitiveExcludeSubdir.wxs new file mode 100644 index 000000000..7bb47429e --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/HarvestFiles/CaseInsensitiveExcludeSubdir.wxs @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/HarvestFiles/CaseInsensitiveIncludeExclude.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/HarvestFiles/CaseInsensitiveIncludeExclude.wxs new file mode 100644 index 000000000..6a7038251 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/HarvestFiles/CaseInsensitiveIncludeExclude.wxs @@ -0,0 +1,11 @@ + + + + + + + + + + +