private string ResolveMedia(MediaTuple mediaRow, string mediaLayoutDirectory, string layoutDirectory) { string layout = null; foreach (var extension in this.BackendExtensions) { layout = extension.ResolveMedia(mediaRow, mediaLayoutDirectory, layoutDirectory); if (!String.IsNullOrEmpty(layout)) { break; } } // If no binder file manager resolved the layout, do the default behavior. if (String.IsNullOrEmpty(layout)) { if (String.IsNullOrEmpty(mediaLayoutDirectory)) { layout = layoutDirectory; } else if (Path.IsPathRooted(mediaLayoutDirectory)) { layout = mediaLayoutDirectory; } else { layout = Path.Combine(layoutDirectory, mediaLayoutDirectory); } } return(layout); }
private void AddMediaTuple(MediaTuple tuple, Output output) { if (this.Section.Type != SectionType.Module) { var table = output.EnsureTable(this.TableDefinitions["Media"]); var row = (MediaRow)table.CreateRow(tuple.SourceLineNumbers); row.DiskId = tuple.DiskId; row.LastSequence = tuple.LastSequence; row.DiskPrompt = tuple.DiskPrompt; row.Cabinet = tuple.Cabinet; row.VolumeLabel = tuple.VolumeLabel; row.Source = tuple.Source; } }
public void Execute() { var filesByCabinetMedia = new Dictionary <MediaTuple, List <FileFacade> >(); var mediaRows = new Dictionary <int, MediaTuple>(); List <FileFacade> uncompressedFiles = new List <FileFacade>(); var mediaTable = this.Section.Tuples.OfType <MediaTuple>().ToList(); var mediaTemplateTable = this.Section.Tuples.OfType <WixMediaTemplateTuple>().ToList(); // If both tables are authored, it is an error. if (mediaTemplateTable.Count > 0 && mediaTable.Count > 1) { throw new WixException(ErrorMessages.MediaTableCollision(null)); } // When building merge module, all the files go to "#MergeModule.CABinet". if (SectionType.Module == this.Section.Type) { var mergeModuleMediaRow = new MediaTuple(); mergeModuleMediaRow.Cabinet = "#MergeModule.CABinet"; this.Section.Tuples.Add(mergeModuleMediaRow); filesByCabinetMedia.Add(mergeModuleMediaRow, new List <FileFacade>(this.FileFacades)); } else if (mediaTemplateTable.Count == 0) { this.ManuallyAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); } else { this.AutoAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); } this.FileFacadesByCabinetMedia = new Dictionary <MediaTuple, IEnumerable <FileFacade> >(); foreach (var mediaRowWithFiles in filesByCabinetMedia) { this.FileFacadesByCabinetMedia.Add(mediaRowWithFiles.Key, mediaRowWithFiles.Value); } this.MediaRows = mediaRows; this.UncompressedFileFacades = uncompressedFiles; }
/// <summary> /// Adds a row to the media table with cab name template filled in. /// </summary> /// <param name="mediaTable"></param> /// <param name="cabIndex"></param> /// <returns></returns> private MediaTuple AddMediaRow(WixMediaTemplateTuple mediaTemplateRow, int cabIndex) { var currentMediaRow = new MediaTuple(mediaTemplateRow.SourceLineNumbers, new Identifier(cabIndex, AccessModifier.Private)); currentMediaRow.DiskId = cabIndex; currentMediaRow.Cabinet = String.Format(CultureInfo.InvariantCulture, this.CabinetNameTemplate, cabIndex); this.Section.Tuples.Add(currentMediaRow); var row = new WixMediaTuple(mediaTemplateRow.SourceLineNumbers, new Identifier(cabIndex, AccessModifier.Private)); row.DiskId_ = cabIndex; row.CompressionLevel = mediaTemplateRow.CompressionLevel; this.Section.Tuples.Add(row); return(currentMediaRow); }
/// <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, MediaTuple 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) { this.Messaging.Write(WarningMessages.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName, true)); } else { this.Messaging.Write(WarningMessages.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName)); } } var cabinetResolver = new CabinetResolver(this.CabCachePath, this.BackendExtensions); ResolvedCabinet resolvedCabinet = cabinetResolver.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. { this.Messaging.Write(VerboseMessages.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) { this.Messaging.Write(WarningMessages.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); if (FileTransfer.TryCreate(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, "Cabinet", mediaRow.SourceLineNumbers, out var transfer)) { transfer.Built = true; fileTransfers.Add(transfer); } } return(cabinetWorkItem); }
/// <summary> /// Assign files to cabinets based on MediaTemplate authoring. /// </summary> /// <param name="fileFacades">FileRowCollection</param> private void AutoAssignFiles(List <MediaTuple> mediaTable, IEnumerable <FileFacade> fileFacades, Dictionary <MediaTuple, List <FileFacade> > filesByCabinetMedia, Dictionary <int, MediaTuple> mediaRows, List <FileFacade> uncompressedFiles) { const int MaxCabIndex = 999; ulong currentPreCabSize = 0; ulong maxPreCabSizeInBytes; int maxPreCabSizeInMB = 0; int currentCabIndex = 0; MediaTuple currentMediaRow = null; var mediaTemplateTable = this.Section.Tuples.OfType <WixMediaTemplateTuple>(); // Remove all previous media tuples since they will be replaced with // media template. foreach (var mediaTuple in mediaTable) { this.Section.Tuples.Remove(mediaTuple); } // Auto assign files to cabinets based on maximum uncompressed media size var mediaTemplateRow = mediaTemplateTable.Single(); if (!String.IsNullOrEmpty(mediaTemplateRow.CabinetTemplate)) { this.CabinetNameTemplate = mediaTemplateRow.CabinetTemplate; } string mumsString = Environment.GetEnvironmentVariable("WIX_MUMS"); try { // Override authored mums value if environment variable is authored. if (!String.IsNullOrEmpty(mumsString)) { maxPreCabSizeInMB = Int32.Parse(mumsString); } else { maxPreCabSizeInMB = mediaTemplateRow.MaximumUncompressedMediaSize; } maxPreCabSizeInBytes = (ulong)maxPreCabSizeInMB * 1024 * 1024; } catch (FormatException) { throw new WixException(ErrorMessages.IllegalEnvironmentVariable("WIX_MUMS", mumsString)); } catch (OverflowException) { throw new WixException(ErrorMessages.MaximumUncompressedMediaSizeTooLarge(null, maxPreCabSizeInMB)); } foreach (FileFacade facade in this.FileFacades) { // When building a product, if the current file is not to be compressed or if // the package set not to be compressed, don't cab it. if (SectionType.Product == this.Section.Type && ((facade.File.Compressed.HasValue && !facade.File.Compressed.Value) || (!facade.File.Compressed.HasValue && !this.FilesCompressed))) { uncompressedFiles.Add(facade); continue; } if (currentCabIndex == MaxCabIndex) { // Associate current file with last cab (irrespective of the size) and cab index is not incremented anymore. List <FileFacade> cabinetFiles = filesByCabinetMedia[currentMediaRow]; facade.WixFile.DiskId = currentCabIndex; cabinetFiles.Add(facade); continue; } // Update current cab size. currentPreCabSize += (ulong)facade.File.FileSize; if (currentPreCabSize > maxPreCabSizeInBytes) { // Overflow due to current file currentMediaRow = this.AddMediaRow(mediaTemplateRow, ++currentCabIndex); mediaRows.Add(currentMediaRow.DiskId, currentMediaRow); filesByCabinetMedia.Add(currentMediaRow, new List <FileFacade>()); List <FileFacade> cabinetFileRows = filesByCabinetMedia[currentMediaRow]; facade.WixFile.DiskId = currentCabIndex; cabinetFileRows.Add(facade); // Now files larger than MaxUncompressedMediaSize will be the only file in its cabinet so as to respect MaxUncompressedMediaSize currentPreCabSize = (ulong)facade.File.FileSize; } else { // File fits in the current cab. if (currentMediaRow == null) { // Create new cab and MediaRow currentMediaRow = this.AddMediaRow(mediaTemplateRow, ++currentCabIndex); mediaRows.Add(currentMediaRow.DiskId, currentMediaRow); filesByCabinetMedia.Add(currentMediaRow, new List <FileFacade>()); } // Associate current file with current cab. List <FileFacade> cabinetFiles = filesByCabinetMedia[currentMediaRow]; facade.WixFile.DiskId = currentCabIndex; cabinetFiles.Add(facade); } } // If there are uncompressed files and no MediaRow, create a default one. if (uncompressedFiles.Count > 0 && !this.Section.Tuples.OfType <MediaTuple>().Any()) { var defaultMediaRow = new MediaTuple(null, new Identifier(1, AccessModifier.Private)); defaultMediaRow.DiskId = 1; mediaRows.Add(1, defaultMediaRow); this.Section.Tuples.Add(defaultMediaRow); } }
public virtual string ResolveMedia(MediaTuple mediaRow, string mediaLayoutDirectory, string layoutDirectory) { return(null); }