diff options
author | Rob Mensching <rob@firegiant.com> | 2022-07-26 17:20:39 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2022-08-01 20:25:19 -0700 |
commit | a627ca9b720047e633a8fe72003ab9bee31006c5 (patch) | |
tree | 2bc8a924bb4141ab718e74d08f6459a0ffe8d573 /src/tools/heat/Extensibility/BaseMutatorExtension.cs | |
parent | 521eb3c9cf38823a2c4019abb85dc0b3200b92cb (diff) | |
download | wix-a627ca9b720047e633a8fe72003ab9bee31006c5.tar.gz wix-a627ca9b720047e633a8fe72003ab9bee31006c5.tar.bz2 wix-a627ca9b720047e633a8fe72003ab9bee31006c5.zip |
Create WixToolset.Heat.nupkg to distribute heat.exe and Heat targets
Moves Heat functionality to the "tools" layer and packages it all
up in WixToolset.Heat.nupkg for distribution in WiX v4.
Completes 6838
Diffstat (limited to 'src/tools/heat/Extensibility/BaseMutatorExtension.cs')
-rw-r--r-- | src/tools/heat/Extensibility/BaseMutatorExtension.cs | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/src/tools/heat/Extensibility/BaseMutatorExtension.cs b/src/tools/heat/Extensibility/BaseMutatorExtension.cs new file mode 100644 index 00000000..c36a8ed1 --- /dev/null +++ b/src/tools/heat/Extensibility/BaseMutatorExtension.cs | |||
@@ -0,0 +1,202 @@ | |||
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 | |||
3 | namespace WixToolset.Harvesters.Extensibility | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Text; | ||
8 | using Wix = WixToolset.Harvesters.Serialize; | ||
9 | |||
10 | /// <summary> | ||
11 | /// The base mutator extension. Any of these methods can be overridden to change | ||
12 | /// the behavior of the mutator. | ||
13 | /// </summary> | ||
14 | public abstract class BaseMutatorExtension : IMutatorExtension | ||
15 | { | ||
16 | /// <summary> | ||
17 | /// Gets or sets the mutator core for the extension. | ||
18 | /// </summary> | ||
19 | /// <value>The mutator core for the extension.</value> | ||
20 | public IHarvesterCore Core { get; set; } | ||
21 | |||
22 | /// <summary> | ||
23 | /// Gets the sequence of the extension. | ||
24 | /// </summary> | ||
25 | /// <value>The sequence of the extension.</value> | ||
26 | public abstract int Sequence { get; } | ||
27 | |||
28 | /// <summary> | ||
29 | /// Mutate a WiX document. | ||
30 | /// </summary> | ||
31 | /// <param name="wix">The Wix document element.</param> | ||
32 | public virtual void Mutate(Wix.Wix wix) | ||
33 | { | ||
34 | } | ||
35 | |||
36 | /// <summary> | ||
37 | /// Mutate a WiX document as a string. | ||
38 | /// </summary> | ||
39 | /// <param name="wixString">The Wix document element as a string.</param> | ||
40 | /// <returns>The mutated Wix document as a string.</returns> | ||
41 | public virtual string Mutate(string wixString) | ||
42 | { | ||
43 | return wixString; | ||
44 | } | ||
45 | |||
46 | /// <summary> | ||
47 | /// Generate unique MSI identifiers. | ||
48 | /// </summary> | ||
49 | protected class IdentifierGenerator | ||
50 | { | ||
51 | /// <summary> | ||
52 | /// | ||
53 | /// </summary> | ||
54 | public const int MaxProductIdentifierLength = 72; | ||
55 | |||
56 | /// <summary> | ||
57 | /// | ||
58 | /// </summary> | ||
59 | public const int MaxModuleIdentifierLength = 35; | ||
60 | |||
61 | private string baseName; | ||
62 | private int maxLength; | ||
63 | private Dictionary<string, object> existingIdentifiers; | ||
64 | private Dictionary<string, object> possibleIdentifiers; | ||
65 | private IHarvesterCore harvesterCore; | ||
66 | |||
67 | /// <summary> | ||
68 | /// Instantiate a new IdentifierGenerator. | ||
69 | /// </summary> | ||
70 | /// <param name="baseName">The base resource name to use if a resource name contains no usable characters.</param> | ||
71 | /// <param name="harvesterCore"></param> | ||
72 | public IdentifierGenerator(string baseName, IHarvesterCore harvesterCore) | ||
73 | { | ||
74 | this.baseName = baseName; | ||
75 | this.maxLength = IdentifierGenerator.MaxProductIdentifierLength; | ||
76 | this.existingIdentifiers = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); | ||
77 | this.possibleIdentifiers = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); | ||
78 | this.harvesterCore = harvesterCore; | ||
79 | } | ||
80 | |||
81 | /// <summary> | ||
82 | /// Gets or sets the maximum length for generated identifiers. | ||
83 | /// </summary> | ||
84 | /// <value>Maximum length for generated identifiers. (Default is 72.)</value> | ||
85 | public int MaxIdentifierLength | ||
86 | { | ||
87 | get { return this.maxLength; } | ||
88 | set { this.maxLength = value; } | ||
89 | } | ||
90 | |||
91 | /// <summary> | ||
92 | /// Index an existing identifier for collision detection. | ||
93 | /// </summary> | ||
94 | /// <param name="identifier">The identifier.</param> | ||
95 | public void IndexExistingIdentifier(string identifier) | ||
96 | { | ||
97 | if (null == identifier) | ||
98 | { | ||
99 | throw new ArgumentNullException("identifier"); | ||
100 | } | ||
101 | |||
102 | this.existingIdentifiers[identifier] = null; | ||
103 | } | ||
104 | |||
105 | /// <summary> | ||
106 | /// Index a resource name for collision detection. | ||
107 | /// </summary> | ||
108 | /// <param name="name">The resource name.</param> | ||
109 | public void IndexName(string name) | ||
110 | { | ||
111 | if (null == name) | ||
112 | { | ||
113 | throw new ArgumentNullException("name"); | ||
114 | } | ||
115 | |||
116 | string identifier = this.CreateIdentifier(name, 0); | ||
117 | |||
118 | if (this.possibleIdentifiers.ContainsKey(identifier)) | ||
119 | { | ||
120 | this.possibleIdentifiers[identifier] = String.Empty; | ||
121 | } | ||
122 | else | ||
123 | { | ||
124 | this.possibleIdentifiers.Add(identifier, null); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | /// <summary> | ||
129 | /// Get the identifier for the given resource name. | ||
130 | /// </summary> | ||
131 | /// <param name="name">The resource name.</param> | ||
132 | /// <returns>A legal MSI identifier.</returns> | ||
133 | public string GetIdentifier(string name) | ||
134 | { | ||
135 | if (null == name) | ||
136 | { | ||
137 | throw new ArgumentNullException("name"); | ||
138 | } | ||
139 | |||
140 | for (int i = 0; i <= Int32.MaxValue; i++) | ||
141 | { | ||
142 | string identifier = this.CreateIdentifier(name, i); | ||
143 | |||
144 | if (this.existingIdentifiers.ContainsKey(identifier) || // already used | ||
145 | (0 == i && 0 != this.possibleIdentifiers.Count && null != this.possibleIdentifiers[identifier]) || // needs an index because its duplicated | ||
146 | (0 != i && this.possibleIdentifiers.ContainsKey(identifier))) // collides with another possible identifier | ||
147 | { | ||
148 | continue; | ||
149 | } | ||
150 | else // use this identifier | ||
151 | { | ||
152 | this.existingIdentifiers.Add(identifier, null); | ||
153 | |||
154 | return identifier; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | throw new InvalidOperationException("Could not find a unique identifier for the given resource name."); | ||
159 | } | ||
160 | |||
161 | /// <summary> | ||
162 | /// Create a legal MSI identifier from a resource name and an index. | ||
163 | /// </summary> | ||
164 | /// <param name="name">The name of the resource for which an identifier should be created.</param> | ||
165 | /// <param name="index">An index to append to the end of the identifier to make it unique.</param> | ||
166 | /// <returns>A legal MSI identifier.</returns> | ||
167 | public string CreateIdentifier(string name, int index) | ||
168 | { | ||
169 | if (null == name) | ||
170 | { | ||
171 | throw new ArgumentNullException("name"); | ||
172 | } | ||
173 | |||
174 | StringBuilder identifier = new StringBuilder(); | ||
175 | |||
176 | // Convert the name to a standard MSI identifier | ||
177 | identifier.Append(this.harvesterCore.CreateIdentifierFromFilename(name)); | ||
178 | |||
179 | // no legal identifier characters were found, use the base id instead | ||
180 | if (0 == identifier.Length) | ||
181 | { | ||
182 | identifier.Append(this.baseName); | ||
183 | } | ||
184 | |||
185 | // truncate the identifier if it's too long (reserve 3 characters for up to 99 collisions) | ||
186 | int adjustedMaxLength = this.MaxIdentifierLength - (index != 0 ? 3 : 0); | ||
187 | if (adjustedMaxLength < identifier.Length) | ||
188 | { | ||
189 | identifier.Length = adjustedMaxLength; | ||
190 | } | ||
191 | |||
192 | // if the index is not zero, then append it to the identifier name | ||
193 | if (0 != index) | ||
194 | { | ||
195 | identifier.AppendFormat("_{0}", index); | ||
196 | } | ||
197 | |||
198 | return identifier.ToString(); | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | } | ||