aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs
new file mode 100644
index 00000000..db74eda5
--- /dev/null
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs
@@ -0,0 +1,126 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Core.WindowsInstaller.Bind
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Linq;
8 using WixToolset.Core.Bind;
9 using WixToolset.Data;
10 using WixToolset.Data.Rows;
11 using WixToolset.Data.Tuples;
12
13 internal class UpdateMediaSequencesCommand
14 {
15 public UpdateMediaSequencesCommand(Output output, List<FileFacade> fileFacades, Dictionary<int, MediaTuple> assignedMediaRows)
16 {
17 this.Output = output;
18 this.FileFacades = fileFacades;
19 }
20
21 private Output Output { get; }
22
23 private List<FileFacade> FileFacades { get; }
24
25 public void Execute()
26 {
27 var fileRows = new RowDictionary<FileRow>(this.Output.Tables["File"]);
28 var mediaRows = new RowDictionary<MediaRow>(this.Output.Tables["Media"]);
29
30 // Calculate sequence numbers and media disk id layout for all file media information objects.
31 if (OutputType.Module == this.Output.Type)
32 {
33 var lastSequence = 0;
34
35 // Order by Component to group the files by directory.
36 var optimized = this.OptimizedFileFacades();
37 foreach (var fileId in optimized.Select(f => f.File.File))
38 {
39 var fileRow = fileRows.Get(fileId);
40 fileRow.Sequence = ++lastSequence;
41 }
42 }
43 else
44 {
45 int lastSequence = 0;
46 MediaRow mediaRow = null;
47 Dictionary<int, List<FileFacade>> patchGroups = new Dictionary<int, List<FileFacade>>();
48
49 // sequence the non-patch-added files
50 var optimized = this.OptimizedFileFacades();
51 foreach (FileFacade facade in optimized)
52 {
53 if (null == mediaRow)
54 {
55 mediaRow = mediaRows.Get(facade.WixFile.DiskId);
56 if (OutputType.Patch == this.Output.Type)
57 {
58 // patch Media cannot start at zero
59 lastSequence = mediaRow.LastSequence;
60 }
61 }
62 else if (mediaRow.DiskId != facade.WixFile.DiskId)
63 {
64 mediaRow.LastSequence = lastSequence;
65 mediaRow = mediaRows.Get(facade.WixFile.DiskId);
66 }
67
68 if (0 < facade.WixFile.PatchGroup)
69 {
70 if (patchGroups.TryGetValue(facade.WixFile.PatchGroup, out var patchGroup))
71 {
72 patchGroup = new List<FileFacade>();
73 patchGroups.Add(facade.WixFile.PatchGroup, patchGroup);
74 }
75
76 patchGroup.Add(facade);
77 }
78 else
79 {
80 var fileRow = fileRows.Get(facade.File.File);
81 fileRow.Sequence = ++lastSequence;
82 }
83 }
84
85 if (null != mediaRow)
86 {
87 mediaRow.LastSequence = lastSequence;
88 mediaRow = null;
89 }
90
91 // sequence the patch-added files
92 foreach (var patchGroup in patchGroups.Values)
93 {
94 foreach (var facade in patchGroup)
95 {
96 if (null == mediaRow)
97 {
98 mediaRow = mediaRows.Get(facade.WixFile.DiskId);
99 }
100 else if (mediaRow.DiskId != facade.WixFile.DiskId)
101 {
102 mediaRow.LastSequence = lastSequence;
103 mediaRow = mediaRows.Get(facade.WixFile.DiskId);
104 }
105
106 var fileRow = fileRows.Get(facade.File.File);
107 fileRow.Sequence = ++lastSequence;
108 }
109 }
110
111 if (null != mediaRow)
112 {
113 mediaRow.LastSequence = lastSequence;
114 }
115 }
116 }
117
118 private IEnumerable<FileFacade> OptimizedFileFacades()
119 {
120 // TODO: Sort these facades even smarter by directory path and component id
121 // and maybe file size or file extension and other creative ideas to
122 // get optimal install speed out of MSI.
123 return this.FileFacades.OrderBy(f => f.File.Component_);
124 }
125 }
126}