From f4a0522fde6066c76e771f6be381bf9e658b875a Mon Sep 17 00:00:00 2001 From: Bob Arnson Date: Sat, 29 Jul 2023 19:03:34 -0400 Subject: [PATCH] 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. --- .../AssignDefaultFeatureCommand.cs | 66 ++++++++++-------- .../Link/AddDefaultSymbolsCommand.cs | 69 +++++++++++++++++++ src/wix/WixToolset.Core/Linker.cs | 14 ++-- .../DirectoryFixture.cs | 38 ++++++++++ .../MsiFixture.cs | 2 +- .../TestData/SingleFile/Package.wxs | 8 --- 6 files changed, 157 insertions(+), 40 deletions(-) create mode 100644 src/wix/WixToolset.Core/Link/AddDefaultSymbolsCommand.cs diff --git a/src/wix/WixToolset.Core/AssignDefaultFeatureCommand.cs b/src/wix/WixToolset.Core/AssignDefaultFeatureCommand.cs index 9904d740a..614af1ebf 100644 --- a/src/wix/WixToolset.Core/AssignDefaultFeatureCommand.cs +++ b/src/wix/WixToolset.Core/AssignDefaultFeatureCommand.cs @@ -3,55 +3,67 @@ namespace WixToolset.Core { using System.Collections.Generic; - using System.ComponentModel; using System.Linq; + using WixToolset.Core.Link; using WixToolset.Data; using WixToolset.Data.Symbols; internal class AssignDefaultFeatureCommand { - public AssignDefaultFeatureCommand(IntermediateSection entrySection, IEnumerable sections) + public AssignDefaultFeatureCommand(FindEntrySectionAndLoadSymbolsCommand find, List sections) { - this.EntrySection = entrySection; + this.Find = find; this.Sections = sections; } - public IntermediateSection EntrySection { get; } - public IEnumerable Sections { get; } + public FindEntrySectionAndLoadSymbolsCommand Find { get; } + public void Execute() { - foreach (var section in this.Sections) + if (this.Find.EntrySection.Type == SectionType.Package + && !this.Sections.Where(s => s.Id != WixStandardLibraryIdentifiers.DefaultFeatureName) + .SelectMany(s => s.Symbols).OfType().Any()) { - var components = section.Symbols.OfType().ToList(); - foreach (var component in components) + var addedToDefaultFeature = false; + + foreach (var section in this.Sections) { - this.EntrySection.AddSymbol(new WixComplexReferenceSymbol(component.SourceLineNumbers) + var components = section.Symbols.OfType().ToList(); + foreach (var component in components) { - Parent = WixStandardLibraryIdentifiers.DefaultFeatureName, - ParentType = ComplexReferenceParentType.Feature, - ParentLanguage = null, - Child = component.Id.Id, - ChildType = ComplexReferenceChildType.Component, - IsPrimary = true, - }); + this.Find.EntrySection.AddSymbol(new WixComplexReferenceSymbol(component.SourceLineNumbers) + { + Parent = WixStandardLibraryIdentifiers.DefaultFeatureName, + ParentType = ComplexReferenceParentType.Feature, + ParentLanguage = null, + Child = component.Id.Id, + ChildType = ComplexReferenceChildType.Component, + IsPrimary = true, + }); + + this.Find.EntrySection.AddSymbol(new WixGroupSymbol(component.SourceLineNumbers) + { + ParentId = WixStandardLibraryIdentifiers.DefaultFeatureName, + ParentType = ComplexReferenceParentType.Feature, + ChildId = component.Id.Id, + ChildType = ComplexReferenceChildType.Component, + }); - this.EntrySection.AddSymbol(new WixGroupSymbol(component.SourceLineNumbers) + addedToDefaultFeature = true; + } + } + + if (addedToDefaultFeature) + { + this.Find.EntrySection.AddSymbol(new WixSimpleReferenceSymbol() { - ParentId = WixStandardLibraryIdentifiers.DefaultFeatureName, - ParentType = ComplexReferenceParentType.Feature, - ChildId = component.Id.Id, - ChildType = ComplexReferenceChildType.Component, + Table = "Feature", + PrimaryKeys = WixStandardLibraryIdentifiers.DefaultFeatureName, }); } } - - this.EntrySection.AddSymbol(new WixSimpleReferenceSymbol() - { - Table = "Feature", - PrimaryKeys = WixStandardLibraryIdentifiers.DefaultFeatureName, - }); } } } diff --git a/src/wix/WixToolset.Core/Link/AddDefaultSymbolsCommand.cs b/src/wix/WixToolset.Core/Link/AddDefaultSymbolsCommand.cs new file mode 100644 index 000000000..221b54110 --- /dev/null +++ b/src/wix/WixToolset.Core/Link/AddDefaultSymbolsCommand.cs @@ -0,0 +1,69 @@ +// 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. + +namespace WixToolset.Core.Link +{ + using System.Collections.Generic; + using System.Linq; + using WixToolset.Data; + using WixToolset.Data.Symbols; + + internal class AddDefaultSymbolsCommand + { + public static readonly string WixStandardInstallFolder = "INSTALLFOLDER"; + public static readonly string WixStandardInstallFolderParent = "ProgramFiles6432Folder"; + public static readonly string WixStandardInstallFolderReference = "Directory:INSTALLFOLDER"; + + public AddDefaultSymbolsCommand(FindEntrySectionAndLoadSymbolsCommand find, IList sections) + { + this.Find = find; + this.Sections = sections; + } + + public IList Sections { get; } + + public FindEntrySectionAndLoadSymbolsCommand Find { get; } + + public void Execute() + { + if (this.Find.EntrySection.Type != SectionType.Package) + { + // Only packages...for now. + return; + } + + if (!this.Find.SymbolsByName.ContainsKey(WixStandardInstallFolderReference)) + { + var sourceLineNumber = new SourceLineNumber("DefaultInstallFolder"); + + this.AddSymbolsToNewSection(WixStandardInstallFolder, + new DirectorySymbol(sourceLineNumber, new Identifier(AccessModifier.Global, WixStandardInstallFolder)) + { + ParentDirectoryRef = WixStandardInstallFolderParent, + Name = "!(bind.Property.Manufacturer) !(bind.Property.ProductName)", + SourceName = ".", + }, + new WixSimpleReferenceSymbol(sourceLineNumber, new Identifier(AccessModifier.Global, WixStandardInstallFolder)) + { + Table = "Directory", + PrimaryKeys = WixStandardInstallFolderParent, + } + ); + } + } + + private void AddSymbolsToNewSection(string sectionId, params IntermediateSymbol[] symbols) + { + var section = new IntermediateSection(sectionId, SectionType.Fragment); + this.Sections.Add(section); + + foreach (var symbol in symbols) + { + section.AddSymbol(symbol); + + var symbolWithSection = new SymbolWithSection(section, symbol); + var fullName = symbolWithSection.GetFullName(); + this.Find.SymbolsByName.Add(fullName, symbolWithSection); + } + } + } +} diff --git a/src/wix/WixToolset.Core/Linker.cs b/src/wix/WixToolset.Core/Linker.cs index ce5612c34..32ccb1449 100644 --- a/src/wix/WixToolset.Core/Linker.cs +++ b/src/wix/WixToolset.Core/Linker.cs @@ -126,11 +126,17 @@ public Intermediate Link(ILinkContext context) } } - // If there are no authored features, create a default feature and assign the components to it. - if (find.EntrySection.Type == SectionType.Package - && !sections.Where(s => s.Id != WixStandardLibraryIdentifiers.DefaultFeatureName).SelectMany(s => s.Symbols).OfType().Any()) + // Add default symbols that need a bit more intelligence than just being + // included in the standard library. { - var command = new AssignDefaultFeatureCommand(find.EntrySection, sections); + var command = new AddDefaultSymbolsCommand(find, sections); + command.Execute(); + } + + // If there are no authored features, create a default feature and assign + // the components to it. + { + var command = new AssignDefaultFeatureCommand(find, sections); command.Execute(); } diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/DirectoryFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/DirectoryFixture.cs index 3f4108cbb..7f019692d 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/DirectoryFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/DirectoryFixture.cs @@ -13,6 +13,44 @@ namespace WixToolsetTest.CoreIntegration public class DirectoryFixture { + [Fact] + public void CanGetDefaultInstallFolder() + { + var folder = TestData.Get(@"TestData\SingleFile"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var msiPath = Path.Combine(baseFolder, @"bin\test.msi"); + + var result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "Package.wxs"), + Path.Combine(folder, "PackageComponents.wxs"), + "-loc", Path.Combine(folder, "Package.en-us.wxl"), + "-bindpath", Path.Combine(folder, "data"), + "-intermediateFolder", intermediateFolder, + "-o", msiPath + }); + + result.AssertSuccess(); + + var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb")); + var section = intermediate.Sections.Single(); + + var dirSymbols = section.Symbols.OfType().ToList(); + WixAssert.CompareLineByLine(new[] + { + "INSTALLFOLDER:ProgramFiles6432Folder:Example Corporation MsiPackage", + "ProgramFiles6432Folder:ProgramFilesFolder:.", + "ProgramFilesFolder:TARGETDIR:PFiles", + "TARGETDIR::SourceDir" + }, dirSymbols.OrderBy(d => d.Id.Id).Select(d => d.Id.Id + ":" + d.ParentDirectoryRef + ":" + d.Name).ToArray()); + } + } + [Fact] public void CanGet32bitProgramFiles6432Folder() { diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/MsiFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/MsiFixture.cs index fe9e8641f..7f5dfcd0c 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/MsiFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/MsiFixture.cs @@ -38,7 +38,7 @@ public void CanBuildSingleFile() Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.msi"))); Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb"))); - Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\PFiles\MsiPackage\test.txt"))); + Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\PFiles\Example Corporation MsiPackage\test.txt"))); var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb")); diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SingleFile/Package.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SingleFile/Package.wxs index 3cab42674..0a5823900 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SingleFile/Package.wxs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SingleFile/Package.wxs @@ -1,17 +1,9 @@ - - - - - - - -