Fix handling of duplicate directories
Rob Mensching committed
Jan 5, 2021 at 15:13 UTC
0d1851c79901ba6ddbba9bb63f758760fe5be994
7 files changed
+92
-15
src/WixToolset.Core.WindowsInstaller/Bind/AddRequiredStandardDirectories.cs
+8
-8
@@ -27,7 +27,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
27
public void Execute()
28
{
29
var directories = this.Section.Symbols.OfType<DirectorySymbol>().ToList();
30
- var directoriesById = directories.ToDictionary(d => d.Id.Id);
30
+ var directoryIds = new SortedSet<string>(directories.Select(d => d.Id.Id));
31
32
foreach (var directory in directories)
33
{
@@ -42,20 +42,20 @@ namespace WixToolset.Core.WindowsInstaller.Bind
42
}
43
else
44
{
45
- this.EnsureStandardDirectoryAdded(directoriesById, parentDirectoryId, directory.SourceLineNumbers);
45
+ this.EnsureStandardDirectoryAdded(directoryIds, parentDirectoryId, directory.SourceLineNumbers);
46
}
47
}
48
49
- if (!directoriesById.ContainsKey("TARGETDIR") && WindowsInstallerStandard.TryGetStandardDirectory("TARGETDIR", out var targetDir))
49
+ if (!directoryIds.Contains("TARGETDIR") && WindowsInstallerStandard.TryGetStandardDirectory("TARGETDIR", out var targetDir))
50
{
51
- directoriesById.Add(targetDir.Id.Id, targetDir);
51
+ directoryIds.Add(targetDir.Id.Id);
52
this.Section.AddSymbol(targetDir);
53
}
54
}
55
56
- private void EnsureStandardDirectoryAdded(Dictionary<string, DirectorySymbol> directoriesById, string directoryId, SourceLineNumber sourceLineNumbers)
56
+ private void EnsureStandardDirectoryAdded(ISet<string> directoryIds, string directoryId, SourceLineNumber sourceLineNumbers)
57
{
58
- if (!directoriesById.ContainsKey(directoryId) && WindowsInstallerStandard.TryGetStandardDirectory(directoryId, out var standardDirectory))
58
+ if (!directoryIds.Contains(directoryId) && WindowsInstallerStandard.TryGetStandardDirectory(directoryId, out var standardDirectory))
59
{
60
var parentDirectoryId = this.GetStandardDirectoryParent(directoryId);
61
@@ -65,12 +65,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
65
ParentDirectoryRef = parentDirectoryId,
66
};
67
68
- directoriesById.Add(directory.Id.Id, directory);
68
+ directoryIds.Add(directory.Id.Id);
69
this.Section.AddSymbol(directory);
70
71
if (!String.IsNullOrEmpty(parentDirectoryId))
72
{
73
- this.EnsureStandardDirectoryAdded(directoriesById, parentDirectoryId, sourceLineNumbers);
73
+ this.EnsureStandardDirectoryAdded(directoryIds, parentDirectoryId, sourceLineNumbers);
74
}
75
}
76
}
src/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs
+10
-2
@@ -38,10 +38,17 @@ namespace WixToolset.Core.Link
38
/// </summary>
39
public IEnumerable<SymbolWithSection> PossibleConflicts { get; private set; }
40
41
+ /// <summary>
42
+ /// Gets the collection of redundant symbols that should not be included
43
+ /// in the final output.
44
+ /// </summary>
45
+ public ISet<IntermediateSymbol> RedundantSymbols { get; private set; }
46
+
47
public void Execute()
48
{
49
var symbolsByName = new Dictionary<string, SymbolWithSection>();
50
var possibleConflicts = new HashSet<SymbolWithSection>();
51
+ var redundantSymbols = new HashSet<IntermediateSymbol>();
52
53
if (!Enum.TryParse(this.ExpectedOutputType.ToString(), out SectionType expectedEntrySectionType))
54
{
@@ -91,13 +98,13 @@ namespace WixToolset.Core.Link
98
// Ensure identical symbol's symbol is marked redundant to ensure (should the symbol be
99
// referenced into the final output) it will not add duplicate primary keys during
100
// the .IDT importing.
94
- //symbol.Row.Redundant = true; - TODO: remove this
101
existingSymbol.AddRedundant(symbolWithSection);
102
+ redundantSymbols.Add(symbolWithSection.Symbol);
103
}
104
else
105
{
106
existingSymbol.AddPossibleConflict(symbolWithSection);
100
- possibleConflicts.Add(existingSymbol);
107
+ possibleConflicts.Add(symbolWithSection);
108
}
109
}
110
}
@@ -105,6 +112,7 @@ namespace WixToolset.Core.Link
112
113
this.SymbolsByName = symbolsByName;
114
this.PossibleConflicts = possibleConflicts;
115
+ this.RedundantSymbols = redundantSymbols;
116
}
117
}
118
}
src/WixToolset.Core/Link/IntermediateSymbolExtensions.cs
+3
-3
@@ -1,4 +1,4 @@
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.
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.Link
4
{
@@ -9,10 +9,10 @@ namespace WixToolset.Core.Link
9
public static bool IsIdentical(this IntermediateSymbol first, IntermediateSymbol second)
10
{
11
var identical = (first.Definition.Type == second.Definition.Type &&
12
- first.Definition.Name == second.Definition.Name &&
12
+ (first.Definition.Type != SymbolDefinitionType.MustBeFromAnExtension || first.Definition.Name == second.Definition.Name) &&
13
first.Definition.FieldDefinitions.Length == second.Definition.FieldDefinitions.Length);
14
15
- for (int i = 0; identical && i < first.Definition.FieldDefinitions.Length; ++i)
15
+ for (var i = 0; identical && i < first.Definition.FieldDefinitions.Length; ++i)
16
{
17
var firstField = first[i];
18
var secondField = second[i];
src/WixToolset.Core/Link/ResolveReferencesCommand.cs
+2
-2
@@ -170,9 +170,9 @@ namespace WixToolset.Core.Link
170
case AccessModifier.Public:
171
return true;
172
case AccessModifier.Internal:
173
- return symbolWithSection.Section.CompilationId.Equals(referencingSection.CompilationId) || (null != symbolWithSection.Section.LibraryId && symbolWithSection.Section.LibraryId.Equals(referencingSection.LibraryId));
173
+ return symbolWithSection.Section.CompilationId == referencingSection.CompilationId || (null != symbolWithSection.Section.LibraryId && symbolWithSection.Section.LibraryId == referencingSection.LibraryId);
174
case AccessModifier.Protected:
175
- return symbolWithSection.Section.CompilationId.Equals(referencingSection.CompilationId);
175
+ return symbolWithSection.Section.CompilationId == referencingSection.CompilationId;
176
case AccessModifier.Private:
177
return referencingSection == symbolWithSection.Section;
178
default:
src/WixToolset.Core/Linker.cs
+5
@@ -226,6 +226,11 @@ namespace WixToolset.Core
226
227
foreach (var symbol in section.Symbols)
228
{
229
+ if (find.RedundantSymbols.Contains(symbol))
230
+ {
231
+ continue;
232
+ }
233
+
234
var copySymbol = true; // by default, copy symbols.
235
236
// handle special tables
src/test/WixToolsetTest.CoreIntegration/DirectoryFixture.cs
+39
@@ -85,5 +85,44 @@ namespace WixToolsetTest.CoreIntegration
85
}, dirSymbols.Select(d => d.Id.Id).ToArray());
86
}
87
}
88
+
89
+ [Fact]
90
+ public void CanGetDuplicateDir()
91
+ {
92
+ var folder = TestData.Get(@"TestData");
93
+
94
+ using (var fs = new DisposableFileSystem())
95
+ {
96
+ var baseFolder = fs.GetFolder();
97
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
98
+ var msiPath = Path.Combine(baseFolder, @"bin\test.msi");
99
+
100
+ var result = WixRunner.Execute(new[]
101
+ {
102
+ "build",
103
+ "-arch", "x64",
104
+ Path.Combine(folder, "DuplicateDir", "DuplicateDir.wxs"),
105
+ Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
106
+ "-bindpath", Path.Combine(folder, "SingleFile", "data"),
107
+ "-intermediateFolder", intermediateFolder,
108
+ "-o", msiPath
109
+ });
110
+
111
+ result.AssertSuccess();
112
+
113
+ var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb"));
114
+ var section = intermediate.Sections.Single();
115
+
116
+ var dirSymbols = section.Symbols.OfType<WixToolset.Data.Symbols.DirectorySymbol>().ToList();
117
+ Assert.Equal(new[]
118
+ {
119
+ "dirZsSsu81KcG46xXTwc4mTSZO5Zx4",
120
+ "INSTALLFOLDER",
121
+ "ProgramFiles6432Folder",
122
+ "ProgramFiles64Folder",
123
+ "TARGETDIR"
124
+ }, dirSymbols.Select(d => d.Id.Id).ToArray());
125
+ }
126
+ }
127
}
128
}
src/test/WixToolsetTest.CoreIntegration/TestData/DuplicateDir/DuplicateDir.wxs
new
+25
@@ -0,0 +1,25 @@
1
+<?xml version="1.0" encoding="utf-8" ?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3
+ <Fragment>
4
+ <ComponentGroup Id="ProductComponents">
5
+ <ComponentGroupRef Id="GroupA" />
6
+ <ComponentGroupRef Id="GroupB" />
7
+ </ComponentGroup>
8
+ </Fragment>
9
+
10
+ <Fragment>
11
+ <ComponentGroup Id="GroupA" Directory="INSTALLFOLDER:\dupe">
12
+ <Component>
13
+ <File Name="a.txt" Source="test.txt" />
14
+ </Component>
15
+ </ComponentGroup>
16
+ </Fragment>
17
+
18
+ <Fragment>
19
+ <ComponentGroup Id="GroupB" Directory="INSTALLFOLDER:\dupe">
20
+ <Component>
21
+ <File Name="b.txt" Source="test.txt" />
22
+ </Component>
23
+ </ComponentGroup>
24
+ </Fragment>
25
+</Wix>