From 2a27f9032aa115bc2f88d9be695d9b049db1a894 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Sat, 11 Aug 2018 01:06:40 -0700 Subject: Track files to enable clean builds in MSBuild --- src/WixToolset.Core/CommandLine/BuildCommand.cs | 3 +- .../ExtensibilityServices/BackendHelper.cs | 12 +- src/WixToolset.Core/FileTransfer.cs | 2 - src/WixToolset.Core/Layout.cs | 140 ++++++++++++++++----- src/WixToolset.Core/LayoutContext.cs | 2 +- src/WixToolset.Core/TrackedFile.cs | 26 ++++ 6 files changed, 148 insertions(+), 37 deletions(-) create mode 100644 src/WixToolset.Core/TrackedFile.cs (limited to 'src/WixToolset.Core') diff --git a/src/WixToolset.Core/CommandLine/BuildCommand.cs b/src/WixToolset.Core/CommandLine/BuildCommand.cs index 5c089b5f..b460e48f 100644 --- a/src/WixToolset.Core/CommandLine/BuildCommand.cs +++ b/src/WixToolset.Core/CommandLine/BuildCommand.cs @@ -276,8 +276,9 @@ namespace WixToolset.Core.CommandLine { var layout = new Layout(this.ServiceProvider); + layout.TrackedFiles = bindResult.TrackedFiles; layout.FileTransfers = bindResult.FileTransfers; - layout.ContentFilePaths = bindResult.ContentFilePaths; + layout.IntermediateFolder = this.IntermediateFolder; layout.ContentsFile = this.ContentsFile; layout.OutputsFile = this.OutputsFile; layout.BuiltOutputsFile = this.BuiltOutputsFile; diff --git a/src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs b/src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs index 0cda4437..6cc91487 100644 --- a/src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs +++ b/src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs @@ -19,18 +19,17 @@ namespace WixToolset.Core.ExtensibilityServices private IMessaging Messaging { get; } - public IFileTransfer CreateFileTransfer(string source, string destination, bool move, FileTransferType type, SourceLineNumber sourceLineNumbers) + public IFileTransfer CreateFileTransfer(string source, string destination, bool move, SourceLineNumber sourceLineNumbers = null) { - var sourceFullPath = GetValidatedFullPath(sourceLineNumbers, source); + var sourceFullPath = this.GetValidatedFullPath(sourceLineNumbers, source); - var destinationFullPath = GetValidatedFullPath(sourceLineNumbers, destination); + var destinationFullPath = this.GetValidatedFullPath(sourceLineNumbers, destination); return (String.IsNullOrEmpty(sourceFullPath) || String.IsNullOrEmpty(destinationFullPath)) ? null : new FileTransfer { Source = sourceFullPath, Destination = destinationFullPath, Move = move, - Type = type, SourceLineNumbers = sourceLineNumbers, Redundant = String.Equals(sourceFullPath, destinationFullPath, StringComparison.OrdinalIgnoreCase) }; @@ -41,6 +40,11 @@ namespace WixToolset.Core.ExtensibilityServices return Uuid.NewUuid(namespaceGuid, value).ToString("B").ToUpperInvariant(); } + public ITrackedFile TrackFile(string path, TrackedFileType type, SourceLineNumber sourceLineNumbers = null) + { + return new TrackedFile(path, type, sourceLineNumbers); + } + private string GetValidatedFullPath(SourceLineNumber sourceLineNumbers, string path) { try diff --git a/src/WixToolset.Core/FileTransfer.cs b/src/WixToolset.Core/FileTransfer.cs index 9da406eb..7f9ed0f3 100644 --- a/src/WixToolset.Core/FileTransfer.cs +++ b/src/WixToolset.Core/FileTransfer.cs @@ -15,8 +15,6 @@ namespace WixToolset.Core public SourceLineNumber SourceLineNumbers { get; set; } - public FileTransferType Type { get; set; } - public bool Redundant { get; set; } } } diff --git a/src/WixToolset.Core/Layout.cs b/src/WixToolset.Core/Layout.cs index 128efc61..b1b03aa7 100644 --- a/src/WixToolset.Core/Layout.cs +++ b/src/WixToolset.Core/Layout.cs @@ -28,9 +28,11 @@ namespace WixToolset.Core private IMessaging Messaging { get; } + public IEnumerable TrackedFiles { get; set; } + public IEnumerable FileTransfers { get; set; } - public IEnumerable ContentFilePaths { get; set; } + public string IntermediateFolder { get; set; } public string ContentsFile { get; set; } @@ -46,8 +48,8 @@ namespace WixToolset.Core var context = this.ServiceProvider.GetService(); context.Extensions = extensionManager.Create(); + context.TrackedFiles = this.TrackedFiles; context.FileTransfers = this.FileTransfers; - context.ContentFilePaths = this.ContentFilePaths; context.ContentsFile = this.ContentsFile; context.OutputsFile = this.OutputsFile; context.BuiltOutputsFile = this.BuiltOutputsFile; @@ -71,24 +73,29 @@ namespace WixToolset.Core var command = new TransferFilesCommand(this.Messaging, context.Extensions, context.FileTransfers, context.SuppressAclReset); command.Execute(); } + + if (context.TrackedFiles != null) + { + this.CleanTempFiles(context.TrackedFiles); + } } finally { - if (!String.IsNullOrEmpty(context.ContentsFile) && context.ContentFilePaths != null) + if (context.TrackedFiles != null) { - this.CreateContentsFile(context.ContentsFile, context.ContentFilePaths); - } + if (!String.IsNullOrEmpty(context.ContentsFile)) + { + this.CreateContentsFile(context.ContentsFile, context.TrackedFiles); + } - if (context.FileTransfers != null) - { if (!String.IsNullOrEmpty(context.OutputsFile)) { - this.CreateOutputsFile(context.OutputsFile, context.FileTransfers); + this.CreateOutputsFile(context.OutputsFile, context.TrackedFiles); } if (!String.IsNullOrEmpty(context.BuiltOutputsFile)) { - this.CreateBuiltOutputsFile(context.BuiltOutputsFile, context.FileTransfers); + this.CreateBuiltOutputsFile(context.BuiltOutputsFile, context.TrackedFiles); } } } @@ -105,16 +112,23 @@ namespace WixToolset.Core /// /// Path to write file. /// Collection of paths to content files that will be written to file. - private void CreateContentsFile(string path, IEnumerable contentFilePaths) + private void CreateContentsFile(string path, IEnumerable trackedFiles) { + var uniqueInputFilePaths = new SortedSet(trackedFiles.Where(t => t.Type == TrackedFileType.Input).Select(t => t.Path), StringComparer.OrdinalIgnoreCase); + + if (!uniqueInputFilePaths.Any()) + { + return; + } + var directory = Path.GetDirectoryName(path); Directory.CreateDirectory(directory); using (var contents = new StreamWriter(path, false)) { - foreach (string contentPath in contentFilePaths) + foreach (string inputPath in uniqueInputFilePaths) { - contents.WriteLine(contentPath); + contents.WriteLine(inputPath); } } } @@ -124,22 +138,28 @@ namespace WixToolset.Core /// /// Path to write file. /// Collection of files that were transferred to the output directory. - private void CreateOutputsFile(string path, IEnumerable fileTransfers) + private void CreateOutputsFile(string path, IEnumerable trackedFiles) { + var uniqueOutputPaths = new SortedSet(trackedFiles.Where(t => t.Clean).Select(t => t.Path), StringComparer.OrdinalIgnoreCase); + + if (!uniqueOutputPaths.Any()) + { + return; + } + var directory = Path.GetDirectoryName(path); Directory.CreateDirectory(directory); using (var outputs = new StreamWriter(path, false)) { - foreach (var fileTransfer in fileTransfers) + //// Don't list files where the source is the same as the destination since + //// that might be the only place the file exists. The outputs file is often + //// used to delete stuff and losing the original source would be bad. + //var uniqueOutputPaths = new SortedSet(fileTransfers.Where(ft => !ft.Redundant).Select(ft => ft.Destination), StringComparer.OrdinalIgnoreCase); + + foreach (var outputPath in uniqueOutputPaths) { - // Don't list files where the source is the same as the destination since - // that might be the only place the file exists. The outputs file is often - // used to delete stuff and losing the original source would be bad. - if (!fileTransfer.Redundant) - { - outputs.WriteLine(fileTransfer.Destination); - } + outputs.WriteLine(outputPath); } } } @@ -149,21 +169,83 @@ namespace WixToolset.Core /// /// Path to write file. /// Collection of files that were transferred to the output directory. - private void CreateBuiltOutputsFile(string path, IEnumerable fileTransfers) + private void CreateBuiltOutputsFile(string path, IEnumerable trackedFiles) { + var uniqueBuiltPaths = new SortedSet(trackedFiles.Where(t => t.Type == TrackedFileType.Final).Select(t => t.Path), StringComparer.OrdinalIgnoreCase); + + if (!uniqueBuiltPaths.Any()) + { + return; + } + var directory = Path.GetDirectoryName(path); Directory.CreateDirectory(directory); using (var outputs = new StreamWriter(path, false)) { - foreach (var fileTransfer in fileTransfers) + foreach (var builtPath in uniqueBuiltPaths) { - // Only write the built file transfers. Also, skip redundant - // files for the same reason spelled out in this.CreateOutputsFile(). - if (fileTransfer.Type == FileTransferType.Built && !fileTransfer.Redundant) - { - outputs.WriteLine(fileTransfer.Destination); - } + outputs.WriteLine(builtPath); + } + } + } + + private void CleanTempFiles(IEnumerable trackedFiles) + { + var uniqueTempPaths = new SortedSet(trackedFiles.Where(t => t.Type == TrackedFileType.Temporary).Select(t => t.Path), StringComparer.OrdinalIgnoreCase); + + if (!uniqueTempPaths.Any()) + { + return; + } + + var uniqueFolders = new SortedSet(StringComparer.OrdinalIgnoreCase) + { + this.IntermediateFolder + }; + + // Clean up temp files. + foreach (var tempPath in uniqueTempPaths) + { + try + { + this.SplitUniqueFolders(tempPath, uniqueFolders); + + File.Delete(tempPath); + } + catch // delete is best effort. + { + } + } + + // Clean up empty temp folders. + foreach (var folder in uniqueFolders.Reverse()) + { + try + { + Directory.Delete(folder); + } + catch // delete is best effort. + { + } + } + } + + private void SplitUniqueFolders(string tempPath, SortedSet uniqueFolders) + { + if (tempPath.StartsWith(this.IntermediateFolder, StringComparison.OrdinalIgnoreCase)) + { + var folder = Path.GetDirectoryName(tempPath).Substring(this.IntermediateFolder.Length); + + var parts = folder.Split(new[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries); + + folder = this.IntermediateFolder; + + foreach (var part in parts) + { + folder = Path.Combine(folder, part); + + uniqueFolders.Add(folder); } } } diff --git a/src/WixToolset.Core/LayoutContext.cs b/src/WixToolset.Core/LayoutContext.cs index 99ca611a..20d29b5f 100644 --- a/src/WixToolset.Core/LayoutContext.cs +++ b/src/WixToolset.Core/LayoutContext.cs @@ -22,7 +22,7 @@ namespace WixToolset.Core public IEnumerable FileTransfers { get; set; } - public IEnumerable ContentFilePaths { get; set; } + public IEnumerable TrackedFiles { get; set; } public string OutputPdbPath { get; set; } diff --git a/src/WixToolset.Core/TrackedFile.cs b/src/WixToolset.Core/TrackedFile.cs new file mode 100644 index 00000000..312b09f4 --- /dev/null +++ b/src/WixToolset.Core/TrackedFile.cs @@ -0,0 +1,26 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Core +{ + using WixToolset.Data; + using WixToolset.Extensibility.Data; + + internal class TrackedFile : ITrackedFile + { + public TrackedFile(string path, TrackedFileType type, SourceLineNumber sourceLineNumbers) + { + this.Path = path; + this.Type = type; + this.SourceLineNumbers = sourceLineNumbers; + this.Clean = (type == TrackedFileType.Intermediate || type == TrackedFileType.Final); + } + + public bool Clean { get; set; } + + public string Path { get; set; } + + public SourceLineNumber SourceLineNumbers { get; set; } + + public TrackedFileType Type { get; set; } + } +} -- cgit v1.2.3-55-g6feb