aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2018-08-11 01:06:40 -0700
committerRob Mensching <rob@firegiant.com>2018-08-11 01:06:40 -0700
commit2a27f9032aa115bc2f88d9be695d9b049db1a894 (patch)
tree7882bd4c94da118a6fc655a3c22e1dd0cf3b60e1 /src/WixToolset.Core
parentb54516035b4ebbfbd8899b26de501bfa13f53e8b (diff)
downloadwix-2a27f9032aa115bc2f88d9be695d9b049db1a894.tar.gz
wix-2a27f9032aa115bc2f88d9be695d9b049db1a894.tar.bz2
wix-2a27f9032aa115bc2f88d9be695d9b049db1a894.zip
Track files to enable clean builds in MSBuild
Diffstat (limited to 'src/WixToolset.Core')
-rw-r--r--src/WixToolset.Core/CommandLine/BuildCommand.cs3
-rw-r--r--src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs12
-rw-r--r--src/WixToolset.Core/FileTransfer.cs2
-rw-r--r--src/WixToolset.Core/Layout.cs140
-rw-r--r--src/WixToolset.Core/LayoutContext.cs2
-rw-r--r--src/WixToolset.Core/TrackedFile.cs26
6 files changed, 148 insertions, 37 deletions
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
276 276
277 { 277 {
278 var layout = new Layout(this.ServiceProvider); 278 var layout = new Layout(this.ServiceProvider);
279 layout.TrackedFiles = bindResult.TrackedFiles;
279 layout.FileTransfers = bindResult.FileTransfers; 280 layout.FileTransfers = bindResult.FileTransfers;
280 layout.ContentFilePaths = bindResult.ContentFilePaths; 281 layout.IntermediateFolder = this.IntermediateFolder;
281 layout.ContentsFile = this.ContentsFile; 282 layout.ContentsFile = this.ContentsFile;
282 layout.OutputsFile = this.OutputsFile; 283 layout.OutputsFile = this.OutputsFile;
283 layout.BuiltOutputsFile = this.BuiltOutputsFile; 284 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
19 19
20 private IMessaging Messaging { get; } 20 private IMessaging Messaging { get; }
21 21
22 public IFileTransfer CreateFileTransfer(string source, string destination, bool move, FileTransferType type, SourceLineNumber sourceLineNumbers) 22 public IFileTransfer CreateFileTransfer(string source, string destination, bool move, SourceLineNumber sourceLineNumbers = null)
23 { 23 {
24 var sourceFullPath = GetValidatedFullPath(sourceLineNumbers, source); 24 var sourceFullPath = this.GetValidatedFullPath(sourceLineNumbers, source);
25 25
26 var destinationFullPath = GetValidatedFullPath(sourceLineNumbers, destination); 26 var destinationFullPath = this.GetValidatedFullPath(sourceLineNumbers, destination);
27 27
28 return (String.IsNullOrEmpty(sourceFullPath) || String.IsNullOrEmpty(destinationFullPath)) ? null : new FileTransfer 28 return (String.IsNullOrEmpty(sourceFullPath) || String.IsNullOrEmpty(destinationFullPath)) ? null : new FileTransfer
29 { 29 {
30 Source = sourceFullPath, 30 Source = sourceFullPath,
31 Destination = destinationFullPath, 31 Destination = destinationFullPath,
32 Move = move, 32 Move = move,
33 Type = type,
34 SourceLineNumbers = sourceLineNumbers, 33 SourceLineNumbers = sourceLineNumbers,
35 Redundant = String.Equals(sourceFullPath, destinationFullPath, StringComparison.OrdinalIgnoreCase) 34 Redundant = String.Equals(sourceFullPath, destinationFullPath, StringComparison.OrdinalIgnoreCase)
36 }; 35 };
@@ -41,6 +40,11 @@ namespace WixToolset.Core.ExtensibilityServices
41 return Uuid.NewUuid(namespaceGuid, value).ToString("B").ToUpperInvariant(); 40 return Uuid.NewUuid(namespaceGuid, value).ToString("B").ToUpperInvariant();
42 } 41 }
43 42
43 public ITrackedFile TrackFile(string path, TrackedFileType type, SourceLineNumber sourceLineNumbers = null)
44 {
45 return new TrackedFile(path, type, sourceLineNumbers);
46 }
47
44 private string GetValidatedFullPath(SourceLineNumber sourceLineNumbers, string path) 48 private string GetValidatedFullPath(SourceLineNumber sourceLineNumbers, string path)
45 { 49 {
46 try 50 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
15 15
16 public SourceLineNumber SourceLineNumbers { get; set; } 16 public SourceLineNumber SourceLineNumbers { get; set; }
17 17
18 public FileTransferType Type { get; set; }
19
20 public bool Redundant { get; set; } 18 public bool Redundant { get; set; }
21 } 19 }
22} 20}
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
28 28
29 private IMessaging Messaging { get; } 29 private IMessaging Messaging { get; }
30 30
31 public IEnumerable<ITrackedFile> TrackedFiles { get; set; }
32
31 public IEnumerable<IFileTransfer> FileTransfers { get; set; } 33 public IEnumerable<IFileTransfer> FileTransfers { get; set; }
32 34
33 public IEnumerable<string> ContentFilePaths { get; set; } 35 public string IntermediateFolder { get; set; }
34 36
35 public string ContentsFile { get; set; } 37 public string ContentsFile { get; set; }
36 38
@@ -46,8 +48,8 @@ namespace WixToolset.Core
46 48
47 var context = this.ServiceProvider.GetService<ILayoutContext>(); 49 var context = this.ServiceProvider.GetService<ILayoutContext>();
48 context.Extensions = extensionManager.Create<ILayoutExtension>(); 50 context.Extensions = extensionManager.Create<ILayoutExtension>();
51 context.TrackedFiles = this.TrackedFiles;
49 context.FileTransfers = this.FileTransfers; 52 context.FileTransfers = this.FileTransfers;
50 context.ContentFilePaths = this.ContentFilePaths;
51 context.ContentsFile = this.ContentsFile; 53 context.ContentsFile = this.ContentsFile;
52 context.OutputsFile = this.OutputsFile; 54 context.OutputsFile = this.OutputsFile;
53 context.BuiltOutputsFile = this.BuiltOutputsFile; 55 context.BuiltOutputsFile = this.BuiltOutputsFile;
@@ -71,24 +73,29 @@ namespace WixToolset.Core
71 var command = new TransferFilesCommand(this.Messaging, context.Extensions, context.FileTransfers, context.SuppressAclReset); 73 var command = new TransferFilesCommand(this.Messaging, context.Extensions, context.FileTransfers, context.SuppressAclReset);
72 command.Execute(); 74 command.Execute();
73 } 75 }
76
77 if (context.TrackedFiles != null)
78 {
79 this.CleanTempFiles(context.TrackedFiles);
80 }
74 } 81 }
75 finally 82 finally
76 { 83 {
77 if (!String.IsNullOrEmpty(context.ContentsFile) && context.ContentFilePaths != null) 84 if (context.TrackedFiles != null)
78 { 85 {
79 this.CreateContentsFile(context.ContentsFile, context.ContentFilePaths); 86 if (!String.IsNullOrEmpty(context.ContentsFile))
80 } 87 {
88 this.CreateContentsFile(context.ContentsFile, context.TrackedFiles);
89 }
81 90
82 if (context.FileTransfers != null)
83 {
84 if (!String.IsNullOrEmpty(context.OutputsFile)) 91 if (!String.IsNullOrEmpty(context.OutputsFile))
85 { 92 {
86 this.CreateOutputsFile(context.OutputsFile, context.FileTransfers); 93 this.CreateOutputsFile(context.OutputsFile, context.TrackedFiles);
87 } 94 }
88 95
89 if (!String.IsNullOrEmpty(context.BuiltOutputsFile)) 96 if (!String.IsNullOrEmpty(context.BuiltOutputsFile))
90 { 97 {
91 this.CreateBuiltOutputsFile(context.BuiltOutputsFile, context.FileTransfers); 98 this.CreateBuiltOutputsFile(context.BuiltOutputsFile, context.TrackedFiles);
92 } 99 }
93 } 100 }
94 } 101 }
@@ -105,16 +112,23 @@ namespace WixToolset.Core
105 /// </summary> 112 /// </summary>
106 /// <param name="path">Path to write file.</param> 113 /// <param name="path">Path to write file.</param>
107 /// <param name="contentFilePaths">Collection of paths to content files that will be written to file.</param> 114 /// <param name="contentFilePaths">Collection of paths to content files that will be written to file.</param>
108 private void CreateContentsFile(string path, IEnumerable<string> contentFilePaths) 115 private void CreateContentsFile(string path, IEnumerable<ITrackedFile> trackedFiles)
109 { 116 {
117 var uniqueInputFilePaths = new SortedSet<string>(trackedFiles.Where(t => t.Type == TrackedFileType.Input).Select(t => t.Path), StringComparer.OrdinalIgnoreCase);
118
119 if (!uniqueInputFilePaths.Any())
120 {
121 return;
122 }
123
110 var directory = Path.GetDirectoryName(path); 124 var directory = Path.GetDirectoryName(path);
111 Directory.CreateDirectory(directory); 125 Directory.CreateDirectory(directory);
112 126
113 using (var contents = new StreamWriter(path, false)) 127 using (var contents = new StreamWriter(path, false))
114 { 128 {
115 foreach (string contentPath in contentFilePaths) 129 foreach (string inputPath in uniqueInputFilePaths)
116 { 130 {
117 contents.WriteLine(contentPath); 131 contents.WriteLine(inputPath);
118 } 132 }
119 } 133 }
120 } 134 }
@@ -124,22 +138,28 @@ namespace WixToolset.Core
124 /// </summary> 138 /// </summary>
125 /// <param name="path">Path to write file.</param> 139 /// <param name="path">Path to write file.</param>
126 /// <param name="fileTransfers">Collection of files that were transferred to the output directory.</param> 140 /// <param name="fileTransfers">Collection of files that were transferred to the output directory.</param>
127 private void CreateOutputsFile(string path, IEnumerable<IFileTransfer> fileTransfers) 141 private void CreateOutputsFile(string path, IEnumerable<ITrackedFile> trackedFiles)
128 { 142 {
143 var uniqueOutputPaths = new SortedSet<string>(trackedFiles.Where(t => t.Clean).Select(t => t.Path), StringComparer.OrdinalIgnoreCase);
144
145 if (!uniqueOutputPaths.Any())
146 {
147 return;
148 }
149
129 var directory = Path.GetDirectoryName(path); 150 var directory = Path.GetDirectoryName(path);
130 Directory.CreateDirectory(directory); 151 Directory.CreateDirectory(directory);
131 152
132 using (var outputs = new StreamWriter(path, false)) 153 using (var outputs = new StreamWriter(path, false))
133 { 154 {
134 foreach (var fileTransfer in fileTransfers) 155 //// Don't list files where the source is the same as the destination since
156 //// that might be the only place the file exists. The outputs file is often
157 //// used to delete stuff and losing the original source would be bad.
158 //var uniqueOutputPaths = new SortedSet<string>(fileTransfers.Where(ft => !ft.Redundant).Select(ft => ft.Destination), StringComparer.OrdinalIgnoreCase);
159
160 foreach (var outputPath in uniqueOutputPaths)
135 { 161 {
136 // Don't list files where the source is the same as the destination since 162 outputs.WriteLine(outputPath);
137 // that might be the only place the file exists. The outputs file is often
138 // used to delete stuff and losing the original source would be bad.
139 if (!fileTransfer.Redundant)
140 {
141 outputs.WriteLine(fileTransfer.Destination);
142 }
143 } 163 }
144 } 164 }
145 } 165 }
@@ -149,21 +169,83 @@ namespace WixToolset.Core
149 /// </summary> 169 /// </summary>
150 /// <param name="path">Path to write file.</param> 170 /// <param name="path">Path to write file.</param>
151 /// <param name="fileTransfers">Collection of files that were transferred to the output directory.</param> 171 /// <param name="fileTransfers">Collection of files that were transferred to the output directory.</param>
152 private void CreateBuiltOutputsFile(string path, IEnumerable<IFileTransfer> fileTransfers) 172 private void CreateBuiltOutputsFile(string path, IEnumerable<ITrackedFile> trackedFiles)
153 { 173 {
174 var uniqueBuiltPaths = new SortedSet<string>(trackedFiles.Where(t => t.Type == TrackedFileType.Final).Select(t => t.Path), StringComparer.OrdinalIgnoreCase);
175
176 if (!uniqueBuiltPaths.Any())
177 {
178 return;
179 }
180
154 var directory = Path.GetDirectoryName(path); 181 var directory = Path.GetDirectoryName(path);
155 Directory.CreateDirectory(directory); 182 Directory.CreateDirectory(directory);
156 183
157 using (var outputs = new StreamWriter(path, false)) 184 using (var outputs = new StreamWriter(path, false))
158 { 185 {
159 foreach (var fileTransfer in fileTransfers) 186 foreach (var builtPath in uniqueBuiltPaths)
160 { 187 {
161 // Only write the built file transfers. Also, skip redundant 188 outputs.WriteLine(builtPath);
162 // files for the same reason spelled out in this.CreateOutputsFile(). 189 }
163 if (fileTransfer.Type == FileTransferType.Built && !fileTransfer.Redundant) 190 }
164 { 191 }
165 outputs.WriteLine(fileTransfer.Destination); 192
166 } 193 private void CleanTempFiles(IEnumerable<ITrackedFile> trackedFiles)
194 {
195 var uniqueTempPaths = new SortedSet<string>(trackedFiles.Where(t => t.Type == TrackedFileType.Temporary).Select(t => t.Path), StringComparer.OrdinalIgnoreCase);
196
197 if (!uniqueTempPaths.Any())
198 {
199 return;
200 }
201
202 var uniqueFolders = new SortedSet<string>(StringComparer.OrdinalIgnoreCase)
203 {
204 this.IntermediateFolder
205 };
206
207 // Clean up temp files.
208 foreach (var tempPath in uniqueTempPaths)
209 {
210 try
211 {
212 this.SplitUniqueFolders(tempPath, uniqueFolders);
213
214 File.Delete(tempPath);
215 }
216 catch // delete is best effort.
217 {
218 }
219 }
220
221 // Clean up empty temp folders.
222 foreach (var folder in uniqueFolders.Reverse())
223 {
224 try
225 {
226 Directory.Delete(folder);
227 }
228 catch // delete is best effort.
229 {
230 }
231 }
232 }
233
234 private void SplitUniqueFolders(string tempPath, SortedSet<string> uniqueFolders)
235 {
236 if (tempPath.StartsWith(this.IntermediateFolder, StringComparison.OrdinalIgnoreCase))
237 {
238 var folder = Path.GetDirectoryName(tempPath).Substring(this.IntermediateFolder.Length);
239
240 var parts = folder.Split(new[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries);
241
242 folder = this.IntermediateFolder;
243
244 foreach (var part in parts)
245 {
246 folder = Path.Combine(folder, part);
247
248 uniqueFolders.Add(folder);
167 } 249 }
168 } 250 }
169 } 251 }
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
22 22
23 public IEnumerable<IFileTransfer> FileTransfers { get; set; } 23 public IEnumerable<IFileTransfer> FileTransfers { get; set; }
24 24
25 public IEnumerable<string> ContentFilePaths { get; set; } 25 public IEnumerable<ITrackedFile> TrackedFiles { get; set; }
26 26
27 public string OutputPdbPath { get; set; } 27 public string OutputPdbPath { get; set; }
28 28
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 @@
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
3namespace WixToolset.Core
4{
5 using WixToolset.Data;
6 using WixToolset.Extensibility.Data;
7
8 internal class TrackedFile : ITrackedFile
9 {
10 public TrackedFile(string path, TrackedFileType type, SourceLineNumber sourceLineNumbers)
11 {
12 this.Path = path;
13 this.Type = type;
14 this.SourceLineNumbers = sourceLineNumbers;
15 this.Clean = (type == TrackedFileType.Intermediate || type == TrackedFileType.Final);
16 }
17
18 public bool Clean { get; set; }
19
20 public string Path { get; set; }
21
22 public SourceLineNumber SourceLineNumbers { get; set; }
23
24 public TrackedFileType Type { get; set; }
25 }
26}