diff options
| author | Rob Mensching <rob@firegiant.com> | 2020-06-15 16:07:45 -0700 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2020-06-16 12:15:13 -0700 |
| commit | 678c92c50c6fb7aa9a093f0d74d4f92742abd5e8 (patch) | |
| tree | ef4d007b74e56734a5258e2235988fbc0ef6996f /src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs | |
| parent | 3fb3475b278803576badecfbe8015760de2e7414 (diff) | |
| download | wix-678c92c50c6fb7aa9a093f0d74d4f92742abd5e8.tar.gz wix-678c92c50c6fb7aa9a093f0d74d4f92742abd5e8.tar.bz2 wix-678c92c50c6fb7aa9a093f0d74d4f92742abd5e8.zip | |
Reorganize media assignment to correctly place facade order optimization
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs')
| -rw-r--r-- | src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs | 159 |
1 files changed, 74 insertions, 85 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs index 1d677a70..b75956b4 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs | |||
| @@ -35,7 +35,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 35 | 35 | ||
| 36 | private bool FilesCompressed { get; } | 36 | private bool FilesCompressed { get; } |
| 37 | 37 | ||
| 38 | public string CabinetNameTemplate { private get; set; } | 38 | private string CabinetNameTemplate { get; set; } |
| 39 | 39 | ||
| 40 | /// <summary> | 40 | /// <summary> |
| 41 | /// Gets cabinets with their file rows. | 41 | /// Gets cabinets with their file rows. |
| @@ -43,11 +43,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 43 | public Dictionary<MediaTuple, IEnumerable<FileFacade>> FileFacadesByCabinetMedia { get; private set; } | 43 | public Dictionary<MediaTuple, IEnumerable<FileFacade>> FileFacadesByCabinetMedia { get; private set; } |
| 44 | 44 | ||
| 45 | /// <summary> | 45 | /// <summary> |
| 46 | /// Get media rows. | ||
| 47 | /// </summary> | ||
| 48 | public Dictionary<int, MediaTuple> MediaRows { get; private set; } | ||
| 49 | |||
| 50 | /// <summary> | ||
| 51 | /// Get uncompressed file rows. This will contain file rows of File elements that are marked with compression=no. | 46 | /// Get uncompressed file rows. This will contain file rows of File elements that are marked with compression=no. |
| 52 | /// This contains all the files when Package element is marked with compression=no | 47 | /// This contains all the files when Package element is marked with compression=no |
| 53 | /// </summary> | 48 | /// </summary> |
| @@ -55,17 +50,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 55 | 50 | ||
| 56 | public void Execute() | 51 | public void Execute() |
| 57 | { | 52 | { |
| 58 | var filesByCabinetMedia = new Dictionary<MediaTuple, List<FileFacade>>(); | 53 | var mediaTuples = this.Section.Tuples.OfType<MediaTuple>().ToList(); |
| 59 | 54 | var mediaTemplateTuples = this.Section.Tuples.OfType<WixMediaTemplateTuple>().ToList(); | |
| 60 | var mediaRows = new Dictionary<int, MediaTuple>(); | ||
| 61 | |||
| 62 | var uncompressedFiles = new List<FileFacade>(); | ||
| 63 | |||
| 64 | var mediaTable = this.Section.Tuples.OfType<MediaTuple>().ToList(); | ||
| 65 | var mediaTemplateTable = this.Section.Tuples.OfType<WixMediaTemplateTuple>().ToList(); | ||
| 66 | 55 | ||
| 67 | // If both tables are authored, it is an error. | 56 | // If both tuples are authored, it is an error. |
| 68 | if (mediaTemplateTable.Count > 0 && mediaTable.Count > 1) | 57 | if (mediaTemplateTuples.Count > 0 && mediaTuples.Count > 1) |
| 69 | { | 58 | { |
| 70 | throw new WixException(ErrorMessages.MediaTableCollision(null)); | 59 | throw new WixException(ErrorMessages.MediaTableCollision(null)); |
| 71 | } | 60 | } |
| @@ -78,34 +67,44 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 78 | Cabinet = "#MergeModule.CABinet", | 67 | Cabinet = "#MergeModule.CABinet", |
| 79 | }); | 68 | }); |
| 80 | 69 | ||
| 81 | filesByCabinetMedia.Add(mergeModuleMediaTuple, new List<FileFacade>(this.FileFacades)); | 70 | this.FileFacadesByCabinetMedia = new Dictionary<MediaTuple, IEnumerable<FileFacade>> |
| 71 | { | ||
| 72 | { mergeModuleMediaTuple, this.FileFacades } | ||
| 73 | }; | ||
| 74 | |||
| 75 | this.UncompressedFileFacades = Array.Empty<FileFacade>(); | ||
| 82 | } | 76 | } |
| 83 | else if (mediaTemplateTable.Count == 0) | 77 | else if (mediaTemplateTuples.Count == 0) |
| 84 | { | 78 | { |
| 85 | this.ManuallyAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); | 79 | var filesByCabinetMedia = new Dictionary<MediaTuple, List<FileFacade>>(); |
| 80 | |||
| 81 | var uncompressedFiles = new List<FileFacade>(); | ||
| 82 | |||
| 83 | this.ManuallyAssignFiles(mediaTuples, filesByCabinetMedia, uncompressedFiles); | ||
| 84 | |||
| 85 | this.FileFacadesByCabinetMedia = filesByCabinetMedia.ToDictionary(kvp => kvp.Key, kvp => (IEnumerable<FileFacade>)kvp.Value); | ||
| 86 | |||
| 87 | this.UncompressedFileFacades = uncompressedFiles; | ||
| 86 | } | 88 | } |
| 87 | else | 89 | else |
| 88 | { | 90 | { |
| 89 | this.AutoAssignFiles(mediaTable, filesByCabinetMedia, mediaRows, uncompressedFiles); | 91 | var filesByCabinetMedia = new Dictionary<MediaTuple, List<FileFacade>>(); |
| 90 | } | ||
| 91 | 92 | ||
| 92 | this.FileFacadesByCabinetMedia = new Dictionary<MediaTuple, IEnumerable<FileFacade>>(); | 93 | var uncompressedFiles = new List<FileFacade>(); |
| 93 | 94 | ||
| 94 | foreach (var mediaRowWithFiles in filesByCabinetMedia) | 95 | this.AutoAssignFiles(mediaTuples, filesByCabinetMedia, uncompressedFiles); |
| 95 | { | ||
| 96 | this.FileFacadesByCabinetMedia.Add(mediaRowWithFiles.Key, mediaRowWithFiles.Value); | ||
| 97 | } | ||
| 98 | 96 | ||
| 99 | this.MediaRows = mediaRows; | 97 | this.FileFacadesByCabinetMedia = filesByCabinetMedia.ToDictionary(kvp => kvp.Key, kvp => (IEnumerable<FileFacade>)kvp.Value); |
| 100 | 98 | ||
| 101 | this.UncompressedFileFacades = uncompressedFiles; | 99 | this.UncompressedFileFacades = uncompressedFiles; |
| 100 | } | ||
| 102 | } | 101 | } |
| 103 | 102 | ||
| 104 | /// <summary> | 103 | /// <summary> |
| 105 | /// Assign files to cabinets based on MediaTemplate authoring. | 104 | /// Assign files to cabinets based on MediaTemplate authoring. |
| 106 | /// </summary> | 105 | /// </summary> |
| 107 | /// <param name="fileFacades">FileRowCollection</param> | 106 | /// <param name="fileFacades">FileRowCollection</param> |
| 108 | private void AutoAssignFiles(List<MediaTuple> mediaTable, Dictionary<MediaTuple, List<FileFacade>> filesByCabinetMedia, Dictionary<int, MediaTuple> mediaRows, List<FileFacade> uncompressedFiles) | 107 | private void AutoAssignFiles(List<MediaTuple> mediaTable, Dictionary<MediaTuple, List<FileFacade>> filesByCabinetMedia, List<FileFacade> uncompressedFiles) |
| 109 | { | 108 | { |
| 110 | const int MaxCabIndex = 999; | 109 | const int MaxCabIndex = 999; |
| 111 | 110 | ||
| @@ -158,6 +157,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 158 | throw new WixException(ErrorMessages.MaximumUncompressedMediaSizeTooLarge(null, maxPreCabSizeInMB)); | 157 | throw new WixException(ErrorMessages.MaximumUncompressedMediaSizeTooLarge(null, maxPreCabSizeInMB)); |
| 159 | } | 158 | } |
| 160 | 159 | ||
| 160 | var mediaTuplesByDiskId = new Dictionary<int, MediaTuple>(); | ||
| 161 | |||
| 161 | foreach (var facade in this.FileFacades) | 162 | foreach (var facade in this.FileFacades) |
| 162 | { | 163 | { |
| 163 | // When building a product, if the current file is not to be compressed or if | 164 | // When building a product, if the current file is not to be compressed or if |
| @@ -171,44 +172,38 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 171 | if (currentCabIndex == MaxCabIndex) | 172 | if (currentCabIndex == MaxCabIndex) |
| 172 | { | 173 | { |
| 173 | // Associate current file with last cab (irrespective of the size) and cab index is not incremented anymore. | 174 | // Associate current file with last cab (irrespective of the size) and cab index is not incremented anymore. |
| 174 | var cabinetFiles = filesByCabinetMedia[currentMediaRow]; | ||
| 175 | facade.DiskId = currentCabIndex; | ||
| 176 | cabinetFiles.Add(facade); | ||
| 177 | continue; | ||
| 178 | } | ||
| 179 | |||
| 180 | // Update current cab size. | ||
| 181 | currentPreCabSize += (ulong)facade.FileSize; | ||
| 182 | |||
| 183 | if (currentPreCabSize > maxPreCabSizeInBytes) | ||
| 184 | { | ||
| 185 | // Overflow due to current file | ||
| 186 | currentMediaRow = this.AddMediaRow(mediaTemplateRow, ++currentCabIndex); | ||
| 187 | mediaRows.Add(currentMediaRow.DiskId, currentMediaRow); | ||
| 188 | filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>()); | ||
| 189 | |||
| 190 | var cabinetFileRows = filesByCabinetMedia[currentMediaRow]; | ||
| 191 | facade.DiskId = currentCabIndex; | ||
| 192 | cabinetFileRows.Add(facade); | ||
| 193 | // Now files larger than MaxUncompressedMediaSize will be the only file in its cabinet so as to respect MaxUncompressedMediaSize | ||
| 194 | currentPreCabSize = (ulong)facade.FileSize; | ||
| 195 | } | 175 | } |
| 196 | else | 176 | else |
| 197 | { | 177 | { |
| 198 | // File fits in the current cab. | 178 | // Update current cab size. |
| 199 | if (currentMediaRow == null) | 179 | currentPreCabSize += (ulong)facade.FileSize; |
| 180 | |||
| 181 | // Overflow due to current file | ||
| 182 | if (currentPreCabSize > maxPreCabSizeInBytes) | ||
| 200 | { | 183 | { |
| 201 | // Create new cab and MediaRow | 184 | currentMediaRow = this.AddMediaTuple(mediaTemplateRow, ++currentCabIndex); |
| 202 | currentMediaRow = this.AddMediaRow(mediaTemplateRow, ++currentCabIndex); | 185 | mediaTuplesByDiskId.Add(currentMediaRow.DiskId, currentMediaRow); |
| 203 | mediaRows.Add(currentMediaRow.DiskId, currentMediaRow); | ||
| 204 | filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>()); | 186 | filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>()); |
| 205 | } | ||
| 206 | 187 | ||
| 207 | // Associate current file with current cab. | 188 | // Now files larger than MaxUncompressedMediaSize will be the only file in its cabinet so as to respect MaxUncompressedMediaSize |
| 208 | var cabinetFiles = filesByCabinetMedia[currentMediaRow]; | 189 | currentPreCabSize = (ulong)facade.FileSize; |
| 209 | facade.DiskId = currentCabIndex; | 190 | } |
| 210 | cabinetFiles.Add(facade); | 191 | else // file fits in the current cab. |
| 192 | { | ||
| 193 | if (currentMediaRow == null) | ||
| 194 | { | ||
| 195 | // Create new cab and MediaRow | ||
| 196 | currentMediaRow = this.AddMediaTuple(mediaTemplateRow, ++currentCabIndex); | ||
| 197 | mediaTuplesByDiskId.Add(currentMediaRow.DiskId, currentMediaRow); | ||
| 198 | filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>()); | ||
| 199 | } | ||
| 200 | } | ||
| 211 | } | 201 | } |
| 202 | |||
| 203 | // Associate current file with current cab. | ||
| 204 | var cabinetFiles = filesByCabinetMedia[currentMediaRow]; | ||
| 205 | facade.DiskId = currentCabIndex; | ||
| 206 | cabinetFiles.Add(facade); | ||
| 212 | } | 207 | } |
| 213 | 208 | ||
| 214 | // If there are uncompressed files and no MediaRow, create a default one. | 209 | // If there are uncompressed files and no MediaRow, create a default one. |
| @@ -219,51 +214,45 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 219 | DiskId = 1, | 214 | DiskId = 1, |
| 220 | }); | 215 | }); |
| 221 | 216 | ||
| 222 | mediaRows.Add(1, defaultMediaRow); | 217 | mediaTuplesByDiskId.Add(1, defaultMediaRow); |
| 223 | } | 218 | } |
| 224 | } | 219 | } |
| 225 | 220 | ||
| 226 | /// <summary> | 221 | /// <summary> |
| 227 | /// Assign files to cabinets based on Media authoring. | 222 | /// Assign files to cabinets based on Media authoring. |
| 228 | /// </summary> | 223 | /// </summary> |
| 229 | /// <param name="mediaTable"></param> | 224 | private void ManuallyAssignFiles(List<MediaTuple> mediaTuples, Dictionary<MediaTuple, List<FileFacade>> filesByCabinetMedia, List<FileFacade> uncompressedFiles) |
| 230 | /// <param name="fileFacades"></param> | ||
| 231 | private void ManuallyAssignFiles(List<MediaTuple> mediaTable, IEnumerable<FileFacade> fileFacades, Dictionary<MediaTuple, List<FileFacade>> filesByCabinetMedia, Dictionary<int, MediaTuple> mediaRows, List<FileFacade> uncompressedFiles) | ||
| 232 | { | 225 | { |
| 233 | if (mediaTable.Any()) | 226 | var mediaTuplesByDiskId = new Dictionary<int, MediaTuple>(); |
| 227 | |||
| 228 | if (mediaTuples.Any()) | ||
| 234 | { | 229 | { |
| 235 | var cabinetMediaRows = new Dictionary<string, MediaTuple>(StringComparer.OrdinalIgnoreCase); | 230 | var cabinetMediaTuples = new Dictionary<string, MediaTuple>(StringComparer.OrdinalIgnoreCase); |
| 236 | foreach (var mediaRow in mediaTable) | 231 | foreach (var mediaTuple in mediaTuples) |
| 237 | { | 232 | { |
| 238 | // If the Media row has a cabinet, make sure it is unique across all Media rows. | 233 | // If the Media row has a cabinet, make sure it is unique across all Media rows. |
| 239 | if (!String.IsNullOrEmpty(mediaRow.Cabinet)) | 234 | if (!String.IsNullOrEmpty(mediaTuple.Cabinet)) |
| 240 | { | 235 | { |
| 241 | if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out var existingRow)) | 236 | if (cabinetMediaTuples.TryGetValue(mediaTuple.Cabinet, out var existingRow)) |
| 242 | { | 237 | { |
| 243 | this.Messaging.Write(ErrorMessages.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet)); | 238 | this.Messaging.Write(ErrorMessages.DuplicateCabinetName(mediaTuple.SourceLineNumbers, mediaTuple.Cabinet)); |
| 244 | this.Messaging.Write(ErrorMessages.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet)); | 239 | this.Messaging.Write(ErrorMessages.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet)); |
| 245 | } | 240 | } |
| 246 | else | 241 | else |
| 247 | { | 242 | { |
| 248 | cabinetMediaRows.Add(mediaRow.Cabinet, mediaRow); | 243 | cabinetMediaTuples.Add(mediaTuple.Cabinet, mediaTuple); |
| 249 | } | 244 | } |
| 250 | } | ||
| 251 | 245 | ||
| 252 | mediaRows.Add(mediaRow.DiskId, mediaRow); | 246 | filesByCabinetMedia.Add(mediaTuple, new List<FileFacade>()); |
| 253 | } | 247 | } |
| 254 | } | ||
| 255 | 248 | ||
| 256 | foreach (var mediaRow in mediaRows.Values) | 249 | mediaTuplesByDiskId.Add(mediaTuple.DiskId, mediaTuple); |
| 257 | { | ||
| 258 | if (null != mediaRow.Cabinet) | ||
| 259 | { | ||
| 260 | filesByCabinetMedia.Add(mediaRow, new List<FileFacade>()); | ||
| 261 | } | 250 | } |
| 262 | } | 251 | } |
| 263 | 252 | ||
| 264 | foreach (var facade in fileFacades) | 253 | foreach (var facade in this.FileFacades) |
| 265 | { | 254 | { |
| 266 | if (!mediaRows.TryGetValue(facade.DiskId, out var mediaRow)) | 255 | if (!mediaTuplesByDiskId.TryGetValue(facade.DiskId, out var mediaTuple)) |
| 267 | { | 256 | { |
| 268 | this.Messaging.Write(ErrorMessages.MissingMedia(facade.SourceLineNumber, facade.DiskId)); | 257 | this.Messaging.Write(ErrorMessages.MissingMedia(facade.SourceLineNumber, facade.DiskId)); |
| 269 | continue; | 258 | continue; |
| @@ -279,7 +268,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 279 | } | 268 | } |
| 280 | else // file is marked compressed. | 269 | else // file is marked compressed. |
| 281 | { | 270 | { |
| 282 | if (filesByCabinetMedia.TryGetValue(mediaRow, out var cabinetFiles)) | 271 | if (filesByCabinetMedia.TryGetValue(mediaTuple, out var cabinetFiles)) |
| 283 | { | 272 | { |
| 284 | cabinetFiles.Add(facade); | 273 | cabinetFiles.Add(facade); |
| 285 | } | 274 | } |
| @@ -292,12 +281,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 292 | } | 281 | } |
| 293 | 282 | ||
| 294 | /// <summary> | 283 | /// <summary> |
| 295 | /// Adds a row to the media table with cab name template filled in. | 284 | /// Adds a tuple to the section with cab name template filled in. |
| 296 | /// </summary> | 285 | /// </summary> |
| 297 | /// <param name="mediaTable"></param> | 286 | /// <param name="mediaTable"></param> |
| 298 | /// <param name="cabIndex"></param> | 287 | /// <param name="cabIndex"></param> |
| 299 | /// <returns></returns> | 288 | /// <returns></returns> |
| 300 | private MediaTuple AddMediaRow(WixMediaTemplateTuple mediaTemplateTuple, int cabIndex) | 289 | private MediaTuple AddMediaTuple(WixMediaTemplateTuple mediaTemplateTuple, int cabIndex) |
| 301 | { | 290 | { |
| 302 | return this.Section.AddTuple(new MediaTuple(mediaTemplateTuple.SourceLineNumbers, new Identifier(AccessModifier.Private, cabIndex)) | 291 | return this.Section.AddTuple(new MediaTuple(mediaTemplateTuple.SourceLineNumbers, new Identifier(AccessModifier.Private, cabIndex)) |
| 303 | { | 292 | { |
