From c455d2290ef903ff36d540903e27d76d473cb67c Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Fri, 27 Mar 2020 14:30:35 +1000 Subject: Add SetVariable. --- .../Bind/SetVariableSearchFacade.cs | 33 +++++ .../Bundles/OrderSearchesCommand.cs | 9 +- src/WixToolset.Core/Compiler.cs | 6 + src/WixToolset.Core/Compiler_Bundle.cs | 142 ++++++++++++++++----- .../BundleManifestFixture.cs | 44 +++++++ .../TestData/SetVariable/Simple.wxs | 15 +++ .../WixToolsetTest.CoreIntegration.csproj | 1 + 7 files changed, 217 insertions(+), 33 deletions(-) create mode 100644 src/WixToolset.Core.Burn/Bind/SetVariableSearchFacade.cs create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/SetVariable/Simple.wxs (limited to 'src') diff --git a/src/WixToolset.Core.Burn/Bind/SetVariableSearchFacade.cs b/src/WixToolset.Core.Burn/Bind/SetVariableSearchFacade.cs new file mode 100644 index 00000000..0fe60422 --- /dev/null +++ b/src/WixToolset.Core.Burn/Bind/SetVariableSearchFacade.cs @@ -0,0 +1,33 @@ +// 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.Burn +{ + using System.Xml; + using WixToolset.Data.Tuples; + + internal class SetVariableSearchFacade : BaseSearchFacade + { + public SetVariableSearchFacade(WixSearchTuple searchTuple, WixSetVariableTuple setVariableTuple) + { + this.SearchTuple = searchTuple; + this.SetVariableTuple = setVariableTuple; + } + + private WixSetVariableTuple SetVariableTuple { get; } + + public override void WriteXml(XmlTextWriter writer) + { + writer.WriteStartElement("SetVariable"); + + base.WriteXml(writer); + + if (this.SetVariableTuple.Type != null) + { + writer.WriteAttributeString("Value", this.SetVariableTuple.Value); + writer.WriteAttributeString("Type", this.SetVariableTuple.Type); + } + + writer.WriteEndElement(); + } + } +} diff --git a/src/WixToolset.Core.Burn/Bundles/OrderSearchesCommand.cs b/src/WixToolset.Core.Burn/Bundles/OrderSearchesCommand.cs index 55b31ed3..3f720115 100644 --- a/src/WixToolset.Core.Burn/Bundles/OrderSearchesCommand.cs +++ b/src/WixToolset.Core.Burn/Bundles/OrderSearchesCommand.cs @@ -36,13 +36,16 @@ namespace WixToolset.Core.Burn.Bundles t.Definition.Type == TupleDefinitionType.WixProductSearch || t.Definition.Type == TupleDefinitionType.WixRegistrySearch) .ToDictionary(t => t.Id.Id); + var setVariablesById = this.Section.Tuples + .OfType() + .ToDictionary(t => t.Id.Id); var extensionSearchesById = this.Section.Tuples .Where(t => t.Definition.HasTag(BurnConstants.BundleExtensionSearchTupleDefinitionTag)) .ToDictionary(t => t.Id.Id); var searchTuples = this.Section.Tuples.OfType().ToList(); this.ExtensionSearchTuplesByExtensionId = new Dictionary>(); - this.OrderedSearchFacades = new List(legacySearchesById.Keys.Count + extensionSearchesById.Keys.Count); + this.OrderedSearchFacades = new List(legacySearchesById.Keys.Count + setVariablesById.Keys.Count + extensionSearchesById.Keys.Count); foreach (var searchTuple in searchTuples) { @@ -50,6 +53,10 @@ namespace WixToolset.Core.Burn.Bundles { this.OrderedSearchFacades.Add(new LegacySearchFacade(searchTuple, specificSearchTuple)); } + else if (setVariablesById.TryGetValue(searchTuple.Id.Id, out var setVariableTuple)) + { + this.OrderedSearchFacades.Add(new SetVariableSearchFacade(searchTuple, setVariableTuple)); + } else if (extensionSearchesById.TryGetValue(searchTuple.Id.Id, out var extensionSearchTuple)) { this.OrderedSearchFacades.Add(new ExtensionSearchFacade(searchTuple)); diff --git a/src/WixToolset.Core/Compiler.cs b/src/WixToolset.Core/Compiler.cs index 6f122f7b..7638c11e 100644 --- a/src/WixToolset.Core/Compiler.cs +++ b/src/WixToolset.Core/Compiler.cs @@ -6221,6 +6221,12 @@ namespace WixToolset.Core case "SetProperty": this.ParseSetPropertyElement(child); break; + case "SetVariable": + this.ParseSetVariableElement(child); + break; + case "SetVariableRef": + this.ParseSimpleRefElement(child, "WixSetVariable"); + break; case "SFPCatalog": string parentName = null; this.ParseSFPCatalogElement(child, ref parentName); diff --git a/src/WixToolset.Core/Compiler_Bundle.cs b/src/WixToolset.Core/Compiler_Bundle.cs index a840e448..5d7072d0 100644 --- a/src/WixToolset.Core/Compiler_Bundle.cs +++ b/src/WixToolset.Core/Compiler_Bundle.cs @@ -323,6 +323,12 @@ namespace WixToolset.Core case "RelatedBundle": this.ParseRelatedBundleElement(child); break; + case "SetVariable": + this.ParseSetVariableElement(child); + break; + case "SetVariableRef": + this.ParseSimpleRefElement(child, "WixSetVariable"); + break; case "Update": this.ParseUpdateElement(child); break; @@ -2704,6 +2710,78 @@ namespace WixToolset.Core } } + /// + /// Parse SetVariable element + /// + /// Element to parse + private void ParseSetVariableElement(XElement node) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + Identifier id = null; + string variable = null; + string condition = null; + string after = null; + string value = null; + string type = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "Variable": + variable = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Condition": + condition = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "After": + after = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Value": + value = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Type": + type = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib, null); + } + } + + type = this.ValidateVariableTypeWithValue(sourceLineNumbers, type, value); + + this.Core.ParseForExtensionElements(node); + + if (id == null) + { + id = this.Core.CreateIdentifier("sbv", variable, condition, after, value, type); + } + + this.Core.CreateWixSearchTuple(sourceLineNumbers, node.Name.LocalName, id, variable, condition, after); + + if (!this.Messaging.EncounteredError) + { + var tuple = new WixSetVariableTuple(sourceLineNumbers, id) + { + Value = value, + Type = type, + }; + this.Core.AddTuple(tuple); + } + } + /// /// Parse Variable element /// @@ -2764,64 +2842,64 @@ namespace WixToolset.Core this.Core.Write(ErrorMessages.ReservedNamespaceViolation(sourceLineNumbers, node.Name.LocalName, "Name", "Wix")); } - if (null == type && null != value) + type = this.ValidateVariableTypeWithValue(sourceLineNumbers, type, value); + + this.Core.ParseForExtensionElements(node); + + if (!this.Core.EncounteredError) + { + var tuple = new WixBundleVariableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, name)) + { + Value = value, + Type = type, + Hidden = hidden, + Persisted = persisted + }; + + this.Core.AddTuple(tuple); + } + } + + private string ValidateVariableTypeWithValue(SourceLineNumber sourceLineNumbers, string type, string value) + { + var newType = type; + if (newType == null && value != null) { // Infer the type from the current value... if (value.StartsWith("v", StringComparison.OrdinalIgnoreCase)) { // Version constructor does not support simple "v#" syntax so check to see if the value is // non-negative real quick. - if (Int32.TryParse(value.Substring(1), NumberStyles.None, CultureInfo.InvariantCulture.NumberFormat, out var number)) + if (Int32.TryParse(value.Substring(1), NumberStyles.None, CultureInfo.InvariantCulture.NumberFormat, out var _)) { - type = "version"; + newType = "version"; } - else + else if (Version.TryParse(value.Substring(1), out var _)) { - // Sadly, Version doesn't have a TryParse() method until .NET 4, so we have to try/catch to see if it parses. - try - { - var version = new Version(value.Substring(1)); - type = "version"; - } - catch (Exception) - { - } + newType = "version"; } } // Not a version, check for numeric. - if (null == type) + if (newType == null) { - if (Int64.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture.NumberFormat, out var number)) + if (Int64.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture.NumberFormat, out var _)) { - type = "numeric"; + newType = "numeric"; } else { - type = "string"; + newType = "string"; } } } - if (null == value && null != type) + if (value == null && newType != null) { this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, "Variable", "Value", "Type")); } - this.Core.ParseForExtensionElements(node); - - if (!this.Core.EncounteredError) - { - var tuple = new WixBundleVariableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, name)) - { - Value = value, - Type = type, - Hidden = hidden, - Persisted = persisted - }; - - this.Core.AddTuple(tuple); - } + return newType; } private class RemotePayload diff --git a/src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs b/src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs index 80f7b875..174ac21b 100644 --- a/src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs +++ b/src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs @@ -113,5 +113,49 @@ namespace WixToolsetTest.CoreIntegration "", bundleExtensionDatas[0].GetTestXml()); } } + + [Fact] + public void PopulatesManifestWithSetVariables() + { + var burnStubPath = TestData.Get(@"TestData\.Data\burn.exe"); + 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, "SetVariable", "Simple.wxs"), + Path.Combine(folder, "BundleWithPackageGroupRef", "MinimalPackageGroup.wxs"), + Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"), + "-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 setVariables = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:SetVariable"); + Assert.Equal(6, setVariables.Count); + Assert.Equal("", setVariables[0].GetTestXml()); + Assert.Equal("", setVariables[1].GetTestXml()); + Assert.Equal("", setVariables[2].GetTestXml()); + Assert.Equal("", setVariables[3].GetTestXml()); + Assert.Equal("", setVariables[4].GetTestXml()); + Assert.Equal("", setVariables[5].GetTestXml()); + } + } } } diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/SetVariable/Simple.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/SetVariable/Simple.wxs new file mode 100644 index 00000000..96c92e54 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/SetVariable/Simple.wxs @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj b/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj index 324d04ff..921c77f9 100644 --- a/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj +++ b/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj @@ -112,6 +112,7 @@ + -- cgit v1.2.3-55-g6feb