Introduce PatchFilterMap to remove Row.SectionId
A Row's SectionId is not set correctly in most scenarios. It was only really needed for the old section-based patch filtering. As section-base patch filtering was replaced in favor of the more logical filter generation, Row.SectionId was archaic and mostly outdated/wrong data.
Rob Mensching committed
Sep 27, 2022 at 15:03 UTC
dfcd6728a9d56ac37a5daa8cbedabbf10c333773
14 files changed
+426
-368
src/api/wix/WixToolset.Data/WindowsInstaller/Row.cs
-31
@@ -52,17 +52,6 @@ namespace WixToolset.Data.WindowsInstaller
52
/// <value>The row transform operation.</value>
53
public RowOperation Operation { get; set; }
54
55
- /// <summary>
56
- /// Gets or sets wether the row is a duplicate of another row thus redundant.
57
- /// </summary>
58
- public bool Redundant { get; set; }
59
-
60
- /// <summary>
61
- /// Gets or sets the SectionId property on the row.
62
- /// </summary>
63
- /// <value>The SectionId property on the row.</value>
64
- public string SectionId { get; set; }
65
-
55
/// <summary>
56
/// Gets the source file and line number for the row.
57
/// </summary>
@@ -276,8 +265,6 @@ namespace WixToolset.Data.WindowsInstaller
265
266
bool empty = reader.IsEmptyElement;
267
RowOperation operation = RowOperation.None;
279
- bool redundant = false;
280
- string sectionId = null;
268
SourceLineNumber sourceLineNumbers = null;
269
270
while (reader.MoveToNextAttribute())
@@ -287,12 +274,6 @@ namespace WixToolset.Data.WindowsInstaller
274
case "op":
275
operation = (RowOperation)Enum.Parse(typeof(RowOperation), reader.Value, true);
276
break;
290
- case "redundant":
291
- redundant = reader.Value.Equals("yes");
292
- break;
293
- case "sectionId":
294
- sectionId = reader.Value;
295
- break;
277
case "sourceLineNumber":
278
sourceLineNumbers = SourceLineNumber.CreateFromEncoded(reader.Value);
279
break;
@@ -301,8 +282,6 @@ namespace WixToolset.Data.WindowsInstaller
282
283
var row = table.CreateRow(sourceLineNumbers);
284
row.Operation = operation;
304
- row.Redundant = redundant;
305
- row.SectionId = sectionId;
285
286
// loop through all the fields in a row
287
if (!empty)
@@ -364,16 +343,6 @@ namespace WixToolset.Data.WindowsInstaller
343
writer.WriteAttributeString("op", this.Operation.ToString().ToLowerInvariant());
344
}
345
367
- if (this.Redundant)
368
- {
369
- writer.WriteAttributeString("redundant", "yes");
370
- }
371
-
372
- if (null != this.SectionId)
373
- {
374
- writer.WriteAttributeString("sectionId", this.SectionId);
375
- }
376
-
346
if (null != this.SourceLineNumbers)
347
{
348
writer.WriteAttributeString("sourceLineNumber", this.SourceLineNumbers.GetEncoded());
src/api/wix/WixToolset.Data/WindowsInstaller/Xsd/objects.xsd
-2
@@ -96,8 +96,6 @@
96
</xs:restriction>
97
</xs:simpleType>
98
</xs:attribute>
99
- <xs:attribute name="redundant" type="YesNoType" />
100
- <xs:attribute name="sectionId" type="xs:string" />
99
<xs:attribute name="sourceLineNumber" type="xs:string" />
100
</xs:complexType>
101
</xs:element>
src/api/wix/WixToolset.Extensibility/BaseWindowsInstallerBackendBinderExtension.cs
+7
@@ -62,6 +62,13 @@ namespace WixToolset.Extensibility
62
{
63
}
64
65
+ /// <summary>
66
+ /// See <see cref="IWindowsInstallerBackendBinderExtension.FinalizePatchFilterIds(WindowsInstallerData, IDictionary{Row, string}, string)"/>
67
+ /// </summary>
68
+ public virtual void FinalizePatchFilterIds(WindowsInstallerData data, IDictionary<Row, string> rowToFilterId, string filterIdPrefix)
69
+ {
70
+ }
71
+
72
/// <summary>
73
/// See <see cref="IWindowsInstallerBackendBinderExtension.PreBackendBind(IBindContext)"/>
74
/// </summary>
src/api/wix/WixToolset.Extensibility/IWindowsInstallerBackendBinderExtension.cs
+8
@@ -29,6 +29,14 @@ namespace WixToolset.Extensibility
29
/// <param name="section">The finalized intermediate section.</param>
30
void SymbolsFinalized(IntermediateSection section);
31
32
+ /// <summary>
33
+ /// Extension can process the filter ids applied to rows when processing patches.
34
+ /// </summary>
35
+ /// <param name="data">The <c>WindowsInstallerData</c> with rows to apply filters to.</param>
36
+ /// <param name="rowToFilterId">The mapping that applies a filter id to a row.</param>
37
+ /// <param name="filterIdPrefix">The prefix to use applying additional filters to rows.</param>
38
+ void FinalizePatchFilterIds(WindowsInstallerData data, IDictionary<Row, string> rowToFilterId, string filterIdPrefix);
39
+
40
/// <summary>
41
/// Finds an existing cabinet that contains the provided files.
42
/// </summary>
src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateIdtFileCommand.cs
-5
@@ -71,11 +71,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
71
72
foreach (Row row in table.Rows)
73
{
74
- if (row.Redundant)
75
- {
76
- continue;
77
- }
78
-
74
string rowString = this.RowToIdtDefinition(row, keepAddedColumns);
75
byte[] rowBytes;
76
src/wix/WixToolset.Core.WindowsInstaller/Bind/CreatePatchTransformsCommand.cs
+15
-4
@@ -16,13 +16,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
16
17
internal class CreatePatchTransformsCommand
18
{
19
- public CreatePatchTransformsCommand(IMessaging messaging, IBackendHelper backendHelper, IPathResolver pathResolver, IFileResolver fileResolver, IReadOnlyCollection<IResolverExtension> resolverExtensions, Intermediate intermediate, string intermediateFolder, IReadOnlyCollection<IBindPath> bindPaths)
19
+ public CreatePatchTransformsCommand(IMessaging messaging, IBackendHelper backendHelper, IPathResolver pathResolver, IFileResolver fileResolver, IReadOnlyCollection<IResolverExtension> resolverExtensions, IReadOnlyCollection<IWindowsInstallerBackendBinderExtension> backendExtensions, Intermediate intermediate, string intermediateFolder, IReadOnlyCollection<IBindPath> bindPaths)
20
{
21
this.Messaging = messaging;
22
this.BackendHelper = backendHelper;
23
this.PathResolver = pathResolver;
24
this.FileResolver = fileResolver;
25
this.ResolverExtensions = resolverExtensions;
26
+ this.BackendExtensions = backendExtensions;
27
this.Intermediate = intermediate;
28
this.IntermediateFolder = intermediateFolder;
29
this.BindPaths = bindPaths;
@@ -38,16 +39,21 @@ namespace WixToolset.Core.WindowsInstaller.Bind
39
40
private IReadOnlyCollection<IResolverExtension> ResolverExtensions { get; }
41
42
+ private IReadOnlyCollection<IWindowsInstallerBackendBinderExtension> BackendExtensions { get; }
43
+
44
private Intermediate Intermediate { get; }
45
46
private string IntermediateFolder { get; }
47
48
private IReadOnlyCollection<IBindPath> BindPaths { get; }
49
50
+ public PatchFilterMap PatchFilterMap { get; private set; }
51
+
52
public IEnumerable<PatchTransform> PatchTransforms { get; private set; }
53
54
public IEnumerable<PatchTransform> Execute()
55
{
56
+ var patchFilterMap = new PatchFilterMap();
57
var patchTransforms = new List<PatchTransform>();
58
59
var symbols = this.Intermediate.Sections.SelectMany(s => s.Symbols);
@@ -63,19 +69,24 @@ namespace WixToolset.Core.WindowsInstaller.Bind
69
70
if (patchRefSymbols.Count > 0)
71
{
66
- var targetCommand = new GenerateSectionIdsCommand(targetData);
72
+ var targetCommand = new GeneratePatchFilterIdsCommand(this.BackendExtensions, targetData, "target:");
73
targetCommand.Execute();
74
69
- var updatedCommand = new GenerateSectionIdsCommand(updatedData);
75
+ patchFilterMap.AddTargetRowFilterIds(targetCommand.RowToFilterId);
76
+
77
+ var updatedCommand = new GeneratePatchFilterIdsCommand(this.BackendExtensions, updatedData, "updated:");
78
updatedCommand.Execute();
79
+
80
+ patchFilterMap.AddUpdatedRowFilterIds(updatedCommand.RowToFilterId);
81
}
82
73
- var command = new GenerateTransformCommand(this.Messaging, targetData, updatedData, preserveUnchangedRows: true, showPedanticMessages: false);
83
+ var command = new GenerateTransformCommand(this.Messaging, targetData, updatedData, patchFilterMap, preserveUnchangedRows: true, showPedanticMessages: false);
84
var transform = command.Execute();
85
86
patchTransforms.Add(new PatchTransform(symbol.Id.Id, transform));
87
}
88
89
+ this.PatchFilterMap = patchFilterMap;
90
this.PatchTransforms = patchTransforms;
91
92
return this.PatchTransforms;
src/wix/WixToolset.Core.WindowsInstaller/Bind/GeneratePatchFilterIdsCommand.cs
new
+233
@@ -0,0 +1,233 @@
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 WixToolset.Core.WindowsInstaller.Bind
4
+{
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using System.Globalization;
8
+ using WixToolset.Data.WindowsInstaller;
9
+ using WixToolset.Extensibility;
10
+
11
+ /// <summary>
12
+ /// Creates section ids on rows which form logical groupings of resources.
13
+ /// </summary>
14
+ internal class GeneratePatchFilterIdsCommand
15
+ {
16
+ public GeneratePatchFilterIdsCommand(IReadOnlyCollection<IWindowsInstallerBackendBinderExtension> backendExtensions, WindowsInstallerData data, string filterIdPrefix)
17
+ {
18
+ this.BackendExtensions = backendExtensions;
19
+ this.Data = data;
20
+ this.FilterIdPrefix = filterIdPrefix;
21
+ }
22
+
23
+ private IReadOnlyCollection<IWindowsInstallerBackendBinderExtension> BackendExtensions { get; }
24
+
25
+ private WindowsInstallerData Data { get; }
26
+
27
+ private string FilterIdPrefix { get; }
28
+
29
+ public IDictionary<Row, string> RowToFilterId { get; private set; }
30
+
31
+ public void Execute()
32
+ {
33
+ this.RowToFilterId = new Dictionary<Row, string>();
34
+
35
+ var output = this.Data;
36
+
37
+ // First assign and index section ids for the tables that are in their own sections.
38
+ this.AssignFilterIdsToTable(output.Tables["Binary"], 0);
39
+ var componentSectionIdIndex = this.AssignFilterIdsToTable(output.Tables["Component"], 0);
40
+ var customActionSectionIdIndex = this.AssignFilterIdsToTable(output.Tables["CustomAction"], 0);
41
+ this.AssignFilterIdsToTable(output.Tables["Directory"], 0);
42
+ var featureSectionIdIndex = this.AssignFilterIdsToTable(output.Tables["Feature"], 0);
43
+ this.AssignFilterIdsToTable(output.Tables["Icon"], 0);
44
+ var digitalCertificateSectionIdIndex = this.AssignFilterIdsToTable(output.Tables["MsiDigitalCertificate"], 0);
45
+ this.AssignFilterIdsToTable(output.Tables["Property"], 0);
46
+
47
+ // Now handle all the tables that rely on the first set of indexes but also produce their own indexes. Order matters here.
48
+ var fileFilterIdIndex = this.ConnectTableToSectionAndIndex(output.Tables["File"], componentSectionIdIndex, 1, 0);
49
+ var appIdFilterIdIndex = this.ConnectTableToSectionAndIndex(output.Tables["Class"], componentSectionIdIndex, 2, 5);
50
+ var odbcDataSourceFilterIdIndex = this.ConnectTableToSectionAndIndex(output.Tables["ODBCDataSource"], componentSectionIdIndex, 1, 0);
51
+ var odbcDriverSectionIdIndex = this.ConnectTableToSectionAndIndex(output.Tables["ODBCDriver"], componentSectionIdIndex, 1, 0);
52
+ var registrySectionIdIndex = this.ConnectTableToSectionAndIndex(output.Tables["Registry"], componentSectionIdIndex, 5, 0);
53
+ var serviceInstallSectionIdIndex = this.ConnectTableToSectionAndIndex(output.Tables["ServiceInstall"], componentSectionIdIndex, 11, 0);
54
+
55
+ // Now handle all the tables which only rely on previous indexes and order does not matter.
56
+ foreach (var table in output.Tables)
57
+ {
58
+ switch (table.Name)
59
+ {
60
+ case "MsiFileHash":
61
+ this.ConnectTableToFilterId(table, fileFilterIdIndex, 0);
62
+ break;
63
+ case "MsiAssembly":
64
+ case "MsiAssemblyName":
65
+ this.ConnectTableToFilterId(table, componentSectionIdIndex, 0);
66
+ break;
67
+ case "MsiPackageCertificate":
68
+ case "MsiPatchCertificate":
69
+ this.ConnectTableToFilterId(table, digitalCertificateSectionIdIndex, 1);
70
+ break;
71
+ case "CreateFolder":
72
+ case "FeatureComponents":
73
+ case "MoveFile":
74
+ case "ReserveCost":
75
+ case "ODBCTranslator":
76
+ this.ConnectTableToFilterId(table, componentSectionIdIndex, 1);
77
+ break;
78
+ case "TypeLib":
79
+ this.ConnectTableToFilterId(table, componentSectionIdIndex, 2);
80
+ break;
81
+ case "Shortcut":
82
+ case "Environment":
83
+ this.ConnectTableToFilterId(table, componentSectionIdIndex, 3);
84
+ break;
85
+ case "RemoveRegistry":
86
+ this.ConnectTableToFilterId(table, componentSectionIdIndex, 4);
87
+ break;
88
+ case "ServiceControl":
89
+ this.ConnectTableToFilterId(table, componentSectionIdIndex, 5);
90
+ break;
91
+ case "IniFile":
92
+ case "RemoveIniFile":
93
+ this.ConnectTableToFilterId(table, componentSectionIdIndex, 7);
94
+ break;
95
+ case "AppId":
96
+ this.ConnectTableToFilterId(table, appIdFilterIdIndex, 0);
97
+ break;
98
+ case "Condition":
99
+ this.ConnectTableToFilterId(table, featureSectionIdIndex, 0);
100
+ break;
101
+ case "ODBCSourceAttribute":
102
+ this.ConnectTableToFilterId(table, odbcDataSourceFilterIdIndex, 0);
103
+ break;
104
+ case "ODBCAttribute":
105
+ this.ConnectTableToFilterId(table, odbcDriverSectionIdIndex, 0);
106
+ break;
107
+ case "AdminExecuteSequence":
108
+ case "AdminUISequence":
109
+ case "AdvtExecuteSequence":
110
+ case "AdvtUISequence":
111
+ case "InstallExecuteSequence":
112
+ case "InstallUISequence":
113
+ this.ConnectTableToFilterId(table, customActionSectionIdIndex, 0);
114
+ break;
115
+ case "LockPermissions":
116
+ case "MsiLockPermissions":
117
+ foreach (var row in table.Rows)
118
+ {
119
+ var lockObject = row.FieldAsString(0);
120
+ var tableName = row.FieldAsString(1);
121
+
122
+ var filterId = String.Empty;
123
+ switch (tableName)
124
+ {
125
+ case "File":
126
+ filterId = fileFilterIdIndex[lockObject];
127
+ break;
128
+ case "Registry":
129
+ filterId = registrySectionIdIndex[lockObject];
130
+ break;
131
+ case "ServiceInstall":
132
+ filterId = serviceInstallSectionIdIndex[lockObject];
133
+ break;
134
+ }
135
+
136
+ if (!String.IsNullOrEmpty(filterId))
137
+ {
138
+ this.RowToFilterId.Add(row, filterId);
139
+ }
140
+ }
141
+ break;
142
+ }
143
+ }
144
+
145
+ // Now pass the data to each backend extension to allow them to analyze the data and determine their proper filter ids.
146
+ foreach (var extension in this.BackendExtensions)
147
+ {
148
+ extension.FinalizePatchFilterIds(this.Data, this.RowToFilterId, this.FilterIdPrefix);
149
+ }
150
+ }
151
+
152
+ private Dictionary<string, string> AssignFilterIdsToTable(Table table, int rowPrimaryKeyIndex)
153
+ {
154
+ var primaryKeyToFilterId = new Dictionary<string, string>();
155
+
156
+ if (null != table)
157
+ {
158
+ foreach (var row in table.Rows)
159
+ {
160
+ var filterId = this.GetNewFilterId(row);
161
+
162
+ this.RowToFilterId.Add(row, filterId);
163
+
164
+ primaryKeyToFilterId.Add(row.FieldAsString(rowPrimaryKeyIndex), filterId);
165
+ }
166
+ }
167
+
168
+ return primaryKeyToFilterId;
169
+ }
170
+
171
+ /// <summary>
172
+ /// Connects a table's rows to an already sectioned table.
173
+ /// </summary>
174
+ /// <param name="table">The table containing rows that need to be connected to sections.</param>
175
+ /// <param name="filterIdByPrimaryKey">A hashtable containing keys to map table to its section.</param>
176
+ /// <param name="rowIndex">The index of the column which is used as the foreign key in to the sectionIdIndex.</param>
177
+ private void ConnectTableToFilterId(Table table, Dictionary<string, string> filterIdByPrimaryKey, int rowIndex)
178
+ {
179
+ if (null != table)
180
+ {
181
+ foreach (var row in table.Rows)
182
+ {
183
+ if (filterIdByPrimaryKey.TryGetValue(row.FieldAsString(rowIndex), out var filterId))
184
+ {
185
+ this.RowToFilterId.Add(row, filterId);
186
+ }
187
+ }
188
+ }
189
+ }
190
+
191
+ /// <summary>
192
+ /// Connects a table's rows to a table with filter ids already assigned and produces an index for other tables to connect to it.
193
+ /// </summary>
194
+ /// <param name="table">The table containing rows that need to be connected to sections.</param>
195
+ /// <param name="filterIdsByPrimaryKey">A dictionary containing keys to map table to its section.</param>
196
+ /// <param name="rowIndex">The index of the column which is used as the foreign key in to the sectionIdIndex.</param>
197
+ /// <param name="rowPrimaryKeyIndex">The index of the column which is used by other tables to reference this table.</param>
198
+ /// <returns>A dictionary containing the tables key for each row paired with its assigned section id.</returns>
199
+ private Dictionary<string, string> ConnectTableToSectionAndIndex(Table table, Dictionary<string, string> filterIdsByPrimaryKey, int rowIndex, int rowPrimaryKeyIndex)
200
+ {
201
+ var newPrimaryKeyToSectionId = new Dictionary<string, string>();
202
+
203
+ if (null != table)
204
+ {
205
+ foreach (var row in table.Rows)
206
+ {
207
+ var foreignKey = row.FieldAsString(rowIndex);
208
+
209
+ if (!filterIdsByPrimaryKey.TryGetValue(foreignKey, out var filterId))
210
+ {
211
+ continue;
212
+ }
213
+
214
+ this.RowToFilterId.Add(row, filterId);
215
+
216
+ var primaryKey = row.FieldAsString(rowPrimaryKeyIndex);
217
+
218
+ if (!String.IsNullOrEmpty(primaryKey) && filterIdsByPrimaryKey.ContainsKey(primaryKey))
219
+ {
220
+ newPrimaryKeyToSectionId.Add(primaryKey, filterId);
221
+ }
222
+ }
223
+ }
224
+
225
+ return newPrimaryKeyToSectionId;
226
+ }
227
+
228
+ private string GetNewFilterId(Row row)
229
+ {
230
+ return this.FilterIdPrefix + row.Number.ToString(CultureInfo.InvariantCulture);
231
+ }
232
+ }
233
+}
src/wix/WixToolset.Core.WindowsInstaller/Bind/GenerateSectionIdsCommand.cs
deleted
-225
@@ -1,225 +0,0 @@
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 WixToolset.Core.WindowsInstaller.Bind
4
-{
5
- using System;
6
- using System.Collections.Generic;
7
- using System.Globalization;
8
- using WixToolset.Data.WindowsInstaller;
9
-
10
- /// <summary>
11
- /// Creates section ids on rows which form logical groupings of resources.
12
- /// </summary>
13
- internal class GenerateSectionIdsCommand
14
- {
15
- private int sectionCount;
16
-
17
- public GenerateSectionIdsCommand(WindowsInstallerData data)
18
- {
19
- this.Data = data;
20
- }
21
-
22
- private WindowsInstallerData Data { get; }
23
-
24
- public void Execute()
25
- {
26
- var output = this.Data;
27
-
28
- this.sectionCount = 0;
29
-
30
- // First assign and index section ids for the tables that are in their own sections.
31
- this.AssignSectionIdsToTable(output.Tables["Binary"], 0);
32
- var componentSectionIdIndex = this.AssignSectionIdsToTable(output.Tables["Component"], 0);
33
- var customActionSectionIdIndex = this.AssignSectionIdsToTable(output.Tables["CustomAction"], 0);
34
- this.AssignSectionIdsToTable(output.Tables["Directory"], 0);
35
- var featureSectionIdIndex = this.AssignSectionIdsToTable(output.Tables["Feature"], 0);
36
- this.AssignSectionIdsToTable(output.Tables["Icon"], 0);
37
- var digitalCertificateSectionIdIndex = this.AssignSectionIdsToTable(output.Tables["MsiDigitalCertificate"], 0);
38
- this.AssignSectionIdsToTable(output.Tables["Property"], 0);
39
-
40
- // Now handle all the tables that rely on the first set of indexes but also produce their own indexes. Order matters here.
41
- var fileSectionIdIndex = ConnectTableToSectionAndIndex(output.Tables["File"], componentSectionIdIndex, 1, 0);
42
- var appIdSectionIdIndex = ConnectTableToSectionAndIndex(output.Tables["Class"], componentSectionIdIndex, 2, 5);
43
- var odbcDataSourceSectionIdIndex = ConnectTableToSectionAndIndex(output.Tables["ODBCDataSource"], componentSectionIdIndex, 1, 0);
44
- var odbcDriverSectionIdIndex = ConnectTableToSectionAndIndex(output.Tables["ODBCDriver"], componentSectionIdIndex, 1, 0);
45
- var registrySectionIdIndex = ConnectTableToSectionAndIndex(output.Tables["Registry"], componentSectionIdIndex, 5, 0);
46
- var serviceInstallSectionIdIndex = ConnectTableToSectionAndIndex(output.Tables["ServiceInstall"], componentSectionIdIndex, 11, 0);
47
-
48
- // Now handle all the tables which only rely on previous indexes and order does not matter.
49
- foreach (var table in output.Tables)
50
- {
51
- switch (table.Name)
52
- {
53
- case "MsiFileHash":
54
- ConnectTableToSection(table, fileSectionIdIndex, 0);
55
- break;
56
- case "MsiAssembly":
57
- case "MsiAssemblyName":
58
- ConnectTableToSection(table, componentSectionIdIndex, 0);
59
- break;
60
- case "MsiPackageCertificate":
61
- case "MsiPatchCertificate":
62
- ConnectTableToSection(table, digitalCertificateSectionIdIndex, 1);
63
- break;
64
- case "CreateFolder":
65
- case "FeatureComponents":
66
- case "MoveFile":
67
- case "ReserveCost":
68
- case "ODBCTranslator":
69
- ConnectTableToSection(table, componentSectionIdIndex, 1);
70
- break;
71
- case "TypeLib":
72
- ConnectTableToSection(table, componentSectionIdIndex, 2);
73
- break;
74
- case "Shortcut":
75
- case "Environment":
76
- ConnectTableToSection(table, componentSectionIdIndex, 3);
77
- break;
78
- case "RemoveRegistry":
79
- ConnectTableToSection(table, componentSectionIdIndex, 4);
80
- break;
81
- case "ServiceControl":
82
- ConnectTableToSection(table, componentSectionIdIndex, 5);
83
- break;
84
- case "IniFile":
85
- case "RemoveIniFile":
86
- ConnectTableToSection(table, componentSectionIdIndex, 7);
87
- break;
88
- case "AppId":
89
- ConnectTableToSection(table, appIdSectionIdIndex, 0);
90
- break;
91
- case "Condition":
92
- ConnectTableToSection(table, featureSectionIdIndex, 0);
93
- break;
94
- case "ODBCSourceAttribute":
95
- ConnectTableToSection(table, odbcDataSourceSectionIdIndex, 0);
96
- break;
97
- case "ODBCAttribute":
98
- ConnectTableToSection(table, odbcDriverSectionIdIndex, 0);
99
- break;
100
- case "AdminExecuteSequence":
101
- case "AdminUISequence":
102
- case "AdvtExecuteSequence":
103
- case "AdvtUISequence":
104
- case "InstallExecuteSequence":
105
- case "InstallUISequence":
106
- ConnectTableToSection(table, customActionSectionIdIndex, 0);
107
- break;
108
- case "LockPermissions":
109
- case "MsiLockPermissions":
110
- foreach (var row in table.Rows)
111
- {
112
- var lockObject = row.FieldAsString(0);
113
- var tableName = row.FieldAsString(1);
114
- switch (tableName)
115
- {
116
- case "File":
117
- row.SectionId = fileSectionIdIndex[lockObject];
118
- break;
119
- case "Registry":
120
- row.SectionId = registrySectionIdIndex[lockObject];
121
- break;
122
- case "ServiceInstall":
123
- row.SectionId = serviceInstallSectionIdIndex[lockObject];
124
- break;
125
- }
126
- }
127
- break;
128
- }
129
- }
130
-
131
- // Now pass the output to each unbinder extension to allow them to analyze the output and determine their proper section ids.
132
- //foreach (IUnbinderExtension extension in this.unbinderExtensions)
133
- //{
134
- // extension.GenerateSectionIds(output);
135
- //}
136
- }
137
-
138
- /// <summary>
139
- /// Creates new section ids on all the rows in a table.
140
- /// </summary>
141
- /// <param name="table">The table to add sections to.</param>
142
- /// <param name="rowPrimaryKeyIndex">The index of the column which is used by other tables to reference this table.</param>
143
- /// <returns>A dictionary containing the tables key for each row paired with its assigned section id.</returns>
144
- private Dictionary<string, string> AssignSectionIdsToTable(Table table, int rowPrimaryKeyIndex)
145
- {
146
- var primaryKeyToSectionId = new Dictionary<string, string>();
147
-
148
- if (null != table)
149
- {
150
- foreach (var row in table.Rows)
151
- {
152
- row.SectionId = this.GetNewSectionId();
153
-
154
- primaryKeyToSectionId.Add(row.FieldAsString(rowPrimaryKeyIndex), row.SectionId);
155
- }
156
- }
157
-
158
- return primaryKeyToSectionId;
159
- }
160
-
161
- /// <summary>
162
- /// Connects a table's rows to an already sectioned table.
163
- /// </summary>
164
- /// <param name="table">The table containing rows that need to be connected to sections.</param>
165
- /// <param name="sectionIdIndex">A hashtable containing keys to map table to its section.</param>
166
- /// <param name="rowIndex">The index of the column which is used as the foreign key in to the sectionIdIndex.</param>
167
- private static void ConnectTableToSection(Table table, Dictionary<string, string> sectionIdIndex, int rowIndex)
168
- {
169
- if (null != table)
170
- {
171
- foreach (var row in table.Rows)
172
- {
173
- if (sectionIdIndex.TryGetValue(row.FieldAsString(rowIndex), out var sectionId))
174
- {
175
- row.SectionId = sectionId;
176
- }
177
- }
178
- }
179
- }
180
-
181
- /// <summary>
182
- /// Connects a table's rows to an already sectioned table and produces an index for other tables to connect to it.
183
- /// </summary>
184
- /// <param name="table">The table containing rows that need to be connected to sections.</param>
185
- /// <param name="sectionIdIndex">A dictionary containing keys to map table to its section.</param>
186
- /// <param name="rowIndex">The index of the column which is used as the foreign key in to the sectionIdIndex.</param>
187
- /// <param name="rowPrimaryKeyIndex">The index of the column which is used by other tables to reference this table.</param>
188
- /// <returns>A dictionary containing the tables key for each row paired with its assigned section id.</returns>
189
- private static Dictionary<string, string> ConnectTableToSectionAndIndex(Table table, Dictionary<string, string> sectionIdIndex, int rowIndex, int rowPrimaryKeyIndex)
190
- {
191
- var newPrimaryKeyToSectionId = new Dictionary<string, string>();
192
-
193
- if (null != table)
194
- {
195
- foreach (var row in table.Rows)
196
- {
197
- var foreignKey = row.FieldAsString(rowIndex);
198
-
199
- if (!sectionIdIndex.TryGetValue(foreignKey, out var sectionId))
200
- {
201
- continue;
202
- }
203
-
204
- row.SectionId = sectionId;
205
-
206
- var primaryKey = row.FieldAsString(rowPrimaryKeyIndex);
207
-
208
- if (!String.IsNullOrEmpty(primaryKey) && sectionIdIndex.ContainsKey(primaryKey))
209
- {
210
- newPrimaryKeyToSectionId.Add(primaryKey, row.SectionId);
211
- }
212
- }
213
- }
214
-
215
- return newPrimaryKeyToSectionId;
216
- }
217
-
218
- private string GetNewSectionId()
219
- {
220
- this.sectionCount++;
221
-
222
- return "wix.section." + this.sectionCount.ToString(CultureInfo.InvariantCulture);
223
- }
224
- }
225
-}
src/wix/WixToolset.Core.WindowsInstaller/Bind/GenerateTransformCommand.cs
+10
-8
@@ -6,6 +6,7 @@ namespace WixToolset.Core.WindowsInstaller
6
using System.Collections.Generic;
7
using System.Globalization;
8
using WixToolset.Core.Native.Msi;
9
+ using WixToolset.Core.WindowsInstaller.Bind;
10
using WixToolset.Data;
11
using WixToolset.Data.Symbols;
12
using WixToolset.Data.WindowsInstaller;
@@ -16,18 +17,18 @@ namespace WixToolset.Core.WindowsInstaller
17
/// </summary>
18
internal class GenerateTransformCommand
19
{
19
- private const char SectionDelimiter = '/';
20
private readonly IMessaging messaging;
21
private SummaryInformationStreams transformSummaryInfo;
22
23
/// <summary>
24
/// Instantiates a new Differ class.
25
/// </summary>
26
- public GenerateTransformCommand(IMessaging messaging, WindowsInstallerData targetOutput, WindowsInstallerData updatedOutput, bool preserveUnchangedRows, bool showPedanticMessages)
26
+ public GenerateTransformCommand(IMessaging messaging, WindowsInstallerData targetOutput, WindowsInstallerData updatedOutput, PatchFilterMap patchFilterMap, bool preserveUnchangedRows, bool showPedanticMessages)
27
{
28
this.messaging = messaging;
29
this.TargetOutput = targetOutput;
30
this.UpdatedOutput = updatedOutput;
31
+ this.PatchFilterMap = patchFilterMap;
32
this.PreserveUnchangedRows = preserveUnchangedRows;
33
this.ShowPedanticMessages = showPedanticMessages;
34
}
@@ -36,6 +37,8 @@ namespace WixToolset.Core.WindowsInstaller
37
38
private WindowsInstallerData UpdatedOutput { get; }
39
40
+ public PatchFilterMap PatchFilterMap { get; }
41
+
42
private TransformFlags ValidationFlags { get; }
43
44
private bool ShowPedanticMessages { get; }
@@ -112,7 +115,6 @@ namespace WixToolset.Core.WindowsInstaller
115
foreach (var updatedRow in updatedTable.Rows)
116
{
117
updatedRow.Operation = RowOperation.Add;
115
- updatedRow.SectionId = SectionDelimiter + updatedRow.SectionId;
118
addedTable.Rows.Add(updatedRow);
119
}
120
}
@@ -177,7 +179,6 @@ namespace WixToolset.Core.WindowsInstaller
179
else if (null == updatedRow)
180
{
181
targetRow.Operation = RowOperation.Delete;
180
- targetRow.SectionId += SectionDelimiter;
182
183
comparedRow = targetRow;
184
keepRow = true;
@@ -189,9 +190,10 @@ namespace WixToolset.Core.WindowsInstaller
190
if (!this.SuppressKeepingSpecialRows && "_SummaryInformation" == targetTable.Name)
191
{
192
// Include only summary information rows that are allowed in a transform.
192
- if (Enum.IsDefined(typeof(SummaryInformation.Transform), (int)updatedRow[0]))
193
+ if (Enum.IsDefined(typeof(SummaryInformation.Transform), updatedRow.FieldAsInteger(0)))
194
{
194
- updatedRow.SectionId = targetRow.SectionId + SectionDelimiter + updatedRow.SectionId;
195
+ this.PatchFilterMap.AddTargetRowFilterToUpdatedRowFilter(targetRow, updatedRow);
196
+
197
comparedRow = updatedRow;
198
keepRow = true;
199
}
@@ -273,8 +275,9 @@ namespace WixToolset.Core.WindowsInstaller
275
276
if (keepRow)
277
{
278
+ this.PatchFilterMap.AddTargetRowFilterToUpdatedRowFilter(targetRow, updatedRow);
279
+
280
comparedRow = updatedRow;
277
- comparedRow.SectionId = targetRow.SectionId + SectionDelimiter + updatedRow.SectionId;
281
}
282
}
283
}
@@ -340,7 +343,6 @@ namespace WixToolset.Core.WindowsInstaller
343
var updatedRow = updatedPrimaryKeyEntry.Value;
344
345
updatedRow.Operation = RowOperation.Add;
343
- updatedRow.SectionId = SectionDelimiter + updatedRow.SectionId;
346
rows.Add(updatedRow);
347
}
348
}
src/wix/WixToolset.Core.WindowsInstaller/Bind/PatchFilterMap.cs
new
+80
@@ -0,0 +1,80 @@
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 WixToolset.Core.WindowsInstaller.Bind
4
+{
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using WixToolset.Data.WindowsInstaller;
8
+
9
+ internal class PatchFilterMap
10
+ {
11
+ private readonly Dictionary<Row, PatchFilter> filterMap = new Dictionary<Row, PatchFilter>();
12
+
13
+ public void AddTargetRowFilterIds(IEnumerable<KeyValuePair<Row, string>> rowFilterIds)
14
+ {
15
+ foreach (var kvp in rowFilterIds)
16
+ {
17
+ this.filterMap.Add(kvp.Key, new PatchFilter(kvp.Key, kvp.Value, null));
18
+ }
19
+ }
20
+
21
+ public void AddUpdatedRowFilterIds(IEnumerable<KeyValuePair<Row, string>> rowFilterIds)
22
+ {
23
+ foreach (var kvp in rowFilterIds)
24
+ {
25
+ this.filterMap.Add(kvp.Key, new PatchFilter(kvp.Key, null, kvp.Value));
26
+ }
27
+ }
28
+
29
+ public void AddTargetRowFilterToUpdatedRowFilter(Row targetRow, Row updatedRow)
30
+ {
31
+ if (this.filterMap.TryGetValue(targetRow, out var targetPatchFilter) && !String.IsNullOrEmpty(targetPatchFilter.TargetFilterId))
32
+ {
33
+ // If the updated row didn't have a patch filter, it gets one now because the target patch has
34
+ // a target filter id to add.
35
+ if (!this.filterMap.TryGetValue(updatedRow, out var updatedPatchFilter))
36
+ {
37
+ updatedPatchFilter = new PatchFilter(updatedRow, null, null);
38
+ this.filterMap.Add(updatedRow, updatedPatchFilter);
39
+ }
40
+
41
+ updatedPatchFilter.SetTargetFilterId(targetPatchFilter);
42
+ }
43
+ }
44
+
45
+ internal bool ContainsPatchFilterForRow(Row row)
46
+ {
47
+ return this.filterMap.ContainsKey(row);
48
+ }
49
+
50
+ internal bool TryGetPatchFiltersForRow(Row row, out string targetFilterId, out string updatedFilterId)
51
+ {
52
+ this.filterMap.TryGetValue(row, out var patchFilter);
53
+
54
+ targetFilterId = patchFilter?.TargetFilterId;
55
+ updatedFilterId = patchFilter?.UpdatedFilterId;
56
+ return patchFilter != null;
57
+ }
58
+
59
+ private class PatchFilter
60
+ {
61
+ public PatchFilter(Row row, string targetFilterId, string updatedFilterId)
62
+ {
63
+ this.Row = row;
64
+ this.TargetFilterId = targetFilterId;
65
+ this.UpdatedFilterId = updatedFilterId;
66
+ }
67
+
68
+ public Row Row { get; }
69
+
70
+ public string TargetFilterId { get; private set; }
71
+
72
+ public string UpdatedFilterId { get; }
73
+
74
+ public void SetTargetFilterId(PatchFilter targetPatchFilter)
75
+ {
76
+ this.TargetFilterId = targetPatchFilter.TargetFilterId;
77
+ }
78
+ }
79
+ }
80
+}
src/wix/WixToolset.Core.WindowsInstaller/Bind/ReduceTransformCommand.cs
+63
-79
@@ -11,18 +11,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind
11
12
internal class ReduceTransformCommand
13
{
14
- private const char SectionDelimiter = '/';
15
-
16
- public ReduceTransformCommand(Intermediate intermediate, IEnumerable<PatchTransform> patchTransforms)
14
+ public ReduceTransformCommand(Intermediate intermediate, IEnumerable<PatchTransform> patchTransforms, PatchFilterMap patchFilterMap)
15
{
16
this.Intermediate = intermediate;
17
this.PatchTransforms = patchTransforms;
18
+ this.PatchFilterMap = patchFilterMap;
19
}
20
21
private Intermediate Intermediate { get; }
22
23
private IEnumerable<PatchTransform> PatchTransforms { get; }
24
25
+ private PatchFilterMap PatchFilterMap { get; }
26
+
27
public void Execute()
28
{
29
var symbols = this.Intermediate.Sections.SelectMany(s => s.Symbols).ToList();
@@ -51,8 +52,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
52
private bool ReduceTransform(WindowsInstallerData transform, IEnumerable<WixPatchRefSymbol> patchRefSymbols)
53
{
54
// identify sections to keep
54
- var oldSections = new Dictionary<string, Row>();
55
- var newSections = new Dictionary<string, Row>();
55
+ var targetFilterIdsToKeep = new Dictionary<string, Row>();
56
+ var updatedFilterIdsToKeep = new Dictionary<string, Row>();
57
var tableKeyRows = new Dictionary<string, Dictionary<string, Row>>();
58
var sequenceList = new List<Table>();
59
var componentFeatureAddsIndex = new Dictionary<string, List<string>>();
@@ -72,10 +73,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
73
foreach (var patchRefSymbol in patchRefSymbols)
74
{
75
var tableName = patchRefSymbol.Table;
75
- var key = patchRefSymbol.PrimaryKeys;
76
+ var primaryKey = patchRefSymbol.PrimaryKeys;
77
78
// Short circuit filtering if all changes should be included.
78
- if ("*" == tableName && "*" == key)
79
+ if ("*" == tableName && "*" == primaryKey)
80
{
81
RemoveProductCodeFromTransform(transform);
82
return true;
@@ -88,22 +89,24 @@ namespace WixToolset.Core.WindowsInstaller.Bind
89
}
90
91
// Index the table.
91
- if (!tableKeyRows.TryGetValue(tableName, out var keyRows))
92
+ if (!tableKeyRows.TryGetValue(tableName, out var rowsByPrimaryKey))
93
{
93
- keyRows = table.Rows.ToDictionary(r => r.GetPrimaryKey());
94
- tableKeyRows.Add(tableName, keyRows);
94
+ rowsByPrimaryKey = table.Rows.ToDictionary(r => r.GetPrimaryKey());
95
+ tableKeyRows.Add(tableName, rowsByPrimaryKey);
96
}
97
97
- if (!keyRows.TryGetValue(key, out var row))
98
+ if (!rowsByPrimaryKey.TryGetValue(primaryKey, out var row))
99
{
100
// Row not found.
101
continue;
102
}
103
104
// Differ.sectionDelimiter
104
- var sections = row.SectionId.Split(SectionDelimiter);
105
- oldSections[sections[0]] = row;
106
- newSections[sections[1]] = row;
105
+ if (this.PatchFilterMap.TryGetPatchFiltersForRow(row, out var targetFilterId, out var updatedFilterId))
106
+ {
107
+ targetFilterIdsToKeep[targetFilterId] = row;
108
+ updatedFilterIdsToKeep[updatedFilterId] = row;
109
+ }
110
}
111
112
// throw away sections not referenced
@@ -221,49 +224,34 @@ namespace WixToolset.Core.WindowsInstaller.Bind
224
}
225
}
226
224
- if (null == row.SectionId)
227
+ if (this.IsInPatchFamily(row, targetFilterIdsToKeep, updatedFilterIdsToKeep))
228
{
226
- table.Rows.RemoveAt(i);
227
- i--;
228
- }
229
- else
230
- {
231
- var sections = row.SectionId.Split(SectionDelimiter);
232
- // ignore the row without section id.
233
- if (0 == sections[0].Length && 0 == sections[1].Length)
229
+ if ("Component" == table.Name)
230
{
235
- table.Rows.RemoveAt(i);
236
- i--;
231
+ keptComponents.Add(row.FieldAsString(0), row);
232
}
238
- else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
239
- {
240
- if ("Component" == table.Name)
241
- {
242
- keptComponents.Add(row.FieldAsString(0), row);
243
- }
233
245
- if ("Directory" == table.Name)
246
- {
247
- keptDirectories.Add(row.FieldAsString(0), row);
248
- }
249
-
250
- if ("Feature" == table.Name)
251
- {
252
- keptFeatures.Add(row.FieldAsString(0), row);
253
- }
254
-
255
- keptRows++;
234
+ if ("Directory" == table.Name)
235
+ {
236
+ keptDirectories.Add(row.FieldAsString(0), row);
237
}
257
- else
238
+
239
+ if ("Feature" == table.Name)
240
{
259
- table.Rows.RemoveAt(i);
260
- i--;
241
+ keptFeatures.Add(row.FieldAsString(0), row);
242
}
243
+
244
+ keptRows++;
245
+ }
246
+ else
247
+ {
248
+ table.Rows.RemoveAt(i);
249
+ i--;
250
}
251
}
252
}
253
266
- keptRows += ReduceTransformSequenceTable(sequenceList, oldSections, newSections, customActionTable);
254
+ keptRows += ReduceTransformSequenceTable(sequenceList, targetFilterIdsToKeep, updatedFilterIdsToKeep, customActionTable);
255
256
if (null != directoryTable)
257
{
@@ -345,7 +333,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
333
}
334
}
335
348
- keptRows += ReduceTransformSequenceTable(sequenceList, oldSections, newSections, customActionTable);
336
+ keptRows += ReduceTransformSequenceTable(sequenceList, targetFilterIdsToKeep, updatedFilterIdsToKeep, customActionTable);
337
338
// Delete tables that are empty.
339
var tablesToDelete = transform.Tables.Where(t => t.Rows.Count == 0).Select(t => t.Name).ToList();
@@ -358,6 +346,25 @@ namespace WixToolset.Core.WindowsInstaller.Bind
346
return keptRows > 0;
347
}
348
349
+ private bool IsInPatchFamily(Row row, Dictionary<string, Row> oldSections, Dictionary<string, Row> newSections)
350
+ {
351
+ var result = false;
352
+
353
+ if (this.PatchFilterMap.TryGetPatchFiltersForRow(row, out var targetFilterId, out var updatedFilterId))
354
+ {
355
+ if ((String.IsNullOrEmpty(targetFilterId) && newSections.ContainsKey(updatedFilterId)) || (String.IsNullOrEmpty(updatedFilterId) && oldSections.ContainsKey(targetFilterId)))
356
+ {
357
+ result = true;
358
+ }
359
+ else if (!String.IsNullOrEmpty(targetFilterId) && !String.IsNullOrEmpty(updatedFilterId) && (oldSections.ContainsKey(targetFilterId) || newSections.ContainsKey(updatedFilterId)))
360
+ {
361
+ result = true;
362
+ }
363
+ }
364
+
365
+ return result;
366
+ }
367
+
368
/// <summary>
369
/// Check if the section is in a PatchFamily.
370
/// </summary>
@@ -415,7 +422,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
422
/// <param name="newSections">Hashtable contains section id should be kept in the target wixout.</param>
423
/// <param name="customAction">Hashtable contains all the rows in the CustomAction table.</param>
424
/// <returns>Number of rows left</returns>
418
- private static int ReduceTransformSequenceTable(List<Table> sequenceList, Dictionary<string, Row> oldSections, Dictionary<string, Row> newSections, Dictionary<string, Row> customAction)
425
+ private int ReduceTransformSequenceTable(List<Table> sequenceList, Dictionary<string, Row> oldSections, Dictionary<string, Row> newSections, Dictionary<string, Row> customAction)
426
{
427
var keptRows = 0;
428
@@ -424,19 +431,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
431
for (var i = 0; i < currentTable.Rows.Count; i++)
432
{
433
var row = currentTable.Rows[i];
427
- var actionName = row.Fields[0].Data.ToString();
428
- var sections = row.SectionId.Split(SectionDelimiter);
429
- var isSectionIdEmpty = (sections[0].Length == 0 && sections[1].Length == 0);
434
+ var actionName = row.FieldAsString(0);
435
436
if (row.Operation == RowOperation.None)
437
{
433
- // Ignore the rows without section id.
434
- if (isSectionIdEmpty)
435
- {
436
- currentTable.Rows.RemoveAt(i);
437
- i--;
438
- }
439
- else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
438
+ if (this.IsInPatchFamily(row, oldSections, newSections))
439
{
440
keptRows++;
441
}
@@ -457,12 +456,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
456
}
457
else if (!sequenceChanged && conditionChanged)
458
{
460
- if (isSectionIdEmpty)
461
- {
462
- currentTable.Rows.RemoveAt(i);
463
- i--;
464
- }
465
- else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
459
+ if (this.IsInPatchFamily(row, oldSections, newSections))
460
{
461
keptRows++;
462
}
@@ -474,12 +468,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
468
}
469
else if (sequenceChanged && conditionChanged)
470
{
477
- if (isSectionIdEmpty)
478
- {
479
- row.Fields[1].Modified = false;
480
- keptRows++;
481
- }
482
- else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
471
+ if (this.IsInPatchFamily(row, oldSections, newSections))
472
{
473
keptRows++;
474
}
@@ -492,13 +481,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
481
}
482
else if (row.Operation == RowOperation.Delete)
483
{
495
- if (isSectionIdEmpty)
496
- {
497
- // it is a stardard action which is added by wix, we should keep this action.
498
- row.Operation = RowOperation.None;
499
- keptRows++;
500
- }
501
- else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
484
+ if (this.IsInPatchFamily(row, oldSections, newSections))
485
{
486
keptRows++;
487
}
@@ -519,11 +502,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
502
}
503
else if (row.Operation == RowOperation.Add)
504
{
522
- if (isSectionIdEmpty)
505
+ // Keep unfiltered added rows.
506
+ if (!this.PatchFilterMap.ContainsPatchFilterForRow(row))
507
{
508
keptRows++;
509
}
526
- else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
510
+ else if (this.IsInPatchFamily(row, oldSections, newSections))
511
{
512
keptRows++;
513
}
src/wix/WixToolset.Core.WindowsInstaller/Differ.cs
+2
-7
@@ -17,7 +17,6 @@ namespace WixToolset.Core.WindowsInstaller
17
/// </summary>
18
public sealed class Differ
19
{
20
- private const char SectionDelimiter = '/';
20
private readonly IMessaging messaging;
21
private SummaryInformationStreams transformSummaryInfo;
22
@@ -111,7 +110,6 @@ namespace WixToolset.Core.WindowsInstaller
110
foreach (var updatedRow in updatedTable.Rows)
111
{
112
updatedRow.Operation = RowOperation.Add;
114
- updatedRow.SectionId = SectionDelimiter + updatedRow.SectionId;
113
addedTable.Rows.Add(updatedRow);
114
}
115
}
@@ -200,7 +198,6 @@ namespace WixToolset.Core.WindowsInstaller
198
else if (null == updatedRow)
199
{
200
operation = targetRow.Operation = RowOperation.Delete;
203
- targetRow.SectionId += SectionDelimiter;
201
comparedRow = targetRow;
202
keepRow = true;
203
}
@@ -211,9 +208,8 @@ namespace WixToolset.Core.WindowsInstaller
208
if (!this.SuppressKeepingSpecialRows && "_SummaryInformation" == targetTable.Name)
209
{
210
// ignore rows that shouldn't be in a transform
214
- if (Enum.IsDefined(typeof(SummaryInformation.Transform), (int)updatedRow[0]))
211
+ if (Enum.IsDefined(typeof(SummaryInformation.Transform), updatedRow.FieldAsInteger(0)))
212
{
216
- updatedRow.SectionId = targetRow.SectionId + SectionDelimiter + updatedRow.SectionId;
213
comparedRow = updatedRow;
214
keepRow = true;
215
operation = RowOperation.Modify;
@@ -297,7 +293,7 @@ namespace WixToolset.Core.WindowsInstaller
293
if (keepRow)
294
{
295
comparedRow = updatedRow;
300
- comparedRow.SectionId = targetRow.SectionId + SectionDelimiter + updatedRow.SectionId;
296
+ //comparedRow.SectionId = targetRow.SectionId + SectionDelimiter + updatedRow.SectionId;
297
}
298
}
299
}
@@ -361,7 +357,6 @@ namespace WixToolset.Core.WindowsInstaller
357
var updatedRow = (Row)updatedPrimaryKeyEntry.Value;
358
359
updatedRow.Operation = RowOperation.Add;
364
- updatedRow.SectionId = SectionDelimiter + updatedRow.SectionId;
360
rows.Add(updatedRow);
361
}
362
}
src/wix/WixToolset.Core.WindowsInstaller/ExtensibilityServices/WindowsInstallerBackendHelper.cs
+1
-4
@@ -141,10 +141,7 @@ namespace WixToolset.Core.WindowsInstaller.ExtensibilityServices
141
{
142
var table = data.EnsureTable(tableDefinition);
143
144
- var row = table.CreateRow(symbol.SourceLineNumbers);
145
- row.SectionId = section.Id;
146
-
147
- return row;
144
+ return table.CreateRow(symbol.SourceLineNumbers);
145
}
146
147
public bool TryAddSymbolToMatchingTableDefinitions(IntermediateSection section, IntermediateSymbol symbol, WindowsInstallerData data, TableDefinitionCollection tableDefinitions)
src/wix/WixToolset.Core.WindowsInstaller/MspBackend.cs
+7
-3
@@ -34,14 +34,18 @@ namespace WixToolset.Core.WindowsInstaller
34
35
// Create transforms named in patch transforms.
36
IEnumerable<PatchTransform> patchTransforms;
37
+ PatchFilterMap patchFilterMap;
38
{
38
- var command = new CreatePatchTransformsCommand(messaging, backendHelper, pathResolver, fileResolver, resolveExtensions, context.IntermediateRepresentation, context.IntermediateFolder, context.BindPaths);
39
- patchTransforms = command.Execute();
39
+ var command = new CreatePatchTransformsCommand(messaging, backendHelper, pathResolver, fileResolver, resolveExtensions, backendExtensions, context.IntermediateRepresentation, context.IntermediateFolder, context.BindPaths);
40
+ command.Execute();
41
+
42
+ patchTransforms = command.PatchTransforms;
43
+ patchFilterMap = command.PatchFilterMap;
44
}
45
46
// Reduce transforms.
47
{
44
- var command = new ReduceTransformCommand(context.IntermediateRepresentation, patchTransforms);
48
+ var command = new ReduceTransformCommand(context.IntermediateRepresentation, patchTransforms, patchFilterMap);
49
command.Execute();
50
}
51