aboutsummaryrefslogtreecommitdiff
path: root/src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2024-03-06 14:48:10 -0800
committerRob Mensching <rob@firegiant.com>2024-03-07 10:55:57 -0800
commit3d2d46f62fc01e2653d0251ad9703090574e7c41 (patch)
treeffdf7dce6c646f38b5e3ad8325c2ce78ca891a1a /src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs
parenta8504dc4eb1c2d09965b0858699ac737336ef3c1 (diff)
downloadwix-3d2d46f62fc01e2653d0251ad9703090574e7c41.tar.gz
wix-3d2d46f62fc01e2653d0251ad9703090574e7c41.tar.bz2
wix-3d2d46f62fc01e2653d0251ad9703090574e7c41.zip
Better .nupkg names
Diffstat (limited to 'src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs')
-rw-r--r--src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs391
1 files changed, 391 insertions, 0 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs b/src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs
new file mode 100644
index 00000000..e835f9ea
--- /dev/null
+++ b/src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs
@@ -0,0 +1,391 @@
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.BootstrapperApplicationApi
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Xml;
8 using System.Xml.XPath;
9
10 /// <summary>
11 /// The type of package.
12 /// </summary>
13 public enum PackageType
14 {
15 /// <summary>
16 /// Invalid type.
17 /// </summary>
18 Unknown,
19
20 /// <summary>
21 /// ExePackage
22 /// </summary>
23 Exe,
24
25 /// <summary>
26 /// MsiPackage
27 /// </summary>
28 Msi,
29
30 /// <summary>
31 /// MspPackage
32 /// </summary>
33 Msp,
34
35 /// <summary>
36 /// MsuPackage
37 /// </summary>
38 Msu,
39
40 /// <summary>
41 /// Related bundle of type Upgrade
42 /// </summary>
43 UpgradeBundle,
44
45 /// <summary>
46 /// Related bundle of type Addon
47 /// </summary>
48 AddonBundle,
49
50 /// <summary>
51 /// Related bundle of type Patch
52 /// </summary>
53 PatchBundle,
54
55 /// <summary>
56 /// Related bundle of type Update
57 /// </summary>
58 UpdateBundle,
59
60 /// <summary>
61 /// BundlePackage
62 /// </summary>
63 ChainBundle,
64 }
65
66 /// <summary>
67 /// Metadata for BAs like WixInternalUIBootstrapperApplication that only support one main package.
68 /// </summary>
69 public enum PrimaryPackageType
70 {
71 /// <summary>
72 /// Not a primary package.
73 /// </summary>
74 None,
75
76 /// <summary>
77 /// The default package if no architecture specific package is available for the current architecture.
78 /// </summary>
79 Default,
80
81 /// <summary>
82 /// The package to use on x86 machines.
83 /// </summary>
84 X86,
85
86 /// <summary>
87 /// The package to use on x64 machines.
88 /// </summary>
89 X64,
90
91 /// <summary>
92 /// The package to use on ARM64 machines.
93 /// </summary>
94 ARM64,
95 }
96
97 /// <summary>
98 /// Default implementation of <see cref="IPackageInfo"/>.
99 /// </summary>
100 public class PackageInfo : IPackageInfo
101 {
102 /// <inheritdoc/>
103 public string Id { get; internal set; }
104
105 /// <inheritdoc/>
106 public string DisplayName { get; internal set; }
107
108 /// <inheritdoc/>
109 public string Description { get; internal set; }
110
111 /// <inheritdoc/>
112 public PackageType Type { get; internal set; }
113
114 /// <inheritdoc/>
115 public bool Permanent { get; internal set; }
116
117 /// <inheritdoc/>
118 public bool Vital { get; internal set; }
119
120 /// <inheritdoc/>
121 public string DisplayInternalUICondition { get; internal set; }
122
123 /// <inheritdoc/>
124 public string ProductCode { get; internal set; }
125
126 /// <inheritdoc/>
127 public string UpgradeCode { get; internal set; }
128
129 /// <inheritdoc/>
130 public string Version { get; internal set; }
131
132 /// <inheritdoc/>
133 public string InstallCondition { get; internal set; }
134
135 /// <inheritdoc/>
136 public string RepairCondition { get; internal set; }
137
138 /// <inheritdoc/>
139 public BOOTSTRAPPER_CACHE_TYPE CacheType { get; internal set; }
140
141 /// <inheritdoc/>
142 public bool PrereqPackage { get; internal set; }
143
144 /// <inheritdoc/>
145 public string PrereqLicenseFile { get; internal set; }
146
147 /// <inheritdoc/>
148 public string PrereqLicenseUrl { get; internal set; }
149
150 /// <inheritdoc/>
151 public PrimaryPackageType PrimaryPackageType { get; internal set; }
152
153 /// <inheritdoc/>
154 public object CustomData { get; set; }
155
156 internal PackageInfo() { }
157
158 /// <summary>
159 /// Parse packages from BootstrapperApplicationData.xml.
160 /// </summary>
161 /// <param name="root">The root node.</param>
162 /// <returns>A dictionary of the packages by Id.</returns>
163 public static IDictionary<string, IPackageInfo> ParsePackagesFromXml(XPathNavigator root)
164 {
165 var packagesById = new Dictionary<string, IPackageInfo>();
166 XmlNamespaceManager namespaceManager = new XmlNamespaceManager(root.NameTable);
167 namespaceManager.AddNamespace("p", BootstrapperApplicationData.XMLNamespace);
168 XPathNodeIterator nodes = root.Select("/p:BootstrapperApplicationData/p:WixPackageProperties", namespaceManager);
169
170 foreach (XPathNavigator node in nodes)
171 {
172 var package = new PackageInfo();
173
174 string id = BootstrapperApplicationData.GetAttribute(node, "Package");
175 if (id == null)
176 {
177 throw new Exception("Failed to get package identifier for package.");
178 }
179 package.Id = id;
180
181 package.DisplayName = BootstrapperApplicationData.GetAttribute(node, "DisplayName");
182
183 package.Description = BootstrapperApplicationData.GetAttribute(node, "Description");
184
185 PackageType? packageType = GetPackageTypeAttribute(node, "PackageType");
186 if (!packageType.HasValue)
187 {
188 throw new Exception("Failed to get package type for package.");
189 }
190 package.Type = packageType.Value;
191
192 bool? permanent = BootstrapperApplicationData.GetYesNoAttribute(node, "Permanent");
193 if (!permanent.HasValue)
194 {
195 throw new Exception("Failed to get permanent settings for package.");
196 }
197 package.Permanent = permanent.Value;
198
199 bool? vital = BootstrapperApplicationData.GetYesNoAttribute(node, "Vital");
200 if (!vital.HasValue)
201 {
202 throw new Exception("Failed to get vital setting for package.");
203 }
204 package.Vital = vital.Value;
205
206 package.ProductCode = BootstrapperApplicationData.GetAttribute(node, "ProductCode");
207
208 package.UpgradeCode = BootstrapperApplicationData.GetAttribute(node, "UpgradeCode");
209
210 package.Version = BootstrapperApplicationData.GetAttribute(node, "Version");
211
212 package.InstallCondition = BootstrapperApplicationData.GetAttribute(node, "InstallCondition");
213
214 package.RepairCondition = BootstrapperApplicationData.GetAttribute(node, "RepairCondition");
215
216 BOOTSTRAPPER_CACHE_TYPE? cacheType = GetCacheTypeAttribute(node, "Cache");
217 if (!cacheType.HasValue)
218 {
219 throw new Exception("Failed to get cache type for package.");
220 }
221 package.CacheType = cacheType.Value;
222
223 packagesById.Add(package.Id, package);
224 }
225
226 ParseBalPackageInfoFromXml(root, namespaceManager, packagesById);
227 return packagesById;
228 }
229
230 /// <summary>
231 /// Parse the cache type attribute.
232 /// </summary>
233 /// <param name="node">Package node</param>
234 /// <param name="attributeName">Attribute name</param>
235 /// <returns>The cache type</returns>
236 public static BOOTSTRAPPER_CACHE_TYPE? GetCacheTypeAttribute(XPathNavigator node, string attributeName)
237 {
238 string attributeValue = BootstrapperApplicationData.GetAttribute(node, attributeName);
239
240 if (attributeValue == null)
241 {
242 return null;
243 }
244
245 if (attributeValue.Equals("keep", StringComparison.InvariantCulture))
246 {
247 return BOOTSTRAPPER_CACHE_TYPE.Keep;
248 }
249 else if (attributeValue.Equals("force", StringComparison.InvariantCulture))
250 {
251 return BOOTSTRAPPER_CACHE_TYPE.Force;
252 }
253 else
254 {
255 return BOOTSTRAPPER_CACHE_TYPE.Remove;
256 }
257 }
258
259 /// <summary>
260 /// Parse the package type attribute
261 /// </summary>
262 /// <param name="node">Package node</param>
263 /// <param name="attributeName">Attribute name</param>
264 /// <returns>The package type</returns>
265 public static PackageType? GetPackageTypeAttribute(XPathNavigator node, string attributeName)
266 {
267 string attributeValue = BootstrapperApplicationData.GetAttribute(node, attributeName);
268
269 if (attributeValue == null)
270 {
271 return null;
272 }
273
274 if (attributeValue.Equals("Bundle", StringComparison.InvariantCulture))
275 {
276 return PackageType.ChainBundle;
277 }
278 else if (attributeValue.Equals("Exe", StringComparison.InvariantCulture))
279 {
280 return PackageType.Exe;
281 }
282 else if (attributeValue.Equals("Msi", StringComparison.InvariantCulture))
283 {
284 return PackageType.Msi;
285 }
286 else if (attributeValue.Equals("Msp", StringComparison.InvariantCulture))
287 {
288 return PackageType.Msp;
289 }
290 else if (attributeValue.Equals("Msu", StringComparison.InvariantCulture))
291 {
292 return PackageType.Msu;
293 }
294 else
295 {
296 return PackageType.Unknown;
297 }
298 }
299
300 /// <summary>
301 /// Create <see cref="IPackageInfo"/> from a related bundle.
302 /// </summary>
303 /// <param name="id">Package id</param>
304 /// <param name="relationType">Relation type</param>
305 /// <param name="perMachine">Whether the related bundle is per-machine</param>
306 /// <param name="version">The related bundle's version</param>
307 /// <returns>The package info</returns>
308 public static IPackageInfo GetRelatedBundleAsPackage(string id, RelationType relationType, bool perMachine, string version)
309 {
310 PackageInfo package = new PackageInfo();
311 package.Id = id;
312 package.Version = version;
313
314 switch (relationType)
315 {
316 case RelationType.Addon:
317 package.Type = PackageType.AddonBundle;
318 break;
319 case RelationType.Patch:
320 package.Type = PackageType.PatchBundle;
321 break;
322 case RelationType.Upgrade:
323 package.Type = PackageType.UpgradeBundle;
324 break;
325 default:
326 throw new Exception(String.Format("Unknown related bundle type: {0}", relationType));
327 }
328
329 return package;
330 }
331
332 /// <summary>
333 /// Create <see cref="IPackageInfo"/> from an update bundle.
334 /// </summary>
335 /// <param name="id">Package id</param>
336 /// <returns>The package info</returns>
337 public static IPackageInfo GetUpdateBundleAsPackage(string id)
338 {
339 PackageInfo package = new PackageInfo();
340 package.Id = id;
341 package.Type = PackageType.UpdateBundle;
342
343 return package;
344 }
345
346 internal static void ParseBalPackageInfoFromXml(XPathNavigator root, XmlNamespaceManager namespaceManager, Dictionary<string, IPackageInfo> packagesById)
347 {
348 XPathNodeIterator nodes = root.Select("/p:BootstrapperApplicationData/p:WixBalPackageInfo", namespaceManager);
349
350 foreach (XPathNavigator node in nodes)
351 {
352 string id = BootstrapperApplicationData.GetAttribute(node, "PackageId");
353 if (id == null)
354 {
355 throw new Exception("Failed to get package identifier for WixBalPackageInfo.");
356 }
357
358 if (!packagesById.TryGetValue(id, out var ipackage))
359 {
360 throw new Exception(String.Format("Failed to find package specified in WixBalPackageInfo: {0}", id));
361 }
362
363 var package = (PackageInfo)ipackage;
364
365 package.DisplayInternalUICondition = BootstrapperApplicationData.GetAttribute(node, "DisplayInternalUICondition");
366 }
367
368 nodes = root.Select("/p:BootstrapperApplicationData/p:WixPrereqInformation", namespaceManager);
369
370 foreach (XPathNavigator node in nodes)
371 {
372 string id = BootstrapperApplicationData.GetAttribute(node, "PackageId");
373 if (id == null)
374 {
375 throw new Exception("Failed to get package identifier for WixPrereqInformation.");
376 }
377
378 if (!packagesById.TryGetValue(id, out var ipackage))
379 {
380 throw new Exception(String.Format("Failed to find package specified in WixPrereqInformation: {0}", id));
381 }
382
383 var package = (PackageInfo)ipackage;
384
385 package.PrereqPackage = true;
386 package.PrereqLicenseFile = BootstrapperApplicationData.GetAttribute(node, "LicenseFile");
387 package.PrereqLicenseUrl = BootstrapperApplicationData.GetAttribute(node, "LicenseUrl");
388 }
389 }
390 }
391}