Skip to content

Commit

Permalink
FileGlob: In-code files/payload harvester with include and exclude gl…
Browse files Browse the repository at this point in the history
…ob patterns

Fix zip unit test
  • Loading branch information
nirbar committed Nov 26, 2024
1 parent eb7ecc1 commit fcc1358
Show file tree
Hide file tree
Showing 16 changed files with 407 additions and 22 deletions.
1 change: 1 addition & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<SevenZapVersion Condition=" '$(SevenZapVersion)' == '' ">24.8.41</SevenZapVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="9.0.0" />
<PackageVersion Include="WixToolset.DUtil" version="$(Wix4Version)" />
<PackageVersion Include="WixToolset.WcaUtil" version="$(Wix4Version)" />
<PackageVersion Include="WixToolset.Extensibility" Version="$(Wix4Version)" />
Expand Down
2 changes: 1 addition & 1 deletion src/PanelSwCustomActions/Unzip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ HRESULT CUnzip::ExecuteOneZip(::com::panelsw::ca::ZipDetails* pDetails)
fileName.setFileName(szEntryName);
ReleaseNullMem(szEntryName);

hr = StrAnsiAllocString(&szEntryName, fileEntry.Path(), 0, CP_UTF8);
hr = StrAnsiAllocString(&szEntryName, (LPCWSTR)fileEntry.Path(), 0, CP_UTF8);
ExitOnFailure(hr, "Failed allocating string");

file.setFileName(szEntryName);
Expand Down
15 changes: 15 additions & 0 deletions src/PanelSwWixExtension.sln
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PanelSwBackendExtension", "
EndProject
Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "CustomSearchUT", "UnitTests\CustomSearchUT\CustomSearchUT.wixproj", "{58B42CEE-5989-4C3B-BAEC-946BF4664BA8}"
EndProject
Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "FileGlobUT", "UnitTests\FileGlobUT\FileGlobUT.wixproj", "{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Expand Down Expand Up @@ -675,6 +677,18 @@ Global
{58B42CEE-5989-4C3B-BAEC-946BF4664BA8}.Release|x64.Build.0 = Release|x64
{58B42CEE-5989-4C3B-BAEC-946BF4664BA8}.Release|x86.ActiveCfg = Release|x86
{58B42CEE-5989-4C3B-BAEC-946BF4664BA8}.Release|x86.Build.0 = Release|x86
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}.Debug|ARM64.ActiveCfg = Debug|ARM64
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}.Debug|ARM64.Build.0 = Debug|ARM64
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}.Debug|x64.ActiveCfg = Debug|x64
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}.Debug|x64.Build.0 = Debug|x64
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}.Debug|x86.ActiveCfg = Debug|x86
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}.Debug|x86.Build.0 = Debug|x86
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}.Release|ARM64.ActiveCfg = Release|ARM64
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}.Release|ARM64.Build.0 = Release|ARM64
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}.Release|x64.ActiveCfg = Release|x64
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}.Release|x64.Build.0 = Release|x64
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}.Release|x86.ActiveCfg = Release|x86
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -726,6 +740,7 @@ Global
{5B7782E9-9913-4E25-81F4-D98DB5E8B4BD} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D}
{7BB9BAE3-93F4-47AD-A630-E0FE147F3026} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D}
{58B42CEE-5989-4C3B-BAEC-946BF4664BA8} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D}
{EDE32548-11C1-42AD-88E9-B96B9CF4BB40} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F5B6389D-77ED-4938-A322-8DFCA4D9FEF5}
Expand Down
7 changes: 5 additions & 2 deletions src/PanelSwWixExtension/PanelSwBurnBackendBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@ protected override IReadOnlyCollection<IntermediateSymbolDefinition> SymbolDefin

