aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.WindowsInstaller
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs2
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/OptimizeFileFacadesOrderCommand.cs92
2 files changed, 86 insertions, 8 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
index 93c617d9..4b3d554a 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
@@ -364,7 +364,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
364 Dictionary<MediaSymbol, IEnumerable<FileFacade>> filesByCabinetMedia; 364 Dictionary<MediaSymbol, IEnumerable<FileFacade>> filesByCabinetMedia;
365 IEnumerable<FileFacade> uncompressedFiles; 365 IEnumerable<FileFacade> uncompressedFiles;
366 { 366 {
367 var order = new OptimizeFileFacadesOrderCommand(fileFacades); 367 var order = new OptimizeFileFacadesOrderCommand(this.BackendHelper, this.PathResolver, section, platform, fileFacades);
368 order.Execute(); 368 order.Execute();
369 369
370 fileFacades = order.FileFacades; 370 fileFacades = order.FileFacades;
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/OptimizeFileFacadesOrderCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/OptimizeFileFacadesOrderCommand.cs
index 6943d345..e96dfd91 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/OptimizeFileFacadesOrderCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/OptimizeFileFacadesOrderCommand.cs
@@ -4,34 +4,112 @@ namespace WixToolset.Core.WindowsInstaller.Bind
4{ 4{
5 using System; 5 using System;
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.Linq;
7 using WixToolset.Core.Bind; 8 using WixToolset.Core.Bind;
9 using WixToolset.Data;
10 using WixToolset.Data.Symbols;
11 using WixToolset.Extensibility.Data;
12 using WixToolset.Extensibility.Services;
8 13
9 internal class OptimizeFileFacadesOrderCommand 14 internal class OptimizeFileFacadesOrderCommand
10 { 15 {
11 public OptimizeFileFacadesOrderCommand(List<FileFacade> fileFacades) 16 public OptimizeFileFacadesOrderCommand(IBackendHelper helper, IPathResolver pathResolver, IntermediateSection section, Platform platform, List<FileFacade> fileFacades)
12 { 17 {
18 this.BackendHelper = helper;
19 this.PathResolver = pathResolver;
20 this.Section = section;
21 this.Platform = platform;
13 this.FileFacades = fileFacades; 22 this.FileFacades = fileFacades;
14 } 23 }
15 24
16 public List<FileFacade> FileFacades { get; private set; } 25 public List<FileFacade> FileFacades { get; private set; }
17 26
27 private IBackendHelper BackendHelper { get; }
28
29 private IPathResolver PathResolver { get; }
30
31 private IntermediateSection Section { get; }
32
33 private Platform Platform { get; }
34
18 public List<FileFacade> Execute() 35 public List<FileFacade> Execute()
19 { 36 {
20 this.FileFacades.Sort(FileFacadeOptimizer.Instance); 37 var canonicalComponentTargetPaths = this.ComponentTargetPaths();
38
39 this.FileFacades.Sort(new FileFacadeOptimizer(canonicalComponentTargetPaths));
21 40
22 return this.FileFacades; 41 return this.FileFacades;
23 } 42 }
24 43
44 private Dictionary<string, string> ComponentTargetPaths()
45 {
46 var directories = this.ResolveDirectories();
47
48 var canonicalPathsByDirectoryId = new Dictionary<string, string>();
49 foreach (var component in this.Section.Symbols.OfType<ComponentSymbol>())
50 {
51 var directoryPath = this.PathResolver.GetCanonicalDirectoryPath(directories, null, component.DirectoryRef, this.Platform);
52 canonicalPathsByDirectoryId.Add(component.Id.Id, directoryPath);
53 }
54
55 return canonicalPathsByDirectoryId;
56 }
57
58 private Dictionary<string, IResolvedDirectory> ResolveDirectories()
59 {
60 var targetPathsByDirectoryId = new Dictionary<string, IResolvedDirectory>();
61
62 // Get the target paths for all directories.
63 foreach (var directory in this.Section.Symbols.OfType<DirectorySymbol>())
64 {
65 var resolvedDirectory = this.BackendHelper.CreateResolvedDirectory(directory.ParentDirectoryRef, directory.Name);
66 targetPathsByDirectoryId.Add(directory.Id.Id, resolvedDirectory);
67 }
68
69 return targetPathsByDirectoryId;
70 }
71
25 private class FileFacadeOptimizer : IComparer<FileFacade> 72 private class FileFacadeOptimizer : IComparer<FileFacade>
26 { 73 {
27 public static readonly FileFacadeOptimizer Instance = new FileFacadeOptimizer(); 74 public FileFacadeOptimizer(Dictionary<string, string> componentTargetPaths)
75 {
76 this.ComponentTargetPaths = componentTargetPaths;
77 }
78
79 private Dictionary<string, string> ComponentTargetPaths { get; }
28 80
29 public int Compare(FileFacade x, FileFacade y) 81 public int Compare(FileFacade x, FileFacade y)
30 { 82 {
31 // TODO: Sort these facades even smarter by directory path and component id 83 // First group files by DiskId.
32 // and maybe file size or file extension and other creative ideas to 84 var compare = x.DiskId.CompareTo(y.DiskId);
33 // get optimal install speed out of MSI. 85
34 return String.Compare(x.ComponentRef, y.ComponentRef, StringComparison.Ordinal); 86 if (compare != 0)
87 {
88 return compare;
89 }
90
91 // Next try to group files by target install directory.
92 if (this.ComponentTargetPaths.TryGetValue(x.ComponentRef, out var canonicalX) &&
93 this.ComponentTargetPaths.TryGetValue(y.ComponentRef, out var canonicalY))
94 {
95 compare = String.Compare(canonicalX, canonicalY, StringComparison.Ordinal);
96
97 if (compare != 0)
98 {
99 return compare;
100 }
101 }
102
103 // TODO: Consider sorting these facades even smarter by file size or file extension
104 // or other creative ideas to get optimal install speed out of MSI.
105 compare = String.Compare(x.FileName, y.FileName, StringComparison.Ordinal);
106
107 if (compare != 0)
108 {
109 return compare;
110 }
111
112 return String.Compare(x.Id, y.Id, StringComparison.Ordinal);
35 } 113 }
36 } 114 }
37 } 115 }