From dbde9e7104b907bbbaea17e21247d8cafc8b3a4c Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Sat, 14 Oct 2017 16:12:07 -0700 Subject: Massive refactoring to introduce the concept of IBackend --- src/WixToolset.Core/Bind/BindTransformCommand.cs | 473 ----------------------- 1 file changed, 473 deletions(-) delete mode 100644 src/WixToolset.Core/Bind/BindTransformCommand.cs (limited to 'src/WixToolset.Core/Bind/BindTransformCommand.cs') diff --git a/src/WixToolset.Core/Bind/BindTransformCommand.cs b/src/WixToolset.Core/Bind/BindTransformCommand.cs deleted file mode 100644 index e909f191..00000000 --- a/src/WixToolset.Core/Bind/BindTransformCommand.cs +++ /dev/null @@ -1,473 +0,0 @@ -// 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.Bind -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.IO; - using WixToolset.Data; - using WixToolset.Extensibility; - using WixToolset.Msi; - using WixToolset.Core.Native; - - internal class BindTransformCommand : ICommand - { - public IEnumerable Extensions { private get; set; } - - public IEnumerable FileManagers { private get; set; } - - public TableDefinitionCollection TableDefinitions { private get; set; } - - public string TempFilesLocation { private get; set; } - - public Output Transform { private get; set; } - - public string OutputPath { private get; set; } - - public void Execute() - { - int transformFlags = 0; - - Output targetOutput = new Output(null); - Output updatedOutput = new Output(null); - - // TODO: handle added columns - - // to generate a localized transform, both the target and updated - // databases need to have the same code page. the only reason to - // set different code pages is to support localized primary key - // columns, but that would only support deleting rows. if this - // becomes necessary, define a PreviousCodepage property on the - // Output class and persist this throughout transform generation. - targetOutput.Codepage = this.Transform.Codepage; - updatedOutput.Codepage = this.Transform.Codepage; - - // remove certain Property rows which will be populated from summary information values - string targetUpgradeCode = null; - string updatedUpgradeCode = null; - - Table propertyTable = this.Transform.Tables["Property"]; - if (null != propertyTable) - { - for (int i = propertyTable.Rows.Count - 1; i >= 0; i--) - { - Row row = propertyTable.Rows[i]; - - if ("ProductCode" == (string)row[0] || "ProductLanguage" == (string)row[0] || "ProductVersion" == (string)row[0] || "UpgradeCode" == (string)row[0]) - { - propertyTable.Rows.RemoveAt(i); - - if ("UpgradeCode" == (string)row[0]) - { - updatedUpgradeCode = (string)row[1]; - } - } - } - } - - Table targetSummaryInfo = targetOutput.EnsureTable(this.TableDefinitions["_SummaryInformation"]); - Table updatedSummaryInfo = updatedOutput.EnsureTable(this.TableDefinitions["_SummaryInformation"]); - Table targetPropertyTable = targetOutput.EnsureTable(this.TableDefinitions["Property"]); - Table updatedPropertyTable = updatedOutput.EnsureTable(this.TableDefinitions["Property"]); - - // process special summary information values - foreach (Row row in this.Transform.Tables["_SummaryInformation"].Rows) - { - if ((int)SummaryInformation.Transform.CodePage == (int)row[0]) - { - // convert from a web name if provided - string codePage = (string)row.Fields[1].Data; - if (null == codePage) - { - codePage = "0"; - } - else - { - codePage = Common.GetValidCodePage(codePage).ToString(CultureInfo.InvariantCulture); - } - - string previousCodePage = (string)row.Fields[1].PreviousData; - if (null == previousCodePage) - { - previousCodePage = "0"; - } - else - { - previousCodePage = Common.GetValidCodePage(previousCodePage).ToString(CultureInfo.InvariantCulture); - } - - Row targetCodePageRow = targetSummaryInfo.CreateRow(null); - targetCodePageRow[0] = 1; // PID_CODEPAGE - targetCodePageRow[1] = previousCodePage; - - Row updatedCodePageRow = updatedSummaryInfo.CreateRow(null); - updatedCodePageRow[0] = 1; // PID_CODEPAGE - updatedCodePageRow[1] = codePage; - } - else if ((int)SummaryInformation.Transform.TargetPlatformAndLanguage == (int)row[0] || - (int)SummaryInformation.Transform.UpdatedPlatformAndLanguage == (int)row[0]) - { - // the target language - string[] propertyData = ((string)row[1]).Split(';'); - string lang = 2 == propertyData.Length ? propertyData[1] : "0"; - - Table tempSummaryInfo = (int)SummaryInformation.Transform.TargetPlatformAndLanguage == (int)row[0] ? targetSummaryInfo : updatedSummaryInfo; - Table tempPropertyTable = (int)SummaryInformation.Transform.TargetPlatformAndLanguage == (int)row[0] ? targetPropertyTable : updatedPropertyTable; - - Row productLanguageRow = tempPropertyTable.CreateRow(null); - productLanguageRow[0] = "ProductLanguage"; - productLanguageRow[1] = lang; - - // set the platform;language on the MSI to be generated - Row templateRow = tempSummaryInfo.CreateRow(null); - templateRow[0] = 7; // PID_TEMPLATE - templateRow[1] = (string)row[1]; - } - else if ((int)SummaryInformation.Transform.ProductCodes == (int)row[0]) - { - string[] propertyData = ((string)row[1]).Split(';'); - - Row targetProductCodeRow = targetPropertyTable.CreateRow(null); - targetProductCodeRow[0] = "ProductCode"; - targetProductCodeRow[1] = propertyData[0].Substring(0, 38); - - Row targetProductVersionRow = targetPropertyTable.CreateRow(null); - targetProductVersionRow[0] = "ProductVersion"; - targetProductVersionRow[1] = propertyData[0].Substring(38); - - Row updatedProductCodeRow = updatedPropertyTable.CreateRow(null); - updatedProductCodeRow[0] = "ProductCode"; - updatedProductCodeRow[1] = propertyData[1].Substring(0, 38); - - Row updatedProductVersionRow = updatedPropertyTable.CreateRow(null); - updatedProductVersionRow[0] = "ProductVersion"; - updatedProductVersionRow[1] = propertyData[1].Substring(38); - - // UpgradeCode is optional and may not exists in the target - // or upgraded databases, so do not include a null-valued - // UpgradeCode property. - - targetUpgradeCode = propertyData[2]; - if (!String.IsNullOrEmpty(targetUpgradeCode)) - { - Row targetUpgradeCodeRow = targetPropertyTable.CreateRow(null); - targetUpgradeCodeRow[0] = "UpgradeCode"; - targetUpgradeCodeRow[1] = targetUpgradeCode; - - // If the target UpgradeCode is specified, an updated - // UpgradeCode is required. - if (String.IsNullOrEmpty(updatedUpgradeCode)) - { - updatedUpgradeCode = targetUpgradeCode; - } - } - - if (!String.IsNullOrEmpty(updatedUpgradeCode)) - { - Row updatedUpgradeCodeRow = updatedPropertyTable.CreateRow(null); - updatedUpgradeCodeRow[0] = "UpgradeCode"; - updatedUpgradeCodeRow[1] = updatedUpgradeCode; - } - } - else if ((int)SummaryInformation.Transform.ValidationFlags == (int)row[0]) - { - transformFlags = Convert.ToInt32(row[1], CultureInfo.InvariantCulture); - } - else if ((int)SummaryInformation.Transform.Reserved11 == (int)row[0]) - { - // PID_LASTPRINTED should be null for transforms - row.Operation = RowOperation.None; - } - else - { - // add everything else as is - Row targetRow = targetSummaryInfo.CreateRow(null); - targetRow[0] = row[0]; - targetRow[1] = row[1]; - - Row updatedRow = updatedSummaryInfo.CreateRow(null); - updatedRow[0] = row[0]; - updatedRow[1] = row[1]; - } - } - - // Validate that both databases have an UpgradeCode if the - // authoring transform will validate the UpgradeCode; otherwise, - // MsiCreateTransformSummaryinfo() will fail with 1620. - if (((int)TransformFlags.ValidateUpgradeCode & transformFlags) != 0 && - (String.IsNullOrEmpty(targetUpgradeCode) || String.IsNullOrEmpty(updatedUpgradeCode))) - { - Messaging.Instance.OnMessage(WixErrors.BothUpgradeCodesRequired()); - } - - string emptyFile = null; - - foreach (Table table in this.Transform.Tables) - { - // Ignore unreal tables when building transforms except the _Stream table. - // These tables are ignored when generating the database so there is no reason - // to process them here. - if (table.Definition.Unreal && "_Streams" != table.Name) - { - continue; - } - - // process table operations - switch (table.Operation) - { - case TableOperation.Add: - updatedOutput.EnsureTable(table.Definition); - break; - case TableOperation.Drop: - targetOutput.EnsureTable(table.Definition); - continue; - default: - targetOutput.EnsureTable(table.Definition); - updatedOutput.EnsureTable(table.Definition); - break; - } - - // process row operations - foreach (Row row in table.Rows) - { - switch (row.Operation) - { - case RowOperation.Add: - Table updatedTable = updatedOutput.EnsureTable(table.Definition); - updatedTable.Rows.Add(row); - continue; - case RowOperation.Delete: - Table targetTable = targetOutput.EnsureTable(table.Definition); - targetTable.Rows.Add(row); - - // fill-in non-primary key values - foreach (Field field in row.Fields) - { - if (!field.Column.PrimaryKey) - { - if (ColumnType.Number == field.Column.Type && !field.Column.IsLocalizable) - { - field.Data = field.Column.MinValue; - } - else if (ColumnType.Object == field.Column.Type) - { - if (null == emptyFile) - { - emptyFile = Path.Combine(this.TempFilesLocation, "empty"); - } - - field.Data = emptyFile; - } - else - { - field.Data = "0"; - } - } - } - continue; - } - - // Assure that the file table's sequence is populated - if ("File" == table.Name) - { - foreach (Row fileRow in table.Rows) - { - if (null == fileRow[7]) - { - if (RowOperation.Add == fileRow.Operation) - { - Messaging.Instance.OnMessage(WixErrors.InvalidAddedFileRowWithoutSequence(fileRow.SourceLineNumbers, (string)fileRow[0])); - break; - } - - // Set to 1 to prevent invalid IDT file from being generated - fileRow[7] = 1; - } - } - } - - // process modified and unmodified rows - bool modifiedRow = false; - Row targetRow = new Row(null, table.Definition); - Row updatedRow = row; - for (int i = 0; i < row.Fields.Length; i++) - { - Field updatedField = row.Fields[i]; - - if (updatedField.Modified) - { - // set a different value in the target row to ensure this value will be modified during transform generation - if (ColumnType.Number == updatedField.Column.Type && !updatedField.Column.IsLocalizable) - { - if (null == updatedField.Data || 1 != (int)updatedField.Data) - { - targetRow[i] = 1; - } - else - { - targetRow[i] = 2; - } - } - else if (ColumnType.Object == updatedField.Column.Type) - { - if (null == emptyFile) - { - emptyFile = Path.Combine(this.TempFilesLocation, "empty"); - } - - targetRow[i] = emptyFile; - } - else - { - if ("0" != (string)updatedField.Data) - { - targetRow[i] = "0"; - } - else - { - targetRow[i] = "1"; - } - } - - modifiedRow = true; - } - else if (ColumnType.Object == updatedField.Column.Type) - { - ObjectField objectField = (ObjectField)updatedField; - - // create an empty file for comparing against - if (null == objectField.PreviousData) - { - if (null == emptyFile) - { - emptyFile = Path.Combine(this.TempFilesLocation, "empty"); - } - - targetRow[i] = emptyFile; - modifiedRow = true; - } - else if (!this.CompareFiles(objectField.PreviousData, (string)objectField.Data)) - { - targetRow[i] = objectField.PreviousData; - modifiedRow = true; - } - } - else // unmodified - { - if (null != updatedField.Data) - { - targetRow[i] = updatedField.Data; - } - } - } - - // modified rows and certain special rows go in the target and updated msi databases - if (modifiedRow || - ("Property" == table.Name && - ("ProductCode" == (string)row[0] || - "ProductLanguage" == (string)row[0] || - "ProductVersion" == (string)row[0] || - "UpgradeCode" == (string)row[0]))) - { - Table targetTable = targetOutput.EnsureTable(table.Definition); - targetTable.Rows.Add(targetRow); - - Table updatedTable = updatedOutput.EnsureTable(table.Definition); - updatedTable.Rows.Add(updatedRow); - } - } - } - - foreach (BinderExtension extension in this.Extensions) - { - extension.Finish(this.Transform); - } - - // Any errors encountered up to this point can cause errors during generation. - if (Messaging.Instance.EncounteredError) - { - return; - } - - string transformFileName = Path.GetFileNameWithoutExtension(this.OutputPath); - string targetDatabaseFile = Path.Combine(this.TempFilesLocation, String.Concat(transformFileName, "_target.msi")); - string updatedDatabaseFile = Path.Combine(this.TempFilesLocation, String.Concat(transformFileName, "_updated.msi")); - - try - { - if (!String.IsNullOrEmpty(emptyFile)) - { - using (FileStream fileStream = File.Create(emptyFile)) - { - } - } - - this.GenerateDatabase(targetOutput, targetDatabaseFile, false); - this.GenerateDatabase(updatedOutput, updatedDatabaseFile, true); - - // make sure the directory exists - Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath)); - - // create the transform file - using (Database targetDatabase = new Database(targetDatabaseFile, OpenDatabase.ReadOnly)) - { - using (Database updatedDatabase = new Database(updatedDatabaseFile, OpenDatabase.ReadOnly)) - { - if (updatedDatabase.GenerateTransform(targetDatabase, this.OutputPath)) - { - updatedDatabase.CreateTransformSummaryInfo(targetDatabase, this.OutputPath, (TransformErrorConditions)(transformFlags & 0xFFFF), (TransformValidations)((transformFlags >> 16) & 0xFFFF)); - } - else - { - Messaging.Instance.OnMessage(WixErrors.NoDifferencesInTransform(this.Transform.SourceLineNumbers)); - } - } - } - } - finally - { - if (!String.IsNullOrEmpty(emptyFile)) - { - File.Delete(emptyFile); - } - } - } - - private bool CompareFiles(string targetFile, string updatedFile) - { - bool? compared = null; - foreach (IBinderFileManager fileManager in this.FileManagers) - { - compared = fileManager.CompareFiles(targetFile, updatedFile); - if (compared.HasValue) - { - break; - } - } - - if (!compared.HasValue) - { - throw new InvalidOperationException(); // TODO: something needs to be said here that none of the binder file managers returned a result. - } - - return compared.Value; - } - - private void GenerateDatabase(Output output, string outputPath, bool keepAddedColumns) - { - GenerateDatabaseCommand command = new GenerateDatabaseCommand(); - command.Codepage = output.Codepage; - command.Extensions = this.Extensions; - command.FileManagers = this.FileManagers; - command.KeepAddedColumns = keepAddedColumns; - command.Output = output; - command.OutputPath = outputPath; - command.TableDefinitions = this.TableDefinitions; - command.TempFilesLocation = this.TempFilesLocation; - command.SuppressAddingValidationRows = true; - command.UseSubDirectory = true; - command.Execute(); - } - } -} -- cgit v1.2.3-55-g6feb