public override bool TryProcessSymbol(IntermediateSection section, IntermediateSymbol symbol)
{
if (symbol is PSW_ContainerTemplate || symbol is PSW_ContainerExtensionData || symbol is PSW_CustomSearch)
foreach (IntermediateSymbolDefinition definition in SymbolDefinitions)
{
return true;
if (definition.Name == symbol.Definition.Name)
{
return true;
}
}
return base.TryProcessSymbol(section, symbol);
}
Expand Down
247 changes: 246 additions & 1 deletion src/PanelSwWixExtension/PanelSwWixCompiler.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Microsoft.Extensions.FileSystemGlobbing;
using Microsoft.Extensions.FileSystemGlobbing.Abstractions;
using Newtonsoft.Json.Linq;
using PanelSw.Wix.Extensions.Symbols;
using System;
Expand Down Expand Up @@ -64,6 +66,10 @@ public override void ParseElement(Intermediate intermediate, IntermediateSection
ParseDuplicateFolderElement(section, element);
break;

case "FileGlob":
ParseFileGlobElement(section, element);
break;

case "Payload":
ParsePayload(section, element, null, null);
break;
Expand Down Expand Up @@ -314,6 +320,34 @@ public override void ParseElement(Intermediate intermediate, IntermediateSection
break;
}

case "ComponentGroup":
case "ComponentGroupRef":
case "Feature":
case "FeatureRef":
switch (element.Name.LocalName)
{
case "FileGlob":
ParseFileGlobElement(section, element);
break;
default:
ParseHelper.UnexpectedElement(parentElement, element);
break;
}
break;

case "PayloadGroup":
case "PayloadGroupRef":
switch (element.Name.LocalName)
{
case "FileGlob":
ParseFileGlobElement(section, element);
break;
default:
ParseHelper.UnexpectedElement(parentElement, element);
break;
}
break;

case "PatchFamily":
switch (element.Name.LocalName)
{
Expand Down Expand Up @@ -391,7 +425,7 @@ private void ParseCustomSearchElement(IntermediateSection section, XElement elem
switch (attrib.Name.LocalName)
{
case "Id":
id = ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
id = ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
break;
case "BundleExtensionRef":
bundleExtension = ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
Expand Down Expand Up @@ -1029,6 +1063,217 @@ private void ParseCustomActionDataAttribute(IntermediateSection section, XElemen
}
}

private void ParseFileGlobElement(IntermediateSection section, XElement element)
{
SourceLineNumber sourceLineNumbers = ParseHelper.GetSourceLineNumbers(element);
string directoryId = null;
string baseDir = null;
List<string> includes = new List<string>();
List<string> excludes = new List<string>();
string feature_ = null;
string componentGroup_ = null;
string payloadGroup_ = null;

foreach (XAttribute attrib in element.Attributes())
{
if (IsMyAttribute(element, attrib))
{
switch (attrib.Name.LocalName)
{
case "Directory":
directoryId = ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
break;
case "SourceDir":
baseDir = ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
break;
case "Include":
includes.Add(ParseHelper.GetAttributeValue(sourceLineNumbers, attrib));
break;
case "Exclude":
excludes.Add(ParseHelper.GetAttributeValue(sourceLineNumbers, attrib));
break;
default:
ParseHelper.UnexpectedAttribute(element, attrib);
break;
}
}
}

XAttribute parentIdAttrib = null;
XAttribute parentDirAttrib = null;
switch (element.Parent.Name.LocalName)
{
case "Feature":
case "FeatureRef":
parentDirAttrib = element.Parent.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("ConfigurableDirectory"));
parentIdAttrib = element.Parent.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("Id"));
if (parentIdAttrib != null)
{
feature_ = ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, parentIdAttrib);
}
break;
case "ComponentGroup":
case "ComponentGroupRef":
parentDirAttrib = element.Parent.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("Directory"));
parentIdAttrib = element.Parent.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("Id"));
if (parentIdAttrib != null)
{
componentGroup_ = ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, parentIdAttrib);
}
break;
case "PayloadGroup":
case "PayloadGroupRef":
parentIdAttrib = element.Parent.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("Id"));
if (parentIdAttrib != null)
{
payloadGroup_ = ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, parentIdAttrib);
}
break;
default:
ParseHelper.UnexpectedElement(element.Parent, element);
break;
}

if (!string.IsNullOrEmpty(payloadGroup_) && !string.IsNullOrEmpty(directoryId))
{
XAttribute dirAttrib = element.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("Directory"));
ParseHelper.UnexpectedAttribute(element, dirAttrib);
}
if (string.IsNullOrEmpty(directoryId) && string.IsNullOrEmpty(payloadGroup_))
{
if (parentDirAttrib != null)
{
directoryId = ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, parentDirAttrib);
}

if (string.IsNullOrEmpty(directoryId))
{
Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Directory"));
}
}
if (string.IsNullOrEmpty(baseDir))
{
Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "SourceDir"));
}

