Resolve container and payload DownloadUrls
Fixes wixtoolset/issues#6405
Rob Mensching committed
Apr 19, 2021 at 12:49 UTC
c76db43a5ce1da70a980dc5651141c2a6cd94f6b
4 files changed
+138
-48
src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+7
-1
@@ -459,12 +459,18 @@ namespace WixToolset.Core.Burn
459
containers = command.Containers;
460
}
461
462
+ // Resolve the download URLs now that we have all of the containers and payloads calculated.
463
+ {
464
+ var command = new ResolveDownloadUrlsCommand(this.Messaging, this.BackendExtensions, containers, payloadSymbols);
465
+ command.Execute();
466
+ }
467
+
468
// Create the bundle manifest.
469
string manifestPath;
470
{
471
var executableName = Path.GetFileName(this.OutputPath);
472
467
- var command = new CreateBurnManifestCommand(this.Messaging, this.BackendExtensions, executableName, section, bundleSymbol, containers, chainSymbol, orderedFacades, boundaries, uxPayloads, payloadSymbols, packagesPayloads, orderedSearches, this.IntermediateFolder);
473
+ var command = new CreateBurnManifestCommand(executableName, section, bundleSymbol, containers, chainSymbol, orderedFacades, boundaries, uxPayloads, payloadSymbols, packagesPayloads, orderedSearches, this.IntermediateFolder);
474
command.Execute();
475
476
manifestPath = command.OutputPath;
src/WixToolset.Core.Burn/Bind/ResolveDownloadUrlsCommand.cs
new
+127
@@ -0,0 +1,127 @@
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.Bind
4
+{
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using WixToolset.Data;
8
+ using WixToolset.Data.Symbols;
9
+ using WixToolset.Extensibility;
10
+ using WixToolset.Extensibility.Services;
11
+
12
+ internal class ResolveDownloadUrlsCommand
13
+ {
14
+ public ResolveDownloadUrlsCommand(IMessaging messaging, IEnumerable<IBurnBackendBinderExtension> backendExtensions, IEnumerable<WixBundleContainerSymbol> containers, Dictionary<string, WixBundlePayloadSymbol> payloadsById)
15
+ {
16
+ this.Messaging = messaging;
17
+ this.BackendExtensions = backendExtensions;
18
+ this.Containers = containers;
19
+ this.PayloadsById = payloadsById;
20
+ }
21
+
22
+ private IMessaging Messaging { get; }
23
+
24
+ private IEnumerable<IBurnBackendBinderExtension> BackendExtensions { get; }
25
+
26
+ private IEnumerable<WixBundleContainerSymbol> Containers { get; }
27
+
28
+ private Dictionary<string, WixBundlePayloadSymbol> PayloadsById { get; }
29
+
30
+ public void Execute()
31
+ {
32
+ this.ResolveContainerUrls();
33
+
34
+ this.ResolvePayloadUrls();
35
+ }
36
+
37
+ private void ResolveContainerUrls()
38
+ {
39
+ foreach (var container in this.Containers)
40
+ {
41
+ if (container.Type == ContainerType.Detached)
42
+ {
43
+ var resolvedUrl = this.ResolveUrl(container.DownloadUrl, null, null, container.Id.Id, container.Name);
44
+ if (!String.IsNullOrEmpty(resolvedUrl))
45
+ {
46
+ container.DownloadUrl = resolvedUrl;
47
+ }
48
+ }
49
+ else if (container.Type == ContainerType.Attached)
50
+ {
51
+ if (!String.IsNullOrEmpty(container.DownloadUrl))
52
+ {
53
+ this.Messaging.Write(WarningMessages.DownloadUrlNotSupportedForAttachedContainers(container.SourceLineNumbers, container.Id.Id));
54
+ }
55
+ }
56
+ }
57
+ }
58
+
59
+ private void ResolvePayloadUrls()
60
+ {
61
+ foreach (var payload in this.PayloadsById.Values)
62
+ {
63
+ if (payload.Packaging == PackagingType.External)
64
+ {
65
+ var packageId = payload.ParentPackagePayloadRef;
66
+ var parentUrl = payload.ParentPackagePayloadRef == null ? null : this.PayloadsById[payload.ParentPackagePayloadRef].DownloadUrl;
67
+ var resolvedUrl = this.ResolveUrl(payload.DownloadUrl, parentUrl, packageId, payload.Id.Id, payload.Name);
68
+ if (!String.IsNullOrEmpty(resolvedUrl))
69
+ {
70
+ payload.DownloadUrl = resolvedUrl;
71
+ }
72
+ }
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
+ }
80
+ }
81
+ }
82
+
83
+ private string ResolveUrl(string url, string fallbackUrl, string packageId, string payloadId, string fileName)
84
+ {
85
+ string resolvedUrl = null;
86
+
87
+ foreach (var extension in this.BackendExtensions)
88
+ {
89
+ resolvedUrl = extension.ResolveUrl(url, fallbackUrl, packageId, payloadId, fileName);
90
+ if (!String.IsNullOrEmpty(resolvedUrl))
91
+ {
92
+ break;
93
+ }
94
+ }
95
+
96
+ if (String.IsNullOrEmpty(resolvedUrl))
97
+ {
98
+ // If a URL was not specified but there is a fallback URL that has a format specifier in it
99
+ // then use the fallback URL formatter for this URL.
100
+ if (String.IsNullOrEmpty(url) && !String.IsNullOrEmpty(fallbackUrl))
101
+ {
102
+ var formattedFallbackUrl = String.Format(fallbackUrl, packageId, payloadId, fileName);
103
+ if (!String.Equals(fallbackUrl, formattedFallbackUrl, StringComparison.OrdinalIgnoreCase))
104
+ {
105
+ url = fallbackUrl;
106
+ }
107
+ }
108
+
109
+ if (!String.IsNullOrEmpty(url))
110
+ {
111
+ var formattedUrl = String.Format(url, packageId, payloadId, fileName);
112
+
113
+ if (Uri.TryCreate(formattedUrl, UriKind.Absolute, out var canonicalUri))
114
+ {
115
+ resolvedUrl = canonicalUri.AbsoluteUri;
116
+ }
117
+ else
118
+ {
119
+ resolvedUrl = null;
120
+ }
121
+ }
122
+ }
123
+
124
+ return resolvedUrl;
125
+ }
126
+ }
127
+}
src/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
+3
-46
@@ -18,10 +18,8 @@ namespace WixToolset.Core.Burn.Bundles
18
19
internal class CreateBurnManifestCommand
20
{
21
- public CreateBurnManifestCommand(IMessaging messaging, IEnumerable<IBurnBackendBinderExtension> backendExtensions, string executableName, IntermediateSection section, WixBundleSymbol bundleSymbol, IEnumerable<WixBundleContainerSymbol> containers, WixChainSymbol chainSymbol, IEnumerable<PackageFacade> orderedPackages, IEnumerable<WixBundleRollbackBoundarySymbol> boundaries, IEnumerable<WixBundlePayloadSymbol> uxPayloads, Dictionary<string, WixBundlePayloadSymbol> allPayloadsById, Dictionary<string, Dictionary<string, WixBundlePayloadSymbol>> packagesPayloads, IEnumerable<ISearchFacade> orderedSearches, string intermediateFolder)
21
+ public CreateBurnManifestCommand(string executableName, IntermediateSection section, WixBundleSymbol bundleSymbol, IEnumerable<WixBundleContainerSymbol> containers, WixChainSymbol chainSymbol, IEnumerable<PackageFacade> orderedPackages, IEnumerable<WixBundleRollbackBoundarySymbol> boundaries, IEnumerable<WixBundlePayloadSymbol> uxPayloads, Dictionary<string, WixBundlePayloadSymbol> allPayloadsById, Dictionary<string, Dictionary<string, WixBundlePayloadSymbol>> packagesPayloads, IEnumerable<ISearchFacade> orderedSearches, string intermediateFolder)
22
{
23
- this.Messaging = messaging;
24
- this.BackendExtensions = backendExtensions;
23
this.ExecutableName = executableName;
24
this.Section = section;
25
this.BundleSymbol = bundleSymbol;
@@ -38,10 +36,6 @@ namespace WixToolset.Core.Burn.Bundles
36
37
public string OutputPath { get; private set; }
38
41
- private IMessaging Messaging { get; }
42
-
43
- private IEnumerable<IBurnBackendBinderExtension> BackendExtensions { get; }
44
-
39
private string ExecutableName { get; }
40
41
private IntermediateSection Section { get; }
@@ -657,12 +651,7 @@ namespace WixToolset.Core.Burn.Bundles
651
652
if (ContainerType.Detached == container.Type)
653
{
660
- string resolvedUrl = this.ResolveUrl(container.DownloadUrl, null, null, container.Id.Id, container.Name);
661
- if (!String.IsNullOrEmpty(resolvedUrl))
662
- {
663
- writer.WriteAttributeString("DownloadUrl", resolvedUrl);
664
- }
665
- else if (!String.IsNullOrEmpty(container.DownloadUrl))
654
+ if (!String.IsNullOrEmpty(container.DownloadUrl))
655
{
656
writer.WriteAttributeString("DownloadUrl", container.DownloadUrl);
657
}
@@ -671,11 +660,6 @@ namespace WixToolset.Core.Burn.Bundles
660
}
661
else if (ContainerType.Attached == container.Type)
662
{
674
- if (!String.IsNullOrEmpty(container.DownloadUrl))
675
- {
676
- this.Messaging.Write(WarningMessages.DownloadUrlNotSupportedForAttachedContainers(container.SourceLineNumbers, container.Id.Id));
677
- }
678
-
663
writer.WriteAttributeString("FilePath", executableName); // attached containers use the name of the bundle since they are attached to the executable.
664
writer.WriteAttributeString("AttachedIndex", container.AttachedContainerIndex.Value.ToString(CultureInfo.InvariantCulture));
665
writer.WriteAttributeString("Attached", "yes");
@@ -700,11 +684,6 @@ namespace WixToolset.Core.Burn.Bundles
684
switch (payload.Packaging)
685
{
686
case PackagingType.Embedded: // this means it's in a container.
703
- if (!String.IsNullOrEmpty(payload.DownloadUrl))
704
- {
705
- this.Messaging.Write(WarningMessages.DownloadUrlNotSupportedForEmbeddedPayloads(payload.SourceLineNumbers, payload.Id.Id));
706
- }
707
-
687
writer.WriteAttributeString("Packaging", "embedded");
688
writer.WriteAttributeString("SourcePath", payload.EmbeddedId);
689
@@ -715,14 +694,7 @@ namespace WixToolset.Core.Burn.Bundles
694
break;
695
696
case PackagingType.External:
718
- var packageId = payload.ParentPackagePayloadRef;
719
- var parentUrl = payload.ParentPackagePayloadRef == null ? null : allPayloads[payload.ParentPackagePayloadRef].DownloadUrl;
720
- var resolvedUrl = this.ResolveUrl(payload.DownloadUrl, parentUrl, packageId, payload.Id.Id, payload.Name);
721
- if (!String.IsNullOrEmpty(resolvedUrl))
722
- {
723
- writer.WriteAttributeString("DownloadUrl", resolvedUrl);
724
- }
725
- else if (!String.IsNullOrEmpty(payload.DownloadUrl))
697
+ if (!String.IsNullOrEmpty(payload.DownloadUrl))
698
{
699
writer.WriteAttributeString("DownloadUrl", payload.DownloadUrl);
700
}
@@ -732,20 +704,5 @@ namespace WixToolset.Core.Burn.Bundles
704
break;
705
}
706
}
735
-
736
- private string ResolveUrl(string url, string fallbackUrl, string packageId, string payloadId, string fileName)
737
- {
738
- string resolved = null;
739
- foreach (var extension in this.BackendExtensions)
740
- {
741
- resolved = extension.ResolveUrl(url, fallbackUrl, packageId, payloadId, fileName);
742
- if (!String.IsNullOrEmpty(resolved))
743
- {
744
- break;
745
- }
746
- }
747
-
748
- return resolved;
749
- }
707
}
708
}
src/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs
+1
-1
@@ -143,7 +143,7 @@ namespace WixToolsetTest.CoreIntegration
143
}
144
}
145
146
- [Fact(Skip = "Test demonstrates failure")]
146
+ [Fact]
147
public void ReplacesDownloadUrlPlaceholders()
148
{
149
var folder = TestData.Get(@"TestData");