@joebigelow / wix-1 / commits / a6013a64

Refactor payload compiling and harvesting.

Sean Hall committed Feb 28, 2021 at 21:04 UTC a6013a643208a8d1fc2d1136ef8d3a6c3e909522
8 files changed +546 -343
src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+6 -2
@@ -11,6 +11,7 @@ namespace WixToolset.Core.Burn
11 using WixToolset.Core.Bind;
12 using WixToolset.Core.Burn.Bind;
13 using WixToolset.Core.Burn.Bundles;
14 + using WixToolset.Core.Burn.Interfaces;
15 using WixToolset.Data;
16 using WixToolset.Data.Burn;
17 using WixToolset.Data.Symbols;
@@ -31,6 +32,7 @@ namespace WixToolset.Core.Burn
32
33 this.BackendHelper = context.ServiceProvider.GetService<IBackendHelper>();
34 this.InternalBurnBackendHelper = context.ServiceProvider.GetService<IInternalBurnBackendHelper>();
35 + this.PayloadHarvester = context.ServiceProvider.GetService<IPayloadHarvester>();
36
37 this.DefaultCompressionLevel = context.DefaultCompressionLevel;
38 this.DelayedFields = context.DelayedFields;
@@ -52,6 +54,8 @@ namespace WixToolset.Core.Burn
54
55 private IInternalBurnBackendHelper InternalBurnBackendHelper { get; }
56
57 + private IPayloadHarvester PayloadHarvester { get; }
58 +
59 private CompressionLevel? DefaultCompressionLevel { get; }
60
61 public IEnumerable<IDelayedField> DelayedFields { get; }
@@ -165,7 +169,7 @@ namespace WixToolset.Core.Burn
169 // Process the explicitly authored payloads.
170 ISet<string> processedPayloads;
171 {
168 - var command = new ProcessPayloadsCommand(this.ServiceProvider, this.BackendHelper, payloadSymbols.Values, bundleSymbol.DefaultPackagingType, layoutDirectory);
172 + var command = new ProcessPayloadsCommand(this.ServiceProvider, this.BackendHelper, this.PayloadHarvester, payloadSymbols.Values, bundleSymbol.DefaultPackagingType, layoutDirectory);
173 command.Execute();
174
175 fileTransfers.AddRange(command.FileTransfers);
@@ -247,7 +251,7 @@ namespace WixToolset.Core.Burn
251 {
252 var toProcess = payloadSymbols.Values.Where(r => !processedPayloads.Contains(r.Id.Id)).ToList();
253
250 - var command = new ProcessPayloadsCommand(this.ServiceProvider, this.BackendHelper, toProcess, bundleSymbol.DefaultPackagingType, layoutDirectory);
254 + var command = new ProcessPayloadsCommand(this.ServiceProvider, this.BackendHelper, this.PayloadHarvester, toProcess, bundleSymbol.DefaultPackagingType, layoutDirectory);
255 command.Execute();
256
257 fileTransfers.AddRange(command.FileTransfers);
src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs
+6 -43
@@ -6,6 +6,7 @@ namespace WixToolset.Core.Burn.Bundles
6 using System.Collections.Generic;
7 using System.Diagnostics;
8 using System.IO;
9 + using WixToolset.Core.Burn.Interfaces;
10 using WixToolset.Data;
11 using WixToolset.Data.Burn;
12 using WixToolset.Data.Symbols;
@@ -14,13 +15,12 @@ namespace WixToolset.Core.Burn.Bundles
15
16 internal class ProcessPayloadsCommand
17 {
17 - private static readonly Version EmptyVersion = new Version(0, 0, 0, 0);
18 -
19 - public ProcessPayloadsCommand(IWixToolsetServiceProvider serviceProvider, IBackendHelper backendHelper, IEnumerable<WixBundlePayloadSymbol> payloads, PackagingType defaultPackaging, string layoutDirectory)
18 + public ProcessPayloadsCommand(IWixToolsetServiceProvider serviceProvider, IBackendHelper backendHelper, IPayloadHarvester payloadHarvester, IEnumerable<WixBundlePayloadSymbol> payloads, PackagingType defaultPackaging, string layoutDirectory)
19 {
20 this.Messaging = serviceProvider.GetService<IMessaging>();
21
22 this.BackendHelper = backendHelper;
23 + this.PayloadHarvester = payloadHarvester;
24 this.Payloads = payloads;
25 this.DefaultPackaging = defaultPackaging;
26 this.LayoutDirectory = layoutDirectory;
@@ -34,6 +34,8 @@ namespace WixToolset.Core.Burn.Bundles
34
35 private IBackendHelper BackendHelper { get; }
36
37 + private IPayloadHarvester PayloadHarvester { get; }
38 +
39 private IEnumerable<WixBundlePayloadSymbol> Payloads { get; }
40
41 private PackagingType DefaultPackaging { get; }
@@ -56,17 +58,13 @@ namespace WixToolset.Core.Burn.Bundles
58
59 this.UpdatePayloadPackagingType(payload);
60
59 - if (String.IsNullOrEmpty(sourceFile?.Path))
61 + if (!this.PayloadHarvester.HarvestStandardInformation(payload))
62 {
63 // Remote payloads obviously cannot be embedded.
64 Debug.Assert(PackagingType.Embedded != payload.Packaging);
65 }
66 else // not a remote payload so we have a lot more to update.
67 {
66 - this.UpdatePayloadFileInformation(payload, sourceFile);
67 -
68 - this.UpdatePayloadVersionInformation(payload, sourceFile);
69 -
68 // External payloads need to be transfered.
69 if (PackagingType.External == payload.Packaging)
70 {
@@ -110,40 +108,5 @@ namespace WixToolset.Core.Burn.Bundles
108 payload.ContainerRef = BurnConstants.BurnDefaultAttachedContainerName;
109 }
110 }
113 -
114 - private void UpdatePayloadFileInformation(WixBundlePayloadSymbol payload, IntermediateFieldPathValue sourceFile)
115 - {
116 - var fileInfo = new FileInfo(sourceFile.Path);
117 -
118 - if (null != fileInfo)
119 - {
120 - payload.FileSize = fileInfo.Length;
121 -
122 - payload.Hash = BundleHashAlgorithm.Hash(fileInfo);
123 - }
124 - else
125 - {
126 - payload.FileSize = 0;
127 - }
128 - }
129 -
130 - private void UpdatePayloadVersionInformation(WixBundlePayloadSymbol payload, IntermediateFieldPathValue sourceFile)
131 - {
132 - var versionInfo = FileVersionInfo.GetVersionInfo(sourceFile.Path);
133 -
134 - if (null != versionInfo)
135 - {
136 - // Use the fixed version info block for the file since the resource text may not be a dotted quad.
137 - var version = new Version(versionInfo.ProductMajorPart, versionInfo.ProductMinorPart, versionInfo.ProductBuildPart, versionInfo.ProductPrivatePart);
138 -
139 - if (ProcessPayloadsCommand.EmptyVersion != version)
140 - {
141 - payload.Version = version.ToString();
142 - }
143 -
144 - payload.Description = versionInfo.FileDescription;
145 - payload.DisplayName = versionInfo.ProductName;
146 - }
147 - }
111 }
112 }
src/WixToolset.Core.Burn/ExtensibilityServices/PayloadHarvester.cs new
+68
@@ -0,0 +1,68 @@
1 +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2 +
3 +namespace WixToolset.Core.Burn.ExtensibilityServices
4 +{
5 + using System;
6 + using System.Diagnostics;
7 + using System.IO;
8 + using WixToolset.Core.Burn.Bundles;
9 + using WixToolset.Core.Burn.Interfaces;
10 + using WixToolset.Data.Symbols;
11 +
12 + internal class PayloadHarvester : IPayloadHarvester
13 + {
14 + private static readonly Version EmptyVersion = new Version(0, 0, 0, 0);
15 +
16 + /// <inheritdoc />
17 + public bool HarvestStandardInformation(WixBundlePayloadSymbol payload)
18 + {
19 + var filePath = payload.SourceFile?.Path;
20 +
21 + if (String.IsNullOrEmpty(filePath))
22 + {
23 + return false;
24 + }
25 +
26 + this.UpdatePayloadFileInformation(payload, filePath);
27 +
28 + this.UpdatePayloadVersionInformation(payload, filePath);
29 +
30 + return true;
31 + }
32 +
33 + private void UpdatePayloadFileInformation(WixBundlePayloadSymbol payload, string filePath)
34 + {
35 + var fileInfo = new FileInfo(filePath);
36 +
37 + if (null != fileInfo)
38 + {
39 + payload.FileSize = fileInfo.Length;
40 +
41 + payload.Hash = BundleHashAlgorithm.Hash(fileInfo);
42 + }
43 + else
44 + {
45 + payload.FileSize = 0;
46 + }
47 + }
48 +
49 + private void UpdatePayloadVersionInformation(WixBundlePayloadSymbol payload, string filePath)
50 + {
51 + var versionInfo = FileVersionInfo.GetVersionInfo(filePath);
52 +
53 + if (null != versionInfo)
54 + {
55 + // Use the fixed version info block for the file since the resource text may not be a dotted quad.
56 + var version = new Version(versionInfo.ProductMajorPart, versionInfo.ProductMinorPart, versionInfo.ProductBuildPart, versionInfo.ProductPrivatePart);
57 +
58 + if (PayloadHarvester.EmptyVersion != version)
59 + {
60 + payload.Version = version.ToString();
61 + }
62 +
63 + payload.Description = versionInfo.FileDescription;
64 + payload.DisplayName = versionInfo.ProductName;
65 + }
66 + }
67 + }
68 +}
src/WixToolset.Core.Burn/Interfaces/IPayloadHarvester.cs new
+23
@@ -0,0 +1,23 @@
1 +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2 +
3 +namespace WixToolset.Core.Burn.Interfaces
4 +{
5 + using System.Diagnostics;
6 + using WixToolset.Data.Symbols;
7 +
8 + /// <summary>
9 + /// Service for harvesting payload information.
10 + /// </summary>
11 + public interface IPayloadHarvester
12 + {
13 + /// <summary>
14 + /// Uses <see cref="WixBundlePayloadSymbol.SourceFile"/> to:
15 + /// update <see cref="WixBundlePayloadSymbol.Hash"/> from file contents,
16 + /// update <see cref="WixBundlePayloadSymbol.FileSize"/> from file size, and
17 + /// update <see cref="WixBundlePayloadSymbol.Description"/>, <see cref="WixBundlePayloadSymbol.DisplayName"/>, and <see cref="WixBundlePayloadSymbol.Version"/> from <see cref="FileVersionInfo"/>.
18 + /// </summary>
19 + /// <param name="payload">The symbol to update.</param>
20 + /// <returns>Whether the symbol had a source file specified.</returns>
21 + bool HarvestStandardInformation(WixBundlePayloadSymbol payload);
22 + }
23 +}
src/WixToolset.Core.Burn/WixToolsetCoreServiceProviderExtensions.cs
+2
@@ -5,6 +5,7 @@ namespace WixToolset.Core.Burn
5 using System;
6 using System.Collections.Generic;
7 using WixToolset.Core.Burn.ExtensibilityServices;
8 + using WixToolset.Core.Burn.Interfaces;
9 using WixToolset.Extensibility.Services;
10
11 /// <summary>
@@ -31,6 +32,7 @@ namespace WixToolset.Core.Burn
32 {
33 // Singletons.
34 coreProvider.AddService((provider, singletons) => AddSingleton<IInternalBurnBackendHelper>(singletons, new BurnBackendHelper(provider)));
35 + coreProvider.AddService((provider, singletons) => AddSingleton<IPayloadHarvester>(singletons, new PayloadHarvester()));
36 coreProvider.AddService((provider, singletons) => AddSingleton<IBurnBackendHelper>(singletons, provider.GetService<IInternalBurnBackendHelper>()));
37 }
38
src/WixToolset.Core/Compile/CompilerPayload.cs new
+247
@@ -0,0 +1,247 @@
1 +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2 +
3 +namespace WixToolset.Core
4 +{
5 + using System;
6 + using System.IO;
7 + using System.Xml.Linq;
8 + using WixToolset.Data;
9 + using WixToolset.Data.Burn;
10 + using WixToolset.Data.Symbols;
11 +
12 + internal class CompilerPayload
13 + {
14 + public YesNoDefaultType Compressed { get; set; } = YesNoDefaultType.Default;
15 +
16 + public string Description { get; set; }
17 +
18 + public string DisplayName { get; set; }
19 +
20 + public string DownloadUrl { get; set; }
21 +
22 + public string Hash { get; set; }
23 +
24 + public Identifier Id { get; set; }
25 +
26 + public bool IsRequired { get; set; } = true;
27 +
28 + public string Name { get; set; }
29 +
30 + public string ProductName { get; set; }
31 +
32 + public long? Size { get; set; }
33 +
34 + public string SourceFile { get; set; }
35 +
36 + public string Version { get; set; }
37 +
38 + public CompilerPayload(CompilerCore core, SourceLineNumber sourceLineNumbers, XElement element)
39 + {
40 + this.Core = core;
41 + this.Element = element;
42 + this.SourceLineNumbers = sourceLineNumbers;
43 + }
44 +
45 + private CompilerCore Core { get; }
46 +
47 + private XElement Element { get; }
48 +
49 + private SourceLineNumber SourceLineNumbers { get; }
50 +
51 + private void CalculateAndVerifyFields(CompilerPayload remotePayload = null)
52 + {
53 + if (String.IsNullOrEmpty(this.SourceFile))
54 + {
55 + if (String.IsNullOrEmpty(this.Name))
56 + {
57 + if (this.IsRequired)
58 + {
59 + this.Core.Write(ErrorMessages.ExpectedAttributesWithOtherAttribute(this.SourceLineNumbers, this.Element.Name.LocalName, "Name", "SourceFile"));
60 + }
61 + }
62 + else if (remotePayload == null)
63 + {
64 + this.SourceFile = Path.Combine("SourceDir", this.Name);
65 + }
66 + }
67 + else if (remotePayload != null)
68 + {
69 + this.Core.Write(ErrorMessages.UnexpectedElementWithAttribute(this.SourceLineNumbers, this.Element.Name.LocalName, "RemotePayload", "SourceFile"));
70 + }
71 + else if (this.SourceFile.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
72 + {
73 + if (String.IsNullOrEmpty(this.Name))
74 + {
75 + this.Core.Write(ErrorMessages.ExpectedAttribute(this.SourceLineNumbers, this.Element.Name.LocalName, "Name", "SourceFile", this.SourceFile));
76 + }
77 + else
78 + {
79 + this.SourceFile = Path.Combine(this.SourceFile, Path.GetFileName(this.Name));
80 + }
81 + }
82 +
83 + if (remotePayload != null)
84 + {
85 + if (this.DownloadUrl == null)
86 + {
87 + this.Core.Write(ErrorMessages.ExpectedAttributeWithElement(this.SourceLineNumbers, this.Element.Name.LocalName, "DownloadUrl", "RemotePayload"));
88 + }
89 +
90 + if (YesNoDefaultType.No != this.Compressed)
91 + {
92 + this.Compressed = YesNoDefaultType.No;
93 + this.Core.Write(WarningMessages.RemotePayloadsMustNotAlsoBeCompressed(this.SourceLineNumbers, this.Element.Name.LocalName));
94 + }
95 +
96 + this.Description = remotePayload.Description;
97 + this.DisplayName = remotePayload.DisplayName;
98 + this.Hash = remotePayload.Hash;
99 + this.Size = remotePayload.Size;
100 + this.Version = remotePayload.Version;
101 + }
102 + }
103 +
104 + public WixBundlePayloadSymbol CreatePayloadSymbol(ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType = ComplexReferenceChildType.Unknown, string previousId = null)
105 + {
106 + WixBundlePayloadSymbol symbol = null;
107 +
108 + if (parentType == ComplexReferenceParentType.Container && parentId == BurnConstants.BurnUXContainerName)
109 + {
110 + if (this.Compressed == YesNoDefaultType.No)
111 + {
112 + this.Core.Write(WarningMessages.UxPayloadsOnlySupportEmbedding(this.SourceLineNumbers, this.SourceFile));
113 + }
114 +
115 + if (!String.IsNullOrEmpty(this.DownloadUrl))
116 + {
117 + this.Core.Write(WarningMessages.DownloadUrlNotSupportedForEmbeddedPayloads(this.SourceLineNumbers, this.Id.Id));
118 + }
119 +
120 + this.Compressed = YesNoDefaultType.Yes;
121 + this.DownloadUrl = null;
122 + }
123 +
124 + if (!this.Core.EncounteredError)
125 + {
126 + symbol = this.Core.AddSymbol(new WixBundlePayloadSymbol(this.SourceLineNumbers, this.Id)
127 + {
128 + Name = String.IsNullOrEmpty(this.Name) ? Path.GetFileName(this.SourceFile) : this.Name,
129 + SourceFile = new IntermediateFieldPathValue { Path = this.SourceFile },
130 + DownloadUrl = this.DownloadUrl,
131 + Compressed = (this.Compressed == YesNoDefaultType.Yes) ? true : (this.Compressed == YesNoDefaultType.No) ? (bool?)false : null,
132 + UnresolvedSourceFile = this.SourceFile, // duplicate of sourceFile but in a string column so it won't get resolved to a full path during binding.
133 + DisplayName = this.DisplayName ?? this.ProductName,
134 + Description = this.Description,
135 + Hash = this.Hash,
136 + FileSize = this.Size,
137 + Version = this.Version,
138 + });
139 +
140 + this.Core.CreateGroupAndOrderingRows(this.SourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Payload, symbol.Id.Id, previousType, previousId);
141 + }
142 +
143 + return symbol;
144 + }
145 +
146 + public void FinishCompilingPackage(CompilerPayload remotePayload)
147 + {
148 + this.CalculateAndVerifyFields(remotePayload);
149 + this.GenerateIdFromFilename();
150 +
151 + if (this.Id == null)
152 + {
153 + this.Core.Write(ErrorMessages.ExpectedAttribute(this.SourceLineNumbers, this.Element.Name.LocalName, "Id"));
154 + this.Id = Identifier.Invalid;
155 + }
156 + }
157 +
158 + public void FinishCompilingPayload()
159 + {
160 + this.CalculateAndVerifyFields();
161 + this.GenerateIdFromPrefix("pay");
162 + }
163 +
164 + private void GenerateIdFromFilename()
165 + {
166 + if (this.Id == null)
167 + {
168 + if (!String.IsNullOrEmpty(this.Name))
169 + {
170 + this.Id = this.Core.CreateIdentifierFromFilename(Path.GetFileName(this.Name));
171 + }
172 + else if (!String.IsNullOrEmpty(this.SourceFile))
173 + {
174 + this.Id = this.Core.CreateIdentifierFromFilename(Path.GetFileName(this.SourceFile));
175 + }
176 + }
177 + }
178 +
179 + private void GenerateIdFromPrefix(string prefix)
180 + {
181 + if (this.Id == null)
182 + {
183 + this.Id = this.Core.CreateIdentifier(prefix, this.SourceFile?.ToUpperInvariant() ?? String.Empty);
184 + }
185 + }
186 +
187 + public void ParseCompressed(XAttribute attrib)
188 + {
189 + this.Compressed = this.Core.GetAttributeYesNoDefaultValue(this.SourceLineNumbers, attrib);
190 + }
191 +
192 + public void ParseDescription(XAttribute attrib)
193 + {
194 + this.Description = this.Core.GetAttributeValue(this.SourceLineNumbers, attrib);
195 + }
196 +
197 + public void ParseDisplayName(XAttribute attrib)
198 + {
199 + this.DisplayName = this.Core.GetAttributeValue(this.SourceLineNumbers, attrib);
200 + }
201 +
202 + public void ParseDownloadUrl(XAttribute attrib)
203 + {
204 + this.DownloadUrl = this.Core.GetAttributeValue(this.SourceLineNumbers, attrib);
205 + }
206 +
207 + public void ParseHash(XAttribute attrib)
208 + {
209 + this.Hash = this.Core.GetAttributeValue(this.SourceLineNumbers, attrib);
210 + }
211 +
212 + public void ParseId(XAttribute attrib)
213 + {
214 + this.Id = this.Core.GetAttributeIdentifier(this.SourceLineNumbers, attrib);
215 + }
216 +
217 + public void ParseName(XAttribute attrib)
218 + {
219 + this.Name = this.Core.GetAttributeLongFilename(this.SourceLineNumbers, attrib, false, true);
220 + if (!this.Core.IsValidLongFilename(this.Name, false, true))
221 + {
222 + this.Core.Write(ErrorMessages.IllegalLongFilename(this.SourceLineNumbers, this.Element.Name.LocalName, "Name", this.Name));
223 + }
224 + }
225 +
226 + public void ParseProductName(XAttribute attrib)
227 + {
228 + this.ProductName = this.Core.GetAttributeValue(this.SourceLineNumbers, attrib);
229 + }
230 +
231 + public void ParseSize(XAttribute attrib)
232 + {
233 + this.Size = this.Core.GetAttributeLongValue(this.SourceLineNumbers, attrib, 1, Int64.MaxValue);
234 + }
235 +
236 + public void ParseSourceFile(XAttribute attrib)
237 + {
238 + this.SourceFile = this.Core.GetAttributeValue(this.SourceLineNumbers, attrib);
239 + }
240 +
241 + public void ParseVersion(XAttribute attrib)
242 + {
243 + this.Version = this.Core.GetAttributeValue(this.SourceLineNumbers, attrib);
244 + }
245 +
246 + }
247 +}
src/WixToolset.Core/CompilerCore.cs
+40
@@ -340,6 +340,46 @@ namespace WixToolset.Core
340 return Common.IsValidModuleOrBundleVersion(version);
341 }
342
343 + /// <summary>
344 + /// Creates group and ordering information.
345 + /// </summary>
346 + /// <param name="sourceLineNumbers">Source line numbers.</param>
347 + /// <param name="parentType">Type of parent group, if known.</param>
348 + /// <param name="parentId">Identifier of parent group, if known.</param>
349 + /// <param name="type">Type of this item.</param>
350 + /// <param name="id">Identifier for this item.</param>
351 + /// <param name="previousType">Type of previous item, if known.</param>
352 + /// <param name="previousId">Identifier of previous item, if known</param>
353 + public void CreateGroupAndOrderingRows(SourceLineNumber sourceLineNumbers,
354 + ComplexReferenceParentType parentType, string parentId,
355 + ComplexReferenceChildType type, string id,
356 + ComplexReferenceChildType previousType, string previousId)
357 + {
358 + if (this.EncounteredError)
359 + {
360 + return;
361 + }
362 +
363 + if (parentType != ComplexReferenceParentType.Unknown && parentId != null)
364 + {
365 + this.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, type, id);
366 + }
367 +
368 + if (previousType != ComplexReferenceChildType.Unknown && previousId != null)
369 + {
370 + // TODO: Should we define our own enum for this, just to ensure there's no "cross-contamination"?
371 + // TODO: Also, we could potentially include an 'Attributes' field to track things like
372 + // 'before' vs. 'after', and explicit vs. inferred dependencies.
373 + this.AddSymbol(new WixOrderingSymbol(sourceLineNumbers)
374 + {
375 + ItemType = type,
376 + ItemIdRef = id,
377 + DependsOnType = previousType,
378 + DependsOnIdRef = previousId,
379 + });
380 + }
381 + }
382 +
383 /// <summary>
384 /// Creates a version 3 name-based UUID.
385 /// </summary>
src/WixToolset.Core/Compiler_Bundle.cs
+154 -298
@@ -651,7 +651,7 @@ namespace WixToolset.Core
651 switch (child.Name.LocalName)
652 {
653 case "BootstrapperApplicationDll":
654 - previousId = this.ParseBootstrapperApplicationDllElement(child, previousType, previousId);
654 + previousId = this.ParseBootstrapperApplicationDllElement(child, id, previousType, previousId);
655 previousType = ComplexReferenceChildType.Payload;
656 break;
657 case "Payload":
@@ -683,15 +683,21 @@ namespace WixToolset.Core
683 /// Parse the BoostrapperApplication element.
684 /// </summary>
685 /// <param name="node">Element to parse</param>
686 + /// <param name="defaultId"></param>
687 /// <param name="previousType"></param>
688 /// <param name="previousId"></param>
688 - private Identifier ParseBootstrapperApplicationDllElement(XElement node, ComplexReferenceChildType previousType, Identifier previousId)
689 + private Identifier ParseBootstrapperApplicationDllElement(XElement node, Identifier defaultId, ComplexReferenceChildType previousType, Identifier previousId)
690 {
691 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
692 + var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node)
693 + {
694 + Id = defaultId,
695 + };
696 var dpiAwareness = WixBootstrapperApplicationDpiAwarenessType.PerMonitorV2;
697
693 - // The BootstrapperApplicationDll element acts like a Payload element so delegate to the "Payload" attribute parsing code to parse and create a Payload entry.
694 - this.ParsePayloadElementContent(node, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId, true, out var id);
698 + // This list lets us evaluate extension attributes *after* all core attributes
699 + // have been parsed and dealt with, regardless of authoring order.
700 + var extensionAttributes = new List<XAttribute>();
701
702 foreach (var attrib in node.Attributes())
703 {
@@ -699,6 +705,15 @@ namespace WixToolset.Core
705 {
706 switch (attrib.Name.LocalName)
707 {
708 + case "Id":
709 + compilerPayload.ParseId(attrib);
710 + break;
711 + case "Name":
712 + compilerPayload.ParseName(attrib);
713 + break;
714 + case "SourceFile":
715 + compilerPayload.ParseSourceFile(attrib);
716 + break;
717 case "DpiAwareness":
718 var dpiAwarenessValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
719 switch (dpiAwarenessValue)
@@ -723,8 +738,28 @@ namespace WixToolset.Core
738 break;
739 }
740 break;
741 + default:
742 + this.Core.UnexpectedAttribute(node, attrib);
743 + break;
744 }
745 }
746 + else
747 + {
748 + extensionAttributes.Add(attrib);
749 + }
750 + }
751 +
752 + compilerPayload.FinishCompilingPayload();
753 +
754 + // Now that the Id is known, we can parse the extension attributes.
755 + var context = new Dictionary<string, string>
756 + {
757 + ["Id"] = compilerPayload.Id.Id,
758 + };
759 +
760 + foreach (var extensionAttribute in extensionAttributes)
761 + {
762 + this.Core.ParseExtensionAttribute(node, extensionAttribute, context);
763 }
764
765 foreach (var child in node.Elements())
@@ -746,19 +781,20 @@ namespace WixToolset.Core
781
782 if (!this.Core.EncounteredError)
783 {
784 + compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id, previousType, previousId?.Id);
785 this.Core.AddSymbol(new WixBundleContainerSymbol(sourceLineNumbers, Compiler.BurnUXContainerId)
786 {
787 Name = "bundle-ux.cab",
788 Type = ContainerType.Attached
789 });
790
755 - this.Core.AddSymbol(new WixBootstrapperApplicationDllSymbol(sourceLineNumbers, id)
791 + this.Core.AddSymbol(new WixBootstrapperApplicationDllSymbol(sourceLineNumbers, compilerPayload.Id)
792 {
793 DpiAwareness = dpiAwareness,
794 });
795 }
796
761 - return id;
797 + return compilerPayload.Id;
798 }
799
800 /// <summary>
@@ -1134,16 +1170,57 @@ namespace WixToolset.Core
1170 private void ParseBundleExtensionElement(XElement node)
1171 {
1172 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1173 + var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node);
1174 Identifier previousId = null;
1175 var previousType = ComplexReferenceChildType.Unknown;
1176
1140 - // The BundleExtension element acts like a Payload element so delegate to the "Payload" attribute parsing code to parse and create a Payload entry.
1141 - if (this.ParsePayloadElementContent(node, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId, true, out var id))
1177 + // This list lets us evaluate extension attributes *after* all core attributes
1178 + // have been parsed and dealt with, regardless of authoring order.
1179 + var extensionAttributes = new List<XAttribute>();
1180 +
1181 + foreach (var attrib in node.Attributes())
1182 {
1143 - previousId = id;
1144 - previousType = ComplexReferenceChildType.Payload;
1183 + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
1184 + {
1185 + switch (attrib.Name.LocalName)
1186 + {
1187 + case "Id":
1188 + compilerPayload.ParseId(attrib);
1189 + break;
1190 + case "Name":
1191 + compilerPayload.ParseName(attrib);
1192 + break;
1193 + case "SourceFile":
1194 + compilerPayload.ParseSourceFile(attrib);
1195 + break;
1196 + default:
1197 + this.Core.UnexpectedAttribute(node, attrib);
1198 + break;
1199 + }
1200 + }
1201 + else
1202 + {
1203 + extensionAttributes.Add(attrib);
1204 + }
1205 }
1206
1207 + compilerPayload.FinishCompilingPayload();
1208 +
1209 + // Now that the Id is known, we can parse the extension attributes.
1210 + var context = new Dictionary<string, string>
1211 + {
1212 + ["Id"] = compilerPayload.Id.Id,
1213 + };
1214 +
1215 + foreach (var extensionAttribute in extensionAttributes)
1216 + {
1217 + this.Core.ParseExtensionAttribute(node, extensionAttribute, context);
1218 + }
1219 +
1220 + compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id, previousType, previousId?.Id);
1221 + previousId = compilerPayload.Id;
1222 + previousType = ComplexReferenceChildType.Payload;
1223 +
1224 foreach (var child in node.Elements())
1225 {
1226 if (CompilerCore.WixNamespace == child.Name.Namespace)
@@ -1172,9 +1249,9 @@ namespace WixToolset.Core
1249 // Add the BundleExtension.
1250 if (!this.Core.EncounteredError)
1251 {
1175 - this.Core.AddSymbol(new WixBundleExtensionSymbol(sourceLineNumbers, id)
1252 + this.Core.AddSymbol(new WixBundleExtensionSymbol(sourceLineNumbers, compilerPayload.Id)
1253 {
1177 - PayloadRef = id.Id,
1254 + PayloadRef = compilerPayload.Id.Id,
1255 });
1256 }
1257 }
@@ -1294,53 +1371,8 @@ namespace WixToolset.Core
1371 Debug.Assert(ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType);
1372 Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType);
1373
1297 - this.ParsePayloadElementContent(node, parentType, parentId, previousType, previousId, true, out var id);
1298 - var context = new Dictionary<string, string>
1299 - {
1300 - ["Id"] = id?.Id
1301 - };
1302 -
1303 - foreach (var child in node.Elements())
1304 - {
1305 - if (CompilerCore.WixNamespace == child.Name.Namespace)
1306 - {
1307 - switch (child.Name.LocalName)
1308 - {
1309 - default:
1310 - this.Core.UnexpectedElement(node, child);
1311 - break;
1312 - }
1313 - }
1314 - else
1315 - {
1316 - this.Core.ParseExtensionElement(node, child, context);
1317 - }
1318 - }
1319 -
1320 - return id;
1321 - }
1322 -
1323 - /// <summary>
1324 - /// Parse the attributes of the Payload element.
1325 - /// </summary>
1326 - /// <param name="node">Element to parse</param>
1327 - /// <param name="parentType">ComplexReferenceParentType of parent element.</param>
1328 - /// <param name="parentId">Identifier of parent element.</param>
1329 - /// <param name="previousType"></param>
1330 - /// <param name="previousId"></param>
1331 - /// <param name="required"></param>
1332 - /// <param name="id"></param>
1333 - /// <returns>Whether SourceFile was specified.</returns>
1334 - private bool ParsePayloadElementContent(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId, bool required, out Identifier id)
1335 - {
1336 - Debug.Assert(ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType);
1337 -
1374 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1339 - var compressed = YesNoDefaultType.Default;
1340 - id = null;
1341 - string name = null;
1342 - string sourceFile = null;
1343 - string downloadUrl = null;
1375 + var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node);
1376
1377 // This list lets us evaluate extension attributes *after* all core attributes
1378 // have been parsed and dealt with, regardless of authoring order.
@@ -1350,32 +1382,32 @@ namespace WixToolset.Core
1382 {
1383 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
1384 {
1385 + var allowed = true;
1386 switch (attrib.Name.LocalName)
1387 {
1355 - case "Id":
1356 - id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
1357 - break;
1358 - case "Compressed":
1359 - compressed = this.Core.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
1360 - break;
1361 - case "Name":
1362 - name = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, false, true);
1363 - break;
1364 - case "SourceFile":
1365 - sourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1366 - break;
1367 - case "DownloadUrl":
1368 - downloadUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1369 - break;
1370 - case "DpiAwareness":
1371 - if (node.Name.LocalName != "BootstrapperApplicationDll")
1372 - {
1373 - this.Core.UnexpectedAttribute(node, attrib);
1374 - }
1375 - break;
1376 - default:
1388 + case "Id":
1389 + compilerPayload.ParseId(attrib);
1390 + break;
1391 + case "Compressed":
1392 + compilerPayload.ParseCompressed(attrib);
1393 + break;
1394 + case "Name":
1395 + compilerPayload.ParseName(attrib);
1396 + break;
1397 + case "SourceFile":
1398 + compilerPayload.ParseSourceFile(attrib);
1399 + break;
1400 + case "DownloadUrl":
1401 + compilerPayload.ParseDownloadUrl(attrib);
1402 + break;
1403 + default:
1404 + allowed = false;
1405 + break;
1406 + }
1407 +
1408 + if (!allowed)
1409 + {
1410 this.Core.UnexpectedAttribute(node, attrib);
1378 - break;
1411 }
1412 }
1413 else
@@ -1384,15 +1416,12 @@ namespace WixToolset.Core
1416 }
1417 }
1418
1387 - if (null == id)
1388 - {
1389 - id = this.Core.CreateIdentifier("pay", sourceFile?.ToUpperInvariant() ?? String.Empty);
1390 - }
1419 + compilerPayload.FinishCompilingPayload();
1420
1421 // Now that the PayloadId is known, we can parse the extension attributes.
1422 var context = new Dictionary<string, string>
1423 {
1395 - ["Id"] = id.Id
1424 + ["Id"] = compilerPayload.Id.Id,
1425 };
1426
1427 foreach (var extensionAttribute in extensionAttributes)
@@ -1400,36 +1429,32 @@ namespace WixToolset.Core
1429 this.Core.ParseExtensionAttribute(node, extensionAttribute, context);
1430 }
1431
1403 - // Let caller handle the children.
1404 -
1405 - if (Compiler.BurnUXContainerId == parentId)
1432 + foreach (var child in node.Elements())
1433 {
1407 - if (compressed == YesNoDefaultType.No)
1434 + if (CompilerCore.WixNamespace == child.Name.Namespace)
1435 {
1409 - this.Core.Write(WarningMessages.UxPayloadsOnlySupportEmbedding(sourceLineNumbers, sourceFile));
1436 + switch (child.Name.LocalName)
1437 + {
1438 + default:
1439 + this.Core.UnexpectedElement(node, child);
1440 + break;
1441 + }
1442 }
1411 -
1412 - compressed = YesNoDefaultType.Yes;
1413 - }
1414 -
1415 - if (sourceFile == null)
1416 - {
1417 - if (required)
1443 + else
1444 {
1419 - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SourceFile"));
1445 + this.Core.ParseExtensionElement(node, child, context);
1446 }
1421 - return false;
1447 }
1448
1424 - this.CreatePayloadRow(sourceLineNumbers, id, name, sourceFile, downloadUrl, parentType, parentId, previousType, previousId, compressed, null, null, null);
1449 + compilerPayload.CreatePayloadSymbol(parentType, parentId?.Id, previousType, previousId?.Id);
1450
1426 - return true;
1451 + return compilerPayload.Id;
1452 }
1453
1429 - private RemotePayload ParseRemotePayloadElement(XElement node)
1454 + private CompilerPayload ParseRemotePayloadElement(XElement node)
1455 {
1456 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1432 - var remotePayload = new RemotePayload();
1457 + var remotePayload = new CompilerPayload(this.Core, sourceLineNumbers, node);
1458
1459 foreach (var attrib in node.Attributes())
1460 {
@@ -1438,19 +1463,19 @@ namespace WixToolset.Core
1463 switch (attrib.Name.LocalName)
1464 {
1465 case "Description":
1441 - remotePayload.Description = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1466 + remotePayload.ParseDescription(attrib);
1467 break;
1468 case "Hash":
1444 - remotePayload.Hash = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1469 + remotePayload.ParseHash(attrib);
1470 break;
1471 case "ProductName":
1447 - remotePayload.ProductName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1472 + remotePayload.ParseProductName(attrib);
1473 break;
1474 case "Size":
1450 - remotePayload.Size = this.Core.GetAttributeLongValue(sourceLineNumbers, attrib, 0, Int64.MaxValue);
1475 + remotePayload.ParseSize(attrib);
1476 break;
1477 case "Version":
1453 - remotePayload.Version = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1478 + remotePayload.ParseVersion(attrib);
1479 break;
1480 default:
1481 this.Core.UnexpectedAttribute(node, attrib);
@@ -1491,57 +1516,6 @@ namespace WixToolset.Core
1516 return remotePayload;
1517 }
1518
1494 - /// <summary>
1495 - /// Creates the row for a Payload.
1496 - /// </summary>
1497 - /// <param name="sourceLineNumbers"></param>
1498 - /// <param name="id"></param>
1499 - /// <param name="name"></param>
1500 - /// <param name="sourceFile"></param>
1501 - /// <param name="downloadUrl"></param>
1502 - /// <param name="parentType">ComplexReferenceParentType of parent element</param>
1503 - /// <param name="parentId">Identifier of parent element.</param>
1504 - /// <param name="previousType"></param>
1505 - /// <param name="previousId"></param>
1506 - /// <param name="compressed"></param>
1507 - /// <param name="displayName"></param>
1508 - /// <param name="description"></param>
1509 - /// <param name="remotePayload"></param>
1510 - /// <returns></returns>
1511 - private WixBundlePayloadSymbol CreatePayloadRow(SourceLineNumber sourceLineNumbers, Identifier id, string name, string sourceFile, string downloadUrl, ComplexReferenceParentType parentType,
1512 - Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId, YesNoDefaultType compressed, string displayName, string description,
1513 - RemotePayload remotePayload)
1514 - {
1515 - WixBundlePayloadSymbol symbol = null;
1516 -
1517 - if (!this.Core.EncounteredError)
1518 - {
1519 - symbol = this.Core.AddSymbol(new WixBundlePayloadSymbol(sourceLineNumbers, id)
1520 - {
1521 - Name = String.IsNullOrEmpty(name) ? Path.GetFileName(sourceFile) : name,
1522 - SourceFile = new IntermediateFieldPathValue { Path = sourceFile },
1523 - DownloadUrl = downloadUrl,
1524 - Compressed = (compressed == YesNoDefaultType.Yes) ? true : (compressed == YesNoDefaultType.No) ? (bool?)false : null,
1525 - UnresolvedSourceFile = sourceFile, // duplicate of sourceFile but in a string column so it won't get resolved to a full path during binding.
1526 - DisplayName = displayName,
1527 - Description = description,
1528 - });
1529 -
1530 - if (null != remotePayload)
1531 - {
1532 - symbol.Description = remotePayload.Description;
1533 - symbol.DisplayName = remotePayload.ProductName;
1534 - symbol.Hash = remotePayload.Hash;
1535 - symbol.FileSize = remotePayload.Size;
1536 - symbol.Version = remotePayload.Version;
1537 - }
1538 -
1539 - this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId.Id, ComplexReferenceChildType.Payload, id.Id, previousType, previousId?.Id);
1540 - }
1541 -
1542 - return symbol;
1543 - }
1544 -
1519 /// <summary>
1520 /// Parse PayloadGroup element.
1521 /// </summary>
@@ -1613,7 +1587,7 @@ namespace WixToolset.Core
1587 {
1588 this.Core.AddSymbol(new WixBundlePayloadGroupSymbol(sourceLineNumbers, id));
1589
1616 - this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId?.Id, ComplexReferenceChildType.PayloadGroup, id.Id, ComplexReferenceChildType.Unknown, null);
1590 + this.Core.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId?.Id, ComplexReferenceChildType.PayloadGroup, id.Id, ComplexReferenceChildType.Unknown, null);
1591 }
1592 }
1593
@@ -1661,51 +1635,11 @@ namespace WixToolset.Core
1635
1636 this.Core.ParseForExtensionElements(node);
1637
1664 - this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId?.Id, ComplexReferenceChildType.PayloadGroup, id?.Id, previousType, previousId?.Id);
1638 + this.Core.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId?.Id, ComplexReferenceChildType.PayloadGroup, id?.Id, previousType, previousId?.Id);
1639
1640 return id;
1641 }
1642
1669 - /// <summary>
1670 - /// Creates group and ordering information.
1671 - /// </summary>
1672 - /// <param name="sourceLineNumbers">Source line numbers.</param>
1673 - /// <param name="parentType">Type of parent group, if known.</param>
1674 - /// <param name="parentId">Identifier of parent group, if known.</param>
1675 - /// <param name="type">Type of this item.</param>
1676 - /// <param name="id">Identifier for this item.</param>
1677 - /// <param name="previousType">Type of previous item, if known.</param>
1678 - /// <param name="previousId">Identifier of previous item, if known</param>
1679 - private void CreateGroupAndOrderingRows(SourceLineNumber sourceLineNumbers,
1680 - ComplexReferenceParentType parentType, string parentId,
1681 - ComplexReferenceChildType type, string id,
1682 - ComplexReferenceChildType previousType, string previousId)
1683 - {
1684 - if (this.Core.EncounteredError)
1685 - {
1686 - return;
1687 - }
1688 -
1689 - if (ComplexReferenceParentType.Unknown != parentType && null != parentId)
1690 - {
1691 - this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, type, id);
1692 - }
1693 -
1694 - if (ComplexReferenceChildType.Unknown != previousType && null != previousId)
1695 - {
1696 - // TODO: Should we define our own enum for this, just to ensure there's no "cross-contamination"?
1697 - // TODO: Also, we could potentially include an 'Attributes' field to track things like
1698 - // 'before' vs. 'after', and explicit vs. inferred dependencies.
1699 - this.Core.AddSymbol(new WixOrderingSymbol(sourceLineNumbers)
1700 - {
1701 - ItemType = type,
1702 - ItemIdRef = id,
1703 - DependsOnType = previousType,
1704 - DependsOnIdRef = previousId
1705 - });
1706 - }
1707 - }
1708 -
1643 /// <summary>
1644 /// Parse ExitCode element.
1645 /// </summary>
@@ -2050,17 +1984,15 @@ namespace WixToolset.Core
1984 Debug.Assert(ComplexReferenceParentType.PackageGroup == parentType);
1985 Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PackageGroup == previousType || ComplexReferenceChildType.Package == previousType);
1986
2053 - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
2054 - Identifier id = null;
2055 - string name = null;
2056 - string sourceFile = null;
2057 - string downloadUrl = null;
1987 + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);;
1988 + var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node)
1989 + {
1990 + IsRequired = false,
1991 + };
1992 string after = null;
1993 string installCondition = null;
1994 var cache = YesNoAlwaysType.Yes; // the default is to cache everything in tradeoff for stability over disk space.
1995 string cacheId = null;
2062 - string description = null;
2063 - string displayName = null;
1996 var logPathVariable = (packageType == WixBundlePackageType.Msu) ? String.Empty : null;
1997 var rollbackPathVariable = (packageType == WixBundlePackageType.Msu) ? String.Empty : null;
1998 var permanent = YesNoType.NotSet;
@@ -2074,10 +2006,9 @@ namespace WixToolset.Core
2006 string protocol = null;
2007 var installSize = CompilerConstants.IntegerNotSet;
2008 string msuKB = null;
2077 - var compressed = YesNoDefaultType.Default;
2009 var enableFeatureSelection = YesNoType.NotSet;
2010 var forcePerMachine = YesNoType.NotSet;
2080 - RemotePayload remotePayload = null;
2011 + CompilerPayload remotePayload = null;
2012 var slipstream = YesNoType.NotSet;
2013
2014 var expectedNetFx4Args = new string[] { "/q", "/norestart", "/chainingpackage" };
@@ -2094,20 +2025,16 @@ namespace WixToolset.Core
2025 switch (attrib.Name.LocalName)
2026 {
2027 case "Id":
2097 - id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
2028 + compilerPayload.ParseId(attrib);
2029 break;
2030 case "Name":
2100 - name = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, false, true);
2101 - if (!this.Core.IsValidLongFilename(name, false, true))
2102 - {
2103 - this.Core.Write(ErrorMessages.IllegalLongFilename(sourceLineNumbers, node.Name.LocalName, "Name", name));
2104 - }
2031 + compilerPayload.ParseName(attrib);
2032 break;
2033 case "SourceFile":
2107 - sourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2034 + compilerPayload.ParseSourceFile(attrib);
2035 break;
2036 case "DownloadUrl":
2110 - downloadUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2037 + compilerPayload.ParseDownloadUrl(attrib);
2038 break;
2039 case "After":
2040 after = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
@@ -2139,10 +2066,10 @@ namespace WixToolset.Core
2066 cacheId = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2067 break;
2068 case "Description":
2142 - description = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2069 + compilerPayload.ParseDescription(attrib);
2070 break;
2071 case "DisplayName":
2145 - displayName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2072 + compilerPayload.ParseDisplayName(attrib);
2073 break;
2074 case "EnableFeatureSelection":
2075 enableFeatureSelection = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
@@ -2200,7 +2127,7 @@ namespace WixToolset.Core
2127 allowed = (packageType == WixBundlePackageType.Msu);
2128 break;
2129 case "Compressed":
2203 - compressed = this.Core.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
2130 + compilerPayload.ParseCompressed(attrib);
2131 break;
2132 case "Slipstream":
2133 slipstream = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
@@ -2242,65 +2169,8 @@ namespace WixToolset.Core
2169 remotePayload = this.ParseRemotePayloadElement(child);
2170 }
2171
2245 - if (String.IsNullOrEmpty(sourceFile))
2246 - {
2247 - if (String.IsNullOrEmpty(name))
2248 - {
2249 - this.Core.Write(ErrorMessages.ExpectedAttributesWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "Name", "SourceFile"));
2250 - }
2251 - else if (null == remotePayload)
2252 - {
2253 - sourceFile = Path.Combine("SourceDir", name);
2254 - }
2255 - }
2256 - else if (null != remotePayload)
2257 - {
2258 - this.Core.Write(ErrorMessages.UnexpectedElementWithAttribute(sourceLineNumbers, node.Name.LocalName, "RemotePayload", "SourceFile"));
2259 - }
2260 - else if (sourceFile.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
2261 - {
2262 - if (String.IsNullOrEmpty(name))
2263 - {
2264 - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name", "SourceFile", sourceFile));
2265 - }
2266 - else
2267 - {
2268 - sourceFile = Path.Combine(sourceFile, Path.GetFileName(name));
2269 - }
2270 - }
2271 -
2272 - if (null == downloadUrl && null != remotePayload)
2273 - {
2274 - this.Core.Write(ErrorMessages.ExpectedAttributeWithElement(sourceLineNumbers, node.Name.LocalName, "DownloadUrl", "RemotePayload"));
2275 - }
2276 -
2277 - if (YesNoDefaultType.No != compressed && null != remotePayload)
2278 - {
2279 - compressed = YesNoDefaultType.No;
2280 - this.Core.Write(WarningMessages.RemotePayloadsMustNotAlsoBeCompressed(sourceLineNumbers, node.Name.LocalName));
2281 - }
2282 -
2283 - if (null == id)
2284 - {
2285 - if (!String.IsNullOrEmpty(name))
2286 - {
2287 - id = this.Core.CreateIdentifierFromFilename(Path.GetFileName(name));
2288 - }
2289 - else if (!String.IsNullOrEmpty(sourceFile))
2290 - {
2291 - id = this.Core.CreateIdentifierFromFilename(Path.GetFileName(sourceFile));
2292 - }
2293 -
2294 - if (null == id)
2295 - {
2296 - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
2297 - id = Identifier.Invalid;
2298 - }
2299 - else if (!Common.IsIdentifier(id.Id))
2300 - {
2301 - this.Core.Write(ErrorMessages.IllegalIdentifier(sourceLineNumbers, node.Name.LocalName, "Id", id.Id));
2302 - }
2303 - }
2172 + compilerPayload.FinishCompilingPackage(remotePayload);
2173 + var id = compilerPayload.Id;
2174
2175 if (null == logPathVariable)
2176 {
@@ -2424,7 +2294,7 @@ namespace WixToolset.Core
2294 }
2295 else
2296 {
2427 - var context = new Dictionary<string, string>() { { "Id", id?.Id } };
2297 + var context = new Dictionary<string, string>() { { "Id", id.Id } };
2298 this.Core.ParseExtensionElement(node, child, context);
2299 }
2300 }
@@ -2432,8 +2302,7 @@ namespace WixToolset.Core
2302 if (!this.Core.EncounteredError)
2303 {
2304 // We create the package contents as a payload with this package as the parent
2435 - this.CreatePayloadRow(sourceLineNumbers, id, name, sourceFile, downloadUrl, ComplexReferenceParentType.Package, id,
2436 - ComplexReferenceChildType.Unknown, null, compressed, displayName, description, remotePayload);
2305 + compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Package, id.Id);
2306
2307 this.Core.AddSymbol(new WixChainItemSymbol(sourceLineNumbers, id));
2308
@@ -2801,7 +2670,7 @@ namespace WixToolset.Core
2670 previousId = afterId;
2671 }
2672
2804 - this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId, type, id, previousType, previousId);
2673 + this.Core.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId, type, id, previousType, previousId);
2674 }
2675
2676 /// <summary>
@@ -3251,18 +3120,5 @@ namespace WixToolset.Core
3120
3121 return WixBundleVariableType.String;
3122 }
3254 -
3255 - private class RemotePayload
3256 - {
3257 - public string Description { get; set; }
3258 -
3259 - public string Hash { get; set; }
3260 -
3261 - public string ProductName { get; set; }
3262 -
3263 - public long Size { get; set; }
3264 -
3265 - public string Version { get; set; }
3266 - }
3123 }
3124 }