Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Files file harvesting. #489

Merged
merged 1 commit into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/api/wix/WixToolset.Data/ErrorMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,11 @@ public static Message ExpectedAttribute(SourceLineNumber sourceLineNumbers, stri
return Message(sourceLineNumbers, Ids.ExpectedAttribute, "The {0}/@{1} attribute was not found; it is required unless the attribute {2} has a value of '{3}'.", elementName, attributeName, otherAttributeName, otherAttributeValue, otherAttributeValueUnless);
}

public static Message ExpectedAttributeInElementOrParent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName)
{
return Message(sourceLineNumbers, Ids.ExpectedAttributeInElementOrParent, "The {0}/@{1} attribute was not found or empty; it is required unless it is specified in the parent element.", elementName, attributeName);
}

public static Message ExpectedAttributeInElementOrParent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string parentElementName)
{
return Message(sourceLineNumbers, Ids.ExpectedAttributeInElementOrParent, "The {0}/@{1} attribute was not found or empty; it is required, or it can be specified in the parent {2} element.", elementName, attributeName, parentElementName);
Expand Down
84 changes: 84 additions & 0 deletions src/api/wix/WixToolset.Data/Symbols/HarvestFilesSymbol.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// 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.Data
{
using WixToolset.Data.Symbols;

public static partial class SymbolDefinitions
{
public static readonly IntermediateSymbolDefinition HarvestFiles = new IntermediateSymbolDefinition(
SymbolDefinitionType.HarvestFiles,
new[]
{
new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.DirectoryRef), IntermediateFieldType.String),
new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.Inclusions), IntermediateFieldType.String),
new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.Exclusions), IntermediateFieldType.String),
new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.ComplexReferenceParentType), IntermediateFieldType.String),
new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.ParentId), IntermediateFieldType.String),
new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.SourcePath), IntermediateFieldType.String),
},
typeof(HarvestFilesSymbol));
}
}

namespace WixToolset.Data.Symbols
{
public enum HarvestFilesSymbolFields
{
DirectoryRef,
Inclusions,
Exclusions,
ComplexReferenceParentType,
ParentId,
SourcePath,
}

public class HarvestFilesSymbol : IntermediateSymbol
{
public HarvestFilesSymbol() : base(SymbolDefinitions.HarvestFiles, null, null)
{
}

public HarvestFilesSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SymbolDefinitions.HarvestFiles, sourceLineNumber, id)
{
}

public IntermediateField this[HarvestFilesSymbolFields index] => this.Fields[(int)index];

public string DirectoryRef
{
get => (string)this.Fields[(int)HarvestFilesSymbolFields.DirectoryRef];
set => this.Set((int)HarvestFilesSymbolFields.DirectoryRef, value);
}

public string Inclusions
{
get => (string)this.Fields[(int)HarvestFilesSymbolFields.Inclusions];
set => this.Set((int)HarvestFilesSymbolFields.Inclusions, value);
}

public string Exclusions
{
get => (string)this.Fields[(int)HarvestFilesSymbolFields.Exclusions];
set => this.Set((int)HarvestFilesSymbolFields.Exclusions, value);
}

public string ComplexReferenceParentType
{
get => (string)this.Fields[(int)HarvestFilesSymbolFields.ComplexReferenceParentType];
set => this.Set((int)HarvestFilesSymbolFields.ComplexReferenceParentType, value);
}

public string ParentId
{
get => (string)this.Fields[(int)HarvestFilesSymbolFields.ParentId];
set => this.Set((int)HarvestFilesSymbolFields.ParentId, value);
}

public string SourcePath
{
get => (string)this.Fields[(int)HarvestFilesSymbolFields.SourcePath];
set => this.Set((int)HarvestFilesSymbolFields.SourcePath, value);
}
}
}
1 change: 1 addition & 0 deletions src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public enum SymbolDefinitionType
FeatureComponents,
File,
FileSFPCatalog,
HarvestFiles,
Icon,
ImageFamilies,
IniFile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace WixToolset.Extensibility.Services
using WixToolset.Extensibility.Data;

/// <summary>
/// Interface provided to help compiler extensions parse.
/// Interface provided to help compiler and optimizer extensions parse.
/// </summary>
public interface IParseHelper
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ private void AddSectionToData()
break;

