aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/Binder.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core/Binder.cs')
-rw-r--r--src/WixToolset.Core/Binder.cs451
1 files changed, 55 insertions, 396 deletions
diff --git a/src/WixToolset.Core/Binder.cs b/src/WixToolset.Core/Binder.cs
index 2369b600..9db27fec 100644
--- a/src/WixToolset.Core/Binder.cs
+++ b/src/WixToolset.Core/Binder.cs
@@ -3,14 +3,11 @@
3namespace WixToolset.Core 3namespace WixToolset.Core
4{ 4{
5 using System; 5 using System;
6 using System.Collections;
7 using System.Collections.Generic; 6 using System.Collections.Generic;
8 using System.Diagnostics; 7 using System.Diagnostics;
9 using System.Globalization;
10 using System.IO; 8 using System.IO;
11 using System.Linq; 9 using System.Linq;
12 using System.Reflection; 10 using System.Reflection;
13 using WixToolset.Bind;
14 using WixToolset.Core.Bind; 11 using WixToolset.Core.Bind;
15 using WixToolset.Data; 12 using WixToolset.Data;
16 using WixToolset.Data.Bind; 13 using WixToolset.Data.Bind;
@@ -148,130 +145,72 @@ namespace WixToolset.Core
148 /// <value>The Wix variable resolver.</value> 145 /// <value>The Wix variable resolver.</value>
149 internal WixVariableResolver WixVariableResolver { get; set; } 146 internal WixVariableResolver WixVariableResolver { get; set; }
150 147
151 /// <summary> 148 public BindResult Bind(IBindContext context)
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)
170 { 149 {
171 this.Context = context; 150 this.Context = context;
172 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
181 this.WriteBuildInfoTable(this.Context.IntermediateRepresentation, this.Context.OutputPath); 152 this.WriteBuildInfoTable(this.Context.IntermediateRepresentation, this.Context.OutputPath);
182 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 //
202 var bindResult = this.BackendBind(); 154 var bindResult = this.BackendBind();
203 155 return bindResult;
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;
219 } 156 }
220 157
221 private ResolveResult Resolve() 158//// private ResolveResult Resolve()
222 { 159//// {
223 var buildingPatch = this.Context.IntermediateRepresentation.Sections.Any(s => s.Type == SectionType.Patch); 160//// var buildingPatch = this.Context.IntermediateRepresentation.Sections.Any(s => s.Type == SectionType.Patch);
224 161
225 var filesWithEmbeddedFiles = new ExtractEmbeddedFiles(); 162//// var filesWithEmbeddedFiles = new ExtractEmbeddedFiles();
226 163
227 IEnumerable<DelayedField> delayedFields; 164//// IEnumerable<DelayedField> delayedFields;
228 { 165//// {
229 var command = new ResolveFieldsCommand(); 166//// var command = new ResolveFieldsCommand();
230 command.Messaging = this.Context.Messaging; 167//// command.Messaging = this.Context.Messaging;
231 command.BuildingPatch = buildingPatch; 168//// command.BuildingPatch = buildingPatch;
232 command.BindVariableResolver = this.Context.WixVariableResolver; 169//// command.BindVariableResolver = this.Context.WixVariableResolver;
233 command.BindPaths = this.Context.BindPaths; 170//// command.BindPaths = this.Context.BindPaths;
234 command.Extensions = this.Context.Extensions; 171//// command.Extensions = this.Context.Extensions;
235 command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles; 172//// command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles;
236 command.IntermediateFolder = this.Context.IntermediateFolder; 173//// command.IntermediateFolder = this.Context.IntermediateFolder;
237 command.Intermediate = this.Context.IntermediateRepresentation; 174//// command.Intermediate = this.Context.IntermediateRepresentation;
238 command.SupportDelayedResolution = true; 175//// command.SupportDelayedResolution = true;
239 command.Execute(); 176//// command.Execute();
240 177
241 delayedFields = command.DelayedFields; 178//// delayedFields = command.DelayedFields;
242 } 179//// }
243 180
244#if REVISIT_FOR_PATCHING 181////#if REVISIT_FOR_PATCHING
245 if (this.Context.IntermediateRepresentation.SubStorages != null) 182//// if (this.Context.IntermediateRepresentation.SubStorages != null)
246 { 183//// {
247 foreach (SubStorage transform in this.Context.IntermediateRepresentation.SubStorages) 184//// foreach (SubStorage transform in this.Context.IntermediateRepresentation.SubStorages)
248 { 185//// {
249 var command = new ResolveFieldsCommand(); 186//// var command = new ResolveFieldsCommand();
250 command.BuildingPatch = buildingPatch; 187//// command.BuildingPatch = buildingPatch;
251 command.BindVariableResolver = this.Context.WixVariableResolver; 188//// command.BindVariableResolver = this.Context.WixVariableResolver;
252 command.BindPaths = this.Context.BindPaths; 189//// command.BindPaths = this.Context.BindPaths;
253 command.Extensions = this.Context.Extensions; 190//// command.Extensions = this.Context.Extensions;
254 command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles; 191//// command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles;
255 command.IntermediateFolder = this.Context.IntermediateFolder; 192//// command.IntermediateFolder = this.Context.IntermediateFolder;
256 command.Intermediate = this.Context.IntermediateRepresentation; 193//// command.Intermediate = this.Context.IntermediateRepresentation;
257 command.SupportDelayedResolution = false; 194//// command.SupportDelayedResolution = false;
258 command.Execute(); 195//// command.Execute();
259 } 196//// }
260 } 197//// }
261#endif 198////#endif
262 199
263 var expectedEmbeddedFiles = filesWithEmbeddedFiles.GetExpectedEmbeddedFiles(); 200//// var expectedEmbeddedFiles = filesWithEmbeddedFiles.GetExpectedEmbeddedFiles();
264 201
265 return new ResolveResult 202//// return new ResolveResult
266 { 203//// {
267 ExpectedEmbeddedFiles = expectedEmbeddedFiles, 204//// ExpectedEmbeddedFiles = expectedEmbeddedFiles,
268 DelayedFields = delayedFields, 205//// DelayedFields = delayedFields,
269 }; 206//// };
270 } 207//// }
271 208
272 private BindResult BackendBind() 209 private BindResult BackendBind()
273 { 210 {
274 var backendFactories = this.Context.ExtensionManager.Create<IBackendFactory>(); 211 var extensionManager = this.Context.ServiceProvider.GetService<IExtensionManager>();
212
213 var backendFactories = extensionManager.Create<IBackendFactory>();
275 214
276 var entrySection = this.Context.IntermediateRepresentation.Sections[0]; 215 var entrySection = this.Context.IntermediateRepresentation.Sections[0];
277 216
@@ -289,31 +228,6 @@ namespace WixToolset.Core
289 return null; 228 return null;
290 } 229 }
291 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
317 /// <summary> 231 /// <summary>
318 /// Binds an output. 232 /// Binds an output.
319 /// </summary> 233 /// </summary>
@@ -429,35 +343,6 @@ namespace WixToolset.Core
429#endif 343#endif
430 344
431 /// <summary> 345 /// <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
460 /// <summary>
461 /// Populates the WixBuildInfo table in an output. 346 /// Populates the WixBuildInfo table in an output.
462 /// </summary> 347 /// </summary>
463 /// <param name="output">The output.</param> 348 /// <param name="output">The output.</param>
@@ -585,231 +470,5 @@ namespace WixToolset.Core
585 command.Execute(); 470 command.Execute();
586 } 471 }
587#endif 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 }
814 } 473 }
815} 474}