@joebigelow / wix / commits / eab59ecb

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 +}