aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Converters/WixConverter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Converters/WixConverter.cs')
-rw-r--r--src/WixToolset.Converters/WixConverter.cs160
1 files changed, 147 insertions, 13 deletions
diff --git a/src/WixToolset.Converters/WixConverter.cs b/src/WixToolset.Converters/WixConverter.cs
index 3348e49c..9ada4745 100644
--- a/src/WixToolset.Converters/WixConverter.cs
+++ b/src/WixToolset.Converters/WixConverter.cs
@@ -15,6 +15,27 @@ namespace WixToolset.Converters
15 using WixToolset.Extensibility.Services; 15 using WixToolset.Extensibility.Services;
16 16
17 /// <summary> 17 /// <summary>
18 /// How to convert CustomTable elements.
19 /// </summary>
20 public enum CustomTableTarget
21 {
22 /// <summary>
23 /// Ambiguous elements will be left alone.
24 /// </summary>
25 Unknown,
26
27 /// <summary>
28 /// Use CustomTable, CustomTableRef, and Unreal.
29 /// </summary>
30 Msi,
31
32 /// <summary>
33 /// Use BundleCustomData and BundleCustomDataRef.
34 /// </summary>
35 Bundle,
36 }
37
38 /// <summary>
18 /// WiX source code converter. 39 /// WiX source code converter.
19 /// </summary> 40 /// </summary>
20 public sealed class WixConverter 41 public sealed class WixConverter
@@ -45,19 +66,25 @@ namespace WixToolset.Converters
45 private static readonly XName BootstrapperApplicationDllElementName = WixNamespace + "BootstrapperApplicationDll"; 66 private static readonly XName BootstrapperApplicationDllElementName = WixNamespace + "BootstrapperApplicationDll";
46 private static readonly XName BootstrapperApplicationRefElementName = WixNamespace + "BootstrapperApplicationRef"; 67 private static readonly XName BootstrapperApplicationRefElementName = WixNamespace + "BootstrapperApplicationRef";
47 private static readonly XName ApprovedExeForElevationElementName = WixNamespace + "ApprovedExeForElevation"; 68 private static readonly XName ApprovedExeForElevationElementName = WixNamespace + "ApprovedExeForElevation";
48 private static readonly XName EmbeddedChainerElementName = WixNamespace + "EmbeddedChainer"; 69 private static readonly XName BundleAttributeElementName = WixNamespace + "BundleAttribute";
70 private static readonly XName BundleAttributeDefinitionElementName = WixNamespace + "BundleAttributeDefinition";
71 private static readonly XName BundleCustomDataElementName = WixNamespace + "BundleCustomData";
72 private static readonly XName BundleCustomDataRefElementName = WixNamespace + "BundleCustomDataRef";
73 private static readonly XName BundleElementElementName = WixNamespace + "BundleElement";
74 private static readonly XName CustomTableElementName = WixNamespace + "CustomTable";
75 private static readonly XName CustomTableRefElementName = WixNamespace + "CustomTableRef";
49 private static readonly XName CatalogElementName = WixNamespace + "Catalog"; 76 private static readonly XName CatalogElementName = WixNamespace + "Catalog";
50 private static readonly XName ColumnElementName = WixNamespace + "Column"; 77 private static readonly XName ColumnElementName = WixNamespace + "Column";
51 private static readonly XName ComponentElementName = WixNamespace + "Component"; 78 private static readonly XName ComponentElementName = WixNamespace + "Component";
52 private static readonly XName ControlElementName = WixNamespace + "Control"; 79 private static readonly XName ControlElementName = WixNamespace + "Control";
53 private static readonly XName ConditionElementName = WixNamespace + "Condition"; 80 private static readonly XName ConditionElementName = WixNamespace + "Condition";
54 private static readonly XName CreateFolderElementName = WixNamespace + "CreateFolder"; 81 private static readonly XName CreateFolderElementName = WixNamespace + "CreateFolder";
55 private static readonly XName CustomTableElementName = WixNamespace + "CustomTable";
56 private static readonly XName DataElementName = WixNamespace + "Data"; 82 private static readonly XName DataElementName = WixNamespace + "Data";
57 private static readonly XName OldProvidesElementName = WixDependencyNamespace + "Provides"; 83 private static readonly XName OldProvidesElementName = WixDependencyNamespace + "Provides";
58 private static readonly XName OldRequiresElementName = WixDependencyNamespace + "Requires"; 84 private static readonly XName OldRequiresElementName = WixDependencyNamespace + "Requires";
59 private static readonly XName OldRequiresRefElementName = WixDependencyNamespace + "RequiresRef"; 85 private static readonly XName OldRequiresRefElementName = WixDependencyNamespace + "RequiresRef";
60 private static readonly XName DirectoryElementName = WixNamespace + "Directory"; 86 private static readonly XName DirectoryElementName = WixNamespace + "Directory";
87 private static readonly XName EmbeddedChainerElementName = WixNamespace + "EmbeddedChainer";
61 private static readonly XName ErrorElementName = WixNamespace + "Error"; 88 private static readonly XName ErrorElementName = WixNamespace + "Error";
62 private static readonly XName FeatureElementName = WixNamespace + "Feature"; 89 private static readonly XName FeatureElementName = WixNamespace + "Feature";
63 private static readonly XName FileElementName = WixNamespace + "File"; 90 private static readonly XName FileElementName = WixNamespace + "File";
@@ -85,6 +112,7 @@ namespace WixToolset.Converters
85 private static readonly XName RemotePayloadElementName = WixNamespace + "RemotePayload"; 112 private static readonly XName RemotePayloadElementName = WixNamespace + "RemotePayload";
86 private static readonly XName RegistrySearchElementName = WixNamespace + "RegistrySearch"; 113 private static readonly XName RegistrySearchElementName = WixNamespace + "RegistrySearch";
87 private static readonly XName RequiredPrivilegeElementName = WixNamespace + "RequiredPrivilege"; 114 private static readonly XName RequiredPrivilegeElementName = WixNamespace + "RequiredPrivilege";
115 private static readonly XName RowElementName = WixNamespace + "Row";
88 private static readonly XName ServiceArgumentElementName = WixNamespace + "ServiceArgument"; 116 private static readonly XName ServiceArgumentElementName = WixNamespace + "ServiceArgument";
89 private static readonly XName SetDirectoryElementName = WixNamespace + "SetDirectory"; 117 private static readonly XName SetDirectoryElementName = WixNamespace + "SetDirectory";
90 private static readonly XName SetPropertyElementName = WixNamespace + "SetProperty"; 118 private static readonly XName SetPropertyElementName = WixNamespace + "SetProperty";
@@ -156,7 +184,8 @@ namespace WixToolset.Converters
156 /// <param name="indentationAmount">Indentation value to use when validating leading whitespace.</param> 184 /// <param name="indentationAmount">Indentation value to use when validating leading whitespace.</param>
157 /// <param name="errorsAsWarnings">Test errors to display as warnings.</param> 185 /// <param name="errorsAsWarnings">Test errors to display as warnings.</param>
158 /// <param name="ignoreErrors">Test errors to ignore.</param> 186 /// <param name="ignoreErrors">Test errors to ignore.</param>
159 public WixConverter(IMessaging messaging, int indentationAmount, IEnumerable<string> errorsAsWarnings = null, IEnumerable<string> ignoreErrors = null) 187 /// <param name="customTableTarget">How to convert CustomTable elements.</param>
188 public WixConverter(IMessaging messaging, int indentationAmount, IEnumerable<string> errorsAsWarnings = null, IEnumerable<string> ignoreErrors = null, CustomTableTarget customTableTarget = CustomTableTarget.Unknown)
160 { 189 {
161 this.ConvertElementMapping = new Dictionary<XName, Action<XElement>> 190 this.ConvertElementMapping = new Dictionary<XName, Action<XElement>>
162 { 191 {
@@ -170,9 +199,10 @@ namespace WixToolset.Converters
170 { WixConverter.ApprovedExeForElevationElementName, this.ConvertApprovedExeForElevationElement }, 199 { WixConverter.ApprovedExeForElevationElementName, this.ConvertApprovedExeForElevationElement },
171 { WixConverter.CatalogElementName, this.ConvertCatalogElement }, 200 { WixConverter.CatalogElementName, this.ConvertCatalogElement },
172 { WixConverter.ColumnElementName, this.ConvertColumnElement }, 201 { WixConverter.ColumnElementName, this.ConvertColumnElement },
173 { WixConverter.CustomTableElementName, this.ConvertCustomTableElement },
174 { WixConverter.ControlElementName, this.ConvertControlElement },
175 { WixConverter.ComponentElementName, this.ConvertComponentElement }, 202 { WixConverter.ComponentElementName, this.ConvertComponentElement },
203 { WixConverter.ControlElementName, this.ConvertControlElement },
204 { WixConverter.CustomActionElementName, this.ConvertCustomActionElement },
205 { WixConverter.CustomTableElementName, this.ConvertCustomTableElement },
176 { WixConverter.DataElementName, this.ConvertDataElement }, 206 { WixConverter.DataElementName, this.ConvertDataElement },
177 { WixConverter.DirectoryElementName, this.ConvertDirectoryElement }, 207 { WixConverter.DirectoryElementName, this.ConvertDirectoryElement },
178 { WixConverter.FeatureElementName, this.ConvertFeatureElement }, 208 { WixConverter.FeatureElementName, this.ConvertFeatureElement },
@@ -198,7 +228,6 @@ namespace WixToolset.Converters
198 { WixConverter.RegistrySearchElementName, this.ConvertRegistrySearchElement }, 228 { WixConverter.RegistrySearchElementName, this.ConvertRegistrySearchElement },
199 { WixConverter.RemotePayloadElementName, this.ConvertRemotePayloadElement }, 229 { WixConverter.RemotePayloadElementName, this.ConvertRemotePayloadElement },
200 { WixConverter.RequiredPrivilegeElementName, this.ConvertRequiredPrivilegeElement }, 230 { WixConverter.RequiredPrivilegeElementName, this.ConvertRequiredPrivilegeElement },
201 { WixConverter.CustomActionElementName, this.ConvertCustomActionElement },
202 { WixConverter.ServiceArgumentElementName, this.ConvertServiceArgumentElement }, 231 { WixConverter.ServiceArgumentElementName, this.ConvertServiceArgumentElement },
203 { WixConverter.SetDirectoryElementName, this.ConvertSetDirectoryElement }, 232 { WixConverter.SetDirectoryElementName, this.ConvertSetDirectoryElement },
204 { WixConverter.SetPropertyElementName, this.ConvertSetPropertyElement }, 233 { WixConverter.SetPropertyElementName, this.ConvertSetPropertyElement },
@@ -224,8 +253,12 @@ namespace WixToolset.Converters
224 this.ErrorsAsWarnings = new HashSet<ConverterTestType>(this.YieldConverterTypes(errorsAsWarnings)); 253 this.ErrorsAsWarnings = new HashSet<ConverterTestType>(this.YieldConverterTypes(errorsAsWarnings));
225 254
226 this.IgnoreErrors = new HashSet<ConverterTestType>(this.YieldConverterTypes(ignoreErrors)); 255 this.IgnoreErrors = new HashSet<ConverterTestType>(this.YieldConverterTypes(ignoreErrors));
256
257 this.CustomTableSetting = customTableTarget;
227 } 258 }
228 259
260 private CustomTableTarget CustomTableSetting { get; }
261
229 private int Errors { get; set; } 262 private int Errors { get; set; }
230 263
231 private HashSet<ConverterTestType> ErrorsAsWarnings { get; set; } 264 private HashSet<ConverterTestType> ErrorsAsWarnings { get; set; }
@@ -717,11 +750,104 @@ namespace WixToolset.Converters
717 private void ConvertCustomTableElement(XElement element) 750 private void ConvertCustomTableElement(XElement element)
718 { 751 {
719 var bootstrapperApplicationData = element.Attribute("BootstrapperApplicationData"); 752 var bootstrapperApplicationData = element.Attribute("BootstrapperApplicationData");
720 if (bootstrapperApplicationData != null 753 if (bootstrapperApplicationData?.Value == "no")
721 && this.OnError(ConverterTestType.BootstrapperApplicationDataDeprecated, element, "The CustomTable element contains deprecated '{0}' attribute. Use the 'Unreal' attribute instead.", bootstrapperApplicationData.Name)) 754 {
755 if (this.OnError(ConverterTestType.BootstrapperApplicationDataDeprecated, element, "The CustomTable element contains deprecated '{0}' attribute. Use the 'Unreal' attribute instead.", bootstrapperApplicationData.Name))
756 {
757 bootstrapperApplicationData.Remove();
758 }
759 }
760 else
761 {
762 if (element.Elements(ColumnElementName).Any() || bootstrapperApplicationData != null)
763 {
764 // Table definition
765 if (bootstrapperApplicationData != null)
766 {
767 switch (this.CustomTableSetting)
768 {
769 case CustomTableTarget.Bundle:
770 if (this.OnError(ConverterTestType.BootstrapperApplicationDataDeprecated, element, "The CustomTable element contains deprecated '{0}' attribute. Use the 'BundleCustomData' element for Bundles.", bootstrapperApplicationData.Name))
771 {
772 element.Name = WixConverter.BundleCustomDataElementName;
773 bootstrapperApplicationData.Remove();
774 this.ConvertCustomTableElementToBundle(element);
775 }
776 break;
777 case CustomTableTarget.Msi:
778 if (this.OnError(ConverterTestType.BootstrapperApplicationDataDeprecated, element, "The CustomTable element contains deprecated '{0}' attribute. Use the 'Unreal' attribute instead.", bootstrapperApplicationData.Name))
779 {
780 element.Add(new XAttribute("Unreal", bootstrapperApplicationData.Value));
781 bootstrapperApplicationData.Remove();
782 }
783 break;
784 default:
785 this.OnError(ConverterTestType.CustomTableNotAlwaysConvertable, element, "The CustomTable element contains deprecated '{0}' attribute so can't be converted. Use the 'Unreal' attribute for MSI. Use the 'BundleCustomData' element for Bundles. Use the --custom-table argument to force conversion to 'msi' or 'bundle'", bootstrapperApplicationData.Name);
786 break;
787 }
788 }
789 }
790 else
791 {
792 // Table ref
793 switch (this.CustomTableSetting)
794 {
795 case CustomTableTarget.Bundle:
796 if (this.OnError(ConverterTestType.CustomTableRef, element, "CustomTable elements that don't contain the table definition are now BundleCustomDataRef for Bundles."))
797 {
798 element.Name = WixConverter.BundleCustomDataRefElementName;
799 this.ConvertCustomTableElementToBundle(element);
800 }
801 break;
802 case CustomTableTarget.Msi:
803 if (this.OnError(ConverterTestType.CustomTableRef, element, "CustomTable elements that don't contain the table definition are now CustomTableRef for MSI."))
804 {
805 element.Name = WixConverter.CustomTableRefElementName;
806 }
807 break;
808 default:
809 this.OnError(ConverterTestType.CustomTableNotAlwaysConvertable, element, "The CustomTable element contains no 'Column' elements so can't be converted. Use the 'CustomTableRef' element for MSI. Use the 'BundleCustomDataRef' element for Bundles. Use the --custom-table argument to force conversion to 'msi' or 'bundle'");
810 break;
811 }
812 }
813 }
814 }
815
816 private void ConvertCustomTableElementToBundle(XElement element)
817 {
818 foreach (var xColumn in element.Elements(ColumnElementName))
722 { 819 {
723 element.Add(new XAttribute("Unreal", bootstrapperApplicationData.Value)); 820 xColumn.Name = WixConverter.BundleAttributeDefinitionElementName;
724 bootstrapperApplicationData.Remove(); 821
822 foreach (var xAttribute in xColumn.Attributes().ToList())
823 {
824 if (xAttribute.Name.LocalName != "Id" &&
825 (xAttribute.Name.Namespace == WixConverter.Wix3Namespace ||
826 xAttribute.Name.Namespace == WixConverter.WixNamespace ||
827 String.IsNullOrEmpty(xAttribute.Name.Namespace.NamespaceName)))
828 {
829 xAttribute.Remove();
830 }
831 }
832 }
833
834 foreach (var xRow in element.Elements(RowElementName))
835 {
836 xRow.Name = WixConverter.BundleElementElementName;
837
838 foreach (var xData in xRow.Elements(DataElementName))
839 {
840 xData.Name = WixConverter.BundleAttributeElementName;
841
842 var xColumn = xData.Attribute("Column");
843 if (xColumn != null)
844 {
845 xData.Add(new XAttribute("Id", xColumn.Value));
846 xColumn.Remove();
847 }
848
849 this.ConvertInnerTextToAttribute(xData, "Value");
850 }
725 } 851 }
726 } 852 }
727 853
@@ -1165,8 +1291,6 @@ namespace WixToolset.Converters
1165 1291
1166 private void ConvertRequiredPrivilegeElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Name"); 1292 private void ConvertRequiredPrivilegeElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Name");
1167 1293
1168 private void ConvertRowElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value");
1169
1170 private void ConvertDataElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); 1294 private void ConvertDataElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value");
1171 1295
1172 private void ConvertSequenceElement(XElement element) 1296 private void ConvertSequenceElement(XElement element)
@@ -1854,7 +1978,7 @@ namespace WixToolset.Converters
1854 AssignDirectoryNameFromShortName, 1978 AssignDirectoryNameFromShortName,
1855 1979
1856 /// <summary> 1980 /// <summary>
1857 /// BootstrapperApplicationData attribute is deprecated and replaced with Unreal. 1981 /// BootstrapperApplicationData attribute is deprecated and replaced with Unreal for MSI. Use BundleCustomData element for Bundles.
1858 /// </summary> 1982 /// </summary>
1859 BootstrapperApplicationDataDeprecated, 1983 BootstrapperApplicationDataDeprecated,
1860 1984
@@ -2022,6 +2146,16 @@ namespace WixToolset.Converters
2022 /// The hash algorithm used for bundles changed from SHA1 to SHA512. 2146 /// The hash algorithm used for bundles changed from SHA1 to SHA512.
2023 /// </summary> 2147 /// </summary>
2024 BurnHashAlgorithmChanged, 2148 BurnHashAlgorithmChanged,
2149
2150 /// <summary>
2151 /// CustomTable elements can't always be converted.
2152 /// </summary>
2153 CustomTableNotAlwaysConvertable,
2154
2155 /// <summary>
2156 /// CustomTable elements that don't contain the table definition are now CustomTableRef.
2157 /// </summary>
2158 CustomTableRef,
2025 } 2159 }
2026 } 2160 }
2027} 2161}