Support wixout and extract Resolve and Layout from Binder
Rob Mensching committed
Dec 21, 2017 at 13:42 UTC
dc9f4c329e6f55ce7595970463e0caf148096f4b
44 files changed
+1005
-799
src/WixToolset.BuildTasks/WixToolTask.cs
+1
-2
@@ -193,8 +193,7 @@ namespace WixToolset.BuildTasks
193
string responseFile = null;
194
try
195
{
196
- string responseFileSwitch;
197
- responseFile = this.GetTemporaryResponseFile(responseFileCommands, out responseFileSwitch);
196
+ responseFile = this.GetTemporaryResponseFile(responseFileCommands, out var responseFileSwitch);
197
if (!String.IsNullOrEmpty(responseFileSwitch))
198
{
199
commandLineCommands = commandLineCommands + " " + responseFileSwitch;
src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+3
-3
@@ -74,7 +74,9 @@ namespace WixToolset.Core.Burn
74
this.DelayedFields = context.DelayedFields;
75
this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles;
76
77
- this.BackendExtensions = context.ExtensionManager.Create<IBurnBackendExtension>();
77
+ var extensionManager = context.ServiceProvider.GetService<IExtensionManager>();
78
+
79
+ this.BackendExtensions = extensionManager.Create<IBurnBackendExtension>();
80
}
81
82
public CompressionLevel DefaultCompressionLevel { private get; set; }
@@ -85,8 +87,6 @@ namespace WixToolset.Core.Burn
87
88
private IEnumerable<IBurnBackendExtension> BackendExtensions { get; }
89
88
- public IEnumerable<IBinderExtension> Extensions { private get; set; }
89
-
90
public Intermediate Output { private get; set; }
91
92
public string OutputPath { private get; set; }
src/WixToolset.Core.Burn/BundleBackend.cs
+1
-2
@@ -9,7 +9,6 @@ namespace WixToolset.Core.Burn
9
using WixToolset.Data;
10
using WixToolset.Data.Bind;
11
using WixToolset.Extensibility;
12
- using WixToolset.Extensibility.Services;
12
13
internal class BundleBackend : IBackend
14
{
@@ -25,7 +24,7 @@ namespace WixToolset.Core.Burn
24
//command.WixVariableResolver = context.WixVariableResolver;
25
command.Execute();
26
28
- return new BindResult(command.FileTransfers, command.ContentFilePaths);
27
+ return new BindResult { FileTransfers = command.FileTransfers, ContentFilePaths = command.ContentFilePaths };
28
}
29
30
public bool Inscribe(IInscribeContext context)
src/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs
-1
@@ -14,7 +14,6 @@ namespace WixToolset.Core.Burn.Bundles
14
using WixToolset.Extensibility;
15
using WixToolset.Core.Native;
16
using Dtf = WixToolset.Dtf.WindowsInstaller;
17
- using WixToolset.Bind;
17
using WixToolset.Data.Bind;
18
19
/// <summary>
src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs
-1
@@ -9,7 +9,6 @@ namespace WixToolset.Core.Burn.Bundles
9
using System.Security.Cryptography;
10
using System.Security.Cryptography.X509Certificates;
11
using System.Text;
12
- using WixToolset.Bind;
12
using WixToolset.Data;
13
using WixToolset.Data.Bind;
14
using WixToolset.Data.Rows;
src/WixToolset.Core.Burn/BurnBackendFactory.cs
+1
-1
@@ -9,7 +9,7 @@ namespace WixToolset.Core.Burn
9
10
internal class BurnBackendFactory : IBackendFactory
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
{
14
if (String.IsNullOrEmpty(outputType))
15
{
src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+6
-92
@@ -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.
23
internal static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}");
24
25
- public BindDatabaseCommand(IBindContext context, IEnumerable<IWindowsInstallerBackendExtension> backendExtension, Validator validator)
25
+ public BindDatabaseCommand(WixToolset.Extensibility.IBindContext context, IEnumerable<IWindowsInstallerBackendExtension> backendExtension, Validator validator)
26
{
27
this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions();
28
29
- this.BindPaths = context.BindPaths;
29
this.CabbingThreadCount = context.CabbingThreadCount;
30
this.CabCachePath = context.CabCachePath;
31
this.Codepage = context.Codepage;
32
this.DefaultCompressionLevel = context.DefaultCompressionLevel;
33
this.DelayedFields = context.DelayedFields;
34
this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles;
36
- this.Extensions = context.Extensions;
35
+ this.FileSystemExtensions = context.FileSystemExtensions;
36
this.Intermediate = context.IntermediateRepresentation;
37
this.Messaging = context.Messaging;
38
this.OutputPath = context.OutputPath;
39
this.PdbFile = context.OutputPdbPath;
40
this.IntermediateFolder = context.IntermediateFolder;
41
this.Validator = validator;
43
- this.WixVariableResolver = context.WixVariableResolver;
44
-
42
+
43
this.BackendExtensions = backendExtension;
44
}
45
48
- private IEnumerable<BindPath> BindPaths { get; }
49
-
46
private int Codepage { get; }
47
48
private int CabbingThreadCount { get; }
@@ -59,12 +55,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
55
56
public IEnumerable<IExpectedExtractFile> ExpectedEmbeddedFiles { get; }
57
58
+ public IEnumerable<IFileSystemExtension> FileSystemExtensions { get; }
59
+
60
public bool DeltaBinaryPatch { get; set; }
61
62
private IEnumerable<IWindowsInstallerBackendExtension> BackendExtensions { get; }
63
66
- private IEnumerable<IBinderExtension> Extensions { get; }
67
-
64
private string PdbFile { get; }
65
66
private Intermediate Intermediate { get; }
@@ -83,7 +79,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
79
80
private Validator Validator { get; }
81
86
- private IBindVariableResolver WixVariableResolver { get; }
82
83
public IEnumerable<FileTransfer> FileTransfers { get; private set; }
84
@@ -100,8 +95,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
95
// If there are any fields to resolve later, create the cache to populate during bind.
96
var variableCache = this.DelayedFields.Any() ? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) : null;
97
103
- this.LocalizeUI(section);
104
-
98
// Process the summary information table before the other tables.
99
bool compressed;
100
bool longNames;
@@ -534,85 +527,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
527
intermediate.Save(Path.ChangeExtension(this.OutputPath, "wir"));
528
}
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
-
530
#if TODO_FINISH_PATCH
531
/// <summary>
532
/// Copy file data between transform substorages and the patch output object
@@ -984,7 +898,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
898
private void GenerateDatabase(Output output, string databaseFile, bool keepAddedColumns, bool useSubdirectory)
899
{
900
var command = new GenerateDatabaseCommand();
987
- command.Extensions = this.Extensions;
901
+ command.Extensions = this.FileSystemExtensions;
902
command.Output = output;
903
command.OutputPath = databaseFile;
904
command.KeepAddedColumns = keepAddedColumns;
src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
+1
-1
@@ -15,7 +15,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
15
16
internal class BindTransformCommand
17
{
18
- public IEnumerable<IBinderExtension> Extensions { private get; set; }
18
+ public IEnumerable<IFileSystemExtension> Extensions { private get; set; }
19
20
public TableDefinitionCollection TableDefinitions { private get; set; }
21
src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs
+1
-2
@@ -6,7 +6,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
6
using System.Collections.Generic;
7
using System.IO;
8
using System.Linq;
9
- using WixToolset.Bind;
9
using WixToolset.Core.Native;
10
using WixToolset.Data;
11
using WixToolset.Data.Tuples;
@@ -135,7 +134,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
134
if (fileRow.File == componentRow.KeyPath)
135
{
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);
138
string fileName = Common.GetName(fileRow.LongFileName, false, true).ToLowerInvariant();
139
path = Path.Combine(directoryPath, fileName);
140
src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs
+1
-1
@@ -18,7 +18,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
18
{
19
public bool CopyOutFileRows { private get; set; }
20
21
- public IEnumerable<IBinderExtension> Extensions { private get; set; }
21
+ public IEnumerable<IFileSystemExtension> Extensions { private get; set; }
22
23
public IMessaging Messaging { private get; set; }
24
src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs
+1
-1
@@ -19,7 +19,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
19
{
20
public int Codepage { private get; set; }
21
22
- public IEnumerable<IBinderExtension> Extensions { private get; set; }
22
+ public IEnumerable<IFileSystemExtension> Extensions { private get; set; }
23
24
/// <summary>
25
/// Whether to keep columns added in a transform.
src/WixToolset.Core.WindowsInstaller/Bind/PathResolver.cs
new
+105
@@ -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
+}
src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs
+5
-6
@@ -5,14 +5,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind
5
using System;
6
using System.Collections.Generic;
7
using System.IO;
8
- using WixToolset.Data;
9
- using WixToolset.Msi;
10
- using WixToolset.Core.Native;
11
- using WixToolset.Bind;
8
+ using System.Linq;
9
using WixToolset.Core.Bind;
10
+ using WixToolset.Core.Native;
11
+ using WixToolset.Data;
12
using WixToolset.Data.Bind;
13
using WixToolset.Data.Tuples;
15
- using System.Linq;
14
+ using WixToolset.Msi;
15
16
/// <summary>
17
/// Defines the file transfers necessary to layout the uncompressed files.
@@ -100,7 +99,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
99
throw new WixException(ErrorMessages.FileIdentifierNotFound(facade.File.SourceLineNumbers, facade.File.File));
100
}
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);
103
}
104
105
// finally put together the base media layout path and the relative file layout path
src/WixToolset.Core.WindowsInstaller/Bind/ResolvedDirectory.cs
renamed
+2
-2
@@ -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.
2
3
-namespace WixToolset.Bind
3
+namespace WixToolset.Core.WindowsInstaller.Bind
4
{
5
/// <summary>
6
/// Structure used for resolved directory information.
7
/// </summary>
8
- public struct ResolvedDirectory
8
+ internal struct ResolvedDirectory
9
{
10
/// <summary>
11
/// Constructor for ResolvedDirectory.
src/WixToolset.Core.WindowsInstaller/MsiBackend.cs
+5
-3
@@ -12,9 +12,11 @@ namespace WixToolset.Core.WindowsInstaller
12
13
internal class MsiBackend : IBackend
14
{
15
- public BindResult Bind(IBindContext context)
15
+ public BindResult Bind(WixToolset.Extensibility.IBindContext context)
16
{
17
- var backendExtensions = context.ExtensionManager.Create<IWindowsInstallerBackendExtension>();
17
+ var extensionManager = context.ServiceProvider.GetService<IExtensionManager>();
18
+
19
+ var backendExtensions = extensionManager.Create<IWindowsInstallerBackendExtension>();
20
21
foreach (var extension in backendExtensions)
22
{
@@ -26,7 +28,7 @@ namespace WixToolset.Core.WindowsInstaller
28
var command = new BindDatabaseCommand(context, backendExtensions, validator);
29
command.Execute();
30
29
- var result = new BindResult(command.FileTransfers, command.ContentFilePaths);
31
+ var result = new BindResult { FileTransfers = command.FileTransfers, ContentFilePaths = command.ContentFilePaths };
32
33
foreach (var extension in backendExtensions)
34
{
src/WixToolset.Core.WindowsInstaller/MsmBackend.cs
+5
-3
@@ -11,9 +11,11 @@ namespace WixToolset.Core.WindowsInstaller
11
12
internal class MsmBackend : IBackend
13
{
14
- public BindResult Bind(IBindContext context)
14
+ public BindResult Bind(WixToolset.Extensibility.IBindContext context)
15
{
16
- var backendExtensions = context.ExtensionManager.Create<IWindowsInstallerBackendExtension>();
16
+ var extensionManager = context.ServiceProvider.GetService<IExtensionManager>();
17
+
18
+ var backendExtensions = extensionManager.Create<IWindowsInstallerBackendExtension>();
19
20
foreach (var extension in backendExtensions)
21
{
@@ -25,7 +27,7 @@ namespace WixToolset.Core.WindowsInstaller
27
var command = new BindDatabaseCommand(context, backendExtensions, validator);
28
command.Execute();
29
28
- var result = new BindResult(command.FileTransfers, command.ContentFilePaths);
30
+ var result = new BindResult { FileTransfers = command.FileTransfers, ContentFilePaths = command.ContentFilePaths };
31
32
foreach (var extension in backendExtensions)
33
{
src/WixToolset.Core.WindowsInstaller/MspBackend.cs
+1
-1
@@ -16,7 +16,7 @@ namespace WixToolset.Core.WindowsInstaller
16
17
internal class MspBackend : IBackend
18
{
19
- public BindResult Bind(IBindContext context)
19
+ public BindResult Bind(WixToolset.Extensibility.IBindContext context)
20
{
21
throw new NotImplementedException();
22
}
src/WixToolset.Core.WindowsInstaller/MstBackend.cs
-1
@@ -7,7 +7,6 @@ namespace WixToolset.Core.WindowsInstaller
7
using WixToolset.Data;
8
using WixToolset.Data.Bind;
9
using WixToolset.Extensibility;
10
- using WixToolset.Extensibility.Services;
10
11
internal class MstBackend : IBackend
12
{
src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs
+1
-1
@@ -244,7 +244,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
244
private void GenerateDatabase(Output output, string databaseFile)
245
{
246
var command = new GenerateDatabaseCommand();
247
- command.Extensions = Array.Empty<IBinderExtension>();
247
+ command.Extensions = Array.Empty<IFileSystemExtension>();
248
command.Output = output;
249
command.OutputPath = databaseFile;
250
command.KeepAddedColumns = true;
src/WixToolset.Core.WindowsInstaller/Validator.cs
+1
-1
@@ -324,7 +324,7 @@ namespace WixToolset.Core.WindowsInstaller
324
}
325
}
326
327
- public static Validator CreateFromContext(IBindContext context, string cubeFilename)
327
+ public static Validator CreateFromContext(WixToolset.Extensibility.IBindContext context, string cubeFilename)
328
{
329
Validator validator = null;
330
src/WixToolset.Core.WindowsInstaller/WindowsInstallerBackendFactory.cs
-1
@@ -5,7 +5,6 @@ namespace WixToolset.Core.WindowsInstaller
5
using System;
6
using System.IO;
7
using WixToolset.Extensibility;
8
- using WixToolset.Extensibility.Services;
8
9
internal class WindowsInstallerBackendFactory : IBackendFactory
10
{
src/WixToolset.Core/Bind/FileResolver.cs
+12
-80
@@ -6,7 +6,6 @@ namespace WixToolset.Core.Bind
6
using System.Collections.Generic;
7
using System.IO;
8
using System.Linq;
9
- using System.Runtime.InteropServices;
9
using WixToolset.Data;
10
using WixToolset.Data.Bind;
11
using WixToolset.Extensibility;
@@ -22,9 +21,9 @@ namespace WixToolset.Core.Bind
21
this.RebaseUpdated = this.BindPaths[BindStage.Updated].Any();
22
}
23
25
- public FileResolver(IEnumerable<BindPath> bindPaths, IEnumerable<IBinderExtension> extensions) : this(bindPaths)
24
+ public FileResolver(IEnumerable<BindPath> bindPaths, IEnumerable<IResolverExtension> extensions) : this(bindPaths)
25
{
27
- this.BinderExtensions = extensions ?? Array.Empty<IBinderExtension>();
26
+ this.ResolverExtensions = extensions ?? Array.Empty<IResolverExtension>();
27
}
28
29
public FileResolver(IEnumerable<BindPath> bindPaths, IEnumerable<ILibrarianExtension> extensions) : this(bindPaths)
@@ -38,79 +37,15 @@ namespace WixToolset.Core.Bind
37
38
public bool RebaseUpdated { get; }
39
41
- private IEnumerable<IBinderExtension> BinderExtensions { get; }
40
+ private IEnumerable<IResolverExtension> ResolverExtensions { get; }
41
42
private IEnumerable<ILibrarianExtension> LibrarianExtensions { get; }
43
45
- /// <summary>
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)
44
+ public string Resolve(SourceLineNumber sourceLineNumbers, IntermediateTupleDefinition tupleDefinition, string source)
45
{
46
foreach (var extension in this.LibrarianExtensions)
47
{
113
- var resolved = extension.Resolve(sourceLineNumbers, table, path);
48
+ var resolved = extension.Resolve(sourceLineNumbers, tupleDefinition, source);
49
50
if (null != resolved)
51
{
@@ -118,7 +53,7 @@ namespace WixToolset.Core.Bind
53
}
54
}
55
121
- return this.ResolveUsingBindPaths(path, table, sourceLineNumbers, BindStage.Normal);
56
+ return this.ResolveUsingBindPaths(source, tupleDefinition, sourceLineNumbers, BindStage.Normal);
57
}
58
59
/// <summary>
@@ -129,11 +64,11 @@ namespace WixToolset.Core.Bind
64
/// <param name="sourceLineNumbers">Optional source line of source file being resolved.</param>
65
/// <param name="bindStage">The binding stage used to determine what collection of bind paths will be used</param>
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)
68
{
134
- foreach (var extension in this.BinderExtensions)
69
+ foreach (var extension in this.ResolverExtensions)
70
{
136
- var resolved = extension.ResolveFile(source, type, sourceLineNumbers, bindStage);
71
+ var resolved = extension.ResolveFile(source, tupleDefinition, sourceLineNumbers, bindStage);
72
73
if (null != resolved)
74
{
@@ -141,10 +76,10 @@ namespace WixToolset.Core.Bind
76
}
77
}
78
144
- return this.ResolveUsingBindPaths(source, type, sourceLineNumbers, bindStage);
79
+ return this.ResolveUsingBindPaths(source, tupleDefinition, sourceLineNumbers, bindStage);
80
}
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)
83
{
84
string resolved = null;
85
@@ -206,7 +141,7 @@ namespace WixToolset.Core.Bind
141
142
if (null == resolved)
143
{
209
- throw new WixFileNotFoundException(sourceLineNumbers, source, type);
144
+ throw new WixFileNotFoundException(sourceLineNumbers, source, tupleDefinition.Name);
145
}
146
147
// Didn't find the file.
@@ -224,8 +159,5 @@ namespace WixToolset.Core.Bind
159
throw new WixException(ErrorMessages.IllegalCharactersInPath(path));
160
}
161
}
227
-
228
- [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
229
- private static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes);
162
}
163
}
src/WixToolset.Core/Bind/FileSystem.cs
new
+87
@@ -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
+}
src/WixToolset.Core/Bind/ResolveFieldsCommand.cs
+9
-8
@@ -22,7 +22,7 @@ namespace WixToolset.Core.Bind
22
23
public IEnumerable<BindPath> BindPaths { private get; set; }
24
25
- public IEnumerable<IBinderExtension> Extensions { private get; set; }
25
+ public IEnumerable<IResolverExtension> Extensions { private get; set; }
26
27
public ExtractEmbeddedFiles FilesWithEmbeddedFiles { private get; set; }
28
@@ -52,7 +52,6 @@ namespace WixToolset.Core.Bind
52
}
53
54
var isDefault = true;
55
- var delayedResolve = false;
55
56
// Check to make sure we're in a scenario where we can handle variable resolution.
57
if (null != delayedFields)
@@ -63,16 +62,18 @@ namespace WixToolset.Core.Bind
62
var original = field.AsString();
63
if (!String.IsNullOrEmpty(original))
64
{
66
- var value = this.BindVariableResolver.ResolveVariables(row.SourceLineNumbers, original, false, out isDefault, out delayedResolve);
67
- if (original != value)
65
+ var resolution = this.BindVariableResolver.ResolveVariables(row.SourceLineNumbers, original, false);
66
+ if (resolution.UpdatedValue)
67
{
69
- field.Set(value);
68
+ field.Set(resolution.Value);
69
}
70
72
- if (delayedResolve)
71
+ if (resolution.DelayedResolve)
72
{
73
delayedFields.Add(new DelayedField(row, field));
74
}
75
+
76
+ isDefault = resolution.IsDefault;
77
}
78
}
79
}
@@ -119,13 +120,13 @@ namespace WixToolset.Core.Bind
120
#endif
121
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);
124
field.Set(value);
125
}
126
else if (!fileResolver.RebaseTarget && !fileResolver.RebaseUpdated) // Normal binding for Patch Scenario (normal patch, no re-basing logic)
127
{
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);
130
field.Set(value);
131
}
132
#if REVISIT_FOR_PATCHING
src/WixToolset.Core/Bind/ResolveResult.cs
deleted
-14
@@ -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
src/WixToolset.Core/Bind/TransferFilesCommand.cs
+10
-12
@@ -13,15 +13,15 @@ namespace WixToolset.Core.Bind
13
14
internal class TransferFilesCommand
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
{
18
- this.FileResolver = new FileResolver(bindPaths, extensions);
18
+ this.FileSystem = new FileSystem(extensions);
19
this.Messaging = messaging;
20
this.FileTransfers = fileTransfers;
21
this.SuppressAclReset = suppressAclReset;
22
}
23
24
- private FileResolver FileResolver { get; }
24
+ private FileSystem FileSystem { get; }
25
26
private IMessaging Messaging { get; }
27
@@ -35,10 +35,8 @@ namespace WixToolset.Core.Bind
35
36
foreach (var fileTransfer in this.FileTransfers)
37
{
38
- string fileSource = this.FileResolver.ResolveFile(fileTransfer.Source, fileTransfer.Type, fileTransfer.SourceLineNumbers, BindStage.Normal);
39
-
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))
40
{
41
fileTransfer.Redundant = true;
42
continue;
@@ -51,13 +49,13 @@ namespace WixToolset.Core.Bind
49
{
50
if (fileTransfer.Move)
51
{
54
- this.Messaging.Write(VerboseMessages.MoveFile(fileSource, fileTransfer.Destination));
55
- this.TransferFile(true, fileSource, fileTransfer.Destination);
52
+ this.Messaging.Write(VerboseMessages.MoveFile(fileTransfer.Source, fileTransfer.Destination));
53
+ this.TransferFile(true, fileTransfer.Source, fileTransfer.Destination);
54
}
55
else
56
{
59
- this.Messaging.Write(VerboseMessages.CopyFile(fileSource, fileTransfer.Destination));
60
- this.TransferFile(false, fileSource, fileTransfer.Destination);
57
+ this.Messaging.Write(VerboseMessages.CopyFile(fileTransfer.Source, fileTransfer.Destination));
58
+ this.TransferFile(false, fileTransfer.Source, fileTransfer.Destination);
59
}
60
61
retry = false;
@@ -183,11 +181,11 @@ namespace WixToolset.Core.Bind
181
182
if (move)
183
{
186
- complete = this.FileResolver.MoveFile(source, destination, true);
184
+ complete = this.FileSystem.MoveFile(source, destination, true);
185
}
186
else
187
{
190
- complete = this.FileResolver.CopyFile(source, destination, true);
188
+ complete = this.FileSystem.CopyFile(source, destination, true);
189
}
190
191
if (!complete)
src/WixToolset.Core/BindContext.cs
+1
-3
@@ -35,7 +35,7 @@ namespace WixToolset.Core
35
36
public IExtensionManager ExtensionManager { get; set; }
37
38
- public IEnumerable<IBinderExtension> Extensions { get; set; }
38
+ public IEnumerable<IFileSystemExtension> FileSystemExtensions { get; set; }
39
40
public IEnumerable<string> Ices { get; set; }
41
@@ -47,8 +47,6 @@ namespace WixToolset.Core
47
48
public string OutputPdbPath { get; set; }
49
50
- public bool SuppressAclReset { get; set; }
51
-
50
public IEnumerable<string> SuppressIces { get; set; }
51
52
public bool SuppressValidation { get; set; }
src/WixToolset.Core/Binder.cs
+55
-396
@@ -3,14 +3,11 @@
3
namespace WixToolset.Core
4
{
5
using System;
6
- using System.Collections;
6
using System.Collections.Generic;
7
using System.Diagnostics;
9
- using System.Globalization;
8
using System.IO;
9
using System.Linq;
10
using System.Reflection;
13
- using WixToolset.Bind;
11
using WixToolset.Core.Bind;
12
using WixToolset.Data;
13
using WixToolset.Data.Bind;
@@ -148,130 +145,72 @@ namespace WixToolset.Core
145
/// <value>The Wix variable resolver.</value>
146
internal WixVariableResolver WixVariableResolver { get; set; }
147
151
- /// <summary>
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)
148
+ public BindResult Bind(IBindContext context)
149
{
150
this.Context = context;
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
-
152
this.WriteBuildInfoTable(this.Context.IntermediateRepresentation, this.Context.OutputPath);
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
- //
154
var bindResult = this.BackendBind();
203
-
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;
155
+ return bindResult;
156
}
157
221
- private ResolveResult Resolve()
222
- {
223
- var buildingPatch = this.Context.IntermediateRepresentation.Sections.Any(s => s.Type == SectionType.Patch);
224
-
225
- var filesWithEmbeddedFiles = new ExtractEmbeddedFiles();
226
-
227
- IEnumerable<DelayedField> delayedFields;
228
- {
229
- var command = new ResolveFieldsCommand();
230
- command.Messaging = this.Context.Messaging;
231
- command.BuildingPatch = buildingPatch;
232
- command.BindVariableResolver = this.Context.WixVariableResolver;
233
- command.BindPaths = this.Context.BindPaths;
234
- command.Extensions = this.Context.Extensions;
235
- command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles;
236
- command.IntermediateFolder = this.Context.IntermediateFolder;
237
- command.Intermediate = this.Context.IntermediateRepresentation;
238
- command.SupportDelayedResolution = true;
239
- command.Execute();
240
-
241
- delayedFields = command.DelayedFields;
242
- }
243
-
244
-#if REVISIT_FOR_PATCHING
245
- if (this.Context.IntermediateRepresentation.SubStorages != null)
246
- {
247
- foreach (SubStorage transform in this.Context.IntermediateRepresentation.SubStorages)
248
- {
249
- var command = new ResolveFieldsCommand();
250
- command.BuildingPatch = buildingPatch;
251
- command.BindVariableResolver = this.Context.WixVariableResolver;
252
- command.BindPaths = this.Context.BindPaths;
253
- command.Extensions = this.Context.Extensions;
254
- command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles;
255
- command.IntermediateFolder = this.Context.IntermediateFolder;
256
- command.Intermediate = this.Context.IntermediateRepresentation;
257
- command.SupportDelayedResolution = false;
258
- command.Execute();
259
- }
260
- }
261
-#endif
262
-
263
- var expectedEmbeddedFiles = filesWithEmbeddedFiles.GetExpectedEmbeddedFiles();
264
-
265
- return new ResolveResult
266
- {
267
- ExpectedEmbeddedFiles = expectedEmbeddedFiles,
268
- DelayedFields = delayedFields,
269
- };
270
- }
158
+//// private ResolveResult Resolve()
159
+//// {
160
+//// var buildingPatch = this.Context.IntermediateRepresentation.Sections.Any(s => s.Type == SectionType.Patch);
161
+
162
+//// var filesWithEmbeddedFiles = new ExtractEmbeddedFiles();
163
+
164
+//// IEnumerable<DelayedField> delayedFields;
165
+//// {
166
+//// var command = new ResolveFieldsCommand();
167
+//// command.Messaging = this.Context.Messaging;
168
+//// command.BuildingPatch = buildingPatch;
169
+//// command.BindVariableResolver = this.Context.WixVariableResolver;
170
+//// command.BindPaths = this.Context.BindPaths;
171
+//// command.Extensions = this.Context.Extensions;
172
+//// command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles;
173
+//// command.IntermediateFolder = this.Context.IntermediateFolder;
174
+//// command.Intermediate = this.Context.IntermediateRepresentation;
175
+//// command.SupportDelayedResolution = true;
176
+//// command.Execute();
177
+
178
+//// delayedFields = command.DelayedFields;
179
+//// }
180
+
181
+////#if REVISIT_FOR_PATCHING
182
+//// if (this.Context.IntermediateRepresentation.SubStorages != null)
183
+//// {
184
+//// foreach (SubStorage transform in this.Context.IntermediateRepresentation.SubStorages)
185
+//// {
186
+//// var command = new ResolveFieldsCommand();
187
+//// command.BuildingPatch = buildingPatch;
188
+//// command.BindVariableResolver = this.Context.WixVariableResolver;
189
+//// command.BindPaths = this.Context.BindPaths;
190
+//// command.Extensions = this.Context.Extensions;
191
+//// command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles;
192
+//// command.IntermediateFolder = this.Context.IntermediateFolder;
193
+//// command.Intermediate = this.Context.IntermediateRepresentation;
194
+//// command.SupportDelayedResolution = false;
195
+//// command.Execute();
196
+//// }
197
+//// }
198
+////#endif
199
+
200
+//// var expectedEmbeddedFiles = filesWithEmbeddedFiles.GetExpectedEmbeddedFiles();
201
+
202
+//// return new ResolveResult
203
+//// {
204
+//// ExpectedEmbeddedFiles = expectedEmbeddedFiles,
205
+//// DelayedFields = delayedFields,
206
+//// };
207
+//// }
208
209
private BindResult BackendBind()
210
{
274
- var backendFactories = this.Context.ExtensionManager.Create<IBackendFactory>();
211
+ var extensionManager = this.Context.ServiceProvider.GetService<IExtensionManager>();
212
+
213
+ var backendFactories = extensionManager.Create<IBackendFactory>();
214
215
var entrySection = this.Context.IntermediateRepresentation.Sections[0];
216
@@ -289,31 +228,6 @@ namespace WixToolset.Core
228
return null;
229
}
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
-
231
/// <summary>
232
/// Binds an output.
233
/// </summary>
@@ -428,35 +342,6 @@ namespace WixToolset.Core
342
}
343
#endif
344
431
- /// <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
-
345
/// <summary>
346
/// Populates the WixBuildInfo table in an output.
347
/// </summary>
@@ -585,231 +470,5 @@ namespace WixToolset.Core
470
command.Execute();
471
}
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
- }
473
}
474
}
src/WixToolset.Core/BinderFileManager.cs
+1
-1
@@ -12,7 +12,7 @@ namespace WixToolset
12
using WixToolset.Data.Rows;
13
using WixToolset.Extensibility;
14
15
-#if false
15
+#if DEAD_CODE
16
/// <summary>
17
/// Base class for creating a binder file manager.
18
/// </summary>
src/WixToolset.Core/BinderFileManagerCore.cs
+2
@@ -9,6 +9,7 @@ namespace WixToolset
9
using WixToolset.Data.Bind;
10
using WixToolset.Extensibility;
11
12
+#if DEAD_CODE
13
public class BinderFileManagerCore : IBinderFileManagerCore
14
{
15
private Dictionary<string, List<string>>[] bindPaths;
@@ -97,4 +98,5 @@ namespace WixToolset
98
return Enumerable.Empty<string>();
99
}
100
}
101
+#endif
102
}
src/WixToolset.Core/CommandLine/BuildCommand.cs
+69
-53
@@ -7,7 +7,7 @@ namespace WixToolset.Core
7
using System.IO;
8
using System.Linq;
9
using WixToolset.Data;
10
- using WixToolset.Data.Tuples;
10
+ using WixToolset.Data.Bind;
11
using WixToolset.Extensibility;
12
using WixToolset.Extensibility.Services;
13
@@ -90,6 +90,12 @@ namespace WixToolset.Core
90
91
library?.Save(this.OutputPath);
92
}
93
+ else if (this.OutputType == OutputType.Wixout)
94
+ {
95
+ var output = this.LinkPhase(intermediates);
96
+
97
+ output?.Save(this.OutputPath);
98
+ }
99
else
100
{
101
var output = this.LinkPhase(intermediates);
@@ -147,22 +153,20 @@ namespace WixToolset.Core
153
{
154
var localizations = this.LoadLocalizationFiles().ToList();
155
150
- // If there was an error adding localization files, then bail.
156
+ // If there was an error loading localization files, then bail.
157
if (this.Messaging.EncounteredError)
158
{
159
return null;
160
}
161
156
- var resolver = CreateWixResolverWithVariables(null, null);
157
-
162
var context = new LibraryContext();
163
+ context.Messaging = this.Messaging;
164
context.BindFiles = this.BindFiles;
165
context.BindPaths = this.BindPaths;
166
context.Extensions = this.ExtensionManager.Create<ILibrarianExtension>();
167
context.Localizations = localizations;
168
context.LibraryId = Guid.NewGuid().ToString("N");
169
context.Intermediates = intermediates;
165
- context.WixVariableResolver = resolver;
170
171
var librarian = new Librarian();
172
return librarian.Combine(context);
@@ -174,6 +178,11 @@ namespace WixToolset.Core
178
179
var libraries = this.LoadLibraries(creator);
180
181
+ if (this.Messaging.EncounteredError)
182
+ {
183
+ return null;
184
+ }
185
+
186
var context = this.ServiceProvider.GetService<ILinkContext>();
187
context.Messaging = this.Messaging;
188
context.Extensions = this.ExtensionManager.Create<ILinkerExtension>();
@@ -183,48 +192,72 @@ namespace WixToolset.Core
192
context.TupleDefinitionCreator = creator;
193
194
var linker = new Linker();
186
- var output = linker.Link(context);
187
- return output;
195
+ return linker.Link(context);
196
}
197
198
private void BindPhase(Intermediate output)
199
{
200
var localizations = this.LoadLocalizationFiles().ToList();
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
+ }
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
+ }
213
198
- var intermediateFolder = this.IntermediateFolder;
199
- if (String.IsNullOrEmpty(intermediateFolder))
214
+ if (this.Messaging.EncounteredError)
215
{
201
- intermediateFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
216
+ return;
217
}
218
204
- var context = this.ServiceProvider.GetService<IBindContext>();
205
- context.Messaging = this.Messaging;
206
- context.ExtensionManager = this.ExtensionManager;
207
- context.BindPaths = this.BindPaths ?? Array.Empty<BindPath>();
208
- //context.CabbingThreadCount = this.CabbingThreadCount;
209
- context.CabCachePath = this.CabCachePath;
210
- context.Codepage = localizer.Codepage;
211
- //context.DefaultCompressionLevel = this.DefaultCompressionLevel;
212
- //context.Ices = this.Ices;
213
- context.IntermediateFolder = intermediateFolder;
214
- context.IntermediateRepresentation = output;
215
- context.OutputPath = this.OutputPath;
216
- context.OutputPdbPath = Path.ChangeExtension(this.OutputPath, ".wixpdb");
217
- //context.SuppressIces = this.SuppressIces;
218
- context.SuppressValidation = true;
219
- //context.SuppressValidation = this.SuppressValidation;
220
- context.WixVariableResolver = resolver;
221
- context.ContentsFile = this.ContentsFile;
222
- context.OutputsFile = this.OutputsFile;
223
- context.BuiltOutputsFile = this.BuiltOutputsFile;
224
- context.WixprojectFile = this.WixProjectFile;
225
-
226
- var binder = new Binder();
227
- binder.Bind(context);
219
+ BindResult bindResult;
220
+ {
221
+ var intermediateFolder = this.IntermediateFolder;
222
+ if (String.IsNullOrEmpty(intermediateFolder))
223
+ {
224
+ intermediateFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
225
+ }
226
+
227
+ var context = this.ServiceProvider.GetService<IBindContext>();
228
+ context.Messaging = this.Messaging;
229
+ //context.CabbingThreadCount = this.CabbingThreadCount;
230
+ context.CabCachePath = this.CabCachePath;
231
+ context.Codepage = resolveResult.Codepage;
232
+ //context.DefaultCompressionLevel = this.DefaultCompressionLevel;
233
+ context.DelayedFields = resolveResult.DelayedFields;
234
+ context.ExpectedEmbeddedFiles = resolveResult.ExpectedEmbeddedFiles;
235
+ //context.Ices = this.Ices;
236
+ context.IntermediateFolder = intermediateFolder;
237
+ context.IntermediateRepresentation = resolveResult.IntermediateRepresentation;
238
+ context.OutputPath = this.OutputPath;
239
+ context.OutputPdbPath = Path.ChangeExtension(this.OutputPath, ".wixpdb");
240
+ //context.SuppressIces = this.SuppressIces;
241
+ context.SuppressValidation = true; // TODO: set this correctly
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
+ }
261
}
262
263
private IEnumerable<Intermediate> LoadLibraries(ITupleDefinitionCreator creator)
@@ -264,22 +297,5 @@ namespace WixToolset.Core
297
yield return localization;
298
}
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
- }
300
}
301
}
src/WixToolset.Core/CommandLine/CommandLine.cs
+4
@@ -260,6 +260,10 @@ namespace WixToolset.Core
260
case "transform":
261
case ".mst":
262
return OutputType.Transform;
263
+
264
+ case "wixout":
265
+ case ".wixout":
266
+ return OutputType.Wixout;
267
}
268
269
return OutputType.Unknown;
src/WixToolset.Core/Compiler.cs
+29
-24
@@ -154,24 +154,40 @@ namespace WixToolset.Core
154
}
155
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)
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)
179
{
161
- foreach (var tuple in section.Tuples)
180
+ foreach (var field in tuple.Fields)
181
{
163
- foreach (var field in tuple.Fields)
182
+ if (field?.Type == IntermediateFieldType.String)
183
{
165
- if (field != null && field.Type == IntermediateFieldType.String)
184
+ var data = field.AsString();
185
+ if (!String.IsNullOrEmpty(data))
186
{
167
- var data = field.AsString();
168
- if (!String.IsNullOrEmpty(data))
187
+ var resolved = this.componentIdPlaceholdersResolver.ResolveVariables(tuple.SourceLineNumbers, data, false, false);
188
+ if (resolved.UpdatedValue)
189
{
170
- var resolved = this.componentIdPlaceholdersResolver.ResolveVariables(tuple.SourceLineNumbers, data, false, false, out var defaultIgnored, out var delayedIgnored);
171
- if (data != resolved)
172
- {
173
- field.Set(resolved);
174
- }
190
+ field.Set(resolved.Value);
191
}
192
}
193
}
@@ -179,17 +195,6 @@ namespace WixToolset.Core
195
}
196
}
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;
198
}
199
200
/// <summary>
@@ -2422,7 +2427,7 @@ namespace WixToolset.Core
2427
{
2428
if (isGeneratableGuidOk || keyFound && !String.IsNullOrEmpty(keyPath))
2429
{
2425
- this.componentIdPlaceholdersResolver.AddVariable(componentIdPlaceholder, keyPath);
2430
+ this.componentIdPlaceholdersResolver.AddVariable(componentIdPlaceholder, keyPath, false);
2431
2432
id = new Identifier(keyPath, AccessModifier.Private);
2433
}
src/WixToolset.Core/Layout.cs
new
+188
@@ -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
+}
src/WixToolset.Core/LayoutContext.cs
new
+40
@@ -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
+}
src/WixToolset.Core/Librarian.cs
+22
-8
@@ -38,11 +38,14 @@ namespace WixToolset.Core
38
39
var sections = this.Context.Intermediates.SelectMany(i => i.Sections).ToList();
40
41
- var fileResolver = new FileResolver(this.Context.BindPaths, this.Context.Extensions);
41
+ var embedFilePaths = this.ResolveFilePathsToEmbed(sections);
42
43
- var embedFilePaths = ResolveFilePathsToEmbed(sections, fileResolver);
43
+ var localizationsByCulture = this.CollateLocalizations(this.Context.Localizations);
44
45
- var localizationsByCulture = CollateLocalizations(this.Context.Localizations);
45
+ if (this.Context.Messaging.EncounteredError)
46
+ {
47
+ return null;
48
+ }
49
50
foreach (var section in sections)
51
{
@@ -83,7 +86,7 @@ namespace WixToolset.Core
86
return (this.Context.Messaging.EncounteredError ? null : library);
87
}
88
86
- private static Dictionary<string, Localization> CollateLocalizations(IEnumerable<Localization> localizations)
89
+ private Dictionary<string, Localization> CollateLocalizations(IEnumerable<Localization> localizations)
90
{
91
var localizationsByCulture = new Dictionary<string, Localization>(StringComparer.OrdinalIgnoreCase);
92
@@ -91,7 +94,14 @@ namespace WixToolset.Core
94
{
95
if (localizationsByCulture.TryGetValue(localization.Culture, out var existingCulture))
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
+ }
105
}
106
else
107
{
@@ -102,13 +112,17 @@ namespace WixToolset.Core
112
return localizationsByCulture;
113
}
114
105
- private List<string> ResolveFilePathsToEmbed(IEnumerable<IntermediateSection> sections, FileResolver fileResolver)
115
+ private List<string> ResolveFilePathsToEmbed(IEnumerable<IntermediateSection> sections)
116
{
117
var embedFilePaths = new List<string>();
118
119
// Resolve paths to files that are to be embedded in the library.
120
if (this.Context.BindFiles)
121
{
122
+ var variableResolver = new WixVariableResolver(this.Context.Messaging);
123
+
124
+ var fileResolver = new FileResolver(this.Context.BindPaths, this.Context.Extensions);
125
+
126
foreach (var tuple in sections.SelectMany(s => s.Tuples))
127
{
128
foreach (var field in tuple.Fields.Where(f => f.Type == IntermediateFieldType.Path))
@@ -117,9 +131,9 @@ namespace WixToolset.Core
131
132
if (pathField != null)
133
{
120
- var resolvedPath = this.Context.WixVariableResolver.ResolveVariables(tuple.SourceLineNumbers, pathField.Path, false);
134
+ var resolution = variableResolver.ResolveVariables(tuple.SourceLineNumbers, pathField.Path, false);
135
122
- var file = fileResolver.Resolve(tuple.SourceLineNumbers, tuple.Definition.Name, resolvedPath);
136
+ var file = fileResolver.Resolve(tuple.SourceLineNumbers, tuple.Definition, resolution.Value);
137
138
if (!String.IsNullOrEmpty(file))
139
{
src/WixToolset.Core/LibraryContext.cs
-2
@@ -25,7 +25,5 @@ namespace WixToolset.Core
25
public IEnumerable<Localization> Localizations { get; set; }
26
27
public IEnumerable<Intermediate> Intermediates { get; set; }
28
-
29
- public IBindVariableResolver WixVariableResolver { get; set; }
28
}
29
}
src/WixToolset.Core/Linker.cs
+3
-3
@@ -8,11 +8,11 @@ namespace WixToolset.Core
8
using System.Diagnostics;
9
using System.Globalization;
10
using System.Linq;
11
- using WixToolset.Data;
12
- using WixToolset.Link;
11
using WixToolset.Core.Link;
12
+ using WixToolset.Data;
13
using WixToolset.Data.Tuples;
15
- using WixToolset.Extensibility.Services;
14
+ using WixToolset.Extensibility;
15
+ using WixToolset.Link;
16
17
/// <summary>
18
/// Linker core of the WiX toolset.
src/WixToolset.Core/PreprocessContext.cs
-3
@@ -8,9 +8,6 @@ namespace WixToolset.Core
8
using WixToolset.Extensibility;
9
using WixToolset.Extensibility.Services;
10
11
- /// <summary>
12
- /// The preprocessor core.
13
- /// </summary>
11
internal class PreprocessContext : IPreprocessContext
12
{
13
internal PreprocessContext(IServiceProvider serviceProvider)
src/WixToolset.Core/ResolveContext.cs
new
+32
@@ -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
+}
src/WixToolset.Core/Resolver.cs
new
+234
@@ -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
+}
src/WixToolset.Core/WixToolsetServiceProvider.cs
+10
@@ -42,6 +42,16 @@ namespace WixToolset.Core
42
return new BindContext(this);
43
}
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
+
55
if (serviceType == typeof(IInscribeContext))
56
{
57
return new InscribeContext(this);
src/WixToolset.Core/WixVariableResolver.cs
+17
-60
@@ -9,8 +9,6 @@ namespace WixToolset.Core
9
using System.Text;
10
using System.Text.RegularExpressions;
11
using WixToolset.Data;
12
- using WixToolset.Data.Tuples;
13
- using WixToolset.Extensibility;
12
using WixToolset.Extensibility.Services;
13
14
/// <summary>
@@ -37,14 +35,15 @@ namespace WixToolset.Core
35
/// <summary>
36
/// Gets the count of variables added to the resolver.
37
/// </summary>
40
- public int VariableCount => this.wixVariables.Count;
38
+ public int VariableCount => this.wixVariables.Count;
39
40
/// <summary>
41
/// Add a variable.
42
/// </summary>
43
/// <param name="name">The name 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)
47
{
48
try
49
{
@@ -52,25 +51,9 @@ namespace WixToolset.Core
51
}
52
catch (ArgumentException)
53
{
55
- this.Messaging.Write(ErrorMessages.WixVariableCollision(null, name));
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
54
+ if (!overridable)
55
{
73
- this.Messaging.Write(ErrorMessages.WixVariableCollision(wixVariableRow.SourceLineNumbers, wixVariableRow.WixVariable));
56
+ throw;
57
}
58
}
59
}
@@ -82,37 +65,9 @@ namespace WixToolset.Core
65
/// <param name="value">The value to resolve.</param>
66
/// <param name="localizationOnly">true to only resolve localization variables; false otherwise.</param>
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)
69
{
87
- return this.ResolveVariables(sourceLineNumbers, value, localizationOnly, out var defaultIgnored, out var delayedIgnored);
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);
70
+ return this.ResolveVariables(sourceLineNumbers, value, localizationOnly, true);
71
}
72
73
/// <summary>
@@ -125,13 +80,12 @@ namespace WixToolset.Core
80
/// <param name="isDefault">true if the resolved value was the default.</param>
81
/// <param name="delayedResolve">true if the value has variables that cannot yet be resolved.</param>
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)
84
{
85
MatchCollection matches = Common.WixVariableRegex.Matches(value);
86
87
// the value is the default unless its substituted further down
133
- isDefault = true;
134
- delayedResolve = false;
88
+ var result = new BindVariableResolution { IsDefault = true, Value = value };
89
90
if (0 < matches.Count)
91
{
@@ -172,6 +126,8 @@ namespace WixToolset.Core
126
if (!localizationOnly)
127
{
128
sb.Remove(matches[i].Index - 1, 1);
129
+
130
+ result.UpdatedValue = true;
131
}
132
}
133
else
@@ -200,7 +156,7 @@ namespace WixToolset.Core
156
if (this.wixVariables.TryGetValue(variableId, out resolvedValue))
157
{
158
resolvedValue = resolvedValue ?? String.Empty;
203
- isDefault = false;
159
+ result.IsDefault = false;
160
}
161
else if (null != variableDefaultValue) // default the resolved value to the inline value if one was specified
162
{
@@ -212,16 +168,17 @@ namespace WixToolset.Core
168
if ("bind" == variableNamespace)
169
{
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;
172
}
173
else
174
{
219
-
175
// insert the resolved value if it was found or display an error
176
if (null != resolvedValue)
177
{
178
sb.Remove(matches[i].Index, matches[i].Length);
179
sb.Insert(matches[i].Index, resolvedValue);
180
+
181
+ result.UpdatedValue = true;
182
}
183
else if ("loc" == variableNamespace && errorOnUnknown) // unresolved loc variable
184
{
@@ -235,10 +192,10 @@ namespace WixToolset.Core
192
}
193
}
194
238
- value = sb.ToString();
195
+ result.Value = sb.ToString();
196
}
197
241
- return value;
198
+ return result;
199
}
200
201
/// <summary>
src/test/WixToolsetTest.CoreIntegration/ProgramFixture.cs
+39
-6
@@ -20,7 +20,8 @@ namespace WixToolsetTest.CoreIntegration
20
21
using (var fs = new DisposableFileSystem())
22
{
23
- var intermediateFolder = fs.GetFolder();
23
+ var baseFolder = fs.GetFolder();
24
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
25
26
var program = new Program();
27
var result = program.Run(new WixToolsetServiceProvider(), null, new[]
@@ -31,16 +32,16 @@ namespace WixToolsetTest.CoreIntegration
32
"-loc", Path.Combine(folder, "Package.en-us.wxl"),
33
"-bindpath", Path.Combine(folder, "data"),
34
"-intermediateFolder", intermediateFolder,
34
- "-o", Path.Combine(intermediateFolder, @"bin\test.msi")
35
+ "-o", Path.Combine(baseFolder, @"bin\test.msi")
36
});
37
38
Assert.Equal(0, result);
39
39
- Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.msi")));
40
- Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb")));
41
- Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\MsiPackage\test.txt")));
40
+ Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.msi")));
41
+ Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb")));
42
+ Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\MsiPackage\test.txt")));
43
43
- var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wir"));
44
+ var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wir"));
45
var section = intermediate.Sections.Single();
46
47
var wixFile = section.Tuples.OfType<WixFileTuple>().Single();
@@ -245,6 +246,38 @@ namespace WixToolsetTest.CoreIntegration
246
}
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
+
281
[Fact(Skip = "Not implemented yet.")]
282
public void CanBuildInstanceTransform()
283
{