// Symbols used internally and are not added to the output.
case SymbolDefinitionType.HarvestFiles:
case SymbolDefinitionType.WixBuildInfo:
case SymbolDefinitionType.WixBindUpdatedFiles:
case SymbolDefinitionType.WixComponentGroup:
Expand Down
8 changes: 2 additions & 6 deletions src/wix/WixToolset.Core/CommandLine/BuildCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,8 @@ public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
{
using (new IntermediateFieldContext("wix.link"))
{
var wixipl = inputsOutputs.Wixipls.SingleOrDefault();

if (wixipl == null)
{
wixipl = this.LinkPhase(wixobjs, inputsOutputs, creator, cancellationToken);
}
var wixipl = inputsOutputs.Wixipls.SingleOrDefault()
?? this.LinkPhase(wixobjs, inputsOutputs, creator, cancellationToken);

if (!this.Messaging.EncounteredError)
{
Expand Down
149 changes: 148 additions & 1 deletion src/wix/WixToolset.Core/Compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2655,6 +2655,9 @@ private void ParseComponentGroupElement(XElement node, ComplexReferenceParentTyp
case "File":
this.ParseNakedFileElement(child, ComplexReferenceParentType.ComponentGroup, id.Id, directoryId, source);
break;
case "Files":
this.ParseFilesElement(child, ComplexReferenceParentType.ComponentGroup, id.Id, directoryId, source);
break;
default:
this.Core.UnexpectedElement(node, child);
break;
Expand Down Expand Up @@ -3106,7 +3109,7 @@ private void ParseCopyFileElement(XElement node, string componentId, string file
this.Core.AddSymbol(new MoveFileSymbol(sourceLineNumbers, id)
{
ComponentRef = componentId,
SourceName = sourceName,
SourceName = sourceName,
DestinationName = destinationName,
DestinationShortName = destinationShortName,
SourceFolder = sourceDirectory ?? sourceProperty,
Expand Down Expand Up @@ -3881,6 +3884,9 @@ private void ParseDirectoryElement(XElement node, string parentId, int diskId, s
case "File":
this.ParseNakedFileElement(child, ComplexReferenceParentType.Unknown, null, id.Id, fileSource);
break;
case "Files":
this.ParseFilesElement(child, ComplexReferenceParentType.Unknown, null, id.Id, fileSource);
break;
case "Merge":
this.ParseMergeElement(child, id.Id, diskId);
break;
Expand Down Expand Up @@ -3996,6 +4002,9 @@ private void ParseDirectoryRefElement(XElement node)
case "File":
this.ParseNakedFileElement(child, ComplexReferenceParentType.Unknown, null, id, fileSource);
break;
case "Files":
this.ParseFilesElement(child, ComplexReferenceParentType.Unknown, null, id, fileSource);
break;
case "Merge":
this.ParseMergeElement(child, id, diskId);
break;
Expand Down Expand Up @@ -4436,6 +4445,9 @@ private void ParseFeatureElement(XElement node, ComplexReferenceParentType paren
case "File":
this.ParseNakedFileElement(child, ComplexReferenceParentType.Feature, id.Id, null, null);
break;
case "Files":
this.ParseFilesElement(child, ComplexReferenceParentType.Feature, id.Id, null, null);
break;
case "Level":
this.ParseLevelElement(child, id.Id);
break;
Expand Down Expand Up @@ -4579,6 +4591,9 @@ private void ParseFeatureRefElement(XElement node, ComplexReferenceParentType pa
case "File":
this.ParseNakedFileElement(child, ComplexReferenceParentType.Feature, id, null, null);
break;
case "Files":
this.ParseFilesElement(child, ComplexReferenceParentType.Feature, id, null, null);
break;
case "MergeRef":
this.ParseMergeRefElement(child, ComplexReferenceParentType.Feature, id);
break;
Expand Down Expand Up @@ -4667,6 +4682,9 @@ private void ParseFeatureGroupElement(XElement node, ComplexReferenceParentType
case "File":
this.ParseNakedFileElement(child, ComplexReferenceParentType.FeatureGroup, id.Id, null, null);
break;
case "Files":
this.ParseFilesElement(child, ComplexReferenceParentType.Feature, id.Id, null, null);
break;
case "MergeRef":
this.ParseMergeRefElement(child, ComplexReferenceParentType.FeatureGroup, id.Id);
break;
Expand Down Expand Up @@ -5677,6 +5695,129 @@ private void ParseNakedFileElement(XElement node, ComplexReferenceParentType par
}
}

/// <summary>
/// Parses a `Files` element.
/// </summary>
/// <param name="node">Files element to parse.</param>
/// <param name="parentType">Type of complex reference parent. Will be Unknown if there is no parent.</param>
/// <param name="parentId">Optional identifier for primary parent.</param>
/// <param name="directoryId">Ancestor's directory id.</param>
/// <param name="sourcePath">Default source path of parent directory.</param>
private void ParseFilesElement(XElement node, ComplexReferenceParentType parentType, string parentId, string directoryId, string sourcePath)
{
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
var win64 = this.Context.IsCurrentPlatform64Bit;
string subdirectory = null;
var inclusions = new List<string>();
var exclusions = new List<string>();

foreach (var attrib in node.Attributes())
{
if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
{
switch (attrib.Name.LocalName)
{
case "Directory":
directoryId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Directory, directoryId);
break;
case "Subdirectory":
subdirectory = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, allowRelative: true);
break;
case "Include":
inclusions.AddRange(this.Core.GetAttributeValue(sourceLineNumbers, attrib).Split(';'));
break;
default:
this.Core.UnexpectedAttribute(node, attrib);
break;
}
}
else
{
var context = new Dictionary<string, string>() { { "Win64", win64.ToString() } };
this.Core.ParseExtensionAttribute(node, attrib, context);
}
}

foreach (var child in node.Elements())
{
if (CompilerCore.WixNamespace == child.Name.Namespace)
{
switch (child.Name.LocalName)
{
case "Exclude":
this.ParseFilesExcludeElement(child, exclusions);
break;
default:
this.Core.UnexpectedElement(node, child);
break;
}
}
else
{
var context = new Dictionary<string, string>() { { "Win64", win64.ToString() } };
this.Core.ParseExtensionElement(node, child, context);
}
}

if (String.IsNullOrEmpty(directoryId))
{
directoryId = "INSTALLFOLDER";
this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Directory, directoryId);
}
else if (!String.IsNullOrEmpty(subdirectory))
{
directoryId = this.HandleSubdirectory(sourceLineNumbers, node, directoryId, subdirectory, "Directory", "Subdirectory");
}

if (!inclusions.Any())
{
this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Include"));
}

var inclusionsAsString = String.Join(";", inclusions);
var exclusionsAsString = String.Join(";", exclusions);

var id = this.Core.CreateIdentifier("hvf", directoryId, inclusionsAsString, exclusionsAsString);

this.Core.AddSymbol(new HarvestFilesSymbol(sourceLineNumbers, id)
{
DirectoryRef = directoryId,
Inclusions = inclusionsAsString,
Exclusions = exclusionsAsString,
ComplexReferenceParentType = parentType.ToString(),
ParentId = parentId,
SourcePath = sourcePath,
});
}

private void ParseFilesExcludeElement(XElement node, IList<string> paths)
{
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);

foreach (var attrib in node.Attributes())
{
if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
{
switch (attrib.Name.LocalName)
{
case "Files":
paths.Add(this.Core.GetAttributeValue(sourceLineNumbers, attrib));
break;
default:
this.Core.UnexpectedAttribute(node, attrib);
break;
}
}
else
{
this.Core.ParseExtensionAttribute(node, attrib);
}
}

this.Core.ParseForExtensionElements(node);
}

/// <summary>
/// Parses a file search element.
/// </summary>
Expand Down Expand Up @@ -5997,6 +6138,9 @@ private void ParseFragmentElement(XElement node)
case "File":
this.ParseNakedFileElement(child, ComplexReferenceParentType.Unknown, null, null, null);
break;
case "Files":
this.ParseFilesElement(child, ComplexReferenceParentType.Unknown, null, null, null);
break;
case "Icon":
this.ParseIconElement(child);
break;
Expand Down Expand Up @@ -7347,6 +7491,9 @@ private void ParseStandardDirectoryElement(XElement node)
case "File":
this.ParseNakedFileElement(child, ComplexReferenceParentType.Unknown, null, id, null);
break;
case "Files":
this.ParseFilesElement(child, ComplexReferenceParentType.Unknown, null, id, null);
break;
case "Merge":
this.ParseMergeElement(child, id, diskId: CompilerConstants.IntegerNotSet);
break;
Expand Down
3 changes: 3 additions & 0 deletions src/wix/WixToolset.Core/Compiler_Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ private void ParseModuleElement(XElement node)
case "File":
this.ParseNakedFileElement(child, ComplexReferenceParentType.Module, this.activeName, null, null);
break;
case "Files":
this.ParseFilesElement(child, ComplexReferenceParentType.Module, this.activeName, null, null);
break;
case "Icon":
this.ParseIconElement(child);
break;
Expand Down
3 changes: 3 additions & 0 deletions src/wix/WixToolset.Core/Compiler_Package.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,9 @@ private void ParsePackageElement(XElement node)
case "File":
this.ParseNakedFileElement(child, ComplexReferenceParentType.Product, productCode, null, null);
break;
case "Files":
this.ParseFilesElement(child, ComplexReferenceParentType.Unknown, null, null, null);
break;
case "Icon":
this.ParseIconElement(child);
break;
Expand Down
Loading
Loading