Try to convert the MBA prereq magic variables to the new attributes.
Fixes 7026
Sean Hall committed
Dec 11, 2022 at 21:07 UTC
eab59ecbfd254bb8707615bc31b840339a6356d6
5 files changed
+210
-26
src/ext/Bal/test/WixToolsetTest.Bal/BalExtensionFixture.cs
+1
-1
@@ -177,7 +177,7 @@ namespace WixToolsetTest.Bal
177
"-o", bundleFile,
178
});
179
Assert.Equal(6802, compileResult.ExitCode);
180
- WixAssert.StringEqual("There must be at least one PrereqPackage when using the ManagedBootstrapperApplicationHost.\nThis is typically done by using the WixNetFxExtension and referencing one of the NetFxAsPrereq package groups.", compileResult.Messages[0].ToString());
180
+ WixAssert.StringEqual("There must be at least one package with bal:PrereqPackage=\"yes\" when using the ManagedBootstrapperApplicationHost.\nThis is typically done by using the WixNetFxExtension and referencing one of the NetFxAsPrereq package groups.", compileResult.Messages[0].ToString());
181
182
Assert.False(File.Exists(bundleFile));
183
Assert.False(File.Exists(Path.Combine(intermediateFolder, "test.exe")));
src/ext/Bal/wixext/BalErrors.cs
+2
-2
@@ -45,7 +45,7 @@ namespace WixToolset.Bal
45
46
public static Message MissingDNCPrereq()
47
{
48
- return Message(null, Ids.MissingDNCPrereq, "There must be at least one PrereqPackage when using the DotNetCoreBootstrapperApplicationHost with SelfContainedDeployment set to \"no\".");
48
+ return Message(null, Ids.MissingDNCPrereq, "There must be at least one package with bal:PrereqPackage=\"yes\" when using the DotNetCoreBootstrapperApplicationHost with SelfContainedDeployment set to \"no\".");
49
}
50
51
public static Message MissingIUIPrimaryPackage()
@@ -55,7 +55,7 @@ namespace WixToolset.Bal
55
56
public static Message MissingMBAPrereq()
57
{
58
- return Message(null, Ids.MissingMBAPrereq, "There must be at least one PrereqPackage when using the ManagedBootstrapperApplicationHost.\nThis is typically done by using the WixNetFxExtension and referencing one of the NetFxAsPrereq package groups.");
58
+ return Message(null, Ids.MissingMBAPrereq, "There must be at least one package with bal:PrereqPackage=\"yes\" when using the ManagedBootstrapperApplicationHost.\nThis is typically done by using the WixNetFxExtension and referencing one of the NetFxAsPrereq package groups.");
59
}
60
61
public static Message MultipleBAFunctions(SourceLineNumber sourceLineNumbers)
src/wix/WixToolset.Converters/ConversionState.cs
+9
@@ -21,6 +21,9 @@ namespace WixToolset.Converters
21
public ConversionState(ConvertOperation operation, string sourceFile)
22
{
23
this.ConversionMessages = new List<Message>();
24
+ this.ChainPackageElementsById = new Dictionary<string, List<XElement>>();
25
+ this.WixMbaPrereqPackageIdElements = new List<XElement>();
26
+ this.WixMbaPrereqLicenseUrlElements = new List<XElement>();
27
this.Operation = operation;
28
this.SourceFile = sourceFile;
29
this.SourceVersion = 0;
@@ -28,6 +31,12 @@ namespace WixToolset.Converters
31
32
public List<Message> ConversionMessages { get; }
33
34
+ public Dictionary<string, List<XElement>> ChainPackageElementsById { get; }
35
+
36
+ public List<XElement> WixMbaPrereqPackageIdElements { get; }
37
+
38
+ public List<XElement> WixMbaPrereqLicenseUrlElements { get; }
39
+
40
public ConvertOperation Operation { get; }
41
42
public string SourceFile { get; }
src/wix/WixToolset.Converters/WixConverter.cs
+104
-23
@@ -131,6 +131,8 @@ namespace WixToolset.Converters
131
private static readonly XName UITextElementName = WixNamespace + "UIText";
132
private static readonly XName VariableElementName = WixNamespace + "Variable";
133
private static readonly XName VerbElementName = WixNamespace + "Verb";
134
+ private static readonly XName BalPrereqLicenseUrlAttributeName = WixBalNamespace + "PrereqLicenseUrl";
135
+ private static readonly XName BalPrereqPackageAttributeName = WixBalNamespace + "PrereqPackage";
136
private static readonly XName BalUseUILanguagesName = WixBalNamespace + "UseUILanguages";
137
private static readonly XName BalStandardBootstrapperApplicationName = WixBalNamespace + "WixStandardBootstrapperApplication";
138
private static readonly XName BalManagedBootstrapperApplicationHostName = WixBalNamespace + "WixManagedBootstrapperApplicationHost";
@@ -147,6 +149,7 @@ namespace WixToolset.Converters
149
private static readonly XName Wix4ElementName = WixNamespace + "Wix";
150
private static readonly XName Wix3ElementName = Wix3Namespace + "Wix";
151
private static readonly XName WixElementWithoutNamespaceName = XNamespace.None + "Wix";
152
+ private static readonly XName WixVariableElementName = WixNamespace + "WixVariable";
153
private static readonly XName Include4ElementName = WixNamespace + "Include";
154
private static readonly XName Include3ElementName = Wix3Namespace + "Include";
155
private static readonly XName IncludeElementWithoutNamespaceName = XNamespace.None + "Include";
@@ -164,11 +167,11 @@ namespace WixToolset.Converters
167
168
private static readonly Dictionary<string, XNamespace> OldToNewNamespaceMapping = new Dictionary<string, XNamespace>()
169
{
167
- { "http://schemas.microsoft.com/wix/BalExtension", "http://wixtoolset.org/schemas/v4/wxs/bal" },
170
+ { "http://schemas.microsoft.com/wix/BalExtension", WixBalNamespace },
171
{ "http://schemas.microsoft.com/wix/ComPlusExtension", "http://wixtoolset.org/schemas/v4/wxs/complus" },
172
{ "http://schemas.microsoft.com/wix/DependencyExtension", WixDependencyNamespace },
173
{ "http://schemas.microsoft.com/wix/DifxAppExtension", "http://wixtoolset.org/schemas/v4/wxs/difxapp" },
171
- { "http://schemas.microsoft.com/wix/FirewallExtension", "http://wixtoolset.org/schemas/v4/wxs/firewall" },
174
+ { "http://schemas.microsoft.com/wix/FirewallExtension", WixFirewallNamespace },
175
{ "http://schemas.microsoft.com/wix/HttpExtension", "http://wixtoolset.org/schemas/v4/wxs/http" },
176
{ "http://schemas.microsoft.com/wix/IIsExtension", "http://wixtoolset.org/schemas/v4/wxs/iis" },
177
{ "http://schemas.microsoft.com/wix/MsmqExtension", "http://wixtoolset.org/schemas/v4/wxs/msmq" },
@@ -177,7 +180,7 @@ namespace WixToolset.Converters
180
{ "http://schemas.microsoft.com/wix/SqlExtension", "http://wixtoolset.org/schemas/v4/wxs/sql" },
181
{ "http://schemas.microsoft.com/wix/TagExtension", XNamespace.None },
182
{ "http://schemas.microsoft.com/wix/UtilExtension", WixUtilNamespace },
180
- { "http://schemas.microsoft.com/wix/VSExtension", "http://wixtoolset.org/schemas/v4/wxs/vs" },
183
+ { "http://schemas.microsoft.com/wix/VSExtension", WixVSNamespace },
184
{ "http://wixtoolset.org/schemas/thmutil/2010", "http://wixtoolset.org/schemas/v4/thmutil" },
185
{ "http://schemas.microsoft.com/wix/2009/Lux", "http://wixtoolset.org/schemas/v4/lux" },
186
{ "http://schemas.microsoft.com/wix/2006/wi", "http://wixtoolset.org/schemas/v4/wxs" },
@@ -394,7 +397,7 @@ namespace WixToolset.Converters
397
398
if (this.TryOpenSourceFile(ConvertOperation.Convert, sourceFile))
399
{
397
- this.Convert(this.State.XDocument);
400
+ this.DoIt(this.State.XDocument);
401
402
// Fix Messages if requested and necessary.
403
if (saveConvertedFile && 0 < this.ConversionMessages.Count)
@@ -416,7 +419,7 @@ namespace WixToolset.Converters
419
{
420
this.State = new ConversionState(ConvertOperation.Convert, sourceFile);
421
this.State.Initialize(document);
419
- this.Convert(document);
422
+ this.DoIt(document);
423
424
return this.ReportMessages(document, false);
425
}
@@ -455,28 +458,12 @@ namespace WixToolset.Converters
458
{
459
this.State = new ConversionState(ConvertOperation.Format, sourceFile);
460
this.State.Initialize(document);
458
- this.Format(document);
461
+ this.DoIt(document);
462
463
return this.ReportMessages(document, false);
464
}
465
463
- private void Convert(XDocument document)
464
- {
465
- // Remove the declaration.
466
- if (null != document.Declaration
467
- && this.OnInformation(ConverterTestType.DeclarationPresent, document, "This file contains an XML declaration on the first line."))
468
- {
469
- document.Declaration = null;
470
- TrimLeadingText(document);
471
- }
472
-
473
- // Start converting the nodes at the top.
474
- this.ConvertNodes(document.Nodes(), 0);
475
- this.RemoveUnusedNamespaces(document.Root);
476
- this.MoveNamespacesToRoot(document.Root);
477
- }
478
-
479
- private void Format(XDocument document)
466
+ private void DoIt(XDocument document)
467
{
468
// Remove the declaration.
469
if (null != document.Declaration
@@ -488,6 +475,7 @@ namespace WixToolset.Converters
475
476
// Start converting the nodes at the top.
477
this.ConvertNodes(document.Nodes(), 0);
478
+ this.ConvertMbaPrereqVariables();
479
this.RemoveUnusedNamespaces(document.Root);
480
this.MoveNamespacesToRoot(document.Root);
481
}
@@ -2309,6 +2297,89 @@ namespace WixToolset.Converters
2297
whitespace.Value = value.Append(' ', level * indentationAmount).ToString();
2298
}
2299
2300
+ private void ConvertMbaPrereqVariables()
2301
+ {
2302
+ XElement root = this.XRoot;
2303
+ VisitElement(root, x =>
2304
+ {
2305
+ if (x is XElement e && e.Attribute("Id") is XAttribute a)
2306
+ {
2307
+ if (e.Name == ExePackageElementName || e.Name == MsiPackageElementName ||
2308
+ e.Name == MspPackageElementName || e.Name == MsuPackageElementName)
2309
+ {
2310
+ if (!this.State.ChainPackageElementsById.TryGetValue(a.Value, out var elements))
2311
+ {
2312
+ elements = new List<XElement>();
2313
+ this.State.ChainPackageElementsById.Add(a.Value, elements);
2314
+ }
2315
+
2316
+ elements.Add(e);
2317
+ }
2318
+ else if (e.Name == WixVariableElementName && e.Attribute("Value") != null)
2319
+ {
2320
+ switch (a.Value)
2321
+ {
2322
+ case "WixMbaPrereqPackageId":
2323
+ this.State.WixMbaPrereqPackageIdElements.Add(e);
2324
+ break;
2325
+ case "WixMbaPrereqLicenseUrl":
2326
+ this.State.WixMbaPrereqLicenseUrlElements.Add(e);
2327
+ break;
2328
+ }
2329
+ }
2330
+ }
2331
+ return true;
2332
+ });
2333
+
2334
+ if (this.State.WixMbaPrereqPackageIdElements.Count == 1 && this.State.WixMbaPrereqLicenseUrlElements.Count < 2)
2335
+ {
2336
+ var wixMbaPrereqPackageIdElement = this.State.WixMbaPrereqPackageIdElements[0];
2337
+ var packageId = wixMbaPrereqPackageIdElement.Attribute("Value")?.Value;
2338
+ if (this.State.ChainPackageElementsById.TryGetValue(packageId, out var packageElements) && packageElements.Count == 1)
2339
+ {
2340
+ var packageElement = packageElements[0];
2341
+
2342
+ if (this.OnInformation(ConverterTestType.WixMbaPrereqPackageIdDeprecated, wixMbaPrereqPackageIdElement, "The magic WixVariable 'WixMbaPrereqPackageId' has been removed. Add bal:PrereqPackage=\"yes\" to the target package instead."))
2343
+ {
2344
+ packageElement.Add(new XAttribute(BalPrereqPackageAttributeName, "yes"));
2345
+
2346
+ using (var lab = new ConversionLab(wixMbaPrereqPackageIdElement))
2347
+ {
2348
+ lab.RemoveTargetElement();
2349
+ }
2350
+
2351
+ this.State.WixMbaPrereqPackageIdElements.Clear();
2352
+ }
2353
+
2354
+ if (this.State.WixMbaPrereqLicenseUrlElements.Count == 1)
2355
+ {
2356
+ var wixMbaPrereqLicenseUrlElement = this.State.WixMbaPrereqLicenseUrlElements[0];
2357
+ if (this.OnInformation(ConverterTestType.WixMbaPrereqLicenseUrlDeprecated, wixMbaPrereqLicenseUrlElement, "The magic WixVariable 'WixMbaPrereqLicenseUrl' has been removed. Add bal:PrereqLicenseUrl=\"yes\" to a prereq package instead."))
2358
+ {
2359
+ var licenseUrl = wixMbaPrereqLicenseUrlElement.Attribute("Value")?.Value;
2360
+ packageElement.Add(new XAttribute(BalPrereqLicenseUrlAttributeName, licenseUrl));
2361
+ using (var lab = new ConversionLab(wixMbaPrereqLicenseUrlElement))
2362
+ {
2363
+ lab.RemoveTargetElement();
2364
+ }
2365
+
2366
+ this.State.WixMbaPrereqLicenseUrlElements.Clear();
2367
+ }
2368
+ }
2369
+ }
2370
+ }
2371
+
2372
+ foreach (var element in this.State.WixMbaPrereqPackageIdElements)
2373
+ {
2374
+ this.OnError(ConverterTestType.WixMbaPrereqPackageIdDeprecated, element, "The magic WixVariable 'WixMbaPrereqPackageId' has been removed. Add bal:PrereqPackage=\"yes\" to the target package instead.");
2375
+ }
2376
+
2377
+ foreach (var element in this.State.WixMbaPrereqLicenseUrlElements)
2378
+ {
2379
+ this.OnError(ConverterTestType.WixMbaPrereqLicenseUrlDeprecated, element, "The magic WixVariable 'WixMbaPrereqLicenseUrl' has been removed. Add bal:PrereqLicenseUrl=\"yes\" to a prereq package instead.");
2380
+ }
2381
+ }
2382
+
2383
/// <summary>
2384
/// Removes unused namespaces from the element and its children.
2385
/// </summary>
@@ -3203,6 +3274,16 @@ namespace WixToolset.Converters
3274
/// Referencing '{0}' directory directly is no longer supported. The DirectoryRef will not be removed but you will probably need to reference a more specific directory.
3275
/// </summary>
3276
EmptyStandardDirectoryRefNotConvertable,
3277
+
3278
+ /// <summary>
3279
+ /// The magic WixVariable 'WixMbaPrereqLicenseUrl' has been removed. Add bal:PrereqLicenseUrl="yes" to a prereq package instead.
3280
+ /// </summary>
3281
+ WixMbaPrereqLicenseUrlDeprecated,
3282
+
3283
+ /// <summary>
3284
+ /// The magic WixVariable 'WixMbaPrereqPackageId' has been removed. Add bal:PrereqPackage="yes" to the target package instead.
3285
+ /// </summary>
3286
+ WixMbaPrereqPackageIdDeprecated,
3287
}
3288
}
3289
}
src/wix/test/WixToolsetTest.Converters/PrereqPackageFixture.cs
new
+94
@@ -0,0 +1,94 @@
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 WixToolsetTest.Converters
4
+{
5
+ using System;
6
+ using System.Linq;
7
+ using System.Xml.Linq;
8
+ using WixInternal.TestSupport;
9
+ using WixToolset.Converters;
10
+ using WixToolsetTest.Converters.Mocks;
11
+ using Xunit;
12
+
13
+ public class PrereqPackageFixture : BaseConverterFixture
14
+ {
15
+ [Fact]
16
+ public void CanConvertWixMbaPrereqPackageIdToPrereqPackage()
17
+ {
18
+ var parse = String.Join(Environment.NewLine,
19
+ "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs' xmlns:bal='http://wixtoolset.org/schemas/v4/wxs/bal'>",
20
+ " <Fragment>",
21
+ " <WixVariable Id='WixMbaPrereqPackageId' Value='NetFx452Web' />",
22
+ " <WixVariable Id='WixMbaPrereqLicenseUrl' Value='$(var.NetFx452EulaLink)' Overridable='yes' />",
23
+ " <PackageGroup Id='NetFx452Web'>",
24
+ " <ExePackage Id='NetFx452Web' />",
25
+ " </PackageGroup>",
26
+ " </Fragment>",
27
+ "</Wix>");
28
+
29
+ var expected = new[]
30
+ {
31
+ "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\" xmlns:bal=\"http://wixtoolset.org/schemas/v4/wxs/bal\">",
32
+ " <Fragment><PackageGroup Id=\"NetFx452Web\">",
33
+ " <ExePackage Id=\"NetFx452Web\" bal:PrereqPackage=\"yes\" bal:PrereqLicenseUrl=\"$(var.NetFx452EulaLink)\" />",
34
+ " </PackageGroup>",
35
+ " </Fragment>",
36
+ "</Wix>"
37
+ };
38
+
39
+ var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
40
+
41
+ var messaging = new MockMessaging();
42
+ var converter = new WixConverter(messaging, 2, null, null);
43
+
44
+ var errors = converter.ConvertDocument(document);
45
+ Assert.Equal(2, errors);
46
+
47
+ var actualLines = UnformattedDocumentLines(document);
48
+ WixAssert.CompareLineByLine(new[]
49
+ {
50
+ "[Converted] The magic WixVariable 'WixMbaPrereqPackageId' has been removed. Add bal:PrereqPackage=\"yes\" to the target package instead. (WixMbaPrereqPackageIdDeprecated)",
51
+ "[Converted] The magic WixVariable 'WixMbaPrereqLicenseUrl' has been removed. Add bal:PrereqLicenseUrl=\"yes\" to a prereq package instead. (WixMbaPrereqLicenseUrlDeprecated)",
52
+ }, messaging.Messages.Select(m => m.ToString()).ToArray());
53
+ WixAssert.CompareLineByLine(expected, actualLines);
54
+ }
55
+
56
+ [Fact]
57
+ public void CanWarnAboutOrphanWixMbaPrereqPackageId()
58
+ {
59
+ var parse = String.Join(Environment.NewLine,
60
+ "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'>",
61
+ " <Fragment>",
62
+ " <WixVariable Id='WixMbaPrereqPackageId' Value='NetFx452Web' />",
63
+ " <WixVariable Id='WixMbaPrereqLicenseUrl' Value='$(var.NetFx452EulaLink)' Overridable='yes' />",
64
+ " </Fragment>",
65
+ "</Wix>");
66
+
67
+ var expected = new[]
68
+ {
69
+ "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
70
+ " <Fragment>",
71
+ " <WixVariable Id=\"WixMbaPrereqPackageId\" Value=\"NetFx452Web\" />",
72
+ " <WixVariable Id=\"WixMbaPrereqLicenseUrl\" Value=\"$(var.NetFx452EulaLink)\" Overridable=\"yes\" />",
73
+ " </Fragment>",
74
+ "</Wix>"
75
+ };
76
+
77
+ var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
78
+
79
+ var messaging = new MockMessaging();
80
+ var converter = new WixConverter(messaging, 2, null, null);
81
+
82
+ var errors = converter.ConvertDocument(document);
83
+ Assert.Equal(2, errors);
84
+
85
+ var actualLines = UnformattedDocumentLines(document);
86
+ WixAssert.CompareLineByLine(new[]
87
+ {
88
+ "The magic WixVariable 'WixMbaPrereqPackageId' has been removed. Add bal:PrereqPackage=\"yes\" to the target package instead. (WixMbaPrereqPackageIdDeprecated)",
89
+ "The magic WixVariable 'WixMbaPrereqLicenseUrl' has been removed. Add bal:PrereqLicenseUrl=\"yes\" to a prereq package instead. (WixMbaPrereqLicenseUrlDeprecated)",
90
+ }, messaging.Messages.Select(m => m.ToString()).ToArray());
91
+ WixAssert.CompareLineByLine(expected, actualLines);
92
+ }
93
+ }
94
+}