// Patterns
foreach (XElement child in element.Descendants())
{
if (child.Name.Namespace.Equals(Namespace))
{
switch (child.Name.LocalName)
{
case "Pattern":
{
foreach (XAttribute a in child.Attributes())
{
if (IsMyAttribute(child, a))
{
switch (a.Name.LocalName)
{
case "Include":
includes.Add(ParseHelper.GetAttributeValue(sourceLineNumbers, a));
break;
case "Exclude":
excludes.Add(ParseHelper.GetAttributeValue(sourceLineNumbers, a));
break;
default:
ParseHelper.UnexpectedAttribute(element, a);
break;
}
}
}
}
break;
default:
ParseHelper.UnexpectedElement(element, child);
break;
}
}
}

if (includes.Count == 0)
{
includes.Add("**");
}
if (Messaging.EncounteredError)
{
return;
}

ExecuteFileGlob(section, sourceLineNumbers, baseDir, includes, excludes, directoryId, feature_, componentGroup_, payloadGroup_);
}

private void ExecuteFileGlob(IntermediateSection section, SourceLineNumber sourceLineNumbers, string baseDir, List<string> includes, List<string> excludes, string directoryId, string feature_, string componentGroup_, string payloadGroup_)
{
Matcher matcher = new Matcher();
matcher.AddIncludePatterns(includes);
if (excludes.Count > 0)
{
matcher.AddExcludePatterns(excludes);
}

if (!Directory.Exists(baseDir))
{
Messaging.Write(ErrorMessages.ExpectedDirectory(baseDir));
return;
}

Dictionary<string, string> sectionCachedInlinedDirectoryIds = new Dictionary<string, string>();
PatternMatchingResult patternMatching = matcher.Execute(new DirectoryInfoWrapper(new DirectoryInfo(baseDir)));
foreach (FilePatternMatch filePattern in patternMatching.Files)
{
string fullPath = Path.Combine(baseDir, filePattern.Path);
fullPath = Path.GetFullPath(fullPath);

string recursiveDir = Path.GetDirectoryName(filePattern.Path);

if (!string.IsNullOrEmpty(payloadGroup_))
{
Identifier id = ParseHelper.CreateIdentifier("glb", payloadGroup_, recursiveDir, Path.GetFileName(fullPath));
string fileName = Path.Combine(recursiveDir, Path.GetFileName(fullPath));

section.AddSymbol(new WixBundlePayloadSymbol(sourceLineNumbers, id) { SourceFile = new IntermediateFieldPathValue() { Path = fullPath }, Name = fileName });
section.AddSymbol(new WixGroupSymbol(sourceLineNumbers, id) { ChildId = id.Id, ChildType = ComplexReferenceChildType.Payload, ParentId = payloadGroup_, ParentType = ComplexReferenceParentType.PayloadGroup });
}
else
{
if (!string.IsNullOrEmpty(recursiveDir))
{
directoryId = ParseHelper.CreateDirectoryReferenceFromInlineSyntax(section, sourceLineNumbers, null, directoryId, recursiveDir, sectionCachedInlinedDirectoryIds);
}
Identifier id = ParseHelper.CreateIdentifier("glb", directoryId, Path.GetFileName(fullPath));

section.AddSymbol(new ComponentSymbol(sourceLineNumbers, id)
{
ComponentId = "*",
DirectoryRef = directoryId,
KeyPath = id.Id,
KeyPathType = ComponentKeyPathType.File,
Location = ComponentLocation.LocalOnly,
Win64 = Context.Platform == Platform.ARM64 || Context.Platform == Platform.X64,
});

section.AddSymbol(new FileSymbol(sourceLineNumbers, id)
{
Source = new IntermediateFieldPathValue() { Path = fullPath },
Name = Path.GetFileName(fullPath),
ComponentRef = id.Id,
DirectoryRef = directoryId,
Attributes = FileSymbolAttributes.None | FileSymbolAttributes.Vital,
});
if (!string.IsNullOrEmpty(componentGroup_))
{
ParseHelper.CreateComplexReference(section, sourceLineNumbers, ComplexReferenceParentType.ComponentGroup, componentGroup_, null, ComplexReferenceChildType.Component, id.Id, false);
}
if (!string.IsNullOrEmpty(feature_))
{
ParseHelper.CreateComplexReference(section, sourceLineNumbers, ComplexReferenceParentType.Feature, feature_, null, ComplexReferenceChildType.Component, id.Id, true);
}
}
}
}

private void ParseDuplicateFolderElement(IntermediateSection section, XElement element)
{
SourceLineNumber sourceLineNumbers = ParseHelper.GetSourceLineNumbers(element);
Expand Down
Loading

0 comments on commit fcc1358

Please sign in to comment.