aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/Layout.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core/Layout.cs')
-rw-r--r--src/WixToolset.Core/Layout.cs140
1 files changed, 111 insertions, 29 deletions
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 }