From 0baf6e26ec7ab2ff0b6ad36e9d44f3d68819b5d6 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Fri, 27 Mar 2020 13:54:56 +1000 Subject: Add ability for extensions to create custom bundle searches. This required creating BundleExtensionData.xml. --- src/test/Example.Extension/Data/example.wxs | 3 + .../Example.Extension/ExampleCompilerExtension.cs | 104 +++++++++++++++++++++ src/test/Example.Extension/ExampleExtensionData.cs | 6 +- src/test/Example.Extension/ExampleSearchTuple.cs | 31 ++++++ .../Example.Extension/ExampleTupleDefinitions.cs | 17 +++- .../BundleManifestFixture.cs | 56 +++++++++++ .../BundleExtension/BundleExtensionSearches.wxs | 8 ++ .../BundleExtension/BundleWithSearches.wxs | 11 +++ .../WixToolsetTest.CoreIntegration.csproj | 2 + 9 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 src/test/Example.Extension/ExampleSearchTuple.cs create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/BundleExtension/BundleExtensionSearches.wxs create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/BundleExtension/BundleWithSearches.wxs (limited to 'src/test') diff --git a/src/test/Example.Extension/Data/example.wxs b/src/test/Example.Extension/Data/example.wxs index cb100adf..cd17d478 100644 --- a/src/test/Example.Extension/Data/example.wxs +++ b/src/test/Example.Extension/Data/example.wxs @@ -8,4 +8,7 @@ + + + diff --git a/src/test/Example.Extension/ExampleCompilerExtension.cs b/src/test/Example.Extension/ExampleCompilerExtension.cs index 5efb428f..543b4165 100644 --- a/src/test/Example.Extension/ExampleCompilerExtension.cs +++ b/src/test/Example.Extension/ExampleCompilerExtension.cs @@ -11,6 +11,7 @@ namespace Example.Extension internal class ExampleCompilerExtension : BaseCompilerExtension { public override XNamespace Namespace => "http://www.example.com/scheams/v1/wxs"; + public string BundleExtensionId => "ExampleBundleExtension"; public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary context) { @@ -18,6 +19,20 @@ namespace Example.Extension switch (parentElement.Name.LocalName) { + case "Bundle": + case "Fragment": + switch (element.Name.LocalName) + { + case "ExampleSearch": + this.ParseExampleSearchElement(intermediate, section, element); + processed = true; + break; + case "ExampleSearchRef": + this.ParseExampleSearchRefElement(intermediate, section, element); + processed = true; + break; + } + break; case "Component": switch (element.Name.LocalName) { @@ -77,5 +92,94 @@ namespace Example.Extension tuple.Set(1, value); } } + + private void ParseExampleSearchElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string searchFor = null; + string variable = null; + string condition = null; + string after = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "Variable": + variable = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Condition": + condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "After": + after = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "SearchFor": + searchFor = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseAttribute(intermediate, section, element, attrib, null); + } + } + + if (null == id) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id")); + } + + if (!this.Messaging.EncounteredError) + { + this.ParseHelper.CreateWixSearchTuple(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, this.BundleExtensionId); + } + + if (!this.Messaging.EncounteredError) + { + + var tuple = new ExampleSearchTuple(sourceLineNumbers, id); + section.Tuples.Add(tuple); + tuple.SearchFor = searchFor; + } + } + + private void ParseExampleSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + var refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "ExampleSearch", refId); + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + } } } diff --git a/src/test/Example.Extension/ExampleExtensionData.cs b/src/test/Example.Extension/ExampleExtensionData.cs index de0b8899..b38eb2a2 100644 --- a/src/test/Example.Extension/ExampleExtensionData.cs +++ b/src/test/Example.Extension/ExampleExtensionData.cs @@ -1,4 +1,4 @@ -// 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. +// 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 Example.Extension { @@ -22,6 +22,10 @@ namespace Example.Extension tupleDefinition = ExampleTupleDefinitions.Example; break; + case "ExampleSearch": + tupleDefinition = ExampleTupleDefinitions.ExampleSearch; + break; + default: tupleDefinition = null; break; diff --git a/src/test/Example.Extension/ExampleSearchTuple.cs b/src/test/Example.Extension/ExampleSearchTuple.cs new file mode 100644 index 00000000..df34f0af --- /dev/null +++ b/src/test/Example.Extension/ExampleSearchTuple.cs @@ -0,0 +1,31 @@ +// 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 Example.Extension +{ + using WixToolset.Data; + + public enum ExampleSearchTupleFields + { + Example, + SearchFor, + } + + public class ExampleSearchTuple : IntermediateTuple + { + public ExampleSearchTuple() : base(ExampleTupleDefinitions.ExampleSearch, null, null) + { + } + + public ExampleSearchTuple(SourceLineNumber sourceLineNumber, Identifier id = null) : base(ExampleTupleDefinitions.ExampleSearch, sourceLineNumber, id) + { + } + + public IntermediateField this[ExampleTupleFields index] => this.Fields[(int)index]; + + public string SearchFor + { + get => this.Fields[(int)ExampleSearchTupleFields.SearchFor]?.AsString(); + set => this.Set((int)ExampleSearchTupleFields.SearchFor, value); + } + } +} diff --git a/src/test/Example.Extension/ExampleTupleDefinitions.cs b/src/test/Example.Extension/ExampleTupleDefinitions.cs index 4775b827..b2c8c484 100644 --- a/src/test/Example.Extension/ExampleTupleDefinitions.cs +++ b/src/test/Example.Extension/ExampleTupleDefinitions.cs @@ -1,8 +1,9 @@ -// 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. +// 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 Example.Extension { using WixToolset.Data; + using WixToolset.Data.Burn; public static class ExampleTupleDefinitions { @@ -16,5 +17,19 @@ namespace Example.Extension new IntermediateFieldDefinition(nameof(ExampleTupleFields.Value), IntermediateFieldType.String), }, typeof(ExampleTuple)); + + public static readonly IntermediateTupleDefinition ExampleSearch = new IntermediateTupleDefinition( + nameof(ExampleSearch), + new[] + { + new IntermediateFieldDefinition(nameof(ExampleTupleFields.Example), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(ExampleSearchTupleFields.SearchFor), IntermediateFieldType.String), + }, + typeof(ExampleSearchTuple)); + + static ExampleTupleDefinitions() + { + ExampleSearch.AddTag(BurnConstants.BundleExtensionSearchTupleDefinitionTag); + } } } diff --git a/src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs b/src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs index da4482ff..80f7b875 100644 --- a/src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs +++ b/src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs @@ -2,8 +2,10 @@ namespace WixToolsetTest.CoreIntegration { + using System; using System.Collections.Generic; using System.IO; + using Example.Extension; using WixBuildTools.TestSupport; using WixToolset.Core.TestPackage; using Xunit; @@ -57,5 +59,59 @@ namespace WixToolsetTest.CoreIntegration Assert.Equal("", bundleExtensionPayloads[0].GetTestXml(ignored)); } } + + [Fact] + public void PopulatesManifestWithBundleExtensionSearches() + { + var burnStubPath = TestData.Get(@"TestData\.Data\burn.exe"); + var extensionPath = Path.GetFullPath(new Uri(typeof(ExampleExtensionFactory).Assembly.CodeBase).LocalPath); + var folder = TestData.Get(@"TestData"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var bundlePath = Path.Combine(baseFolder, @"bin\test.exe"); + var baFolderPath = Path.Combine(baseFolder, "ba"); + var extractFolderPath = Path.Combine(baseFolder, "extract"); + + var result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "BundleExtension", "BundleExtensionSearches.wxs"), + Path.Combine(folder, "BundleExtension", "BundleWithSearches.wxs"), + Path.Combine(folder, "BundleWithPackageGroupRef", "MinimalPackageGroup.wxs"), + Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"), + "-ext", extensionPath, + "-bindpath", Path.Combine(folder, "SimpleBundle", "data"), + "-intermediateFolder", intermediateFolder, + "-burnStub", burnStubPath, + "-o", bundlePath + }); + + result.AssertSuccess(); + + Assert.True(File.Exists(bundlePath)); + + var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); + extractResult.AssertSuccess(); + + var bundleExtensions = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:BundleExtension"); + Assert.Equal(1, bundleExtensions.Count); + Assert.Equal("", bundleExtensions[0].GetTestXml()); + + var extensionSearches = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:ExtensionSearch"); + Assert.Equal(2, extensionSearches.Count); + Assert.Equal("", extensionSearches[0].GetTestXml()); + Assert.Equal("", extensionSearches[1].GetTestXml()); + + var bundleExtensionDatas = extractResult.SelectBundleExtensionDataNodes("/be:BundleExtensionData/be:BundleExtension[@Id='ExampleBundleExtension']"); + Assert.Equal(1, bundleExtensionDatas.Count); + Assert.Equal("" + + "" + + "" + + "", bundleExtensionDatas[0].GetTestXml()); + } + } } } diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/BundleExtension/BundleExtensionSearches.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/BundleExtension/BundleExtensionSearches.wxs new file mode 100644 index 00000000..fd8d3698 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/BundleExtension/BundleExtensionSearches.wxs @@ -0,0 +1,8 @@ + + + + + + + diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/BundleExtension/BundleWithSearches.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/BundleExtension/BundleWithSearches.wxs new file mode 100644 index 00000000..c5a93eb3 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/BundleExtension/BundleWithSearches.wxs @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj b/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj index 85538b79..324d04ff 100644 --- a/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj +++ b/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj @@ -22,6 +22,8 @@ + + -- cgit v1.2.3-55-g6feb