diff options
| author | Rob Mensching <rob@firegiant.com> | 2017-12-21 13:42:52 -0800 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2017-12-21 13:42:52 -0800 |
| commit | dc9f4c329e6f55ce7595970463e0caf148096f4b (patch) | |
| tree | 86155ac36c76acda0a4b1673c77f54a9780c6885 /src | |
| parent | 155a6e96346e0cb3d9ab6f5372fa29b46ebaee89 (diff) | |
| download | wix-dc9f4c329e6f55ce7595970463e0caf148096f4b.tar.gz wix-dc9f4c329e6f55ce7595970463e0caf148096f4b.tar.bz2 wix-dc9f4c329e6f55ce7595970463e0caf148096f4b.zip | |
Support wixout and extract Resolve and Layout from Binder
Diffstat (limited to 'src')
44 files changed, 1005 insertions, 799 deletions
diff --git a/src/WixToolset.BuildTasks/WixToolTask.cs b/src/WixToolset.BuildTasks/WixToolTask.cs index 69c837c3..7ccf0327 100644 --- a/src/WixToolset.BuildTasks/WixToolTask.cs +++ b/src/WixToolset.BuildTasks/WixToolTask.cs | |||
| @@ -193,8 +193,7 @@ namespace WixToolset.BuildTasks | |||
| 193 | string responseFile = null; | 193 | string responseFile = null; |
| 194 | try | 194 | try |
| 195 | { | 195 | { |
| 196 | string responseFileSwitch; | 196 | responseFile = this.GetTemporaryResponseFile(responseFileCommands, out var responseFileSwitch); |
| 197 | responseFile = this.GetTemporaryResponseFile(responseFileCommands, out responseFileSwitch); | ||
| 198 | if (!String.IsNullOrEmpty(responseFileSwitch)) | 197 | if (!String.IsNullOrEmpty(responseFileSwitch)) |
| 199 | { | 198 | { |
| 200 | commandLineCommands = commandLineCommands + " " + responseFileSwitch; | 199 | commandLineCommands = commandLineCommands + " " + responseFileSwitch; |
diff --git a/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs b/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs index 5e04e722..bc3ba8df 100644 --- a/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs +++ b/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs | |||
| @@ -74,7 +74,9 @@ namespace WixToolset.Core.Burn | |||
| 74 | this.DelayedFields = context.DelayedFields; | 74 | this.DelayedFields = context.DelayedFields; |
| 75 | this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles; | 75 | this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles; |
| 76 | 76 | ||
| 77 | this.BackendExtensions = context.ExtensionManager.Create<IBurnBackendExtension>(); | 77 | var extensionManager = context.ServiceProvider.GetService<IExtensionManager>(); |
| 78 | |||
| 79 | this.BackendExtensions = extensionManager.Create<IBurnBackendExtension>(); | ||
| 78 | } | 80 | } |
| 79 | 81 | ||
| 80 | public CompressionLevel DefaultCompressionLevel { private get; set; } | 82 | public CompressionLevel DefaultCompressionLevel { private get; set; } |
| @@ -85,8 +87,6 @@ namespace WixToolset.Core.Burn | |||
| 85 | 87 | ||
| 86 | private IEnumerable<IBurnBackendExtension> BackendExtensions { get; } | 88 | private IEnumerable<IBurnBackendExtension> BackendExtensions { get; } |
| 87 | 89 | ||
| 88 | public IEnumerable<IBinderExtension> Extensions { private get; set; } | ||
| 89 | |||
| 90 | public Intermediate Output { private get; set; } | 90 | public Intermediate Output { private get; set; } |
| 91 | 91 | ||
| 92 | public string OutputPath { private get; set; } | 92 | public string OutputPath { private get; set; } |
diff --git a/src/WixToolset.Core.Burn/BundleBackend.cs b/src/WixToolset.Core.Burn/BundleBackend.cs index f66a3fbe..83d33c8a 100644 --- a/src/WixToolset.Core.Burn/BundleBackend.cs +++ b/src/WixToolset.Core.Burn/BundleBackend.cs | |||
| @@ -9,7 +9,6 @@ namespace WixToolset.Core.Burn | |||
| 9 | using WixToolset.Data; | 9 | using WixToolset.Data; |
| 10 | using WixToolset.Data.Bind; | 10 | using WixToolset.Data.Bind; |
| 11 | using WixToolset.Extensibility; | 11 | using WixToolset.Extensibility; |
| 12 | using WixToolset.Extensibility.Services; | ||
| 13 | 12 | ||
| 14 | internal class BundleBackend : IBackend | 13 | internal class BundleBackend : IBackend |
| 15 | { | 14 | { |
| @@ -25,7 +24,7 @@ namespace WixToolset.Core.Burn | |||
| 25 | //command.WixVariableResolver = context.WixVariableResolver; | 24 | //command.WixVariableResolver = context.WixVariableResolver; |
| 26 | command.Execute(); | 25 | command.Execute(); |
| 27 | 26 | ||
| 28 | return new BindResult(command.FileTransfers, command.ContentFilePaths); | 27 | return new BindResult { FileTransfers = command.FileTransfers, ContentFilePaths = command.ContentFilePaths }; |
| 29 | } | 28 | } |
| 30 | 29 | ||
| 31 | public bool Inscribe(IInscribeContext context) | 30 | public bool Inscribe(IInscribeContext context) |
diff --git a/src/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs b/src/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs index 2ee58514..636cb1a0 100644 --- a/src/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs +++ b/src/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs | |||
| @@ -14,7 +14,6 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 14 | using WixToolset.Extensibility; | 14 | using WixToolset.Extensibility; |
| 15 | using WixToolset.Core.Native; | 15 | using WixToolset.Core.Native; |
| 16 | using Dtf = WixToolset.Dtf.WindowsInstaller; | 16 | using Dtf = WixToolset.Dtf.WindowsInstaller; |
| 17 | using WixToolset.Bind; | ||
| 18 | using WixToolset.Data.Bind; | 17 | using WixToolset.Data.Bind; |
| 19 | 18 | ||
| 20 | /// <summary> | 19 | /// <summary> |
diff --git a/src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs b/src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs index 7900fcd1..1d91ddf2 100644 --- a/src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs +++ b/src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs | |||
| @@ -9,7 +9,6 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 9 | using System.Security.Cryptography; | 9 | using System.Security.Cryptography; |
| 10 | using System.Security.Cryptography.X509Certificates; | 10 | using System.Security.Cryptography.X509Certificates; |
| 11 | using System.Text; | 11 | using System.Text; |
| 12 | using WixToolset.Bind; | ||
| 13 | using WixToolset.Data; | 12 | using WixToolset.Data; |
| 14 | using WixToolset.Data.Bind; | 13 | using WixToolset.Data.Bind; |
| 15 | using WixToolset.Data.Rows; | 14 | using WixToolset.Data.Rows; |
diff --git a/src/WixToolset.Core.Burn/BurnBackendFactory.cs b/src/WixToolset.Core.Burn/BurnBackendFactory.cs index 8e2b3ce2..5da3a0cb 100644 --- a/src/WixToolset.Core.Burn/BurnBackendFactory.cs +++ b/src/WixToolset.Core.Burn/BurnBackendFactory.cs | |||
| @@ -9,7 +9,7 @@ namespace WixToolset.Core.Burn | |||
| 9 | 9 | ||
| 10 | internal class BurnBackendFactory : IBackendFactory | 10 | internal class BurnBackendFactory : IBackendFactory |
| 11 | { | 11 | { |
| 12 | public bool TryCreateBackend(string outputType, string outputFile, IBindContext context, out IBackend backend) | 12 | public bool TryCreateBackend(string outputType, string outputFile, WixToolset.Extensibility.IBindContext context, out IBackend backend) |
| 13 | { | 13 | { |
| 14 | if (String.IsNullOrEmpty(outputType)) | 14 | if (String.IsNullOrEmpty(outputType)) |
| 15 | { | 15 | { |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs index 410e462a..2f161305 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs | |||
| @@ -22,31 +22,27 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 22 | // As outlined in RFC 4122, this is our namespace for generating name-based (version 3) UUIDs. | 22 | // As outlined in RFC 4122, this is our namespace for generating name-based (version 3) UUIDs. |
| 23 | internal static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}"); | 23 | internal static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}"); |
| 24 | 24 | ||
| 25 | public BindDatabaseCommand(IBindContext context, IEnumerable<IWindowsInstallerBackendExtension> backendExtension, Validator validator) | 25 | public BindDatabaseCommand(WixToolset.Extensibility.IBindContext context, IEnumerable<IWindowsInstallerBackendExtension> backendExtension, Validator validator) |
| 26 | { | 26 | { |
| 27 | this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); | 27 | this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); |
| 28 | 28 | ||
| 29 | this.BindPaths = context.BindPaths; | ||
| 30 | this.CabbingThreadCount = context.CabbingThreadCount; | 29 | this.CabbingThreadCount = context.CabbingThreadCount; |
| 31 | this.CabCachePath = context.CabCachePath; | 30 | this.CabCachePath = context.CabCachePath; |
| 32 | this.Codepage = context.Codepage; | 31 | this.Codepage = context.Codepage; |
| 33 | this.DefaultCompressionLevel = context.DefaultCompressionLevel; | 32 | this.DefaultCompressionLevel = context.DefaultCompressionLevel; |
| 34 | this.DelayedFields = context.DelayedFields; | 33 | this.DelayedFields = context.DelayedFields; |
| 35 | this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles; | 34 | this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles; |
| 36 | this.Extensions = context.Extensions; | 35 | this.FileSystemExtensions = context.FileSystemExtensions; |
| 37 | this.Intermediate = context.IntermediateRepresentation; | 36 | this.Intermediate = context.IntermediateRepresentation; |
| 38 | this.Messaging = context.Messaging; | 37 | this.Messaging = context.Messaging; |
| 39 | this.OutputPath = context.OutputPath; | 38 | this.OutputPath = context.OutputPath; |
| 40 | this.PdbFile = context.OutputPdbPath; | 39 | this.PdbFile = context.OutputPdbPath; |
| 41 | this.IntermediateFolder = context.IntermediateFolder; | 40 | this.IntermediateFolder = context.IntermediateFolder; |
| 42 | this.Validator = validator; | 41 | this.Validator = validator; |
| 43 | this.WixVariableResolver = context.WixVariableResolver; | 42 | |
| 44 | |||
| 45 | this.BackendExtensions = backendExtension; | 43 | this.BackendExtensions = backendExtension; |
| 46 | } | 44 | } |
| 47 | 45 | ||
| 48 | private IEnumerable<BindPath> BindPaths { get; } | ||
| 49 | |||
| 50 | private int Codepage { get; } | 46 | private int Codepage { get; } |
| 51 | 47 | ||
| 52 | private int CabbingThreadCount { get; } | 48 | private int CabbingThreadCount { get; } |
| @@ -59,12 +55,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 59 | 55 | ||
| 60 | public IEnumerable<IExpectedExtractFile> ExpectedEmbeddedFiles { get; } | 56 | public IEnumerable<IExpectedExtractFile> ExpectedEmbeddedFiles { get; } |
| 61 | 57 | ||
| 58 | public IEnumerable<IFileSystemExtension> FileSystemExtensions { get; } | ||
| 59 | |||
| 62 | public bool DeltaBinaryPatch { get; set; } | 60 | public bool DeltaBinaryPatch { get; set; } |
| 63 | 61 | ||
| 64 | private IEnumerable<IWindowsInstallerBackendExtension> BackendExtensions { get; } | 62 | private IEnumerable<IWindowsInstallerBackendExtension> BackendExtensions { get; } |
| 65 | 63 | ||
| 66 | private IEnumerable<IBinderExtension> Extensions { get; } | ||
| 67 | |||
| 68 | private string PdbFile { get; } | 64 | private string PdbFile { get; } |
| 69 | 65 | ||
| 70 | private Intermediate Intermediate { get; } | 66 | private Intermediate Intermediate { get; } |
| @@ -83,7 +79,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 83 | 79 | ||
| 84 | private Validator Validator { get; } | 80 | private Validator Validator { get; } |
| 85 | 81 | ||
| 86 | private IBindVariableResolver WixVariableResolver { get; } | ||
| 87 | 82 | ||
| 88 | public IEnumerable<FileTransfer> FileTransfers { get; private set; } | 83 | public IEnumerable<FileTransfer> FileTransfers { get; private set; } |
| 89 | 84 | ||
| @@ -100,8 +95,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 100 | // If there are any fields to resolve later, create the cache to populate during bind. | 95 | // If there are any fields to resolve later, create the cache to populate during bind. |
| 101 | var variableCache = this.DelayedFields.Any() ? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) : null; | 96 | var variableCache = this.DelayedFields.Any() ? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) : null; |
| 102 | 97 | ||
| 103 | this.LocalizeUI(section); | ||
| 104 | |||
| 105 | // Process the summary information table before the other tables. | 98 | // Process the summary information table before the other tables. |
| 106 | bool compressed; | 99 | bool compressed; |
| 107 | bool longNames; | 100 | bool longNames; |
| @@ -534,85 +527,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 534 | intermediate.Save(Path.ChangeExtension(this.OutputPath, "wir")); | 527 | intermediate.Save(Path.ChangeExtension(this.OutputPath, "wir")); |
| 535 | } | 528 | } |
| 536 | 529 | ||
| 537 | /// <summary> | ||
| 538 | /// Localize dialogs and controls. | ||
| 539 | /// </summary> | ||
| 540 | /// <param name="tables">The tables to localize.</param> | ||
| 541 | private void LocalizeUI(IntermediateSection section) | ||
| 542 | { | ||
| 543 | foreach (var row in section.Tuples.OfType<DialogTuple>()) | ||
| 544 | { | ||
| 545 | string dialog = row.Dialog; | ||
| 546 | |||
| 547 | if (this.WixVariableResolver.TryGetLocalizedControl(dialog, null, out LocalizedControl localizedControl)) | ||
| 548 | { | ||
| 549 | if (CompilerConstants.IntegerNotSet != localizedControl.X) | ||
| 550 | { | ||
| 551 | row.HCentering = localizedControl.X; | ||
| 552 | } | ||
| 553 | |||
| 554 | if (CompilerConstants.IntegerNotSet != localizedControl.Y) | ||
| 555 | { | ||
| 556 | row.VCentering = localizedControl.Y; | ||
| 557 | } | ||
| 558 | |||
| 559 | if (CompilerConstants.IntegerNotSet != localizedControl.Width) | ||
| 560 | { | ||
| 561 | row.Width = localizedControl.Width; | ||
| 562 | } | ||
| 563 | |||
| 564 | if (CompilerConstants.IntegerNotSet != localizedControl.Height) | ||
| 565 | { | ||
| 566 | row.Height = localizedControl.Height; | ||
| 567 | } | ||
| 568 | |||
| 569 | row.Attributes = row.Attributes | localizedControl.Attributes; | ||
| 570 | |||
| 571 | if (!String.IsNullOrEmpty(localizedControl.Text)) | ||
| 572 | { | ||
| 573 | row.Title = localizedControl.Text; | ||
| 574 | } | ||
| 575 | } | ||
| 576 | } | ||
| 577 | |||
| 578 | |||
| 579 | foreach (var row in section.Tuples.OfType<ControlTuple>()) | ||
| 580 | { | ||
| 581 | string dialog = row.Dialog_; | ||
| 582 | string control = row.Control; | ||
| 583 | |||
| 584 | if (this.WixVariableResolver.TryGetLocalizedControl(dialog, control, out LocalizedControl localizedControl)) | ||
| 585 | { | ||
| 586 | if (CompilerConstants.IntegerNotSet != localizedControl.X) | ||
| 587 | { | ||
| 588 | row.X = localizedControl.X; | ||
| 589 | } | ||
| 590 | |||
| 591 | if (CompilerConstants.IntegerNotSet != localizedControl.Y) | ||
| 592 | { | ||
| 593 | row.Y = localizedControl.Y; | ||
| 594 | } | ||
| 595 | |||
| 596 | if (CompilerConstants.IntegerNotSet != localizedControl.Width) | ||
| 597 | { | ||
| 598 | row.Width = localizedControl.Width; | ||
| 599 | } | ||
| 600 | |||
| 601 | if (CompilerConstants.IntegerNotSet != localizedControl.Height) | ||
| 602 | { | ||
| 603 | row.Height = localizedControl.Height; | ||
| 604 | } | ||
| 605 | |||
| 606 | row.Attributes = row.Attributes | localizedControl.Attributes; | ||
| 607 | |||
| 608 | if (!String.IsNullOrEmpty(localizedControl.Text)) | ||
| 609 | { | ||
| 610 | row.Text = localizedControl.Text; | ||
| 611 | } | ||
| 612 | } | ||
| 613 | } | ||
| 614 | } | ||
| 615 | |||
| 616 | #if TODO_FINISH_PATCH | 530 | #if TODO_FINISH_PATCH |
| 617 | /// <summary> | 531 | /// <summary> |
| 618 | /// Copy file data between transform substorages and the patch output object | 532 | /// Copy file data between transform substorages and the patch output object |
| @@ -984,7 +898,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 984 | private void GenerateDatabase(Output output, string databaseFile, bool keepAddedColumns, bool useSubdirectory) | 898 | private void GenerateDatabase(Output output, string databaseFile, bool keepAddedColumns, bool useSubdirectory) |
| 985 | { | 899 | { |
| 986 | var command = new GenerateDatabaseCommand(); | 900 | var command = new GenerateDatabaseCommand(); |
| 987 | command.Extensions = this.Extensions; | 901 | command.Extensions = this.FileSystemExtensions; |
| 988 | command.Output = output; | 902 | command.Output = output; |
| 989 | command.OutputPath = databaseFile; | 903 | command.OutputPath = databaseFile; |
| 990 | command.KeepAddedColumns = keepAddedColumns; | 904 | command.KeepAddedColumns = keepAddedColumns; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs index 800ebac0..8cb0e0de 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs | |||
| @@ -15,7 +15,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 15 | 15 | ||
| 16 | internal class BindTransformCommand | 16 | internal class BindTransformCommand |
| 17 | { | 17 | { |
| 18 | public IEnumerable<IBinderExtension> Extensions { private get; set; } | 18 | public IEnumerable<IFileSystemExtension> Extensions { private get; set; } |
| 19 | 19 | ||
| 20 | public TableDefinitionCollection TableDefinitions { private get; set; } | 20 | public TableDefinitionCollection TableDefinitions { private get; set; } |
| 21 | 21 | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs index 056f92a7..76747728 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs | |||
| @@ -6,7 +6,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| 7 | using System.IO; | 7 | using System.IO; |
| 8 | using System.Linq; | 8 | using System.Linq; |
| 9 | using WixToolset.Bind; | ||
| 10 | using WixToolset.Core.Native; | 9 | using WixToolset.Core.Native; |
| 11 | using WixToolset.Data; | 10 | using WixToolset.Data; |
| 12 | using WixToolset.Data.Tuples; | 11 | using WixToolset.Data.Tuples; |
| @@ -135,7 +134,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 135 | if (fileRow.File == componentRow.KeyPath) | 134 | if (fileRow.File == componentRow.KeyPath) |
| 136 | { | 135 | { |
| 137 | // calculate the key file's canonical target path | 136 | // calculate the key file's canonical target path |
| 138 | string directoryPath = Binder.GetDirectoryPath(targetPathsByDirectoryId, componentIdGenSeeds, componentRow.Directory_, true); | 137 | string directoryPath = PathResolver.GetDirectoryPath(targetPathsByDirectoryId, componentIdGenSeeds, componentRow.Directory_, true); |
| 139 | string fileName = Common.GetName(fileRow.LongFileName, false, true).ToLowerInvariant(); | 138 | string fileName = Common.GetName(fileRow.LongFileName, false, true).ToLowerInvariant(); |
| 140 | path = Path.Combine(directoryPath, fileName); | 139 | path = Path.Combine(directoryPath, fileName); |
| 141 | 140 | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs index 13408312..6ff03941 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs | |||
| @@ -18,7 +18,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 18 | { | 18 | { |
| 19 | public bool CopyOutFileRows { private get; set; } | 19 | public bool CopyOutFileRows { private get; set; } |
| 20 | 20 | ||
| 21 | public IEnumerable<IBinderExtension> Extensions { private get; set; } | 21 | public IEnumerable<IFileSystemExtension> Extensions { private get; set; } |
| 22 | 22 | ||
| 23 | public IMessaging Messaging { private get; set; } | 23 | public IMessaging Messaging { private get; set; } |
| 24 | 24 | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs index ee7cc61b..cc920ac2 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs | |||
| @@ -19,7 +19,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 19 | { | 19 | { |
| 20 | public int Codepage { private get; set; } | 20 | public int Codepage { private get; set; } |
| 21 | 21 | ||
| 22 | public IEnumerable<IBinderExtension> Extensions { private get; set; } | 22 | public IEnumerable<IFileSystemExtension> Extensions { private get; set; } |
| 23 | 23 | ||
| 24 | /// <summary> | 24 | /// <summary> |
| 25 | /// Whether to keep columns added in a transform. | 25 | /// Whether to keep columns added in a transform. |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/PathResolver.cs b/src/WixToolset.Core.WindowsInstaller/Bind/PathResolver.cs new file mode 100644 index 00000000..492c9137 --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/PathResolver.cs | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.WindowsInstaller.Bind | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using System.IO; | ||
| 8 | using WixToolset.Data; | ||
| 9 | |||
| 10 | internal static class PathResolver | ||
| 11 | { | ||
| 12 | /// <summary> | ||
| 13 | /// Get the source path of a directory. | ||
| 14 | /// </summary> | ||
| 15 | /// <param name="directories">All cached directories.</param> | ||
| 16 | /// <param name="componentIdGenSeeds">Hash table of Component GUID generation seeds indexed by directory id.</param> | ||
| 17 | /// <param name="directory">Directory identifier.</param> | ||
| 18 | /// <param name="canonicalize">Canonicalize the path for standard directories.</param> | ||
| 19 | /// <returns>Source path of a directory.</returns> | ||
| 20 | public static string GetDirectoryPath(Dictionary<string, ResolvedDirectory> directories, Dictionary<string, string> componentIdGenSeeds, string directory, bool canonicalize) | ||
| 21 | { | ||
| 22 | if (!directories.TryGetValue(directory, out var resolvedDirectory)) | ||
| 23 | { | ||
| 24 | throw new WixException(ErrorMessages.ExpectedDirectory(directory)); | ||
| 25 | } | ||
| 26 | |||
| 27 | if (null == resolvedDirectory.Path) | ||
| 28 | { | ||
| 29 | if (null != componentIdGenSeeds && componentIdGenSeeds.ContainsKey(directory)) | ||
| 30 | { | ||
| 31 | resolvedDirectory.Path = (string)componentIdGenSeeds[directory]; | ||
| 32 | } | ||
| 33 | else if (canonicalize && WindowsInstallerStandard.IsStandardDirectory(directory)) | ||
| 34 | { | ||
| 35 | // when canonicalization is on, standard directories are treated equally | ||
| 36 | resolvedDirectory.Path = directory; | ||
| 37 | } | ||
| 38 | else | ||
| 39 | { | ||
| 40 | string name = resolvedDirectory.Name; | ||
| 41 | |||
| 42 | if (canonicalize) | ||
| 43 | { | ||
| 44 | name = name?.ToLowerInvariant(); | ||
| 45 | } | ||
| 46 | |||
| 47 | if (String.IsNullOrEmpty(resolvedDirectory.DirectoryParent)) | ||
| 48 | { | ||
| 49 | resolvedDirectory.Path = name; | ||
| 50 | } | ||
| 51 | else | ||
| 52 | { | ||
| 53 | string parentPath = GetDirectoryPath(directories, componentIdGenSeeds, resolvedDirectory.DirectoryParent, canonicalize); | ||
| 54 | |||
| 55 | if (null != resolvedDirectory.Name) | ||
| 56 | { | ||
| 57 | resolvedDirectory.Path = Path.Combine(parentPath, name); | ||
| 58 | } | ||
| 59 | else | ||
| 60 | { | ||
| 61 | resolvedDirectory.Path = parentPath; | ||
| 62 | } | ||
| 63 | } | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | return resolvedDirectory.Path; | ||
| 68 | } | ||
| 69 | |||
| 70 | /// <summary> | ||
| 71 | /// Gets the source path of a file. | ||
| 72 | /// </summary> | ||
| 73 | /// <param name="directories">All cached directories in <see cref="ResolvedDirectory"/>.</param> | ||
| 74 | /// <param name="directoryId">Parent directory identifier.</param> | ||
| 75 | /// <param name="fileName">File name (in long|source format).</param> | ||
| 76 | /// <param name="compressed">Specifies the package is compressed.</param> | ||
| 77 | /// <param name="useLongName">Specifies the package uses long file names.</param> | ||
| 78 | /// <returns>Source path of file relative to package directory.</returns> | ||
| 79 | public static string GetFileSourcePath(Dictionary<string, ResolvedDirectory> directories, string directoryId, string fileName, bool compressed, bool useLongName) | ||
| 80 | { | ||
| 81 | string fileSourcePath = Common.GetName(fileName, true, useLongName); | ||
| 82 | |||
| 83 | if (compressed) | ||
| 84 | { | ||
| 85 | // Use just the file name of the file since all uncompressed files must appear | ||
| 86 | // in the root of the image in a compressed package. | ||
| 87 | } | ||
| 88 | else | ||
| 89 | { | ||
| 90 | // Get the relative path of where we want the file to be layed out as specified | ||
| 91 | // in the Directory table. | ||
| 92 | string directoryPath = PathResolver.GetDirectoryPath(directories, null, directoryId, false); | ||
| 93 | fileSourcePath = Path.Combine(directoryPath, fileSourcePath); | ||
| 94 | } | ||
| 95 | |||
| 96 | // Strip off "SourceDir" if it's still on there. | ||
| 97 | if (fileSourcePath.StartsWith("SourceDir\\", StringComparison.Ordinal)) | ||
| 98 | { | ||
| 99 | fileSourcePath = fileSourcePath.Substring(10); | ||
| 100 | } | ||
| 101 | |||
| 102 | return fileSourcePath; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | } | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs index e1a26a67..39771508 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs | |||
| @@ -5,14 +5,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| 7 | using System.IO; | 7 | using System.IO; |
| 8 | using WixToolset.Data; | 8 | using System.Linq; |
| 9 | using WixToolset.Msi; | ||
| 10 | using WixToolset.Core.Native; | ||
| 11 | using WixToolset.Bind; | ||
| 12 | using WixToolset.Core.Bind; | 9 | using WixToolset.Core.Bind; |
| 10 | using WixToolset.Core.Native; | ||
| 11 | using WixToolset.Data; | ||
| 13 | using WixToolset.Data.Bind; | 12 | using WixToolset.Data.Bind; |
| 14 | using WixToolset.Data.Tuples; | 13 | using WixToolset.Data.Tuples; |
| 15 | using System.Linq; | 14 | using WixToolset.Msi; |
| 16 | 15 | ||
| 17 | /// <summary> | 16 | /// <summary> |
| 18 | /// Defines the file transfers necessary to layout the uncompressed files. | 17 | /// Defines the file transfers necessary to layout the uncompressed files. |
| @@ -100,7 +99,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 100 | throw new WixException(ErrorMessages.FileIdentifierNotFound(facade.File.SourceLineNumbers, facade.File.File)); | 99 | throw new WixException(ErrorMessages.FileIdentifierNotFound(facade.File.SourceLineNumbers, facade.File.File)); |
| 101 | } | 100 | } |
| 102 | 101 | ||
| 103 | relativeFileLayoutPath = Binder.GetFileSourcePath(directories, fileRecord[1], fileRecord[2], this.Compressed, this.LongNamesInImage); | 102 | relativeFileLayoutPath = PathResolver.GetFileSourcePath(directories, fileRecord[1], fileRecord[2], this.Compressed, this.LongNamesInImage); |
| 104 | } | 103 | } |
| 105 | 104 | ||
| 106 | // finally put together the base media layout path and the relative file layout path | 105 | // finally put together the base media layout path and the relative file layout path |
diff --git a/src/WixToolset.Core/Bind/ResolvedDirectory.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ResolvedDirectory.cs index 9d07fc93..e06321cf 100644 --- a/src/WixToolset.Core/Bind/ResolvedDirectory.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ResolvedDirectory.cs | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | // 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. | 1 | // 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. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Bind | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | /// <summary> | 5 | /// <summary> |
| 6 | /// Structure used for resolved directory information. | 6 | /// Structure used for resolved directory information. |
| 7 | /// </summary> | 7 | /// </summary> |
| 8 | public struct ResolvedDirectory | 8 | internal struct ResolvedDirectory |
| 9 | { | 9 | { |
| 10 | /// <summary> | 10 | /// <summary> |
| 11 | /// Constructor for ResolvedDirectory. | 11 | /// Constructor for ResolvedDirectory. |
diff --git a/src/WixToolset.Core.WindowsInstaller/MsiBackend.cs b/src/WixToolset.Core.WindowsInstaller/MsiBackend.cs index 4753677a..00f09db3 100644 --- a/src/WixToolset.Core.WindowsInstaller/MsiBackend.cs +++ b/src/WixToolset.Core.WindowsInstaller/MsiBackend.cs | |||
| @@ -12,9 +12,11 @@ namespace WixToolset.Core.WindowsInstaller | |||
| 12 | 12 | ||
| 13 | internal class MsiBackend : IBackend | 13 | internal class MsiBackend : IBackend |
| 14 | { | 14 | { |
| 15 | public BindResult Bind(IBindContext context) | 15 | public BindResult Bind(WixToolset.Extensibility.IBindContext context) |
| 16 | { | 16 | { |
| 17 | var backendExtensions = context.ExtensionManager.Create<IWindowsInstallerBackendExtension>(); | 17 | var extensionManager = context.ServiceProvider.GetService<IExtensionManager>(); |
| 18 | |||
| 19 | var backendExtensions = extensionManager.Create<IWindowsInstallerBackendExtension>(); | ||
| 18 | 20 | ||
| 19 | foreach (var extension in backendExtensions) | 21 | foreach (var extension in backendExtensions) |
| 20 | { | 22 | { |
| @@ -26,7 +28,7 @@ namespace WixToolset.Core.WindowsInstaller | |||
| 26 | var command = new BindDatabaseCommand(context, backendExtensions, validator); | 28 | var command = new BindDatabaseCommand(context, backendExtensions, validator); |
| 27 | command.Execute(); | 29 | command.Execute(); |
| 28 | 30 | ||
| 29 | var result = new BindResult(command.FileTransfers, command.ContentFilePaths); | 31 | var result = new BindResult { FileTransfers = command.FileTransfers, ContentFilePaths = command.ContentFilePaths }; |
| 30 | 32 | ||
| 31 | foreach (var extension in backendExtensions) | 33 | foreach (var extension in backendExtensions) |
| 32 | { | 34 | { |
diff --git a/src/WixToolset.Core.WindowsInstaller/MsmBackend.cs b/src/WixToolset.Core.WindowsInstaller/MsmBackend.cs index 2323f8dd..9c70860e 100644 --- a/src/WixToolset.Core.WindowsInstaller/MsmBackend.cs +++ b/src/WixToolset.Core.WindowsInstaller/MsmBackend.cs | |||
| @@ -11,9 +11,11 @@ namespace WixToolset.Core.WindowsInstaller | |||
| 11 | 11 | ||
| 12 | internal class MsmBackend : IBackend | 12 | internal class MsmBackend : IBackend |
| 13 | { | 13 | { |
| 14 | public BindResult Bind(IBindContext context) | 14 | public BindResult Bind(WixToolset.Extensibility.IBindContext context) |
| 15 | { | 15 | { |
| 16 | var backendExtensions = context.ExtensionManager.Create<IWindowsInstallerBackendExtension>(); | 16 | var extensionManager = context.ServiceProvider.GetService<IExtensionManager>(); |
| 17 | |||
| 18 | var backendExtensions = extensionManager.Create<IWindowsInstallerBackendExtension>(); | ||
| 17 | 19 | ||
| 18 | foreach (var extension in backendExtensions) | 20 | foreach (var extension in backendExtensions) |
| 19 | { | 21 | { |
| @@ -25,7 +27,7 @@ namespace WixToolset.Core.WindowsInstaller | |||
| 25 | var command = new BindDatabaseCommand(context, backendExtensions, validator); | 27 | var command = new BindDatabaseCommand(context, backendExtensions, validator); |
| 26 | command.Execute(); | 28 | command.Execute(); |
| 27 | 29 | ||
| 28 | var result = new BindResult(command.FileTransfers, command.ContentFilePaths); | 30 | var result = new BindResult { FileTransfers = command.FileTransfers, ContentFilePaths = command.ContentFilePaths }; |
| 29 | 31 | ||
| 30 | foreach (var extension in backendExtensions) | 32 | foreach (var extension in backendExtensions) |
| 31 | { | 33 | { |
diff --git a/src/WixToolset.Core.WindowsInstaller/MspBackend.cs b/src/WixToolset.Core.WindowsInstaller/MspBackend.cs index 8fb63665..5dbed241 100644 --- a/src/WixToolset.Core.WindowsInstaller/MspBackend.cs +++ b/src/WixToolset.Core.WindowsInstaller/MspBackend.cs | |||
| @@ -16,7 +16,7 @@ namespace WixToolset.Core.WindowsInstaller | |||
| 16 | 16 | ||
| 17 | internal class MspBackend : IBackend | 17 | internal class MspBackend : IBackend |
| 18 | { | 18 | { |
| 19 | public BindResult Bind(IBindContext context) | 19 | public BindResult Bind(WixToolset.Extensibility.IBindContext context) |
| 20 | { | 20 | { |
| 21 | throw new NotImplementedException(); | 21 | throw new NotImplementedException(); |
| 22 | } | 22 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/MstBackend.cs b/src/WixToolset.Core.WindowsInstaller/MstBackend.cs index 17617dbc..4eb0901c 100644 --- a/src/WixToolset.Core.WindowsInstaller/MstBackend.cs +++ b/src/WixToolset.Core.WindowsInstaller/MstBackend.cs | |||
| @@ -7,7 +7,6 @@ namespace WixToolset.Core.WindowsInstaller | |||
| 7 | using WixToolset.Data; | 7 | using WixToolset.Data; |
| 8 | using WixToolset.Data.Bind; | 8 | using WixToolset.Data.Bind; |
| 9 | using WixToolset.Extensibility; | 9 | using WixToolset.Extensibility; |
| 10 | using WixToolset.Extensibility.Services; | ||
| 11 | 10 | ||
| 12 | internal class MstBackend : IBackend | 11 | internal class MstBackend : IBackend |
| 13 | { | 12 | { |
diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs index 2b018013..00e5a755 100644 --- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs | |||
| @@ -244,7 +244,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind | |||
| 244 | private void GenerateDatabase(Output output, string databaseFile) | 244 | private void GenerateDatabase(Output output, string databaseFile) |
| 245 | { | 245 | { |
| 246 | var command = new GenerateDatabaseCommand(); | 246 | var command = new GenerateDatabaseCommand(); |
| 247 | command.Extensions = Array.Empty<IBinderExtension>(); | 247 | command.Extensions = Array.Empty<IFileSystemExtension>(); |
| 248 | command.Output = output; | 248 | command.Output = output; |
| 249 | command.OutputPath = databaseFile; | 249 | command.OutputPath = databaseFile; |
| 250 | command.KeepAddedColumns = true; | 250 | command.KeepAddedColumns = true; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Validator.cs b/src/WixToolset.Core.WindowsInstaller/Validator.cs index d553cc71..5f41e88d 100644 --- a/src/WixToolset.Core.WindowsInstaller/Validator.cs +++ b/src/WixToolset.Core.WindowsInstaller/Validator.cs | |||
| @@ -324,7 +324,7 @@ namespace WixToolset.Core.WindowsInstaller | |||
| 324 | } | 324 | } |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | public static Validator CreateFromContext(IBindContext context, string cubeFilename) | 327 | public static Validator CreateFromContext(WixToolset.Extensibility.IBindContext context, string cubeFilename) |
| 328 | { | 328 | { |
| 329 | Validator validator = null; | 329 | Validator validator = null; |
| 330 | 330 | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/WindowsInstallerBackendFactory.cs b/src/WixToolset.Core.WindowsInstaller/WindowsInstallerBackendFactory.cs index a7f58ed4..b66a4617 100644 --- a/src/WixToolset.Core.WindowsInstaller/WindowsInstallerBackendFactory.cs +++ b/src/WixToolset.Core.WindowsInstaller/WindowsInstallerBackendFactory.cs | |||
| @@ -5,7 +5,6 @@ namespace WixToolset.Core.WindowsInstaller | |||
| 5 | using System; | 5 | using System; |
| 6 | using System.IO; | 6 | using System.IO; |
| 7 | using WixToolset.Extensibility; | 7 | using WixToolset.Extensibility; |
| 8 | using WixToolset.Extensibility.Services; | ||
| 9 | 8 | ||
| 10 | internal class WindowsInstallerBackendFactory : IBackendFactory | 9 | internal class WindowsInstallerBackendFactory : IBackendFactory |
| 11 | { | 10 | { |
diff --git a/src/WixToolset.Core/Bind/FileResolver.cs b/src/WixToolset.Core/Bind/FileResolver.cs index 2142d261..a20d3f34 100644 --- a/src/WixToolset.Core/Bind/FileResolver.cs +++ b/src/WixToolset.Core/Bind/FileResolver.cs | |||
| @@ -6,7 +6,6 @@ namespace WixToolset.Core.Bind | |||
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| 7 | using System.IO; | 7 | using System.IO; |
| 8 | using System.Linq; | 8 | using System.Linq; |
| 9 | using System.Runtime.InteropServices; | ||
| 10 | using WixToolset.Data; | 9 | using WixToolset.Data; |
| 11 | using WixToolset.Data.Bind; | 10 | using WixToolset.Data.Bind; |
| 12 | using WixToolset.Extensibility; | 11 | using WixToolset.Extensibility; |
| @@ -22,9 +21,9 @@ namespace WixToolset.Core.Bind | |||
| 22 | this.RebaseUpdated = this.BindPaths[BindStage.Updated].Any(); | 21 | this.RebaseUpdated = this.BindPaths[BindStage.Updated].Any(); |
| 23 | } | 22 | } |
| 24 | 23 | ||
| 25 | public FileResolver(IEnumerable<BindPath> bindPaths, IEnumerable<IBinderExtension> extensions) : this(bindPaths) | 24 | public FileResolver(IEnumerable<BindPath> bindPaths, IEnumerable<IResolverExtension> extensions) : this(bindPaths) |
| 26 | { | 25 | { |
| 27 | this.BinderExtensions = extensions ?? Array.Empty<IBinderExtension>(); | 26 | this.ResolverExtensions = extensions ?? Array.Empty<IResolverExtension>(); |
| 28 | } | 27 | } |
| 29 | 28 | ||
| 30 | public FileResolver(IEnumerable<BindPath> bindPaths, IEnumerable<ILibrarianExtension> extensions) : this(bindPaths) | 29 | public FileResolver(IEnumerable<BindPath> bindPaths, IEnumerable<ILibrarianExtension> extensions) : this(bindPaths) |
| @@ -38,79 +37,15 @@ namespace WixToolset.Core.Bind | |||
| 38 | 37 | ||
| 39 | public bool RebaseUpdated { get; } | 38 | public bool RebaseUpdated { get; } |
| 40 | 39 | ||
| 41 | private IEnumerable<IBinderExtension> BinderExtensions { get; } | 40 | private IEnumerable<IResolverExtension> ResolverExtensions { get; } |
| 42 | 41 | ||
| 43 | private IEnumerable<ILibrarianExtension> LibrarianExtensions { get; } | 42 | private IEnumerable<ILibrarianExtension> LibrarianExtensions { get; } |
| 44 | 43 | ||
| 45 | /// <summary> | 44 | public string Resolve(SourceLineNumber sourceLineNumbers, IntermediateTupleDefinition tupleDefinition, string source) |
| 46 | /// Copies a file. | ||
| 47 | /// </summary> | ||
| 48 | /// <param name="source">The file to copy.</param> | ||
| 49 | /// <param name="destination">The destination file.</param> | ||
| 50 | /// <param name="overwrite">true if the destination file can be overwritten; otherwise, false.</param> | ||
| 51 | public bool CopyFile(string source, string destination, bool overwrite) | ||
| 52 | { | ||
| 53 | foreach (var extension in this.BinderExtensions) | ||
| 54 | { | ||
| 55 | if (extension.CopyFile(source, destination, overwrite)) | ||
| 56 | { | ||
| 57 | return true; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | if (overwrite && File.Exists(destination)) | ||
| 62 | { | ||
| 63 | File.Delete(destination); | ||
| 64 | } | ||
| 65 | |||
| 66 | if (!CreateHardLink(destination, source, IntPtr.Zero)) | ||
| 67 | { | ||
| 68 | #if DEBUG | ||
| 69 | int er = Marshal.GetLastWin32Error(); | ||
| 70 | #endif | ||
| 71 | |||
| 72 | File.Copy(source, destination, overwrite); | ||
| 73 | } | ||
| 74 | |||
| 75 | return true; | ||
| 76 | } | ||
| 77 | |||
| 78 | /// <summary> | ||
| 79 | /// Moves a file. | ||
| 80 | /// </summary> | ||
| 81 | /// <param name="source">The file to move.</param> | ||
| 82 | /// <param name="destination">The destination file.</param> | ||
| 83 | public bool MoveFile(string source, string destination, bool overwrite) | ||
| 84 | { | ||
| 85 | foreach (var extension in this.BinderExtensions) | ||
| 86 | { | ||
| 87 | if (extension.MoveFile(source, destination, overwrite)) | ||
| 88 | { | ||
| 89 | return true; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | if (overwrite && File.Exists(destination)) | ||
| 94 | { | ||
| 95 | File.Delete(destination); | ||
| 96 | } | ||
| 97 | |||
| 98 | var directory = Path.GetDirectoryName(destination); | ||
| 99 | if (!String.IsNullOrEmpty(directory)) | ||
| 100 | { | ||
| 101 | Directory.CreateDirectory(directory); | ||
| 102 | } | ||
| 103 | |||
| 104 | File.Move(source, destination); | ||
| 105 | |||
| 106 | return true; | ||
| 107 | } | ||
| 108 | |||
| 109 | public string Resolve(SourceLineNumber sourceLineNumbers, string table, string path) | ||
| 110 | { | 45 | { |
| 111 | foreach (var extension in this.LibrarianExtensions) | 46 | foreach (var extension in this.LibrarianExtensions) |
| 112 | { | 47 | { |
| 113 | var resolved = extension.Resolve(sourceLineNumbers, table, path); | 48 | var resolved = extension.Resolve(sourceLineNumbers, tupleDefinition, source); |
| 114 | 49 | ||
| 115 | if (null != resolved) | 50 | if (null != resolved) |
| 116 | { | 51 | { |
| @@ -118,7 +53,7 @@ namespace WixToolset.Core.Bind | |||
| 118 | } | 53 | } |
| 119 | } | 54 | } |
| 120 | 55 | ||
| 121 | return this.ResolveUsingBindPaths(path, table, sourceLineNumbers, BindStage.Normal); | 56 | return this.ResolveUsingBindPaths(source, tupleDefinition, sourceLineNumbers, BindStage.Normal); |
| 122 | } | 57 | } |
| 123 | 58 | ||
| 124 | /// <summary> | 59 | /// <summary> |
| @@ -129,11 +64,11 @@ namespace WixToolset.Core.Bind | |||
| 129 | /// <param name="sourceLineNumbers">Optional source line of source file being resolved.</param> | 64 | /// <param name="sourceLineNumbers">Optional source line of source file being resolved.</param> |
| 130 | /// <param name="bindStage">The binding stage used to determine what collection of bind paths will be used</param> | 65 | /// <param name="bindStage">The binding stage used to determine what collection of bind paths will be used</param> |
| 131 | /// <returns>Should return a valid path for the stream to be imported.</returns> | 66 | /// <returns>Should return a valid path for the stream to be imported.</returns> |
| 132 | public string ResolveFile(string source, string type, SourceLineNumber sourceLineNumbers, BindStage bindStage) | 67 | public string ResolveFile(string source, IntermediateTupleDefinition tupleDefinition, SourceLineNumber sourceLineNumbers, BindStage bindStage) |
| 133 | { | 68 | { |
| 134 | foreach (var extension in this.BinderExtensions) | 69 | foreach (var extension in this.ResolverExtensions) |
| 135 | { | 70 | { |
| 136 | var resolved = extension.ResolveFile(source, type, sourceLineNumbers, bindStage); | 71 | var resolved = extension.ResolveFile(source, tupleDefinition, sourceLineNumbers, bindStage); |
| 137 | 72 | ||
| 138 | if (null != resolved) | 73 | if (null != resolved) |
| 139 | { | 74 | { |
| @@ -141,10 +76,10 @@ namespace WixToolset.Core.Bind | |||
| 141 | } | 76 | } |
| 142 | } | 77 | } |
| 143 | 78 | ||
| 144 | return this.ResolveUsingBindPaths(source, type, sourceLineNumbers, bindStage); | 79 | return this.ResolveUsingBindPaths(source, tupleDefinition, sourceLineNumbers, bindStage); |
| 145 | } | 80 | } |
| 146 | 81 | ||
| 147 | private string ResolveUsingBindPaths(string source, string type, SourceLineNumber sourceLineNumbers, BindStage bindStage) | 82 | private string ResolveUsingBindPaths(string source, IntermediateTupleDefinition tupleDefinition, SourceLineNumber sourceLineNumbers, BindStage bindStage) |
| 148 | { | 83 | { |
| 149 | string resolved = null; | 84 | string resolved = null; |
| 150 | 85 | ||
| @@ -206,7 +141,7 @@ namespace WixToolset.Core.Bind | |||
| 206 | 141 | ||
| 207 | if (null == resolved) | 142 | if (null == resolved) |
| 208 | { | 143 | { |
| 209 | throw new WixFileNotFoundException(sourceLineNumbers, source, type); | 144 | throw new WixFileNotFoundException(sourceLineNumbers, source, tupleDefinition.Name); |
| 210 | } | 145 | } |
| 211 | 146 | ||
| 212 | // Didn't find the file. | 147 | // Didn't find the file. |
| @@ -224,8 +159,5 @@ namespace WixToolset.Core.Bind | |||
| 224 | throw new WixException(ErrorMessages.IllegalCharactersInPath(path)); | 159 | throw new WixException(ErrorMessages.IllegalCharactersInPath(path)); |
| 225 | } | 160 | } |
| 226 | } | 161 | } |
| 227 | |||
| 228 | [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | ||
| 229 | private static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes); | ||
| 230 | } | 162 | } |
| 231 | } | 163 | } |
diff --git a/src/WixToolset.Core/Bind/FileSystem.cs b/src/WixToolset.Core/Bind/FileSystem.cs new file mode 100644 index 00000000..7d1b223e --- /dev/null +++ b/src/WixToolset.Core/Bind/FileSystem.cs | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.Bind | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using System.IO; | ||
| 8 | using System.Runtime.InteropServices; | ||
| 9 | using WixToolset.Extensibility; | ||
| 10 | |||
| 11 | internal class FileSystem | ||
| 12 | { | ||
| 13 | public FileSystem(IEnumerable<IFileSystemExtension> extensions) | ||
| 14 | { | ||
| 15 | this.Extensions = extensions ?? Array.Empty<IFileSystemExtension>(); | ||
| 16 | } | ||
| 17 | |||
| 18 | private IEnumerable<IFileSystemExtension> Extensions { get; } | ||
| 19 | |||
| 20 | /// <summary> | ||
| 21 | /// Copies a file. | ||
| 22 | /// </summary> | ||
| 23 | /// <param name="source">The file to copy.</param> | ||
| 24 | /// <param name="destination">The destination file.</param> | ||
| 25 | /// <param name="overwrite">true if the destination file can be overwritten; otherwise, false.</param> | ||
| 26 | public bool CopyFile(string source, string destination, bool overwrite) | ||
| 27 | { | ||
| 28 | foreach (var extension in this.Extensions) | ||
| 29 | { | ||
| 30 | if (extension.CopyFile(source, destination, overwrite)) | ||
| 31 | { | ||
| 32 | return true; | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | if (overwrite && File.Exists(destination)) | ||
| 37 | { | ||
| 38 | File.Delete(destination); | ||
| 39 | } | ||
| 40 | |||
| 41 | if (!CreateHardLink(destination, source, IntPtr.Zero)) | ||
| 42 | { | ||
| 43 | #if DEBUG | ||
| 44 | int er = Marshal.GetLastWin32Error(); | ||
| 45 | #endif | ||
| 46 | |||
| 47 | File.Copy(source, destination, overwrite); | ||
| 48 | } | ||
| 49 | |||
| 50 | return true; | ||
| 51 | } | ||
| 52 | |||
| 53 | /// <summary> | ||
| 54 | /// Moves a file. | ||
| 55 | /// </summary> | ||
| 56 | /// <param name="source">The file to move.</param> | ||
| 57 | /// <param name="destination">The destination file.</param> | ||
| 58 | public bool MoveFile(string source, string destination, bool overwrite) | ||
| 59 | { | ||
| 60 | foreach (var extension in this.Extensions) | ||
| 61 | { | ||
| 62 | if (extension.MoveFile(source, destination, overwrite)) | ||
| 63 | { | ||
| 64 | return true; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | if (overwrite && File.Exists(destination)) | ||
| 69 | { | ||
| 70 | File.Delete(destination); | ||
| 71 | } | ||
| 72 | |||
| 73 | var directory = Path.GetDirectoryName(destination); | ||
| 74 | if (!String.IsNullOrEmpty(directory)) | ||
| 75 | { | ||
| 76 | Directory.CreateDirectory(directory); | ||
| 77 | } | ||
| 78 | |||
| 79 | File.Move(source, destination); | ||
| 80 | |||
| 81 | return true; | ||
| 82 | } | ||
| 83 | |||
| 84 | [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | ||
| 85 | private static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes); | ||
| 86 | } | ||
| 87 | } | ||
diff --git a/src/WixToolset.Core/Bind/ResolveFieldsCommand.cs b/src/WixToolset.Core/Bind/ResolveFieldsCommand.cs index e8c90956..824eb9a5 100644 --- a/src/WixToolset.Core/Bind/ResolveFieldsCommand.cs +++ b/src/WixToolset.Core/Bind/ResolveFieldsCommand.cs | |||
| @@ -22,7 +22,7 @@ namespace WixToolset.Core.Bind | |||
| 22 | 22 | ||
| 23 | public IEnumerable<BindPath> BindPaths { private get; set; } | 23 | public IEnumerable<BindPath> BindPaths { private get; set; } |
| 24 | 24 | ||
| 25 | public IEnumerable<IBinderExtension> Extensions { private get; set; } | 25 | public IEnumerable<IResolverExtension> Extensions { private get; set; } |
| 26 | 26 | ||
| 27 | public ExtractEmbeddedFiles FilesWithEmbeddedFiles { private get; set; } | 27 | public ExtractEmbeddedFiles FilesWithEmbeddedFiles { private get; set; } |
| 28 | 28 | ||
| @@ -52,7 +52,6 @@ namespace WixToolset.Core.Bind | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | var isDefault = true; | 54 | var isDefault = true; |
| 55 | var delayedResolve = false; | ||
| 56 | 55 | ||
| 57 | // Check to make sure we're in a scenario where we can handle variable resolution. | 56 | // Check to make sure we're in a scenario where we can handle variable resolution. |
| 58 | if (null != delayedFields) | 57 | if (null != delayedFields) |
| @@ -63,16 +62,18 @@ namespace WixToolset.Core.Bind | |||
| 63 | var original = field.AsString(); | 62 | var original = field.AsString(); |
| 64 | if (!String.IsNullOrEmpty(original)) | 63 | if (!String.IsNullOrEmpty(original)) |
| 65 | { | 64 | { |
| 66 | var value = this.BindVariableResolver.ResolveVariables(row.SourceLineNumbers, original, false, out isDefault, out delayedResolve); | 65 | var resolution = this.BindVariableResolver.ResolveVariables(row.SourceLineNumbers, original, false); |
| 67 | if (original != value) | 66 | if (resolution.UpdatedValue) |
| 68 | { | 67 | { |
| 69 | field.Set(value); | 68 | field.Set(resolution.Value); |
| 70 | } | 69 | } |
| 71 | 70 | ||
| 72 | if (delayedResolve) | 71 | if (resolution.DelayedResolve) |
| 73 | { | 72 | { |
| 74 | delayedFields.Add(new DelayedField(row, field)); | 73 | delayedFields.Add(new DelayedField(row, field)); |
| 75 | } | 74 | } |
| 75 | |||
| 76 | isDefault = resolution.IsDefault; | ||
| 76 | } | 77 | } |
| 77 | } | 78 | } |
| 78 | } | 79 | } |
| @@ -119,13 +120,13 @@ namespace WixToolset.Core.Bind | |||
| 119 | #endif | 120 | #endif |
| 120 | 121 | ||
| 121 | // resolve the path to the file | 122 | // resolve the path to the file |
| 122 | var value = fileResolver.ResolveFile(objectField.Path, row.Definition.Name, row.SourceLineNumbers, BindStage.Normal); | 123 | var value = fileResolver.ResolveFile(objectField.Path, row.Definition, row.SourceLineNumbers, BindStage.Normal); |
| 123 | field.Set(value); | 124 | field.Set(value); |
| 124 | } | 125 | } |
| 125 | else if (!fileResolver.RebaseTarget && !fileResolver.RebaseUpdated) // Normal binding for Patch Scenario (normal patch, no re-basing logic) | 126 | else if (!fileResolver.RebaseTarget && !fileResolver.RebaseUpdated) // Normal binding for Patch Scenario (normal patch, no re-basing logic) |
| 126 | { | 127 | { |
| 127 | // resolve the path to the file | 128 | // resolve the path to the file |
| 128 | var value = fileResolver.ResolveFile(objectField.Path, row.Definition.Name, row.SourceLineNumbers, BindStage.Normal); | 129 | var value = fileResolver.ResolveFile(objectField.Path, row.Definition, row.SourceLineNumbers, BindStage.Normal); |
| 129 | field.Set(value); | 130 | field.Set(value); |
| 130 | } | 131 | } |
| 131 | #if REVISIT_FOR_PATCHING | 132 | #if REVISIT_FOR_PATCHING |
diff --git a/src/WixToolset.Core/Bind/ResolveResult.cs b/src/WixToolset.Core/Bind/ResolveResult.cs deleted file mode 100644 index 13f25054..00000000 --- a/src/WixToolset.Core/Bind/ResolveResult.cs +++ /dev/null | |||
| @@ -1,14 +0,0 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.Bind | ||
| 4 | { | ||
| 5 | using System.Collections.Generic; | ||
| 6 | using WixToolset.Extensibility; | ||
| 7 | |||
| 8 | public class ResolveResult | ||
| 9 | { | ||
| 10 | public IEnumerable<IExpectedExtractFile> ExpectedEmbeddedFiles { get; set; } | ||
| 11 | |||
| 12 | public IEnumerable<IDelayedField> DelayedFields { get; set; } | ||
| 13 | } | ||
| 14 | } \ No newline at end of file | ||
diff --git a/src/WixToolset.Core/Bind/TransferFilesCommand.cs b/src/WixToolset.Core/Bind/TransferFilesCommand.cs index 68d8b129..d4e143c3 100644 --- a/src/WixToolset.Core/Bind/TransferFilesCommand.cs +++ b/src/WixToolset.Core/Bind/TransferFilesCommand.cs | |||
| @@ -13,15 +13,15 @@ namespace WixToolset.Core.Bind | |||
| 13 | 13 | ||
| 14 | internal class TransferFilesCommand | 14 | internal class TransferFilesCommand |
| 15 | { | 15 | { |
| 16 | public TransferFilesCommand(IMessaging messaging, IEnumerable<BindPath> bindPaths, IEnumerable<IBinderExtension> extensions, IEnumerable<FileTransfer> fileTransfers, bool suppressAclReset) | 16 | public TransferFilesCommand(IMessaging messaging, IEnumerable<IFileSystemExtension> extensions, IEnumerable<FileTransfer> fileTransfers, bool suppressAclReset) |
| 17 | { | 17 | { |
| 18 | this.FileResolver = new FileResolver(bindPaths, extensions); | 18 | this.FileSystem = new FileSystem(extensions); |
| 19 | this.Messaging = messaging; | 19 | this.Messaging = messaging; |
| 20 | this.FileTransfers = fileTransfers; | 20 | this.FileTransfers = fileTransfers; |
| 21 | this.SuppressAclReset = suppressAclReset; | 21 | this.SuppressAclReset = suppressAclReset; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | private FileResolver FileResolver { get; } | 24 | private FileSystem FileSystem { get; } |
| 25 | 25 | ||
| 26 | private IMessaging Messaging { get; } | 26 | private IMessaging Messaging { get; } |
| 27 | 27 | ||
| @@ -35,10 +35,8 @@ namespace WixToolset.Core.Bind | |||
| 35 | 35 | ||
| 36 | foreach (var fileTransfer in this.FileTransfers) | 36 | foreach (var fileTransfer in this.FileTransfers) |
| 37 | { | 37 | { |
| 38 | string fileSource = this.FileResolver.ResolveFile(fileTransfer.Source, fileTransfer.Type, fileTransfer.SourceLineNumbers, BindStage.Normal); | ||
| 39 | |||
| 40 | // If the source and destination are identical, then there's nothing to do here | 38 | // If the source and destination are identical, then there's nothing to do here |
| 41 | if (0 == String.Compare(fileSource, fileTransfer.Destination, StringComparison.OrdinalIgnoreCase)) | 39 | if (0 == String.Compare(fileTransfer.Source, fileTransfer.Destination, StringComparison.OrdinalIgnoreCase)) |
| 42 | { | 40 | { |
| 43 | fileTransfer.Redundant = true; | 41 | fileTransfer.Redundant = true; |
| 44 | continue; | 42 | continue; |
| @@ -51,13 +49,13 @@ namespace WixToolset.Core.Bind | |||
| 51 | { | 49 | { |
| 52 | if (fileTransfer.Move) | 50 | if (fileTransfer.Move) |
| 53 | { | 51 | { |
| 54 | this.Messaging.Write(VerboseMessages.MoveFile(fileSource, fileTransfer.Destination)); | 52 | this.Messaging.Write(VerboseMessages.MoveFile(fileTransfer.Source, fileTransfer.Destination)); |
| 55 | this.TransferFile(true, fileSource, fileTransfer.Destination); | 53 | this.TransferFile(true, fileTransfer.Source, fileTransfer.Destination); |
| 56 | } | 54 | } |
| 57 | else | 55 | else |
| 58 | { | 56 | { |
| 59 | this.Messaging.Write(VerboseMessages.CopyFile(fileSource, fileTransfer.Destination)); | 57 | this.Messaging.Write(VerboseMessages.CopyFile(fileTransfer.Source, fileTransfer.Destination)); |
| 60 | this.TransferFile(false, fileSource, fileTransfer.Destination); | 58 | this.TransferFile(false, fileTransfer.Source, fileTransfer.Destination); |
| 61 | } | 59 | } |
| 62 | 60 | ||
| 63 | retry = false; | 61 | retry = false; |
| @@ -183,11 +181,11 @@ namespace WixToolset.Core.Bind | |||
| 183 | 181 | ||
| 184 | if (move) | 182 | if (move) |
| 185 | { | 183 | { |
| 186 | complete = this.FileResolver.MoveFile(source, destination, true); | 184 | complete = this.FileSystem.MoveFile(source, destination, true); |
| 187 | } | 185 | } |
| 188 | else | 186 | else |
| 189 | { | 187 | { |
| 190 | complete = this.FileResolver.CopyFile(source, destination, true); | 188 | complete = this.FileSystem.CopyFile(source, destination, true); |
| 191 | } | 189 | } |
| 192 | 190 | ||
| 193 | if (!complete) | 191 | if (!complete) |
diff --git a/src/WixToolset.Core/BindContext.cs b/src/WixToolset.Core/BindContext.cs index 41d0ddf9..8bdacf75 100644 --- a/src/WixToolset.Core/BindContext.cs +++ b/src/WixToolset.Core/BindContext.cs | |||
| @@ -35,7 +35,7 @@ namespace WixToolset.Core | |||
| 35 | 35 | ||
| 36 | public IExtensionManager ExtensionManager { get; set; } | 36 | public IExtensionManager ExtensionManager { get; set; } |
| 37 | 37 | ||
| 38 | public IEnumerable<IBinderExtension> Extensions { get; set; } | 38 | public IEnumerable<IFileSystemExtension> FileSystemExtensions { get; set; } |
| 39 | 39 | ||
| 40 | public IEnumerable<string> Ices { get; set; } | 40 | public IEnumerable<string> Ices { get; set; } |
| 41 | 41 | ||
| @@ -47,8 +47,6 @@ namespace WixToolset.Core | |||
| 47 | 47 | ||
| 48 | public string OutputPdbPath { get; set; } | 48 | public string OutputPdbPath { get; set; } |
| 49 | 49 | ||
| 50 | public bool SuppressAclReset { get; set; } | ||
| 51 | |||
| 52 | public IEnumerable<string> SuppressIces { get; set; } | 50 | public IEnumerable<string> SuppressIces { get; set; } |
| 53 | 51 | ||
| 54 | public bool SuppressValidation { get; set; } | 52 | public bool SuppressValidation { get; set; } |
diff --git a/src/WixToolset.Core/Binder.cs b/src/WixToolset.Core/Binder.cs index 2369b600..9db27fec 100644 --- a/src/WixToolset.Core/Binder.cs +++ b/src/WixToolset.Core/Binder.cs | |||
| @@ -3,14 +3,11 @@ | |||
| 3 | namespace WixToolset.Core | 3 | namespace WixToolset.Core |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections; | ||
| 7 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| 8 | using System.Diagnostics; | 7 | using System.Diagnostics; |
| 9 | using System.Globalization; | ||
| 10 | using System.IO; | 8 | using System.IO; |
| 11 | using System.Linq; | 9 | using System.Linq; |
| 12 | using System.Reflection; | 10 | using System.Reflection; |
| 13 | using WixToolset.Bind; | ||
| 14 | using WixToolset.Core.Bind; | 11 | using WixToolset.Core.Bind; |
| 15 | using WixToolset.Data; | 12 | using WixToolset.Data; |
| 16 | using WixToolset.Data.Bind; | 13 | using WixToolset.Data.Bind; |
| @@ -148,130 +145,72 @@ namespace WixToolset.Core | |||
| 148 | /// <value>The Wix variable resolver.</value> | 145 | /// <value>The Wix variable resolver.</value> |
| 149 | internal WixVariableResolver WixVariableResolver { get; set; } | 146 | internal WixVariableResolver WixVariableResolver { get; set; } |
| 150 | 147 | ||
| 151 | /// <summary> | 148 | public BindResult Bind(IBindContext context) |
| 152 | /// Add a binder extension. | ||
| 153 | /// </summary> | ||
| 154 | /// <param name="extension">New extension.</param> | ||
| 155 | //public void AddExtension(IBinderExtension extension) | ||
| 156 | //{ | ||
| 157 | // this.extensions.Add(extension); | ||
| 158 | //} | ||
| 159 | |||
| 160 | /// <summary> | ||
| 161 | /// Add a file manager extension. | ||
| 162 | /// </summary> | ||
| 163 | /// <param name="extension">New file manager.</param> | ||
| 164 | //public void AddExtension(IBinderFileManager extension) | ||
| 165 | //{ | ||
| 166 | // this.fileManagers.Add(extension); | ||
| 167 | //} | ||
| 168 | |||
| 169 | public bool Bind(IBindContext context) | ||
| 170 | { | 149 | { |
| 171 | this.Context = context; | 150 | this.Context = context; |
| 172 | 151 | ||
| 173 | //if (!String.IsNullOrEmpty(this.Context.FileManagerCore.CabCachePath)) | ||
| 174 | //{ | ||
| 175 | // Directory.CreateDirectory(this.Context.FileManagerCore.CabCachePath); | ||
| 176 | //} | ||
| 177 | |||
| 178 | //this.core = new BinderCore(); | ||
| 179 | //this.core.FileManagerCore = this.Context.FileManagerCore; | ||
| 180 | |||
| 181 | this.WriteBuildInfoTable(this.Context.IntermediateRepresentation, this.Context.OutputPath); | 152 | this.WriteBuildInfoTable(this.Context.IntermediateRepresentation, this.Context.OutputPath); |
| 182 | 153 | ||
| 183 | // Prebind. | ||
| 184 | // | ||
| 185 | this.Context.Extensions = this.Context.ExtensionManager.Create<IBinderExtension>(); | ||
| 186 | |||
| 187 | foreach (IBinderExtension extension in this.Context.Extensions) | ||
| 188 | { | ||
| 189 | extension.PreBind(this.Context); | ||
| 190 | } | ||
| 191 | |||
| 192 | // Resolve. | ||
| 193 | // | ||
| 194 | var resolveResult = this.Resolve(); | ||
| 195 | |||
| 196 | this.Context.DelayedFields = resolveResult.DelayedFields; | ||
| 197 | |||
| 198 | this.Context.ExpectedEmbeddedFiles = resolveResult.ExpectedEmbeddedFiles; | ||
| 199 | |||
| 200 | // Backend. | ||
| 201 | // | ||
| 202 | var bindResult = this.BackendBind(); | 154 | var bindResult = this.BackendBind(); |
| 203 | 155 | return bindResult; | |
| 204 | if (bindResult != null) | ||
| 205 | { | ||
| 206 | // Postbind. | ||
| 207 | // | ||
| 208 | foreach (IBinderExtension extension in this.Context.Extensions) | ||
| 209 | { | ||
| 210 | extension.PostBind(bindResult); | ||
| 211 | } | ||
| 212 | |||
| 213 | // Layout. | ||
| 214 | // | ||
| 215 | this.Layout(bindResult); | ||
| 216 | } | ||
| 217 | |||
| 218 | return this.Context.Messaging.EncounteredError; | ||
| 219 | } | 156 | } |
| 220 | 157 | ||
| 221 | private ResolveResult Resolve() | 158 | //// private ResolveResult Resolve() |
| 222 | { | 159 | //// { |
| 223 | var buildingPatch = this.Context.IntermediateRepresentation.Sections.Any(s => s.Type == SectionType.Patch); | 160 | //// var buildingPatch = this.Context.IntermediateRepresentation.Sections.Any(s => s.Type == SectionType.Patch); |
| 224 | 161 | ||
| 225 | var filesWithEmbeddedFiles = new ExtractEmbeddedFiles(); | 162 | //// var filesWithEmbeddedFiles = new ExtractEmbeddedFiles(); |
| 226 | 163 | ||
| 227 | IEnumerable<DelayedField> delayedFields; | 164 | //// IEnumerable<DelayedField> delayedFields; |
| 228 | { | 165 | //// { |
| 229 | var command = new ResolveFieldsCommand(); | 166 | //// var command = new ResolveFieldsCommand(); |
| 230 | command.Messaging = this.Context.Messaging; | 167 | //// command.Messaging = this.Context.Messaging; |
| 231 | command.BuildingPatch = buildingPatch; | 168 | //// command.BuildingPatch = buildingPatch; |
| 232 | command.BindVariableResolver = this.Context.WixVariableResolver; | 169 | //// command.BindVariableResolver = this.Context.WixVariableResolver; |
| 233 | command.BindPaths = this.Context.BindPaths; | 170 | //// command.BindPaths = this.Context.BindPaths; |
| 234 | command.Extensions = this.Context.Extensions; | 171 | //// command.Extensions = this.Context.Extensions; |
| 235 | command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles; | 172 | //// command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles; |
| 236 | command.IntermediateFolder = this.Context.IntermediateFolder; | 173 | //// command.IntermediateFolder = this.Context.IntermediateFolder; |
| 237 | command.Intermediate = this.Context.IntermediateRepresentation; | 174 | //// command.Intermediate = this.Context.IntermediateRepresentation; |
| 238 | command.SupportDelayedResolution = true; | 175 | //// command.SupportDelayedResolution = true; |
| 239 | command.Execute(); | 176 | //// command.Execute(); |
| 240 | 177 | ||
| 241 | delayedFields = command.DelayedFields; | 178 | //// delayedFields = command.DelayedFields; |
| 242 | } | 179 | //// } |
| 243 | 180 | ||
| 244 | #if REVISIT_FOR_PATCHING | 181 | ////#if REVISIT_FOR_PATCHING |
| 245 | if (this.Context.IntermediateRepresentation.SubStorages != null) | 182 | //// if (this.Context.IntermediateRepresentation.SubStorages != null) |
| 246 | { | 183 | //// { |
| 247 | foreach (SubStorage transform in this.Context.IntermediateRepresentation.SubStorages) | 184 | //// foreach (SubStorage transform in this.Context.IntermediateRepresentation.SubStorages) |
| 248 | { | 185 | //// { |
| 249 | var command = new ResolveFieldsCommand(); | 186 | //// var command = new ResolveFieldsCommand(); |
| 250 | command.BuildingPatch = buildingPatch; | 187 | //// command.BuildingPatch = buildingPatch; |
| 251 | command.BindVariableResolver = this.Context.WixVariableResolver; | 188 | //// command.BindVariableResolver = this.Context.WixVariableResolver; |
| 252 | command.BindPaths = this.Context.BindPaths; | 189 | //// command.BindPaths = this.Context.BindPaths; |
| 253 | command.Extensions = this.Context.Extensions; | 190 | //// command.Extensions = this.Context.Extensions; |
| 254 | command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles; | 191 | //// command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles; |
| 255 | command.IntermediateFolder = this.Context.IntermediateFolder; | 192 | //// command.IntermediateFolder = this.Context.IntermediateFolder; |
| 256 | command.Intermediate = this.Context.IntermediateRepresentation; | 193 | //// command.Intermediate = this.Context.IntermediateRepresentation; |
| 257 | command.SupportDelayedResolution = false; | 194 | //// command.SupportDelayedResolution = false; |
| 258 | command.Execute(); | 195 | //// command.Execute(); |
| 259 | } | 196 | //// } |
| 260 | } | 197 | //// } |
| 261 | #endif | 198 | ////#endif |
| 262 | 199 | ||
| 263 | var expectedEmbeddedFiles = filesWithEmbeddedFiles.GetExpectedEmbeddedFiles(); | 200 | //// var expectedEmbeddedFiles = filesWithEmbeddedFiles.GetExpectedEmbeddedFiles(); |
| 264 | 201 | ||
| 265 | return new ResolveResult | 202 | //// return new ResolveResult |
| 266 | { | 203 | //// { |
| 267 | ExpectedEmbeddedFiles = expectedEmbeddedFiles, | 204 | //// ExpectedEmbeddedFiles = expectedEmbeddedFiles, |
| 268 | DelayedFields = delayedFields, | 205 | //// DelayedFields = delayedFields, |
| 269 | }; | 206 | //// }; |
| 270 | } | 207 | //// } |
| 271 | 208 | ||
| 272 | private BindResult BackendBind() | 209 | private BindResult BackendBind() |
| 273 | { | 210 | { |
| 274 | var backendFactories = this.Context.ExtensionManager.Create<IBackendFactory>(); | 211 | var extensionManager = this.Context.ServiceProvider.GetService<IExtensionManager>(); |
| 212 | |||
| 213 | var backendFactories = extensionManager.Create<IBackendFactory>(); | ||
| 275 | 214 | ||
| 276 | var entrySection = this.Context.IntermediateRepresentation.Sections[0]; | 215 | var entrySection = this.Context.IntermediateRepresentation.Sections[0]; |
| 277 | 216 | ||
| @@ -289,31 +228,6 @@ namespace WixToolset.Core | |||
| 289 | return null; | 228 | return null; |
| 290 | } | 229 | } |
| 291 | 230 | ||
| 292 | private void Layout(BindResult result) | ||
| 293 | { | ||
| 294 | try | ||
| 295 | { | ||
| 296 | this.LayoutMedia(result.FileTransfers); | ||
| 297 | } | ||
| 298 | finally | ||
| 299 | { | ||
| 300 | if (!String.IsNullOrEmpty(this.Context.ContentsFile) && result.ContentFilePaths != null) | ||
| 301 | { | ||
| 302 | this.CreateContentsFile(this.Context.ContentsFile, result.ContentFilePaths); | ||
| 303 | } | ||
| 304 | |||
| 305 | if (!String.IsNullOrEmpty(this.Context.OutputsFile) && result.FileTransfers != null) | ||
| 306 | { | ||
| 307 | this.CreateOutputsFile(this.Context.OutputsFile, result.FileTransfers, this.Context.OutputPdbPath); | ||
| 308 | } | ||
| 309 | |||
| 310 | if (!String.IsNullOrEmpty(this.Context.BuiltOutputsFile) && result.FileTransfers != null) | ||
| 311 | { | ||
| 312 | this.CreateBuiltOutputsFile(this.Context.BuiltOutputsFile, result.FileTransfers, this.Context.OutputPdbPath); | ||
| 313 | } | ||
| 314 | } | ||
| 315 | } | ||
| 316 | |||
| 317 | /// <summary> | 231 | /// <summary> |
| 318 | /// Binds an output. | 232 | /// Binds an output. |
| 319 | /// </summary> | 233 | /// </summary> |
| @@ -429,35 +343,6 @@ namespace WixToolset.Core | |||
| 429 | #endif | 343 | #endif |
| 430 | 344 | ||
| 431 | /// <summary> | 345 | /// <summary> |
| 432 | /// Does any housekeeping after Bind. | ||
| 433 | /// </summary> | ||
| 434 | /// <param name="tidy">Whether or not any actual tidying should be done.</param> | ||
| 435 | public void Cleanup(bool tidy) | ||
| 436 | { | ||
| 437 | if (tidy) | ||
| 438 | { | ||
| 439 | if (!this.DeleteTempFiles()) | ||
| 440 | { | ||
| 441 | this.Context.Messaging.Write(WarningMessages.FailedToDeleteTempDir(this.TempFilesLocation)); | ||
| 442 | } | ||
| 443 | } | ||
| 444 | else | ||
| 445 | { | ||
| 446 | this.Context.Messaging.Write(VerboseMessages.BinderTempDirLocatedAt(this.TempFilesLocation)); | ||
| 447 | } | ||
| 448 | } | ||
| 449 | |||
| 450 | /// <summary> | ||
| 451 | /// Cleans up the temp files used by the Binder. | ||
| 452 | /// </summary> | ||
| 453 | /// <returns>True if all files were deleted, false otherwise.</returns> | ||
| 454 | private bool DeleteTempFiles() | ||
| 455 | { | ||
| 456 | bool deleted = Common.DeleteTempFiles(this.TempFilesLocation, this.Context.Messaging); | ||
| 457 | return deleted; | ||
| 458 | } | ||
| 459 | |||
| 460 | /// <summary> | ||
| 461 | /// Populates the WixBuildInfo table in an output. | 346 | /// Populates the WixBuildInfo table in an output. |
| 462 | /// </summary> | 347 | /// </summary> |
| 463 | /// <param name="output">The output.</param> | 348 | /// <param name="output">The output.</param> |
| @@ -585,231 +470,5 @@ namespace WixToolset.Core | |||
| 585 | command.Execute(); | 470 | command.Execute(); |
| 586 | } | 471 | } |
| 587 | #endif | 472 | #endif |
| 588 | |||
| 589 | /// <summary> | ||
| 590 | /// Final step in binding that transfers (moves/copies) all files generated into the appropriate | ||
| 591 | /// location in the source image | ||
| 592 | /// </summary> | ||
| 593 | /// <param name="fileTransfers">List of files to transfer.</param> | ||
| 594 | private void LayoutMedia(IEnumerable<FileTransfer> transfers) | ||
| 595 | { | ||
| 596 | if (null != transfers && transfers.Any()) | ||
| 597 | { | ||
| 598 | this.Context.Messaging.Write(VerboseMessages.LayingOutMedia()); | ||
| 599 | |||
| 600 | var command = new TransferFilesCommand(this.Context.Messaging, this.Context.BindPaths, this.Context.Extensions, transfers, this.Context.SuppressAclReset); | ||
| 601 | command.Execute(); | ||
| 602 | } | ||
| 603 | } | ||
| 604 | |||
| 605 | /// <summary> | ||
| 606 | /// Get the source path of a directory. | ||
| 607 | /// </summary> | ||
| 608 | /// <param name="directories">All cached directories.</param> | ||
| 609 | /// <param name="componentIdGenSeeds">Hash table of Component GUID generation seeds indexed by directory id.</param> | ||
| 610 | /// <param name="directory">Directory identifier.</param> | ||
| 611 | /// <param name="canonicalize">Canonicalize the path for standard directories.</param> | ||
| 612 | /// <returns>Source path of a directory.</returns> | ||
| 613 | public static string GetDirectoryPath(Dictionary<string, ResolvedDirectory> directories, Dictionary<string, string> componentIdGenSeeds, string directory, bool canonicalize) | ||
| 614 | { | ||
| 615 | if (!directories.ContainsKey(directory)) | ||
| 616 | { | ||
| 617 | throw new WixException(ErrorMessages.ExpectedDirectory(directory)); | ||
| 618 | } | ||
| 619 | |||
| 620 | ResolvedDirectory resolvedDirectory = (ResolvedDirectory)directories[directory]; | ||
| 621 | |||
| 622 | if (null == resolvedDirectory.Path) | ||
| 623 | { | ||
| 624 | if (null != componentIdGenSeeds && componentIdGenSeeds.ContainsKey(directory)) | ||
| 625 | { | ||
| 626 | resolvedDirectory.Path = (string)componentIdGenSeeds[directory]; | ||
| 627 | } | ||
| 628 | else if (canonicalize && WindowsInstallerStandard.IsStandardDirectory(directory)) | ||
| 629 | { | ||
| 630 | // when canonicalization is on, standard directories are treated equally | ||
| 631 | resolvedDirectory.Path = directory; | ||
| 632 | } | ||
| 633 | else | ||
| 634 | { | ||
| 635 | string name = resolvedDirectory.Name; | ||
| 636 | |||
| 637 | if (canonicalize && null != name) | ||
| 638 | { | ||
| 639 | name = name.ToLower(CultureInfo.InvariantCulture); | ||
| 640 | } | ||
| 641 | |||
| 642 | if (String.IsNullOrEmpty(resolvedDirectory.DirectoryParent)) | ||
| 643 | { | ||
| 644 | resolvedDirectory.Path = name; | ||
| 645 | } | ||
| 646 | else | ||
| 647 | { | ||
| 648 | string parentPath = GetDirectoryPath(directories, componentIdGenSeeds, resolvedDirectory.DirectoryParent, canonicalize); | ||
| 649 | |||
| 650 | if (null != resolvedDirectory.Name) | ||
| 651 | { | ||
| 652 | resolvedDirectory.Path = Path.Combine(parentPath, name); | ||
| 653 | } | ||
| 654 | else | ||
| 655 | { | ||
| 656 | resolvedDirectory.Path = parentPath; | ||
| 657 | } | ||
| 658 | } | ||
| 659 | } | ||
| 660 | } | ||
| 661 | |||
| 662 | return resolvedDirectory.Path; | ||
| 663 | } | ||
| 664 | |||
| 665 | /// <summary> | ||
| 666 | /// Gets the source path of a file. | ||
| 667 | /// </summary> | ||
| 668 | /// <param name="directories">All cached directories in <see cref="ResolvedDirectory"/>.</param> | ||
| 669 | /// <param name="directoryId">Parent directory identifier.</param> | ||
| 670 | /// <param name="fileName">File name (in long|source format).</param> | ||
| 671 | /// <param name="compressed">Specifies the package is compressed.</param> | ||
| 672 | /// <param name="useLongName">Specifies the package uses long file names.</param> | ||
| 673 | /// <returns>Source path of file relative to package directory.</returns> | ||
| 674 | public static string GetFileSourcePath(Dictionary<string, ResolvedDirectory> directories, string directoryId, string fileName, bool compressed, bool useLongName) | ||
| 675 | { | ||
| 676 | string fileSourcePath = Common.GetName(fileName, true, useLongName); | ||
| 677 | |||
| 678 | if (compressed) | ||
| 679 | { | ||
| 680 | // Use just the file name of the file since all uncompressed files must appear | ||
| 681 | // in the root of the image in a compressed package. | ||
| 682 | } | ||
| 683 | else | ||
| 684 | { | ||
| 685 | // Get the relative path of where we want the file to be layed out as specified | ||
| 686 | // in the Directory table. | ||
| 687 | string directoryPath = Binder.GetDirectoryPath(directories, null, directoryId, false); | ||
| 688 | fileSourcePath = Path.Combine(directoryPath, fileSourcePath); | ||
| 689 | } | ||
| 690 | |||
| 691 | // Strip off "SourceDir" if it's still on there. | ||
| 692 | if (fileSourcePath.StartsWith("SourceDir\\", StringComparison.Ordinal)) | ||
| 693 | { | ||
| 694 | fileSourcePath = fileSourcePath.Substring(10); | ||
| 695 | } | ||
| 696 | |||
| 697 | return fileSourcePath; | ||
| 698 | } | ||
| 699 | |||
| 700 | /// <summary> | ||
| 701 | /// Writes the paths to the content files included in the package to a text file. | ||
| 702 | /// </summary> | ||
| 703 | /// <param name="path">Path to write file.</param> | ||
| 704 | /// <param name="contentFilePaths">Collection of paths to content files that will be written to file.</param> | ||
| 705 | private void CreateContentsFile(string path, IEnumerable<string> contentFilePaths) | ||
| 706 | { | ||
| 707 | string directory = Path.GetDirectoryName(path); | ||
| 708 | if (!Directory.Exists(directory)) | ||
| 709 | { | ||
| 710 | Directory.CreateDirectory(directory); | ||
| 711 | } | ||
| 712 | |||
| 713 | using (StreamWriter contents = new StreamWriter(path, false)) | ||
| 714 | { | ||
| 715 | foreach (string contentPath in contentFilePaths) | ||
| 716 | { | ||
| 717 | contents.WriteLine(contentPath); | ||
| 718 | } | ||
| 719 | } | ||
| 720 | } | ||
| 721 | |||
| 722 | /// <summary> | ||
| 723 | /// Writes the paths to the content files included in the bundle to a text file. | ||
| 724 | /// </summary> | ||
| 725 | /// <param name="path">Path to write file.</param> | ||
| 726 | /// <param name="payloads">Collection of payloads whose source will be written to file.</param> | ||
| 727 | private void CreateContentsFile(string path, IEnumerable<WixBundlePayloadTuple> payloads) | ||
| 728 | { | ||
| 729 | string directory = Path.GetDirectoryName(path); | ||
| 730 | if (!Directory.Exists(directory)) | ||
| 731 | { | ||
| 732 | Directory.CreateDirectory(directory); | ||
| 733 | } | ||
| 734 | |||
| 735 | using (StreamWriter contents = new StreamWriter(path, false)) | ||
| 736 | { | ||
| 737 | foreach (var payload in payloads) | ||
| 738 | { | ||
| 739 | if (payload.ContentFile) | ||
| 740 | { | ||
| 741 | var fullPath = Path.GetFullPath(payload.SourceFile); | ||
| 742 | contents.WriteLine(fullPath); | ||
| 743 | } | ||
| 744 | } | ||
| 745 | } | ||
| 746 | } | ||
| 747 | |||
| 748 | /// <summary> | ||
| 749 | /// Writes the paths to the output files to a text file. | ||
| 750 | /// </summary> | ||
| 751 | /// <param name="path">Path to write file.</param> | ||
| 752 | /// <param name="fileTransfers">Collection of files that were transferred to the output directory.</param> | ||
| 753 | /// <param name="pdbPath">Optional path to created .wixpdb.</param> | ||
| 754 | private void CreateOutputsFile(string path, IEnumerable<FileTransfer> fileTransfers, string pdbPath) | ||
| 755 | { | ||
| 756 | string directory = Path.GetDirectoryName(path); | ||
| 757 | if (!Directory.Exists(directory)) | ||
| 758 | { | ||
| 759 | Directory.CreateDirectory(directory); | ||
| 760 | } | ||
| 761 | |||
| 762 | using (StreamWriter outputs = new StreamWriter(path, false)) | ||
| 763 | { | ||
| 764 | foreach (FileTransfer fileTransfer in fileTransfers) | ||
| 765 | { | ||
| 766 | // Don't list files where the source is the same as the destination since | ||
| 767 | // that might be the only place the file exists. The outputs file is often | ||
| 768 | // used to delete stuff and losing the original source would be bad. | ||
| 769 | if (!fileTransfer.Redundant) | ||
| 770 | { | ||
| 771 | outputs.WriteLine(fileTransfer.Destination); | ||
| 772 | } | ||
| 773 | } | ||
| 774 | |||
| 775 | if (!String.IsNullOrEmpty(pdbPath)) | ||
| 776 | { | ||
| 777 | outputs.WriteLine(Path.GetFullPath(pdbPath)); | ||
| 778 | } | ||
| 779 | } | ||
| 780 | } | ||
| 781 | |||
| 782 | /// <summary> | ||
| 783 | /// Writes the paths to the built output files to a text file. | ||
| 784 | /// </summary> | ||
| 785 | /// <param name="path">Path to write file.</param> | ||
| 786 | /// <param name="fileTransfers">Collection of files that were transferred to the output directory.</param> | ||
| 787 | /// <param name="pdbPath">Optional path to created .wixpdb.</param> | ||
| 788 | private void CreateBuiltOutputsFile(string path, IEnumerable<FileTransfer> fileTransfers, string pdbPath) | ||
| 789 | { | ||
| 790 | string directory = Path.GetDirectoryName(path); | ||
| 791 | if (!Directory.Exists(directory)) | ||
| 792 | { | ||
| 793 | Directory.CreateDirectory(directory); | ||
| 794 | } | ||
| 795 | |||
| 796 | using (StreamWriter outputs = new StreamWriter(path, false)) | ||
| 797 | { | ||
| 798 | foreach (FileTransfer fileTransfer in fileTransfers) | ||
| 799 | { | ||
| 800 | // Only write the built file transfers. Also, skip redundant | ||
| 801 | // files for the same reason spelled out in this.CreateOutputsFile(). | ||
| 802 | if (fileTransfer.Built && !fileTransfer.Redundant) | ||
| 803 | { | ||
| 804 | outputs.WriteLine(fileTransfer.Destination); | ||
| 805 | } | ||
| 806 | } | ||
| 807 | |||
| 808 | if (!String.IsNullOrEmpty(pdbPath)) | ||
| 809 | { | ||
| 810 | outputs.WriteLine(Path.GetFullPath(pdbPath)); | ||
| 811 | } | ||
| 812 | } | ||
| 813 | } | ||
| 814 | } | 473 | } |
| 815 | } | 474 | } |
diff --git a/src/WixToolset.Core/BinderFileManager.cs b/src/WixToolset.Core/BinderFileManager.cs index 1527d93d..5e08bc40 100644 --- a/src/WixToolset.Core/BinderFileManager.cs +++ b/src/WixToolset.Core/BinderFileManager.cs | |||
| @@ -12,7 +12,7 @@ namespace WixToolset | |||
| 12 | using WixToolset.Data.Rows; | 12 | using WixToolset.Data.Rows; |
| 13 | using WixToolset.Extensibility; | 13 | using WixToolset.Extensibility; |
| 14 | 14 | ||
| 15 | #if false | 15 | #if DEAD_CODE |
| 16 | /// <summary> | 16 | /// <summary> |
| 17 | /// Base class for creating a binder file manager. | 17 | /// Base class for creating a binder file manager. |
| 18 | /// </summary> | 18 | /// </summary> |
diff --git a/src/WixToolset.Core/BinderFileManagerCore.cs b/src/WixToolset.Core/BinderFileManagerCore.cs index e699f0ce..aa9a45de 100644 --- a/src/WixToolset.Core/BinderFileManagerCore.cs +++ b/src/WixToolset.Core/BinderFileManagerCore.cs | |||
| @@ -9,6 +9,7 @@ namespace WixToolset | |||
| 9 | using WixToolset.Data.Bind; | 9 | using WixToolset.Data.Bind; |
| 10 | using WixToolset.Extensibility; | 10 | using WixToolset.Extensibility; |
| 11 | 11 | ||
| 12 | #if DEAD_CODE | ||
| 12 | public class BinderFileManagerCore : IBinderFileManagerCore | 13 | public class BinderFileManagerCore : IBinderFileManagerCore |
| 13 | { | 14 | { |
| 14 | private Dictionary<string, List<string>>[] bindPaths; | 15 | private Dictionary<string, List<string>>[] bindPaths; |
| @@ -97,4 +98,5 @@ namespace WixToolset | |||
| 97 | return Enumerable.Empty<string>(); | 98 | return Enumerable.Empty<string>(); |
| 98 | } | 99 | } |
| 99 | } | 100 | } |
| 101 | #endif | ||
| 100 | } | 102 | } |
diff --git a/src/WixToolset.Core/CommandLine/BuildCommand.cs b/src/WixToolset.Core/CommandLine/BuildCommand.cs index 43b75f33..92aa3343 100644 --- a/src/WixToolset.Core/CommandLine/BuildCommand.cs +++ b/src/WixToolset.Core/CommandLine/BuildCommand.cs | |||
| @@ -7,7 +7,7 @@ namespace WixToolset.Core | |||
| 7 | using System.IO; | 7 | using System.IO; |
| 8 | using System.Linq; | 8 | using System.Linq; |
| 9 | using WixToolset.Data; | 9 | using WixToolset.Data; |
| 10 | using WixToolset.Data.Tuples; | 10 | using WixToolset.Data.Bind; |
| 11 | using WixToolset.Extensibility; | 11 | using WixToolset.Extensibility; |
| 12 | using WixToolset.Extensibility.Services; | 12 | using WixToolset.Extensibility.Services; |
| 13 | 13 | ||
| @@ -90,6 +90,12 @@ namespace WixToolset.Core | |||
| 90 | 90 | ||
| 91 | library?.Save(this.OutputPath); | 91 | library?.Save(this.OutputPath); |
| 92 | } | 92 | } |
| 93 | else if (this.OutputType == OutputType.Wixout) | ||
| 94 | { | ||
| 95 | var output = this.LinkPhase(intermediates); | ||
| 96 | |||
| 97 | output?.Save(this.OutputPath); | ||
| 98 | } | ||
| 93 | else | 99 | else |
| 94 | { | 100 | { |
| 95 | var output = this.LinkPhase(intermediates); | 101 | var output = this.LinkPhase(intermediates); |
| @@ -147,22 +153,20 @@ namespace WixToolset.Core | |||
| 147 | { | 153 | { |
| 148 | var localizations = this.LoadLocalizationFiles().ToList(); | 154 | var localizations = this.LoadLocalizationFiles().ToList(); |
| 149 | 155 | ||
| 150 | // If there was an error adding localization files, then bail. | 156 | // If there was an error loading localization files, then bail. |
| 151 | if (this.Messaging.EncounteredError) | 157 | if (this.Messaging.EncounteredError) |
| 152 | { | 158 | { |
| 153 | return null; | 159 | return null; |
| 154 | } | 160 | } |
| 155 | 161 | ||
| 156 | var resolver = CreateWixResolverWithVariables(null, null); | ||
| 157 | |||
| 158 | var context = new LibraryContext(); | 162 | var context = new LibraryContext(); |
| 163 | context.Messaging = this.Messaging; | ||
| 159 | context.BindFiles = this.BindFiles; | 164 | context.BindFiles = this.BindFiles; |
| 160 | context.BindPaths = this.BindPaths; | 165 | context.BindPaths = this.BindPaths; |
| 161 | context.Extensions = this.ExtensionManager.Create<ILibrarianExtension>(); | 166 | context.Extensions = this.ExtensionManager.Create<ILibrarianExtension>(); |
| 162 | context.Localizations = localizations; | 167 | context.Localizations = localizations; |
| 163 | context.LibraryId = Guid.NewGuid().ToString("N"); | 168 | context.LibraryId = Guid.NewGuid().ToString("N"); |
| 164 | context.Intermediates = intermediates; | 169 | context.Intermediates = intermediates; |
| 165 | context.WixVariableResolver = resolver; | ||
| 166 | 170 | ||
| 167 | var librarian = new Librarian(); | 171 | var librarian = new Librarian(); |
| 168 | return librarian.Combine(context); | 172 | return librarian.Combine(context); |
| @@ -174,6 +178,11 @@ namespace WixToolset.Core | |||
| 174 | 178 | ||
| 175 | var libraries = this.LoadLibraries(creator); | 179 | var libraries = this.LoadLibraries(creator); |
| 176 | 180 | ||
| 181 | if (this.Messaging.EncounteredError) | ||
| 182 | { | ||
| 183 | return null; | ||
| 184 | } | ||
| 185 | |||
| 177 | var context = this.ServiceProvider.GetService<ILinkContext>(); | 186 | var context = this.ServiceProvider.GetService<ILinkContext>(); |
| 178 | context.Messaging = this.Messaging; | 187 | context.Messaging = this.Messaging; |
| 179 | context.Extensions = this.ExtensionManager.Create<ILinkerExtension>(); | 188 | context.Extensions = this.ExtensionManager.Create<ILinkerExtension>(); |
| @@ -183,48 +192,72 @@ namespace WixToolset.Core | |||
| 183 | context.TupleDefinitionCreator = creator; | 192 | context.TupleDefinitionCreator = creator; |
| 184 | 193 | ||
| 185 | var linker = new Linker(); | 194 | var linker = new Linker(); |
| 186 | var output = linker.Link(context); | 195 | return linker.Link(context); |
| 187 | return output; | ||
| 188 | } | 196 | } |
| 189 | 197 | ||
| 190 | private void BindPhase(Intermediate output) | 198 | private void BindPhase(Intermediate output) |
| 191 | { | 199 | { |
| 192 | var localizations = this.LoadLocalizationFiles().ToList(); | 200 | var localizations = this.LoadLocalizationFiles().ToList(); |
| 193 | 201 | ||
| 194 | var localizer = new Localizer(this.Messaging, localizations); | 202 | // If there was an error loading localization files, then bail. |
| 203 | if (this.Messaging.EncounteredError) | ||
| 204 | { | ||
| 205 | return; | ||
| 206 | } | ||
| 195 | 207 | ||
| 196 | var resolver = CreateWixResolverWithVariables(localizer, output); | 208 | ResolveResult resolveResult; |
| 209 | { | ||
| 210 | var resolver = new Resolver(this.ServiceProvider, this.BindPaths, output, this.IntermediateFolder, localizations); | ||
| 211 | resolveResult = resolver.Execute(); | ||
| 212 | } | ||
| 197 | 213 | ||
| 198 | var intermediateFolder = this.IntermediateFolder; | 214 | if (this.Messaging.EncounteredError) |
| 199 | if (String.IsNullOrEmpty(intermediateFolder)) | ||
| 200 | { | 215 | { |
| 201 | intermediateFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); | 216 | return; |
| 202 | } | 217 | } |
| 203 | 218 | ||
| 204 | var context = this.ServiceProvider.GetService<IBindContext>(); | 219 | BindResult bindResult; |
| 205 | context.Messaging = this.Messaging; | 220 | { |
| 206 | context.ExtensionManager = this.ExtensionManager; | 221 | var intermediateFolder = this.IntermediateFolder; |
| 207 | context.BindPaths = this.BindPaths ?? Array.Empty<BindPath>(); | 222 | if (String.IsNullOrEmpty(intermediateFolder)) |
| 208 | //context.CabbingThreadCount = this.CabbingThreadCount; | 223 | { |
| 209 | context.CabCachePath = this.CabCachePath; | 224 | intermediateFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); |
| 210 | context.Codepage = localizer.Codepage; | 225 | } |
| 211 | //context.DefaultCompressionLevel = this.DefaultCompressionLevel; | 226 | |
| 212 | //context.Ices = this.Ices; | 227 | var context = this.ServiceProvider.GetService<IBindContext>(); |
| 213 | context.IntermediateFolder = intermediateFolder; | 228 | context.Messaging = this.Messaging; |
| 214 | context.IntermediateRepresentation = output; | 229 | //context.CabbingThreadCount = this.CabbingThreadCount; |
| 215 | context.OutputPath = this.OutputPath; | 230 | context.CabCachePath = this.CabCachePath; |
| 216 | context.OutputPdbPath = Path.ChangeExtension(this.OutputPath, ".wixpdb"); | 231 | context.Codepage = resolveResult.Codepage; |
| 217 | //context.SuppressIces = this.SuppressIces; | 232 | //context.DefaultCompressionLevel = this.DefaultCompressionLevel; |
| 218 | context.SuppressValidation = true; | 233 | context.DelayedFields = resolveResult.DelayedFields; |
| 219 | //context.SuppressValidation = this.SuppressValidation; | 234 | context.ExpectedEmbeddedFiles = resolveResult.ExpectedEmbeddedFiles; |
| 220 | context.WixVariableResolver = resolver; | 235 | //context.Ices = this.Ices; |
| 221 | context.ContentsFile = this.ContentsFile; | 236 | context.IntermediateFolder = intermediateFolder; |
| 222 | context.OutputsFile = this.OutputsFile; | 237 | context.IntermediateRepresentation = resolveResult.IntermediateRepresentation; |
| 223 | context.BuiltOutputsFile = this.BuiltOutputsFile; | 238 | context.OutputPath = this.OutputPath; |
| 224 | context.WixprojectFile = this.WixProjectFile; | 239 | context.OutputPdbPath = Path.ChangeExtension(this.OutputPath, ".wixpdb"); |
| 225 | 240 | //context.SuppressIces = this.SuppressIces; | |
| 226 | var binder = new Binder(); | 241 | context.SuppressValidation = true; // TODO: set this correctly |
| 227 | binder.Bind(context); | 242 | context.ContentsFile = this.ContentsFile; |
| 243 | context.OutputsFile = this.OutputsFile; | ||
| 244 | context.BuiltOutputsFile = this.BuiltOutputsFile; | ||
| 245 | context.WixprojectFile = this.WixProjectFile; | ||
| 246 | |||
| 247 | var binder = new Binder(); | ||
| 248 | bindResult = binder.Bind(context); | ||
| 249 | } | ||
| 250 | |||
| 251 | if (this.Messaging.EncounteredError) | ||
| 252 | { | ||
| 253 | return; | ||
| 254 | } | ||
| 255 | |||
| 256 | { | ||
| 257 | // TODO: correctly set SuppressAclReset bool at the end. | ||
| 258 | var layout = new Layout(this.ServiceProvider, bindResult.FileTransfers, bindResult.ContentFilePaths, this.ContentsFile, this.OutputsFile, this.BuiltOutputsFile, false); | ||
| 259 | layout.Execute(); | ||
| 260 | } | ||
| 228 | } | 261 | } |
| 229 | 262 | ||
| 230 | private IEnumerable<Intermediate> LoadLibraries(ITupleDefinitionCreator creator) | 263 | private IEnumerable<Intermediate> LoadLibraries(ITupleDefinitionCreator creator) |
| @@ -264,22 +297,5 @@ namespace WixToolset.Core | |||
| 264 | yield return localization; | 297 | yield return localization; |
| 265 | } | 298 | } |
| 266 | } | 299 | } |
| 267 | |||
| 268 | private WixVariableResolver CreateWixResolverWithVariables(Localizer localizer, Intermediate output) | ||
| 269 | { | ||
| 270 | var resolver = new WixVariableResolver(this.Messaging, localizer); | ||
| 271 | |||
| 272 | // Gather all the wix variables. | ||
| 273 | var wixVariables = output?.Sections.SelectMany(s => s.Tuples).OfType<WixVariableTuple>(); | ||
| 274 | if (wixVariables != null) | ||
| 275 | { | ||
| 276 | foreach (var wixVariableRow in wixVariables) | ||
| 277 | { | ||
| 278 | resolver.AddVariable(wixVariableRow); | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | return resolver; | ||
| 283 | } | ||
| 284 | } | 300 | } |
| 285 | } | 301 | } |
diff --git a/src/WixToolset.Core/CommandLine/CommandLine.cs b/src/WixToolset.Core/CommandLine/CommandLine.cs index 9db1b2f9..97f79755 100644 --- a/src/WixToolset.Core/CommandLine/CommandLine.cs +++ b/src/WixToolset.Core/CommandLine/CommandLine.cs | |||
| @@ -260,6 +260,10 @@ namespace WixToolset.Core | |||
| 260 | case "transform": | 260 | case "transform": |
| 261 | case ".mst": | 261 | case ".mst": |
| 262 | return OutputType.Transform; | 262 | return OutputType.Transform; |
| 263 | |||
| 264 | case "wixout": | ||
| 265 | case ".wixout": | ||
| 266 | return OutputType.Wixout; | ||
| 263 | } | 267 | } |
| 264 | 268 | ||
| 265 | return OutputType.Unknown; | 269 | return OutputType.Unknown; |
diff --git a/src/WixToolset.Core/Compiler.cs b/src/WixToolset.Core/Compiler.cs index 74ca86ac..2dd7da4d 100644 --- a/src/WixToolset.Core/Compiler.cs +++ b/src/WixToolset.Core/Compiler.cs | |||
| @@ -154,24 +154,40 @@ namespace WixToolset.Core | |||
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | // Resolve any Component Id placeholders compiled into the intermediate. | 156 | // Resolve any Component Id placeholders compiled into the intermediate. |
| 157 | if (0 < this.componentIdPlaceholdersResolver.VariableCount) | 157 | this.ResolveComponentIdPlaceholders(target); |
| 158 | } | ||
| 159 | finally | ||
| 160 | { | ||
| 161 | foreach (var extension in context.Extensions) | ||
| 158 | { | 162 | { |
| 159 | foreach (var section in target.Sections) | 163 | extension.PostCompile(target); |
| 164 | } | ||
| 165 | |||
| 166 | this.Core = null; | ||
| 167 | } | ||
| 168 | |||
| 169 | return this.Context.Messaging.EncounteredError ? null : target; | ||
| 170 | } | ||
| 171 | |||
| 172 | private void ResolveComponentIdPlaceholders(Intermediate target) | ||
| 173 | { | ||
| 174 | if (0 < this.componentIdPlaceholdersResolver.VariableCount) | ||
| 175 | { | ||
| 176 | foreach (var section in target.Sections) | ||
| 177 | { | ||
| 178 | foreach (var tuple in section.Tuples) | ||
| 160 | { | 179 | { |
| 161 | foreach (var tuple in section.Tuples) | 180 | foreach (var field in tuple.Fields) |
| 162 | { | 181 | { |
| 163 | foreach (var field in tuple.Fields) | 182 | if (field?.Type == IntermediateFieldType.String) |
| 164 | { | 183 | { |
| 165 | if (field != null && field.Type == IntermediateFieldType.String) | 184 | var data = field.AsString(); |
| 185 | if (!String.IsNullOrEmpty(data)) | ||
| 166 | { | 186 | { |
| 167 | var data = field.AsString(); | 187 | var resolved = this.componentIdPlaceholdersResolver.ResolveVariables(tuple.SourceLineNumbers, data, false, false); |
| 168 | if (!String.IsNullOrEmpty(data)) | 188 | if (resolved.UpdatedValue) |
| 169 | { | 189 | { |
| 170 | var resolved = this.componentIdPlaceholdersResolver.ResolveVariables(tuple.SourceLineNumbers, data, false, false, out var defaultIgnored, out var delayedIgnored); | 190 | field.Set(resolved.Value); |
| 171 | if (data != resolved) | ||
| 172 | { | ||
| 173 | field.Set(resolved); | ||
| 174 | } | ||
| 175 | } | 191 | } |
| 176 | } | 192 | } |
| 177 | } | 193 | } |
| @@ -179,17 +195,6 @@ namespace WixToolset.Core | |||
| 179 | } | 195 | } |
| 180 | } | 196 | } |
| 181 | } | 197 | } |
| 182 | finally | ||
| 183 | { | ||
| 184 | foreach (var extension in context.Extensions) | ||
| 185 | { | ||
| 186 | extension.PostCompile(target); | ||
| 187 | } | ||
| 188 | |||
| 189 | this.Core = null; | ||
| 190 | } | ||
| 191 | |||
| 192 | return this.Context.Messaging.EncounteredError ? null : target; | ||
| 193 | } | 198 | } |
| 194 | 199 | ||
| 195 | /// <summary> | 200 | /// <summary> |
| @@ -2422,7 +2427,7 @@ namespace WixToolset.Core | |||
| 2422 | { | 2427 | { |
| 2423 | if (isGeneratableGuidOk || keyFound && !String.IsNullOrEmpty(keyPath)) | 2428 | if (isGeneratableGuidOk || keyFound && !String.IsNullOrEmpty(keyPath)) |
| 2424 | { | 2429 | { |
| 2425 | this.componentIdPlaceholdersResolver.AddVariable(componentIdPlaceholder, keyPath); | 2430 | this.componentIdPlaceholdersResolver.AddVariable(componentIdPlaceholder, keyPath, false); |
| 2426 | 2431 | ||
| 2427 | id = new Identifier(keyPath, AccessModifier.Private); | 2432 | id = new Identifier(keyPath, AccessModifier.Private); |
| 2428 | } | 2433 | } |
diff --git a/src/WixToolset.Core/Layout.cs b/src/WixToolset.Core/Layout.cs new file mode 100644 index 00000000..d7322a12 --- /dev/null +++ b/src/WixToolset.Core/Layout.cs | |||
| @@ -0,0 +1,188 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | namespace WixToolset.Core | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using System.IO; | ||
| 8 | using System.Linq; | ||
| 9 | using WixToolset.Core.Bind; | ||
| 10 | using WixToolset.Data; | ||
| 11 | using WixToolset.Data.Bind; | ||
| 12 | using WixToolset.Data.Tuples; | ||
| 13 | using WixToolset.Extensibility; | ||
| 14 | using WixToolset.Extensibility.Services; | ||
| 15 | |||
| 16 | /// <summary> | ||
| 17 | /// Layout for the WiX toolset. | ||
| 18 | /// </summary> | ||
| 19 | public sealed class Layout | ||
| 20 | { | ||
| 21 | public Layout(IServiceProvider serviceProvider, IEnumerable<FileTransfer> fileTransfers, IEnumerable<string> contentFilePaths, string contentsFile, string outputsFile, string builtOutputsFile, bool suppressAclReset) | ||
| 22 | { | ||
| 23 | this.ServiceProvider = serviceProvider; | ||
| 24 | this.FileTransfers = fileTransfers; | ||
| 25 | this.ContentFilePaths = contentFilePaths; | ||
| 26 | this.ContentsFile = contentsFile; | ||
| 27 | this.OutputsFile = outputsFile; | ||
| 28 | this.BuiltOutputsFile = builtOutputsFile; | ||
| 29 | this.SuppressAclReset = suppressAclReset; | ||
| 30 | this.Messaging = this.ServiceProvider.GetService<IMessaging>(); | ||
| 31 | } | ||
| 32 | |||
| 33 | private IServiceProvider ServiceProvider { get; } | ||
| 34 | |||
| 35 | private IEnumerable<FileTransfer> FileTransfers { get; } | ||
| 36 | |||
| 37 | private IEnumerable<string> ContentFilePaths { get; } | ||
| 38 | |||
| 39 | private string ContentsFile { get; } | ||
| 40 | |||
| 41 | private string OutputsFile { get; } | ||
| 42 | |||
| 43 | private string BuiltOutputsFile { get; } | ||
| 44 | |||
| 45 | private bool SuppressAclReset { get; } | ||
| 46 | |||
| 47 | private IMessaging Messaging { get; } | ||
| 48 | |||
| 49 | public void Execute() | ||
| 50 | { | ||
| 51 | var extensionManager = this.ServiceProvider.GetService<IExtensionManager>(); | ||
| 52 | |||
| 53 | var context = this.ServiceProvider.GetService<ILayoutContext>(); | ||
| 54 | context.Messaging = this.Messaging; | ||
| 55 | context.Extensions = extensionManager.Create<ILayoutExtension>(); | ||
| 56 | context.FileSystemExtensions = extensionManager.Create<IFileSystemExtension>(); | ||
| 57 | context.FileTransfers = this.FileTransfers; | ||
| 58 | context.ContentFilePaths = this.ContentFilePaths; | ||
| 59 | context.ContentsFile = this.ContentsFile; | ||
| 60 | context.OutputPdbPath = this.OutputsFile; | ||
| 61 | context.BuiltOutputsFile = this.BuiltOutputsFile; | ||
| 62 | context.SuppressAclReset = this.SuppressAclReset; | ||
| 63 | |||
| 64 | // Pre-layout. | ||
| 65 | // | ||
| 66 | foreach (var extension in context.Extensions) | ||
| 67 | { | ||
| 68 | extension.PreLayout(context); | ||
| 69 | } | ||
| 70 | |||
| 71 | try | ||
| 72 | { | ||
| 73 | // Final step in binding that transfers (moves/copies) all files generated into the appropriate | ||
| 74 | // location in the source image. | ||
| 75 | if (context.FileTransfers?.Any() == true) | ||
| 76 | { | ||
| 77 | this.Messaging.Write(VerboseMessages.LayingOutMedia()); | ||
| 78 | |||
| 79 | var command = new TransferFilesCommand(context.Messaging, context.FileSystemExtensions, context.FileTransfers, context.SuppressAclReset); | ||
| 80 | command.Execute(); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | finally | ||
| 84 | { | ||
| 85 | if (!String.IsNullOrEmpty(context.ContentsFile) && context.ContentFilePaths != null) | ||
| 86 | { | ||
| 87 | this.CreateContentsFile(context.ContentsFile, context.ContentFilePaths); | ||
| 88 | } | ||
| 89 | |||
| 90 | if (!String.IsNullOrEmpty(context.OutputsFile) && context.FileTransfers != null) | ||
| 91 | { | ||
| 92 | this.CreateOutputsFile(context.OutputsFile, context.FileTransfers, context.OutputPdbPath); | ||
| 93 | } | ||
| 94 | |||
| 95 | if (!String.IsNullOrEmpty(context.BuiltOutputsFile) && context.FileTransfers != null) | ||
| 96 | { | ||
| 97 | this.CreateBuiltOutputsFile(context.BuiltOutputsFile, context.FileTransfers, context.OutputPdbPath); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | // Post-layout. | ||
| 102 | foreach (var extension in context.Extensions) | ||
| 103 | { | ||
| 104 | extension.PostLayout(); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | /// <summary> | ||
| 109 | /// Writes the paths to the content files to a text file. | ||
| 110 | /// </summary> | ||
| 111 | /// <param name="path">Path to write file.</param> | ||
| 112 | /// <param name="contentFilePaths">Collection of paths to content files that will be written to file.</param> | ||
| 113 | private void CreateContentsFile(string path, IEnumerable<string> contentFilePaths) | ||
| 114 | { | ||
| 115 | var directory = Path.GetDirectoryName(path); | ||
| 116 | Directory.CreateDirectory(directory); | ||
| 117 | |||
| 118 | using (var contents = new StreamWriter(path, false)) | ||
| 119 | { | ||
| 120 | foreach (string contentPath in contentFilePaths) | ||
| 121 | { | ||
| 122 | contents.WriteLine(contentPath); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | /// <summary> | ||
| 128 | /// Writes the paths to the output files to a text file. | ||
| 129 | /// </summary> | ||
| 130 | /// <param name="path">Path to write file.</param> | ||
| 131 | /// <param name="fileTransfers">Collection of files that were transferred to the output directory.</param> | ||
| 132 | /// <param name="pdbPath">Optional path to created .wixpdb.</param> | ||
| 133 | private void CreateOutputsFile(string path, IEnumerable<FileTransfer> fileTransfers, string pdbPath) | ||
| 134 | { | ||
| 135 | var directory = Path.GetDirectoryName(path); | ||
| 136 | Directory.CreateDirectory(directory); | ||
| 137 | |||
| 138 | using (var outputs = new StreamWriter(path, false)) | ||
| 139 | { | ||
| 140 | foreach (FileTransfer fileTransfer in fileTransfers) | ||
| 141 | { | ||
| 142 | // Don't list files where the source is the same as the destination since | ||
| 143 | // that might be the only place the file exists. The outputs file is often | ||
| 144 | // used to delete stuff and losing the original source would be bad. | ||
| 145 | if (!fileTransfer.Redundant) | ||
| 146 | { | ||
| 147 | outputs.WriteLine(fileTransfer.Destination); | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | if (!String.IsNullOrEmpty(pdbPath)) | ||
| 152 | { | ||
| 153 | outputs.WriteLine(Path.GetFullPath(pdbPath)); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | /// <summary> | ||
| 159 | /// Writes the paths to the built output files to a text file. | ||
| 160 | /// </summary> | ||
| 161 | /// <param name="path">Path to write file.</param> | ||
| 162 | /// <param name="fileTransfers">Collection of files that were transferred to the output directory.</param> | ||
| 163 | /// <param name="pdbPath">Optional path to created .wixpdb.</param> | ||
| 164 | private void CreateBuiltOutputsFile(string path, IEnumerable<FileTransfer> fileTransfers, string pdbPath) | ||
| 165 | { | ||
| 166 | var directory = Path.GetDirectoryName(path); | ||
| 167 | Directory.CreateDirectory(directory); | ||
| 168 | |||
| 169 | using (var outputs = new StreamWriter(path, false)) | ||
| 170 | { | ||
| 171 | foreach (FileTransfer fileTransfer in fileTransfers) | ||
| 172 | { | ||
| 173 | // Only write the built file transfers. Also, skip redundant | ||
| 174 | // files for the same reason spelled out in this.CreateOutputsFile(). | ||
| 175 | if (fileTransfer.Built && !fileTransfer.Redundant) | ||
| 176 | { | ||
| 177 | outputs.WriteLine(fileTransfer.Destination); | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | if (!String.IsNullOrEmpty(pdbPath)) | ||
| 182 | { | ||
| 183 | outputs.WriteLine(Path.GetFullPath(pdbPath)); | ||
| 184 | } | ||
| 185 | } | ||
| 186 | } | ||
| 187 | } | ||
| 188 | } | ||
diff --git a/src/WixToolset.Core/LayoutContext.cs b/src/WixToolset.Core/LayoutContext.cs new file mode 100644 index 00000000..24f171a9 --- /dev/null +++ b/src/WixToolset.Core/LayoutContext.cs | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | namespace WixToolset.Core | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using WixToolset.Data.Bind; | ||
| 8 | using WixToolset.Extensibility; | ||
| 9 | using WixToolset.Extensibility.Services; | ||
| 10 | |||
| 11 | public class LayoutContext : ILayoutContext | ||
| 12 | { | ||
| 13 | internal LayoutContext(IServiceProvider serviceProvider) | ||
| 14 | { | ||
| 15 | this.ServiceProvider = serviceProvider; | ||
| 16 | } | ||
| 17 | |||
| 18 | public IServiceProvider ServiceProvider { get; } | ||
| 19 | |||
| 20 | public IMessaging Messaging { get; set; } | ||
| 21 | |||
| 22 | public IEnumerable<ILayoutExtension> Extensions { get; set; } | ||
| 23 | |||
| 24 | public IEnumerable<IFileSystemExtension> FileSystemExtensions { get; set; } | ||
| 25 | |||
| 26 | public IEnumerable<FileTransfer> FileTransfers { get; set; } | ||
| 27 | |||
| 28 | public IEnumerable<string> ContentFilePaths { get; set; } | ||
| 29 | |||
| 30 | public string OutputPdbPath { get; set; } | ||
| 31 | |||
| 32 | public string ContentsFile { get; set; } | ||
| 33 | |||
| 34 | public string OutputsFile { get; set; } | ||
| 35 | |||
| 36 | public string BuiltOutputsFile { get; set; } | ||
| 37 | |||
| 38 | public bool SuppressAclReset { get; set; } | ||
| 39 | } | ||
| 40 | } | ||
diff --git a/src/WixToolset.Core/Librarian.cs b/src/WixToolset.Core/Librarian.cs index a64d77dd..2efb0f9b 100644 --- a/src/WixToolset.Core/Librarian.cs +++ b/src/WixToolset.Core/Librarian.cs | |||
| @@ -38,11 +38,14 @@ namespace WixToolset.Core | |||
| 38 | 38 | ||
| 39 | var sections = this.Context.Intermediates.SelectMany(i => i.Sections).ToList(); | 39 | var sections = this.Context.Intermediates.SelectMany(i => i.Sections).ToList(); |
| 40 | 40 | ||
| 41 | var fileResolver = new FileResolver(this.Context.BindPaths, this.Context.Extensions); | 41 | var embedFilePaths = this.ResolveFilePathsToEmbed(sections); |
| 42 | 42 | ||
| 43 | var embedFilePaths = ResolveFilePathsToEmbed(sections, fileResolver); | 43 | var localizationsByCulture = this.CollateLocalizations(this.Context.Localizations); |
| 44 | 44 | ||
| 45 | var localizationsByCulture = CollateLocalizations(this.Context.Localizations); | 45 | if (this.Context.Messaging.EncounteredError) |
| 46 | { | ||
| 47 | return null; | ||
| 48 | } | ||
| 46 | 49 | ||
| 47 | foreach (var section in sections) | 50 | foreach (var section in sections) |
| 48 | { | 51 | { |
| @@ -83,7 +86,7 @@ namespace WixToolset.Core | |||
| 83 | return (this.Context.Messaging.EncounteredError ? null : library); | 86 | return (this.Context.Messaging.EncounteredError ? null : library); |
| 84 | } | 87 | } |
| 85 | 88 | ||
| 86 | private static Dictionary<string, Localization> CollateLocalizations(IEnumerable<Localization> localizations) | 89 | private Dictionary<string, Localization> CollateLocalizations(IEnumerable<Localization> localizations) |
| 87 | { | 90 | { |
| 88 | var localizationsByCulture = new Dictionary<string, Localization>(StringComparer.OrdinalIgnoreCase); | 91 | var localizationsByCulture = new Dictionary<string, Localization>(StringComparer.OrdinalIgnoreCase); |
| 89 | 92 | ||
| @@ -91,7 +94,14 @@ namespace WixToolset.Core | |||
| 91 | { | 94 | { |
| 92 | if (localizationsByCulture.TryGetValue(localization.Culture, out var existingCulture)) | 95 | if (localizationsByCulture.TryGetValue(localization.Culture, out var existingCulture)) |
| 93 | { | 96 | { |
| 94 | existingCulture.Merge(localization); | 97 | try |
| 98 | { | ||
| 99 | existingCulture.Merge(localization); | ||
| 100 | } | ||
| 101 | catch (WixException e) | ||
| 102 | { | ||
| 103 | this.Context.Messaging.Write(e.Error); | ||
| 104 | } | ||
| 95 | } | 105 | } |
| 96 | else | 106 | else |
| 97 | { | 107 | { |
| @@ -102,13 +112,17 @@ namespace WixToolset.Core | |||
| 102 | return localizationsByCulture; | 112 | return localizationsByCulture; |
| 103 | } | 113 | } |
| 104 | 114 | ||
| 105 | private List<string> ResolveFilePathsToEmbed(IEnumerable<IntermediateSection> sections, FileResolver fileResolver) | 115 | private List<string> ResolveFilePathsToEmbed(IEnumerable<IntermediateSection> sections) |
| 106 | { | 116 | { |
| 107 | var embedFilePaths = new List<string>(); | 117 | var embedFilePaths = new List<string>(); |
| 108 | 118 | ||
| 109 | // Resolve paths to files that are to be embedded in the library. | 119 | // Resolve paths to files that are to be embedded in the library. |
| 110 | if (this.Context.BindFiles) | 120 | if (this.Context.BindFiles) |
| 111 | { | 121 | { |
| 122 | var variableResolver = new WixVariableResolver(this.Context.Messaging); | ||
| 123 | |||
| 124 | var fileResolver = new FileResolver(this.Context.BindPaths, this.Context.Extensions); | ||
| 125 | |||
| 112 | foreach (var tuple in sections.SelectMany(s => s.Tuples)) | 126 | foreach (var tuple in sections.SelectMany(s => s.Tuples)) |
| 113 | { | 127 | { |
| 114 | foreach (var field in tuple.Fields.Where(f => f.Type == IntermediateFieldType.Path)) | 128 | foreach (var field in tuple.Fields.Where(f => f.Type == IntermediateFieldType.Path)) |
| @@ -117,9 +131,9 @@ namespace WixToolset.Core | |||
| 117 | 131 | ||
| 118 | if (pathField != null) | 132 | if (pathField != null) |
| 119 | { | 133 | { |
| 120 | var resolvedPath = this.Context.WixVariableResolver.ResolveVariables(tuple.SourceLineNumbers, pathField.Path, false); | 134 | var resolution = variableResolver.ResolveVariables(tuple.SourceLineNumbers, pathField.Path, false); |
| 121 | 135 | ||
| 122 | var file = fileResolver.Resolve(tuple.SourceLineNumbers, tuple.Definition.Name, resolvedPath); | 136 | var file = fileResolver.Resolve(tuple.SourceLineNumbers, tuple.Definition, resolution.Value); |
| 123 | 137 | ||
| 124 | if (!String.IsNullOrEmpty(file)) | 138 | if (!String.IsNullOrEmpty(file)) |
| 125 | { | 139 | { |
diff --git a/src/WixToolset.Core/LibraryContext.cs b/src/WixToolset.Core/LibraryContext.cs index c6278482..c1aec5ce 100644 --- a/src/WixToolset.Core/LibraryContext.cs +++ b/src/WixToolset.Core/LibraryContext.cs | |||
| @@ -25,7 +25,5 @@ namespace WixToolset.Core | |||
| 25 | public IEnumerable<Localization> Localizations { get; set; } | 25 | public IEnumerable<Localization> Localizations { get; set; } |
| 26 | 26 | ||
| 27 | public IEnumerable<Intermediate> Intermediates { get; set; } | 27 | public IEnumerable<Intermediate> Intermediates { get; set; } |
| 28 | |||
| 29 | public IBindVariableResolver WixVariableResolver { get; set; } | ||
| 30 | } | 28 | } |
| 31 | } | 29 | } |
diff --git a/src/WixToolset.Core/Linker.cs b/src/WixToolset.Core/Linker.cs index d980d79f..93f50efa 100644 --- a/src/WixToolset.Core/Linker.cs +++ b/src/WixToolset.Core/Linker.cs | |||
| @@ -8,11 +8,11 @@ namespace WixToolset.Core | |||
| 8 | using System.Diagnostics; | 8 | using System.Diagnostics; |
| 9 | using System.Globalization; | 9 | using System.Globalization; |
| 10 | using System.Linq; | 10 | using System.Linq; |
| 11 | using WixToolset.Data; | ||
| 12 | using WixToolset.Link; | ||
| 13 | using WixToolset.Core.Link; | 11 | using WixToolset.Core.Link; |
| 12 | using WixToolset.Data; | ||
| 14 | using WixToolset.Data.Tuples; | 13 | using WixToolset.Data.Tuples; |
| 15 | using WixToolset.Extensibility.Services; | 14 | using WixToolset.Extensibility; |
| 15 | using WixToolset.Link; | ||
| 16 | 16 | ||
| 17 | /// <summary> | 17 | /// <summary> |
| 18 | /// Linker core of the WiX toolset. | 18 | /// Linker core of the WiX toolset. |
diff --git a/src/WixToolset.Core/PreprocessContext.cs b/src/WixToolset.Core/PreprocessContext.cs index cb29d1ff..a6085b81 100644 --- a/src/WixToolset.Core/PreprocessContext.cs +++ b/src/WixToolset.Core/PreprocessContext.cs | |||
| @@ -8,9 +8,6 @@ namespace WixToolset.Core | |||
| 8 | using WixToolset.Extensibility; | 8 | using WixToolset.Extensibility; |
| 9 | using WixToolset.Extensibility.Services; | 9 | using WixToolset.Extensibility.Services; |
| 10 | 10 | ||
| 11 | /// <summary> | ||
| 12 | /// The preprocessor core. | ||
| 13 | /// </summary> | ||
| 14 | internal class PreprocessContext : IPreprocessContext | 11 | internal class PreprocessContext : IPreprocessContext |
| 15 | { | 12 | { |
| 16 | internal PreprocessContext(IServiceProvider serviceProvider) | 13 | internal PreprocessContext(IServiceProvider serviceProvider) |
diff --git a/src/WixToolset.Core/ResolveContext.cs b/src/WixToolset.Core/ResolveContext.cs new file mode 100644 index 00000000..6d7b9df1 --- /dev/null +++ b/src/WixToolset.Core/ResolveContext.cs | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | namespace WixToolset.Core | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using WixToolset.Data; | ||
| 8 | using WixToolset.Extensibility; | ||
| 9 | using WixToolset.Extensibility.Services; | ||
| 10 | |||
| 11 | public class ResolveContext : IResolveContext | ||
| 12 | { | ||
| 13 | internal ResolveContext(IServiceProvider serviceProvider) | ||
| 14 | { | ||
| 15 | this.ServiceProvider = serviceProvider; | ||
| 16 | } | ||
| 17 | |||
| 18 | public IServiceProvider ServiceProvider { get; } | ||
| 19 | |||
| 20 | public IMessaging Messaging { get; set; } | ||
| 21 | |||
| 22 | public IEnumerable<BindPath> BindPaths { get; set; } | ||
| 23 | |||
| 24 | public IEnumerable<IResolverExtension> Extensions { get; set; } | ||
| 25 | |||
| 26 | public string IntermediateFolder { get; set; } | ||
| 27 | |||
| 28 | public Intermediate IntermediateRepresentation { get; set; } | ||
| 29 | |||
| 30 | public IBindVariableResolver WixVariableResolver { get; set; } | ||
| 31 | } | ||
| 32 | } | ||
diff --git a/src/WixToolset.Core/Resolver.cs b/src/WixToolset.Core/Resolver.cs new file mode 100644 index 00000000..b0d3a189 --- /dev/null +++ b/src/WixToolset.Core/Resolver.cs | |||
| @@ -0,0 +1,234 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | namespace WixToolset.Core | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using System.Linq; | ||
| 8 | using WixToolset.Core.Bind; | ||
| 9 | using WixToolset.Data; | ||
| 10 | using WixToolset.Data.Tuples; | ||
| 11 | using WixToolset.Extensibility; | ||
| 12 | using WixToolset.Extensibility.Services; | ||
| 13 | |||
| 14 | /// <summary> | ||
| 15 | /// Resolver for the WiX toolset. | ||
| 16 | /// </summary> | ||
| 17 | public sealed class Resolver | ||
| 18 | { | ||
| 19 | public Resolver(IServiceProvider serviceProvider, IEnumerable<BindPath> bindPaths, Intermediate intermediateRepresentation, string intermediateFolder, IEnumerable<Localization> localizations) | ||
| 20 | { | ||
| 21 | this.ServiceProvider = serviceProvider; | ||
| 22 | this.BindPaths = bindPaths; | ||
| 23 | this.IntermediateRepresentation = intermediateRepresentation; | ||
| 24 | this.IntermediateFolder = intermediateFolder; | ||
| 25 | this.Localizations = localizations; | ||
| 26 | |||
| 27 | this.Messaging = this.ServiceProvider.GetService<IMessaging>(); | ||
| 28 | } | ||
| 29 | |||
| 30 | private IServiceProvider ServiceProvider { get; } | ||
| 31 | |||
| 32 | private IEnumerable<BindPath> BindPaths { get; } | ||
| 33 | |||
| 34 | private Intermediate IntermediateRepresentation { get; } | ||
| 35 | |||
| 36 | private string IntermediateFolder { get; } | ||
| 37 | |||
| 38 | private IEnumerable<Localization> Localizations { get; } | ||
| 39 | |||
| 40 | private IMessaging Messaging { get; } | ||
| 41 | |||
| 42 | public ResolveResult Execute() | ||
| 43 | { | ||
| 44 | var localizer = new Localizer(this.Messaging, this.Localizations); | ||
| 45 | |||
| 46 | var variableResolver = new WixVariableResolver(this.Messaging, localizer); | ||
| 47 | |||
| 48 | var context = this.ServiceProvider.GetService<IResolveContext>(); | ||
| 49 | context.Messaging = this.Messaging; | ||
| 50 | context.BindPaths = this.BindPaths; | ||
| 51 | context.Extensions = this.ServiceProvider.GetService<IExtensionManager>().Create<IResolverExtension>(); | ||
| 52 | context.IntermediateFolder = this.IntermediateFolder; | ||
| 53 | context.IntermediateRepresentation = this.IntermediateRepresentation; | ||
| 54 | context.WixVariableResolver = this.PopulateVariableResolver(variableResolver); | ||
| 55 | |||
| 56 | // Preresolve. | ||
| 57 | // | ||
| 58 | foreach (IResolverExtension extension in context.Extensions) | ||
| 59 | { | ||
| 60 | extension.PreResolve(context); | ||
| 61 | } | ||
| 62 | |||
| 63 | // Resolve. | ||
| 64 | // | ||
| 65 | this.LocalizeUI(context); | ||
| 66 | |||
| 67 | var resolveResult = this.Resolve(localizer.Codepage, context); | ||
| 68 | |||
| 69 | if (resolveResult != null) | ||
| 70 | { | ||
| 71 | // Postresolve. | ||
| 72 | // | ||
| 73 | foreach (IResolverExtension extension in context.Extensions) | ||
| 74 | { | ||
| 75 | extension.PostResolve(resolveResult); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | return resolveResult; | ||
| 80 | } | ||
| 81 | |||
| 82 | private ResolveResult Resolve(int codepage, IResolveContext context) | ||
| 83 | { | ||
| 84 | var buildingPatch = context.IntermediateRepresentation.Sections.Any(s => s.Type == SectionType.Patch); | ||
| 85 | |||
| 86 | var filesWithEmbeddedFiles = new ExtractEmbeddedFiles(); | ||
| 87 | |||
| 88 | IEnumerable<DelayedField> delayedFields; | ||
| 89 | { | ||
| 90 | var command = new ResolveFieldsCommand(); | ||
| 91 | command.Messaging = context.Messaging; | ||
| 92 | command.BuildingPatch = buildingPatch; | ||
| 93 | command.BindVariableResolver = context.WixVariableResolver; | ||
| 94 | command.BindPaths = context.BindPaths; | ||
| 95 | command.Extensions = context.Extensions; | ||
| 96 | command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles; | ||
| 97 | command.IntermediateFolder = context.IntermediateFolder; | ||
| 98 | command.Intermediate = context.IntermediateRepresentation; | ||
| 99 | command.SupportDelayedResolution = true; | ||
| 100 | command.Execute(); | ||
| 101 | |||
| 102 | delayedFields = command.DelayedFields; | ||
| 103 | } | ||
| 104 | |||
| 105 | #if REVISIT_FOR_PATCHING | ||
| 106 | if (context.IntermediateRepresentation.SubStorages != null) | ||
| 107 | { | ||
| 108 | foreach (SubStorage transform in context.IntermediateRepresentation.SubStorages) | ||
| 109 | { | ||
| 110 | var command = new ResolveFieldsCommand(); | ||
| 111 | command.BuildingPatch = buildingPatch; | ||
| 112 | command.BindVariableResolver = context.WixVariableResolver; | ||
| 113 | command.BindPaths = context.BindPaths; | ||
| 114 | command.Extensions = context.Extensions; | ||
| 115 | command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles; | ||
| 116 | command.IntermediateFolder = context.IntermediateFolder; | ||
| 117 | command.Intermediate = context.IntermediateRepresentation; | ||
| 118 | command.SupportDelayedResolution = false; | ||
| 119 | command.Execute(); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | #endif | ||
| 123 | |||
| 124 | var expectedEmbeddedFiles = filesWithEmbeddedFiles.GetExpectedEmbeddedFiles(); | ||
| 125 | |||
| 126 | return new ResolveResult | ||
| 127 | { | ||
| 128 | Codepage = codepage, | ||
| 129 | ExpectedEmbeddedFiles = expectedEmbeddedFiles, | ||
| 130 | DelayedFields = delayedFields, | ||
| 131 | IntermediateRepresentation = context.IntermediateRepresentation | ||
| 132 | }; | ||
| 133 | } | ||
| 134 | |||
| 135 | /// <summary> | ||
| 136 | /// Localize dialogs and controls. | ||
| 137 | /// </summary> | ||
| 138 | private void LocalizeUI(IResolveContext context) | ||
| 139 | { | ||
| 140 | foreach (var section in context.IntermediateRepresentation.Sections) | ||
| 141 | { | ||
| 142 | foreach (var row in section.Tuples.OfType<DialogTuple>()) | ||
| 143 | { | ||
| 144 | string dialog = row.Dialog; | ||
| 145 | |||
| 146 | if (context.WixVariableResolver.TryGetLocalizedControl(dialog, null, out LocalizedControl localizedControl)) | ||
| 147 | { | ||
| 148 | if (CompilerConstants.IntegerNotSet != localizedControl.X) | ||
| 149 | { | ||
| 150 | row.HCentering = localizedControl.X; | ||
| 151 | } | ||
| 152 | |||
| 153 | if (CompilerConstants.IntegerNotSet != localizedControl.Y) | ||
| 154 | { | ||
| 155 | row.VCentering = localizedControl.Y; | ||
| 156 | } | ||
| 157 | |||
| 158 | if (CompilerConstants.IntegerNotSet != localizedControl.Width) | ||
| 159 | { | ||
| 160 | row.Width = localizedControl.Width; | ||
| 161 | } | ||
| 162 | |||
| 163 | if (CompilerConstants.IntegerNotSet != localizedControl.Height) | ||
| 164 | { | ||
| 165 | row.Height = localizedControl.Height; | ||
| 166 | } | ||
| 167 | |||
| 168 | row.Attributes = row.Attributes | localizedControl.Attributes; | ||
| 169 | |||
| 170 | if (!String.IsNullOrEmpty(localizedControl.Text)) | ||
| 171 | { | ||
| 172 | row.Title = localizedControl.Text; | ||
| 173 | } | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | foreach (var row in section.Tuples.OfType<ControlTuple>()) | ||
| 178 | { | ||
| 179 | string dialog = row.Dialog_; | ||
| 180 | string control = row.Control; | ||
| 181 | |||
| 182 | if (context.WixVariableResolver.TryGetLocalizedControl(dialog, control, out LocalizedControl localizedControl)) | ||
| 183 | { | ||
| 184 | if (CompilerConstants.IntegerNotSet != localizedControl.X) | ||
| 185 | { | ||
| 186 | row.X = localizedControl.X; | ||
| 187 | } | ||
| 188 | |||
| 189 | if (CompilerConstants.IntegerNotSet != localizedControl.Y) | ||
| 190 | { | ||
| 191 | row.Y = localizedControl.Y; | ||
| 192 | } | ||
| 193 | |||
| 194 | if (CompilerConstants.IntegerNotSet != localizedControl.Width) | ||
| 195 | { | ||
| 196 | row.Width = localizedControl.Width; | ||
| 197 | } | ||
| 198 | |||
| 199 | if (CompilerConstants.IntegerNotSet != localizedControl.Height) | ||
| 200 | { | ||
| 201 | row.Height = localizedControl.Height; | ||
| 202 | } | ||
| 203 | |||
| 204 | row.Attributes = row.Attributes | localizedControl.Attributes; | ||
| 205 | |||
| 206 | if (!String.IsNullOrEmpty(localizedControl.Text)) | ||
| 207 | { | ||
| 208 | row.Text = localizedControl.Text; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | } | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | private WixVariableResolver PopulateVariableResolver(WixVariableResolver resolver) | ||
| 216 | { | ||
| 217 | // Gather all the wix variables. | ||
| 218 | var wixVariableTuples = this.IntermediateRepresentation.Sections.SelectMany(s => s.Tuples).OfType<WixVariableTuple>(); | ||
| 219 | foreach (var tuple in wixVariableTuples) | ||
| 220 | { | ||
| 221 | try | ||
| 222 | { | ||
| 223 | resolver.AddVariable(tuple.WixVariable, tuple.Value, tuple.Overridable); | ||
| 224 | } | ||
| 225 | catch (ArgumentException) | ||
| 226 | { | ||
| 227 | this.Messaging.Write(ErrorMessages.WixVariableCollision(tuple.SourceLineNumbers, tuple.WixVariable)); | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | return resolver; | ||
| 232 | } | ||
| 233 | } | ||
| 234 | } | ||
diff --git a/src/WixToolset.Core/WixToolsetServiceProvider.cs b/src/WixToolset.Core/WixToolsetServiceProvider.cs index 995daa89..74b312c6 100644 --- a/src/WixToolset.Core/WixToolsetServiceProvider.cs +++ b/src/WixToolset.Core/WixToolsetServiceProvider.cs | |||
| @@ -42,6 +42,16 @@ namespace WixToolset.Core | |||
| 42 | return new BindContext(this); | 42 | return new BindContext(this); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | if (serviceType == typeof(ILayoutContext)) | ||
| 46 | { | ||
| 47 | return new LayoutContext(this); | ||
| 48 | } | ||
| 49 | |||
| 50 | if (serviceType == typeof(IResolveContext)) | ||
| 51 | { | ||
| 52 | return new ResolveContext(this); | ||
| 53 | } | ||
| 54 | |||
| 45 | if (serviceType == typeof(IInscribeContext)) | 55 | if (serviceType == typeof(IInscribeContext)) |
| 46 | { | 56 | { |
| 47 | return new InscribeContext(this); | 57 | return new InscribeContext(this); |
diff --git a/src/WixToolset.Core/WixVariableResolver.cs b/src/WixToolset.Core/WixVariableResolver.cs index f8bccef0..7339840e 100644 --- a/src/WixToolset.Core/WixVariableResolver.cs +++ b/src/WixToolset.Core/WixVariableResolver.cs | |||
| @@ -9,8 +9,6 @@ namespace WixToolset.Core | |||
| 9 | using System.Text; | 9 | using System.Text; |
| 10 | using System.Text.RegularExpressions; | 10 | using System.Text.RegularExpressions; |
| 11 | using WixToolset.Data; | 11 | using WixToolset.Data; |
| 12 | using WixToolset.Data.Tuples; | ||
| 13 | using WixToolset.Extensibility; | ||
| 14 | using WixToolset.Extensibility.Services; | 12 | using WixToolset.Extensibility.Services; |
| 15 | 13 | ||
| 16 | /// <summary> | 14 | /// <summary> |
| @@ -37,14 +35,15 @@ namespace WixToolset.Core | |||
| 37 | /// <summary> | 35 | /// <summary> |
| 38 | /// Gets the count of variables added to the resolver. | 36 | /// Gets the count of variables added to the resolver. |
| 39 | /// </summary> | 37 | /// </summary> |
| 40 | public int VariableCount => this.wixVariables.Count; | 38 | public int VariableCount => this.wixVariables.Count; |
| 41 | 39 | ||
| 42 | /// <summary> | 40 | /// <summary> |
| 43 | /// Add a variable. | 41 | /// Add a variable. |
| 44 | /// </summary> | 42 | /// </summary> |
| 45 | /// <param name="name">The name of the variable.</param> | 43 | /// <param name="name">The name of the variable.</param> |
| 46 | /// <param name="value">The value of the variable.</param> | 44 | /// <param name="value">The value of the variable.</param> |
| 47 | public void AddVariable(string name, string value) | 45 | /// <param name="overridable">Indicates whether the variable can be overridden by an existing variable.</param> |
| 46 | public void AddVariable(string name, string value, bool overridable) | ||
| 48 | { | 47 | { |
| 49 | try | 48 | try |
| 50 | { | 49 | { |
| @@ -52,25 +51,9 @@ namespace WixToolset.Core | |||
| 52 | } | 51 | } |
| 53 | catch (ArgumentException) | 52 | catch (ArgumentException) |
| 54 | { | 53 | { |
| 55 | this.Messaging.Write(ErrorMessages.WixVariableCollision(null, name)); | 54 | if (!overridable) |
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | /// <summary> | ||
| 60 | /// Add a variable. | ||
| 61 | /// </summary> | ||
| 62 | /// <param name="wixVariableRow">The WixVariableRow to add.</param> | ||
| 63 | public void AddVariable(WixVariableTuple wixVariableRow) | ||
| 64 | { | ||
| 65 | try | ||
| 66 | { | ||
| 67 | this.wixVariables.Add(wixVariableRow.WixVariable, wixVariableRow.Value); | ||
| 68 | } | ||
| 69 | catch (ArgumentException) | ||
| 70 | { | ||
| 71 | if (!wixVariableRow.Overridable) // collision | ||
| 72 | { | 55 | { |
| 73 | this.Messaging.Write(ErrorMessages.WixVariableCollision(wixVariableRow.SourceLineNumbers, wixVariableRow.WixVariable)); | 56 | throw; |
| 74 | } | 57 | } |
| 75 | } | 58 | } |
| 76 | } | 59 | } |
| @@ -82,37 +65,9 @@ namespace WixToolset.Core | |||
| 82 | /// <param name="value">The value to resolve.</param> | 65 | /// <param name="value">The value to resolve.</param> |
| 83 | /// <param name="localizationOnly">true to only resolve localization variables; false otherwise.</param> | 66 | /// <param name="localizationOnly">true to only resolve localization variables; false otherwise.</param> |
| 84 | /// <returns>The resolved value.</returns> | 67 | /// <returns>The resolved value.</returns> |
| 85 | public string ResolveVariables(SourceLineNumber sourceLineNumbers, string value, bool localizationOnly) | 68 | public BindVariableResolution ResolveVariables(SourceLineNumber sourceLineNumbers, string value, bool localizationOnly) |
| 86 | { | 69 | { |
| 87 | return this.ResolveVariables(sourceLineNumbers, value, localizationOnly, out var defaultIgnored, out var delayedIgnored); | 70 | return this.ResolveVariables(sourceLineNumbers, value, localizationOnly, true); |
| 88 | } | ||
| 89 | |||
| 90 | /// <summary> | ||
| 91 | /// Resolve the wix variables in a value. | ||
| 92 | /// </summary> | ||
| 93 | /// <param name="sourceLineNumbers">The source line information for the value.</param> | ||
| 94 | /// <param name="value">The value to resolve.</param> | ||
| 95 | /// <param name="localizationOnly">true to only resolve localization variables; false otherwise.</param> | ||
| 96 | /// <param name="isDefault">true if the resolved value was the default.</param> | ||
| 97 | /// <returns>The resolved value.</returns> | ||
| 98 | public string ResolveVariables(SourceLineNumber sourceLineNumbers, string value, bool localizationOnly, out bool isDefault) | ||
| 99 | { | ||
| 100 | return this.ResolveVariables(sourceLineNumbers, value, localizationOnly, out isDefault, out var ignored); | ||
| 101 | } | ||
| 102 | |||
| 103 | /// <summary> | ||
| 104 | /// Resolve the wix variables in a value. | ||
| 105 | /// </summary> | ||
| 106 | /// <param name="sourceLineNumbers">The source line information for the value.</param> | ||
| 107 | /// <param name="value">The value to resolve.</param> | ||
| 108 | /// <param name="localizationOnly">true to only resolve localization variables; false otherwise.</param> | ||
| 109 | /// <param name="errorOnUnknown">true if unknown variables should throw errors.</param> | ||
| 110 | /// <param name="isDefault">true if the resolved value was the default.</param> | ||
| 111 | /// <param name="delayedResolve">true if the value has variables that cannot yet be resolved.</param> | ||
| 112 | /// <returns>The resolved value.</returns> | ||
| 113 | public string ResolveVariables(SourceLineNumber sourceLineNumbers, string value, bool localizationOnly, out bool isDefault, out bool delayedResolve) | ||
| 114 | { | ||
| 115 | return this.ResolveVariables(sourceLineNumbers, value, localizationOnly, true, out isDefault, out delayedResolve); | ||
| 116 | } | 71 | } |
| 117 | 72 | ||
| 118 | /// <summary> | 73 | /// <summary> |
| @@ -125,13 +80,12 @@ namespace WixToolset.Core | |||
| 125 | /// <param name="isDefault">true if the resolved value was the default.</param> | 80 | /// <param name="isDefault">true if the resolved value was the default.</param> |
| 126 | /// <param name="delayedResolve">true if the value has variables that cannot yet be resolved.</param> | 81 | /// <param name="delayedResolve">true if the value has variables that cannot yet be resolved.</param> |
| 127 | /// <returns>The resolved value.</returns> | 82 | /// <returns>The resolved value.</returns> |
| 128 | public string ResolveVariables(SourceLineNumber sourceLineNumbers, string value, bool localizationOnly, bool errorOnUnknown, out bool isDefault, out bool delayedResolve) | 83 | internal BindVariableResolution ResolveVariables(SourceLineNumber sourceLineNumbers, string value, bool localizationOnly, bool errorOnUnknown) |
| 129 | { | 84 | { |
| 130 | MatchCollection matches = Common.WixVariableRegex.Matches(value); | 85 | MatchCollection matches = Common.WixVariableRegex.Matches(value); |
| 131 | 86 | ||
| 132 | // the value is the default unless its substituted further down | 87 | // the value is the default unless its substituted further down |
| 133 | isDefault = true; | 88 | var result = new BindVariableResolution { IsDefault = true, Value = value }; |
| 134 | delayedResolve = false; | ||
| 135 | 89 | ||
| 136 | if (0 < matches.Count) | 90 | if (0 < matches.Count) |
| 137 | { | 91 | { |
| @@ -172,6 +126,8 @@ namespace WixToolset.Core | |||
| 172 | if (!localizationOnly) | 126 | if (!localizationOnly) |
| 173 | { | 127 | { |
| 174 | sb.Remove(matches[i].Index - 1, 1); | 128 | sb.Remove(matches[i].Index - 1, 1); |
| 129 | |||
| 130 | result.UpdatedValue = true; | ||
| 175 | } | 131 | } |
| 176 | } | 132 | } |
| 177 | else | 133 | else |
| @@ -200,7 +156,7 @@ namespace WixToolset.Core | |||
| 200 | if (this.wixVariables.TryGetValue(variableId, out resolvedValue)) | 156 | if (this.wixVariables.TryGetValue(variableId, out resolvedValue)) |
| 201 | { | 157 | { |
| 202 | resolvedValue = resolvedValue ?? String.Empty; | 158 | resolvedValue = resolvedValue ?? String.Empty; |
| 203 | isDefault = false; | 159 | result.IsDefault = false; |
| 204 | } | 160 | } |
| 205 | else if (null != variableDefaultValue) // default the resolved value to the inline value if one was specified | 161 | else if (null != variableDefaultValue) // default the resolved value to the inline value if one was specified |
| 206 | { | 162 | { |
| @@ -212,16 +168,17 @@ namespace WixToolset.Core | |||
| 212 | if ("bind" == variableNamespace) | 168 | if ("bind" == variableNamespace) |
| 213 | { | 169 | { |
| 214 | // can't resolve these yet, but keep track of where we find them so they can be resolved later with less effort | 170 | // can't resolve these yet, but keep track of where we find them so they can be resolved later with less effort |
| 215 | delayedResolve = true; | 171 | result.DelayedResolve = true; |
| 216 | } | 172 | } |
| 217 | else | 173 | else |
| 218 | { | 174 | { |
| 219 | |||
| 220 | // insert the resolved value if it was found or display an error | 175 | // insert the resolved value if it was found or display an error |
| 221 | if (null != resolvedValue) | 176 | if (null != resolvedValue) |
| 222 | { | 177 | { |
| 223 | sb.Remove(matches[i].Index, matches[i].Length); | 178 | sb.Remove(matches[i].Index, matches[i].Length); |
| 224 | sb.Insert(matches[i].Index, resolvedValue); | 179 | sb.Insert(matches[i].Index, resolvedValue); |
| 180 | |||
| 181 | result.UpdatedValue = true; | ||
| 225 | } | 182 | } |
| 226 | else if ("loc" == variableNamespace && errorOnUnknown) // unresolved loc variable | 183 | else if ("loc" == variableNamespace && errorOnUnknown) // unresolved loc variable |
| 227 | { | 184 | { |
| @@ -235,10 +192,10 @@ namespace WixToolset.Core | |||
| 235 | } | 192 | } |
| 236 | } | 193 | } |
| 237 | 194 | ||
| 238 | value = sb.ToString(); | 195 | result.Value = sb.ToString(); |
| 239 | } | 196 | } |
| 240 | 197 | ||
| 241 | return value; | 198 | return result; |
| 242 | } | 199 | } |
| 243 | 200 | ||
| 244 | /// <summary> | 201 | /// <summary> |
diff --git a/src/test/WixToolsetTest.CoreIntegration/ProgramFixture.cs b/src/test/WixToolsetTest.CoreIntegration/ProgramFixture.cs index 4f34f330..b4a7c8b2 100644 --- a/src/test/WixToolsetTest.CoreIntegration/ProgramFixture.cs +++ b/src/test/WixToolsetTest.CoreIntegration/ProgramFixture.cs | |||
| @@ -20,7 +20,8 @@ namespace WixToolsetTest.CoreIntegration | |||
| 20 | 20 | ||
| 21 | using (var fs = new DisposableFileSystem()) | 21 | using (var fs = new DisposableFileSystem()) |
| 22 | { | 22 | { |
| 23 | var intermediateFolder = fs.GetFolder(); | 23 | var baseFolder = fs.GetFolder(); |
| 24 | var intermediateFolder = Path.Combine(baseFolder, "obj"); | ||
| 24 | 25 | ||
| 25 | var program = new Program(); | 26 | var program = new Program(); |
| 26 | var result = program.Run(new WixToolsetServiceProvider(), null, new[] | 27 | var result = program.Run(new WixToolsetServiceProvider(), null, new[] |
| @@ -31,16 +32,16 @@ namespace WixToolsetTest.CoreIntegration | |||
| 31 | "-loc", Path.Combine(folder, "Package.en-us.wxl"), | 32 | "-loc", Path.Combine(folder, "Package.en-us.wxl"), |
| 32 | "-bindpath", Path.Combine(folder, "data"), | 33 | "-bindpath", Path.Combine(folder, "data"), |
| 33 | "-intermediateFolder", intermediateFolder, | 34 | "-intermediateFolder", intermediateFolder, |
| 34 | "-o", Path.Combine(intermediateFolder, @"bin\test.msi") | 35 | "-o", Path.Combine(baseFolder, @"bin\test.msi") |
| 35 | }); | 36 | }); |
| 36 | 37 | ||
| 37 | Assert.Equal(0, result); | 38 | Assert.Equal(0, result); |
| 38 | 39 | ||
| 39 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.msi"))); | 40 | Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.msi"))); |
| 40 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb"))); | 41 | Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb"))); |
| 41 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\MsiPackage\test.txt"))); | 42 | Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\MsiPackage\test.txt"))); |
| 42 | 43 | ||
| 43 | var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wir")); | 44 | var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wir")); |
| 44 | var section = intermediate.Sections.Single(); | 45 | var section = intermediate.Sections.Single(); |
| 45 | 46 | ||
| 46 | var wixFile = section.Tuples.OfType<WixFileTuple>().Single(); | 47 | var wixFile = section.Tuples.OfType<WixFileTuple>().Single(); |
| @@ -245,6 +246,38 @@ namespace WixToolsetTest.CoreIntegration | |||
| 245 | } | 246 | } |
| 246 | } | 247 | } |
| 247 | 248 | ||
| 249 | [Fact] | ||
| 250 | public void CanBuildWixout() | ||
| 251 | { | ||
| 252 | var folder = TestData.Get(@"TestData\SingleFile"); | ||
| 253 | |||
| 254 | using (var fs = new DisposableFileSystem()) | ||
| 255 | { | ||
| 256 | var baseFolder = fs.GetFolder(); | ||
| 257 | var intermediateFolder = Path.Combine(baseFolder, "obj"); | ||
| 258 | |||
| 259 | var program = new Program(); | ||
| 260 | var result = program.Run(new WixToolsetServiceProvider(), null, new[] | ||
| 261 | { | ||
| 262 | "build", | ||
| 263 | Path.Combine(folder, "Package.wxs"), | ||
| 264 | Path.Combine(folder, "PackageComponents.wxs"), | ||
| 265 | "-loc", Path.Combine(folder, "Package.en-us.wxl"), | ||
| 266 | "-bindpath", Path.Combine(folder, "data"), | ||
| 267 | "-intermediateFolder", intermediateFolder, | ||
| 268 | "-o", Path.Combine(baseFolder, @"bin\test.wixout") | ||
| 269 | }); | ||
| 270 | |||
| 271 | Assert.Equal(0, result); | ||
| 272 | |||
| 273 | var builtFiles = Directory.GetFiles(Path.Combine(baseFolder, @"bin")); | ||
| 274 | |||
| 275 | Assert.Equal(new[]{ | ||
| 276 | "test.wixout" | ||
| 277 | }, builtFiles.Select(Path.GetFileName).ToArray()); | ||
| 278 | } | ||
| 279 | } | ||
| 280 | |||
| 248 | [Fact(Skip = "Not implemented yet.")] | 281 | [Fact(Skip = "Not implemented yet.")] |
| 249 | public void CanBuildInstanceTransform() | 282 | public void CanBuildInstanceTransform() |
| 250 | { | 283 | { |
