Skip to content

Commit

Permalink
Provide a default INSTALLFOLDER.
Browse files Browse the repository at this point in the history
If INSTALLFOLDER is referenced and not defined, define one with
reasonable default values.

Implements WIP wixtoolset/issues#7588.
  • Loading branch information
barnson committed Dec 30, 2023
1 parent 1c249dd commit f4a0522
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 40 deletions.
66 changes: 39 additions & 27 deletions src/wix/WixToolset.Core/AssignDefaultFeatureCommand.cs
Expand Up @@ -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<IntermediateSection> sections)
public AssignDefaultFeatureCommand(FindEntrySectionAndLoadSymbolsCommand find, List<IntermediateSection> sections)
{
this.EntrySection = entrySection;
this.Find = find;
this.Sections = sections;
}

public IntermediateSection EntrySection { get; }

public IEnumerable<IntermediateSection> 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<FeatureSymbol>().Any())
{
var components = section.Symbols.OfType<ComponentSymbol>().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<ComponentSymbol>().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,
});
}
}
}
69 changes: 69 additions & 0 deletions 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<IntermediateSection> sections)
{
this.Find = find;
this.Sections = sections;
}

public IList<IntermediateSection> 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);
}
}
}
}
14 changes: 10 additions & 4 deletions src/wix/WixToolset.Core/Linker.cs
Expand Up @@ -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<FeatureSymbol>().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();
}

Expand Down
38 changes: 38 additions & 0 deletions src/wix/test/WixToolsetTest.CoreIntegration/DirectoryFixture.cs
Expand Up @@ -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<WixToolset.Data.Symbols.DirectorySymbol>().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()
{
Expand Down
2 changes: 1 addition & 1 deletion src/wix/test/WixToolsetTest.CoreIntegration/MsiFixture.cs
Expand Up @@ -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"));

Expand Down
@@ -1,17 +1,9 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<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">


<MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />

<Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Package>

<Fragment>
<StandardDirectory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="MsiPackage" SourceName="." />
</StandardDirectory>
</Fragment>
</Wix>

0 comments on commit f4a0522

Please sign in to comment.