@joebigelow / wix-1 / commits / f4a0522f

Provide a default INSTALLFOLDER.

If INSTALLFOLDER is referenced and not defined, define one with reasonable default values. Implements WIP https://github.com/wixtoolset/issues/issues/7588.

Bob Arnson committed Jul 29, 2023 at 19:03 UTC f4a0522fde6066c76e771f6be381bf9e658b875a
6 files changed +157 -40
src/wix/WixToolset.Core/AssignDefaultFeatureCommand.cs
+39 -27
@@ -3,55 +3,67 @@
3 namespace WixToolset.Core
4 {
5 using System.Collections.Generic;
6 - using System.ComponentModel;
6 using System.Linq;
7 + using WixToolset.Core.Link;
8 using WixToolset.Data;
9 using WixToolset.Data.Symbols;
10
11 internal class AssignDefaultFeatureCommand
12 {
13 - public AssignDefaultFeatureCommand(IntermediateSection entrySection, IEnumerable<IntermediateSection> sections)
13 + public AssignDefaultFeatureCommand(FindEntrySectionAndLoadSymbolsCommand find, List<IntermediateSection> sections)
14 {
15 - this.EntrySection = entrySection;
15 + this.Find = find;
16 this.Sections = sections;
17 }
18
19 - public IntermediateSection EntrySection { get; }
20 -
19 public IEnumerable<IntermediateSection> Sections { get; }
20
21 + public FindEntrySectionAndLoadSymbolsCommand Find { get; }
22 +
23 public void Execute()
24 {
25 - foreach (var section in this.Sections)
25 + if (this.Find.EntrySection.Type == SectionType.Package
26 + && !this.Sections.Where(s => s.Id != WixStandardLibraryIdentifiers.DefaultFeatureName)
27 + .SelectMany(s => s.Symbols).OfType<FeatureSymbol>().Any())
28 {
27 - var components = section.Symbols.OfType<ComponentSymbol>().ToList();
28 - foreach (var component in components)
29 + var addedToDefaultFeature = false;
30 +
31 + foreach (var section in this.Sections)
32 {
30 - this.EntrySection.AddSymbol(new WixComplexReferenceSymbol(component.SourceLineNumbers)
33 + var components = section.Symbols.OfType<ComponentSymbol>().ToList();
34 + foreach (var component in components)
35 {
32 - Parent = WixStandardLibraryIdentifiers.DefaultFeatureName,
33 - ParentType = ComplexReferenceParentType.Feature,
34 - ParentLanguage = null,
35 - Child = component.Id.Id,
36 - ChildType = ComplexReferenceChildType.Component,
37 - IsPrimary = true,
38 - });
36 + this.Find.EntrySection.AddSymbol(new WixComplexReferenceSymbol(component.SourceLineNumbers)
37 + {
38 + Parent = WixStandardLibraryIdentifiers.DefaultFeatureName,
39 + ParentType = ComplexReferenceParentType.Feature,
40 + ParentLanguage = null,
41 + Child = component.Id.Id,
42 + ChildType = ComplexReferenceChildType.Component,
43 + IsPrimary = true,
44 + });
45 +
46 + this.Find.EntrySection.AddSymbol(new WixGroupSymbol(component.SourceLineNumbers)
47 + {
48 + ParentId = WixStandardLibraryIdentifiers.DefaultFeatureName,
49 + ParentType = ComplexReferenceParentType.Feature,
50 + ChildId = component.Id.Id,
51 + ChildType = ComplexReferenceChildType.Component,
52 + });
53
40 - this.EntrySection.AddSymbol(new WixGroupSymbol(component.SourceLineNumbers)
54 + addedToDefaultFeature = true;
55 + }
56 + }
57 +
58 + if (addedToDefaultFeature)
59 + {
60 + this.Find.EntrySection.AddSymbol(new WixSimpleReferenceSymbol()
61 {
42 - ParentId = WixStandardLibraryIdentifiers.DefaultFeatureName,
43 - ParentType = ComplexReferenceParentType.Feature,
44 - ChildId = component.Id.Id,
45 - ChildType = ComplexReferenceChildType.Component,
62 + Table = "Feature",
63 + PrimaryKeys = WixStandardLibraryIdentifiers.DefaultFeatureName,
64 });
65 }
66 }
49 -
50 - this.EntrySection.AddSymbol(new WixSimpleReferenceSymbol()
51 - {
52 - Table = "Feature",
53 - PrimaryKeys = WixStandardLibraryIdentifiers.DefaultFeatureName,
54 - });
67 }
68 }
69 }
src/wix/WixToolset.Core/Link/AddDefaultSymbolsCommand.cs new
+69
@@ -0,0 +1,69 @@
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 +{
5 + using System.Collections.Generic;
6 + using System.Linq;
7 + using WixToolset.Data;
8 + using WixToolset.Data.Symbols;
9 +
10 + internal class AddDefaultSymbolsCommand
11 + {
12 + public static readonly string WixStandardInstallFolder = "INSTALLFOLDER";
13 + public static readonly string WixStandardInstallFolderParent = "ProgramFiles6432Folder";
14 + public static readonly string WixStandardInstallFolderReference = "Directory:INSTALLFOLDER";
15 +
16 + public AddDefaultSymbolsCommand(FindEntrySectionAndLoadSymbolsCommand find, IList<IntermediateSection> sections)
17 + {
18 + this.Find = find;
19 + this.Sections = sections;
20 + }
21 +
22 + public IList<IntermediateSection> Sections { get; }
23 +
24 + public FindEntrySectionAndLoadSymbolsCommand Find { get; }
25 +
26 + public void Execute()
27 + {
28 + if (this.Find.EntrySection.Type != SectionType.Package)
29 + {
30 + // Only packages...for now.
31 + return;
32 + }
33 +
34 + if (!this.Find.SymbolsByName.ContainsKey(WixStandardInstallFolderReference))
35 + {
36 + var sourceLineNumber = new SourceLineNumber("DefaultInstallFolder");
37 +
38 + this.AddSymbolsToNewSection(WixStandardInstallFolder,
39 + new DirectorySymbol(sourceLineNumber, new Identifier(AccessModifier.Global, WixStandardInstallFolder))
40 + {
41 + ParentDirectoryRef = WixStandardInstallFolderParent,
42 + Name = "!(bind.Property.Manufacturer) !(bind.Property.ProductName)",
43 + SourceName = ".",
44 + },
45 + new WixSimpleReferenceSymbol(sourceLineNumber, new Identifier(AccessModifier.Global, WixStandardInstallFolder))
46 + {
47 + Table = "Directory",
48 + PrimaryKeys = WixStandardInstallFolderParent,
49 + }
50 + );
51 + }
52 + }
53 +
54 + private void AddSymbolsToNewSection(string sectionId, params IntermediateSymbol[] symbols)
55 + {
56 + var section = new IntermediateSection(sectionId, SectionType.Fragment);
57 + this.Sections.Add(section);
58 +
59 + foreach (var symbol in symbols)
60 + {
61 + section.AddSymbol(symbol);
62 +
63 + var symbolWithSection = new SymbolWithSection(section, symbol);
64 + var fullName = symbolWithSection.GetFullName();
65 + this.Find.SymbolsByName.Add(fullName, symbolWithSection);
66 + }
67 + }
68 + }
69 +}
src/wix/WixToolset.Core/Linker.cs
+10 -4
@@ -126,11 +126,17 @@ namespace WixToolset.Core
126 }
127 }
128
129 - // If there are no authored features, create a default feature and assign the components to it.
130 - if (find.EntrySection.Type == SectionType.Package
131 - && !sections.Where(s => s.Id != WixStandardLibraryIdentifiers.DefaultFeatureName).SelectMany(s => s.Symbols).OfType<FeatureSymbol>().Any())
129 + // Add default symbols that need a bit more intelligence than just being
130 + // included in the standard library.
131 {
133 - var command = new AssignDefaultFeatureCommand(find.EntrySection, sections);
132 + var command = new AddDefaultSymbolsCommand(find, sections);
133 + command.Execute();
134 + }
135 +
136 + // If there are no authored features, create a default feature and assign
137 + // the components to it.
138 + {
139 + var command = new AssignDefaultFeatureCommand(find, sections);
140 command.Execute();
141 }
142
src/wix/test/WixToolsetTest.CoreIntegration/DirectoryFixture.cs
+38
@@ -13,6 +13,44 @@ namespace WixToolsetTest.CoreIntegration
13
14 public class DirectoryFixture
15 {
16 + [Fact]
17 + public void CanGetDefaultInstallFolder()
18 + {
19 + var folder = TestData.Get(@"TestData\SingleFile");
20 +
21 + using (var fs = new DisposableFileSystem())
22 + {
23 + var baseFolder = fs.GetFolder();
24 + var intermediateFolder = Path.Combine(baseFolder, "obj");
25 + var msiPath = Path.Combine(baseFolder, @"bin\test.msi");
26 +
27 + var result = WixRunner.Execute(new[]
28 + {
29 + "build",
30 + Path.Combine(folder, "Package.wxs"),
31 + Path.Combine(folder, "PackageComponents.wxs"),
32 + "-loc", Path.Combine(folder, "Package.en-us.wxl"),
33 + "-bindpath", Path.Combine(folder, "data"),
34 + "-intermediateFolder", intermediateFolder,
35 + "-o", msiPath
36 + });
37 +
38 + result.AssertSuccess();
39 +
40 + var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb"));
41 + var section = intermediate.Sections.Single();
42 +
43 + var dirSymbols = section.Symbols.OfType<WixToolset.Data.Symbols.DirectorySymbol>().ToList();
44 + WixAssert.CompareLineByLine(new[]
45 + {
46 + "INSTALLFOLDER:ProgramFiles6432Folder:Example Corporation MsiPackage",
47 + "ProgramFiles6432Folder:ProgramFilesFolder:.",
48 + "ProgramFilesFolder:TARGETDIR:PFiles",
49 + "TARGETDIR::SourceDir"
50 + }, dirSymbols.OrderBy(d => d.Id.Id).Select(d => d.Id.Id + ":" + d.ParentDirectoryRef + ":" + d.Name).ToArray());
51 + }
52 + }
53 +
54 [Fact]
55 public void CanGet32bitProgramFiles6432Folder()
56 {
src/wix/test/WixToolsetTest.CoreIntegration/MsiFixture.cs
+1 -1
@@ -38,7 +38,7 @@ namespace WixToolsetTest.CoreIntegration
38
39 Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.msi")));
40 Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb")));
41 - Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\PFiles\MsiPackage\test.txt")));
41 + Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\PFiles\Example Corporation MsiPackage\test.txt")));
42
43 var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb"));
44
src/wix/test/WixToolsetTest.CoreIntegration/TestData/SingleFile/Package.wxs
-8
@@ -1,17 +1,9 @@
1 <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Package Name="MsiPackage" Codepage="1252" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" Compressed="no" InstallerVersion="200" Scope="perMachine">
3 -
4 -
3 <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
4
5 <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
6 <ComponentGroupRef Id="ProductComponents" />
7 </Feature>
8 </Package>
11 -
12 - <Fragment>
13 - <StandardDirectory Id="ProgramFilesFolder">
14 - <Directory Id="INSTALLFOLDER" Name="MsiPackage" SourceName="." />
15 - </StandardDirectory>
16 - </Fragment>
9 </Wix>