aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Converters
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-02-27 07:25:13 -0800
committerRob Mensching <rob@firegiant.com>2021-02-27 07:53:32 -0800
commite9ef9924b00fab9dc3988d10d50d1f11d1ddf097 (patch)
tree49f22441868035cf4f675c06f5f0331ef8226463 /src/WixToolset.Converters
parente0ef9e78ad5478abb650bbb004f7494f47896b0d (diff)
downloadwix-e9ef9924b00fab9dc3988d10d50d1f11d1ddf097.tar.gz
wix-e9ef9924b00fab9dc3988d10d50d1f11d1ddf097.tar.bz2
wix-e9ef9924b00fab9dc3988d10d50d1f11d1ddf097.zip
Convert Dependency elements to WiX v4 schema
Diffstat (limited to 'src/WixToolset.Converters')
-rw-r--r--src/WixToolset.Converters/WixConverter.cs136
1 files changed, 134 insertions, 2 deletions
diff --git a/src/WixToolset.Converters/WixConverter.cs b/src/WixToolset.Converters/WixConverter.cs
index 1ba28df3..c30a40ac 100644
--- a/src/WixToolset.Converters/WixConverter.cs
+++ b/src/WixToolset.Converters/WixConverter.cs
@@ -32,6 +32,7 @@ namespace WixToolset.Converters
32 private static readonly XNamespace WixNamespace = "http://wixtoolset.org/schemas/v4/wxs"; 32 private static readonly XNamespace WixNamespace = "http://wixtoolset.org/schemas/v4/wxs";
33 private static readonly XNamespace Wix3Namespace = "http://schemas.microsoft.com/wix/2006/wi"; 33 private static readonly XNamespace Wix3Namespace = "http://schemas.microsoft.com/wix/2006/wi";
34 private static readonly XNamespace WixBalNamespace = "http://wixtoolset.org/schemas/v4/wxs/bal"; 34 private static readonly XNamespace WixBalNamespace = "http://wixtoolset.org/schemas/v4/wxs/bal";
35 private static readonly XNamespace WixDependencyNamespace = "http://wixtoolset.org/schemas/v4/wxs/dependency";
35 private static readonly XNamespace WixUtilNamespace = "http://wixtoolset.org/schemas/v4/wxs/util"; 36 private static readonly XNamespace WixUtilNamespace = "http://wixtoolset.org/schemas/v4/wxs/util";
36 private static readonly XNamespace WixFirewallNamespace = "http://wixtoolset.org/schemas/v4/wxs/firewall"; 37 private static readonly XNamespace WixFirewallNamespace = "http://wixtoolset.org/schemas/v4/wxs/firewall";
37 38
@@ -53,6 +54,9 @@ namespace WixToolset.Converters
53 private static readonly XName CreateFolderElementName = WixNamespace + "CreateFolder"; 54 private static readonly XName CreateFolderElementName = WixNamespace + "CreateFolder";
54 private static readonly XName CustomTableElementName = WixNamespace + "CustomTable"; 55 private static readonly XName CustomTableElementName = WixNamespace + "CustomTable";
55 private static readonly XName DataElementName = WixNamespace + "Data"; 56 private static readonly XName DataElementName = WixNamespace + "Data";
57 private static readonly XName OldProvidesElementName = WixDependencyNamespace + "Provides";
58 private static readonly XName OldRequiresElementName = WixDependencyNamespace + "Requires";
59 private static readonly XName OldRequiresRefElementName = WixDependencyNamespace + "RequiresRef";
56 private static readonly XName DirectoryElementName = WixNamespace + "Directory"; 60 private static readonly XName DirectoryElementName = WixNamespace + "Directory";
57 private static readonly XName ErrorElementName = WixNamespace + "Error"; 61 private static readonly XName ErrorElementName = WixNamespace + "Error";
58 private static readonly XName FeatureElementName = WixNamespace + "Feature"; 62 private static readonly XName FeatureElementName = WixNamespace + "Feature";
@@ -72,6 +76,9 @@ namespace WixToolset.Converters
72 private static readonly XName ProductElementName = WixNamespace + "Product"; 76 private static readonly XName ProductElementName = WixNamespace + "Product";
73 private static readonly XName ProgressTextElementName = WixNamespace + "ProgressText"; 77 private static readonly XName ProgressTextElementName = WixNamespace + "ProgressText";
74 private static readonly XName PublishElementName = WixNamespace + "Publish"; 78 private static readonly XName PublishElementName = WixNamespace + "Publish";
79 private static readonly XName ProvidesElementName = WixNamespace + "Provides";
80 private static readonly XName RequiresElementName = WixNamespace + "Requires";
81 private static readonly XName RequiresRefElementName = WixNamespace + "RequiresRef";
75 private static readonly XName MultiStringValueElementName = WixNamespace + "MultiStringValue"; 82 private static readonly XName MultiStringValueElementName = WixNamespace + "MultiStringValue";
76 private static readonly XName RemotePayloadElementName = WixNamespace + "RemotePayload"; 83 private static readonly XName RemotePayloadElementName = WixNamespace + "RemotePayload";
77 private static readonly XName RegistrySearchElementName = WixNamespace + "RegistrySearch"; 84 private static readonly XName RegistrySearchElementName = WixNamespace + "RegistrySearch";
@@ -106,11 +113,14 @@ namespace WixToolset.Converters
106 private static readonly XName SummaryInformationElementName = WixNamespace + "SummaryInformation"; 113 private static readonly XName SummaryInformationElementName = WixNamespace + "SummaryInformation";
107 private static readonly XName MediaTemplateElementName = WixNamespace + "MediaTemplate"; 114 private static readonly XName MediaTemplateElementName = WixNamespace + "MediaTemplate";
108 115
116 private static readonly XName DependencyCheckAttributeName = WixDependencyNamespace + "Check";
117 private static readonly XName DependencyEnforceAttributeName = WixDependencyNamespace + "Enforce";
118
109 private static readonly Dictionary<string, XNamespace> OldToNewNamespaceMapping = new Dictionary<string, XNamespace>() 119 private static readonly Dictionary<string, XNamespace> OldToNewNamespaceMapping = new Dictionary<string, XNamespace>()
110 { 120 {
111 { "http://schemas.microsoft.com/wix/BalExtension", "http://wixtoolset.org/schemas/v4/wxs/bal" }, 121 { "http://schemas.microsoft.com/wix/BalExtension", "http://wixtoolset.org/schemas/v4/wxs/bal" },
112 { "http://schemas.microsoft.com/wix/ComPlusExtension", "http://wixtoolset.org/schemas/v4/wxs/complus" }, 122 { "http://schemas.microsoft.com/wix/ComPlusExtension", "http://wixtoolset.org/schemas/v4/wxs/complus" },
113 { "http://schemas.microsoft.com/wix/DependencyExtension", "http://wixtoolset.org/schemas/v4/wxs/dependency" }, 123 { "http://schemas.microsoft.com/wix/DependencyExtension", WixDependencyNamespace },
114 { "http://schemas.microsoft.com/wix/DifxAppExtension", "http://wixtoolset.org/schemas/v4/wxs/difxapp" }, 124 { "http://schemas.microsoft.com/wix/DifxAppExtension", "http://wixtoolset.org/schemas/v4/wxs/difxapp" },
115 { "http://schemas.microsoft.com/wix/FirewallExtension", "http://wixtoolset.org/schemas/v4/wxs/firewall" }, 125 { "http://schemas.microsoft.com/wix/FirewallExtension", "http://wixtoolset.org/schemas/v4/wxs/firewall" },
116 { "http://schemas.microsoft.com/wix/HttpExtension", "http://wixtoolset.org/schemas/v4/wxs/http" }, 126 { "http://schemas.microsoft.com/wix/HttpExtension", "http://wixtoolset.org/schemas/v4/wxs/http" },
@@ -174,6 +184,9 @@ namespace WixToolset.Converters
174 { WixConverter.MsiPackageElementName, this.ConvertWindowsInstallerPackageElement }, 184 { WixConverter.MsiPackageElementName, this.ConvertWindowsInstallerPackageElement },
175 { WixConverter.MspPackageElementName, this.ConvertWindowsInstallerPackageElement }, 185 { WixConverter.MspPackageElementName, this.ConvertWindowsInstallerPackageElement },
176 { WixConverter.MsuPackageElementName, this.ConvertSuppressSignatureValidation }, 186 { WixConverter.MsuPackageElementName, this.ConvertSuppressSignatureValidation },
187 { WixConverter.OldProvidesElementName, this.ConvertProvidesElement },
188 { WixConverter.OldRequiresElementName, this.ConvertRequiresElement },
189 { WixConverter.OldRequiresRefElementName, this.ConvertRequiresRefElement },
177 { WixConverter.PayloadElementName, this.ConvertSuppressSignatureValidation }, 190 { WixConverter.PayloadElementName, this.ConvertSuppressSignatureValidation },
178 { WixConverter.PermissionExElementName, this.ConvertPermissionExElement }, 191 { WixConverter.PermissionExElementName, this.ConvertPermissionExElement },
179 { WixConverter.ProductElementName, this.ConvertProductElement }, 192 { WixConverter.ProductElementName, this.ConvertProductElement },
@@ -275,6 +288,7 @@ namespace WixToolset.Converters
275 288
276 // Start converting the nodes at the top. 289 // Start converting the nodes at the top.
277 this.ConvertNodes(document.Nodes(), 0); 290 this.ConvertNodes(document.Nodes(), 0);
291 this.RemoveUnusedNamspaces(document.Root);
278 292
279 return this.Errors; 293 return this.Errors;
280 } 294 }
@@ -327,6 +341,7 @@ namespace WixToolset.Converters
327 341
328 // Start converting the nodes at the top. 342 // Start converting the nodes at the top.
329 this.ConvertNodes(document.Nodes(), 0); 343 this.ConvertNodes(document.Nodes(), 0);
344 this.RemoveUnusedNamspaces(document.Root);
330 345
331 return this.Errors; 346 return this.Errors;
332 } 347 }
@@ -1136,6 +1151,50 @@ namespace WixToolset.Converters
1136 1151
1137 private void ConvertShortcutPropertyElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); 1152 private void ConvertShortcutPropertyElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value");
1138 1153
1154 private void ConvertProvidesElement(XElement element)
1155 {
1156 if (this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The Provides element has been integrated into the WiX v4 namespace. Remove the namespace."))
1157 {
1158 element.Name = ProvidesElementName;
1159 }
1160
1161 if (element.Parent.Name == ComponentElementName &&
1162 this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The Provides element has been integrated into the WiX v4 namespace. Add the 'Check' attribute from the WixDependency.wixext to match v3 runtime behavior."))
1163 {
1164 element.Add(new XAttribute(DependencyCheckAttributeName, "yes"));
1165 }
1166 }
1167
1168 private void ConvertRequiresElement(XElement element)
1169 {
1170 if (this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The Requires element has been integrated into the WiX v4 namespace. Remove the namespace."))
1171 {
1172 element.Name = RequiresElementName;
1173 }
1174
1175 if (element.Parent.Name == ProvidesElementName &&
1176 element.Parent.Parent?.Name == ComponentElementName &&
1177 this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The Requires element has been integrated into the WiX v4 namespace. Add the 'Enforce' attribute from the WixDependency.wixext to match v3 runtime behavior."))
1178 {
1179 element.Add(new XAttribute(DependencyEnforceAttributeName, "yes"));
1180 }
1181 }
1182
1183 private void ConvertRequiresRefElement(XElement element)
1184 {
1185 if (this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The RequiresRef element has been integrated into the WiX v4 namespace. Remove the namespace."))
1186 {
1187 element.Name = RequiresRefElementName;
1188 }
1189
1190 if (element.Parent.Name == ProvidesElementName &&
1191 element.Parent.Parent?.Name == ComponentElementName &&
1192 this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The RequiresRef element has been integrated into the WiX v4 namespace. Add the 'Enforce' attribute from the WixDependency.wixext to match v3 runtime behavior."))
1193 {
1194 element.Add(new XAttribute(DependencyEnforceAttributeName, "yes"));
1195 }
1196 }
1197
1139 private void ConvertSuppressSignatureValidation(XElement element) 1198 private void ConvertSuppressSignatureValidation(XElement element)
1140 { 1199 {
1141 var suppressSignatureValidation = element.Attribute("SuppressSignatureValidation"); 1200 var suppressSignatureValidation = element.Attribute("SuppressSignatureValidation");
@@ -1149,7 +1208,7 @@ namespace WixToolset.Converters
1149 1208
1150 private void ConvertTagElement(XElement element) 1209 private void ConvertTagElement(XElement element)
1151 { 1210 {
1152 if (this.OnError(ConverterTestType.TagElementRenamed, element, "The Tag element has been renamed. Use the element 'SoftwareTag' name.")) 1211 if (this.OnError(ConverterTestType.TagElementRenamed, element, "The Tag element has been renamed. Use the 'SoftwareTag' element instead."))
1153 { 1212 {
1154 element.Name = SoftwareTagElementName; 1213 element.Name = SoftwareTagElementName;
1155 } 1214 }
@@ -1311,6 +1370,10 @@ namespace WixToolset.Converters
1311 element.Add(new XAttribute("Bitness", value)); 1370 element.Add(new XAttribute("Bitness", value));
1312 win64.Remove(); 1371 win64.Remove();
1313 } 1372 }
1373 //else if (this.OnError(ConverterTestType.BitnessAttributeRequired, element, "Use the Bitness attribute instead."))
1374 //{
1375 // element.Add(new XAttribute("Bitness", "always32"));
1376 //}
1314 1377
1315 var result = element.Attribute("Result")?.Value; 1378 var result = element.Attribute("Result")?.Value;
1316 if (result == null || result == "value") 1379 if (result == null || result == "value")
@@ -1461,6 +1524,50 @@ namespace WixToolset.Converters
1461 } 1524 }
1462 1525
1463 /// <summary> 1526 /// <summary>
1527 /// Removes unused namespaces from the element and its children.
1528 /// </summary>
1529 /// <param name="root">Root element to start at.</param>
1530 private void RemoveUnusedNamspaces(XElement root)
1531 {
1532 var declarations = new List<XAttribute>();
1533 var namespaces = new HashSet<string>();
1534
1535 VisitElement(root, x =>
1536 {
1537 if (x is XAttribute a && a.IsNamespaceDeclaration)
1538 {
1539 declarations.Add(a);
1540 namespaces.Add(a.Value);
1541 }
1542 return true;
1543 });
1544
1545 foreach (var ns in namespaces.ToList())
1546 {
1547 VisitElement(root, x =>
1548 {
1549 if ((x is XElement e && e.Name.Namespace == ns) ||
1550 (x is XAttribute a && !a.IsNamespaceDeclaration && a.Name.Namespace == ns))
1551 {
1552 namespaces.Remove(ns);
1553 return false;
1554 }
1555
1556 return true;
1557 });
1558 }
1559
1560 foreach (var declaration in declarations)
1561 {
1562 if (namespaces.Contains(declaration.Value) &&
1563 this.OnError(ConverterTestType.RemoveUnusedNamespaces, declaration, "The namespace '{0}' is not used. Remove unused namespaces.", declaration.Value))
1564 {
1565 declaration.Remove();
1566 }
1567 }
1568 }
1569
1570 /// <summary>
1464 /// Output an error message to the console. 1571 /// Output an error message to the console.
1465 /// </summary> 1572 /// </summary>
1466 /// <param name="converterTestType">The type of converter test.</param> 1573 /// <param name="converterTestType">The type of converter test.</param>
@@ -1601,6 +1708,21 @@ namespace WixToolset.Converters
1601 } 1708 }
1602 } 1709 }
1603 1710
1711 private static bool VisitElement(XElement element, Func<XObject, bool> visitor)
1712 {
1713 if (!visitor(element))
1714 {
1715 return false;
1716 }
1717
1718 if (!element.Attributes().All(a => visitor(a)))
1719 {
1720 return false;
1721 }
1722
1723 return element.Elements().All(e => VisitElement(e, visitor));
1724 }
1725
1604 private static bool WasImplicitlyStringTyped(string value) 1726 private static bool WasImplicitlyStringTyped(string value)
1605 { 1727 {
1606 if (value == null) 1728 if (value == null)
@@ -1835,6 +1957,16 @@ namespace WixToolset.Converters
1835 /// The Tag element has been renamed. Use the element 'SoftwareTag' name. 1957 /// The Tag element has been renamed. Use the element 'SoftwareTag' name.
1836 /// </summary> 1958 /// </summary>
1837 TagElementRenamed, 1959 TagElementRenamed,
1960
1961 /// <summary>
1962 /// The Dependency namespace has been incorporated into WiX v4 namespace.
1963 /// </summary>
1964 IntegratedDependencyNamespace,
1965
1966 /// <summary>
1967 /// Remove unused namespaces.
1968 /// </summary>
1969 RemoveUnusedNamespaces,
1838 } 1970 }
1839 } 1971 }
1840} 1972}