private ResolvedCabinet ResolveCabinet(string cabinetPath, IEnumerable <FileFacade> fileFacades) { ResolvedCabinet resolved = null; List <BindFileWithPath> filesWithPath = fileFacades.Select(f => new BindFileWithPath() { Id = f.File.File, Path = f.WixFile.Source }).ToList(); foreach (IBinderFileManager fileManager in this.FileManagers) { resolved = fileManager.ResolveCabinet(cabinetPath, filesWithPath); if (null != resolved) { break; } } return(resolved); }
/// <summary> /// Creates a work item to create a cabinet. /// </summary> /// <param name="output">Output for the current database.</param> /// <param name="cabinetDir">Directory to create cabinet in.</param> /// <param name="mediaRow">MediaRow containing information about the cabinet.</param> /// <param name="fileFacades">Collection of files in this cabinet.</param> /// <param name="fileTransfers">Array of files to be transfered.</param> /// <returns>created CabinetWorkItem object</returns> private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaRow mediaRow, CompressionLevel compressionLevel, IEnumerable <FileFacade> fileFacades, List <FileTransfer> fileTransfers) { CabinetWorkItem cabinetWorkItem = null; string tempCabinetFileX = Path.Combine(this.TempFilesLocation, mediaRow.Cabinet); // check for an empty cabinet if (!fileFacades.Any()) { string cabinetName = mediaRow.Cabinet; // remove the leading '#' from the embedded cabinet name to make the warning easier to understand if (cabinetName.StartsWith("#", StringComparison.Ordinal)) { cabinetName = cabinetName.Substring(1); } // If building a patch, remind them to run -p for torch. if (OutputType.Patch == output.Type) { Messaging.Instance.OnMessage(WixWarnings.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName, true)); } else { Messaging.Instance.OnMessage(WixWarnings.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName)); } } ResolvedCabinet resolvedCabinet = this.ResolveCabinet(tempCabinetFileX, fileFacades); // create a cabinet work item if it's not being skipped if (CabinetBuildOption.BuildAndCopy == resolvedCabinet.BuildOption || CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption) { int maxThreshold = 0; // default to the threshold for best smartcabbing (makes smallest cabinet). cabinetWorkItem = new CabinetWorkItem(fileFacades, resolvedCabinet.Path, maxThreshold, compressionLevel /*, this.FileManager*/); } else // reuse the cabinet from the cabinet cache. { Messaging.Instance.OnMessage(WixVerboses.ReusingCabCache(mediaRow.SourceLineNumbers, mediaRow.Cabinet, resolvedCabinet.Path)); try { // Ensure the cached cabinet timestamp is current to prevent perpetual incremental builds. The // problematic scenario goes like this. Imagine two cabinets in the cache. Update a file that // goes into one of the cabinets. One cabinet will get rebuilt, the other will be copied from // the cache. Now the file (an input) has a newer timestamp than the reused cabient (an output) // causing the project to look like it perpetually needs a rebuild until all of the reused // cabinets get newer timestamps. File.SetLastWriteTime(resolvedCabinet.Path, DateTime.Now); } catch (Exception e) { Messaging.Instance.OnMessage(WixWarnings.CannotUpdateCabCache(mediaRow.SourceLineNumbers, resolvedCabinet.Path, e.Message)); } } if (mediaRow.Cabinet.StartsWith("#", StringComparison.Ordinal)) { Table streamsTable = output.EnsureTable(this.TableDefinitions["_Streams"]); Row streamRow = streamsTable.CreateRow(mediaRow.SourceLineNumbers); streamRow[0] = mediaRow.Cabinet.Substring(1); streamRow[1] = resolvedCabinet.Path; } else { string destinationPath = Path.Combine(cabinetDir, mediaRow.Cabinet); FileTransfer transfer; if (FileTransfer.TryCreate(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, "Cabinet", mediaRow.SourceLineNumbers, out transfer)) { transfer.Built = true; fileTransfers.Add(transfer); } } return(cabinetWorkItem); }
public ResolvedCabinet ResolveCabinet(string cabinetPath, IEnumerable <FileFacade> fileFacades) { var filesWithPath = fileFacades.Select(f => new BindFileWithPath() { Id = f.File.File, Path = f.WixFile.Source.Path }).ToList(); ResolvedCabinet resolved = null; foreach (var extension in this.BackendExtensions) { resolved = extension.ResolveCabinet(cabinetPath, filesWithPath); if (null != resolved) { return(resolved); } } // By default cabinet should be built and moved to the suggested location. resolved = new ResolvedCabinet() { BuildOption = CabinetBuildOption.BuildAndMove, Path = cabinetPath }; // If a cabinet cache path was provided, change the location for the cabinet // to be built to and check if there is a cabinet that can be reused. if (!String.IsNullOrEmpty(this.CabCachePath)) { string cabinetName = Path.GetFileName(cabinetPath); resolved.Path = Path.Combine(this.CabCachePath, cabinetName); if (CheckFileExists(resolved.Path)) { // Assume that none of the following are true: // 1. any files are added or removed // 2. order of files changed or names changed // 3. modified time changed bool cabinetValid = true; var cabinet = new Cabinet(resolved.Path); List <CabinetFileInfo> fileList = cabinet.Enumerate(); if (filesWithPath.Count() != fileList.Count) { cabinetValid = false; } else { int i = 0; foreach (BindFileWithPath file in filesWithPath) { // First check that the file identifiers match because that is quick and easy. CabinetFileInfo cabFileInfo = fileList[i]; cabinetValid = (cabFileInfo.FileId == file.Id); if (cabinetValid) { // Still valid so ensure the file sizes are the same. FileInfo fileInfo = new FileInfo(file.Path); cabinetValid = (cabFileInfo.Size == fileInfo.Length); if (cabinetValid) { // Still valid so ensure the source time stamp hasn't changed. cabinetValid = cabFileInfo.SameAsDateTime(fileInfo.LastWriteTime); } } if (!cabinetValid) { break; } i++; } } resolved.BuildOption = cabinetValid ? CabinetBuildOption.Copy : CabinetBuildOption.BuildAndCopy; } } return(resolved); }
public virtual ResolvedCabinet ResolveCabinet(string cabinetPath, IEnumerable <BindFileWithPath> filesWithPath) { if (null == filesWithPath) { throw new ArgumentNullException("fileRows"); } // By default cabinet should be built and moved to the suggested location. ResolvedCabinet resolved = new ResolvedCabinet() { BuildOption = CabinetBuildOption.BuildAndMove, Path = cabinetPath }; // If a cabinet cache path was provided, change the location for the cabinet // to be built to and check if there is a cabinet that can be reused. if (!String.IsNullOrEmpty(this.Core.CabCachePath)) { string cabinetName = Path.GetFileName(cabinetPath); resolved.Path = Path.Combine(this.Core.CabCachePath, cabinetName); if (BinderFileManager.CheckFileExists(resolved.Path)) { // Assume that none of the following are true: // 1. any files are added or removed // 2. order of files changed or names changed // 3. modified time changed bool cabinetValid = true; // Need to force garbage collection of WixEnumerateCab to ensure the handle // associated with it is closed before it is reused. using (Cab.WixEnumerateCab wixEnumerateCab = new Cab.WixEnumerateCab()) { List <CabinetFileInfo> fileList = wixEnumerateCab.Enumerate(resolved.Path); if (filesWithPath.Count() != fileList.Count) { cabinetValid = false; } else { int i = 0; foreach (BindFileWithPath file in filesWithPath) { // First check that the file identifiers match because that is quick and easy. CabinetFileInfo cabFileInfo = fileList[i]; cabinetValid = (cabFileInfo.FileId == file.Id); if (cabinetValid) { // Still valid so ensure the file sizes are the same. FileInfo fileInfo = new FileInfo(file.Path); cabinetValid = (cabFileInfo.Size == fileInfo.Length); if (cabinetValid) { // Still valid so ensure the source time stamp hasn't changed. Thus we need // to convert the source file time stamp into a cabinet compatible data/time. ushort sourceCabDate; ushort sourceCabTime; WixToolset.Core.Native.CabInterop.DateTimeToCabDateAndTime(fileInfo.LastWriteTime, out sourceCabDate, out sourceCabTime); cabinetValid = (cabFileInfo.Date == sourceCabDate && cabFileInfo.Time == sourceCabTime); } } if (!cabinetValid) { break; } i++; } } } resolved.BuildOption = cabinetValid ? CabinetBuildOption.Copy : CabinetBuildOption.BuildAndCopy; } } return(resolved); }
public virtual ResolvedCabinet ResolveCabinet(string cabinetPath, FileRowCollection fileRows) { if (fileRows == null) { throw new ArgumentNullException("fileRows"); } // By default cabinet should be built and moved to the suggested location. ResolvedCabinet resolved = new ResolvedCabinet() { BuildOption = CabinetBuildOption.BuildAndMove, Path = cabinetPath }; // No special behavior specified, use the default. if (null == this.Core.CabCachePath && !this.Core.ReuseCabinets) { return(resolved); } // If a cabinet cache path was provided, change the location for the cabinet // to be built to. if (null != this.Core.CabCachePath) { string cabinetName = Path.GetFileName(cabinetPath); resolved.Path = Path.Combine(this.Core.CabCachePath, cabinetName); } // If we still think we're going to reuse the cabinet check to see if the cabinet exists first. if (this.Core.ReuseCabinets) { bool cabinetValid = false; if (BinderFileManager.CheckFileExists(resolved.Path)) { // check to see if // 1. any files are added or removed // 2. order of files changed or names changed // 3. modified time changed cabinetValid = true; // Need to force garbage collection of WixEnumerateCab to ensure the handle // associated with it is closed before it is reused. using (Cab.WixEnumerateCab wixEnumerateCab = new Cab.WixEnumerateCab()) { ArrayList fileList = wixEnumerateCab.Enumerate(resolved.Path); if (fileRows.Count != fileList.Count) { cabinetValid = false; } else { int i = 0; foreach (FileRow fileRow in fileRows) { // First check that the file identifiers match because that is quick and easy. CabinetFileInfo cabFileInfo = fileList[i] as CabinetFileInfo; cabinetValid = (cabFileInfo.FileId == fileRow.File); if (cabinetValid) { // Still valid so ensure the source time stamp hasn't changed. Thus we need // to convert the source file time stamp into a cabinet compatible data/time. DateTime sourceFileTime = File.GetLastWriteTime(fileRow.Source); ushort sourceCabDate; ushort sourceCabTime; Cab.Interop.CabInterop.DateTimeToCabDateAndTime(sourceFileTime, out sourceCabDate, out sourceCabTime); cabinetValid = (cabFileInfo.Date == sourceCabDate && cabFileInfo.Time == sourceCabTime); } if (!cabinetValid) { break; } i++; } } } } resolved.BuildOption = cabinetValid ? CabinetBuildOption.Copy : CabinetBuildOption.BuildAndCopy; } return(resolved); }