Abstract file system to remove Core to Core.Native dependency
The only dependency Core had on Core.Native was for FileSystem which would be better served as an extensibility service everywhere anyway. This moves FileSystem to Core and exposes it via IFileSystem from Extensibility for use everywhere. Core now carries no native code dependencies.
Rob Mensching committed
Jul 26, 2022 at 17:20 UTC
024e03c1ae9d956834b9ccc4d4f91a991507b27c
19 files changed
+143
-93
src/api/wix/WixToolset.Extensibility/Services/IFileSystem.cs
new
+25
@@ -0,0 +1,25 @@
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.Extensibility.Services
4
+{
5
+ /// <summary>
6
+ /// Abstracts basic file system operations.
7
+ /// </summary>
8
+ public interface IFileSystem
9
+ {
10
+ /// <summary>
11
+ /// Copies a file.
12
+ /// </summary>
13
+ /// <param name="source">The file to copy.</param>
14
+ /// <param name="destination">The destination file.</param>
15
+ /// <param name="allowHardlink">Allow hardlinks.</param>
16
+ void CopyFile(string source, string destination, bool allowHardlink);
17
+
18
+ /// <summary>
19
+ /// Moves a file.
20
+ /// </summary>
21
+ /// <param name="source">The file to move.</param>
22
+ /// <param name="destination">The destination file.</param>
23
+ void MoveFile(string source, string destination);
24
+ }
25
+}
src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+4
-1
@@ -28,6 +28,7 @@ namespace WixToolset.Core.Burn
28
this.ServiceProvider = context.ServiceProvider;
29
30
this.Messaging = context.ServiceProvider.GetService<IMessaging>();
31
+ this.FileSystem = context.ServiceProvider.GetService<IFileSystem>();
32
33
this.BackendHelper = context.ServiceProvider.GetService<IBackendHelper>();
34
this.InternalBurnBackendHelper = context.ServiceProvider.GetService<IInternalBurnBackendHelper>();
@@ -49,6 +50,8 @@ namespace WixToolset.Core.Burn
50
51
private IMessaging Messaging { get; }
52
53
+ private IFileSystem FileSystem { get; }
54
+
55
private IBackendHelper BackendHelper { get; }
56
57
private IInternalBurnBackendHelper InternalBurnBackendHelper { get; }
@@ -507,7 +510,7 @@ namespace WixToolset.Core.Burn
510
}
511
512
{
510
- var command = new CreateBundleExeCommand(this.Messaging, this.BackendHelper, this.IntermediateFolder, this.OutputPath, bundleApplicationDllSymbol, bundleSymbol, uxContainer, containers.Values);
513
+ var command = new CreateBundleExeCommand(this.Messaging, this.FileSystem, this.BackendHelper, this.IntermediateFolder, this.OutputPath, bundleApplicationDllSymbol, bundleSymbol, uxContainer, containers.Values);
514
command.Execute();
515
516
fileTransfers.Add(command.Transfer);
src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs
+12
-11
@@ -27,16 +27,19 @@ namespace WixToolset.Core.Burn.Bundles
27
28
private BinaryReader binaryReader;
29
private readonly List<DictionaryEntry> attachedContainerPayloadNames;
30
+ private readonly IFileSystem fileSystem;
31
32
/// <summary>
33
/// Creates a BurnReader for reading a PE file.
34
/// </summary>
34
- /// <param name="messaging"></param>
35
+ /// <param name="messaging">Messaging.</param>
36
+ /// <param name="fileSystem">File system.</param>
37
/// <param name="fileExe">File to read.</param>
36
- private BurnReader(IMessaging messaging, string fileExe)
38
+ private BurnReader(IMessaging messaging, IFileSystem fileSystem, string fileExe)
39
: base(messaging, fileExe)
40
{
41
this.attachedContainerPayloadNames = new List<DictionaryEntry>();
42
+ this.fileSystem = fileSystem;
43
}
44
45
/// <summary>
@@ -47,13 +50,14 @@ namespace WixToolset.Core.Burn.Bundles
50
/// <summary>
51
/// Opens a Burn reader.
52
/// </summary>
50
- /// <param name="messaging"></param>
53
+ /// <param name="messaging">Messaging.</param>
54
+ /// <param name="fileSystem">File system.</param>
55
/// <param name="fileExe">Path to file.</param>
56
/// <returns>Burn reader.</returns>
53
- public static BurnReader Open(IMessaging messaging, string fileExe)
57
+ public static BurnReader Open(IMessaging messaging, IFileSystem fileSystem, string fileExe)
58
{
59
var binaryReader = new BinaryReader(File.Open(fileExe, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete));
56
- var reader = new BurnReader(messaging, fileExe)
60
+ var reader = new BurnReader(messaging, fileSystem, fileExe)
61
{
62
binaryReader = binaryReader,
63
};
@@ -96,8 +100,7 @@ namespace WixToolset.Core.Burn.Bundles
100
var cabinet = new Cabinet(tempCabPath);
101
cabinet.Extract(outputDirectory);
102
99
- Directory.CreateDirectory(Path.GetDirectoryName(manifestPath));
100
- FileSystem.MoveFile(manifestOriginalPath, manifestPath);
103
+ this.fileSystem.MoveFile(manifestOriginalPath, manifestPath);
104
105
var document = new XmlDocument();
106
document.Load(manifestPath);
@@ -114,8 +117,7 @@ namespace WixToolset.Core.Burn.Bundles
117
var sourcePath = Path.Combine(outputDirectory, sourcePathNode.Value);
118
var destinationPath = Path.Combine(outputDirectory, filePathNode.Value);
119
117
- Directory.CreateDirectory(Path.GetDirectoryName(destinationPath));
118
- FileSystem.MoveFile(sourcePath, destinationPath);
120
+ this.fileSystem.MoveFile(sourcePath, destinationPath);
121
}
122
123
foreach (XmlNode payload in payloads)
@@ -183,8 +185,7 @@ namespace WixToolset.Core.Burn.Bundles
185
var sourcePath = Path.Combine(outputDirectory, (string)entry.Key);
186
var destinationPath = Path.Combine(outputDirectory, (string)entry.Value);
187
186
- Directory.CreateDirectory(Path.GetDirectoryName(destinationPath));
187
- FileSystem.MoveFile(sourcePath, destinationPath);
188
+ this.fileSystem.MoveFile(sourcePath, destinationPath);
189
}
190
191
return true;
src/wix/WixToolset.Core.Burn/Bundles/CreateBundleExeCommand.cs
+5
-3
@@ -9,7 +9,6 @@ namespace WixToolset.Core.Burn.Bundles
9
using System.Runtime.InteropServices;
10
using System.Text;
11
using System.Xml;
12
- using WixToolset.Core.Native;
12
using WixToolset.Data;
13
using WixToolset.Data.Burn;
14
using WixToolset.Data.Symbols;
@@ -19,9 +18,10 @@ namespace WixToolset.Core.Burn.Bundles
18
19
internal class CreateBundleExeCommand
20
{
22
- public CreateBundleExeCommand(IMessaging messaging, IBackendHelper backendHelper, string intermediateFolder, string outputPath, WixBootstrapperApplicationDllSymbol bootstrapperApplicationDllSymbol, WixBundleSymbol bundleSymbol, WixBundleContainerSymbol uxContainer, IEnumerable<WixBundleContainerSymbol> containers)
21
+ public CreateBundleExeCommand(IMessaging messaging, IFileSystem fileSystem, IBackendHelper backendHelper, string intermediateFolder, string outputPath, WixBootstrapperApplicationDllSymbol bootstrapperApplicationDllSymbol, WixBundleSymbol bundleSymbol, WixBundleContainerSymbol uxContainer, IEnumerable<WixBundleContainerSymbol> containers)
22
{
23
this.Messaging = messaging;
24
+ this.FileSystem = fileSystem;
25
this.BackendHelper = backendHelper;
26
this.IntermediateFolder = intermediateFolder;
27
this.OutputPath = outputPath;
@@ -35,6 +35,8 @@ namespace WixToolset.Core.Burn.Bundles
35
36
private IMessaging Messaging { get; }
37
38
+ private IFileSystem FileSystem { get; }
39
+
40
private IBackendHelper BackendHelper { get; }
41
42
private string IntermediateFolder { get; }
@@ -68,7 +70,7 @@ namespace WixToolset.Core.Burn.Bundles
70
71
this.Transfer = this.BackendHelper.CreateFileTransfer(bundleTempPath, this.OutputPath, true, this.BundleSymbol.SourceLineNumbers);
72
71
- FileSystem.CopyFile(stubFile, bundleTempPath, allowHardlink: false);
73
+ this.FileSystem.CopyFile(stubFile, bundleTempPath, allowHardlink: false);
74
File.SetAttributes(bundleTempPath, FileAttributes.Normal);
75
76
var fourPartVersion = this.GetFourPartVersion(this.BundleSymbol);
src/wix/WixToolset.Core.Burn/Bundles/HarvestBundlePackageCommand.cs
+4
-1
@@ -18,6 +18,7 @@ namespace WixToolset.Core.Burn.Bundles
18
public HarvestBundlePackageCommand(IServiceProvider serviceProvider, IEnumerable<IBurnBackendBinderExtension> backendExtensions, string intermediateFolder, WixBundlePayloadSymbol payloadSymbol, WixBundleBundlePackagePayloadSymbol packagePayloadSymbol, Dictionary<string, WixBundlePayloadSymbol> packagePayloadsById)
19
{
20
this.Messaging = serviceProvider.GetService<IMessaging>();
21
+ this.FileSystem = serviceProvider.GetService<IFileSystem>();
22
this.BackendHelper = serviceProvider.GetService<IBackendHelper>();
23
this.BackendExtensions = backendExtensions;
24
this.IntermediateFolder = intermediateFolder;
@@ -29,6 +30,8 @@ namespace WixToolset.Core.Burn.Bundles
30
31
private IMessaging Messaging { get; }
32
33
+ private IFileSystem FileSystem { get; }
34
+
35
private IBackendHelper BackendHelper { get; }
36
37
private IEnumerable<IBurnBackendBinderExtension> BackendExtensions { get; }
@@ -66,7 +69,7 @@ namespace WixToolset.Core.Burn.Bundles
69
var sourcePath = this.PackagePayload.SourceFile.Path;
70
var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
71
69
- using (var burnReader = BurnReader.Open(this.Messaging, sourcePath))
72
+ using (var burnReader = BurnReader.Open(this.Messaging, this.FileSystem, sourcePath))
73
{
74
if (burnReader.Invalid)
75
{
src/wix/WixToolset.Core.Burn/CommandLine/ExtractSubcommand.cs
+4
-5
@@ -7,21 +7,20 @@ namespace WixToolset.Core.Burn.CommandLine
7
using System.Threading;
8
using System.Threading.Tasks;
9
using WixToolset.Core.Burn.Bundles;
10
- using WixToolset.Core.Burn.Inscribe;
10
using WixToolset.Extensibility.Services;
11
12
internal class ExtractSubcommand : BurnSubcommandBase
13
{
14
public ExtractSubcommand(IServiceProvider serviceProvider)
15
{
17
- this.ServiceProvider = serviceProvider;
16
this.Messaging = serviceProvider.GetService<IMessaging>();
17
+ this.FileSystem = serviceProvider.GetService<IFileSystem>();
18
}
19
21
- private IServiceProvider ServiceProvider { get; }
22
-
20
private IMessaging Messaging { get; }
21
22
+ private IFileSystem FileSystem { get; }
23
+
24
private string InputPath { get; set; }
25
26
private string IntermediateFolder { get; set; }
@@ -49,7 +48,7 @@ namespace WixToolset.Core.Burn.CommandLine
48
49
var uxExtractPath = Path.Combine(this.ExtractPath, "BA");
50
52
- using (var reader = BurnReader.Open(this.Messaging, this.InputPath))
51
+ using (var reader = BurnReader.Open(this.Messaging, this.FileSystem, this.InputPath))
52
{
53
reader.ExtractUXContainer(uxExtractPath, this.IntermediateFolder);
54
src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleCommand.cs
+6
-6
@@ -5,7 +5,6 @@ namespace WixToolset.Core.Burn.Inscribe
5
using System;
6
using System.IO;
7
using WixToolset.Core.Burn.Bundles;
8
- using WixToolset.Core.Native;
8
using WixToolset.Extensibility.Services;
9
10
internal class InscribeBundleCommand
@@ -13,6 +12,7 @@ namespace WixToolset.Core.Burn.Inscribe
12
public InscribeBundleCommand(IServiceProvider serviceProvider, string inputPath, string signedEngineFile, string outputPath, string intermediateFolder)
13
{
14
this.Messaging = serviceProvider.GetService<IMessaging>();
15
+ this.FileSystem = serviceProvider.GetService<IFileSystem>();
16
this.IntermediateFolder = intermediateFolder;
17
this.InputFilePath = inputPath;
18
this.SignedEngineFile = signedEngineFile;
@@ -21,6 +21,8 @@ namespace WixToolset.Core.Burn.Inscribe
21
22
private IMessaging Messaging { get; }
23
24
+ private IFileSystem FileSystem { get; }
25
+
26
private string IntermediateFolder { get; }
27
28
private string InputFilePath { get; }
@@ -34,9 +36,9 @@ namespace WixToolset.Core.Burn.Inscribe
36
var inscribed = false;
37
var tempFile = Path.Combine(this.IntermediateFolder, "~bundle_engine_signed.exe");
38
37
- using (var reader = BurnReader.Open(this.Messaging, this.InputFilePath))
39
+ using (var reader = BurnReader.Open(this.Messaging, this.FileSystem, this.InputFilePath))
40
{
39
- FileSystem.CopyFile(this.SignedEngineFile, tempFile, allowHardlink: false);
41
+ this.FileSystem.CopyFile(this.SignedEngineFile, tempFile, allowHardlink: false);
42
43
using (var writer = BurnWriter.Open(this.Messaging, tempFile))
44
{
@@ -44,9 +46,7 @@ namespace WixToolset.Core.Burn.Inscribe
46
}
47
}
48
47
- Directory.CreateDirectory(Path.GetDirectoryName(this.OutputFile));
48
-
49
- FileSystem.MoveFile(tempFile, this.OutputFile);
49
+ this.FileSystem.MoveFile(tempFile, this.OutputFile);
50
51
return inscribed;
52
}
src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleEngineCommand.cs
+5
-5
@@ -5,7 +5,6 @@ namespace WixToolset.Core.Burn.Inscribe
5
using System;
6
using System.IO;
7
using WixToolset.Core.Burn.Bundles;
8
- using WixToolset.Core.Native;
8
using WixToolset.Extensibility.Services;
9
10
internal class InscribeBundleEngineCommand
@@ -13,6 +12,7 @@ namespace WixToolset.Core.Burn.Inscribe
12
public InscribeBundleEngineCommand(IServiceProvider serviceProvider, string inputPath, string outputPath, string intermediateFolder)
13
{
14
this.Messaging = serviceProvider.GetService<IMessaging>();
15
+ this.FileSystem = serviceProvider.GetService<IFileSystem>();
16
this.IntermediateFolder = intermediateFolder;
17
this.InputFilePath = inputPath;
18
this.OutputFile = outputPath;
@@ -20,6 +20,8 @@ namespace WixToolset.Core.Burn.Inscribe
20
21
private IMessaging Messaging { get; }
22
23
+ private IFileSystem FileSystem { get; }
24
+
25
private string IntermediateFolder { get; }
26
27
private string InputFilePath { get; }
@@ -30,7 +32,7 @@ namespace WixToolset.Core.Burn.Inscribe
32
{
33
var tempFile = Path.Combine(this.IntermediateFolder, "bundle_engine_unsigned.exe");
34
33
- using (var reader = BurnReader.Open(this.Messaging, this.InputFilePath))
35
+ using (var reader = BurnReader.Open(this.Messaging, this.FileSystem, this.InputFilePath))
36
using (var writer = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read | FileShare.Delete))
37
{
38
reader.Stream.Seek(0, SeekOrigin.Begin);
@@ -56,9 +58,7 @@ namespace WixToolset.Core.Burn.Inscribe
58
// TODO: update writer with detached container signatures.
59
}
60
59
- Directory.CreateDirectory(Path.GetDirectoryName(this.OutputFile));
60
-
61
- FileSystem.MoveFile(tempFile, this.OutputFile);
61
+ this.FileSystem.MoveFile(tempFile, this.OutputFile);
62
}
63
}
64
}
src/wix/WixToolset.Core.Native/DateTimeInterop.cs
+2
-2
@@ -20,8 +20,8 @@ namespace WixToolset.Core.Native
20
{
21
// dateTime.ToLocalTime() does not match FileTimeToLocalFileTime() for some reason.
22
// so we need to call FileTimeToLocalFileTime() from kernel32.dll.
23
- long filetime = dateTime.ToFileTime();
24
- long localTime = 0;
23
+ var filetime = dateTime.ToFileTime();
24
+ var localTime = 0L;
25
FileTimeToLocalFileTime(ref filetime, ref localTime);
26
FileTimeToDosDateTime(ref localTime, out cabDate, out cabTime);
27
}
src/wix/WixToolset.Core.Native/WixToolset.Core.Native.csproj
-1
@@ -24,6 +24,5 @@
24
25
<ItemGroup>
26
<PackageReference Include="WixToolset.Data" />
27
- <PackageReference Include="System.IO.FileSystem.AccessControl" />
27
</ItemGroup>
28
</Project>
src/wix/WixToolset.Core.TestPackage/BundleExtractor.cs
+16
-1
@@ -39,7 +39,7 @@ namespace WixToolset.Core.TestPackage
39
{
40
var result = new ExtractBAContainerResult();
41
Directory.CreateDirectory(tempFolderPath);
42
- using (var burnReader = BurnReader.Open(messaging, bundleFilePath))
42
+ using (var burnReader = BurnReader.Open(messaging, new TestFileSystem(), bundleFilePath))
43
{
44
result.Success = burnReader.ExtractUXContainer(baFolderPath, tempFolderPath);
45
@@ -138,5 +138,20 @@ namespace WixToolset.Core.TestPackage
138
document.Load(Path.Combine(baFolderPath, "manifest.xml"));
139
return document;
140
}
141
+
142
+ private class TestFileSystem : IFileSystem
143
+ {
144
+ public void CopyFile(string source, string destination, bool allowHardlink)
145
+ {
146
+ Directory.CreateDirectory(Path.GetDirectoryName(destination));
147
+ File.Copy(source, destination);
148
+ }
149
+
150
+ public void MoveFile(string source, string destination)
151
+ {
152
+ Directory.CreateDirectory(Path.GetDirectoryName(destination));
153
+ File.Move(source, destination);
154
+ }
155
+ }
156
}
157
}
src/wix/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs
+19
-3
@@ -71,10 +71,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
71
{
72
merge = MsmInterop.GetMsmMerge();
73
74
- FileSystem.ActionWithRetries(() => merge.OpenLog(logPath));
74
+ ActionWithRetries(() => merge.OpenLog(logPath));
75
logOpen = true;
76
77
- FileSystem.ActionWithRetries(() => merge.OpenDatabase(this.OutputPath));
77
+ ActionWithRetries(() => merge.OpenDatabase(this.OutputPath));
78
databaseOpen = true;
79
80
var featureModulesByMergeId = this.Section.Symbols.OfType<WixFeatureModulesSymbol>().GroupBy(t => t.WixMergeRef).ToDictionary(g => g.Key);
@@ -99,7 +99,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
99
}
100
101
this.Messaging.Write(VerboseMessages.OpeningMergeModule(wixMergeRow.SourceFile, mergeLanguage));
102
- FileSystem.ActionWithRetries(() => merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage));
102
+ ActionWithRetries(() => merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage));
103
moduleOpen = true;
104
105
trackedFiles.Add(this.BackendHelper.TrackFile(wixMergeRow.SourceFile, TrackedFileType.Input, wixMergeRow.SourceLineNumbers));
@@ -340,5 +340,21 @@ namespace WixToolset.Core.WindowsInstaller.Bind
340
341
this.TrackedFiles = trackedFiles;
342
}
343
+
344
+ internal static void ActionWithRetries(Action action, int maxRetries = 3)
345
+ {
346
+ for (var attempt = 1; attempt <= maxRetries; ++attempt)
347
+ {
348
+ try
349
+ {
350
+ action();
351
+ break;
352
+ }
353
+ catch when (attempt < maxRetries)
354
+ {
355
+ Thread.Sleep(250);
356
+ }
357
+ }
358
+ }
359
}
360
}
src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs
+4
-1
@@ -16,10 +16,13 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
16
public ValidateSubcommand(IServiceProvider serviceProvider)
17
{
18
this.Messaging = serviceProvider.GetService<IMessaging>();
19
+ this.FileSystem = serviceProvider.GetService<IFileSystem>();
20
}
21
22
private IMessaging Messaging { get; }
23
24
+ private IFileSystem FileSystem { get; }
25
+
26
private string DatabasePath { get; set; }
27
28
private string WixpdbPath { get; set; }
@@ -76,7 +79,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
79
data = WindowsInstallerData.Load(this.WixpdbPath);
80
}
81
79
- var command = new ValidateDatabaseCommand(this.Messaging, this.IntermediateFolder, this.DatabasePath, data, this.CubeFiles, this.Ices, this.SuppressIces);
82
+ var command = new ValidateDatabaseCommand(this.Messaging, this.FileSystem, this.IntermediateFolder, this.DatabasePath, data, this.CubeFiles, this.Ices, this.SuppressIces);
83
command.Execute();
84
85
return Task.FromResult(this.Messaging.EncounteredError ? 1 : 0);
src/wix/WixToolset.Core.WindowsInstaller/Validate/ValidateDatabaseCommand.cs
+5
-2
@@ -18,9 +18,10 @@ namespace WixToolset.Core.WindowsInstaller.Validate
18
// Set of ICEs that have equivalent-or-better checks in WiX.
19
private static readonly string[] WellKnownSuppressedIces = new[] { "ICE08", "ICE33", "ICE47", "ICE66" };
20
21
- public ValidateDatabaseCommand(IMessaging messaging, string intermediateFolder, string databasePath, WindowsInstallerData data, IEnumerable<string> cubeFiles, IEnumerable<string> ices, IEnumerable<string> suppressedIces)
21
+ public ValidateDatabaseCommand(IMessaging messaging, IFileSystem fileSystem, string intermediateFolder, string databasePath, WindowsInstallerData data, IEnumerable<string> cubeFiles, IEnumerable<string> ices, IEnumerable<string> suppressedIces)
22
{
23
this.Messaging = messaging;
24
+ this.FileSystem = fileSystem;
25
this.Data = data;
26
this.DatabasePath = databasePath;
27
this.CubeFiles = cubeFiles;
@@ -40,6 +41,8 @@ namespace WixToolset.Core.WindowsInstaller.Validate
41
42
private IMessaging Messaging { get; }
43
44
+ private IFileSystem FileSystem { get; }
45
+
46
private WindowsInstallerData Data { get; }
47
48
private string DatabasePath { get; }
@@ -71,7 +74,7 @@ namespace WixToolset.Core.WindowsInstaller.Validate
74
var workingDatabasePath = Path.Combine(this.IntermediateFolder, workingDatabaseFilename);
75
try
76
{
74
- FileSystem.CopyFile(this.DatabasePath, workingDatabasePath, allowHardlink: false);
77
+ this.FileSystem.CopyFile(this.DatabasePath, workingDatabasePath, allowHardlink: false);
78
79
var attributes = File.GetAttributes(workingDatabasePath);
80
File.SetAttributes(workingDatabasePath, attributes & ~FileAttributes.ReadOnly);
src/wix/WixToolset.Core/Bind/TransferFilesCommand.cs
+20
-5
@@ -5,7 +5,7 @@ namespace WixToolset.Core.Bind
5
using System;
6
using System.Collections.Generic;
7
using System.IO;
8
- using WixToolset.Core.Native;
8
+ using System.Security.AccessControl;
9
using WixToolset.Data;
10
using WixToolset.Extensibility;
11
using WixToolset.Extensibility.Data;
@@ -13,16 +13,19 @@ namespace WixToolset.Core.Bind
13
14
internal class TransferFilesCommand
15
{
16
- public TransferFilesCommand(IMessaging messaging, IEnumerable<ILayoutExtension> extensions, IEnumerable<IFileTransfer> fileTransfers, bool resetAcls)
16
+ public TransferFilesCommand(IMessaging messaging, IFileSystem fileSystem, IEnumerable<ILayoutExtension> extensions, IEnumerable<IFileTransfer> fileTransfers, bool resetAcls)
17
{
18
this.Extensions = extensions;
19
this.Messaging = messaging;
20
+ this.FileSystem = fileSystem;
21
this.FileTransfers = fileTransfers;
22
this.ResetAcls = resetAcls;
23
}
24
25
private IMessaging Messaging { get; }
26
27
+ private IFileSystem FileSystem { get; }
28
+
29
private IEnumerable<ILayoutExtension> Extensions { get; }
30
31
private IEnumerable<IFileTransfer> FileTransfers { get; }
@@ -158,7 +161,7 @@ namespace WixToolset.Core.Bind
161
{
162
try
163
{
161
- FileSystem.ResetAcls(destinationFiles);
164
+ this.AclReset(destinationFiles);
165
}
166
catch (Exception e)
167
{
@@ -177,7 +180,7 @@ namespace WixToolset.Core.Bind
180
}
181
}
182
180
- FileSystem.CopyFile(source, destination, allowHardlink: true);
183
+ this.FileSystem.CopyFile(source, destination, allowHardlink: true);
184
}
185
186
private void MoveFile(string source, string destination)
@@ -190,7 +193,19 @@ namespace WixToolset.Core.Bind
193
}
194
}
195
193
- FileSystem.MoveFile(source, destination);
196
+ this.FileSystem.MoveFile(source, destination);
197
+ }
198
+
199
+ private void AclReset(IEnumerable<string> files)
200
+ {
201
+ var aclReset = new FileSecurity();
202
+ aclReset.SetAccessRuleProtection(false, false);
203
+
204
+ foreach (var file in files)
205
+ {
206
+ var fileInfo = new FileInfo(file);
207
+ ExtensibilityServices.FileSystem.ActionWithRetries(() => fileInfo.SetAccessControl(aclReset));
208
+ }
209
}
210
}
211
}
src/wix/WixToolset.Core/ExtensibilityServices/FileSystem.cs
renamed
+6
-37
@@ -1,26 +1,16 @@
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.Native
3
+namespace WixToolset.Core.ExtensibilityServices
4
{
5
using System;
6
- using System.Collections.Generic;
6
using System.IO;
7
using System.Runtime.InteropServices;
9
- using System.Security.AccessControl;
8
using System.Threading;
9
+ using WixToolset.Extensibility.Services;
10
12
- /// <summary>
13
- /// File system helpers.
14
- /// </summary>
15
- public static class FileSystem
11
+ internal class FileSystem : IFileSystem
12
{
17
- /// <summary>
18
- /// Copies a file.
19
- /// </summary>
20
- /// <param name="source">The file to copy.</param>
21
- /// <param name="destination">The destination file.</param>
22
- /// <param name="allowHardlink">Allow hardlinks.</param>
23
- public static void CopyFile(string source, string destination, bool allowHardlink)
13
+ public void CopyFile(string source, string destination, bool allowHardlink)
14
{
15
EnsureDirectoryWithoutFile(destination);
16
@@ -41,34 +31,13 @@ namespace WixToolset.Core.Native
31
}
32
}
33
44
- /// <summary>
45
- /// Moves a file.
46
- /// </summary>
47
- /// <param name="source">The file to move.</param>
48
- /// <param name="destination">The destination file.</param>
49
- public static void MoveFile(string source, string destination)
34
+ public void MoveFile(string source, string destination)
35
{
36
EnsureDirectoryWithoutFile(destination);
37
38
ActionWithRetries(() => File.Move(source, destination));
39
}
40
56
- /// <summary>
57
- /// Reset the ACLs on a set of files.
58
- /// </summary>
59
- /// <param name="files">The list of file paths to set ACLs.</param>
60
- public static void ResetAcls(IEnumerable<string> files)
61
- {
62
- var aclReset = new FileSecurity();
63
- aclReset.SetAccessRuleProtection(false, false);
64
-
65
- foreach (var file in files)
66
- {
67
- var fileInfo = new FileInfo(file);
68
- ActionWithRetries(() => fileInfo.SetAccessControl(aclReset));
69
- }
70
- }
71
-
41
/// <summary>
42
/// Executes an action and retries on any exception up to a few times. Primarily
43
/// intended for use with file system operations that might get interrupted by
@@ -76,7 +45,7 @@ namespace WixToolset.Core.Native
45
/// </summary>
46
/// <param name="action">Action to execute.</param>
47
/// <param name="maxRetries">Maximum retry attempts.</param>
79
- public static void ActionWithRetries(Action action, int maxRetries = 3)
48
+ internal static void ActionWithRetries(Action action, int maxRetries = 3)
49
{
50
for (var attempt = 1; attempt <= maxRetries; ++attempt)
51
{
src/wix/WixToolset.Core/LayoutCreator.cs
+4
-1
@@ -21,10 +21,13 @@ namespace WixToolset.Core
21
internal LayoutCreator(IServiceProvider serviceProvider)
22
{
23
this.Messaging = serviceProvider.GetService<IMessaging>();
24
+ this.FileSystem = serviceProvider.GetService<IFileSystem>();
25
}
26
27
private IMessaging Messaging { get; }
28
29
+ private IFileSystem FileSystem { get; }
30
+
31
public void Layout(ILayoutContext context)
32
{
33
// Pre-layout.
@@ -42,7 +45,7 @@ namespace WixToolset.Core
45
{
46
this.Messaging.Write(VerboseMessages.LayingOutMedia());
47
45
- var command = new TransferFilesCommand(this.Messaging, context.Extensions, context.FileTransfers, context.ResetAcls);
48
+ var command = new TransferFilesCommand(this.Messaging, this.FileSystem, context.Extensions, context.FileTransfers, context.ResetAcls);
49
command.Execute();
50
}
51
src/wix/WixToolset.Core/WixToolset.Core.csproj
+1
-8
@@ -14,20 +14,13 @@
14
<GitThisAssembly>true</GitThisAssembly>
15
</PropertyGroup>
16
17
- <ItemGroup>
18
- <ProjectReference Include="..\WixToolset.Core.Native\WixToolset.Core.Native.csproj" />
19
- </ItemGroup>
20
-
17
<ItemGroup>
18
<PackageReference Include="WixToolset.Data" />
19
<PackageReference Include="WixToolset.Extensibility" />
20
</ItemGroup>
21
26
- <!--
27
- These package references are duplicated in WixToolset.Core.TestPackage.csproj. If
28
- you update these here, be sure to update them there.
29
- -->
22
<ItemGroup>
23
+ <PackageReference Include="System.IO.FileSystem.AccessControl" />
24
<PackageReference Include="System.Text.Encoding.CodePages" />
25
<PackageReference Include="NuGet.Versioning" />
26
</ItemGroup>
src/wix/WixToolset.Core/WixToolsetServiceProvider.cs
+1
@@ -27,6 +27,7 @@ namespace WixToolset.Core
27
this.AddService((provider, singletons) => AddSingleton<ILayoutServices>(singletons, new LayoutServices(provider)));
28
this.AddService((provider, singletons) => AddSingleton<IBackendHelper>(singletons, new BackendHelper(provider)));
29
this.AddService((provider, singletons) => AddSingleton<IPathResolver>(singletons, new PathResolver()));
30
+ this.AddService((provider, singletons) => AddSingleton<IFileSystem>(singletons, new FileSystem()));
31
this.AddService((provider, singletons) => AddSingleton<IWixBranding>(singletons, new WixBranding()));
32
33
// Transients.