Allow DownloadUrl on embedded payloads.
#5253
Sean Hall committed
Apr 25, 2021 at 15:36 UTC
b4210b23ea28e0acc5a8b7ca5357d7d3926071b4
8 files changed
+110
-58
src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+1
-1
@@ -300,7 +300,7 @@ namespace WixToolset.Core.Burn
300
301
if (PackagingType.Embedded == payload.Packaging && String.IsNullOrEmpty(payload.EmbeddedId))
302
{
303
- payload.EmbeddedId = String.Format(CultureInfo.InvariantCulture, BurnCommon.BurnAttachedContainerEmbeddedIdFormat, payloadIndex);
303
+ payload.EmbeddedId = String.Format(CultureInfo.InvariantCulture, BurnCommon.BurnAuthoredContainerEmbeddedIdFormat, payloadIndex);
304
++payloadIndex;
305
}
306
}
src/WixToolset.Core.Burn/Bind/ResolveDownloadUrlsCommand.cs
+9
-8
@@ -5,6 +5,7 @@ namespace WixToolset.Core.Burn.Bind
5
using System;
6
using System.Collections.Generic;
7
using WixToolset.Data;
8
+ using WixToolset.Data.Burn;
9
using WixToolset.Data.Symbols;
10
using WixToolset.Extensibility;
11
using WixToolset.Extensibility.Services;
@@ -60,7 +61,14 @@ namespace WixToolset.Core.Burn.Bind
61
{
62
foreach (var payload in this.PayloadsById.Values)
63
{
63
- if (payload.Packaging == PackagingType.External)
64
+ if (payload.Packaging == PackagingType.Embedded && payload.ContainerRef == BurnConstants.BurnUXContainerName)
65
+ {
66
+ if (!String.IsNullOrEmpty(payload.DownloadUrl))
67
+ {
68
+ this.Messaging.Write(WarningMessages.DownloadUrlNotSupportedForBAPayloads(payload.SourceLineNumbers, payload.Id.Id));
69
+ }
70
+ }
71
+ else
72
{
73
var packageId = payload.ParentPackagePayloadRef;
74
var parentUrl = payload.ParentPackagePayloadRef == null ? null : this.PayloadsById[payload.ParentPackagePayloadRef].DownloadUrl;
@@ -70,13 +78,6 @@ namespace WixToolset.Core.Burn.Bind
78
payload.DownloadUrl = resolvedUrl;
79
}
80
}
73
- else if (payload.Packaging == PackagingType.Embedded)
74
- {
75
- if (!String.IsNullOrEmpty(payload.DownloadUrl))
76
- {
77
- this.Messaging.Write(WarningMessages.DownloadUrlNotSupportedForEmbeddedPayloads(payload.SourceLineNumbers, payload.Id.Id));
78
- }
79
- }
81
}
82
}
83
src/WixToolset.Core.Burn/Bundles/BurnCommon.cs
+1
-2
@@ -19,8 +19,7 @@ namespace WixToolset.Core.Burn.Bundles
19
{
20
public const string BurnNamespace = "http://wixtoolset.org/schemas/v4/2008/Burn";
21
public const string BurnUXContainerEmbeddedIdFormat = "u{0}";
22
- public const string BurnUXContainerPayloadIdFormat = "p{0}";
23
- public const string BurnAttachedContainerEmbeddedIdFormat = "a{0}";
22
+ public const string BurnAuthoredContainerEmbeddedIdFormat = "a{0}";
23
24
public const string BADataFileName = "BootstrapperApplicationData.xml";
25
public const string BADataNamespace = "http://wixtoolset.org/schemas/v4/BootstrapperApplicationData";
src/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
+33
-28
@@ -166,9 +166,7 @@ namespace WixToolset.Core.Burn.Bundles
166
// write the UX allPayloads...
167
foreach (var payload in this.UXContainerPayloads)
168
{
169
- writer.WriteStartElement("Payload");
170
- this.WriteBurnManifestPayloadAttributes(writer, payload, true, this.Payloads);
171
- writer.WriteEndElement();
169
+ this.WriteBurnManifestUXPayload(writer, payload);
170
}
171
172
writer.WriteEndElement(); // </UX>
@@ -183,20 +181,9 @@ namespace WixToolset.Core.Burn.Bundles
181
}
182
}
183
186
- foreach (var payload in this.Payloads.Values)
184
+ foreach (var payload in this.Payloads.Values.Where(p => p.ContainerRef != BurnConstants.BurnUXContainerName))
185
{
188
- if (PackagingType.Embedded == payload.Packaging && BurnConstants.BurnUXContainerName != payload.ContainerRef)
189
- {
190
- writer.WriteStartElement("Payload");
191
- this.WriteBurnManifestPayloadAttributes(writer, payload, true, this.Payloads);
192
- writer.WriteEndElement();
193
- }
194
- else if (PackagingType.External == payload.Packaging)
195
- {
196
- writer.WriteStartElement("Payload");
197
- this.WriteBurnManifestPayloadAttributes(writer, payload, false, this.Payloads);
198
- writer.WriteEndElement();
199
- }
186
+ this.WriteBurnManifestPayload(writer, payload);
187
}
188
189
foreach (var rollbackBoundary in this.RollbackBoundaries)
@@ -654,9 +641,9 @@ namespace WixToolset.Core.Burn.Bundles
641
}
642
}
643
657
- private void WriteBurnManifestPayloadAttributes(XmlTextWriter writer, WixBundlePayloadSymbol payload, bool embeddedOnly, Dictionary<string, WixBundlePayloadSymbol> allPayloads)
644
+ private void WriteBurnManifestPayload(XmlTextWriter writer, WixBundlePayloadSymbol payload)
645
{
659
- Debug.Assert(!embeddedOnly || PackagingType.Embedded == payload.Packaging);
646
+ writer.WriteStartElement("Payload");
647
648
writer.WriteAttributeString("Id", payload.Id.Id);
649
writer.WriteAttributeString("FilePath", payload.Name);
@@ -668,28 +655,46 @@ namespace WixToolset.Core.Burn.Bundles
655
writer.WriteAttributeString("LayoutOnly", "yes");
656
}
657
658
+ if (!String.IsNullOrEmpty(payload.DownloadUrl))
659
+ {
660
+ writer.WriteAttributeString("DownloadUrl", payload.DownloadUrl);
661
+ }
662
+
663
switch (payload.Packaging)
664
{
665
case PackagingType.Embedded: // this means it's in a container.
666
+ Debug.Assert(BurnConstants.BurnUXContainerName != payload.ContainerRef);
667
+
668
writer.WriteAttributeString("Packaging", "embedded");
669
writer.WriteAttributeString("SourcePath", payload.EmbeddedId);
676
-
677
- if (BurnConstants.BurnUXContainerName != payload.ContainerRef)
678
- {
679
- writer.WriteAttributeString("Container", payload.ContainerRef);
680
- }
670
+ writer.WriteAttributeString("Container", payload.ContainerRef);
671
break;
672
673
case PackagingType.External:
684
- if (!String.IsNullOrEmpty(payload.DownloadUrl))
685
- {
686
- writer.WriteAttributeString("DownloadUrl", payload.DownloadUrl);
687
- }
688
-
674
writer.WriteAttributeString("Packaging", "external");
675
writer.WriteAttributeString("SourcePath", payload.Name);
676
break;
677
}
678
+
679
+ writer.WriteEndElement();
680
+ }
681
+
682
+ private void WriteBurnManifestUXPayload(XmlTextWriter writer, WixBundlePayloadSymbol payload)
683
+ {
684
+ Debug.Assert(PackagingType.Embedded == payload.Packaging);
685
+ Debug.Assert(BurnConstants.BurnUXContainerName == payload.ContainerRef);
686
+
687
+ writer.WriteStartElement("Payload");
688
+
689
+ // TODO: The engine should be updated to not require FileSize, Hash, or Packaging for UX payloads since the values are never used.
690
+ writer.WriteAttributeString("Id", payload.Id.Id);
691
+ writer.WriteAttributeString("FilePath", payload.Name);
692
+ writer.WriteAttributeString("FileSize", payload.FileSize.Value.ToString(CultureInfo.InvariantCulture));
693
+ writer.WriteAttributeString("Hash", payload.Hash);
694
+ writer.WriteAttributeString("Packaging", "embedded");
695
+ writer.WriteAttributeString("SourcePath", payload.EmbeddedId);
696
+
697
+ writer.WriteEndElement();
698
}
699
}
700
}
src/WixToolset.Core.Burn/Bundles/CreateContainerCommand.cs
-7
@@ -44,13 +44,6 @@ namespace WixToolset.Core.Burn.Bundles
44
45
public void Execute()
46
{
47
- var payloadCount = this.Payloads.Count(); // The number of embedded payloads
48
-
49
- if (!String.IsNullOrEmpty(this.ManifestFile))
50
- {
51
- ++payloadCount;
52
- }
53
-
47
var cabinetPath = Path.GetFullPath(this.OutputPath);
48
49
var files = new List<CabinetCompressFile>();
src/WixToolset.Core/Compile/CompilerPayload.cs
+2
-9
@@ -15,8 +15,6 @@ namespace WixToolset.Core
15
16
public string Description { get; set; }
17
18
- public string DisplayName { get; set; }
19
-
18
public string DownloadUrl { get; set; }
19
20
public string Hash { get; set; }
@@ -158,7 +156,7 @@ namespace WixToolset.Core
156
157
if (!String.IsNullOrEmpty(this.DownloadUrl))
158
{
161
- this.Core.Write(WarningMessages.DownloadUrlNotSupportedForEmbeddedPayloads(this.SourceLineNumbers, this.Id.Id));
159
+ this.Core.Write(WarningMessages.DownloadUrlNotSupportedForBAPayloads(this.SourceLineNumbers, this.Id.Id));
160
}
161
162
this.Compressed = YesNoDefaultType.Yes;
@@ -174,7 +172,7 @@ namespace WixToolset.Core
172
DownloadUrl = this.DownloadUrl,
173
Compressed = (this.Compressed == YesNoDefaultType.Yes) ? true : (this.Compressed == YesNoDefaultType.No) ? (bool?)false : null,
174
UnresolvedSourceFile = this.SourceFile, // duplicate of sourceFile but in a string column so it won't get resolved to a full path during binding.
177
- DisplayName = this.DisplayName ?? this.ProductName,
175
+ DisplayName = this.ProductName,
176
Description = this.Description,
177
Hash = this.Hash,
178
FileSize = this.Size,
@@ -245,11 +243,6 @@ namespace WixToolset.Core
243
this.Description = this.Core.GetAttributeValue(this.SourceLineNumbers, attrib);
244
}
245
248
- public void ParseDisplayName(XAttribute attrib)
249
- {
250
- this.DisplayName = this.Core.GetAttributeValue(this.SourceLineNumbers, attrib);
251
- }
252
-
246
public void ParseDownloadUrl(XAttribute attrib)
247
{
248
this.DownloadUrl = this.Core.GetAttributeValue(this.SourceLineNumbers, attrib);
src/test/WixToolsetTest.CoreIntegration/ContainerFixture.cs
+47
-3
@@ -15,6 +15,50 @@ namespace WixToolsetTest.CoreIntegration
15
16
public class ContainerFixture
17
{
18
+ [Fact(Skip = "Test demonstrates failure")]
19
+ public void CanBuildWithCustomAttachedContainer()
20
+ {
21
+ var folder = TestData.Get(@"TestData");
22
+
23
+ using (var fs = new DisposableFileSystem())
24
+ {
25
+ var baseFolder = fs.GetFolder();
26
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
27
+ var binFolder = Path.Combine(baseFolder, "bin");
28
+ var bundlePath = Path.Combine(binFolder, "test.exe");
29
+ var baFolderPath = Path.Combine(baseFolder, "ba");
30
+ var extractFolderPath = Path.Combine(baseFolder, "extract");
31
+
32
+ this.BuildMsis(folder, intermediateFolder, binFolder, buildToSubfolder: true);
33
+
34
+ var result = WixRunner.Execute(new[]
35
+ {
36
+ "build",
37
+ Path.Combine(folder, "Container", "HarvestIntoAttachedContainer.wxs"),
38
+ Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"),
39
+ "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
40
+ "-bindpath", binFolder,
41
+ "-intermediateFolder", intermediateFolder,
42
+ "-o", bundlePath
43
+ });
44
+
45
+ result.AssertSuccess();
46
+
47
+ Assert.True(File.Exists(bundlePath));
48
+
49
+ var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
50
+ extractResult.AssertSuccess();
51
+
52
+ var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload");
53
+ Assert.Equal(4, payloads.Count);
54
+ var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } };
55
+ Assert.Equal(@"<Payload Id='FirstX64' FilePath='FirstX64\FirstX64.msi' FileSize='*' Hash='*' DownloadUrl='http://example.com//FirstX64/FirstX64/FirstX64.msi' Packaging='embedded' SourcePath='a0' Container='BundlePackages' />", payloads[0].GetTestXml(ignoreAttributes));
56
+ Assert.Equal(@"<Payload Id='FirstX86.msi' FilePath='FirstX86\FirstX86.msi' FileSize='*' Hash='*' DownloadUrl='http://example.com//FirstX86.msi/FirstX86/FirstX86.msi' Packaging='embedded' SourcePath='a1' Container='BundlePackages' />", payloads[1].GetTestXml(ignoreAttributes));
57
+ Assert.Equal(@"<Payload Id='fk1m38Cf9RZ2Bx_ipinRY6BftelU' FilePath='FirstX86\PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' DownloadUrl='http://example.com/FirstX86/fk1m38Cf9RZ2Bx_ipinRY6BftelU/FirstX86/PFiles/MsiPackage/test.txt' Packaging='embedded' SourcePath='a2' Container='BundlePackages' />", payloads[2].GetTestXml(ignoreAttributes));
58
+ Assert.Equal(@"<Payload Id='ff2L_N_DLQ.nSUi.l8LxG14gd2V4' FilePath='FirstX64\PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' DownloadUrl='http://example.com/FirstX64/ff2L_N_DLQ.nSUi.l8LxG14gd2V4/FirstX64/PFiles/MsiPackage/test.txt' Packaging='embedded' SourcePath='a3' Container='BundlePackages' />", payloads[3].GetTestXml(ignoreAttributes));
59
+ }
60
+ }
61
+
62
[Fact]
63
public void HarvestedPayloadsArePutInCorrectContainer()
64
{
@@ -309,7 +353,7 @@ namespace WixToolsetTest.CoreIntegration
353
}
354
}
355
312
- private void BuildMsis(string folder, string intermediateFolder, string binFolder)
356
+ private void BuildMsis(string folder, string intermediateFolder, string binFolder, bool buildToSubfolder = false)
357
{
358
var result = WixRunner.Execute(new[]
359
{
@@ -319,7 +363,7 @@ namespace WixToolsetTest.CoreIntegration
363
Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
364
"-bindpath", Path.Combine(folder, "SingleFile", "data"),
365
"-intermediateFolder", intermediateFolder,
322
- "-o", Path.Combine(binFolder, "FirstX86.msi"),
366
+ "-o", Path.Combine(binFolder, buildToSubfolder ? "FirstX86" : ".", "FirstX86.msi"),
367
});
368
369
result.AssertSuccess();
@@ -332,7 +376,7 @@ namespace WixToolsetTest.CoreIntegration
376
Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
377
"-bindpath", Path.Combine(folder, "SingleFile", "data"),
378
"-intermediateFolder", intermediateFolder,
335
- "-o", Path.Combine(binFolder, "FirstX64.msi"),
379
+ "-o", Path.Combine(binFolder, buildToSubfolder ? "FirstX64" : ".", "FirstX64.msi"),
380
});
381
382
result.AssertSuccess();
src/test/WixToolsetTest.CoreIntegration/TestData/Container/HarvestIntoAttachedContainer.wxs
new
+17
@@ -0,0 +1,17 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3
+ <Fragment>
4
+ <PackageGroup Id="BundlePackages">
5
+ <MsiPackage Id="FirstX86">
6
+ <PayloadGroupRef Id="FirstX86Payloads" />
7
+ </MsiPackage>
8
+ <MsiPackage Id="FirstX64" Name="FirstX64\FirstX64.msi" SourceFile="FirstX64\" DownloadUrl="http://example.com/{0}/{1}/{2}" />
9
+ </PackageGroup>
10
+ <Container Id="BundlePackages" Type="attached">
11
+ <PackageGroupRef Id="BundlePackages" />
12
+ </Container>
13
+ <PayloadGroup Id="FirstX86Payloads">
14
+ <MsiPackagePayload Name="FirstX86\FirstX86.msi" SourceFile="FirstX86\" DownloadUrl="http://example.com/{0}/{1}/{2}" />
15
+ </PayloadGroup>
16
+ </Fragment>
17
+</Wix>