@joebigelow / wix / commits / 28a2c0e9

Magicked files in modules need complex references.

Magic files (naked `File`s and `Files`) that are direct children of a `Module` need complex references from the generated component to that module, to ensure that they're wired up correctly as module components. Fixes https://github.com/wixtoolset/issues/issues/8860

Bob Arnson committed Dec 22, 2024 at 22:44 UTC 28a2c0e963897ddc61e6673bcb93e10b9696375f
5 files changed +64 -10
src/api/wix/WixToolset.Data/Symbols/HarvestFilesSymbol.cs
+8
@@ -16,6 +16,7 @@ namespace WixToolset.Data
16 new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.ComplexReferenceParentType), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.ParentId), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.SourcePath), IntermediateFieldType.String),
19 + new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.ModuleLanguage), IntermediateFieldType.String),
20 },
21 typeof(HarvestFilesSymbol));
22 }
@@ -31,6 +32,7 @@ namespace WixToolset.Data.Symbols
32 ComplexReferenceParentType,
33 ParentId,
34 SourcePath,
35 + ModuleLanguage,
36 }
37
38 public class HarvestFilesSymbol : IntermediateSymbol
@@ -80,5 +82,11 @@ namespace WixToolset.Data.Symbols
82 get => (string)this.Fields[(int)HarvestFilesSymbolFields.SourcePath];
83 set => this.Set((int)HarvestFilesSymbolFields.SourcePath, value);
84 }
85 +
86 + public string ModuleLanguage
87 + {
88 + get => (string)this.Fields[(int)HarvestFilesSymbolFields.ModuleLanguage];
89 + set => this.Set((int)HarvestFilesSymbolFields.ModuleLanguage, value);
90 + }
91 }
92 }
src/wix/WixToolset.Core/Compiler.cs
+7 -1
@@ -5689,7 +5689,12 @@ namespace WixToolset.Core
5689
5690 this.ParseFileElementChildren(node, fileSymbol, keyPath, win64);
5691
5692 - if (ComplexReferenceParentType.Unknown != parentType && null != parentId) // if parent was provided, add a complex reference to that.
5692 + // if this is a module, automatically add this component to the references to ensure it gets in the ModuleComponents table
5693 + if (this.compilingModule)
5694 + {
5695 + this.Core.CreateComplexReference(sourceLineNumbers, ComplexReferenceParentType.Module, this.activeName, this.activeLanguage, ComplexReferenceChildType.Component, fileSymbol.Id.Id, false);
5696 + }
5697 + else if (ComplexReferenceParentType.Unknown != parentType && null != parentId) // if parent was provided, add a complex reference to that.
5698 {
5699 // If the naked file's component is defined directly under a feature, then mark the complex reference primary.
5700 this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.Component, fileSymbol.Id.Id, ComplexReferenceParentType.Feature == parentType);
@@ -5790,6 +5795,7 @@ namespace WixToolset.Core
5795 ComplexReferenceParentType = parentType.ToString(),
5796 ParentId = parentId,
5797 SourcePath = sourcePath,
5798 + ModuleLanguage = this.compilingModule ? this.activeLanguage : null,
5799 });
5800 }
5801
src/wix/WixToolset.Core/HarvestFilesCommand.cs
+7 -2
@@ -107,10 +107,15 @@ namespace WixToolset.Core
107 Win64 = this.Context.Platform == Platform.ARM64 || this.Context.Platform == Platform.X64,
108 });
109
110 - if (Enum.TryParse<ComplexReferenceParentType>(harvestFile.ComplexReferenceParentType, out var parentType)
110 + // if this is a module, automatically add this component to the references to ensure it gets in the ModuleComponents table
111 + if (!String.IsNullOrEmpty(harvestFile.ModuleLanguage))
112 + {
113 + this.ParseHelper.CreateComplexReference(section, harvestFile.SourceLineNumbers, ComplexReferenceParentType.Module, harvestFile.ParentId, harvestFile.ModuleLanguage, ComplexReferenceChildType.Component, id.Id, false);
114 + }
115 + else if (Enum.TryParse<ComplexReferenceParentType>(harvestFile.ComplexReferenceParentType, out var parentType)
116 && ComplexReferenceParentType.Unknown != parentType && null != harvestFile.ParentId)
117 {
113 - // If the parent was provided, add a complex reference to that, and, if
118 + // If the parent was provided, add a complex reference to that, and, if
119 // the Files is under a feature, then mark the complex reference primary.
120 this.ParseHelper.CreateComplexReference(section, harvestFile.SourceLineNumbers, parentType, harvestFile.ParentId, null, ComplexReferenceChildType.Component, id.Id, ComplexReferenceParentType.Feature == parentType);
121 }
src/wix/test/WixToolsetTest.CoreIntegration/HarvestFilesFixture.cs
+25 -6
@@ -9,6 +9,7 @@ namespace WixToolsetTest.CoreIntegration
9 using System.Linq;
10 using WixInternal.Core.TestPackage;
11 using WixInternal.TestSupport;
12 + using WixToolset.Data.WindowsInstaller;
13 using Xunit;
14
15 public class HarvestFilesFixture
@@ -225,16 +226,34 @@ namespace WixToolsetTest.CoreIntegration
226 [Fact]
227 public void CanHarvestFilesInModules()
228 {
228 - var expected = new[]
229 + var expectedFilesAndTargetPaths = new[]
230 {
230 - @"flsgrgAVAsCQ8tCCxfnbBNis66623c.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test1.txt",
231 + @"flsBvxG729t7hKBa4KOmfvNMPptZkM.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test4.txt",
232 @"flsDBWSWjpVSU3Zs33bREsJa2ygSQM.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test2.txt",
233 @"flsehdwEdXusUijRShuTszSxwf8joA.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test3.txt",
233 - @"flsBvxG729t7hKBa4KOmfvNMPptZkM.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test4.txt",
234 + @"flsgrgAVAsCQ8tCCxfnbBNis66623c.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test1.txt",
235 @"flskqOUVMfAE13k2h.ZkPhurwO4Y1c.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\notatest.txt",
236 };
237
237 - Build("Module.wxs", (msiPath, _) => AssertFileIdsAndTargetPaths(msiPath, expected), isPackage: false);
238 + var expectedModuleComponents = new[]
239 + {
240 + "ModuleComponents:flsBvxG729t7hKBa4KOmfvNMPptZkM.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
241 + "ModuleComponents:flsDBWSWjpVSU3Zs33bREsJa2ygSQM.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
242 + "ModuleComponents:flsehdwEdXusUijRShuTszSxwf8joA.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
243 + "ModuleComponents:flsgrgAVAsCQ8tCCxfnbBNis66623c.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
244 + "ModuleComponents:flskqOUVMfAE13k2h.ZkPhurwO4Y1c.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
245 + };
246 +
247 + Build("Module.wxs", (msiPath, _) => AssertModuleComponentsFileIdsAndTargetPaths(msiPath, expectedFilesAndTargetPaths, expectedModuleComponents), isMsi: false);
248 +
249 + static void AssertModuleComponentsFileIdsAndTargetPaths(string msiPath, string[] expectedFilesAndTargetPaths, string[] expectedModuleComponents)
250 + {
251 + AssertFileIdsAndTargetPaths(msiPath, expectedFilesAndTargetPaths);
252 +
253 + var query = Query.QueryDatabase(msiPath, new[] { "ModuleComponents" });
254 +
255 + Assert.Equal(expectedModuleComponents, query);
256 + }
257 }
258
259 [Fact]
@@ -346,7 +365,7 @@ namespace WixToolsetTest.CoreIntegration
365 Assert.Equal(sortedExpected, actual);
366 }
367
349 - private static void Build(string file, Action<string, WixRunnerResult> tester, bool isPackage = true, bool warningsAsErrors = true, bool addUnnamedBindPath = false, params string[] additionalCommandLineArguments)
368 + private static void Build(string file, Action<string, WixRunnerResult> tester, bool isMsi = true, bool warningsAsErrors = true, bool addUnnamedBindPath = false, params string[] additionalCommandLineArguments)
369 {
370 var folder = TestData.Get("TestData", "HarvestFiles");
371
@@ -355,7 +374,7 @@ namespace WixToolsetTest.CoreIntegration
374 var baseFolder = fs.GetFolder();
375 var intermediateFolder = Path.Combine(baseFolder, "obj");
376 var binFolder = Path.Combine(baseFolder, "bin");
358 - var msiPath = Path.Combine(binFolder, isPackage ? "test.msi" : "test.msm");
377 + var msiPath = Path.Combine(binFolder, isMsi ? "test.msi" : "test.msm");
378
379 var arguments = new List<string>()
380 {
src/wix/test/WixToolsetTest.CoreIntegration/NakedFileFixture.cs
+17 -1
@@ -2,6 +2,7 @@
2
3 namespace WixToolsetTest.CoreIntegration
4 {
5 + using System.Collections.Generic;
6 using System.Data;
7 using System.IO;
8 using System.Linq;
@@ -82,6 +83,14 @@ namespace WixToolsetTest.CoreIntegration
83 var rows = BuildAndQueryComponentAndFileTables("Module.wxs", isPackage: false);
84
85 AssertFileComponentIds(2, rows);
86 +
87 + var expectedModuleComponents = new[]
88 + {
89 + "ModuleComponents:FILE1.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
90 + "ModuleComponents:FILE2.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
91 + };
92 +
93 + Assert.Equal(expectedModuleComponents, rows.Where(row => row.StartsWith("ModuleComponents:")));
94 }
95
96 [Fact]
@@ -215,7 +224,14 @@ namespace WixToolsetTest.CoreIntegration
224 {
225 result.AssertSuccess();
226
218 - return Query.QueryDatabase(msiPath, new[] { "Component", "File" })
227 + var tables = new List<string> { "Component", "File" };
228 +
229 + if (!isPackage)
230 + {
231 + tables.Add("ModuleComponents");
232 + }
233 +
234 + return Query.QueryDatabase(msiPath, tables.ToArray())
235 .OrderBy(s => s)
236 .ToArray();
237 }