@joebigelow / wix-1 / commits / 0d1851c7

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>