Handle references to standard directories
Closes 7072
Rob Mensching committed
Dec 8, 2022 at 16:59 UTC
7d41de1a726038d71873db48e9f5a575578679f5
2 files changed
+136
-45
src/wix/WixToolset.Converters/WixConverter.cs
+56
-45
@@ -1094,40 +1094,18 @@ namespace WixToolset.Converters
1094
1095
var id = element.Attribute("Id")?.Value;
1096
1097
- if (id == "TARGETDIR" &&
1098
- this.OnInformation(ConverterTestType.TargetDirDeprecated, element, "The TARGETDIR directory should not longer be explicitly defined. Remove the Directory element with Id attribute 'TARGETDIR'."))
1097
+ if (id == "TARGETDIR")
1098
{
1100
- var parentElement = element.Parent;
1101
-
1102
- element.Remove();
1103
-
1104
- if (parentElement.FirstNode is XText text && String.IsNullOrWhiteSpace(text.Value))
1105
- {
1106
- parentElement.FirstNode.Remove();
1107
- }
1108
-
1109
- foreach (var child in element.Nodes())
1099
+ if (this.OnInformation(ConverterTestType.TargetDirDeprecated, element, "The TARGETDIR directory should no longer be explicitly defined. Remove the Directory element with Id attribute 'TARGETDIR'."))
1100
{
1111
- parentElement.Add(child);
1112
- }
1113
-
1114
- element.RemoveAll();
1115
-
1116
- if (parentElement.FirstNode is XText textAgain && String.IsNullOrWhiteSpace(textAgain.Value))
1117
- {
1118
- parentElement.FirstNode.Remove();
1101
+ RemoveElementKeepChildren(element);
1102
}
1103
}
1104
else if (id != null &&
1105
WindowsInstallerStandard.IsStandardDirectory(id) &&
1106
this.OnInformation(ConverterTestType.DefiningStandardDirectoryDeprecated, element, "Standard directories such as '{0}' should no longer be defined using the Directory element. Use the StandardDirectory element instead.", id))
1107
{
1125
- element.Name = StandardDirectoryElementName;
1126
-
1127
- foreach (var attrib in element.Attributes().Where(a => a.Name.LocalName != "Id").ToList())
1128
- {
1129
- attrib.Remove();
1130
- }
1108
+ RenameElementToStandardDirectory(element);
1109
}
1110
}
1111
@@ -1135,28 +1113,22 @@ namespace WixToolset.Converters
1113
{
1114
var id = element.Attribute("Id")?.Value;
1115
1138
- if (id == "TARGETDIR" &&
1139
- this.OnInformation(ConverterTestType.TargetDirRefDeprecated, element, "The TARGETDIR directory should not longer be explicitly referenced. Remove the DirectoryRef element with Id attribute 'TARGETDIR'."))
1116
+ if (id != null && WindowsInstallerStandard.IsStandardDirectory(id))
1117
{
1141
- var parentElement = element.Parent;
1142
-
1143
- element.Remove();
1144
-
1145
- if (parentElement.FirstNode is XText text && String.IsNullOrWhiteSpace(text.Value))
1118
+ if (!element.HasElements)
1119
{
1147
- parentElement.FirstNode.Remove();
1120
+ this.OnError(ConverterTestType.EmptyStandardDirectoryRefNotConvertable, element, "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.", id);
1121
}
1149
-
1150
- foreach (var child in element.Nodes())
1122
+ else if (id == "TARGETDIR")
1123
{
1152
- parentElement.Add(child);
1124
+ if (this.OnInformation(ConverterTestType.StandardDirectoryRefDeprecated, element, "The {0} directory should no longer be explicitly referenced. Remove the DirectoryRef element with Id attribute '{0}'.", id))
1125
+ {
1126
+ RemoveElementKeepChildren(element);
1127
+ }
1128
}
1154
-
1155
- element.RemoveAll();
1156
-
1157
- if (parentElement.FirstNode is XText textAgain && String.IsNullOrWhiteSpace(textAgain.Value))
1129
+ else if (this.OnInformation(ConverterTestType.StandardDirectoryRefDeprecated, element, "The standard directory '{0}' should no longer be directly referenced. Use the StandardDirectory element instead.", id))
1130
{
1159
- parentElement.FirstNode.Remove();
1131
+ RenameElementToStandardDirectory(element);
1132
}
1133
}
1134
}
@@ -2725,6 +2697,40 @@ namespace WixToolset.Converters
2697
return value;
2698
}
2699
2700
+ private static void RemoveElementKeepChildren(XElement element)
2701
+ {
2702
+ var parentElement = element.Parent;
2703
+
2704
+ element.Remove();
2705
+
2706
+ if (parentElement.FirstNode is XText text && String.IsNullOrWhiteSpace(text.Value))
2707
+ {
2708
+ parentElement.FirstNode.Remove();
2709
+ }
2710
+
2711
+ foreach (var child in element.Nodes())
2712
+ {
2713
+ parentElement.Add(child);
2714
+ }
2715
+
2716
+ element.RemoveAll();
2717
+
2718
+ if (parentElement.FirstNode is XText textAgain && String.IsNullOrWhiteSpace(textAgain.Value))
2719
+ {
2720
+ parentElement.FirstNode.Remove();
2721
+ }
2722
+ }
2723
+
2724
+ private static void RenameElementToStandardDirectory(XElement element)
2725
+ {
2726
+ element.Name = StandardDirectoryElementName;
2727
+
2728
+ foreach (var attrib in element.Attributes().Where(a => a.Name.LocalName != "Id").ToList())
2729
+ {
2730
+ attrib.Remove();
2731
+ }
2732
+ }
2733
+
2734
private static bool TryGetInnerText(XElement element, out string value, out List<XNode> comments)
2735
{
2736
return TryGetInnerText(element, out value, out comments, new List<XNode>());
@@ -3138,7 +3144,7 @@ namespace WixToolset.Converters
3144
SoftwareTagTypeObsolete,
3145
3146
/// <summary>
3141
- /// TARGETDIR directory should not longer be explicitly defined.
3147
+ /// TARGETDIR directory should no longer be explicitly defined.
3148
/// </summary>
3149
TargetDirDeprecated,
3150
@@ -3178,9 +3184,14 @@ namespace WixToolset.Converters
3184
CustomActionIdsIncludePlatformSuffix,
3185
3186
/// <summary>
3181
- /// The TARGETDIR directory should not longer be explicitly referenced.
3187
+ /// The {0} directory should no longer be explicitly referenced. Remove the DirectoryRef element with Id attribute '{0}'.
3188
+ /// </summary>
3189
+ StandardDirectoryRefDeprecated,
3190
+
3191
+ /// <summary>
3192
+ /// 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.
3193
/// </summary>
3183
- TargetDirRefDeprecated,
3194
+ EmptyStandardDirectoryRefNotConvertable,
3195
}
3196
}
3197
}
src/wix/test/WixToolsetTest.Converters/DirectoryFixture.cs
+80
@@ -3,6 +3,7 @@
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;
@@ -129,6 +130,42 @@ namespace WixToolsetTest.Converters
130
Assert.Equal(4, errors);
131
}
132
133
+ [Fact]
134
+ public void FixStandardDirectoryRef()
135
+ {
136
+ var parse = String.Join(Environment.NewLine,
137
+ "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
138
+ "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>",
139
+ " <Fragment>",
140
+ " <DirectoryRef Id='ProgramFilesFolder'>",
141
+ " <Directory Id='ChildFolder' Name='Child' />",
142
+ " </DirectoryRef>",
143
+ " </Fragment>",
144
+ "</Wix>");
145
+
146
+ var expected = new[]
147
+ {
148
+ "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
149
+ " <Fragment>",
150
+ " <StandardDirectory Id=\"ProgramFilesFolder\">",
151
+ " <Directory Id=\"ChildFolder\" Name=\"Child\" />",
152
+ " </StandardDirectory>",
153
+ " </Fragment>",
154
+ "</Wix>"
155
+ };
156
+
157
+ var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
158
+
159
+ var messaging = new MockMessaging();
160
+ var converter = new WixConverter(messaging, 2, null, null);
161
+
162
+ var errors = converter.ConvertDocument(document);
163
+
164
+ var actualLines = UnformattedDocumentLines(document);
165
+ WixAssert.CompareLineByLine(expected, actualLines);
166
+ Assert.Equal(3, errors);
167
+ }
168
+
169
[Fact]
170
public void RemoveTargetDirRefAndFixStandardDirectory()
171
{
@@ -166,5 +203,48 @@ namespace WixToolsetTest.Converters
203
WixAssert.CompareLineByLine(expected, actualLines);
204
Assert.Equal(4, errors);
205
}
206
+
207
+ [Fact]
208
+ public void ErrorOnEmptyStandardDirectoryRef()
209
+ {
210
+ var parse = String.Join(Environment.NewLine,
211
+ "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>",
212
+ " <Fragment>",
213
+ " <DirectoryRef Id='TARGETDIR' />",
214
+ " <DirectoryRef Id='ProgramFilesFolder' />",
215
+ " <DirectoryRef Id='DesktopFolder' />",
216
+ " </Fragment>",
217
+ "</Wix>");
218
+
219
+ var expected = new[]
220
+ {
221
+ "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
222
+ " <Fragment>",
223
+ " <DirectoryRef Id=\"TARGETDIR\" />",
224
+ " <DirectoryRef Id=\"ProgramFilesFolder\" />",
225
+ " <DirectoryRef Id=\"DesktopFolder\" />",
226
+ " </Fragment>",
227
+ "</Wix>"
228
+ };
229
+
230
+ var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
231
+
232
+ var messaging = new MockMessaging();
233
+ var converter = new WixConverter(messaging, 2, null, null);
234
+
235
+ var errors = converter.ConvertDocument(document);
236
+
237
+ WixAssert.CompareLineByLine(new[]
238
+ {
239
+ "[Converted] The namespace 'http://schemas.microsoft.com/wix/2006/wi' is out of date. It must be 'http://wixtoolset.org/schemas/v4/wxs'. (XmlnsValueWrong)",
240
+ "Referencing 'TARGETDIR' directory directly is no longer supported. The DirectoryRef will not be removed but you will probably need to reference a more specific directory. (EmptyStandardDirectoryRefNotConvertable)",
241
+ "Referencing 'ProgramFilesFolder' directory directly is no longer supported. The DirectoryRef will not be removed but you will probably need to reference a more specific directory. (EmptyStandardDirectoryRefNotConvertable)",
242
+ "Referencing 'DesktopFolder' directory directly is no longer supported. The DirectoryRef will not be removed but you will probably need to reference a more specific directory. (EmptyStandardDirectoryRefNotConvertable)"
243
+ }, messaging.Messages.Select(m => m.ToString()).ToArray());
244
+
245
+ var actualLines = UnformattedDocumentLines(document);
246
+ WixAssert.CompareLineByLine(expected, actualLines);
247
+ Assert.Equal(4, errors);
248
+ }
249
}
250
}