@joebigelow / wix / commits / 535e4165

Add bundle support to "burn remotepayload" command.

Sean Hall committed Apr 13, 2022 at 12:17 UTC 535e4165e3121a14e5799f575a1010671212c539
7 files changed +379 -206
src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+2
@@ -182,6 +182,8 @@ namespace WixToolset.Core.Burn
182 {
183 var command = new ProcessBundlePackageCommand(this.ServiceProvider, section, facade, packagesPayloads[facade.PackageId], this.IntermediateFolder);
184 command.Execute();
185 +
186 + trackedFiles.AddRange(command.TrackedFiles);
187 }
188 break;
189
src/wix/WixToolset.Core.Burn/Bundles/HarvestBundlePackageCommand.cs new
+248
@@ -0,0 +1,248 @@
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.Bundles
4 +{
5 + using System;
6 + using System.Collections.Generic;
7 + using System.IO;
8 + using System.Text;
9 + using System.Xml;
10 + using WixToolset.Data;
11 + using WixToolset.Data.Symbols;
12 + using WixToolset.Extensibility.Data;
13 + using WixToolset.Extensibility.Services;
14 +
15 + internal class HarvestBundlePackageCommand
16 + {
17 + public HarvestBundlePackageCommand(IServiceProvider serviceProvider, string intermediateFolder, WixBundlePayloadSymbol payloadSymbol)
18 + {
19 + this.Messaging = serviceProvider.GetService<IMessaging>();
20 + this.BackendHelper = serviceProvider.GetService<IBackendHelper>();
21 + this.IntermediateFolder = intermediateFolder;
22 +
23 + this.PackagePayload = payloadSymbol;
24 + }
25 +
26 + private IMessaging Messaging { get; }
27 +
28 + private IBackendHelper BackendHelper { get; }
29 +
30 + private string IntermediateFolder { get; }
31 +
32 + private WixBundlePayloadSymbol PackagePayload { get; }
33 +
34 + public WixBundleHarvestedBundlePackageSymbol HarvestedBundlePackage { get; private set; }
35 +
36 + public WixBundleHarvestedDependencyProviderSymbol HarvestedDependencyProvider { get; private set; }
37 +
38 + public List<WixBundlePackageRelatedBundleSymbol> RelatedBundles { get; } = new List<WixBundlePackageRelatedBundleSymbol>();
39 +
40 + public List<ITrackedFile> TrackedFiles { get; } = new List<ITrackedFile>();
41 +
42 + public void Execute()
43 + {
44 + bool win64;
45 + string bundleId;
46 + string engineVersion;
47 + int protocolVersion;
48 + string manifestNamespace;
49 + bool perMachine;
50 + string version;
51 + string displayName;
52 + long installSize;
53 +
54 + var sourcePath = this.PackagePayload.SourceFile.Path;
55 + var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
56 +
57 + using (var burnReader = BurnReader.Open(this.Messaging, sourcePath))
58 + {
59 + if (burnReader.Invalid)
60 + {
61 + return;
62 + }
63 +
64 + var baFolderPath = Path.Combine(this.IntermediateFolder, burnReader.BundleId.ToString());
65 +
66 + if (!burnReader.ExtractUXContainer(baFolderPath, baFolderPath))
67 + {
68 + return;
69 + }
70 +
71 + foreach (var filePath in Directory.EnumerateFiles(baFolderPath, "*.*", SearchOption.AllDirectories))
72 + {
73 + this.TrackedFiles.Add(this.BackendHelper.TrackFile(filePath, TrackedFileType.Temporary, sourceLineNumbers));
74 + }
75 +
76 + bundleId = burnReader.BundleId.ToString("B").ToUpperInvariant();
77 +
78 + try
79 + {
80 + var document = new XmlDocument();
81 + document.Load(Path.Combine(baFolderPath, "manifest.xml"));
82 + var namespaceManager = new XmlNamespaceManager(document.NameTable);
83 +
84 + if (document.DocumentElement.LocalName != "BurnManifest")
85 + {
86 + this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(sourceLineNumbers, sourcePath, $"Expected root element to be 'BurnManifest' but was '{document.DocumentElement.LocalName}'."));
87 + return;
88 + }
89 +
90 + engineVersion = document.DocumentElement.GetAttribute("EngineVersion");
91 + protocolVersion = this.ProcessProtocolVersion(burnReader, document);
92 + win64 = this.ProcessWin64(burnReader, document, sourceLineNumbers, sourcePath);
93 +
94 + manifestNamespace = document.DocumentElement.NamespaceURI;
95 +
96 + namespaceManager.AddNamespace("burn", document.DocumentElement.NamespaceURI);
97 + var registrationElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration", namespaceManager) as XmlElement;
98 + var arpElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration/burn:Arp", namespaceManager) as XmlElement;
99 +
100 + perMachine = registrationElement.GetAttribute("PerMachine") == "yes";
101 +
102 + version = registrationElement.GetAttribute("Version");
103 +
104 + var providerKey = registrationElement.GetAttribute("ProviderKey");
105 + var depId = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", this.PackagePayload.Id.Id, providerKey));
106 + this.HarvestedDependencyProvider = new WixBundleHarvestedDependencyProviderSymbol(sourceLineNumbers, depId)
107 + {
108 + PackagePayloadRef = this.PackagePayload.Id.Id,
109 + ProviderKey = providerKey,
110 + Version = version,
111 + };
112 +
113 + displayName = arpElement.GetAttribute("DisplayName");
114 +
115 + installSize = this.ProcessPackages(document, namespaceManager);
116 +
117 + this.ProcessRelatedBundles(document, namespaceManager, sourcePath);
118 +
119 + // TODO: Add payloads?
120 + }
121 + catch (Exception e)
122 + {
123 + this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(sourceLineNumbers, sourcePath, e.ToString()));
124 + return;
125 + }
126 + }
127 +
128 + this.HarvestedBundlePackage = new WixBundleHarvestedBundlePackageSymbol(this.PackagePayload.SourceLineNumbers, this.PackagePayload.Id)
129 + {
130 + Win64 = win64,
131 + BundleId = bundleId,
132 + EngineVersion = engineVersion,
133 + ManifestNamespace = manifestNamespace,
134 + ProtocolVersion = protocolVersion,
135 + PerMachine = perMachine,
136 + Version = version,
137 + DisplayName = displayName,
138 + InstallSize = installSize,
139 + };
140 + }
141 +
142 + private int ProcessProtocolVersion(BurnReader burnReader, XmlDocument document)
143 + {
144 + var protocolVersionValue = document.DocumentElement.GetAttribute("ProtocolVersion");
145 +
146 + if (Int32.TryParse(protocolVersionValue, out var protocolVersion))
147 + {
148 + return protocolVersion;
149 + }
150 +
151 + // Assume that the .wixburn section version will change when the Burn protocol changes.
152 + // This should be a safe assumption since only old bundles should be missing the ProtocolVersion from the manifest.
153 + return burnReader.Version == 2 ? 1 : 0;
154 + }
155 +
156 + private bool ProcessWin64(BurnReader burnReader, XmlDocument document, SourceLineNumber sourceLineNumbers, string sourcePath)
157 + {
158 + var win64Value = document.DocumentElement.GetAttribute("Win64");
159 +
160 + switch (win64Value)
161 + {
162 + case "yes":
163 + return true;
164 + case "no":
165 + return false;
166 + }
167 +
168 + switch (burnReader.MachineType)
169 + {
170 + case BurnCommon.IMAGE_FILE_MACHINE_ARM:
171 + case BurnCommon.IMAGE_FILE_MACHINE_ARMNT:
172 + case BurnCommon.IMAGE_FILE_MACHINE_I386:
173 + case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH32:
174 + return false;
175 + case BurnCommon.IMAGE_FILE_MACHINE_AMD64:
176 + case BurnCommon.IMAGE_FILE_MACHINE_ARM64:
177 + case BurnCommon.IMAGE_FILE_MACHINE_IA64:
178 + case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH64:
179 + return true;
180 + case BurnCommon.IMAGE_FILE_MACHINE_AM33:
181 + case BurnCommon.IMAGE_FILE_MACHINE_EBC:
182 + case BurnCommon.IMAGE_FILE_MACHINE_M32R:
183 + case BurnCommon.IMAGE_FILE_MACHINE_MIPS16:
184 + case BurnCommon.IMAGE_FILE_MACHINE_MIPSFPU:
185 + case BurnCommon.IMAGE_FILE_MACHINE_MIPSFPU16:
186 + case BurnCommon.IMAGE_FILE_MACHINE_POWERPC:
187 + case BurnCommon.IMAGE_FILE_MACHINE_POWERPCFP:
188 + case BurnCommon.IMAGE_FILE_MACHINE_R4000:
189 + case BurnCommon.IMAGE_FILE_MACHINE_RISCV32:
190 + case BurnCommon.IMAGE_FILE_MACHINE_RISCV64:
191 + case BurnCommon.IMAGE_FILE_MACHINE_RISCV128:
192 + case BurnCommon.IMAGE_FILE_MACHINE_SH3:
193 + case BurnCommon.IMAGE_FILE_MACHINE_SH3DSP:
194 + case BurnCommon.IMAGE_FILE_MACHINE_SH4:
195 + case BurnCommon.IMAGE_FILE_MACHINE_SH5:
196 + case BurnCommon.IMAGE_FILE_MACHINE_THUMB:
197 + case BurnCommon.IMAGE_FILE_MACHINE_WCEMIPSV2:
198 + default:
199 + this.Messaging.Write(BurnBackendWarnings.UnknownCoffMachineType(sourceLineNumbers, sourcePath, burnReader.MachineType));
200 + return false;
201 + }
202 + }
203 +
204 + private long ProcessPackages(XmlDocument document, XmlNamespaceManager namespaceManager)
205 + {
206 + long packageInstallSize = 0;
207 +
208 + foreach (XmlElement packageElement in document.SelectNodes("/burn:BurnManifest/burn:Chain/*", namespaceManager))
209 + {
210 + if (!packageElement.Name.EndsWith("Package"))
211 + {
212 + continue;
213 + }
214 +
215 + if (Int64.TryParse(packageElement.GetAttribute("InstallSize"), out var installSize))
216 + {
217 + packageInstallSize += installSize;
218 + }
219 + }
220 +
221 + return packageInstallSize;
222 + }
223 +
224 + private void ProcessRelatedBundles(XmlDocument document, XmlNamespaceManager namespaceManager, string sourcePath)
225 + {
226 + var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
227 +
228 + foreach (XmlElement relatedBundleElement in document.SelectNodes("/burn:BurnManifest/burn:RelatedBundle", namespaceManager))
229 + {
230 + var id = relatedBundleElement.GetAttribute("Id");
231 + var actionValue = relatedBundleElement.GetAttribute("Action");
232 +
233 + if (!Enum.TryParse(actionValue, out RelatedBundleActionType action))
234 + {
235 + this.Messaging.Write(BurnBackendWarnings.UnknownBundleRelationAction(sourceLineNumbers, sourcePath, actionValue));
236 + continue;
237 + }
238 +
239 + this.RelatedBundles.Add(new WixBundlePackageRelatedBundleSymbol(sourceLineNumbers)
240 + {
241 + PackagePayloadRef = this.PackagePayload.Id.Id,
242 + BundleId = id,
243 + Action = action,
244 + });
245 + }
246 + }
247 + }
248 +}
src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs
+14 -201
@@ -4,10 +4,7 @@ namespace WixToolset.Core.Burn.Bundles
4 {
5 using System;
6 using System.Collections.Generic;
7 - using System.Diagnostics;
8 - using System.IO;
7 using System.Linq;
10 - using System.Xml;
8 using WixToolset.Data;
9 using WixToolset.Data.Symbols;
10 using WixToolset.Extensibility.Data;
@@ -20,8 +17,8 @@ namespace WixToolset.Core.Burn.Bundles
17 {
18 public ProcessBundlePackageCommand(IServiceProvider serviceProvider, IntermediateSection section, PackageFacade facade, Dictionary<string, WixBundlePayloadSymbol> packagePayloads, string intermediateFolder)
19 {
20 + this.ServiceProvider = serviceProvider;
21 this.Messaging = serviceProvider.GetService<IMessaging>();
24 - this.BackendHelper = serviceProvider.GetService<IBackendHelper>();
22 this.PackagePayloads = packagePayloads;
23 this.Section = section;
24 this.IntermediateFolder = intermediateFolder;
@@ -31,9 +28,9 @@ namespace WixToolset.Core.Burn.Bundles
28 this.PackagePayload = packagePayloads[this.ChainPackage.PayloadRef];
29 }
30
34 - private IMessaging Messaging { get; }
31 + private IServiceProvider ServiceProvider { get; }
32
36 - private IBackendHelper BackendHelper { get; }
33 + private IMessaging Messaging { get; }
34
35 private Dictionary<string, WixBundlePayloadSymbol> PackagePayloads { get; }
36
@@ -101,210 +98,26 @@ namespace WixToolset.Core.Burn.Bundles
98 this.ChainPackage.InstallSize = harvestedBundlePackage.InstallSize;
99 }
100
104 - public WixBundleHarvestedBundlePackageSymbol HarvestPackage()
101 + private WixBundleHarvestedBundlePackageSymbol HarvestPackage()
102 {
106 - bool win64;
107 - string bundleId;
108 - string engineVersion;
109 - int protocolVersion;
110 - string manifestNamespace;
111 - bool perMachine;
112 - string version;
113 - string displayName;
114 - long installSize;
115 -
116 - var sourcePath = this.PackagePayload.SourceFile.Path;
117 - var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
103 + var command = new HarvestBundlePackageCommand(this.ServiceProvider, this.IntermediateFolder, this.PackagePayload);
104 + command.Execute();
105
119 - using (var burnReader = BurnReader.Open(this.Messaging, sourcePath))
106 + this.TrackedFiles.AddRange(command.TrackedFiles);
107 + if (this.Messaging.EncounteredError)
108 {
121 - if (burnReader.Invalid)
122 - {
123 - return null;
124 - }
125 -
126 - var baFolderPath = Path.Combine(this.IntermediateFolder, burnReader.BundleId.ToString());
127 -
128 - if (!burnReader.ExtractUXContainer(baFolderPath, baFolderPath))
129 - {
130 - return null;
131 - }
132 -
133 - foreach (var filePath in Directory.EnumerateFiles(baFolderPath, "*.*", SearchOption.AllDirectories))
134 - {
135 - this.TrackedFiles.Add(this.BackendHelper.TrackFile(filePath, TrackedFileType.Temporary, sourceLineNumbers));
136 - }
137 -
138 - bundleId = burnReader.BundleId.ToString("B").ToUpperInvariant();
139 -
140 - try
141 - {
142 - var document = new XmlDocument();
143 - document.Load(Path.Combine(baFolderPath, "manifest.xml"));
144 - var namespaceManager = new XmlNamespaceManager(document.NameTable);
145 -
146 - if (document.DocumentElement.LocalName != "BurnManifest")
147 - {
148 - this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(sourceLineNumbers, sourcePath, $"Expected root element to be 'BurnManifest' but was '{document.DocumentElement.LocalName}'."));
149 - return null;
150 - }
151 -
152 - engineVersion = document.DocumentElement.GetAttribute("EngineVersion");
153 - protocolVersion = this.ProcessProtocolVersion(burnReader, document);
154 - win64 = this.ProcessWin64(burnReader, document, sourceLineNumbers, sourcePath);
155 -
156 - manifestNamespace = document.DocumentElement.NamespaceURI;
157 -
158 - namespaceManager.AddNamespace("burn", document.DocumentElement.NamespaceURI);
159 - var registrationElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration", namespaceManager) as XmlElement;
160 - var arpElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration/burn:Arp", namespaceManager) as XmlElement;
161 -
162 - perMachine = registrationElement.GetAttribute("PerMachine") == "yes";
163 -
164 - version = registrationElement.GetAttribute("Version");
165 -
166 - var providerKey = registrationElement.GetAttribute("ProviderKey");
167 - var depId = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", this.PackagePayload.Id.Id, providerKey));
168 - this.Section.AddSymbol(new WixBundleHarvestedDependencyProviderSymbol(sourceLineNumbers, depId)
169 - {
170 - PackagePayloadRef = this.PackagePayload.Id.Id,
171 - ProviderKey = providerKey,
172 - Version = version,
173 - });
174 -
175 - displayName = arpElement.GetAttribute("DisplayName");
176 -
177 - installSize = this.ProcessPackages(document, namespaceManager);
178 -
179 - this.ProcessRelatedBundles(document, namespaceManager, sourcePath);
180 -
181 - // TODO: Add payloads?
182 - }
183 - catch (Exception e)
184 - {
185 - this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(sourceLineNumbers, sourcePath, e.ToString()));
186 - return null;
187 - }
109 + return null;
110 }
111
190 - return this.Section.AddSymbol(new WixBundleHarvestedBundlePackageSymbol(this.PackagePayload.SourceLineNumbers, this.PackagePayload.Id)
191 - {
192 - Win64 = win64,
193 - BundleId = bundleId,
194 - EngineVersion = engineVersion,
195 - ManifestNamespace = manifestNamespace,
196 - ProtocolVersion = protocolVersion,
197 - PerMachine = perMachine,
198 - Version = version,
199 - DisplayName = displayName,
200 - InstallSize = installSize,
201 - });
202 - }
203 -
204 - private int ProcessProtocolVersion(BurnReader burnReader, XmlDocument document)
205 - {
206 - var protocolVersionValue = document.DocumentElement.GetAttribute("ProtocolVersion");
112 + this.Section.AddSymbol(command.HarvestedBundlePackage);
113 + this.Section.AddSymbol(command.HarvestedDependencyProvider);
114
208 - if (Int32.TryParse(protocolVersionValue, out var protocolVersion))
115 + foreach (var relatedBundle in command.RelatedBundles)
116 {
210 - return protocolVersion;
117 + this.Section.AddSymbol(relatedBundle);
118 }
119
213 - // Assume that the .wixburn section version will change when the Burn protocol changes.
214 - // This should be a safe assumption since only old bundles should be missing the ProtocolVersion from the manifest.
215 - return burnReader.Version == 2 ? 1 : 0;
216 - }
217 -
218 - private bool ProcessWin64(BurnReader burnReader, XmlDocument document, SourceLineNumber sourceLineNumbers, string sourcePath)
219 - {
220 - var win64Value = document.DocumentElement.GetAttribute("Win64");
221 -
222 - switch (win64Value)
223 - {
224 - case "yes":
225 - return true;
226 - case "no":
227 - return false;
228 - }
229 -
230 - switch (burnReader.MachineType)
231 - {
232 - case BurnCommon.IMAGE_FILE_MACHINE_ARM:
233 - case BurnCommon.IMAGE_FILE_MACHINE_ARMNT:
234 - case BurnCommon.IMAGE_FILE_MACHINE_I386:
235 - case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH32:
236 - return false;
237 - case BurnCommon.IMAGE_FILE_MACHINE_AMD64:
238 - case BurnCommon.IMAGE_FILE_MACHINE_ARM64:
239 - case BurnCommon.IMAGE_FILE_MACHINE_IA64:
240 - case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH64:
241 - return true;
242 - case BurnCommon.IMAGE_FILE_MACHINE_AM33:
243 - case BurnCommon.IMAGE_FILE_MACHINE_EBC:
244 - case BurnCommon.IMAGE_FILE_MACHINE_M32R:
245 - case BurnCommon.IMAGE_FILE_MACHINE_MIPS16:
246 - case BurnCommon.IMAGE_FILE_MACHINE_MIPSFPU:
247 - case BurnCommon.IMAGE_FILE_MACHINE_MIPSFPU16:
248 - case BurnCommon.IMAGE_FILE_MACHINE_POWERPC:
249 - case BurnCommon.IMAGE_FILE_MACHINE_POWERPCFP:
250 - case BurnCommon.IMAGE_FILE_MACHINE_R4000:
251 - case BurnCommon.IMAGE_FILE_MACHINE_RISCV32:
252 - case BurnCommon.IMAGE_FILE_MACHINE_RISCV64:
253 - case BurnCommon.IMAGE_FILE_MACHINE_RISCV128:
254 - case BurnCommon.IMAGE_FILE_MACHINE_SH3:
255 - case BurnCommon.IMAGE_FILE_MACHINE_SH3DSP:
256 - case BurnCommon.IMAGE_FILE_MACHINE_SH4:
257 - case BurnCommon.IMAGE_FILE_MACHINE_SH5:
258 - case BurnCommon.IMAGE_FILE_MACHINE_THUMB:
259 - case BurnCommon.IMAGE_FILE_MACHINE_WCEMIPSV2:
260 - default:
261 - this.Messaging.Write(BurnBackendWarnings.UnknownCoffMachineType(sourceLineNumbers, sourcePath, burnReader.MachineType));
262 - return false;
263 - }
264 - }
265 -
266 - private long ProcessPackages(XmlDocument document, XmlNamespaceManager namespaceManager)
267 - {
268 - long packageInstallSize = 0;
269 -
270 - foreach (XmlElement packageElement in document.SelectNodes("/burn:BurnManifest/burn:Chain/*", namespaceManager))
271 - {
272 - if (!packageElement.Name.EndsWith("Package"))
273 - {
274 - continue;
275 - }
276 -
277 - if (Int64.TryParse(packageElement.GetAttribute("InstallSize"), out var installSize))
278 - {
279 - packageInstallSize += installSize;
280 - }
281 - }
282 -
283 - return packageInstallSize;
284 - }
285 -
286 - private void ProcessRelatedBundles(XmlDocument document, XmlNamespaceManager namespaceManager, string sourcePath)
287 - {
288 - var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
289 -
290 - foreach (XmlElement relatedBundleElement in document.SelectNodes("/burn:BurnManifest/burn:RelatedBundle", namespaceManager))
291 - {
292 - var id = relatedBundleElement.GetAttribute("Id");
293 - var actionValue = relatedBundleElement.GetAttribute("Action");
294 -
295 - if (!Enum.TryParse(actionValue, out RelatedBundleActionType action))
296 - {
297 - this.Messaging.Write(BurnBackendWarnings.UnknownBundleRelationAction(sourceLineNumbers, sourcePath, actionValue));
298 - continue;
299 - }
300 -
301 - this.Section.AddSymbol(new WixBundlePackageRelatedBundleSymbol(sourceLineNumbers)
302 - {
303 - PackagePayloadRef = this.PackagePayload.Id.Id,
304 - BundleId = id,
305 - Action = action,
306 - });
307 - }
120 + return command.HarvestedBundlePackage;
121 }
122 }
123 }
src/wix/WixToolset.Core.Burn/CommandLine/RemotePayloadSubcommand.cs
+78 -1
@@ -9,6 +9,7 @@ namespace WixToolset.Core.Burn.CommandLine
9 using System.Threading;
10 using System.Threading.Tasks;
11 using System.Xml.Linq;
12 + using WixToolset.Core.Burn.Bundles;
13 using WixToolset.Core.Burn.Interfaces;
14 using WixToolset.Core.Native;
15 using WixToolset.Data;
@@ -17,16 +18,22 @@ namespace WixToolset.Core.Burn.CommandLine
18
19 internal class RemotePayloadSubcommand : BurnSubcommandBase
20 {
21 + private static readonly XName BundlePackagePayloadName = "BundlePackagePayload";
22 private static readonly XName ExePackagePayloadName = "ExePackagePayload";
23 private static readonly XName MsuPackagePayloadName = "MsuPackagePayload";
24 private static readonly XName PayloadName = "Payload";
25 + private static readonly XName RemoteBundleName = "RemoteBundle";
26 + private static readonly XName RemoteRelatedBundleName = "RemoteRelatedBundle";
27
28 public RemotePayloadSubcommand(IServiceProvider serviceProvider)
29 {
30 + this.ServiceProvider = serviceProvider;
31 this.Messaging = serviceProvider.GetService<IMessaging>();
32 this.PayloadHarvester = serviceProvider.GetService<IPayloadHarvester>();
33 }
34
35 + private IServiceProvider ServiceProvider { get; }
36 +
37 private IMessaging Messaging { get; }
38
39 private IPayloadHarvester PayloadHarvester { get; }
@@ -37,6 +44,8 @@ namespace WixToolset.Core.Burn.CommandLine
44
45 private List<string> InputPaths { get; } = new List<string>();
46
47 + private string IntermediateFolder { get; set; }
48 +
49 private string OutputPath { get; set; }
50
51 private WixBundlePackageType? PackageType { get; set; }
@@ -58,6 +67,11 @@ namespace WixToolset.Core.Burn.CommandLine
67 this.BasePaths.Sort();
68 this.BasePaths.Reverse();
69
70 + if (String.IsNullOrEmpty(this.IntermediateFolder))
71 + {
72 + this.IntermediateFolder = Path.GetTempPath();
73 + }
74 +
75 var elements = this.HarvestRemotePayloads(inputPaths);
76
77 if (!this.Messaging.EncounteredError)
@@ -98,6 +112,10 @@ namespace WixToolset.Core.Burn.CommandLine
112 this.DownloadUrl = parser.GetNextArgumentOrError(argument);
113 return true;
114
115 + case "intermediatefolder":
116 + this.IntermediateFolder = parser.GetNextArgumentAsDirectoryOrError(argument);
117 + return true;
118 +
119 case "packagetype":
120 var packageTypeValue = parser.GetNextArgumentOrError(argument);
121 if (Enum.TryParse<WixBundlePackageType>(packageTypeValue, ignoreCase: true, out var packageType))
@@ -174,7 +192,7 @@ namespace WixToolset.Core.Burn.CommandLine
192 continue;
193 }
194
177 - var payloadSymbol = new WixBundlePayloadSymbol
195 + var payloadSymbol = new WixBundlePayloadSymbol(null, new Identifier(AccessModifier.Section, "id"))
196 {
197 SourceFile = new IntermediateFieldPathValue { Path = path },
198 };
@@ -225,6 +243,62 @@ namespace WixToolset.Core.Burn.CommandLine
243 element.Add(new XAttribute("Version", payloadSymbol.Version));
244 }
245
246 + if (element.Name == BundlePackagePayloadName)
247 + {
248 + var command = new HarvestBundlePackageCommand(this.ServiceProvider, this.IntermediateFolder, payloadSymbol);
249 + command.Execute();
250 +
251 + if (!this.Messaging.EncounteredError)
252 + {
253 + var bundleElement = new XElement(RemoteBundleName);
254 +
255 + bundleElement.Add(new XAttribute("BundleId", command.HarvestedBundlePackage.BundleId));
256 +
257 + if (!String.IsNullOrEmpty(command.HarvestedBundlePackage.DisplayName))
258 + {
259 + bundleElement.Add(new XAttribute("DisplayName", command.HarvestedBundlePackage.DisplayName));
260 + }
261 +
262 + if (!String.IsNullOrEmpty(command.HarvestedBundlePackage.EngineVersion))
263 + {
264 + bundleElement.Add(new XAttribute("EngineVersion", command.HarvestedBundlePackage.EngineVersion));
265 + }
266 +
267 + bundleElement.Add(new XAttribute("InstallSize", command.HarvestedBundlePackage.InstallSize));
268 + bundleElement.Add(new XAttribute("ManifestNamespace", command.HarvestedBundlePackage.ManifestNamespace));
269 + bundleElement.Add(new XAttribute("PerMachine", command.HarvestedBundlePackage.PerMachine ? "yes" : "no"));
270 + bundleElement.Add(new XAttribute("ProviderKey", command.HarvestedDependencyProvider.ProviderKey));
271 + bundleElement.Add(new XAttribute("ProtocolVersion", command.HarvestedBundlePackage.ProtocolVersion));
272 +
273 + if (!String.IsNullOrEmpty(command.HarvestedBundlePackage.Version))
274 + {
275 + bundleElement.Add(new XAttribute("Version", command.HarvestedBundlePackage.Version));
276 + }
277 +
278 + bundleElement.Add(new XAttribute("Win64", command.HarvestedBundlePackage.Win64 ? "yes" : "no"));
279 +
280 + var setUpgradeCode = false;
281 + foreach (var relatedBundle in command.RelatedBundles)
282 + {
283 + if (!setUpgradeCode && relatedBundle.Action == RelatedBundleActionType.Upgrade)
284 + {
285 + setUpgradeCode = true;
286 + bundleElement.Add(new XAttribute("UpgradeCode", relatedBundle.BundleId));
287 + continue;
288 + }
289 +
290 + var relatedBundleElement = new XElement(RemoteRelatedBundleName);
291 +
292 + relatedBundleElement.Add(new XAttribute("Id", relatedBundle.BundleId));
293 + relatedBundleElement.Add(new XAttribute("Action", relatedBundle.Action.ToString()));
294 +
295 + bundleElement.Add(relatedBundleElement);
296 + }
297 +
298 + element.Add(bundleElement);
299 + }
300 + }
301 +
302 yield return element;
303 }
304 }
@@ -237,6 +311,9 @@ namespace WixToolset.Core.Burn.CommandLine
311
312 switch (extension.ToUpperInvariant())
313 {
314 + case "BUNDLE":
315 + return new XElement(BundlePackagePayloadName);
316 +
317 case "EXE":
318 case ".EXE":
319 return new XElement(ExePackagePayloadName);
src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs
+1 -1
@@ -574,7 +574,7 @@ namespace WixToolsetTest.CoreIntegration
574 }
575
576 [Fact]
577 - public void CantBuildWithSubfolderContainer()
577 + public void CanBuildWithSubfolderContainer()
578 {
579 var folder = TestData.Get(@"TestData");
580
src/wix/test/WixToolsetTest.CoreIntegration/PackagePayloadFixture.cs
+2 -2
@@ -90,7 +90,7 @@ namespace WixToolsetTest.CoreIntegration
90 }
91
92 [Fact]
93 - public void CanSpecifyPackagePayloadInPayloadGroup()
93 + public void CanSpecifyExePackagePayloadInPayloadGroup()
94 {
95 var folder = TestData.Get(@"TestData");
96
@@ -135,7 +135,7 @@ namespace WixToolsetTest.CoreIntegration
135 }
136
137 [Fact]
138 - public void CanSpecifyPackagePayloadWithCertificate()
138 + public void CanSpecifyExePackagePayloadWithCertificate()
139 {
140 var folder = TestData.Get(@"TestData", "PackagePayload");
141
src/wix/test/WixToolsetTest.CoreIntegration/RemotePayloadFixture.cs
+34 -1
@@ -11,7 +11,40 @@ namespace WixToolsetTest.CoreIntegration
11 public class RemotePayloadFixture
12 {
13 [Fact]
14 - public void CanGetRemotePayload()
14 + public void CanGetRemoteV3BundlePayload()
15 + {
16 + var folder = TestData.Get(@"TestData");
17 +
18 + using (var fs = new DisposableFileSystem())
19 + {
20 + var outputFolder = fs.GetFolder();
21 + var outFile = Path.Combine(outputFolder, "out.xml");
22 +
23 + var result = WixRunner.Execute(new[]
24 + {
25 + "burn", "remotepayload",
26 + Path.Combine(folder, ".Data", "v3bundle.exe"),
27 + "-downloadurl", "https://www.example.com/files/{0}",
28 + "-o", outFile,
29 + "-packagetype", "bundle",
30 + });
31 +
32 + result.AssertSuccess();
33 +
34 + var elements = File.ReadAllLines(outFile);
35 + elements = elements.Select(s => s.Replace("\"", "'")).ToArray();
36 +
37 + WixAssert.CompareLineByLine(new[]
38 + {
39 + "<BundlePackagePayload Name='v3bundle.exe' ProductName='CustomV3Theme' Description='CustomV3Theme' DownloadUrl='https://www.example.com/files/v3bundle.exe' Hash='80739E7B8C31D75B4CDC48D60D74F5E481CB904212A3AE3FB0920365A163FBF32B0C5C175AB516D4124F107923E96200605DE1D560D362FEB47350FA727823B4' Size='648397' Version='1.0.0.0'>",
40 + " <RemoteBundle BundleId='{215A70DB-AB35-48C7-BE51-D66EAAC87177}' DisplayName='CustomV3Theme' InstallSize='1135' ManifestNamespace='http://schemas.microsoft.com/wix/2008/Burn' PerMachine='yes' ProviderKey='{215a70db-ab35-48c7-be51-d66eaac87177}' ProtocolVersion='1' Version='1.0.0.0' Win64='no' UpgradeCode='{2BF4C01F-C132-4E70-97AB-2BC68C7CCD10}' />",
41 + "</BundlePackagePayload>",
42 + }, elements);
43 + }
44 + }
45 +
46 + [Fact]
47 + public void CanGetRemoteExePayload()
48 {
49 var folder = TestData.Get(@"TestData");
50